From 4aed69c6f107beb154aaa6c0eb59d1a4844691a7 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 21 Nov 2016 19:36:54 +0100 Subject: [PATCH 001/472] Fix merge errors. --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index e6eb005e3..45342a05b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,10 @@ before_install: - sudo apt-get update -qq -<<<<<<< HEAD - sudo apt-get install cmake env: global: - secure: "lZ7pHQvl5dpZWzBQAaIMf0wqrvtcZ4wiZKeIZjf83TEsflW8+z0uTpIuN30ZV6Glth/Sq1OhLnTP5+N57fZU/1ebA5twHdvP4bS5CIUUg71/CXQZNl36xeaqvxsG/xRrdpKOsPdjAOsQ9KPTQulsX43XDLS7CasMiLvYOpqKcPc=" -======= - sudo apt-get install cmake python3 - if [ $LINUX ]; then sudo apt-get install -qq freeglut3-dev libxmu-dev libxi-dev ; fi - echo -e "#ifndef A_R_H_INC\n#define A_R_H_INC\n#define GitVersion ${TRAVIS_JOB_ID}\n#define GitBranch \"${TRAVIS_BRANCH}\"\n#endif // A_R_H_INC" > revision.h @@ -66,3 +64,4 @@ addons: build_command_prepend: "cmake . -DASSIMP_ENABLE_BOOST_WORKAROUND=YES" build_command: "make" branch_pattern: coverity_scan + From 350619a17f37e319a25a958aef42f5f4ec755a6a Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 22 Nov 2016 07:28:00 +0100 Subject: [PATCH 002/472] Old coverity scan config. --- .travis.yml | 45 ++++----------------------------------------- 1 file changed, 4 insertions(+), 41 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2e10890e3..ea8ed55a6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,65 +1,28 @@ 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 - - echo -e "#ifndef A_R_H_INC\n#define A_R_H_INC\n#define GitVersion ${TRAVIS_JOB_ID}\n#define GitBranch \"${TRAVIS_BRANCH}\"\n#endif // A_R_H_INC" > revision.h - # install latest LCOV (1.9 was failing) - - cd ${TRAVIS_BUILD_DIR} - - wget http://ftp.de.debian.org/debian/pool/main/l/lcov/lcov_1.11.orig.tar.gz - - tar xf lcov_1.11.orig.tar.gz - - sudo make -C lcov-1.11/ install - - gem install coveralls-lcov - - lcov --version - - g++ --version - -branches: - only: - - master env: 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 -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 + cmake . -DASSIMP_ENABLE_BOOST_WORKAROUND=YES 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 + make addons: coverity_scan: project: name: "assimp/assimp" notification_email: kim.kulling@googlemail.com - build_command_prepend: "cmake" + build_command_prepend: "cmake . -DASSIMP_ENABLE_BOOST_WORKAROUND=YES" build_command: "make" branch_pattern: coverity_scan - From ef30abfbcd65b3cdc66294242192767b459f1d1f Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 22 Nov 2016 07:43:51 +0100 Subject: [PATCH 003/472] Use old config. --- .travis.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index ea8ed55a6..2ee456327 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,12 @@ -before_install: - - sudo apt-get update -qq - - sudo apt-get install cmake - env: global: - secure: "lZ7pHQvl5dpZWzBQAaIMf0wqrvtcZ4wiZKeIZjf83TEsflW8+z0uTpIuN30ZV6Glth/Sq1OhLnTP5+N57fZU/1ebA5twHdvP4bS5CIUUg71/CXQZNl36xeaqvxsG/xRrdpKOsPdjAOsQ9KPTQulsX43XDLS7CasMiLvYOpqKcPc=" +before_install: + - sudo apt-get update -qq + - sudo apt-get install cmake + - echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca- + language: cpp compiler: @@ -13,7 +14,7 @@ compiler: - clang before_script: - cmake . -DASSIMP_ENABLE_BOOST_WORKAROUND=YES + cmake . script: make @@ -23,6 +24,6 @@ addons: project: name: "assimp/assimp" notification_email: kim.kulling@googlemail.com - build_command_prepend: "cmake . -DASSIMP_ENABLE_BOOST_WORKAROUND=YES" - build_command: "make" + build_command_prepend: "cmake ." + build_command: "make -j4" branch_pattern: coverity_scan From c27f35a6fdddcc4ba2a7dbf7595e8b9a4d98bcbc Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 28 Jun 2017 20:18:37 +0200 Subject: [PATCH 004/472] Update .travis.yml remove dead code. --- .travis.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index a00e0ce70..fbef08285 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,11 +23,6 @@ env: - 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 - #exclude: - # - os: linux - # compiler: clang - # - os: osx - # compiler: gcc compiler: - gcc From 7b15ec0b64be14811cee20f81922a4fef5af94bc Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 1 Jul 2017 11:02:03 +0200 Subject: [PATCH 005/472] pyassimp: update readme. --- port/PyAssimp/README.md | 188 ++++++++++++++++++++-------------------- 1 file changed, 94 insertions(+), 94 deletions(-) diff --git a/port/PyAssimp/README.md b/port/PyAssimp/README.md index 0000f9386..37ecdb65d 100644 --- a/port/PyAssimp/README.md +++ b/port/PyAssimp/README.md @@ -1,94 +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 ------ - -### 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. - +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. + From 0e6cbdba3e74b425aa490b3612c09ddec70b05aa Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 1 Jul 2017 11:33:17 +0200 Subject: [PATCH 006/472] back to 3.3.1 version with build on 4 cpus. --- .travis.yml | 41 ++++++++--------------------------------- 1 file changed, 8 insertions(+), 33 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5c88ecb39..0c16c6c41 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,54 +1,29 @@ sudo: required -language: cpp - before_install: - - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get update -qq && sudo apt-get install cmake && 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 brew install cmake python3 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) - - 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 - -osx_image: xcode8.3 + - sudo apt-get update -qq + - sudo apt-get install cmake + - sudo apt-get install -qq freeglut3-dev libxmu-dev libxi-dev 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: - - 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 +language: cpp + compiler: - gcc - - clang before_script: - # init coverage to 0 (optional) - - if [ "$TRAVIS_OS_NAME" = "linux" ]; then cd ${TRAVIS_BUILD_DIR} && lcov --directory . --zerocounters ; fi + cmake . -DASSIMP_ENABLE_BOOST_WORKAROUND=YES script: - - export COVERALLS_SERVICE_NAME=travis-ci - - export COVERALLS_REPO_TOKEN=abc12345 - - . ./.travis.sh -os: - - linux - - osx - -after_success: - - 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 + make addons: coverity_scan: project: name: "assimp/assimp" notification_email: kim.kulling@googlemail.com - build_command_prepend: "cmake ." + build_command_prepend: "cmake . -DASSIMP_ENABLE_BOOST_WORKAROUND=YES" build_command: "make -j4" branch_pattern: coverity_scan From cb567d9f654b6d07b22c6fae96350e3d6f454f78 Mon Sep 17 00:00:00 2001 From: Marco Di Benedetto Date: Wed, 1 Aug 2018 16:38:33 +0200 Subject: [PATCH 007/472] added internal to_string. --- code/FBXExportNode.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/FBXExportNode.cpp b/code/FBXExportNode.cpp index a1171eca8..17269ffb0 100644 --- a/code/FBXExportNode.cpp +++ b/code/FBXExportNode.cpp @@ -432,7 +432,7 @@ void FBX::Node::WritePropertyNodeAscii( char buffer[32]; FBX::Node node(name); node.Begin(s, false, indent); - std::string vsize = std::to_string(v.size()); + std::string vsize = to_string(v.size()); // * { s.PutChar('*'); s.PutString(vsize); s.PutString(" {\n"); // indent + 1 @@ -468,7 +468,7 @@ void FBX::Node::WritePropertyNodeAscii( char buffer[32]; FBX::Node node(name); node.Begin(s, false, indent); - std::string vsize = std::to_string(v.size()); + std::string vsize = to_string(v.size()); // * { s.PutChar('*'); s.PutString(vsize); s.PutString(" {\n"); // indent + 1 From 1c577f66f7f6afa4d46508e1ba1ac4fdfa765ade Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 7 Sep 2018 19:14:52 +0200 Subject: [PATCH 008/472] Collada-Exporter: fix some minor findings. --- code/ColladaExporter.cpp | 388 +++++++++++++++++++-------------------- 1 file changed, 190 insertions(+), 198 deletions(-) diff --git a/code/ColladaExporter.cpp b/code/ColladaExporter.cpp index 96421a532..82a755c58 100644 --- a/code/ColladaExporter.cpp +++ b/code/ColladaExporter.cpp @@ -62,15 +62,11 @@ 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 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)); @@ -83,7 +79,7 @@ void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* p // we're still here - export successfully completed. Write result to the given IOSYstem std::unique_ptr outfile (pIOSystem->Open(pFile,"wt")); - if(outfile == NULL) { + if(outfile == nullptr) { throw DeadlyExportError("could not open output .dae file: " + std::string(pFile)); } @@ -93,19 +89,20 @@ void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* p } // end of namespace Assimp - +using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor for a specific scene to export -ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file) : mIOSystem(pIOSystem), mPath(path), mFile(file) -{ +ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file) +: mIOSystem( pIOSystem ) +, mPath( path ) +, mFile( file ) +, mScene(pScene) +, mSceneOwned(false) { // make sure that all formatting happens using the standard, C locale and not the user's current locale mOutput.imbue( std::locale("C") ); mOutput.precision(16); - mScene = pScene; - mSceneOwned = false; - // set up strings endstr = "\n"; @@ -115,17 +112,16 @@ ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, co // ------------------------------------------------------------------------------------------------ // Destructor -ColladaExporter::~ColladaExporter() -{ +ColladaExporter::~ColladaExporter() { if(mSceneOwned) { delete mScene; + mScene = nullptr; } } // ------------------------------------------------------------------------------------------------ // Starts writing the contents -void ColladaExporter::WriteFile() -{ +void ColladaExporter::WriteFile() { // write the DTD mOutput << "" << endstr; // COLLADA element start @@ -158,8 +154,7 @@ void ColladaExporter::WriteFile() // ------------------------------------------------------------------------------------------------ // Writes the asset header -void ColladaExporter::WriteHeader() -{ +void ColladaExporter::WriteHeader() { static const ai_real epsilon = ai_real( 0.00001 ); static const aiQuaternion x_rot(aiMatrix3x3( 0, -1, 0, @@ -269,54 +264,56 @@ void ColladaExporter::WriteTextures() { static const unsigned int buffer_size = 1024; char str[buffer_size]; - if(mScene->HasTextures()) { - for(unsigned int i = 0; i < mScene->mNumTextures; i++) { - // It would be great to be able to create a directory in portable standard C++, but it's not the case, - // so we just write the textures in the current directory. + if (!mScene->HasTextures()) { + return; + } - aiTexture* texture = mScene->mTextures[i]; + for(unsigned int i = 0; i < mScene->mNumTextures; i++) { + // It would be great to be able to create a directory in portable standard C++, but it's not the case, + // so we just write the textures in the current directory. - ASSIMP_itoa10(str, buffer_size, i + 1); + aiTexture* texture = mScene->mTextures[i]; - std::string name = mFile + "_texture_" + (i < 1000 ? "0" : "") + (i < 100 ? "0" : "") + (i < 10 ? "0" : "") + str + "." + ((const char*) texture->achFormatHint); + ASSIMP_itoa10(str, buffer_size, i + 1); - std::unique_ptr outfile(mIOSystem->Open(mPath + name, "wb")); - if(outfile == NULL) { - throw DeadlyExportError("could not open output texture file: " + mPath + name); - } + std::string name = mFile + "_texture_" + (i < 1000 ? "0" : "") + (i < 100 ? "0" : "") + (i < 10 ? "0" : "") + str + "." + ((const char*) texture->achFormatHint); - if(texture->mHeight == 0) { - outfile->Write((void*) texture->pcData, texture->mWidth, 1); - } else { - Bitmap::Save(texture, outfile.get()); - } - - outfile->Flush(); - - textures.insert(std::make_pair(i, name)); + std::unique_ptr outfile(mIOSystem->Open(mPath + name, "wb")); + if(outfile == NULL) { + throw DeadlyExportError("could not open output texture file: " + mPath + name); } + + if(texture->mHeight == 0) { + outfile->Write((void*) texture->pcData, texture->mWidth, 1); + } else { + Bitmap::Save(texture, outfile.get()); + } + + outfile->Flush(); + + textures.insert(std::make_pair(i, name)); } } // ------------------------------------------------------------------------------------------------ // Write the embedded textures void ColladaExporter::WriteCamerasLibrary() { - if(mScene->HasCameras()) { - - mOutput << startstr << "" << endstr; - PushTag(); - - for( size_t a = 0; a < mScene->mNumCameras; ++a) - WriteCamera( a); - - PopTag(); - mOutput << startstr << "" << endstr; - + if (mScene->HasCameras()) { + return; } + + mOutput << startstr << "" << endstr; + PushTag(); + + for (size_t a = 0; a < mScene->mNumCameras; ++a) { + WriteCamera(a); + } + + PopTag(); + mOutput << startstr << "" << endstr; } void ColladaExporter::WriteCamera(size_t pIndex){ - const aiCamera *cam = mScene->mCameras[pIndex]; const std::string idstrEscaped = XMLEscape(cam->mName.C_Str()); @@ -350,30 +347,29 @@ void ColladaExporter::WriteCamera(size_t pIndex){ mOutput << startstr << "" << endstr; PopTag(); mOutput << startstr << "" << endstr; - } - // ------------------------------------------------------------------------------------------------ // Write the embedded textures void ColladaExporter::WriteLightsLibrary() { - if(mScene->HasLights()) { - - mOutput << startstr << "" << endstr; - PushTag(); - - for( size_t a = 0; a < mScene->mNumLights; ++a) - WriteLight( a); - - PopTag(); - mOutput << startstr << "" << endstr; - + if (!mScene->HasLights()) { + return; } + + mOutput << startstr << "" << endstr; + PushTag(); + + for (size_t a = 0; a < mScene->mNumLights; ++a) { + WriteLight(a); + } + + PopTag(); + mOutput << startstr << "" << endstr; } void ColladaExporter::WriteLight(size_t pIndex){ - const aiLight *light = mScene->mLights[pIndex]; + ai_assert(nullptr != light); const std::string idstrEscaped = XMLEscape(light->mName.C_Str()); mOutput << startstr << "" << light->mAttenuationQuadratic <<"" << endstr; - /* - out->mAngleOuterCone = AI_DEG_TO_RAD (std::acos(std::pow(0.1f,1.f/srcLight->mFalloffExponent))+ - srcLight->mFalloffAngle); - */ const ai_real fallOffAngle = AI_RAD_TO_DEG(light->mAngleInnerCone); mOutput << startstr <<"" @@ -481,8 +473,7 @@ void ColladaExporter::WriteSpotLight(const aiLight *const light){ } -void ColladaExporter::WriteAmbienttLight(const aiLight *const light){ - +void ColladaExporter::WriteAmbienttLight(const aiLight *const light) { const aiColor3D &color= light->mColorAmbient; mOutput << startstr << "" << endstr; PushTag(); @@ -496,8 +487,7 @@ void ColladaExporter::WriteAmbienttLight(const aiLight *const light){ // ------------------------------------------------------------------------------------------------ // Reads a single surface entry from the given material keys -void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial* pSrcMat, aiTextureType pTexture, const char* pKey, size_t pType, size_t pIndex) -{ +void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial* pSrcMat, aiTextureType pTexture, const char* pKey, size_t pType, size_t pIndex) { if( pSrcMat->GetTextureCount( pTexture) > 0 ) { aiString texfile; @@ -623,8 +613,7 @@ void ColladaExporter::WriteTextureParamEntry( const Surface& pSurface, const std // ------------------------------------------------------------------------------------------------ // Writes a scalar property -void ColladaExporter::WriteFloatEntry( const Property& pProperty, const std::string& pTypeName) -{ +void ColladaExporter::WriteFloatEntry( const Property& pProperty, const std::string& pTypeName) { if(pProperty.exist) { mOutput << startstr << "<" << pTypeName << ">" << endstr; PushTag(); @@ -798,13 +787,13 @@ void ColladaExporter::WriteMaterials() // ------------------------------------------------------------------------------------------------ // Writes the controller library -void ColladaExporter::WriteControllerLibrary() -{ +void ColladaExporter::WriteControllerLibrary() { mOutput << startstr << "" << endstr; PushTag(); - for( size_t a = 0; a < mScene->mNumMeshes; ++a) - WriteController( a); + for (size_t a = 0; a < mScene->mNumMeshes; ++a) { + WriteController( a ); + } PopTag(); mOutput << startstr << "" << endstr; @@ -812,8 +801,7 @@ void ColladaExporter::WriteControllerLibrary() // ------------------------------------------------------------------------------------------------ // Writes a skin controller of the given mesh -void ColladaExporter::WriteController( size_t pIndex) -{ +void ColladaExporter::WriteController( size_t pIndex) { const aiMesh* mesh = mScene->mMeshes[pIndex]; const std::string idstr = GetMeshId( pIndex); const std::string idstrEscaped = XMLEscape(idstr); @@ -874,9 +862,11 @@ void ColladaExporter::WriteController( size_t pIndex) 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) + 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); @@ -884,9 +874,11 @@ void ColladaExporter::WriteController( size_t pIndex) 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) + 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()); @@ -910,12 +902,15 @@ void ColladaExporter::WriteController( size_t pIndex) 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) + 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) + for (size_t i = 0; i < mesh->mNumVertices; ++i) { mOutput << num_influences[i] << " "; + } mOutput << "" << endstr; @@ -924,19 +919,17 @@ void ColladaExporter::WriteController( size_t pIndex) 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) - { + 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) - { + 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) + for (ai_uint k = 0; k < num_influences[vId]; ++k) { if (joint_weight_indices[2 * (accum_influences[vId] + k)] == -1) { @@ -947,9 +940,11 @@ void ColladaExporter::WriteController( size_t pIndex) } ++weight_index; } + } - for( size_t i = 0; i < joint_weight_indices.size(); ++i) + for (size_t i = 0; i < joint_weight_indices.size(); ++i) { mOutput << joint_weight_indices[i] << " "; + } num_influences.clear(); accum_influences.clear(); @@ -969,13 +964,13 @@ void ColladaExporter::WriteController( size_t pIndex) // ------------------------------------------------------------------------------------------------ // Writes the geometry library -void ColladaExporter::WriteGeometryLibrary() -{ +void ColladaExporter::WriteGeometryLibrary() { mOutput << startstr << "" << endstr; PushTag(); - for( size_t a = 0; a < mScene->mNumMeshes; ++a) - WriteGeometry( a); + for (size_t a = 0; a < mScene->mNumMeshes; ++a) { + WriteGeometry(a); + } PopTag(); mOutput << startstr << "" << endstr; @@ -983,14 +978,14 @@ void ColladaExporter::WriteGeometryLibrary() // ------------------------------------------------------------------------------------------------ // Writes the given mesh -void ColladaExporter::WriteGeometry( size_t pIndex) -{ +void ColladaExporter::WriteGeometry( 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 ) + if (mesh->mNumFaces == 0 || mesh->mNumVertices == 0) { return; + } // opening tag mOutput << startstr << "" << endstr; @@ -1002,24 +997,23 @@ void ColladaExporter::WriteGeometry( size_t pIndex) // Positions WriteFloatArray( idstr + "-positions", FloatType_Vector, (ai_real*) mesh->mVertices, mesh->mNumVertices); // Normals, if any - if( mesh->HasNormals() ) - WriteFloatArray( idstr + "-normals", FloatType_Vector, (ai_real*) mesh->mNormals, mesh->mNumVertices); + if (mesh->HasNormals()) { + WriteFloatArray(idstr + "-normals", FloatType_Vector, (ai_real*)mesh->mNormals, mesh->mNumVertices); + } // texture coords - for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) - { - if( mesh->HasTextureCoords(static_cast(a)) ) - { + for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { + if( mesh->HasTextureCoords(static_cast(a)) ){ WriteFloatArray( idstr + "-tex" + to_string(a), mesh->mNumUVComponents[a] == 3 ? FloatType_TexCoord3 : FloatType_TexCoord2, (ai_real*) mesh->mTextureCoords[a], mesh->mNumVertices); } } // vertex colors - for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) - { - if( mesh->HasVertexColors(static_cast(a)) ) - WriteFloatArray( idstr + "-color" + to_string(a), FloatType_Color, (ai_real*) mesh->mColors[a], mesh->mNumVertices); + for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { + if (mesh->HasVertexColors(static_cast(a))) { + WriteFloatArray(idstr + "-color" + to_string(a), FloatType_Color, (ai_real*)mesh->mColors[a], mesh->mNumVertices); + } } // assemble vertex structure @@ -1031,40 +1025,43 @@ void ColladaExporter::WriteGeometry( size_t pIndex) mOutput << startstr << "" << endstr; // count the number of lines, triangles and polygon meshes - int countLines = 0; - int countPoly = 0; - for( size_t a = 0; a < mesh->mNumFaces; ++a ) - { - if (mesh->mFaces[a].mNumIndices == 2) countLines++; - else if (mesh->mFaces[a].mNumIndices >= 3) countPoly++; + int countLines( 0 ), countPoly( 0 ); + for( size_t a = 0; a < mesh->mNumFaces; ++a ) { + if (mesh->mFaces[a].mNumIndices == 2) { + countLines++; + } else if (mesh->mFaces[a].mNumIndices >= 3) { + countPoly++; + } } // lines - if (countLines) - { + if (countLines) { mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" << endstr; - if( mesh->HasNormals() ) + 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; + 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 ) - { + for( size_t a = 0; a < mesh->mNumFaces; ++a ) { const aiFace& face = mesh->mFaces[a]; - if (face.mNumIndices != 2) continue; - for( size_t b = 0; b < face.mNumIndices; ++b ) + if (face.mNumIndices != 2) { + continue; + } + for (size_t b = 0; b < face.mNumIndices; ++b) { mOutput << face.mIndices[b] << " "; + } } mOutput << "

" << endstr; PopTag(); @@ -1074,39 +1071,42 @@ void ColladaExporter::WriteGeometry( size_t pIndex) // triangle - don't use it, because compatibility problems // polygons - if (countPoly) - { + if (countPoly) { mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" << endstr; - if( mesh->HasNormals() ) + 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; + 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 ) - { - if (mesh->mFaces[a].mNumIndices < 3) continue; + for( size_t a = 0; a < mesh->mNumFaces; ++a ) { + if (mesh->mFaces[a].mNumIndices < 3) { + continue; + } mOutput << mesh->mFaces[a].mNumIndices << " "; } mOutput << "" << endstr; mOutput << startstr << "

"; - for( size_t a = 0; a < mesh->mNumFaces; ++a ) - { + for( size_t a = 0; a < mesh->mNumFaces; ++a ) { const aiFace& face = mesh->mFaces[a]; - if (face.mNumIndices < 3) continue; - for( size_t b = 0; b < face.mNumIndices; ++b ) + if (face.mNumIndices < 3) { + continue; + } + for (size_t b = 0; b < face.mNumIndices; ++b) { mOutput << face.mIndices[b] << " "; + } } mOutput << "

" << endstr; PopTag(); @@ -1122,18 +1122,23 @@ void ColladaExporter::WriteGeometry( size_t pIndex) // ------------------------------------------------------------------------------------------------ // Writes a float array of the given type -void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataType pType, const ai_real* pData, size_t pElementCount) -{ +void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataType pType, const ai_real* pData, size_t pElementCount) { size_t floatsPerElement = 0; - switch( pType ) - { - case FloatType_Vector: floatsPerElement = 3; break; - 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; + switch( pType ) { + case FloatType_TexCoord2: + floatsPerElement = 2; + break; + case FloatType_Vector: + case FloatType_TexCoord3: + case FloatType_Color: + floatsPerElement = 3; + break; + case FloatType_Mat4x4: floatsPerElement = 16; + break; + case FloatType_Weight: + case FloatType_Time: + floatsPerElement = 1; + break; default: return; } @@ -1147,28 +1152,23 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy mOutput << startstr << " "; PushTag(); - if( pType == FloatType_TexCoord2 ) - { - for( size_t a = 0; a < pElementCount; ++a ) - { + if( pType == FloatType_TexCoord2 ) { + for( size_t a = 0; a < pElementCount; ++a ) { mOutput << pData[a*3+0] << " "; mOutput << pData[a*3+1] << " "; } - } - else if( pType == FloatType_Color ) - { - for( size_t a = 0; a < pElementCount; ++a ) - { + } else if( pType == FloatType_Color ) { + for( size_t a = 0; a < pElementCount; ++a ) { mOutput << pData[a*4+0] << " "; mOutput << pData[a*4+1] << " "; mOutput << pData[a*4+2] << " "; } - } - else - { - for( size_t a = 0; a < pElementCount * floatsPerElement; ++a ) + } else { + for (size_t a = 0; a < pElementCount * floatsPerElement; ++a) { mOutput << pData[a] << " "; + } } + mOutput << "" << endstr; PopTag(); @@ -1178,8 +1178,7 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy mOutput << startstr << "" << endstr; PushTag(); - switch( pType ) - { + switch( pType ) { case FloatType_Vector: mOutput << startstr << "" << endstr; mOutput << startstr << "" << endstr; @@ -1228,8 +1227,7 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy // ------------------------------------------------------------------------------------------------ // Writes the scene library -void ColladaExporter::WriteSceneLibrary() -{ +void ColladaExporter::WriteSceneLibrary() { const std::string scene_name_escaped = XMLEscape(mScene->mRootNode->mName.C_Str()); mOutput << startstr << "" << endstr; @@ -1238,21 +1236,23 @@ void ColladaExporter::WriteSceneLibrary() PushTag(); // start recursive write at the root node - for( size_t a = 0; a < mScene->mRootNode->mNumChildren; ++a ) - WriteNode( mScene, mScene->mRootNode->mChildren[a]); + for (size_t a = 0; a < mScene->mRootNode->mNumChildren; ++a) { + WriteNode(mScene, mScene->mRootNode->mChildren[a]); + } PopTag(); mOutput << startstr << "" << endstr; PopTag(); mOutput << startstr << "" << endstr; } + // ------------------------------------------------------------------------------------------------ -void ColladaExporter::WriteAnimationLibrary(size_t pIndex) -{ +void ColladaExporter::WriteAnimationLibrary(size_t pIndex) { const aiAnimation * anim = mScene->mAnimations[pIndex]; - if ( anim->mNumChannels == 0 && anim->mNumMeshChannels == 0 && anim->mNumMorphMeshChannels ==0 ) - return; + 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(); @@ -1428,7 +1428,7 @@ aiBone* findBone( const aiScene* scene, const char * name) { } } } - return NULL; + return nullptr; } // ------------------------------------------------------------------------------------------------ @@ -1449,7 +1449,7 @@ const aiNode * findBoneNode( const aiNode* aNode, const aiBone* bone) } } - return NULL; + return nullptr; } const aiNode * findSkeletonRootNode( const aiScene* scene, const aiMesh * mesh) @@ -1481,7 +1481,7 @@ const aiNode * findSkeletonRootNode( const aiScene* scene, const aiMesh * mesh) } } - return NULL; + return nullptr; } // ------------------------------------------------------------------------------------------------ @@ -1500,24 +1500,17 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) // 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())) { + if (nullptr == 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())) + if(!pNode->mParent || nullptr == 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 - << "mTransformation; // customized, sid should be 'matrix' to match with loader code. - //mOutput << startstr << ""; mOutput << startstr << ""; mOutput << mat.a1 << " " << mat.a2 << " " << mat.a3 << " " << mat.a4 << " "; From 4f7bacd10888313671f751d3278254417605e083 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 11 Sep 2018 20:01:16 +0200 Subject: [PATCH 009/472] Collada: some reformatting + minor findings. --- code/ColladaExporter.cpp | 452 +++++++++++++++++----------------- code/ColladaExporter.h | 3 +- include/assimp/ParsingUtils.h | 3 +- include/assimp/defs.h | 8 +- 4 files changed, 237 insertions(+), 229 deletions(-) diff --git a/code/ColladaExporter.cpp b/code/ColladaExporter.cpp index 82a755c58..d3abe7366 100644 --- a/code/ColladaExporter.cpp +++ b/code/ColladaExporter.cpp @@ -155,7 +155,6 @@ void ColladaExporter::WriteFile() { // ------------------------------------------------------------------------------------------------ // Writes the asset header void ColladaExporter::WriteHeader() { - static const ai_real epsilon = ai_real( 0.00001 ); static const aiQuaternion x_rot(aiMatrix3x3( 0, -1, 0, 1, 0, 0, @@ -182,19 +181,19 @@ void ColladaExporter::WriteHeader() { bool add_root_node = false; - ai_real scale = 1.0; - if(std::abs(scaling.x - scaling.y) <= epsilon && std::abs(scaling.x - scaling.z) <= epsilon && std::abs(scaling.y - scaling.z) <= epsilon) { + ai_real scale( 1.0 ); + if(std::abs(scaling.x - scaling.y) <= ai_epsilon && std::abs(scaling.x - scaling.z) <= ai_epsilon && std::abs(scaling.y - scaling.z) <= ai_epsilon) { scale = (ai_real) ((((double) scaling.x) + ((double) scaling.y) + ((double) scaling.z)) / 3.0); } else { add_root_node = true; } std::string up_axis = "Y_UP"; - if(rotation.Equal(x_rot, epsilon)) { + if(rotation.Equal(x_rot, ai_epsilon)) { up_axis = "X_UP"; - } else if(rotation.Equal(y_rot, epsilon)) { + } else if(rotation.Equal(y_rot, ai_epsilon)) { up_axis = "Y_UP"; - } else if(rotation.Equal(z_rot, epsilon)) { + } else if(rotation.Equal(z_rot, ai_epsilon)) { up_axis = "Z_UP"; } else { add_root_node = true; @@ -235,15 +234,17 @@ void ColladaExporter::WriteHeader() { aiMetadata* meta = mScene->mRootNode->mMetaData; aiString value; - if (!meta || !meta->Get("Author", value)) + if (!meta || !meta->Get("Author", value)) { mOutput << startstr << "" << "Assimp" << "" << endstr; - else + } else { mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; + } - if (!meta || !meta->Get("AuthoringTool", value)) + if (!meta || !meta->Get("AuthoringTool", value)) { mOutput << startstr << "" << "Assimp Exporter" << "" << endstr; - else + } else { mOutput << startstr << "" << XMLEscape(value.C_Str()) << "" << endstr; + } //mOutput << startstr << "" << mScene->author.C_Str() << "" << endstr; //mOutput << startstr << "" << mScene->authoringTool.C_Str() << "" << endstr; @@ -261,13 +262,12 @@ void ColladaExporter::WriteHeader() { // ------------------------------------------------------------------------------------------------ // Write the embedded textures void ColladaExporter::WriteTextures() { - static const unsigned int buffer_size = 1024; - char str[buffer_size]; - if (!mScene->HasTextures()) { return; } + static const size_t buffer_size = 1024; + char str[buffer_size]; for(unsigned int i = 0; i < mScene->mNumTextures; i++) { // It would be great to be able to create a directory in portable standard C++, but it's not the case, // so we just write the textures in the current directory. @@ -279,7 +279,7 @@ void ColladaExporter::WriteTextures() { std::string name = mFile + "_texture_" + (i < 1000 ? "0" : "") + (i < 100 ? "0" : "") + (i < 10 ? "0" : "") + str + "." + ((const char*) texture->achFormatHint); std::unique_ptr outfile(mIOSystem->Open(mPath + name, "wb")); - if(outfile == NULL) { + if(outfile == nullptr) { throw DeadlyExportError("could not open output texture file: " + mPath + name); } @@ -425,7 +425,7 @@ void ColladaExporter::WritePointLight(const aiLight *const light){ } void ColladaExporter::WriteDirectionalLight(const aiLight *const light){ - const aiColor3D &color= light->mColorDiffuse; + const aiColor3D &color( light->mColorDiffuse ); mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" @@ -437,8 +437,7 @@ void ColladaExporter::WriteDirectionalLight(const aiLight *const light){ } void ColladaExporter::WriteSpotLight(const aiLight *const light){ - - const aiColor3D &color= light->mColorDiffuse; + const aiColor3D &color( light->mColorDiffuse ); mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" @@ -474,7 +473,7 @@ void ColladaExporter::WriteSpotLight(const aiLight *const light){ } void ColladaExporter::WriteAmbienttLight(const aiLight *const light) { - const aiColor3D &color= light->mColorAmbient; + const aiColor3D &color(light->mColorAmbient); mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" @@ -488,18 +487,21 @@ void ColladaExporter::WriteAmbienttLight(const aiLight *const light) { // ------------------------------------------------------------------------------------------------ // Reads a single surface entry from the given material keys void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial* pSrcMat, aiTextureType pTexture, const char* pKey, size_t pType, size_t pIndex) { - if( pSrcMat->GetTextureCount( pTexture) > 0 ) - { + if (pSrcMat->GetTextureCount(pTexture) < 1) { + if (pKey) { + poSurface.exist = pSrcMat->Get(pKey, static_cast(pType), static_cast(pIndex), poSurface.color) == aiReturn_SUCCESS; + } + return; + } + aiString texfile; unsigned int uvChannel = 0; - pSrcMat->GetTexture( pTexture, 0, &texfile, NULL, &uvChannel); + pSrcMat->GetTexture( pTexture, 0, &texfile, nullptr, &uvChannel); std::string index_str(texfile.C_Str()); - if(index_str.size() != 0 && index_str[0] == '*') - { + if(index_str.size() != 0 && index_str[0] == '*') { unsigned int index; - index_str = index_str.substr(1, std::string::npos); try { @@ -507,88 +509,82 @@ void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial* } catch(std::exception& error) { throw DeadlyExportError(error.what()); } - std::map::const_iterator name = textures.find(index); - if(name != textures.end()) { + if (name != textures.end()) { poSurface.texture = name->second; } else { throw DeadlyExportError("could not find embedded texture at index " + index_str); } - } else - { + } else { poSurface.texture = texfile.C_Str(); } poSurface.channel = uvChannel; poSurface.exist = true; - } else - { - if( pKey ) - poSurface.exist = pSrcMat->Get( pKey, static_cast(pType), static_cast(pIndex), poSurface.color) == aiReturn_SUCCESS; - } } // ------------------------------------------------------------------------------------------------ // Reimplementation of isalnum(,C locale), because AppVeyor does not see standard version. -static bool isalnum_C(char c) -{ +static bool isalnum_C(char c) { return ( nullptr != strchr("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",c) ); } // ------------------------------------------------------------------------------------------------ // Writes an image entry for the given surface -void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::string& pNameAdd) -{ - if( !pSurface.texture.empty() ) - { +void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::string& pNameAdd) { + if (pSurface.texture.empty()) { + return; + } + mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << ""; // URL encode image file name first, then XML encode on top std::stringstream imageUrlEncoded; - for( std::string::const_iterator it = pSurface.texture.begin(); it != pSurface.texture.end(); ++it ) - { - if( isalnum_C( (unsigned char) *it) || *it == ':' || *it == '_' || *it == '-' || *it == '.' || *it == '/' || *it == '\\' ) - imageUrlEncoded << *it; - else - imageUrlEncoded << '%' << std::hex << size_t( (unsigned char) *it) << std::dec; + 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 == '/' || *it == '\\') { + imageUrlEncoded << *it; + } else { + imageUrlEncoded << '%' << std::hex << size_t((unsigned char)*it) << std::dec; + } } mOutput << XMLEscape(imageUrlEncoded.str()); mOutput << "" << endstr; PopTag(); mOutput << startstr << "" << endstr; - } } // ------------------------------------------------------------------------------------------------ // Writes a color-or-texture entry into an effect definition -void ColladaExporter::WriteTextureColorEntry( const Surface& pSurface, const std::string& pTypeName, const std::string& pImageName) -{ - if(pSurface.exist) { +void ColladaExporter::WriteTextureColorEntry( const Surface& pSurface, const std::string& pTypeName, + const std::string& pImageName) { + if (!pSurface.exist) { + return; + } + mOutput << startstr << "<" << pTypeName << ">" << endstr; PushTag(); - if( pSurface.texture.empty() ) - { - mOutput << startstr << "" << pSurface.color.r << " " << pSurface.color.g << " " << pSurface.color.b << " " << pSurface.color.a << "" << endstr; - } - else - { - mOutput << startstr << "" << endstr; + if( pSurface.texture.empty() ) { + mOutput << startstr << "" + << pSurface.color.r << " " << pSurface.color.g << " " << pSurface.color.b << " " << pSurface.color.a + << "" << endstr; + } else { + mOutput << startstr << "" << endstr; } PopTag(); mOutput << startstr << "" << endstr; - } } // ------------------------------------------------------------------------------------------------ // Writes the two parameters necessary for referencing a texture in an effect entry -void ColladaExporter::WriteTextureParamEntry( const Surface& pSurface, const std::string& pTypeName, const std::string& pMatName) -{ - // if surface is a texture, write out the sampler and the surface parameters necessary to reference the texture - if( !pSurface.texture.empty() ) - { +void ColladaExporter::WriteTextureParamEntry( const Surface& pSurface, const std::string& pTypeName, const std::string& pMatName) { + if (pSurface.texture.empty()) { + return; + } + + // if surface is a texture, write out the sampler and the surface parameters necessary to reference the texture mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" << endstr; @@ -608,181 +604,194 @@ void ColladaExporter::WriteTextureParamEntry( const Surface& pSurface, const std mOutput << startstr << "" << endstr; PopTag(); mOutput << startstr << "" << endstr; - } } // ------------------------------------------------------------------------------------------------ // Writes a scalar property void ColladaExporter::WriteFloatEntry( const Property& pProperty, const std::string& pTypeName) { - if(pProperty.exist) { - mOutput << startstr << "<" << pTypeName << ">" << endstr; - PushTag(); - mOutput << startstr << "" << pProperty.value << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; + if (!pProperty.exist) { + return; } + + mOutput << startstr << "<" << pTypeName << ">" << endstr; + PushTag(); + mOutput << startstr << "" << pProperty.value << "" << endstr; + PopTag(); + mOutput << startstr << "" << endstr; } // ------------------------------------------------------------------------------------------------ // Writes the material setup -void ColladaExporter::WriteMaterials() +void ColladaExporter::WriteMaterials() { + materials.resize( mScene->mNumMaterials); + + // collect all materials from the scene + size_t numTextures = 0; + for( size_t a = 0; a < mScene->mNumMaterials; ++a ) { + const aiMaterial* mat = mScene->mMaterials[a]; + aiString name; + if( mat->Get( AI_MATKEY_NAME, name) != aiReturn_SUCCESS ) { + name = "mat"; + materials[a].name = std::string( "m") + to_string(a) + name.C_Str(); + } else { + // try to use the material's name if no other material has already taken it, else append # + std::string testName = name.C_Str(); + size_t materialCountWithThisName = 0; + for( size_t i = 0; i < a; i ++ ) { + if( materials[i].name == testName ) { + ++materialCountWithThisName; + } + } + if( materialCountWithThisName == 0 ) { + materials[a].name = name.C_Str(); + } else { + 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 ) { + if( !isalnum_C( *it ) ) { + *it = '_'; + } + } + + aiShadingMode shading = aiShadingMode_Flat; + materials[a].shading_model = "phong"; + if(mat->Get( AI_MATKEY_SHADING_MODEL, shading) == aiReturn_SUCCESS) { + if(shading == aiShadingMode_Phong) { + materials[a].shading_model = "phong"; + } else if(shading == aiShadingMode_Blinn) { + materials[a].shading_model = "blinn"; + } else if(shading == aiShadingMode_NoShading) { + materials[a].shading_model = "constant"; + } else if(shading == aiShadingMode_Gouraud) { + materials[a].shading_model = "lambert"; + } + } + + ReadMaterialSurface( materials[a].ambient, mat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT); + if (!materials[a].ambient.texture.empty()) { + ++numTextures; + } + ReadMaterialSurface( materials[a].diffuse, mat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE); + if (!materials[a].diffuse.texture.empty()) { + ++numTextures; + } + ReadMaterialSurface( materials[a].specular, mat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR); + if (!materials[a].specular.texture.empty()) { + numTextures++; + } + ReadMaterialSurface( materials[a].emissive, mat, aiTextureType_EMISSIVE, AI_MATKEY_COLOR_EMISSIVE); + if (!materials[a].emissive.texture.empty()) { + numTextures++; + } + ReadMaterialSurface( materials[a].reflective, mat, aiTextureType_REFLECTION, AI_MATKEY_COLOR_REFLECTIVE); + if (!materials[a].reflective.texture.empty()) { + numTextures++; + } + ReadMaterialSurface( materials[a].transparent, mat, aiTextureType_OPACITY, AI_MATKEY_COLOR_TRANSPARENT); + if (!materials[a].transparent.texture.empty()) { + numTextures++; + } + ReadMaterialSurface( materials[a].normal, mat, aiTextureType_NORMALS, NULL, 0, 0); + if (!materials[a].normal.texture.empty()) { + numTextures++; + } + +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].index_refraction.exist = mat->Get( AI_MATKEY_REFRACTI, materials[a].index_refraction.value) == aiReturn_SUCCESS; +} + +// output textures if present +if( numTextures > 0 ) { - materials.resize( mScene->mNumMaterials); +mOutput << startstr << "" << endstr; +PushTag(); +for( std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it ) +{ +const Material& mat = *it; +WriteImageEntry( mat.ambient, mat.name + "-ambient-image"); +WriteImageEntry( mat.diffuse, mat.name + "-diffuse-image"); +WriteImageEntry( mat.specular, mat.name + "-specular-image"); +WriteImageEntry( mat.emissive, mat.name + "-emission-image"); +WriteImageEntry( mat.reflective, mat.name + "-reflective-image"); +WriteImageEntry( mat.transparent, mat.name + "-transparent-image"); +WriteImageEntry( mat.normal, mat.name + "-normal-image"); +} +PopTag(); +mOutput << startstr << "" << endstr; +} - /// collect all materials from the scene - size_t numTextures = 0; - for( size_t a = 0; a < mScene->mNumMaterials; ++a ) - { - const aiMaterial* mat = mScene->mMaterials[a]; +// output effects - those are the actual carriers of information +if( !materials.empty() ) +{ +mOutput << startstr << "" << endstr; +PushTag(); +for( std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it ) +{ +const Material& mat = *it; +// this is so ridiculous it must be right +mOutput << startstr << "" << endstr; +PushTag(); +mOutput << startstr << "" << endstr; +PushTag(); - aiString name; - if( mat->Get( AI_MATKEY_NAME, name) != aiReturn_SUCCESS ) { - name = "mat"; - materials[a].name = std::string( "m") + to_string(a) + name.C_Str(); - } else { - // try to use the material's name if no other material has already taken it, else append # - std::string testName = name.C_Str(); - size_t materialCountWithThisName = 0; - for( size_t i = 0; i < a; i ++ ) { - if( materials[i].name == testName ) { - materialCountWithThisName ++; - } - } - if( materialCountWithThisName == 0 ) { - materials[a].name = name.C_Str(); - } else { - 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 ) { - if( !isalnum_C( *it ) ) { - *it = '_'; - } - } +// write sampler- and surface params for the texture entries +WriteTextureParamEntry( mat.emissive, "emission", mat.name); +WriteTextureParamEntry( mat.ambient, "ambient", mat.name); +WriteTextureParamEntry( mat.diffuse, "diffuse", mat.name); +WriteTextureParamEntry( mat.specular, "specular", mat.name); +WriteTextureParamEntry( mat.reflective, "reflective", mat.name); +WriteTextureParamEntry( mat.transparent, "transparent", mat.name); +WriteTextureParamEntry( mat.normal, "normal", mat.name); - aiShadingMode shading = aiShadingMode_Flat; - materials[a].shading_model = "phong"; - if(mat->Get( AI_MATKEY_SHADING_MODEL, shading) == aiReturn_SUCCESS) { - if(shading == aiShadingMode_Phong) { - materials[a].shading_model = "phong"; - } else if(shading == aiShadingMode_Blinn) { - materials[a].shading_model = "blinn"; - } else if(shading == aiShadingMode_NoShading) { - materials[a].shading_model = "constant"; - } else if(shading == aiShadingMode_Gouraud) { - materials[a].shading_model = "lambert"; - } - } +mOutput << startstr << "" << endstr; +PushTag(); +mOutput << startstr << "<" << mat.shading_model << ">" << endstr; +PushTag(); - ReadMaterialSurface( materials[a].ambient, mat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT); - if( !materials[a].ambient.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].diffuse, mat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE); - if( !materials[a].diffuse.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].specular, mat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR); - if( !materials[a].specular.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].emissive, mat, aiTextureType_EMISSIVE, AI_MATKEY_COLOR_EMISSIVE); - if( !materials[a].emissive.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].reflective, mat, aiTextureType_REFLECTION, AI_MATKEY_COLOR_REFLECTIVE); - if( !materials[a].reflective.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].transparent, mat, aiTextureType_OPACITY, AI_MATKEY_COLOR_TRANSPARENT); - if( !materials[a].transparent.texture.empty() ) numTextures++; - ReadMaterialSurface( materials[a].normal, mat, aiTextureType_NORMALS, NULL, 0, 0); - if( !materials[a].normal.texture.empty() ) numTextures++; +WriteTextureColorEntry( mat.emissive, "emission", mat.name + "-emission-sampler"); +WriteTextureColorEntry( mat.ambient, "ambient", mat.name + "-ambient-sampler"); +WriteTextureColorEntry( mat.diffuse, "diffuse", mat.name + "-diffuse-sampler"); +WriteTextureColorEntry( mat.specular, "specular", mat.name + "-specular-sampler"); +WriteFloatEntry(mat.shininess, "shininess"); +WriteTextureColorEntry( mat.reflective, "reflective", mat.name + "-reflective-sampler"); +WriteTextureColorEntry( mat.transparent, "transparent", mat.name + "-transparent-sampler"); +WriteFloatEntry(mat.transparency, "transparency"); +WriteFloatEntry(mat.index_refraction, "index_of_refraction"); - 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].index_refraction.exist = mat->Get( AI_MATKEY_REFRACTI, materials[a].index_refraction.value) == aiReturn_SUCCESS; - } +if(! mat.normal.texture.empty()) { +WriteTextureColorEntry( mat.normal, "bump", mat.name + "-normal-sampler"); +} - // output textures if present - if( numTextures > 0 ) - { - mOutput << startstr << "" << endstr; - PushTag(); - for( std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it ) - { - const Material& mat = *it; - WriteImageEntry( mat.ambient, mat.name + "-ambient-image"); - WriteImageEntry( mat.diffuse, mat.name + "-diffuse-image"); - WriteImageEntry( mat.specular, mat.name + "-specular-image"); - WriteImageEntry( mat.emissive, mat.name + "-emission-image"); - WriteImageEntry( mat.reflective, mat.name + "-reflective-image"); - WriteImageEntry( mat.transparent, mat.name + "-transparent-image"); - WriteImageEntry( mat.normal, mat.name + "-normal-image"); - } - PopTag(); - mOutput << startstr << "" << endstr; - } +PopTag(); +mOutput << startstr << "" << endstr; +PopTag(); +mOutput << startstr << "" << endstr; +PopTag(); +mOutput << startstr << "" << endstr; +PopTag(); +mOutput << startstr << "" << endstr; +} +PopTag(); +mOutput << startstr << "" << endstr; - // output effects - those are the actual carriers of information - if( !materials.empty() ) - { - mOutput << startstr << "" << endstr; - PushTag(); - for( std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it ) - { - const Material& mat = *it; - // this is so ridiculous it must be right - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - - // write sampler- and surface params for the texture entries - WriteTextureParamEntry( mat.emissive, "emission", mat.name); - WriteTextureParamEntry( mat.ambient, "ambient", mat.name); - WriteTextureParamEntry( mat.diffuse, "diffuse", mat.name); - WriteTextureParamEntry( mat.specular, "specular", mat.name); - WriteTextureParamEntry( mat.reflective, "reflective", mat.name); - WriteTextureParamEntry( mat.transparent, "transparent", mat.name); - WriteTextureParamEntry( mat.normal, "normal", mat.name); - - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "<" << mat.shading_model << ">" << endstr; - PushTag(); - - WriteTextureColorEntry( mat.emissive, "emission", mat.name + "-emission-sampler"); - WriteTextureColorEntry( mat.ambient, "ambient", mat.name + "-ambient-sampler"); - WriteTextureColorEntry( mat.diffuse, "diffuse", mat.name + "-diffuse-sampler"); - WriteTextureColorEntry( mat.specular, "specular", mat.name + "-specular-sampler"); - WriteFloatEntry(mat.shininess, "shininess"); - WriteTextureColorEntry( mat.reflective, "reflective", mat.name + "-reflective-sampler"); - WriteTextureColorEntry( mat.transparent, "transparent", mat.name + "-transparent-sampler"); - WriteFloatEntry(mat.transparency, "transparency"); - WriteFloatEntry(mat.index_refraction, "index_of_refraction"); - - if(! mat.normal.texture.empty()) { - WriteTextureColorEntry( mat.normal, "bump", mat.name + "-normal-sampler"); - } - - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - } - PopTag(); - mOutput << startstr << "" << endstr; - - // write materials - they're just effect references - mOutput << startstr << "" << endstr; - PushTag(); - for( std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it ) - { - const Material& mat = *it; - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - } - PopTag(); - mOutput << startstr << "" << endstr; - } +// write materials - they're just effect references +mOutput << startstr << "" << endstr; +PushTag(); +for( std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it ) +{ +const Material& mat = *it; +mOutput << startstr << "" << endstr; +PushTag(); +mOutput << startstr << "" << endstr; +PopTag(); +mOutput << startstr << "" << endstr; +} +PopTag(); +mOutput << startstr << "" << endstr; +} } // ------------------------------------------------------------------------------------------------ @@ -1611,8 +1620,9 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) } // recurse into subnodes - for( size_t a = 0; a < pNode->mNumChildren; ++a ) - WriteNode( pScene, pNode->mChildren[a]); + for (size_t a = 0; a < pNode->mNumChildren; ++a) { + WriteNode(pScene, pNode->mChildren[a]); + } PopTag(); mOutput << startstr << "" << endstr; diff --git a/code/ColladaExporter.h b/code/ColladaExporter.h index d1a307532..65f82d4ad 100644 --- a/code/ColladaExporter.h +++ b/code/ColladaExporter.h @@ -150,7 +150,6 @@ public: /// Stringstream to write all output into std::stringstream mOutput; -protected: /// The IOSystem for output IOSystem* mIOSystem; @@ -204,7 +203,7 @@ protected: std::map textures; -protected: +public: /// Dammit C++ - y u no compile two-pass? No I have to add all methods below the struct definitions /// Reads a single surface entry from the given material keys void ReadMaterialSurface( Surface& poSurface, const aiMaterial* pSrcMat, aiTextureType pTexture, const char* pKey, size_t pType, size_t pIndex); diff --git a/include/assimp/ParsingUtils.h b/include/assimp/ParsingUtils.h index 4553072db..9b3a9ddce 100644 --- a/include/assimp/ParsingUtils.h +++ b/include/assimp/ParsingUtils.h @@ -196,8 +196,7 @@ bool GetNextLine( const char_t*& buffer, char_t out[ BufferSize ] ) { // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool IsNumeric( char_t in) -{ +AI_FORCE_INLINE bool IsNumeric( char_t in) { return ( in >= '0' && in <= '9' ) || '-' == in || '+' == in; } diff --git a/include/assimp/defs.h b/include/assimp/defs.h index b587396bf..b2e837eef 100644 --- a/include/assimp/defs.h +++ b/include/assimp/defs.h @@ -213,10 +213,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif #if (defined(__BORLANDC__) || defined (__BCPLUSPLUS__)) -#error Currently, Borland is unsupported. Feel free to port Assimp. - -// "W8059 Packgröße der Struktur geändert" - +# error Currently, Borland is unsupported. Feel free to port Assimp. #endif @@ -266,6 +263,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_DEG_TO_RAD(x) ((x)*(ai_real)0.0174532925) #define AI_RAD_TO_DEG(x) ((x)*(ai_real)57.2957795) +/* Numerical limits */ +static const ai_real ai_epsilon = (ai_real) 0.00001; + /* Support for big-endian builds */ #if defined(__BYTE_ORDER__) # if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) From 27b331eb0c40485b0072eb7f29e5ce0b8312c092 Mon Sep 17 00:00:00 2001 From: Marco Di Benedetto Date: Thu, 18 Oct 2018 18:46:02 +0200 Subject: [PATCH 010/472] disabled static zlib build --- contrib/zlib/CMakeLists.txt | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/contrib/zlib/CMakeLists.txt b/contrib/zlib/CMakeLists.txt index 5f1368adb..a13b7725e 100644 --- a/contrib/zlib/CMakeLists.txt +++ b/contrib/zlib/CMakeLists.txt @@ -130,12 +130,6 @@ set(ZLIB_SRCS zutil.c ) -if(NOT MINGW) - set(ZLIB_DLL_SRCS - win32/zlib1.rc # If present will override custom build rule below. - ) -endif() - if(CMAKE_COMPILER_IS_GNUCC) if(ASM686) set(ZLIB_ASMS contrib/asm686/match.S) @@ -174,26 +168,7 @@ file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h _zlib_h_contents) string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*" "\\1" ZLIB_FULL_VERSION ${_zlib_h_contents}) -if(MINGW) - # This gets us DLL resource information when compiling on MinGW. - if(NOT CMAKE_RC_COMPILER) - set(CMAKE_RC_COMPILER windres.exe) - endif() - - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj - COMMAND ${CMAKE_RC_COMPILER} - -D GCC_WINDRES - -I ${CMAKE_CURRENT_SOURCE_DIR} - -I ${CMAKE_CURRENT_BINARY_DIR} - -o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj - -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc) - 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} From e97d07ce82bec02b72ed832335820a2b8059ae97 Mon Sep 17 00:00:00 2001 From: escherstair Date: Thu, 8 Nov 2018 09:25:48 +0100 Subject: [PATCH 011/472] add clang to pushpack1.h --- include/assimp/Compiler/pushpack1.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/assimp/Compiler/pushpack1.h b/include/assimp/Compiler/pushpack1.h index 94ee1e474..4c9fbb857 100644 --- a/include/assimp/Compiler/pushpack1.h +++ b/include/assimp/Compiler/pushpack1.h @@ -25,7 +25,7 @@ #if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) # pragma pack(push,1) # define PACK_STRUCT -#elif defined( __GNUC__ ) +#elif defined( __GNUC__ ) || defined(__clang__) # if !defined(HOST_MINGW) # define PACK_STRUCT __attribute__((__packed__)) # else From 97450fcb5511886e35ff68e33da3f4060c0186d6 Mon Sep 17 00:00:00 2001 From: mnml_ Date: Thu, 8 Nov 2018 11:44:44 +0100 Subject: [PATCH 012/472] added DropFaceNormalsProcess to out vector --- code/PostStepRegistry.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/PostStepRegistry.cpp b/code/PostStepRegistry.cpp index a04092d3a..646aeaeb0 100644 --- a/code/PostStepRegistry.cpp +++ b/code/PostStepRegistry.cpp @@ -203,6 +203,9 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out) #if (!defined ASSIMP_BUILD_NO_SPLITLARGEMESHES_PROCESS) out.push_back( new SplitLargeMeshesProcess_Triangle()); #endif +#if (!defined ASSIMP_BUILD_NO_GENFACENORMALS_PROCESS) + out.push_back( new DropFaceNormalsProcess()); +#endif #if (!defined ASSIMP_BUILD_NO_GENFACENORMALS_PROCESS) out.push_back( new GenFaceNormalsProcess()); #endif From b47739cfb8190328afd5f0394a35c517e5ad8e94 Mon Sep 17 00:00:00 2001 From: escherstair Date: Thu, 8 Nov 2018 11:47:09 +0100 Subject: [PATCH 013/472] build AppVeyor clang_on_Windows branch --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 2b5f212f9..213cbaf75 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,7 +8,7 @@ clone_folder: c:\projects\assimp branches: # whitelist only: - - master + - clang_on_Windows matrix: fast_finish: true From d5c9b27af887f2223ca8a0ecf4ce9aac6c0b0f64 Mon Sep 17 00:00:00 2001 From: mnml_ Date: Thu, 8 Nov 2018 12:49:35 +0100 Subject: [PATCH 014/472] delete[] doesnt set nullptr --- code/DropFaceNormalsProcess.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/code/DropFaceNormalsProcess.cpp b/code/DropFaceNormalsProcess.cpp index 3800fee0b..57e8b972b 100644 --- a/code/DropFaceNormalsProcess.cpp +++ b/code/DropFaceNormalsProcess.cpp @@ -104,5 +104,6 @@ bool DropFaceNormalsProcess::DropMeshFaceNormals (aiMesh* pMesh) { } delete[] pMesh->mNormals; + pMesh->mNormals = nullptr; return true; } From deb9eb974b09fbb6904aa32657ff2e5a74efb8c8 Mon Sep 17 00:00:00 2001 From: escherstair Date: Thu, 8 Nov 2018 13:40:04 +0100 Subject: [PATCH 015/472] Update appveyor.yml --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 213cbaf75..2b5f212f9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,7 +8,7 @@ clone_folder: c:\projects\assimp branches: # whitelist only: - - clang_on_Windows + - master matrix: fast_finish: true From 850d57b39d5e6746e649a1d638274a20af0d770b Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 8 Nov 2018 22:12:05 +0100 Subject: [PATCH 016/472] closes https://github.com/assimp/assimp/issues/2206: make bone error in verification more verbose. --- code/ValidateDataStructure.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/code/ValidateDataStructure.cpp b/code/ValidateDataStructure.cpp index ed6bde724..3bdae5166 100644 --- a/code/ValidateDataStructure.cpp +++ b/code/ValidateDataStructure.cpp @@ -491,8 +491,12 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh) { if (pMesh->mBones[i]->mName == pMesh->mBones[a]->mName) { - ReportError("aiMesh::mBones[%i] has the same name as " - "aiMesh::mBones[%i]",i,a); + std::string name; + if (nullptr != pMesh->mBones[ i ]->mName.C_Str()) { + name = pMesh->mBones[ i ]->mName.C_Str(); + } + ReportError("aiMesh::mBones[%i], name = \"%s\" has the same name as " + "aiMesh::mBones[%i]", i, name, a ); } } } From e787604ff17c1e8280b6437d1bb7af72996b4c4f Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 9 Nov 2018 11:54:12 +0100 Subject: [PATCH 017/472] Update ValidateDataStructure.cpp Integrate review findings. --- code/ValidateDataStructure.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/ValidateDataStructure.cpp b/code/ValidateDataStructure.cpp index 3bdae5166..931c52822 100644 --- a/code/ValidateDataStructure.cpp +++ b/code/ValidateDataStructure.cpp @@ -491,7 +491,7 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh) { if (pMesh->mBones[i]->mName == pMesh->mBones[a]->mName) { - std::string name; + const char *name = "unknown"; if (nullptr != pMesh->mBones[ i ]->mName.C_Str()) { name = pMesh->mBones[ i ]->mName.C_Str(); } From c30c4ae6e287f443d01e273451799011b0e15fd8 Mon Sep 17 00:00:00 2001 From: ruyo Date: Sun, 11 Nov 2018 14:27:11 +0900 Subject: [PATCH 018/472] glTF2 importer multiple primitives and 16-bit index buffer skinmesh support. --- code/glTF2Importer.cpp | 74 ++++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 277eddcfd..e8d2a2d95 100755 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -732,9 +732,9 @@ static void GetNodeTransform(aiMatrix4x4& matrix, const glTF2::Node& node) { } } -static void BuildVertexWeightMapping(Ref& mesh, std::vector>& map) +static void BuildVertexWeightMapping(Mesh::Primitive& primitive, std::vector>& map) { - Mesh::Primitive::Attributes& attr = mesh->primitives[0].attributes; + Mesh::Primitive::Attributes& attr = primitive.attributes; if (attr.weight.empty() || attr.joint.empty()) { return; } @@ -745,15 +745,22 @@ static void BuildVertexWeightMapping(Ref& mesh, std::vectorcount; struct Weights { float values[4]; }; - struct Indices { uint8_t values[4]; }; Weights* weights = nullptr; - Indices* indices = nullptr; attr.weight[0]->ExtractData(weights); - attr.joint[0]->ExtractData(indices); + + struct Indices8 { uint8_t values[4]; }; + struct Indices16 { uint16_t values[4]; }; + Indices8* indices8 = nullptr; + Indices16* indices16 = nullptr; + if (attr.joint[0]->GetElementSize() == 4) { + attr.joint[0]->ExtractData(indices8); + }else { + attr.joint[0]->ExtractData(indices16); + } for (int i = 0; i < num_vertices; ++i) { for (int j = 0; j < 4; ++j) { - const unsigned int bone = indices[i].values[j]; + const unsigned int bone = (indices8!=nullptr) ? indices8[i].values[j] : indices16[i].values[j]; const float weight = weights[i].values[j]; if (weight > 0 && bone < map.size()) { map[bone].reserve(8); @@ -763,7 +770,8 @@ static void BuildVertexWeightMapping(Ref& mesh, std::vector& meshOffsets, glTF2::Ref& ptr) @@ -797,37 +805,39 @@ aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector& ainode->mMeshes = new unsigned int[count]; if (node.skin) { - aiMesh* mesh = pScene->mMeshes[meshOffsets[mesh_idx]]; - mesh->mNumBones = node.skin->jointNames.size(); - mesh->mBones = new aiBone*[mesh->mNumBones]; + for (int primitiveNo = 0; primitiveNo < count; ++primitiveNo) { + aiMesh* mesh = pScene->mMeshes[meshOffsets[mesh_idx]+primitiveNo]; + mesh->mNumBones = node.skin->jointNames.size(); + mesh->mBones = new aiBone*[mesh->mNumBones]; - // GLTF and Assimp choose to store bone weights differently. - // GLTF has each vertex specify which bones influence the vertex. - // Assimp has each bone specify which vertices it has influence over. - // To convert this data, we first read over the vertex data and pull - // out the bone-to-vertex mapping. Then, when creating the aiBones, - // we copy the bone-to-vertex mapping into the bone. This is unfortunate - // both because it's somewhat slow and because, for many applications, - // we then need to reconvert the data back into the vertex-to-bone - // mapping which makes things doubly-slow. - std::vector> weighting(mesh->mNumBones); - BuildVertexWeightMapping(node.meshes[0], weighting); + // GLTF and Assimp choose to store bone weights differently. + // GLTF has each vertex specify which bones influence the vertex. + // Assimp has each bone specify which vertices it has influence over. + // To convert this data, we first read over the vertex data and pull + // out the bone-to-vertex mapping. Then, when creating the aiBones, + // we copy the bone-to-vertex mapping into the bone. This is unfortunate + // both because it's somewhat slow and because, for many applications, + // we then need to reconvert the data back into the vertex-to-bone + // mapping which makes things doubly-slow. + std::vector> weighting(mesh->mNumBones); + BuildVertexWeightMapping(node.meshes[0]->primitives[primitiveNo], weighting); - for (size_t i = 0; i < mesh->mNumBones; ++i) { - aiBone* bone = new aiBone(); + for (size_t i = 0; i < mesh->mNumBones; ++i) { + aiBone* bone = new aiBone(); - Ref joint = node.skin->jointNames[i]; - bone->mName = joint->name; - GetNodeTransform(bone->mOffsetMatrix, *joint); + Ref joint = node.skin->jointNames[i]; + bone->mName = joint->name; + GetNodeTransform(bone->mOffsetMatrix, *joint); - std::vector& weights = weighting[i]; + std::vector& weights = weighting[i]; - bone->mNumWeights = weights.size(); - if (bone->mNumWeights > 0) { - bone->mWeights = new aiVertexWeight[bone->mNumWeights]; - memcpy(bone->mWeights, weights.data(), bone->mNumWeights * sizeof(aiVertexWeight)); + bone->mNumWeights = weights.size(); + if (bone->mNumWeights > 0) { + bone->mWeights = new aiVertexWeight[bone->mNumWeights]; + memcpy(bone->mWeights, weights.data(), bone->mNumWeights * sizeof(aiVertexWeight)); + } + mesh->mBones[i] = bone; } - mesh->mBones[i] = bone; } } From b6af80f2fd31804542e0ae6bea098cb3944d0009 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 12 Nov 2018 22:26:10 +0100 Subject: [PATCH 019/472] closes https://github.com/assimp/assimp/issues/2199: introduce first version for exporter. --- code/DefaultProgressHandler.h | 4 +- code/Exporter.cpp | 122 ++++++++++++++++---------- code/Importer.cpp | 15 ++-- include/assimp/Exporter.hpp | 17 +++- include/assimp/Importer.hpp | 2 +- include/assimp/ProgressHandler.hpp | 24 ++++- test/CMakeLists.txt | 1 + test/unit/ImportExport/utExporter.cpp | 74 ++++++++++++++++ 8 files changed, 194 insertions(+), 65 deletions(-) create mode 100644 test/unit/ImportExport/utExporter.cpp diff --git a/code/DefaultProgressHandler.h b/code/DefaultProgressHandler.h index a40501fe5..851c17be6 100644 --- a/code/DefaultProgressHandler.h +++ b/code/DefaultProgressHandler.h @@ -52,9 +52,7 @@ namespace Assimp { // ------------------------------------------------------------------------------------ /** @brief Internal default implementation of the #ProgressHandler interface. */ -class DefaultProgressHandler - : public ProgressHandler { - +class DefaultProgressHandler : public ProgressHandler { virtual bool Update(float /*percentage*/) { return false; diff --git a/code/Exporter.cpp b/code/Exporter.cpp index 725d7bf5a..63a934091 100644 --- a/code/Exporter.cpp +++ b/code/Exporter.cpp @@ -56,22 +56,22 @@ Here we implement only the C++ interface (Assimp::Exporter). #include #include -#include "BaseProcess.h" -#include "Importer.h" // need this for GetPostProcessingStepInstanceList() +#include +#include +#include +#include +#include +#include "DefaultProgressHandler.h" +#include "BaseProcess.h" #include "JoinVerticesProcess.h" #include "MakeVerboseFormat.h" #include "ConvertToLHProcess.h" #include "PretransformVertices.h" #include #include "ScenePrivate.h" -#include -#include -#include -#include -#include -#include +#include namespace Assimp { @@ -188,10 +188,14 @@ Exporter::ExportFormatEntry gExporters[] = class ExporterPimpl { public: ExporterPimpl() - : blob() - , mIOSystem(new Assimp::DefaultIOSystem()) - , mIsDefaultIOHandler(true) - { + : blob() + , mIOSystem(new Assimp::DefaultIOSystem()) + , mIsDefaultIOHandler(true) + , mProgressHandler( nullptr ) + , mIsDefaultProgressHandler( true ) + , mPostProcessingSteps() + , mError() + , mExporters() { GetPostProcessingStepInstanceList(mPostProcessingSteps); // grab all built-in exporters @@ -201,8 +205,7 @@ public: } } - ~ExporterPimpl() - { + ~ExporterPimpl() { delete blob; // Delete all post-processing plug-ins @@ -216,6 +219,10 @@ public: std::shared_ptr< Assimp::IOSystem > mIOSystem; bool mIsDefaultIOHandler; + /** The progress handler */ + ProgressHandler *mProgressHandler; + bool mIsDefaultProgressHandler; + /** Post processing steps we can apply at the imported data. */ std::vector< BaseProcess* > mPostProcessingSteps; @@ -233,13 +240,16 @@ using namespace Assimp; // ------------------------------------------------------------------------------------------------ Exporter :: Exporter() : pimpl(new ExporterPimpl()) { - // empty + pimpl->mProgressHandler = new DefaultProgressHandler(); } // ------------------------------------------------------------------------------------------------ Exporter::~Exporter() { FreeBlob(); - + if (pimpl->mIsDefaultProgressHandler) { + delete pimpl->mProgressHandler; + pimpl->mProgressHandler = nullptr; + } delete pimpl; } @@ -259,12 +269,32 @@ bool Exporter::IsDefaultIOHandler() const { return pimpl->mIsDefaultIOHandler; } +// ------------------------------------------------------------------------------------------------ +void Exporter::SetProgressHandler(ProgressHandler* pHandler) { + ai_assert(nullptr != pimpl); + + if ( nullptr == pHandler) { + // Release pointer in the possession of the caller + pimpl->mProgressHandler = new DefaultProgressHandler(); + pimpl->mIsDefaultProgressHandler = true; + return; + } + + if (pimpl->mProgressHandler == pHandler) { + return; + } + + delete pimpl->mProgressHandler; + pimpl->mProgressHandler = pHandler; + pimpl->mIsDefaultProgressHandler = false; +} + // ------------------------------------------------------------------------------------------------ const aiExportDataBlob* Exporter::ExportToBlob( const aiScene* pScene, const char* pFormatId, unsigned int, const ExportProperties* /*pProperties*/ ) { if (pimpl->blob) { delete pimpl->blob; - pimpl->blob = NULL; + pimpl->blob = nullptr; } std::shared_ptr old = pimpl->mIOSystem; @@ -273,7 +303,7 @@ const aiExportDataBlob* Exporter::ExportToBlob( const aiScene* pScene, const cha if (AI_SUCCESS != Export(pScene,pFormatId,blobio->GetMagicFileName())) { pimpl->mIOSystem = old; - return NULL; + return nullptr; } pimpl->blob = blobio->GetBlobChain(); @@ -295,6 +325,7 @@ bool IsVerboseFormat(const aiMesh* mesh) { } } } + return true; } @@ -305,6 +336,7 @@ bool IsVerboseFormat(const aiScene* pScene) { return false; } } + return true; } @@ -319,6 +351,8 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c // meshes upfront. const bool is_verbose_format = !(pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) || IsVerboseFormat(pScene); + pimpl->mProgressHandler->UpdateFileWrite(0, 4); + pimpl->mError = ""; for (size_t i = 0; i < pimpl->mExporters.size(); ++i) { const Exporter::ExportFormatEntry& exp = pimpl->mExporters[i]; @@ -326,9 +360,11 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c 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; + aiScene* scenecopy_tmp = nullptr; SceneCombiner::CopyScene(&scenecopy_tmp,pScene); + pimpl->mProgressHandler->UpdateFileWrite(1, 4); + std::unique_ptr scenecopy(scenecopy_tmp); const ScenePrivateData* const priv = ScenePriv(pScene); @@ -375,6 +411,8 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c } } + pimpl->mProgressHandler->UpdateFileWrite(2, 4); + if (pp) { // the three 'conversion' steps need to be executed first because all other steps rely on the standard data layout { @@ -418,11 +456,13 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c } } ScenePrivateData* const privOut = ScenePriv(scenecopy.get()); - ai_assert(privOut); + ai_assert(nullptr != privOut); privOut->mPPStepsApplied |= pp; } + pimpl->mProgressHandler->UpdateFileWrite(3, 4); + if(must_join_again) { JoinVerticesProcess proc; proc.Execute(scenecopy.get()); @@ -430,6 +470,8 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c ExportProperties emptyProperties; // Never pass NULL ExportProperties so Exporters don't have to worry. exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProperties ? pProperties : &emptyProperties); + + pimpl->mProgressHandler->UpdateFileWrite(4, 4); } catch (DeadlyExportError& err) { pimpl->mError = err.what(); return AI_FAILURE; @@ -452,7 +494,7 @@ const char* Exporter::GetErrorString() const { // ------------------------------------------------------------------------------------------------ void Exporter::FreeBlob() { delete pimpl->blob; - pimpl->blob = NULL; + pimpl->blob = nullptr; pimpl->mError = ""; } @@ -465,7 +507,7 @@ const aiExportDataBlob* Exporter::GetBlob() const { // ------------------------------------------------------------------------------------------------ const aiExportDataBlob* Exporter::GetOrphanedBlob() const { const aiExportDataBlob* tmp = pimpl->blob; - pimpl->blob = NULL; + pimpl->blob = nullptr; return tmp; } @@ -545,75 +587,63 @@ bool ExportProperties::SetPropertyString(const char* szName, const std::string& // ------------------------------------------------------------------------------------------------ // Set a configuration property -bool ExportProperties :: SetPropertyMatrix(const char* szName, const aiMatrix4x4& value) -{ +bool ExportProperties::SetPropertyMatrix(const char* szName, const aiMatrix4x4& value) { return SetGenericProperty(mMatrixProperties, szName,value); } // ------------------------------------------------------------------------------------------------ // Get a configuration property -int ExportProperties :: GetPropertyInteger(const char* szName, - int iErrorReturn /*= 0xffffffff*/) const -{ +int ExportProperties::GetPropertyInteger(const char* szName, int iErrorReturn /*= 0xffffffff*/) const { return GetGenericProperty(mIntProperties,szName,iErrorReturn); } // ------------------------------------------------------------------------------------------------ // Get a configuration property -ai_real ExportProperties :: GetPropertyFloat(const char* szName, - ai_real iErrorReturn /*= 10e10*/) const -{ +ai_real ExportProperties::GetPropertyFloat(const char* szName, ai_real iErrorReturn /*= 10e10*/) const { return GetGenericProperty(mFloatProperties,szName,iErrorReturn); } // ------------------------------------------------------------------------------------------------ // Get a configuration property -const std::string ExportProperties :: GetPropertyString(const char* szName, - const std::string& iErrorReturn /*= ""*/) const -{ +const std::string ExportProperties::GetPropertyString(const char* szName, + const std::string& iErrorReturn /*= ""*/) const { return GetGenericProperty(mStringProperties,szName,iErrorReturn); } // ------------------------------------------------------------------------------------------------ // Has a configuration property -const aiMatrix4x4 ExportProperties :: GetPropertyMatrix(const char* szName, - const aiMatrix4x4& iErrorReturn /*= aiMatrix4x4()*/) const -{ +const aiMatrix4x4 ExportProperties::GetPropertyMatrix(const char* szName, + const aiMatrix4x4& iErrorReturn /*= aiMatrix4x4()*/) const { return GetGenericProperty(mMatrixProperties,szName,iErrorReturn); } // ------------------------------------------------------------------------------------------------ // Has a configuration property -bool ExportProperties :: HasPropertyInteger(const char* szName) const -{ +bool ExportProperties::HasPropertyInteger(const char* szName) const { return HasGenericProperty(mIntProperties, szName); } // ------------------------------------------------------------------------------------------------ // Has a configuration property -bool ExportProperties :: HasPropertyBool(const char* szName) const -{ +bool ExportProperties::HasPropertyBool(const char* szName) const { return HasGenericProperty(mIntProperties, szName); } // ------------------------------------------------------------------------------------------------ // Has a configuration property -bool ExportProperties :: HasPropertyFloat(const char* szName) const -{ +bool ExportProperties::HasPropertyFloat(const char* szName) const { return HasGenericProperty(mFloatProperties, szName); } // ------------------------------------------------------------------------------------------------ // Has a configuration property -bool ExportProperties :: HasPropertyString(const char* szName) const -{ +bool ExportProperties::HasPropertyString(const char* szName) const { return HasGenericProperty(mStringProperties, szName); } // ------------------------------------------------------------------------------------------------ // Has a configuration property -bool ExportProperties :: HasPropertyMatrix(const char* szName) const -{ +bool ExportProperties::HasPropertyMatrix(const char* szName) const { return HasGenericProperty(mMatrixProperties, szName); } diff --git a/code/Importer.cpp b/code/Importer.cpp index 32bec9414..fe6df187c 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -315,22 +315,19 @@ void Importer::SetIOHandler( IOSystem* pIOHandler) // ------------------------------------------------------------------------------------------------ // Get the currently set IO handler -IOSystem* Importer::GetIOHandler() const -{ +IOSystem* Importer::GetIOHandler() const { return pimpl->mIOHandler; } // ------------------------------------------------------------------------------------------------ // Check whether a custom IO handler is currently set -bool Importer::IsDefaultIOHandler() const -{ +bool Importer::IsDefaultIOHandler() const { return pimpl->mIsDefaultHandler; } // ------------------------------------------------------------------------------------------------ // Supplies a custom progress handler to get regular callbacks during importing -void Importer::SetProgressHandler ( ProgressHandler* pHandler ) -{ +void Importer::SetProgressHandler ( ProgressHandler* pHandler ) { ASSIMP_BEGIN_EXCEPTION_REGION(); // If the new handler is zero, allocate a default implementation. if (!pHandler) @@ -351,15 +348,13 @@ void Importer::SetProgressHandler ( ProgressHandler* pHandler ) // ------------------------------------------------------------------------------------------------ // Get the currently set progress handler -ProgressHandler* Importer::GetProgressHandler() const -{ +ProgressHandler* Importer::GetProgressHandler() const { return pimpl->mProgressHandler; } // ------------------------------------------------------------------------------------------------ // Check whether a custom progress handler is currently set -bool Importer::IsDefaultProgressHandler() const -{ +bool Importer::IsDefaultProgressHandler() const { return pimpl->mIsDefaultProgressHandler; } diff --git a/include/assimp/Exporter.hpp b/include/assimp/Exporter.hpp index 3d1a9ea85..4e0843b60 100644 --- a/include/assimp/Exporter.hpp +++ b/include/assimp/Exporter.hpp @@ -57,6 +57,7 @@ namespace Assimp { class ExporterPimpl; class IOSystem; +class ProgressHandler; // ---------------------------------------------------------------------------------- /** CPP-API: The Exporter class forms an C++ interface to the export functionality @@ -84,8 +85,7 @@ public: typedef void (*fpExportFunc)(const char*, IOSystem*, const aiScene*, const ExportProperties*); /** Internal description of an Assimp export format option */ - struct ExportFormatEntry - { + struct ExportFormatEntry { /// Public description structure to be returned by aiGetExportFormatDescription() aiExportFormatDesc mDescription; @@ -158,6 +158,19 @@ public: * @return true by default */ bool IsDefaultIOHandler() const; + // ------------------------------------------------------------------- + /** Supplies a custom progress handler to the exporter. This + * interface exposes an #Update() callback, which is called + * more or less periodically (please don't sue us if it + * isn't as periodically as you'd like it to have ...). + * This can be used to implement progress bars and loading + * timeouts. + * @param pHandler Progress callback interface. Pass nullptr to + * disable progress reporting. + * @note Progress handlers can be used to abort the loading + * at almost any time.*/ + void SetProgressHandler(ProgressHandler* pHandler); + // ------------------------------------------------------------------- /** Exports the given scene to a chosen file format. Returns the exported * data as a binary blob which you can write into a file or something. diff --git a/include/assimp/Importer.hpp b/include/assimp/Importer.hpp index 7445c9797..1d1dac19f 100644 --- a/include/assimp/Importer.hpp +++ b/include/assimp/Importer.hpp @@ -330,7 +330,7 @@ public: // ------------------------------------------------------------------- /** Supplies a custom progress handler to the importer. This - * interface exposes a #Update() callback, which is called + * interface exposes an #Update() callback, which is called * more or less periodically (please don't sue us if it * isn't as periodically as you'd like it to have ...). * This can be used to implement progress bars and loading diff --git a/include/assimp/ProgressHandler.hpp b/include/assimp/ProgressHandler.hpp index 0fa1501d4..f295eac39 100644 --- a/include/assimp/ProgressHandler.hpp +++ b/include/assimp/ProgressHandler.hpp @@ -62,11 +62,13 @@ class ASSIMP_API ProgressHandler #endif { protected: - /** @brief Default constructor */ - ProgressHandler () AI_NO_EXCEPT { + /// @brief Default constructor + ProgressHandler () AI_NO_EXCEPT { + // empty } + public: - /** @brief Virtual destructor */ + /// @brief Virtual destructor. virtual ~ProgressHandler () { } @@ -120,8 +122,24 @@ public: Update( f * 0.5f + 0.5f ); } + + // ------------------------------------------------------------------- + /** @brief Progress callback for export steps. + * @param numberOfSteps The number of total processing + * steps + * @param currentStep The index of the current post-processing + * step that will run, or equal to numberOfSteps if all of + * them has finished. This number is always strictly monotone + * increasing, although not necessarily linearly. + * */ + virtual void UpdateFileWrite(int currentStep /*= 0*/, int numberOfSteps /*= 0*/) { + float f = numberOfSteps ? currentStep / (float)numberOfSteps : 1.0f; + Update(f * 0.5f); + } }; // !class ProgressHandler + // ------------------------------------------------------------------------------------ + } // Namespace Assimp #endif // AI_PROGRESSHANDLER_H_INC diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 687432085..01c8daa09 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -87,6 +87,7 @@ SET( IMPORTERS unit/utIFCImportExport.cpp unit/utFBXImporterExporter.cpp unit/utImporter.cpp + unit/ImportExport/utExporter.cpp unit/ut3DImportExport.cpp unit/ut3DSImportExport.cpp unit/utACImportExport.cpp diff --git a/test/unit/ImportExport/utExporter.cpp b/test/unit/ImportExport/utExporter.cpp new file mode 100644 index 000000000..1efe9e132 --- /dev/null +++ b/test/unit/ImportExport/utExporter.cpp @@ -0,0 +1,74 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2018, 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 + +using namespace Assimp; + +class TestProgressHandler : public ProgressHandler { +public: + TestProgressHandler() : ProgressHandler() { + // empty + } + + virtual ~TestProgressHandler() { + // empty + } + + bool Update(float percentage = -1.f) override { + return true; + } +}; + +class ExporterTest : public ::testing::Test { + // empty +}; + +TEST_F(ExporterTest, ProgressHandlerTest) { + Exporter exporter; + TestProgressHandler *ph(new TestProgressHandler); + exporter.SetProgressHandler(ph); + delete ph; +} From 6a8e11dbb2da81e3f2562442b51b608b03a6b482 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 13 Nov 2018 13:10:16 +0100 Subject: [PATCH 020/472] Update Exporter.cpp Fix review finding. --- code/Exporter.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/code/Exporter.cpp b/code/Exporter.cpp index 63a934091..0acde75bf 100644 --- a/code/Exporter.cpp +++ b/code/Exporter.cpp @@ -212,6 +212,7 @@ public: for( unsigned int a = 0; a < mPostProcessingSteps.size(); a++) { delete mPostProcessingSteps[a]; } + delete mProgressHandler; } public: @@ -246,10 +247,6 @@ Exporter :: Exporter() // ------------------------------------------------------------------------------------------------ Exporter::~Exporter() { FreeBlob(); - if (pimpl->mIsDefaultProgressHandler) { - delete pimpl->mProgressHandler; - pimpl->mProgressHandler = nullptr; - } delete pimpl; } From e1404d349c1588c6b52d2b9da2fc50ce8a8dc98f Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 13 Nov 2018 14:44:34 +0100 Subject: [PATCH 021/472] Update utExporter.cpp Remove misuse of the API. --- test/unit/ImportExport/utExporter.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/test/unit/ImportExport/utExporter.cpp b/test/unit/ImportExport/utExporter.cpp index 1efe9e132..9ce4bfdd7 100644 --- a/test/unit/ImportExport/utExporter.cpp +++ b/test/unit/ImportExport/utExporter.cpp @@ -70,5 +70,4 @@ TEST_F(ExporterTest, ProgressHandlerTest) { Exporter exporter; TestProgressHandler *ph(new TestProgressHandler); exporter.SetProgressHandler(ph); - delete ph; } From 3f85a2ca079e3f26fd2b6e59cab29960e45eb743 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 13 Nov 2018 16:11:13 +0100 Subject: [PATCH 022/472] Update vector2.h Remove unused include to fix xcode build. --- include/assimp/vector2.h | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/include/assimp/vector2.h b/include/assimp/vector2.h index d290945c9..62bfb3b01 100644 --- a/include/assimp/vector2.h +++ b/include/assimp/vector2.h @@ -53,7 +53,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # include #endif -#include "./Compiler/pushpack1.h" #include "defs.h" // ---------------------------------------------------------------------------------- @@ -62,24 +61,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef __cplusplus template -class aiVector2t -{ +class aiVector2t { public: - aiVector2t () : x(), y() {} aiVector2t (TReal _x, TReal _y) : x(_x), y(_y) {} explicit aiVector2t (TReal _xyz) : x(_xyz), y(_xyz) {} aiVector2t (const aiVector2t& o) : x(o.x), y(o.y) {} - -public: - + void Set( TReal pX, TReal pY); TReal SquareLength() const ; TReal Length() const ; aiVector2t& Normalize(); -public: - const aiVector2t& operator += (const aiVector2t& o); const aiVector2t& operator -= (const aiVector2t& o); const aiVector2t& operator *= (TReal f); @@ -111,6 +104,4 @@ struct aiVector2D { #endif // __cplusplus -#include "./Compiler/poppack1.h" - #endif // AI_VECTOR2D_H_INC From 48ee14c64e7f2f89e102f3d3cfe87008abb3cfb3 Mon Sep 17 00:00:00 2001 From: Matthias Moulin Date: Wed, 14 Nov 2018 21:20:27 +0100 Subject: [PATCH 023/472] C4703 workaround for msvc++ `error C4703: potentially uninitialized local pointer variable 'pcFirstFrame'` in debug mode --- code/MDLLoader.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/MDLLoader.cpp b/code/MDLLoader.cpp index dfe1c1311..791a3bc67 100644 --- a/code/MDLLoader.cpp +++ b/code/MDLLoader.cpp @@ -413,8 +413,9 @@ void MDLImporter::InternReadFile_Quake1() { #if 1 // FIXME: the cast is wrong and cause a warning on clang 5.0 - // disable thi code for now, fix it later + // disable this code for now, fix it later ai_assert(false && "Bad pointer cast"); + pcFirstFrame = NULL; #else BE_NCONST MDL::GroupFrame* pcFrames2 = (BE_NCONST MDL::GroupFrame*)pcFrames; pcFirstFrame = (BE_NCONST MDL::SimpleFrame*)(&pcFrames2->time + pcFrames->type); From 0535b2890833314f09fe48a7159b4dd970c05860 Mon Sep 17 00:00:00 2001 From: Matthias Moulin Date: Fri, 16 Nov 2018 12:17:12 +0100 Subject: [PATCH 024/472] nullptr instead of NULL --- code/MDLLoader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/MDLLoader.cpp b/code/MDLLoader.cpp index 791a3bc67..eb067a1c9 100644 --- a/code/MDLLoader.cpp +++ b/code/MDLLoader.cpp @@ -415,7 +415,7 @@ void MDLImporter::InternReadFile_Quake1() { // FIXME: the cast is wrong and cause a warning on clang 5.0 // disable this code for now, fix it later ai_assert(false && "Bad pointer cast"); - pcFirstFrame = NULL; + pcFirstFrame = nullptr; // Workaround: msvc++ C4703 error #else BE_NCONST MDL::GroupFrame* pcFrames2 = (BE_NCONST MDL::GroupFrame*)pcFrames; pcFirstFrame = (BE_NCONST MDL::SimpleFrame*)(&pcFrames2->time + pcFrames->type); From 4b4f18fb3111bf0368f489fe339ae68a7c72f228 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 19 Nov 2018 21:46:02 +0100 Subject: [PATCH 025/472] Dox: remove parts about boost support - already replaced by c++11. --- doc/dox.h | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/doc/dox.h b/doc/dox.h index af9eeb609..d63c8a806 100644 --- a/doc/dox.h +++ b/doc/dox.h @@ -1486,9 +1486,8 @@ Just copy'n'paste the template from Appendix A and adapt it for your needs. with DefaultLogger::get()->[error, warn, debug, info].
  • -Make sure that your loader compiles against all build configurations on all supported platforms. This includes -noboost! To avoid problems, -see the boost section on this page for a list of all 'allowed' boost classes (again, this grew historically when we had to accept that boost -is not THAT widely spread that one could rely on it being available everywhere). +Make sure that your loader compiles against all build configurations on all supported platforms. You can use our CI-build to check several platforms +like Windows and Linux ( 32 bit and 64 bit ).
  • Provide some _free_ test models in <root>/test/models/<FormatName>/ and credit their authors. @@ -1567,22 +1566,6 @@ NewMaterial->AddProperty(&aiString(MaterialName.c_str()), AI_MATKEY_NAME);//Mate NewMaterial->AddProperty(&aiString(Texturename.c_str()), AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));//again, Texturename is a std::string @endcode -@section boost Boost - -The boost whitelist: -
      -
    • boost.scoped_ptr
    • -
    • boost.scoped_array
    • -
    • boost.format
    • -
    • boost.random
    • -
    • boost.common_factor
    • -
    • boost.foreach
    • -
    • boost.tuple
    • -
    - -(if you happen to need something else, i.e. boost::thread, make this an optional feature. -assimp_BUILD_BOOST_WORKAROUND is defined for -noboost builds) - @section appa Appendix A - Template for BaseImporter's abstract methods @code From 9ae8efcf09a39c4c78660eb5a374a94ac50a88f9 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 21 Nov 2018 21:29:09 +0100 Subject: [PATCH 026/472] closes https://github.com/assimp/assimp/issues/2229: fix count of polylines when only one vertex was indexed. --- code/DXFHelper.h | 13 ++----------- code/DXFLoader.cpp | 41 +++++++++++++++++++++++++++-------------- code/DXFLoader.h | 5 ----- 3 files changed, 29 insertions(+), 30 deletions(-) diff --git a/code/DXFHelper.h b/code/DXFHelper.h index 00e66a0db..f3f73d4c2 100644 --- a/code/DXFHelper.h +++ b/code/DXFHelper.h @@ -62,9 +62,7 @@ namespace Assimp { // to convert the data to the target data type. class LineReader { - public: - LineReader(StreamReaderLE& reader) // do NOT skip empty lines. In DXF files, they count as valid data. : splitter(reader,false,true) @@ -74,9 +72,6 @@ public: { } -public: - - // ----------------------------------------- bool Is(int gc, const char* what) const { return groupcode == gc && !strcmp(what,value.c_str()); @@ -102,8 +97,6 @@ public: return !((bool)*this); } -public: - // ----------------------------------------- unsigned int ValueAsUnsignedInt() const { return strtoul10(value.c_str()); @@ -228,9 +221,7 @@ struct FileData std::vector blocks; }; +} +} // Namespace Assimp - - - -}} #endif diff --git a/code/DXFLoader.cpp b/code/DXFLoader.cpp index d317382dc..24410da55 100644 --- a/code/DXFLoader.cpp +++ b/code/DXFLoader.cpp @@ -63,11 +63,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; // AutoCAD Binary DXF -#define AI_DXF_BINARY_IDENT ("AutoCAD Binary DXF\r\n\x1a\0") -#define AI_DXF_BINARY_IDENT_LEN (24) +const std::string AI_DXF_BINARY_IDENT = std::string("AutoCAD Binary DXF\r\n\x1a\0"); +const size_t AI_DXF_BINARY_IDENT_LEN = 24u; // default vertex color that all uncolored vertices will receive -#define AI_DXF_DEFAULT_COLOR aiColor4D(0.6f,0.6f,0.6f,0.6f) +const aiColor4D AI_DXF_DEFAULT_COLOR(aiColor4D(0.6f, 0.6f, 0.6f, 0.6f)); // color indices for DXF - 16 are supported, the table is // taken directly from the DXF spec. @@ -93,7 +93,6 @@ static aiColor4D g_aclrDxfIndexColors[] = #define AI_DXF_NUM_INDEX_COLORS (sizeof(g_aclrDxfIndexColors)/sizeof(g_aclrDxfIndexColors[0])) #define AI_DXF_ENTITIES_MAGIC_BLOCK "$ASSIMP_ENTITIES_MAGIC" - static const aiImporterDesc desc = { "Drawing Interchange Format (DXF) Importer", "", @@ -110,24 +109,27 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer DXFImporter::DXFImporter() -{} +: BaseImporter() { + // empty +} // ------------------------------------------------------------------------------------------------ // Destructor, private as well -DXFImporter::~DXFImporter() -{} +DXFImporter::~DXFImporter() { + // empty +} // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool DXFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const { - const std::string& extension = GetExtension( pFile ); +bool DXFImporter::CanRead( const std::string& filename, IOSystem* pIOHandler, bool checkSig ) const { + const std::string& extension = GetExtension( filename ); if ( extension == "dxf" ) { return true; } if ( extension.empty() || checkSig ) { static const char *pTokens[] = { "SECTION", "HEADER", "ENDSEC", "BLOCKS" }; - return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 4, 32 ); + return BaseImporter::SearchFileHeaderForToken(pIOHandler, filename, pTokens, 4, 32 ); } return false; @@ -157,7 +159,7 @@ void DXFImporter::InternReadFile( const std::string& pFile, char buff[AI_DXF_BINARY_IDENT_LEN+1] = {0}; file->Read(buff,AI_DXF_BINARY_IDENT_LEN,1); - if (!strncmp(AI_DXF_BINARY_IDENT,buff,AI_DXF_BINARY_IDENT_LEN)) { + if (!strncmp(AI_DXF_BINARY_IDENT.c_str(),buff,AI_DXF_BINARY_IDENT_LEN)) { throw DeadlyImportError("DXF: Binary files are not supported at the moment"); } @@ -734,9 +736,17 @@ void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& li break; // VERTEX COORDINATES - case 10: out.x = reader.ValueAsFloat();break; - case 20: out.y = reader.ValueAsFloat();break; - case 30: out.z = reader.ValueAsFloat();break; + case 10: + out.x = reader.ValueAsFloat(); + break; + + case 20: + out.y = reader.ValueAsFloat(); + break; + + case 30: + out.z = reader.ValueAsFloat(); + break; // POLYFACE vertex indices case 71: @@ -770,6 +780,9 @@ void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& li if (indices[i] == 0) { ASSIMP_LOG_WARN("DXF: invalid vertex index, indices are one-based."); --line.counts.back(); + if (line.counts.back() == 0) { + line.counts.pop_back(); + } continue; } line.indices.push_back(indices[i]-1); diff --git a/code/DXFLoader.h b/code/DXFLoader.h index 487bb99f8..3392b8f63 100644 --- a/code/DXFLoader.h +++ b/code/DXFLoader.h @@ -72,10 +72,6 @@ public: DXFImporter(); ~DXFImporter(); - - -public: - // ------------------------------------------------------------------- /** Returns whether the class can handle the format of the given file. * See BaseImporter::CanRead() for details. */ @@ -83,7 +79,6 @@ public: bool checkSig) const; protected: - // ------------------------------------------------------------------- /** Return importer meta information. * See #BaseImporter::GetInfo for the details*/ From f00154802cc841b5406ea3f251787098abc33d2c Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 21 Nov 2018 21:39:16 +0100 Subject: [PATCH 027/472] Issue 2229: add a unittest. --- test/models/DXF/issue_2229.dxf | 64584 ++++++++++++++++++++++++++ test/unit/utDXFImporterExporter.cpp | 5 + 2 files changed, 64589 insertions(+) create mode 100644 test/models/DXF/issue_2229.dxf diff --git a/test/models/DXF/issue_2229.dxf b/test/models/DXF/issue_2229.dxf new file mode 100644 index 000000000..2f0d7a7e6 --- /dev/null +++ b/test/models/DXF/issue_2229.dxf @@ -0,0 +1,64584 @@ + 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1015 + 9 +$ACADMAINTVER + 70 + 6 + 9 +$DWGCODEPAGE + 3 +ANSI_1252 + 9 +$INSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$EXTMIN + 10 +-600.0 + 20 +-420.0 + 30 +0.0 + 9 +$EXTMAX + 10 +600.0 + 20 +0.0 + 30 +116.0 + 9 +$LIMMIN + 10 +-600.0 + 20 +-420.0 + 9 +$LIMMAX + 10 +600.0 + 20 +0.0 + 9 +$ORTHOMODE + 70 + 0 + 9 +$REGENMODE + 70 + 1 + 9 +$FILLMODE + 70 + 1 + 9 +$QTEXTMODE + 70 + 0 + 9 +$MIRRTEXT + 70 + 0 + 9 +$LTSCALE + 40 +1.0 + 9 +$ATTMODE + 70 + 1 + 9 +$TEXTSIZE + 40 +5.0 + 9 +$TRACEWID + 40 +1.0 + 9 +$TEXTSTYLE + 7 +Standard + 9 +$CLAYER + 8 +0 + 9 +$CELTYPE + 6 +ByLayer + 9 +$CECOLOR + 62 + 7 + 9 +$CELTSCALE + 40 +1.0 + 9 +$DISPSILH + 70 + 0 + 9 +$DIMSCALE + 40 +1.0 + 9 +$DIMASZ + 40 +3.0 + 9 +$DIMEXO + 40 +1.0 + 9 +$DIMDLI + 40 +7.5 + 9 +$DIMRND + 40 +0.2 + 9 +$DIMDLE + 40 +0.0 + 9 +$DIMEXE + 40 +2.0 + 9 +$DIMTP + 40 +0.0 + 9 +$DIMTM + 40 +0.0 + 9 +$DIMTXT + 40 +3.0 + 9 +$DIMCEN + 40 +0.0 + 9 +$DIMTSZ + 40 +0.0 + 9 +$DIMTOL + 70 + 0 + 9 +$DIMLIM + 70 + 0 + 9 +$DIMTIH + 70 + 1 + 9 +$DIMTOH + 70 + 0 + 9 +$DIMSE1 + 70 + 0 + 9 +$DIMSE2 + 70 + 0 + 9 +$DIMTAD + 70 + 1 + 9 +$DIMZIN + 70 + 1 + 9 +$DIMBLK + 1 + + 9 +$DIMASO + 70 + 1 + 9 +$DIMSHO + 70 + 1 + 9 +$DIMPOST + 1 + mm + 9 +$DIMAPOST + 1 + mm + 9 +$DIMALT + 70 + 0 + 9 +$DIMALTD + 70 + 2 + 9 +$DIMALTF + 40 +1.0 + 9 +$DIMLFAC + 40 +1.0 + 9 +$DIMTOFL + 70 + 1 + 9 +$DIMTVP + 40 +0.0 + 9 +$DIMTIX + 70 + 0 + 9 +$DIMSOXD + 70 + 0 + 9 +$DIMSAH + 70 + 0 + 9 +$DIMBLK1 + 1 + + 9 +$DIMBLK2 + 1 + + 9 +$DIMSTYLE + 2 +Standard + 9 +$DIMCLRD + 70 + 7 + 9 +$DIMCLRE + 70 + 7 + 9 +$DIMCLRT + 70 + 7 + 9 +$DIMTFAC + 40 +1.0 + 9 +$DIMGAP + 40 +2.0 + 9 +$DIMJUST + 70 + 0 + 9 +$DIMSD1 + 70 + 0 + 9 +$DIMSD2 + 70 + 0 + 9 +$DIMTOLJ + 70 + 1 + 9 +$DIMTZIN + 70 + 0 + 9 +$DIMALTZ + 70 + 0 + 9 +$DIMALTTZ + 70 + 0 + 9 +$DIMUPT + 70 + 0 + 9 +$DIMDEC + 70 + 2 + 9 +$DIMTDEC + 70 + 3 + 9 +$DIMALTU + 70 + 2 + 9 +$DIMALTTD + 70 + 2 + 9 +$DIMTXSTY + 7 +Standard + 9 +$DIMAUNIT + 70 + 0 + 9 +$DIMADEC + 70 + 0 + 9 +$DIMALTRND + 40 +0.01 + 9 +$DIMAZIN + 70 + 0 + 9 +$DIMDSEP + 70 + 0 + 9 +$DIMATFIT + 70 + 3 + 9 +$DIMFRAC + 70 + 2 + 9 +$DIMLDRBLK + 1 + + 9 +$DIMLUNIT + 70 + 2 + 9 +$DIMLWD + 70 + -2 + 9 +$DIMLWE + 70 + -2 + 9 +$DIMTMOVE + 70 + 0 + 9 +$LUNITS + 70 + 2 + 9 +$LUPREC + 70 + 2 + 9 +$SKETCHINC + 40 +1.0 + 9 +$FILLETRAD + 40 +3.0 + 9 +$AUNITS + 70 + 0 + 9 +$AUPREC + 70 + 2 + 9 +$MENU + 1 +. + 9 +$ELEVATION + 40 +0.0 + 9 +$PELEVATION + 40 +0.0 + 9 +$THICKNESS + 40 +0.0 + 9 +$LIMCHECK + 70 + 0 + 9 +$CHAMFERA + 40 +0.5 + 9 +$CHAMFERB + 40 +0.5 + 9 +$CHAMFERC + 40 +1.0 + 9 +$CHAMFERD + 40 +0.0 + 9 +$SKPOLY + 70 + 0 + 9 +$TDCREATE + 40 +2457980.424153067 + 9 +$TDUCREATE + 40 +2457980.340819734 + 9 +$TDUPDATE + 40 +2457980.424153079 + 9 +$TDUUPDATE + 40 +2457980.340819745 + 9 +$TDINDWG + 40 +0.0 + 9 +$TDUSRTIMER + 40 +0.0 + 9 +$USRTIMER + 70 + 1 + 9 +$ANGBASE + 50 +0.0 + 9 +$ANGDIR + 70 + 0 + 9 +$PDMODE + 70 + 0 + 9 +$PDSIZE + 40 +0.0 + 9 +$PLINEWID + 40 +0.0 + 9 +$SPLFRAME + 70 + 0 + 9 +$SPLINETYPE + 70 + 5 + 9 +$SPLINESEGS + 70 + 20 + 9 +$HANDSEED + 5 +884 + 9 +$SURFTAB1 + 70 + 6 + 9 +$SURFTAB2 + 70 + 6 + 9 +$SURFTYPE + 70 + 6 + 9 +$SURFU + 70 + 6 + 9 +$SURFV + 70 + 6 + 9 +$UCSBASE + 2 + + 9 +$UCSNAME + 2 + + 9 +$UCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$UCSORTHOREF + 2 + + 9 +$UCSORTHOVIEW + 70 + 0 + 9 +$UCSORGTOP + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGBOTTOM + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGLEFT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGRIGHT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGFRONT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$UCSORGBACK + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSBASE + 2 + + 9 +$PUCSNAME + 2 + + 9 +$PUCSORG + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSXDIR + 10 +1.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSYDIR + 10 +0.0 + 20 +1.0 + 30 +0.0 + 9 +$PUCSORTHOREF + 2 + + 9 +$PUCSORTHOVIEW + 70 + 0 + 9 +$PUCSORGTOP + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGBOTTOM + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGLEFT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGRIGHT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGFRONT + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PUCSORGBACK + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$USERI1 + 70 + 0 + 9 +$USERI2 + 70 + 0 + 9 +$USERI3 + 70 + 0 + 9 +$USERI4 + 70 + 0 + 9 +$USERI5 + 70 + 0 + 9 +$USERR1 + 40 +0.0 + 9 +$USERR2 + 40 +0.0 + 9 +$USERR3 + 40 +0.0 + 9 +$USERR4 + 40 +0.0 + 9 +$USERR5 + 40 +0.0 + 9 +$WORLDVIEW + 70 + 1 + 9 +$SHADEDGE + 70 + 3 + 9 +$SHADEDIF + 70 + 70 + 9 +$TILEMODE + 70 + 1 + 9 +$MAXACTVP + 70 + 64 + 9 +$PINSBASE + 10 +0.0 + 20 +0.0 + 30 +0.0 + 9 +$PLIMCHECK + 70 + 0 + 9 +$PEXTMIN + 10 +-139.7 + 20 +-317.95 + 30 +0.0 + 9 +$PEXTMAX + 10 +139.7 + 20 +-102.05 + 30 +0.0 + 9 +$PLIMMIN + 10 +-139.7 + 20 +-317.95 + 9 +$PLIMMAX + 10 +139.7 + 20 +-102.05 + 9 +$UNITMODE + 70 + 0 + 9 +$VISRETAIN + 70 + 1 + 9 +$PLINEGEN + 70 + 0 + 9 +$PSLTSCALE + 70 + 1 + 9 +$TREEDEPTH + 70 + 3020 + 9 +$CMLSTYLE + 2 +Standard + 9 +$CMLJUST + 70 + 0 + 9 +$CMLSCALE + 40 +1.0 + 9 +$PROXYGRAPHICS + 70 + 1 + 9 +$MEASUREMENT + 70 + 1 + 9 +$CELWEIGHT +370 + -1 + 9 +$ENDCAPS +280 + 0 + 9 +$JOINSTYLE +280 + 0 + 9 +$LWDISPLAY +290 + 0 + 9 +$INSUNITS + 70 + 1 + 9 +$HYPERLINKBASE + 1 + + 9 +$STYLESHEET + 1 + + 9 +$XEDIT +290 + 1 + 9 +$CEPSNTYPE +380 + 0 + 9 +$PSTYLEMODE +290 + 1 + 9 +$FINGERPRINTGUID + 2 +{405C4499-50CC-4141-B4E7-9C06DD072391} + 9 +$VERSIONGUID + 2 +{FAEB1C32-E019-11D5-929B-00C0DF256EC4} + 9 +$EXTNAMES +290 + 1 + 9 +$PSVPSCALE + 40 +0.0 + 9 +$OLESTARTUP +290 + 0 + 0 +ENDSEC + 0 +SECTION + 2 +CLASSES + 0 +CLASS + 1 +ACDBDICTIONARYWDFLT + 2 +AcDbDictionaryWithDefault + 3 +ObjectDBX Classes + 90 + 0 +280 + 0 +281 + 0 + 0 +CLASS + 1 +VISUALSTYLE + 2 +AcDbVisualStyle + 3 +ObjectDBX Classes + 90 + 4095 +280 + 0 +281 + 0 + 0 +CLASS + 1 +TABLESTYLE + 2 +AcDbTableStyle + 3 +ObjectDBX Classes + 90 + 4095 +280 + 0 +281 + 0 + 0 +CLASS + 1 +SCALE + 2 +AcDbScale + 3 +ObjectDBX Classes + 90 + 1153 +280 + 0 +281 + 0 + 0 +CLASS + 1 +DICTIONARYVAR + 2 +AcDbDictionaryVar + 3 +ObjectDBX Classes + 90 + 0 +280 + 0 +281 + 0 + 0 +CLASS + 1 +ACDBPLACEHOLDER + 2 +AcDbPlaceHolder + 3 +ObjectDBX Classes + 90 + 0 +280 + 0 +281 + 0 + 0 +CLASS + 1 +LAYOUT + 2 +AcDbLayout + 3 +ObjectDBX Classes + 90 + 0 +280 + 0 +281 + 0 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +VPORT + 5 +8 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +VPORT + 5 +29 +330 +8 +100 +AcDbSymbolTableRecord +100 +AcDbViewportTableRecord + 2 +*Active + 70 + 0 + 10 +0.0 + 20 +0.0 + 11 +1.0 + 21 +1.0 + 12 +0.0 + 22 +0.0 + 13 +0.0 + 23 +0.0 + 14 +5.0 + 24 +5.0 + 15 +5.0 + 25 +5.0 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +-210.0 + 37 +0.0 + 40 +544.620425996723 + 41 +2.203369434416366 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 51 +0.0 + 71 + 0 + 72 + 100 + 73 + 1 + 74 + 3 + 75 + 0 + 76 + 0 + 77 + 0 + 78 + 0 +281 + 0 + 65 + 1 +110 +0.0 +120 +0.0 +130 +0.0 +111 +1.0 +121 +0.0 +131 +0.0 +112 +0.0 +122 +1.0 +132 +0.0 + 79 + 0 +146 +0.0 + 0 +ENDTAB + 0 +TABLE + 2 +LTYPE + 5 +5 +330 +0 +100 +AcDbSymbolTable + 70 + 10 + 0 +LTYPE + 5 +14 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByBlock + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +15 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +ByLayer + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +16 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Continuous + 70 + 0 + 3 +Solid line + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +3C +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Durchgehend + 70 + 0 + 3 +Durchgehend + 72 + 65 + 73 + 0 + 40 +0.0 + 0 +LTYPE + 5 +3D +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Rand + 70 + 0 + 3 +Rand + 72 + 65 + 73 + 6 + 40 +1.75 + 49 +0.5 + 74 + 0 + 49 +-0.25 + 74 + 0 + 49 +0.5 + 74 + 0 + 49 +-0.25 + 74 + 0 + 49 +0.0 + 74 + 0 + 49 +-0.25 + 74 + 0 + 0 +LTYPE + 5 +3E +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Mitte + 70 + 0 + 3 +Mitte + 72 + 65 + 73 + 4 + 40 +2.0 + 49 +1.25 + 74 + 0 + 49 +-0.25 + 74 + 0 + 49 +0.25 + 74 + 0 + 49 +-0.25 + 74 + 0 + 0 +LTYPE + 5 +3F +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Strichpunkt + 70 + 0 + 3 +Strichpunkt + 72 + 65 + 73 + 4 + 40 +1.0 + 49 +0.5 + 74 + 0 + 49 +-0.25 + 74 + 0 + 49 +0.0 + 74 + 0 + 49 +-0.25 + 74 + 0 + 0 +LTYPE + 5 +40 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Gestrichelt + 70 + 0 + 3 +Gestrichelt + 72 + 65 + 73 + 2 + 40 +0.75 + 49 +0.5 + 74 + 0 + 49 +-0.25 + 74 + 0 + 0 +LTYPE + 5 +41 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Geteilt + 70 + 0 + 3 +Geteilt + 72 + 65 + 73 + 6 + 40 +1.25 + 49 +0.5 + 74 + 0 + 49 +-0.25 + 74 + 0 + 49 +0.0 + 74 + 0 + 49 +-0.25 + 74 + 0 + 49 +0.0 + 74 + 0 + 49 +-0.25 + 74 + 0 + 0 +LTYPE + 5 +42 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Punkt + 70 + 0 + 3 +Punkt + 72 + 65 + 73 + 2 + 40 +0.25 + 49 +0.0 + 74 + 0 + 49 +-0.25 + 74 + 0 + 0 +LTYPE + 5 +43 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +Verdeckt + 70 + 0 + 3 +Verdeckt + 72 + 65 + 73 + 2 + 40 +0.375 + 49 +0.25 + 74 + 0 + 49 +-0.125 + 74 + 0 + 0 +LTYPE + 5 +44 +330 +5 +100 +AcDbSymbolTableRecord +100 +AcDbLinetypeTableRecord + 2 +$INVISIBLE + 70 + 0 + 3 +$INVISIBLE + 72 + 65 + 73 + 2 + 40 +200.0 + 49 +-100.0 + 74 + 0 + 49 +-100.0 + 74 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +LAYER + 5 +2 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +LAYER + 5 +10 +330 +2 +100 +AcDbSymbolTableRecord +100 +AcDbLayerTableRecord + 2 +0 + 70 + 0 + 62 + 7 + 6 +Durchgehend +370 + 0 +390 +F + 0 +ENDTAB + 0 +TABLE + 2 +STYLE + 5 +3 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +STYLE + 5 +11 +330 +3 +100 +AcDbSymbolTableRecord +100 +AcDbTextStyleTableRecord + 2 +Standard + 70 + 0 + 40 +0.0 + 41 +1.0 + 50 +0.0 + 71 + 0 + 42 +5.0 + 3 + + 4 + +1001 +ACAD +1000 +Times New Roman +1071 + 290 + 0 +ENDTAB + 0 +TABLE + 2 +VIEW + 5 +6 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +VIEW + 5 +45 +330 +6 +100 +AcDbSymbolTableRecord +100 +AcDbViewTableRecord + 2 +Ansicht_0 + 70 + 0 + 40 +420.0 + 10 +0.0 + 20 +-210.0 + 41 +1200.0 + 11 +0.0 + 21 +0.0 + 31 +1.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 50 +0.0 + 71 + 0 +281 + 0 + 72 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +UCS + 5 +7 +330 +0 +100 +AcDbSymbolTable + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +APPID + 5 +9 +330 +0 +100 +AcDbSymbolTable + 70 + 6 + 0 +APPID + 5 +12 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD + 70 + 0 + 0 +APPID + 5 +3B +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +TCAD + 70 + 0 + 0 +APPID + 5 +87F +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD_DSTYLE_DIMTEXT_FILL + 70 + 0 + 0 +APPID + 5 +880 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD_DSTYLE_DIM_LINETYPE + 70 + 0 + 0 +APPID + 5 +881 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD_DSTYLE_DIM_EXT1_LINETYPE + 70 + 0 + 0 +APPID + 5 +882 +330 +9 +100 +AcDbSymbolTableRecord +100 +AcDbRegAppTableRecord + 2 +ACAD_DSTYLE_DIM_EXT2_LINETYPE + 70 + 0 + 0 +ENDTAB + 0 +TABLE + 2 +DIMSTYLE + 5 +A +330 +0 +100 +AcDbSymbolTable + 70 + 1 +100 +AcDbDimStyleTable + 0 +DIMSTYLE +105 +27 +330 +A +100 +AcDbSymbolTableRecord +100 +AcDbDimStyleTableRecord + 2 +Standard + 70 + 0 + 3 + mm + 4 + mm + 41 +3.0 + 42 +1.0 + 43 +7.5 + 44 +2.0 + 45 +0.2 + 74 + 0 + 77 + 1 + 78 + 1 +140 +3.0 +141 +0.0 +143 +1.0 +147 +2.0 +148 +0.01 +172 + 1 +176 + 7 +177 + 7 +178 + 7 +271 + 2 +272 + 3 +276 + 2 +278 + 0 +340 +11 +1001 +ACAD_DSTYLE_DIMTEXT_FILL +1070 + 376 +1070 + 0 +1001 +ACAD_DSTYLE_DIM_LINETYPE +1070 + 380 +1005 +14 +1001 +ACAD_DSTYLE_DIM_EXT1_LINETYPE +1070 + 381 +1005 +14 +1001 +ACAD_DSTYLE_DIM_EXT2_LINETYPE +1070 + 382 +1005 +14 + 0 +ENDTAB + 0 +TABLE + 2 +BLOCK_RECORD + 5 +1 +330 +0 +100 +AcDbSymbolTable + 70 + 1 + 0 +BLOCK_RECORD + 5 +1F +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Model_Space +340 +22 + 0 +BLOCK_RECORD + 5 +1B +330 +1 +100 +AcDbSymbolTableRecord +100 +AcDbBlockTableRecord + 2 +*Paper_Space +340 +1E + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +BLOCKS + 0 +BLOCK + 5 +20 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockBegin + 2 +*Model_Space + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Model_Space + 1 + + 0 +ENDBLK + 5 +21 +330 +1F +100 +AcDbEntity + 8 +0 +100 +AcDbBlockEnd + 0 +BLOCK + 5 +1C +330 +1B +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockBegin + 2 +*Paper_Space + 70 + 0 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 3 +*Paper_Space + 1 + + 0 +ENDBLK + 5 +1D +330 +1B +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbBlockEnd + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +POLYLINE + 5 +48 +330 +1F +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbPolyFaceMesh + 66 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 64 + 71 + 8 + 72 + 6 + 0 +VERTEX + 5 +49 +330 +48 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-362.985 + 20 +-59.50000000000001 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +4A +330 +48 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-362.985 + 20 +-59.50000000000001 + 30 +116.0 + 70 + 192 + 0 +VERTEX + 5 +4B +330 +48 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-361.985 + 20 +-59.50000000000001 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +4C +330 +48 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-361.985 + 20 +-59.50000000000001 + 30 +116.0 + 70 + 192 + 0 +VERTEX + 5 +4D +330 +48 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-361.985 + 20 +-60.5 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +4E +330 +48 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-362.985 + 20 +-60.5 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +4F +330 +48 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-362.985 + 20 +-60.5 + 30 +116.0 + 70 + 192 + 0 +VERTEX + 5 +50 +330 +48 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-361.985 + 20 +-60.5 + 30 +116.0 + 70 + 192 + 0 +VERTEX + 5 +51 +330 +48 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 4 + 72 + 2 + 73 + 7 + 74 + 8 + 0 +VERTEX + 5 +52 +330 +48 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 1 + 72 + 3 + 73 + 5 + 74 + 6 + 0 +VERTEX + 5 +53 +330 +48 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 7 + 72 + 2 + 73 + 1 + 74 + 6 + 0 +VERTEX + 5 +54 +330 +48 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 2 + 72 + 4 + 73 + 3 + 74 + 1 + 0 +VERTEX + 5 +55 +330 +48 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 4 + 72 + 8 + 73 + 5 + 74 + 3 + 0 +VERTEX + 5 +56 +330 +48 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 8 + 72 + 7 + 73 + 6 + 74 + 5 + 0 +SEQEND + 5 +57 +330 +48 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 + 0 +POLYLINE + 5 +58 +330 +1F +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbPolyFaceMesh + 66 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 64 + 71 + 8 + 72 + 6 + 0 +VERTEX + 5 +59 +330 +58 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +362.015 + 20 +-59.50000000000001 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +5A +330 +58 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +362.015 + 20 +-59.50000000000001 + 30 +116.0 + 70 + 192 + 0 +VERTEX + 5 +5B +330 +58 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +363.015 + 20 +-59.50000000000001 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +5C +330 +58 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +363.015 + 20 +-59.50000000000001 + 30 +116.0 + 70 + 192 + 0 +VERTEX + 5 +5D +330 +58 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +363.015 + 20 +-60.5 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +5E +330 +58 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +362.015 + 20 +-60.5 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +5F +330 +58 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +362.015 + 20 +-60.5 + 30 +116.0 + 70 + 192 + 0 +VERTEX + 5 +60 +330 +58 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +363.015 + 20 +-60.5 + 30 +116.0 + 70 + 192 + 0 +VERTEX + 5 +61 +330 +58 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 4 + 72 + 2 + 73 + 7 + 74 + 8 + 0 +VERTEX + 5 +62 +330 +58 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 1 + 72 + 3 + 73 + 5 + 74 + 6 + 0 +VERTEX + 5 +63 +330 +58 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 7 + 72 + 2 + 73 + 1 + 74 + 6 + 0 +VERTEX + 5 +64 +330 +58 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 2 + 72 + 4 + 73 + 3 + 74 + 1 + 0 +VERTEX + 5 +65 +330 +58 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 4 + 72 + 8 + 73 + 5 + 74 + 3 + 0 +VERTEX + 5 +66 +330 +58 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 8 + 72 + 7 + 73 + 6 + 74 + 5 + 0 +SEQEND + 5 +67 +330 +58 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 + 0 +POLYLINE + 5 +68 +330 +1F +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbPolyFaceMesh + 66 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 64 + 71 + 680 + 72 + 1174 + 0 +VERTEX + 5 +69 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +41.00199999999998 + 20 +-50.0 + 30 +89.994 + 70 + 192 + 0 +VERTEX + 5 +6A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +42.43300000000006 + 20 +-50.0 + 30 +89.529 + 70 + 192 + 0 +VERTEX + 5 +6B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +43.64999999999996 + 20 +-50.0 + 30 +88.645 + 70 + 192 + 0 +VERTEX + 5 +6C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +44.53499999999999 + 20 +-50.0 + 30 +87.42800000000003 + 70 + 192 + 0 +VERTEX + 5 +6D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +44.53499999999999 + 20 +-50.0 + 30 +83.06099999999999 + 70 + 192 + 0 +VERTEX + 5 +6E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +43.64999999999996 + 20 +-50.0 + 30 +81.844 + 70 + 192 + 0 +VERTEX + 5 +6F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +42.43300000000006 + 20 +-50.0 + 30 +80.959 + 70 + 192 + 0 +VERTEX + 5 +70 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-42.433 + 20 +-50.0 + 30 +80.959 + 70 + 192 + 0 +VERTEX + 5 +71 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-43.651 + 20 +-50.0 + 30 +81.844 + 70 + 192 + 0 +VERTEX + 5 +72 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-44.53499999999999 + 20 +-50.0 + 30 +83.06099999999999 + 70 + 192 + 0 +VERTEX + 5 +73 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-44.99999999999999 + 20 +-50.0 + 30 +84.49200000000002 + 70 + 192 + 0 +VERTEX + 5 +74 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-44.99999999999999 + 20 +-50.0 + 30 +85.997 + 70 + 192 + 0 +VERTEX + 5 +75 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-44.53499999999999 + 20 +-50.0 + 30 +87.42800000000003 + 70 + 192 + 0 +VERTEX + 5 +76 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-43.651 + 20 +-50.0 + 30 +88.645 + 70 + 192 + 0 +VERTEX + 5 +77 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-42.433 + 20 +-50.0 + 30 +89.529 + 70 + 192 + 0 +VERTEX + 5 +78 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-41.00199999999998 + 20 +-50.0 + 30 +89.994 + 70 + 192 + 0 +VERTEX + 5 +79 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +45.00000000000005 + 20 +-50.0 + 30 +84.49200000000002 + 70 + 192 + 0 +VERTEX + 5 +7A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +45.00000000000005 + 20 +-50.0 + 30 +85.997 + 70 + 192 + 0 +VERTEX + 5 +7B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-41.00199999999998 + 20 +-50.0 + 30 +80.49400000000001 + 70 + 192 + 0 +VERTEX + 5 +7C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +41.00199999999998 + 20 +-50.0 + 30 +80.49400000000001 + 70 + 192 + 0 +VERTEX + 5 +7D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +599.883 + 20 +-1.687 + 30 +113.29 + 70 + 192 + 0 +VERTEX + 5 +7E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +598.1390000000001 + 20 +-1.308 + 30 +114.782 + 70 + 192 + 0 +VERTEX + 5 +7F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +599.47 + 20 +-1.789 + 30 +114.172 + 70 + 192 + 0 +VERTEX + 5 +80 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +598.7269999999999 + 20 +-1.972 + 30 +114.782 + 70 + 192 + 0 +VERTEX + 5 +81 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +598.515 + 20 +-1.567 + 30 +114.782 + 70 + 192 + 0 +VERTEX + 5 +82 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +599.406 + 20 +-0.778 + 30 +113.29 + 70 + 192 + 0 +VERTEX + 5 +83 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +599.088 + 20 +-1.06 + 30 +114.172 + 70 + 192 + 0 +VERTEX + 5 +84 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +598.41 + 20 +-0.592 + 30 +114.172 + 70 + 192 + 0 +VERTEX + 5 +85 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +598.561 + 20 +-0.195 + 30 +113.29 + 70 + 192 + 0 +VERTEX + 5 +86 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-598.059 + 20 +-0.071 + 30 +113.29 + 70 + 192 + 0 +VERTEX + 5 +87 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-599.7 + 20 +-1.203 + 30 +113.29 + 70 + 192 + 0 +VERTEX + 5 +88 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-599.019 + 20 +-0.435 + 30 +113.29 + 70 + 192 + 0 +VERTEX + 5 +89 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-598.343 + 20 +-1.415 + 30 +114.782 + 70 + 192 + 0 +VERTEX + 5 +8A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-598.778 + 20 +-0.785 + 30 +114.172 + 70 + 192 + 0 +VERTEX + 5 +8B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-599.324 + 20 +-1.401 + 30 +114.172 + 70 + 192 + 0 +VERTEX + 5 +8C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-598.646 + 20 +-1.757 + 30 +114.782 + 70 + 192 + 0 +VERTEX + 5 +8D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-598.008 + 20 +-0.4929999999999999 + 30 +114.172 + 70 + 192 + 0 +VERTEX + 5 +8E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-597.9160000000002 + 20 +-1.253 + 30 +114.782 + 70 + 192 + 0 +VERTEX + 5 +8F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-595.146 + 20 +-390.164 + 30 +114.824 + 70 + 192 + 0 +VERTEX + 5 +90 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-598.478 + 20 +-381.643 + 30 +114.335 + 70 + 192 + 0 +VERTEX + 5 +91 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-598.94 + 20 +-381.7350000000001 + 30 +113.6 + 70 + 192 + 0 +VERTEX + 5 +92 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-595.813 + 20 +-390.44 + 30 +114.332 + 70 + 192 + 0 +VERTEX + 5 +93 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-596.2480000000002 + 20 +-390.62 + 30 +113.596 + 70 + 192 + 0 +VERTEX + 5 +94 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-578.809 + 20 +-411.874 + 30 +113.593 + 70 + 192 + 0 +VERTEX + 5 +95 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-591.483 + 20 +-398.547 + 30 +114.331 + 70 + 192 + 0 +VERTEX + 5 +96 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-585.142 + 20 +-405.142 + 30 +114.824 + 70 + 192 + 0 +VERTEX + 5 +97 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-585.653 + 20 +-405.653 + 30 +114.331 + 70 + 192 + 0 +VERTEX + 5 +98 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-585.985 + 20 +-405.985 + 30 +113.592 + 70 + 192 + 0 +VERTEX + 5 +99 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-591.874 + 20 +-398.808 + 30 +113.593 + 70 + 192 + 0 +VERTEX + 5 +9A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-578.5480000000002 + 20 +-411.483 + 30 +114.331 + 70 + 192 + 0 +VERTEX + 5 +9B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-570.62 + 20 +-416.247 + 30 +113.596 + 70 + 192 + 0 +VERTEX + 5 +9C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-561.736 + 20 +-418.939 + 30 +113.6 + 70 + 192 + 0 +VERTEX + 5 +9D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-570.44 + 20 +-415.813 + 30 +114.332 + 70 + 192 + 0 +VERTEX + 5 +9E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-570.164 + 20 +-415.145 + 30 +114.824 + 70 + 192 + 0 +VERTEX + 5 +9F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-561.644 + 20 +-418.478 + 30 +114.335 + 70 + 192 + 0 +VERTEX + 5 +A0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.507 + 20 +-419.696 + 30 +113.917 + 70 + 192 + 0 +VERTEX + 5 +A1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.507 + 20 +-419.373 + 30 +114.338 + 70 + 192 + 0 +VERTEX + 5 +A2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.507 + 20 +-418.96 + 30 +114.67 + 70 + 192 + 0 +VERTEX + 5 +A3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.507 + 20 +-418.6530000000001 + 30 +114.828 + 70 + 192 + 0 +VERTEX + 5 +A4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.507 + 20 +-417.958 + 30 +114.994 + 70 + 192 + 0 +VERTEX + 5 +A5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.507 + 20 +-419.998 + 30 +112.908 + 70 + 192 + 0 +VERTEX + 5 +A6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.507 + 20 +-419.847 + 30 +113.608 + 70 + 192 + 0 +VERTEX + 5 +A7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.507 + 20 +-417.958 + 30 +114.994 + 70 + 192 + 0 +VERTEX + 5 +A8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.507 + 20 +-418.6540000000001 + 30 +114.828 + 70 + 192 + 0 +VERTEX + 5 +A9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.507 + 20 +-418.96 + 30 +114.67 + 70 + 192 + 0 +VERTEX + 5 +AA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.507 + 20 +-419.374 + 30 +114.338 + 70 + 192 + 0 +VERTEX + 5 +AB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.507 + 20 +-419.696 + 30 +113.917 + 70 + 192 + 0 +VERTEX + 5 +AC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.507 + 20 +-419.847 + 30 +113.607 + 70 + 192 + 0 +VERTEX + 5 +AD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.507 + 20 +-419.998 + 30 +112.908 + 70 + 192 + 0 +VERTEX + 5 +AE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +586.491 + 20 +-404.777 + 30 +114.331 + 70 + 192 + 0 +VERTEX + 5 +AF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +585.967 + 20 +-404.279 + 30 +114.824 + 70 + 192 + 0 +VERTEX + 5 +B0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +562.0440000000001 + 20 +-418.877 + 30 +113.6 + 70 + 192 + 0 +VERTEX + 5 +B1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +579.3009999999999 + 20 +-410.968 + 30 +114.331 + 70 + 192 + 0 +VERTEX + 5 +B2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +571.1890000000001 + 20 +-416.006 + 30 +113.596 + 70 + 192 + 0 +VERTEX + 5 +B3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +570.719 + 20 +-414.9100000000001 + 30 +114.824 + 70 + 192 + 0 +VERTEX + 5 +B4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +571.0039999999999 + 20 +-415.574 + 30 +114.332 + 70 + 192 + 0 +VERTEX + 5 +B5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +561.949 + 20 +-418.416 + 30 +114.335 + 70 + 192 + 0 +VERTEX + 5 +B6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +579.5689999999998 + 20 +-411.354 + 30 +113.593 + 70 + 192 + 0 +VERTEX + 5 +B7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +596.9110000000001 + 20 +-388.913 + 30 +113.597 + 70 + 192 + 0 +VERTEX + 5 +B8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +599.2950000000002 + 20 +-379.6290000000001 + 30 +113.602 + 70 + 192 + 0 +VERTEX + 5 +B9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +596.4699999999999 + 20 +-388.75 + 30 +114.333 + 70 + 192 + 0 +VERTEX + 5 +BA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +595.792 + 20 +-388.5 + 30 +114.824 + 70 + 192 + 0 +VERTEX + 5 +BB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +598.83 + 20 +-379.559 + 30 +114.335 + 70 + 192 + 0 +VERTEX + 5 +BC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +592.3 + 20 +-397.273 + 30 +114.331 + 70 + 192 + 0 +VERTEX + 5 +BD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +592.699 + 20 +-397.521 + 30 +113.593 + 70 + 192 + 0 +VERTEX + 5 +BE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +586.8319999999999 + 20 +-405.1 + 30 +113.592 + 70 + 192 + 0 +VERTEX + 5 +BF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +597.9580000000001 + 20 +-372.5060000000001 + 30 +114.994 + 70 + 192 + 0 +VERTEX + 5 +C0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +597.9580000000001 + 20 +-2.2 + 30 +114.994 + 70 + 192 + 0 +VERTEX + 5 +C1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +598.65 + 20 +-372.5060000000001 + 30 +114.829 + 70 + 192 + 0 +VERTEX + 5 +C2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +598.755 + 20 +-2.2 + 30 +114.782 + 70 + 192 + 0 +VERTEX + 5 +C3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +598.96 + 20 +-372.5060000000001 + 30 +114.67 + 70 + 192 + 0 +VERTEX + 5 +C4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +599.9979999999999 + 20 +-372.5060000000001 + 30 +112.908 + 70 + 192 + 0 +VERTEX + 5 +C5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +599.9979999999999 + 20 +-2.2 + 30 +112.908 + 70 + 192 + 0 +VERTEX + 5 +C6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +599.846 + 20 +-372.5060000000001 + 30 +113.609 + 70 + 192 + 0 +VERTEX + 5 +C7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +599.945 + 20 +-2.2 + 30 +113.29 + 70 + 192 + 0 +VERTEX + 5 +C8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +599.6959999999999 + 20 +-372.5060000000001 + 30 +113.917 + 70 + 192 + 0 +VERTEX + 5 +C9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +599.6959999999999 + 20 +-2.2 + 30 +113.917 + 70 + 192 + 0 +VERTEX + 5 +CA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +599.371 + 20 +-372.5060000000001 + 30 +114.34 + 70 + 192 + 0 +VERTEX + 5 +CB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +598.96 + 20 +-2.2 + 30 +114.67 + 70 + 192 + 0 +VERTEX + 5 +CC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +599.52 + 20 +-2.2 + 30 +114.172 + 70 + 192 + 0 +VERTEX + 5 +CD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-597.958 + 20 +-372.5060000000001 + 30 +114.994 + 70 + 192 + 0 +VERTEX + 5 +CE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-598.653 + 20 +-372.5060000000001 + 30 +114.828 + 70 + 192 + 0 +VERTEX + 5 +CF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-597.958 + 20 +-2.2 + 30 +114.994 + 70 + 192 + 0 +VERTEX + 5 +D0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-598.96 + 20 +-372.5060000000001 + 30 +114.67 + 70 + 192 + 0 +VERTEX + 5 +D1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-598.755 + 20 +-2.2 + 30 +114.782 + 70 + 192 + 0 +VERTEX + 5 +D2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-599.373 + 20 +-372.5060000000001 + 30 +114.338 + 70 + 192 + 0 +VERTEX + 5 +D3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-598.96 + 20 +-2.2 + 30 +114.67 + 70 + 192 + 0 +VERTEX + 5 +D4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-599.696 + 20 +-372.5060000000001 + 30 +113.917 + 70 + 192 + 0 +VERTEX + 5 +D5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-599.521 + 20 +-2.2 + 30 +114.172 + 70 + 192 + 0 +VERTEX + 5 +D6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-599.847 + 20 +-372.5060000000001 + 30 +113.608 + 70 + 192 + 0 +VERTEX + 5 +D7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-599.696 + 20 +-2.2 + 30 +113.917 + 70 + 192 + 0 +VERTEX + 5 +D8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-599.998 + 20 +-372.5060000000001 + 30 +112.908 + 70 + 192 + 0 +VERTEX + 5 +D9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-599.998 + 20 +-2.2 + 30 +112.908 + 70 + 192 + 0 +VERTEX + 5 +DA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-599.9460000000001 + 20 +-2.2 + 30 +113.29 + 70 + 192 + 0 +VERTEX + 5 +DB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-597.8 + 20 +-0.004 + 30 +112.933 + 70 + 192 + 0 +VERTEX + 5 +DC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +597.8 + 20 +-0.004 + 30 +112.933 + 70 + 192 + 0 +VERTEX + 5 +DD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-597.8 + 20 +-0.055 + 30 +113.29 + 70 + 192 + 0 +VERTEX + 5 +DE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +597.8 + 20 +-0.055 + 30 +113.29 + 70 + 192 + 0 +VERTEX + 5 +DF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-597.8 + 20 +-0.317 + 30 +113.938 + 70 + 192 + 0 +VERTEX + 5 +E0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +597.8 + 20 +-0.317 + 30 +113.938 + 70 + 192 + 0 +VERTEX + 5 +E1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-597.8 + 20 +-0.4800000000000001 + 30 +114.172 + 70 + 192 + 0 +VERTEX + 5 +E2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +597.8 + 20 +-0.4800000000000001 + 30 +114.172 + 70 + 192 + 0 +VERTEX + 5 +E3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-597.8 + 20 +-1.062 + 30 +114.683 + 70 + 192 + 0 +VERTEX + 5 +E4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +597.8 + 20 +-1.062 + 30 +114.683 + 70 + 192 + 0 +VERTEX + 5 +E5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-597.8 + 20 +-1.246 + 30 +114.782 + 70 + 192 + 0 +VERTEX + 5 +E6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +597.8 + 20 +-1.246 + 30 +114.782 + 70 + 192 + 0 +VERTEX + 5 +E7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +597.8 + 20 +-2.067 + 30 +114.996 + 70 + 192 + 0 +VERTEX + 5 +E8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-597.8 + 20 +-2.067 + 30 +114.996 + 70 + 192 + 0 +VERTEX + 5 +E9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-597.1990000000001 + 20 +-1.203 + 30 +1.710000000000003 + 70 + 192 + 0 +VERTEX + 5 +EA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-595.4150000000002 + 20 +-1.253 + 30 +0.2180000000000099 + 70 + 192 + 0 +VERTEX + 5 +EB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-595.842 + 20 +-1.415 + 30 +0.2180000000000099 + 70 + 192 + 0 +VERTEX + 5 +EC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-596.518 + 20 +-0.435 + 30 +1.710000000000003 + 70 + 192 + 0 +VERTEX + 5 +ED +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-596.2769999999999 + 20 +-0.785 + 30 +0.8280000000000093 + 70 + 192 + 0 +VERTEX + 5 +EE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-595.5070000000002 + 20 +-0.4929999999999999 + 30 +0.8280000000000093 + 70 + 192 + 0 +VERTEX + 5 +EF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-595.558 + 20 +-0.071 + 30 +1.710000000000003 + 70 + 192 + 0 +VERTEX + 5 +F0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-596.145 + 20 +-1.757 + 30 +0.2180000000000099 + 70 + 192 + 0 +VERTEX + 5 +F1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-596.823 + 20 +-1.401 + 30 +0.8280000000000093 + 70 + 192 + 0 +VERTEX + 5 +F2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-597.182 + 20 +-1.062 + 30 +2.157000000000006 + 70 + 192 + 0 +VERTEX + 5 +F3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-599.683 + 20 +-1.062 + 30 +112.757 + 70 + 192 + 0 +VERTEX + 5 +F4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-597.247 + 20 +-1.178 + 30 +2.156000000000005 + 70 + 192 + 0 +VERTEX + 5 +F5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-599.7479999999999 + 20 +-1.178 + 30 +112.756 + 70 + 192 + 0 +VERTEX + 5 +F6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-597.495 + 20 +-2.067 + 30 +2.149999999999999 + 70 + 192 + 0 +VERTEX + 5 +F7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-599.996 + 20 +-2.067 + 30 +112.75 + 70 + 192 + 0 +VERTEX + 5 +F8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-599.05 + 20 +-0.3900000000000001 + 30 +112.772 + 70 + 192 + 0 +VERTEX + 5 +F9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-596.549 + 20 +-0.3900000000000001 + 30 +2.172000000000007 + 70 + 192 + 0 +VERTEX + 5 +FA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-598.938 + 20 +-0.317 + 30 +112.774 + 70 + 192 + 0 +VERTEX + 5 +FB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-596.438 + 20 +-0.317 + 30 +2.174000000000009 + 70 + 192 + 0 +VERTEX + 5 +FC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-598.0660000000001 + 20 +-0.016 + 30 +112.794 + 70 + 192 + 0 +VERTEX + 5 +FD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-595.5650000000002 + 20 +-0.016 + 30 +2.194000000000002 + 70 + 192 + 0 +VERTEX + 5 +FE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-595.432 + 20 +-0.004 + 30 +2.197000000000005 + 70 + 192 + 0 +VERTEX + 5 +FF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-597.933 + 20 +-0.004 + 30 +112.797 + 70 + 192 + 0 +VERTEX + 5 +100 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +596.06 + 20 +-0.195 + 30 +1.710000000000003 + 70 + 192 + 0 +VERTEX + 5 +101 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +595.9089999999999 + 20 +-0.592 + 30 +0.8280000000000093 + 70 + 192 + 0 +VERTEX + 5 +102 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +595.638 + 20 +-1.308 + 30 +0.2180000000000099 + 70 + 192 + 0 +VERTEX + 5 +103 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +596.0139999999999 + 20 +-1.567 + 30 +0.2180000000000099 + 70 + 192 + 0 +VERTEX + 5 +104 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +596.226 + 20 +-1.972 + 30 +0.2180000000000099 + 70 + 192 + 0 +VERTEX + 5 +105 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +596.9049999999999 + 20 +-0.778 + 30 +1.710000000000003 + 70 + 192 + 0 +VERTEX + 5 +106 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +596.5870000000001 + 20 +-1.06 + 30 +0.8280000000000093 + 70 + 192 + 0 +VERTEX + 5 +107 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +596.9699999999999 + 20 +-1.789 + 30 +0.8280000000000093 + 70 + 192 + 0 +VERTEX + 5 +108 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +597.382 + 20 +-1.687 + 30 +1.710000000000003 + 70 + 192 + 0 +VERTEX + 5 +109 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-595.3 + 20 +-2.067 + 30 +0.004000000000004 + 70 + 192 + 0 +VERTEX + 5 +10A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +595.2989999999999 + 20 +-2.067 + 30 +0.004000000000004 + 70 + 192 + 0 +VERTEX + 5 +10B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +595.2989999999999 + 20 +-0.004 + 30 +2.066999999999999 + 70 + 192 + 0 +VERTEX + 5 +10C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-595.3 + 20 +-0.004 + 30 +2.066999999999999 + 70 + 192 + 0 +VERTEX + 5 +10D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +595.2989999999999 + 20 +-0.055 + 30 +1.710000000000003 + 70 + 192 + 0 +VERTEX + 5 +10E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-595.3 + 20 +-0.055 + 30 +1.710000000000003 + 70 + 192 + 0 +VERTEX + 5 +10F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +595.2989999999999 + 20 +-0.317 + 30 +1.062000000000007 + 70 + 192 + 0 +VERTEX + 5 +110 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-595.3 + 20 +-0.317 + 30 +1.062000000000007 + 70 + 192 + 0 +VERTEX + 5 +111 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +595.2989999999999 + 20 +-0.4800000000000001 + 30 +0.8280000000000093 + 70 + 192 + 0 +VERTEX + 5 +112 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-595.3 + 20 +-0.4800000000000001 + 30 +0.8280000000000093 + 70 + 192 + 0 +VERTEX + 5 +113 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +595.2989999999999 + 20 +-1.062 + 30 +0.3170000000000117 + 70 + 192 + 0 +VERTEX + 5 +114 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-595.3 + 20 +-1.062 + 30 +0.3170000000000117 + 70 + 192 + 0 +VERTEX + 5 +115 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-595.3 + 20 +-1.246 + 30 +0.2180000000000099 + 70 + 192 + 0 +VERTEX + 5 +116 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +595.2989999999999 + 20 +-1.246 + 30 +0.2180000000000099 + 70 + 192 + 0 +VERTEX + 5 +117 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +597.933 + 20 +-0.004 + 30 +112.797 + 70 + 192 + 0 +VERTEX + 5 +118 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +595.432 + 20 +-0.004 + 30 +2.197000000000005 + 70 + 192 + 0 +VERTEX + 5 +119 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +599.6830000000001 + 20 +-1.062 + 30 +112.757 + 70 + 192 + 0 +VERTEX + 5 +11A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +597.182 + 20 +-1.062 + 30 +2.157000000000006 + 70 + 192 + 0 +VERTEX + 5 +11B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +599.9359999999999 + 20 +-1.674 + 30 +112.752 + 70 + 192 + 0 +VERTEX + 5 +11C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +597.4350000000001 + 20 +-1.674 + 30 +2.152000000000001 + 70 + 192 + 0 +VERTEX + 5 +11D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +599.9960000000001 + 20 +-2.067 + 30 +112.75 + 70 + 192 + 0 +VERTEX + 5 +11E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +597.495 + 20 +-2.067 + 30 +2.149999999999999 + 70 + 192 + 0 +VERTEX + 5 +11F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +596.9460000000003 + 20 +-0.741 + 30 +2.162999999999998 + 70 + 192 + 0 +VERTEX + 5 +120 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +599.4470000000001 + 20 +-0.741 + 30 +112.763 + 70 + 192 + 0 +VERTEX + 5 +121 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +596.437 + 20 +-0.317 + 30 +2.174000000000009 + 70 + 192 + 0 +VERTEX + 5 +122 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +598.9380000000001 + 20 +-0.317 + 30 +112.774 + 70 + 192 + 0 +VERTEX + 5 +123 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +598.58 + 20 +-0.143 + 30 +112.782 + 70 + 192 + 0 +VERTEX + 5 +124 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +596.08 + 20 +-0.143 + 30 +2.182000000000003 + 70 + 192 + 0 +VERTEX + 5 +125 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-582.6179999999999 + 20 +-402.618 + 30 +0.1630000000000104 + 70 + 192 + 0 +VERTEX + 5 +126 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-593.7130000000001 + 20 +-388.104 + 30 +1.31400000000001 + 70 + 192 + 0 +VERTEX + 5 +127 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-567.6510000000002 + 20 +-412.617 + 30 +0.1630000000000104 + 70 + 192 + 0 +VERTEX + 5 +128 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-583.117 + 20 +-403.117 + 30 +0.6200000000000094 + 70 + 192 + 0 +VERTEX + 5 +129 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-567.921 + 20 +-413.27 + 30 +0.6220000000000114 + 70 + 192 + 0 +VERTEX + 5 +12A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-583.456 + 20 +-403.456 + 30 +1.310000000000006 + 70 + 192 + 0 +VERTEX + 5 +12B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-568.1039999999999 + 20 +-413.7130000000001 + 30 +1.31400000000001 + 70 + 192 + 0 +VERTEX + 5 +12C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-593.27 + 20 +-387.92 + 30 +0.6220000000000114 + 70 + 192 + 0 +VERTEX + 5 +12D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-592.6179999999999 + 20 +-387.65 + 30 +0.1630000000000104 + 70 + 192 + 0 +VERTEX + 5 +12E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +582.6179999999999 + 20 +-402.618 + 30 +0.1630000000000104 + 70 + 192 + 0 +VERTEX + 5 +12F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +568.104 + 20 +-413.7130000000001 + 30 +1.31400000000001 + 70 + 192 + 0 +VERTEX + 5 +130 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +592.6170000000001 + 20 +-387.65 + 30 +0.1630000000000104 + 70 + 192 + 0 +VERTEX + 5 +131 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +583.117 + 20 +-403.117 + 30 +0.6200000000000094 + 70 + 192 + 0 +VERTEX + 5 +132 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +593.2700000000001 + 20 +-387.92 + 30 +0.6220000000000114 + 70 + 192 + 0 +VERTEX + 5 +133 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +583.4560000000002 + 20 +-403.456 + 30 +1.310000000000006 + 70 + 192 + 0 +VERTEX + 5 +134 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +593.7130000000001 + 20 +-388.104 + 30 +1.31400000000001 + 70 + 192 + 0 +VERTEX + 5 +135 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +567.921 + 20 +-413.27 + 30 +0.6220000000000114 + 70 + 192 + 0 +VERTEX + 5 +136 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +567.6500000000001 + 20 +-412.617 + 30 +0.1630000000000104 + 70 + 192 + 0 +VERTEX + 5 +137 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.006 + 20 +-417.318 + 30 +1.324000000000006 + 70 + 192 + 0 +VERTEX + 5 +138 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.0060000000001 + 20 +-417.318 + 30 +1.324000000000006 + 70 + 192 + 0 +VERTEX + 5 +139 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.006 + 20 +-417.308 + 30 +1.30100000000001 + 70 + 192 + 0 +VERTEX + 5 +13A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.0060000000001 + 20 +-417.308 + 30 +1.30100000000001 + 70 + 192 + 0 +VERTEX + 5 +13B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.006 + 20 +-416.838 + 30 +0.6270000000000026 + 70 + 192 + 0 +VERTEX + 5 +13C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.0060000000001 + 20 +-416.838 + 30 +0.6270000000000026 + 70 + 192 + 0 +VERTEX + 5 +13D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.006 + 20 +-416.8 + 30 +0.5910000000000082 + 70 + 192 + 0 +VERTEX + 5 +13E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.0060000000001 + 20 +-416.8 + 30 +0.5910000000000082 + 70 + 192 + 0 +VERTEX + 5 +13F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.006 + 20 +-416.13 + 30 +0.1630000000000104 + 70 + 192 + 0 +VERTEX + 5 +140 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.0060000000001 + 20 +-416.13 + 30 +0.1630000000000104 + 70 + 192 + 0 +VERTEX + 5 +141 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.0060000000001 + 20 +-416.055 + 30 +0.1340000000000091 + 70 + 192 + 0 +VERTEX + 5 +142 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.006 + 20 +-416.055 + 30 +0.1340000000000091 + 70 + 192 + 0 +VERTEX + 5 +143 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +596.0549999999998 + 20 +-370.0060000000001 + 30 +0.1340000000000091 + 70 + 192 + 0 +VERTEX + 5 +144 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +596.0549999999998 + 20 +-2.2 + 30 +0.1340000000000091 + 70 + 192 + 0 +VERTEX + 5 +145 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +597.444 + 20 +-2.2 + 30 +1.710000000000003 + 70 + 192 + 0 +VERTEX + 5 +146 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +597.3069999999999 + 20 +-2.2 + 30 +1.30100000000001 + 70 + 192 + 0 +VERTEX + 5 +147 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +597.3179999999999 + 20 +-370.0060000000001 + 30 +1.324000000000006 + 70 + 192 + 0 +VERTEX + 5 +148 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +597.02 + 20 +-2.2 + 30 +0.8280000000000093 + 70 + 192 + 0 +VERTEX + 5 +149 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +597.3069999999999 + 20 +-370.0060000000001 + 30 +1.30100000000001 + 70 + 192 + 0 +VERTEX + 5 +14A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +596.799 + 20 +-2.2 + 30 +0.5910000000000082 + 70 + 192 + 0 +VERTEX + 5 +14B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +596.837 + 20 +-370.0060000000001 + 30 +0.6270000000000026 + 70 + 192 + 0 +VERTEX + 5 +14C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +596.2539999999999 + 20 +-2.2 + 30 +0.2180000000000099 + 70 + 192 + 0 +VERTEX + 5 +14D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +596.1299999999999 + 20 +-370.0060000000001 + 30 +0.1630000000000104 + 70 + 192 + 0 +VERTEX + 5 +14E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +596.799 + 20 +-370.0060000000001 + 30 +0.5910000000000082 + 70 + 192 + 0 +VERTEX + 5 +14F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-596.13 + 20 +-370.0060000000001 + 30 +0.1630000000000104 + 70 + 192 + 0 +VERTEX + 5 +150 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-596.8 + 20 +-370.0060000000001 + 30 +0.5910000000000082 + 70 + 192 + 0 +VERTEX + 5 +151 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-596.8 + 20 +-2.2 + 30 +0.5910000000000082 + 70 + 192 + 0 +VERTEX + 5 +152 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-596.838 + 20 +-370.0060000000001 + 30 +0.6270000000000026 + 70 + 192 + 0 +VERTEX + 5 +153 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-597.318 + 20 +-370.0060000000001 + 30 +1.324000000000006 + 70 + 192 + 0 +VERTEX + 5 +154 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-597.4450000000002 + 20 +-2.2 + 30 +1.710000000000003 + 70 + 192 + 0 +VERTEX + 5 +155 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-597.308 + 20 +-370.0060000000001 + 30 +1.30100000000001 + 70 + 192 + 0 +VERTEX + 5 +156 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-597.02 + 20 +-2.2 + 30 +0.8280000000000093 + 70 + 192 + 0 +VERTEX + 5 +157 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-597.308 + 20 +-2.2 + 30 +1.30100000000001 + 70 + 192 + 0 +VERTEX + 5 +158 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-596.055 + 20 +-370.0060000000001 + 30 +0.1340000000000091 + 70 + 192 + 0 +VERTEX + 5 +159 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-596.055 + 20 +-2.2 + 30 +0.1340000000000091 + 70 + 192 + 0 +VERTEX + 5 +15A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-596.254 + 20 +-2.2 + 30 +0.2180000000000099 + 70 + 192 + 0 +VERTEX + 5 +15B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-597.499 + 20 +-2.2 + 30 +2.149999999999999 + 70 + 192 + 0 +VERTEX + 5 +15C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-600.0 + 20 +-2.2 + 30 +112.75 + 70 + 192 + 0 +VERTEX + 5 +15D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +585.3530000000001 + 20 +-403.696 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +15E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +570.3820000000001 + 20 +-414.125 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +15F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.507 + 20 +-417.8 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +160 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.507 + 20 +-417.8 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +161 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-569.837 + 20 +-414.355 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +162 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-584.536 + 20 +-404.535 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +163 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-594.3550000000001 + 20 +-389.836 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +164 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-597.8 + 20 +-372.5060000000001 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +165 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-597.8 + 20 +-2.2 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +166 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +597.8 + 20 +-2.2 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +167 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +597.8 + 20 +-372.5060000000001 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +168 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +594.9939999999999 + 20 +-388.205 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +169 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +597.8 + 20 +0.0 + 30 +112.8 + 70 + 192 + 0 +VERTEX + 5 +16A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-597.8 + 20 +0.0 + 30 +112.8 + 70 + 192 + 0 +VERTEX + 5 +16B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-595.3 + 20 +0.0 + 30 +2.200000000000007 + 70 + 192 + 0 +VERTEX + 5 +16C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +595.2989999999999 + 20 +0.0 + 30 +2.200000000000007 + 70 + 192 + 0 +VERTEX + 5 +16D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +595.2989999999999 + 20 +-2.2 + 30 +0.0 + 70 + 192 + 0 +VERTEX + 5 +16E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-595.3 + 20 +-2.2 + 30 +0.0 + 70 + 192 + 0 +VERTEX + 5 +16F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-595.3 + 20 +-370.0060000000001 + 30 +0.0 + 70 + 192 + 0 +VERTEX + 5 +170 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-591.855 + 20 +-387.334 + 30 +0.0 + 70 + 192 + 0 +VERTEX + 5 +171 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-582.035 + 20 +-402.035 + 30 +0.0 + 70 + 192 + 0 +VERTEX + 5 +172 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-567.335 + 20 +-411.855 + 30 +0.0 + 70 + 192 + 0 +VERTEX + 5 +173 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.006 + 20 +-415.299 + 30 +0.0 + 70 + 192 + 0 +VERTEX + 5 +174 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.0060000000001 + 20 +-415.299 + 30 +0.0 + 70 + 192 + 0 +VERTEX + 5 +175 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +567.335 + 20 +-411.855 + 30 +0.0 + 70 + 192 + 0 +VERTEX + 5 +176 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +582.035 + 20 +-402.035 + 30 +0.0 + 70 + 192 + 0 +VERTEX + 5 +177 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +591.8549999999999 + 20 +-387.334 + 30 +0.0 + 70 + 192 + 0 +VERTEX + 5 +178 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +595.2989999999999 + 20 +-370.0060000000001 + 30 +0.0 + 70 + 192 + 0 +VERTEX + 5 +179 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-568.444 + 20 +-120.987 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +17A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-581.9830000000001 + 20 +-130.029 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +17B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-591.028 + 20 +-143.565 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +17C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-567.852 + 20 +-122.418 + 30 +114.362 + 70 + 192 + 0 +VERTEX + 5 +17D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-589.164 + 20 +-144.337 + 30 +113.673 + 70 + 192 + 0 +VERTEX + 5 +17E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-589.605 + 20 +-144.154 + 30 +114.372 + 70 + 192 + 0 +VERTEX + 5 +17F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-590.26 + 20 +-143.883 + 30 +114.835 + 70 + 192 + 0 +VERTEX + 5 +180 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-568.1239999999999 + 20 +-121.76 + 30 +114.832 + 70 + 192 + 0 +VERTEX + 5 +181 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-580.8919999999999 + 20 +-131.121 + 30 +114.368 + 70 + 192 + 0 +VERTEX + 5 +182 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-581.394 + 20 +-130.619 + 30 +114.834 + 70 + 192 + 0 +VERTEX + 5 +183 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-580.5550000000001 + 20 +-131.458 + 30 +113.665 + 70 + 192 + 0 +VERTEX + 5 +184 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-567.669 + 20 +-122.858 + 30 +113.654 + 70 + 192 + 0 +VERTEX + 5 +185 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.486 + 20 +-117.814 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +186 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.486 + 20 +-117.947 + 30 +114.996 + 70 + 192 + 0 +VERTEX + 5 +187 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.486 + 20 +-118.656 + 30 +114.833 + 70 + 192 + 0 +VERTEX + 5 +188 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.486 + 20 +-118.953 + 30 +114.683 + 70 + 192 + 0 +VERTEX + 5 +189 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.486 + 20 +-119.37 + 30 +114.356 + 70 + 192 + 0 +VERTEX + 5 +18A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.486 + 20 +-119.697 + 30 +113.938 + 70 + 192 + 0 +VERTEX + 5 +18B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.486 + 20 +-119.847 + 30 +113.642 + 70 + 192 + 0 +VERTEX + 5 +18C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.486 + 20 +-120.011 + 30 +112.933 + 70 + 192 + 0 +VERTEX + 5 +18D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.4859999999999 + 20 +-117.814 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +18E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.4859999999999 + 20 +-117.947 + 30 +114.996 + 70 + 192 + 0 +VERTEX + 5 +18F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.4859999999999 + 20 +-118.656 + 30 +114.833 + 70 + 192 + 0 +VERTEX + 5 +190 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.4859999999999 + 20 +-119.37 + 30 +114.356 + 70 + 192 + 0 +VERTEX + 5 +191 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.4859999999999 + 20 +-119.697 + 30 +113.938 + 70 + 192 + 0 +VERTEX + 5 +192 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.4859999999999 + 20 +-118.953 + 30 +114.683 + 70 + 192 + 0 +VERTEX + 5 +193 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +568.2029999999999 + 20 +-121.794 + 30 +114.832 + 70 + 192 + 0 +VERTEX + 5 +194 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +591.119 + 20 +-143.786 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +195 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +590.3459999999999 + 20 +-144.1 + 30 +114.835 + 70 + 192 + 0 +VERTEX + 5 +196 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +581.5 + 20 +-130.738 + 30 +114.834 + 70 + 192 + 0 +VERTEX + 5 +197 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +568.5250000000001 + 20 +-121.02 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +198 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +582.0979999999998 + 20 +-130.145 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +199 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.4859999999999 + 20 +-119.847 + 30 +113.642 + 70 + 192 + 0 +VERTEX + 5 +19A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.4859999999999 + 20 +-120.011 + 30 +112.933 + 70 + 192 + 0 +VERTEX + 5 +19B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +589.689 + 20 +-144.368 + 30 +114.372 + 70 + 192 + 0 +VERTEX + 5 +19C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +589.247 + 20 +-144.548 + 30 +113.673 + 70 + 192 + 0 +VERTEX + 5 +19D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +580.996 + 20 +-131.238 + 30 +114.368 + 70 + 192 + 0 +VERTEX + 5 +19E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +580.658 + 20 +-131.574 + 30 +113.665 + 70 + 192 + 0 +VERTEX + 5 +19F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +567.746 + 20 +-122.891 + 30 +113.654 + 70 + 192 + 0 +VERTEX + 5 +1A0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +567.929 + 20 +-122.451 + 30 +114.362 + 70 + 192 + 0 +VERTEX + 5 +1A1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +592.1820000000001 + 20 +-159.519 + 30 +113.675 + 70 + 192 + 0 +VERTEX + 5 +1A2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +592.6619999999999 + 20 +-159.519 + 30 +114.372 + 70 + 192 + 0 +VERTEX + 5 +1A3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +592.696 + 20 +-159.519 + 30 +114.405 + 70 + 192 + 0 +VERTEX + 5 +1A4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +593.3689999999999 + 20 +-159.519 + 30 +114.837 + 70 + 192 + 0 +VERTEX + 5 +1A5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +593.4359999999999 + 20 +-159.519 + 30 +114.863 + 70 + 192 + 0 +VERTEX + 5 +1A6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +594.2010000000002 + 20 +-159.519 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +1A7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +592.1919999999999 + 20 +-159.519 + 30 +113.696 + 70 + 192 + 0 +VERTEX + 5 +1A8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-594.201 + 20 +-159.519 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +1A9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-593.4359999999999 + 20 +-159.519 + 30 +114.863 + 70 + 192 + 0 +VERTEX + 5 +1AA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-593.371 + 20 +-159.519 + 30 +114.837 + 70 + 192 + 0 +VERTEX + 5 +1AB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-592.696 + 20 +-159.519 + 30 +114.405 + 70 + 192 + 0 +VERTEX + 5 +1AC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-592.6629999999999 + 20 +-159.519 + 30 +114.373 + 70 + 192 + 0 +VERTEX + 5 +1AD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-592.192 + 20 +-159.519 + 30 +113.696 + 70 + 192 + 0 +VERTEX + 5 +1AE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-592.183 + 20 +-159.519 + 30 +113.676 + 70 + 192 + 0 +VERTEX + 5 +1AF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +594.2010000000002 + 20 +-372.507 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +1B0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +593.4359999999999 + 20 +-372.507 + 30 +114.863 + 70 + 192 + 0 +VERTEX + 5 +1B1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +593.3700000000001 + 20 +-372.507 + 30 +114.837 + 70 + 192 + 0 +VERTEX + 5 +1B2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +592.663 + 20 +-372.507 + 30 +114.373 + 70 + 192 + 0 +VERTEX + 5 +1B3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +592.1919999999999 + 20 +-372.507 + 30 +113.696 + 70 + 192 + 0 +VERTEX + 5 +1B4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +589.138 + 20 +-387.765 + 30 +113.686 + 70 + 192 + 0 +VERTEX + 5 +1B5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +568.2379999999999 + 20 +-411.1210000000001 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +1B6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +580.7909999999999 + 20 +-401.0120000000001 + 30 +114.38 + 70 + 192 + 0 +VERTEX + 5 +1B7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +567.926 + 20 +-410.353 + 30 +114.837 + 70 + 192 + 0 +VERTEX + 5 +1B8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +590.996 + 20 +-388.5390000000001 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +1B9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +581.875 + 20 +-402.105 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +1BA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +592.183 + 20 +-372.507 + 30 +113.676 + 70 + 192 + 0 +VERTEX + 5 +1BB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +567.659 + 20 +-409.698 + 30 +114.378 + 70 + 192 + 0 +VERTEX + 5 +1BC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +567.4789999999999 + 20 +-409.255 + 30 +113.686 + 70 + 192 + 0 +VERTEX + 5 +1BD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +580.453 + 20 +-400.672 + 30 +113.69 + 70 + 192 + 0 +VERTEX + 5 +1BE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +581.2879999999999 + 20 +-401.5130000000001 + 30 +114.837 + 70 + 192 + 0 +VERTEX + 5 +1BF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +592.696 + 20 +-372.507 + 30 +114.405 + 70 + 192 + 0 +VERTEX + 5 +1C0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +590.232 + 20 +-388.2210000000001 + 30 +114.837 + 70 + 192 + 0 +VERTEX + 5 +1C1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +589.5800000000003 + 20 +-387.9490000000001 + 30 +114.378 + 70 + 192 + 0 +VERTEX + 5 +1C2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.507 + 20 +-412.1820000000001 + 30 +113.675 + 70 + 192 + 0 +VERTEX + 5 +1C3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.507 + 20 +-414.201 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +1C4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.507 + 20 +-413.483 + 30 +114.88 + 70 + 192 + 0 +VERTEX + 5 +1C5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.507 + 20 +-413.366 + 30 +114.835 + 70 + 192 + 0 +VERTEX + 5 +1C6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.507 + 20 +-412.721 + 30 +114.428 + 70 + 192 + 0 +VERTEX + 5 +1C7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.507 + 20 +-412.1980000000001 + 30 +113.711 + 70 + 192 + 0 +VERTEX + 5 +1C8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.507 + 20 +-412.661 + 30 +114.371 + 70 + 192 + 0 +VERTEX + 5 +1C9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.507 + 20 +-414.201 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +1CA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-592.696 + 20 +-372.507 + 30 +114.405 + 70 + 192 + 0 +VERTEX + 5 +1CB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-593.371 + 20 +-372.507 + 30 +114.837 + 70 + 192 + 0 +VERTEX + 5 +1CC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-594.201 + 20 +-372.507 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +1CD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-593.4359999999999 + 20 +-372.507 + 30 +114.863 + 70 + 192 + 0 +VERTEX + 5 +1CE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-591.028 + 20 +-388.4640000000001 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +1CF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-590.264 + 20 +-388.147 + 30 +114.837 + 70 + 192 + 0 +VERTEX + 5 +1D0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.507 + 20 +-413.483 + 30 +114.88 + 70 + 192 + 0 +VERTEX + 5 +1D1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.507 + 20 +-413.37 + 30 +114.837 + 70 + 192 + 0 +VERTEX + 5 +1D2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.507 + 20 +-412.663 + 30 +114.373 + 70 + 192 + 0 +VERTEX + 5 +1D3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.507 + 20 +-412.1980000000001 + 30 +113.711 + 70 + 192 + 0 +VERTEX + 5 +1D4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.507 + 20 +-412.721 + 30 +114.428 + 70 + 192 + 0 +VERTEX + 5 +1D5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.507 + 20 +-412.183 + 30 +113.676 + 70 + 192 + 0 +VERTEX + 5 +1D6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-592.183 + 20 +-372.507 + 30 +113.676 + 70 + 192 + 0 +VERTEX + 5 +1D7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-589.168 + 20 +-387.694 + 30 +113.686 + 70 + 192 + 0 +VERTEX + 5 +1D8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-592.6629999999999 + 20 +-372.507 + 30 +114.373 + 70 + 192 + 0 +VERTEX + 5 +1D9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-592.192 + 20 +-372.507 + 30 +113.696 + 70 + 192 + 0 +VERTEX + 5 +1DA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-568.1469999999999 + 20 +-410.259 + 30 +114.837 + 70 + 192 + 0 +VERTEX + 5 +1DB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-568.465 + 20 +-411.028 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +1DC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-581.991 + 20 +-401.99 + 30 +115.0 + 70 + 192 + 0 +VERTEX + 5 +1DD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-581.4019999999999 + 20 +-401.402 + 30 +114.837 + 70 + 192 + 0 +VERTEX + 5 +1DE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-589.611 + 20 +-387.877 + 30 +114.378 + 70 + 192 + 0 +VERTEX + 5 +1DF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-580.9029999999999 + 20 +-400.903 + 30 +114.38 + 70 + 192 + 0 +VERTEX + 5 +1E0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-580.564 + 20 +-400.564 + 30 +113.69 + 70 + 192 + 0 +VERTEX + 5 +1E1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-567.693 + 20 +-409.164 + 30 +113.686 + 70 + 192 + 0 +VERTEX + 5 +1E2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-567.877 + 20 +-409.607 + 30 +114.378 + 70 + 192 + 0 +VERTEX + 5 +1E3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +592.0009999999999 + 20 +-159.519 + 30 +112.85 + 70 + 192 + 0 +VERTEX + 5 +1E4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +591.5149999999999 + 20 +-153.339 + 30 +112.849 + 70 + 192 + 0 +VERTEX + 5 +1E5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +589.0810000000001 + 20 +-144.616 + 30 +112.846 + 70 + 192 + 0 +VERTEX + 5 +1E6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +587.6940000000001 + 20 +-141.585 + 30 +112.844 + 70 + 192 + 0 +VERTEX + 5 +1E7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +567.679 + 20 +-123.051 + 30 +112.819 + 70 + 192 + 0 +VERTEX + 5 +1E8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +558.6669999999999 + 20 +-120.501 + 30 +112.808 + 70 + 192 + 0 +VERTEX + 5 +1E9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +570.4250000000001 + 20 +-124.32 + 30 +112.823 + 70 + 192 + 0 +VERTEX + 5 +1EA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +580.4269999999999 + 20 +-131.585 + 30 +112.835 + 70 + 192 + 0 +VERTEX + 5 +1EB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +580.5369999999999 + 20 +-131.695 + 30 +112.835 + 70 + 192 + 0 +VERTEX + 5 +1EC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +44.53499999999999 + 20 +-120.015 + 30 +87.42800000000003 + 70 + 192 + 0 +VERTEX + 5 +1ED +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +43.64999999999996 + 20 +-120.015 + 30 +88.645 + 70 + 192 + 0 +VERTEX + 5 +1EE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +42.43300000000006 + 20 +-120.015 + 30 +89.529 + 70 + 192 + 0 +VERTEX + 5 +1EF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +41.00199999999998 + 20 +-120.015 + 30 +89.994 + 70 + 192 + 0 +VERTEX + 5 +1F0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-41.00199999999998 + 20 +-120.015 + 30 +89.994 + 70 + 192 + 0 +VERTEX + 5 +1F1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-42.433 + 20 +-120.015 + 30 +89.529 + 70 + 192 + 0 +VERTEX + 5 +1F2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-43.651 + 20 +-120.015 + 30 +88.645 + 70 + 192 + 0 +VERTEX + 5 +1F3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-44.53499999999999 + 20 +-120.015 + 30 +87.42800000000003 + 70 + 192 + 0 +VERTEX + 5 +1F4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-44.99999999999999 + 20 +-120.015 + 30 +85.997 + 70 + 192 + 0 +VERTEX + 5 +1F5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-44.99999999999999 + 20 +-120.015 + 30 +84.49200000000002 + 70 + 192 + 0 +VERTEX + 5 +1F6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-44.53499999999999 + 20 +-120.015 + 30 +83.06099999999999 + 70 + 192 + 0 +VERTEX + 5 +1F7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-43.651 + 20 +-120.015 + 30 +81.844 + 70 + 192 + 0 +VERTEX + 5 +1F8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-42.433 + 20 +-120.015 + 30 +80.959 + 70 + 192 + 0 +VERTEX + 5 +1F9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-41.00199999999998 + 20 +-120.015 + 30 +80.49400000000001 + 70 + 192 + 0 +VERTEX + 5 +1FA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +41.00199999999998 + 20 +-120.015 + 30 +80.49400000000001 + 70 + 192 + 0 +VERTEX + 5 +1FB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +42.43300000000006 + 20 +-120.015 + 30 +80.959 + 70 + 192 + 0 +VERTEX + 5 +1FC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +43.64999999999996 + 20 +-120.015 + 30 +81.844 + 70 + 192 + 0 +VERTEX + 5 +1FD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +44.53499999999999 + 20 +-120.015 + 30 +83.06099999999999 + 70 + 192 + 0 +VERTEX + 5 +1FE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +45.00000000000005 + 20 +-120.015 + 30 +84.49200000000002 + 70 + 192 + 0 +VERTEX + 5 +1FF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +45.00000000000005 + 20 +-120.015 + 30 +85.997 + 70 + 192 + 0 +VERTEX + 5 +200 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.4859999999999 + 20 +-120.015 + 30 +112.8 + 70 + 192 + 0 +VERTEX + 5 +201 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.486 + 20 +-120.015 + 30 +112.8 + 70 + 192 + 0 +VERTEX + 5 +202 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-591.515 + 20 +-153.339 + 30 +112.849 + 70 + 192 + 0 +VERTEX + 5 +203 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-587.6949999999999 + 20 +-141.585 + 30 +112.844 + 70 + 192 + 0 +VERTEX + 5 +204 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-580.4280000000001 + 20 +-131.585 + 30 +112.835 + 70 + 192 + 0 +VERTEX + 5 +205 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-570.426 + 20 +-124.32 + 30 +112.823 + 70 + 192 + 0 +VERTEX + 5 +206 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-558.6679999999999 + 20 +-120.501 + 30 +112.808 + 70 + 192 + 0 +VERTEX + 5 +207 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-120.015 + 30 +44.50000000000001 + 70 + 192 + 0 +VERTEX + 5 +208 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-120.501 + 30 +38.32100000000001 + 70 + 192 + 0 +VERTEX + 5 +209 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-588.286 + 20 +-159.519 + 30 +31.617 + 70 + 192 + 0 +VERTEX + 5 +20A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-588.2270000000001 + 20 +-159.519 + 30 +31.448 + 70 + 192 + 0 +VERTEX + 5 +20B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-582.368 + 20 +-159.519 + 30 +20.56600000000001 + 70 + 192 + 0 +VERTEX + 5 +20C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-573.8720000000001 + 20 +-159.519 + 30 +12.335 + 70 + 192 + 0 +VERTEX + 5 +20D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-573.433 + 20 +-159.519 + 30 +12.02700000000001 + 70 + 192 + 0 +VERTEX + 5 +20E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-159.065 + 30 +5.003000000000007 + 70 + 192 + 0 +VERTEX + 5 +20F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-158.632 + 30 +5.010000000000001 + 70 + 192 + 0 +VERTEX + 5 +210 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-121.949 + 30 +32.291 + 70 + 192 + 0 +VERTEX + 5 +211 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-159.378 + 30 +5.000000000000004 + 70 + 192 + 0 +VERTEX + 5 +212 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-562.297 + 20 +-159.519 + 30 +6.667000000000006 + 70 + 192 + 0 +VERTEX + 5 +213 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-147.341 + 30 +6.923999999999999 + 70 + 192 + 0 +VERTEX + 5 +214 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.002 + 20 +-147.462 + 30 +6.900000000000003 + 70 + 192 + 0 +VERTEX + 5 +215 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-153.339 + 30 +5.486000000000006 + 70 + 192 + 0 +VERTEX + 5 +216 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-153.936 + 30 +5.396000000000011 + 70 + 192 + 0 +VERTEX + 5 +217 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-555.633 + 20 +-148.642 + 30 +6.818000000000006 + 70 + 192 + 0 +VERTEX + 5 +218 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-141.585 + 30 +9.305000000000007 + 70 + 192 + 0 +VERTEX + 5 +219 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-136.31 + 30 +12.536 + 70 + 192 + 0 +VERTEX + 5 +21A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-127.564 + 30 +21.277 + 70 + 192 + 0 +VERTEX + 5 +21B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-124.32 + 30 +26.56700000000001 + 70 + 192 + 0 +VERTEX + 5 +21C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-557.12 + 20 +-120.501 + 30 +44.36000000000002 + 70 + 192 + 0 +VERTEX + 5 +21D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-568.8720000000001 + 20 +-124.32 + 30 +44.09500000000001 + 70 + 192 + 0 +VERTEX + 5 +21E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-578.868 + 20 +-131.585 + 30 +43.86900000000001 + 70 + 192 + 0 +VERTEX + 5 +21F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-586.131 + 20 +-141.585 + 30 +43.70400000000001 + 70 + 192 + 0 +VERTEX + 5 +220 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-589.9499999999999 + 20 +-153.339 + 30 +43.618 + 70 + 192 + 0 +VERTEX + 5 +221 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-562.979 + 20 +-159.519 + 30 +6.878000000000009 + 70 + 192 + 0 +VERTEX + 5 +222 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-577.226 + 20 +-132.952 + 30 +31.697 + 70 + 192 + 0 +VERTEX + 5 +223 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-584.133 + 20 +-142.462 + 30 +31.54 + 70 + 192 + 0 +VERTEX + 5 +224 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-582.583 + 20 +-159.519 + 30 +20.85100000000001 + 70 + 192 + 0 +VERTEX + 5 +225 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-587.765 + 20 +-153.642 + 30 +31.458 + 70 + 192 + 0 +VERTEX + 5 +226 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-581.975 + 20 +-154.52 + 30 +20.57500000000001 + 70 + 192 + 0 +VERTEX + 5 +227 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-157.769 + 30 +5.039000000000001 + 70 + 192 + 0 +VERTEX + 5 +228 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-562.1469999999999 + 20 +-157.61 + 30 +6.670000000000009 + 70 + 192 + 0 +VERTEX + 5 +229 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-573.148 + 20 +-155.887 + 30 +12.034 + 70 + 192 + 0 +VERTEX + 5 +22A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-567.718 + 20 +-126.043 + 30 +31.91100000000001 + 70 + 192 + 0 +VERTEX + 5 +22B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-560.967 + 20 +-153.977 + 30 +6.697000000000008 + 70 + 192 + 0 +VERTEX + 5 +22C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-558.722 + 20 +-150.887 + 30 +6.748000000000004 + 70 + 192 + 0 +VERTEX + 5 +22D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-570.903 + 20 +-148.978 + 30 +12.08400000000001 + 70 + 192 + 0 +VERTEX + 5 +22E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-578.886 + 20 +-145.01 + 30 +20.64500000000001 + 70 + 192 + 0 +VERTEX + 5 +22F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-573.01 + 20 +-136.92 + 30 +20.77800000000001 + 70 + 192 + 0 +VERTEX + 5 +230 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-566.634 + 20 +-143.1 + 30 +12.18100000000001 + 70 + 192 + 0 +VERTEX + 5 +231 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-131.585 + 30 +16.569 + 70 + 192 + 0 +VERTEX + 5 +232 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-560.7579999999999 + 20 +-138.83 + 30 +12.31400000000001 + 70 + 192 + 0 +VERTEX + 5 +233 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-553.851 + 20 +-136.585 + 30 +12.47000000000001 + 70 + 192 + 0 +VERTEX + 5 +234 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-564.922 + 20 +-131.043 + 30 +20.96000000000001 + 70 + 192 + 0 +VERTEX + 5 +235 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-556.5420000000001 + 20 +-122.411 + 30 +32.16400000000001 + 70 + 192 + 0 +VERTEX + 5 +236 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-555.415 + 20 +-127.953 + 30 +21.175 + 70 + 192 + 0 +VERTEX + 5 +237 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-588.286 + 20 +-370.941 + 30 +31.617 + 70 + 192 + 0 +VERTEX + 5 +238 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-408.285 + 30 +31.617 + 70 + 192 + 0 +VERTEX + 5 +239 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-408.2260000000001 + 30 +31.445 + 70 + 192 + 0 +VERTEX + 5 +23A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-402.363 + 30 +20.56000000000001 + 70 + 192 + 0 +VERTEX + 5 +23B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-393.871 + 30 +12.335 + 70 + 192 + 0 +VERTEX + 5 +23C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-393.421 + 30 +12.019 + 70 + 192 + 0 +VERTEX + 5 +23D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-382.2660000000001 + 30 +6.658000000000011 + 70 + 192 + 0 +VERTEX + 5 +23E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-375.647 + 30 +5.281000000000008 + 70 + 192 + 0 +VERTEX + 5 +23F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-562.2669999999999 + 20 +-370.941 + 30 +6.658000000000011 + 70 + 192 + 0 +VERTEX + 5 +240 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-382.979 + 30 +6.878000000000009 + 70 + 192 + 0 +VERTEX + 5 +241 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-562.979 + 20 +-370.941 + 30 +6.878000000000009 + 70 + 192 + 0 +VERTEX + 5 +242 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-573.422 + 20 +-370.941 + 30 +12.019 + 70 + 192 + 0 +VERTEX + 5 +243 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-582.364 + 20 +-370.941 + 30 +20.56000000000001 + 70 + 192 + 0 +VERTEX + 5 +244 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-588.226 + 20 +-370.941 + 30 +31.445 + 70 + 192 + 0 +VERTEX + 5 +245 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-582.583 + 20 +-370.941 + 30 +20.85100000000001 + 70 + 192 + 0 +VERTEX + 5 +246 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-371.8090000000001 + 30 +5.010000000000001 + 70 + 192 + 0 +VERTEX + 5 +247 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-551.8100000000001 + 20 +-370.941 + 30 +5.010000000000001 + 70 + 192 + 0 +VERTEX + 5 +248 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-577.219 + 20 +-397.218 + 30 +31.1 + 70 + 192 + 0 +VERTEX + 5 +249 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-567.71 + 20 +-404.128 + 30 +31.158 + 70 + 192 + 0 +VERTEX + 5 +24A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-564.9150000000001 + 20 +-398.882 + 30 +20.32300000000001 + 70 + 192 + 0 +VERTEX + 5 +24B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-551.999 + 20 +-382.146 + 30 +6.637000000000004 + 70 + 192 + 0 +VERTEX + 5 +24C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-553.845 + 20 +-393.146 + 30 +11.96 + 70 + 192 + 0 +VERTEX + 5 +24D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-555.631 + 20 +-380.965 + 30 +6.581000000000003 + 70 + 192 + 0 +VERTEX + 5 +24E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-560.753 + 20 +-390.9 + 30 +11.854 + 70 + 192 + 0 +VERTEX + 5 +24F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-558.72 + 20 +-378.7200000000001 + 30 +6.561999999999999 + 70 + 192 + 0 +VERTEX + 5 +250 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-555.648 + 20 +-370.941 + 30 +5.281000000000008 + 70 + 192 + 0 +VERTEX + 5 +251 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-560.965 + 20 +-375.63 + 30 +6.581000000000003 + 70 + 192 + 0 +VERTEX + 5 +252 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-562.1460000000001 + 20 +-371.998 + 30 +6.637000000000004 + 70 + 192 + 0 +VERTEX + 5 +253 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-566.63 + 20 +-386.6300000000001 + 30 +11.81800000000001 + 70 + 192 + 0 +VERTEX + 5 +254 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-573.0039999999999 + 20 +-393.004 + 30 +20.273 + 70 + 192 + 0 +VERTEX + 5 +255 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-584.129 + 20 +-387.709 + 30 +31.158 + 70 + 192 + 0 +VERTEX + 5 +256 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-587.763 + 20 +-376.532 + 30 +31.32900000000001 + 70 + 192 + 0 +VERTEX + 5 +257 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-573.8720000000001 + 20 +-370.941 + 30 +12.335 + 70 + 192 + 0 +VERTEX + 5 +258 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-570.901 + 20 +-380.753 + 30 +11.854 + 70 + 192 + 0 +VERTEX + 5 +259 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-578.8820000000001 + 20 +-384.915 + 30 +20.32300000000001 + 70 + 192 + 0 +VERTEX + 5 +25A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-581.974 + 20 +-375.407 + 30 +20.468 + 70 + 192 + 0 +VERTEX + 5 +25B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-573.1469999999999 + 20 +-373.844 + 30 +11.96 + 70 + 192 + 0 +VERTEX + 5 +25C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-556.532 + 20 +-407.763 + 30 +31.32900000000001 + 70 + 192 + 0 +VERTEX + 5 +25D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-555.407 + 20 +-401.973 + 30 +20.468 + 70 + 192 + 0 +VERTEX + 5 +25E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-402.583 + 30 +20.85100000000001 + 70 + 192 + 0 +VERTEX + 5 +25F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-408.285 + 30 +31.617 + 70 + 192 + 0 +VERTEX + 5 +260 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +588.2850000000001 + 20 +-370.941 + 30 +31.617 + 70 + 192 + 0 +VERTEX + 5 +261 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +588.226 + 20 +-370.941 + 30 +31.445 + 70 + 192 + 0 +VERTEX + 5 +262 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +582.364 + 20 +-370.941 + 30 +20.56000000000001 + 70 + 192 + 0 +VERTEX + 5 +263 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +573.8720000000001 + 20 +-370.941 + 30 +12.335 + 70 + 192 + 0 +VERTEX + 5 +264 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +573.422 + 20 +-370.941 + 30 +12.019 + 70 + 192 + 0 +VERTEX + 5 +265 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +562.2669999999999 + 20 +-370.941 + 30 +6.658000000000011 + 70 + 192 + 0 +VERTEX + 5 +266 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +555.6469999999999 + 20 +-370.941 + 30 +5.281000000000008 + 70 + 192 + 0 +VERTEX + 5 +267 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-382.2660000000001 + 30 +6.658000000000011 + 70 + 192 + 0 +VERTEX + 5 +268 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +562.979 + 20 +-370.941 + 30 +6.878000000000009 + 70 + 192 + 0 +VERTEX + 5 +269 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-382.979 + 30 +6.878000000000009 + 70 + 192 + 0 +VERTEX + 5 +26A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-393.422 + 30 +12.019 + 70 + 192 + 0 +VERTEX + 5 +26B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-402.364 + 30 +20.56000000000001 + 70 + 192 + 0 +VERTEX + 5 +26C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-408.2260000000001 + 30 +31.445 + 70 + 192 + 0 +VERTEX + 5 +26D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-402.583 + 30 +20.85100000000001 + 70 + 192 + 0 +VERTEX + 5 +26E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +551.8100000000001 + 20 +-370.941 + 30 +5.010000000000001 + 70 + 192 + 0 +VERTEX + 5 +26F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-371.8090000000001 + 30 +5.010000000000001 + 70 + 192 + 0 +VERTEX + 5 +270 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +577.219 + 20 +-397.218 + 30 +31.1 + 70 + 192 + 0 +VERTEX + 5 +271 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +584.129 + 20 +-387.709 + 30 +31.158 + 70 + 192 + 0 +VERTEX + 5 +272 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +578.8820000000001 + 20 +-384.915 + 30 +20.32300000000001 + 70 + 192 + 0 +VERTEX + 5 +273 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +562.146 + 20 +-371.998 + 30 +6.637000000000004 + 70 + 192 + 0 +VERTEX + 5 +274 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +573.1469999999999 + 20 +-373.844 + 30 +11.96 + 70 + 192 + 0 +VERTEX + 5 +275 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +560.965 + 20 +-375.63 + 30 +6.581000000000003 + 70 + 192 + 0 +VERTEX + 5 +276 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +570.9000000000001 + 20 +-380.753 + 30 +11.854 + 70 + 192 + 0 +VERTEX + 5 +277 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +558.72 + 20 +-378.7200000000001 + 30 +6.561999999999999 + 70 + 192 + 0 +VERTEX + 5 +278 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-375.647 + 30 +5.281000000000008 + 70 + 192 + 0 +VERTEX + 5 +279 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +555.63 + 20 +-380.965 + 30 +6.581000000000003 + 70 + 192 + 0 +VERTEX + 5 +27A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +551.999 + 20 +-382.146 + 30 +6.637000000000004 + 70 + 192 + 0 +VERTEX + 5 +27B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +566.6300000000001 + 20 +-386.6300000000001 + 30 +11.81800000000001 + 70 + 192 + 0 +VERTEX + 5 +27C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +573.0039999999999 + 20 +-393.004 + 30 +20.273 + 70 + 192 + 0 +VERTEX + 5 +27D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +567.709 + 20 +-404.128 + 30 +31.158 + 70 + 192 + 0 +VERTEX + 5 +27E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +556.5319999999999 + 20 +-407.763 + 30 +31.32900000000001 + 70 + 192 + 0 +VERTEX + 5 +27F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-393.871 + 30 +12.335 + 70 + 192 + 0 +VERTEX + 5 +280 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +560.7529999999999 + 20 +-390.9 + 30 +11.854 + 70 + 192 + 0 +VERTEX + 5 +281 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +564.915 + 20 +-398.882 + 30 +20.32300000000001 + 70 + 192 + 0 +VERTEX + 5 +282 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +555.407 + 20 +-401.973 + 30 +20.468 + 70 + 192 + 0 +VERTEX + 5 +283 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +553.845 + 20 +-393.146 + 30 +11.96 + 70 + 192 + 0 +VERTEX + 5 +284 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +587.7629999999999 + 20 +-376.532 + 30 +31.32900000000001 + 70 + 192 + 0 +VERTEX + 5 +285 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +581.974 + 20 +-375.407 + 30 +20.468 + 70 + 192 + 0 +VERTEX + 5 +286 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +582.583 + 20 +-370.941 + 30 +20.85100000000001 + 70 + 192 + 0 +VERTEX + 5 +287 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-120.015 + 30 +44.50000000000001 + 70 + 192 + 0 +VERTEX + 5 +288 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +573.8720000000001 + 20 +-159.519 + 30 +12.335 + 70 + 192 + 0 +VERTEX + 5 +289 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +582.368 + 20 +-159.519 + 30 +20.56600000000001 + 70 + 192 + 0 +VERTEX + 5 +28A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +588.227 + 20 +-159.519 + 30 +31.448 + 70 + 192 + 0 +VERTEX + 5 +28B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +590.436 + 20 +-159.519 + 30 +43.60700000000001 + 70 + 192 + 0 +VERTEX + 5 +28C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +588.2850000000001 + 20 +-159.519 + 30 +31.617 + 70 + 192 + 0 +VERTEX + 5 +28D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-120.501 + 30 +38.32100000000001 + 70 + 192 + 0 +VERTEX + 5 +28E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-121.949 + 30 +32.291 + 70 + 192 + 0 +VERTEX + 5 +28F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-127.564 + 30 +21.277 + 70 + 192 + 0 +VERTEX + 5 +290 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-131.585 + 30 +16.569 + 70 + 192 + 0 +VERTEX + 5 +291 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-136.31 + 30 +12.536 + 70 + 192 + 0 +VERTEX + 5 +292 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-147.341 + 30 +6.923999999999999 + 70 + 192 + 0 +VERTEX + 5 +293 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-153.339 + 30 +5.486000000000006 + 70 + 192 + 0 +VERTEX + 5 +294 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-153.936 + 30 +5.396000000000011 + 70 + 192 + 0 +VERTEX + 5 +295 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-141.585 + 30 +9.305000000000007 + 70 + 192 + 0 +VERTEX + 5 +296 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.0010000000001 + 20 +-147.462 + 30 +6.900000000000003 + 70 + 192 + 0 +VERTEX + 5 +297 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +560.966 + 20 +-153.977 + 30 +6.697000000000008 + 70 + 192 + 0 +VERTEX + 5 +298 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-159.378 + 30 +5.000000000000004 + 70 + 192 + 0 +VERTEX + 5 +299 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-159.065 + 30 +5.003000000000007 + 70 + 192 + 0 +VERTEX + 5 +29A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-158.632 + 30 +5.010000000000001 + 70 + 192 + 0 +VERTEX + 5 +29B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +573.433 + 20 +-159.519 + 30 +12.02700000000001 + 70 + 192 + 0 +VERTEX + 5 +29C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +562.146 + 20 +-157.61 + 30 +6.670000000000009 + 70 + 192 + 0 +VERTEX + 5 +29D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +562.979 + 20 +-159.519 + 30 +6.878000000000009 + 70 + 192 + 0 +VERTEX + 5 +29E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +562.2969999999999 + 20 +-159.519 + 30 +6.667000000000006 + 70 + 192 + 0 +VERTEX + 5 +29F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +573.0099999999999 + 20 +-136.92 + 30 +20.77800000000001 + 70 + 192 + 0 +VERTEX + 5 +2A0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +577.225 + 20 +-132.952 + 30 +31.697 + 70 + 192 + 0 +VERTEX + 5 +2A1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +578.868 + 20 +-131.585 + 30 +43.86900000000001 + 70 + 192 + 0 +VERTEX + 5 +2A2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +589.949 + 20 +-153.339 + 30 +43.618 + 70 + 192 + 0 +VERTEX + 5 +2A3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +586.1310000000001 + 20 +-141.585 + 30 +43.70400000000001 + 70 + 192 + 0 +VERTEX + 5 +2A4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +568.871 + 20 +-124.32 + 30 +44.09500000000001 + 70 + 192 + 0 +VERTEX + 5 +2A5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +557.12 + 20 +-120.501 + 30 +44.36000000000002 + 70 + 192 + 0 +VERTEX + 5 +2A6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +567.7180000000001 + 20 +-126.043 + 30 +31.91100000000001 + 70 + 192 + 0 +VERTEX + 5 +2A7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +553.851 + 20 +-136.585 + 30 +12.47000000000001 + 70 + 192 + 0 +VERTEX + 5 +2A8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +564.922 + 20 +-131.043 + 30 +20.96000000000001 + 70 + 192 + 0 +VERTEX + 5 +2A9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +566.634 + 20 +-143.1 + 30 +12.18100000000001 + 70 + 192 + 0 +VERTEX + 5 +2AA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +560.7579999999999 + 20 +-138.83 + 30 +12.31400000000001 + 70 + 192 + 0 +VERTEX + 5 +2AB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-157.769 + 30 +5.039000000000001 + 70 + 192 + 0 +VERTEX + 5 +2AC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +555.6329999999999 + 20 +-148.642 + 30 +6.818000000000006 + 70 + 192 + 0 +VERTEX + 5 +2AD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +558.7220000000001 + 20 +-150.887 + 30 +6.748000000000004 + 70 + 192 + 0 +VERTEX + 5 +2AE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +573.1469999999999 + 20 +-155.887 + 30 +12.034 + 70 + 192 + 0 +VERTEX + 5 +2AF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +570.903 + 20 +-148.978 + 30 +12.08400000000001 + 70 + 192 + 0 +VERTEX + 5 +2B0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +578.8859999999999 + 20 +-145.01 + 30 +20.64500000000001 + 70 + 192 + 0 +VERTEX + 5 +2B1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +584.1329999999999 + 20 +-142.462 + 30 +31.54 + 70 + 192 + 0 +VERTEX + 5 +2B2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +582.583 + 20 +-159.519 + 30 +20.85100000000001 + 70 + 192 + 0 +VERTEX + 5 +2B3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +581.975 + 20 +-154.52 + 30 +20.57500000000001 + 70 + 192 + 0 +VERTEX + 5 +2B4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +587.764 + 20 +-153.642 + 30 +31.458 + 70 + 192 + 0 +VERTEX + 5 +2B5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +556.541 + 20 +-122.411 + 30 +32.16400000000001 + 70 + 192 + 0 +VERTEX + 5 +2B6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +555.4150000000001 + 20 +-127.953 + 30 +21.175 + 70 + 192 + 0 +VERTEX + 5 +2B7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-124.32 + 30 +26.56700000000001 + 70 + 192 + 0 +VERTEX + 5 +2B8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-370.941 + 30 +5.000000000000004 + 70 + 192 + 0 +VERTEX + 5 +2B9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-159.519 + 30 +5.000000000000004 + 70 + 192 + 0 +VERTEX + 5 +2BA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-159.519 + 30 +5.000000000000004 + 70 + 192 + 0 +VERTEX + 5 +2BB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-370.941 + 30 +5.000000000000004 + 70 + 192 + 0 +VERTEX + 5 +2BC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-561.765 + 20 +-419.089 + 30 +112.742 + 70 + 192 + 0 +VERTEX + 5 +2BD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-562.5740000000002 + 20 +-418.921 + 30 +112.741 + 70 + 192 + 0 +VERTEX + 5 +2BE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-560.074 + 20 +-416.42 + 30 +2.141000000000004 + 70 + 192 + 0 +VERTEX + 5 +2BF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-568.176 + 20 +-413.887 + 30 +2.135000000000012 + 70 + 192 + 0 +VERTEX + 5 +2C0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-570.678 + 20 +-416.387 + 30 +112.735 + 70 + 192 + 0 +VERTEX + 5 +2C1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-575.26 + 20 +-414.196 + 30 +112.733 + 70 + 192 + 0 +VERTEX + 5 +2C2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-572.759 + 20 +-411.695 + 30 +2.13300000000001 + 70 + 192 + 0 +VERTEX + 5 +2C3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-578.8919999999999 + 20 +-411.998 + 30 +112.731 + 70 + 192 + 0 +VERTEX + 5 +2C4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-586.091 + 20 +-406.0900000000001 + 30 +112.73 + 70 + 192 + 0 +VERTEX + 5 +2C5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-596.387 + 20 +-390.678 + 30 +112.735 + 70 + 192 + 0 +VERTEX + 5 +2C6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-598.921 + 20 +-382.574 + 30 +112.741 + 70 + 192 + 0 +VERTEX + 5 +2C7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-596.42 + 20 +-380.073 + 30 +2.141000000000004 + 70 + 192 + 0 +VERTEX + 5 +2C8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-600.0 + 20 +-372.5060000000001 + 30 +112.75 + 70 + 192 + 0 +VERTEX + 5 +2C9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-599.0889999999999 + 20 +-381.7650000000001 + 30 +112.742 + 70 + 192 + 0 +VERTEX + 5 +2CA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-597.499 + 20 +-370.0060000000001 + 30 +2.149999999999999 + 70 + 192 + 0 +VERTEX + 5 +2CB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-594.1959999999999 + 20 +-395.259 + 30 +112.733 + 70 + 192 + 0 +VERTEX + 5 +2CC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-593.8870000000001 + 20 +-388.1760000000001 + 30 +2.135000000000012 + 70 + 192 + 0 +VERTEX + 5 +2CD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-591.998 + 20 +-398.8910000000001 + 30 +112.731 + 70 + 192 + 0 +VERTEX + 5 +2CE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-583.59 + 20 +-403.59 + 30 +2.130000000000007 + 70 + 192 + 0 +VERTEX + 5 +2CF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-591.696 + 20 +-392.758 + 30 +2.13300000000001 + 70 + 192 + 0 +VERTEX + 5 +2D0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +599.4590000000001 + 20 +-379.654 + 30 +112.743 + 70 + 192 + 0 +VERTEX + 5 +2D1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +598.9209999999999 + 20 +-382.574 + 30 +112.741 + 70 + 192 + 0 +VERTEX + 5 +2D2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +596.4200000000001 + 20 +-380.073 + 30 +2.141000000000004 + 70 + 192 + 0 +VERTEX + 5 +2D3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +597.057 + 20 +-388.967 + 30 +112.736 + 70 + 192 + 0 +VERTEX + 5 +2D4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +593.887 + 20 +-388.1760000000001 + 30 +2.135000000000012 + 70 + 192 + 0 +VERTEX + 5 +2D5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +595.0859999999999 + 20 +-393.547 + 30 +112.733 + 70 + 192 + 0 +VERTEX + 5 +2D6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +594.196 + 20 +-395.259 + 30 +112.733 + 70 + 192 + 0 +VERTEX + 5 +2D7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +591.6949999999999 + 20 +-392.758 + 30 +2.13300000000001 + 70 + 192 + 0 +VERTEX + 5 +2D8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +592.829 + 20 +-397.6020000000001 + 30 +112.732 + 70 + 192 + 0 +VERTEX + 5 +2D9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +586.9479999999999 + 20 +-405.2100000000001 + 30 +112.73 + 70 + 192 + 0 +VERTEX + 5 +2DA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +586.091 + 20 +-406.0900000000001 + 30 +112.73 + 70 + 192 + 0 +VERTEX + 5 +2DB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +583.5899999999999 + 20 +-403.59 + 30 +2.130000000000007 + 70 + 192 + 0 +VERTEX + 5 +2DC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +579.6550000000001 + 20 +-411.477 + 30 +112.731 + 70 + 192 + 0 +VERTEX + 5 +2DD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +572.7589999999999 + 20 +-411.695 + 30 +2.13300000000001 + 70 + 192 + 0 +VERTEX + 5 +2DE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +575.2590000000002 + 20 +-414.196 + 30 +112.733 + 70 + 192 + 0 +VERTEX + 5 +2DF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +571.249 + 20 +-416.146 + 30 +112.735 + 70 + 192 + 0 +VERTEX + 5 +2E0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +568.1759999999999 + 20 +-413.887 + 30 +2.135000000000012 + 70 + 192 + 0 +VERTEX + 5 +2E1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +562.663 + 20 +-418.902 + 30 +112.741 + 70 + 192 + 0 +VERTEX + 5 +2E2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +562.5740000000002 + 20 +-418.921 + 30 +112.741 + 70 + 192 + 0 +VERTEX + 5 +2E3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +560.0730000000001 + 20 +-416.42 + 30 +2.141000000000004 + 70 + 192 + 0 +VERTEX + 5 +2E4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.006 + 20 +-417.499 + 30 +2.149999999999999 + 70 + 192 + 0 +VERTEX + 5 +2E5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.507 + 20 +-420.0 + 30 +112.75 + 70 + 192 + 0 +VERTEX + 5 +2E6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.507 + 20 +-420.0 + 30 +112.75 + 70 + 192 + 0 +VERTEX + 5 +2E7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.0060000000001 + 20 +-417.499 + 30 +2.149999999999999 + 70 + 192 + 0 +VERTEX + 5 +2E8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +600.0 + 20 +-2.2 + 30 +112.75 + 70 + 192 + 0 +VERTEX + 5 +2E9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +597.4989999999999 + 20 +-2.2 + 30 +2.149999999999999 + 70 + 192 + 0 +VERTEX + 5 +2EA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +597.4989999999999 + 20 +-102.812 + 30 +2.149999999999999 + 70 + 192 + 0 +VERTEX + 5 +2EB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +597.4989999999999 + 20 +-370.0060000000001 + 30 +2.149999999999999 + 70 + 192 + 0 +VERTEX + 5 +2EC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +600.0 + 20 +-372.5060000000001 + 30 +112.75 + 70 + 192 + 0 +VERTEX + 5 +2ED +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-591.519 + 20 +-378.666 + 30 +112.857 + 70 + 192 + 0 +VERTEX + 5 +2EE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-587.704 + 20 +-390.427 + 30 +112.867 + 70 + 192 + 0 +VERTEX + 5 +2EF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-578.861 + 20 +-398.8610000000001 + 30 +43.238 + 70 + 192 + 0 +VERTEX + 5 +2F0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-580.4359999999999 + 20 +-400.435 + 30 +112.87 + 70 + 192 + 0 +VERTEX + 5 +2F1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-570.428 + 20 +-407.704 + 30 +112.867 + 70 + 192 + 0 +VERTEX + 5 +2F2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-558.667 + 20 +-411.518 + 30 +112.857 + 70 + 192 + 0 +VERTEX + 5 +2F3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-567.6229999999999 + 20 +-408.996 + 30 +112.865 + 70 + 192 + 0 +VERTEX + 5 +2F4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-568.8630000000002 + 20 +-406.126 + 30 +43.29900000000001 + 70 + 192 + 0 +VERTEX + 5 +2F5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-557.11 + 20 +-409.948 + 30 +43.47900000000001 + 70 + 192 + 0 +VERTEX + 5 +2F6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-588.996 + 20 +-387.622 + 30 +112.865 + 70 + 192 + 0 +VERTEX + 5 +2F7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-589.948 + 20 +-377.109 + 30 +43.47900000000001 + 70 + 192 + 0 +VERTEX + 5 +2F8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-586.127 + 20 +-388.862 + 30 +43.29900000000001 + 70 + 192 + 0 +VERTEX + 5 +2F9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +558.6669999999999 + 20 +-411.518 + 30 +112.857 + 70 + 192 + 0 +VERTEX + 5 +2FA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +570.4269999999999 + 20 +-407.704 + 30 +112.867 + 70 + 192 + 0 +VERTEX + 5 +2FB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +580.326 + 20 +-400.544 + 30 +112.87 + 70 + 192 + 0 +VERTEX + 5 +2FC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +578.861 + 20 +-398.8610000000001 + 30 +43.238 + 70 + 192 + 0 +VERTEX + 5 +2FD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +580.435 + 20 +-400.435 + 30 +112.87 + 70 + 192 + 0 +VERTEX + 5 +2FE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +587.7039999999998 + 20 +-390.427 + 30 +112.867 + 70 + 192 + 0 +VERTEX + 5 +2FF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +586.1260000000002 + 20 +-388.862 + 30 +43.29900000000001 + 70 + 192 + 0 +VERTEX + 5 +300 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +588.966 + 20 +-387.694 + 30 +112.865 + 70 + 192 + 0 +VERTEX + 5 +301 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +589.948 + 20 +-377.109 + 30 +43.47900000000001 + 70 + 192 + 0 +VERTEX + 5 +302 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +592.0009999999999 + 20 +-372.507 + 30 +112.85 + 70 + 192 + 0 +VERTEX + 5 +303 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +591.5180000000003 + 20 +-378.666 + 30 +112.857 + 70 + 192 + 0 +VERTEX + 5 +304 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +590.436 + 20 +-370.941 + 30 +43.60700000000001 + 70 + 192 + 0 +VERTEX + 5 +305 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +567.408 + 20 +-409.084 + 30 +112.865 + 70 + 192 + 0 +VERTEX + 5 +306 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +557.1100000000001 + 20 +-409.948 + 30 +43.47900000000001 + 70 + 192 + 0 +VERTEX + 5 +307 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +568.8620000000001 + 20 +-406.126 + 30 +43.29900000000001 + 70 + 192 + 0 +VERTEX + 5 +308 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-590.4359999999999 + 20 +-159.519 + 30 +43.60700000000001 + 70 + 192 + 0 +VERTEX + 5 +309 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-590.4359999999999 + 20 +-370.941 + 30 +43.60700000000001 + 70 + 192 + 0 +VERTEX + 5 +30A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-592.0020000000001 + 20 +-372.507 + 30 +112.85 + 70 + 192 + 0 +VERTEX + 5 +30B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-592.0020000000001 + 20 +-159.519 + 30 +112.85 + 70 + 192 + 0 +VERTEX + 5 +30C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +550.941 + 20 +-410.436 + 30 +43.60700000000001 + 70 + 192 + 0 +VERTEX + 5 +30D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +552.507 + 20 +-412.0010000000001 + 30 +112.85 + 70 + 192 + 0 +VERTEX + 5 +30E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +131.4769999999999 + 20 +-412.0010000000001 + 30 +112.85 + 70 + 192 + 0 +VERTEX + 5 +30F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-552.507 + 20 +-412.0010000000001 + 30 +112.85 + 70 + 192 + 0 +VERTEX + 5 +310 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-550.942 + 20 +-410.436 + 30 +43.60700000000001 + 70 + 192 + 0 +VERTEX + 5 +311 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 4 + 72 + 18 + 73 + 407 + 74 + 388 + 0 +VERTEX + 5 +312 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 3 + 72 + 4 + 73 + 388 + 74 + 389 + 0 +VERTEX + 5 +313 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 2 + 72 + 3 + 73 + 389 + 74 + 390 + 0 +VERTEX + 5 +314 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 1 + 72 + 2 + 73 + 390 + 74 + 391 + 0 +VERTEX + 5 +315 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 16 + 72 + 1 + 73 + 391 + 74 + 392 + 0 +VERTEX + 5 +316 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 15 + 72 + 16 + 73 + 392 + 74 + 393 + 0 +VERTEX + 5 +317 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 14 + 72 + 15 + 73 + 393 + 74 + 394 + 0 +VERTEX + 5 +318 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 13 + 72 + 14 + 73 + 394 + 74 + 395 + 0 +VERTEX + 5 +319 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 12 + 72 + 13 + 73 + 395 + 74 + 396 + 0 +VERTEX + 5 +31A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 11 + 72 + 12 + 73 + 396 + 74 + 397 + 0 +VERTEX + 5 +31B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 5 + 72 + 6 + 73 + 404 + 74 + 405 + 0 +VERTEX + 5 +31C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 6 + 72 + 7 + 73 + 403 + 74 + 404 + 0 +VERTEX + 5 +31D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 17 + 72 + 5 + 73 + 405 + 74 + 406 + 0 +VERTEX + 5 +31E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 7 + 72 + 20 + 73 + 402 + 74 + 403 + 0 +VERTEX + 5 +31F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 9 + 72 + 10 + 73 + 398 + 74 + 399 + 0 +VERTEX + 5 +320 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 8 + 72 + 9 + 73 + 399 + 74 + 400 + 0 +VERTEX + 5 +321 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 10 + 72 + 11 + 73 + 397 + 74 + 398 + 0 +VERTEX + 5 +322 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 19 + 72 + 8 + 73 + 400 + 74 + 401 + 0 +VERTEX + 5 +323 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -644 + 72 + 641 + 73 + 640 + 0 +VERTEX + 5 +324 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 18 + 72 + 17 + 73 + 406 + 74 + 407 + 0 +VERTEX + 5 +325 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 20 + 72 + 19 + 73 + 401 + 74 + 402 + 0 +VERTEX + 5 +326 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 640 + 72 + 181 + 73 + 93 + 0 +VERTEX + 5 +327 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 93 + 72 + 181 + 73 + 21 + 0 +VERTEX + 5 +328 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 95 + 72 + 21 + 73 + 97 + 0 +VERTEX + 5 +329 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 95 + 72 + 93 + 73 + 21 + 0 +VERTEX + 5 +32A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 181 + 72 + 179 + 73 + 21 + 0 +VERTEX + 5 +32B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 21 + 72 + 179 + 73 + 177 + 0 +VERTEX + 5 +32C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 26 + 72 + 177 + 73 + 184 + 0 +VERTEX + 5 +32D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 186 + 72 + 26 + 73 + 184 + 0 +VERTEX + 5 +32E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 186 + 72 + 29 + 73 + 26 + 0 +VERTEX + 5 +32F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 186 + 72 + 187 + 73 + 29 + 0 +VERTEX + 5 +330 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 29 + 72 + 187 + 73 + 175 + 0 +VERTEX + 5 +331 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 118 + 72 + 175 + 73 + 116 + 0 +VERTEX + 5 +332 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 118 + 72 + 29 + 73 + 175 + 0 +VERTEX + 5 +333 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 118 + 72 + 120 + 73 + 29 + 0 +VERTEX + 5 +334 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 29 + 72 + 120 + 73 + 28 + 0 +VERTEX + 5 +335 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 99 + 72 + 24 + 73 + 90 + 0 +VERTEX + 5 +336 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 99 + 72 + 23 + 73 + 24 + 0 +VERTEX + 5 +337 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 99 + 72 + 100 + 73 + 23 + 0 +VERTEX + 5 +338 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 23 + 72 + 100 + 73 + 97 + 0 +VERTEX + 5 +339 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 21 + 72 + 23 + 73 + 97 + 0 +VERTEX + 5 +33A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 26 + 72 + 27 + 73 + 23 + 74 + 21 + 0 +VERTEX + 5 +33B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 21 + 72 + 177 + 73 + 26 + 0 +VERTEX + 5 +33C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 175 + 72 + 257 + 73 + 116 + 0 +VERTEX + 5 +33D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 120 + 72 + 122 + 73 + 28 + 0 +VERTEX + 5 +33E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 28 + 72 + 122 + 73 + 124 + 0 +VERTEX + 5 +33F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 22 + 72 + 124 + 73 + 126 + 0 +VERTEX + 5 +340 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 127 + 72 + 22 + 73 + 126 + 0 +VERTEX + 5 +341 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 127 + 72 + 254 + 73 + 22 + 0 +VERTEX + 5 +342 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 254 + 72 + 88 + 73 + 24 + 0 +VERTEX + 5 +343 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 254 + 72 + 24 + 73 + 25 + 0 +VERTEX + 5 +344 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 22 + 72 + 25 + 73 + 27 + 74 + 28 + 0 +VERTEX + 5 +345 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 124 + 72 + 22 + 73 + 28 + 0 +VERTEX + 5 +346 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 254 + 72 + 25 + 73 + 22 + 0 +VERTEX + 5 +347 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 90 + 72 + 24 + 73 + 88 + 0 +VERTEX + 5 +348 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 27 + 72 + 25 + 73 + 24 + 74 + 23 + 0 +VERTEX + 5 +349 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 29 + 72 + 28 + 73 + 27 + 74 + 26 + 0 +VERTEX + 5 +34A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 258 + 72 + 151 + 73 + 115 + 0 +VERTEX + 5 +34B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 115 + 72 + 151 + 73 + 148 + 0 +VERTEX + 5 +34C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 30 + 72 + 148 + 73 + 146 + 0 +VERTEX + 5 +34D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 32 + 72 + 146 + 73 + 144 + 0 +VERTEX + 5 +34E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 139 + 72 + 32 + 73 + 144 + 0 +VERTEX + 5 +34F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 139 + 72 + 31 + 73 + 32 + 0 +VERTEX + 5 +350 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 139 + 72 + 141 + 73 + 31 + 0 +VERTEX + 5 +351 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 31 + 72 + 141 + 73 + 143 + 0 +VERTEX + 5 +352 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 114 + 72 + 143 + 73 + 113 + 0 +VERTEX + 5 +353 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 114 + 72 + 31 + 73 + 143 + 0 +VERTEX + 5 +354 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 114 + 72 + 111 + 73 + 31 + 0 +VERTEX + 5 +355 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 31 + 72 + 111 + 73 + 35 + 0 +VERTEX + 5 +356 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 33 + 72 + 36 + 73 + 253 + 0 +VERTEX + 5 +357 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 143 + 72 + 244 + 73 + 113 + 0 +VERTEX + 5 +358 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 111 + 72 + 109 + 73 + 35 + 0 +VERTEX + 5 +359 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 35 + 72 + 109 + 73 + 107 + 0 +VERTEX + 5 +35A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 36 + 72 + 107 + 73 + 105 + 0 +VERTEX + 5 +35B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 103 + 72 + 36 + 73 + 105 + 0 +VERTEX + 5 +35C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 103 + 72 + 253 + 73 + 36 + 0 +VERTEX + 5 +35D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 253 + 72 + 128 + 73 + 38 + 0 +VERTEX + 5 +35E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 253 + 72 + 38 + 73 + 33 + 0 +VERTEX + 5 +35F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 128 + 72 + 125 + 73 + 38 + 0 +VERTEX + 5 +360 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 38 + 72 + 125 + 73 + 123 + 0 +VERTEX + 5 +361 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 37 + 72 + 123 + 73 + 121 + 0 +VERTEX + 5 +362 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 119 + 72 + 37 + 73 + 121 + 0 +VERTEX + 5 +363 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 119 + 72 + 30 + 73 + 37 + 0 +VERTEX + 5 +364 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 119 + 72 + 117 + 73 + 30 + 0 +VERTEX + 5 +365 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 30 + 72 + 117 + 73 + 115 + 0 +VERTEX + 5 +366 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 148 + 72 + 30 + 73 + 115 + 0 +VERTEX + 5 +367 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 32 + 72 + 30 + 73 + 146 + 0 +VERTEX + 5 +368 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 32 + 72 + 34 + 73 + 37 + 74 + 30 + 0 +VERTEX + 5 +369 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 34 + 72 + 32 + 73 + 31 + 74 + 35 + 0 +VERTEX + 5 +36A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 33 + 72 + 34 + 73 + 35 + 74 + 36 + 0 +VERTEX + 5 +36B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 34 + 72 + 33 + 73 + 38 + 74 + 37 + 0 +VERTEX + 5 +36C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 36 + 72 + 35 + 73 + 107 + 0 +VERTEX + 5 +36D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 38 + 72 + 123 + 73 + 37 + 0 +VERTEX + 5 +36E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 637 + 72 + 61 + 73 + 596 + 0 +VERTEX + 5 +36F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 596 + 72 + 61 + 73 + 52 + 0 +VERTEX + 5 +370 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 597 + 72 + 52 + 73 + 51 + 0 +VERTEX + 5 +371 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 600 + 72 + 51 + 73 + 601 + 0 +VERTEX + 5 +372 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 600 + 72 + 597 + 73 + 51 + 0 +VERTEX + 5 +373 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 61 + 72 + 62 + 73 + 52 + 0 +VERTEX + 5 +374 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 52 + 72 + 62 + 73 + 56 + 0 +VERTEX + 5 +375 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 55 + 72 + 56 + 73 + 57 + 0 +VERTEX + 5 +376 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 58 + 72 + 55 + 73 + 57 + 0 +VERTEX + 5 +377 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 58 + 72 + 59 + 73 + 55 + 0 +VERTEX + 5 +378 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 55 + 72 + 59 + 73 + 54 + 0 +VERTEX + 5 +379 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 53 + 72 + 54 + 73 + 50 + 0 +VERTEX + 5 +37A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 51 + 72 + 50 + 73 + 44 + 0 +VERTEX + 5 +37B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 601 + 72 + 44 + 73 + 603 + 0 +VERTEX + 5 +37C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 601 + 72 + 51 + 73 + 44 + 0 +VERTEX + 5 +37D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 59 + 72 + 60 + 73 + 54 + 0 +VERTEX + 5 +37E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 54 + 72 + 60 + 73 + 249 + 0 +VERTEX + 5 +37F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 250 + 72 + 54 + 73 + 249 + 0 +VERTEX + 5 +380 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 250 + 72 + 46 + 73 + 54 + 0 +VERTEX + 5 +381 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 250 + 72 + 39 + 73 + 46 + 0 +VERTEX + 5 +382 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 250 + 72 + 251 + 73 + 39 + 0 +VERTEX + 5 +383 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 39 + 72 + 251 + 73 + 101 + 0 +VERTEX + 5 +384 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 102 + 72 + 39 + 73 + 101 + 0 +VERTEX + 5 +385 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 102 + 72 + 40 + 73 + 39 + 0 +VERTEX + 5 +386 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 102 + 72 + 104 + 73 + 40 + 0 +VERTEX + 5 +387 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 40 + 72 + 104 + 73 + 106 + 0 +VERTEX + 5 +388 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 108 + 72 + 40 + 73 + 106 + 0 +VERTEX + 5 +389 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 108 + 72 + 41 + 73 + 40 + 0 +VERTEX + 5 +38A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 108 + 72 + 110 + 73 + 41 + 0 +VERTEX + 5 +38B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 41 + 72 + 110 + 73 + 112 + 0 +VERTEX + 5 +38C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 609 + 72 + 112 + 73 + 608 + 0 +VERTEX + 5 +38D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 609 + 72 + 41 + 73 + 112 + 0 +VERTEX + 5 +38E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 609 + 72 + 606 + 73 + 41 + 0 +VERTEX + 5 +38F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 41 + 72 + 606 + 73 + 43 + 0 +VERTEX + 5 +390 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 42 + 72 + 43 + 73 + 45 + 0 +VERTEX + 5 +391 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 39 + 72 + 45 + 73 + 46 + 0 +VERTEX + 5 +392 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 39 + 72 + 42 + 73 + 45 + 0 +VERTEX + 5 +393 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 39 + 72 + 40 + 73 + 42 + 0 +VERTEX + 5 +394 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 42 + 72 + 40 + 73 + 41 + 0 +VERTEX + 5 +395 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 43 + 72 + 42 + 73 + 41 + 0 +VERTEX + 5 +396 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 60 + 72 + 248 + 73 + 249 + 0 +VERTEX + 5 +397 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 251 + 72 + 252 + 73 + 101 + 0 +VERTEX + 5 +398 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 606 + 72 + 605 + 73 + 43 + 0 +VERTEX + 5 +399 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 43 + 72 + 605 + 73 + 611 + 0 +VERTEX + 5 +39A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 49 + 72 + 611 + 73 + 613 + 0 +VERTEX + 5 +39B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 48 + 72 + 613 + 73 + 604 + 0 +VERTEX + 5 +39C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 603 + 72 + 48 + 73 + 604 + 0 +VERTEX + 5 +39D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 603 + 72 + 44 + 73 + 48 + 0 +VERTEX + 5 +39E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 48 + 72 + 44 + 73 + 47 + 0 +VERTEX + 5 +39F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 49 + 72 + 47 + 73 + 45 + 0 +VERTEX + 5 +3A0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 43 + 72 + 49 + 73 + 45 + 0 +VERTEX + 5 +3A1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 43 + 72 + 611 + 73 + 49 + 0 +VERTEX + 5 +3A2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 597 + 72 + 596 + 73 + 52 + 0 +VERTEX + 5 +3A3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 54 + 72 + 46 + 73 + 50 + 0 +VERTEX + 5 +3A4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 50 + 72 + 46 + 73 + 47 + 0 +VERTEX + 5 +3A5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 44 + 72 + 50 + 73 + 47 + 0 +VERTEX + 5 +3A6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 47 + 72 + 46 + 73 + 45 + 0 +VERTEX + 5 +3A7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 613 + 72 + 48 + 73 + 49 + 0 +VERTEX + 5 +3A8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 49 + 72 + 48 + 73 + 47 + 0 +VERTEX + 5 +3A9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 50 + 72 + 51 + 73 + 53 + 0 +VERTEX + 5 +3AA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 53 + 72 + 51 + 73 + 52 + 0 +VERTEX + 5 +3AB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 55 + 72 + 52 + 73 + 56 + 0 +VERTEX + 5 +3AC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 55 + 72 + 53 + 73 + 52 + 0 +VERTEX + 5 +3AD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 55 + 72 + 54 + 73 + 53 + 0 +VERTEX + 5 +3AE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 61 + 72 + 637 + 73 + 638 + 74 + 69 + 0 +VERTEX + 5 +3AF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 62 + 72 + 69 + 73 + 68 + 0 +VERTEX + 5 +3B0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 67 + 72 + 62 + 73 + 68 + 0 +VERTEX + 5 +3B1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 67 + 72 + 56 + 73 + 62 + 0 +VERTEX + 5 +3B2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 67 + 72 + 57 + 73 + 56 + 0 +VERTEX + 5 +3B3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 67 + 72 + 66 + 73 + 57 + 0 +VERTEX + 5 +3B4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 57 + 72 + 66 + 73 + 65 + 0 +VERTEX + 5 +3B5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 58 + 72 + 65 + 73 + 59 + 0 +VERTEX + 5 +3B6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 58 + 72 + 57 + 73 + 65 + 0 +VERTEX + 5 +3B7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 65 + 72 + 64 + 73 + 59 + 0 +VERTEX + 5 +3B8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 59 + 72 + 64 + 73 + 63 + 0 +VERTEX + 5 +3B9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 60 + 72 + 59 + 73 + 63 + 0 +VERTEX + 5 +3BA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 247 + 72 + 248 + 73 + 60 + 74 + 63 + 0 +VERTEX + 5 +3BB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 62 + 72 + 61 + 73 + 69 + 0 +VERTEX + 5 +3BC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 644 + 72 + 92 + 73 + 616 + 0 +VERTEX + 5 +3BD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 616 + 72 + 92 + 73 + 80 + 0 +VERTEX + 5 +3BE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 617 + 72 + 80 + 73 + 79 + 0 +VERTEX + 5 +3BF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 619 + 72 + 79 + 73 + 621 + 0 +VERTEX + 5 +3C0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 619 + 72 + 617 + 73 + 79 + 0 +VERTEX + 5 +3C1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 92 + 72 + 94 + 73 + 80 + 0 +VERTEX + 5 +3C2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 80 + 72 + 94 + 73 + 96 + 0 +VERTEX + 5 +3C3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 83 + 72 + 96 + 73 + 98 + 0 +VERTEX + 5 +3C4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 91 + 72 + 83 + 73 + 98 + 0 +VERTEX + 5 +3C5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 91 + 72 + 89 + 73 + 83 + 0 +VERTEX + 5 +3C6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 83 + 72 + 89 + 73 + 82 + 0 +VERTEX + 5 +3C7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 81 + 72 + 82 + 73 + 84 + 0 +VERTEX + 5 +3C8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 79 + 72 + 84 + 73 + 85 + 0 +VERTEX + 5 +3C9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 621 + 72 + 85 + 73 + 622 + 0 +VERTEX + 5 +3CA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 621 + 72 + 79 + 73 + 85 + 0 +VERTEX + 5 +3CB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 89 + 72 + 87 + 73 + 82 + 0 +VERTEX + 5 +3CC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 82 + 72 + 87 + 73 + 256 + 0 +VERTEX + 5 +3CD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 71 + 72 + 256 + 73 + 245 + 0 +VERTEX + 5 +3CE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 246 + 72 + 71 + 73 + 245 + 0 +VERTEX + 5 +3CF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 246 + 72 + 75 + 73 + 71 + 0 +VERTEX + 5 +3D0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 246 + 72 + 63 + 73 + 75 + 0 +VERTEX + 5 +3D1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 246 + 72 + 247 + 73 + 63 + 0 +VERTEX + 5 +3D2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 87 + 72 + 255 + 73 + 256 + 0 +VERTEX + 5 +3D3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 63 + 72 + 64 + 73 + 75 + 0 +VERTEX + 5 +3D4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 75 + 72 + 64 + 73 + 77 + 0 +VERTEX + 5 +3D5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 76 + 72 + 77 + 73 + 72 + 0 +VERTEX + 5 +3D6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 74 + 72 + 72 + 73 + 633 + 0 +VERTEX + 5 +3D7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 631 + 72 + 74 + 73 + 633 + 0 +VERTEX + 5 +3D8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 631 + 72 + 630 + 73 + 74 + 0 +VERTEX + 5 +3D9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 74 + 72 + 630 + 73 + 78 + 0 +VERTEX + 5 +3DA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 73 + 72 + 78 + 73 + 86 + 0 +VERTEX + 5 +3DB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 70 + 72 + 86 + 73 + 84 + 0 +VERTEX + 5 +3DC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 71 + 72 + 84 + 73 + 82 + 0 +VERTEX + 5 +3DD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 256 + 72 + 71 + 73 + 82 + 0 +VERTEX + 5 +3DE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 64 + 72 + 65 + 73 + 77 + 0 +VERTEX + 5 +3DF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 77 + 72 + 65 + 73 + 66 + 0 +VERTEX + 5 +3E0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 67 + 72 + 77 + 73 + 66 + 0 +VERTEX + 5 +3E1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 67 + 72 + 72 + 73 + 77 + 0 +VERTEX + 5 +3E2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 67 + 72 + 68 + 73 + 72 + 0 +VERTEX + 5 +3E3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 72 + 72 + 68 + 73 + 69 + 0 +VERTEX + 5 +3E4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 638 + 72 + 72 + 73 + 69 + 0 +VERTEX + 5 +3E5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 638 + 72 + 634 + 73 + 72 + 0 +VERTEX + 5 +3E6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 72 + 72 + 634 + 73 + 633 + 0 +VERTEX + 5 +3E7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 630 + 72 + 628 + 73 + 78 + 0 +VERTEX + 5 +3E8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 78 + 72 + 628 + 73 + 626 + 0 +VERTEX + 5 +3E9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 86 + 72 + 626 + 73 + 625 + 0 +VERTEX + 5 +3EA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 624 + 72 + 86 + 73 + 625 + 0 +VERTEX + 5 +3EB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 624 + 72 + 85 + 73 + 86 + 0 +VERTEX + 5 +3EC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 624 + 72 + 622 + 73 + 85 + 0 +VERTEX + 5 +3ED +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 617 + 72 + 616 + 73 + 80 + 0 +VERTEX + 5 +3EE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 84 + 72 + 71 + 73 + 70 + 0 +VERTEX + 5 +3EF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 70 + 72 + 71 + 73 + 73 + 0 +VERTEX + 5 +3F0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 86 + 72 + 70 + 73 + 73 + 0 +VERTEX + 5 +3F1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 71 + 72 + 75 + 73 + 73 + 0 +VERTEX + 5 +3F2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 73 + 72 + 75 + 73 + 76 + 0 +VERTEX + 5 +3F3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 74 + 72 + 76 + 73 + 72 + 0 +VERTEX + 5 +3F4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 74 + 72 + 73 + 73 + 76 + 0 +VERTEX + 5 +3F5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 74 + 72 + 78 + 73 + 73 + 0 +VERTEX + 5 +3F6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 77 + 72 + 76 + 73 + 75 + 0 +VERTEX + 5 +3F7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 86 + 72 + 78 + 73 + 626 + 0 +VERTEX + 5 +3F8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 84 + 72 + 79 + 73 + 81 + 0 +VERTEX + 5 +3F9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 81 + 72 + 79 + 73 + 80 + 0 +VERTEX + 5 +3FA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 83 + 72 + 80 + 73 + 96 + 0 +VERTEX + 5 +3FB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 83 + 72 + 81 + 73 + 80 + 0 +VERTEX + 5 +3FC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 83 + 72 + 82 + 73 + 81 + 0 +VERTEX + 5 +3FD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 86 + 72 + 85 + 73 + 84 + 0 +VERTEX + 5 +3FE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 88 + 72 + 254 + 73 + 255 + 74 + 87 + 0 +VERTEX + 5 +3FF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 89 + 72 + 88 + 73 + 87 + 0 +VERTEX + 5 +400 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 89 + 72 + 90 + 73 + 88 + 0 +VERTEX + 5 +401 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 89 + 72 + 91 + 73 + 90 + 0 +VERTEX + 5 +402 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 90 + 72 + 91 + 73 + 99 + 0 +VERTEX + 5 +403 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 99 + 72 + 91 + 73 + 98 + 0 +VERTEX + 5 +404 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 100 + 72 + 98 + 73 + 96 + 0 +VERTEX + 5 +405 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 97 + 72 + 96 + 73 + 94 + 0 +VERTEX + 5 +406 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 95 + 72 + 94 + 73 + 92 + 0 +VERTEX + 5 +407 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 93 + 72 + 95 + 73 + 92 + 0 +VERTEX + 5 +408 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 644 + 72 + 640 + 73 + 93 + 74 + 92 + 0 +VERTEX + 5 +409 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 95 + 72 + 97 + 73 + 94 + 0 +VERTEX + 5 +40A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 97 + 72 + 100 + 73 + 96 + 0 +VERTEX + 5 +40B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 100 + 72 + 99 + 73 + 98 + 0 +VERTEX + 5 +40C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 113 + 72 + 244 + 73 + 608 + 74 + 112 + 0 +VERTEX + 5 +40D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 114 + 72 + 112 + 73 + 110 + 0 +VERTEX + 5 +40E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 111 + 72 + 110 + 73 + 108 + 0 +VERTEX + 5 +40F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 109 + 72 + 108 + 73 + 106 + 0 +VERTEX + 5 +410 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 107 + 72 + 106 + 73 + 104 + 0 +VERTEX + 5 +411 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 105 + 72 + 104 + 73 + 102 + 0 +VERTEX + 5 +412 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 103 + 72 + 102 + 73 + 101 + 0 +VERTEX + 5 +413 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 103 + 72 + 101 + 73 + 252 + 74 + 253 + 0 +VERTEX + 5 +414 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 103 + 72 + 105 + 73 + 102 + 0 +VERTEX + 5 +415 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 105 + 72 + 107 + 73 + 104 + 0 +VERTEX + 5 +416 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 107 + 72 + 109 + 73 + 106 + 0 +VERTEX + 5 +417 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 109 + 72 + 111 + 73 + 108 + 0 +VERTEX + 5 +418 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 111 + 72 + 114 + 73 + 110 + 0 +VERTEX + 5 +419 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 114 + 72 + 113 + 73 + 112 + 0 +VERTEX + 5 +41A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 128 + 72 + 253 + 73 + 254 + 74 + 127 + 0 +VERTEX + 5 +41B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 115 + 72 + 116 + 73 + 257 + 74 + 258 + 0 +VERTEX + 5 +41C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 117 + 72 + 118 + 73 + 116 + 74 + 115 + 0 +VERTEX + 5 +41D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 119 + 72 + 120 + 73 + 118 + 74 + 117 + 0 +VERTEX + 5 +41E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 121 + 72 + 122 + 73 + 120 + 74 + 119 + 0 +VERTEX + 5 +41F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 123 + 72 + 124 + 73 + 122 + 74 + 121 + 0 +VERTEX + 5 +420 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 125 + 72 + 126 + 73 + 124 + 74 + 123 + 0 +VERTEX + 5 +421 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 128 + 72 + 127 + 73 + 126 + 74 + 125 + 0 +VERTEX + 5 +422 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 262 + 72 + 241 + 73 + 136 + 0 +VERTEX + 5 +423 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 262 + 72 + 136 + 73 + 131 + 0 +VERTEX + 5 +424 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 262 + 72 + 131 + 73 + 130 + 0 +VERTEX + 5 +425 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 161 + 72 + 130 + 73 + 173 + 0 +VERTEX + 5 +426 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 161 + 72 + 262 + 73 + 130 + 0 +VERTEX + 5 +427 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 241 + 72 + 242 + 73 + 136 + 0 +VERTEX + 5 +428 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 136 + 72 + 242 + 73 + 233 + 0 +VERTEX + 5 +429 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 137 + 72 + 233 + 73 + 238 + 0 +VERTEX + 5 +42A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 239 + 72 + 137 + 73 + 238 + 0 +VERTEX + 5 +42B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 239 + 72 + 129 + 73 + 137 + 0 +VERTEX + 5 +42C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 239 + 72 + 236 + 73 + 129 + 0 +VERTEX + 5 +42D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 129 + 72 + 236 + 73 + 142 + 0 +VERTEX + 5 +42E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 140 + 72 + 129 + 73 + 142 + 0 +VERTEX + 5 +42F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 140 + 72 + 138 + 73 + 129 + 0 +VERTEX + 5 +430 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 129 + 72 + 138 + 73 + 132 + 0 +VERTEX + 5 +431 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 130 + 72 + 134 + 73 + 172 + 0 +VERTEX + 5 +432 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 173 + 72 + 130 + 73 + 172 + 0 +VERTEX + 5 +433 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 236 + 72 + 243 + 73 + 142 + 0 +VERTEX + 5 +434 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 138 + 72 + 145 + 73 + 132 + 0 +VERTEX + 5 +435 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 132 + 72 + 145 + 73 + 147 + 0 +VERTEX + 5 +436 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 135 + 72 + 147 + 73 + 149 + 0 +VERTEX + 5 +437 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 164 + 72 + 149 + 73 + 150 + 0 +VERTEX + 5 +438 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 259 + 72 + 164 + 73 + 150 + 0 +VERTEX + 5 +439 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 149 + 72 + 164 + 73 + 135 + 0 +VERTEX + 5 +43A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 135 + 72 + 164 + 73 + 166 + 0 +VERTEX + 5 +43B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 168 + 72 + 135 + 73 + 166 + 0 +VERTEX + 5 +43C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 168 + 72 + 134 + 73 + 135 + 0 +VERTEX + 5 +43D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 168 + 72 + 170 + 73 + 134 + 0 +VERTEX + 5 +43E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 134 + 72 + 170 + 73 + 172 + 0 +VERTEX + 5 +43F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 132 + 72 + 133 + 73 + 137 + 74 + 129 + 0 +VERTEX + 5 +440 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 134 + 72 + 130 + 73 + 131 + 74 + 133 + 0 +VERTEX + 5 +441 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 133 + 72 + 131 + 73 + 136 + 74 + 137 + 0 +VERTEX + 5 +442 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 147 + 72 + 135 + 73 + 132 + 0 +VERTEX + 5 +443 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 135 + 72 + 134 + 73 + 133 + 74 + 132 + 0 +VERTEX + 5 +444 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 233 + 72 + 137 + 73 + 136 + 0 +VERTEX + 5 +445 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 151 + 72 + 258 + 73 + 259 + 74 + 150 + 0 +VERTEX + 5 +446 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 139 + 72 + 144 + 73 + 145 + 74 + 138 + 0 +VERTEX + 5 +447 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 140 + 72 + 141 + 73 + 139 + 74 + 138 + 0 +VERTEX + 5 +448 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 143 + 72 + 141 + 73 + 140 + 74 + 142 + 0 +VERTEX + 5 +449 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 143 + 72 + 142 + 73 + 243 + 74 + 244 + 0 +VERTEX + 5 +44A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 146 + 72 + 147 + 73 + 145 + 74 + 144 + 0 +VERTEX + 5 +44B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 148 + 72 + 149 + 73 + 147 + 74 + 146 + 0 +VERTEX + 5 +44C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 151 + 72 + 150 + 73 + 149 + 74 + 148 + 0 +VERTEX + 5 +44D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 641 + 72 + 221 + 73 + 182 + 0 +VERTEX + 5 +44E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 182 + 72 + 221 + 73 + 160 + 0 +VERTEX + 5 +44F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 180 + 72 + 160 + 73 + 178 + 0 +VERTEX + 5 +450 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 180 + 72 + 182 + 73 + 160 + 0 +VERTEX + 5 +451 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 221 + 72 + 222 + 73 + 160 + 0 +VERTEX + 5 +452 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 160 + 72 + 222 + 73 + 159 + 0 +VERTEX + 5 +453 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 167 + 72 + 153 + 73 + 169 + 0 +VERTEX + 5 +454 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 167 + 72 + 152 + 73 + 153 + 0 +VERTEX + 5 +455 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 167 + 72 + 165 + 73 + 152 + 0 +VERTEX + 5 +456 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 152 + 72 + 165 + 73 + 176 + 0 +VERTEX + 5 +457 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 188 + 72 + 152 + 73 + 176 + 0 +VERTEX + 5 +458 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 188 + 72 + 185 + 73 + 152 + 0 +VERTEX + 5 +459 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 152 + 72 + 185 + 73 + 157 + 0 +VERTEX + 5 +45A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 158 + 72 + 153 + 73 + 152 + 74 + 157 + 0 +VERTEX + 5 +45B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 222 + 72 + 224 + 73 + 159 + 0 +VERTEX + 5 +45C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 159 + 72 + 224 + 73 + 226 + 0 +VERTEX + 5 +45D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 156 + 72 + 226 + 73 + 228 + 0 +VERTEX + 5 +45E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 220 + 72 + 156 + 73 + 228 + 0 +VERTEX + 5 +45F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 220 + 72 + 261 + 73 + 156 + 0 +VERTEX + 5 +460 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 261 + 72 + 162 + 73 + 154 + 0 +VERTEX + 5 +461 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 261 + 72 + 154 + 73 + 155 + 0 +VERTEX + 5 +462 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 261 + 72 + 155 + 73 + 156 + 0 +VERTEX + 5 +463 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 162 + 72 + 174 + 73 + 154 + 0 +VERTEX + 5 +464 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 154 + 72 + 174 + 73 + 171 + 0 +VERTEX + 5 +465 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 153 + 72 + 171 + 73 + 169 + 0 +VERTEX + 5 +466 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 153 + 72 + 154 + 73 + 171 + 0 +VERTEX + 5 +467 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 158 + 72 + 155 + 73 + 154 + 74 + 153 + 0 +VERTEX + 5 +468 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 156 + 72 + 155 + 73 + 158 + 74 + 159 + 0 +VERTEX + 5 +469 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 226 + 72 + 156 + 73 + 159 + 0 +VERTEX + 5 +46A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 165 + 72 + 163 + 73 + 176 + 0 +VERTEX + 5 +46B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 176 + 72 + 163 + 73 + 260 + 0 +VERTEX + 5 +46C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 185 + 72 + 183 + 73 + 157 + 0 +VERTEX + 5 +46D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 157 + 72 + 183 + 73 + 178 + 0 +VERTEX + 5 +46E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 160 + 72 + 157 + 73 + 178 + 0 +VERTEX + 5 +46F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 160 + 72 + 159 + 73 + 158 + 74 + 157 + 0 +VERTEX + 5 +470 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 261 + 72 + 262 + 73 + 161 + 74 + 162 + 0 +VERTEX + 5 +471 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 174 + 72 + 162 + 73 + 161 + 74 + 173 + 0 +VERTEX + 5 +472 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 163 + 72 + 164 + 73 + 259 + 74 + 260 + 0 +VERTEX + 5 +473 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 165 + 72 + 166 + 73 + 164 + 74 + 163 + 0 +VERTEX + 5 +474 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 167 + 72 + 168 + 73 + 166 + 74 + 165 + 0 +VERTEX + 5 +475 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 169 + 72 + 170 + 73 + 168 + 74 + 167 + 0 +VERTEX + 5 +476 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 171 + 72 + 172 + 73 + 170 + 74 + 169 + 0 +VERTEX + 5 +477 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 174 + 72 + 173 + 73 + 172 + 74 + 171 + 0 +VERTEX + 5 +478 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 260 + 72 + 257 + 73 + 175 + 74 + 176 + 0 +VERTEX + 5 +479 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 188 + 72 + 176 + 73 + 175 + 74 + 187 + 0 +VERTEX + 5 +47A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 178 + 72 + 183 + 73 + 184 + 74 + 177 + 0 +VERTEX + 5 +47B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 179 + 72 + 180 + 73 + 178 + 74 + 177 + 0 +VERTEX + 5 +47C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 182 + 72 + 180 + 73 + 179 + 74 + 181 + 0 +VERTEX + 5 +47D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 182 + 72 + 181 + 73 + 640 + 74 + 641 + 0 +VERTEX + 5 +47E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 185 + 72 + 186 + 73 + 184 + 74 + 183 + 0 +VERTEX + 5 +47F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 188 + 72 + 187 + 73 + 186 + 74 + 185 + 0 +VERTEX + 5 +480 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 610 + 72 + 235 + 73 + 607 + 0 +VERTEX + 5 +481 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 607 + 72 + 235 + 73 + 190 + 0 +VERTEX + 5 +482 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 612 + 72 + 190 + 73 + 615 + 0 +VERTEX + 5 +483 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 612 + 72 + 607 + 73 + 190 + 0 +VERTEX + 5 +484 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 235 + 72 + 237 + 73 + 190 + 0 +VERTEX + 5 +485 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 190 + 72 + 237 + 73 + 234 + 0 +VERTEX + 5 +486 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 196 + 72 + 234 + 73 + 232 + 0 +VERTEX + 5 +487 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 197 + 72 + 232 + 73 + 231 + 0 +VERTEX + 5 +488 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 240 + 72 + 197 + 73 + 231 + 0 +VERTEX + 5 +489 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 240 + 72 + 264 + 73 + 197 + 0 +VERTEX + 5 +48A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 240 + 72 + 263 + 73 + 264 + 0 +VERTEX + 5 +48B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 264 + 72 + 265 + 73 + 197 + 0 +VERTEX + 5 +48C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 197 + 72 + 265 + 73 + 189 + 0 +VERTEX + 5 +48D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 192 + 72 + 189 + 73 + 191 + 0 +VERTEX + 5 +48E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 193 + 72 + 191 + 73 + 213 + 0 +VERTEX + 5 +48F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 211 + 72 + 193 + 73 + 213 + 0 +VERTEX + 5 +490 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 211 + 72 + 195 + 73 + 193 + 0 +VERTEX + 5 +491 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 211 + 72 + 209 + 73 + 195 + 0 +VERTEX + 5 +492 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 195 + 72 + 209 + 73 + 207 + 0 +VERTEX + 5 +493 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 598 + 72 + 207 + 73 + 636 + 0 +VERTEX + 5 +494 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 598 + 72 + 195 + 73 + 207 + 0 +VERTEX + 5 +495 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 598 + 72 + 599 + 73 + 195 + 0 +VERTEX + 5 +496 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 195 + 72 + 599 + 73 + 602 + 0 +VERTEX + 5 +497 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 194 + 72 + 602 + 73 + 614 + 0 +VERTEX + 5 +498 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 615 + 72 + 194 + 73 + 614 + 0 +VERTEX + 5 +499 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 615 + 72 + 190 + 73 + 194 + 0 +VERTEX + 5 +49A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 194 + 72 + 190 + 73 + 196 + 0 +VERTEX + 5 +49B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 192 + 72 + 196 + 73 + 197 + 0 +VERTEX + 5 +49C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 189 + 72 + 192 + 73 + 197 + 0 +VERTEX + 5 +49D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 189 + 72 + 265 + 73 + 191 + 0 +VERTEX + 5 +49E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 191 + 72 + 265 + 73 + 266 + 0 +VERTEX + 5 +49F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 218 + 72 + 266 + 73 + 267 + 0 +VERTEX + 5 +4A0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 218 + 72 + 191 + 73 + 266 + 0 +VERTEX + 5 +4A1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 218 + 72 + 215 + 73 + 191 + 0 +VERTEX + 5 +4A2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 191 + 72 + 215 + 73 + 213 + 0 +VERTEX + 5 +4A3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 234 + 72 + 196 + 73 + 190 + 0 +VERTEX + 5 +4A4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 192 + 72 + 193 + 73 + 194 + 0 +VERTEX + 5 +4A5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 196 + 72 + 192 + 73 + 194 + 0 +VERTEX + 5 +4A6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 193 + 72 + 192 + 73 + 191 + 0 +VERTEX + 5 +4A7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 602 + 72 + 194 + 73 + 195 + 0 +VERTEX + 5 +4A8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 195 + 72 + 194 + 73 + 193 + 0 +VERTEX + 5 +4A9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 197 + 72 + 196 + 73 + 232 + 0 +VERTEX + 5 +4AA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 639 + 72 + 208 + 73 + 635 + 0 +VERTEX + 5 +4AB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 635 + 72 + 208 + 73 + 199 + 0 +VERTEX + 5 +4AC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 632 + 72 + 199 + 73 + 629 + 0 +VERTEX + 5 +4AD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 632 + 72 + 635 + 73 + 199 + 0 +VERTEX + 5 +4AE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 208 + 72 + 210 + 73 + 199 + 0 +VERTEX + 5 +4AF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 199 + 72 + 210 + 73 + 212 + 0 +VERTEX + 5 +4B0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 205 + 72 + 212 + 73 + 214 + 0 +VERTEX + 5 +4B1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 206 + 72 + 214 + 73 + 216 + 0 +VERTEX + 5 +4B2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 217 + 72 + 206 + 73 + 216 + 0 +VERTEX + 5 +4B3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 217 + 72 + 269 + 73 + 206 + 0 +VERTEX + 5 +4B4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 217 + 72 + 268 + 73 + 269 + 0 +VERTEX + 5 +4B5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 269 + 72 + 270 + 73 + 206 + 0 +VERTEX + 5 +4B6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 206 + 72 + 270 + 73 + 198 + 0 +VERTEX + 5 +4B7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 201 + 72 + 198 + 73 + 200 + 0 +VERTEX + 5 +4B8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 202 + 72 + 200 + 73 + 230 + 0 +VERTEX + 5 +4B9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 227 + 72 + 202 + 73 + 230 + 0 +VERTEX + 5 +4BA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 227 + 72 + 204 + 73 + 202 + 0 +VERTEX + 5 +4BB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 227 + 72 + 225 + 73 + 204 + 0 +VERTEX + 5 +4BC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 204 + 72 + 225 + 73 + 223 + 0 +VERTEX + 5 +4BD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 618 + 72 + 223 + 73 + 643 + 0 +VERTEX + 5 +4BE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 618 + 72 + 204 + 73 + 223 + 0 +VERTEX + 5 +4BF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 618 + 72 + 620 + 73 + 204 + 0 +VERTEX + 5 +4C0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 204 + 72 + 620 + 73 + 623 + 0 +VERTEX + 5 +4C1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 203 + 72 + 623 + 73 + 627 + 0 +VERTEX + 5 +4C2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 629 + 72 + 203 + 73 + 627 + 0 +VERTEX + 5 +4C3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 629 + 72 + 199 + 73 + 203 + 0 +VERTEX + 5 +4C4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 203 + 72 + 199 + 73 + 205 + 0 +VERTEX + 5 +4C5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 201 + 72 + 205 + 73 + 206 + 0 +VERTEX + 5 +4C6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 198 + 72 + 201 + 73 + 206 + 0 +VERTEX + 5 +4C7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 198 + 72 + 270 + 73 + 200 + 0 +VERTEX + 5 +4C8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 200 + 72 + 270 + 73 + 271 + 0 +VERTEX + 5 +4C9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 219 + 72 + 271 + 73 + 272 + 0 +VERTEX + 5 +4CA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 219 + 72 + 200 + 73 + 271 + 0 +VERTEX + 5 +4CB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 219 + 72 + 229 + 73 + 200 + 0 +VERTEX + 5 +4CC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 200 + 72 + 229 + 73 + 230 + 0 +VERTEX + 5 +4CD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 212 + 72 + 205 + 73 + 199 + 0 +VERTEX + 5 +4CE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 201 + 72 + 202 + 73 + 203 + 0 +VERTEX + 5 +4CF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 205 + 72 + 201 + 73 + 203 + 0 +VERTEX + 5 +4D0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 202 + 72 + 201 + 73 + 200 + 0 +VERTEX + 5 +4D1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 623 + 72 + 203 + 73 + 204 + 0 +VERTEX + 5 +4D2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 204 + 72 + 203 + 73 + 202 + 0 +VERTEX + 5 +4D3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 206 + 72 + 205 + 73 + 214 + 0 +VERTEX + 5 +4D4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 218 + 72 + 267 + 73 + 268 + 74 + 217 + 0 +VERTEX + 5 +4D5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 207 + 72 + 208 + 73 + 639 + 74 + 636 + 0 +VERTEX + 5 +4D6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 209 + 72 + 210 + 73 + 208 + 74 + 207 + 0 +VERTEX + 5 +4D7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 211 + 72 + 212 + 73 + 210 + 74 + 209 + 0 +VERTEX + 5 +4D8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 213 + 72 + 214 + 73 + 212 + 74 + 211 + 0 +VERTEX + 5 +4D9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 215 + 72 + 216 + 73 + 214 + 74 + 213 + 0 +VERTEX + 5 +4DA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 218 + 72 + 217 + 73 + 216 + 74 + 215 + 0 +VERTEX + 5 +4DB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 272 + 72 + 261 + 73 + 220 + 74 + 219 + 0 +VERTEX + 5 +4DC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 219 + 72 + 220 + 73 + 229 + 0 +VERTEX + 5 +4DD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 229 + 72 + 220 + 73 + 228 + 0 +VERTEX + 5 +4DE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 230 + 72 + 228 + 73 + 226 + 0 +VERTEX + 5 +4DF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 227 + 72 + 226 + 73 + 224 + 0 +VERTEX + 5 +4E0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 225 + 72 + 224 + 73 + 222 + 0 +VERTEX + 5 +4E1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 223 + 72 + 222 + 73 + 221 + 0 +VERTEX + 5 +4E2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 642 + 72 + 221 + 73 + 641 + 0 +VERTEX + 5 +4E3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 642 + 72 + 223 + 73 + 221 + 0 +VERTEX + 5 +4E4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 642 + 72 + 643 + 73 + 223 + 0 +VERTEX + 5 +4E5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 223 + 72 + 225 + 73 + 222 + 0 +VERTEX + 5 +4E6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 225 + 72 + 227 + 73 + 224 + 0 +VERTEX + 5 +4E7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 227 + 72 + 230 + 73 + 226 + 0 +VERTEX + 5 +4E8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 230 + 72 + 229 + 73 + 228 + 0 +VERTEX + 5 +4E9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 241 + 72 + 262 + 73 + 263 + 74 + 240 + 0 +VERTEX + 5 +4EA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 242 + 72 + 240 + 73 + 231 + 0 +VERTEX + 5 +4EB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 232 + 72 + 242 + 73 + 231 + 0 +VERTEX + 5 +4EC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 232 + 72 + 233 + 73 + 242 + 0 +VERTEX + 5 +4ED +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 232 + 72 + 234 + 73 + 233 + 0 +VERTEX + 5 +4EE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 233 + 72 + 234 + 73 + 238 + 0 +VERTEX + 5 +4EF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 238 + 72 + 234 + 73 + 237 + 0 +VERTEX + 5 +4F0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 239 + 72 + 237 + 73 + 235 + 0 +VERTEX + 5 +4F1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 236 + 72 + 235 + 73 + 610 + 0 +VERTEX + 5 +4F2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 243 + 72 + 236 + 73 + 610 + 0 +VERTEX + 5 +4F3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 236 + 72 + 239 + 73 + 235 + 0 +VERTEX + 5 +4F4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 239 + 72 + 238 + 73 + 237 + 0 +VERTEX + 5 +4F5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 242 + 72 + 241 + 73 + 240 + 0 +VERTEX + 5 +4F6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 610 + 72 + 608 + 73 + 244 + 74 + 243 + 0 +VERTEX + 5 +4F7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -16 + 72 + 2 + 73 + 1 + 0 +VERTEX + 5 +4F8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 260 + 72 + 259 + 73 + 258 + 74 + 257 + 0 +VERTEX + 5 +4F9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -251 + 72 + 356 + 73 + 252 + 0 +VERTEX + 5 +4FA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 409 + 72 + 292 + 73 + 414 + 0 +VERTEX + 5 +4FB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 414 + 72 + 292 + 73 + 291 + 0 +VERTEX + 5 +4FC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 284 + 72 + 291 + 73 + 290 + 0 +VERTEX + 5 +4FD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 276 + 72 + 290 + 73 + 289 + 0 +VERTEX + 5 +4FE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 288 + 72 + 276 + 73 + 289 + 0 +VERTEX + 5 +4FF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 288 + 72 + 280 + 73 + 276 + 0 +VERTEX + 5 +500 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 288 + 72 + 287 + 73 + 280 + 0 +VERTEX + 5 +501 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 280 + 72 + 287 + 73 + 286 + 0 +VERTEX + 5 +502 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 273 + 72 + 286 + 73 + 285 + 0 +VERTEX + 5 +503 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 273 + 72 + 280 + 73 + 286 + 0 +VERTEX + 5 +504 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 273 + 72 + 282 + 73 + 280 + 0 +VERTEX + 5 +505 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 273 + 72 + 274 + 73 + 282 + 0 +VERTEX + 5 +506 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 282 + 72 + 274 + 73 + 279 + 0 +VERTEX + 5 +507 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 278 + 72 + 279 + 73 + 323 + 0 +VERTEX + 5 +508 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 324 + 72 + 278 + 73 + 323 + 0 +VERTEX + 5 +509 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 324 + 72 + 325 + 73 + 278 + 0 +VERTEX + 5 +50A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 278 + 72 + 325 + 73 + 277 + 0 +VERTEX + 5 +50B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 281 + 72 + 277 + 73 + 283 + 0 +VERTEX + 5 +50C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 276 + 72 + 283 + 73 + 284 + 0 +VERTEX + 5 +50D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 290 + 72 + 276 + 73 + 284 + 0 +VERTEX + 5 +50E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 274 + 72 + 275 + 73 + 279 + 0 +VERTEX + 5 +50F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 279 + 72 + 275 + 73 + 321 + 0 +VERTEX + 5 +510 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 322 + 72 + 279 + 73 + 321 + 0 +VERTEX + 5 +511 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 322 + 72 + 323 + 73 + 279 + 0 +VERTEX + 5 +512 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 275 + 72 + 320 + 73 + 321 + 0 +VERTEX + 5 +513 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 325 + 72 + 326 + 73 + 277 + 0 +VERTEX + 5 +514 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 277 + 72 + 326 + 73 + 410 + 0 +VERTEX + 5 +515 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 411 + 72 + 277 + 73 + 410 + 0 +VERTEX + 5 +516 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 411 + 72 + 283 + 73 + 277 + 0 +VERTEX + 5 +517 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 411 + 72 + 412 + 73 + 283 + 0 +VERTEX + 5 +518 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 283 + 72 + 412 + 73 + 413 + 0 +VERTEX + 5 +519 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 284 + 72 + 413 + 73 + 414 + 0 +VERTEX + 5 +51A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 291 + 72 + 284 + 73 + 414 + 0 +VERTEX + 5 +51B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 326 + 72 + 675 + 73 + 410 + 0 +VERTEX + 5 +51C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 276 + 72 + 280 + 73 + 281 + 0 +VERTEX + 5 +51D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 283 + 72 + 276 + 73 + 281 + 0 +VERTEX + 5 +51E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 277 + 72 + 281 + 73 + 278 + 0 +VERTEX + 5 +51F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 278 + 72 + 281 + 73 + 282 + 0 +VERTEX + 5 +520 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 279 + 72 + 278 + 73 + 282 + 0 +VERTEX + 5 +521 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 282 + 72 + 281 + 73 + 280 + 0 +VERTEX + 5 +522 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 284 + 72 + 283 + 73 + 413 + 0 +VERTEX + 5 +523 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 292 + 72 + 409 + 73 + 408 + 74 + 306 + 0 +VERTEX + 5 +524 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 286 + 72 + 294 + 73 + 293 + 74 + 285 + 0 +VERTEX + 5 +525 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 287 + 72 + 295 + 73 + 294 + 74 + 286 + 0 +VERTEX + 5 +526 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 288 + 72 + 298 + 73 + 295 + 74 + 287 + 0 +VERTEX + 5 +527 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 289 + 72 + 296 + 73 + 298 + 74 + 288 + 0 +VERTEX + 5 +528 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 290 + 72 + 297 + 73 + 296 + 74 + 289 + 0 +VERTEX + 5 +529 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 291 + 72 + 305 + 73 + 297 + 74 + 290 + 0 +VERTEX + 5 +52A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 292 + 72 + 306 + 73 + 305 + 74 + 291 + 0 +VERTEX + 5 +52B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 379 + 72 + 313 + 73 + 380 + 0 +VERTEX + 5 +52C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 380 + 72 + 313 + 73 + 308 + 0 +VERTEX + 5 +52D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 381 + 72 + 308 + 73 + 382 + 0 +VERTEX + 5 +52E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 381 + 72 + 380 + 73 + 308 + 0 +VERTEX + 5 +52F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 313 + 72 + 319 + 73 + 308 + 0 +VERTEX + 5 +530 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 308 + 72 + 319 + 73 + 307 + 0 +VERTEX + 5 +531 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 309 + 72 + 307 + 73 + 302 + 0 +VERTEX + 5 +532 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 299 + 72 + 302 + 73 + 303 + 0 +VERTEX + 5 +533 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 294 + 72 + 303 + 73 + 293 + 0 +VERTEX + 5 +534 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 294 + 72 + 299 + 73 + 303 + 0 +VERTEX + 5 +535 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 294 + 72 + 295 + 73 + 299 + 0 +VERTEX + 5 +536 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 299 + 72 + 295 + 73 + 298 + 0 +VERTEX + 5 +537 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 312 + 72 + 298 + 73 + 296 + 0 +VERTEX + 5 +538 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 297 + 72 + 312 + 73 + 296 + 0 +VERTEX + 5 +539 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 297 + 72 + 311 + 73 + 312 + 0 +VERTEX + 5 +53A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 297 + 72 + 305 + 73 + 311 + 0 +VERTEX + 5 +53B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 311 + 72 + 305 + 73 + 384 + 0 +VERTEX + 5 +53C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 383 + 72 + 311 + 73 + 384 + 0 +VERTEX + 5 +53D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 383 + 72 + 385 + 73 + 311 + 0 +VERTEX + 5 +53E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 311 + 72 + 385 + 73 + 310 + 0 +VERTEX + 5 +53F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 312 + 72 + 310 + 73 + 309 + 0 +VERTEX + 5 +540 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 299 + 72 + 309 + 73 + 302 + 0 +VERTEX + 5 +541 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 299 + 72 + 312 + 73 + 309 + 0 +VERTEX + 5 +542 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 299 + 72 + 298 + 73 + 312 + 0 +VERTEX + 5 +543 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 319 + 72 + 314 + 73 + 307 + 0 +VERTEX + 5 +544 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 307 + 72 + 314 + 73 + 315 + 0 +VERTEX + 5 +545 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 301 + 72 + 315 + 73 + 316 + 0 +VERTEX + 5 +546 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 317 + 72 + 301 + 73 + 316 + 0 +VERTEX + 5 +547 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 317 + 72 + 300 + 73 + 301 + 0 +VERTEX + 5 +548 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 317 + 72 + 318 + 73 + 300 + 0 +VERTEX + 5 +549 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 300 + 72 + 304 + 73 + 301 + 0 +VERTEX + 5 +54A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 301 + 72 + 304 + 73 + 302 + 0 +VERTEX + 5 +54B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 307 + 72 + 301 + 73 + 302 + 0 +VERTEX + 5 +54C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 307 + 72 + 315 + 73 + 301 + 0 +VERTEX + 5 +54D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 304 + 72 + 303 + 73 + 302 + 0 +VERTEX + 5 +54E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 305 + 72 + 306 + 73 + 384 + 0 +VERTEX + 5 +54F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 384 + 72 + 306 + 73 + 408 + 0 +VERTEX + 5 +550 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 385 + 72 + 386 + 73 + 310 + 0 +VERTEX + 5 +551 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 310 + 72 + 386 + 73 + 387 + 0 +VERTEX + 5 +552 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 382 + 72 + 310 + 73 + 387 + 0 +VERTEX + 5 +553 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 382 + 72 + 308 + 73 + 310 + 0 +VERTEX + 5 +554 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 310 + 72 + 308 + 73 + 309 + 0 +VERTEX + 5 +555 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 309 + 72 + 308 + 73 + 307 + 0 +VERTEX + 5 +556 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 312 + 72 + 311 + 73 + 310 + 0 +VERTEX + 5 +557 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 379 + 72 + 666 + 73 + 313 + 0 +VERTEX + 5 +558 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 329 + 72 + 317 + 73 + 316 + 0 +VERTEX + 5 +559 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 343 + 72 + 316 + 73 + 315 + 0 +VERTEX + 5 +55A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 330 + 72 + 315 + 73 + 314 + 0 +VERTEX + 5 +55B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 331 + 72 + 314 + 73 + 319 + 0 +VERTEX + 5 +55C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 338 + 72 + 319 + 73 + 313 + 0 +VERTEX + 5 +55D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 666 + 72 + 338 + 73 + 313 + 0 +VERTEX + 5 +55E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 331 + 72 + 330 + 73 + 314 + 0 +VERTEX + 5 +55F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 330 + 72 + 343 + 73 + 315 + 0 +VERTEX + 5 +560 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 343 + 72 + 329 + 73 + 316 + 0 +VERTEX + 5 +561 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 329 + 72 + 328 + 73 + 317 + 0 +VERTEX + 5 +562 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 318 + 72 + 317 + 73 + 328 + 74 + 327 + 0 +VERTEX + 5 +563 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 331 + 72 + 319 + 73 + 338 + 0 +VERTEX + 5 +564 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 321 + 72 + 320 + 73 + 356 + 74 + 357 + 0 +VERTEX + 5 +565 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 355 + 72 + 321 + 73 + 357 + 0 +VERTEX + 5 +566 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 355 + 72 + 322 + 73 + 321 + 0 +VERTEX + 5 +567 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 355 + 72 + 323 + 73 + 322 + 0 +VERTEX + 5 +568 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 355 + 72 + 354 + 73 + 323 + 0 +VERTEX + 5 +569 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 323 + 72 + 354 + 73 + 368 + 0 +VERTEX + 5 +56A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 324 + 72 + 368 + 73 + 325 + 0 +VERTEX + 5 +56B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 324 + 72 + 323 + 73 + 368 + 0 +VERTEX + 5 +56C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 368 + 72 + 369 + 73 + 325 + 0 +VERTEX + 5 +56D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 325 + 72 + 369 + 73 + 366 + 0 +VERTEX + 5 +56E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 326 + 72 + 366 + 73 + 675 + 0 +VERTEX + 5 +56F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 326 + 72 + 325 + 73 + 366 + 0 +VERTEX + 5 +570 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 366 + 72 + 674 + 73 + 675 + 0 +VERTEX + 5 +571 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 677 + 72 + 346 + 73 + 657 + 0 +VERTEX + 5 +572 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 657 + 72 + 346 + 73 + 340 + 0 +VERTEX + 5 +573 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 669 + 72 + 340 + 73 + 658 + 0 +VERTEX + 5 +574 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 669 + 72 + 657 + 73 + 340 + 0 +VERTEX + 5 +575 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 346 + 72 + 351 + 73 + 340 + 0 +VERTEX + 5 +576 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 340 + 72 + 351 + 73 + 339 + 0 +VERTEX + 5 +577 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 341 + 72 + 339 + 73 + 334 + 0 +VERTEX + 5 +578 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 345 + 72 + 334 + 73 + 342 + 0 +VERTEX + 5 +579 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 344 + 72 + 342 + 73 + 336 + 0 +VERTEX + 5 +57A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 328 + 72 + 336 + 73 + 327 + 0 +VERTEX + 5 +57B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 328 + 72 + 344 + 73 + 336 + 0 +VERTEX + 5 +57C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 328 + 72 + 329 + 73 + 344 + 0 +VERTEX + 5 +57D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 344 + 72 + 329 + 73 + 343 + 0 +VERTEX + 5 +57E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 345 + 72 + 343 + 73 + 330 + 0 +VERTEX + 5 +57F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 331 + 72 + 345 + 73 + 330 + 0 +VERTEX + 5 +580 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 331 + 72 + 332 + 73 + 345 + 0 +VERTEX + 5 +581 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 331 + 72 + 338 + 73 + 332 + 0 +VERTEX + 5 +582 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 332 + 72 + 338 + 73 + 667 + 0 +VERTEX + 5 +583 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 664 + 72 + 332 + 73 + 667 + 0 +VERTEX + 5 +584 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 664 + 72 + 662 + 73 + 332 + 0 +VERTEX + 5 +585 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 332 + 72 + 662 + 73 + 341 + 0 +VERTEX + 5 +586 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 345 + 72 + 341 + 73 + 334 + 0 +VERTEX + 5 +587 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 345 + 72 + 332 + 73 + 341 + 0 +VERTEX + 5 +588 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 351 + 72 + 352 + 73 + 339 + 0 +VERTEX + 5 +589 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 339 + 72 + 352 + 73 + 350 + 0 +VERTEX + 5 +58A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 335 + 72 + 350 + 73 + 349 + 0 +VERTEX + 5 +58B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 348 + 72 + 335 + 73 + 349 + 0 +VERTEX + 5 +58C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 348 + 72 + 333 + 73 + 335 + 0 +VERTEX + 5 +58D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 348 + 72 + 347 + 73 + 333 + 0 +VERTEX + 5 +58E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 333 + 72 + 337 + 73 + 335 + 0 +VERTEX + 5 +58F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 335 + 72 + 337 + 73 + 342 + 0 +VERTEX + 5 +590 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 339 + 72 + 342 + 73 + 334 + 0 +VERTEX + 5 +591 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 339 + 72 + 335 + 73 + 342 + 0 +VERTEX + 5 +592 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 339 + 72 + 350 + 73 + 335 + 0 +VERTEX + 5 +593 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 337 + 72 + 336 + 73 + 342 + 0 +VERTEX + 5 +594 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 338 + 72 + 666 + 73 + 667 + 0 +VERTEX + 5 +595 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 662 + 72 + 661 + 73 + 341 + 0 +VERTEX + 5 +596 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 341 + 72 + 661 + 73 + 659 + 0 +VERTEX + 5 +597 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 658 + 72 + 341 + 73 + 659 + 0 +VERTEX + 5 +598 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 658 + 72 + 340 + 73 + 341 + 0 +VERTEX + 5 +599 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 341 + 72 + 340 + 73 + 339 + 0 +VERTEX + 5 +59A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 342 + 72 + 344 + 73 + 345 + 0 +VERTEX + 5 +59B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 345 + 72 + 344 + 73 + 343 + 0 +VERTEX + 5 +59C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 679 + 72 + 365 + 73 + 678 + 0 +VERTEX + 5 +59D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 678 + 72 + 365 + 73 + 346 + 0 +VERTEX + 5 +59E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 677 + 72 + 678 + 73 + 346 + 0 +VERTEX + 5 +59F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 346 + 72 + 365 + 73 + 351 + 0 +VERTEX + 5 +5A0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 351 + 72 + 365 + 73 + 363 + 0 +VERTEX + 5 +5A1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 352 + 72 + 363 + 73 + 362 + 0 +VERTEX + 5 +5A2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 350 + 72 + 362 + 73 + 364 + 0 +VERTEX + 5 +5A3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 349 + 72 + 364 + 73 + 361 + 0 +VERTEX + 5 +5A4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 348 + 72 + 361 + 73 + 360 + 0 +VERTEX + 5 +5A5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 347 + 72 + 348 + 73 + 360 + 74 + 353 + 0 +VERTEX + 5 +5A6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 348 + 72 + 349 + 73 + 361 + 0 +VERTEX + 5 +5A7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 349 + 72 + 350 + 73 + 364 + 0 +VERTEX + 5 +5A8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 350 + 72 + 352 + 73 + 362 + 0 +VERTEX + 5 +5A9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 352 + 72 + 351 + 73 + 363 + 0 +VERTEX + 5 +5AA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 353 + 72 + 360 + 73 + 371 + 0 +VERTEX + 5 +5AB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 371 + 72 + 360 + 73 + 370 + 0 +VERTEX + 5 +5AC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 372 + 72 + 370 + 73 + 373 + 0 +VERTEX + 5 +5AD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 359 + 72 + 373 + 73 + 374 + 0 +VERTEX + 5 +5AE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 354 + 72 + 374 + 73 + 368 + 0 +VERTEX + 5 +5AF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 354 + 72 + 359 + 73 + 374 + 0 +VERTEX + 5 +5B0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 354 + 72 + 355 + 73 + 359 + 0 +VERTEX + 5 +5B1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 359 + 72 + 355 + 73 + 357 + 0 +VERTEX + 5 +5B2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 358 + 72 + 357 + 73 + 356 + 0 +VERTEX + 5 +5B3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 358 + 72 + 359 + 73 + 357 + 0 +VERTEX + 5 +5B4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 358 + 72 + 372 + 73 + 359 + 0 +VERTEX + 5 +5B5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 359 + 72 + 372 + 73 + 373 + 0 +VERTEX + 5 +5B6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 360 + 72 + 361 + 73 + 370 + 0 +VERTEX + 5 +5B7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 370 + 72 + 361 + 73 + 364 + 0 +VERTEX + 5 +5B8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 378 + 72 + 364 + 73 + 362 + 0 +VERTEX + 5 +5B9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 363 + 72 + 378 + 73 + 362 + 0 +VERTEX + 5 +5BA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 363 + 72 + 377 + 73 + 378 + 0 +VERTEX + 5 +5BB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 363 + 72 + 365 + 73 + 377 + 0 +VERTEX + 5 +5BC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 377 + 72 + 365 + 73 + 650 + 0 +VERTEX + 5 +5BD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 651 + 72 + 377 + 73 + 650 + 0 +VERTEX + 5 +5BE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 651 + 72 + 649 + 73 + 377 + 0 +VERTEX + 5 +5BF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 377 + 72 + 649 + 73 + 376 + 0 +VERTEX + 5 +5C0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 378 + 72 + 376 + 73 + 375 + 0 +VERTEX + 5 +5C1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 370 + 72 + 375 + 73 + 373 + 0 +VERTEX + 5 +5C2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 370 + 72 + 378 + 73 + 375 + 0 +VERTEX + 5 +5C3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 370 + 72 + 364 + 73 + 378 + 0 +VERTEX + 5 +5C4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 365 + 72 + 679 + 73 + 650 + 0 +VERTEX + 5 +5C5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 649 + 72 + 648 + 73 + 376 + 0 +VERTEX + 5 +5C6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 376 + 72 + 648 + 73 + 646 + 0 +VERTEX + 5 +5C7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 367 + 72 + 646 + 73 + 654 + 0 +VERTEX + 5 +5C8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 645 + 72 + 367 + 73 + 654 + 0 +VERTEX + 5 +5C9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 645 + 72 + 366 + 73 + 367 + 0 +VERTEX + 5 +5CA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 645 + 72 + 674 + 73 + 366 + 0 +VERTEX + 5 +5CB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 366 + 72 + 369 + 73 + 367 + 0 +VERTEX + 5 +5CC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 367 + 72 + 369 + 73 + 374 + 0 +VERTEX + 5 +5CD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 376 + 72 + 374 + 73 + 375 + 0 +VERTEX + 5 +5CE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 376 + 72 + 367 + 73 + 374 + 0 +VERTEX + 5 +5CF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 376 + 72 + 646 + 73 + 367 + 0 +VERTEX + 5 +5D0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 369 + 72 + 368 + 73 + 374 + 0 +VERTEX + 5 +5D1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 372 + 72 + 371 + 73 + 370 + 0 +VERTEX + 5 +5D2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 375 + 72 + 374 + 73 + 373 + 0 +VERTEX + 5 +5D3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 378 + 72 + 377 + 73 + 376 + 0 +VERTEX + 5 +5D4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 547 + 72 + 668 + 73 + 666 + 74 + 379 + 0 +VERTEX + 5 +5D5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 570 + 72 + 547 + 73 + 379 + 74 + 380 + 0 +VERTEX + 5 +5D6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 381 + 72 + 570 + 73 + 380 + 0 +VERTEX + 5 +5D7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 381 + 72 + 571 + 73 + 570 + 0 +VERTEX + 5 +5D8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 381 + 72 + 382 + 73 + 571 + 0 +VERTEX + 5 +5D9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 571 + 72 + 382 + 73 + 387 + 0 +VERTEX + 5 +5DA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 569 + 72 + 387 + 73 + 386 + 0 +VERTEX + 5 +5DB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 383 + 72 + 572 + 73 + 385 + 0 +VERTEX + 5 +5DC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 383 + 72 + 573 + 73 + 572 + 0 +VERTEX + 5 +5DD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 383 + 72 + 384 + 73 + 573 + 0 +VERTEX + 5 +5DE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 543 + 72 + 573 + 73 + 384 + 74 + 408 + 0 +VERTEX + 5 +5DF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 569 + 72 + 386 + 73 + 385 + 74 + 572 + 0 +VERTEX + 5 +5E0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 569 + 72 + 571 + 73 + 387 + 0 +VERTEX + 5 +5E1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -272 + 72 + 262 + 73 + 261 + 0 +VERTEX + 5 +5E2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 436 + 72 + 415 + 73 + 409 + 74 + 414 + 0 +VERTEX + 5 +5E3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 440 + 72 + 410 + 73 + 675 + 74 + 672 + 0 +VERTEX + 5 +5E4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 439 + 72 + 411 + 73 + 410 + 74 + 440 + 0 +VERTEX + 5 +5E5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 438 + 72 + 412 + 73 + 411 + 74 + 439 + 0 +VERTEX + 5 +5E6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 437 + 72 + 413 + 73 + 412 + 74 + 438 + 0 +VERTEX + 5 +5E7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 436 + 72 + 414 + 73 + 413 + 74 + 437 + 0 +VERTEX + 5 +5E8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 425 + 72 + 593 + 73 + 594 + 74 + 560 + 0 +VERTEX + 5 +5E9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 432 + 72 + 427 + 73 + 554 + 74 + 557 + 0 +VERTEX + 5 +5EA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 553 + 72 + 433 + 73 + 432 + 74 + 557 + 0 +VERTEX + 5 +5EB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 457 + 72 + 552 + 73 + 434 + 0 +VERTEX + 5 +5EC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 457 + 72 + 433 + 73 + 553 + 74 + 552 + 0 +VERTEX + 5 +5ED +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 552 + 72 + 551 + 73 + 434 + 0 +VERTEX + 5 +5EE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 434 + 72 + 551 + 73 + 435 + 0 +VERTEX + 5 +5EF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 435 + 72 + 551 + 73 + 591 + 0 +VERTEX + 5 +5F0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 416 + 72 + 424 + 73 + 550 + 74 + 549 + 0 +VERTEX + 5 +5F1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 543 + 72 + 415 + 73 + 416 + 74 + 549 + 0 +VERTEX + 5 +5F2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 435 + 72 + 591 + 73 + 550 + 74 + 424 + 0 +VERTEX + 5 +5F3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 429 + 72 + 555 + 73 + 554 + 74 + 427 + 0 +VERTEX + 5 +5F4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 430 + 72 + 556 + 73 + 555 + 74 + 429 + 0 +VERTEX + 5 +5F5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 447 + 72 + 579 + 73 + 556 + 74 + 430 + 0 +VERTEX + 5 +5F6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 423 + 72 + 562 + 73 + 579 + 74 + 447 + 0 +VERTEX + 5 +5F7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 422 + 72 + 561 + 73 + 562 + 74 + 423 + 0 +VERTEX + 5 +5F8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 425 + 72 + 560 + 73 + 561 + 74 + 422 + 0 +VERTEX + 5 +5F9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 473 + 72 + 471 + 73 + 426 + 0 +VERTEX + 5 +5FA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 441 + 72 + 473 + 73 + 426 + 0 +VERTEX + 5 +5FB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 441 + 72 + 474 + 73 + 473 + 0 +VERTEX + 5 +5FC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 441 + 72 + 421 + 73 + 474 + 0 +VERTEX + 5 +5FD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 474 + 72 + 421 + 73 + 495 + 0 +VERTEX + 5 +5FE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 495 + 72 + 421 + 73 + 420 + 0 +VERTEX + 5 +5FF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 475 + 72 + 420 + 73 + 419 + 0 +VERTEX + 5 +600 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 477 + 72 + 419 + 73 + 444 + 0 +VERTEX + 5 +601 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 476 + 72 + 444 + 73 + 418 + 0 +VERTEX + 5 +602 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 463 + 72 + 418 + 73 + 417 + 0 +VERTEX + 5 +603 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 463 + 72 + 417 + 73 + 672 + 74 + 673 + 0 +VERTEX + 5 +604 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 463 + 72 + 476 + 73 + 418 + 0 +VERTEX + 5 +605 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 476 + 72 + 477 + 73 + 444 + 0 +VERTEX + 5 +606 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 477 + 72 + 475 + 73 + 419 + 0 +VERTEX + 5 +607 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 475 + 72 + 495 + 73 + 420 + 0 +VERTEX + 5 +608 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 471 + 72 + 488 + 73 + 426 + 0 +VERTEX + 5 +609 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 426 + 72 + 488 + 73 + 593 + 0 +VERTEX + 5 +60A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 593 + 72 + 488 + 73 + 479 + 0 +VERTEX + 5 +60B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 592 + 72 + 593 + 73 + 479 + 0 +VERTEX + 5 +60C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 672 + 72 + 417 + 73 + 440 + 0 +VERTEX + 5 +60D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 440 + 72 + 417 + 73 + 445 + 0 +VERTEX + 5 +60E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 437 + 72 + 442 + 73 + 450 + 0 +VERTEX + 5 +60F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 436 + 72 + 450 + 73 + 461 + 0 +VERTEX + 5 +610 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 416 + 72 + 461 + 73 + 424 + 0 +VERTEX + 5 +611 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 416 + 72 + 436 + 73 + 461 + 0 +VERTEX + 5 +612 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 416 + 72 + 415 + 73 + 436 + 0 +VERTEX + 5 +613 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 417 + 72 + 418 + 73 + 445 + 0 +VERTEX + 5 +614 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 445 + 72 + 418 + 73 + 444 + 0 +VERTEX + 5 +615 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 446 + 72 + 444 + 73 + 419 + 0 +VERTEX + 5 +616 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 420 + 72 + 446 + 73 + 419 + 0 +VERTEX + 5 +617 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 420 + 72 + 449 + 73 + 446 + 0 +VERTEX + 5 +618 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 420 + 72 + 421 + 73 + 449 + 0 +VERTEX + 5 +619 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 449 + 72 + 421 + 73 + 441 + 0 +VERTEX + 5 +61A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 448 + 72 + 441 + 73 + 426 + 0 +VERTEX + 5 +61B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 422 + 72 + 426 + 73 + 425 + 0 +VERTEX + 5 +61C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 422 + 72 + 448 + 73 + 426 + 0 +VERTEX + 5 +61D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 422 + 72 + 423 + 73 + 448 + 0 +VERTEX + 5 +61E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 448 + 72 + 423 + 73 + 447 + 0 +VERTEX + 5 +61F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 451 + 72 + 447 + 73 + 452 + 0 +VERTEX + 5 +620 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 456 + 72 + 452 + 73 + 458 + 0 +VERTEX + 5 +621 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 460 + 72 + 458 + 73 + 462 + 0 +VERTEX + 5 +622 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 461 + 72 + 462 + 73 + 435 + 0 +VERTEX + 5 +623 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 424 + 72 + 461 + 73 + 435 + 0 +VERTEX + 5 +624 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 426 + 72 + 593 + 73 + 425 + 0 +VERTEX + 5 +625 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 447 + 72 + 430 + 73 + 431 + 0 +VERTEX + 5 +626 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 452 + 72 + 431 + 73 + 458 + 0 +VERTEX + 5 +627 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 452 + 72 + 447 + 73 + 431 + 0 +VERTEX + 5 +628 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 427 + 72 + 428 + 73 + 429 + 0 +VERTEX + 5 +629 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 427 + 72 + 432 + 73 + 428 + 0 +VERTEX + 5 +62A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 428 + 72 + 432 + 73 + 459 + 0 +VERTEX + 5 +62B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 431 + 72 + 459 + 73 + 458 + 0 +VERTEX + 5 +62C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 431 + 72 + 428 + 73 + 459 + 0 +VERTEX + 5 +62D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 431 + 72 + 429 + 73 + 428 + 0 +VERTEX + 5 +62E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 431 + 72 + 430 + 73 + 429 + 0 +VERTEX + 5 +62F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 432 + 72 + 433 + 73 + 459 + 0 +VERTEX + 5 +630 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 459 + 72 + 433 + 73 + 457 + 0 +VERTEX + 5 +631 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 462 + 72 + 457 + 73 + 434 + 0 +VERTEX + 5 +632 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 435 + 72 + 462 + 73 + 434 + 0 +VERTEX + 5 +633 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 436 + 72 + 437 + 73 + 450 + 0 +VERTEX + 5 +634 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 437 + 72 + 438 + 73 + 442 + 0 +VERTEX + 5 +635 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 439 + 72 + 443 + 73 + 442 + 74 + 438 + 0 +VERTEX + 5 +636 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 440 + 72 + 445 + 73 + 443 + 74 + 439 + 0 +VERTEX + 5 +637 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 441 + 72 + 448 + 73 + 449 + 0 +VERTEX + 5 +638 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 442 + 72 + 455 + 73 + 450 + 0 +VERTEX + 5 +639 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 443 + 72 + 454 + 73 + 455 + 74 + 442 + 0 +VERTEX + 5 +63A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 453 + 72 + 454 + 73 + 446 + 74 + 449 + 0 +VERTEX + 5 +63B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 445 + 72 + 446 + 73 + 454 + 74 + 443 + 0 +VERTEX + 5 +63C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 446 + 72 + 445 + 73 + 444 + 0 +VERTEX + 5 +63D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 447 + 72 + 451 + 73 + 448 + 0 +VERTEX + 5 +63E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 451 + 72 + 453 + 73 + 449 + 74 + 448 + 0 +VERTEX + 5 +63F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 455 + 72 + 456 + 73 + 460 + 0 +VERTEX + 5 +640 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 450 + 72 + 460 + 73 + 461 + 0 +VERTEX + 5 +641 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 450 + 72 + 455 + 73 + 460 + 0 +VERTEX + 5 +642 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 452 + 72 + 456 + 73 + 453 + 74 + 451 + 0 +VERTEX + 5 +643 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 456 + 72 + 455 + 73 + 454 + 74 + 453 + 0 +VERTEX + 5 +644 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 458 + 72 + 460 + 73 + 456 + 0 +VERTEX + 5 +645 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 457 + 72 + 462 + 73 + 459 + 0 +VERTEX + 5 +646 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 459 + 72 + 462 + 73 + 458 + 0 +VERTEX + 5 +647 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 462 + 72 + 461 + 73 + 460 + 0 +VERTEX + 5 +648 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 519 + 72 + 595 + 73 + 592 + 74 + 478 + 0 +VERTEX + 5 +649 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 511 + 72 + 470 + 73 + 469 + 0 +VERTEX + 5 +64A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 472 + 72 + 511 + 73 + 469 + 0 +VERTEX + 5 +64B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 472 + 72 + 513 + 73 + 511 + 0 +VERTEX + 5 +64C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 468 + 72 + 514 + 73 + 513 + 74 + 472 + 0 +VERTEX + 5 +64D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 535 + 72 + 514 + 73 + 468 + 74 + 467 + 0 +VERTEX + 5 +64E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 466 + 72 + 515 + 73 + 535 + 74 + 467 + 0 +VERTEX + 5 +64F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 517 + 72 + 515 + 73 + 466 + 74 + 502 + 0 +VERTEX + 5 +650 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 465 + 72 + 516 + 73 + 517 + 74 + 502 + 0 +VERTEX + 5 +651 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 503 + 72 + 516 + 73 + 465 + 74 + 464 + 0 +VERTEX + 5 +652 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 503 + 72 + 464 + 73 + 680 + 74 + 676 + 0 +VERTEX + 5 +653 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 511 + 72 + 528 + 73 + 470 + 0 +VERTEX + 5 +654 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 519 + 72 + 478 + 73 + 470 + 74 + 528 + 0 +VERTEX + 5 +655 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 680 + 72 + 464 + 73 + 653 + 0 +VERTEX + 5 +656 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 653 + 72 + 464 + 73 + 500 + 0 +VERTEX + 5 +657 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 463 + 72 + 494 + 73 + 476 + 0 +VERTEX + 5 +658 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 463 + 72 + 655 + 73 + 494 + 0 +VERTEX + 5 +659 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 463 + 72 + 673 + 73 + 655 + 0 +VERTEX + 5 +65A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 464 + 72 + 465 + 73 + 500 + 0 +VERTEX + 5 +65B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 500 + 72 + 465 + 73 + 502 + 0 +VERTEX + 5 +65C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 501 + 72 + 502 + 73 + 466 + 0 +VERTEX + 5 +65D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 467 + 72 + 501 + 73 + 466 + 0 +VERTEX + 5 +65E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 467 + 72 + 484 + 73 + 501 + 0 +VERTEX + 5 +65F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 467 + 72 + 468 + 73 + 484 + 0 +VERTEX + 5 +660 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 484 + 72 + 468 + 73 + 472 + 0 +VERTEX + 5 +661 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 483 + 72 + 472 + 73 + 469 + 0 +VERTEX + 5 +662 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 470 + 72 + 483 + 73 + 469 + 0 +VERTEX + 5 +663 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 470 + 72 + 485 + 73 + 483 + 0 +VERTEX + 5 +664 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 470 + 72 + 487 + 73 + 485 + 0 +VERTEX + 5 +665 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 470 + 72 + 478 + 73 + 487 + 0 +VERTEX + 5 +666 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 471 + 72 + 490 + 73 + 488 + 0 +VERTEX + 5 +667 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 471 + 72 + 473 + 73 + 490 + 0 +VERTEX + 5 +668 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 490 + 72 + 473 + 73 + 499 + 0 +VERTEX + 5 +669 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 472 + 72 + 483 + 73 + 484 + 0 +VERTEX + 5 +66A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 473 + 72 + 474 + 73 + 499 + 0 +VERTEX + 5 +66B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 499 + 72 + 474 + 73 + 495 + 0 +VERTEX + 5 +66C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 498 + 72 + 495 + 73 + 475 + 0 +VERTEX + 5 +66D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 477 + 72 + 498 + 73 + 475 + 0 +VERTEX + 5 +66E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 477 + 72 + 494 + 73 + 498 + 0 +VERTEX + 5 +66F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 477 + 72 + 476 + 73 + 494 + 0 +VERTEX + 5 +670 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 656 + 72 + 493 + 73 + 494 + 74 + 655 + 0 +VERTEX + 5 +671 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 647 + 72 + 480 + 73 + 493 + 74 + 656 + 0 +VERTEX + 5 +672 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 652 + 72 + 481 + 73 + 480 + 74 + 647 + 0 +VERTEX + 5 +673 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 653 + 72 + 500 + 73 + 481 + 74 + 652 + 0 +VERTEX + 5 +674 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 479 + 72 + 488 + 73 + 487 + 0 +VERTEX + 5 +675 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 592 + 72 + 487 + 73 + 478 + 0 +VERTEX + 5 +676 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 592 + 72 + 479 + 73 + 487 + 0 +VERTEX + 5 +677 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 486 + 72 + 482 + 73 + 501 + 74 + 484 + 0 +VERTEX + 5 +678 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 491 + 72 + 492 + 73 + 482 + 74 + 486 + 0 +VERTEX + 5 +679 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 480 + 72 + 492 + 73 + 497 + 74 + 493 + 0 +VERTEX + 5 +67A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 482 + 72 + 492 + 73 + 480 + 74 + 481 + 0 +VERTEX + 5 +67B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 482 + 72 + 481 + 73 + 500 + 74 + 501 + 0 +VERTEX + 5 +67C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 485 + 72 + 486 + 73 + 484 + 74 + 483 + 0 +VERTEX + 5 +67D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 487 + 72 + 491 + 73 + 486 + 74 + 485 + 0 +VERTEX + 5 +67E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 496 + 72 + 491 + 73 + 487 + 74 + 489 + 0 +VERTEX + 5 +67F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 489 + 72 + 487 + 73 + 488 + 0 +VERTEX + 5 +680 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 490 + 72 + 489 + 73 + 488 + 0 +VERTEX + 5 +681 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 490 + 72 + 499 + 73 + 496 + 74 + 489 + 0 +VERTEX + 5 +682 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 496 + 72 + 497 + 73 + 492 + 74 + 491 + 0 +VERTEX + 5 +683 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 494 + 72 + 493 + 73 + 497 + 74 + 498 + 0 +VERTEX + 5 +684 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 495 + 72 + 498 + 73 + 499 + 0 +VERTEX + 5 +685 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 499 + 72 + 498 + 73 + 497 + 74 + 496 + 0 +VERTEX + 5 +686 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 502 + 72 + 501 + 73 + 500 + 0 +VERTEX + 5 +687 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 595 + 72 + 518 + 73 + 594 + 0 +VERTEX + 5 +688 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 594 + 72 + 518 + 73 + 510 + 0 +VERTEX + 5 +689 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 566 + 72 + 510 + 73 + 509 + 0 +VERTEX + 5 +68A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 512 + 72 + 566 + 73 + 509 + 0 +VERTEX + 5 +68B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 512 + 72 + 565 + 73 + 566 + 0 +VERTEX + 5 +68C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 512 + 72 + 563 + 73 + 565 + 0 +VERTEX + 5 +68D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 512 + 72 + 508 + 73 + 563 + 0 +VERTEX + 5 +68E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 563 + 72 + 508 + 73 + 507 + 0 +VERTEX + 5 +68F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 544 + 72 + 507 + 73 + 545 + 0 +VERTEX + 5 +690 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 544 + 72 + 563 + 73 + 507 + 0 +VERTEX + 5 +691 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 507 + 72 + 506 + 73 + 545 + 0 +VERTEX + 5 +692 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 545 + 72 + 506 + 73 + 542 + 0 +VERTEX + 5 +693 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 586 + 72 + 542 + 73 + 546 + 0 +VERTEX + 5 +694 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 586 + 72 + 545 + 73 + 542 + 0 +VERTEX + 5 +695 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 542 + 72 + 505 + 73 + 546 + 0 +VERTEX + 5 +696 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 546 + 72 + 505 + 73 + 504 + 0 +VERTEX + 5 +697 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 548 + 72 + 546 + 73 + 504 + 0 +VERTEX + 5 +698 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 668 + 72 + 547 + 73 + 548 + 74 + 504 + 0 +VERTEX + 5 +699 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 566 + 72 + 594 + 73 + 510 + 0 +VERTEX + 5 +69A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 668 + 72 + 504 + 73 + 665 + 0 +VERTEX + 5 +69B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 665 + 72 + 504 + 73 + 540 + 0 +VERTEX + 5 +69C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 503 + 72 + 534 + 73 + 516 + 0 +VERTEX + 5 +69D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 503 + 72 + 670 + 73 + 534 + 0 +VERTEX + 5 +69E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 503 + 72 + 676 + 73 + 670 + 0 +VERTEX + 5 +69F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 504 + 72 + 505 + 73 + 540 + 0 +VERTEX + 5 +6A0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 540 + 72 + 505 + 73 + 542 + 0 +VERTEX + 5 +6A1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 541 + 72 + 542 + 73 + 506 + 0 +VERTEX + 5 +6A2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 507 + 72 + 541 + 73 + 506 + 0 +VERTEX + 5 +6A3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 507 + 72 + 524 + 73 + 541 + 0 +VERTEX + 5 +6A4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 507 + 72 + 508 + 73 + 524 + 0 +VERTEX + 5 +6A5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 524 + 72 + 508 + 73 + 512 + 0 +VERTEX + 5 +6A6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 523 + 72 + 512 + 73 + 509 + 0 +VERTEX + 5 +6A7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 510 + 72 + 523 + 73 + 509 + 0 +VERTEX + 5 +6A8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 510 + 72 + 525 + 73 + 523 + 0 +VERTEX + 5 +6A9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 510 + 72 + 527 + 73 + 525 + 0 +VERTEX + 5 +6AA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 510 + 72 + 518 + 73 + 527 + 0 +VERTEX + 5 +6AB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 511 + 72 + 530 + 73 + 528 + 0 +VERTEX + 5 +6AC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 511 + 72 + 513 + 73 + 530 + 0 +VERTEX + 5 +6AD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 530 + 72 + 513 + 73 + 539 + 0 +VERTEX + 5 +6AE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 512 + 72 + 523 + 73 + 524 + 0 +VERTEX + 5 +6AF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 513 + 72 + 514 + 73 + 539 + 0 +VERTEX + 5 +6B0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 539 + 72 + 514 + 73 + 535 + 0 +VERTEX + 5 +6B1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 538 + 72 + 535 + 73 + 515 + 0 +VERTEX + 5 +6B2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 517 + 72 + 538 + 73 + 515 + 0 +VERTEX + 5 +6B3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 517 + 72 + 534 + 73 + 538 + 0 +VERTEX + 5 +6B4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 517 + 72 + 516 + 73 + 534 + 0 +VERTEX + 5 +6B5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 671 + 72 + 533 + 73 + 534 + 74 + 670 + 0 +VERTEX + 5 +6B6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 660 + 72 + 520 + 73 + 533 + 74 + 671 + 0 +VERTEX + 5 +6B7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 663 + 72 + 521 + 73 + 520 + 74 + 660 + 0 +VERTEX + 5 +6B8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 665 + 72 + 540 + 73 + 521 + 74 + 663 + 0 +VERTEX + 5 +6B9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 519 + 72 + 528 + 73 + 527 + 0 +VERTEX + 5 +6BA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 595 + 72 + 527 + 73 + 518 + 0 +VERTEX + 5 +6BB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 595 + 72 + 519 + 73 + 527 + 0 +VERTEX + 5 +6BC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 526 + 72 + 522 + 73 + 541 + 74 + 524 + 0 +VERTEX + 5 +6BD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 531 + 72 + 532 + 73 + 522 + 74 + 526 + 0 +VERTEX + 5 +6BE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 520 + 72 + 532 + 73 + 537 + 74 + 533 + 0 +VERTEX + 5 +6BF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 522 + 72 + 532 + 73 + 520 + 74 + 521 + 0 +VERTEX + 5 +6C0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 522 + 72 + 521 + 73 + 540 + 74 + 541 + 0 +VERTEX + 5 +6C1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 525 + 72 + 526 + 73 + 524 + 74 + 523 + 0 +VERTEX + 5 +6C2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 527 + 72 + 531 + 73 + 526 + 74 + 525 + 0 +VERTEX + 5 +6C3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 536 + 72 + 531 + 73 + 527 + 74 + 529 + 0 +VERTEX + 5 +6C4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 529 + 72 + 527 + 73 + 528 + 0 +VERTEX + 5 +6C5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 530 + 72 + 529 + 73 + 528 + 0 +VERTEX + 5 +6C6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 530 + 72 + 539 + 73 + 536 + 74 + 529 + 0 +VERTEX + 5 +6C7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 536 + 72 + 537 + 73 + 532 + 74 + 531 + 0 +VERTEX + 5 +6C8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 534 + 72 + 533 + 73 + 537 + 74 + 538 + 0 +VERTEX + 5 +6C9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 535 + 72 + 538 + 73 + 539 + 0 +VERTEX + 5 +6CA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 539 + 72 + 538 + 73 + 537 + 74 + 536 + 0 +VERTEX + 5 +6CB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 542 + 72 + 541 + 73 + 540 + 0 +VERTEX + 5 +6CC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 543 + 72 + 549 + 73 + 573 + 0 +VERTEX + 5 +6CD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 573 + 72 + 549 + 73 + 589 + 0 +VERTEX + 5 +6CE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 574 + 72 + 589 + 73 + 576 + 0 +VERTEX + 5 +6CF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 567 + 72 + 576 + 73 + 577 + 0 +VERTEX + 5 +6D0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 544 + 72 + 582 + 73 + 563 + 0 +VERTEX + 5 +6D1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 544 + 72 + 587 + 73 + 582 + 0 +VERTEX + 5 +6D2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 544 + 72 + 545 + 73 + 587 + 0 +VERTEX + 5 +6D3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 587 + 72 + 545 + 73 + 586 + 0 +VERTEX + 5 +6D4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 588 + 72 + 586 + 73 + 546 + 0 +VERTEX + 5 +6D5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 548 + 72 + 588 + 73 + 546 + 0 +VERTEX + 5 +6D6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 548 + 72 + 570 + 73 + 588 + 0 +VERTEX + 5 +6D7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 548 + 72 + 547 + 73 + 570 + 0 +VERTEX + 5 +6D8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 549 + 72 + 550 + 73 + 589 + 0 +VERTEX + 5 +6D9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 589 + 72 + 550 + 73 + 591 + 0 +VERTEX + 5 +6DA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 590 + 72 + 591 + 73 + 551 + 0 +VERTEX + 5 +6DB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 552 + 72 + 590 + 73 + 551 + 0 +VERTEX + 5 +6DC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 552 + 72 + 575 + 73 + 590 + 0 +VERTEX + 5 +6DD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 552 + 72 + 553 + 73 + 575 + 0 +VERTEX + 5 +6DE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 575 + 72 + 553 + 73 + 557 + 0 +VERTEX + 5 +6DF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 558 + 72 + 557 + 73 + 554 + 0 +VERTEX + 5 +6E0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 555 + 72 + 558 + 73 + 554 + 0 +VERTEX + 5 +6E1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 555 + 72 + 580 + 73 + 558 + 0 +VERTEX + 5 +6E2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 555 + 72 + 556 + 73 + 580 + 0 +VERTEX + 5 +6E3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 580 + 72 + 556 + 73 + 579 + 0 +VERTEX + 5 +6E4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 581 + 72 + 579 + 73 + 559 + 0 +VERTEX + 5 +6E5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 577 + 72 + 581 + 73 + 559 + 74 + 583 + 0 +VERTEX + 5 +6E6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 581 + 72 + 577 + 73 + 578 + 0 +VERTEX + 5 +6E7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 580 + 72 + 578 + 73 + 575 + 0 +VERTEX + 5 +6E8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 558 + 72 + 575 + 73 + 557 + 0 +VERTEX + 5 +6E9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 558 + 72 + 580 + 73 + 575 + 0 +VERTEX + 5 +6EA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 579 + 72 + 562 + 73 + 564 + 0 +VERTEX + 5 +6EB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 564 + 72 + 582 + 73 + 583 + 74 + 559 + 0 +VERTEX + 5 +6EC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 559 + 72 + 579 + 73 + 564 + 0 +VERTEX + 5 +6ED +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 560 + 72 + 566 + 73 + 561 + 0 +VERTEX + 5 +6EE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 560 + 72 + 594 + 73 + 566 + 0 +VERTEX + 5 +6EF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 561 + 72 + 566 + 73 + 564 + 0 +VERTEX + 5 +6F0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 562 + 72 + 561 + 73 + 564 + 0 +VERTEX + 5 +6F1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 563 + 72 + 582 + 73 + 565 + 0 +VERTEX + 5 +6F2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 565 + 72 + 582 + 73 + 564 + 0 +VERTEX + 5 +6F3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 566 + 72 + 565 + 73 + 564 + 0 +VERTEX + 5 +6F4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 577 + 72 + 583 + 73 + 584 + 74 + 567 + 0 +VERTEX + 5 +6F5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 569 + 72 + 572 + 73 + 568 + 0 +VERTEX + 5 +6F6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 568 + 72 + 572 + 73 + 574 + 0 +VERTEX + 5 +6F7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 567 + 72 + 574 + 73 + 576 + 0 +VERTEX + 5 +6F8 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 567 + 72 + 568 + 73 + 574 + 0 +VERTEX + 5 +6F9 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 567 + 72 + 584 + 73 + 585 + 74 + 568 + 0 +VERTEX + 5 +6FA +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 585 + 72 + 571 + 73 + 569 + 74 + 568 + 0 +VERTEX + 5 +6FB +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 571 + 72 + 585 + 73 + 588 + 74 + 570 + 0 +VERTEX + 5 +6FC +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 572 + 72 + 573 + 73 + 574 + 0 +VERTEX + 5 +6FD +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 574 + 72 + 573 + 73 + 589 + 0 +VERTEX + 5 +6FE +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 576 + 72 + 589 + 73 + 590 + 0 +VERTEX + 5 +6FF +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 578 + 72 + 590 + 73 + 575 + 0 +VERTEX + 5 +700 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 578 + 72 + 576 + 73 + 590 + 0 +VERTEX + 5 +701 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 578 + 72 + 577 + 73 + 576 + 0 +VERTEX + 5 +702 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 578 + 72 + 580 + 73 + 581 + 0 +VERTEX + 5 +703 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 581 + 72 + 580 + 73 + 579 + 0 +VERTEX + 5 +704 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 583 + 72 + 582 + 73 + 587 + 74 + 584 + 0 +VERTEX + 5 +705 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 585 + 72 + 584 + 73 + 587 + 74 + 588 + 0 +VERTEX + 5 +706 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 588 + 72 + 587 + 73 + 586 + 0 +VERTEX + 5 +707 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 591 + 72 + 590 + 73 + 589 + 0 +VERTEX + 5 +708 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 595 + 72 + 594 + 73 + 593 + 74 + 592 + 0 +VERTEX + 5 +709 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 636 + 72 + 637 + 73 + 598 + 0 +VERTEX + 5 +70A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 598 + 72 + 637 + 73 + 596 + 0 +VERTEX + 5 +70B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 597 + 72 + 598 + 73 + 596 + 0 +VERTEX + 5 +70C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 597 + 72 + 600 + 73 + 598 + 0 +VERTEX + 5 +70D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 598 + 72 + 600 + 73 + 599 + 0 +VERTEX + 5 +70E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 599 + 72 + 600 + 73 + 602 + 0 +VERTEX + 5 +70F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 602 + 72 + 600 + 73 + 601 + 0 +VERTEX + 5 +710 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 603 + 72 + 602 + 73 + 601 + 0 +VERTEX + 5 +711 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 603 + 72 + 614 + 73 + 602 + 0 +VERTEX + 5 +712 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 603 + 72 + 604 + 73 + 614 + 0 +VERTEX + 5 +713 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 614 + 72 + 604 + 73 + 613 + 0 +VERTEX + 5 +714 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 615 + 72 + 613 + 73 + 611 + 0 +VERTEX + 5 +715 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 612 + 72 + 611 + 73 + 605 + 0 +VERTEX + 5 +716 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 606 + 72 + 612 + 73 + 605 + 0 +VERTEX + 5 +717 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 606 + 72 + 607 + 73 + 612 + 0 +VERTEX + 5 +718 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 606 + 72 + 609 + 73 + 607 + 0 +VERTEX + 5 +719 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 607 + 72 + 609 + 73 + 610 + 0 +VERTEX + 5 +71A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 610 + 72 + 609 + 73 + 608 + 0 +VERTEX + 5 +71B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 612 + 72 + 615 + 73 + 611 + 0 +VERTEX + 5 +71C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 615 + 72 + 614 + 73 + 613 + 0 +VERTEX + 5 +71D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 644 + 72 + 616 + 73 + 643 + 0 +VERTEX + 5 +71E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 643 + 72 + 616 + 73 + 618 + 0 +VERTEX + 5 +71F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 618 + 72 + 616 + 73 + 617 + 0 +VERTEX + 5 +720 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 619 + 72 + 618 + 73 + 617 + 0 +VERTEX + 5 +721 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 619 + 72 + 620 + 73 + 618 + 0 +VERTEX + 5 +722 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 619 + 72 + 621 + 73 + 620 + 0 +VERTEX + 5 +723 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 620 + 72 + 621 + 73 + 623 + 0 +VERTEX + 5 +724 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 623 + 72 + 621 + 73 + 622 + 0 +VERTEX + 5 +725 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 624 + 72 + 623 + 73 + 622 + 0 +VERTEX + 5 +726 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 624 + 72 + 627 + 73 + 623 + 0 +VERTEX + 5 +727 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 624 + 72 + 625 + 73 + 627 + 0 +VERTEX + 5 +728 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 627 + 72 + 625 + 73 + 626 + 0 +VERTEX + 5 +729 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 628 + 72 + 627 + 73 + 626 + 0 +VERTEX + 5 +72A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 628 + 72 + 629 + 73 + 627 + 0 +VERTEX + 5 +72B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 628 + 72 + 630 + 73 + 629 + 0 +VERTEX + 5 +72C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 629 + 72 + 630 + 73 + 632 + 0 +VERTEX + 5 +72D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 632 + 72 + 630 + 73 + 631 + 0 +VERTEX + 5 +72E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 633 + 72 + 632 + 73 + 631 + 0 +VERTEX + 5 +72F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 633 + 72 + 635 + 73 + 632 + 0 +VERTEX + 5 +730 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 633 + 72 + 634 + 73 + 635 + 0 +VERTEX + 5 +731 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 639 + 72 + 635 + 73 + 634 + 74 + 638 + 0 +VERTEX + 5 +732 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 639 + 72 + 638 + 73 + 637 + 74 + 636 + 0 +VERTEX + 5 +733 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -409 + 72 + 393 + 73 + -392 + 0 +VERTEX + 5 +734 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 674 + 72 + 645 + 73 + 673 + 0 +VERTEX + 5 +735 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 673 + 72 + 645 + 73 + 655 + 0 +VERTEX + 5 +736 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 655 + 72 + 645 + 73 + 654 + 0 +VERTEX + 5 +737 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 656 + 72 + 654 + 73 + 646 + 0 +VERTEX + 5 +738 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 648 + 72 + 656 + 73 + 646 + 0 +VERTEX + 5 +739 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 648 + 72 + 647 + 73 + 656 + 0 +VERTEX + 5 +73A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 648 + 72 + 652 + 73 + 647 + 0 +VERTEX + 5 +73B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 648 + 72 + 649 + 73 + 652 + 0 +VERTEX + 5 +73C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 652 + 72 + 649 + 73 + 651 + 0 +VERTEX + 5 +73D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 653 + 72 + 651 + 73 + 650 + 0 +VERTEX + 5 +73E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 680 + 72 + 650 + 73 + 679 + 0 +VERTEX + 5 +73F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 680 + 72 + 653 + 73 + 650 + 0 +VERTEX + 5 +740 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 653 + 72 + 652 + 73 + 651 + 0 +VERTEX + 5 +741 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 656 + 72 + 655 + 73 + 654 + 0 +VERTEX + 5 +742 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 677 + 72 + 657 + 73 + 676 + 0 +VERTEX + 5 +743 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 676 + 72 + 657 + 73 + 670 + 0 +VERTEX + 5 +744 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 670 + 72 + 657 + 73 + 669 + 0 +VERTEX + 5 +745 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 671 + 72 + 669 + 73 + 658 + 0 +VERTEX + 5 +746 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 659 + 72 + 671 + 73 + 658 + 0 +VERTEX + 5 +747 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 659 + 72 + 660 + 73 + 671 + 0 +VERTEX + 5 +748 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 659 + 72 + 661 + 73 + 660 + 0 +VERTEX + 5 +749 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 660 + 72 + 661 + 73 + 663 + 0 +VERTEX + 5 +74A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 663 + 72 + 661 + 73 + 662 + 0 +VERTEX + 5 +74B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 664 + 72 + 663 + 73 + 662 + 0 +VERTEX + 5 +74C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 664 + 72 + 665 + 73 + 663 + 0 +VERTEX + 5 +74D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 664 + 72 + 667 + 73 + 665 + 0 +VERTEX + 5 +74E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 665 + 72 + 667 + 73 + 668 + 0 +VERTEX + 5 +74F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 668 + 72 + 667 + 73 + 666 + 0 +VERTEX + 5 +750 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 671 + 72 + 670 + 73 + 669 + 0 +VERTEX + 5 +751 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 675 + 72 + 674 + 73 + 673 + 74 + 672 + 0 +VERTEX + 5 +752 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 16 + 72 + 15 + 73 + -14 + 0 +VERTEX + 5 +753 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -16 + 72 + 14 + 73 + -13 + 0 +VERTEX + 5 +754 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -16 + 72 + 13 + 73 + -12 + 0 +VERTEX + 5 +755 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -16 + 72 + 12 + 73 + -11 + 0 +VERTEX + 5 +756 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -16 + 72 + 11 + 73 + -10 + 0 +VERTEX + 5 +757 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -16 + 72 + 10 + 73 + -9 + 0 +VERTEX + 5 +758 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -16 + 72 + 9 + 73 + -8 + 0 +VERTEX + 5 +759 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -16 + 72 + 8 + 73 + -19 + 0 +VERTEX + 5 +75A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -16 + 72 + 19 + 73 + -20 + 0 +VERTEX + 5 +75B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -16 + 72 + 20 + 73 + -7 + 0 +VERTEX + 5 +75C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -16 + 72 + 7 + 73 + -6 + 0 +VERTEX + 5 +75D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -16 + 72 + 6 + 73 + -5 + 0 +VERTEX + 5 +75E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -16 + 72 + 5 + 73 + -17 + 0 +VERTEX + 5 +75F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -16 + 72 + 17 + 73 + -18 + 0 +VERTEX + 5 +760 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -16 + 72 + 18 + 73 + -4 + 0 +VERTEX + 5 +761 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -16 + 72 + 4 + 73 + -3 + 0 +VERTEX + 5 +762 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -16 + 72 + 3 + 73 + -2 + 0 +VERTEX + 5 +763 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 254 + 72 + -253 + 73 + -285 + 0 +VERTEX + 5 +764 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -254 + 72 + 285 + 73 + -293 + 0 +VERTEX + 5 +765 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -254 + 72 + 293 + 73 + -303 + 0 +VERTEX + 5 +766 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -254 + 72 + 303 + 73 + -304 + 0 +VERTEX + 5 +767 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -254 + 72 + 304 + 73 + -300 + 0 +VERTEX + 5 +768 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -254 + 72 + 300 + 73 + -318 + 0 +VERTEX + 5 +769 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -254 + 72 + -318 + 73 + -256 + 0 +VERTEX + 5 +76A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -254 + 72 + 256 + 73 + 255 + 0 +VERTEX + 5 +76B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 253 + 72 + 252 + 73 + -356 + 0 +VERTEX + 5 +76C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -253 + 72 + 356 + 73 + -320 + 0 +VERTEX + 5 +76D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -253 + 72 + 320 + 73 + -275 + 0 +VERTEX + 5 +76E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -253 + 72 + 275 + 73 + -274 + 0 +VERTEX + 5 +76F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -253 + 72 + 274 + 73 + -273 + 0 +VERTEX + 5 +770 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -253 + 72 + 273 + 73 + -285 + 0 +VERTEX + 5 +771 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 318 + 72 + -327 + 73 + -256 + 0 +VERTEX + 5 +772 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -336 + 72 + -256 + 73 + 327 + 0 +VERTEX + 5 +773 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -256 + 72 + -336 + 73 + 245 + 0 +VERTEX + 5 +774 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -337 + 72 + -245 + 73 + 336 + 0 +VERTEX + 5 +775 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -245 + 72 + -337 + 73 + 246 + 0 +VERTEX + 5 +776 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -333 + 72 + -246 + 73 + 337 + 0 +VERTEX + 5 +777 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -246 + 72 + 333 + 73 + -347 + 0 +VERTEX + 5 +778 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -246 + 72 + -347 + 73 + 247 + 0 +VERTEX + 5 +779 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -353 + 72 + -247 + 73 + 347 + 0 +VERTEX + 5 +77A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -247 + 72 + -353 + 73 + 248 + 0 +VERTEX + 5 +77B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -371 + 72 + -248 + 73 + 353 + 0 +VERTEX + 5 +77C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -248 + 72 + -371 + 73 + 249 + 0 +VERTEX + 5 +77D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -372 + 72 + -249 + 73 + 371 + 0 +VERTEX + 5 +77E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -249 + 72 + -372 + 73 + 250 + 0 +VERTEX + 5 +77F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -358 + 72 + -250 + 73 + 372 + 0 +VERTEX + 5 +780 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -250 + 72 + -358 + 73 + 251 + 0 +VERTEX + 5 +781 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -356 + 72 + -251 + 73 + 358 + 0 +VERTEX + 5 +782 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 272 + 72 + 271 + 73 + -270 + 0 +VERTEX + 5 +783 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -272 + 72 + 270 + 73 + -269 + 0 +VERTEX + 5 +784 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -272 + 72 + 269 + 73 + -268 + 0 +VERTEX + 5 +785 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -272 + 72 + 268 + 73 + -267 + 0 +VERTEX + 5 +786 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -272 + 72 + 267 + 73 + -266 + 0 +VERTEX + 5 +787 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -272 + 72 + 266 + 73 + -265 + 0 +VERTEX + 5 +788 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -272 + 72 + 265 + 73 + -264 + 0 +VERTEX + 5 +789 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -272 + 72 + 264 + 73 + -263 + 0 +VERTEX + 5 +78A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -272 + 72 + 263 + 73 + -262 + 0 +VERTEX + 5 +78B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 415 + 72 + -543 + 73 + -402 + 0 +VERTEX + 5 +78C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -415 + 72 + 402 + 73 + -401 + 0 +VERTEX + 5 +78D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -415 + 72 + 401 + 73 + -400 + 0 +VERTEX + 5 +78E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -415 + 72 + 400 + 73 + -399 + 0 +VERTEX + 5 +78F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -415 + 72 + 399 + 73 + -398 + 0 +VERTEX + 5 +790 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -415 + 72 + 398 + 73 + 397 + 0 +VERTEX + 5 +791 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 415 + 72 + -397 + 73 + 409 + 0 +VERTEX + 5 +792 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 408 + 72 + -409 + 73 + -392 + 0 +VERTEX + 5 +793 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -408 + 72 + 392 + 73 + -391 + 0 +VERTEX + 5 +794 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -408 + 72 + 391 + 73 + -390 + 0 +VERTEX + 5 +795 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -408 + 72 + 390 + 73 + -389 + 0 +VERTEX + 5 +796 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -408 + 72 + 389 + 73 + -388 + 0 +VERTEX + 5 +797 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -408 + 72 + 388 + 73 + -407 + 0 +VERTEX + 5 +798 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -408 + 72 + 407 + 73 + -406 + 0 +VERTEX + 5 +799 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -408 + 72 + 406 + 73 + -405 + 0 +VERTEX + 5 +79A +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -408 + 72 + 405 + 73 + -404 + 0 +VERTEX + 5 +79B +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -408 + 72 + 404 + 73 + -403 + 0 +VERTEX + 5 +79C +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -408 + 72 + 403 + 73 + -402 + 0 +VERTEX + 5 +79D +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -408 + 72 + -402 + 73 + 543 + 0 +VERTEX + 5 +79E +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -409 + 72 + 397 + 73 + -396 + 0 +VERTEX + 5 +79F +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -409 + 72 + 396 + 73 + -395 + 0 +VERTEX + 5 +7A0 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -409 + 72 + 395 + 73 + -394 + 0 +VERTEX + 5 +7A1 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -409 + 72 + 394 + 73 + -393 + 0 +VERTEX + 5 +7A2 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 644 + 72 + 643 + 73 + -642 + 0 +VERTEX + 5 +7A3 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -644 + 72 + 642 + 73 + -641 + 0 +VERTEX + 5 +7A4 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 680 + 72 + 679 + 73 + -678 + 0 +VERTEX + 5 +7A5 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -680 + 72 + 678 + 73 + -677 + 0 +VERTEX + 5 +7A6 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -680 + 72 + 677 + 73 + 676 + 0 +SEQEND + 5 +7A7 +330 +68 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 7 + 0 +POLYLINE + 5 +7A8 +330 +1F +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbPolyFaceMesh + 66 + 1 + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 64 + 71 + 72 + 72 + 104 + 0 +VERTEX + 5 +7A9 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +0.0 + 20 +-199.0 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7AA +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-4.774999999999999 + 20 +-199.418 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7AB +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-9.405999999999999 + 20 +-200.658 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7AC +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-13.75 + 20 +-202.684 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7AD +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-17.677 + 20 +-205.434 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7AE +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-21.066 + 20 +-208.823 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7AF +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-23.816 + 20 +-212.75 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7B0 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-25.842 + 20 +-217.0940000000001 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7B1 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-27.082 + 20 +-221.725 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7B2 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-27.5 + 20 +-226.5 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7B3 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-27.082 + 20 +-231.275 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7B4 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-25.842 + 20 +-235.906 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7B5 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-23.816 + 20 +-240.2500000000001 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7B6 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-21.066 + 20 +-244.177 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7B7 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-17.677 + 20 +-247.566 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7B8 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-13.75 + 20 +-250.316 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7B9 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-9.405999999999999 + 20 +-252.342 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7BA +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-4.774999999999999 + 20 +-253.582 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7BB +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +0.0 + 20 +-254.0 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7BC +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +4.774999999999999 + 20 +-253.582 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7BD +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +9.405999999999999 + 20 +-252.342 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7BE +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +13.75 + 20 +-250.316 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7BF +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +17.677 + 20 +-247.566 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7C0 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +21.066 + 20 +-244.177 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7C1 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +23.816 + 20 +-240.2500000000001 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7C2 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +25.842 + 20 +-235.906 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7C3 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +27.082 + 20 +-231.275 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7C4 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +27.5 + 20 +-226.5 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7C5 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +27.082 + 20 +-221.725 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7C6 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +25.842 + 20 +-217.0940000000001 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7C7 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +23.816 + 20 +-212.75 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7C8 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +21.066 + 20 +-208.823 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7C9 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +17.677 + 20 +-205.434 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7CA +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +13.75 + 20 +-202.684 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7CB +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +9.405999999999999 + 20 +-200.658 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7CC +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +4.774999999999999 + 20 +-199.418 + 30 +5.0 + 70 + 192 + 0 +VERTEX + 5 +7CD +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +4.774999999999999 + 20 +-199.418 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7CE +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +9.405999999999999 + 20 +-200.658 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7CF +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +13.75 + 20 +-202.684 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7D0 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +17.677 + 20 +-205.434 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7D1 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +21.066 + 20 +-208.823 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7D2 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +23.816 + 20 +-212.75 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7D3 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +25.842 + 20 +-217.0940000000001 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7D4 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +27.082 + 20 +-221.725 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7D5 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +27.5 + 20 +-226.5 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7D6 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +27.082 + 20 +-231.275 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7D7 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +25.842 + 20 +-235.906 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7D8 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +23.816 + 20 +-240.2500000000001 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7D9 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +21.066 + 20 +-244.177 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7DA +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +17.677 + 20 +-247.566 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7DB +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +13.75 + 20 +-250.316 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7DC +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +9.405999999999999 + 20 +-252.342 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7DD +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +4.774999999999999 + 20 +-253.582 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7DE +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +0.0 + 20 +-254.0 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7DF +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-4.774999999999999 + 20 +-253.582 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7E0 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-9.405999999999999 + 20 +-252.342 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7E1 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-13.75 + 20 +-250.316 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7E2 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-17.677 + 20 +-247.566 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7E3 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-21.066 + 20 +-244.177 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7E4 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-23.816 + 20 +-240.2500000000001 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7E5 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-25.842 + 20 +-235.906 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7E6 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-27.082 + 20 +-231.275 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7E7 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-27.5 + 20 +-226.5 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7E8 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-27.082 + 20 +-221.725 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7E9 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-25.842 + 20 +-217.0940000000001 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7EA +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-23.816 + 20 +-212.75 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7EB +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-21.066 + 20 +-208.823 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7EC +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-17.677 + 20 +-205.434 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7ED +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-13.75 + 20 +-202.684 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7EE +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-9.405999999999999 + 20 +-200.658 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7EF +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +-4.774999999999999 + 20 +-199.418 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7F0 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbVertex +100 +AcDbPolyFaceMeshVertex + 10 +0.0 + 20 +-199.0 + 30 +7.0 + 70 + 192 + 0 +VERTEX + 5 +7F1 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 37 + 72 + 36 + 73 + 1 + 74 + 72 + 0 +VERTEX + 5 +7F2 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 37 + 72 + 38 + 73 + 35 + 74 + 36 + 0 +VERTEX + 5 +7F3 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 38 + 72 + 39 + 73 + 34 + 74 + 35 + 0 +VERTEX + 5 +7F4 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 39 + 72 + 40 + 73 + 33 + 74 + 34 + 0 +VERTEX + 5 +7F5 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 40 + 72 + 41 + 73 + 32 + 74 + 33 + 0 +VERTEX + 5 +7F6 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 41 + 72 + 42 + 73 + 31 + 74 + 32 + 0 +VERTEX + 5 +7F7 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 42 + 72 + 43 + 73 + 30 + 74 + 31 + 0 +VERTEX + 5 +7F8 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 43 + 72 + 44 + 73 + 29 + 74 + 30 + 0 +VERTEX + 5 +7F9 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 44 + 72 + 45 + 73 + 28 + 74 + 29 + 0 +VERTEX + 5 +7FA +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 45 + 72 + 46 + 73 + 27 + 74 + 28 + 0 +VERTEX + 5 +7FB +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 46 + 72 + 47 + 73 + 26 + 74 + 27 + 0 +VERTEX + 5 +7FC +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 47 + 72 + 48 + 73 + 25 + 74 + 26 + 0 +VERTEX + 5 +7FD +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 48 + 72 + 49 + 73 + 24 + 74 + 25 + 0 +VERTEX + 5 +7FE +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 49 + 72 + 50 + 73 + 23 + 74 + 24 + 0 +VERTEX + 5 +7FF +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 50 + 72 + 51 + 73 + 22 + 74 + 23 + 0 +VERTEX + 5 +800 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 51 + 72 + 52 + 73 + 21 + 74 + 22 + 0 +VERTEX + 5 +801 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 52 + 72 + 53 + 73 + 20 + 74 + 21 + 0 +VERTEX + 5 +802 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 53 + 72 + 54 + 73 + 19 + 74 + 20 + 0 +VERTEX + 5 +803 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 54 + 72 + 55 + 73 + 18 + 74 + 19 + 0 +VERTEX + 5 +804 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 55 + 72 + 56 + 73 + 17 + 74 + 18 + 0 +VERTEX + 5 +805 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 56 + 72 + 57 + 73 + 16 + 74 + 17 + 0 +VERTEX + 5 +806 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 57 + 72 + 58 + 73 + 15 + 74 + 16 + 0 +VERTEX + 5 +807 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 58 + 72 + 59 + 73 + 14 + 74 + 15 + 0 +VERTEX + 5 +808 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 59 + 72 + 60 + 73 + 13 + 74 + 14 + 0 +VERTEX + 5 +809 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 60 + 72 + 61 + 73 + 12 + 74 + 13 + 0 +VERTEX + 5 +80A +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 61 + 72 + 62 + 73 + 11 + 74 + 12 + 0 +VERTEX + 5 +80B +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 62 + 72 + 63 + 73 + 10 + 74 + 11 + 0 +VERTEX + 5 +80C +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 63 + 72 + 64 + 73 + 9 + 74 + 10 + 0 +VERTEX + 5 +80D +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 64 + 72 + 65 + 73 + 8 + 74 + 9 + 0 +VERTEX + 5 +80E +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 65 + 72 + 66 + 73 + 7 + 74 + 8 + 0 +VERTEX + 5 +80F +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 66 + 72 + 67 + 73 + 6 + 74 + 7 + 0 +VERTEX + 5 +810 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 67 + 72 + 68 + 73 + 5 + 74 + 6 + 0 +VERTEX + 5 +811 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 68 + 72 + 69 + 73 + 4 + 74 + 5 + 0 +VERTEX + 5 +812 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 69 + 72 + 70 + 73 + 3 + 74 + 4 + 0 +VERTEX + 5 +813 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 70 + 72 + 71 + 73 + 2 + 74 + 3 + 0 +VERTEX + 5 +814 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 71 + 72 + 72 + 73 + 1 + 74 + 2 + 0 +VERTEX + 5 +815 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 2 + 73 + 1 + 0 +VERTEX + 5 +816 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 36 + 72 + 35 + 73 + -34 + 0 +VERTEX + 5 +817 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 34 + 73 + -33 + 0 +VERTEX + 5 +818 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 33 + 73 + -32 + 0 +VERTEX + 5 +819 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 32 + 73 + -31 + 0 +VERTEX + 5 +81A +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 31 + 73 + -30 + 0 +VERTEX + 5 +81B +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 30 + 73 + -29 + 0 +VERTEX + 5 +81C +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 29 + 73 + -28 + 0 +VERTEX + 5 +81D +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 28 + 73 + -27 + 0 +VERTEX + 5 +81E +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 27 + 73 + -26 + 0 +VERTEX + 5 +81F +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 26 + 73 + -25 + 0 +VERTEX + 5 +820 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 25 + 73 + -24 + 0 +VERTEX + 5 +821 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 24 + 73 + -23 + 0 +VERTEX + 5 +822 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 23 + 73 + -22 + 0 +VERTEX + 5 +823 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 22 + 73 + -21 + 0 +VERTEX + 5 +824 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 21 + 73 + -20 + 0 +VERTEX + 5 +825 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 20 + 73 + -19 + 0 +VERTEX + 5 +826 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 19 + 73 + -18 + 0 +VERTEX + 5 +827 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 18 + 73 + -17 + 0 +VERTEX + 5 +828 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 17 + 73 + -16 + 0 +VERTEX + 5 +829 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 16 + 73 + -15 + 0 +VERTEX + 5 +82A +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 15 + 73 + -14 + 0 +VERTEX + 5 +82B +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 14 + 73 + -13 + 0 +VERTEX + 5 +82C +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 13 + 73 + -12 + 0 +VERTEX + 5 +82D +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 12 + 73 + -11 + 0 +VERTEX + 5 +82E +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 11 + 73 + -10 + 0 +VERTEX + 5 +82F +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 10 + 73 + -9 + 0 +VERTEX + 5 +830 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 9 + 73 + -8 + 0 +VERTEX + 5 +831 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 8 + 73 + -7 + 0 +VERTEX + 5 +832 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 7 + 73 + -6 + 0 +VERTEX + 5 +833 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 6 + 73 + -5 + 0 +VERTEX + 5 +834 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 5 + 73 + -4 + 0 +VERTEX + 5 +835 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 4 + 73 + -3 + 0 +VERTEX + 5 +836 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -36 + 72 + 3 + 73 + -2 + 0 +VERTEX + 5 +837 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + 72 + 72 + 71 + 73 + -70 + 0 +VERTEX + 5 +838 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 70 + 73 + -69 + 0 +VERTEX + 5 +839 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 69 + 73 + -68 + 0 +VERTEX + 5 +83A +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 68 + 73 + -67 + 0 +VERTEX + 5 +83B +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 67 + 73 + -66 + 0 +VERTEX + 5 +83C +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 66 + 73 + -65 + 0 +VERTEX + 5 +83D +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 65 + 73 + -64 + 0 +VERTEX + 5 +83E +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 64 + 73 + -63 + 0 +VERTEX + 5 +83F +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 63 + 73 + -62 + 0 +VERTEX + 5 +840 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 62 + 73 + -61 + 0 +VERTEX + 5 +841 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 61 + 73 + -60 + 0 +VERTEX + 5 +842 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 60 + 73 + -59 + 0 +VERTEX + 5 +843 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 59 + 73 + -58 + 0 +VERTEX + 5 +844 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 58 + 73 + -57 + 0 +VERTEX + 5 +845 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 57 + 73 + -56 + 0 +VERTEX + 5 +846 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 56 + 73 + -55 + 0 +VERTEX + 5 +847 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 55 + 73 + -54 + 0 +VERTEX + 5 +848 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 54 + 73 + -53 + 0 +VERTEX + 5 +849 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 53 + 73 + -52 + 0 +VERTEX + 5 +84A +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 52 + 73 + -51 + 0 +VERTEX + 5 +84B +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 51 + 73 + -50 + 0 +VERTEX + 5 +84C +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 50 + 73 + -49 + 0 +VERTEX + 5 +84D +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 49 + 73 + -48 + 0 +VERTEX + 5 +84E +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 48 + 73 + -47 + 0 +VERTEX + 5 +84F +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 47 + 73 + -46 + 0 +VERTEX + 5 +850 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 46 + 73 + -45 + 0 +VERTEX + 5 +851 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 45 + 73 + -44 + 0 +VERTEX + 5 +852 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 44 + 73 + -43 + 0 +VERTEX + 5 +853 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 43 + 73 + -42 + 0 +VERTEX + 5 +854 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 42 + 73 + -41 + 0 +VERTEX + 5 +855 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 41 + 73 + -40 + 0 +VERTEX + 5 +856 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 40 + 73 + -39 + 0 +VERTEX + 5 +857 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 39 + 73 + -38 + 0 +VERTEX + 5 +858 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 +100 +AcDbFaceRecord + 10 +0.0 + 20 +0.0 + 30 +0.0 + 70 + 128 + 71 + -72 + 72 + 38 + 73 + 37 + 0 +SEQEND + 5 +859 +330 +7A8 +100 +AcDbEntity + 8 +0 + 6 +Durchgehend + 62 + 250 + 0 +VIEWPORT + 5 +85A +330 +1B +100 +AcDbEntity + 67 + 1 + 8 +0 +100 +AcDbViewport + 10 +0.0 + 20 +-210.0 + 30 +0.0 + 40 +1200.0 + 41 +420.0 + 68 + 1 + 69 + 1 + 12 +0.0 + 22 +-210.0 + 13 +0.0 + 23 +0.0 + 14 +5.0 + 24 +5.0 + 15 +5.0 + 25 +5.0 + 16 +0.0 + 26 +0.0 + 36 +1.0 + 17 +0.0 + 27 +0.0 + 37 +0.0 + 42 +50.0 + 43 +0.0 + 44 +0.0 + 45 +420.0 + 50 +0.0 + 51 +0.0 + 72 + 1000 + 90 + 32800 + 1 + +281 + 0 + 71 + 1 + 74 + 0 +110 +0.0 +120 +0.0 +130 +0.0 +111 +1.0 +121 +0.0 +131 +0.0 +112 +0.0 +122 +1.0 +132 +0.0 + 79 + 0 +146 +0.0 + 0 +ENDSEC + 0 +SECTION + 2 +OBJECTS + 0 +DICTIONARY + 5 +C +330 +0 +100 +AcDbDictionary +281 + 1 + 3 +ACAD_GROUP +350 +D + 3 +ACAD_LAYOUT +350 +1A + 3 +ACAD_MLEADERSTYLE +350 +85C + 3 +ACAD_MLINESTYLE +350 +17 + 3 +ACAD_PLOTSETTINGS +350 +19 + 3 +ACAD_PLOTSTYLENAME +350 +E + 3 +ACAD_SCALELIST +350 +85D + 3 +ACAD_TABLESTYLE +350 +46 + 3 +ACAD_VISUALSTYLE +350 +2A + 3 +AcDbVariableDictionary +350 +85B + 0 +DICTIONARY + 5 +D +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 0 +DICTIONARY + 5 +1A +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 3 +Model +350 +22 + 3 +Papier 1 +350 +1E + 0 +DICTIONARY + 5 +85C +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 0 +DICTIONARY + 5 +17 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 3 +Standard +350 +18 + 0 +DICTIONARY + 5 +19 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 0 +ACDBDICTIONARYWDFLT + 5 +E +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 3 +Normal +350 +F +100 +AcDbDictionaryWithDefault +340 +F + 0 +DICTIONARY + 5 +85D +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 3 +A0 +350 +85E + 3 +A1 +350 +85F + 3 +A2 +350 +860 + 3 +A3 +350 +861 + 3 +A4 +350 +862 + 3 +A5 +350 +863 + 3 +A6 +350 +864 + 3 +A7 +350 +865 + 3 +A8 +350 +866 + 3 +A9 +350 +867 + 3 +B0 +350 +868 + 3 +B1 +350 +869 + 3 +B2 +350 +86A + 3 +B3 +350 +86B + 3 +B4 +350 +86C + 3 +B5 +350 +86D + 3 +B6 +350 +86E + 3 +B7 +350 +86F + 3 +B8 +350 +870 + 3 +B9 +350 +871 + 3 +C0 +350 +872 + 3 +C1 +350 +873 + 3 +C2 +350 +874 + 3 +C3 +350 +875 + 3 +C4 +350 +876 + 3 +C5 +350 +877 + 3 +C6 +350 +878 + 3 +C7 +350 +879 + 3 +C8 +350 +87A + 3 +C9 +350 +87B + 3 +D0 +350 +87C + 3 +D1 +350 +87D + 3 +D2 +350 +87E + 0 +DICTIONARY + 5 +46 +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 3 +Standard +350 +47 + 0 +DICTIONARY + 5 +2A +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 3 +2dWireframe +350 +2F + 3 +3D Hidden +350 +31 + 3 +3dWireframe +350 +30 + 3 +Basic +350 +32 + 3 +Brighten +350 +36 + 3 +ColorChange +350 +3A + 3 +Conceptual +350 +34 + 3 +Dim +350 +35 + 3 +Facepattern +350 +39 + 3 +Flat +350 +2B + 3 +FlatWithEdges +350 +2C + 3 +Gouraud +350 +2D + 3 +GouraudWithEdges +350 +2E + 3 +Linepattern +350 +38 + 3 +Realistic +350 +33 + 3 +Thicken +350 +37 + 0 +DICTIONARY + 5 +85B +102 +{ACAD_REACTORS +330 +C +102 +} +330 +C +100 +AcDbDictionary +281 + 1 + 3 +CANNOSCALE +350 +883 + 0 +LAYOUT + 5 +22 +102 +{ACAD_REACTORS +330 +1A +102 +} +330 +1A +100 +AcDbPlotSettings + 1 + + 2 +TCAD_Plot + 4 +1200.00 x 420.00 MM + 6 + + 40 +0.0 + 41 +0.0 + 42 +0.0 + 43 +0.0 + 44 +1200.0 + 45 +420.0 + 46 +0.0 + 47 +0.0 + 48 +-600.0 + 49 +-210.0 +140 +600.0 +141 +210.0 +142 +1.0 +143 +1.0 + 70 + 1696 + 72 + 1 + 73 + 0 + 74 + 4 + 7 + + 75 + 0 +147 +0.771179302045728 +148 +0.0 +149 +0.0 +100 +AcDbLayout + 1 +Model + 70 + 1 + 71 + 0 + 10 +-600.0 + 20 +-420.0 + 11 +600.0 + 21 +0.0 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +-600.0 + 24 +-420.0 + 34 +0.0 + 15 +600.0 + 25 +0.0 + 35 +116.0 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 + 0 +330 +1F +331 +29 + 0 +LAYOUT + 5 +1E +102 +{ACAD_REACTORS +330 +1A +102 +} +330 +1A +100 +AcDbPlotSettings + 1 + + 2 +TCAD_Plot + 4 +279.40 x 215.90 MM + 6 + + 40 +0.0 + 41 +0.0 + 42 +0.0 + 43 +0.0 + 44 +279.4 + 45 +215.9 + 46 +0.0 + 47 +0.0 + 48 +0.0 + 49 +0.0 +140 +0.0 +141 +0.0 +142 +1.0 +143 +1.0 + 70 + 672 + 72 + 1 + 73 + 0 + 74 + 5 + 7 + + 75 + 16 +147 +1.0 +148 +139.7 +149 +317.95 +100 +AcDbLayout + 1 +Papier 1 + 70 + 1 + 71 + 1 + 10 +-139.7 + 20 +-317.95 + 11 +139.7 + 21 +-102.05 + 12 +0.0 + 22 +0.0 + 32 +0.0 + 14 +-139.7 + 24 +-317.95 + 34 +0.0 + 15 +139.7 + 25 +-102.05 + 35 +0.0 +146 +0.0 + 13 +0.0 + 23 +0.0 + 33 +0.0 + 16 +1.0 + 26 +0.0 + 36 +0.0 + 17 +0.0 + 27 +1.0 + 37 +0.0 + 76 + 0 +330 +1B +331 +85A + 0 +MLINESTYLE + 5 +18 +102 +{ACAD_REACTORS +330 +17 +102 +} +330 +17 +100 +AcDbMlineStyle + 2 +Standard + 70 + 0 + 3 + + 62 + 256 + 51 +90.0 + 52 +90.0 + 71 + 5 + 49 +0.5 + 62 + 256 + 6 +BYLAYER + 49 +-0.5 + 62 + 256 + 6 +BYLAYER + 49 +5.0 + 62 + 7 + 6 +BYLAYER + 49 +0.0 + 62 + 7 + 6 +BYLAYER + 49 +-5.0 + 62 + 7 + 6 +BYLAYER + 0 +ACDBPLACEHOLDER + 5 +F +102 +{ACAD_REACTORS +330 +E +102 +} +330 +E + 0 +SCALE + 5 +85E +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +1:1 +140 +1.0 +141 +1.0 +290 + 1 + 0 +SCALE + 5 +85F +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +1:2 +140 +1.0 +141 +2.0 +290 + 0 + 0 +SCALE + 5 +860 +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +1:4 +140 +1.0 +141 +4.0 +290 + 0 + 0 +SCALE + 5 +861 +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +1:5 +140 +1.0 +141 +5.0 +290 + 0 + 0 +SCALE + 5 +862 +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +1:8 +140 +1.0 +141 +8.0 +290 + 0 + 0 +SCALE + 5 +863 +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +1:10 +140 +1.0 +141 +10.0 +290 + 0 + 0 +SCALE + 5 +864 +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +1:16 +140 +1.0 +141 +16.0 +290 + 0 + 0 +SCALE + 5 +865 +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +1:20 +140 +1.0 +141 +20.0 +290 + 0 + 0 +SCALE + 5 +866 +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +1:30 +140 +1.0 +141 +30.0 +290 + 0 + 0 +SCALE + 5 +867 +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +1:40 +140 +1.0 +141 +40.0 +290 + 0 + 0 +SCALE + 5 +868 +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +1:50 +140 +1.0 +141 +50.0 +290 + 0 + 0 +SCALE + 5 +869 +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +1:100 +140 +1.0 +141 +100.0 +290 + 0 + 0 +SCALE + 5 +86A +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +2:1 +140 +2.0 +141 +1.0 +290 + 0 + 0 +SCALE + 5 +86B +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +4:1 +140 +4.0 +141 +1.0 +290 + 0 + 0 +SCALE + 5 +86C +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +8:1 +140 +8.0 +141 +1.0 +290 + 0 + 0 +SCALE + 5 +86D +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +10:1 +140 +10.0 +141 +1.0 +290 + 0 + 0 +SCALE + 5 +86E +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +100:1 +140 +100.0 +141 +1.0 +290 + 0 + 0 +SCALE + 5 +86F +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +1/128" = 1'-0" +140 +0.0078125 +141 +12.0 +290 + 0 + 0 +SCALE + 5 +870 +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +1/64" = 1'-0" +140 +0.015625 +141 +12.0 +290 + 0 + 0 +SCALE + 5 +871 +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +1/32" = 1'-0" +140 +0.03125 +141 +12.0 +290 + 0 + 0 +SCALE + 5 +872 +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +1/16" = 1'-0" +140 +0.0625 +141 +12.0 +290 + 0 + 0 +SCALE + 5 +873 +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +3/32" = 1'-0" +140 +0.09375 +141 +12.0 +290 + 0 + 0 +SCALE + 5 +874 +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +1/8" = 1'-0" +140 +0.125 +141 +12.0 +290 + 0 + 0 +SCALE + 5 +875 +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +3/16" = 1'-0" +140 +0.1875 +141 +12.0 +290 + 0 + 0 +SCALE + 5 +876 +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +1/4" = 1'-0" +140 +0.25 +141 +12.0 +290 + 0 + 0 +SCALE + 5 +877 +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +3/8" = 1'-0" +140 +0.375 +141 +12.0 +290 + 0 + 0 +SCALE + 5 +878 +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +1/2" = 1'-0" +140 +0.5 +141 +12.0 +290 + 0 + 0 +SCALE + 5 +879 +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +3/4" = 1'-0" +140 +0.75 +141 +12.0 +290 + 0 + 0 +SCALE + 5 +87A +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +1" = 1'-0" +140 +1.0 +141 +12.0 +290 + 0 + 0 +SCALE + 5 +87B +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +1-1/2" = 1'-0" +140 +1.5 +141 +12.0 +290 + 0 + 0 +SCALE + 5 +87C +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +3" = 1'-0" +140 +3.0 +141 +12.0 +290 + 0 + 0 +SCALE + 5 +87D +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +6" = 1'-0" +140 +6.0 +141 +12.0 +290 + 0 + 0 +SCALE + 5 +87E +102 +{ACAD_REACTORS +330 +85D +102 +} +330 +85D +100 +AcDbScale + 70 + 0 +300 +1'-0" = 1'-0" +140 +12.0 +141 +12.0 +290 + 0 + 0 +TABLESTYLE + 5 +47 +102 +{ACAD_REACTORS +330 +46 +102 +} +330 +46 +100 +AcDbTableStyle + 3 + + 70 + 0 + 71 + 0 + 40 +1.0 + 41 +1.0 +280 + 0 +281 + 0 + 7 +Standard +140 +3.0 +170 + 5 + 62 + 0 + 63 + 257 +283 + 0 +274 + -2 +284 + 1 + 64 + 0 +275 + -2 +285 + 1 + 65 + 0 +276 + -2 +286 + 1 + 66 + 0 +277 + -2 +287 + 1 + 67 + 0 +278 + -2 +288 + 1 + 68 + 0 +279 + -2 +289 + 1 + 69 + 0 + 7 +Standard +140 +3.0 +170 + 5 + 62 + 0 + 63 + 257 +283 + 0 +274 + -2 +284 + 1 + 64 + 0 +275 + -2 +285 + 1 + 65 + 0 +276 + -2 +286 + 1 + 66 + 0 +277 + -2 +287 + 1 + 67 + 0 +278 + -2 +288 + 1 + 68 + 0 +279 + -2 +289 + 1 + 69 + 0 + 7 +Standard +140 +3.0 +170 + 5 + 62 + 0 + 63 + 257 +283 + 0 +274 + -2 +284 + 1 + 64 + 0 +275 + -2 +285 + 1 + 65 + 0 +276 + -2 +286 + 1 + 66 + 0 +277 + -2 +287 + 1 + 67 + 0 +278 + -2 +288 + 1 + 68 + 0 +279 + -2 +289 + 1 + 69 + 0 + 0 +VISUALSTYLE + 5 +2F +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbVisualStyle + 2 +2dWireframe + 70 + 4 + 71 + 0 + 72 + 2 + 73 + 0 + 90 + 0 + 40 +-0.6 + 41 +-30.0 + 62 + 5 + 63 + 7 + 74 + 1 + 91 + 4 + 64 + 7 + 65 + 257 + 75 + 1 +175 + 1 + 42 +1.0 + 92 + 0 + 66 + 257 + 43 +1.0 + 76 + 1 + 77 + 6 + 78 + 2 + 67 + 7 + 79 + 5 +170 + 0 +171 + 0 +290 + 0 +174 + 0 + 93 + 1 + 44 +0.0 +173 + 0 +291 + 0 + 45 +0.0 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +31 +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbVisualStyle + 2 +3D Hidden + 70 + 6 + 71 + 1 + 72 + 2 + 73 + 2 + 90 + 0 + 40 +-0.6 + 41 +-30.0 + 62 + 5 + 63 + 7 + 74 + 2 + 91 + 2 + 64 + 7 + 65 + 257 + 75 + 2 +175 + 1 + 42 +40.0 + 92 + 0 + 66 + 257 + 43 +1.0 + 76 + 1 + 77 + 6 + 78 + 2 + 67 + 7 + 79 + 3 +170 + 0 +171 + 0 +290 + 0 +174 + 0 + 93 + 1 + 44 +0.0 +173 + 0 +291 + 0 + 45 +0.0 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +30 +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbVisualStyle + 2 +3dWireframe + 70 + 5 + 71 + 0 + 72 + 2 + 73 + 0 + 90 + 0 + 40 +-0.6 + 41 +-30.0 + 62 + 5 + 63 + 7 + 74 + 1 + 91 + 4 + 64 + 7 + 65 + 257 + 75 + 1 +175 + 1 + 42 +1.0 + 92 + 0 + 66 + 257 + 43 +1.0 + 76 + 1 + 77 + 6 + 78 + 2 + 67 + 7 + 79 + 5 +170 + 0 +171 + 0 +290 + 0 +174 + 0 + 93 + 1 + 44 +0.0 +173 + 0 +291 + 0 + 45 +0.0 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +32 +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbVisualStyle + 2 +Basic + 70 + 7 + 71 + 1 + 72 + 0 + 73 + 1 + 90 + 0 + 40 +-0.6 + 41 +-30.0 + 62 + 5 + 63 + 7 + 74 + 0 + 91 + 4 + 64 + 7 + 65 + 257 + 75 + 1 +175 + 1 + 42 +1.0 + 92 + 8 + 66 + 7 + 43 +1.0 + 76 + 1 + 77 + 6 + 78 + 2 + 67 + 7 + 79 + 5 +170 + 0 +171 + 0 +290 + 0 +174 + 0 + 93 + 1 + 44 +0.0 +173 + 0 +291 + 1 + 45 +0.0 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +36 +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbVisualStyle + 2 +Brighten + 70 + 12 + 71 + 2 + 72 + 2 + 73 + 0 + 90 + 0 + 40 +-0.6 + 41 +-30.0 + 62 + 5 + 63 + 7 + 74 + 1 + 91 + 4 + 64 + 7 + 65 + 257 + 75 + 1 +175 + 1 + 42 +1.0 + 92 + 8 + 66 + 7 + 43 +1.0 + 76 + 1 + 77 + 6 + 78 + 2 + 67 + 7 + 79 + 5 +170 + 0 +171 + 0 +290 + 0 +174 + 0 + 93 + 1 + 44 +50.0 +173 + 0 +291 + 1 + 45 +0.0 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +3A +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbVisualStyle + 2 +ColorChange + 70 + 16 + 71 + 2 + 72 + 2 + 73 + 3 + 90 + 0 + 40 +-0.6 + 41 +-30.0 + 62 + 5 + 63 + 8 + 74 + 1 + 91 + 4 + 64 + 7 + 65 + 257 + 75 + 1 +175 + 1 + 42 +1.0 + 92 + 8 + 66 + 8 + 43 +1.0 + 76 + 1 + 77 + 6 + 78 + 2 + 67 + 7 + 79 + 5 +170 + 0 +171 + 0 +290 + 0 +174 + 0 + 93 + 1 + 44 +0.0 +173 + 0 +291 + 1 + 45 +0.0 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +34 +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbVisualStyle + 2 +Conceptual + 70 + 9 + 71 + 3 + 72 + 2 + 73 + 0 + 90 + 0 + 40 +-0.6 + 41 +-30.0 + 62 + 5 + 63 + 7 + 74 + 2 + 91 + 2 + 64 + 7 + 65 + 257 + 75 + 1 +175 + 1 + 42 +40.0 + 92 + 8 + 66 + 7 + 43 +1.0 + 76 + 1 + 77 + 6 + 78 + 2 + 67 + 7 + 79 + 3 +170 + 0 +171 + 0 +290 + 0 +174 + 0 + 93 + 1 + 44 +0.0 +173 + 0 +291 + 0 + 45 +0.0 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +35 +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbVisualStyle + 2 +Dim + 70 + 11 + 71 + 2 + 72 + 2 + 73 + 0 + 90 + 0 + 40 +-0.6 + 41 +-30.0 + 62 + 5 + 63 + 7 + 74 + 1 + 91 + 4 + 64 + 7 + 65 + 257 + 75 + 1 +175 + 1 + 42 +1.0 + 92 + 8 + 66 + 7 + 43 +1.0 + 76 + 1 + 77 + 6 + 78 + 2 + 67 + 7 + 79 + 5 +170 + 0 +171 + 0 +290 + 0 +174 + 0 + 93 + 1 + 44 +-50.0 +173 + 0 +291 + 1 + 45 +0.0 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +39 +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbVisualStyle + 2 +Facepattern + 70 + 15 + 71 + 2 + 72 + 2 + 73 + 0 + 90 + 0 + 40 +-0.6 + 41 +-30.0 + 62 + 5 + 63 + 7 + 74 + 1 + 91 + 4 + 64 + 7 + 65 + 257 + 75 + 1 +175 + 1 + 42 +1.0 + 92 + 8 + 66 + 7 + 43 +1.0 + 76 + 1 + 77 + 6 + 78 + 2 + 67 + 7 + 79 + 5 +170 + 0 +171 + 0 +290 + 0 +174 + 0 + 93 + 1 + 44 +0.0 +173 + 0 +291 + 1 + 45 +0.0 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +2B +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbVisualStyle + 2 +Flat + 70 + 0 + 71 + 2 + 72 + 1 + 73 + 1 + 90 + 2 + 40 +-0.6 + 41 +30.0 + 62 + 5 + 63 + 7 + 74 + 0 + 91 + 4 + 64 + 7 + 65 + 257 + 75 + 1 +175 + 1 + 42 +1.0 + 92 + 8 + 66 + 7 + 43 +1.0 + 76 + 1 + 77 + 6 + 78 + 2 + 67 + 7 + 79 + 5 +170 + 0 +171 + 0 +290 + 0 +174 + 0 + 93 + 13 + 44 +0.0 +173 + 0 +291 + 1 + 45 +0.0 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +2C +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbVisualStyle + 2 +FlatWithEdges + 70 + 1 + 71 + 2 + 72 + 1 + 73 + 1 + 90 + 2 + 40 +-0.6 + 41 +30.0 + 62 + 5 + 63 + 7 + 74 + 1 + 91 + 4 + 64 + 7 + 65 + 257 + 75 + 1 +175 + 1 + 42 +1.0 + 92 + 0 + 66 + 257 + 43 +1.0 + 76 + 1 + 77 + 6 + 78 + 2 + 67 + 7 + 79 + 5 +170 + 0 +171 + 0 +290 + 0 +174 + 0 + 93 + 13 + 44 +0.0 +173 + 0 +291 + 1 + 45 +0.0 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +2D +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbVisualStyle + 2 +Gouraud + 70 + 2 + 71 + 2 + 72 + 2 + 73 + 1 + 90 + 2 + 40 +-0.6 + 41 +30.0 + 62 + 5 + 63 + 7 + 74 + 0 + 91 + 4 + 64 + 7 + 65 + 257 + 75 + 1 +175 + 1 + 42 +1.0 + 92 + 0 + 66 + 7 + 43 +1.0 + 76 + 1 + 77 + 6 + 78 + 2 + 67 + 7 + 79 + 5 +170 + 0 +171 + 0 +290 + 0 +174 + 0 + 93 + 13 + 44 +0.0 +173 + 0 +291 + 1 + 45 +0.0 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +2E +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbVisualStyle + 2 +GouraudWithEdges + 70 + 3 + 71 + 2 + 72 + 2 + 73 + 1 + 90 + 2 + 40 +-0.6 + 41 +30.0 + 62 + 5 + 63 + 7 + 74 + 1 + 91 + 4 + 64 + 7 + 65 + 257 + 75 + 1 +175 + 1 + 42 +1.0 + 92 + 0 + 66 + 257 + 43 +1.0 + 76 + 1 + 77 + 6 + 78 + 2 + 67 + 7 + 79 + 5 +170 + 0 +171 + 0 +290 + 0 +174 + 0 + 93 + 13 + 44 +0.0 +173 + 0 +291 + 1 + 45 +0.0 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +38 +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbVisualStyle + 2 +Linepattern + 70 + 14 + 71 + 2 + 72 + 2 + 73 + 0 + 90 + 0 + 40 +-0.6 + 41 +-30.0 + 62 + 5 + 63 + 7 + 74 + 1 + 91 + 4 + 64 + 7 + 65 + 257 + 75 + 7 +175 + 7 + 42 +1.0 + 92 + 8 + 66 + 7 + 43 +1.0 + 76 + 1 + 77 + 6 + 78 + 2 + 67 + 7 + 79 + 5 +170 + 0 +171 + 0 +290 + 0 +174 + 0 + 93 + 1 + 44 +0.0 +173 + 0 +291 + 1 + 45 +0.0 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +33 +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbVisualStyle + 2 +Realistic + 70 + 8 + 71 + 2 + 72 + 2 + 73 + 0 + 90 + 0 + 40 +-0.6 + 41 +-30.0 + 62 + 5 + 63 + 7 + 74 + 1 + 91 + 0 + 64 + 7 + 65 + 257 + 75 + 1 +175 + 1 + 42 +1.0 + 92 + 8 + 66 + 8 + 43 +1.0 + 76 + 1 + 77 + 6 + 78 + 2 + 67 + 7 + 79 + 5 +170 + 0 +171 + 0 +290 + 0 +174 + 0 + 93 + 13 + 44 +0.0 +173 + 0 +291 + 0 + 45 +0.0 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +VISUALSTYLE + 5 +37 +102 +{ACAD_REACTORS +330 +2A +102 +} +330 +2A +100 +AcDbVisualStyle + 2 +Thicken + 70 + 13 + 71 + 2 + 72 + 2 + 73 + 0 + 90 + 0 + 40 +-0.6 + 41 +-30.0 + 62 + 5 + 63 + 7 + 74 + 1 + 91 + 4 + 64 + 7 + 65 + 257 + 75 + 1 +175 + 1 + 42 +1.0 + 92 + 12 + 66 + 7 + 43 +1.0 + 76 + 1 + 77 + 6 + 78 + 2 + 67 + 7 + 79 + 5 +170 + 0 +171 + 0 +290 + 0 +174 + 0 + 93 + 1 + 44 +0.0 +173 + 0 +291 + 1 + 45 +0.0 +1001 +ACAD +1000 +AcDbSavedByObjectVersion +1070 + 0 + 0 +DICTIONARYVAR + 5 +883 +102 +{ACAD_REACTORS +330 +85B +102 +} +330 +85B +100 +DictionaryVariables +280 + 0 + 1 +1:1 + 0 +ENDSEC + 0 +EOF diff --git a/test/unit/utDXFImporterExporter.cpp b/test/unit/utDXFImporterExporter.cpp index ee6f34ecd..e0e764ea6 100644 --- a/test/unit/utDXFImporterExporter.cpp +++ b/test/unit/utDXFImporterExporter.cpp @@ -69,3 +69,8 @@ TEST_F( utDXFImporterExporter, importerWithoutExtensionTest ) { EXPECT_NE( nullptr, scene ); } +TEST_F(utDXFImporterExporter, issue2229) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/DXF/issue_2229.dxf", aiProcess_ValidateDataStructure); + EXPECT_NE(nullptr, scene); +} From a24502577fd0a7d53851fc366c037c734d9410e7 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 21 Nov 2018 22:00:11 +0100 Subject: [PATCH 028/472] DXF-Importer: some small review findings. --- code/DXFHelper.h | 43 +++++++--------- code/DXFLoader.cpp | 121 +++++++++++++++++++++++---------------------- code/DXFLoader.h | 27 +++++----- 3 files changed, 94 insertions(+), 97 deletions(-) diff --git a/code/DXFHelper.h b/code/DXFHelper.h index f3f73d4c2..daf2f97e2 100644 --- a/code/DXFHelper.h +++ b/code/DXFHelper.h @@ -55,21 +55,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include namespace Assimp { - namespace DXF { - +namespace DXF { // read pairs of lines, parse group code and value and provide utilities // to convert the data to the target data type. -class LineReader -{ +// do NOT skip empty lines. In DXF files, they count as valid data. +class LineReader { public: LineReader(StreamReaderLE& reader) - // do NOT skip empty lines. In DXF files, they count as valid data. - : splitter(reader,false,true) - , groupcode( 0 ) - , value() - , end() - { + : splitter(reader,false,true) + , groupcode( 0 ) + , value() + , end() { + // empty } // ----------------------------------------- @@ -112,8 +110,6 @@ public: return fast_atof(value.c_str()); } -public: - // ----------------------------------------- /** pseudo-iterator increment to advance to the next (groupcode/value) pair */ LineReader& operator++() { @@ -168,14 +164,12 @@ private: int end; }; - - // represents a POLYLINE or a LWPOLYLINE. or even a 3DFACE The data is converted as needed. -struct PolyLine -{ +struct PolyLine { PolyLine() - : flags() - {} + : flags() { + // empty + } std::vector positions; std::vector colors; @@ -187,14 +181,15 @@ struct PolyLine std::string desc; }; - // reference to a BLOCK. Specifies its own coordinate system. -struct InsertBlock -{ +struct InsertBlock { InsertBlock() - : scale(1.f,1.f,1.f) - , angle() - {} + : pos() + , scale(1.f,1.f,1.f) + , angle() + , name() { + // empty + } aiVector3D pos; aiVector3D scale; diff --git a/code/DXFLoader.cpp b/code/DXFLoader.cpp index 24410da55..6710597df 100644 --- a/code/DXFLoader.cpp +++ b/code/DXFLoader.cpp @@ -71,8 +71,7 @@ const aiColor4D AI_DXF_DEFAULT_COLOR(aiColor4D(0.6f, 0.6f, 0.6f, 0.6f)); // color indices for DXF - 16 are supported, the table is // taken directly from the DXF spec. -static aiColor4D g_aclrDxfIndexColors[] = -{ +static aiColor4D g_aclrDxfIndexColors[] = { aiColor4D (0.6f, 0.6f, 0.6f, 1.0f), aiColor4D (1.0f, 0.0f, 0.0f, 1.0f), // red aiColor4D (0.0f, 1.0f, 0.0f, 1.0f), // green @@ -93,6 +92,11 @@ static aiColor4D g_aclrDxfIndexColors[] = #define AI_DXF_NUM_INDEX_COLORS (sizeof(g_aclrDxfIndexColors)/sizeof(g_aclrDxfIndexColors[0])) #define AI_DXF_ENTITIES_MAGIC_BLOCK "$ASSIMP_ENTITIES_MAGIC" +static const int GroupCode_Name = 2; +static const int GroupCode_XComp = 10; +static const int GroupCode_YComp = 20; +static const int GroupCode_ZComp = 30; + static const aiImporterDesc desc = { "Drawing Interchange Format (DXF) Importer", "", @@ -123,12 +127,12 @@ DXFImporter::~DXFImporter() { // Returns whether the class can handle the format of the given file. bool DXFImporter::CanRead( const std::string& filename, IOSystem* pIOHandler, bool checkSig ) const { const std::string& extension = GetExtension( filename ); - if ( extension == "dxf" ) { + if ( extension == desc.mFileExtensions ) { return true; } if ( extension.empty() || checkSig ) { - static const char *pTokens[] = { "SECTION", "HEADER", "ENDSEC", "BLOCKS" }; + const char *pTokens[] = { "SECTION", "HEADER", "ENDSEC", "BLOCKS" }; return BaseImporter::SearchFileHeaderForToken(pIOHandler, filename, pTokens, 4, 32 ); } @@ -137,29 +141,25 @@ bool DXFImporter::CanRead( const std::string& filename, IOSystem* pIOHandler, bo // ------------------------------------------------------------------------------------------------ // Get a list of all supported file extensions -const aiImporterDesc* DXFImporter::GetInfo () const -{ +const aiImporterDesc* DXFImporter::GetInfo () const { return &desc; } // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void DXFImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, - IOSystem* pIOHandler) -{ - std::shared_ptr file = std::shared_ptr( pIOHandler->Open( pFile) ); +void DXFImporter::InternReadFile( const std::string& filename, aiScene* pScene, IOSystem* pIOHandler) { + std::shared_ptr file = std::shared_ptr( pIOHandler->Open( filename) ); // Check whether we can read the file - if( file.get() == NULL) { - throw DeadlyImportError( "Failed to open DXF file " + pFile + ""); + if( file.get() == nullptr ) { + throw DeadlyImportError( "Failed to open DXF file " + filename + ""); } - // check whether this is a binaray DXF file - we can't read binary DXF files :-( + // Check whether this is a binary DXF file - we can't read binary DXF files :-( char buff[AI_DXF_BINARY_IDENT_LEN+1] = {0}; file->Read(buff,AI_DXF_BINARY_IDENT_LEN,1); - if (!strncmp(AI_DXF_BINARY_IDENT.c_str(),buff,AI_DXF_BINARY_IDENT_LEN)) { + if (0 == strncmp(AI_DXF_BINARY_IDENT.c_str(),buff,AI_DXF_BINARY_IDENT_LEN)) { throw DeadlyImportError("DXF: Binary files are not supported at the moment"); } @@ -228,13 +228,11 @@ void DXFImporter::InternReadFile( const std::string& pFile, } // ------------------------------------------------------------------------------------------------ -void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output) -{ +void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output) { // the process of resolving all the INSERT statements can grow the // poly-count excessively, so log the original number. // XXX Option to import blocks as separate nodes? if (!DefaultLogger::isNullLogger()) { - unsigned int vcount = 0, icount = 0; for (const DXF::Block& bl : output.blocks) { for (std::shared_ptr pl : bl.lines) { @@ -295,7 +293,7 @@ void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output) } } - if (!pScene->mNumMeshes) { + if ( 0 == pScene->mNumMeshes) { throw DeadlyImportError("DXF: this file contains no 3d data"); } @@ -368,8 +366,7 @@ void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output) // ------------------------------------------------------------------------------------------------ -void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& blocks_by_name) -{ +void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& blocks_by_name) { for (const DXF::InsertBlock& insert : bl.insertions) { // first check if the referenced blocks exists ... @@ -409,8 +406,7 @@ void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& bloc } // ------------------------------------------------------------------------------------------------ -void DXFImporter::GenerateMaterials(aiScene* pScene, DXF::FileData& /*output*/) -{ +void DXFImporter::GenerateMaterials(aiScene* pScene, DXF::FileData& /*output*/) { // generate an almost-white default material. Reason: // the default vertex color is GREY, so we are // already at Assimp's usual default color. @@ -435,8 +431,7 @@ void DXFImporter::GenerateMaterials(aiScene* pScene, DXF::FileData& /*output*/) } // ------------------------------------------------------------------------------------------------ -void DXFImporter::GenerateHierarchy(aiScene* pScene, DXF::FileData& /*output*/) -{ +void DXFImporter::GenerateHierarchy(aiScene* pScene, DXF::FileData& /*output*/) { // generate the output scene graph, which is just the root node with a single child for each layer. pScene->mRootNode = new aiNode(); pScene->mRootNode->mName.Set(""); @@ -490,17 +485,17 @@ void DXFImporter::ParseBlock(DXF::LineReader& reader, DXF::FileData& output) { while( !reader.End() && !reader.Is(0,"ENDBLK")) { switch(reader.GroupCode()) { - case 2: + case GroupCode_Name: block.name = reader.Value(); break; - case 10: + case GroupCode_XComp: block.base.x = reader.ValueAsFloat(); break; - case 20: + case GroupCode_YComp: block.base.y = reader.ValueAsFloat(); break; - case 30: + case GroupCode_ZComp: block.base.z = reader.ValueAsFloat(); break; } @@ -527,9 +522,8 @@ void DXFImporter::ParseBlock(DXF::LineReader& reader, DXF::FileData& output) { } // ------------------------------------------------------------------------------------------------ -void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output) -{ - // push a new block onto the stack. +void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output) { + // Push a new block onto the stack. output.blocks.push_back( DXF::Block() ); DXF::Block& block = output.blocks.back(); @@ -559,27 +553,25 @@ void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output) " inserted blocks in ENTITIES" ); } -void DXFImporter::ParseInsertion(DXF::LineReader& reader, DXF::FileData& output) -{ +void DXFImporter::ParseInsertion(DXF::LineReader& reader, DXF::FileData& output) { output.blocks.back().insertions.push_back( DXF::InsertBlock() ); DXF::InsertBlock& bl = output.blocks.back().insertions.back(); while( !reader.End() && !reader.Is(0)) { - switch(reader.GroupCode()) - { + switch(reader.GroupCode()) { // name of referenced block - case 2: + case GroupCode_Name: bl.name = reader.Value(); break; // translation - case 10: + case GroupCode_XComp: bl.pos.x = reader.ValueAsFloat(); break; - case 20: + case GroupCode_YComp: bl.pos.y = reader.ValueAsFloat(); break; - case 30: + case GroupCode_ZComp: bl.pos.z = reader.ValueAsFloat(); break; @@ -706,8 +698,7 @@ void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output) #define DXF_VERTEX_FLAG_HAS_POSITIONS 0x40 // ------------------------------------------------------------------------------------------------ -void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& line) -{ +void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& line) { unsigned int cnti = 0, flags = 0; unsigned int indices[4]; @@ -720,8 +711,7 @@ void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& li break; } - switch (reader.GroupCode()) - { + switch (reader.GroupCode()) { case 8: // layer to which the vertex belongs to - assume that // this is always the layer the top-level poly-line @@ -736,15 +726,15 @@ void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& li break; // VERTEX COORDINATES - case 10: + case GroupCode_XComp: out.x = reader.ValueAsFloat(); break; - case 20: + case GroupCode_YComp: out.y = reader.ValueAsFloat(); break; - case 30: + case GroupCode_ZComp: out.z = reader.ValueAsFloat(); break; @@ -780,6 +770,7 @@ void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& li if (indices[i] == 0) { ASSIMP_LOG_WARN("DXF: invalid vertex index, indices are one-based."); --line.counts.back(); + // Workaround to fix issue 2229 if (line.counts.back() == 0) { line.counts.pop_back(); } @@ -821,62 +812,74 @@ void DXFImporter::Parse3DFace(DXF::LineReader& reader, DXF::FileData& output) break; // x position of the first corner - case 10: vip[0].x = reader.ValueAsFloat(); + case 10: + vip[0].x = reader.ValueAsFloat(); b[2] = true; break; // y position of the first corner - case 20: vip[0].y = reader.ValueAsFloat(); + case 20: + vip[0].y = reader.ValueAsFloat(); b[2] = true; break; // z position of the first corner - case 30: vip[0].z = reader.ValueAsFloat(); + case 30: + vip[0].z = reader.ValueAsFloat(); b[2] = true; break; // x position of the second corner - case 11: vip[1].x = reader.ValueAsFloat(); + case 11: + vip[1].x = reader.ValueAsFloat(); b[3] = true; break; // y position of the second corner - case 21: vip[1].y = reader.ValueAsFloat(); + case 21: + vip[1].y = reader.ValueAsFloat(); b[3] = true; break; // z position of the second corner - case 31: vip[1].z = reader.ValueAsFloat(); + case 31: + vip[1].z = reader.ValueAsFloat(); b[3] = true; break; // x position of the third corner - case 12: vip[2].x = reader.ValueAsFloat(); + case 12: + vip[2].x = reader.ValueAsFloat(); b[0] = true; break; // y position of the third corner - case 22: vip[2].y = reader.ValueAsFloat(); + case 22: + vip[2].y = reader.ValueAsFloat(); b[0] = true; break; // z position of the third corner - case 32: vip[2].z = reader.ValueAsFloat(); + case 32: + vip[2].z = reader.ValueAsFloat(); b[0] = true; break; // x position of the fourth corner - case 13: vip[3].x = reader.ValueAsFloat(); + case 13: + vip[3].x = reader.ValueAsFloat(); b[1] = true; break; // y position of the fourth corner - case 23: vip[3].y = reader.ValueAsFloat(); + case 23: + vip[3].y = reader.ValueAsFloat(); b[1] = true; break; // z position of the fourth corner - case 33: vip[3].z = reader.ValueAsFloat(); + case 33: + vip[3].z = reader.ValueAsFloat(); b[1] = true; break; diff --git a/code/DXFLoader.h b/code/DXFLoader.h index 3392b8f63..e7f534e98 100644 --- a/code/DXFLoader.h +++ b/code/DXFLoader.h @@ -50,24 +50,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include namespace Assimp { - namespace DXF { - class LineReader; - struct FileData; - struct PolyLine; - struct Block; - struct InsertBlock; - - typedef std::map BlockMap; - } +// Forward declarations +namespace DXF { + class LineReader; + struct FileData; + struct PolyLine; + struct Block; + struct InsertBlock; + typedef std::map BlockMap; +} // --------------------------------------------------------------------------- -/** DXF importer implementation. - * -*/ -class DXFImporter : public BaseImporter -{ +/** + * @brief DXF importer implementation. + */ +class DXFImporter : public BaseImporter { public: DXFImporter(); ~DXFImporter(); From e595410de1c9a841e6a9e1570831d986d63a0aa7 Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 23 Nov 2018 20:04:16 +0100 Subject: [PATCH 029/472] Fix static init ordering issue in 3mf importer --- code/D3MFImporter.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index bf0e6a102..c434d8000 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -419,8 +419,6 @@ private: } //namespace D3MF -static const std::string Extension = "3mf"; - static const aiImporterDesc desc = { "3mf Importer", "", @@ -431,7 +429,7 @@ static const aiImporterDesc desc = { 0, 0, 0, - Extension.c_str() + "3mf" }; D3MFImporter::D3MFImporter() @@ -445,7 +443,7 @@ D3MFImporter::~D3MFImporter() { bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool checkSig) const { const std::string extension( GetExtension( filename ) ); - if(extension == Extension ) { + if(extension == "3mf" ) { return true; } else if ( !extension.length() || checkSig ) { if ( nullptr == pIOHandler ) { From 23af5336d55d358f7338f284e4a7e0fb4cd7aa22 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 23 Nov 2018 20:21:58 +0100 Subject: [PATCH 030/472] Update D3MFImporter.cpp Avoid using extension twice. --- code/D3MFImporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index c434d8000..de5708149 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -443,7 +443,7 @@ D3MFImporter::~D3MFImporter() { bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool checkSig) const { const std::string extension( GetExtension( filename ) ); - if(extension == "3mf" ) { + if(extension == desc.mFileExtensions ) { return true; } else if ( !extension.length() || checkSig ) { if ( nullptr == pIOHandler ) { From d03e978c1bb9ca3a962760d6081dead90e2d6e1e Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 25 Nov 2018 10:45:45 +0100 Subject: [PATCH 031/472] closes https://github.com/assimp/assimp/issues/2210: use different enum value. --- code/STEPFile.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/STEPFile.h b/code/STEPFile.h index 6245290b6..f5b56c31f 100644 --- a/code/STEPFile.h +++ b/code/STEPFile.h @@ -142,7 +142,7 @@ namespace STEP { struct TypeError : DeadlyImportError { enum { ENTITY_NOT_SPECIFIED = 0xffffffffffffffffLL, - ENTITY_NOT_SPECIFIED_32 = -1u + ENTITY_NOT_SPECIFIED_32 = 0x00000000ffffffff }; TypeError (const std::string& s,uint64_t entity = ENTITY_NOT_SPECIFIED, uint64_t line = SyntaxError::LINE_NOT_SPECIFIED); From 02359ea36931778e5494cdde668ddce371cbc858 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 25 Nov 2018 12:00:51 +0100 Subject: [PATCH 032/472] closes https://github.com/assimp/assimp/issues/2202: put STEPParser out of IFC importer. --- code/CMakeLists.txt | 14 ++++++++++---- code/Importer/IFC/IFCLoader.cpp | 2 +- .../{IFC => STEPParser}/STEPFileEncoding.cpp | 0 .../{IFC => STEPParser}/STEPFileEncoding.h | 0 .../{IFC => STEPParser}/STEPFileReader.cpp | 0 code/Importer/{IFC => STEPParser}/STEPFileReader.h | 0 code/Importer/StepFile/StepFileImporter.cpp | 2 +- 7 files changed, 12 insertions(+), 6 deletions(-) rename code/Importer/{IFC => STEPParser}/STEPFileEncoding.cpp (100%) rename code/Importer/{IFC => STEPParser}/STEPFileEncoding.h (100%) rename code/Importer/{IFC => STEPParser}/STEPFileReader.cpp (100%) rename code/Importer/{IFC => STEPParser}/STEPFileReader.h (100%) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 7ad49ad33..f34aac5c9 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -191,6 +191,14 @@ SET( Common_SRCS ) SOURCE_GROUP(Common FILES ${Common_SRCS}) +SET( STEPParser_SRCS + Importer/STEPParser/STEPFileReader.h + Importer/STEPParser/STEPFileReader.cpp + Importer/STEPParser/STEPFileEncoding.cpp + Importer/STEPParser/STEPFileEncoding.h +) +SOURCE_GROUP(STEPParser FILES ${STEPParser_SRCS}) + IF ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER ) SET( C4D_SRCS C4DImporter.cpp @@ -487,11 +495,8 @@ ADD_ASSIMP_IMPORTER( IFC Importer/IFC/IFCCurve.cpp Importer/IFC/IFCBoolean.cpp Importer/IFC/IFCOpenings.cpp - Importer/IFC/STEPFileReader.h - Importer/IFC/STEPFileReader.cpp - Importer/IFC/STEPFileEncoding.cpp - Importer/IFC/STEPFileEncoding.h ) + if (ASSIMP_BUILD_IFC_IMPORTER) if (MSVC) set_source_files_properties(Importer/IFC/IFCReaderGen1_2x3.cpp Importer/IFC/IFCReaderGen2_2x3.cpp PROPERTIES COMPILE_FLAGS "/bigobj") @@ -885,6 +890,7 @@ SET( assimp_src ${Exporter_SRCS} ${PostProcessing_SRCS} ${MaterialSystem_SRCS} + ${STEPParser_SRCS} ${Step_SRCS} # Model Support diff --git a/code/Importer/IFC/IFCLoader.cpp b/code/Importer/IFC/IFCLoader.cpp index f1c99a0f4..473355538 100644 --- a/code/Importer/IFC/IFCLoader.cpp +++ b/code/Importer/IFC/IFCLoader.cpp @@ -56,7 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif #include "IFCLoader.h" -#include "STEPFileReader.h" +#include "../STEPParser/STEPFileReader.h" #include "IFCUtil.h" diff --git a/code/Importer/IFC/STEPFileEncoding.cpp b/code/Importer/STEPParser/STEPFileEncoding.cpp similarity index 100% rename from code/Importer/IFC/STEPFileEncoding.cpp rename to code/Importer/STEPParser/STEPFileEncoding.cpp diff --git a/code/Importer/IFC/STEPFileEncoding.h b/code/Importer/STEPParser/STEPFileEncoding.h similarity index 100% rename from code/Importer/IFC/STEPFileEncoding.h rename to code/Importer/STEPParser/STEPFileEncoding.h diff --git a/code/Importer/IFC/STEPFileReader.cpp b/code/Importer/STEPParser/STEPFileReader.cpp similarity index 100% rename from code/Importer/IFC/STEPFileReader.cpp rename to code/Importer/STEPParser/STEPFileReader.cpp diff --git a/code/Importer/IFC/STEPFileReader.h b/code/Importer/STEPParser/STEPFileReader.h similarity index 100% rename from code/Importer/IFC/STEPFileReader.h rename to code/Importer/STEPParser/STEPFileReader.h diff --git a/code/Importer/StepFile/StepFileImporter.cpp b/code/Importer/StepFile/StepFileImporter.cpp index 9a34a84f5..9bfaf7051 100644 --- a/code/Importer/StepFile/StepFileImporter.cpp +++ b/code/Importer/StepFile/StepFileImporter.cpp @@ -44,7 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_STEPFILE_IMPORTER #include "StepFileImporter.h" -#include "../../Importer/IFC/STEPFileReader.h" +#include "../../Importer/STEPParser/STEPFileReader.h" #include #include From 396b518ecb82bb52b1ec4ef6b09ee258a9efe9fd Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 25 Nov 2018 20:16:49 +0100 Subject: [PATCH 033/472] Update Build.md Some doc improvements. --- Build.md | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/Build.md b/Build.md index 418749a0f..5f352c8a3 100644 --- a/Build.md +++ b/Build.md @@ -1,5 +1,5 @@ # Install CMake -Asset-Importer-Lib supports a lot of different OSes and platforms. We are using cmake to generate the build environment for these via cmake. So you have to make sure that you have a working cmake-installation on your system. You can download it at https://cmake.org/ +Asset-Importer-Lib can be buildfor a lot of different OS'es and platforms. We are using cmake to generate the build environment for these via cmake. So you have to make sure that you have a working cmake-installation on your system. You can download it at https://cmake.org/ # Get the source Make sure you have a working git-installation. Open a command prompt and clone the Asset-Importer-Lib via: @@ -22,33 +22,35 @@ See https://stackoverflow.com/questions/40803170/cmake-uwp-using-cmake-to-build- # Build instrcutions for Linux / Unix -Open a terminal and got to your repository. You can generate the projectfiles and build the library via: +Open a terminal and got to your repository. You can generate the makefiles and build the library via: ``` cmake CMakeLists.txt make -j4 ``` -The option -j descripes the number of parallel processes for the build. +The option -j descripes the number of parallel processes for the build. In this case make will try to use 4 cores for the build. + +If you want to use a IDE for linux you can try QTCreator for instance. # CMake build options The cmake-build-environment provides options to configure the build. The following options can be used: -- BUILD_SHARED_LIBS ( default ON ): Generation of shared libs ( dll for windows, so for Linux ). Set this to OFF to get a static lib. -- BUILD_FRAMEWORK ( default OFF, MacOnly): Build package as Mac OS X Framework bundle -- ASSIMP_DOUBLE_PRECISION( default OFF ): All data will be stored as double values. -- ASSIMP_OPT_BUILD_PACKAGES ( default OFF): Set to ON to generate CPack configuration files and packaging targets -- ASSIMP_ANDROID_JNIIOSYSTEM ( default OFF ): Android JNI IOSystem support is active -- ASSIMP_NO_EXPORT ( default OFF ): Disable Assimp's export functionality -- ASSIMP_BUILD_ZLIB ( default OFF ): Build your own zlib -- ASSIMP_BUILD_ASSIMP_TOOLS ( default ON ): If the supplementary tools for Assimp are built in addition to the library. -- ASSIMP_BUILD_SAMPLES ( default OFF ): If the official samples are built as well (needs Glut). -- ASSIMP_BUILD_TESTS ( default ON ): If the test suite for Assimp is built in addition to the library. -- ASSIMP_COVERALLS ( default OFF ): Enable this to measure test coverage. -- ASSIMP_WERROR( default OFF ): Treat warnings as errors. -- ASSIMP_ASAN ( default OFF ): Enable AddressSanitizer. -- ASSIMP_UBSAN ( default OFF ): Enable Undefined Behavior sanitizer. -- SYSTEM_IRRXML ( default OFF ): Use system installed Irrlicht/IrrXML library. -- BUILD_DOCS ( default OFF ): Build documentation using Doxygen. -- INJECT_DEBUG_POSTFIX( default ON ): Inject debug postfix in .a/.so lib names -- IGNORE_GIT_HASH ( default OFF ): Don't call git to get the hash. -- ASSIMP_INSTALL_PDB ( default ON ): Install MSVC debug files. +- **BUILD_SHARED_LIBS ( default ON )**: Generation of shared libs ( dll for windows, so for Linux ). Set this to OFF to get a static lib. +- **BUILD_FRAMEWORK ( default OFF, MacOnly)**: Build package as Mac OS X Framework bundle +- **ASSIMP_DOUBLE_PRECISION( default OFF )**: All data will be stored as double values. +- **ASSIMP_OPT_BUILD_PACKAGES ( default OFF)**: Set to ON to generate CPack configuration files and packaging targets +- **ASSIMP_ANDROID_JNIIOSYSTEM ( default OFF )**: Android JNI IOSystem support is active +- **ASSIMP_NO_EXPORT ( default OFF )**: Disable Assimp's export functionality +- **ASSIMP_BUILD_ZLIB ( default OFF )**: Build your own zlib +- **ASSIMP_BUILD_ASSIMP_TOOLS ( default ON )**: If the supplementary tools for Assimp are built in addition to the library. +- **ASSIMP_BUILD_SAMPLES ( default OFF )**: If the official samples are built as well (needs Glut). +- **ASSIMP_BUILD_TESTS ( default ON )**: If the test suite for Assimp is built in addition to the library. +- **ASSIMP_COVERALLS ( default OFF )**: Enable this to measure test coverage. +- **ASSIMP_WERROR( default OFF )**: Treat warnings as errors. +- **ASSIMP_ASAN ( default OFF )**: Enable AddressSanitizer. +- **ASSIMP_UBSAN ( default OFF )**: Enable Undefined Behavior sanitizer. +- **SYSTEM_IRRXML ( default OFF )**: Use system installed Irrlicht/IrrXML library. +- **BUILD_DOCS ( default OFF )**: Build documentation using Doxygen. +- **INJECT_DEBUG_POSTFIX( default ON )**: Inject debug postfix in .a/.so lib names +- **IGNORE_GIT_HASH ( default OFF )**: Don't call git to get the hash. +- **ASSIMP_INSTALL_PDB ( default ON )**: Install MSVC debug files. From 4231844647d675feff0d368edcbfb3c1d5c7dbe6 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 25 Nov 2018 20:56:28 +0100 Subject: [PATCH 034/472] Update Build.md Fix typos and try to make build doc more explicit. --- Build.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Build.md b/Build.md index 5f352c8a3..d5b443a79 100644 --- a/Build.md +++ b/Build.md @@ -1,5 +1,8 @@ # Install CMake -Asset-Importer-Lib can be buildfor a lot of different OS'es and platforms. We are using cmake to generate the build environment for these via cmake. So you have to make sure that you have a working cmake-installation on your system. You can download it at https://cmake.org/ +Asset-Importer-Lib can be build for a lot of different platforms. We are using cmake to generate the build environment for these via cmake. So you have to make sure that you have a working cmake-installation on your system. You can download it at https://cmake.org/ or for linux install it via +``` +sudo apt-get install cmake +``` # Get the source Make sure you have a working git-installation. Open a command prompt and clone the Asset-Importer-Lib via: @@ -11,11 +14,10 @@ git clone https://github.com/assimp/assimp.git First you have to install Visual-Studio on your windows-system. You can get the Community-Version for free here: https://visualstudio.microsoft.com/de/downloads/ To generate the build environment for your IDE open a command prompt, navigate to your repo and type: - ``` > cmake CMakeLists.txt ``` -This will generate the project files. +This will generate the project files for the visual studio. All dependencies used to build Asset-IMporter-Lib shall be part of the repo. If you want to use you own zlib.installation this is possible as well. Check the options for it. # Build instructions for Windows with UWP See https://stackoverflow.com/questions/40803170/cmake-uwp-using-cmake-to-build-universal-windows-app From e8e8578d7f942bb9754d6de19bc31e45e41182cf Mon Sep 17 00:00:00 2001 From: Martin Jerabek Date: Sun, 16 Aug 2015 18:08:19 +0200 Subject: [PATCH 035/472] assimp_cmd: fix writing compressed binary assimp format Also print someting to console when compression fails. --- tools/assimp_cmd/WriteDumb.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/assimp_cmd/WriteDumb.cpp b/tools/assimp_cmd/WriteDumb.cpp index 3fbfab824..b05adf249 100644 --- a/tools/assimp_cmd/WriteDumb.cpp +++ b/tools/assimp_cmd/WriteDumb.cpp @@ -82,15 +82,18 @@ void CompressBinaryDump(const char* file, unsigned int head_size) uint8_t* data = new uint8_t[size]; fread(data,1,size,p); - uLongf out_size = (uLongf)((size-head_size) * 1.001 + 12.); + uint32_t uncompressed_size = size-head_size; + uLongf out_size = (uLongf)compressBound(uncompressed_size); uint8_t* out = new uint8_t[out_size]; - compress2(out,&out_size,data+head_size,size-head_size,9); + int res = compress2(out,&out_size,data+head_size,uncompressed_size,9); + if(res != Z_OK) + fprintf(stderr, "compress2: error\n"); fclose(p); p = fopen(file,"w"); fwrite(data,head_size,1,p); - fwrite(&out_size,4,1,p); // write size of uncompressed data + fwrite(&uncompressed_size,4,1,p); // write size of uncompressed data fwrite(out,out_size,1,p); fclose(p); From 66599b63920551d88c48d03df54f609cce7f61fb Mon Sep 17 00:00:00 2001 From: Martin Jerabek Date: Sun, 16 Aug 2015 18:10:11 +0200 Subject: [PATCH 036/472] Assbin: fix loading/exporting compressed format --- code/AssbinExporter.cpp | 12 +++++++++--- code/AssbinLoader.cpp | 12 ++++++++++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/code/AssbinExporter.cpp b/code/AssbinExporter.cpp index d64b5c1de..f49389f78 100644 --- a/code/AssbinExporter.cpp +++ b/code/AssbinExporter.cpp @@ -89,7 +89,7 @@ size_t Write(IOStream * stream, const unsigned int& w) { const uint32_t t = (uint32_t)w; if (w > t) { // this shouldn't happen, integers in Assimp data structures never exceed 2^32 - throw new DeadlyExportError("loss of data due to 64 -> 32 bit integer conversion"); + throw DeadlyExportError("loss of data due to 64 -> 32 bit integer conversion"); } stream->Write(&t,4,1); @@ -805,10 +805,16 @@ public: WriteBinaryScene( &uncompressedStream, pScene ); uLongf uncompressedSize = static_cast(uncompressedStream.Tell()); - uLongf compressedSize = (uLongf)(uncompressedStream.Tell() * 1.001 + 12.); + uLongf compressedSize = (uLongf)compressBound(uncompressedSize); uint8_t* compressedBuffer = new uint8_t[ compressedSize ]; - compress2( compressedBuffer, &compressedSize, (const Bytef*)uncompressedStream.GetBufferPointer(), uncompressedSize, 9 ); + int res = compress2( compressedBuffer, &compressedSize, (const Bytef*)uncompressedStream.GetBufferPointer(), uncompressedSize, 9 ); + if(res != Z_OK) + { + delete [] compressedBuffer; + pIOSystem->Close(out); + throw DeadlyExportError("Compression failed."); + } out->Write( &uncompressedSize, sizeof(uint32_t), 1 ); out->Write( compressedBuffer, sizeof(char), compressedSize ); diff --git a/code/AssbinLoader.cpp b/code/AssbinLoader.cpp index 81c77f3fa..ad91ce043 100644 --- a/code/AssbinLoader.cpp +++ b/code/AssbinLoader.cpp @@ -701,11 +701,19 @@ void AssbinImporter::InternReadFile( const std::string& pFile, aiScene* pScene, uLongf compressedSize = static_cast(stream->FileSize() - stream->Tell()); unsigned char * compressedData = new unsigned char[ compressedSize ]; - stream->Read( compressedData, 1, compressedSize ); + size_t len = stream->Read( compressedData, 1, compressedSize ); + ai_assert(len == compressedSize); unsigned char * uncompressedData = new unsigned char[ uncompressedSize ]; - uncompress( uncompressedData, &uncompressedSize, compressedData, compressedSize ); + int res = uncompress( uncompressedData, &uncompressedSize, compressedData, len ); + if(res != Z_OK) + { + delete [] uncompressedData; + delete [] compressedData; + pIOHandler->Close(stream); + throw DeadlyImportError("Zlib decompression failed."); + } MemoryIOStream io( uncompressedData, uncompressedSize ); From 430fe98c5367538f415b2e438bda481a98e14371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Je=C5=99=C3=A1bek?= Date: Thu, 22 Nov 2018 11:45:52 +0100 Subject: [PATCH 037/472] AssbinLoader: hardening, exception safety Fixes potential memory leaks and crashes on malformed input. --- code/AssbinLoader.cpp | 117 ++++++++++++++++--------------- include/assimp/MemoryIOWrapper.h | 3 +- 2 files changed, 61 insertions(+), 59 deletions(-) diff --git a/code/AssbinLoader.cpp b/code/AssbinLoader.cpp index ad91ce043..415d3576c 100644 --- a/code/AssbinLoader.cpp +++ b/code/AssbinLoader.cpp @@ -57,6 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #ifdef ASSIMP_BUILD_NO_OWN_ZLIB # include @@ -103,7 +104,9 @@ bool AssbinImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bo template T Read(IOStream * stream) { T t; - stream->Read( &t, sizeof(T), 1 ); + size_t res = stream->Read( &t, sizeof(T), 1 ); + if(res != 1) + throw DeadlyImportError("Unexpected EOF"); return t; } @@ -144,7 +147,8 @@ template <> aiString Read(IOStream * stream) { aiString s; stream->Read(&s.length,4,1); - stream->Read(s.data,s.length,1); + if(s.length) + stream->Read(s.data,s.length,1); s.data[s.length] = 0; return s; } @@ -207,46 +211,48 @@ void ReadBounds( IOStream * stream, T* /*p*/, unsigned int n ) { } // ----------------------------------------------------------------------------------- -void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node, aiNode* parent ) { - uint32_t chunkID = Read(stream); - (void)(chunkID); - ai_assert(chunkID == ASSBIN_CHUNK_AINODE); +void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** onode, aiNode* parent ) { + if(Read(stream) != ASSBIN_CHUNK_AINODE) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); - *node = new aiNode(); + std::unique_ptr node(new aiNode()); - (*node)->mName = Read(stream); - (*node)->mTransformation = Read(stream); - (*node)->mNumChildren = Read(stream); - (*node)->mNumMeshes = Read(stream); + node->mName = Read(stream); + node->mTransformation = Read(stream); + unsigned numChildren = Read(stream); + unsigned numMeshes = Read(stream); unsigned int nb_metadata = Read(stream); if(parent) { - (*node)->mParent = 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 (numMeshes) + { + node->mMeshes = new unsigned int[numMeshes]; + for (unsigned int i = 0; i < numMeshes; ++i) { + node->mMeshes[i] = Read(stream); + node->mNumMeshes++; } } - if ((*node)->mNumChildren) { - (*node)->mChildren = new aiNode*[(*node)->mNumChildren]; - for (unsigned int i = 0; i < (*node)->mNumChildren; ++i) { - ReadBinaryNode( stream, &(*node)->mChildren[i], *node ); + if (numChildren) { + node->mChildren = new aiNode*[numChildren]; + for (unsigned int i = 0; i < numChildren; ++i) { + ReadBinaryNode( stream, &node->mChildren[i], node.get() ); } } + *onode = node.release(); if ( nb_metadata > 0 ) { - (*node)->mMetaData = aiMetadata::Alloc(nb_metadata); + 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 ); + node->mMetaData->mKeys[i] = Read(stream); + node->mMetaData->mValues[i].mType = (aiMetadataType) Read(stream); + void* data = nullptr; - switch ((*node)->mMetaData->mValues[i].mType) { + switch (node->mMetaData->mValues[i].mType) { case AI_BOOL: data = new bool(Read(stream)); break; @@ -275,16 +281,15 @@ void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node, aiNode* p break; } - (*node)->mMetaData->mValues[i].mData = data; + 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); + if(Read(stream) != ASSBIN_CHUNK_AIBONE) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); b->mName = Read(stream); @@ -306,12 +311,10 @@ void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b ) { static bool fitsIntoUI16(unsigned int mNumVertices) { return ( mNumVertices < (1u<<16) ); } - // ----------------------------------------------------------------------------------- void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) { - uint32_t chunkID = Read(stream); - (void)(chunkID); - ai_assert(chunkID == ASSBIN_CHUNK_AIMESH); + if(Read(stream) != ASSBIN_CHUNK_AIMESH) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); mesh->mPrimitiveTypes = Read(stream); @@ -423,9 +426,8 @@ 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); + if(Read(stream) != ASSBIN_CHUNK_AIMATERIALPROPERTY) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); prop->mKey = Read(stream); @@ -440,9 +442,8 @@ 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); + if(Read(stream) != ASSBIN_CHUNK_AIMATERIAL) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); mat->mNumAllocated = mat->mNumProperties = Read(stream); @@ -462,9 +463,8 @@ 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); + if(Read(stream) != ASSBIN_CHUNK_AINODEANIM) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); nd->mNodeName = Read(stream); @@ -508,9 +508,8 @@ 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); + if(Read(stream) != ASSBIN_CHUNK_AIANIMATION) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); anim->mName = Read (stream); @@ -529,9 +528,8 @@ 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); + if(Read(stream) != ASSBIN_CHUNK_AITEXTURE) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); tex->mWidth = Read(stream); @@ -551,9 +549,8 @@ 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); + if(Read(stream) != ASSBIN_CHUNK_AILIGHT) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); l->mName = Read(stream); @@ -577,9 +574,8 @@ 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); + if(Read(stream) != ASSBIN_CHUNK_AICAMERA) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); cam->mName = Read(stream); @@ -594,9 +590,8 @@ 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); + if(Read(stream) != ASSBIN_CHUNK_AISCENE) + throw DeadlyImportError("Magic chunk identifiers are wrong!"); /*uint32_t size =*/ Read(stream); scene->mFlags = Read(stream); @@ -614,6 +609,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) { // Read all meshes if (scene->mNumMeshes) { scene->mMeshes = new aiMesh*[scene->mNumMeshes]; + memset(scene->mMeshes, 0, scene->mNumMeshes*sizeof(aiMesh*)); for (unsigned int i = 0; i < scene->mNumMeshes;++i) { scene->mMeshes[i] = new aiMesh(); ReadBinaryMesh( stream,scene->mMeshes[i]); @@ -623,6 +619,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) { // Read materials if (scene->mNumMaterials) { scene->mMaterials = new aiMaterial*[scene->mNumMaterials]; + memset(scene->mMaterials, 0, scene->mNumMaterials*sizeof(aiMaterial*)); for (unsigned int i = 0; i< scene->mNumMaterials; ++i) { scene->mMaterials[i] = new aiMaterial(); ReadBinaryMaterial(stream,scene->mMaterials[i]); @@ -632,6 +629,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) { // Read all animations if (scene->mNumAnimations) { scene->mAnimations = new aiAnimation*[scene->mNumAnimations]; + memset(scene->mAnimations, 0, scene->mNumAnimations*sizeof(aiAnimation*)); for (unsigned int i = 0; i < scene->mNumAnimations;++i) { scene->mAnimations[i] = new aiAnimation(); ReadBinaryAnim(stream,scene->mAnimations[i]); @@ -641,6 +639,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) { // Read all textures if (scene->mNumTextures) { scene->mTextures = new aiTexture*[scene->mNumTextures]; + memset(scene->mTextures, 0, scene->mNumTextures*sizeof(aiTexture*)); for (unsigned int i = 0; i < scene->mNumTextures;++i) { scene->mTextures[i] = new aiTexture(); ReadBinaryTexture(stream,scene->mTextures[i]); @@ -650,6 +649,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) { // Read lights if (scene->mNumLights) { scene->mLights = new aiLight*[scene->mNumLights]; + memset(scene->mLights, 0, scene->mNumLights*sizeof(aiLight*)); for (unsigned int i = 0; i < scene->mNumLights;++i) { scene->mLights[i] = new aiLight(); ReadBinaryLight(stream,scene->mLights[i]); @@ -659,6 +659,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) { // Read cameras if (scene->mNumCameras) { scene->mCameras = new aiCamera*[scene->mNumCameras]; + memset(scene->mCameras, 0, scene->mNumCameras*sizeof(aiCamera*)); for (unsigned int i = 0; i < scene->mNumCameras;++i) { scene->mCameras[i] = new aiCamera(); ReadBinaryCamera(stream,scene->mCameras[i]); @@ -675,7 +676,7 @@ void AssbinImporter::InternReadFile( const std::string& pFile, aiScene* pScene, } // signature - stream->Seek( 44, aiOrigin_CUR ); + stream->Seek( 44, aiOrigin_CUR ); unsigned int versionMajor = Read(stream); unsigned int versionMinor = Read(stream); diff --git a/include/assimp/MemoryIOWrapper.h b/include/assimp/MemoryIOWrapper.h index bfcfff9c2..54d89aa64 100644 --- a/include/assimp/MemoryIOWrapper.h +++ b/include/assimp/MemoryIOWrapper.h @@ -80,7 +80,8 @@ public: // ------------------------------------------------------------------- // Read from stream size_t Read(void* pvBuffer, size_t pSize, size_t pCount) { - const size_t cnt = std::min(pCount,(length-pos)/pSize),ofs = pSize*cnt; + ai_assert(pvBuffer && pSize); + const size_t cnt = std::min(pCount,(length-pos)/pSize), ofs = pSize*cnt; memcpy(pvBuffer,buffer+pos,ofs); pos += ofs; From 6e95601875c0782fc68ffc0f93f8bb57cdbf217c Mon Sep 17 00:00:00 2001 From: Martin Jerabek Date: Sat, 12 Mar 2016 18:36:05 +0100 Subject: [PATCH 038/472] OpenDDLParserUtils: replace chartype_table with simple comparison --- .../openddlparser/OpenDDLParserUtils.h | 24 +------------------ 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h b/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h index 64897436e..f0762ac67 100644 --- a/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h +++ b/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h @@ -59,32 +59,10 @@ bool isSeparator( T in ) { return false; } -static const unsigned char chartype_table[ 256 ] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0-15 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32-47 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 48-63 - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 64-79 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80-95 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 96-111 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 112-127 - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // > 127 - 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, -}; - template inline bool isNumeric( const T in ) { - return ( chartype_table[ static_cast( in ) ] == 1 ); + return ( in >= '0' && in <= '9' ); } template From a7cbb4386ca487687d6d3f5bf1103a1c5f1dc03a Mon Sep 17 00:00:00 2001 From: Martin Jerabek Date: Sat, 12 Mar 2016 19:00:52 +0100 Subject: [PATCH 039/472] 3DSLoader: exception-safety Fixes memory leaks and/or crashes on malformed input. --- code/3DSLoader.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/code/3DSLoader.cpp b/code/3DSLoader.cpp index cd79b0a6d..34066e44b 100644 --- a/code/3DSLoader.cpp +++ b/code/3DSLoader.cpp @@ -161,19 +161,21 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { StreamReaderLE stream(pIOHandler->Open(pFile,"rb")); - this->stream = &stream; // We should have at least one chunk if (stream.GetRemainingSize() < 16) { throw DeadlyImportError("3DS file is either empty or corrupt: " + pFile); } + this->stream = &stream; // Allocate our temporary 3DS representation - mScene = new D3DS::Scene(); + D3DS::Scene _scene; + mScene = &_scene; // Initialize members + D3DS::Node _rootNode("UNNAMED"); mLastNodeIndex = -1; - mCurrentNode = new D3DS::Node("UNNAMED"); + mCurrentNode = &_rootNode; mRootNode = mCurrentNode; mRootNode->mHierarchyPos = -1; mRootNode->mHierarchyIndex = -1; @@ -193,7 +195,6 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile, // file. for (auto &mesh : mScene->mMeshes) { if (mesh.mFaces.size() > 0 && mesh.mPositions.size() == 0) { - delete mScene; throw DeadlyImportError("3DS file contains faces but no vertices: " + pFile); } CheckIndices(mesh); @@ -201,7 +202,7 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile, ComputeNormalsWithSmoothingsGroups(mesh); } - // Replace all occurrences of the default material with a + // Replace all occurences of the default material with a // valid material. Generate it if no material containing // DEFAULT in its name has been found in the file ReplaceDefaultMaterial(); @@ -218,10 +219,8 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile, // Now apply the master scaling factor to the scene ApplyMasterScale(pScene); - // Delete our internal scene representation and the root - // node, so the whole hierarchy will follow - delete mRootNode; - delete mScene; + // Our internal scene representation and the root + // node will be automatically deleted, so the whole hierarchy will follow AI_DEBUG_INVALIDATE_PTR(mRootNode); AI_DEBUG_INVALIDATE_PTR(mScene); From 65a79029ecbfe73cc761129ab9c4c4a64f0fcdca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Je=C5=99=C3=A1bek?= Date: Thu, 22 Nov 2018 12:12:57 +0100 Subject: [PATCH 040/472] eliminate some compiler warnings by making copy constructors implicitly defaulted Addresses #2222 --- include/assimp/color4.h | 3 +-- include/assimp/vector2.h | 2 +- include/assimp/vector3.h | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/include/assimp/color4.h b/include/assimp/color4.h index 570b8f44c..9de275af1 100644 --- a/include/assimp/color4.h +++ b/include/assimp/color4.h @@ -63,8 +63,7 @@ public: aiColor4t (TReal _r, TReal _g, TReal _b, TReal _a) : r(_r), g(_g), b(_b), a(_a) {} explicit aiColor4t (TReal _r) : r(_r), g(_r), b(_r), a(_r) {} - aiColor4t (const aiColor4t& o) - : r(o.r), g(o.g), b(o.b), a(o.a) {} + // aiColor4t (const aiColor4t& o) = default; public: // combined operators diff --git a/include/assimp/vector2.h b/include/assimp/vector2.h index d290945c9..2da60c982 100644 --- a/include/assimp/vector2.h +++ b/include/assimp/vector2.h @@ -69,7 +69,7 @@ public: aiVector2t () : x(), y() {} aiVector2t (TReal _x, TReal _y) : x(_x), y(_y) {} explicit aiVector2t (TReal _xyz) : x(_xyz), y(_xyz) {} - aiVector2t (const aiVector2t& o) : x(o.x), y(o.y) {} + // aiVector2t (const aiVector2t& o) = default; public: diff --git a/include/assimp/vector3.h b/include/assimp/vector3.h index 2c610b3a9..3bc176451 100644 --- a/include/assimp/vector3.h +++ b/include/assimp/vector3.h @@ -69,7 +69,7 @@ public: aiVector3t() AI_NO_EXCEPT : 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( const aiVector3t& o ) = default; public: From a916c7b1e3c13d26a6e8c4fabb09161555f7a217 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Je=C5=99=C3=A1bek?= Date: Thu, 22 Nov 2018 12:46:02 +0100 Subject: [PATCH 041/472] ensure that GitVersion fits into 32 bits --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ade45f719..645d92689 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -170,7 +170,7 @@ IF(NOT IGNORE_GIT_HASH) # Get the latest abbreviated commit hash of the working branch EXECUTE_PROCESS( - COMMAND git log -1 --format=%h --no-show-signature + COMMAND git rev-parse --short=8 HEAD WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE GIT_COMMIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE From 770356a55b42557d4126c48e57613037866a4570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Je=C5=99=C3=A1bek?= Date: Mon, 26 Nov 2018 15:10:48 +0100 Subject: [PATCH 042/472] AssbinLoader: fix setting mNumChildren and releasing the smart pointer --- code/AssbinLoader.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/AssbinLoader.cpp b/code/AssbinLoader.cpp index 415d3576c..321a0cfec 100644 --- a/code/AssbinLoader.cpp +++ b/code/AssbinLoader.cpp @@ -241,9 +241,9 @@ void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** onode, aiNode* node->mChildren = new aiNode*[numChildren]; for (unsigned int i = 0; i < numChildren; ++i) { ReadBinaryNode( stream, &node->mChildren[i], node.get() ); + node->mNumChildren++; } } - *onode = node.release(); if ( nb_metadata > 0 ) { node->mMetaData = aiMetadata::Alloc(nb_metadata); @@ -284,6 +284,7 @@ void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** onode, aiNode* node->mMetaData->mValues[i].mData = data; } } + *onode = node.release(); } // ----------------------------------------------------------------------------------- From 0bb672c6fa9e2dbdabbcd9d7294caab406d9ea81 Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Tue, 27 Nov 2018 11:45:53 +0000 Subject: [PATCH 043/472] Fix scenes not always being loaded --- code/glTF2Asset.inl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 687e16ce1..ed37937f4 100755 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -1357,6 +1357,13 @@ inline void Asset::Load(const std::string& pFile, bool isBinary) } } + // Force reading of skins since they're not always directly referenced + if (Value* skinsArray = FindArray(doc, "skins")) { + for (unsigned int i = 0; i < skinsArray->Size(); ++i) { + skins.Retrieve(i); + } + } + if (Value* animsArray = FindArray(doc, "animations")) { for (unsigned int i = 0; i < animsArray->Size(); ++i) { animations.Retrieve(i); From ccea70c61f027c9f1811c1c3862a05e022beed4a Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Tue, 27 Nov 2018 11:49:00 +0000 Subject: [PATCH 044/472] Calculate the mMaxDuration property based off of keyframes --- code/glTF2Importer.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index e8d2a2d95..ff9fd4269 100755 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -1022,6 +1022,26 @@ void glTF2Importer::ImportAnimations(glTF2::Asset& r) ++j; } } + + // Use the latest keyframe for the duration of the animation + unsigned int maxDuration = 0; + for (unsigned int j = 0; j < ai_anim->mNumChannels; ++j) { + auto chan = ai_anim->mChannels[j]; + if (chan->mNumPositionKeys) { + auto lastPosKey = chan->mPositionKeys[chan->mNumPositionKeys - 1]; + if (lastPosKey.mTime > maxDuration) maxDuration = lastPosKey.mTime; + } + if (chan->mNumRotationKeys) { + auto lastRotKey = chan->mRotationKeys[chan->mNumRotationKeys - 1]; + if (lastRotKey.mTime > maxDuration) maxDuration = lastRotKey.mTime; + } + if (chan->mNumScalingKeys) { + auto lastScaleKey = chan->mScalingKeys[chan->mNumScalingKeys - 1]; + if (lastScaleKey.mTime > maxDuration) maxDuration = lastScaleKey.mTime; + } + } + ai_anim->mDuration = maxDuration; + mScene->mAnimations[i] = ai_anim; } } From 657014dff6a493783b17317031f0ca6fa2e4e1bc Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 27 Nov 2018 20:18:00 +0100 Subject: [PATCH 045/472] Update glTF2Asset.inl Fix possible nullptr-dereferencing. --- code/glTF2Asset.inl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index ed37937f4..f8955d6d2 100755 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -1359,9 +1359,11 @@ inline void Asset::Load(const std::string& pFile, bool isBinary) // Force reading of skins since they're not always directly referenced if (Value* skinsArray = FindArray(doc, "skins")) { - for (unsigned int i = 0; i < skinsArray->Size(); ++i) { - skins.Retrieve(i); - } + if ( nullptr != skinsArray ) { + for (unsigned int i = 0; i < skinsArray->Size(); ++i) { + skins.Retrieve(i); + } + } } if (Value* animsArray = FindArray(doc, "animations")) { From 47e3301c4768de184fc031e18dfcca00dfc9f0c0 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 27 Nov 2018 23:22:09 +0100 Subject: [PATCH 046/472] Update glTF2Asset.inl Remove my nonsense, sorry! --- code/glTF2Asset.inl | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index f8955d6d2..ed37937f4 100755 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -1359,11 +1359,9 @@ inline void Asset::Load(const std::string& pFile, bool isBinary) // Force reading of skins since they're not always directly referenced if (Value* skinsArray = FindArray(doc, "skins")) { - if ( nullptr != skinsArray ) { - for (unsigned int i = 0; i < skinsArray->Size(); ++i) { - skins.Retrieve(i); - } - } + for (unsigned int i = 0; i < skinsArray->Size(); ++i) { + skins.Retrieve(i); + } } if (Value* animsArray = FindArray(doc, "animations")) { From 4f767ecd13d1f6f6bd0406e59816ad0dcd2642b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Je=C5=99=C3=A1bek?= Date: Wed, 28 Nov 2018 14:19:46 +0100 Subject: [PATCH 047/472] Apply suggestions from code review * make the copy constructors explicitly defaulted * split compound assert --- include/assimp/MemoryIOWrapper.h | 3 ++- include/assimp/color4.h | 2 +- include/assimp/vector2.h | 2 +- include/assimp/vector3.h | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/assimp/MemoryIOWrapper.h b/include/assimp/MemoryIOWrapper.h index 54d89aa64..5260cb2b2 100644 --- a/include/assimp/MemoryIOWrapper.h +++ b/include/assimp/MemoryIOWrapper.h @@ -80,7 +80,8 @@ public: // ------------------------------------------------------------------- // Read from stream size_t Read(void* pvBuffer, size_t pSize, size_t pCount) { - ai_assert(pvBuffer && pSize); + ai_assert(pvBuffer); + ai_assert(pSize); const size_t cnt = std::min(pCount,(length-pos)/pSize), ofs = pSize*cnt; memcpy(pvBuffer,buffer+pos,ofs); diff --git a/include/assimp/color4.h b/include/assimp/color4.h index 9de275af1..fddd1b638 100644 --- a/include/assimp/color4.h +++ b/include/assimp/color4.h @@ -63,7 +63,7 @@ public: aiColor4t (TReal _r, TReal _g, TReal _b, TReal _a) : r(_r), g(_g), b(_b), a(_a) {} explicit aiColor4t (TReal _r) : r(_r), g(_r), b(_r), a(_r) {} - // aiColor4t (const aiColor4t& o) = default; + aiColor4t (const aiColor4t& o) = default; public: // combined operators diff --git a/include/assimp/vector2.h b/include/assimp/vector2.h index 2da60c982..68eee081f 100644 --- a/include/assimp/vector2.h +++ b/include/assimp/vector2.h @@ -69,7 +69,7 @@ public: aiVector2t () : x(), y() {} aiVector2t (TReal _x, TReal _y) : x(_x), y(_y) {} explicit aiVector2t (TReal _xyz) : x(_xyz), y(_xyz) {} - // aiVector2t (const aiVector2t& o) = default; + aiVector2t (const aiVector2t& o) = default; public: diff --git a/include/assimp/vector3.h b/include/assimp/vector3.h index 3bc176451..33ae7d22f 100644 --- a/include/assimp/vector3.h +++ b/include/assimp/vector3.h @@ -69,7 +69,7 @@ public: aiVector3t() AI_NO_EXCEPT : 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 ) = default; + aiVector3t( const aiVector3t& o ) = default; public: From ef151b46100238dc491b09e0d645973ce1fc8c81 Mon Sep 17 00:00:00 2001 From: wxyu <157348532@qq.com> Date: Tue, 27 Nov 2018 13:28:42 +0800 Subject: [PATCH 048/472] Smd loads a single animation file Can't load without mesh before --- code/SMDLoader.cpp | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/code/SMDLoader.cpp b/code/SMDLoader.cpp index dc6706934..4668da0f1 100644 --- a/code/SMDLoader.cpp +++ b/code/SMDLoader.cpp @@ -81,7 +81,7 @@ SMDImporter::SMDImporter() mBuffer(), pScene( nullptr ), iFileSize( 0 ), -iSmallestFrame( -1 ), +iSmallestFrame( INT_MAX ), dLengthOfAnim( 0.0 ), bHasUVs(false ), iLineNumber(-1) { @@ -141,7 +141,7 @@ void SMDImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS mBuffer.resize( iFileSize + 1 ); TextFileToBuffer(file.get(), mBuffer ); - iSmallestFrame = (1 << 31); + iSmallestFrame = INT_MAX; bHasUVs = true; iLineNumber = 1; @@ -499,7 +499,7 @@ void SMDImporter::CreateOutputNodes() } // now add all bones as dummy sub nodes to the graph - // AddBoneChildren(pScene->mRootNode,(uint32_t)-1); + AddBoneChildren(pScene->mRootNode,(uint32_t)-1); // if we have only one bone we can even remove the root node if (pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE && @@ -523,26 +523,12 @@ void SMDImporter::CreateOutputNodes() // create output animations void SMDImporter::CreateOutputAnimations() { - unsigned int iNumBones = 0; - for (std::vector::const_iterator - i = asBones.begin(); - i != asBones.end();++i) - { - if ((*i).bIsUsed)++iNumBones; - } - if (!iNumBones) - { - // just make sure this case doesn't occur ... (it could occur - // if the file was invalid) - return; - } - pScene->mNumAnimations = 1; pScene->mAnimations = new aiAnimation*[1]; aiAnimation*& anim = pScene->mAnimations[0] = new aiAnimation(); anim->mDuration = dLengthOfAnim; - anim->mNumChannels = iNumBones; + anim->mNumChannels = asBones.size(); anim->mTicksPerSecond = 25.0; // FIXME: is this correct? aiNodeAnim** pp = anim->mChannels = new aiNodeAnim*[anim->mNumChannels]; @@ -553,8 +539,6 @@ void SMDImporter::CreateOutputAnimations() i = asBones.begin(); i != asBones.end();++i) { - if (!(*i).bIsUsed)continue; - aiNodeAnim* p = pp[a] = new aiNodeAnim(); // copy the name of the bone @@ -865,7 +849,6 @@ void SMDImporter::ParseSkeletonSection(const char* szCurrent, // "time \n" - Specifies the current animation frame else if (TokenMatch(szCurrent,"time",4)) { - // NOTE: The doc says that time values COULD be negative ... if(!ParseSignedInt(szCurrent,&szCurrent,iTime))break; iSmallestFrame = std::min(iSmallestFrame,iTime); @@ -1006,7 +989,8 @@ void SMDImporter::ParseSkeletonElement(const char* szCurrent, mTemp.c4 = vPos.z; key.matrix = key.matrix * mTemp; } - + key.vPos = vPos; + key.vRot = vRot; // go to the beginning of the next line SMDI_PARSE_RETURN; } From 8c2e9755082fd30d6b146471d58bc21cf3622779 Mon Sep 17 00:00:00 2001 From: wxyu <157348532@qq.com> Date: Thu, 29 Nov 2018 10:48:13 +0800 Subject: [PATCH 049/472] Fix smd animation mess aiMatrix4x4t::FromEulerAnglesXYZ modified to row order --- code/MS3DLoader.cpp | 10 +++------- code/SMDLoader.cpp | 5 +++-- include/assimp/matrix4x4.inl | 34 ++++++++++++++++------------------ 3 files changed, 22 insertions(+), 27 deletions(-) diff --git a/code/MS3DLoader.cpp b/code/MS3DLoader.cpp index b06bea31c..c659d2ec7 100644 --- a/code/MS3DLoader.cpp +++ b/code/MS3DLoader.cpp @@ -181,8 +181,7 @@ void MS3DImporter :: CollectChildJoints(const std::vector& joints, ch->mParent = nd; ch->mTransformation = aiMatrix4x4::Translation(joints[i].position,aiMatrix4x4()=aiMatrix4x4())* - // XXX actually, I don't *know* why we need the inverse here. Probably column vs. row order? - aiMatrix4x4().FromEulerAnglesXYZ(joints[i].rotation).Transpose(); + aiMatrix4x4().FromEulerAnglesXYZ(joints[i].rotation); const aiMatrix4x4 abs = absTrafo*ch->mTransformation; for(unsigned int a = 0; a < mScene->mNumMeshes; ++a) { @@ -639,11 +638,8 @@ void MS3DImporter::InternReadFile( const std::string& pFile, aiQuatKey& q = nd->mRotationKeys[nd->mNumRotationKeys++]; q.mTime = (*rot).time*animfps; - - // XXX it seems our matrix&quaternion code has faults in its conversion routines -- - // aiQuaternion(x,y,z) seems to besomething different as quat(matrix.fromeuler(x,y,z)). - q.mValue = aiQuaternion(aiMatrix3x3(aiMatrix4x4().FromEulerAnglesXYZ((*rot).value)* - aiMatrix4x4().FromEulerAnglesXYZ((*it).rotation)).Transpose()); + q.mValue = aiQuaternion(aiMatrix3x3(aiMatrix4x4().FromEulerAnglesXYZ((*it).rotation)* + aiMatrix4x4().FromEulerAnglesXYZ((*rot).value))); } } diff --git a/code/SMDLoader.cpp b/code/SMDLoader.cpp index 4668da0f1..5a0f4e87c 100644 --- a/code/SMDLoader.cpp +++ b/code/SMDLoader.cpp @@ -558,7 +558,8 @@ void SMDImporter::CreateOutputAnimations() pRotKeys->mTime = pVecKeys->mTime = (*qq).dTime; // compute the rotation quaternion from the euler angles - pRotKeys->mValue = aiQuaternion( (*qq).vRot.x, (*qq).vRot.y, (*qq).vRot.z ); + // aiQuaternion: The order of the parameters is yzx? + pRotKeys->mValue = aiQuaternion( (*qq).vRot.y, (*qq).vRot.z, (*qq).vRot.x ); pVecKeys->mValue = (*qq).vPos; ++pVecKeys; ++pRotKeys; @@ -987,7 +988,7 @@ void SMDImporter::ParseSkeletonElement(const char* szCurrent, mTemp.a4 = vPos.x; mTemp.b4 = vPos.y; mTemp.c4 = vPos.z; - key.matrix = key.matrix * mTemp; + key.matrix = mTemp * key.matrix; } key.vPos = vPos; key.vRot = vRot; diff --git a/include/assimp/matrix4x4.inl b/include/assimp/matrix4x4.inl index 9920f0059..680d7666d 100644 --- a/include/assimp/matrix4x4.inl +++ b/include/assimp/matrix4x4.inl @@ -527,27 +527,25 @@ inline aiMatrix4x4t& aiMatrix4x4t::FromEulerAnglesXYZ(TReal x, TRe { aiMatrix4x4t& _this = *this; - TReal cr = std::cos( x ); - TReal sr = std::sin( x ); - TReal cp = std::cos( y ); - TReal sp = std::sin( y ); - TReal cy = std::cos( z ); - TReal sy = std::sin( z ); + TReal cx = std::cos(x); + TReal sx = std::sin(x); + TReal cy = std::cos(y); + TReal sy = std::sin(y); + TReal cz = std::cos(z); + TReal sz = std::sin(z); - _this.a1 = cp*cy ; - _this.a2 = cp*sy; - _this.a3 = -sp ; + // mz*my*mx + _this.a1 = cz * cy; + _this.a2 = cz * sy * sx - sz * cx; + _this.a3 = sz * sx + cz * sy * cx; - TReal srsp = sr*sp; - TReal crsp = cr*sp; + _this.b1 = sz * cy; + _this.b2 = cz * cx + sz * sy * sx; + _this.b3 = sz * sy * cx - cz * sx; - _this.b1 = srsp*cy-cr*sy ; - _this.b2 = srsp*sy+cr*cy ; - _this.b3 = sr*cp ; - - _this.c1 = crsp*cy+sr*sy ; - _this.c2 = crsp*sy-sr*cy ; - _this.c3 = cr*cp ; + _this.c1 = -sy; + _this.c2 = cy * sx; + _this.c3 = cy * cx; return *this; } From 19521d222b905f7420346133116f84031ab962d0 Mon Sep 17 00:00:00 2001 From: wxyu <157348532@qq.com> Date: Fri, 30 Nov 2018 09:47:29 +0800 Subject: [PATCH 050/472] Issue 1117: Smd load multiple animations Read an animation list from a file --- code/SMDLoader.cpp | 177 ++++++++++++++++++++++++++++--------- code/SMDLoader.h | 7 +- include/assimp/config.h.in | 6 ++ 3 files changed, 145 insertions(+), 45 deletions(-) diff --git a/code/SMDLoader.cpp b/code/SMDLoader.cpp index 5a0f4e87c..5fe208422 100644 --- a/code/SMDLoader.cpp +++ b/code/SMDLoader.cpp @@ -58,6 +58,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include +#include + +#ifndef _WIN32 +#define strtok_s strtok_r +#endif using namespace Assimp; @@ -120,43 +126,17 @@ void SMDImporter::SetupProperties(const Importer* pImp) if(static_cast(-1) == configFrameID) { configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0); } + + bLoadAnimationList = pImp->GetPropertyBool(AI_CONFIG_IMPORT_SMD_LOAD_ANIMATION_LIST, true); + noSkeletonMesh = pImp->GetPropertyBool(AI_CONFIG_IMPORT_NO_SKELETON_MESHES, false); } // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. void SMDImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { - std::unique_ptr file( pIOHandler->Open( pFile, "rb")); - - // Check whether we can read from the file - if( file.get() == NULL) { - throw DeadlyImportError( "Failed to open SMD/VTA file " + pFile + "."); - } - - iFileSize = (unsigned int)file->FileSize(); - - // Allocate storage and copy the contents of the file to a memory buffer this->pScene = pScene; - - mBuffer.resize( iFileSize + 1 ); - TextFileToBuffer(file.get(), mBuffer ); - - iSmallestFrame = INT_MAX; - bHasUVs = true; - iLineNumber = 1; - - // Reserve enough space for ... hm ... 10 textures - aszTextures.reserve(10); - - // Reserve enough space for ... hm ... 1000 triangles - asTriangles.reserve(1000); - - // Reserve enough space for ... hm ... 20 bones - asBones.reserve(20); - - - // parse the file ... - ParseFile(); + ReadSmd(pFile, pIOHandler); // If there are no triangles it seems to be an animation SMD, // containing only the animation skeleton. @@ -203,13 +183,13 @@ void SMDImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS CreateOutputMaterials(); } - // build the output animation - CreateOutputAnimations(); - // build output nodes (bones are added as empty dummy nodes) CreateOutputNodes(); - if (pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE) + // build the output animation + CreateOutputAnimations(pFile, pIOHandler); + + if ((pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE) && !noSkeletonMesh) { SkeletonMeshBuilder skeleton(pScene); } @@ -521,12 +501,35 @@ void SMDImporter::CreateOutputNodes() // ------------------------------------------------------------------------------------------------ // create output animations -void SMDImporter::CreateOutputAnimations() +void SMDImporter::CreateOutputAnimations(const std::string &pFile, IOSystem* pIOHandler) { - pScene->mNumAnimations = 1; - pScene->mAnimations = new aiAnimation*[1]; - aiAnimation*& anim = pScene->mAnimations[0] = new aiAnimation(); + std::vector> animFileList; + if (bLoadAnimationList) GetAnimationFileList(pFile, pIOHandler, animFileList); + int animCount = animFileList.size() + 1; + pScene->mNumAnimations = 1; + pScene->mAnimations = new aiAnimation*[animCount]; + memset(pScene->mAnimations, 0, sizeof(aiAnimation*)*animCount); + CreateOutputAnimation(0, ""); + + for (auto &animFile : animFileList) + { + ReadSmd(std::get<1>(animFile), pIOHandler); + if (asBones.empty()) continue; + + FixTimeValues(); + CreateOutputAnimation(pScene->mNumAnimations++, std::get<0>(animFile)); + } +} + +void SMDImporter::CreateOutputAnimation(int index, const std::string &name) +{ + aiAnimation*& anim = pScene->mAnimations[index] = new aiAnimation(); + + if (name.length()) + { + anim->mName.Set(name.c_str()); + } anim->mDuration = dLengthOfAnim; anim->mNumChannels = asBones.size(); anim->mTicksPerSecond = 25.0; // FIXME: is this correct? @@ -536,15 +539,15 @@ void SMDImporter::CreateOutputAnimations() // now build valid keys unsigned int a = 0; for (std::vector::const_iterator - i = asBones.begin(); - i != asBones.end();++i) + i = asBones.begin(); + i != asBones.end(); ++i) { aiNodeAnim* p = pp[a] = new aiNodeAnim(); // copy the name of the bone - p->mNodeName.Set( i->mName); + p->mNodeName.Set(i->mName); - p->mNumRotationKeys = (unsigned int) (*i).sAnim.asKeys.size(); + p->mNumRotationKeys = (unsigned int)(*i).sAnim.asKeys.size(); if (p->mNumRotationKeys) { p->mNumPositionKeys = p->mNumRotationKeys; @@ -552,14 +555,14 @@ void SMDImporter::CreateOutputAnimations() aiQuatKey* pRotKeys = p->mRotationKeys = new aiQuatKey[p->mNumRotationKeys]; for (std::vector::const_iterator - qq = (*i).sAnim.asKeys.begin(); + qq = (*i).sAnim.asKeys.begin(); qq != (*i).sAnim.asKeys.end(); ++qq) { pRotKeys->mTime = pVecKeys->mTime = (*qq).dTime; // compute the rotation quaternion from the euler angles // aiQuaternion: The order of the parameters is yzx? - pRotKeys->mValue = aiQuaternion( (*qq).vRot.y, (*qq).vRot.z, (*qq).vRot.x ); + pRotKeys->mValue = aiQuaternion((*qq).vRot.y, (*qq).vRot.z, (*qq).vRot.x); pVecKeys->mValue = (*qq).vPos; ++pVecKeys; ++pRotKeys; @@ -571,6 +574,56 @@ void SMDImporter::CreateOutputAnimations() } } +void SMDImporter::GetAnimationFileList(const std::string &pFile, IOSystem* pIOHandler, std::vector>& outList) +{ + auto base = DefaultIOSystem::absolutePath(pFile); + auto name = DefaultIOSystem::completeBaseName(pFile); + auto path = base + "/" + name + "_animation.txt"; + + std::unique_ptr file(pIOHandler->Open(path.c_str(), "rb")); + if (file.get() == NULL) return; + + // Allocate storage and copy the contents of the file to a memory buffer + std::vector buf; + size_t fileSize = file->FileSize(); + buf.resize(fileSize + 1); + TextFileToBuffer(file.get(), buf); + + /* + *_animation.txt format: + name path + idle idle.smd + jump anim/jump.smd + walk.smd + ... + */ + std::string animName, animPath; + char *tok1, *tok2; + char *context1, *context2; + + tok1 = strtok_s(&buf[0], "\r\n", &context1); + while (tok1 != NULL) { + tok2 = strtok_s(tok1, " \t", &context2); + if (tok2) + { + char *p = tok2; + tok2 = strtok_s(NULL, " \t", &context2); + if (tok2) + { + animPath = tok2; + animName = p; + } + else // No name + { + animPath = p; + animName = DefaultIOSystem::completeBaseName(animPath); + } + outList.push_back(std::make_tuple(animName, base + "/" + animPath)); + } + tok1 = strtok_s(NULL, "\r\n", &context1); + } +} + // ------------------------------------------------------------------------------------------------ void SMDImporter::ComputeAbsoluteBoneTransformations() { @@ -735,6 +788,42 @@ void SMDImporter::ParseFile() return; } +void SMDImporter::ReadSmd(const std::string &pFile, IOSystem* pIOHandler) +{ + std::unique_ptr file(pIOHandler->Open(pFile, "rb")); + + // Check whether we can read from the file + if (file.get() == NULL) { + throw DeadlyImportError("Failed to open SMD/VTA file " + pFile + "."); + } + + iFileSize = (unsigned int)file->FileSize(); + + // Allocate storage and copy the contents of the file to a memory buffer + mBuffer.resize(iFileSize + 1); + TextFileToBuffer(file.get(), mBuffer); + + iSmallestFrame = INT_MAX; + bHasUVs = true; + iLineNumber = 1; + + // Reserve enough space for ... hm ... 10 textures + aszTextures.reserve(10); + + // Reserve enough space for ... hm ... 1000 triangles + asTriangles.reserve(1000); + + // Reserve enough space for ... hm ... 20 bones + asBones.reserve(20); + + aszTextures.clear(); + asTriangles.clear(); + asBones.clear(); + + // parse the file ... + ParseFile(); +} + // ------------------------------------------------------------------------------------------------ unsigned int SMDImporter::GetTextureIndex(const std::string& filename) { diff --git a/code/SMDLoader.h b/code/SMDLoader.h index 40c08385f..cbf04d9d0 100644 --- a/code/SMDLoader.h +++ b/code/SMDLoader.h @@ -219,6 +219,7 @@ protected: /** Parse the SMD file and create the output scene */ void ParseFile(); + void ReadSmd(const std::string &pFile, IOSystem* pIOHandler); // ------------------------------------------------------------------- /** Parse the triangles section of the SMD file @@ -344,7 +345,9 @@ protected: */ void CreateOutputMeshes(); void CreateOutputNodes(); - void CreateOutputAnimations(); + void CreateOutputAnimations(const std::string &pFile, IOSystem* pIOHandler); + void CreateOutputAnimation(int index, const std::string &name); + void GetAnimationFileList(const std::string &pFile, IOSystem* pIOHandler, std::vector>& outList); void CreateOutputMaterials(); @@ -413,6 +416,8 @@ private: */ unsigned int iLineNumber; + bool bLoadAnimationList = true; + bool noSkeletonMesh = false; }; } // end of namespace Assimp diff --git a/include/assimp/config.h.in b/include/assimp/config.h.in index 8de2ea43e..fd828bc6e 100644 --- a/include/assimp/config.h.in +++ b/include/assimp/config.h.in @@ -673,6 +673,12 @@ enum aiComponent #define AI_CONFIG_IMPORT_SMD_KEYFRAME "IMPORT_SMD_KEYFRAME" #define AI_CONFIG_IMPORT_UNREAL_KEYFRAME "IMPORT_UNREAL_KEYFRAME" +// --------------------------------------------------------------------------- +/** Smd load multiple animations + * + * Property type: bool. Default value: true. + */ +#define AI_CONFIG_IMPORT_SMD_LOAD_ANIMATION_LIST "IMPORT_SMD_LOAD_ANIMATION_LIST" // --------------------------------------------------------------------------- /** @brief Configures the AC loader to collect all surfaces which have the From 9100ca8664e7173cdd329aad00bcb1cb1465cd4f Mon Sep 17 00:00:00 2001 From: wxyu <157348532@qq.com> Date: Fri, 30 Nov 2018 10:02:01 +0800 Subject: [PATCH 051/472] Fix: Smd Cannot read bone names containing spaces --- code/SMDLoader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/SMDLoader.cpp b/code/SMDLoader.cpp index 5fe208422..02ebd9797 100644 --- a/code/SMDLoader.cpp +++ b/code/SMDLoader.cpp @@ -989,7 +989,7 @@ void SMDImporter::ParseNodeInfo(const char* szCurrent, ++szEnd; break; } - else if (IsSpaceOrNewLine(*szEnd)) + else if (!bQuota && IsSpaceOrNewLine(*szEnd)) { iBone = (unsigned int)(szEnd - szCurrent); break; From 276168102244612f2be7dba8f5fc4fdc854c265a Mon Sep 17 00:00:00 2001 From: wxyu <157348532@qq.com> Date: Fri, 30 Nov 2018 14:30:18 +0800 Subject: [PATCH 052/472] Issue 1639: Smd mesh vertex bone assignment bone.mOffsetMatrix not set when bone.iParent == -1 --- code/SMDLoader.cpp | 97 ++++++++++------------------------------------ code/SMDLoader.h | 7 ---- 2 files changed, 20 insertions(+), 84 deletions(-) diff --git a/code/SMDLoader.cpp b/code/SMDLoader.cpp index 02ebd9797..ef3b9b7f8 100644 --- a/code/SMDLoader.cpp +++ b/code/SMDLoader.cpp @@ -169,11 +169,11 @@ void SMDImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS // now fix invalid time values and make sure the animation starts at frame 0 FixTimeValues(); - - // compute absolute bone transformation matrices - // ComputeAbsoluteBoneTransformations(); } + // build output nodes (bones are added as empty dummy nodes) + CreateOutputNodes(); + if (!(pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) { // create output meshes @@ -181,10 +181,13 @@ void SMDImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS // build an output material list CreateOutputMaterials(); - } - // build output nodes (bones are added as empty dummy nodes) - CreateOutputNodes(); + // use root node that renders all meshes + 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; + } // build the output animation CreateOutputAnimations(pFile, pIOHandler); @@ -397,7 +400,7 @@ void SMDImporter::CreateOutputMeshes() for (unsigned int iBone = 0; iBone < asBones.size();++iBone) if (!aaiBones[iBone].empty())++iNum; - if (false && iNum) + if (iNum) { pcMesh->mNumBones = iNum; pcMesh->mBones = new aiBone*[pcMesh->mNumBones]; @@ -456,7 +459,14 @@ void SMDImporter::AddBoneChildren(aiNode* pcNode, uint32_t iParent) pc->mName.Set(bone.mName); // store the local transformation matrix of the bind pose - pc->mTransformation = bone.sAnim.asKeys[bone.sAnim.iFirstTimeKey].matrix; + if (bone.sAnim.asKeys.size()) + pc->mTransformation = bone.sAnim.asKeys[0].matrix; + + if (bone.iParent == -1) + bone.mOffsetMatrix = pc->mTransformation; + else + bone.mOffsetMatrix = asBones[bone.iParent].mOffsetMatrix * pc->mTransformation; + pc->mParent = pcNode; // add children to this node, too @@ -469,17 +479,11 @@ void SMDImporter::AddBoneChildren(aiNode* pcNode, uint32_t iParent) void SMDImporter::CreateOutputNodes() { pScene->mRootNode = new aiNode(); - if (!(pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) - { - // create one root node that renders all meshes - 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; - } // now add all bones as dummy sub nodes to the graph AddBoneChildren(pScene->mRootNode,(uint32_t)-1); + for (auto &bone : asBones) + bone.mOffsetMatrix.Inverse(); // if we have only one bone we can even remove the root node if (pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE && @@ -624,67 +628,6 @@ void SMDImporter::GetAnimationFileList(const std::string &pFile, IOSystem* pIOHa } } -// ------------------------------------------------------------------------------------------------ -void SMDImporter::ComputeAbsoluteBoneTransformations() -{ - // For each bone: determine the key with the lowest time value - // theoretically the SMD format should have all keyframes - // in order. However, I've seen a file where this wasn't true. - for (unsigned int i = 0; i < asBones.size();++i) - { - SMD::Bone& bone = asBones[i]; - - uint32_t iIndex = 0; - double dMin = 10e10; - for (unsigned int i = 0; i < bone.sAnim.asKeys.size();++i) - { - double d = std::min(bone.sAnim.asKeys[i].dTime,dMin); - if (d < dMin) - { - dMin = d; - iIndex = i; - } - } - bone.sAnim.iFirstTimeKey = iIndex; - } - - unsigned int iParent = 0; - while (iParent < asBones.size()) - { - for (unsigned int iBone = 0; iBone < asBones.size();++iBone) - { - SMD::Bone& bone = asBones[iBone]; - - if (iParent == bone.iParent) - { - SMD::Bone& parentBone = asBones[iParent]; - - - uint32_t iIndex = bone.sAnim.iFirstTimeKey; - const aiMatrix4x4& mat = bone.sAnim.asKeys[iIndex].matrix; - aiMatrix4x4& matOut = bone.sAnim.asKeys[iIndex].matrixAbsolute; - - // The same for the parent bone ... - iIndex = parentBone.sAnim.iFirstTimeKey; - const aiMatrix4x4& mat2 = parentBone.sAnim.asKeys[iIndex].matrixAbsolute; - - // Compute the absolute transformation matrix - matOut = mat * mat2; - } - } - ++iParent; - } - - // Store the inverse of the absolute transformation matrix - // of the first key as bone offset matrix - for (iParent = 0; iParent < asBones.size();++iParent) - { - SMD::Bone& bone = asBones[iParent]; - bone.mOffsetMatrix = bone.sAnim.asKeys[bone.sAnim.iFirstTimeKey].matrixAbsolute; - bone.mOffsetMatrix.Inverse(); - } -} -\ // ------------------------------------------------------------------------------------------------ // create output materials void SMDImporter::CreateOutputMaterials() diff --git a/code/SMDLoader.h b/code/SMDLoader.h index cbf04d9d0..a791e7dde 100644 --- a/code/SMDLoader.h +++ b/code/SMDLoader.h @@ -290,13 +290,6 @@ protected: */ unsigned int GetTextureIndex(const std::string& filename); - // ------------------------------------------------------------------- - /** Computes absolute bone transformations - * All output transformations are in worldspace. - */ - void ComputeAbsoluteBoneTransformations(); - - // ------------------------------------------------------------------- /** Parse a line in the skeleton section */ From 576673536bb8910601eb095bfcee9f5e85224d2e Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 30 Nov 2018 22:17:42 +0100 Subject: [PATCH 053/472] Update SMDLoader.cpp Fix compiler warning and do some reformattings. --- code/SMDLoader.cpp | 570 +++++++++++++++++++-------------------------- 1 file changed, 245 insertions(+), 325 deletions(-) diff --git a/code/SMDLoader.cpp b/code/SMDLoader.cpp index ef3b9b7f8..c6ec61624 100644 --- a/code/SMDLoader.cpp +++ b/code/SMDLoader.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2018, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -48,8 +46,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_SMD_IMPORTER -// internal headers -#include "SMDLoader.h" #include #include #include @@ -61,6 +57,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +// internal headers +#include "SMDLoader.h" + #ifndef _WIN32 #define strtok_s strtok_r #endif @@ -83,14 +82,14 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer SMDImporter::SMDImporter() -: configFrameID(), -mBuffer(), -pScene( nullptr ), -iFileSize( 0 ), -iSmallestFrame( INT_MAX ), -dLengthOfAnim( 0.0 ), -bHasUVs(false ), -iLineNumber(-1) { +: configFrameID() +, mBuffer() +, pScene( nullptr ) +, iFileSize( 0 ) +, iSmallestFrame( INT_MAX ) +, dLengthOfAnim( 0.0 ) +, bHasUVs(false ) +, iLineNumber(-1) { // empty } @@ -102,23 +101,20 @@ SMDImporter::~SMDImporter() { // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool SMDImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool) const -{ +bool SMDImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool) const { // fixme: auto format detection return SimpleExtensionCheck(pFile,"smd","vta"); } // ------------------------------------------------------------------------------------------------ // Get a list of all supported file extensions -const aiImporterDesc* SMDImporter::GetInfo () const -{ +const aiImporterDesc* SMDImporter::GetInfo () const { return &desc; } // ------------------------------------------------------------------------------------------------ // Setup configuration properties -void SMDImporter::SetupProperties(const Importer* pImp) -{ +void SMDImporter::SetupProperties(const Importer* pImp) { // The // AI_CONFIG_IMPORT_SMD_KEYFRAME option overrides the // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option. @@ -133,17 +129,14 @@ void SMDImporter::SetupProperties(const Importer* pImp) // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void SMDImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) -{ +void SMDImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { this->pScene = pScene; ReadSmd(pFile, pIOHandler); // If there are no triangles it seems to be an animation SMD, // containing only the animation skeleton. - if (asTriangles.empty()) - { - if (asBones.empty()) - { + if (asTriangles.empty()) { + if (asBones.empty()) { throw DeadlyImportError("SMD: No triangles and no bones have " "been found in the file. This file seems to be invalid."); } @@ -153,15 +146,12 @@ void SMDImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; } - if (!asBones.empty()) - { + if (!asBones.empty()) { // Check whether all bones have been initialized for (std::vector::const_iterator - i = asBones.begin(); - i != asBones.end();++i) - { - if (!(*i).mName.length()) - { + i = asBones.begin(); + i != asBones.end();++i) { + if (!(*i).mName.length()) { ASSIMP_LOG_WARN("SMD: Not all bones have been initialized"); break; } @@ -174,8 +164,7 @@ void SMDImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS // build output nodes (bones are added as empty dummy nodes) CreateOutputNodes(); - if (!(pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) - { + if (!(pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) { // create output meshes CreateOutputMeshes(); @@ -185,51 +174,49 @@ void SMDImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS // use root node that renders all meshes pScene->mRootNode->mNumMeshes = pScene->mNumMeshes; pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes]; - for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) + for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { pScene->mRootNode->mMeshes[i] = i; + } } // build the output animation CreateOutputAnimations(pFile, pIOHandler); - if ((pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE) && !noSkeletonMesh) - { + if ((pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE) && !noSkeletonMesh) { SkeletonMeshBuilder skeleton(pScene); } } + // ------------------------------------------------------------------------------------------------ // Write an error message with line number to the log file -void SMDImporter::LogErrorNoThrow(const char* msg) -{ - char szTemp[1024]; - ai_snprintf(szTemp,1024,"Line %u: %s",iLineNumber,msg); +void SMDImporter::LogErrorNoThrow(const char* msg) { + const size_t BufferSize = 1024; + char szTemp[BufferSize]; + ai_snprintf(szTemp,BufferSize,"Line %u: %s",iLineNumber,msg); DefaultLogger::get()->error(szTemp); } // ------------------------------------------------------------------------------------------------ // Write a warning with line number to the log file -void SMDImporter::LogWarning(const char* msg) -{ - char szTemp[1024]; +void SMDImporter::LogWarning(const char* msg) { + const size_t BufferSize = 1024; + char szTemp[BufferSize]; ai_assert(strlen(msg) < 1000); - ai_snprintf(szTemp,1024,"Line %u: %s",iLineNumber,msg); + ai_snprintf(szTemp,BufferSize,"Line %u: %s",iLineNumber,msg); ASSIMP_LOG_WARN(szTemp); } // ------------------------------------------------------------------------------------------------ // Fix invalid time values in the file -void SMDImporter::FixTimeValues() -{ +void SMDImporter::FixTimeValues() { double dDelta = (double)iSmallestFrame; double dMax = 0.0f; for (std::vector::iterator - iBone = asBones.begin(); - iBone != asBones.end();++iBone) - { + iBone = asBones.begin(); + iBone != asBones.end();++iBone) { for (std::vector::iterator - iKey = (*iBone).sAnim.asKeys.begin(); - iKey != (*iBone).sAnim.asKeys.end();++iKey) - { + iKey = (*iBone).sAnim.asKeys.begin(); + iKey != (*iBone).sAnim.asKeys.end();++iKey) { (*iKey).dTime -= dDelta; dMax = std::max(dMax, (*iKey).dTime); } @@ -239,10 +226,10 @@ void SMDImporter::FixTimeValues() // ------------------------------------------------------------------------------------------------ // create output meshes -void SMDImporter::CreateOutputMeshes() -{ - if (aszTextures.empty()) +void SMDImporter::CreateOutputMeshes() { + if (aszTextures.empty()) { aszTextures.push_back(std::string()); + } // we need to sort all faces by their material index // in opposition to other loaders we can be sure that each @@ -256,28 +243,27 @@ void SMDImporter::CreateOutputMeshes() // approximate the space that will be required unsigned int iNum = (unsigned int)asTriangles.size() / pScene->mNumMeshes; iNum += iNum >> 1; - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) + for (unsigned int i = 0; i < pScene->mNumMeshes;++i) { aaiFaces[i].reserve(iNum); - + } // collect all faces iNum = 0; for (std::vector::const_iterator - iFace = asTriangles.begin(); - iFace != asTriangles.end();++iFace,++iNum) - { - if (UINT_MAX == (*iFace).iTexture)aaiFaces[(*iFace).iTexture].push_back( 0 ); - else if ((*iFace).iTexture >= aszTextures.size()) - { + iFace = asTriangles.begin(); + iFace != asTriangles.end();++iFace,++iNum) { + if (UINT_MAX == (*iFace).iTexture) { + aaiFaces[(*iFace).iTexture].push_back( 0 ); + } else if ((*iFace).iTexture >= aszTextures.size()) { ASSIMP_LOG_INFO("[SMD/VTA] Material index overflow in face"); aaiFaces[(*iFace).iTexture].push_back((unsigned int)aszTextures.size()-1); + } else { + aaiFaces[(*iFace).iTexture].push_back(iNum); } - else aaiFaces[(*iFace).iTexture].push_back(iNum); } // now create the output meshes - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - { + for (unsigned int i = 0; i < pScene->mNumMeshes;++i) { aiMesh*& pcMesh = pScene->mMeshes[i] = new aiMesh(); ai_assert(!aaiFaces[i].empty()); // should not be empty ... @@ -293,8 +279,7 @@ void SMDImporter::CreateOutputMeshes() TempBoneWeightList* aaiBones = new TempBoneWeightList[asBones.size()](); // try to reserve enough memory without wasting too much - for (unsigned int iBone = 0; iBone < asBones.size();++iBone) - { + for (unsigned int iBone = 0; iBone < asBones.size();++iBone) { aaiBones[iBone].reserve(pcMesh->mNumVertices/asBones.size()); } @@ -303,16 +288,14 @@ void SMDImporter::CreateOutputMeshes() aiVector3D* pcNormals = pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices]; aiVector3D* pcVerts = pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices]; - aiVector3D* pcUVs = NULL; - if (bHasUVs) - { + aiVector3D* pcUVs = nullptr; + if (bHasUVs) { pcUVs = pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices]; pcMesh->mNumUVComponents[0] = 2; } iNum = 0; - for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace) - { + for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace) { pcMesh->mFaces[iFace].mIndices = new unsigned int[3]; pcMesh->mFaces[iFace].mNumIndices = 3; @@ -330,25 +313,20 @@ void SMDImporter::CreateOutputMeshes() *pcNormals++ = face.avVertices[2].nor; // fill the texture coordinates - if (pcUVs) - { + if (pcUVs) { *pcUVs++ = face.avVertices[0].uv; *pcUVs++ = face.avVertices[1].uv; *pcUVs++ = face.avVertices[2].uv; } - for (unsigned int iVert = 0; iVert < 3;++iVert) - { + for (unsigned int iVert = 0; iVert < 3;++iVert) { float fSum = 0.0f; - for (unsigned int iBone = 0;iBone < face.avVertices[iVert].aiBoneLinks.size();++iBone) - { + for (unsigned int iBone = 0;iBone < face.avVertices[iVert].aiBoneLinks.size();++iBone) { TempWeightListEntry& pairval = face.avVertices[iVert].aiBoneLinks[iBone]; // FIX: The second check is here just to make sure we won't // assign more than one weight to a single vertex index - if (pairval.first >= asBones.size() || - pairval.first == face.avVertices[iVert].iParentNode) - { + if (pairval.first >= asBones.size() || pairval.first == face.avVertices[iVert].iParentNode) { ASSIMP_LOG_ERROR("[SMD/VTA] Bone index overflow. " "The bone index will be ignored, the weight will be assigned " "to the vertex' parent node"); @@ -366,27 +344,23 @@ void SMDImporter::CreateOutputMeshes() // that the parent of a vertex is 0xffffffff (if the corresponding // entry in the file was unreadable) // ****************************************************************** - if (fSum < 0.975f && face.avVertices[iVert].iParentNode != UINT_MAX) - { - if (face.avVertices[iVert].iParentNode >= asBones.size()) - { + if (fSum < 0.975f && face.avVertices[iVert].iParentNode != UINT_MAX) { + if (face.avVertices[iVert].iParentNode >= asBones.size()) { ASSIMP_LOG_ERROR("[SMD/VTA] Bone index overflow. " "The index of the vertex parent bone is invalid. " "The remaining weights will be normalized to 1.0"); - if (fSum) - { + if (fSum) { fSum = 1 / fSum; - for (unsigned int iBone = 0;iBone < face.avVertices[iVert].aiBoneLinks.size();++iBone) - { + for (unsigned int iBone = 0;iBone < face.avVertices[iVert].aiBoneLinks.size();++iBone) { TempWeightListEntry& pairval = face.avVertices[iVert].aiBoneLinks[iBone]; - if (pairval.first >= asBones.size())continue; + if (pairval.first >= asBones.size()) { + continue; + } aaiBones[pairval.first].back().second *= fSum; } } - } - else - { + } else { aaiBones[face.avVertices[iVert].iParentNode].push_back( TempWeightListEntry(iNum,1.0f-fSum)); } @@ -397,17 +371,18 @@ void SMDImporter::CreateOutputMeshes() // now build all bones of the mesh iNum = 0; - for (unsigned int iBone = 0; iBone < asBones.size();++iBone) + for (unsigned int iBone = 0; iBone < asBones.size();++iBone) { if (!aaiBones[iBone].empty())++iNum; + } - if (iNum) - { + if (iNum) { pcMesh->mNumBones = iNum; pcMesh->mBones = new aiBone*[pcMesh->mNumBones]; iNum = 0; - for (unsigned int iBone = 0; iBone < asBones.size();++iBone) - { - if (aaiBones[iBone].empty())continue; + for (unsigned int iBone = 0; iBone < asBones.size();++iBone) { + if (aaiBones[iBone].empty()) { + continue; + } aiBone*& bone = pcMesh->mBones[iNum] = new aiBone(); bone->mNumWeights = (unsigned int)aaiBones[iBone].size(); @@ -417,8 +392,7 @@ void SMDImporter::CreateOutputMeshes() asBones[iBone].bIsUsed = true; - for (unsigned int iWeight = 0; iWeight < bone->mNumWeights;++iWeight) - { + for (unsigned int iWeight = 0; iWeight < bone->mNumWeights;++iWeight) { bone->mWeights[iWeight].mVertexId = aaiBones[iBone][iWeight].first; bone->mWeights[iWeight].mWeight = aaiBones[iBone][iWeight].second; } @@ -432,40 +406,43 @@ void SMDImporter::CreateOutputMeshes() // ------------------------------------------------------------------------------------------------ // add bone child nodes -void SMDImporter::AddBoneChildren(aiNode* pcNode, uint32_t iParent) -{ - ai_assert( NULL != pcNode ); +void SMDImporter::AddBoneChildren(aiNode* pcNode, uint32_t iParent) { + ai_assert( nullptr != pcNode ); ai_assert( 0 == pcNode->mNumChildren ); - ai_assert( NULL == pcNode->mChildren); + ai_assert( nullptr == pcNode->mChildren); // first count ... - for (unsigned int i = 0; i < asBones.size();++i) - { + for (unsigned int i = 0; i < asBones.size();++i) { SMD::Bone& bone = asBones[i]; - if (bone.iParent == iParent)++pcNode->mNumChildren; + if (bone.iParent == iParent) { + ++pcNode->mNumChildren; + } } // now allocate the output array pcNode->mChildren = new aiNode*[pcNode->mNumChildren]; // and fill all subnodes - unsigned int qq = 0; - for (unsigned int i = 0; i < asBones.size();++i) - { + unsigned int qq( 0 ); + for (unsigned int i = 0; i < asBones.size();++i) { SMD::Bone& bone = asBones[i]; - if (bone.iParent != iParent)continue; + if (bone.iParent != iParent) { + continue; + } aiNode* pc = pcNode->mChildren[qq++] = new aiNode(); pc->mName.Set(bone.mName); // store the local transformation matrix of the bind pose - if (bone.sAnim.asKeys.size()) + if (bone.sAnim.asKeys.size()) { pc->mTransformation = bone.sAnim.asKeys[0].matrix; + } - if (bone.iParent == -1) + if (bone.iParent == static_cast(-1)) { bone.mOffsetMatrix = pc->mTransformation; - else + } else { bone.mOffsetMatrix = asBones[bone.iParent].mOffsetMatrix * pc->mTransformation; + } pc->mParent = pcNode; @@ -476,25 +453,23 @@ void SMDImporter::AddBoneChildren(aiNode* pcNode, uint32_t iParent) // ------------------------------------------------------------------------------------------------ // create output nodes -void SMDImporter::CreateOutputNodes() -{ +void SMDImporter::CreateOutputNodes() { pScene->mRootNode = new aiNode(); // now add all bones as dummy sub nodes to the graph AddBoneChildren(pScene->mRootNode,(uint32_t)-1); - for (auto &bone : asBones) + for (auto &bone : asBones) { bone.mOffsetMatrix.Inverse(); + } // if we have only one bone we can even remove the root node - if (pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE && - 1 == pScene->mRootNode->mNumChildren) - { + if (pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE && 1 == pScene->mRootNode->mNumChildren) { aiNode* pcOldRoot = pScene->mRootNode; pScene->mRootNode = pcOldRoot->mChildren[0]; - pcOldRoot->mChildren[0] = NULL; + pcOldRoot->mChildren[0] = nullptr; delete pcOldRoot; - pScene->mRootNode->mParent = NULL; + pScene->mRootNode->mParent = nullptr; } else { @@ -505,33 +480,33 @@ void SMDImporter::CreateOutputNodes() // ------------------------------------------------------------------------------------------------ // create output animations -void SMDImporter::CreateOutputAnimations(const std::string &pFile, IOSystem* pIOHandler) -{ +void SMDImporter::CreateOutputAnimations(const std::string &pFile, IOSystem* pIOHandler) { std::vector> animFileList; - if (bLoadAnimationList) GetAnimationFileList(pFile, pIOHandler, animFileList); + if (bLoadAnimationList) { + GetAnimationFileList(pFile, pIOHandler, animFileList); + } int animCount = animFileList.size() + 1; pScene->mNumAnimations = 1; pScene->mAnimations = new aiAnimation*[animCount]; memset(pScene->mAnimations, 0, sizeof(aiAnimation*)*animCount); CreateOutputAnimation(0, ""); - for (auto &animFile : animFileList) - { + for (auto &animFile : animFileList) { ReadSmd(std::get<1>(animFile), pIOHandler); - if (asBones.empty()) continue; + if (asBones.empty()) { + continue; + } FixTimeValues(); CreateOutputAnimation(pScene->mNumAnimations++, std::get<0>(animFile)); } } -void SMDImporter::CreateOutputAnimation(int index, const std::string &name) -{ +void SMDImporter::CreateOutputAnimation(int index, const std::string &name) { aiAnimation*& anim = pScene->mAnimations[index] = new aiAnimation(); - if (name.length()) - { + if (name.length()) { anim->mName.Set(name.c_str()); } anim->mDuration = dLengthOfAnim; @@ -542,26 +517,21 @@ void SMDImporter::CreateOutputAnimation(int index, const std::string &name) // now build valid keys unsigned int a = 0; - for (std::vector::const_iterator - i = asBones.begin(); - i != asBones.end(); ++i) - { + for (std::vector::const_iterator i = asBones.begin(); i != asBones.end(); ++i) { aiNodeAnim* p = pp[a] = new aiNodeAnim(); // copy the name of the bone p->mNodeName.Set(i->mName); p->mNumRotationKeys = (unsigned int)(*i).sAnim.asKeys.size(); - if (p->mNumRotationKeys) - { + if (p->mNumRotationKeys){ p->mNumPositionKeys = p->mNumRotationKeys; aiVectorKey* pVecKeys = p->mPositionKeys = new aiVectorKey[p->mNumRotationKeys]; aiQuatKey* pRotKeys = p->mRotationKeys = new aiQuatKey[p->mNumRotationKeys]; for (std::vector::const_iterator - qq = (*i).sAnim.asKeys.begin(); - qq != (*i).sAnim.asKeys.end(); ++qq) - { + qq = (*i).sAnim.asKeys.begin(); + qq != (*i).sAnim.asKeys.end(); ++qq) { pRotKeys->mTime = pVecKeys->mTime = (*qq).dTime; // compute the rotation quaternion from the euler angles @@ -578,14 +548,15 @@ void SMDImporter::CreateOutputAnimation(int index, const std::string &name) } } -void SMDImporter::GetAnimationFileList(const std::string &pFile, IOSystem* pIOHandler, std::vector>& outList) -{ +void SMDImporter::GetAnimationFileList(const std::string &pFile, IOSystem* pIOHandler, std::vector>& outList) { auto base = DefaultIOSystem::absolutePath(pFile); auto name = DefaultIOSystem::completeBaseName(pFile); auto path = base + "/" + name + "_animation.txt"; std::unique_ptr file(pIOHandler->Open(path.c_str(), "rb")); - if (file.get() == NULL) return; + if (file.get() == nullptr) { + return; + } // Allocate storage and copy the contents of the file to a memory buffer std::vector buf; @@ -608,30 +579,26 @@ void SMDImporter::GetAnimationFileList(const std::string &pFile, IOSystem* pIOHa tok1 = strtok_s(&buf[0], "\r\n", &context1); while (tok1 != NULL) { tok2 = strtok_s(tok1, " \t", &context2); - if (tok2) - { + if (tok2) { char *p = tok2; - tok2 = strtok_s(NULL, " \t", &context2); - if (tok2) - { + tok2 = strtok_s(nullptr, " \t", &context2); + if (tok2) { animPath = tok2; animName = p; - } - else // No name - { + } else { + // No name animPath = p; animName = DefaultIOSystem::completeBaseName(animPath); } outList.push_back(std::make_tuple(animName, base + "/" + animPath)); } - tok1 = strtok_s(NULL, "\r\n", &context1); + tok1 = strtok_s(nullptr, "\r\n", &context1); } } // ------------------------------------------------------------------------------------------------ // create output materials -void SMDImporter::CreateOutputMaterials() -{ +void SMDImporter::CreateOutputMaterials() { ai_assert( nullptr != pScene ); pScene->mNumMaterials = (unsigned int)aszTextures.size(); @@ -655,14 +622,13 @@ void SMDImporter::CreateOutputMaterials() } // create a default material if necessary - if (0 == pScene->mNumMaterials) - { + if (0 == pScene->mNumMaterials) { pScene->mNumMaterials = 1; aiMaterial* pcHelper = new aiMaterial(); pScene->mMaterials[0] = pcHelper; - int iMode = (int)aiShadingMode_Gouraud; + int iMode = static_cast(aiShadingMode_Gouraud); pcHelper->AddProperty(&iMode, 1, AI_MATKEY_SHADING_MODEL); aiColor3D clr; @@ -681,62 +647,54 @@ void SMDImporter::CreateOutputMaterials() // ------------------------------------------------------------------------------------------------ // Parse the file -void SMDImporter::ParseFile() -{ +void SMDImporter::ParseFile() { const char* szCurrent = &mBuffer[0]; // read line per line ... - for ( ;; ) - { - if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break; + for ( ;; ) { + if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) { + break; + } // "version \n", should be 1 for hl and hl2 SMD files - if (TokenMatch(szCurrent,"version",7)) - { + if (TokenMatch(szCurrent,"version",7)) { if(!SkipSpaces(szCurrent,&szCurrent)) break; - if (1 != strtoul10(szCurrent,&szCurrent)) - { + if (1 != strtoul10(szCurrent,&szCurrent)) { ASSIMP_LOG_WARN("SMD.version is not 1. This " "file format is not known. Continuing happily ..."); } continue; } // "nodes\n" - Starts the node section - if (TokenMatch(szCurrent,"nodes",5)) - { + if (TokenMatch(szCurrent,"nodes",5)) { ParseNodesSection(szCurrent,&szCurrent); continue; } // "triangles\n" - Starts the triangle section - if (TokenMatch(szCurrent,"triangles",9)) - { + if (TokenMatch(szCurrent,"triangles",9)) { ParseTrianglesSection(szCurrent,&szCurrent); continue; } // "vertexanimation\n" - Starts the vertex animation section - if (TokenMatch(szCurrent,"vertexanimation",15)) - { + if (TokenMatch(szCurrent,"vertexanimation",15)) { bHasUVs = false; ParseVASection(szCurrent,&szCurrent); continue; } // "skeleton\n" - Starts the skeleton section - if (TokenMatch(szCurrent,"skeleton",8)) - { + if (TokenMatch(szCurrent,"skeleton",8)) { ParseSkeletonSection(szCurrent,&szCurrent); continue; } SkipLine(szCurrent,&szCurrent); } - return; } -void SMDImporter::ReadSmd(const std::string &pFile, IOSystem* pIOHandler) -{ +void SMDImporter::ReadSmd(const std::string &pFile, IOSystem* pIOHandler) { std::unique_ptr file(pIOHandler->Open(pFile, "rb")); // Check whether we can read from the file - if (file.get() == NULL) { + if (file.get() == nullptr) { throw DeadlyImportError("Failed to open SMD/VTA file " + pFile + "."); } @@ -768,15 +726,15 @@ void SMDImporter::ReadSmd(const std::string &pFile, IOSystem* pIOHandler) } // ------------------------------------------------------------------------------------------------ -unsigned int SMDImporter::GetTextureIndex(const std::string& filename) -{ +unsigned int SMDImporter::GetTextureIndex(const std::string& filename) { unsigned int iIndex = 0; for (std::vector::const_iterator - i = aszTextures.begin(); - i != aszTextures.end();++i,++iIndex) - { + i = aszTextures.begin(); + i != aszTextures.end();++i,++iIndex) { // case-insensitive ... it's a path - if (0 == ASSIMP_stricmp ( filename.c_str(),(*i).c_str()))return iIndex; + if (0 == ASSIMP_stricmp ( filename.c_str(),(*i).c_str())) { + return iIndex; + } } iIndex = (unsigned int)aszTextures.size(); aszTextures.push_back(filename); @@ -785,15 +743,10 @@ unsigned int SMDImporter::GetTextureIndex(const std::string& filename) // ------------------------------------------------------------------------------------------------ // Parse the nodes section of the file -void SMDImporter::ParseNodesSection(const char* szCurrent, - const char** szCurrentOut) -{ - for ( ;; ) - { +void SMDImporter::ParseNodesSection(const char* szCurrent, const char** szCurrentOut) { + for ( ;; ) { // "end\n" - Ends the nodes section - if (0 == ASSIMP_strincmp(szCurrent,"end",3) && - IsSpaceOrNewLine(*(szCurrent+3))) - { + if (0 == ASSIMP_strincmp(szCurrent,"end",3) && IsSpaceOrNewLine(*(szCurrent+3))) { szCurrent += 4; break; } @@ -805,18 +758,18 @@ void SMDImporter::ParseNodesSection(const char* szCurrent, // ------------------------------------------------------------------------------------------------ // Parse the triangles section of the file -void SMDImporter::ParseTrianglesSection(const char* szCurrent, - const char** szCurrentOut) -{ +void SMDImporter::ParseTrianglesSection(const char* szCurrent, const char** szCurrentOut) { // Parse a triangle, parse another triangle, parse the next triangle ... // and so on until we reach a token that looks quite similar to "end" - for ( ;; ) - { - if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break; + for ( ;; ) { + if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) { + break; + } // "end\n" - Ends the triangles section - if (TokenMatch(szCurrent,"end",3)) + if (TokenMatch(szCurrent,"end",3)) { break; + } ParseTriangle(szCurrent,&szCurrent); } SkipSpacesAndLineEnd(szCurrent,&szCurrent); @@ -824,40 +777,39 @@ void SMDImporter::ParseTrianglesSection(const char* szCurrent, } // ------------------------------------------------------------------------------------------------ // Parse the vertex animation section of the file -void SMDImporter::ParseVASection(const char* szCurrent, - const char** szCurrentOut) -{ +void SMDImporter::ParseVASection(const char* szCurrent, const char** szCurrentOut) { unsigned int iCurIndex = 0; - for ( ;; ) - { - if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break; + for ( ;; ) { + if (!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) { + break; + } // "end\n" - Ends the "vertexanimation" section - if (TokenMatch(szCurrent,"end",3)) + if (TokenMatch(szCurrent,"end",3)) { break; + } // "time \n" - if (TokenMatch(szCurrent,"time",4)) - { + if (TokenMatch(szCurrent,"time",4)) { // NOTE: The doc says that time values COULD be negative ... // NOTE2: this is the shape key -> valve docs int iTime = 0; - if(!ParseSignedInt(szCurrent,&szCurrent,iTime) || configFrameID != (unsigned int)iTime)break; + if(!ParseSignedInt(szCurrent,&szCurrent,iTime) || configFrameID != (unsigned int)iTime) { + break; + } SkipLine(szCurrent,&szCurrent); - } - else - { - if(0 == iCurIndex) - { + } else { + if(0 == iCurIndex) { asTriangles.push_back(SMD::Face()); } - if (++iCurIndex == 3)iCurIndex = 0; + if (++iCurIndex == 3) { + iCurIndex = 0; + } ParseVertex(szCurrent,&szCurrent,asTriangles.back().avVertices[iCurIndex],true); } } - if (iCurIndex != 2 && !asTriangles.empty()) - { + if (iCurIndex != 2 && !asTriangles.empty()) { // we want to no degenerates, so throw this triangle away asTriangles.pop_back(); } @@ -865,29 +817,30 @@ void SMDImporter::ParseVASection(const char* szCurrent, SkipSpacesAndLineEnd(szCurrent,&szCurrent); *szCurrentOut = szCurrent; } + // ------------------------------------------------------------------------------------------------ // Parse the skeleton section of the file -void SMDImporter::ParseSkeletonSection(const char* szCurrent, - const char** szCurrentOut) -{ +void SMDImporter::ParseSkeletonSection(const char* szCurrent, const char** szCurrentOut) { int iTime = 0; - for ( ;; ) - { - if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break; + for ( ;; ) { + if (!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) { + break; + } // "end\n" - Ends the skeleton section - if (TokenMatch(szCurrent,"end",3)) + if (TokenMatch(szCurrent,"end",3)) { break; - + } else if (TokenMatch(szCurrent,"time",4)) { // "time \n" - Specifies the current animation frame - else if (TokenMatch(szCurrent,"time",4)) - { - if(!ParseSignedInt(szCurrent,&szCurrent,iTime))break; + if(!ParseSignedInt(szCurrent,&szCurrent,iTime)) { + break; + } iSmallestFrame = std::min(iSmallestFrame,iTime); SkipLine(szCurrent,&szCurrent); + } else { + ParseSkeletonElement(szCurrent,&szCurrent,iTime); } - else ParseSkeletonElement(szCurrent,&szCurrent,iTime); } *szCurrentOut = szCurrent; } @@ -900,45 +853,38 @@ void SMDImporter::ParseSkeletonSection(const char* szCurrent, } // ------------------------------------------------------------------------------------------------ // Parse a node line -void SMDImporter::ParseNodeInfo(const char* szCurrent, - const char** szCurrentOut) -{ +void SMDImporter::ParseNodeInfo(const char* szCurrent, const char** szCurrentOut) { unsigned int iBone = 0; SkipSpacesAndLineEnd(szCurrent,&szCurrent); - if(!ParseUnsignedInt(szCurrent,&szCurrent,iBone) || !SkipSpaces(szCurrent,&szCurrent)) - { + if ( !ParseUnsignedInt(szCurrent,&szCurrent,iBone) || !SkipSpaces(szCurrent,&szCurrent)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing bone index"); SMDI_PARSE_RETURN; } // add our bone to the list - if (iBone >= asBones.size())asBones.resize(iBone+1); + if (iBone >= asBones.size()) { + asBones.resize(iBone+1); + } SMD::Bone& bone = asBones[iBone]; bool bQuota = true; - if ('\"' != *szCurrent) - { + if ('\"' != *szCurrent) { LogWarning("Bone name is expcted to be enclosed in " "double quotation marks. "); bQuota = false; + } else { + ++szCurrent; } - else ++szCurrent; const char* szEnd = szCurrent; - for ( ;; ) - { - if (bQuota && '\"' == *szEnd) - { + for ( ;; ) { + if (bQuota && '\"' == *szEnd) { iBone = (unsigned int)(szEnd - szCurrent); ++szEnd; break; - } - else if (!bQuota && IsSpaceOrNewLine(*szEnd)) - { + } else if (!bQuota && IsSpaceOrNewLine(*szEnd)) { iBone = (unsigned int)(szEnd - szCurrent); break; - } - else if (!(*szEnd)) - { + } else if (!(*szEnd)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing bone name"); SMDI_PARSE_RETURN; } @@ -948,8 +894,7 @@ void SMDImporter::ParseNodeInfo(const char* szCurrent, szCurrent = szEnd; // the only negative bone parent index that could occur is -1 AFAIK - if(!ParseSignedInt(szCurrent,&szCurrent,(int&)bone.iParent)) - { + if(!ParseSignedInt(szCurrent,&szCurrent,(int&)bone.iParent)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing bone parent index. Assuming -1"); SMDI_PARSE_RETURN; } @@ -960,20 +905,16 @@ void SMDImporter::ParseNodeInfo(const char* szCurrent, // ------------------------------------------------------------------------------------------------ // Parse a skeleton element -void SMDImporter::ParseSkeletonElement(const char* szCurrent, - const char** szCurrentOut,int iTime) -{ +void SMDImporter::ParseSkeletonElement(const char* szCurrent, const char** szCurrentOut,int iTime) { aiVector3D vPos; aiVector3D vRot; unsigned int iBone = 0; - if(!ParseUnsignedInt(szCurrent,&szCurrent,iBone)) - { + if(!ParseUnsignedInt(szCurrent,&szCurrent,iBone)) { ASSIMP_LOG_ERROR("Unexpected EOF/EOL while parsing bone index"); SMDI_PARSE_RETURN; } - if (iBone >= asBones.size()) - { + if (iBone >= asBones.size()) { LogErrorNoThrow("Bone index in skeleton section is out of range"); SMDI_PARSE_RETURN; } @@ -983,39 +924,32 @@ void SMDImporter::ParseSkeletonElement(const char* szCurrent, SMD::Bone::Animation::MatrixKey& key = bone.sAnim.asKeys.back(); key.dTime = (double)iTime; - if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.x)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.x)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.pos.x"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.y)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.y)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.pos.y"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.z)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.z)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.pos.z"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.x)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.x)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.rot.x"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.y)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.y)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.rot.y"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.z)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.z)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.rot.z"); SMDI_PARSE_RETURN; } // build the transformation matrix of the key - key.matrix.FromEulerAnglesXYZ(vRot.x,vRot.y,vRot.z); - { + key.matrix.FromEulerAnglesXYZ(vRot.x,vRot.y,vRot.z); { aiMatrix4x4 mTemp; mTemp.a4 = vPos.x; mTemp.b4 = vPos.y; @@ -1030,14 +964,11 @@ void SMDImporter::ParseSkeletonElement(const char* szCurrent, // ------------------------------------------------------------------------------------------------ // Parse a triangle -void SMDImporter::ParseTriangle(const char* szCurrent, - const char** szCurrentOut) -{ +void SMDImporter::ParseTriangle(const char* szCurrent, const char** szCurrentOut) { asTriangles.push_back(SMD::Face()); SMD::Face& face = asTriangles.back(); - if(!SkipSpaces(szCurrent,&szCurrent)) - { + if(!SkipSpaces(szCurrent,&szCurrent)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing a triangle"); return; } @@ -1052,21 +983,18 @@ void SMDImporter::ParseTriangle(const char* szCurrent, SkipSpacesAndLineEnd(szCurrent,&szCurrent); // load three vertices - for (unsigned int iVert = 0; iVert < 3;++iVert) - { - ParseVertex(szCurrent,&szCurrent, - face.avVertices[iVert]); + for (unsigned int iVert = 0; iVert < 3;++iVert) { + ParseVertex(szCurrent,&szCurrent, face.avVertices[iVert]); } *szCurrentOut = szCurrent; } // ------------------------------------------------------------------------------------------------ // Parse a float -bool SMDImporter::ParseFloat(const char* szCurrent, - const char** szCurrentOut, float& out) -{ - if(!SkipSpaces(&szCurrent)) +bool SMDImporter::ParseFloat(const char* szCurrent, const char** szCurrentOut, float& out) { + if(!SkipSpaces(&szCurrent)) { return false; + } *szCurrentOut = fast_atoreal_move(szCurrent,out); return true; @@ -1074,11 +1002,10 @@ bool SMDImporter::ParseFloat(const char* szCurrent, // ------------------------------------------------------------------------------------------------ // Parse an unsigned int -bool SMDImporter::ParseUnsignedInt(const char* szCurrent, - const char** szCurrentOut, unsigned int& out) -{ - if(!SkipSpaces(&szCurrent)) +bool SMDImporter::ParseUnsignedInt(const char* szCurrent, const char** szCurrentOut, unsigned int& out) { + if(!SkipSpaces(&szCurrent)) { return false; + } out = strtoul10(szCurrent,szCurrentOut); return true; @@ -1086,11 +1013,10 @@ bool SMDImporter::ParseUnsignedInt(const char* szCurrent, // ------------------------------------------------------------------------------------------------ // Parse a signed int -bool SMDImporter::ParseSignedInt(const char* szCurrent, - const char** szCurrentOut, int& out) -{ - if(!SkipSpaces(&szCurrent)) +bool SMDImporter::ParseSignedInt(const char* szCurrent, const char** szCurrentOut, int& out) { + if(!SkipSpaces(&szCurrent)) { return false; + } out = strtol10(szCurrent,szCurrentOut); return true; @@ -1099,59 +1025,50 @@ bool SMDImporter::ParseSignedInt(const char* szCurrent, // ------------------------------------------------------------------------------------------------ // Parse a vertex void SMDImporter::ParseVertex(const char* szCurrent, - const char** szCurrentOut, SMD::Vertex& vertex, - bool bVASection /*= false*/) -{ - if (SkipSpaces(&szCurrent) && IsLineEnd(*szCurrent)) - { + const char** szCurrentOut, SMD::Vertex& vertex, + bool bVASection /*= false*/) { + if (SkipSpaces(&szCurrent) && IsLineEnd(*szCurrent)) { SkipSpacesAndLineEnd(szCurrent,&szCurrent); return ParseVertex(szCurrent,szCurrentOut,vertex,bVASection); } - if(!ParseSignedInt(szCurrent,&szCurrent,(int&)vertex.iParentNode)) - { + if(!ParseSignedInt(szCurrent,&szCurrent,(int&)vertex.iParentNode)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.parent"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.x)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.x)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.pos.x"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.y)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.y)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.pos.y"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.z)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.z)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.pos.z"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.x)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.x)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.nor.x"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.y)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.y)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.nor.y"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.z)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.z)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.nor.z"); SMDI_PARSE_RETURN; } - if (bVASection)SMDI_PARSE_RETURN; + if (bVASection) { + SMDI_PARSE_RETURN; + } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.uv.x)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.uv.x)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.uv.x"); SMDI_PARSE_RETURN; } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.uv.y)) - { + if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.uv.y)) { LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.uv.y"); SMDI_PARSE_RETURN; } @@ -1159,17 +1076,20 @@ void SMDImporter::ParseVertex(const char* szCurrent, // now read the number of bones affecting this vertex // all elements from now are fully optional, we don't need them unsigned int iSize = 0; - if(!ParseUnsignedInt(szCurrent,&szCurrent,iSize))SMDI_PARSE_RETURN; + if(!ParseUnsignedInt(szCurrent,&szCurrent,iSize)) { + SMDI_PARSE_RETURN; + } vertex.aiBoneLinks.resize(iSize,std::pair(0,0.0f)); for (std::vector >::iterator - i = vertex.aiBoneLinks.begin(); - i != vertex.aiBoneLinks.end();++i) - { - if(!ParseUnsignedInt(szCurrent,&szCurrent,(*i).first)) + i = vertex.aiBoneLinks.begin(); + i != vertex.aiBoneLinks.end();++i) { + if(!ParseUnsignedInt(szCurrent,&szCurrent,(*i).first)) { SMDI_PARSE_RETURN; - if(!ParseFloat(szCurrent,&szCurrent,(*i).second)) + } + if(!ParseFloat(szCurrent,&szCurrent,(*i).second)) { SMDI_PARSE_RETURN; + } } // go to the beginning of the next line From bb66af544a6e177cdf5a8d6e27dd105c947375fd Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 2 Dec 2018 13:08:47 +0100 Subject: [PATCH 054/472] closes https://github.com/assimp/assimp/issues/2228: prepare pull-request. --- code/OFFLoader.cpp | 240 +++++++++++++++++++++++++++++++-------------- 1 file changed, 165 insertions(+), 75 deletions(-) diff --git a/code/OFFLoader.cpp b/code/OFFLoader.cpp index 81f9c9916..977b1b36c 100644 --- a/code/OFFLoader.cpp +++ b/code/OFFLoader.cpp @@ -106,15 +106,23 @@ const aiImporterDesc* OFFImporter::GetInfo () const return &desc; } + +// skip blank space, lines and comments +static void NextToken(const char **car, const char* end) { + SkipSpacesAndLineEnd(car); + while (*car < end && (**car == '#' || **car == '\n' || **car == '\r')) { + SkipLine(car); + SkipSpacesAndLineEnd(car); + } +} + // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void OFFImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ +void OFFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { std::unique_ptr file( pIOHandler->Open( pFile, "rb")); // Check whether we can read from the file - if( file.get() == NULL) { + if( file.get() == nullptr) { throw DeadlyImportError( "Failed to open OFF file " + pFile + "."); } @@ -123,15 +131,61 @@ void OFFImporter::InternReadFile( const std::string& pFile, TextFileToBuffer(file.get(),mBuffer2); const char* buffer = &mBuffer2[0]; - char line[4096]; - GetNextLine(buffer,line); - if ('O' == line[0]) { - GetNextLine(buffer,line); // skip the 'OFF' line + // Proper OFF header parser. We only implement normal loading for now. + bool hasTexCoord = false, hasNormals = false, hasColors = false; + bool hasHomogenous = false, hasDimension = false; + unsigned int dimensions = 3; + const char* car = buffer; + const char* end = buffer + mBuffer2.size(); + NextToken(&car, end); + + if (car < end - 2 && car[0] == 'S' && car[1] == 'T') { + hasTexCoord = true; car += 2; + } + if (car < end - 1 && car[0] == 'C') { + hasColors = true; car++; + } + if (car < end- 1 && car[0] == 'N') { + hasNormals = true; car++; + } + if (car < end - 1 && car[0] == '4') { + hasHomogenous = true; car++; + } + if (car < end - 1 && car[0] == 'n') { + hasDimension = true; car++; + } + if (car < end - 3 && car[0] == 'O' && car[1] == 'F' && car[2] == 'F') { + car += 3; + NextToken(&car, end); + } else { + // in case there is no OFF header (which is allowed by the + // specification...), then we might have unintentionally read an + // additional dimension from the primitive count fields + dimensions = 3; + hasHomogenous = false; + NextToken(&car, end); + + // at this point the next token should be an integer number + if (car >= end - 1 || *car < '0' || *car > '9') { + throw DeadlyImportError("OFF: Header is invalid"); + } + } + if (hasDimension) { + dimensions = strtoul10(car, &car); + NextToken(&car, end); + } + if (dimensions > 3) { + throw DeadlyImportError + ("OFF: Number of vertex coordinates higher than 3 unsupported"); } - const char* sz = line; SkipSpaces(&sz); - const unsigned int numVertices = strtoul10(sz,&sz);SkipSpaces(&sz); - const unsigned int numFaces = strtoul10(sz,&sz); + NextToken(&car, end); + const unsigned int numVertices = strtoul10(car, &car); + NextToken(&car, end); + const unsigned int numFaces = strtoul10(car, &car); + NextToken(&car, end); + strtoul10(car, &car); // skip edge count + NextToken(&car, end); if (!numVertices) { throw DeadlyImportError("OFF: There are no valid vertices"); @@ -147,91 +201,127 @@ void OFFImporter::InternReadFile( const std::string& pFile, pScene->mMeshes[0] = mesh; mesh->mNumFaces = numFaces; - aiFace* faces = new aiFace [mesh->mNumFaces]; + aiFace* faces = new aiFace[mesh->mNumFaces]; mesh->mFaces = faces; - std::vector tempPositions(numVertices); + mesh->mNumVertices = numVertices; + mesh->mVertices = new aiVector3D[numVertices]; + mesh->mNormals = hasNormals ? new aiVector3D[numVertices] : nullptr; + mesh->mColors[0] = hasColors ? new aiColor4D[numVertices] : nullptr; + + if (hasTexCoord) { + mesh->mNumUVComponents[0] = 2; + mesh->mTextureCoords[0] = new aiVector3D[numVertices]; + } + char line[4096]; + buffer = car; + const char *sz = car; // now read all vertex lines - for (unsigned int i = 0; i< numVertices;++i) - { - if(!GetNextLine(buffer,line)) - { + for (unsigned int i = 0; i < numVertices; ++i) { + if(!GetNextLine(buffer, line)) { ASSIMP_LOG_ERROR("OFF: The number of verts in the header is incorrect"); break; } - aiVector3D& v = tempPositions[i]; + aiVector3D& v = mesh->mVertices[i]; + sz = line; - sz = line; SkipSpaces(&sz); - sz = fast_atoreal_move(sz,(ai_real&)v.x); SkipSpaces(&sz); - sz = fast_atoreal_move(sz,(ai_real&)v.y); SkipSpaces(&sz); - fast_atoreal_move(sz,(ai_real&)v.z); + // helper array to write a for loop over possible dimension values + ai_real* vec[3] = {&v.x, &v.y, &v.z}; + + // stop at dimensions: this allows loading 1D or 2D coordinate vertices + for (unsigned int dim = 0; dim < dimensions; ++dim ) { + SkipSpaces(&sz); + sz = fast_atoreal_move(sz, *vec[dim]); + } + + // if has homogenous coordinate, divide others by this one + if (hasHomogenous) { + SkipSpaces(&sz); + ai_real w = 1.; + sz = fast_atoreal_move(sz, w); + for (unsigned int dim = 0; dim < dimensions; ++dim ) { + *(vec[dim]) /= w; + } + } + + // read optional normals + if (hasNormals) { + aiVector3D& n = mesh->mNormals[i]; + SkipSpaces(&sz); + sz = fast_atoreal_move(sz,(ai_real&)n.x); + SkipSpaces(&sz); + sz = fast_atoreal_move(sz,(ai_real&)n.y); + SkipSpaces(&sz); + fast_atoreal_move(sz,(ai_real&)n.z); + } + + // reading colors is a pain because the specification says it can be + // integers or floats, and any number of them between 1 and 4 included, + // until the next comment or end of line + // in theory should be testing type ! + if (hasColors) { + aiColor4D& c = mesh->mColors[0][i]; + SkipSpaces(&sz); + sz = fast_atoreal_move(sz,(ai_real&)c.r); + if (*sz != '#' && *sz != '\n' && *sz != '\r') { + SkipSpaces(&sz); + sz = fast_atoreal_move(sz,(ai_real&)c.g); + } else { + c.g = 0.; + } + if (*sz != '#' && *sz != '\n' && *sz != '\r') { + SkipSpaces(&sz); + sz = fast_atoreal_move(sz,(ai_real&)c.b); + } else { + c.b = 0.; + } + if (*sz != '#' && *sz != '\n' && *sz != '\r') { + SkipSpaces(&sz); + sz = fast_atoreal_move(sz,(ai_real&)c.a); + } else { + c.a = 1.; + } + } + if (hasTexCoord) { + aiVector3D& t = mesh->mTextureCoords[0][i]; + SkipSpaces(&sz); + sz = fast_atoreal_move(sz,(ai_real&)t.x); + SkipSpaces(&sz); + fast_atoreal_move(sz,(ai_real&)t.y); + } } - - // First find out how many vertices we'll need - const char* old = buffer; - for (unsigned int i = 0; i< mesh->mNumFaces;++i) - { - if(!GetNextLine(buffer,line)) - { + // load faces with their indices + faces = mesh->mFaces; + for (unsigned int i = 0; i < numFaces; ++i ) { + if(!GetNextLine(buffer,line)) { ASSIMP_LOG_ERROR("OFF: The number of faces in the header is incorrect"); break; } - sz = line;SkipSpaces(&sz); - faces->mNumIndices = strtoul10(sz,&sz); - if(!(faces->mNumIndices) || faces->mNumIndices > 9) - { - ASSIMP_LOG_ERROR("OFF: Faces with zero indices aren't allowed"); + unsigned int idx; + sz = line; SkipSpaces(&sz); + idx = strtoul10(sz,&sz); + if(!idx || idx > 9) { + ASSIMP_LOG_ERROR("OFF: Faces with zero indices aren't allowed"); --mesh->mNumFaces; continue; - } - mesh->mNumVertices += faces->mNumIndices; - ++faces; - } - - if (!mesh->mNumVertices) - throw DeadlyImportError("OFF: There are no valid faces"); - - // allocate storage for the output vertices - std::vector verts; - verts.reserve(mesh->mNumVertices); - - // second: now parse all face indices - buffer = old; - faces = mesh->mFaces; - for (unsigned int i = 0, p = 0; i< mesh->mNumFaces;) - { - if(!GetNextLine(buffer,line))break; - - unsigned int idx; - sz = line;SkipSpaces(&sz); - idx = strtoul10(sz,&sz); - if(!(idx) || idx > 9) - continue; - - faces->mIndices = new unsigned int [faces->mNumIndices]; - for (unsigned int m = 0; m < faces->mNumIndices;++m) - { + } + faces->mNumIndices = idx; + faces->mIndices = new unsigned int[faces->mNumIndices]; + for (unsigned int m = 0; m < faces->mNumIndices;++m) { SkipSpaces(&sz); idx = strtoul10(sz,&sz); - if ((idx) >= numVertices) - { + if (idx >= numVertices) { ASSIMP_LOG_ERROR("OFF: Vertex index is out of range"); - idx = numVertices-1; + idx = numVertices - 1; } - faces->mIndices[m] = p++; - verts.push_back(tempPositions[idx]); + faces->mIndices[m] = idx; } ++i; ++faces; } - - if (mesh->mNumVertices != verts.size()) { - throw DeadlyImportError("OFF: Vertex count mismatch"); - } - mesh->mVertices = new aiVector3D[verts.size()]; - memcpy(mesh->mVertices, &verts[0], verts.size() * sizeof(aiVector3D)); + // generate the output node graph pScene->mRootNode = new aiNode(); pScene->mRootNode->mName.Set(""); @@ -248,8 +338,8 @@ void OFFImporter::InternReadFile( const std::string& pFile, pcMat->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE); pScene->mMaterials[0] = pcMat; - const int twosided =1; - pcMat->AddProperty(&twosided,1,AI_MATKEY_TWOSIDED); + const int twosided = 1; + pcMat->AddProperty(&twosided, 1, AI_MATKEY_TWOSIDED); } #endif // !! ASSIMP_BUILD_NO_OFF_IMPORTER From 30d3c8c6a37a3b098702dfb714fe8e5e2abbfa5e Mon Sep 17 00:00:00 2001 From: sfalexrog Date: Mon, 3 Dec 2018 23:22:34 +0300 Subject: [PATCH 055/472] Fix CMake target alias typo --- code/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index f34aac5c9..6b8d3d322 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -923,7 +923,7 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) ADD_LIBRARY( assimp ${assimp_src} ) -ADD_LIBRARY(assimp::asimp ALIAS assimp) +ADD_LIBRARY(assimp::assimp ALIAS assimp) TARGET_INCLUDE_DIRECTORIES ( assimp PUBLIC $ From ce91f5c88890cc635986ccc52afb56d375efed5d Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 3 Dec 2018 21:24:06 +0100 Subject: [PATCH 056/472] Off-Importer: introduce unittest. --- code/OFFLoader.cpp | 2 +- code/glTF2Importer.cpp | 14 +++-- test/CMakeLists.txt | 2 + test/unit/ImportExport/utOFFImportExport.cpp | 63 ++++++++++++++++++++ test/unit/utObjTools.cpp | 1 - 5 files changed, 76 insertions(+), 6 deletions(-) create mode 100644 test/unit/ImportExport/utOFFImportExport.cpp diff --git a/code/OFFLoader.cpp b/code/OFFLoader.cpp index 977b1b36c..a72e6d9d4 100644 --- a/code/OFFLoader.cpp +++ b/code/OFFLoader.cpp @@ -294,7 +294,7 @@ void OFFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS // load faces with their indices faces = mesh->mFaces; - for (unsigned int i = 0; i < numFaces; ++i ) { + for (unsigned int i = 0; i < numFaces; ) { if(!GetNextLine(buffer,line)) { ASSIMP_LOG_ERROR("OFF: The number of faces in the header is incorrect"); break; diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index ff9fd4269..f6a664e5e 100755 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -1024,20 +1024,26 @@ void glTF2Importer::ImportAnimations(glTF2::Asset& r) } // Use the latest keyframe for the duration of the animation - unsigned int maxDuration = 0; + double maxDuration = 0; for (unsigned int j = 0; j < ai_anim->mNumChannels; ++j) { auto chan = ai_anim->mChannels[j]; if (chan->mNumPositionKeys) { auto lastPosKey = chan->mPositionKeys[chan->mNumPositionKeys - 1]; - if (lastPosKey.mTime > maxDuration) maxDuration = lastPosKey.mTime; + if (lastPosKey.mTime > maxDuration) { + maxDuration = lastPosKey.mTime; + } } if (chan->mNumRotationKeys) { auto lastRotKey = chan->mRotationKeys[chan->mNumRotationKeys - 1]; - if (lastRotKey.mTime > maxDuration) maxDuration = lastRotKey.mTime; + if (lastRotKey.mTime > maxDuration) { + maxDuration = lastRotKey.mTime; + } } if (chan->mNumScalingKeys) { auto lastScaleKey = chan->mScalingKeys[chan->mNumScalingKeys - 1]; - if (lastScaleKey.mTime > maxDuration) maxDuration = lastScaleKey.mTime; + if (lastScaleKey.mTime > maxDuration) { + maxDuration = lastScaleKey.mTime; + } } } ai_anim->mDuration = maxDuration; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 01c8daa09..7e2aec270 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -49,6 +49,7 @@ INCLUDE_DIRECTORIES( if (MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING") endif() + # Add the temporary output directories to the library path to make sure the # Assimp library can be found, even if it is not installed system-wide yet. LINK_DIRECTORIES( ${Assimp_BINARY_DIR} ${AssetImporter_BINARY_DIR}/lib ) @@ -121,6 +122,7 @@ SET( IMPORTERS unit/ImportExport/utCOBImportExport.cpp unit/ImportExport/utOgreImportExport.cpp unit/ImportExport/utQ3BSPFileImportExport.cpp + unit/ImportExport/utOFFImportExport.cpp ) SET( MATERIAL diff --git a/test/unit/ImportExport/utOFFImportExport.cpp b/test/unit/ImportExport/utOFFImportExport.cpp new file mode 100644 index 000000000..a355beab6 --- /dev/null +++ b/test/unit/ImportExport/utOFFImportExport.cpp @@ -0,0 +1,63 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2018, 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 +#include +#include + +class utOFFImportExport : public AbstractImportExportBase { +protected: + virtual bool importerTest() { + ::Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/OFF/Cube.off", aiProcess_ValidateDataStructure); + return nullptr != scene; + } +}; + +TEST_F(utOFFImportExport, importOFFFromFileTest) { + EXPECT_TRUE(importerTest()); +} diff --git a/test/unit/utObjTools.cpp b/test/unit/utObjTools.cpp index 093244eb1..6604dfd59 100644 --- a/test/unit/utObjTools.cpp +++ b/test/unit/utObjTools.cpp @@ -115,4 +115,3 @@ TEST_F( utObjTools, countComponents_TwoLines_Success ) { size_t numComps = test_parser.testGetNumComponentsInDataDefinition(); EXPECT_EQ( 3U, numComps ); } - From b506d35999edcec448b71fa3545f937b9f04dcc2 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 3 Dec 2018 21:53:54 +0100 Subject: [PATCH 057/472] closes https://github.com/assimp/assimp/issues/2247: change include folder from debian package from /usr/lib/include to /usr/include --- assimp.pc.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assimp.pc.in b/assimp.pc.in index 02cf59dc4..c659e19f2 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@ +includedir=@CMAKE_INSTALL_PREFIX@/../include/@ASSIMP_INCLUDE_INSTALL_DIR@ Name: @CMAKE_PROJECT_NAME@ Description: Import various well-known 3D model formats in an uniform manner. From 54be5fdb7b81917e5e624538b6a01a308ed06b02 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 3 Dec 2018 22:03:50 +0100 Subject: [PATCH 058/472] Update XFileParser.cpp --- code/XFileParser.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/code/XFileParser.cpp b/code/XFileParser.cpp index e7bf8518c..95875116f 100644 --- a/code/XFileParser.cpp +++ b/code/XFileParser.cpp @@ -583,22 +583,31 @@ void XFileParser::ParseDataObjectMeshNormals( Mesh* pMesh) pMesh->mNormals.resize( numNormals); // read normal vectors - for( unsigned int a = 0; a < numNormals; a++) + for( unsigned int a = 0; a < numNormals; ++a) { pMesh->mNormals[a] = ReadVector3(); + } // read normal indices unsigned int numFaces = ReadInt(); - if( numFaces != pMesh->mPosFaces.size()) + if( numFaces != pMesh->mPosFaces.size()) { ThrowException( "Normal face count does not match vertex face count."); + } - for( unsigned int a = 0; a < numFaces; a++) - { + // do not crah when no face definitions are there + if (numFaces == 0) { + TestForSeparator(); + CheckForClosingBrace(); + return; + + // normal face creation + pMesh->mNormFaces.resize( pMesh->mNormFaces.size() + numFaces ); + for( unsigned int a = 0; a < numFaces; ++a ) { unsigned int numIndices = ReadInt(); - pMesh->mNormFaces.push_back( Face()); + pMesh->mNormFaces.push_back( Face() ); Face& face = pMesh->mNormFaces.back(); - - for( unsigned int b = 0; b < numIndices; b++) + for( unsigned int b = 0; b < numIndices; ++b ) { face.mIndices.push_back( ReadInt()); + } TestForSeparator(); } From b1da322debc6fe1bb549f3d716e8d5787c0e89f8 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 3 Dec 2018 23:13:10 +0100 Subject: [PATCH 059/472] Update XFileParser.cpp Add misisng bracket. --- code/XFileParser.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/code/XFileParser.cpp b/code/XFileParser.cpp index 95875116f..0adddd957 100644 --- a/code/XFileParser.cpp +++ b/code/XFileParser.cpp @@ -598,6 +598,7 @@ void XFileParser::ParseDataObjectMeshNormals( Mesh* pMesh) TestForSeparator(); CheckForClosingBrace(); return; + } // normal face creation pMesh->mNormFaces.resize( pMesh->mNormFaces.size() + numFaces ); From 8b6c6613f9b1408f43f2e411789401966941624d Mon Sep 17 00:00:00 2001 From: twhittock Date: Tue, 4 Dec 2018 14:44:49 +0000 Subject: [PATCH 060/472] collada export: Use Camera local coordinate system Fixes #2255 --- code/ColladaExporter.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/code/ColladaExporter.cpp b/code/ColladaExporter.cpp index 96421a532..0d5bdd46d 100644 --- a/code/ColladaExporter.cpp +++ b/code/ColladaExporter.cpp @@ -1533,7 +1533,23 @@ 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; + aiMatrix4x4 mat = pNode->mTransformation; + + // If this node is a Camera node, the camera coordinate system needs to be multiplied in. + // When importing from Collada, the mLookAt is set to 0, 0, -1, and the node transform is unchanged. + // When importing from a different format, mLookAt is set to 0, 0, 1. Therefore, the local camera + // coordinate system must be changed to matche the Collada specification. + for (size_t i = 0; imNumCameras; i++){ + if (mScene->mCameras[i]->mName == pNode->mName){ + aiMatrix4x4 sourceView; + mScene->mCameras[i]->GetCameraMatrix(sourceView); + + aiMatrix4x4 colladaView; + colladaView.a1 = colladaView.c3 = -1; // move into -z space. + mat *= (sourceView * colladaView); + break; + } + } // customized, sid should be 'matrix' to match with loader code. //mOutput << startstr << ""; From af323de74127ded5e66337bdf585dfe4e19c3d45 Mon Sep 17 00:00:00 2001 From: sfalexrog Date: Tue, 4 Dec 2018 23:28:50 +0300 Subject: [PATCH 061/472] Use ADD_ASSIMP_IMPORTER for STEP importer --- code/CMakeLists.txt | 3 +-- code/Importer/StepFile/StepFileGen1.cpp | 2 +- code/Importer/StepFile/StepFileImporter.cpp | 4 ++-- code/Importer/StepFile/StepFileImporter.h | 4 ++-- code/ImporterRegistry.cpp | 4 ++-- scripts/StepImporter/StepReaderGen.cpp.template | 2 +- 6 files changed, 9 insertions(+), 10 deletions(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 6b8d3d322..e29467164 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -727,7 +727,7 @@ ADD_ASSIMP_IMPORTER( MMD MMDVmdParser.h ) -SET( Step_SRCS +ADD_ASSIMP_IMPORTER( STEP STEPFile.h Importer/StepFile/StepFileImporter.h Importer/StepFile/StepFileImporter.cpp @@ -738,7 +738,6 @@ SET( Step_SRCS StepExporter.h StepExporter.cpp ) -SOURCE_GROUP( Step FILES ${Step_SRCS}) SET( Exporter_SRCS Exporter.cpp diff --git a/code/Importer/StepFile/StepFileGen1.cpp b/code/Importer/StepFile/StepFileGen1.cpp index 32df66c17..50c54818e 100644 --- a/code/Importer/StepFile/StepFileGen1.cpp +++ b/code/Importer/StepFile/StepFileGen1.cpp @@ -40,7 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** MACHINE-GENERATED by scripts/ICFImporter/CppGenerator.py */ -#ifndef ASSIMP_BUILD_NO_STEPFILE_IMPORTER +#ifndef ASSIMP_BUILD_NO_STEP_IMPORTER #include "code/Importer/StepFile/StepReaderGen.h" diff --git a/code/Importer/StepFile/StepFileImporter.cpp b/code/Importer/StepFile/StepFileImporter.cpp index 9bfaf7051..edfe30754 100644 --- a/code/Importer/StepFile/StepFileImporter.cpp +++ b/code/Importer/StepFile/StepFileImporter.cpp @@ -41,7 +41,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------- */ -#ifndef ASSIMP_BUILD_NO_STEPFILE_IMPORTER +#ifndef ASSIMP_BUILD_NO_STEP_IMPORTER #include "StepFileImporter.h" #include "../../Importer/STEPParser/STEPFileReader.h" @@ -110,5 +110,5 @@ void StepFileImporter::InternReadFile(const std::string &file, aiScene* pScene, } // Namespace StepFile } // Namespace Assimp -#endif // ASSIMP_BUILD_NO_STEPFILE_IMPORTER +#endif // ASSIMP_BUILD_NO_STEP_IMPORTER diff --git a/code/Importer/StepFile/StepFileImporter.h b/code/Importer/StepFile/StepFileImporter.h index 7314a54f3..68d5a09ad 100644 --- a/code/Importer/StepFile/StepFileImporter.h +++ b/code/Importer/StepFile/StepFileImporter.h @@ -43,7 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #pragma once -#ifndef ASSIMP_BUILD_NO_STEPFILE_IMPORTER +#ifndef ASSIMP_BUILD_NO_STEP_IMPORTER #include @@ -66,4 +66,4 @@ private: } // Namespace StepFile } // Namespace Assimp -#endif // ASSIMP_BUILD_NO_STEPFILE_IMPORTER +#endif // ASSIMP_BUILD_NO_STEP_IMPORTER diff --git a/code/ImporterRegistry.cpp b/code/ImporterRegistry.cpp index d3ae53c7d..e6cf8299e 100644 --- a/code/ImporterRegistry.cpp +++ b/code/ImporterRegistry.cpp @@ -197,7 +197,7 @@ corresponding preprocessor flag to selectively disable formats. #ifndef ASSIMP_BUILD_NO_MMD_IMPORTER # include "MMDImporter.h" #endif -#ifndef ASSIMP_BUILD_NO_STEPFILE_IMPORTER +#ifndef ASSIMP_BUILD_NO_STEP_IMPORTER # include "Importer/StepFile/StepFileImporter.h" #endif @@ -355,7 +355,7 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out) #ifndef ASSIMP_BUILD_NO_MMD_IMPORTER out.push_back( new MMDImporter() ); #endif -#ifndef ASSIMP_BUILD_NO_STEPFILE_IMPORTER +#ifndef ASSIMP_BUILD_NO_STEP_IMPORTER out.push_back(new StepFile::StepFileImporter()); #endif } diff --git a/scripts/StepImporter/StepReaderGen.cpp.template b/scripts/StepImporter/StepReaderGen.cpp.template index 343c43019..91705f7a4 100644 --- a/scripts/StepImporter/StepReaderGen.cpp.template +++ b/scripts/StepImporter/StepReaderGen.cpp.template @@ -40,7 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** MACHINE-GENERATED by scripts/ICFImporter/CppGenerator.py */ -#ifndef ASSIMP_BUILD_NO_STEPFILE_IMPORTER +#ifndef ASSIMP_BUILD_NO_STEP_IMPORTER #include "code/Importer/StepFile/StepReaderGen.h" From bb9e3c3593ad58cbe7e333aa2877aab28f36b8a3 Mon Sep 17 00:00:00 2001 From: tirichards Date: Wed, 5 Dec 2018 14:46:56 -0800 Subject: [PATCH 062/472] Fix failed assimp validation for glTF2 sample animations --- code/glTF2Importer.cpp | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index f6a664e5e..be319d1da 100755 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -826,15 +826,29 @@ aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector& aiBone* bone = new aiBone(); Ref joint = node.skin->jointNames[i]; - bone->mName = joint->name; + if (!joint->name.empty()) { + bone->mName = joint->name; + } else { + // Assimp expects each bone to have a unique name. + static const std::string kDefaultName = "bone_"; + char postfix[10] = {0}; + ASSIMP_itoa10(postfix, i); + bone->mName = (kDefaultName + postfix); + } GetNodeTransform(bone->mOffsetMatrix, *joint); std::vector& weights = weighting[i]; bone->mNumWeights = weights.size(); if (bone->mNumWeights > 0) { - bone->mWeights = new aiVertexWeight[bone->mNumWeights]; - memcpy(bone->mWeights, weights.data(), bone->mNumWeights * sizeof(aiVertexWeight)); + bone->mWeights = new aiVertexWeight[bone->mNumWeights]; + memcpy(bone->mWeights, weights.data(), bone->mNumWeights * sizeof(aiVertexWeight)); + } else { + // Assimp expects all bones to have at least 1 weight. + bone->mWeights = new aiVertexWeight[1]; + bone->mNumWeights = 1; + bone->mWeights->mVertexId = 0; + bone->mWeights->mWeight = 0.f; } mesh->mBones[i] = bone; } @@ -1022,7 +1036,7 @@ void glTF2Importer::ImportAnimations(glTF2::Asset& r) ++j; } } - + // Use the latest keyframe for the duration of the animation double maxDuration = 0; for (unsigned int j = 0; j < ai_anim->mNumChannels; ++j) { @@ -1047,7 +1061,7 @@ void glTF2Importer::ImportAnimations(glTF2::Asset& r) } } ai_anim->mDuration = maxDuration; - + mScene->mAnimations[i] = ai_anim; } } From f63caf894e8cd5eee6dbfe0fd4c25895ec5ffdcd Mon Sep 17 00:00:00 2001 From: Paul Arden Date: Thu, 6 Dec 2018 12:56:02 +1100 Subject: [PATCH 063/472] Add check for NULL texcoord values. --- code/glTF2Importer.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 740935601..34f8cfcee 100755 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -437,6 +437,12 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r) } for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) { + if (!attr.texcoord[tc]) { + DefaultLogger::get()->warn("NULL texcoord encountered in mesh \"" + mesh.name + + "\" and will be ignored"); + continue; + } + if (attr.texcoord[tc]->count != aim->mNumVertices) { DefaultLogger::get()->warn("Texcoord stream size in mesh \"" + mesh.name + "\" does not match the vertex count"); From b5ebd24688b237abc7ea448b388b005bb0016ce3 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 10 Dec 2018 22:07:26 +0100 Subject: [PATCH 064/472] closes https://github.com/assimp/assimp/issues/817: use emmisive factor instead of color. --- code/FBXConverter.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 0cbe04d8f..7dd9f94b4 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -1559,8 +1559,7 @@ void FBXConverter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMa } const Texture* const tex = ( *it ).second; - if ( tex != 0 ) - { + if ( tex != nullptr ) { aiString path = GetTexturePath(tex); out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, 0 ); @@ -1794,10 +1793,9 @@ void FBXConverter::SetTextureProperties( aiMaterial* out_mat, const TextureMap& { TrySetTextureProperties( out_mat, textures, "DiffuseColor", aiTextureType_DIFFUSE, mesh ); TrySetTextureProperties( out_mat, textures, "AmbientColor", aiTextureType_AMBIENT, mesh ); - TrySetTextureProperties( out_mat, textures, "EmissiveColor", aiTextureType_EMISSIVE, mesh ); - TrySetTextureProperties( out_mat, textures, "SpecularColor", aiTextureType_SPECULAR, mesh ); + TrySetTextureProperties( out_mat, textures, "EmissiveFactor", aiTextureType_EMISSIVE, mesh ); TrySetTextureProperties( out_mat, textures, "SpecularFactor", aiTextureType_SPECULAR, mesh); - TrySetTextureProperties( out_mat, textures, "TransparentColor", aiTextureType_OPACITY, mesh ); + TrySetTextureProperties( out_mat, textures, "TransparencyFactor", aiTextureType_OPACITY, mesh ); TrySetTextureProperties( out_mat, textures, "ReflectionColor", aiTextureType_REFLECTION, mesh ); TrySetTextureProperties( out_mat, textures, "DisplacementColor", aiTextureType_DISPLACEMENT, mesh ); TrySetTextureProperties( out_mat, textures, "NormalMap", aiTextureType_NORMALS, mesh ); @@ -1809,10 +1807,9 @@ void FBXConverter::SetTextureProperties( aiMaterial* out_mat, const LayeredTextu { TrySetTextureProperties( out_mat, layeredTextures, "DiffuseColor", aiTextureType_DIFFUSE, mesh ); TrySetTextureProperties( out_mat, layeredTextures, "AmbientColor", aiTextureType_AMBIENT, mesh ); - TrySetTextureProperties( out_mat, layeredTextures, "EmissiveColor", aiTextureType_EMISSIVE, mesh ); - TrySetTextureProperties( out_mat, layeredTextures, "SpecularColor", aiTextureType_SPECULAR, mesh ); + TrySetTextureProperties( out_mat, layeredTextures, "EmissiveFactor", aiTextureType_EMISSIVE, mesh ); TrySetTextureProperties( out_mat, layeredTextures, "SpecularFactor", aiTextureType_SPECULAR, mesh); - TrySetTextureProperties( out_mat, layeredTextures, "TransparentColor", aiTextureType_OPACITY, mesh ); + TrySetTextureProperties( out_mat, layeredTextures, "TransparencyFactor", aiTextureType_OPACITY, mesh ); TrySetTextureProperties( out_mat, layeredTextures, "ReflectionColor", aiTextureType_REFLECTION, mesh ); TrySetTextureProperties( out_mat, layeredTextures, "DisplacementColor", aiTextureType_DISPLACEMENT, mesh ); TrySetTextureProperties( out_mat, layeredTextures, "NormalMap", aiTextureType_NORMALS, mesh ); From 95d9c16a3b18ad3fcf28337766c518e4817a4aae Mon Sep 17 00:00:00 2001 From: Alexandre Avenel Date: Sat, 8 Dec 2018 22:00:23 +0100 Subject: [PATCH 065/472] Add minimal unit-test for LWO file format --- test/CMakeLists.txt | 1 + test/unit/utLWOImportExport.cpp | 81 +++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 test/unit/utLWOImportExport.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7e2aec270..82d320bed 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -81,6 +81,7 @@ SET( COMMON SET( IMPORTERS unit/utLWSImportExport.cpp + unit/utLWOImportExport.cpp unit/utSMDImportExport.cpp unit/utglTFImportExport.cpp unit/utglTF2ImportExport.cpp diff --git a/test/unit/utLWOImportExport.cpp b/test/unit/utLWOImportExport.cpp new file mode 100644 index 000000000..7e03ee2e4 --- /dev/null +++ b/test/unit/utLWOImportExport.cpp @@ -0,0 +1,81 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2018, 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 utLWOImportExport : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/boxuv.lwo", aiProcess_ValidateDataStructure); + + EXPECT_EQ(1u, scene->mNumMeshes); + EXPECT_NE(nullptr, scene->mMeshes[0]); + EXPECT_EQ(24u, scene->mMeshes[0]->mNumVertices); + + //This test model is using n-gons, so 6 faces instead of 12 tris + EXPECT_EQ(6u, scene->mMeshes[0]->mNumFaces); + EXPECT_EQ(aiPrimitiveType_POLYGON, scene->mMeshes[0]->mPrimitiveTypes); + EXPECT_EQ(true, scene->mMeshes[0]->HasTextureCoords(0)); + + return nullptr != scene; + } +}; + +TEST_F( utLWOImportExport, importLWObox_uv ) { + EXPECT_TRUE( importerTest() ); +} + +TEST_F(utLWOImportExport, importLWOformatdetection) { + ::Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/LWO/LWO2/formatDetection", aiProcess_ValidateDataStructure); + + EXPECT_NE(nullptr, scene); +} + From b25975af481550b4bd291db8ba8350ab16c1eb1c Mon Sep 17 00:00:00 2001 From: Alexandre Avenel Date: Sat, 8 Dec 2018 22:52:23 +0100 Subject: [PATCH 066/472] Add unit-test for STL format auto detection --- test/unit/utSTLImportExport.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/unit/utSTLImportExport.cpp b/test/unit/utSTLImportExport.cpp index ee62253fd..77602a882 100644 --- a/test/unit/utSTLImportExport.cpp +++ b/test/unit/utSTLImportExport.cpp @@ -80,6 +80,12 @@ TEST_F(utSTLImporterExporter, test_multiple) { EXPECT_NE(nullptr, scene2); } +TEST_F(utSTLImporterExporter, importSTLformatdetection) { + ::Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/STL/formatDetection", aiProcess_ValidateDataStructure); + + EXPECT_NE(nullptr, scene); +} TEST_F( utSTLImporterExporter, test_with_two_solids ) { Assimp::Importer importer; From b226982a3c60c732605576dd587ebe7c1e24a166 Mon Sep 17 00:00:00 2001 From: Alexandre Avenel Date: Sun, 9 Dec 2018 18:11:22 +0100 Subject: [PATCH 067/472] Add formatDetection unit-test for 3DS importer --- test/unit/ut3DSImportExport.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/unit/ut3DSImportExport.cpp b/test/unit/ut3DSImportExport.cpp index b40694132..0f91e0f7d 100644 --- a/test/unit/ut3DSImportExport.cpp +++ b/test/unit/ut3DSImportExport.cpp @@ -66,3 +66,11 @@ public: TEST_F( ut3DSImportExport, import3DSFromFileTest ) { EXPECT_TRUE( importerTest() ); } + +TEST_F( ut3DSImportExport, import3DSformatdetection) { + ::Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/3DS/testFormatDetection", aiProcess_ValidateDataStructure); + + EXPECT_NE(nullptr, scene); +} + From b71b7982b5012d5a233b519511d9f33bd272447c Mon Sep 17 00:00:00 2001 From: Alexandre Avenel Date: Sat, 8 Dec 2018 22:58:24 +0100 Subject: [PATCH 068/472] Add silent flag to assimp cmd Add a new command line flag to assimp cmd in order to only display minimal info when loading a file. This is especially useful for quick profiling/fuzzing. --- tools/assimp_cmd/Info.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tools/assimp_cmd/Info.cpp b/tools/assimp_cmd/Info.cpp index ae858bfe8..d6d3de804 100644 --- a/tools/assimp_cmd/Info.cpp +++ b/tools/assimp_cmd/Info.cpp @@ -54,7 +54,8 @@ const char* AICMD_MSG_INFO_HELP_E = "assimp info [-r] [-v]\n" "\tPrint basic structure of a 3D model\n" "\t-r,--raw: No postprocessing, do a raw import\n" -"\t-v,--verbose: Print verbose info such as node transform data\n"; +"\t-v,--verbose: Print verbose info such as node transform data\n" +"\t-s, --silent: Print only minimal info\n"; const std::string TREE_BRANCH_ASCII = "|-"; const std::string TREE_BRANCH_UTF8 = "\xe2\x94\x9c\xe2\x95\xb4"; @@ -305,6 +306,7 @@ int Assimp_Info (const char* const* params, unsigned int num) // get -r and -v arguments bool raw = false; bool verbose = false; + bool silent = false; for(unsigned int i = 1; i < num; ++i) { if (!strcmp(params[i],"--raw")||!strcmp(params[i],"-r")) { raw = true; @@ -312,6 +314,9 @@ int Assimp_Info (const char* const* params, unsigned int num) if (!strcmp(params[i],"--verbose")||!strcmp(params[i],"-v")) { verbose = true; } + if (!strcmp(params[i], "--silent") || !strcmp(params[i], "-s")) { + silent = true; + } } // do maximum post-processing unless -r was specified @@ -380,6 +385,12 @@ int Assimp_Info (const char* const* params, unsigned int num) ) ; + if (silent) + { + printf("\n"); + return 0; + } + // meshes if (scene->mNumMeshes) { printf("\nMeshes: (name) [vertices / bones / faces | primitive_types]\n"); From 3c1d6a3f874b3298f1fd6b8487a03e2f1d92f9ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Iraolagoit=C3=ADa?= Date: Wed, 19 Dec 2018 20:28:43 -0300 Subject: [PATCH 069/472] Fix animations import in gltf2 --- code/glTF2Importer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 67c26bf62..107281a33 100755 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -1033,12 +1033,12 @@ void glTF2Importer::ImportAnimations(glTF2::Asset& r) std::unordered_map samplers = GatherSamplers(anim); - ai_anim->mNumChannels = r.skins[0].jointNames.size(); + ai_anim->mNumChannels = samplers.size(); if (ai_anim->mNumChannels > 0) { ai_anim->mChannels = new aiNodeAnim*[ai_anim->mNumChannels]; int j = 0; - for (auto& iter : r.skins[0].jointNames) { - ai_anim->mChannels[j] = CreateNodeAnim(r, *iter, samplers[iter.GetIndex()]); + for (auto& iter : samplers) { + ai_anim->mChannels[j] = CreateNodeAnim(r, r.nodes[iter.first], iter.second); ++j; } } From 7ce8c9778b56a59912668a2ef9aa8729202c8809 Mon Sep 17 00:00:00 2001 From: Maxim Petrovsky Date: Thu, 20 Dec 2018 16:50:38 +0200 Subject: [PATCH 070/472] added arm64e to iOS build script added arm64e iOS cmake file --- port/iOS/IPHONEOS_ARM64E_TOOLCHAIN.cmake | 17 +++++++++++++++++ port/iOS/build.sh | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 port/iOS/IPHONEOS_ARM64E_TOOLCHAIN.cmake diff --git a/port/iOS/IPHONEOS_ARM64E_TOOLCHAIN.cmake b/port/iOS/IPHONEOS_ARM64E_TOOLCHAIN.cmake new file mode 100644 index 000000000..0cf2b6b66 --- /dev/null +++ b/port/iOS/IPHONEOS_ARM64E_TOOLCHAIN.cmake @@ -0,0 +1,17 @@ +INCLUDE(CMakeForceCompiler) + +SET (CMAKE_CROSSCOMPILING TRUE) +SET (CMAKE_SYSTEM_NAME "Darwin") +SET (CMAKE_SYSTEM_PROCESSOR "arm64e") +SET (IOS TRUE) + +SET (IOS_SDK_DEVICE iPhoneOS) + +SET (SDKVER "${IOS_SDK_VERSION}") +SET (DEVROOT "${XCODE_ROOT_DIR}/Platforms/${IOS_SDK_DEVICE}.platform/Developer") + + +SET (CMAKE_FIND_ROOT_PATH "${SDKROOT}" "${DEVROOT}") +SET (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +SET (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +SET (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) \ No newline at end of file diff --git a/port/iOS/build.sh b/port/iOS/build.sh index 288c9c4a4..f118c45c1 100755 --- a/port/iOS/build.sh +++ b/port/iOS/build.sh @@ -31,7 +31,7 @@ TOOLCHAIN=$XCODE_ROOT_DIR/Toolchains/XcodeDefault.xctoolchain CMAKE_C_COMPILER=$(xcrun -find cc) CMAKE_CXX_COMPILER=$(xcrun -find c++) -BUILD_ARCHS_DEVICE="arm64 armv7s armv7" +BUILD_ARCHS_DEVICE="arm64e arm64 armv7s armv7" BUILD_ARCHS_SIMULATOR="x86_64 i386" BUILD_ARCHS_ALL=($BUILD_ARCHS_DEVICE $BUILD_ARCHS_SIMULATOR) From b4c427912f1f4875cdcb524b1a6a6fbc5fe33bdd Mon Sep 17 00:00:00 2001 From: Maxim Petrovsky Date: Thu, 20 Dec 2018 16:51:01 +0200 Subject: [PATCH 071/472] added bitcode ios --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 645d92689..a97174de4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -119,6 +119,7 @@ IF (IOS) IF (NOT CMAKE_BUILD_TYPE) SET(CMAKE_BUILD_TYPE "Release") ENDIF (NOT CMAKE_BUILD_TYPE) + ADD_DEFINITIONS(-DENABLE_BITCODE) ENDIF (IOS) # Use subset of Windows.h @@ -126,6 +127,7 @@ if (WIN32) ADD_DEFINITIONS( -DWIN32_LEAN_AND_MEAN ) endif() + IF(MSVC) OPTION( ASSIMP_INSTALL_PDB "Install MSVC debug files." From ad7964be63ec71d45d897c79cc1201d364ad49cd Mon Sep 17 00:00:00 2001 From: Marco Di Benedetto Date: Fri, 21 Dec 2018 10:36:03 +0100 Subject: [PATCH 072/472] imported animation fix. --- code/glTF2Importer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 67c26bf62..107281a33 100755 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -1033,12 +1033,12 @@ void glTF2Importer::ImportAnimations(glTF2::Asset& r) std::unordered_map samplers = GatherSamplers(anim); - ai_anim->mNumChannels = r.skins[0].jointNames.size(); + ai_anim->mNumChannels = samplers.size(); if (ai_anim->mNumChannels > 0) { ai_anim->mChannels = new aiNodeAnim*[ai_anim->mNumChannels]; int j = 0; - for (auto& iter : r.skins[0].jointNames) { - ai_anim->mChannels[j] = CreateNodeAnim(r, *iter, samplers[iter.GetIndex()]); + for (auto& iter : samplers) { + ai_anim->mChannels[j] = CreateNodeAnim(r, r.nodes[iter.first], iter.second); ++j; } } From 194b59b3b21050f6516725e5b18d76829504a863 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 22 Dec 2018 09:12:10 +0100 Subject: [PATCH 073/472] Update Info.cpp Add a simple check to avoid verbose + silent mode together, --- tools/assimp_cmd/Info.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/assimp_cmd/Info.cpp b/tools/assimp_cmd/Info.cpp index d6d3de804..050dbf989 100644 --- a/tools/assimp_cmd/Info.cpp +++ b/tools/assimp_cmd/Info.cpp @@ -319,6 +319,12 @@ int Assimp_Info (const char* const* params, unsigned int num) } } + // Verbose and silent at the same time are not allowed + if ( verbose && silent ) { + printf("assimp info: Invalid arguments, verbose and silent at the same time are forbitten. "); + return 1; + } + // do maximum post-processing unless -r was specified ImportData import; if (!raw) { From a65535343050fa2dac18f150bffdedde528f9bd8 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 22 Dec 2018 11:20:31 +0100 Subject: [PATCH 074/472] Update Readme.md Add issue solution time-tracking. --- Readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Readme.md b/Readme.md index 1ba026d5a..6bffbdcee 100644 --- a/Readme.md +++ b/Readme.md @@ -10,6 +10,7 @@ A library to import and export various 3d-model-formats including scene-post-pro [![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) +[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Average time to resolve an issue")
    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. From 1a32558d47b2cf87e83f87f5f85bc0daec23fc32 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 22 Dec 2018 15:17:10 +0100 Subject: [PATCH 075/472] Update Readme.md Add codacy badge. --- Readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Readme.md b/Readme.md index 6bffbdcee..7f42fb75c 100644 --- a/Readme.md +++ b/Readme.md @@ -11,6 +11,7 @@ A library to import and export various 3d-model-formats including scene-post-pro [![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) [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Average time to resolve an issue") +[![Codacy Badge](https://api.codacy.com/project/badge/Grade/5be56faac64f46fc941ac890fb4febef)](https://www.codacy.com/app/kimkulling/assimp?utm_source=github.com&utm_medium=referral&utm_content=assimp/assimp&utm_campaign=Badge_Grade)
    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. From e5f6a72eccafcfab85339372876dbef244d3ead7 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 22 Dec 2018 21:04:52 +0100 Subject: [PATCH 076/472] Update .travis.yml make coverity scan looking for master. --- .travis.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index e768c530c..6fefa694e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,10 +33,6 @@ env: matrix: include: - # disabled until clang 5.0 analyzer issues are fixed - # - os: linux - # compiler: clang - # env: ANALYZE=ON - os: linux compiler: clang env: ASAN=ON @@ -51,7 +47,6 @@ matrix: env: ANALYZE=ON - os: linux compiler: gcc -# env: DISABLE_EXPORTERS=YES ENABLE_COVERALLS=ON env: ENABLE_COVERALLS=ON - os: linux compiler: gcc @@ -79,4 +74,4 @@ addons: notification_email: kim.kulling@googlemail.com build_command_prepend: "cmake" build_command: "make" - branch_pattern: coverity_scan + branch_pattern: master From 3087ebb93a7e45d3fcfd53f58c912816660c7cc8 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 23 Dec 2018 11:57:32 +0100 Subject: [PATCH 077/472] JAssimp: fix simple code analysis issues. --- .../jassimp/src/jassimp/AiAnimation.java | 46 +++-- port/jassimp/jassimp/src/jassimp/AiBone.java | 39 ++-- port/jassimp/jassimp/src/jassimp/AiColor.java | 22 +-- .../jassimp/src/jassimp/AiMaterial.java | 26 ++- port/jassimp/jassimp/src/jassimp/AiMesh.java | 178 ++++++++---------- port/jassimp/jassimp/src/jassimp/AiNode.java | 59 +++--- .../jassimp/src/jassimp/AiQuaternion.java | 25 ++- port/jassimp/jassimp/src/jassimp/Jassimp.java | 90 +++++---- 8 files changed, 230 insertions(+), 255 deletions(-) diff --git a/port/jassimp/jassimp/src/jassimp/AiAnimation.java b/port/jassimp/jassimp/src/jassimp/AiAnimation.java index fca3bc53d..777d2a9fe 100644 --- a/port/jassimp/jassimp/src/jassimp/AiAnimation.java +++ b/port/jassimp/jassimp/src/jassimp/AiAnimation.java @@ -54,6 +54,26 @@ import java.util.List; * {@link AiMesh} for a description and comparison of these APIs. */ public final class AiAnimation { + /** + * Name. + */ + private final String m_name; + + /** + * Duration. + */ + private final double m_duration; + + /** + * Ticks per second. + */ + private final double m_ticksPerSecond; + + /** + * Bone animation channels. + */ + private final List m_nodeAnims = new ArrayList(); + /** * Constructor. * @@ -151,29 +171,5 @@ public final class AiAnimation { */ public List getMeshChannels() { throw new UnsupportedOperationException("not implemented yet"); - } - - - /** - * Name. - */ - private final String m_name; - - - /** - * Duration. - */ - private final double m_duration; - - - /** - * Ticks per second. - */ - private final double m_ticksPerSecond; - - - /** - * Bone animation channels. - */ - private final List m_nodeAnims = new ArrayList(); + } } \ No newline at end of file diff --git a/port/jassimp/jassimp/src/jassimp/AiBone.java b/port/jassimp/jassimp/src/jassimp/AiBone.java index 87c4b8199..1e6d49beb 100644 --- a/port/jassimp/jassimp/src/jassimp/AiBone.java +++ b/port/jassimp/jassimp/src/jassimp/AiBone.java @@ -55,6 +55,24 @@ import java.util.List; * writable and may be modified. */ public final class AiBone { + /** + * Name of the bone. + */ + private String m_name; + + + /** + * Bone weights. + */ + private final List m_boneWeights = + new ArrayList(); + + + /** + * Offset matrix. + */ + private Object m_offsetMatrix; + /** * Constructor. */ @@ -114,24 +132,5 @@ public final class AiBone { AiWrapperProvider wrapperProvider) { return (M4) m_offsetMatrix; - } - - - /** - * Name of the bone. - */ - private String m_name; - - - /** - * Bone weights. - */ - private final List m_boneWeights = - new ArrayList(); - - - /** - * Offset matrix. - */ - private Object m_offsetMatrix; + } } diff --git a/port/jassimp/jassimp/src/jassimp/AiColor.java b/port/jassimp/jassimp/src/jassimp/AiColor.java index 25eb251d6..6befeecbd 100644 --- a/port/jassimp/jassimp/src/jassimp/AiColor.java +++ b/port/jassimp/jassimp/src/jassimp/AiColor.java @@ -50,6 +50,16 @@ import java.nio.ByteBuffer; * modify the underlying mesh. */ public final class AiColor { + /** + * Wrapped buffer. + */ + private final ByteBuffer m_buffer; + + /** + * Offset into m_buffer. + */ + private final int m_offset; + /** * Constructor. * @@ -147,16 +157,4 @@ public final class AiColor { return "[" + getRed() + ", " + getGreen() + ", " + getBlue() + ", " + getAlpha() + "]"; } - - - /** - * Wrapped buffer. - */ - private final ByteBuffer m_buffer; - - - /** - * Offset into m_buffer. - */ - private final int m_offset; } diff --git a/port/jassimp/jassimp/src/jassimp/AiMaterial.java b/port/jassimp/jassimp/src/jassimp/AiMaterial.java index 7a9abc0d3..6ba7665fb 100644 --- a/port/jassimp/jassimp/src/jassimp/AiMaterial.java +++ b/port/jassimp/jassimp/src/jassimp/AiMaterial.java @@ -70,6 +70,17 @@ import java.util.Set; * properties (i.e., properties starting with TEX_). */ public final class AiMaterial { + /** + * List of properties. + */ + private final List m_properties = new ArrayList(); + + /** + * Number of textures for each type. + */ + private final Map m_numTextures = + new EnumMap(AiTextureType.class); + /** * Enumerates all supported material properties. */ @@ -1185,18 +1196,5 @@ public final class AiMaterial { @SuppressWarnings("unused") private void setTextureNumber(int type, int number) { m_numTextures.put(AiTextureType.fromRawValue(type), number); - } - - - /** - * List of properties. - */ - private final List m_properties = new ArrayList(); - - - /** - * Number of textures for each type. - */ - private final Map m_numTextures = - new EnumMap(AiTextureType.class); + } } diff --git a/port/jassimp/jassimp/src/jassimp/AiMesh.java b/port/jassimp/jassimp/src/jassimp/AiMesh.java index b6a478d18..3f4a29760 100644 --- a/port/jassimp/jassimp/src/jassimp/AiMesh.java +++ b/port/jassimp/jassimp/src/jassimp/AiMesh.java @@ -153,6 +153,89 @@ public final class AiMesh { private final int SIZEOF_V3D = Jassimp.NATIVE_AIVEKTOR3D_SIZE; + /** + * The primitive types used by this mesh. + */ + private final Set m_primitiveTypes = + EnumSet.noneOf(AiPrimitiveType.class); + + + /** + * Number of vertices in this mesh. + */ + private int m_numVertices = 0; + + + /** + * Number of faces in this mesh. + */ + private int m_numFaces = 0; + + /** + * Material used by this mesh. + */ + private int m_materialIndex = -1; + + /** + * The name of the mesh. + */ + private String m_name = ""; + + /** + * Buffer for vertex position data. + */ + private ByteBuffer m_vertices = null; + + /** + * Buffer for faces/ indices. + */ + private ByteBuffer m_faces = null; + + + /** + * Index structure for m_faces.

    + * + * Only used by meshes that are not pure triangular + */ + private ByteBuffer m_faceOffsets = null; + + /** + * Buffer for normals. + */ + private ByteBuffer m_normals = null; + + /** + * Buffer for tangents. + */ + private ByteBuffer m_tangents = null; + + /** + * Buffer for bitangents. + */ + private ByteBuffer m_bitangents = null; + + /** + * Vertex colors. + */ + private ByteBuffer[] m_colorsets = + new ByteBuffer[JassimpConfig.MAX_NUMBER_COLORSETS]; + + /** + * Number of UV components for each texture coordinate set. + */ + private int[] m_numUVComponents = new int[JassimpConfig.MAX_NUMBER_TEXCOORDS]; + + /** + * Texture coordinates. + */ + private ByteBuffer[] m_texcoords = + new ByteBuffer[JassimpConfig.MAX_NUMBER_TEXCOORDS]; + + /** + * Bones. + */ + private final List m_bones = new ArrayList(); + /** * This class is instantiated via JNI, no accessible constructor. */ @@ -1335,99 +1418,4 @@ public final class AiMesh { } } // }} - - - /** - * The primitive types used by this mesh. - */ - private final Set m_primitiveTypes = - EnumSet.noneOf(AiPrimitiveType.class); - - - /** - * Number of vertices in this mesh. - */ - private int m_numVertices = 0; - - - /** - * Number of faces in this mesh. - */ - private int m_numFaces = 0; - - - /** - * Material used by this mesh. - */ - private int m_materialIndex = -1; - - - /** - * The name of the mesh. - */ - private String m_name = ""; - - - /** - * Buffer for vertex position data. - */ - private ByteBuffer m_vertices = null; - - - /** - * Buffer for faces/ indices. - */ - private ByteBuffer m_faces = null; - - - /** - * Index structure for m_faces.

    - * - * Only used by meshes that are not pure triangular - */ - private ByteBuffer m_faceOffsets = null; - - - /** - * Buffer for normals. - */ - private ByteBuffer m_normals = null; - - - /** - * Buffer for tangents. - */ - private ByteBuffer m_tangents = null; - - - /** - * Buffer for bitangents. - */ - private ByteBuffer m_bitangents = null; - - - /** - * Vertex colors. - */ - private ByteBuffer[] m_colorsets = - new ByteBuffer[JassimpConfig.MAX_NUMBER_COLORSETS]; - - - /** - * Number of UV components for each texture coordinate set. - */ - private int[] m_numUVComponents = new int[JassimpConfig.MAX_NUMBER_TEXCOORDS]; - - - /** - * Texture coordinates. - */ - private ByteBuffer[] m_texcoords = - new ByteBuffer[JassimpConfig.MAX_NUMBER_TEXCOORDS]; - - - /** - * Bones. - */ - private final List m_bones = new ArrayList(); } diff --git a/port/jassimp/jassimp/src/jassimp/AiNode.java b/port/jassimp/jassimp/src/jassimp/AiNode.java index 9345b7af4..e585e0449 100644 --- a/port/jassimp/jassimp/src/jassimp/AiNode.java +++ b/port/jassimp/jassimp/src/jassimp/AiNode.java @@ -55,6 +55,34 @@ import java.util.Map; * the imported scene consists of only a single root node without children. */ public final class AiNode { + /** + * Parent node. + */ + private final AiNode m_parent; + + + /** + * Mesh references. + */ + private final int[] m_meshReferences; + + + /** + * List of children. + */ + private final List m_children = new ArrayList(); + + /** + * List of metadata entries. + */ + private final Map m_metaData = new HashMap(); + + + /** + * Buffer for transformation matrix. + */ + private final Object m_transformationMatrix; + /** * Constructor. * @@ -214,34 +242,5 @@ public final class AiNode { /** * Name. */ - private final String m_name; - - - /** - * Parent node. - */ - private final AiNode m_parent; - - - /** - * Mesh references. - */ - private final int[] m_meshReferences; - - - /** - * List of children. - */ - private final List m_children = new ArrayList(); - - /** - * List of metadata entries. - */ - private final Map m_metaData = new HashMap(); - - - /** - * Buffer for transformation matrix. - */ - private final Object m_transformationMatrix; + private final String m_name; } diff --git a/port/jassimp/jassimp/src/jassimp/AiQuaternion.java b/port/jassimp/jassimp/src/jassimp/AiQuaternion.java index de162631b..00630e644 100644 --- a/port/jassimp/jassimp/src/jassimp/AiQuaternion.java +++ b/port/jassimp/jassimp/src/jassimp/AiQuaternion.java @@ -50,6 +50,17 @@ import java.nio.ByteBuffer; * modify the underlying mesh/animation. */ public final class AiQuaternion { + /** + * Wrapped buffer. + */ + private final ByteBuffer m_buffer; + + + /** + * Offset into m_buffer. + */ + private final int m_offset; + /** * Constructor. * @@ -150,17 +161,5 @@ public final class AiQuaternion { public String toString() { return "[" + getX() + ", " + getY() + ", " + getZ() + ", " + getW() + "]"; - } - - - /** - * Wrapped buffer. - */ - private final ByteBuffer m_buffer; - - - /** - * Offset into m_buffer. - */ - private final int m_offset; + } } \ No newline at end of file diff --git a/port/jassimp/jassimp/src/jassimp/Jassimp.java b/port/jassimp/jassimp/src/jassimp/Jassimp.java index d1b4aae4e..34dbfabc9 100644 --- a/port/jassimp/jassimp/src/jassimp/Jassimp.java +++ b/port/jassimp/jassimp/src/jassimp/Jassimp.java @@ -60,6 +60,44 @@ import java.util.Set; */ public final class Jassimp { + /** + * The native interface. + * + * @param filename the file to load + * @param postProcessing post processing flags + * @return the loaded scene, or null if an error occurred + * @throws IOException if an error occurs + */ + private static native AiScene aiImportFile(String filename, + long postProcessing, AiIOSystem ioSystem) throws IOException; + + + /** + * The active wrapper provider. + */ + private static AiWrapperProvider s_wrapperProvider = + 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(); + /** * The default wrapper provider using built in types. */ @@ -222,7 +260,7 @@ public final class Jassimp { * @param data the matrix data * @return the wrapped matrix */ - static Object wrapMatrix(float[] data) { + private static Object wrapMatrix(float[] data) { return s_wrapperProvider.wrapMatrix4f(data); } @@ -237,7 +275,7 @@ public final class Jassimp { * @param blue blue component * @return the wrapped color */ - static Object wrapColor3(float red, float green, float blue) { + private static Object wrapColor3(float red, float green, float blue) { return wrapColor4(red, green, blue, 1.0f); } @@ -253,7 +291,7 @@ public final class Jassimp { * @param alpha alpha component * @return the wrapped color */ - static Object wrapColor4(float red, float green, float blue, float alpha) { + private static Object wrapColor4(float red, float green, float blue, float alpha) { ByteBuffer temp = ByteBuffer.allocate(4 * 4); temp.putFloat(red); temp.putFloat(green); @@ -274,7 +312,7 @@ public final class Jassimp { * @param z z component * @return the wrapped vector */ - static Object wrapVec3(float x, float y, float z) { + private static Object wrapVec3(float x, float y, float z) { ByteBuffer temp = ByteBuffer.allocate(3 * 4); temp.putFloat(x); temp.putFloat(y); @@ -295,7 +333,7 @@ public final class Jassimp { * @param name the name of the node * @return the wrapped matrix */ - static Object wrapSceneNode(Object parent, Object matrix, int[] meshRefs, + private static Object wrapSceneNode(Object parent, Object matrix, int[] meshRefs, String name) { return s_wrapperProvider.wrapSceneNode(parent, matrix, meshRefs, name); @@ -327,48 +365,9 @@ public final class Jassimp { s_libraryLoaded = true; } } - } } - - /** - * The native interface. - * - * @param filename the file to load - * @param postProcessing post processing flags - * @return the loaded scene, or null if an error occurred - * @throws IOException if an error occurs - */ - private static native AiScene aiImportFile(String filename, - long postProcessing, AiIOSystem ioSystem) throws IOException; - - - /** - * The active wrapper provider. - */ - private static AiWrapperProvider s_wrapperProvider = - 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. */ @@ -384,5 +383,4 @@ public final class Jassimp { public static int NATIVE_UINT_SIZE; public static int NATIVE_DOUBLE_SIZE; public static int NATIVE_LONG_SIZE; - } From f73dd52956ff35cf6af54f668eab5400b540c2ca Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 23 Dec 2018 11:58:48 +0100 Subject: [PATCH 078/472] Fix next finding. --- port/jassimp/jassimp/src/jassimp/AiSceneFlag.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/port/jassimp/jassimp/src/jassimp/AiSceneFlag.java b/port/jassimp/jassimp/src/jassimp/AiSceneFlag.java index 7f7e01ea9..4c7dd6072 100644 --- a/port/jassimp/jassimp/src/jassimp/AiSceneFlag.java +++ b/port/jassimp/jassimp/src/jassimp/AiSceneFlag.java @@ -47,6 +47,11 @@ import java.util.Set; * Status flags for {@link AiScene}s. */ public enum AiSceneFlag { + /** + * The mapped c/c++ integer enum value. + */ + private final int m_rawValue; + /** * Specifies that the scene data structure that was imported is not * complete.

    @@ -143,11 +148,5 @@ public enum AiSceneFlag { */ private AiSceneFlag(int rawValue) { m_rawValue = rawValue; - } - - - /** - * The mapped c/c++ integer enum value. - */ - private final int m_rawValue; + } } From e9d1330eddbd4d02174a7d06baf35e0e5b556ba5 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 23 Dec 2018 12:01:08 +0100 Subject: [PATCH 079/472] Fix next finding. --- .../src/jassimp/AiClassLoaderIOSystem.java | 6 +- .../jassimp/src/jassimp/AiMaterial.java | 61 +++++++++---------- 2 files changed, 32 insertions(+), 35 deletions(-) diff --git a/port/jassimp/jassimp/src/jassimp/AiClassLoaderIOSystem.java b/port/jassimp/jassimp/src/jassimp/AiClassLoaderIOSystem.java index e14a87f77..95afc2e02 100644 --- a/port/jassimp/jassimp/src/jassimp/AiClassLoaderIOSystem.java +++ b/port/jassimp/jassimp/src/jassimp/AiClassLoaderIOSystem.java @@ -139,10 +139,8 @@ public class AiClassLoaderIOSystem implements AiIOSystem { return false; } - else - { - return true; - } + + return true; } diff --git a/port/jassimp/jassimp/src/jassimp/AiMaterial.java b/port/jassimp/jassimp/src/jassimp/AiMaterial.java index 6ba7665fb..bf077dff3 100644 --- a/port/jassimp/jassimp/src/jassimp/AiMaterial.java +++ b/port/jassimp/jassimp/src/jassimp/AiMaterial.java @@ -328,7 +328,36 @@ public final class AiMaterial { * properties easily. */ public static final class Property { + /** + * Key. + */ + private final String m_key; + + /** + * Semantic. + */ + private final int m_semantic; + + + /** + * Index. + */ + private final int m_index; + + + /** + * Type. + */ + private final PropertyType m_type; + + + /** + * Data. + */ + private final Object m_data; + + /** * Constructor. * * @param key @@ -428,39 +457,9 @@ public final class AiMaterial { * * @return the data */ - Object getData() { + private Object getData() { return m_data; } - - - /** - * Key. - */ - private final String m_key; - - - /** - * Semantic. - */ - private final int m_semantic; - - - /** - * Index. - */ - private final int m_index; - - - /** - * Type. - */ - private final PropertyType m_type; - - - /** - * Data. - */ - private final Object m_data; } From 7eee959d55ce0f6f5d0765038a789b168ddc6eac Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 23 Dec 2018 13:12:57 +0100 Subject: [PATCH 080/472] Review: fix wrong interpretation of methods for JNI. --- port/jassimp/jassimp/src/jassimp/Jassimp.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/port/jassimp/jassimp/src/jassimp/Jassimp.java b/port/jassimp/jassimp/src/jassimp/Jassimp.java index 34dbfabc9..ac072a331 100644 --- a/port/jassimp/jassimp/src/jassimp/Jassimp.java +++ b/port/jassimp/jassimp/src/jassimp/Jassimp.java @@ -260,7 +260,7 @@ public final class Jassimp { * @param data the matrix data * @return the wrapped matrix */ - private static Object wrapMatrix(float[] data) { + static Object wrapMatrix(float[] data) { return s_wrapperProvider.wrapMatrix4f(data); } @@ -275,7 +275,7 @@ public final class Jassimp { * @param blue blue component * @return the wrapped color */ - private static Object wrapColor3(float red, float green, float blue) { + static Object wrapColor3(float red, float green, float blue) { return wrapColor4(red, green, blue, 1.0f); } @@ -291,7 +291,7 @@ public final class Jassimp { * @param alpha alpha component * @return the wrapped color */ - private static Object wrapColor4(float red, float green, float blue, float alpha) { + static Object wrapColor4(float red, float green, float blue, float alpha) { ByteBuffer temp = ByteBuffer.allocate(4 * 4); temp.putFloat(red); temp.putFloat(green); @@ -312,7 +312,7 @@ public final class Jassimp { * @param z z component * @return the wrapped vector */ - private static Object wrapVec3(float x, float y, float z) { + static Object wrapVec3(float x, float y, float z) { ByteBuffer temp = ByteBuffer.allocate(3 * 4); temp.putFloat(x); temp.putFloat(y); From 6631f7877a6406d9701e90343c43a1f92f5c1a5f Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 23 Dec 2018 13:37:03 +0100 Subject: [PATCH 081/472] Update Jassimp.java Fix another misinterpretation from the JNI-interface. --- port/jassimp/jassimp/src/jassimp/Jassimp.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/port/jassimp/jassimp/src/jassimp/Jassimp.java b/port/jassimp/jassimp/src/jassimp/Jassimp.java index ac072a331..727570a5b 100644 --- a/port/jassimp/jassimp/src/jassimp/Jassimp.java +++ b/port/jassimp/jassimp/src/jassimp/Jassimp.java @@ -333,7 +333,7 @@ public final class Jassimp { * @param name the name of the node * @return the wrapped matrix */ - private static Object wrapSceneNode(Object parent, Object matrix, int[] meshRefs, + static Object wrapSceneNode(Object parent, Object matrix, int[] meshRefs, String name) { return s_wrapperProvider.wrapSceneNode(parent, matrix, meshRefs, name); From b3c2fdc11dda34861ec1eadb6280cfac65e88478 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 23 Dec 2018 14:28:40 +0100 Subject: [PATCH 082/472] python: fix review findings. --- port/PyAssimp/pyassimp/core.py | 15 +++++------ port/PyAssimp/scripts/3d_viewer_py3.py | 36 ++++++++++++-------------- 2 files changed, 22 insertions(+), 29 deletions(-) diff --git a/port/PyAssimp/pyassimp/core.py b/port/PyAssimp/pyassimp/core.py index 64dd351a7..25821ff9b 100644 --- a/port/PyAssimp/pyassimp/core.py +++ b/port/PyAssimp/pyassimp/core.py @@ -29,7 +29,6 @@ from . import structs from . import helper from . import postprocess from .errors import AssimpError -from .formats import available_formats class AssimpLib(object): """ @@ -300,14 +299,12 @@ def load(filename, ''' if hasattr(filename, 'read'): - ''' - 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, - unsigned int pFlags, - const char* pHint) - ''' + # 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, + # unsigned int pFlags, + # const char* pHint) if file_type == None: raise AssimpError('File type must be specified when passing file objects!') data = filename.read() diff --git a/port/PyAssimp/scripts/3d_viewer_py3.py b/port/PyAssimp/scripts/3d_viewer_py3.py index 4c88edc7b..477b1a103 100755 --- a/port/PyAssimp/scripts/3d_viewer_py3.py +++ b/port/PyAssimp/scripts/3d_viewer_py3.py @@ -1177,6 +1177,22 @@ class PyAssimp3DViewer: return True def controls_3d(self, dx, dy, zooming_one_shot=False): + """ 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 """ CAMERA_TRANSLATION_FACTOR = 0.01 CAMERA_ROTATION_FACTOR = 0.01 @@ -1188,26 +1204,6 @@ class PyAssimp3DViewer: 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) From 49cce86f5f7f237e33fe13c23fad2fd9319f2fb7 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 26 Dec 2018 13:40:22 +0100 Subject: [PATCH 083/472] Testing: improve test coverage: --- test/CMakeLists.txt | 2 + test/unit/ImportExport/utNFFImportExport.cpp | 63 ++++++++++++++++++++ test/unit/ImportExport/utXGLImportExport.cpp | 63 ++++++++++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 test/unit/ImportExport/utNFFImportExport.cpp create mode 100644 test/unit/ImportExport/utXGLImportExport.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 82d320bed..210d95550 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -124,6 +124,8 @@ SET( IMPORTERS unit/ImportExport/utOgreImportExport.cpp unit/ImportExport/utQ3BSPFileImportExport.cpp unit/ImportExport/utOFFImportExport.cpp + unit/ImportExport/utNFFImportExport.cpp + unit/ImportExport/utXGLImportExport.cpp ) SET( MATERIAL diff --git a/test/unit/ImportExport/utNFFImportExport.cpp b/test/unit/ImportExport/utNFFImportExport.cpp new file mode 100644 index 000000000..aca9e0392 --- /dev/null +++ b/test/unit/ImportExport/utNFFImportExport.cpp @@ -0,0 +1,63 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2018, 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 utNFFImportExport : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/NFF/NFF/ManyEarthsNotJustOne.nff", 0); + return true; + return nullptr != scene; + } +}; + +TEST_F(utNFFImportExport, importNFFFromFileTest) { + EXPECT_TRUE(importerTest()); +} diff --git a/test/unit/ImportExport/utXGLImportExport.cpp b/test/unit/ImportExport/utXGLImportExport.cpp new file mode 100644 index 000000000..8f82ba48d --- /dev/null +++ b/test/unit/ImportExport/utXGLImportExport.cpp @@ -0,0 +1,63 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2018, 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 utXGLImportExport : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/XGL/sample_official.xgl", 0); + return true; + return nullptr != scene; + } +}; + +TEST_F(utXGLImportExport, importXGLFromFileTest) { + EXPECT_TRUE(importerTest()); +} From bc97e45d3939c5ada3031b54485b17a347326252 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 26 Dec 2018 18:22:29 +0100 Subject: [PATCH 084/472] Update .travis.yml revert name of branch --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6fefa694e..e222db23f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -74,4 +74,4 @@ addons: notification_email: kim.kulling@googlemail.com build_command_prepend: "cmake" build_command: "make" - branch_pattern: master + branch_pattern: coverity_scan From 4c6db68d34906d6686683ce382dd49c327ab118a Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 27 Dec 2018 22:28:23 +0100 Subject: [PATCH 085/472] Coverity-findings --- code/FBXExportNode.h | 19 ++++++++++++++++--- code/FBXExporter.cpp | 16 +++++++++------- code/XGLLoader.cpp | 10 ++++------ code/glTF2AssetWriter.inl | 3 +++ code/glTF2Exporter.cpp | 5 ++++- 5 files changed, 36 insertions(+), 17 deletions(-) diff --git a/code/FBXExportNode.h b/code/FBXExportNode.h index 5ddd8c77b..b9cd5156f 100644 --- a/code/FBXExportNode.h +++ b/code/FBXExportNode.h @@ -70,14 +70,27 @@ public: // public data members bool force_has_children = false; public: // constructors + /// The default class constructor. Node() = default; - Node(const std::string& n) : name(n) {} + + /// The class constructor with the name. + Node(const std::string& n) + : name(n) + , properties() + , children() + , force_has_children( false ) { + // empty + } // convenience template to construct with properties directly template Node(const std::string& n, const More... more) - : name(n) - { AddProperties(more...); } + : name(n) + , properties() + , children() + , force_has_children(false) { + AddProperties(more...); + } public: // functions to add properties or children // add a single property to the node diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index 037520641..2e153dde0 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -131,13 +131,15 @@ namespace Assimp { } // end of namespace Assimp -FBXExporter::FBXExporter ( - const aiScene* pScene, - const ExportProperties* pProperties -) - : mScene(pScene) - , mProperties(pProperties) -{ +FBXExporter::FBXExporter ( const aiScene* pScene, const ExportProperties* pProperties ) +: binary(false) +, mScene(pScene) +, mProperties(pProperties) +, outfile() +, connections() +, mesh_uids() +, material_uids() +, node_uids() { // will probably need to determine UIDs, connections, etc here. // basically anything that needs to be known // before we start writing sections to the stream. diff --git a/code/XGLLoader.cpp b/code/XGLLoader.cpp index 0706ffd55..196f20e90 100644 --- a/code/XGLLoader.cpp +++ b/code/XGLLoader.cpp @@ -731,11 +731,10 @@ unsigned int XGLImporter::ResolveMaterialRef(TempScope& scope) } // ------------------------------------------------------------------------------------------------ -void XGLImporter::ReadMaterial(TempScope& scope) -{ +void XGLImporter::ReadMaterial(TempScope& scope) { const unsigned int mat_id = ReadIDAttr(); - std::unique_ptr mat(new aiMaterial()); + aiMaterial *mat(new aiMaterial ); while (ReadElementUpToClosing("mat")) { const std::string& s = GetElementName(); if (s == "amb") { @@ -764,11 +763,10 @@ void XGLImporter::ReadMaterial(TempScope& scope) } } - scope.materials[mat_id] = mat.get(); - scope.materials_linear.push_back(mat.release()); + scope.materials[mat_id] = mat; + scope.materials_linear.push_back(mat); } - // ---------------------------------------------------------------------------------------------- void XGLImporter::ReadFaceVertex(const TempMesh& t, TempFace& out) { diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl index 50d855aaa..75726fd08 100644 --- a/code/glTF2AssetWriter.inl +++ b/code/glTF2AssetWriter.inl @@ -744,6 +744,9 @@ namespace glTF2 { if (!(dict = FindArray(*container, d.mDictId))) { container->AddMember(StringRef(d.mDictId), Value().SetArray().Move(), mDoc.GetAllocator()); dict = FindArray(*container, d.mDictId); + if (nullptr == dict) { + return; + } } for (size_t i = 0; i < d.mObjs.size(); ++i) { diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index 40db27264..2c6bab2e0 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -643,11 +643,12 @@ void ExportSkin(Asset& mAsset, const aiMesh* aimesh, Ref& meshRef, Ref buf = vertexJointAccessor->bufferView->buffer; uint8_t* arrys = new uint8_t[bytesLen]; unsigned int i = 0; + uint8_t* data = new uint8_t[s_bytesPerComp]; for ( unsigned int j = 0; j <= bytesLen; j += bytesPerComp ){ size_t len_p = offset + j; float f_value = *(float *)&buf->GetPointer()[len_p]; unsigned short c = static_cast(f_value); - uint8_t* data = new uint8_t[s_bytesPerComp]; + ::memset(data, 0, s_bytesPerComp * sizeof(uint8_t)); data = (uint8_t*)&c; memcpy(&arrys[i*s_bytesPerComp], data, s_bytesPerComp); ++i; @@ -657,6 +658,8 @@ void ExportSkin(Asset& mAsset, const aiMesh* aimesh, Ref& meshRef, RefbufferView->byteLength = s_bytesLen; p.attributes.joint.push_back( vertexJointAccessor ); + delete[] arrys; + delete[] data; } Ref vertexWeightAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices, vertexWeightData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT); From 859153e3e6ac053934dd6a689b9ecefacecfb07b Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 28 Dec 2018 01:44:56 +0100 Subject: [PATCH 086/472] more fixes for coverity-findings. --- code/ColladaLoader.cpp | 33 +++++++++++++++++-------------- test/unit/utPLYImportExport.cpp | 3 +++ test/unit/utglTF2ImportExport.cpp | 5 +++-- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/code/ColladaLoader.cpp b/code/ColladaLoader.cpp index d86985a29..ab896c000 100644 --- a/code/ColladaLoader.cpp +++ b/code/ColladaLoader.cpp @@ -85,24 +85,27 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer ColladaLoader::ColladaLoader() - : mFileName() - , mMeshIndexByID() - , mMaterialIndexByName() - , mMeshes() - , newMats() - , mCameras() - , mLights() - , mTextures() - , mAnims() - , noSkeletonMesh( false ) - , ignoreUpDirection(false) - , mNodeNameCounter( 0 ) -{} +: mFileName() +, mMeshIndexByID() +, mMaterialIndexByName() +, mMeshes() +, newMats() +, mCameras() +, mLights() +, mTextures() +, mAnims() +, noSkeletonMesh( false ) +, ignoreUpDirection(false) +, useColladaName( false ) +, mNodeNameCounter( 0 ) { + // empty +} // ------------------------------------------------------------------------------------------------ // Destructor, private as well -ColladaLoader::~ColladaLoader() -{} +ColladaLoader::~ColladaLoader() { + // empty +} // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. diff --git a/test/unit/utPLYImportExport.cpp b/test/unit/utPLYImportExport.cpp index 5aabe0805..540996b21 100644 --- a/test/unit/utPLYImportExport.cpp +++ b/test/unit/utPLYImportExport.cpp @@ -56,6 +56,9 @@ public: const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", aiProcess_ValidateDataStructure); EXPECT_EQ( 1u, scene->mNumMeshes ); EXPECT_NE( nullptr, scene->mMeshes[0] ); + if (nullptr == scene->mMeshes[0]) { + return false; + } EXPECT_EQ( 8u, scene->mMeshes[0]->mNumVertices ); EXPECT_EQ( 6u, scene->mMeshes[0]->mNumFaces ); diff --git a/test/unit/utglTF2ImportExport.cpp b/test/unit/utglTF2ImportExport.cpp index 264580aad..08fa9d989 100644 --- a/test/unit/utglTF2ImportExport.cpp +++ b/test/unit/utglTF2ImportExport.cpp @@ -356,11 +356,12 @@ std::vector ReadFile(const char* name) { } ::fseek(p, 0, SEEK_END); - const auto size = ::ftell(p); + const size_t size = ::ftell(p); ::fseek(p, 0, SEEK_SET); ret.resize(size); - ::fread(&ret[0], 1, size, p); + const size_t readSize = ::fread(&ret[0], 1, size, p); + EXPECT_EQ(readSize, size); ::fclose(p); return ret; From db202584ab55328de2488e5ad5f6208f2d7aae29 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 28 Dec 2018 01:45:47 +0100 Subject: [PATCH 087/472] remove dead code. --- code/ColladaExporter.cpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/code/ColladaExporter.cpp b/code/ColladaExporter.cpp index 0d5bdd46d..9d66741eb 100644 --- a/code/ColladaExporter.cpp +++ b/code/ColladaExporter.cpp @@ -1500,24 +1500,18 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) // 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())) { + if (nullptr == 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())) + if (!pNode->mParent || nullptr == 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 - << " Date: Fri, 28 Dec 2018 11:17:27 +0100 Subject: [PATCH 088/472] fix more findings. --- code/SceneCombiner.cpp | 6 +++++- code/XGLLoader.cpp | 6 +++--- code/glTF2Asset.h | 6 +++++- code/glTF2Importer.cpp | 6 ++++++ 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/code/SceneCombiner.cpp b/code/SceneCombiner.cpp index 883447372..2271194ca 100644 --- a/code/SceneCombiner.cpp +++ b/code/SceneCombiner.cpp @@ -738,7 +738,11 @@ void SceneCombiner::MergeBones(aiMesh* out,std::vector::const_iterator // And copy the final weights - adjust the vertex IDs by the // face index offset of the corresponding mesh. - for (std::vector< BoneSrcIndex >::const_iterator wmit = (*boneIt).pSrcBones.begin(); wmit != wend; ++wmit) { + for (std::vector< BoneSrcIndex >::const_iterator wmit = (*boneIt).pSrcBones.begin(); wmit != (*boneIt).pSrcBones.end(); ++wmit) { + if (wmit == wend) { + break; + } + aiBone* pip = (*wmit).first; for (unsigned int mp = 0; mp < pip->mNumWeights;++mp,++avw) { const aiVertexWeight& vfi = pip->mWeights[mp]; diff --git a/code/XGLLoader.cpp b/code/XGLLoader.cpp index 196f20e90..2dfd51284 100644 --- a/code/XGLLoader.cpp +++ b/code/XGLLoader.cpp @@ -370,7 +370,7 @@ aiLight* XGLImporter::ReadDirectionalLight() // ------------------------------------------------------------------------------------------------ aiNode* XGLImporter::ReadObject(TempScope& scope, bool skipFirst, const char* closetag) { - std::unique_ptr nd(new aiNode()); + aiNode *nd = new aiNode; std::vector children; std::vector meshes; @@ -453,11 +453,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.get(); + children[i]->mParent = nd; } } - return nd.release(); + return nd; } // ------------------------------------------------------------------------------------------------ diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 92be82f3b..6672dd7a9 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -656,7 +656,11 @@ namespace glTF2 } ortographic; } cameraProperties; - Camera() {} + Camera() + : type(Perspective) + , cameraProperties() { + // empty + } void Read(Value& obj, Asset& r); }; diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 107281a33..20c28f498 100755 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -763,6 +763,12 @@ static void BuildVertexWeightMapping(Mesh::Primitive& primitive, std::vectorExtractData(indices16); } + // + if (nullptr == indices8 && nullptr == indices16) { + // Something went completely wrong! + ai_assert(false); + return; + } for (int i = 0; i < num_vertices; ++i) { for (int j = 0; j < 4; ++j) { From f5e94a2840ae2a03310cfab51d668f1ba9d9c45f Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 29 Dec 2018 21:27:20 +0100 Subject: [PATCH 089/472] Add a check for the resule of a dynamic cast. --- code/BlenderCustomData.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/code/BlenderCustomData.cpp b/code/BlenderCustomData.cpp index 682186618..6561eaf22 100644 --- a/code/BlenderCustomData.cpp +++ b/code/BlenderCustomData.cpp @@ -28,7 +28,11 @@ namespace Assimp { #define IMPL_STRUCT_READ(ty) \ bool read##ty(ElemBase *v, const size_t cnt, const FileDatabase &db) { \ - return read(db.dna[#ty], dynamic_cast(v), cnt, db); \ + ty *ptr = dynamic_cast(v); \ + if (nullptr == ptr) { \ + return false; \ + } \ + return read(db.dna[#ty], ptr, cnt, db); \ } #define IMPL_STRUCT_CREATE(ty) \ From e09428c95b457c0389766ee7dc69ac82bdd8e33f Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 29 Dec 2018 21:29:42 +0100 Subject: [PATCH 090/472] eremove useless assertion test. --- code/FBXExporter.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index 2e153dde0..ce00deee3 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -2446,7 +2446,6 @@ void FBXExporter::WriteAnimationCurve( // TODO: keyattr flags and data (STUB for now) n.AddChild("KeyAttrFlags", std::vector{0}); n.AddChild("KeyAttrDataFloat", std::vector{0,0,0,0}); - ai_assert(static_cast(times.size()) <= std::numeric_limits::max()); n.AddChild( "KeyAttrRefCount", std::vector{static_cast(times.size())} From 69ea55d1808c8f3cfe3624a3d2cae792f5e87d03 Mon Sep 17 00:00:00 2001 From: carasuca Date: Sun, 30 Dec 2018 02:59:49 +0100 Subject: [PATCH 091/472] Fix: except `SyntaxError` for py3 viewer Following https://www.python.org/dev/peps/pep-3110/ --- port/PyAssimp/scripts/3d_viewer_py3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/port/PyAssimp/scripts/3d_viewer_py3.py b/port/PyAssimp/scripts/3d_viewer_py3.py index 477b1a103..fcee63717 100755 --- a/port/PyAssimp/scripts/3d_viewer_py3.py +++ b/port/PyAssimp/scripts/3d_viewer_py3.py @@ -468,7 +468,7 @@ class PyAssimp3DViewer: try: self.set_shaders_v130() self.prepare_shaders() - except RuntimeError, message: + except RuntimeError as message: sys.stderr.write("%s\n" % message) sys.stdout.write("Could not compile shaders in version 1.30, trying version 1.20\n") From f6cbb26d9c3947313e49deeac5674928dada8c1d Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 30 Dec 2018 10:30:12 +0100 Subject: [PATCH 092/472] Fix unnecessary allocation. --- code/glTF2Exporter.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index 2c6bab2e0..774eedc1e 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -643,14 +643,11 @@ void ExportSkin(Asset& mAsset, const aiMesh* aimesh, Ref& meshRef, Ref buf = vertexJointAccessor->bufferView->buffer; uint8_t* arrys = new uint8_t[bytesLen]; unsigned int i = 0; - uint8_t* data = new uint8_t[s_bytesPerComp]; for ( unsigned int j = 0; j <= bytesLen; j += bytesPerComp ){ size_t len_p = offset + j; float f_value = *(float *)&buf->GetPointer()[len_p]; unsigned short c = static_cast(f_value); - ::memset(data, 0, s_bytesPerComp * sizeof(uint8_t)); - data = (uint8_t*)&c; - memcpy(&arrys[i*s_bytesPerComp], data, s_bytesPerComp); + memcpy(&arrys[i*s_bytesPerComp], &c, s_bytesPerComp); ++i; } buf->ReplaceData_joint(offset, bytesLen, arrys, bytesLen); @@ -659,7 +656,6 @@ void ExportSkin(Asset& mAsset, const aiMesh* aimesh, Ref& meshRef, Ref vertexWeightAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices, vertexWeightData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT); From 8912bb333cbed8a5f20af3f21c7bed2be3a0c43e Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 30 Dec 2018 10:33:21 +0100 Subject: [PATCH 093/472] Fix memory leak. --- code/glTF2Exporter.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index 774eedc1e..d513dc45d 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -658,7 +658,8 @@ void ExportSkin(Asset& mAsset, const aiMesh* aimesh, Ref& meshRef, Ref vertexWeightAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices, vertexWeightData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT); + Ref vertexWeightAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices, + vertexWeightData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT); if ( vertexWeightAccessor ) { p.attributes.weight.push_back( vertexWeightAccessor ); } @@ -747,8 +748,7 @@ void glTF2Exporter::ExportMeshes() } /*************** Vertex colors ****************/ - for (unsigned int indexColorChannel = 0; indexColorChannel < aim->GetNumColorChannels(); ++indexColorChannel) - { + for (unsigned int indexColorChannel = 0; indexColorChannel < aim->GetNumColorChannels(); ++indexColorChannel) { Ref c = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mColors[indexColorChannel], AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT, false); if (c) p.attributes.color.push_back(c); @@ -794,8 +794,12 @@ void glTF2Exporter::ExportMeshes() 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; + 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 @@ -823,10 +827,11 @@ void glTF2Exporter::ExportMeshes() meshNode->skeletons.push_back(rootJoint); meshNode->skin = skinRef; } + delete[] invBindMatrixData; } } -//merges a node's multiple meshes (with one primitive each) into one mesh with multiple primitives +// 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) { From a8fda890797fe0625c75446263f9f9f9c2b9ea70 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 30 Dec 2018 10:36:23 +0100 Subject: [PATCH 094/472] remove unique_ptr ina local function / method. --- code/Importer/IFC/IFCLoader.cpp | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/code/Importer/IFC/IFCLoader.cpp b/code/Importer/IFC/IFCLoader.cpp index 473355538..01cb39773 100644 --- a/code/Importer/IFC/IFCLoader.cpp +++ b/code/Importer/IFC/IFCLoader.cpp @@ -659,8 +659,8 @@ void ProcessMetadata(uint64_t relDefinesByPropertiesID, ConversionData& conv, Me } // ------------------------------------------------------------------------------------------------ -aiNode* ProcessSpatialStructure(aiNode* parent, const Schema_2x3::IfcProduct& el, ConversionData& conv, std::vector* collect_openings = NULL) -{ +aiNode* ProcessSpatialStructure(aiNode* parent, const Schema_2x3::IfcProduct& el, ConversionData& conv, + std::vector* collect_openings = nullptr ) { const STEP::DB::RefMap& refs = conv.db.GetRefs(); // skip over space and annotation nodes - usually, these have no meaning in Assimp's context @@ -675,12 +675,12 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const Schema_2x3::IfcProduct& el if(conv.settings.skipAnnotations) { if(el.ToPtr()) { IFCImporter::LogDebug("skipping IfcAnnotation entity due to importer settings"); - return NULL; + return nullptr; } } // add an output node for this spatial structure - std::unique_ptr nd(new aiNode()); + aiNode *nd(new aiNode ); nd->mName.Set(el.GetClassName()+"_"+(el.Name?el.Name.Get():"Unnamed")+"_"+el.GlobalId); nd->mParent = parent; @@ -693,8 +693,7 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const Schema_2x3::IfcProduct& el if (children.first==children.second) { // handles single property set ProcessMetadata((*children.first).second, conv, properties); - } - else { + } else { // handles multiple property sets (currently all property sets are merged, // which may not be the best solution in the long run) for (STEP::DB::RefMap::const_iterator it=children.first; it!=children.second; ++it) { @@ -751,7 +750,7 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const Schema_2x3::IfcProduct& el continue; } - aiNode* const ndnew = ProcessSpatialStructure(nd.get(),pro,conv,NULL); + aiNode* const ndnew = ProcessSpatialStructure(nd,pro,conv,nullptr); if(ndnew) { subnodes.push_back( ndnew ); } @@ -765,7 +764,7 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const Schema_2x3::IfcProduct& el // move opening elements to a separate node since they are semantically different than elements that are just 'contained' std::unique_ptr nd_aggr(new aiNode()); nd_aggr->mName.Set("$RelVoidsElement"); - nd_aggr->mParent = nd.get(); + nd_aggr->mParent = nd; nd_aggr->mTransformation = nd->mTransformation; @@ -810,7 +809,7 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const Schema_2x3::IfcProduct& el // move aggregate elements to a separate node since they are semantically different than elements that are just 'contained' std::unique_ptr nd_aggr(new aiNode()); nd_aggr->mName.Set("$RelAggregates"); - nd_aggr->mParent = nd.get(); + nd_aggr->mParent = nd; nd_aggr->mTransformation = nd->mTransformation; @@ -835,8 +834,8 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const Schema_2x3::IfcProduct& el } if (!skipGeometry) { - ProcessProductRepresentation(el,nd.get(),subnodes,conv); - conv.apply_openings = conv.collect_openings = NULL; + ProcessProductRepresentation(el, nd, subnodes, conv); + conv.apply_openings = conv.collect_openings = nullptr; } if (subnodes.size()) { @@ -846,8 +845,7 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const Schema_2x3::IfcProduct& el nd2->mParent = nd.get(); } } - } - catch(...) { + } catch(...) { // it hurts, but I don't want to pull boost::ptr_vector into -noboost only for these few spots here std::for_each(subnodes.begin(),subnodes.end(),delete_fun()); throw; @@ -855,7 +853,7 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const Schema_2x3::IfcProduct& el ai_assert(conv.already_processed.find(el.GetID()) != conv.already_processed.end()); conv.already_processed.erase(conv.already_processed.find(el.GetID())); - return nd.release(); + return nd; } // ------------------------------------------------------------------------------------------------ From 281c1913678f130ec04fb8ee5d49975efc12a01b Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 30 Dec 2018 10:44:43 +0100 Subject: [PATCH 095/472] fix streamreader::end definition for iterators. --- code/Importer/IFC/IFCLoader.cpp | 2 +- include/assimp/StreamReader.h | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/code/Importer/IFC/IFCLoader.cpp b/code/Importer/IFC/IFCLoader.cpp index 01cb39773..97c514d44 100644 --- a/code/Importer/IFC/IFCLoader.cpp +++ b/code/Importer/IFC/IFCLoader.cpp @@ -842,7 +842,7 @@ aiNode* ProcessSpatialStructure(aiNode* parent, const Schema_2x3::IfcProduct& el nd->mChildren = new aiNode*[subnodes.size()](); for(aiNode* nd2 : subnodes) { nd->mChildren[nd->mNumChildren++] = nd2; - nd2->mParent = nd.get(); + nd2->mParent = nd; } } } catch(...) { diff --git a/include/assimp/StreamReader.h b/include/assimp/StreamReader.h index b01ee4b66..4e5d2ddfa 100644 --- a/include/assimp/StreamReader.h +++ b/include/assimp/StreamReader.h @@ -48,11 +48,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_STREAMREADER_H_INCLUDED #define AI_STREAMREADER_H_INCLUDED +#include +#include + #include "ByteSwapper.h" #include "Exceptional.h" #include -#include -#include namespace Assimp { @@ -314,7 +315,7 @@ private: const size_t read = stream->Read(current,1,s); // (read < s) can only happen if the stream was opened in text mode, in which case FileSize() is not reliable ai_assert(read <= s); - end = limit = &buffer[read]; + end = limit = &buffer[read-1] + 1; } private: From 7c23a6c5ca9b7dcf7b2acbfe17b7e0fe0c45dd2c Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 30 Dec 2018 11:41:58 +0100 Subject: [PATCH 096/472] fix review findings. --- port/PyAssimp/README.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/port/PyAssimp/README.md b/port/PyAssimp/README.md index 37ecdb65d..22c9b2625 100644 --- a/port/PyAssimp/README.md +++ b/port/PyAssimp/README.md @@ -76,19 +76,16 @@ INSTALL Install `pyassimp` by running: -``` +```console $ 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` +`.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. - From ba80410c486a20cc0280c441dc405876e6351464 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 30 Dec 2018 15:56:42 +0100 Subject: [PATCH 097/472] fix review findings. --- port/PyAssimp/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/port/PyAssimp/README.md b/port/PyAssimp/README.md index 22c9b2625..b2ec6491e 100644 --- a/port/PyAssimp/README.md +++ b/port/PyAssimp/README.md @@ -82,9 +82,9 @@ $ 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` +- 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`. From 35d69c360c890e09407d46c49184275d96bca88b Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 30 Dec 2018 15:59:15 +0100 Subject: [PATCH 098/472] fix out-of-bound access. --- code/Q3DLoader.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/code/Q3DLoader.cpp b/code/Q3DLoader.cpp index f1165dc2c..1aa7cb72f 100644 --- a/code/Q3DLoader.cpp +++ b/code/Q3DLoader.cpp @@ -302,13 +302,14 @@ void Q3DImporter::InternReadFile( const std::string& pFile, case 't': pScene->mNumTextures = numTextures; - if (!numTextures)break; - pScene->mTextures = new aiTexture*[pScene->mNumTextures]; + if (!numTextures) { + break; + } + pScene->mTextures = new aiTexture*[pScene->mNumTextures]; // to make sure we won't crash if we leave through an exception ::memset(pScene->mTextures,0,sizeof(void*)*pScene->mNumTextures); - for (unsigned int i = 0; i < pScene->mNumTextures; ++i) - { - aiTexture* tex = pScene->mTextures[i] = new aiTexture(); + for (unsigned int i = 0; i < pScene->mNumTextures; ++i) { + aiTexture* tex = pScene->mTextures[i] = new aiTexture; // skip the texture name while (stream.GetI1()); @@ -317,15 +318,16 @@ void Q3DImporter::InternReadFile( const std::string& pFile, tex->mWidth = (unsigned int)stream.GetI4(); tex->mHeight = (unsigned int)stream.GetI4(); - if (!tex->mWidth || !tex->mHeight) + if (!tex->mWidth || !tex->mHeight) { throw DeadlyImportError("Quick3D: Invalid texture. Width or height is zero"); + } unsigned int mul = tex->mWidth * tex->mHeight; aiTexel* begin = tex->pcData = new aiTexel[mul]; - aiTexel* const end = & begin [mul]; + aiTexel* const end = & begin[mul-1] +1; - for (;begin != end; ++begin) - { + + for (;begin != end; ++begin) { begin->r = stream.GetI1(); begin->g = stream.GetI1(); begin->b = stream.GetI1(); From b42d959418a3969ed9858567c68eb752831282d3 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 30 Dec 2018 16:02:22 +0100 Subject: [PATCH 099/472] fix review warning: wrapper object used after free. --- code/glTFExporter.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/glTFExporter.cpp b/code/glTFExporter.cpp index 29a88af8b..5d00c9178 100644 --- a/code/glTFExporter.cpp +++ b/code/glTFExporter.cpp @@ -101,17 +101,17 @@ glTFExporter::glTFExporter(const char* filename, IOSystem* pIOSystem, const aiSc { aiScene* sceneCopy_tmp; SceneCombiner::CopyScene(&sceneCopy_tmp, pScene); - std::unique_ptr sceneCopy(sceneCopy_tmp); + aiScene *sceneCopy(sceneCopy_tmp); SplitLargeMeshesProcess_Triangle tri_splitter; tri_splitter.SetLimit(0xffff); - tri_splitter.Execute(sceneCopy.get()); + tri_splitter.Execute(sceneCopy); SplitLargeMeshesProcess_Vertex vert_splitter; vert_splitter.SetLimit(0xffff); - vert_splitter.Execute(sceneCopy.get()); + vert_splitter.Execute(sceneCopy); - mScene = sceneCopy.get(); + mScene = sceneCopy; mAsset.reset( new glTF::Asset( pIOSystem ) ); From 3596c822a5d27077275c0b961bce4d48ec1a849d Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 30 Dec 2018 16:04:49 +0100 Subject: [PATCH 100/472] fix review finding: Wrapper object use after free. --- code/STLLoader.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/code/STLLoader.cpp b/code/STLLoader.cpp index fb866bb7a..f8c4bb7db 100644 --- a/code/STLLoader.cpp +++ b/code/STLLoader.cpp @@ -182,7 +182,7 @@ void STLImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS std::unique_ptr file( pIOHandler->Open( pFile, "rb")); // Check whether we can read from the file - if( file.get() == NULL) { + if( file.get() == nullptr) { throw DeadlyImportError( "Failed to open STL file " + pFile + "."); } @@ -190,11 +190,11 @@ void STLImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS // allocate storage and copy the contents of the file to a memory buffer // (terminate it with zero) - std::vector mBuffer2; - TextFileToBuffer(file.get(),mBuffer2); + std::vector buffer2; + TextFileToBuffer(file.get(),buffer2); this->pScene = pScene; - this->mBuffer = &mBuffer2[0]; + this->mBuffer = &buffer2[0]; // the default vertex color is light gray. clrColorDefault.r = clrColorDefault.g = clrColorDefault.b = clrColorDefault.a = (ai_real) 0.6; @@ -231,6 +231,8 @@ void STLImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS pScene->mNumMaterials = 1; pScene->mMaterials = new aiMaterial*[1]; pScene->mMaterials[0] = pcMat; + + mBuffer = nullptr; } // ------------------------------------------------------------------------------------------------ From 92bb0febdfd06bc2187cfe2a4a7c0004ac7b56f0 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 30 Dec 2018 16:11:39 +0100 Subject: [PATCH 101/472] fix review finding: fix resource leak. --- code/IRRLoader.cpp | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/code/IRRLoader.cpp b/code/IRRLoader.cpp index 0640b0d66..9432eff61 100644 --- a/code/IRRLoader.cpp +++ b/code/IRRLoader.cpp @@ -89,14 +89,16 @@ static const aiImporterDesc desc = { // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer IRRImporter::IRRImporter() - : fps(), - configSpeedFlag() -{} +: fps() +, configSpeedFlag(){ + // empty +} // ------------------------------------------------------------------------------------------------ // Destructor, private as well -IRRImporter::~IRRImporter() -{} +IRRImporter::~IRRImporter() { + // empty +} // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. @@ -107,9 +109,9 @@ bool IRRImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool } else if (extension == "xml" || checkSig) { /* If CanRead() is called in order to check whether we * support a specific file extension in general pIOHandler - * might be NULL and it's our duty to return true here. + * might be nullptr and it's our duty to return true here. */ - if ( nullptr == pIOHandler ) { + if (nullptr == pIOHandler ) { return true; } const char* tokens[] = {"irr_scene"}; @@ -290,8 +292,8 @@ void IRRImporter::CopyMaterial(std::vector& materials, // ------------------------------------------------------------------------------------------------ -inline int ClampSpline(int idx, int size) -{ +inline +int ClampSpline(int idx, int size) { return ( idx<0 ? size+idx : ( idx>=size ? idx-size : idx ) ); } @@ -310,7 +312,7 @@ inline void FindSuitableMultiple(int& angle) // ------------------------------------------------------------------------------------------------ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector& anims) { - ai_assert(NULL != root && NULL != real); + ai_assert(nullptr != root && nullptr != real); // XXX totally WIP - doesn't produce proper results, need to evaluate // whether there's any use for Irrlicht's proprietary scene format @@ -521,7 +523,8 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector file( pIOHandler->Open( pFile)); // Check whether we can read from the file - if( file.get() == NULL) - throw DeadlyImportError( "Failed to open IRR file " + pFile + ""); + if (file.get() == nullptr) { + throw DeadlyImportError("Failed to open IRR file " + pFile + ""); + } // Construct the irrXML parser CIrrXML_IOStreamReader st(file.get()); @@ -914,14 +918,14 @@ void IRRImporter::InternReadFile( const std::string& pFile, // The root node of the scene Node* root = new Node(Node::DUMMY); - root->parent = NULL; + root->parent = nullptr; root->name = ""; // Current node parent Node* curParent = root; // Scenegraph node we're currently working on - Node* curNode = NULL; + Node* curNode = nullptr; // List of output cameras std::vector cameras; @@ -1048,7 +1052,7 @@ void IRRImporter::InternReadFile( const std::string& pFile, continue; } - Animator* curAnim = NULL; + Animator* curAnim = nullptr; // Materials can occur for nearly any type of node if (inMaterials && curNode->type != Node::DUMMY) { @@ -1353,7 +1357,7 @@ void IRRImporter::InternReadFile( const std::string& pFile, } else curParent = curParent->parent; } - else curNode = NULL; + else curNode = nullptr; } // clear all flags else if (!ASSIMP_stricmp(reader->getNodeName(),"materials")) { @@ -1479,7 +1483,8 @@ void IRRImporter::InternReadFile( const std::string& pFile, /* Finished ... everything destructs automatically and all * temporary scenes have already been deleted by MergeScenes() */ - return; + + delete root; } #endif // !! ASSIMP_BUILD_NO_IRR_IMPORTER From ae31be1e23b4732347b2177316796832509dd5a2 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 30 Dec 2018 17:06:50 +0100 Subject: [PATCH 102/472] next try. --- port/PyAssimp/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/port/PyAssimp/README.md b/port/PyAssimp/README.md index b2ec6491e..d64d72763 100644 --- a/port/PyAssimp/README.md +++ b/port/PyAssimp/README.md @@ -20,7 +20,7 @@ model using a shader-based OpenGL pipeline. To use it, from within `/port/PyAssimp`: -``` +```console $ cd scripts $ python ./3D-viewer ``` @@ -82,9 +82,9 @@ $ 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` + - 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`. From 425a784b23de2104827b61f7aea4cd664d3d0bf0 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 31 Dec 2018 12:16:20 +0100 Subject: [PATCH 103/472] fix finding: possible override. --- code/EmbedTexturesProcess.cpp | 6 +++++- include/assimp/texture.h | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/code/EmbedTexturesProcess.cpp b/code/EmbedTexturesProcess.cpp index ebe7a0897..ed9b79232 100644 --- a/code/EmbedTexturesProcess.cpp +++ b/code/EmbedTexturesProcess.cpp @@ -138,7 +138,11 @@ bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const { auto extension = path.substr(path.find_last_of('.') + 1u); std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower); if (extension == "jpeg") extension = "jpg"; - strcpy(pTexture->achFormatHint, extension.c_str()); + size_t len = extension.size(); + if (len > HINTMAXTEXTURELEN -1) { + len = HINTMAXTEXTURELEN - 1; + } + strncpy(pTexture->achFormatHint, extension.c_str(), len); pScene->mTextures[textureId] = pTexture; diff --git a/include/assimp/texture.h b/include/assimp/texture.h index 5be7229ec..575f5754f 100644 --- a/include/assimp/texture.h +++ b/include/assimp/texture.h @@ -117,6 +117,8 @@ struct aiTexel #include "./Compiler/poppack1.h" +#define HINTMAXTEXTURELEN 9 + // -------------------------------------------------------------------------------- /** Helper structure to describe an embedded texture * @@ -166,7 +168,7 @@ struct aiTexture { * E.g. 'dds\\0', 'pcx\\0', 'jpg\\0'. All characters are lower-case. * The fourth character will always be '\\0'. */ - char achFormatHint[9];// 8 for string + 1 for terminator. + char achFormatHint[ HINTMAXTEXTURELEN ];// 8 for string + 1 for terminator. /** Data of the texture. * From c63b1a1fd539ed6bd2024e5d0867f4edbc0a4d61 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 31 Dec 2018 14:47:54 +0100 Subject: [PATCH 104/472] fix review finding: dereference after null-check. --- code/EmbedTexturesProcess.cpp | 16 +++++++++------- code/Q3BSPFileImporter.cpp | 3 +-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/code/EmbedTexturesProcess.cpp b/code/EmbedTexturesProcess.cpp index ed9b79232..a6dd8457e 100644 --- a/code/EmbedTexturesProcess.cpp +++ b/code/EmbedTexturesProcess.cpp @@ -124,26 +124,28 @@ bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const { file.read(reinterpret_cast(imageContent), imageSize); // Enlarging the textures table - auto textureId = pScene->mNumTextures++; + unsigned int textureId = pScene->mNumTextures++; auto oldTextures = pScene->mTextures; pScene->mTextures = new aiTexture*[pScene->mNumTextures]; - memmove(pScene->mTextures, oldTextures, sizeof(aiTexture*) * (pScene->mNumTextures - 1u)); + ::memmove(pScene->mTextures, oldTextures, sizeof(aiTexture*) * (pScene->mNumTextures - 1u)); // Add the new texture - auto pTexture = new aiTexture(); + auto pTexture = new aiTexture; pTexture->mHeight = 0; // Means that this is still compressed pTexture->mWidth = static_cast(imageSize); pTexture->pcData = imageContent; auto extension = path.substr(path.find_last_of('.') + 1u); std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower); - if (extension == "jpeg") extension = "jpg"; + if (extension == "jpeg") { + extension = "jpg"; + } + size_t len = extension.size(); - if (len > HINTMAXTEXTURELEN -1) { + if (len > HINTMAXTEXTURELEN -1 ) { len = HINTMAXTEXTURELEN - 1; } - strncpy(pTexture->achFormatHint, extension.c_str(), len); - + ::strncpy(pTexture->achFormatHint, extension.c_str(), len); pScene->mTextures[textureId] = pTexture; return true; diff --git a/code/Q3BSPFileImporter.cpp b/code/Q3BSPFileImporter.cpp index 58fbef985..8b9e3c037 100644 --- a/code/Q3BSPFileImporter.cpp +++ b/code/Q3BSPFileImporter.cpp @@ -400,6 +400,7 @@ void Q3BSPFileImporter::createTriangleTopology( const Q3BSP::Q3BSPModel *pModel, if (nullptr != m_pCurrentFace) { m_pCurrentFace->mNumIndices = 3; m_pCurrentFace->mIndices = new unsigned int[3]; + m_pCurrentFace->mIndices[ idx ] = vertIdx; } } @@ -409,9 +410,7 @@ void Q3BSPFileImporter::createTriangleTopology( const Q3BSP::Q3BSPModel *pModel, pMesh->mTextureCoords[ 0 ][ vertIdx ].Set( pVertex->vTexCoord.x, pVertex->vTexCoord.y, 0.0f ); pMesh->mTextureCoords[ 1 ][ vertIdx ].Set( pVertex->vLightmap.x, pVertex->vLightmap.y, 0.0f ); - m_pCurrentFace->mIndices[ idx ] = vertIdx; vertIdx++; - idx++; } } From b59d931486c3ceb1ea819d42cade6c646fa98ad4 Mon Sep 17 00:00:00 2001 From: Arkeon Date: Wed, 2 Jan 2019 14:56:38 +0100 Subject: [PATCH 105/472] Correction on clipper crash on some IFC files when points are empty --- contrib/clipper/clipper.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/contrib/clipper/clipper.cpp b/contrib/clipper/clipper.cpp index 074f22b21..857cd1c3e 100644 --- a/contrib/clipper/clipper.cpp +++ b/contrib/clipper/clipper.cpp @@ -371,6 +371,9 @@ inline bool PointsEqual( const IntPoint &pt1, const IntPoint &pt2) bool Orientation(OutRec *outRec, bool UseFullInt64Range) { + if (!outRec->pts) + return 0.0; + //first make sure bottomPt is correctly assigned ... OutPt *opBottom = outRec->pts, *op = outRec->pts->next; while (op != outRec->pts) @@ -434,6 +437,9 @@ double Area(const Polygon &poly) double Area(const OutRec &outRec, bool UseFullInt64Range) { + if (!outRec.pts) + return 0.0; + OutPt *op = outRec.pts; if (UseFullInt64Range) { Int128 a(0); @@ -3085,9 +3091,9 @@ void Clipper::JoinCommonEdges(bool fixHoleLinkages) FixupOutPolygon(*outRec1); FixupOutPolygon(*outRec2); - if (Orientation(outRec1, m_UseFullRange) != (Area(*outRec1, m_UseFullRange) > 0)) + if (outRec1->pts && (Orientation(outRec1, m_UseFullRange) != (Area(*outRec1, m_UseFullRange) > 0))) DisposeBottomPt(*outRec1); - if (Orientation(outRec2, m_UseFullRange) != (Area(*outRec2, m_UseFullRange) > 0)) + if (outRec2->pts && (Orientation(outRec2, m_UseFullRange) != (Area(*outRec2, m_UseFullRange) > 0))) DisposeBottomPt(*outRec2); } else From 35a044bda37b2bad50a41746622c746acd139631 Mon Sep 17 00:00:00 2001 From: rickomax Date: Sun, 6 Jan 2019 16:37:30 -0200 Subject: [PATCH 106/472] Various additions/fixes (FBX blend-shapes support added) Added animMesh name assignment at ColladaLoader Fixed animMesh post-processing on ConvertToLhProcess (blend-shapes weren't being affected by post-processing) Added WindowsStore define. This is used to change some incompatible WinRT methods Added FBX blend-shapes and blend-shapes animations support Added Maya FBX specific texture slots parsing Added extra FBX metadata parsing Added GLTF2 vertex color parsing Fixed IFC-Loader zip-buffer reading rountine Fixed OBJ file parsing line-breaker bug Fixed IOStreamBuffer cache over-read bug Added mName field to aiAnimMesh Reverted EmissiveFactor, TransparencyFactor and SpecularFactor assignment on FBXConverter. Really, the commit #817 breaks a lot of old code. --- code/CMakeLists.txt | 3 + code/ColladaLoader.cpp | 7 +- code/ConvertToLHProcess.cpp | 66 +- code/DefaultIOSystem.cpp | 12 + code/FBXAnimation.cpp | 4 +- code/FBXConverter.cpp | 5952 ++++++++++++++++--------------- code/FBXConverter.h | 10 + code/FBXDeformer.cpp | 47 + code/FBXDocument.cpp | 9 + code/FBXDocument.h | 43 + code/FBXMeshGeometry.cpp | 47 +- code/FBXMeshGeometry.h | 34 +- code/Importer/IFC/IFCLoader.cpp | 17 +- code/ObjFileParser.cpp | 2 +- code/glTF2Importer.cpp | 13 +- include/assimp/IOStreamBuffer.h | 5 +- include/assimp/mesh.h | 5 +- 17 files changed, 3372 insertions(+), 2904 deletions(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index e29467164..043599aca 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -966,6 +966,9 @@ if( MSVC ) set(LIBRARY_SUFFIX "${ASSIMP_LIBRARY_SUFFIX}-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library") endif() +if (${CMAKE_SYSTEM_NAME} MATCHES "WindowsStore") + set(WindowsStore TRUE) +endif() SET_TARGET_PROPERTIES( assimp PROPERTIES VERSION ${ASSIMP_VERSION} SOVERSION ${ASSIMP_SOVERSION} # use full version diff --git a/code/ColladaLoader.cpp b/code/ColladaLoader.cpp index ab896c000..af04e9a16 100644 --- a/code/ColladaLoader.cpp +++ b/code/ColladaLoader.cpp @@ -728,8 +728,11 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada:: std::vector animMeshes; for (unsigned int i = 0; i < targetMeshes.size(); i++) { - aiAnimMesh *animMesh = aiCreateAnimMesh(targetMeshes.at(i)); - animMesh->mWeight = targetWeights[i]; + aiMesh* targetMesh = targetMeshes.at(i); + aiAnimMesh *animMesh = aiCreateAnimMesh(targetMesh); + float weight = targetWeights[i]; + animMesh->mWeight = weight == 0 ? 1.0f : weight; + animMesh->mName = targetMesh->mName; animMeshes.push_back(animMesh); } dstMesh->mMethod = (method == Collada::Relative) diff --git a/code/ConvertToLHProcess.cpp b/code/ConvertToLHProcess.cpp index 9cb45cc69..1831739ac 100644 --- a/code/ConvertToLHProcess.cpp +++ b/code/ConvertToLHProcess.cpp @@ -166,8 +166,9 @@ void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) { for( size_t a = 0; a < pMesh->mNumVertices; ++a) { pMesh->mVertices[a].z *= -1.0f; - if( pMesh->HasNormals()) + if (pMesh->HasNormals()) { pMesh->mNormals[a].z *= -1.0f; + } if( pMesh->HasTangentsAndBitangents()) { pMesh->mTangents[a].z *= -1.0f; @@ -175,6 +176,23 @@ void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) { } } + // mirror anim meshes positions, normals and stuff along the Z axis + for (size_t m = 0; m < pMesh->mNumAnimMeshes; ++m) + { + for (size_t a = 0; a < pMesh->mAnimMeshes[m]->mNumVertices; ++a) + { + pMesh->mAnimMeshes[m]->mVertices[a].z *= -1.0f; + if (pMesh->mAnimMeshes[m]->HasNormals()) { + pMesh->mAnimMeshes[m]->mNormals[a].z *= -1.0f; + } + if (pMesh->mAnimMeshes[m]->HasTangentsAndBitangents()) + { + pMesh->mAnimMeshes[m]->mTangents[a].z *= -1.0f; + pMesh->mAnimMeshes[m]->mBitangents[a].z *= -1.0f; + } + } + } + // mirror offset matrices of all bones for( size_t a = 0; a < pMesh->mNumBones; ++a) { @@ -346,8 +364,50 @@ void FlipWindingOrderProcess::ProcessMesh( aiMesh* pMesh) for( unsigned int a = 0; a < pMesh->mNumFaces; a++) { aiFace& face = pMesh->mFaces[a]; - for( unsigned int b = 0; b < face.mNumIndices / 2; b++) - std::swap( face.mIndices[b], face.mIndices[ face.mNumIndices - 1 - b]); + for (unsigned int b = 0; b < face.mNumIndices / 2; b++) { + std::swap(face.mIndices[b], face.mIndices[face.mNumIndices - 1 - b]); + } + } + + // invert the order of all components in this mesh anim meshes + for (unsigned int m = 0; m < pMesh->mNumAnimMeshes; m++) { + aiAnimMesh* animMesh = pMesh->mAnimMeshes[m]; + unsigned int numVertices = animMesh->mNumVertices; + if (animMesh->HasPositions()) { + for (unsigned int a = 0; a < numVertices; a++) + { + std::swap(animMesh->mVertices[a], animMesh->mVertices[numVertices - 1 - a]); + } + } + if (animMesh->HasNormals()) { + for (unsigned int a = 0; a < numVertices; a++) + { + std::swap(animMesh->mNormals[a], animMesh->mNormals[numVertices - 1 - a]); + } + } + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) { + if (animMesh->HasTextureCoords(i)) { + for (unsigned int a = 0; a < numVertices; a++) + { + std::swap(animMesh->mTextureCoords[i][a], animMesh->mTextureCoords[i][numVertices - 1 - a]); + } + } + } + if (animMesh->HasTangentsAndBitangents()) { + for (unsigned int a = 0; a < numVertices; a++) + { + std::swap(animMesh->mTangents[a], animMesh->mTangents[numVertices - 1 - a]); + std::swap(animMesh->mBitangents[a], animMesh->mBitangents[numVertices - 1 - a]); + } + } + for (unsigned int v = 0; v < AI_MAX_NUMBER_OF_COLOR_SETS; v++) { + if (animMesh->HasVertexColors(v)) { + for (unsigned int a = 0; a < numVertices; a++) + { + std::swap(animMesh->mColors[v][a], animMesh->mColors[v][numVertices - 1 - a]); + } + } + } } } diff --git a/code/DefaultIOSystem.cpp b/code/DefaultIOSystem.cpp index 58afe475c..67fd82f17 100644 --- a/code/DefaultIOSystem.cpp +++ b/code/DefaultIOSystem.cpp @@ -76,6 +76,7 @@ bool DefaultIOSystem::Exists( const char* pFile) const #ifdef _WIN32 wchar_t fileName16[PATHLIMIT]; +#ifndef WindowsStore bool isUnicode = IsTextUnicode(pFile, static_cast(strlen(pFile)), NULL) != 0; if (isUnicode) { @@ -85,12 +86,15 @@ bool DefaultIOSystem::Exists( const char* pFile) const return false; } } else { +#endif FILE* file = ::fopen(pFile, "rb"); if (!file) return false; ::fclose(file); +#ifndef WindowsStore } +#endif #else FILE* file = ::fopen( pFile, "rb"); if( !file) @@ -110,14 +114,18 @@ IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode) FILE* file; #ifdef _WIN32 wchar_t fileName16[PATHLIMIT]; +#ifndef WindowsStore bool isUnicode = IsTextUnicode(strFile, static_cast(strlen(strFile)), NULL) != 0; if (isUnicode) { MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, strFile, -1, fileName16, PATHLIMIT); std::string mode8(strMode); file = ::_wfopen(fileName16, std::wstring(mode8.begin(), mode8.end()).c_str()); } else { +#endif file = ::fopen(strFile, strMode); +#ifndef WindowsStore } +#endif #else file = ::fopen(strFile, strMode); #endif @@ -158,6 +166,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out) { ai_assert(in && _out); #if defined( _MSC_VER ) || defined( __MINGW32__ ) +#ifndef WindowsStore bool isUnicode = IsTextUnicode(in, static_cast(strlen(in)), NULL) != 0; if (isUnicode) { wchar_t out16[PATHLIMIT]; @@ -175,6 +184,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out) } } else { +#endif char* ret = :: _fullpath(_out, in, PATHLIMIT); if (!ret) { // preserve the input path, maybe someone else is able to fix @@ -182,7 +192,9 @@ inline static void MakeAbsolutePath (const char* in, char* _out) ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in)); strcpy(_out, in); } +#ifndef WindowsStore } +#endif #else // use realpath char* ret = realpath(in, _out); diff --git a/code/FBXAnimation.cpp b/code/FBXAnimation.cpp index 24ab9b14b..871d62578 100644 --- a/code/FBXAnimation.cpp +++ b/code/FBXAnimation.cpp @@ -105,8 +105,8 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons const Scope& sc = GetRequiredScope(element); // find target node - const char* whitelist[] = {"Model","NodeAttribute"}; - const std::vector& conns = doc.GetConnectionsBySourceSequenced(ID(),whitelist,2); + const char* whitelist[] = {"Model","NodeAttribute","Deformer"}; + const std::vector& conns = doc.GetConnectionsBySourceSequenced(ID(),whitelist,3); for(const Connection* con : conns) { diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 7dd9f94b4..cd9ad0966 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -53,10 +53,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXUtil.h" #include "FBXProperties.h" #include "FBXImporter.h" + #include #include +#include + #include #include #include @@ -65,3025 +68,3214 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include namespace Assimp { -namespace FBX { + namespace FBX { -using namespace Util; + using namespace Util; #define MAGIC_NODE_TAG "_$AssimpFbx$" #define CONVERT_FBX_TIME(time) static_cast(time) / 46186158000L -FBXConverter::FBXConverter( aiScene* out, const Document& doc ) -: defaultMaterialIndex() -, out( out ) -, doc( doc ) { - // animations need to be converted first since this will - // populate the node_anim_chain_bits map, which is needed - // to determine which nodes need to be generated. - ConvertAnimations(); - ConvertRootNode(); + FBXConverter::FBXConverter(aiScene* out, const Document& doc) + : defaultMaterialIndex() + , out(out) + , doc(doc) { + // animations need to be converted first since this will + // populate the node_anim_chain_bits map, which is needed + // to determine which nodes need to be generated. + ConvertAnimations(); + ConvertRootNode(); - if ( doc.Settings().readAllMaterials ) { - // unfortunately this means we have to evaluate all objects - for( const ObjectMap::value_type& v : doc.Objects() ) { + if (doc.Settings().readAllMaterials) { + // unfortunately this means we have to evaluate all objects + for (const ObjectMap::value_type& v : doc.Objects()) { - const Object* ob = v.second->Get(); - if ( !ob ) { - continue; + const Object* ob = v.second->Get(); + if (!ob) { + continue; + } + + const Material* mat = dynamic_cast(ob); + if (mat) { + + if (materials_converted.find(mat) == materials_converted.end()) { + ConvertMaterial(*mat, 0); + } + } + } } - const Material* mat = dynamic_cast( ob ); - if ( mat ) { + ConvertGlobalSettings(); + TransferDataToScene(); - if ( materials_converted.find( mat ) == materials_converted.end() ) { - ConvertMaterial( *mat, 0 ); - } + // if we didn't read any meshes set the AI_SCENE_FLAGS_INCOMPLETE + // to make sure the scene passes assimp's validation. FBX files + // need not contain geometry (i.e. camera animations, raw armatures). + if (out->mNumMeshes == 0) { + out->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; } } - } - - ConvertGlobalSettings(); - TransferDataToScene(); - - // if we didn't read any meshes set the AI_SCENE_FLAGS_INCOMPLETE - // to make sure the scene passes assimp's validation. FBX files - // need not contain geometry (i.e. camera animations, raw armatures). - if ( out->mNumMeshes == 0 ) { - out->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; - } -} -FBXConverter::~FBXConverter() { - std::for_each( meshes.begin(), meshes.end(), Util::delete_fun() ); - std::for_each( materials.begin(), materials.end(), Util::delete_fun() ); - std::for_each( animations.begin(), animations.end(), Util::delete_fun() ); - std::for_each( lights.begin(), lights.end(), Util::delete_fun() ); - std::for_each( cameras.begin(), cameras.end(), Util::delete_fun() ); - std::for_each( textures.begin(), textures.end(), Util::delete_fun() ); -} + FBXConverter::~FBXConverter() { + std::for_each(meshes.begin(), meshes.end(), Util::delete_fun()); + std::for_each(materials.begin(), materials.end(), Util::delete_fun()); + std::for_each(animations.begin(), animations.end(), Util::delete_fun()); + std::for_each(lights.begin(), lights.end(), Util::delete_fun()); + std::for_each(cameras.begin(), cameras.end(), Util::delete_fun()); + std::for_each(textures.begin(), textures.end(), Util::delete_fun()); + } -void FBXConverter::ConvertRootNode() { - out->mRootNode = new aiNode(); - out->mRootNode->mName.Set( "RootNode" ); + void FBXConverter::ConvertRootNode() { + out->mRootNode = new aiNode(); + out->mRootNode->mName.Set("RootNode"); - // root has ID 0 - ConvertNodes( 0L, *out->mRootNode ); -} + // root has ID 0 + ConvertNodes(0L, *out->mRootNode); + } -void FBXConverter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform ) { - const std::vector& conns = doc.GetConnectionsByDestinationSequenced( id, "Model" ); + void FBXConverter::ConvertNodes(uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform) { + const std::vector& conns = doc.GetConnectionsByDestinationSequenced(id, "Model"); - std::vector nodes; - nodes.reserve( conns.size() ); + std::vector nodes; + nodes.reserve(conns.size()); - std::vector nodes_chain; - std::vector post_nodes_chain; + std::vector nodes_chain; + std::vector post_nodes_chain; - try { - for( const Connection* con : conns ) { + try { + for (const Connection* con : conns) { - // ignore object-property links - if ( con->PropertyName().length() ) { - continue; - } - - const Object* const object = con->SourceObject(); - if ( nullptr == object ) { - FBXImporter::LogWarn( "failed to convert source object for Model link" ); - continue; - } - - const Model* const model = dynamic_cast( object ); - - if ( nullptr != model ) { - nodes_chain.clear(); - post_nodes_chain.clear(); - - aiMatrix4x4 new_abs_transform = parent_transform; - - // even though there is only a single input node, the design of - // assimp (or rather: the complicated transformation chain that - // is employed by fbx) means that we may need multiple aiNode's - // to represent a fbx node's transformation. - GenerateTransformationNodeChain( *model, nodes_chain, post_nodes_chain ); - - ai_assert( nodes_chain.size() ); - - std::string original_name = FixNodeName( model->Name() ); - - // check if any of the nodes in the chain has the name the fbx node - // is supposed to have. If there is none, add another node to - // preserve the name - people might have scripts etc. that rely - // on specific node names. - aiNode* name_carrier = NULL; - for( aiNode* prenode : nodes_chain ) { - if ( !strcmp( prenode->mName.C_Str(), original_name.c_str() ) ) { - name_carrier = prenode; - break; - } - } - - if ( !name_carrier ) { - std::string old_original_name = original_name; - GetUniqueName(old_original_name, original_name); - nodes_chain.push_back( new aiNode( original_name ) ); - } else { - original_name = nodes_chain.back()->mName.C_Str(); - } - - //setup metadata on newest node - SetupNodeMetadata( *model, *nodes_chain.back() ); - - // link all nodes in a row - aiNode* last_parent = &parent; - for( aiNode* prenode : nodes_chain ) { - ai_assert( prenode ); - - if ( last_parent != &parent ) { - last_parent->mNumChildren = 1; - last_parent->mChildren = new aiNode*[ 1 ]; - last_parent->mChildren[ 0 ] = prenode; + // ignore object-property links + if (con->PropertyName().length()) { + continue; } - prenode->mParent = last_parent; - last_parent = prenode; + const Object* const object = con->SourceObject(); + if (nullptr == object) { + FBXImporter::LogWarn("failed to convert source object for Model link"); + continue; + } - new_abs_transform *= prenode->mTransformation; - } + const Model* const model = dynamic_cast(object); - // attach geometry - ConvertModel( *model, *nodes_chain.back(), new_abs_transform ); + if (nullptr != model) { + nodes_chain.clear(); + post_nodes_chain.clear(); - // check if there will be any child nodes - const std::vector& child_conns - = doc.GetConnectionsByDestinationSequenced( model->ID(), "Model" ); + aiMatrix4x4 new_abs_transform = parent_transform; - // if so, link the geometric transform inverse nodes - // before we attach any child nodes - if (child_conns.size()) { - for( aiNode* postnode : post_nodes_chain ) { - ai_assert( postnode ); + // even though there is only a single input node, the design of + // assimp (or rather: the complicated transformation chain that + // is employed by fbx) means that we may need multiple aiNode's + // to represent a fbx node's transformation. + GenerateTransformationNodeChain(*model, nodes_chain, post_nodes_chain); - if ( last_parent != &parent ) { - last_parent->mNumChildren = 1; - last_parent->mChildren = new aiNode*[ 1 ]; - last_parent->mChildren[ 0 ] = postnode; + ai_assert(nodes_chain.size()); + + std::string original_name = FixNodeName(model->Name()); + + // check if any of the nodes in the chain has the name the fbx node + // is supposed to have. If there is none, add another node to + // preserve the name - people might have scripts etc. that rely + // on specific node names. + aiNode* name_carrier = NULL; + for (aiNode* prenode : nodes_chain) { + if (!strcmp(prenode->mName.C_Str(), original_name.c_str())) { + name_carrier = prenode; + break; + } } - postnode->mParent = last_parent; - last_parent = postnode; - - new_abs_transform *= postnode->mTransformation; - } - } else { - // free the nodes we allocated as we don't need them - Util::delete_fun deleter; - std::for_each( - post_nodes_chain.begin(), - post_nodes_chain.end(), - deleter - ); - } - - // attach sub-nodes (if any) - ConvertNodes( model->ID(), *last_parent, new_abs_transform ); - - if ( doc.Settings().readLights ) { - ConvertLights( *model, original_name ); - } - - if ( doc.Settings().readCameras ) { - ConvertCameras( *model, original_name ); - } - - nodes.push_back( nodes_chain.front() ); - nodes_chain.clear(); - } - } - - if ( nodes.size() ) { - parent.mChildren = new aiNode*[ nodes.size() ](); - parent.mNumChildren = static_cast( nodes.size() ); - - std::swap_ranges( nodes.begin(), nodes.end(), parent.mChildren ); - } - } - catch ( std::exception& ) { - Util::delete_fun deleter; - std::for_each( nodes.begin(), nodes.end(), deleter ); - std::for_each( nodes_chain.begin(), nodes_chain.end(), deleter ); - std::for_each( post_nodes_chain.begin(), post_nodes_chain.end(), deleter ); - } -} - - -void FBXConverter::ConvertLights( const Model& model, const std::string &orig_name ) { - const std::vector& node_attrs = model.GetAttributes(); - for( const NodeAttribute* attr : node_attrs ) { - const Light* const light = dynamic_cast( attr ); - if ( light ) { - ConvertLight( *light, orig_name ); - } - } -} - -void FBXConverter::ConvertCameras( const Model& model, const std::string &orig_name ) { - const std::vector& node_attrs = model.GetAttributes(); - for( const NodeAttribute* attr : node_attrs ) { - const Camera* const cam = dynamic_cast( attr ); - if ( cam ) { - ConvertCamera( *cam, orig_name ); - } - } -} - -void FBXConverter::ConvertLight( const Light& light, const std::string &orig_name ) { - lights.push_back( new aiLight() ); - aiLight* const out_light = lights.back(); - - out_light->mName.Set( orig_name ); - - const float intensity = light.Intensity() / 100.0f; - const aiVector3D& col = light.Color(); - - out_light->mColorDiffuse = aiColor3D( col.x, col.y, col.z ); - out_light->mColorDiffuse.r *= intensity; - out_light->mColorDiffuse.g *= intensity; - out_light->mColorDiffuse.b *= intensity; - - 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: - out_light->mType = aiLightSource_POINT; - break; - - case Light::Type_Directional: - out_light->mType = aiLightSource_DIRECTIONAL; - break; - - case Light::Type_Spot: - out_light->mType = aiLightSource_SPOT; - out_light->mAngleOuterCone = AI_DEG_TO_RAD( light.OuterAngle() ); - out_light->mAngleInnerCone = AI_DEG_TO_RAD( light.InnerAngle() ); - break; - - case Light::Type_Area: - FBXImporter::LogWarn( "cannot represent area light, set to UNDEFINED" ); - out_light->mType = aiLightSource_UNDEFINED; - break; - - case Light::Type_Volume: - FBXImporter::LogWarn( "cannot represent volume light, set to UNDEFINED" ); - out_light->mType = aiLightSource_UNDEFINED; - break; - default: - ai_assert( false ); - } - - float decay = light.DecayStart(); - switch ( light.DecayType() ) - { - case Light::Decay_None: - out_light->mAttenuationConstant = decay; - out_light->mAttenuationLinear = 0.0f; - out_light->mAttenuationQuadratic = 0.0f; - break; - case Light::Decay_Linear: - out_light->mAttenuationConstant = 0.0f; - out_light->mAttenuationLinear = 2.0f / decay; - out_light->mAttenuationQuadratic = 0.0f; - break; - case Light::Decay_Quadratic: - 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" ); - out_light->mAttenuationQuadratic = 1.0f; - break; - default: - ai_assert( false ); - } -} - -void FBXConverter::ConvertCamera( const Camera& cam, const std::string &orig_name ) -{ - cameras.push_back( new aiCamera() ); - aiCamera* const out_camera = cameras.back(); - - out_camera->mName.Set( orig_name ); - - out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight(); - - //cameras are defined along positive x direction - out_camera->mPosition = cam.Position(); - out_camera->mLookAt = ( cam.InterestPosition() - out_camera->mPosition ).Normalize(); - out_camera->mUp = cam.UpVector(); - - out_camera->mHorizontalFOV = AI_DEG_TO_RAD( cam.FieldOfView() ); - out_camera->mClipPlaneNear = cam.NearPlane(); - out_camera->mClipPlaneFar = cam.FarPlane(); -} - -void FBXConverter::GetUniqueName( const std::string &name, std::string &uniqueName ) -{ - int i = 0; - uniqueName = name; - while (mNodeNames.find(uniqueName) != mNodeNames.end()) - { - ++i; - std::stringstream ext; - ext << name << std::setfill('0') << std::setw(3) << i; - uniqueName = ext.str(); - } - mNodeNames.insert(uniqueName); -} - - -const char* FBXConverter::NameTransformationComp( TransformationComp comp ) { - switch ( comp ) { - case TransformationComp_Translation: - return "Translation"; - case TransformationComp_RotationOffset: - return "RotationOffset"; - case TransformationComp_RotationPivot: - return "RotationPivot"; - case TransformationComp_PreRotation: - return "PreRotation"; - case TransformationComp_Rotation: - return "Rotation"; - case TransformationComp_PostRotation: - return "PostRotation"; - case TransformationComp_RotationPivotInverse: - return "RotationPivotInverse"; - case TransformationComp_ScalingOffset: - return "ScalingOffset"; - case TransformationComp_ScalingPivot: - return "ScalingPivot"; - case TransformationComp_Scaling: - return "Scaling"; - case TransformationComp_ScalingPivotInverse: - return "ScalingPivotInverse"; - case TransformationComp_GeometricScaling: - return "GeometricScaling"; - case TransformationComp_GeometricRotation: - return "GeometricRotation"; - case TransformationComp_GeometricTranslation: - return "GeometricTranslation"; - case TransformationComp_GeometricScalingInverse: - return "GeometricScalingInverse"; - case TransformationComp_GeometricRotationInverse: - return "GeometricRotationInverse"; - case TransformationComp_GeometricTranslationInverse: - return "GeometricTranslationInverse"; - case TransformationComp_MAXIMUM: // this is to silence compiler warnings - default: - break; - } - - ai_assert( false ); - - return nullptr; -} - -const char* FBXConverter::NameTransformationCompProperty( TransformationComp comp ) { - switch ( comp ) { - case TransformationComp_Translation: - return "Lcl Translation"; - case TransformationComp_RotationOffset: - return "RotationOffset"; - case TransformationComp_RotationPivot: - return "RotationPivot"; - case TransformationComp_PreRotation: - return "PreRotation"; - case TransformationComp_Rotation: - return "Lcl Rotation"; - case TransformationComp_PostRotation: - return "PostRotation"; - case TransformationComp_RotationPivotInverse: - return "RotationPivotInverse"; - case TransformationComp_ScalingOffset: - return "ScalingOffset"; - case TransformationComp_ScalingPivot: - return "ScalingPivot"; - case TransformationComp_Scaling: - return "Lcl Scaling"; - case TransformationComp_ScalingPivotInverse: - return "ScalingPivotInverse"; - case TransformationComp_GeometricScaling: - return "GeometricScaling"; - case TransformationComp_GeometricRotation: - return "GeometricRotation"; - case TransformationComp_GeometricTranslation: - return "GeometricTranslation"; - case TransformationComp_GeometricScalingInverse: - return "GeometricScalingInverse"; - case TransformationComp_GeometricRotationInverse: - return "GeometricRotationInverse"; - case TransformationComp_GeometricTranslationInverse: - return "GeometricTranslationInverse"; - case TransformationComp_MAXIMUM: // this is to silence compiler warnings - break; - } - - ai_assert( false ); - - return nullptr; -} - -aiVector3D FBXConverter::TransformationCompDefaultValue( TransformationComp comp ) -{ - // XXX a neat way to solve the never-ending special cases for scaling - // would be to do everything in log space! - return comp == TransformationComp_Scaling ? aiVector3D( 1.f, 1.f, 1.f ) : aiVector3D(); -} - -void FBXConverter::GetRotationMatrix( Model::RotOrder mode, const aiVector3D& rotation, aiMatrix4x4& out ) -{ - if ( mode == Model::RotOrder_SphericXYZ ) { - FBXImporter::LogError( "Unsupported RotationMode: SphericXYZ" ); - out = aiMatrix4x4(); - return; - } - - const float angle_epsilon = 1e-6f; - - out = aiMatrix4x4(); - - bool is_id[ 3 ] = { true, true, true }; - - aiMatrix4x4 temp[ 3 ]; - if ( std::fabs( rotation.z ) > angle_epsilon ) { - aiMatrix4x4::RotationZ( AI_DEG_TO_RAD( rotation.z ), temp[ 2 ] ); - is_id[ 2 ] = false; - } - if ( std::fabs( rotation.y ) > angle_epsilon ) { - aiMatrix4x4::RotationY( AI_DEG_TO_RAD( rotation.y ), temp[ 1 ] ); - is_id[ 1 ] = false; - } - if ( std::fabs( rotation.x ) > angle_epsilon ) { - aiMatrix4x4::RotationX( AI_DEG_TO_RAD( rotation.x ), temp[ 0 ] ); - is_id[ 0 ] = false; - } - - int order[ 3 ] = { -1, -1, -1 }; - - // note: rotation order is inverted since we're left multiplying as is usual in assimp - switch ( mode ) - { - case Model::RotOrder_EulerXYZ: - order[ 0 ] = 2; - order[ 1 ] = 1; - order[ 2 ] = 0; - break; - - case Model::RotOrder_EulerXZY: - order[ 0 ] = 1; - order[ 1 ] = 2; - order[ 2 ] = 0; - break; - - case Model::RotOrder_EulerYZX: - order[ 0 ] = 0; - order[ 1 ] = 2; - order[ 2 ] = 1; - break; - - case Model::RotOrder_EulerYXZ: - order[ 0 ] = 2; - order[ 1 ] = 0; - order[ 2 ] = 1; - break; - - case Model::RotOrder_EulerZXY: - order[ 0 ] = 1; - order[ 1 ] = 0; - order[ 2 ] = 2; - break; - - case Model::RotOrder_EulerZYX: - order[ 0 ] = 0; - order[ 1 ] = 1; - order[ 2 ] = 2; - break; - - default: - ai_assert( false ); - break; - } - - ai_assert( order[ 0 ] >= 0 ); - ai_assert( order[ 0 ] <= 2 ); - ai_assert( order[ 1 ] >= 0 ); - ai_assert( order[ 1 ] <= 2 ); - ai_assert( order[ 2 ] >= 0 ); - ai_assert( order[ 2 ] <= 2 ); - - if ( !is_id[ order[ 0 ] ] ) { - out = temp[ order[ 0 ] ]; - } - - if ( !is_id[ order[ 1 ] ] ) { - out = out * temp[ order[ 1 ] ]; - } - - if ( !is_id[ order[ 2 ] ] ) { - out = out * temp[ order[ 2 ] ]; - } -} - -bool FBXConverter::NeedsComplexTransformationChain( const Model& model ) -{ - const PropertyTable& props = model.Props(); - bool ok; - - const float zero_epsilon = 1e-6f; - const aiVector3D all_ones(1.0f, 1.0f, 1.0f); - for ( size_t i = 0; i < TransformationComp_MAXIMUM; ++i ) { - const TransformationComp comp = static_cast< TransformationComp >( i ); - - if ( comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation ) { - continue; - } - - bool scale_compare = ( comp == TransformationComp_GeometricScaling || comp == TransformationComp_Scaling ); - - const aiVector3D& v = PropertyGet( props, NameTransformationCompProperty( comp ), ok ); - if ( ok && scale_compare ) { - if ( (v - all_ones).SquareLength() > zero_epsilon ) { - return true; - } - } else if ( ok ) { - if ( v.SquareLength() > zero_epsilon ) { - return true; - } - } - } - - return false; -} - -std::string FBXConverter::NameTransformationChainNode( const std::string& name, TransformationComp comp ) -{ - return name + std::string( MAGIC_NODE_TAG ) + "_" + NameTransformationComp( comp ); -} - -void FBXConverter::GenerateTransformationNodeChain( const Model& model, std::vector& output_nodes, - std::vector& post_output_nodes ) { - const PropertyTable& props = model.Props(); - const Model::RotOrder rot = model.RotationOrder(); - - bool ok; - - aiMatrix4x4 chain[ TransformationComp_MAXIMUM ]; - std::fill_n( chain, static_cast( TransformationComp_MAXIMUM ), aiMatrix4x4() ); - - // generate transformation matrices for all the different transformation components - const float zero_epsilon = 1e-6f; - const aiVector3D all_ones(1.0f, 1.0f, 1.0f); - bool is_complex = false; - - const aiVector3D& PreRotation = PropertyGet( props, "PreRotation", ok ); - if ( ok && PreRotation.SquareLength() > zero_epsilon ) { - is_complex = true; - - GetRotationMatrix( Model::RotOrder::RotOrder_EulerXYZ, PreRotation, chain[ TransformationComp_PreRotation ] ); - } - - const aiVector3D& PostRotation = PropertyGet( props, "PostRotation", ok ); - if ( ok && PostRotation.SquareLength() > zero_epsilon ) { - is_complex = true; - - GetRotationMatrix( Model::RotOrder::RotOrder_EulerXYZ, PostRotation, chain[ TransformationComp_PostRotation ] ); - } - - const aiVector3D& RotationPivot = PropertyGet( props, "RotationPivot", ok ); - if ( ok && RotationPivot.SquareLength() > zero_epsilon ) { - is_complex = true; - - aiMatrix4x4::Translation( RotationPivot, chain[ TransformationComp_RotationPivot ] ); - aiMatrix4x4::Translation( -RotationPivot, chain[ TransformationComp_RotationPivotInverse ] ); - } - - const aiVector3D& RotationOffset = PropertyGet( props, "RotationOffset", ok ); - if ( ok && RotationOffset.SquareLength() > zero_epsilon ) { - is_complex = true; - - aiMatrix4x4::Translation( RotationOffset, chain[ TransformationComp_RotationOffset ] ); - } - - const aiVector3D& ScalingOffset = PropertyGet( props, "ScalingOffset", ok ); - if ( ok && ScalingOffset.SquareLength() > zero_epsilon ) { - is_complex = true; - - aiMatrix4x4::Translation( ScalingOffset, chain[ TransformationComp_ScalingOffset ] ); - } - - const aiVector3D& ScalingPivot = PropertyGet( props, "ScalingPivot", ok ); - if ( ok && ScalingPivot.SquareLength() > zero_epsilon ) { - is_complex = true; - - aiMatrix4x4::Translation( ScalingPivot, chain[ TransformationComp_ScalingPivot ] ); - aiMatrix4x4::Translation( -ScalingPivot, chain[ TransformationComp_ScalingPivotInverse ] ); - } - - const aiVector3D& Translation = PropertyGet( props, "Lcl Translation", ok ); - if ( ok && Translation.SquareLength() > zero_epsilon ) { - aiMatrix4x4::Translation( Translation, chain[ TransformationComp_Translation ] ); - } - - const aiVector3D& Scaling = PropertyGet( props, "Lcl Scaling", ok ); - if ( ok && (Scaling - all_ones).SquareLength() > zero_epsilon ) { - aiMatrix4x4::Scaling( Scaling, chain[ TransformationComp_Scaling ] ); - } - - const aiVector3D& Rotation = PropertyGet( props, "Lcl Rotation", ok ); - if ( ok && Rotation.SquareLength() > zero_epsilon ) { - GetRotationMatrix( rot, Rotation, chain[ TransformationComp_Rotation ] ); - } - - const aiVector3D& GeometricScaling = PropertyGet( props, "GeometricScaling", ok ); - if ( ok && (GeometricScaling - all_ones).SquareLength() > zero_epsilon ) { - is_complex = true; - aiMatrix4x4::Scaling( GeometricScaling, chain[ TransformationComp_GeometricScaling ] ); - aiVector3D GeometricScalingInverse = GeometricScaling; - bool canscale = true; - for (unsigned int i = 0; i < 3; ++i) { - if ( std::fabs( GeometricScalingInverse[i] ) > zero_epsilon ) { - GeometricScalingInverse[i] = 1.0f / GeometricScaling[i]; - } else { - FBXImporter::LogError( "cannot invert geometric scaling matrix with a 0.0 scale component" ); - canscale = false; - break; - } - } - if (canscale) { - aiMatrix4x4::Scaling( GeometricScalingInverse, chain[ TransformationComp_GeometricScalingInverse ] ); - } - } - - const aiVector3D& GeometricRotation = PropertyGet( props, "GeometricRotation", ok ); - if ( ok && GeometricRotation.SquareLength() > zero_epsilon ) { - is_complex = true; - GetRotationMatrix( rot, GeometricRotation, chain[ TransformationComp_GeometricRotation ] ); - GetRotationMatrix( rot, GeometricRotation, chain[ TransformationComp_GeometricRotationInverse ] ); - chain[ TransformationComp_GeometricRotationInverse ].Inverse(); - } - - const aiVector3D& GeometricTranslation = PropertyGet( props, "GeometricTranslation", ok ); - if ( ok && GeometricTranslation.SquareLength() > zero_epsilon ) { - is_complex = true; - aiMatrix4x4::Translation( GeometricTranslation, chain[ TransformationComp_GeometricTranslation ] ); - aiMatrix4x4::Translation( -GeometricTranslation, chain[ TransformationComp_GeometricTranslationInverse ] ); - } - - // is_complex needs to be consistent with NeedsComplexTransformationChain() - // or the interplay between this code and the animation converter would - // not be guaranteed. - ai_assert( NeedsComplexTransformationChain( model ) == is_complex ); - - std::string name = FixNodeName( model.Name() ); - - // now, if we have more than just Translation, Scaling and Rotation, - // we need to generate a full node chain to accommodate for assimp's - // lack to express pivots and offsets. - if ( is_complex && doc.Settings().preservePivots ) { - FBXImporter::LogInfo( "generating full transformation chain for node: " + name ); - - // query the anim_chain_bits dictionary to find out which chain elements - // have associated node animation channels. These can not be dropped - // even if they have identity transform in bind pose. - NodeAnimBitMap::const_iterator it = node_anim_chain_bits.find( name ); - const unsigned int anim_chain_bitmask = ( it == node_anim_chain_bits.end() ? 0 : ( *it ).second ); - - unsigned int bit = 0x1; - for ( size_t i = 0; i < TransformationComp_MAXIMUM; ++i, bit <<= 1 ) { - const TransformationComp comp = static_cast( i ); - - if ( chain[ i ].IsIdentity() && ( anim_chain_bitmask & bit ) == 0 ) { - continue; - } - - if ( comp == TransformationComp_PostRotation ) { - chain[ i ] = chain[ i ].Inverse(); - } - - aiNode* nd = new aiNode(); - nd->mName.Set( NameTransformationChainNode( name, comp ) ); - nd->mTransformation = chain[ i ]; - - // geometric inverses go in a post-node chain - if ( comp == TransformationComp_GeometricScalingInverse || - comp == TransformationComp_GeometricRotationInverse || - comp == TransformationComp_GeometricTranslationInverse - ) { - post_output_nodes.push_back( nd ); - } else { - output_nodes.push_back( nd ); - } - } - - ai_assert( output_nodes.size() ); - return; - } - - // else, we can just multiply the matrices together - aiNode* nd = new aiNode(); - output_nodes.push_back( nd ); - std::string uniqueName; - GetUniqueName( name, uniqueName ); - - nd->mName.Set( uniqueName ); - - for (const auto &transform : chain) { - nd->mTransformation = nd->mTransformation * transform; - } -} - -void FBXConverter::SetupNodeMetadata( const Model& model, aiNode& nd ) -{ - const PropertyTable& props = model.Props(); - DirectPropertyMap unparsedProperties = props.GetUnparsedProperties(); - - // create metadata on node - const std::size_t numStaticMetaData = 2; - aiMetadata* data = aiMetadata::Alloc( static_cast(unparsedProperties.size() + numStaticMetaData) ); - nd.mMetaData = data; - int index = 0; - - // find user defined properties (3ds Max) - data->Set( index++, "UserProperties", aiString( PropertyGet( props, "UDP3DSMAX", "" ) ) ); - // preserve the info that a node was marked as Null node in the original file. - data->Set( index++, "IsNull", model.IsNull() ? true : false ); - - // add unparsed properties to the node's metadata - for( const DirectPropertyMap::value_type& prop : unparsedProperties ) { - // Interpret the property as a concrete type - if ( const TypedProperty* interpreted = prop.second->As >() ) { - data->Set( index++, prop.first, interpreted->Value() ); - } else if ( const TypedProperty* interpreted = prop.second->As >() ) { - data->Set( index++, prop.first, interpreted->Value() ); - } else if ( const TypedProperty* interpreted = prop.second->As >() ) { - data->Set( index++, prop.first, interpreted->Value() ); - } else if ( const TypedProperty* interpreted = prop.second->As >() ) { - data->Set( index++, prop.first, interpreted->Value() ); - } else if ( const TypedProperty* interpreted = prop.second->As >() ) { - data->Set( index++, prop.first, aiString( interpreted->Value() ) ); - } else if ( const TypedProperty* interpreted = prop.second->As >() ) { - data->Set( index++, prop.first, interpreted->Value() ); - } else { - ai_assert( false ); - } - } -} - -void FBXConverter::ConvertModel( const Model& model, aiNode& nd, const aiMatrix4x4& node_global_transform ) -{ - const std::vector& geos = model.GetGeometry(); - - std::vector meshes; - meshes.reserve( geos.size() ); - - for( const Geometry* geo : geos ) { - - const MeshGeometry* const mesh = dynamic_cast< const MeshGeometry* >( geo ); - if ( mesh ) { - const std::vector& indices = ConvertMesh( *mesh, model, node_global_transform, nd); - std::copy( indices.begin(), indices.end(), std::back_inserter( meshes ) ); - } - else { - FBXImporter::LogWarn( "ignoring unrecognized geometry: " + geo->Name() ); - } - } - - if ( meshes.size() ) { - nd.mMeshes = new unsigned int[ meshes.size() ](); - nd.mNumMeshes = static_cast< unsigned int >( meshes.size() ); - - std::swap_ranges( meshes.begin(), meshes.end(), nd.mMeshes ); - } -} - -std::vector FBXConverter::ConvertMesh( const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform, aiNode& nd) -{ - std::vector temp; - - MeshMap::const_iterator it = meshes_converted.find( &mesh ); - if ( it != meshes_converted.end() ) { - std::copy( ( *it ).second.begin(), ( *it ).second.end(), std::back_inserter( temp ) ); - return temp; - } - - const std::vector& vertices = mesh.GetVertices(); - const std::vector& faces = mesh.GetFaceIndexCounts(); - if ( vertices.empty() || faces.empty() ) { - FBXImporter::LogWarn( "ignoring empty geometry: " + mesh.Name() ); - return temp; - } - - // one material per mesh maps easily to aiMesh. Multiple material - // meshes need to be split. - const MatIndexArray& mindices = mesh.GetMaterialIndices(); - if ( doc.Settings().readMaterials && !mindices.empty() ) { - const MatIndexArray::value_type base = mindices[ 0 ]; - for( MatIndexArray::value_type index : mindices ) { - if ( index != base ) { - return ConvertMeshMultiMaterial( mesh, model, node_global_transform, nd); - } - } - } - - // faster code-path, just copy the data - temp.push_back( ConvertMeshSingleMaterial( mesh, model, node_global_transform, nd) ); - return temp; -} - -aiMesh* FBXConverter::SetupEmptyMesh( const MeshGeometry& mesh, aiNode& nd) -{ - aiMesh* const out_mesh = new aiMesh(); - meshes.push_back( out_mesh ); - meshes_converted[ &mesh ].push_back( static_cast( meshes.size() - 1 ) ); - - // set name - std::string name = mesh.Name(); - if ( name.substr( 0, 10 ) == "Geometry::" ) { - name = name.substr( 10 ); - } - - if ( name.length() ) { - out_mesh->mName.Set( name ); - } - else - { - out_mesh->mName = nd.mName; - } - - return out_mesh; -} - -unsigned int FBXConverter::ConvertMeshSingleMaterial( const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform, aiNode& nd) -{ - const MatIndexArray& mindices = mesh.GetMaterialIndices(); - aiMesh* const out_mesh = SetupEmptyMesh(mesh, nd); - - const std::vector& vertices = mesh.GetVertices(); - const std::vector& faces = mesh.GetFaceIndexCounts(); - - // copy vertices - out_mesh->mNumVertices = static_cast( vertices.size() ); - out_mesh->mVertices = new aiVector3D[ vertices.size() ]; - std::copy( vertices.begin(), vertices.end(), out_mesh->mVertices ); - - // generate dummy faces - out_mesh->mNumFaces = static_cast( faces.size() ); - aiFace* fac = out_mesh->mFaces = new aiFace[ faces.size() ](); - - unsigned int cursor = 0; - for( unsigned int pcount : faces ) { - aiFace& f = *fac++; - f.mNumIndices = pcount; - f.mIndices = new unsigned int[ pcount ]; - switch ( pcount ) - { - case 1: - out_mesh->mPrimitiveTypes |= aiPrimitiveType_POINT; - break; - case 2: - out_mesh->mPrimitiveTypes |= aiPrimitiveType_LINE; - break; - case 3: - out_mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; - break; - default: - out_mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON; - break; - } - for ( unsigned int i = 0; i < pcount; ++i ) { - f.mIndices[ i ] = cursor++; - } - } - - // copy normals - const std::vector& normals = mesh.GetNormals(); - if ( normals.size() ) { - ai_assert( normals.size() == vertices.size() ); - - out_mesh->mNormals = new aiVector3D[ vertices.size() ]; - std::copy( normals.begin(), normals.end(), out_mesh->mNormals ); - } - - // copy tangents - assimp requires both tangents and bitangents (binormals) - // to be present, or neither of them. Compute binormals from normals - // and tangents if needed. - const std::vector& tangents = mesh.GetTangents(); - const std::vector* binormals = &mesh.GetBinormals(); - - if ( tangents.size() ) { - std::vector tempBinormals; - if ( !binormals->size() ) { - if ( normals.size() ) { - tempBinormals.resize( normals.size() ); - for ( unsigned int i = 0; i < tangents.size(); ++i ) { - tempBinormals[ i ] = normals[ i ] ^ tangents[ i ]; - } - - binormals = &tempBinormals; - } - else { - binormals = NULL; - } - } - - if ( binormals ) { - ai_assert( tangents.size() == vertices.size() ); - ai_assert( binormals->size() == vertices.size() ); - - out_mesh->mTangents = new aiVector3D[ vertices.size() ]; - std::copy( tangents.begin(), tangents.end(), out_mesh->mTangents ); - - out_mesh->mBitangents = new aiVector3D[ vertices.size() ]; - std::copy( binormals->begin(), binormals->end(), out_mesh->mBitangents ); - } - } - - // copy texture coords - for ( unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i ) { - const std::vector& uvs = mesh.GetTextureCoords( i ); - if ( uvs.empty() ) { - break; - } - - aiVector3D* out_uv = out_mesh->mTextureCoords[ i ] = new aiVector3D[ vertices.size() ]; - for( const aiVector2D& v : uvs ) { - *out_uv++ = aiVector3D( v.x, v.y, 0.0f ); - } - - out_mesh->mNumUVComponents[ i ] = 2; - } - - // copy vertex colors - for ( unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i ) { - const std::vector& colors = mesh.GetVertexColors( i ); - if ( colors.empty() ) { - break; - } - - out_mesh->mColors[ i ] = new aiColor4D[ vertices.size() ]; - std::copy( colors.begin(), colors.end(), out_mesh->mColors[ i ] ); - } - - if ( !doc.Settings().readMaterials || mindices.empty() ) { - FBXImporter::LogError( "no material assigned to mesh, setting default material" ); - out_mesh->mMaterialIndex = GetDefaultMaterial(); - } - else { - ConvertMaterialForMesh( out_mesh, model, mesh, mindices[ 0 ] ); - } - - if ( doc.Settings().readWeights && mesh.DeformerSkin() != NULL ) { - ConvertWeights( out_mesh, model, mesh, node_global_transform, NO_MATERIAL_SEPARATION ); - } - - return static_cast( meshes.size() - 1 ); -} - -std::vector FBXConverter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model, - const aiMatrix4x4& node_global_transform, aiNode& nd) -{ - const MatIndexArray& mindices = mesh.GetMaterialIndices(); - ai_assert( mindices.size() ); - - std::set had; - std::vector indices; - - for( MatIndexArray::value_type index : mindices ) { - if ( had.find( index ) == had.end() ) { - - indices.push_back( ConvertMeshMultiMaterial( mesh, model, index, node_global_transform, nd) ); - had.insert( index ); - } - } - - return indices; -} - -unsigned int FBXConverter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model, - MatIndexArray::value_type index, - const aiMatrix4x4& node_global_transform, - aiNode& nd) -{ - aiMesh* const out_mesh = SetupEmptyMesh(mesh, nd); - - const MatIndexArray& mindices = mesh.GetMaterialIndices(); - const std::vector& vertices = mesh.GetVertices(); - const std::vector& faces = mesh.GetFaceIndexCounts(); - - const bool process_weights = doc.Settings().readWeights && mesh.DeformerSkin() != NULL; - - unsigned int count_faces = 0; - unsigned int count_vertices = 0; - - // count faces - std::vector::const_iterator itf = faces.begin(); - for ( MatIndexArray::const_iterator it = mindices.begin(), - end = mindices.end(); it != end; ++it, ++itf ) - { - if ( ( *it ) != index ) { - continue; - } - ++count_faces; - count_vertices += *itf; - } - - ai_assert( count_faces ); - ai_assert( count_vertices ); - - // mapping from output indices to DOM indexing, needed to resolve weights - std::vector reverseMapping; - - if ( process_weights ) { - reverseMapping.resize( count_vertices ); - } - - // allocate output data arrays, but don't fill them yet - out_mesh->mNumVertices = count_vertices; - out_mesh->mVertices = new aiVector3D[ count_vertices ]; - - out_mesh->mNumFaces = count_faces; - aiFace* fac = out_mesh->mFaces = new aiFace[ count_faces ](); - - - // allocate normals - const std::vector& normals = mesh.GetNormals(); - if ( normals.size() ) { - ai_assert( normals.size() == vertices.size() ); - out_mesh->mNormals = new aiVector3D[ vertices.size() ]; - } - - // allocate tangents, binormals. - const std::vector& tangents = mesh.GetTangents(); - const std::vector* binormals = &mesh.GetBinormals(); - std::vector tempBinormals; - - if ( tangents.size() ) { - if ( !binormals->size() ) { - if ( normals.size() ) { - // XXX this computes the binormals for the entire mesh, not only - // the part for which we need them. - tempBinormals.resize( normals.size() ); - for ( unsigned int i = 0; i < tangents.size(); ++i ) { - tempBinormals[ i ] = normals[ i ] ^ tangents[ i ]; - } - - binormals = &tempBinormals; - } - else { - binormals = NULL; - } - } - - if ( binormals ) { - ai_assert( tangents.size() == vertices.size() && binormals->size() == vertices.size() ); - - out_mesh->mTangents = new aiVector3D[ vertices.size() ]; - out_mesh->mBitangents = new aiVector3D[ vertices.size() ]; - } - } - - // allocate texture coords - unsigned int num_uvs = 0; - for ( unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i, ++num_uvs ) { - const std::vector& uvs = mesh.GetTextureCoords( i ); - if ( uvs.empty() ) { - break; - } - - out_mesh->mTextureCoords[ i ] = new aiVector3D[ vertices.size() ]; - out_mesh->mNumUVComponents[ i ] = 2; - } - - // allocate vertex colors - unsigned int num_vcs = 0; - for ( unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i, ++num_vcs ) { - const std::vector& colors = mesh.GetVertexColors( i ); - if ( colors.empty() ) { - break; - } - - out_mesh->mColors[ i ] = new aiColor4D[ vertices.size() ]; - } - - unsigned int cursor = 0, in_cursor = 0; - - itf = faces.begin(); - for ( MatIndexArray::const_iterator it = mindices.begin(), - end = mindices.end(); it != end; ++it, ++itf ) - { - const unsigned int pcount = *itf; - if ( ( *it ) != index ) { - in_cursor += pcount; - continue; - } - - aiFace& f = *fac++; - - f.mNumIndices = pcount; - f.mIndices = new unsigned int[ pcount ]; - switch ( pcount ) - { - case 1: - out_mesh->mPrimitiveTypes |= aiPrimitiveType_POINT; - break; - case 2: - out_mesh->mPrimitiveTypes |= aiPrimitiveType_LINE; - break; - case 3: - out_mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; - break; - default: - out_mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON; - break; - } - for ( unsigned int i = 0; i < pcount; ++i, ++cursor, ++in_cursor ) { - f.mIndices[ i ] = cursor; - - if ( reverseMapping.size() ) { - reverseMapping[ cursor ] = in_cursor; - } - - out_mesh->mVertices[ cursor ] = vertices[ in_cursor ]; - - if ( out_mesh->mNormals ) { - out_mesh->mNormals[ cursor ] = normals[ in_cursor ]; - } - - if ( out_mesh->mTangents ) { - out_mesh->mTangents[ cursor ] = tangents[ in_cursor ]; - out_mesh->mBitangents[ cursor ] = ( *binormals )[ in_cursor ]; - } - - for ( unsigned int j = 0; j < num_uvs; ++j ) { - const std::vector& uvs = mesh.GetTextureCoords( j ); - out_mesh->mTextureCoords[ j ][ cursor ] = aiVector3D( uvs[ in_cursor ].x, uvs[ in_cursor ].y, 0.0f ); - } - - for ( unsigned int j = 0; j < num_vcs; ++j ) { - const std::vector& cols = mesh.GetVertexColors( j ); - out_mesh->mColors[ j ][ cursor ] = cols[ in_cursor ]; - } - } - } - - ConvertMaterialForMesh( out_mesh, model, mesh, index ); - - if ( process_weights ) { - ConvertWeights( out_mesh, model, mesh, node_global_transform, index, &reverseMapping ); - } - - return static_cast( meshes.size() - 1 ); -} - -void FBXConverter::ConvertWeights( aiMesh* out, const Model& model, const MeshGeometry& geo, - const aiMatrix4x4& node_global_transform , - unsigned int materialIndex, - std::vector* outputVertStartIndices ) -{ - ai_assert( geo.DeformerSkin() ); - - std::vector out_indices; - std::vector index_out_indices; - std::vector count_out_indices; - - const Skin& sk = *geo.DeformerSkin(); - - std::vector bones; - bones.reserve( sk.Clusters().size() ); - - const bool no_mat_check = materialIndex == NO_MATERIAL_SEPARATION; - ai_assert( no_mat_check || outputVertStartIndices ); - - try { - - for( const Cluster* cluster : sk.Clusters() ) { - ai_assert( cluster ); - - const WeightIndexArray& indices = cluster->GetIndices(); - - if ( indices.empty() ) { - continue; - } - - const MatIndexArray& mats = geo.GetMaterialIndices(); - - bool ok = false; - - const size_t no_index_sentinel = std::numeric_limits::max(); - - count_out_indices.clear(); - index_out_indices.clear(); - out_indices.clear(); - - // now check if *any* of these weights is contained in the output mesh, - // taking notes so we don't need to do it twice. - for( WeightIndexArray::value_type index : indices ) { - - unsigned int count = 0; - const unsigned int* const out_idx = geo.ToOutputVertexIndex( index, count ); - // ToOutputVertexIndex only returns NULL if index is out of bounds - // which should never happen - ai_assert( out_idx != NULL ); - - index_out_indices.push_back( no_index_sentinel ); - count_out_indices.push_back( 0 ); - - for ( unsigned int i = 0; i < count; ++i ) { - if ( no_mat_check || static_cast( mats[ geo.FaceForVertexIndex( out_idx[ i ] ) ] ) == materialIndex ) { - - if ( index_out_indices.back() == no_index_sentinel ) { - index_out_indices.back() = out_indices.size(); - - } - - if ( no_mat_check ) { - out_indices.push_back( out_idx[ i ] ); + if (!name_carrier) { + std::string old_original_name = original_name; + GetUniqueName(old_original_name, original_name); + nodes_chain.push_back(new aiNode(original_name)); } else { - // this extra lookup is in O(logn), so the entire algorithm becomes O(nlogn) - const std::vector::iterator it = std::lower_bound( - outputVertStartIndices->begin(), - outputVertStartIndices->end(), - out_idx[ i ] - ); - - out_indices.push_back( std::distance( outputVertStartIndices->begin(), it ) ); + original_name = nodes_chain.back()->mName.C_Str(); } - ++count_out_indices.back(); - ok = true; - } - } - } + //setup metadata on newest node + SetupNodeMetadata(*model, *nodes_chain.back()); - // if we found at least one, generate the output bones - // XXX this could be heavily simplified by collecting the bone - // data in a single step. - if ( ok ) { - ConvertCluster( bones, model, *cluster, out_indices, index_out_indices, - count_out_indices, node_global_transform ); - } - } - } - catch ( std::exception& ) { - std::for_each( bones.begin(), bones.end(), Util::delete_fun() ); - throw; - } + // link all nodes in a row + aiNode* last_parent = &parent; + for (aiNode* prenode : nodes_chain) { + ai_assert(prenode); - if ( bones.empty() ) { - return; - } - - out->mBones = new aiBone*[ bones.size() ](); - out->mNumBones = static_cast( bones.size() ); - - std::swap_ranges( bones.begin(), bones.end(), out->mBones ); -} - -void FBXConverter::ConvertCluster( std::vector& bones, const Model& /*model*/, const Cluster& cl, - std::vector& out_indices, - std::vector& index_out_indices, - std::vector& count_out_indices, - const aiMatrix4x4& node_global_transform ) -{ - - aiBone* const bone = new aiBone(); - bones.push_back( bone ); - - bone->mName = FixNodeName( cl.TargetNode()->Name() ); - - bone->mOffsetMatrix = cl.TransformLink(); - bone->mOffsetMatrix.Inverse(); - - bone->mOffsetMatrix = bone->mOffsetMatrix * node_global_transform; - - bone->mNumWeights = static_cast( out_indices.size() ); - aiVertexWeight* cursor = bone->mWeights = new aiVertexWeight[ out_indices.size() ]; - - const size_t no_index_sentinel = std::numeric_limits::max(); - const WeightArray& weights = cl.GetWeights(); - - const size_t c = index_out_indices.size(); - for ( size_t i = 0; i < c; ++i ) { - const size_t index_index = index_out_indices[ i ]; - - if ( index_index == no_index_sentinel ) { - continue; - } - - const size_t cc = count_out_indices[ i ]; - for ( size_t j = 0; j < cc; ++j ) { - aiVertexWeight& out_weight = *cursor++; - - out_weight.mVertexId = static_cast( out_indices[ index_index + j ] ); - out_weight.mWeight = weights[ i ]; - } - } -} - -void FBXConverter::ConvertMaterialForMesh( aiMesh* out, const Model& model, const MeshGeometry& geo, - MatIndexArray::value_type materialIndex ) -{ - // locate source materials for this mesh - const std::vector& mats = model.GetMaterials(); - if ( static_cast( materialIndex ) >= mats.size() || materialIndex < 0 ) { - FBXImporter::LogError( "material index out of bounds, setting default material" ); - out->mMaterialIndex = GetDefaultMaterial(); - return; - } - - const Material* const mat = mats[ materialIndex ]; - MaterialMap::const_iterator it = materials_converted.find( mat ); - if ( it != materials_converted.end() ) { - out->mMaterialIndex = ( *it ).second; - return; - } - - out->mMaterialIndex = ConvertMaterial( *mat, &geo ); - materials_converted[ mat ] = out->mMaterialIndex; -} - -unsigned int FBXConverter::GetDefaultMaterial() -{ - if ( defaultMaterialIndex ) { - return defaultMaterialIndex - 1; - } - - aiMaterial* out_mat = new aiMaterial(); - materials.push_back( out_mat ); - - const aiColor3D diffuse = aiColor3D( 0.8f, 0.8f, 0.8f ); - out_mat->AddProperty( &diffuse, 1, AI_MATKEY_COLOR_DIFFUSE ); - - aiString s; - s.Set( AI_DEFAULT_MATERIAL_NAME ); - - out_mat->AddProperty( &s, AI_MATKEY_NAME ); - - defaultMaterialIndex = static_cast< unsigned int >( materials.size() ); - return defaultMaterialIndex - 1; -} - - -unsigned int FBXConverter::ConvertMaterial( const Material& material, const MeshGeometry* const mesh ) -{ - const PropertyTable& props = material.Props(); - - // generate empty output material - aiMaterial* out_mat = new aiMaterial(); - materials_converted[ &material ] = static_cast( materials.size() ); - - materials.push_back( out_mat ); - - aiString str; - - // strip Material:: prefix - std::string name = material.Name(); - if ( name.substr( 0, 10 ) == "Material::" ) { - name = name.substr( 10 ); - } - - // set material name if not empty - this could happen - // and there should be no key for it in this case. - if ( name.length() ) { - str.Set( name ); - out_mat->AddProperty( &str, AI_MATKEY_NAME ); - } - - // shading stuff and colors - SetShadingPropertiesCommon( out_mat, props ); - - // texture assignments - SetTextureProperties( out_mat, material.Textures(), mesh ); - SetTextureProperties( out_mat, material.LayeredTextures(), mesh ); - - return static_cast( materials.size() - 1 ); -} - -unsigned int FBXConverter::ConvertVideo( const Video& video ) -{ - // generate empty output texture - aiTexture* out_tex = new aiTexture(); - textures.push_back( out_tex ); - - // assuming the texture is compressed - 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 - out_tex->pcData = reinterpret_cast( const_cast( video ).RelinquishContent() ); - - // try to extract a hint from the file extension - const std::string& filename = video.FileName().empty() ? video.RelativeFilename() : video.FileName(); - std::string ext = BaseImporter::GetExtension( filename ); - - if ( ext == "jpeg" ) { - ext = "jpg"; - } - - if ( ext.size() <= 3 ) { - memcpy( out_tex->achFormatHint, ext.c_str(), ext.size() ); - } - - out_tex->mFilename.Set(video.FileName().c_str()); - - return static_cast( textures.size() - 1 ); -} - -aiString FBXConverter::GetTexturePath(const Texture* tex) -{ - aiString path; - path.Set(tex->RelativeFilename()); - - const Video* media = tex->Media(); - if (media != nullptr) { - 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; - textureReady = true; - } - else { - if (media->ContentLength() > 0) { - index = ConvertVideo(*media); - textures_converted[media] = index; - textureReady = true; - } - } - - // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture), if the texture is ready - if (doc.Settings().useLegacyEmbeddedTextureNaming) { - if (textureReady) { - // TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING" - // In FBX files textures are now stored internally by Assimp with their filename included - // Now Assimp can lookup through the loaded textures after all data is processed - // We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it - // This may occur on this case too, it has to be studied - path.data[0] = '*'; - path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index); - } - } - } - - return path; -} - -void FBXConverter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap& textures, - const std::string& propName, - aiTextureType target, const MeshGeometry* const mesh ) -{ - TextureMap::const_iterator it = textures.find( propName ); - if ( it == textures.end() ) { - return; - } - - const Texture* const tex = ( *it ).second; - if ( tex != nullptr ) { - aiString path = GetTexturePath(tex); - out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, 0 ); - - aiUVTransform uvTrafo; - // XXX handle all kinds of UV transformations - uvTrafo.mScaling = tex->UVScaling(); - uvTrafo.mTranslation = tex->UVTranslation(); - out_mat->AddProperty( &uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, 0 ); - - const PropertyTable& props = tex->Props(); - - int uvIndex = 0; - - bool ok; - const std::string& uvSet = PropertyGet( props, "UVSet", ok ); - if ( ok ) { - // "default" is the name which usually appears in the FbxFileTexture template - if ( uvSet != "default" && uvSet.length() ) { - // this is a bit awkward - we need to find a mesh that uses this - // material and scan its UV channels for the given UV name because - // assimp references UV channels by index, not by name. - - // XXX: the case that UV channels may appear in different orders - // in meshes is unhandled. A possible solution would be to sort - // the UV channels alphabetically, but this would have the side - // effect that the primary (first) UV channel would sometimes - // be moved, causing trouble when users read only the first - // UV channel and ignore UV channel assignments altogether. - - const unsigned int matIndex = static_cast( std::distance( materials.begin(), - std::find( materials.begin(), materials.end(), out_mat ) - ) ); - - - uvIndex = -1; - if ( !mesh ) - { - for( const MeshMap::value_type& v : meshes_converted ) { - const MeshGeometry* const mesh = dynamic_cast ( v.first ); - if ( !mesh ) { - continue; - } - - const MatIndexArray& mats = mesh->GetMaterialIndices(); - if ( std::find( mats.begin(), mats.end(), matIndex ) == mats.end() ) { - continue; - } - - int index = -1; - for ( unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i ) { - if ( mesh->GetTextureCoords( i ).empty() ) { - break; + if (last_parent != &parent) { + last_parent->mNumChildren = 1; + last_parent->mChildren = new aiNode*[1]; + last_parent->mChildren[0] = prenode; } - const std::string& name = mesh->GetTextureCoordChannelName( i ); - if ( name == uvSet ) { - index = static_cast( i ); - break; - } - } - if ( index == -1 ) { - FBXImporter::LogWarn( "did not find UV channel named " + uvSet + " in a mesh using this material" ); - continue; + + prenode->mParent = last_parent; + last_parent = prenode; + + new_abs_transform *= prenode->mTransformation; } - if ( uvIndex == -1 ) { - uvIndex = index; + // attach geometry + ConvertModel(*model, *nodes_chain.back(), new_abs_transform); + + // check if there will be any child nodes + const std::vector& child_conns + = doc.GetConnectionsByDestinationSequenced(model->ID(), "Model"); + + // if so, link the geometric transform inverse nodes + // before we attach any child nodes + if (child_conns.size()) { + for (aiNode* postnode : post_nodes_chain) { + ai_assert(postnode); + + if (last_parent != &parent) { + last_parent->mNumChildren = 1; + last_parent->mChildren = new aiNode*[1]; + last_parent->mChildren[0] = postnode; + } + + postnode->mParent = last_parent; + last_parent = postnode; + + new_abs_transform *= postnode->mTransformation; + } } else { - FBXImporter::LogWarn( "the UV channel named " + uvSet + - " appears at different positions in meshes, results will be wrong" ); + // free the nodes we allocated as we don't need them + Util::delete_fun deleter; + std::for_each( + post_nodes_chain.begin(), + post_nodes_chain.end(), + deleter + ); } - } - } - else - { - int index = -1; - for ( unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i ) { - if ( mesh->GetTextureCoords( i ).empty() ) { - break; - } - const std::string& name = mesh->GetTextureCoordChannelName( i ); - if ( name == uvSet ) { - index = static_cast( i ); - break; - } - } - if ( index == -1 ) { - FBXImporter::LogWarn( "did not find UV channel named " + uvSet + " in a mesh using this material" ); - } - if ( uvIndex == -1 ) { - uvIndex = index; + // attach sub-nodes (if any) + ConvertNodes(model->ID(), *last_parent, new_abs_transform); + + if (doc.Settings().readLights) { + ConvertLights(*model, original_name); + } + + if (doc.Settings().readCameras) { + ConvertCameras(*model, original_name); + } + + nodes.push_back(nodes_chain.front()); + nodes_chain.clear(); } } - if ( uvIndex == -1 ) { - FBXImporter::LogWarn( "failed to resolve UV channel " + uvSet + ", using first UV channel" ); - uvIndex = 0; + if (nodes.size()) { + parent.mChildren = new aiNode*[nodes.size()](); + parent.mNumChildren = static_cast(nodes.size()); + + std::swap_ranges(nodes.begin(), nodes.end(), parent.mChildren); + } + } + catch (std::exception&) { + Util::delete_fun deleter; + std::for_each(nodes.begin(), nodes.end(), deleter); + std::for_each(nodes_chain.begin(), nodes_chain.end(), deleter); + std::for_each(post_nodes_chain.begin(), post_nodes_chain.end(), deleter); + } + } + + + void FBXConverter::ConvertLights(const Model& model, const std::string &orig_name) { + const std::vector& node_attrs = model.GetAttributes(); + for (const NodeAttribute* attr : node_attrs) { + const Light* const light = dynamic_cast(attr); + if (light) { + ConvertLight(*light, orig_name); } } } - out_mat->AddProperty( &uvIndex, 1, _AI_MATKEY_UVWSRC_BASE, target, 0 ); - } -} - -void FBXConverter::TrySetTextureProperties( aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, - const std::string& propName, - aiTextureType target, const MeshGeometry* const mesh ) { - LayeredTextureMap::const_iterator it = layeredTextures.find( propName ); - if ( it == layeredTextures.end() ) { - return; - } - - int texCount = (*it).second->textureCount(); - - // Set the blend mode for layered textures - int blendmode= (*it).second->GetBlendMode(); - out_mat->AddProperty(&blendmode,1,_AI_MATKEY_TEXOP_BASE,target,0); - - for(int texIndex = 0; texIndex < texCount; texIndex++){ - - const Texture* const tex = ( *it ).second->getTexture(texIndex); - - aiString path = GetTexturePath(tex); - out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, texIndex ); - - aiUVTransform uvTrafo; - // XXX handle all kinds of UV transformations - uvTrafo.mScaling = tex->UVScaling(); - uvTrafo.mTranslation = tex->UVTranslation(); - out_mat->AddProperty( &uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, texIndex ); - - const PropertyTable& props = tex->Props(); - - int uvIndex = 0; - - bool ok; - const std::string& uvSet = PropertyGet( props, "UVSet", ok ); - if ( ok ) { - // "default" is the name which usually appears in the FbxFileTexture template - if ( uvSet != "default" && uvSet.length() ) { - // this is a bit awkward - we need to find a mesh that uses this - // material and scan its UV channels for the given UV name because - // assimp references UV channels by index, not by name. - - // XXX: the case that UV channels may appear in different orders - // in meshes is unhandled. A possible solution would be to sort - // the UV channels alphabetically, but this would have the side - // effect that the primary (first) UV channel would sometimes - // be moved, causing trouble when users read only the first - // UV channel and ignore UV channel assignments altogether. - - const unsigned int matIndex = static_cast( std::distance( materials.begin(), - std::find( materials.begin(), materials.end(), out_mat ) - ) ); - - uvIndex = -1; - if ( !mesh ) - { - for( const MeshMap::value_type& v : meshes_converted ) { - const MeshGeometry* const mesh = dynamic_cast ( v.first ); - if ( !mesh ) { - continue; - } - - const MatIndexArray& mats = mesh->GetMaterialIndices(); - if ( std::find( mats.begin(), mats.end(), matIndex ) == mats.end() ) { - continue; - } - - int index = -1; - for ( unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i ) { - if ( mesh->GetTextureCoords( i ).empty() ) { - break; - } - const std::string& name = mesh->GetTextureCoordChannelName( i ); - if ( name == uvSet ) { - index = static_cast( i ); - break; - } - } - if ( index == -1 ) { - FBXImporter::LogWarn( "did not find UV channel named " + uvSet + " in a mesh using this material" ); - continue; - } - - if ( uvIndex == -1 ) { - uvIndex = index; - } - else { - FBXImporter::LogWarn( "the UV channel named " + uvSet + - " appears at different positions in meshes, results will be wrong" ); - } - } - } - else - { - int index = -1; - for ( unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i ) { - if ( mesh->GetTextureCoords( i ).empty() ) { - break; - } - const std::string& name = mesh->GetTextureCoordChannelName( i ); - if ( name == uvSet ) { - index = static_cast( i ); - break; - } - } - if ( index == -1 ) { - FBXImporter::LogWarn( "did not find UV channel named " + uvSet + " in a mesh using this material" ); - } - - if ( uvIndex == -1 ) { - uvIndex = index; - } - } - - if ( uvIndex == -1 ) { - FBXImporter::LogWarn( "failed to resolve UV channel " + uvSet + ", using first UV channel" ); - uvIndex = 0; + void FBXConverter::ConvertCameras(const Model& model, const std::string &orig_name) { + const std::vector& node_attrs = model.GetAttributes(); + for (const NodeAttribute* attr : node_attrs) { + const Camera* const cam = dynamic_cast(attr); + if (cam) { + ConvertCamera(*cam, orig_name); } } } - out_mat->AddProperty( &uvIndex, 1, _AI_MATKEY_UVWSRC_BASE, target, texIndex ); - } -} + void FBXConverter::ConvertLight(const Light& light, const std::string &orig_name) { + lights.push_back(new aiLight()); + aiLight* const out_light = lights.back(); -void FBXConverter::SetTextureProperties( aiMaterial* out_mat, const TextureMap& textures, const MeshGeometry* const mesh ) -{ - TrySetTextureProperties( out_mat, textures, "DiffuseColor", aiTextureType_DIFFUSE, mesh ); - TrySetTextureProperties( out_mat, textures, "AmbientColor", aiTextureType_AMBIENT, mesh ); - TrySetTextureProperties( out_mat, textures, "EmissiveFactor", aiTextureType_EMISSIVE, mesh ); - TrySetTextureProperties( out_mat, textures, "SpecularFactor", aiTextureType_SPECULAR, mesh); - TrySetTextureProperties( out_mat, textures, "TransparencyFactor", aiTextureType_OPACITY, mesh ); - TrySetTextureProperties( out_mat, textures, "ReflectionColor", aiTextureType_REFLECTION, mesh ); - TrySetTextureProperties( out_mat, textures, "DisplacementColor", aiTextureType_DISPLACEMENT, mesh ); - TrySetTextureProperties( out_mat, textures, "NormalMap", aiTextureType_NORMALS, mesh ); - TrySetTextureProperties( out_mat, textures, "Bump", aiTextureType_HEIGHT, mesh ); - TrySetTextureProperties( out_mat, textures, "ShininessExponent", aiTextureType_SHININESS, mesh ); -} + out_light->mName.Set(orig_name); -void FBXConverter::SetTextureProperties( aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, const MeshGeometry* const mesh ) -{ - TrySetTextureProperties( out_mat, layeredTextures, "DiffuseColor", aiTextureType_DIFFUSE, mesh ); - TrySetTextureProperties( out_mat, layeredTextures, "AmbientColor", aiTextureType_AMBIENT, mesh ); - TrySetTextureProperties( out_mat, layeredTextures, "EmissiveFactor", aiTextureType_EMISSIVE, mesh ); - TrySetTextureProperties( out_mat, layeredTextures, "SpecularFactor", aiTextureType_SPECULAR, mesh); - TrySetTextureProperties( out_mat, layeredTextures, "TransparencyFactor", aiTextureType_OPACITY, mesh ); - TrySetTextureProperties( out_mat, layeredTextures, "ReflectionColor", aiTextureType_REFLECTION, mesh ); - TrySetTextureProperties( out_mat, layeredTextures, "DisplacementColor", aiTextureType_DISPLACEMENT, mesh ); - TrySetTextureProperties( out_mat, layeredTextures, "NormalMap", aiTextureType_NORMALS, mesh ); - TrySetTextureProperties( out_mat, layeredTextures, "Bump", aiTextureType_HEIGHT, mesh ); - TrySetTextureProperties( out_mat, layeredTextures, "ShininessExponent", aiTextureType_SHININESS, mesh ); -} + const float intensity = light.Intensity() / 100.0f; + const aiVector3D& col = light.Color(); -aiColor3D FBXConverter::GetColorPropertyFactored( const PropertyTable& props, const std::string& colorName, - const std::string& factorName, bool& result, bool useTemplate ) -{ - result = true; + out_light->mColorDiffuse = aiColor3D(col.x, col.y, col.z); + out_light->mColorDiffuse.r *= intensity; + out_light->mColorDiffuse.g *= intensity; + out_light->mColorDiffuse.b *= intensity; - bool ok; - aiVector3D BaseColor = PropertyGet( props, colorName, ok, useTemplate ); - if ( ! ok ) { - result = false; - return aiColor3D( 0.0f, 0.0f, 0.0f ); - } + out_light->mColorSpecular = out_light->mColorDiffuse; - // if no factor name, return the colour as is - if ( factorName.empty() ) { - return aiColor3D( BaseColor.x, BaseColor.y, BaseColor.z ); - } + //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); - // otherwise it should be multiplied by the factor, if found. - float factor = PropertyGet( props, factorName, ok, useTemplate ); - if ( ok ) { - BaseColor *= factor; - } - return aiColor3D( BaseColor.x, BaseColor.y, BaseColor.z ); -} - -aiColor3D FBXConverter::GetColorPropertyFromMaterial( const PropertyTable& props, const std::string& baseName, - bool& result ) -{ - return GetColorPropertyFactored( props, baseName + "Color", baseName + "Factor", result, true ); -} - -aiColor3D FBXConverter::GetColorProperty( const PropertyTable& props, const std::string& colorName, - bool& result, bool useTemplate ) -{ - result = true; - bool ok; - const aiVector3D& ColorVec = PropertyGet( props, colorName, ok, useTemplate ); - if ( ! ok ) { - result = false; - return aiColor3D( 0.0f, 0.0f, 0.0f ); - } - return aiColor3D( ColorVec.x, ColorVec.y, ColorVec.z ); -} - -void FBXConverter::SetShadingPropertiesCommon( aiMaterial* out_mat, const PropertyTable& props ) -{ - // Set shading properties. - // Modern FBX Files have two separate systems for defining these, - // with only the more comprehensive one described in the property template. - // Likely the other values are a legacy system, - // which is still always exported by the official FBX SDK. - // - // Blender's FBX import and export mostly ignore this legacy system, - // and as we only support recent versions of FBX anyway, we can do the same. - bool ok; - - const aiColor3D& Diffuse = GetColorPropertyFromMaterial( props, "Diffuse", ok ); - if ( ok ) { - out_mat->AddProperty( &Diffuse, 1, AI_MATKEY_COLOR_DIFFUSE ); - } - - const aiColor3D& Emissive = GetColorPropertyFromMaterial( props, "Emissive", ok ); - if ( ok ) { - out_mat->AddProperty( &Emissive, 1, AI_MATKEY_COLOR_EMISSIVE ); - } - - const aiColor3D& Ambient = GetColorPropertyFromMaterial( props, "Ambient", ok ); - if ( ok ) { - out_mat->AddProperty( &Ambient, 1, AI_MATKEY_COLOR_AMBIENT ); - } - - // we store specular factor as SHININESS_STRENGTH, so just get the color - const aiColor3D& Specular = GetColorProperty( props, "SpecularColor", ok, true ); - if ( ok ) { - out_mat->AddProperty( &Specular, 1, AI_MATKEY_COLOR_SPECULAR ); - } - - // and also try to get SHININESS_STRENGTH - const float SpecularFactor = PropertyGet( props, "SpecularFactor", ok, true ); - if ( ok ) { - out_mat->AddProperty( &SpecularFactor, 1, AI_MATKEY_SHININESS_STRENGTH ); - } - - // and the specular exponent - const float ShininessExponent = PropertyGet( props, "ShininessExponent", ok ); - if ( ok ) { - out_mat->AddProperty( &ShininessExponent, 1, AI_MATKEY_SHININESS ); - } - - // TransparentColor / TransparencyFactor... gee thanks FBX :rolleyes: - const aiColor3D& Transparent = GetColorPropertyFactored( props, "TransparentColor", "TransparencyFactor", ok ); - float CalculatedOpacity = 1.0f; - if ( ok ) { - out_mat->AddProperty( &Transparent, 1, AI_MATKEY_COLOR_TRANSPARENT ); - // as calculated by FBX SDK 2017: - CalculatedOpacity = 1.0f - ((Transparent.r + Transparent.g + Transparent.b) / 3.0f); - } - - // use of TransparencyFactor is inconsistent. - // Maya always stores it as 1.0, - // so we can't use it to set AI_MATKEY_OPACITY. - // Blender is more sensible and stores it as the alpha value. - // However both the FBX SDK and Blender always write an additional - // legacy "Opacity" field, so we can try to use that. - // - // If we can't find it, - // we can fall back to the value which the FBX SDK calculates - // from transparency colour (RGB) and factor (F) as - // 1.0 - F*((R+G+B)/3). - // - // There's no consistent way to interpret this opacity value, - // so it's up to clients to do the correct thing. - const float Opacity = PropertyGet( props, "Opacity", ok ); - if ( ok ) { - out_mat->AddProperty( &Opacity, 1, AI_MATKEY_OPACITY ); - } - else if ( CalculatedOpacity != 1.0 ) { - out_mat->AddProperty( &CalculatedOpacity, 1, AI_MATKEY_OPACITY ); - } - - // reflection color and factor are stored separately - const aiColor3D& Reflection = GetColorProperty( props, "ReflectionColor", ok, true ); - if ( ok ) { - out_mat->AddProperty( &Reflection, 1, AI_MATKEY_COLOR_REFLECTIVE ); - } - - float ReflectionFactor = PropertyGet( props, "ReflectionFactor", ok, true ); - if ( ok ) { - out_mat->AddProperty( &ReflectionFactor, 1, AI_MATKEY_REFLECTIVITY ); - } - - 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); - } -} - - -double FBXConverter::FrameRateToDouble( FileGlobalSettings::FrameRate fp, double customFPSVal ) { - switch ( fp ) { - case FileGlobalSettings::FrameRate_DEFAULT: - return 1.0; - - case FileGlobalSettings::FrameRate_120: - return 120.0; - - case FileGlobalSettings::FrameRate_100: - return 100.0; - - case FileGlobalSettings::FrameRate_60: - return 60.0; - - case FileGlobalSettings::FrameRate_50: - return 50.0; - - case FileGlobalSettings::FrameRate_48: - return 48.0; - - case FileGlobalSettings::FrameRate_30: - case FileGlobalSettings::FrameRate_30_DROP: - return 30.0; - - case FileGlobalSettings::FrameRate_NTSC_DROP_FRAME: - case FileGlobalSettings::FrameRate_NTSC_FULL_FRAME: - return 29.9700262; - - case FileGlobalSettings::FrameRate_PAL: - return 25.0; - - case FileGlobalSettings::FrameRate_CINEMA: - return 24.0; - - case FileGlobalSettings::FrameRate_1000: - return 1000.0; - - case FileGlobalSettings::FrameRate_CINEMA_ND: - return 23.976; - - case FileGlobalSettings::FrameRate_CUSTOM: - return customFPSVal; - - case FileGlobalSettings::FrameRate_MAX: // this is to silence compiler warnings - break; - } - - ai_assert( false ); - - return -1.0f; -} - - -void FBXConverter::ConvertAnimations() -{ - // first of all determine framerate - const FileGlobalSettings::FrameRate fps = doc.GlobalSettings().TimeMode(); - const float custom = doc.GlobalSettings().CustomFrameRate(); - anim_fps = FrameRateToDouble( fps, custom ); - - const std::vector& animations = doc.AnimationStacks(); - for( const AnimationStack* stack : animations ) { - ConvertAnimationStack( *stack ); - } -} - -std::string FBXConverter::FixNodeName( const std::string& name ) { - // strip Model:: prefix, avoiding ambiguities (i.e. don't strip if - // this causes ambiguities, well possible between empty identifiers, - // such as "Model::" and ""). Make sure the behaviour is consistent - // across multiple calls to FixNodeName(). - if ( name.substr( 0, 7 ) == "Model::" ) { - std::string temp = name.substr( 7 ); - return temp; - } - - return name; -} - -void FBXConverter::ConvertAnimationStack( const AnimationStack& st ) -{ - const AnimationLayerList& layers = st.Layers(); - if ( layers.empty() ) { - return; - } - - aiAnimation* const anim = new aiAnimation(); - animations.push_back( anim ); - - // strip AnimationStack:: prefix - std::string name = st.Name(); - if ( name.substr( 0, 16 ) == "AnimationStack::" ) { - name = name.substr( 16 ); - } - else if ( name.substr( 0, 11 ) == "AnimStack::" ) { - name = name.substr( 11 ); - } - - anim->mName.Set( name ); - - // need to find all nodes for which we need to generate node animations - - // it may happen that we need to merge multiple layers, though. - NodeMap node_map; - - // reverse mapping from curves to layers, much faster than querying - // the FBX DOM for it. - LayerMap layer_map; - - const char* prop_whitelist[] = { - "Lcl Scaling", - "Lcl Rotation", - "Lcl Translation" - }; - - for( const AnimationLayer* layer : layers ) { - ai_assert( layer ); - - const AnimationCurveNodeList& nodes = layer->Nodes( prop_whitelist, 3 ); - for( const AnimationCurveNode* node : nodes ) { - ai_assert( node ); - - const Model* const model = dynamic_cast( node->Target() ); - // this can happen - it could also be a NodeAttribute (i.e. for camera animations) - if ( !model ) { - continue; - } - - const std::string& name = FixNodeName( model->Name() ); - node_map[ name ].push_back( node ); - - layer_map[ node ] = layer; - } - } - - // generate node animations - std::vector node_anims; - - double min_time = 1e10; - double max_time = -1e10; - - int64_t start_time = st.LocalStart(); - int64_t stop_time = st.LocalStop(); - 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 ) { - GenerateNodeAnimations( node_anims, - kv.first, - kv.second, - layer_map, - start_time, stop_time, - max_time, - min_time ); - } - } - catch ( std::exception& ) { - std::for_each( node_anims.begin(), node_anims.end(), Util::delete_fun() ); - throw; - } - - if ( node_anims.size() ) { - anim->mChannels = new aiNodeAnim*[ node_anims.size() ](); - anim->mNumChannels = static_cast( node_anims.size() ); - - std::swap_ranges( node_anims.begin(), node_anims.end(), anim->mChannels ); - } - else { - // empty animations would fail validation, so drop them - delete anim; - animations.pop_back(); - FBXImporter::LogInfo( "ignoring empty AnimationStack (using IK?): " + name ); - return; - } - - 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; - - // 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_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, - bool strictMode ) { - const Object* target( NULL ); - for( const AnimationCurveNode* node : curves ) { - if ( !target ) { - target = node->Target(); - } - if ( node->Target() != target ) { - FBXImporter::LogWarn( "Node target is nullptr type." ); - } - if ( strictMode ) { - ai_assert( node->Target() == target ); - } - } -} -#endif // ASSIMP_BUILD_DEBUG - -// ------------------------------------------------------------------------------------------------ -void FBXConverter::GenerateNodeAnimations( std::vector& node_anims, - const std::string& fixed_name, - const std::vector& curves, - const LayerMap& layer_map, - int64_t start, int64_t stop, - double& max_time, - double& min_time ) -{ - - NodeMap node_property_map; - ai_assert( curves.size() ); - -#ifdef ASSIMP_BUILD_DEBUG - validateAnimCurveNodes( curves, doc.Settings().strictMode ); -#endif - const AnimationCurveNode* curve_node = NULL; - for( const AnimationCurveNode* node : curves ) { - ai_assert( node ); - - if ( node->TargetProperty().empty() ) { - FBXImporter::LogWarn( "target property for animation curve not set: " + node->Name() ); - continue; - } - - curve_node = node; - if ( node->Curves().empty() ) { - FBXImporter::LogWarn( "no animation curves assigned to AnimationCurveNode: " + node->Name() ); - continue; - } - - node_property_map[ node->TargetProperty() ].push_back( node ); - } - - ai_assert( curve_node ); - ai_assert( curve_node->TargetAsModel() ); - - const Model& target = *curve_node->TargetAsModel(); - - // check for all possible transformation components - NodeMap::const_iterator chain[ TransformationComp_MAXIMUM ]; - - bool has_any = false; - bool has_complex = false; - - for ( size_t i = 0; i < TransformationComp_MAXIMUM; ++i ) { - const TransformationComp comp = static_cast( i ); - - // inverse pivots don't exist in the input, we just generate them - if ( comp == TransformationComp_RotationPivotInverse || comp == TransformationComp_ScalingPivotInverse ) { - chain[ i ] = node_property_map.end(); - continue; - } - - chain[ i ] = node_property_map.find( NameTransformationCompProperty( comp ) ); - if ( chain[ i ] != node_property_map.end() ) { - - // check if this curves contains redundant information by looking - // up the corresponding node's transformation chain. - if ( doc.Settings().optimizeEmptyAnimationCurves && - IsRedundantAnimationData( target, comp, ( *chain[ i ] ).second ) ) { - - FBXImporter::LogDebug( "dropping redundant animation channel for node " + target.Name() ); - continue; - } - - has_any = true; - - if ( comp != TransformationComp_Rotation && comp != TransformationComp_Scaling && comp != TransformationComp_Translation ) + switch (light.LightType()) { - has_complex = true; - } - } - } - - if ( !has_any ) { - FBXImporter::LogWarn( "ignoring node animation, did not find any transformation key frames" ); - return; - } - - // this needs to play nicely with GenerateTransformationNodeChain() which will - // be invoked _later_ (animations come first). If this node has only rotation, - // scaling and translation _and_ there are no animated other components either, - // we can use a single node and also a single node animation channel. - if ( !has_complex && !NeedsComplexTransformationChain( target ) ) { - - aiNodeAnim* const nd = GenerateSimpleNodeAnim( fixed_name, target, chain, - node_property_map.end(), - layer_map, - start, stop, - max_time, - min_time, - true // input is TRS order, assimp is SRT - ); - - ai_assert( nd ); - if ( nd->mNumPositionKeys == 0 && nd->mNumRotationKeys == 0 && nd->mNumScalingKeys == 0 ) { - delete nd; - } - else { - node_anims.push_back( nd ); - } - return; - } - - // otherwise, things get gruesome and we need separate animation channels - // for each part of the transformation chain. Remember which channels - // we generated and pass this information to the node conversion - // code to avoid nodes that have identity transform, but non-identity - // animations, being dropped. - unsigned int flags = 0, bit = 0x1; - for ( size_t i = 0; i < TransformationComp_MAXIMUM; ++i, bit <<= 1 ) { - const TransformationComp comp = static_cast( i ); - - if ( chain[ i ] != node_property_map.end() ) { - flags |= bit; - - ai_assert( comp != TransformationComp_RotationPivotInverse ); - ai_assert( comp != TransformationComp_ScalingPivotInverse ); - - const std::string& chain_name = NameTransformationChainNode( fixed_name, comp ); - - aiNodeAnim* na = nullptr; - switch ( comp ) - { - case TransformationComp_Rotation: - case TransformationComp_PreRotation: - case TransformationComp_PostRotation: - case TransformationComp_GeometricRotation: - na = GenerateRotationNodeAnim( chain_name, - target, - ( *chain[ i ] ).second, - layer_map, - start, stop, - max_time, - min_time ); - + case Light::Type_Point: + out_light->mType = aiLightSource_POINT; break; - case TransformationComp_RotationOffset: - case TransformationComp_RotationPivot: - case TransformationComp_ScalingOffset: - case TransformationComp_ScalingPivot: + case Light::Type_Directional: + out_light->mType = aiLightSource_DIRECTIONAL; + break; + + case Light::Type_Spot: + out_light->mType = aiLightSource_SPOT; + out_light->mAngleOuterCone = AI_DEG_TO_RAD(light.OuterAngle()); + out_light->mAngleInnerCone = AI_DEG_TO_RAD(light.InnerAngle()); + break; + + case Light::Type_Area: + FBXImporter::LogWarn("cannot represent area light, set to UNDEFINED"); + out_light->mType = aiLightSource_UNDEFINED; + break; + + case Light::Type_Volume: + FBXImporter::LogWarn("cannot represent volume light, set to UNDEFINED"); + out_light->mType = aiLightSource_UNDEFINED; + break; + default: + ai_assert(false); + } + + float decay = light.DecayStart(); + switch (light.DecayType()) + { + case Light::Decay_None: + out_light->mAttenuationConstant = decay; + out_light->mAttenuationLinear = 0.0f; + out_light->mAttenuationQuadratic = 0.0f; + break; + case Light::Decay_Linear: + out_light->mAttenuationConstant = 0.0f; + out_light->mAttenuationLinear = 2.0f / decay; + out_light->mAttenuationQuadratic = 0.0f; + break; + case Light::Decay_Quadratic: + 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"); + out_light->mAttenuationQuadratic = 1.0f; + break; + default: + ai_assert(false); + } + } + + void FBXConverter::ConvertCamera(const Camera& cam, const std::string &orig_name) + { + cameras.push_back(new aiCamera()); + aiCamera* const out_camera = cameras.back(); + + out_camera->mName.Set(orig_name); + + out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight(); + + //cameras are defined along positive x direction + out_camera->mPosition = cam.Position(); + out_camera->mLookAt = (cam.InterestPosition() - out_camera->mPosition).Normalize(); + out_camera->mUp = cam.UpVector(); + + out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView()); + out_camera->mClipPlaneNear = cam.NearPlane(); + out_camera->mClipPlaneFar = cam.FarPlane(); + } + + void FBXConverter::GetUniqueName(const std::string &name, std::string &uniqueName) + { + int i = 0; + uniqueName = name; + while (mNodeNames.find(uniqueName) != mNodeNames.end()) + { + ++i; + std::stringstream ext; + ext << name << std::setfill('0') << std::setw(3) << i; + uniqueName = ext.str(); + } + mNodeNames.insert(uniqueName); + } + + + const char* FBXConverter::NameTransformationComp(TransformationComp comp) { + switch (comp) { case TransformationComp_Translation: + return "Translation"; + case TransformationComp_RotationOffset: + return "RotationOffset"; + case TransformationComp_RotationPivot: + return "RotationPivot"; + case TransformationComp_PreRotation: + return "PreRotation"; + case TransformationComp_Rotation: + return "Rotation"; + case TransformationComp_PostRotation: + return "PostRotation"; + case TransformationComp_RotationPivotInverse: + return "RotationPivotInverse"; + case TransformationComp_ScalingOffset: + return "ScalingOffset"; + case TransformationComp_ScalingPivot: + return "ScalingPivot"; + case TransformationComp_Scaling: + return "Scaling"; + case TransformationComp_ScalingPivotInverse: + return "ScalingPivotInverse"; + case TransformationComp_GeometricScaling: + return "GeometricScaling"; + case TransformationComp_GeometricRotation: + return "GeometricRotation"; case TransformationComp_GeometricTranslation: - na = GenerateTranslationNodeAnim( chain_name, - target, - ( *chain[ i ] ).second, - layer_map, - start, stop, - max_time, - min_time ); + return "GeometricTranslation"; + case TransformationComp_GeometricScalingInverse: + return "GeometricScalingInverse"; + case TransformationComp_GeometricRotationInverse: + return "GeometricRotationInverse"; + case TransformationComp_GeometricTranslationInverse: + return "GeometricTranslationInverse"; + case TransformationComp_MAXIMUM: // this is to silence compiler warnings + default: + break; + } - // pivoting requires us to generate an implicit inverse channel to undo the pivot translation - if ( comp == TransformationComp_RotationPivot ) { - const std::string& invName = NameTransformationChainNode( fixed_name, - TransformationComp_RotationPivotInverse ); + ai_assert(false); - aiNodeAnim* const inv = GenerateTranslationNodeAnim( invName, - target, - ( *chain[ i ] ).second, - layer_map, - start, stop, - max_time, - min_time, - true ); + return nullptr; + } - ai_assert( inv ); - if ( inv->mNumPositionKeys == 0 && inv->mNumRotationKeys == 0 && inv->mNumScalingKeys == 0 ) { - delete inv; - } - else { - node_anims.push_back( inv ); - } + const char* FBXConverter::NameTransformationCompProperty(TransformationComp comp) { + switch (comp) { + case TransformationComp_Translation: + return "Lcl Translation"; + case TransformationComp_RotationOffset: + return "RotationOffset"; + case TransformationComp_RotationPivot: + return "RotationPivot"; + case TransformationComp_PreRotation: + return "PreRotation"; + case TransformationComp_Rotation: + return "Lcl Rotation"; + case TransformationComp_PostRotation: + return "PostRotation"; + case TransformationComp_RotationPivotInverse: + return "RotationPivotInverse"; + case TransformationComp_ScalingOffset: + return "ScalingOffset"; + case TransformationComp_ScalingPivot: + return "ScalingPivot"; + case TransformationComp_Scaling: + return "Lcl Scaling"; + case TransformationComp_ScalingPivotInverse: + return "ScalingPivotInverse"; + case TransformationComp_GeometricScaling: + return "GeometricScaling"; + case TransformationComp_GeometricRotation: + return "GeometricRotation"; + case TransformationComp_GeometricTranslation: + return "GeometricTranslation"; + case TransformationComp_GeometricScalingInverse: + return "GeometricScalingInverse"; + case TransformationComp_GeometricRotationInverse: + return "GeometricRotationInverse"; + case TransformationComp_GeometricTranslationInverse: + return "GeometricTranslationInverse"; + case TransformationComp_MAXIMUM: // this is to silence compiler warnings + break; + } - ai_assert( TransformationComp_RotationPivotInverse > i ); - flags |= bit << ( TransformationComp_RotationPivotInverse - i ); - } - else if ( comp == TransformationComp_ScalingPivot ) { - const std::string& invName = NameTransformationChainNode( fixed_name, - TransformationComp_ScalingPivotInverse ); + ai_assert(false); - aiNodeAnim* const inv = GenerateTranslationNodeAnim( invName, - target, - ( *chain[ i ] ).second, - layer_map, - start, stop, - max_time, - min_time, - true ); + return nullptr; + } - ai_assert( inv ); - if ( inv->mNumPositionKeys == 0 && inv->mNumRotationKeys == 0 && inv->mNumScalingKeys == 0 ) { - delete inv; - } - else { - node_anims.push_back( inv ); - } + aiVector3D FBXConverter::TransformationCompDefaultValue(TransformationComp comp) + { + // XXX a neat way to solve the never-ending special cases for scaling + // would be to do everything in log space! + return comp == TransformationComp_Scaling ? aiVector3D(1.f, 1.f, 1.f) : aiVector3D(); + } - ai_assert( TransformationComp_RotationPivotInverse > i ); - flags |= bit << ( TransformationComp_RotationPivotInverse - i ); - } + void FBXConverter::GetRotationMatrix(Model::RotOrder mode, const aiVector3D& rotation, aiMatrix4x4& out) + { + if (mode == Model::RotOrder_SphericXYZ) { + FBXImporter::LogError("Unsupported RotationMode: SphericXYZ"); + out = aiMatrix4x4(); + return; + } + const float angle_epsilon = 1e-6f; + + out = aiMatrix4x4(); + + bool is_id[3] = { true, true, true }; + + aiMatrix4x4 temp[3]; + if (std::fabs(rotation.z) > angle_epsilon) { + aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(rotation.z), temp[2]); + is_id[2] = false; + } + if (std::fabs(rotation.y) > angle_epsilon) { + aiMatrix4x4::RotationY(AI_DEG_TO_RAD(rotation.y), temp[1]); + is_id[1] = false; + } + if (std::fabs(rotation.x) > angle_epsilon) { + aiMatrix4x4::RotationX(AI_DEG_TO_RAD(rotation.x), temp[0]); + is_id[0] = false; + } + + int order[3] = { -1, -1, -1 }; + + // note: rotation order is inverted since we're left multiplying as is usual in assimp + switch (mode) + { + case Model::RotOrder_EulerXYZ: + order[0] = 2; + order[1] = 1; + order[2] = 0; break; - case TransformationComp_Scaling: - case TransformationComp_GeometricScaling: - na = GenerateScalingNodeAnim( chain_name, - target, - ( *chain[ i ] ).second, - layer_map, - start, stop, - max_time, - min_time ); + case Model::RotOrder_EulerXZY: + order[0] = 1; + order[1] = 2; + order[2] = 0; + break; + case Model::RotOrder_EulerYZX: + order[0] = 0; + order[1] = 2; + order[2] = 1; + break; + + case Model::RotOrder_EulerYXZ: + order[0] = 2; + order[1] = 0; + order[2] = 1; + break; + + case Model::RotOrder_EulerZXY: + order[0] = 1; + order[1] = 0; + order[2] = 2; + break; + + case Model::RotOrder_EulerZYX: + order[0] = 0; + order[1] = 1; + order[2] = 2; break; default: - ai_assert( false ); + ai_assert(false); + break; } - ai_assert( na ); - if ( na->mNumPositionKeys == 0 && na->mNumRotationKeys == 0 && na->mNumScalingKeys == 0 ) { - delete na; + ai_assert(order[0] >= 0); + ai_assert(order[0] <= 2); + ai_assert(order[1] >= 0); + ai_assert(order[1] <= 2); + ai_assert(order[2] >= 0); + ai_assert(order[2] <= 2); + + if (!is_id[order[0]]) { + out = temp[order[0]]; } - else { - node_anims.push_back( na ); + + if (!is_id[order[1]]) { + out = out * temp[order[1]]; } - continue; - } - } - node_anim_chain_bits[ fixed_name ] = flags; -} - -bool FBXConverter::IsRedundantAnimationData( const Model& target, - TransformationComp comp, - const std::vector& curves ) { - ai_assert( curves.size() ); - - // look for animation nodes with - // * sub channels for all relevant components set - // * one key/value pair per component - // * combined values match up the corresponding value in the bind pose node transformation - // only such nodes are 'redundant' for this function. - - if ( curves.size() > 1 ) { - return false; - } - - const AnimationCurveNode& nd = *curves.front(); - const AnimationCurveMap& sub_curves = nd.Curves(); - - const AnimationCurveMap::const_iterator dx = sub_curves.find( "d|X" ); - const AnimationCurveMap::const_iterator dy = sub_curves.find( "d|Y" ); - const AnimationCurveMap::const_iterator dz = sub_curves.find( "d|Z" ); - - if ( dx == sub_curves.end() || dy == sub_curves.end() || dz == sub_curves.end() ) { - return false; - } - - const KeyValueList& vx = ( *dx ).second->GetValues(); - const KeyValueList& vy = ( *dy ).second->GetValues(); - const KeyValueList& vz = ( *dz ).second->GetValues(); - - if ( vx.size() != 1 || vy.size() != 1 || vz.size() != 1 ) { - return false; - } - - const aiVector3D dyn_val = aiVector3D( vx[ 0 ], vy[ 0 ], vz[ 0 ] ); - const aiVector3D& static_val = PropertyGet( target.Props(), - NameTransformationCompProperty( comp ), - TransformationCompDefaultValue( comp ) - ); - - const float epsilon = 1e-6f; - return ( dyn_val - static_val ).SquareLength() < epsilon; -} - - -aiNodeAnim* FBXConverter::GenerateRotationNodeAnim( const std::string& name, - const Model& target, - const std::vector& curves, - const LayerMap& layer_map, - int64_t start, int64_t stop, - double& max_time, - double& min_time ) -{ - std::unique_ptr na( new aiNodeAnim() ); - na->mNodeName.Set( name ); - - ConvertRotationKeys( na.get(), curves, layer_map, start, stop, max_time, min_time, target.RotationOrder() ); - - // dummy scaling key - na->mScalingKeys = new aiVectorKey[ 1 ]; - na->mNumScalingKeys = 1; - - na->mScalingKeys[ 0 ].mTime = 0.; - na->mScalingKeys[ 0 ].mValue = aiVector3D( 1.0f, 1.0f, 1.0f ); - - // dummy position key - na->mPositionKeys = new aiVectorKey[ 1 ]; - na->mNumPositionKeys = 1; - - na->mPositionKeys[ 0 ].mTime = 0.; - na->mPositionKeys[ 0 ].mValue = aiVector3D(); - - return na.release(); -} - -aiNodeAnim* FBXConverter::GenerateScalingNodeAnim( const std::string& name, - const Model& /*target*/, - const std::vector& curves, - const LayerMap& layer_map, - int64_t start, int64_t stop, - double& max_time, - double& min_time ) -{ - std::unique_ptr na( new aiNodeAnim() ); - na->mNodeName.Set( name ); - - ConvertScaleKeys( na.get(), curves, layer_map, start, stop, max_time, min_time ); - - // dummy rotation key - na->mRotationKeys = new aiQuatKey[ 1 ]; - na->mNumRotationKeys = 1; - - na->mRotationKeys[ 0 ].mTime = 0.; - na->mRotationKeys[ 0 ].mValue = aiQuaternion(); - - // dummy position key - na->mPositionKeys = new aiVectorKey[ 1 ]; - na->mNumPositionKeys = 1; - - na->mPositionKeys[ 0 ].mTime = 0.; - na->mPositionKeys[ 0 ].mValue = aiVector3D(); - - return na.release(); -} - -aiNodeAnim* FBXConverter::GenerateTranslationNodeAnim( const std::string& name, - const Model& /*target*/, - const std::vector& curves, - const LayerMap& layer_map, - int64_t start, int64_t stop, - double& max_time, - double& min_time, - bool inverse ) { - std::unique_ptr na( new aiNodeAnim() ); - na->mNodeName.Set( name ); - - ConvertTranslationKeys( na.get(), curves, layer_map, start, stop, max_time, min_time ); - - if ( inverse ) { - for ( unsigned int i = 0; i < na->mNumPositionKeys; ++i ) { - na->mPositionKeys[ i ].mValue *= -1.0f; - } - } - - // dummy scaling key - na->mScalingKeys = new aiVectorKey[ 1 ]; - na->mNumScalingKeys = 1; - - na->mScalingKeys[ 0 ].mTime = 0.; - na->mScalingKeys[ 0 ].mValue = aiVector3D( 1.0f, 1.0f, 1.0f ); - - // dummy rotation key - na->mRotationKeys = new aiQuatKey[ 1 ]; - na->mNumRotationKeys = 1; - - na->mRotationKeys[ 0 ].mTime = 0.; - na->mRotationKeys[ 0 ].mValue = aiQuaternion(); - - return na.release(); -} - -aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim( const std::string& name, - const Model& target, - NodeMap::const_iterator chain[ TransformationComp_MAXIMUM ], - NodeMap::const_iterator iter_end, - const LayerMap& layer_map, - int64_t start, int64_t stop, - double& max_time, - double& min_time, - bool reverse_order ) - -{ - std::unique_ptr na( new aiNodeAnim() ); - na->mNodeName.Set( name ); - - const PropertyTable& props = target.Props(); - - // need to convert from TRS order to SRT? - if ( reverse_order ) { - - aiVector3D def_scale = PropertyGet( props, "Lcl Scaling", aiVector3D( 1.f, 1.f, 1.f ) ); - aiVector3D def_translate = PropertyGet( props, "Lcl Translation", aiVector3D( 0.f, 0.f, 0.f ) ); - aiVector3D def_rot = PropertyGet( props, "Lcl Rotation", aiVector3D( 0.f, 0.f, 0.f ) ); - - KeyFrameListList scaling; - KeyFrameListList translation; - KeyFrameListList rotation; - - if ( chain[ TransformationComp_Scaling ] != iter_end ) { - scaling = GetKeyframeList( ( *chain[ TransformationComp_Scaling ] ).second, start, stop ); + if (!is_id[order[2]]) { + out = out * temp[order[2]]; + } } - if ( chain[ TransformationComp_Translation ] != iter_end ) { - translation = GetKeyframeList( ( *chain[ TransformationComp_Translation ] ).second, start, stop ); - } - - if ( chain[ TransformationComp_Rotation ] != iter_end ) { - rotation = GetKeyframeList( ( *chain[ TransformationComp_Rotation ] ).second, start, stop ); - } - - KeyFrameListList joined; - joined.insert( joined.end(), scaling.begin(), scaling.end() ); - joined.insert( joined.end(), translation.begin(), translation.end() ); - joined.insert( joined.end(), rotation.begin(), rotation.end() ); - - const KeyTimeList& times = GetKeyTimeList( joined ); - - aiQuatKey* out_quat = new aiQuatKey[ times.size() ]; - aiVectorKey* out_scale = new aiVectorKey[ times.size() ]; - aiVectorKey* out_translation = new aiVectorKey[ times.size() ]; - - if ( times.size() ) + bool FBXConverter::NeedsComplexTransformationChain(const Model& model) { - ConvertTransformOrder_TRStoSRT( out_quat, out_scale, out_translation, - scaling, - translation, - rotation, - times, - max_time, - min_time, - target.RotationOrder(), - def_scale, - def_translate, - def_rot ); - } + const PropertyTable& props = model.Props(); + bool ok; - // XXX remove duplicates / redundant keys which this operation did - // likely produce if not all three channels were equally dense. + const float zero_epsilon = 1e-6f; + const aiVector3D all_ones(1.0f, 1.0f, 1.0f); + for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) { + const TransformationComp comp = static_cast(i); - na->mNumScalingKeys = static_cast( times.size() ); - na->mNumRotationKeys = na->mNumScalingKeys; - na->mNumPositionKeys = na->mNumScalingKeys; + if (comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation) { + continue; + } - na->mScalingKeys = out_scale; - na->mRotationKeys = out_quat; - na->mPositionKeys = out_translation; - } - else { + bool scale_compare = (comp == TransformationComp_GeometricScaling || comp == TransformationComp_Scaling); - // if a particular transformation is not given, grab it from - // the corresponding node to meet the semantics of aiNodeAnim, - // which requires all of rotation, scaling and translation - // to be set. - if ( chain[ TransformationComp_Scaling ] != iter_end ) { - ConvertScaleKeys( na.get(), ( *chain[ TransformationComp_Scaling ] ).second, - layer_map, - start, stop, - max_time, - min_time ); - } - else { - na->mScalingKeys = new aiVectorKey[ 1 ]; - na->mNumScalingKeys = 1; - - na->mScalingKeys[ 0 ].mTime = 0.; - na->mScalingKeys[ 0 ].mValue = PropertyGet( props, "Lcl Scaling", - aiVector3D( 1.f, 1.f, 1.f ) ); - } - - if ( chain[ TransformationComp_Rotation ] != iter_end ) { - ConvertRotationKeys( na.get(), ( *chain[ TransformationComp_Rotation ] ).second, - layer_map, - start, stop, - max_time, - min_time, - target.RotationOrder() ); - } - else { - na->mRotationKeys = new aiQuatKey[ 1 ]; - na->mNumRotationKeys = 1; - - na->mRotationKeys[ 0 ].mTime = 0.; - na->mRotationKeys[ 0 ].mValue = EulerToQuaternion( - PropertyGet( props, "Lcl Rotation", aiVector3D( 0.f, 0.f, 0.f ) ), - target.RotationOrder() ); - } - - if ( chain[ TransformationComp_Translation ] != iter_end ) { - ConvertTranslationKeys( na.get(), ( *chain[ TransformationComp_Translation ] ).second, - layer_map, - start, stop, - max_time, - min_time ); - } - else { - na->mPositionKeys = new aiVectorKey[ 1 ]; - na->mNumPositionKeys = 1; - - na->mPositionKeys[ 0 ].mTime = 0.; - na->mPositionKeys[ 0 ].mValue = PropertyGet( props, "Lcl Translation", - aiVector3D( 0.f, 0.f, 0.f ) ); - } - - } - return na.release(); -} - -FBXConverter::KeyFrameListList FBXConverter::GetKeyframeList( const std::vector& nodes, int64_t start, int64_t stop ) -{ - KeyFrameListList inputs; - inputs.reserve( nodes.size() * 3 ); - - //give some breathing room for rounding errors - int64_t adj_start = start - 10000; - int64_t adj_stop = stop + 10000; - - for( const AnimationCurveNode* node : nodes ) { - ai_assert( node ); - - const AnimationCurveMap& curves = node->Curves(); - for( const AnimationCurveMap::value_type& kv : curves ) { - - unsigned int mapto; - if ( kv.first == "d|X" ) { - mapto = 0; - } - else if ( kv.first == "d|Y" ) { - mapto = 1; - } - else if ( kv.first == "d|Z" ) { - mapto = 2; - } - else { - FBXImporter::LogWarn( "ignoring scale animation curve, did not recognize target component" ); - continue; - } - - const AnimationCurve* const curve = kv.second; - ai_assert( curve->GetKeys().size() == curve->GetValues().size() && curve->GetKeys().size() ); - - //get values within the start/stop time window - std::shared_ptr Keys( new KeyTimeList() ); - std::shared_ptr Values( new KeyValueList() ); - const size_t count = curve->GetKeys().size(); - Keys->reserve( count ); - Values->reserve( count ); - for (size_t n = 0; n < count; n++ ) - { - int64_t k = curve->GetKeys().at( n ); - if ( k >= adj_start && k <= adj_stop ) - { - Keys->push_back( k ); - Values->push_back( curve->GetValues().at( n ) ); + const aiVector3D& v = PropertyGet(props, NameTransformationCompProperty(comp), ok); + if (ok && scale_compare) { + if ((v - all_ones).SquareLength() > zero_epsilon) { + return true; + } + } + else if (ok) { + if (v.SquareLength() > zero_epsilon) { + return true; + } } } - inputs.push_back( std::make_tuple( Keys, Values, mapto ) ); - } - } - return inputs; // pray for NRVO :-) -} - - -KeyTimeList FBXConverter::GetKeyTimeList( const KeyFrameListList& inputs ) { - ai_assert( !inputs.empty() ); - - // reserve some space upfront - it is likely that the key-frame lists - // have matching time values, so max(of all key-frame lists) should - // be a good estimate. - KeyTimeList keys; - - size_t estimate = 0; - for( const KeyFrameList& kfl : inputs ) { - estimate = std::max( estimate, std::get<0>(kfl)->size() ); - } - - keys.reserve( estimate ); - - std::vector next_pos; - next_pos.resize( inputs.size(), 0 ); - - const size_t count = inputs.size(); - while ( true ) { - - int64_t min_tick = std::numeric_limits::max(); - for ( size_t i = 0; i < count; ++i ) { - const KeyFrameList& kfl = inputs[ i ]; - - if ( std::get<0>(kfl)->size() > next_pos[ i ] && std::get<0>(kfl)->at( next_pos[ i ] ) < min_tick ) { - min_tick = std::get<0>(kfl)->at( next_pos[ i ] ); - } + return false; } - if ( min_tick == std::numeric_limits::max() ) { - break; - } - keys.push_back( min_tick ); - - for ( size_t i = 0; i < count; ++i ) { - const KeyFrameList& kfl = inputs[ i ]; - - - while ( std::get<0>(kfl)->size() > next_pos[ i ] && std::get<0>(kfl)->at( next_pos[ i ] ) == min_tick ) { - ++next_pos[ i ]; - } - } - } - - return keys; -} - -void FBXConverter::InterpolateKeys( aiVectorKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs, - const aiVector3D& def_value, - double& max_time, - double& min_time ) { - ai_assert( !keys.empty() ); - ai_assert( nullptr != valOut ); - - std::vector next_pos; - const size_t count( inputs.size() ); - - next_pos.resize( inputs.size(), 0 ); - - for( KeyTimeList::value_type time : keys ) { - ai_real result[ 3 ] = { def_value.x, def_value.y, def_value.z }; - - for ( size_t i = 0; i < count; ++i ) { - const KeyFrameList& kfl = inputs[ i ]; - - const size_t ksize = std::get<0>(kfl)->size(); - if (ksize == 0) { - continue; - } - if ( ksize > next_pos[ i ] && std::get<0>(kfl)->at( next_pos[ i ] ) == time ) { - ++next_pos[ i ]; - } - - const size_t id0 = next_pos[ i ]>0 ? next_pos[ i ] - 1 : 0; - const size_t id1 = next_pos[ i ] == ksize ? ksize - 1 : next_pos[ i ]; - - // use lerp for interpolation - const KeyValueList::value_type valueA = std::get<1>(kfl)->at( id0 ); - const KeyValueList::value_type valueB = std::get<1>(kfl)->at( id1 ); - - const KeyTimeList::value_type timeA = std::get<0>(kfl)->at( id0 ); - const KeyTimeList::value_type timeB = std::get<0>(kfl)->at( id1 ); - - const ai_real factor = timeB == timeA ? ai_real(0.) : static_cast( ( time - timeA ) ) / ( timeB - timeA ); - const ai_real interpValue = static_cast( valueA + ( valueB - valueA ) * factor ); - - result[ std::get<2>(kfl) ] = interpValue; - } - - // magic value to convert fbx times to seconds - valOut->mTime = CONVERT_FBX_TIME( time ) * anim_fps; - - min_time = std::min( min_time, valOut->mTime ); - max_time = std::max( max_time, valOut->mTime ); - - valOut->mValue.x = result[ 0 ]; - valOut->mValue.y = result[ 1 ]; - valOut->mValue.z = result[ 2 ]; - - ++valOut; - } -} - -void FBXConverter::InterpolateKeys( aiQuatKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs, - const aiVector3D& def_value, - double& maxTime, - double& minTime, - Model::RotOrder order ) -{ - ai_assert( !keys.empty() ); - ai_assert( nullptr != valOut ); - - std::unique_ptr temp( new aiVectorKey[ keys.size() ] ); - InterpolateKeys( temp.get(), keys, inputs, def_value, maxTime, minTime ); - - aiMatrix4x4 m; - - aiQuaternion lastq; - - for ( size_t i = 0, c = keys.size(); i < c; ++i ) { - - valOut[ i ].mTime = temp[ i ].mTime; - - GetRotationMatrix( order, temp[ i ].mValue, m ); - aiQuaternion quat = aiQuaternion( aiMatrix3x3( m ) ); - - // take shortest path by checking the inner product - // http://www.3dkingdoms.com/weekly/weekly.php?a=36 - if ( quat.x * lastq.x + quat.y * lastq.y + quat.z * lastq.z + quat.w * lastq.w < 0 ) + std::string FBXConverter::NameTransformationChainNode(const std::string& name, TransformationComp comp) { - quat.x = -quat.x; - quat.y = -quat.y; - quat.z = -quat.z; - quat.w = -quat.w; + return name + std::string(MAGIC_NODE_TAG) + "_" + NameTransformationComp(comp); } - lastq = quat; - valOut[ i ].mValue = quat; - } -} + void FBXConverter::GenerateTransformationNodeChain(const Model& model, std::vector& output_nodes, + std::vector& post_output_nodes) { + const PropertyTable& props = model.Props(); + const Model::RotOrder rot = model.RotationOrder(); -void FBXConverter::ConvertTransformOrder_TRStoSRT( aiQuatKey* out_quat, aiVectorKey* out_scale, - aiVectorKey* out_translation, - const KeyFrameListList& scaling, - const KeyFrameListList& translation, - const KeyFrameListList& rotation, - const KeyTimeList& times, - double& maxTime, - double& minTime, - Model::RotOrder order, - const aiVector3D& def_scale, - const aiVector3D& def_translate, - const aiVector3D& def_rotation ) -{ - if ( rotation.size() ) { - InterpolateKeys( out_quat, times, rotation, def_rotation, maxTime, minTime, order ); - } - else { - for ( size_t i = 0; i < times.size(); ++i ) { - out_quat[ i ].mTime = CONVERT_FBX_TIME( times[ i ] ) * anim_fps; - out_quat[ i ].mValue = EulerToQuaternion( def_rotation, order ); + bool ok; + + aiMatrix4x4 chain[TransformationComp_MAXIMUM]; + std::fill_n(chain, static_cast(TransformationComp_MAXIMUM), aiMatrix4x4()); + + // generate transformation matrices for all the different transformation components + const float zero_epsilon = 1e-6f; + const aiVector3D all_ones(1.0f, 1.0f, 1.0f); + bool is_complex = false; + + const aiVector3D& PreRotation = PropertyGet(props, "PreRotation", ok); + if (ok && PreRotation.SquareLength() > zero_epsilon) { + is_complex = true; + + GetRotationMatrix(Model::RotOrder::RotOrder_EulerXYZ, PreRotation, chain[TransformationComp_PreRotation]); + } + + const aiVector3D& PostRotation = PropertyGet(props, "PostRotation", ok); + if (ok && PostRotation.SquareLength() > zero_epsilon) { + is_complex = true; + + GetRotationMatrix(Model::RotOrder::RotOrder_EulerXYZ, PostRotation, chain[TransformationComp_PostRotation]); + } + + const aiVector3D& RotationPivot = PropertyGet(props, "RotationPivot", ok); + if (ok && RotationPivot.SquareLength() > zero_epsilon) { + is_complex = true; + + aiMatrix4x4::Translation(RotationPivot, chain[TransformationComp_RotationPivot]); + aiMatrix4x4::Translation(-RotationPivot, chain[TransformationComp_RotationPivotInverse]); + } + + const aiVector3D& RotationOffset = PropertyGet(props, "RotationOffset", ok); + if (ok && RotationOffset.SquareLength() > zero_epsilon) { + is_complex = true; + + aiMatrix4x4::Translation(RotationOffset, chain[TransformationComp_RotationOffset]); + } + + const aiVector3D& ScalingOffset = PropertyGet(props, "ScalingOffset", ok); + if (ok && ScalingOffset.SquareLength() > zero_epsilon) { + is_complex = true; + + aiMatrix4x4::Translation(ScalingOffset, chain[TransformationComp_ScalingOffset]); + } + + const aiVector3D& ScalingPivot = PropertyGet(props, "ScalingPivot", ok); + if (ok && ScalingPivot.SquareLength() > zero_epsilon) { + is_complex = true; + + aiMatrix4x4::Translation(ScalingPivot, chain[TransformationComp_ScalingPivot]); + aiMatrix4x4::Translation(-ScalingPivot, chain[TransformationComp_ScalingPivotInverse]); + } + + const aiVector3D& Translation = PropertyGet(props, "Lcl Translation", ok); + if (ok && Translation.SquareLength() > zero_epsilon) { + aiMatrix4x4::Translation(Translation, chain[TransformationComp_Translation]); + } + + const aiVector3D& Scaling = PropertyGet(props, "Lcl Scaling", ok); + if (ok && (Scaling - all_ones).SquareLength() > zero_epsilon) { + aiMatrix4x4::Scaling(Scaling, chain[TransformationComp_Scaling]); + } + + const aiVector3D& Rotation = PropertyGet(props, "Lcl Rotation", ok); + if (ok && Rotation.SquareLength() > zero_epsilon) { + GetRotationMatrix(rot, Rotation, chain[TransformationComp_Rotation]); + } + + const aiVector3D& GeometricScaling = PropertyGet(props, "GeometricScaling", ok); + if (ok && (GeometricScaling - all_ones).SquareLength() > zero_epsilon) { + is_complex = true; + aiMatrix4x4::Scaling(GeometricScaling, chain[TransformationComp_GeometricScaling]); + aiVector3D GeometricScalingInverse = GeometricScaling; + bool canscale = true; + for (unsigned int i = 0; i < 3; ++i) { + if (std::fabs(GeometricScalingInverse[i]) > zero_epsilon) { + GeometricScalingInverse[i] = 1.0f / GeometricScaling[i]; + } + else { + FBXImporter::LogError("cannot invert geometric scaling matrix with a 0.0 scale component"); + canscale = false; + break; + } + } + if (canscale) { + aiMatrix4x4::Scaling(GeometricScalingInverse, chain[TransformationComp_GeometricScalingInverse]); + } + } + + const aiVector3D& GeometricRotation = PropertyGet(props, "GeometricRotation", ok); + if (ok && GeometricRotation.SquareLength() > zero_epsilon) { + is_complex = true; + GetRotationMatrix(rot, GeometricRotation, chain[TransformationComp_GeometricRotation]); + GetRotationMatrix(rot, GeometricRotation, chain[TransformationComp_GeometricRotationInverse]); + chain[TransformationComp_GeometricRotationInverse].Inverse(); + } + + const aiVector3D& GeometricTranslation = PropertyGet(props, "GeometricTranslation", ok); + if (ok && GeometricTranslation.SquareLength() > zero_epsilon) { + is_complex = true; + aiMatrix4x4::Translation(GeometricTranslation, chain[TransformationComp_GeometricTranslation]); + aiMatrix4x4::Translation(-GeometricTranslation, chain[TransformationComp_GeometricTranslationInverse]); + } + + // is_complex needs to be consistent with NeedsComplexTransformationChain() + // or the interplay between this code and the animation converter would + // not be guaranteed. + ai_assert(NeedsComplexTransformationChain(model) == is_complex); + + std::string name = FixNodeName(model.Name()); + + // now, if we have more than just Translation, Scaling and Rotation, + // we need to generate a full node chain to accommodate for assimp's + // lack to express pivots and offsets. + if (is_complex && doc.Settings().preservePivots) { + FBXImporter::LogInfo("generating full transformation chain for node: " + name); + + // query the anim_chain_bits dictionary to find out which chain elements + // have associated node animation channels. These can not be dropped + // even if they have identity transform in bind pose. + NodeAnimBitMap::const_iterator it = node_anim_chain_bits.find(name); + const unsigned int anim_chain_bitmask = (it == node_anim_chain_bits.end() ? 0 : (*it).second); + + unsigned int bit = 0x1; + for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i, bit <<= 1) { + const TransformationComp comp = static_cast(i); + + if (chain[i].IsIdentity() && (anim_chain_bitmask & bit) == 0) { + continue; + } + + if (comp == TransformationComp_PostRotation) { + chain[i] = chain[i].Inverse(); + } + + aiNode* nd = new aiNode(); + nd->mName.Set(NameTransformationChainNode(name, comp)); + nd->mTransformation = chain[i]; + + // geometric inverses go in a post-node chain + if (comp == TransformationComp_GeometricScalingInverse || + comp == TransformationComp_GeometricRotationInverse || + comp == TransformationComp_GeometricTranslationInverse + ) { + post_output_nodes.push_back(nd); + } + else { + output_nodes.push_back(nd); + } + } + + ai_assert(output_nodes.size()); + return; + } + + // else, we can just multiply the matrices together + aiNode* nd = new aiNode(); + output_nodes.push_back(nd); + std::string uniqueName; + GetUniqueName(name, uniqueName); + + nd->mName.Set(uniqueName); + + for (const auto &transform : chain) { + nd->mTransformation = nd->mTransformation * transform; + } } - } - if ( scaling.size() ) { - InterpolateKeys( out_scale, times, scaling, def_scale, maxTime, minTime ); - } - else { - for ( size_t i = 0; i < times.size(); ++i ) { - out_scale[ i ].mTime = CONVERT_FBX_TIME( times[ i ] ) * anim_fps; - out_scale[ i ].mValue = def_scale; + void FBXConverter::SetupNodeMetadata(const Model& model, aiNode& nd) + { + const PropertyTable& props = model.Props(); + DirectPropertyMap unparsedProperties = props.GetUnparsedProperties(); + + // create metadata on node + const std::size_t numStaticMetaData = 2; + aiMetadata* data = aiMetadata::Alloc(static_cast(unparsedProperties.size() + numStaticMetaData)); + nd.mMetaData = data; + int index = 0; + + // find user defined properties (3ds Max) + data->Set(index++, "UserProperties", aiString(PropertyGet(props, "UDP3DSMAX", ""))); + // preserve the info that a node was marked as Null node in the original file. + data->Set(index++, "IsNull", model.IsNull() ? true : false); + + // add unparsed properties to the node's metadata + for (const DirectPropertyMap::value_type& prop : unparsedProperties) { + // Interpret the property as a concrete type + if (const TypedProperty* interpreted = prop.second->As >()) { + data->Set(index++, prop.first, interpreted->Value()); + } + else if (const TypedProperty* interpreted = prop.second->As >()) { + data->Set(index++, prop.first, interpreted->Value()); + } + else if (const TypedProperty* interpreted = prop.second->As >()) { + data->Set(index++, prop.first, interpreted->Value()); + } + else if (const TypedProperty* interpreted = prop.second->As >()) { + data->Set(index++, prop.first, interpreted->Value()); + } + else if (const TypedProperty* interpreted = prop.second->As >()) { + data->Set(index++, prop.first, aiString(interpreted->Value())); + } + else if (const TypedProperty* interpreted = prop.second->As >()) { + data->Set(index++, prop.first, interpreted->Value()); + } + else { + ai_assert(false); + } + } } - } - if ( translation.size() ) { - InterpolateKeys( out_translation, times, translation, def_translate, maxTime, minTime ); - } - else { - for ( size_t i = 0; i < times.size(); ++i ) { - out_translation[ i ].mTime = CONVERT_FBX_TIME( times[ i ] ) * anim_fps; - out_translation[ i ].mValue = def_translate; + void FBXConverter::ConvertModel(const Model& model, aiNode& nd, const aiMatrix4x4& node_global_transform) + { + const std::vector& geos = model.GetGeometry(); + + std::vector meshes; + meshes.reserve(geos.size()); + + for (const Geometry* geo : geos) { + + const MeshGeometry* const mesh = dynamic_cast(geo); + if (mesh) { + const std::vector& indices = ConvertMesh(*mesh, model, node_global_transform, nd); + std::copy(indices.begin(), indices.end(), std::back_inserter(meshes)); + } + else { + FBXImporter::LogWarn("ignoring unrecognized geometry: " + geo->Name()); + } + } + + if (meshes.size()) { + nd.mMeshes = new unsigned int[meshes.size()](); + nd.mNumMeshes = static_cast(meshes.size()); + + std::swap_ranges(meshes.begin(), meshes.end(), nd.mMeshes); + } } - } - const size_t count = times.size(); - for ( size_t i = 0; i < count; ++i ) { - aiQuaternion& r = out_quat[ i ].mValue; - aiVector3D& s = out_scale[ i ].mValue; - aiVector3D& t = out_translation[ i ].mValue; + std::vector FBXConverter::ConvertMesh(const MeshGeometry& mesh, const Model& model, + const aiMatrix4x4& node_global_transform, aiNode& nd) + { + std::vector temp; - aiMatrix4x4 mat, temp; - aiMatrix4x4::Translation( t, mat ); - mat *= aiMatrix4x4( r.GetMatrix() ); - mat *= aiMatrix4x4::Scaling( s, temp ); + MeshMap::const_iterator it = meshes_converted.find(&mesh); + if (it != meshes_converted.end()) { + std::copy((*it).second.begin(), (*it).second.end(), std::back_inserter(temp)); + return temp; + } - mat.Decompose( s, r, t ); - } -} + const std::vector& vertices = mesh.GetVertices(); + const std::vector& faces = mesh.GetFaceIndexCounts(); + if (vertices.empty() || faces.empty()) { + FBXImporter::LogWarn("ignoring empty geometry: " + mesh.Name()); + return temp; + } -aiQuaternion FBXConverter::EulerToQuaternion( const aiVector3D& rot, Model::RotOrder order ) -{ - aiMatrix4x4 m; - GetRotationMatrix( order, rot, m ); + // one material per mesh maps easily to aiMesh. Multiple material + // meshes need to be split. + const MatIndexArray& mindices = mesh.GetMaterialIndices(); + if (doc.Settings().readMaterials && !mindices.empty()) { + const MatIndexArray::value_type base = mindices[0]; + for (MatIndexArray::value_type index : mindices) { + if (index != base) { + return ConvertMeshMultiMaterial(mesh, model, node_global_transform, nd); + } + } + } - return aiQuaternion( aiMatrix3x3( m ) ); -} + // faster code-path, just copy the data + temp.push_back(ConvertMeshSingleMaterial(mesh, model, node_global_transform, nd)); + return temp; + } -void FBXConverter::ConvertScaleKeys( aiNodeAnim* na, const std::vector& nodes, const LayerMap& /*layers*/, - int64_t start, int64_t stop, - double& maxTime, - double& minTime ) -{ - ai_assert( nodes.size() ); + aiMesh* FBXConverter::SetupEmptyMesh(const MeshGeometry& mesh, aiNode& nd) + { + aiMesh* const out_mesh = new aiMesh(); + meshes.push_back(out_mesh); + meshes_converted[&mesh].push_back(static_cast(meshes.size() - 1)); - // XXX for now, assume scale should be blended geometrically (i.e. two - // layers should be multiplied with each other). There is a FBX - // property in the layer to specify the behaviour, though. + // set name + std::string name = mesh.Name(); + if (name.substr(0, 10) == "Geometry::") { + name = name.substr(10); + } - const KeyFrameListList& inputs = GetKeyframeList( nodes, start, stop ); - const KeyTimeList& keys = GetKeyTimeList( inputs ); + if (name.length()) { + out_mesh->mName.Set(name); + } + else + { + out_mesh->mName = nd.mName; + } - na->mNumScalingKeys = static_cast( keys.size() ); - na->mScalingKeys = new aiVectorKey[ keys.size() ]; - if ( keys.size() > 0 ) - InterpolateKeys( na->mScalingKeys, keys, inputs, aiVector3D( 1.0f, 1.0f, 1.0f ), maxTime, minTime ); -} + return out_mesh; + } -void FBXConverter::ConvertTranslationKeys( aiNodeAnim* na, const std::vector& nodes, - const LayerMap& /*layers*/, - int64_t start, int64_t stop, - double& maxTime, - double& minTime ) -{ - ai_assert( nodes.size() ); + unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry& mesh, const Model& model, + const aiMatrix4x4& node_global_transform, aiNode& nd) + { + const MatIndexArray& mindices = mesh.GetMaterialIndices(); + aiMesh* const out_mesh = SetupEmptyMesh(mesh, nd); - // XXX see notes in ConvertScaleKeys() - const KeyFrameListList& inputs = GetKeyframeList( nodes, start, stop ); - const KeyTimeList& keys = GetKeyTimeList( inputs ); + const std::vector& vertices = mesh.GetVertices(); + const std::vector& faces = mesh.GetFaceIndexCounts(); - na->mNumPositionKeys = static_cast( keys.size() ); - na->mPositionKeys = new aiVectorKey[ keys.size() ]; - if ( keys.size() > 0 ) - InterpolateKeys( na->mPositionKeys, keys, inputs, aiVector3D( 0.0f, 0.0f, 0.0f ), maxTime, minTime ); -} + // copy vertices + out_mesh->mNumVertices = static_cast(vertices.size()); + out_mesh->mVertices = new aiVector3D[vertices.size()]; + std::copy(vertices.begin(), vertices.end(), out_mesh->mVertices); -void FBXConverter::ConvertRotationKeys( aiNodeAnim* na, const std::vector& nodes, - const LayerMap& /*layers*/, - int64_t start, int64_t stop, - double& maxTime, - double& minTime, - Model::RotOrder order ) -{ - ai_assert( nodes.size() ); + // generate dummy faces + out_mesh->mNumFaces = static_cast(faces.size()); + aiFace* fac = out_mesh->mFaces = new aiFace[faces.size()](); - // XXX see notes in ConvertScaleKeys() - const std::vector< KeyFrameList >& inputs = GetKeyframeList( nodes, start, stop ); - const KeyTimeList& keys = GetKeyTimeList( inputs ); + unsigned int cursor = 0; + for (unsigned int pcount : faces) { + aiFace& f = *fac++; + f.mNumIndices = pcount; + f.mIndices = new unsigned int[pcount]; + switch (pcount) + { + case 1: + out_mesh->mPrimitiveTypes |= aiPrimitiveType_POINT; + break; + case 2: + out_mesh->mPrimitiveTypes |= aiPrimitiveType_LINE; + break; + case 3: + out_mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; + break; + default: + out_mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON; + break; + } + for (unsigned int i = 0; i < pcount; ++i) { + f.mIndices[i] = cursor++; + } + } - na->mNumRotationKeys = static_cast( keys.size() ); - na->mRotationKeys = new aiQuatKey[ keys.size() ]; - if (!keys.empty()) { - InterpolateKeys(na->mRotationKeys, keys, inputs, aiVector3D(0.0f, 0.0f, 0.0f), maxTime, minTime, order); - } -} + // copy normals + const std::vector& normals = mesh.GetNormals(); + if (normals.size()) { + ai_assert(normals.size() == vertices.size()); -void FBXConverter::ConvertGlobalSettings() { - if (nullptr == out) { - return; - } + out_mesh->mNormals = new aiVector3D[vertices.size()]; + std::copy(normals.begin(), normals.end(), out_mesh->mNormals); + } - out->mMetaData = aiMetadata::Alloc(1); - unsigned int index(0); - const double unitScalFactor(doc.GlobalSettings().UnitScaleFactor()); - out->mMetaData->Set(index, "UnitScaleFactor", unitScalFactor); -} + // copy tangents - assimp requires both tangents and bitangents (binormals) + // to be present, or neither of them. Compute binormals from normals + // and tangents if needed. + const std::vector& tangents = mesh.GetTangents(); + const std::vector* binormals = &mesh.GetBinormals(); -void FBXConverter::TransferDataToScene() -{ - ai_assert( !out->mMeshes ); - ai_assert( !out->mNumMeshes ); + if (tangents.size()) { + std::vector tempBinormals; + if (!binormals->size()) { + if (normals.size()) { + tempBinormals.resize(normals.size()); + for (unsigned int i = 0; i < tangents.size(); ++i) { + tempBinormals[i] = normals[i] ^ tangents[i]; + } - // note: the trailing () ensures initialization with NULL - not - // many C++ users seem to know this, so pointing it out to avoid - // confusion why this code works. + binormals = &tempBinormals; + } + else { + binormals = NULL; + } + } - if ( meshes.size() ) { - out->mMeshes = new aiMesh*[ meshes.size() ](); - out->mNumMeshes = static_cast( meshes.size() ); + if (binormals) { + ai_assert(tangents.size() == vertices.size()); + ai_assert(binormals->size() == vertices.size()); - std::swap_ranges( meshes.begin(), meshes.end(), out->mMeshes ); - } + out_mesh->mTangents = new aiVector3D[vertices.size()]; + std::copy(tangents.begin(), tangents.end(), out_mesh->mTangents); - if ( materials.size() ) { - out->mMaterials = new aiMaterial*[ materials.size() ](); - out->mNumMaterials = static_cast( materials.size() ); + out_mesh->mBitangents = new aiVector3D[vertices.size()]; + std::copy(binormals->begin(), binormals->end(), out_mesh->mBitangents); + } + } - std::swap_ranges( materials.begin(), materials.end(), out->mMaterials ); - } + // copy texture coords + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { + const std::vector& uvs = mesh.GetTextureCoords(i); + if (uvs.empty()) { + break; + } - if ( animations.size() ) { - out->mAnimations = new aiAnimation*[ animations.size() ](); - out->mNumAnimations = static_cast( animations.size() ); + aiVector3D* out_uv = out_mesh->mTextureCoords[i] = new aiVector3D[vertices.size()]; + for (const aiVector2D& v : uvs) { + *out_uv++ = aiVector3D(v.x, v.y, 0.0f); + } - std::swap_ranges( animations.begin(), animations.end(), out->mAnimations ); - } + out_mesh->mNumUVComponents[i] = 2; + } - if ( lights.size() ) { - out->mLights = new aiLight*[ lights.size() ](); - out->mNumLights = static_cast( lights.size() ); + // copy vertex colors + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) { + const std::vector& colors = mesh.GetVertexColors(i); + if (colors.empty()) { + break; + } - std::swap_ranges( lights.begin(), lights.end(), out->mLights ); - } + out_mesh->mColors[i] = new aiColor4D[vertices.size()]; + std::copy(colors.begin(), colors.end(), out_mesh->mColors[i]); + } - if ( cameras.size() ) { - out->mCameras = new aiCamera*[ cameras.size() ](); - out->mNumCameras = static_cast( cameras.size() ); + if (!doc.Settings().readMaterials || mindices.empty()) { + FBXImporter::LogError("no material assigned to mesh, setting default material"); + out_mesh->mMaterialIndex = GetDefaultMaterial(); + } + else { + ConvertMaterialForMesh(out_mesh, model, mesh, mindices[0]); + } - std::swap_ranges( cameras.begin(), cameras.end(), out->mCameras ); - } + if (doc.Settings().readWeights && mesh.DeformerSkin() != NULL) { + ConvertWeights(out_mesh, model, mesh, node_global_transform, NO_MATERIAL_SEPARATION); + } - if ( textures.size() ) { - out->mTextures = new aiTexture*[ textures.size() ](); - out->mNumTextures = static_cast( textures.size() ); + std::vector animMeshes; + for (const BlendShape* blendShape : mesh.GetBlendShapes()) { + for (const BlendShapeChannel* blendShapeChannel : blendShape->BlendShapeChannels()) { + const std::vector& shapeGeometries = blendShapeChannel->GetShapeGeometries(); + for (size_t i = 0; i < shapeGeometries.size(); i++) { + aiAnimMesh *animMesh = aiCreateAnimMesh(out_mesh); + const ShapeGeometry* shapeGeometry = shapeGeometries.at(i); + const std::vector& vertices = shapeGeometry->GetVertices(); + const std::vector& normals = shapeGeometry->GetNormals(); + const std::vector& indices = shapeGeometry->GetIndices(); + animMesh->mName.Set(FixAnimMeshName(shapeGeometry->Name())); + for (size_t j = 0; j < indices.size(); j++) { + unsigned int index = indices.at(j); + aiVector3D vertex = vertices.at(j); + aiVector3D normal = normals.at(j); + unsigned int count = 0; + const unsigned int* outIndices = mesh.ToOutputVertexIndex(index, count); + for (unsigned int k = 0; k < count; k++) { + unsigned int index = outIndices[k]; + animMesh->mVertices[index] += vertex; + if (animMesh->mNormals != nullptr) { + animMesh->mNormals[index] += normal; + animMesh->mNormals[index].NormalizeSafe(); + } + } + } + animMesh->mWeight = shapeGeometries.size() > 1 ? blendShapeChannel->DeformPercent() / 100.0f : 1.0f; + animMeshes.push_back(animMesh); + } + } + } + size_t numAnimMeshes = animMeshes.size(); + if (numAnimMeshes > 0) { + out_mesh->mNumAnimMeshes = static_cast(numAnimMeshes); + out_mesh->mAnimMeshes = new aiAnimMesh*[numAnimMeshes]; + for (size_t i = 0; i < numAnimMeshes; i++) { + out_mesh->mAnimMeshes[i] = animMeshes.at(i); + } + } + return static_cast(meshes.size() - 1); + } - std::swap_ranges( textures.begin(), textures.end(), out->mTextures ); - } -} + std::vector FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model, + const aiMatrix4x4& node_global_transform, aiNode& nd) + { + const MatIndexArray& mindices = mesh.GetMaterialIndices(); + ai_assert(mindices.size()); -// ------------------------------------------------------------------------------------------------ -void ConvertToAssimpScene(aiScene* out, const Document& doc) -{ - FBXConverter converter(out,doc); -} + std::set had; + std::vector indices; -} // !FBX + for (MatIndexArray::value_type index : mindices) { + if (had.find(index) == had.end()) { + + indices.push_back(ConvertMeshMultiMaterial(mesh, model, index, node_global_transform, nd)); + had.insert(index); + } + } + + return indices; + } + + unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model, + MatIndexArray::value_type index, + const aiMatrix4x4& node_global_transform, + aiNode& nd) + { + aiMesh* const out_mesh = SetupEmptyMesh(mesh, nd); + + const MatIndexArray& mindices = mesh.GetMaterialIndices(); + const std::vector& vertices = mesh.GetVertices(); + const std::vector& faces = mesh.GetFaceIndexCounts(); + + const bool process_weights = doc.Settings().readWeights && mesh.DeformerSkin() != NULL; + + unsigned int count_faces = 0; + unsigned int count_vertices = 0; + + // count faces + std::vector::const_iterator itf = faces.begin(); + for (MatIndexArray::const_iterator it = mindices.begin(), + end = mindices.end(); it != end; ++it, ++itf) + { + if ((*it) != index) { + continue; + } + ++count_faces; + count_vertices += *itf; + } + + ai_assert(count_faces); + ai_assert(count_vertices); + + // mapping from output indices to DOM indexing, needed to resolve weights + std::vector reverseMapping; + + if (process_weights) { + reverseMapping.resize(count_vertices); + } + + // allocate output data arrays, but don't fill them yet + out_mesh->mNumVertices = count_vertices; + out_mesh->mVertices = new aiVector3D[count_vertices]; + + out_mesh->mNumFaces = count_faces; + aiFace* fac = out_mesh->mFaces = new aiFace[count_faces](); + + + // allocate normals + const std::vector& normals = mesh.GetNormals(); + if (normals.size()) { + ai_assert(normals.size() == vertices.size()); + out_mesh->mNormals = new aiVector3D[vertices.size()]; + } + + // allocate tangents, binormals. + const std::vector& tangents = mesh.GetTangents(); + const std::vector* binormals = &mesh.GetBinormals(); + std::vector tempBinormals; + + if (tangents.size()) { + if (!binormals->size()) { + if (normals.size()) { + // XXX this computes the binormals for the entire mesh, not only + // the part for which we need them. + tempBinormals.resize(normals.size()); + for (unsigned int i = 0; i < tangents.size(); ++i) { + tempBinormals[i] = normals[i] ^ tangents[i]; + } + + binormals = &tempBinormals; + } + else { + binormals = NULL; + } + } + + if (binormals) { + ai_assert(tangents.size() == vertices.size() && binormals->size() == vertices.size()); + + out_mesh->mTangents = new aiVector3D[vertices.size()]; + out_mesh->mBitangents = new aiVector3D[vertices.size()]; + } + } + + // allocate texture coords + unsigned int num_uvs = 0; + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i, ++num_uvs) { + const std::vector& uvs = mesh.GetTextureCoords(i); + if (uvs.empty()) { + break; + } + + out_mesh->mTextureCoords[i] = new aiVector3D[vertices.size()]; + out_mesh->mNumUVComponents[i] = 2; + } + + // allocate vertex colors + unsigned int num_vcs = 0; + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i, ++num_vcs) { + const std::vector& colors = mesh.GetVertexColors(i); + if (colors.empty()) { + break; + } + + out_mesh->mColors[i] = new aiColor4D[vertices.size()]; + } + + unsigned int cursor = 0, in_cursor = 0; + + itf = faces.begin(); + for (MatIndexArray::const_iterator it = mindices.begin(), + end = mindices.end(); it != end; ++it, ++itf) + { + const unsigned int pcount = *itf; + if ((*it) != index) { + in_cursor += pcount; + continue; + } + + aiFace& f = *fac++; + + f.mNumIndices = pcount; + f.mIndices = new unsigned int[pcount]; + switch (pcount) + { + case 1: + out_mesh->mPrimitiveTypes |= aiPrimitiveType_POINT; + break; + case 2: + out_mesh->mPrimitiveTypes |= aiPrimitiveType_LINE; + break; + case 3: + out_mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; + break; + default: + out_mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON; + break; + } + for (unsigned int i = 0; i < pcount; ++i, ++cursor, ++in_cursor) { + f.mIndices[i] = cursor; + + if (reverseMapping.size()) { + reverseMapping[cursor] = in_cursor; + } + + out_mesh->mVertices[cursor] = vertices[in_cursor]; + + if (out_mesh->mNormals) { + out_mesh->mNormals[cursor] = normals[in_cursor]; + } + + if (out_mesh->mTangents) { + out_mesh->mTangents[cursor] = tangents[in_cursor]; + out_mesh->mBitangents[cursor] = (*binormals)[in_cursor]; + } + + for (unsigned int j = 0; j < num_uvs; ++j) { + const std::vector& uvs = mesh.GetTextureCoords(j); + out_mesh->mTextureCoords[j][cursor] = aiVector3D(uvs[in_cursor].x, uvs[in_cursor].y, 0.0f); + } + + for (unsigned int j = 0; j < num_vcs; ++j) { + const std::vector& cols = mesh.GetVertexColors(j); + out_mesh->mColors[j][cursor] = cols[in_cursor]; + } + } + } + + ConvertMaterialForMesh(out_mesh, model, mesh, index); + + if (process_weights) { + ConvertWeights(out_mesh, model, mesh, node_global_transform, index, &reverseMapping); + } + + return static_cast(meshes.size() - 1); + } + + void FBXConverter::ConvertWeights(aiMesh* out, const Model& model, const MeshGeometry& geo, + const aiMatrix4x4& node_global_transform, + unsigned int materialIndex, + std::vector* outputVertStartIndices) + { + ai_assert(geo.DeformerSkin()); + + std::vector out_indices; + std::vector index_out_indices; + std::vector count_out_indices; + + const Skin& sk = *geo.DeformerSkin(); + + std::vector bones; + bones.reserve(sk.Clusters().size()); + + const bool no_mat_check = materialIndex == NO_MATERIAL_SEPARATION; + ai_assert(no_mat_check || outputVertStartIndices); + + try { + + for (const Cluster* cluster : sk.Clusters()) { + ai_assert(cluster); + + const WeightIndexArray& indices = cluster->GetIndices(); + + if (indices.empty()) { + continue; + } + + const MatIndexArray& mats = geo.GetMaterialIndices(); + + bool ok = false; + + const size_t no_index_sentinel = std::numeric_limits::max(); + + count_out_indices.clear(); + index_out_indices.clear(); + out_indices.clear(); + + // now check if *any* of these weights is contained in the output mesh, + // taking notes so we don't need to do it twice. + for (WeightIndexArray::value_type index : indices) { + + unsigned int count = 0; + const unsigned int* const out_idx = geo.ToOutputVertexIndex(index, count); + // ToOutputVertexIndex only returns NULL if index is out of bounds + // which should never happen + ai_assert(out_idx != NULL); + + index_out_indices.push_back(no_index_sentinel); + count_out_indices.push_back(0); + + for (unsigned int i = 0; i < count; ++i) { + if (no_mat_check || static_cast(mats[geo.FaceForVertexIndex(out_idx[i])]) == materialIndex) { + + if (index_out_indices.back() == no_index_sentinel) { + index_out_indices.back() = out_indices.size(); + + } + + if (no_mat_check) { + out_indices.push_back(out_idx[i]); + } + else { + // this extra lookup is in O(logn), so the entire algorithm becomes O(nlogn) + const std::vector::iterator it = std::lower_bound( + outputVertStartIndices->begin(), + outputVertStartIndices->end(), + out_idx[i] + ); + + out_indices.push_back(std::distance(outputVertStartIndices->begin(), it)); + } + + ++count_out_indices.back(); + ok = true; + } + } + } + + // if we found at least one, generate the output bones + // XXX this could be heavily simplified by collecting the bone + // data in a single step. + if (ok) { + ConvertCluster(bones, model, *cluster, out_indices, index_out_indices, + count_out_indices, node_global_transform); + } + } + } + catch (std::exception&) { + std::for_each(bones.begin(), bones.end(), Util::delete_fun()); + throw; + } + + if (bones.empty()) { + return; + } + + out->mBones = new aiBone*[bones.size()](); + out->mNumBones = static_cast(bones.size()); + + std::swap_ranges(bones.begin(), bones.end(), out->mBones); + } + + void FBXConverter::ConvertCluster(std::vector& bones, const Model& /*model*/, const Cluster& cl, + std::vector& out_indices, + std::vector& index_out_indices, + std::vector& count_out_indices, + const aiMatrix4x4& node_global_transform) + { + + aiBone* const bone = new aiBone(); + bones.push_back(bone); + + bone->mName = FixNodeName(cl.TargetNode()->Name()); + + bone->mOffsetMatrix = cl.TransformLink(); + bone->mOffsetMatrix.Inverse(); + + bone->mOffsetMatrix = bone->mOffsetMatrix * node_global_transform; + + bone->mNumWeights = static_cast(out_indices.size()); + aiVertexWeight* cursor = bone->mWeights = new aiVertexWeight[out_indices.size()]; + + const size_t no_index_sentinel = std::numeric_limits::max(); + const WeightArray& weights = cl.GetWeights(); + + const size_t c = index_out_indices.size(); + for (size_t i = 0; i < c; ++i) { + const size_t index_index = index_out_indices[i]; + + if (index_index == no_index_sentinel) { + continue; + } + + const size_t cc = count_out_indices[i]; + for (size_t j = 0; j < cc; ++j) { + aiVertexWeight& out_weight = *cursor++; + + out_weight.mVertexId = static_cast(out_indices[index_index + j]); + out_weight.mWeight = weights[i]; + } + } + } + + void FBXConverter::ConvertMaterialForMesh(aiMesh* out, const Model& model, const MeshGeometry& geo, + MatIndexArray::value_type materialIndex) + { + // locate source materials for this mesh + const std::vector& mats = model.GetMaterials(); + if (static_cast(materialIndex) >= mats.size() || materialIndex < 0) { + FBXImporter::LogError("material index out of bounds, setting default material"); + out->mMaterialIndex = GetDefaultMaterial(); + return; + } + + const Material* const mat = mats[materialIndex]; + MaterialMap::const_iterator it = materials_converted.find(mat); + if (it != materials_converted.end()) { + out->mMaterialIndex = (*it).second; + return; + } + + out->mMaterialIndex = ConvertMaterial(*mat, &geo); + materials_converted[mat] = out->mMaterialIndex; + } + + unsigned int FBXConverter::GetDefaultMaterial() + { + if (defaultMaterialIndex) { + return defaultMaterialIndex - 1; + } + + aiMaterial* out_mat = new aiMaterial(); + materials.push_back(out_mat); + + const aiColor3D diffuse = aiColor3D(0.8f, 0.8f, 0.8f); + out_mat->AddProperty(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE); + + aiString s; + s.Set(AI_DEFAULT_MATERIAL_NAME); + + out_mat->AddProperty(&s, AI_MATKEY_NAME); + + defaultMaterialIndex = static_cast(materials.size()); + return defaultMaterialIndex - 1; + } + + + unsigned int FBXConverter::ConvertMaterial(const Material& material, const MeshGeometry* const mesh) + { + const PropertyTable& props = material.Props(); + + // generate empty output material + aiMaterial* out_mat = new aiMaterial(); + materials_converted[&material] = static_cast(materials.size()); + + materials.push_back(out_mat); + + aiString str; + + // strip Material:: prefix + std::string name = material.Name(); + if (name.substr(0, 10) == "Material::") { + name = name.substr(10); + } + + // set material name if not empty - this could happen + // and there should be no key for it in this case. + if (name.length()) { + str.Set(name); + out_mat->AddProperty(&str, AI_MATKEY_NAME); + } + + // shading stuff and colors + SetShadingPropertiesCommon(out_mat, props); + + // texture assignments + SetTextureProperties(out_mat, material.Textures(), mesh); + SetTextureProperties(out_mat, material.LayeredTextures(), mesh); + + return static_cast(materials.size() - 1); + } + + unsigned int FBXConverter::ConvertVideo(const Video& video) + { + // generate empty output texture + aiTexture* out_tex = new aiTexture(); + textures.push_back(out_tex); + + // assuming the texture is compressed + 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 + out_tex->pcData = reinterpret_cast(const_cast(video).RelinquishContent()); + + // try to extract a hint from the file extension + const std::string& filename = video.FileName().empty() ? video.RelativeFilename() : video.FileName(); + std::string ext = BaseImporter::GetExtension(filename); + + if (ext == "jpeg") { + ext = "jpg"; + } + + if (ext.size() <= 3) { + memcpy(out_tex->achFormatHint, ext.c_str(), ext.size()); + } + + out_tex->mFilename.Set(video.FileName().c_str()); + + return static_cast(textures.size() - 1); + } + + aiString FBXConverter::GetTexturePath(const Texture* tex) + { + aiString path; + path.Set(tex->RelativeFilename()); + + const Video* media = tex->Media(); + if (media != nullptr) { + 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; + textureReady = true; + } + else { + if (media->ContentLength() > 0) { + index = ConvertVideo(*media); + textures_converted[media] = index; + textureReady = true; + } + } + + // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture), if the texture is ready + if (doc.Settings().useLegacyEmbeddedTextureNaming) { + if (textureReady) { + // TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING" + // In FBX files textures are now stored internally by Assimp with their filename included + // Now Assimp can lookup through the loaded textures after all data is processed + // We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it + // This may occur on this case too, it has to be studied + path.data[0] = '*'; + path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index); + } + } + } + + return path; + } + + void FBXConverter::TrySetTextureProperties(aiMaterial* out_mat, const TextureMap& textures, + const std::string& propName, + aiTextureType target, const MeshGeometry* const mesh) + { + TextureMap::const_iterator it = textures.find(propName); + if (it == textures.end()) { + return; + } + + const Texture* const tex = (*it).second; + if (tex != 0) + { + aiString path = GetTexturePath(tex); + out_mat->AddProperty(&path, _AI_MATKEY_TEXTURE_BASE, target, 0); + + aiUVTransform uvTrafo; + // XXX handle all kinds of UV transformations + uvTrafo.mScaling = tex->UVScaling(); + uvTrafo.mTranslation = tex->UVTranslation(); + out_mat->AddProperty(&uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, 0); + + const PropertyTable& props = tex->Props(); + + int uvIndex = 0; + + bool ok; + const std::string& uvSet = PropertyGet(props, "UVSet", ok); + if (ok) { + // "default" is the name which usually appears in the FbxFileTexture template + if (uvSet != "default" && uvSet.length()) { + // this is a bit awkward - we need to find a mesh that uses this + // material and scan its UV channels for the given UV name because + // assimp references UV channels by index, not by name. + + // XXX: the case that UV channels may appear in different orders + // in meshes is unhandled. A possible solution would be to sort + // the UV channels alphabetically, but this would have the side + // effect that the primary (first) UV channel would sometimes + // be moved, causing trouble when users read only the first + // UV channel and ignore UV channel assignments altogether. + + const unsigned int matIndex = static_cast(std::distance(materials.begin(), + std::find(materials.begin(), materials.end(), out_mat) + )); + + + uvIndex = -1; + if (!mesh) + { + for (const MeshMap::value_type& v : meshes_converted) { + const MeshGeometry* const mesh = dynamic_cast (v.first); + if (!mesh) { + continue; + } + + const MatIndexArray& mats = mesh->GetMaterialIndices(); + if (std::find(mats.begin(), mats.end(), matIndex) == mats.end()) { + continue; + } + + int index = -1; + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { + if (mesh->GetTextureCoords(i).empty()) { + break; + } + const std::string& name = mesh->GetTextureCoordChannelName(i); + if (name == uvSet) { + index = static_cast(i); + break; + } + } + if (index == -1) { + FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); + continue; + } + + if (uvIndex == -1) { + uvIndex = index; + } + else { + FBXImporter::LogWarn("the UV channel named " + uvSet + + " appears at different positions in meshes, results will be wrong"); + } + } + } + else + { + int index = -1; + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { + if (mesh->GetTextureCoords(i).empty()) { + break; + } + const std::string& name = mesh->GetTextureCoordChannelName(i); + if (name == uvSet) { + index = static_cast(i); + break; + } + } + if (index == -1) { + FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); + } + + if (uvIndex == -1) { + uvIndex = index; + } + } + + if (uvIndex == -1) { + FBXImporter::LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel"); + uvIndex = 0; + } + } + } + + out_mat->AddProperty(&uvIndex, 1, _AI_MATKEY_UVWSRC_BASE, target, 0); + } + } + + void FBXConverter::TrySetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, + const std::string& propName, + aiTextureType target, const MeshGeometry* const mesh) { + LayeredTextureMap::const_iterator it = layeredTextures.find(propName); + if (it == layeredTextures.end()) { + return; + } + + int texCount = (*it).second->textureCount(); + + // Set the blend mode for layered textures + int blendmode = (*it).second->GetBlendMode(); + out_mat->AddProperty(&blendmode, 1, _AI_MATKEY_TEXOP_BASE, target, 0); + + for (int texIndex = 0; texIndex < texCount; texIndex++) { + + const Texture* const tex = (*it).second->getTexture(texIndex); + + aiString path = GetTexturePath(tex); + out_mat->AddProperty(&path, _AI_MATKEY_TEXTURE_BASE, target, texIndex); + + aiUVTransform uvTrafo; + // XXX handle all kinds of UV transformations + uvTrafo.mScaling = tex->UVScaling(); + uvTrafo.mTranslation = tex->UVTranslation(); + out_mat->AddProperty(&uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, texIndex); + + const PropertyTable& props = tex->Props(); + + int uvIndex = 0; + + bool ok; + const std::string& uvSet = PropertyGet(props, "UVSet", ok); + if (ok) { + // "default" is the name which usually appears in the FbxFileTexture template + if (uvSet != "default" && uvSet.length()) { + // this is a bit awkward - we need to find a mesh that uses this + // material and scan its UV channels for the given UV name because + // assimp references UV channels by index, not by name. + + // XXX: the case that UV channels may appear in different orders + // in meshes is unhandled. A possible solution would be to sort + // the UV channels alphabetically, but this would have the side + // effect that the primary (first) UV channel would sometimes + // be moved, causing trouble when users read only the first + // UV channel and ignore UV channel assignments altogether. + + const unsigned int matIndex = static_cast(std::distance(materials.begin(), + std::find(materials.begin(), materials.end(), out_mat) + )); + + uvIndex = -1; + if (!mesh) + { + for (const MeshMap::value_type& v : meshes_converted) { + const MeshGeometry* const mesh = dynamic_cast (v.first); + if (!mesh) { + continue; + } + + const MatIndexArray& mats = mesh->GetMaterialIndices(); + if (std::find(mats.begin(), mats.end(), matIndex) == mats.end()) { + continue; + } + + int index = -1; + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { + if (mesh->GetTextureCoords(i).empty()) { + break; + } + const std::string& name = mesh->GetTextureCoordChannelName(i); + if (name == uvSet) { + index = static_cast(i); + break; + } + } + if (index == -1) { + FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); + continue; + } + + if (uvIndex == -1) { + uvIndex = index; + } + else { + FBXImporter::LogWarn("the UV channel named " + uvSet + + " appears at different positions in meshes, results will be wrong"); + } + } + } + else + { + int index = -1; + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { + if (mesh->GetTextureCoords(i).empty()) { + break; + } + const std::string& name = mesh->GetTextureCoordChannelName(i); + if (name == uvSet) { + index = static_cast(i); + break; + } + } + if (index == -1) { + FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); + } + + if (uvIndex == -1) { + uvIndex = index; + } + } + + if (uvIndex == -1) { + FBXImporter::LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel"); + uvIndex = 0; + } + } + } + + out_mat->AddProperty(&uvIndex, 1, _AI_MATKEY_UVWSRC_BASE, target, texIndex); + } + } + + void FBXConverter::SetTextureProperties(aiMaterial* out_mat, const TextureMap& textures, const MeshGeometry* const mesh) + { + TrySetTextureProperties(out_mat, textures, "DiffuseColor", aiTextureType_DIFFUSE, mesh); + TrySetTextureProperties(out_mat, textures, "AmbientColor", aiTextureType_AMBIENT, mesh); + TrySetTextureProperties(out_mat, textures, "EmissiveColor", aiTextureType_EMISSIVE, mesh); + TrySetTextureProperties(out_mat, textures, "SpecularColor", aiTextureType_SPECULAR, mesh); + TrySetTextureProperties(out_mat, textures, "SpecularFactor", aiTextureType_SPECULAR, mesh); + TrySetTextureProperties(out_mat, textures, "TransparentColor", aiTextureType_OPACITY, mesh); + TrySetTextureProperties(out_mat, textures, "ReflectionColor", aiTextureType_REFLECTION, mesh); + TrySetTextureProperties(out_mat, textures, "DisplacementColor", aiTextureType_DISPLACEMENT, mesh); + TrySetTextureProperties(out_mat, textures, "NormalMap", aiTextureType_NORMALS, mesh); + TrySetTextureProperties(out_mat, textures, "Bump", aiTextureType_HEIGHT, mesh); + TrySetTextureProperties(out_mat, textures, "ShininessExponent", aiTextureType_SHININESS, mesh); + TrySetTextureProperties( out_mat, textures, "TransparencyFactor", aiTextureType_OPACITY, mesh ); + TrySetTextureProperties( out_mat, textures, "EmissiveFactor", aiTextureType_EMISSIVE, mesh ); + //Maya counterparts + TrySetTextureProperties(out_mat, textures, "Maya|DiffuseTexture", aiTextureType_DIFFUSE, mesh); + TrySetTextureProperties(out_mat, textures, "Maya|NormalTexture", aiTextureType_NORMALS, mesh); + TrySetTextureProperties(out_mat, textures, "Maya|SpecularTexture", aiTextureType_SPECULAR, mesh); + TrySetTextureProperties(out_mat, textures, "Maya|FalloffTexture", aiTextureType_OPACITY, mesh); + TrySetTextureProperties(out_mat, textures, "Maya|ReflectionMapTexture", aiTextureType_REFLECTION, mesh); + } + + void FBXConverter::SetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, const MeshGeometry* const mesh) + { + TrySetTextureProperties(out_mat, layeredTextures, "DiffuseColor", aiTextureType_DIFFUSE, mesh); + TrySetTextureProperties(out_mat, layeredTextures, "AmbientColor", aiTextureType_AMBIENT, mesh); + TrySetTextureProperties(out_mat, layeredTextures, "EmissiveColor", aiTextureType_EMISSIVE, mesh); + TrySetTextureProperties(out_mat, layeredTextures, "SpecularColor", aiTextureType_SPECULAR, mesh); + TrySetTextureProperties(out_mat, layeredTextures, "SpecularFactor", aiTextureType_SPECULAR, mesh); + TrySetTextureProperties(out_mat, layeredTextures, "TransparentColor", aiTextureType_OPACITY, mesh); + TrySetTextureProperties(out_mat, layeredTextures, "ReflectionColor", aiTextureType_REFLECTION, mesh); + TrySetTextureProperties(out_mat, layeredTextures, "DisplacementColor", aiTextureType_DISPLACEMENT, mesh); + TrySetTextureProperties(out_mat, layeredTextures, "NormalMap", aiTextureType_NORMALS, mesh); + TrySetTextureProperties(out_mat, layeredTextures, "Bump", aiTextureType_HEIGHT, mesh); + TrySetTextureProperties(out_mat, layeredTextures, "ShininessExponent", aiTextureType_SHININESS, mesh); + TrySetTextureProperties( out_mat, layeredTextures, "EmissiveFactor", aiTextureType_EMISSIVE, mesh ); + TrySetTextureProperties( out_mat, layeredTextures, "TransparencyFactor", aiTextureType_OPACITY, mesh ); + } + + aiColor3D FBXConverter::GetColorPropertyFactored(const PropertyTable& props, const std::string& colorName, + const std::string& factorName, bool& result, bool useTemplate) + { + result = true; + + bool ok; + aiVector3D BaseColor = PropertyGet(props, colorName, ok, useTemplate); + if (!ok) { + result = false; + return aiColor3D(0.0f, 0.0f, 0.0f); + } + + // if no factor name, return the colour as is + if (factorName.empty()) { + return aiColor3D(BaseColor.x, BaseColor.y, BaseColor.z); + } + + // otherwise it should be multiplied by the factor, if found. + float factor = PropertyGet(props, factorName, ok, useTemplate); + if (ok) { + BaseColor *= factor; + } + return aiColor3D(BaseColor.x, BaseColor.y, BaseColor.z); + } + + aiColor3D FBXConverter::GetColorPropertyFromMaterial(const PropertyTable& props, const std::string& baseName, + bool& result) + { + return GetColorPropertyFactored(props, baseName + "Color", baseName + "Factor", result, true); + } + + aiColor3D FBXConverter::GetColorProperty(const PropertyTable& props, const std::string& colorName, + bool& result, bool useTemplate) + { + result = true; + bool ok; + const aiVector3D& ColorVec = PropertyGet(props, colorName, ok, useTemplate); + if (!ok) { + result = false; + return aiColor3D(0.0f, 0.0f, 0.0f); + } + return aiColor3D(ColorVec.x, ColorVec.y, ColorVec.z); + } + + void FBXConverter::SetShadingPropertiesCommon(aiMaterial* out_mat, const PropertyTable& props) + { + // Set shading properties. + // Modern FBX Files have two separate systems for defining these, + // with only the more comprehensive one described in the property template. + // Likely the other values are a legacy system, + // which is still always exported by the official FBX SDK. + // + // Blender's FBX import and export mostly ignore this legacy system, + // and as we only support recent versions of FBX anyway, we can do the same. + bool ok; + + const aiColor3D& Diffuse = GetColorPropertyFromMaterial(props, "Diffuse", ok); + if (ok) { + out_mat->AddProperty(&Diffuse, 1, AI_MATKEY_COLOR_DIFFUSE); + } + + const aiColor3D& Emissive = GetColorPropertyFromMaterial(props, "Emissive", ok); + if (ok) { + out_mat->AddProperty(&Emissive, 1, AI_MATKEY_COLOR_EMISSIVE); + } + + const aiColor3D& Ambient = GetColorPropertyFromMaterial(props, "Ambient", ok); + if (ok) { + out_mat->AddProperty(&Ambient, 1, AI_MATKEY_COLOR_AMBIENT); + } + + // we store specular factor as SHININESS_STRENGTH, so just get the color + const aiColor3D& Specular = GetColorProperty(props, "SpecularColor", ok, true); + if (ok) { + out_mat->AddProperty(&Specular, 1, AI_MATKEY_COLOR_SPECULAR); + } + + // and also try to get SHININESS_STRENGTH + const float SpecularFactor = PropertyGet(props, "SpecularFactor", ok, true); + if (ok) { + out_mat->AddProperty(&SpecularFactor, 1, AI_MATKEY_SHININESS_STRENGTH); + } + + // and the specular exponent + const float ShininessExponent = PropertyGet(props, "ShininessExponent", ok); + if (ok) { + out_mat->AddProperty(&ShininessExponent, 1, AI_MATKEY_SHININESS); + } + + // TransparentColor / TransparencyFactor... gee thanks FBX :rolleyes: + const aiColor3D& Transparent = GetColorPropertyFactored(props, "TransparentColor", "TransparencyFactor", ok); + float CalculatedOpacity = 1.0f; + if (ok) { + out_mat->AddProperty(&Transparent, 1, AI_MATKEY_COLOR_TRANSPARENT); + // as calculated by FBX SDK 2017: + CalculatedOpacity = 1.0f - ((Transparent.r + Transparent.g + Transparent.b) / 3.0f); + } + + // use of TransparencyFactor is inconsistent. + // Maya always stores it as 1.0, + // so we can't use it to set AI_MATKEY_OPACITY. + // Blender is more sensible and stores it as the alpha value. + // However both the FBX SDK and Blender always write an additional + // legacy "Opacity" field, so we can try to use that. + // + // If we can't find it, + // we can fall back to the value which the FBX SDK calculates + // from transparency colour (RGB) and factor (F) as + // 1.0 - F*((R+G+B)/3). + // + // There's no consistent way to interpret this opacity value, + // so it's up to clients to do the correct thing. + const float Opacity = PropertyGet(props, "Opacity", ok); + if (ok) { + out_mat->AddProperty(&Opacity, 1, AI_MATKEY_OPACITY); + } + else if (CalculatedOpacity != 1.0) { + out_mat->AddProperty(&CalculatedOpacity, 1, AI_MATKEY_OPACITY); + } + + // reflection color and factor are stored separately + const aiColor3D& Reflection = GetColorProperty(props, "ReflectionColor", ok, true); + if (ok) { + out_mat->AddProperty(&Reflection, 1, AI_MATKEY_COLOR_REFLECTIVE); + } + + float ReflectionFactor = PropertyGet(props, "ReflectionFactor", ok, true); + if (ok) { + out_mat->AddProperty(&ReflectionFactor, 1, AI_MATKEY_REFLECTIVITY); + } + + 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); + } + } + + + double FBXConverter::FrameRateToDouble(FileGlobalSettings::FrameRate fp, double customFPSVal) { + switch (fp) { + case FileGlobalSettings::FrameRate_DEFAULT: + return 1.0; + + case FileGlobalSettings::FrameRate_120: + return 120.0; + + case FileGlobalSettings::FrameRate_100: + return 100.0; + + case FileGlobalSettings::FrameRate_60: + return 60.0; + + case FileGlobalSettings::FrameRate_50: + return 50.0; + + case FileGlobalSettings::FrameRate_48: + return 48.0; + + case FileGlobalSettings::FrameRate_30: + case FileGlobalSettings::FrameRate_30_DROP: + return 30.0; + + case FileGlobalSettings::FrameRate_NTSC_DROP_FRAME: + case FileGlobalSettings::FrameRate_NTSC_FULL_FRAME: + return 29.9700262; + + case FileGlobalSettings::FrameRate_PAL: + return 25.0; + + case FileGlobalSettings::FrameRate_CINEMA: + return 24.0; + + case FileGlobalSettings::FrameRate_1000: + return 1000.0; + + case FileGlobalSettings::FrameRate_CINEMA_ND: + return 23.976; + + case FileGlobalSettings::FrameRate_CUSTOM: + return customFPSVal; + + case FileGlobalSettings::FrameRate_MAX: // this is to silence compiler warnings + break; + } + + ai_assert(false); + + return -1.0f; + } + + + void FBXConverter::ConvertAnimations() + { + // first of all determine framerate + const FileGlobalSettings::FrameRate fps = doc.GlobalSettings().TimeMode(); + const float custom = doc.GlobalSettings().CustomFrameRate(); + anim_fps = FrameRateToDouble(fps, custom); + + const std::vector& animations = doc.AnimationStacks(); + for (const AnimationStack* stack : animations) { + ConvertAnimationStack(*stack); + } + } + + std::string FBXConverter::FixNodeName(const std::string& name) { + // strip Model:: prefix, avoiding ambiguities (i.e. don't strip if + // this causes ambiguities, well possible between empty identifiers, + // such as "Model::" and ""). Make sure the behaviour is consistent + // across multiple calls to FixNodeName(). + if (name.substr(0, 7) == "Model::") { + std::string temp = name.substr(7); + return temp; + } + + return name; + } + + std::string FBXConverter::FixAnimMeshName(const std::string& name) { + if (name.length()) { + size_t indexOf = name.find_first_of("::"); + if (indexOf != std::string::npos && indexOf < name.size() - 2) { + return name.substr(indexOf + 2); + } + } + return name.length() ? name : "AnimMesh"; + } + + void FBXConverter::ConvertAnimationStack(const AnimationStack& st) + { + const AnimationLayerList& layers = st.Layers(); + if (layers.empty()) { + return; + } + + aiAnimation* const anim = new aiAnimation(); + animations.push_back(anim); + + // strip AnimationStack:: prefix + std::string name = st.Name(); + if (name.substr(0, 16) == "AnimationStack::") { + name = name.substr(16); + } + else if (name.substr(0, 11) == "AnimStack::") { + name = name.substr(11); + } + + anim->mName.Set(name); + + // need to find all nodes for which we need to generate node animations - + // it may happen that we need to merge multiple layers, though. + NodeMap node_map; + + // reverse mapping from curves to layers, much faster than querying + // the FBX DOM for it. + LayerMap layer_map; + + const char* prop_whitelist[] = { + "Lcl Scaling", + "Lcl Rotation", + "Lcl Translation", + "DeformPercent" + }; + + std::map morphAnimDatas; + + for (const AnimationLayer* layer : layers) { + ai_assert(layer); + const AnimationCurveNodeList& nodes = layer->Nodes(prop_whitelist, 4); + for (const AnimationCurveNode* node : nodes) { + ai_assert(node); + const Model* const model = dynamic_cast(node->Target()); + if (model) { + const std::string& name = FixNodeName(model->Name()); + node_map[name].push_back(node); + layer_map[node] = layer; + continue; + } + const BlendShapeChannel* const bsc = dynamic_cast(node->Target()); + if (bsc) { + ProcessMorphAnimDatas(&morphAnimDatas, bsc, node); + } + } + } + + // generate node animations + std::vector node_anims; + + double min_time = 1e10; + double max_time = -1e10; + + int64_t start_time = st.LocalStart(); + int64_t stop_time = st.LocalStop(); + 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) { + GenerateNodeAnimations(node_anims, + kv.first, + kv.second, + layer_map, + start_time, stop_time, + max_time, + min_time); + } + } + catch (std::exception&) { + std::for_each(node_anims.begin(), node_anims.end(), Util::delete_fun()); + throw; + } + + if (node_anims.size() || morphAnimDatas.size()) { + if (node_anims.size()) { + anim->mChannels = new aiNodeAnim*[node_anims.size()](); + anim->mNumChannels = static_cast(node_anims.size()); + std::swap_ranges(node_anims.begin(), node_anims.end(), anim->mChannels); + } + if (morphAnimDatas.size()) { + unsigned int numMorphMeshChannels = static_cast(morphAnimDatas.size()); + anim->mMorphMeshChannels = new aiMeshMorphAnim*[numMorphMeshChannels]; + anim->mNumMorphMeshChannels = numMorphMeshChannels; + unsigned int i = 0; + for (auto morphAnimIt : morphAnimDatas) { + morphAnimData* animData = morphAnimIt.second; + unsigned int numKeys = static_cast(animData->size()); + aiMeshMorphAnim* meshMorphAnim = new aiMeshMorphAnim(); + meshMorphAnim->mName.Set(morphAnimIt.first); + meshMorphAnim->mNumKeys = numKeys; + meshMorphAnim->mKeys = new aiMeshMorphKey[numKeys]; + unsigned int j = 0; + for (auto animIt : *animData) { + morphKeyData* keyData = animIt.second; + unsigned int numValuesAndWeights = static_cast(keyData->values.size()); + meshMorphAnim->mKeys[j].mNumValuesAndWeights = numValuesAndWeights; + meshMorphAnim->mKeys[j].mValues = new unsigned int[numValuesAndWeights]; + meshMorphAnim->mKeys[j].mWeights = new double[numValuesAndWeights]; + meshMorphAnim->mKeys[j].mTime = CONVERT_FBX_TIME(animIt.first) * anim_fps; + for (unsigned int k = 0; k < numValuesAndWeights; k++) { + meshMorphAnim->mKeys[j].mValues[k] = keyData->values.at(k); + meshMorphAnim->mKeys[j].mWeights[k] = keyData->weights.at(k); + } + j++; + } + anim->mMorphMeshChannels[i++] = meshMorphAnim; + } + } + } + else { + // empty animations would fail validation, so drop them + delete anim; + animations.pop_back(); + FBXImporter::LogInfo("ignoring empty AnimationStack (using IK?): " + name); + return; + } + + 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; + + // 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 (unsigned int c = 0; c < anim->mNumMorphMeshChannels; c++) { + aiMeshMorphAnim* channel = anim->mMorphMeshChannels[c]; + for (uint32_t i = 0; i < channel->mNumKeys; i++) { + channel->mKeys[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_time_fps - start_time_fps; + anim->mTicksPerSecond = anim_fps; + } + + // ------------------------------------------------------------------------------------------------ + void FBXConverter::ProcessMorphAnimDatas(std::map* morphAnimDatas, const BlendShapeChannel* bsc, const AnimationCurveNode* node) { + std::vector bscConnections = doc.GetConnectionsBySourceSequenced(bsc->ID(), "Deformer"); + for (const Connection* bscConnection : bscConnections) { + auto bs = dynamic_cast(bscConnection->DestinationObject()); + if (bs) { + auto channelIt = std::find(bs->BlendShapeChannels().begin(), bs->BlendShapeChannels().end(), bsc); + if (channelIt != bs->BlendShapeChannels().end()) { + auto channelIndex = static_cast(std::distance(bs->BlendShapeChannels().begin(), channelIt)); + std::vector bsConnections = doc.GetConnectionsBySourceSequenced(bs->ID(), "Geometry"); + for (const Connection* bsConnection : bsConnections) { + auto geo = dynamic_cast(bsConnection->DestinationObject()); + if (geo) { + std::vector geoConnections = doc.GetConnectionsBySourceSequenced(geo->ID(), "Model"); + for (const Connection* geoConnection : geoConnections) { + auto model = dynamic_cast(geoConnection->DestinationObject()); + if (model) { + auto geoIt = std::find(model->GetGeometry().begin(), model->GetGeometry().end(), geo); + auto geoIndex = static_cast(std::distance(model->GetGeometry().begin(), geoIt)); + auto name = aiString(FixNodeName(model->Name() + "*")); + name.length = 1 + ASSIMP_itoa10(name.data + name.length, MAXLEN - 1, geoIndex); + morphAnimData* animData; + auto animIt = morphAnimDatas->find(name.C_Str()); + if (animIt == morphAnimDatas->end()) { + animData = new morphAnimData(); + morphAnimDatas->insert(std::make_pair(name.C_Str(), animData)); + } + else { + animData = animIt->second; + } + for (std::pair curvesIt : node->Curves()) { + if (curvesIt.first == "d|DeformPercent") { + const AnimationCurve* animationCurve = curvesIt.second; + const KeyTimeList& keys = animationCurve->GetKeys(); + const KeyValueList& values = animationCurve->GetValues(); + unsigned int k = 0; + for (auto key : keys) { + morphKeyData* keyData; + auto keyIt = animData->find(key); + if (keyIt == animData->end()) { + keyData = new morphKeyData(); + animData->insert(std::make_pair(key, keyData)); + } + else { + keyData = keyIt->second; + } + keyData->values.push_back(channelIndex); + keyData->weights.push_back(values.at(k) / 100.0f); + k++; + } + } + } + } + } + } + } + } + } + } + } + + // ------------------------------------------------------------------------------------------------ +#ifdef ASSIMP_BUILD_DEBUG + // ------------------------------------------------------------------------------------------------ + // sanity check whether the input is ok + static void validateAnimCurveNodes(const std::vector& curves, + bool strictMode) { + const Object* target(NULL); + for (const AnimationCurveNode* node : curves) { + if (!target) { + target = node->Target(); + } + if (node->Target() != target) { + FBXImporter::LogWarn("Node target is nullptr type."); + } + if (strictMode) { + ai_assert(node->Target() == target); + } + } + } +#endif // ASSIMP_BUILD_DEBUG + + // ------------------------------------------------------------------------------------------------ + void FBXConverter::GenerateNodeAnimations(std::vector& node_anims, + const std::string& fixed_name, + const std::vector& curves, + const LayerMap& layer_map, + int64_t start, int64_t stop, + double& max_time, + double& min_time) + { + + NodeMap node_property_map; + ai_assert(curves.size()); + +#ifdef ASSIMP_BUILD_DEBUG + validateAnimCurveNodes(curves, doc.Settings().strictMode); +#endif + const AnimationCurveNode* curve_node = NULL; + for (const AnimationCurveNode* node : curves) { + ai_assert(node); + + if (node->TargetProperty().empty()) { + FBXImporter::LogWarn("target property for animation curve not set: " + node->Name()); + continue; + } + + curve_node = node; + if (node->Curves().empty()) { + FBXImporter::LogWarn("no animation curves assigned to AnimationCurveNode: " + node->Name()); + continue; + } + + node_property_map[node->TargetProperty()].push_back(node); + } + + ai_assert(curve_node); + ai_assert(curve_node->TargetAsModel()); + + const Model& target = *curve_node->TargetAsModel(); + + // check for all possible transformation components + NodeMap::const_iterator chain[TransformationComp_MAXIMUM]; + + bool has_any = false; + bool has_complex = false; + + for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) { + const TransformationComp comp = static_cast(i); + + // inverse pivots don't exist in the input, we just generate them + if (comp == TransformationComp_RotationPivotInverse || comp == TransformationComp_ScalingPivotInverse) { + chain[i] = node_property_map.end(); + continue; + } + + chain[i] = node_property_map.find(NameTransformationCompProperty(comp)); + if (chain[i] != node_property_map.end()) { + + // check if this curves contains redundant information by looking + // up the corresponding node's transformation chain. + if (doc.Settings().optimizeEmptyAnimationCurves && + IsRedundantAnimationData(target, comp, (*chain[i]).second)) { + + FBXImporter::LogDebug("dropping redundant animation channel for node " + target.Name()); + continue; + } + + has_any = true; + + if (comp != TransformationComp_Rotation && comp != TransformationComp_Scaling && comp != TransformationComp_Translation) + { + has_complex = true; + } + } + } + + if (!has_any) { + FBXImporter::LogWarn("ignoring node animation, did not find any transformation key frames"); + return; + } + + // this needs to play nicely with GenerateTransformationNodeChain() which will + // be invoked _later_ (animations come first). If this node has only rotation, + // scaling and translation _and_ there are no animated other components either, + // we can use a single node and also a single node animation channel. + if (!has_complex && !NeedsComplexTransformationChain(target)) { + + aiNodeAnim* const nd = GenerateSimpleNodeAnim(fixed_name, target, chain, + node_property_map.end(), + layer_map, + start, stop, + max_time, + min_time, + true // input is TRS order, assimp is SRT + ); + + ai_assert(nd); + if (nd->mNumPositionKeys == 0 && nd->mNumRotationKeys == 0 && nd->mNumScalingKeys == 0) { + delete nd; + } + else { + node_anims.push_back(nd); + } + return; + } + + // otherwise, things get gruesome and we need separate animation channels + // for each part of the transformation chain. Remember which channels + // we generated and pass this information to the node conversion + // code to avoid nodes that have identity transform, but non-identity + // animations, being dropped. + unsigned int flags = 0, bit = 0x1; + for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i, bit <<= 1) { + const TransformationComp comp = static_cast(i); + + if (chain[i] != node_property_map.end()) { + flags |= bit; + + ai_assert(comp != TransformationComp_RotationPivotInverse); + ai_assert(comp != TransformationComp_ScalingPivotInverse); + + const std::string& chain_name = NameTransformationChainNode(fixed_name, comp); + + aiNodeAnim* na = nullptr; + switch (comp) + { + case TransformationComp_Rotation: + case TransformationComp_PreRotation: + case TransformationComp_PostRotation: + case TransformationComp_GeometricRotation: + na = GenerateRotationNodeAnim(chain_name, + target, + (*chain[i]).second, + layer_map, + start, stop, + max_time, + min_time); + + break; + + case TransformationComp_RotationOffset: + case TransformationComp_RotationPivot: + case TransformationComp_ScalingOffset: + case TransformationComp_ScalingPivot: + case TransformationComp_Translation: + case TransformationComp_GeometricTranslation: + na = GenerateTranslationNodeAnim(chain_name, + target, + (*chain[i]).second, + layer_map, + start, stop, + max_time, + min_time); + + // pivoting requires us to generate an implicit inverse channel to undo the pivot translation + if (comp == TransformationComp_RotationPivot) { + const std::string& invName = NameTransformationChainNode(fixed_name, + TransformationComp_RotationPivotInverse); + + aiNodeAnim* const inv = GenerateTranslationNodeAnim(invName, + target, + (*chain[i]).second, + layer_map, + start, stop, + max_time, + min_time, + true); + + ai_assert(inv); + if (inv->mNumPositionKeys == 0 && inv->mNumRotationKeys == 0 && inv->mNumScalingKeys == 0) { + delete inv; + } + else { + node_anims.push_back(inv); + } + + ai_assert(TransformationComp_RotationPivotInverse > i); + flags |= bit << (TransformationComp_RotationPivotInverse - i); + } + else if (comp == TransformationComp_ScalingPivot) { + const std::string& invName = NameTransformationChainNode(fixed_name, + TransformationComp_ScalingPivotInverse); + + aiNodeAnim* const inv = GenerateTranslationNodeAnim(invName, + target, + (*chain[i]).second, + layer_map, + start, stop, + max_time, + min_time, + true); + + ai_assert(inv); + if (inv->mNumPositionKeys == 0 && inv->mNumRotationKeys == 0 && inv->mNumScalingKeys == 0) { + delete inv; + } + else { + node_anims.push_back(inv); + } + + ai_assert(TransformationComp_RotationPivotInverse > i); + flags |= bit << (TransformationComp_RotationPivotInverse - i); + } + + break; + + case TransformationComp_Scaling: + case TransformationComp_GeometricScaling: + na = GenerateScalingNodeAnim(chain_name, + target, + (*chain[i]).second, + layer_map, + start, stop, + max_time, + min_time); + + break; + + default: + ai_assert(false); + } + + ai_assert(na); + if (na->mNumPositionKeys == 0 && na->mNumRotationKeys == 0 && na->mNumScalingKeys == 0) { + delete na; + } + else { + node_anims.push_back(na); + } + continue; + } + } + + node_anim_chain_bits[fixed_name] = flags; + } + + + bool FBXConverter::IsRedundantAnimationData(const Model& target, + TransformationComp comp, + const std::vector& curves) { + ai_assert(curves.size()); + + // look for animation nodes with + // * sub channels for all relevant components set + // * one key/value pair per component + // * combined values match up the corresponding value in the bind pose node transformation + // only such nodes are 'redundant' for this function. + + if (curves.size() > 1) { + return false; + } + + const AnimationCurveNode& nd = *curves.front(); + const AnimationCurveMap& sub_curves = nd.Curves(); + + const AnimationCurveMap::const_iterator dx = sub_curves.find("d|X"); + const AnimationCurveMap::const_iterator dy = sub_curves.find("d|Y"); + const AnimationCurveMap::const_iterator dz = sub_curves.find("d|Z"); + + if (dx == sub_curves.end() || dy == sub_curves.end() || dz == sub_curves.end()) { + return false; + } + + const KeyValueList& vx = (*dx).second->GetValues(); + const KeyValueList& vy = (*dy).second->GetValues(); + const KeyValueList& vz = (*dz).second->GetValues(); + + if (vx.size() != 1 || vy.size() != 1 || vz.size() != 1) { + return false; + } + + const aiVector3D dyn_val = aiVector3D(vx[0], vy[0], vz[0]); + const aiVector3D& static_val = PropertyGet(target.Props(), + NameTransformationCompProperty(comp), + TransformationCompDefaultValue(comp) + ); + + const float epsilon = 1e-6f; + return (dyn_val - static_val).SquareLength() < epsilon; + } + + + aiNodeAnim* FBXConverter::GenerateRotationNodeAnim(const std::string& name, + const Model& target, + const std::vector& curves, + const LayerMap& layer_map, + int64_t start, int64_t stop, + double& max_time, + double& min_time) + { + std::unique_ptr na(new aiNodeAnim()); + na->mNodeName.Set(name); + + ConvertRotationKeys(na.get(), curves, layer_map, start, stop, max_time, min_time, target.RotationOrder()); + + // dummy scaling key + na->mScalingKeys = new aiVectorKey[1]; + na->mNumScalingKeys = 1; + + na->mScalingKeys[0].mTime = 0.; + na->mScalingKeys[0].mValue = aiVector3D(1.0f, 1.0f, 1.0f); + + // dummy position key + na->mPositionKeys = new aiVectorKey[1]; + na->mNumPositionKeys = 1; + + na->mPositionKeys[0].mTime = 0.; + na->mPositionKeys[0].mValue = aiVector3D(); + + return na.release(); + } + + aiNodeAnim* FBXConverter::GenerateScalingNodeAnim(const std::string& name, + const Model& /*target*/, + const std::vector& curves, + const LayerMap& layer_map, + int64_t start, int64_t stop, + double& max_time, + double& min_time) + { + std::unique_ptr na(new aiNodeAnim()); + na->mNodeName.Set(name); + + ConvertScaleKeys(na.get(), curves, layer_map, start, stop, max_time, min_time); + + // dummy rotation key + na->mRotationKeys = new aiQuatKey[1]; + na->mNumRotationKeys = 1; + + na->mRotationKeys[0].mTime = 0.; + na->mRotationKeys[0].mValue = aiQuaternion(); + + // dummy position key + na->mPositionKeys = new aiVectorKey[1]; + na->mNumPositionKeys = 1; + + na->mPositionKeys[0].mTime = 0.; + na->mPositionKeys[0].mValue = aiVector3D(); + + return na.release(); + } + + aiNodeAnim* FBXConverter::GenerateTranslationNodeAnim(const std::string& name, + const Model& /*target*/, + const std::vector& curves, + const LayerMap& layer_map, + int64_t start, int64_t stop, + double& max_time, + double& min_time, + bool inverse) { + std::unique_ptr na(new aiNodeAnim()); + na->mNodeName.Set(name); + + ConvertTranslationKeys(na.get(), curves, layer_map, start, stop, max_time, min_time); + + if (inverse) { + for (unsigned int i = 0; i < na->mNumPositionKeys; ++i) { + na->mPositionKeys[i].mValue *= -1.0f; + } + } + + // dummy scaling key + na->mScalingKeys = new aiVectorKey[1]; + na->mNumScalingKeys = 1; + + na->mScalingKeys[0].mTime = 0.; + na->mScalingKeys[0].mValue = aiVector3D(1.0f, 1.0f, 1.0f); + + // dummy rotation key + na->mRotationKeys = new aiQuatKey[1]; + na->mNumRotationKeys = 1; + + na->mRotationKeys[0].mTime = 0.; + na->mRotationKeys[0].mValue = aiQuaternion(); + + return na.release(); + } + + aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name, + const Model& target, + NodeMap::const_iterator chain[TransformationComp_MAXIMUM], + NodeMap::const_iterator iter_end, + const LayerMap& layer_map, + int64_t start, int64_t stop, + double& max_time, + double& min_time, + bool reverse_order) + + { + std::unique_ptr na(new aiNodeAnim()); + na->mNodeName.Set(name); + + const PropertyTable& props = target.Props(); + + // need to convert from TRS order to SRT? + if (reverse_order) { + + aiVector3D def_scale = PropertyGet(props, "Lcl Scaling", aiVector3D(1.f, 1.f, 1.f)); + aiVector3D def_translate = PropertyGet(props, "Lcl Translation", aiVector3D(0.f, 0.f, 0.f)); + aiVector3D def_rot = PropertyGet(props, "Lcl Rotation", aiVector3D(0.f, 0.f, 0.f)); + + KeyFrameListList scaling; + KeyFrameListList translation; + KeyFrameListList rotation; + + if (chain[TransformationComp_Scaling] != iter_end) { + scaling = GetKeyframeList((*chain[TransformationComp_Scaling]).second, start, stop); + } + + if (chain[TransformationComp_Translation] != iter_end) { + translation = GetKeyframeList((*chain[TransformationComp_Translation]).second, start, stop); + } + + if (chain[TransformationComp_Rotation] != iter_end) { + rotation = GetKeyframeList((*chain[TransformationComp_Rotation]).second, start, stop); + } + + KeyFrameListList joined; + joined.insert(joined.end(), scaling.begin(), scaling.end()); + joined.insert(joined.end(), translation.begin(), translation.end()); + joined.insert(joined.end(), rotation.begin(), rotation.end()); + + const KeyTimeList& times = GetKeyTimeList(joined); + + aiQuatKey* out_quat = new aiQuatKey[times.size()]; + aiVectorKey* out_scale = new aiVectorKey[times.size()]; + aiVectorKey* out_translation = new aiVectorKey[times.size()]; + + if (times.size()) + { + ConvertTransformOrder_TRStoSRT(out_quat, out_scale, out_translation, + scaling, + translation, + rotation, + times, + max_time, + min_time, + target.RotationOrder(), + def_scale, + def_translate, + def_rot); + } + + // XXX remove duplicates / redundant keys which this operation did + // likely produce if not all three channels were equally dense. + + na->mNumScalingKeys = static_cast(times.size()); + na->mNumRotationKeys = na->mNumScalingKeys; + na->mNumPositionKeys = na->mNumScalingKeys; + + na->mScalingKeys = out_scale; + na->mRotationKeys = out_quat; + na->mPositionKeys = out_translation; + } + else { + + // if a particular transformation is not given, grab it from + // the corresponding node to meet the semantics of aiNodeAnim, + // which requires all of rotation, scaling and translation + // to be set. + if (chain[TransformationComp_Scaling] != iter_end) { + ConvertScaleKeys(na.get(), (*chain[TransformationComp_Scaling]).second, + layer_map, + start, stop, + max_time, + min_time); + } + else { + na->mScalingKeys = new aiVectorKey[1]; + na->mNumScalingKeys = 1; + + na->mScalingKeys[0].mTime = 0.; + na->mScalingKeys[0].mValue = PropertyGet(props, "Lcl Scaling", + aiVector3D(1.f, 1.f, 1.f)); + } + + if (chain[TransformationComp_Rotation] != iter_end) { + ConvertRotationKeys(na.get(), (*chain[TransformationComp_Rotation]).second, + layer_map, + start, stop, + max_time, + min_time, + target.RotationOrder()); + } + else { + na->mRotationKeys = new aiQuatKey[1]; + na->mNumRotationKeys = 1; + + na->mRotationKeys[0].mTime = 0.; + na->mRotationKeys[0].mValue = EulerToQuaternion( + PropertyGet(props, "Lcl Rotation", aiVector3D(0.f, 0.f, 0.f)), + target.RotationOrder()); + } + + if (chain[TransformationComp_Translation] != iter_end) { + ConvertTranslationKeys(na.get(), (*chain[TransformationComp_Translation]).second, + layer_map, + start, stop, + max_time, + min_time); + } + else { + na->mPositionKeys = new aiVectorKey[1]; + na->mNumPositionKeys = 1; + + na->mPositionKeys[0].mTime = 0.; + na->mPositionKeys[0].mValue = PropertyGet(props, "Lcl Translation", + aiVector3D(0.f, 0.f, 0.f)); + } + + } + return na.release(); + } + + FBXConverter::KeyFrameListList FBXConverter::GetKeyframeList(const std::vector& nodes, int64_t start, int64_t stop) + { + KeyFrameListList inputs; + inputs.reserve(nodes.size() * 3); + + //give some breathing room for rounding errors + int64_t adj_start = start - 10000; + int64_t adj_stop = stop + 10000; + + for (const AnimationCurveNode* node : nodes) { + ai_assert(node); + + const AnimationCurveMap& curves = node->Curves(); + for (const AnimationCurveMap::value_type& kv : curves) { + + unsigned int mapto; + if (kv.first == "d|X") { + mapto = 0; + } + else if (kv.first == "d|Y") { + mapto = 1; + } + else if (kv.first == "d|Z") { + mapto = 2; + } + else { + FBXImporter::LogWarn("ignoring scale animation curve, did not recognize target component"); + continue; + } + + const AnimationCurve* const curve = kv.second; + ai_assert(curve->GetKeys().size() == curve->GetValues().size() && curve->GetKeys().size()); + + //get values within the start/stop time window + std::shared_ptr Keys(new KeyTimeList()); + std::shared_ptr Values(new KeyValueList()); + const size_t count = curve->GetKeys().size(); + Keys->reserve(count); + Values->reserve(count); + for (size_t n = 0; n < count; n++) + { + int64_t k = curve->GetKeys().at(n); + if (k >= adj_start && k <= adj_stop) + { + Keys->push_back(k); + Values->push_back(curve->GetValues().at(n)); + } + } + + inputs.push_back(std::make_tuple(Keys, Values, mapto)); + } + } + return inputs; // pray for NRVO :-) + } + + + KeyTimeList FBXConverter::GetKeyTimeList(const KeyFrameListList& inputs) { + ai_assert(!inputs.empty()); + + // reserve some space upfront - it is likely that the key-frame lists + // have matching time values, so max(of all key-frame lists) should + // be a good estimate. + KeyTimeList keys; + + size_t estimate = 0; + for (const KeyFrameList& kfl : inputs) { + estimate = std::max(estimate, std::get<0>(kfl)->size()); + } + + keys.reserve(estimate); + + std::vector next_pos; + next_pos.resize(inputs.size(), 0); + + const size_t count = inputs.size(); + while (true) { + + int64_t min_tick = std::numeric_limits::max(); + for (size_t i = 0; i < count; ++i) { + const KeyFrameList& kfl = inputs[i]; + + if (std::get<0>(kfl)->size() > next_pos[i] && std::get<0>(kfl)->at(next_pos[i]) < min_tick) { + min_tick = std::get<0>(kfl)->at(next_pos[i]); + } + } + + if (min_tick == std::numeric_limits::max()) { + break; + } + keys.push_back(min_tick); + + for (size_t i = 0; i < count; ++i) { + const KeyFrameList& kfl = inputs[i]; + + + while (std::get<0>(kfl)->size() > next_pos[i] && std::get<0>(kfl)->at(next_pos[i]) == min_tick) { + ++next_pos[i]; + } + } + } + + return keys; + } + + void FBXConverter::InterpolateKeys(aiVectorKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs, + const aiVector3D& def_value, + double& max_time, + double& min_time) { + ai_assert(!keys.empty()); + ai_assert(nullptr != valOut); + + std::vector next_pos; + const size_t count(inputs.size()); + + next_pos.resize(inputs.size(), 0); + + for (KeyTimeList::value_type time : keys) { + ai_real result[3] = { def_value.x, def_value.y, def_value.z }; + + for (size_t i = 0; i < count; ++i) { + const KeyFrameList& kfl = inputs[i]; + + const size_t ksize = std::get<0>(kfl)->size(); + if (ksize == 0) { + continue; + } + if (ksize > next_pos[i] && std::get<0>(kfl)->at(next_pos[i]) == time) { + ++next_pos[i]; + } + + const size_t id0 = next_pos[i] > 0 ? next_pos[i] - 1 : 0; + const size_t id1 = next_pos[i] == ksize ? ksize - 1 : next_pos[i]; + + // use lerp for interpolation + const KeyValueList::value_type valueA = std::get<1>(kfl)->at(id0); + const KeyValueList::value_type valueB = std::get<1>(kfl)->at(id1); + + const KeyTimeList::value_type timeA = std::get<0>(kfl)->at(id0); + const KeyTimeList::value_type timeB = std::get<0>(kfl)->at(id1); + + const ai_real factor = timeB == timeA ? ai_real(0.) : static_cast((time - timeA)) / (timeB - timeA); + const ai_real interpValue = static_cast(valueA + (valueB - valueA) * factor); + + result[std::get<2>(kfl)] = interpValue; + } + + // magic value to convert fbx times to seconds + valOut->mTime = CONVERT_FBX_TIME(time) * anim_fps; + + min_time = std::min(min_time, valOut->mTime); + max_time = std::max(max_time, valOut->mTime); + + valOut->mValue.x = result[0]; + valOut->mValue.y = result[1]; + valOut->mValue.z = result[2]; + + ++valOut; + } + } + + void FBXConverter::InterpolateKeys(aiQuatKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs, + const aiVector3D& def_value, + double& maxTime, + double& minTime, + Model::RotOrder order) + { + ai_assert(!keys.empty()); + ai_assert(nullptr != valOut); + + std::unique_ptr temp(new aiVectorKey[keys.size()]); + InterpolateKeys(temp.get(), keys, inputs, def_value, maxTime, minTime); + + aiMatrix4x4 m; + + aiQuaternion lastq; + + for (size_t i = 0, c = keys.size(); i < c; ++i) { + + valOut[i].mTime = temp[i].mTime; + + GetRotationMatrix(order, temp[i].mValue, m); + aiQuaternion quat = aiQuaternion(aiMatrix3x3(m)); + + // take shortest path by checking the inner product + // http://www.3dkingdoms.com/weekly/weekly.php?a=36 + if (quat.x * lastq.x + quat.y * lastq.y + quat.z * lastq.z + quat.w * lastq.w < 0) + { + quat.x = -quat.x; + quat.y = -quat.y; + quat.z = -quat.z; + quat.w = -quat.w; + } + lastq = quat; + + valOut[i].mValue = quat; + } + } + + void FBXConverter::ConvertTransformOrder_TRStoSRT(aiQuatKey* out_quat, aiVectorKey* out_scale, + aiVectorKey* out_translation, + const KeyFrameListList& scaling, + const KeyFrameListList& translation, + const KeyFrameListList& rotation, + const KeyTimeList& times, + double& maxTime, + double& minTime, + Model::RotOrder order, + const aiVector3D& def_scale, + const aiVector3D& def_translate, + const aiVector3D& def_rotation) + { + if (rotation.size()) { + InterpolateKeys(out_quat, times, rotation, def_rotation, maxTime, minTime, order); + } + else { + for (size_t i = 0; i < times.size(); ++i) { + out_quat[i].mTime = CONVERT_FBX_TIME(times[i]) * anim_fps; + out_quat[i].mValue = EulerToQuaternion(def_rotation, order); + } + } + + if (scaling.size()) { + InterpolateKeys(out_scale, times, scaling, def_scale, maxTime, minTime); + } + else { + for (size_t i = 0; i < times.size(); ++i) { + out_scale[i].mTime = CONVERT_FBX_TIME(times[i]) * anim_fps; + out_scale[i].mValue = def_scale; + } + } + + if (translation.size()) { + InterpolateKeys(out_translation, times, translation, def_translate, maxTime, minTime); + } + else { + for (size_t i = 0; i < times.size(); ++i) { + out_translation[i].mTime = CONVERT_FBX_TIME(times[i]) * anim_fps; + out_translation[i].mValue = def_translate; + } + } + + const size_t count = times.size(); + for (size_t i = 0; i < count; ++i) { + aiQuaternion& r = out_quat[i].mValue; + aiVector3D& s = out_scale[i].mValue; + aiVector3D& t = out_translation[i].mValue; + + aiMatrix4x4 mat, temp; + aiMatrix4x4::Translation(t, mat); + mat *= aiMatrix4x4(r.GetMatrix()); + mat *= aiMatrix4x4::Scaling(s, temp); + + mat.Decompose(s, r, t); + } + } + + aiQuaternion FBXConverter::EulerToQuaternion(const aiVector3D& rot, Model::RotOrder order) + { + aiMatrix4x4 m; + GetRotationMatrix(order, rot, m); + + return aiQuaternion(aiMatrix3x3(m)); + } + + void FBXConverter::ConvertScaleKeys(aiNodeAnim* na, const std::vector& nodes, const LayerMap& /*layers*/, + int64_t start, int64_t stop, + double& maxTime, + double& minTime) + { + ai_assert(nodes.size()); + + // XXX for now, assume scale should be blended geometrically (i.e. two + // layers should be multiplied with each other). There is a FBX + // property in the layer to specify the behaviour, though. + + const KeyFrameListList& inputs = GetKeyframeList(nodes, start, stop); + const KeyTimeList& keys = GetKeyTimeList(inputs); + + na->mNumScalingKeys = static_cast(keys.size()); + na->mScalingKeys = new aiVectorKey[keys.size()]; + if (keys.size() > 0) + InterpolateKeys(na->mScalingKeys, keys, inputs, aiVector3D(1.0f, 1.0f, 1.0f), maxTime, minTime); + } + + void FBXConverter::ConvertTranslationKeys(aiNodeAnim* na, const std::vector& nodes, + const LayerMap& /*layers*/, + int64_t start, int64_t stop, + double& maxTime, + double& minTime) + { + ai_assert(nodes.size()); + + // XXX see notes in ConvertScaleKeys() + const KeyFrameListList& inputs = GetKeyframeList(nodes, start, stop); + const KeyTimeList& keys = GetKeyTimeList(inputs); + + na->mNumPositionKeys = static_cast(keys.size()); + na->mPositionKeys = new aiVectorKey[keys.size()]; + if (keys.size() > 0) + InterpolateKeys(na->mPositionKeys, keys, inputs, aiVector3D(0.0f, 0.0f, 0.0f), maxTime, minTime); + } + + void FBXConverter::ConvertRotationKeys(aiNodeAnim* na, const std::vector& nodes, + const LayerMap& /*layers*/, + int64_t start, int64_t stop, + double& maxTime, + double& minTime, + Model::RotOrder order) + { + ai_assert(nodes.size()); + + // XXX see notes in ConvertScaleKeys() + const std::vector< KeyFrameList >& inputs = GetKeyframeList(nodes, start, stop); + const KeyTimeList& keys = GetKeyTimeList(inputs); + + na->mNumRotationKeys = static_cast(keys.size()); + na->mRotationKeys = new aiQuatKey[keys.size()]; + if (!keys.empty()) { + InterpolateKeys(na->mRotationKeys, keys, inputs, aiVector3D(0.0f, 0.0f, 0.0f), maxTime, minTime, order); + } + } + + void FBXConverter::ConvertGlobalSettings() { + if (nullptr == out) { + return; + } + + out->mMetaData = aiMetadata::Alloc(15); + out->mMetaData->Set(0, "UpAxis", doc.GlobalSettings().UpAxis()); + out->mMetaData->Set(1, "UpAxisSign", doc.GlobalSettings().UpAxisSign()); + out->mMetaData->Set(2, "FrontAxis", doc.GlobalSettings().FrontAxis()); + out->mMetaData->Set(3, "FrontAxisSign", doc.GlobalSettings().FrontAxisSign()); + out->mMetaData->Set(4, "CoordAxis", doc.GlobalSettings().CoordAxis()); + out->mMetaData->Set(5, "CoordAxisSign", doc.GlobalSettings().CoordAxisSign()); + out->mMetaData->Set(6, "OriginalUpAxis", doc.GlobalSettings().OriginalUpAxis()); + out->mMetaData->Set(7, "OriginalUpAxisSign", doc.GlobalSettings().OriginalUpAxisSign()); + out->mMetaData->Set(8, "UnitScaleFactor", doc.GlobalSettings().UnitScaleFactor()); + out->mMetaData->Set(9, "OriginalUnitScaleFactor", doc.GlobalSettings().OriginalUnitScaleFactor()); + out->mMetaData->Set(10, "AmbientColor", doc.GlobalSettings().AmbientColor()); + out->mMetaData->Set(11, "FrameRate", (int)doc.GlobalSettings().TimeMode()); + out->mMetaData->Set(12, "TimeSpanStart", doc.GlobalSettings().TimeSpanStart()); + out->mMetaData->Set(13, "TimeSpanStop", doc.GlobalSettings().TimeSpanStop()); + out->mMetaData->Set(14, "CustomFrameRate", doc.GlobalSettings().CustomFrameRate()); + } + + void FBXConverter::TransferDataToScene() + { + 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 + // confusion why this code works. + + if (meshes.size()) { + out->mMeshes = new aiMesh*[meshes.size()](); + out->mNumMeshes = static_cast(meshes.size()); + + std::swap_ranges(meshes.begin(), meshes.end(), out->mMeshes); + } + + if (materials.size()) { + out->mMaterials = new aiMaterial*[materials.size()](); + out->mNumMaterials = static_cast(materials.size()); + + std::swap_ranges(materials.begin(), materials.end(), out->mMaterials); + } + + if (animations.size()) { + out->mAnimations = new aiAnimation*[animations.size()](); + out->mNumAnimations = static_cast(animations.size()); + + std::swap_ranges(animations.begin(), animations.end(), out->mAnimations); + } + + if (lights.size()) { + out->mLights = new aiLight*[lights.size()](); + out->mNumLights = static_cast(lights.size()); + + std::swap_ranges(lights.begin(), lights.end(), out->mLights); + } + + if (cameras.size()) { + out->mCameras = new aiCamera*[cameras.size()](); + out->mNumCameras = static_cast(cameras.size()); + + std::swap_ranges(cameras.begin(), cameras.end(), out->mCameras); + } + + if (textures.size()) { + out->mTextures = new aiTexture*[textures.size()](); + out->mNumTextures = static_cast(textures.size()); + + std::swap_ranges(textures.begin(), textures.end(), out->mTextures); + } + } + + // ------------------------------------------------------------------------------------------------ + void ConvertToAssimpScene(aiScene* out, const Document& doc) + { + FBXConverter converter(out, doc); + } + + } // !FBX } // !Assimp #endif diff --git a/code/FBXConverter.h b/code/FBXConverter.h index ca8dcba2e..039422839 100644 --- a/code/FBXConverter.h +++ b/code/FBXConverter.h @@ -63,6 +63,12 @@ struct aiScene; struct aiNode; struct aiMaterial; +struct morphKeyData { + std::vector values; + std::vector weights; +}; +typedef std::map morphAnimData; + namespace Assimp { namespace FBX { @@ -272,6 +278,7 @@ private: // the function is guaranteed to provide consistent results over multiple invocations // UNLESS RenameNode() is called for a particular node name. std::string FixNodeName(const std::string& name); + std::string FixAnimMeshName(const std::string& name); typedef std::map LayerMap; @@ -281,6 +288,9 @@ private: // ------------------------------------------------------------------------------------------------ void ConvertAnimationStack(const AnimationStack& st); + // ------------------------------------------------------------------------------------------------ + void ProcessMorphAnimDatas(std::map* morphAnimDatas, const BlendShapeChannel* bsc, const AnimationCurveNode* node); + // ------------------------------------------------------------------------------------------------ void GenerateNodeAnimations(std::vector& node_anims, const std::string& fixed_name, diff --git a/code/FBXDeformer.cpp b/code/FBXDeformer.cpp index 9c7c7a4c4..fc8b38e57 100644 --- a/code/FBXDeformer.cpp +++ b/code/FBXDeformer.cpp @@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXParser.h" #include "FBXDocument.h" +#include "FBXMeshGeometry.h" #include "FBXImporter.h" #include "FBXDocumentUtil.h" @@ -158,9 +159,55 @@ Skin::~Skin() { } +// ------------------------------------------------------------------------------------------------ +BlendShape::BlendShape(uint64_t id, const Element& element, const Document& doc, const std::string& name) + : Deformer(id, element, doc, name) +{ + const std::vector& conns = doc.GetConnectionsByDestinationSequenced(ID(), "Deformer"); + blendShapeChannels.reserve(conns.size()); + for (const Connection* con : conns) { + const BlendShapeChannel* const bspc = ProcessSimpleConnection(*con, false, "BlendShapeChannel -> BlendShape", element); + if (bspc) { + blendShapeChannels.push_back(bspc); + continue; + } + } +} +// ------------------------------------------------------------------------------------------------ +BlendShape::~BlendShape() +{ } +// ------------------------------------------------------------------------------------------------ +BlendShapeChannel::BlendShapeChannel(uint64_t id, const Element& element, const Document& doc, const std::string& name) + : Deformer(id, element, doc, name) +{ + const Scope& sc = GetRequiredScope(element); + const Element* const DeformPercent = sc["DeformPercent"]; + if (DeformPercent) { + percent = ParseTokenAsFloat(GetRequiredToken(*DeformPercent, 0)); + } + const Element* const FullWeights = sc["FullWeights"]; + if (FullWeights) { + ParseVectorDataArray(fullWeights, *FullWeights); + } + const std::vector& conns = doc.GetConnectionsByDestinationSequenced(ID(), "Geometry"); + shapeGeometries.reserve(conns.size()); + for (const Connection* con : conns) { + const ShapeGeometry* const sg = ProcessSimpleConnection(*con, false, "Shape -> BlendShapeChannel", element); + if (sg) { + shapeGeometries.push_back(sg); + continue; + } + } } +// ------------------------------------------------------------------------------------------------ +BlendShapeChannel::~BlendShapeChannel() +{ +} +// ------------------------------------------------------------------------------------------------ +} +} #endif diff --git a/code/FBXDocument.cpp b/code/FBXDocument.cpp index f53ae4405..29bc052da 100644 --- a/code/FBXDocument.cpp +++ b/code/FBXDocument.cpp @@ -146,6 +146,9 @@ const Object* LazyObject::Get(bool dieOnError) if (!strcmp(classtag.c_str(),"Mesh")) { object.reset(new MeshGeometry(id,element,name,doc)); } + if (!strcmp(classtag.c_str(), "Shape")) { + object.reset(new ShapeGeometry(id, element, name, doc)); + } } else if (!strncmp(obtype,"NodeAttribute",length)) { if (!strcmp(classtag.c_str(),"Camera")) { @@ -171,6 +174,12 @@ const Object* LazyObject::Get(bool dieOnError) else if (!strcmp(classtag.c_str(),"Skin")) { object.reset(new Skin(id,element,doc,name)); } + else if (!strcmp(classtag.c_str(), "BlendShape")) { + object.reset(new BlendShape(id, element, doc, name)); + } + else if (!strcmp(classtag.c_str(), "BlendShapeChannel")) { + object.reset(new BlendShapeChannel(id, element, doc, name)); + } } else if ( !strncmp( obtype, "Model", length ) ) { // FK and IK effectors are not supported diff --git a/code/FBXDocument.h b/code/FBXDocument.h index 654f5bfa8..a7d81cf0a 100644 --- a/code/FBXDocument.h +++ b/code/FBXDocument.h @@ -65,6 +65,7 @@ struct ImportSettings; class PropertyTable; class Document; class Material; +class ShapeGeometry; class Geometry; class Video; @@ -74,6 +75,8 @@ class AnimationCurveNode; class AnimationLayer; class AnimationStack; +class BlendShapeChannel; +class BlendShape; class Skin; class Cluster; @@ -869,6 +872,46 @@ private: typedef std::vector WeightArray; typedef std::vector WeightIndexArray; + +/** DOM class for BlendShapeChannel deformers */ +class BlendShapeChannel : public Deformer +{ +public: + BlendShapeChannel(uint64_t id, const Element& element, const Document& doc, const std::string& name); + virtual ~BlendShapeChannel(); + + float DeformPercent() const { + return percent; + } + + const WeightArray& GetFullWeights() const { + return fullWeights; + } + + const std::vector& GetShapeGeometries() const { + return shapeGeometries; + } +private: + float percent; + WeightArray fullWeights; + std::vector shapeGeometries; +}; + +/** DOM class for BlendShape deformers */ +class BlendShape : public Deformer +{ +public: + BlendShape(uint64_t id, const Element& element, const Document& doc, const std::string& name); + virtual ~BlendShape(); + + const std::vector& BlendShapeChannels() const { + return blendShapeChannels; + } + +private: + std::vector blendShapeChannels; +}; + /** DOM class for skin deformer clusters (aka subdeformers) */ class Cluster : public Deformer { diff --git a/code/FBXMeshGeometry.cpp b/code/FBXMeshGeometry.cpp index aa794d4df..aa60ee184 100644 --- a/code/FBXMeshGeometry.cpp +++ b/code/FBXMeshGeometry.cpp @@ -62,7 +62,7 @@ using namespace Util; // ------------------------------------------------------------------------------------------------ Geometry::Geometry(uint64_t id, const Element& element, const std::string& name, const Document& doc) - : Object(id, element,name) + : Object(id, element, name) , skin() { const std::vector& conns = doc.GetConnectionsByDestinationSequenced(ID(),"Deformer"); @@ -70,18 +70,26 @@ Geometry::Geometry(uint64_t id, const Element& element, const std::string& name, const Skin* const sk = ProcessSimpleConnection(*con, false, "Skin -> Geometry", element); if(sk) { skin = sk; - break; + } + const BlendShape* const bsp = ProcessSimpleConnection(*con, false, "BlendShape -> Geometry", element); + if (bsp) { + blendShapes.push_back(bsp); } } } - // ------------------------------------------------------------------------------------------------ Geometry::~Geometry() { // empty } +// ------------------------------------------------------------------------------------------------ +const std::vector& Geometry::GetBlendShapes() const { + return blendShapes; +} + +// ------------------------------------------------------------------------------------------------ const Skin* Geometry::DeformerSkin() const { return skin; } @@ -232,7 +240,6 @@ const std::vector& MeshGeometry::GetVertexColors( unsigned int index const MatIndexArray& MeshGeometry::GetMaterialIndices() const { return m_materials; } - // ------------------------------------------------------------------------------------------------ const unsigned int* MeshGeometry::ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const { if ( in_index >= m_mapping_counts.size() ) { @@ -640,9 +647,39 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector& materials_out, cons << MappingInformationType << "," << ReferenceInformationType); } } +// ------------------------------------------------------------------------------------------------ +ShapeGeometry::ShapeGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc) + : Geometry(id, element, name, doc) +{ + const Scope* sc = element.Compound(); + if (!sc) { + DOMError("failed to read Geometry object (class: Shape), no data scope found"); + } + const Element& Indexes = GetRequiredElement(*sc, "Indexes", &element); + const Element& Normals = GetRequiredElement(*sc, "Normals", &element); + const Element& Vertices = GetRequiredElement(*sc, "Vertices", &element); + ParseVectorDataArray(m_indices, Indexes); + ParseVectorDataArray(m_vertices, Vertices); + ParseVectorDataArray(m_normals, Normals); +} +// ------------------------------------------------------------------------------------------------ +ShapeGeometry::~ShapeGeometry() { + // empty +} +// ------------------------------------------------------------------------------------------------ +const std::vector& ShapeGeometry::GetVertices() const { + return m_vertices; +} +// ------------------------------------------------------------------------------------------------ +const std::vector& ShapeGeometry::GetNormals() const { + return m_normals; +} +// ------------------------------------------------------------------------------------------------ +const std::vector& ShapeGeometry::GetIndices() const { + return m_indices; +} } // !FBX } // !Assimp - #endif diff --git a/code/FBXMeshGeometry.h b/code/FBXMeshGeometry.h index acd44668a..3e10d73d3 100644 --- a/code/FBXMeshGeometry.h +++ b/code/FBXMeshGeometry.h @@ -64,8 +64,13 @@ public: /** Get the Skin attached to this geometry or NULL */ const Skin* DeformerSkin() const; + /** Get the BlendShape attached to this geometry or NULL */ + const std::vector& GetBlendShapes() const; + private: const Skin* skin; + std::vector blendShapes; + }; typedef std::vector MatIndexArray; @@ -125,7 +130,6 @@ public: /** Determine the face to which a particular output vertex index belongs. * This mapping is always unique. */ unsigned int FaceForVertexIndex( unsigned int in_index ) const; - private: void ReadLayer( const Scope& layer ); void ReadLayerElement( const Scope& layerElement ); @@ -174,6 +178,34 @@ private: std::vector m_mappings; }; +/** +* DOM class for FBX geometry of type "Shape" +*/ +class ShapeGeometry : public Geometry +{ +public: + /** The class constructor */ + ShapeGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc); + + /** The class destructor */ + virtual ~ShapeGeometry(); + + /** Get a list of all vertex points, non-unique*/ + const std::vector& GetVertices() const; + + /** Get a list of all vertex normals or an empty array if + * no normals are specified. */ + const std::vector& GetNormals() const; + + /** Return list of vertex indices. */ + const std::vector& GetIndices() const; + +private: + std::vector m_vertices; + std::vector m_normals; + std::vector m_indices; +}; + } } diff --git a/code/Importer/IFC/IFCLoader.cpp b/code/Importer/IFC/IFCLoader.cpp index 97c514d44..0b423a4cd 100644 --- a/code/Importer/IFC/IFCLoader.cpp +++ b/code/Importer/IFC/IFCLoader.cpp @@ -207,10 +207,21 @@ void IFCImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS } uint8_t* buff = new uint8_t[fileInfo.uncompressed_size]; LogInfo("Decompressing IFCZIP file"); - unzOpenCurrentFile( zip ); - const int ret = unzReadCurrentFile( zip, buff, fileInfo.uncompressed_size); + unzOpenCurrentFile(zip); + size_t total = 0; + int read = 0; + do { + int bufferSize = fileInfo.uncompressed_size < INT16_MAX ? fileInfo.uncompressed_size : INT16_MAX; + void* buffer = malloc(bufferSize); + read = unzReadCurrentFile(zip, buffer, bufferSize); + if (read > 0) { + memcpy((char*)buff + total, buffer, read); + total += read; + } + free(buffer); + } while (read > 0); size_t filesize = fileInfo.uncompressed_size; - if ( ret < 0 || size_t(ret) != filesize ) + if (total < 0 || size_t(total) != filesize) { delete[] buff; ThrowException("Failed to decompress IFC ZIP file"); diff --git a/code/ObjFileParser.cpp b/code/ObjFileParser.cpp index 7630127fa..62d2ad46a 100644 --- a/code/ObjFileParser.cpp +++ b/code/ObjFileParser.cpp @@ -119,7 +119,7 @@ void ObjFileParser::parseFile( IOStreamBuffer &streamBuffer ) { size_t lastFilePos( 0 ); std::vector buffer; - while ( streamBuffer.getNextDataLine( buffer, '\\' ) ) { + while ( streamBuffer.getNextDataLine( buffer, '\0' ) ) { m_DataIt = buffer.begin(); m_DataItEnd = buffer.end(); diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 20c28f498..c73e1eabb 100755 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -438,13 +438,16 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r) } } - for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) { - if (!attr.texcoord[tc]) { - DefaultLogger::get()->warn("NULL texcoord encountered in mesh \"" + mesh.name + - "\" and will be ignored"); + for (size_t c = 0; c < attr.color.size() && c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c) { + if (attr.color[c]->count != aim->mNumVertices) { + DefaultLogger::get()->warn("Color stream size in mesh \"" + mesh.name + + "\" does not match the vertex count"); continue; } - + aim->mColors[c] = new aiColor4D[attr.color[c]->count]; + attr.color[c]->ExtractData(aim->mColors[c]); + } + for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) { if (attr.texcoord[tc]->count != aim->mNumVertices) { DefaultLogger::get()->warn("Texcoord stream size in mesh \"" + mesh.name + "\" does not match the vertex count"); diff --git a/include/assimp/IOStreamBuffer.h b/include/assimp/IOStreamBuffer.h index c93a191df..be5e4d0c5 100644 --- a/include/assimp/IOStreamBuffer.h +++ b/include/assimp/IOStreamBuffer.h @@ -243,7 +243,7 @@ template inline bool IOStreamBuffer::getNextDataLine( std::vector &buffer, T continuationToken ) { buffer.resize( m_cacheSize ); - if ( m_cachePos == m_cacheSize || 0 == m_filePos ) { + if ( m_cachePos >= m_cacheSize || 0 == m_filePos ) { if ( !readNextBlock() ) { return false; } @@ -273,6 +273,9 @@ bool IOStreamBuffer::getNextDataLine( std::vector &buffer, T continuationT buffer[ i ] = m_cache[ m_cachePos ]; ++m_cachePos; ++i; + if (m_cachePos >= size()) { + break; + } if ( m_cachePos >= m_cacheSize ) { if ( !readNextBlock() ) { return false; diff --git a/include/assimp/mesh.h b/include/assimp/mesh.h index f47d5fd00..f9c2c1e67 100644 --- a/include/assimp/mesh.h +++ b/include/assimp/mesh.h @@ -402,7 +402,7 @@ enum aiPrimitiveType // --------------------------------------------------------------------------- -/** @brief NOT CURRENTLY IN USE. An AnimMesh is an attachment to an #aiMesh stores per-vertex +/** @brief An AnimMesh is an attachment to an #aiMesh stores per-vertex * animations for a particular frame. * * You may think of an #aiAnimMesh as a `patch` for the host mesh, which @@ -414,6 +414,9 @@ enum aiPrimitiveType */ struct aiAnimMesh { + /**Anim Mesh name */ + C_STRUCT aiString mName; + /** Replacement for aiMesh::mVertices. If this array is non-NULL, * it *must* contain mNumVertices entries. The corresponding * array in the host mesh must be non-NULL as well - animation From f170c842263b0d3ddd3d92e4445175ec9a6ae6dd Mon Sep 17 00:00:00 2001 From: rickomax Date: Sun, 6 Jan 2019 19:38:29 -0200 Subject: [PATCH 107/472] Test fixes Test fixes --- code/FBXConverter.cpp | 2 +- code/Importer/IFC/IFCLoader.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index cd9ad0966..b14bbfe98 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -3208,7 +3208,7 @@ namespace Assimp { out->mMetaData->Set(5, "CoordAxisSign", doc.GlobalSettings().CoordAxisSign()); out->mMetaData->Set(6, "OriginalUpAxis", doc.GlobalSettings().OriginalUpAxis()); out->mMetaData->Set(7, "OriginalUpAxisSign", doc.GlobalSettings().OriginalUpAxisSign()); - out->mMetaData->Set(8, "UnitScaleFactor", doc.GlobalSettings().UnitScaleFactor()); + out->mMetaData->Set(8, "UnitScaleFactor", (double)doc.GlobalSettings().UnitScaleFactor()); out->mMetaData->Set(9, "OriginalUnitScaleFactor", doc.GlobalSettings().OriginalUnitScaleFactor()); out->mMetaData->Set(10, "AmbientColor", doc.GlobalSettings().AmbientColor()); out->mMetaData->Set(11, "FrameRate", (int)doc.GlobalSettings().TimeMode()); diff --git a/code/Importer/IFC/IFCLoader.cpp b/code/Importer/IFC/IFCLoader.cpp index 0b423a4cd..2c95872d3 100644 --- a/code/Importer/IFC/IFCLoader.cpp +++ b/code/Importer/IFC/IFCLoader.cpp @@ -221,7 +221,7 @@ void IFCImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS free(buffer); } while (read > 0); size_t filesize = fileInfo.uncompressed_size; - if (total < 0 || size_t(total) != filesize) + if (total == 0 || size_t(total) != filesize) { delete[] buff; ThrowException("Failed to decompress IFC ZIP file"); From e06b1d0de23af83c2801b25c422f4a80e29a67f4 Mon Sep 17 00:00:00 2001 From: Marc Kurtz Date: Tue, 8 Jan 2019 11:16:41 -0500 Subject: [PATCH 108/472] Change access of getData() to package-private for access in JaiDebug. Move private field to fix compile error. --- port/jassimp/jassimp/src/jassimp/AiMaterial.java | 2 +- port/jassimp/jassimp/src/jassimp/AiSceneFlag.java | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/port/jassimp/jassimp/src/jassimp/AiMaterial.java b/port/jassimp/jassimp/src/jassimp/AiMaterial.java index bf077dff3..77a15a455 100644 --- a/port/jassimp/jassimp/src/jassimp/AiMaterial.java +++ b/port/jassimp/jassimp/src/jassimp/AiMaterial.java @@ -457,7 +457,7 @@ public final class AiMaterial { * * @return the data */ - private Object getData() { + Object getData() { return m_data; } } diff --git a/port/jassimp/jassimp/src/jassimp/AiSceneFlag.java b/port/jassimp/jassimp/src/jassimp/AiSceneFlag.java index 4c7dd6072..af3ee5d5f 100644 --- a/port/jassimp/jassimp/src/jassimp/AiSceneFlag.java +++ b/port/jassimp/jassimp/src/jassimp/AiSceneFlag.java @@ -47,11 +47,6 @@ import java.util.Set; * Status flags for {@link AiScene}s. */ public enum AiSceneFlag { - /** - * The mapped c/c++ integer enum value. - */ - private final int m_rawValue; - /** * Specifies that the scene data structure that was imported is not * complete.

    @@ -119,8 +114,12 @@ public enum AiSceneFlag { * you actually need to render it). */ TERRAIN(0x10); - - + + /** + * The mapped c/c++ integer enum value. + */ + private final int m_rawValue; + /** * Utility method for converting from c/c++ based integer enums to java * enums.

    From d2f6c6d65e3412406ea0cde7eacdcb7684f5e987 Mon Sep 17 00:00:00 2001 From: Marc Kurtz Date: Tue, 8 Jan 2019 11:17:11 -0500 Subject: [PATCH 109/472] Add ProgressHandler support. --- port/jassimp/jassimp-native/src/jassimp.cpp | 28 ++++++++++- port/jassimp/jassimp-native/src/jassimp.h | 2 +- .../src/jassimp/AiProgressHandler.java | 46 +++++++++++++++++++ port/jassimp/jassimp/src/jassimp/Jassimp.java | 28 ++++++++--- 4 files changed, 95 insertions(+), 9 deletions(-) create mode 100644 port/jassimp/jassimp/src/jassimp/AiProgressHandler.java diff --git a/port/jassimp/jassimp-native/src/jassimp.cpp b/port/jassimp/jassimp-native/src/jassimp.cpp index 070dbc95d..0cf01b1e3 100644 --- a/port/jassimp/jassimp-native/src/jassimp.cpp +++ b/port/jassimp/jassimp-native/src/jassimp.cpp @@ -1,6 +1,7 @@ #include "jassimp.h" #include +#include #include #include #include @@ -248,7 +249,7 @@ static bool call(JNIEnv *env, jobject object, const char* typeName, const char* return false; } - jboolean jReturnValue = env->CallBooleanMethod(object, mid, params[0].l); + jboolean jReturnValue = env->CallBooleanMethodA(object, mid, params); return (bool)jReturnValue; } @@ -591,6 +592,24 @@ class JavaIOSystem : public Assimp::IOSystem { }; +class JavaProgressHandler : public Assimp::ProgressHandler { + private: + JNIEnv* mJniEnv; + jobject& mJavaProgressHandler; + + public: + JavaProgressHandler(JNIEnv* env, jobject& javaProgressHandler) : + mJniEnv(env), + mJavaProgressHandler(javaProgressHandler) + {}; + + bool Update(float percentage) + { + jvalue params[1]; + params[0].f = percentage; + return call(mJniEnv, mJavaProgressHandler, "jassimp/AiProgressHandler", "update", "(F)Z", params); + } +}; static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene) { @@ -1880,7 +1899,7 @@ JNIEXPORT jstring JNICALL Java_jassimp_Jassimp_getErrorString JNIEXPORT jobject JNICALL Java_jassimp_Jassimp_aiImportFile - (JNIEnv *env, jclass jClazz, jstring jFilename, jlong postProcess, jobject ioSystem) + (JNIEnv *env, jclass jClazz, jstring jFilename, jlong postProcess, jobject ioSystem, jobject progressHandler) { jobject jScene = NULL; @@ -1896,6 +1915,11 @@ JNIEXPORT jobject JNICALL Java_jassimp_Jassimp_aiImportFile lprintf("Created aiFileIO\n"); } + if(progressHandler != NULL) + { + imp.SetProgressHandler(new JavaProgressHandler(env, progressHandler)); + } + lprintf("opening file: %s\n", cFilename); /* do import */ diff --git a/port/jassimp/jassimp-native/src/jassimp.h b/port/jassimp/jassimp-native/src/jassimp.h index 7d4b66e29..2a4a84538 100644 --- a/port/jassimp/jassimp-native/src/jassimp.h +++ b/port/jassimp/jassimp-native/src/jassimp.h @@ -39,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, jobject); + (JNIEnv *, jclass, jstring, jlong, jobject, jobject); #ifdef __cplusplus } diff --git a/port/jassimp/jassimp/src/jassimp/AiProgressHandler.java b/port/jassimp/jassimp/src/jassimp/AiProgressHandler.java new file mode 100644 index 000000000..5512942d9 --- /dev/null +++ b/port/jassimp/jassimp/src/jassimp/AiProgressHandler.java @@ -0,0 +1,46 @@ +/* +--------------------------------------------------------------------------- +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; + +public interface AiProgressHandler +{ + boolean update(float percentage); +} \ No newline at end of file diff --git a/port/jassimp/jassimp/src/jassimp/Jassimp.java b/port/jassimp/jassimp/src/jassimp/Jassimp.java index 727570a5b..c33f95c0a 100644 --- a/port/jassimp/jassimp/src/jassimp/Jassimp.java +++ b/port/jassimp/jassimp/src/jassimp/Jassimp.java @@ -68,8 +68,9 @@ public final class Jassimp { * @return the loaded scene, or null if an error occurred * @throws IOException if an error occurs */ - private static native AiScene aiImportFile(String filename, - long postProcessing, AiIOSystem ioSystem) throws IOException; + private static native AiScene aiImportFile(String filename, + long postProcessing, AiIOSystem ioSystem, + AiProgressHandler progressHandler) throws IOException; /** @@ -158,11 +159,26 @@ public final class Jassimp { public static AiScene importFile(String filename, Set postProcessing, AiIOSystem ioSystem) throws IOException { - - loadLibrary(); - + return importFile(filename, postProcessing, ioSystem, 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, + AiProgressHandler progressHandler) throws IOException { + + loadLibrary(); + return aiImportFile(filename, AiPostProcessSteps.toRawValue( - postProcessing), ioSystem); + postProcessing), ioSystem, progressHandler); } From f384d1221a160c6abe892fea01e3db3e9f78d14a Mon Sep 17 00:00:00 2001 From: Marc Kurtz Date: Tue, 8 Jan 2019 13:55:07 -0500 Subject: [PATCH 110/472] Make this public for JaiDebug and to pass quality checks. --- port/jassimp/jassimp/src/jassimp/AiMaterial.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/port/jassimp/jassimp/src/jassimp/AiMaterial.java b/port/jassimp/jassimp/src/jassimp/AiMaterial.java index 77a15a455..8582d881a 100644 --- a/port/jassimp/jassimp/src/jassimp/AiMaterial.java +++ b/port/jassimp/jassimp/src/jassimp/AiMaterial.java @@ -457,7 +457,7 @@ public final class AiMaterial { * * @return the data */ - Object getData() { + public Object getData() { return m_data; } } From e37a4de2c218240e5705524ab8b05521e3034131 Mon Sep 17 00:00:00 2001 From: Marc Kurtz Date: Tue, 8 Jan 2019 15:56:20 -0500 Subject: [PATCH 111/472] Fix progress reporting in ObjFileParser. Remove old unused code which is claiming to still take up "1/3" of the total progress. --- code/ObjFileImporter.cpp | 32 -------------------------------- code/ObjFileParser.cpp | 7 +++---- 2 files changed, 3 insertions(+), 36 deletions(-) diff --git a/code/ObjFileImporter.cpp b/code/ObjFileImporter.cpp index 6fd48cfa1..93b2de6f4 100644 --- a/code/ObjFileImporter.cpp +++ b/code/ObjFileImporter.cpp @@ -144,38 +144,6 @@ void ObjFileImporter::InternReadFile( const std::string &file, aiScene* pScene, modelName = file; } - // This next stage takes ~ 1/3th of the total readFile task - // so should amount for 1/3th of the progress - // only update every 100KB or it'll be too slow - /*unsigned int progress = 0; - unsigned int progressCounter = 0; - const unsigned int updateProgressEveryBytes = 100 * 1024; - const unsigned int progressTotal = static_cast(3*m_Buffer.size()/updateProgressEveryBytes);*/ - // process all '\' - /*std::vector ::iterator iter = m_Buffer.begin(); - while (iter != m_Buffer.end()) - { - if (*iter == '\\') - { - // remove '\' - iter = m_Buffer.erase(iter); - // remove next character - while (*iter == '\r' || *iter == '\n') - iter = m_Buffer.erase(iter); - } - else - ++iter; - - if (++progressCounter >= updateProgressEveryBytes) - { - m_progress->UpdateFileRead(++progress, progressTotal); - progressCounter = 0; - } - }*/ - - // 1/3rd progress - m_progress->UpdateFileRead(1, 3); - // parse the file into a temporary representation ObjFileParser parser( streamedBuffer, modelName, pIOHandler, m_progress, file); diff --git a/code/ObjFileParser.cpp b/code/ObjFileParser.cpp index 7630127fa..6b0815a99 100644 --- a/code/ObjFileParser.cpp +++ b/code/ObjFileParser.cpp @@ -113,8 +113,7 @@ void ObjFileParser::parseFile( IOStreamBuffer &streamBuffer ) { //const unsigned int updateProgressEveryBytes = 100 * 1024; unsigned int progressCounter = 0; const unsigned int bytesToProcess = static_cast(streamBuffer.size()); - const unsigned int progressTotal = 3 * bytesToProcess; - const unsigned int progressOffset = bytesToProcess; + const unsigned int progressTotal = bytesToProcess; unsigned int processed = 0; size_t lastFilePos( 0 ); @@ -126,10 +125,10 @@ void ObjFileParser::parseFile( IOStreamBuffer &streamBuffer ) { // Handle progress reporting const size_t filePos( streamBuffer.getFilePos() ); if ( lastFilePos < filePos ) { - processed += static_cast(filePos); + processed = static_cast(filePos); lastFilePos = filePos; progressCounter++; - m_progress->UpdateFileRead( progressOffset + processed * 2, progressTotal ); + m_progress->UpdateFileRead( processed, progressTotal ); } // parse line From fe6b3166953fd2fe8611fbfd8d4122297ed78cb9 Mon Sep 17 00:00:00 2001 From: Richard Date: Thu, 10 Jan 2019 17:27:54 +0000 Subject: [PATCH 112/472] Set MSVC projects to default to Unicode MBCS is deprecated and shouldn't be used in new projects --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index a97174de4..9f9327a93 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -133,6 +133,8 @@ IF(MSVC) "Install MSVC debug files." ON ) + # Multibyte character set is deprecated, but default + ADD_DEFINITIONS( -DUNICODE -D_UNICODE ) ENDIF(MSVC) IF (BUILD_FRAMEWORK) From 3a3340b9260a09046d0041b8345eca11c7873c56 Mon Sep 17 00:00:00 2001 From: SchroerDev <46781125+SchroerDev@users.noreply.github.com> Date: Thu, 17 Jan 2019 12:26:22 +0100 Subject: [PATCH 113/472] add FBX Line Element support add FBX Line Element support --- code/FBXConverter.cpp | 56 +++++++++++++++++++++++++++++++++++++++- code/FBXConverter.h | 9 +++++-- code/FBXDocument.cpp | 3 +++ code/FBXDocument.h | 1 + code/FBXMeshGeometry.cpp | 26 +++++++++++++++++++ code/FBXMeshGeometry.h | 22 ++++++++++++++++ 6 files changed, 114 insertions(+), 3 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index b14bbfe98..6070465d5 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -870,10 +870,15 @@ namespace Assimp { for (const Geometry* geo : geos) { const MeshGeometry* const mesh = dynamic_cast(geo); + const LineGeometry* const line = dynamic_cast(geo); if (mesh) { const std::vector& indices = ConvertMesh(*mesh, model, node_global_transform, nd); std::copy(indices.begin(), indices.end(), std::back_inserter(meshes)); } + else if (line) { + const std::vector& indices = ConvertLine(*line, model, node_global_transform, nd); + std::copy(indices.begin(), indices.end(), std::back_inserter(meshes)); + } else { FBXImporter::LogWarn("ignoring unrecognized geometry: " + geo->Name()); } @@ -922,7 +927,52 @@ namespace Assimp { return temp; } - aiMesh* FBXConverter::SetupEmptyMesh(const MeshGeometry& mesh, aiNode& nd) + std::vector FBXConverter::ConvertLine(const LineGeometry& line, const Model& model, + const aiMatrix4x4& node_global_transform, aiNode& nd) + { + std::vector temp; + + const std::vector& vertices = line.GetVertices(); + const std::vector& indices = line.GetIndices(); + if (vertices.empty() || indices.empty()) { + FBXImporter::LogWarn("ignoring empty line: " + line.Name()); + return temp; + } + + aiMesh* const out_mesh = SetupEmptyMesh(line, nd); + out_mesh->mPrimitiveTypes |= aiPrimitiveType_LINE; + + // copy vertices + out_mesh->mNumVertices = static_cast(vertices.size()); + out_mesh->mVertices = new aiVector3D[out_mesh->mNumVertices]; + std::copy(vertices.begin(), vertices.end(), out_mesh->mVertices); + + //Number of line segments (faces) is "Number of Points - Number of Endpoints" + //N.B.: Endpoints in FbxLine are denoted by negative indices. + //If such an Index is encountered, add 1 and multiply by -1 to get the real index. + unsigned int epcount = 0; + for (unsigned i = 0; i < indices.size(); i++) + { + if (indices[i] < 0) epcount++; + } + unsigned int pcount = indices.size(); + unsigned int scount = out_mesh->mNumFaces = pcount - epcount; + + aiFace* fac = out_mesh->mFaces = new aiFace[scount](); + for (unsigned int i = 0; i < pcount; ++i) { + if (indices[i] < 0) continue; + aiFace& f = *fac++; + f.mNumIndices = 2; //2 == aiPrimitiveType_LINE + f.mIndices = new unsigned int[2]; + f.mIndices[0] = indices[i]; + int segid = indices[(i + 1 == pcount ? 0 : i + 1)]; //If we have reached he last point, wrap around + f.mIndices[1] = (segid < 0 ? (segid + 1)*-1 : segid); //Convert EndPoint Index to normal Index + } + temp.push_back(static_cast(meshes.size() - 1)); + return temp; + } + + aiMesh* FBXConverter::SetupEmptyMesh(const Geometry& mesh, aiNode& nd) { aiMesh* const out_mesh = new aiMesh(); meshes.push_back(out_mesh); @@ -957,6 +1007,10 @@ namespace Assimp { // copy vertices out_mesh->mNumVertices = static_cast(vertices.size()); out_mesh->mVertices = new aiVector3D[vertices.size()]; + // for (unsigned int i = 0; i < vertices.size(); i++) + // { + // aiMatrix4x4::Translation(vertices[i], nd); + // } std::copy(vertices.begin(), vertices.end(), out_mesh->mVertices); // generate dummy faces diff --git a/code/FBXConverter.h b/code/FBXConverter.h index 039422839..2d1278373 100644 --- a/code/FBXConverter.h +++ b/code/FBXConverter.h @@ -174,14 +174,18 @@ private: // ------------------------------------------------------------------------------------------------ void ConvertModel(const Model& model, aiNode& nd, const aiMatrix4x4& node_global_transform); - + // ------------------------------------------------------------------------------------------------ // MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed std::vector ConvertMesh(const MeshGeometry& mesh, const Model& model, const aiMatrix4x4& node_global_transform, aiNode& nd); // ------------------------------------------------------------------------------------------------ - aiMesh* SetupEmptyMesh(const MeshGeometry& mesh, aiNode& nd); + std::vector ConvertLine(const LineGeometry& line, const Model& model, + const aiMatrix4x4& node_global_transform, aiNode& nd); + + // ------------------------------------------------------------------------------------------------ + aiMesh* SetupEmptyMesh(const Geometry& mesh, aiNode& nd); // ------------------------------------------------------------------------------------------------ unsigned int ConvertMeshSingleMaterial(const MeshGeometry& mesh, const Model& model, @@ -424,6 +428,7 @@ private: std::vector lights; std::vector cameras; std::vector textures; + typedef std::map MaterialMap; MaterialMap materials_converted; diff --git a/code/FBXDocument.cpp b/code/FBXDocument.cpp index 29bc052da..deac89ca0 100644 --- a/code/FBXDocument.cpp +++ b/code/FBXDocument.cpp @@ -149,6 +149,9 @@ const Object* LazyObject::Get(bool dieOnError) if (!strcmp(classtag.c_str(), "Shape")) { object.reset(new ShapeGeometry(id, element, name, doc)); } + if (!strcmp(classtag.c_str(), "Line")) { + object.reset(new LineGeometry(id, element, name, doc)); + } } else if (!strncmp(obtype,"NodeAttribute",length)) { if (!strcmp(classtag.c_str(),"Camera")) { diff --git a/code/FBXDocument.h b/code/FBXDocument.h index a7d81cf0a..02accf92e 100644 --- a/code/FBXDocument.h +++ b/code/FBXDocument.h @@ -66,6 +66,7 @@ class PropertyTable; class Document; class Material; class ShapeGeometry; +class LineGeometry; class Geometry; class Video; diff --git a/code/FBXMeshGeometry.cpp b/code/FBXMeshGeometry.cpp index aa60ee184..faa5de75c 100644 --- a/code/FBXMeshGeometry.cpp +++ b/code/FBXMeshGeometry.cpp @@ -679,6 +679,32 @@ const std::vector& ShapeGeometry::GetNormals() const { const std::vector& ShapeGeometry::GetIndices() const { return m_indices; } +// ------------------------------------------------------------------------------------------------ +LineGeometry::LineGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc) + : Geometry(id, element, name, doc) +{ + const Scope* sc = element.Compound(); + if (!sc) { + DOMError("failed to read Geometry object (class: Line), no data scope found"); + } + const Element& Points = GetRequiredElement(*sc, "Points", &element); + const Element& PointsIndex = GetRequiredElement(*sc, "PointsIndex", &element); + ParseVectorDataArray(m_vertices, Points); + ParseVectorDataArray(m_indices, PointsIndex); +} + +// ------------------------------------------------------------------------------------------------ +LineGeometry::~LineGeometry() { + // empty +} +// ------------------------------------------------------------------------------------------------ +const std::vector& LineGeometry::GetVertices() const { + return m_vertices; +} +// ------------------------------------------------------------------------------------------------ +const std::vector& LineGeometry::GetIndices() const { + return m_indices; +} } // !FBX } // !Assimp #endif diff --git a/code/FBXMeshGeometry.h b/code/FBXMeshGeometry.h index 3e10d73d3..641461a69 100644 --- a/code/FBXMeshGeometry.h +++ b/code/FBXMeshGeometry.h @@ -205,6 +205,28 @@ private: std::vector m_normals; std::vector m_indices; }; +/** +* DOM class for FBX geometry of type "Line" +*/ +class LineGeometry : public Geometry +{ +public: + /** The class constructor */ + LineGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc); + + /** The class destructor */ + virtual ~LineGeometry(); + + /** Get a list of all vertex points, non-unique*/ + const std::vector& GetVertices() const; + + /** Return list of vertex indices. */ + const std::vector& GetIndices() const; + +private: + std::vector m_vertices; + std::vector m_indices; +}; } } From f7fe729c88308734efb0c9927291965ceaa548a6 Mon Sep 17 00:00:00 2001 From: SchroerDev <46781125+SchroerDev@users.noreply.github.com> Date: Thu, 17 Jan 2019 12:32:36 +0100 Subject: [PATCH 114/472] Update FBXConverter.cpp --- code/FBXConverter.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 6070465d5..14d2b2c5c 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -1007,10 +1007,7 @@ namespace Assimp { // copy vertices out_mesh->mNumVertices = static_cast(vertices.size()); out_mesh->mVertices = new aiVector3D[vertices.size()]; - // for (unsigned int i = 0; i < vertices.size(); i++) - // { - // aiMatrix4x4::Translation(vertices[i], nd); - // } + std::copy(vertices.begin(), vertices.end(), out_mesh->mVertices); // generate dummy faces From 3c651be6404c024fb70ed9b22243dea3fd3022de Mon Sep 17 00:00:00 2001 From: Richard Date: Thu, 17 Jan 2019 13:55:05 +0000 Subject: [PATCH 115/472] Exporter::ExportToBlob() Pass on preprocessing and properties. Issue #2302 --- code/Exporter.cpp | 4 ++-- include/assimp/Exporter.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/Exporter.cpp b/code/Exporter.cpp index 0acde75bf..0414f661c 100644 --- a/code/Exporter.cpp +++ b/code/Exporter.cpp @@ -288,7 +288,7 @@ void Exporter::SetProgressHandler(ProgressHandler* pHandler) { // ------------------------------------------------------------------------------------------------ const aiExportDataBlob* Exporter::ExportToBlob( const aiScene* pScene, const char* pFormatId, - unsigned int, const ExportProperties* /*pProperties*/ ) { + unsigned int pPreprocessing, const ExportProperties* pProperties) { if (pimpl->blob) { delete pimpl->blob; pimpl->blob = nullptr; @@ -298,7 +298,7 @@ const aiExportDataBlob* Exporter::ExportToBlob( const aiScene* pScene, const cha BlobIOSystem* blobio = new BlobIOSystem(); pimpl->mIOSystem = std::shared_ptr( blobio ); - if (AI_SUCCESS != Export(pScene,pFormatId,blobio->GetMagicFileName())) { + if (AI_SUCCESS != Export(pScene,pFormatId,blobio->GetMagicFileName(), pPreprocessing, pProperties)) { pimpl->mIOSystem = old; return nullptr; } diff --git a/include/assimp/Exporter.hpp b/include/assimp/Exporter.hpp index 4e0843b60..d254aae66 100644 --- a/include/assimp/Exporter.hpp +++ b/include/assimp/Exporter.hpp @@ -190,7 +190,7 @@ public: * @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* = nullptr); + unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = nullptr); const aiExportDataBlob* ExportToBlob( const aiScene* pScene, const std::string& pFormatId, unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = nullptr); From 7dc32ab9b6bf96515bd1978a5892b7cbefd964fb Mon Sep 17 00:00:00 2001 From: Merwan Achibet Date: Tue, 8 Jan 2019 22:14:45 +0100 Subject: [PATCH 116/472] Preserve all the material parameters from FBX models --- code/FBXConverter.cpp | 175 ++++++++++++++++++++++++++++++++++++++++++ code/FBXConverter.h | 1 + 2 files changed, 176 insertions(+) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index b14bbfe98..a67f171da 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -1524,6 +1524,7 @@ namespace Assimp { // shading stuff and colors SetShadingPropertiesCommon(out_mat, props); + SetShadingPropertiesRaw( out_mat, props, material.Textures(), mesh ); // texture assignments SetTextureProperties(out_mat, material.Textures(), mesh); @@ -2022,6 +2023,180 @@ namespace Assimp { const float DispFactor = PropertyGet(props, "DisplacementFactor", ok); if (ok) { out_mat->AddProperty(&DispFactor, 1, "$mat.displacementscaling", 0, 0); + } +} + + +void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTable& props, const TextureMap& textures, const MeshGeometry* const mesh) +{ + // Add all the unparsed properties with a "$raw." prefix + + const std::string prefix = "$raw."; + + for (const DirectPropertyMap::value_type& prop : props.GetUnparsedProperties()) { + + std::string name = prefix + prop.first; + + if (const TypedProperty* interpreted = prop.second->As >()) + { + out_mat->AddProperty(&interpreted->Value(), 1, name.c_str(), 0, 0); + } + else if (const TypedProperty* interpreted = prop.second->As >()) + { + out_mat->AddProperty(&interpreted->Value(), 1, name.c_str(), 0, 0); + } + else if (const TypedProperty* interpreted = prop.second->As >()) + { + out_mat->AddProperty(&interpreted->Value(), 1, name.c_str(), 0, 0); + } + else if (const TypedProperty* interpreted = prop.second->As >()) + { + out_mat->AddProperty(&interpreted->Value(), 1, name.c_str(), 0, 0); + } + else if (const TypedProperty* interpreted = prop.second->As >()) + { + out_mat->AddProperty(&interpreted->Value(), 1, name.c_str(), 0, 0); + } + else if (const TypedProperty* interpreted = prop.second->As >()) + { + int value = interpreted->Value() ? 1 : 0; + out_mat->AddProperty(&value, 1, name.c_str(), 0, 0); + } + else if (const TypedProperty* interpreted = prop.second->As >()) + { + const aiString value = aiString(interpreted->Value()); + out_mat->AddProperty(&value, name.c_str(), 0, 0); + } + } + + // Add the textures' properties + + for (TextureMap::const_iterator it = textures.begin(); it != textures.end(); it++) { + + std::string name = prefix + it->first; + + const Texture* const tex = (*it).second; + if (tex != nullptr) + { + aiString path; + path.Set(tex->RelativeFilename()); + + const Video* media = tex->Media(); + if (media != nullptr && media->ContentLength() > 0) { + 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; + } + + // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture) + path.data[0] = '*'; + path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index); + } + + out_mat->AddProperty(&path, (name + "|file").c_str(), aiTextureType_UNKNOWN, 0); + + aiUVTransform uvTrafo; + // XXX handle all kinds of UV transformations + uvTrafo.mScaling = tex->UVScaling(); + uvTrafo.mTranslation = tex->UVTranslation(); + out_mat->AddProperty(&uvTrafo, 1, (name + "|uvtrafo").c_str(), aiTextureType_UNKNOWN, 0); + + int uvIndex = 0; + + bool uvFound = false; + const std::string& uvSet = PropertyGet(tex->Props(), "UVSet", uvFound); + if (uvFound) { + // "default" is the name which usually appears in the FbxFileTexture template + if (uvSet != "default" && uvSet.length()) { + // this is a bit awkward - we need to find a mesh that uses this + // material and scan its UV channels for the given UV name because + // assimp references UV channels by index, not by name. + + // XXX: the case that UV channels may appear in different orders + // in meshes is unhandled. A possible solution would be to sort + // the UV channels alphabetically, but this would have the side + // effect that the primary (first) UV channel would sometimes + // be moved, causing trouble when users read only the first + // UV channel and ignore UV channel assignments altogether. + + std::vector::iterator materialIt = std::find(materials.begin(), materials.end(), out_mat); + const unsigned int matIndex = static_cast(std::distance(materials.begin(), materialIt)); + + uvIndex = -1; + if (!mesh) + { + for (const MeshMap::value_type& v : meshes_converted) { + const MeshGeometry* const mesh = dynamic_cast(v.first); + if (!mesh) { + continue; + } + + const MatIndexArray& mats = mesh->GetMaterialIndices(); + if (std::find(mats.begin(), mats.end(), matIndex) == mats.end()) { + continue; + } + + int index = -1; + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { + if (mesh->GetTextureCoords(i).empty()) { + break; + } + const std::string& name = mesh->GetTextureCoordChannelName(i); + if (name == uvSet) { + index = static_cast(i); + break; + } + } + if (index == -1) { + FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); + continue; + } + + if (uvIndex == -1) { + uvIndex = index; + } + else { + FBXImporter::LogWarn("the UV channel named " + uvSet + " appears at different positions in meshes, results will be wrong"); + } + } + } + else + { + int index = -1; + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { + if (mesh->GetTextureCoords(i).empty()) { + break; + } + const std::string& name = mesh->GetTextureCoordChannelName(i); + if (name == uvSet) { + index = static_cast(i); + break; + } + } + if (index == -1) { + FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); + } + + if (uvIndex == -1) { + uvIndex = index; + } + } + + if (uvIndex == -1) { + FBXImporter::LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel"); + uvIndex = 0; + } + } + } + + out_mat->AddProperty(&uvIndex, 1, (name + "|uvwsrc").c_str(), aiTextureType_UNKNOWN, 0); + } } } diff --git a/code/FBXConverter.h b/code/FBXConverter.h index 039422839..0f87038bb 100644 --- a/code/FBXConverter.h +++ b/code/FBXConverter.h @@ -264,6 +264,7 @@ private: // ------------------------------------------------------------------------------------------------ void SetShadingPropertiesCommon(aiMaterial* out_mat, const PropertyTable& props); + void SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTable& props, const TextureMap& textures, const MeshGeometry* const mesh); // ------------------------------------------------------------------------------------------------ // get the number of fps for a FrameRate enumerated value From a04b96ef66dd625121792b2ae8d7029213e87a5b Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 20 Jan 2019 20:29:23 +0100 Subject: [PATCH 117/472] Disable step. --- code/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 043599aca..b9b9c211b 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -890,7 +890,7 @@ SET( assimp_src ${PostProcessing_SRCS} ${MaterialSystem_SRCS} ${STEPParser_SRCS} - ${Step_SRCS} +# ${Step_SRCS} check if we need a different approach # Model Support ${ASSIMP_LOADER_SRCS} From 819108098687970edb661d3fbfaac1c92ca952a0 Mon Sep 17 00:00:00 2001 From: Adrian Perez Date: Fri, 18 Jan 2019 16:43:39 -0800 Subject: [PATCH 118/472] Adapt MemoryIOSystem to delegate unhandled calls to shadowed IO system --- code/Importer.cpp | 2 +- include/assimp/MemoryIOWrapper.h | 37 +++++++++++++++++++++----------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/code/Importer.cpp b/code/Importer.cpp index fe6df187c..da395edb2 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -483,7 +483,7 @@ const aiScene* Importer::ReadFileFromMemory( const void* pBuffer, IOSystem* io = pimpl->mIOHandler; pimpl->mIOHandler = NULL; - SetIOHandler(new MemoryIOSystem((const uint8_t*)pBuffer,pLength)); + SetIOHandler(new MemoryIOSystem((const uint8_t*)pBuffer,pLength,io)); // read the file and recover the previous IOSystem static const size_t BufSize(Importer::MaxLenHint + 28); diff --git a/include/assimp/MemoryIOWrapper.h b/include/assimp/MemoryIOWrapper.h index 5260cb2b2..540f5f32c 100644 --- a/include/assimp/MemoryIOWrapper.h +++ b/include/assimp/MemoryIOWrapper.h @@ -151,9 +151,8 @@ class MemoryIOSystem : public IOSystem { public: /** Constructor. */ - MemoryIOSystem (const uint8_t* buff, size_t len) - : buffer (buff), length(len) { - } + MemoryIOSystem(const uint8_t* buff, size_t len, IOSystem* io) + : buffer(buff), length(len), existing_io(io), created_stream(NULL) {} /** Destructor. */ ~MemoryIOSystem() { @@ -161,40 +160,52 @@ public: // ------------------------------------------------------------------- /** Tests for the existence of a file at the given path. */ - bool Exists( const char* pFile) const { - return !strncmp(pFile,AI_MEMORYIO_MAGIC_FILENAME,AI_MEMORYIO_MAGIC_FILENAME_LENGTH); + bool Exists(const char* pFile) const { + if (!strncmp(pFile,AI_MEMORYIO_MAGIC_FILENAME,AI_MEMORYIO_MAGIC_FILENAME_LENGTH)) { + return true; + } + return existing_io ? existing_io->Exists(pFile) : false; } // ------------------------------------------------------------------- /** Returns the directory separator. */ char getOsSeparator() const { - return '/'; // why not? it doesn't care + return existing_io ? existing_io->getOsSeparator() + : '/'; // why not? it doesn't care } // ------------------------------------------------------------------- /** Open a new file with a given path. */ - IOStream* Open( const char* pFile, const char* /*pMode*/ = "rb") { - if (strncmp(pFile,AI_MEMORYIO_MAGIC_FILENAME,AI_MEMORYIO_MAGIC_FILENAME_LENGTH)) { - return NULL; + IOStream* Open(const char* pFile, const char* pMode = "rb") { + if (!strncmp(pFile,AI_MEMORYIO_MAGIC_FILENAME,AI_MEMORYIO_MAGIC_FILENAME_LENGTH)) { + created_stream = new MemoryIOStream(buffer, length); + return created_stream; } - return new MemoryIOStream(buffer,length); + return existing_io ? existing_io->Open(pFile, pMode) : NULL; } // ------------------------------------------------------------------- /** Closes the given file and releases all resources associated with it. */ void Close( IOStream* pFile) { - delete pFile; + if (pFile == created_stream) { + delete pFile; + created_stream = NULL; + } else if (existing_io) { + existing_io->Close(pFile); + } } // ------------------------------------------------------------------- /** Compare two paths */ - bool ComparePaths (const char* /*one*/, const char* /*second*/) const { - return false; + bool ComparePaths(const char* one, const char* second) const { + return existing_io ? existing_io->ComparePaths(one, second) : false; } private: const uint8_t* buffer; size_t length; + IOSystem* existing_io; + IOStream* created_stream; }; } // end namespace Assimp From 87112eefaee620a7473cbcf54361a2f8dcabe5f7 Mon Sep 17 00:00:00 2001 From: Adrian Perez Date: Mon, 21 Jan 2019 14:37:33 -0800 Subject: [PATCH 119/472] Fill in rest of interface; switch created_stream to a unique_ptr --- include/assimp/MemoryIOWrapper.h | 54 ++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 13 deletions(-) diff --git a/include/assimp/MemoryIOWrapper.h b/include/assimp/MemoryIOWrapper.h index 540f5f32c..33be00393 100644 --- a/include/assimp/MemoryIOWrapper.h +++ b/include/assimp/MemoryIOWrapper.h @@ -152,7 +152,7 @@ class MemoryIOSystem : public IOSystem public: /** Constructor. */ MemoryIOSystem(const uint8_t* buff, size_t len, IOSystem* io) - : buffer(buff), length(len), existing_io(io), created_stream(NULL) {} + : buffer(buff), length(len), existing_io(io), created_stream() {} /** Destructor. */ ~MemoryIOSystem() { @@ -160,7 +160,7 @@ public: // ------------------------------------------------------------------- /** Tests for the existence of a file at the given path. */ - bool Exists(const char* pFile) const { + bool Exists(const char* pFile) const override { if (!strncmp(pFile,AI_MEMORYIO_MAGIC_FILENAME,AI_MEMORYIO_MAGIC_FILENAME_LENGTH)) { return true; } @@ -169,27 +169,26 @@ public: // ------------------------------------------------------------------- /** Returns the directory separator. */ - char getOsSeparator() const { + char getOsSeparator() const override { return existing_io ? existing_io->getOsSeparator() - : '/'; // why not? it doesn't care + : '/'; // why not? it doesn't care } // ------------------------------------------------------------------- /** Open a new file with a given path. */ - IOStream* Open(const char* pFile, const char* pMode = "rb") { + IOStream* Open(const char* pFile, const char* pMode = "rb") override { if (!strncmp(pFile,AI_MEMORYIO_MAGIC_FILENAME,AI_MEMORYIO_MAGIC_FILENAME_LENGTH)) { - created_stream = new MemoryIOStream(buffer, length); - return created_stream; + created_stream.reset(new MemoryIOStream(buffer, length)); + return created_stream.get(); } return existing_io ? existing_io->Open(pFile, pMode) : NULL; } // ------------------------------------------------------------------- /** Closes the given file and releases all resources associated with it. */ - void Close( IOStream* pFile) { - if (pFile == created_stream) { - delete pFile; - created_stream = NULL; + void Close( IOStream* pFile) override { + if (pFile == created_stream.get()) { + created_stream.reset(); } else if (existing_io) { existing_io->Close(pFile); } @@ -197,15 +196,44 @@ public: // ------------------------------------------------------------------- /** Compare two paths */ - bool ComparePaths(const char* one, const char* second) const { + bool ComparePaths(const char* one, const char* second) const override { return existing_io ? existing_io->ComparePaths(one, second) : false; } + bool PushDirectory( const std::string &path ) override { + return existing_io ? existing_io->PushDirectory(path) : false; + } + + const std::string &CurrentDirectory() const override { + static std::string empty; + return existing_io ? existing_io->CurrentDirectory() : empty; + } + + size_t StackSize() const override { + return existing_io ? existing_io->StackSize() : 0; + } + + bool PopDirectory() override { + return existing_io ? existing_io->PopDirectory() : false; + } + + bool CreateDirectory( const std::string &path ) override { + return existing_io ? existing_io->CreateDirectory(path) : false; + } + + bool ChangeDirectory( const std::string &path ) override { + return existing_io ? existing_io->ChangeDirectory(path) : false; + } + + bool DeleteFile( const std::string &file ) override { + return existing_io ? existing_io->DeleteFile(file) : false; + } + private: const uint8_t* buffer; size_t length; IOSystem* existing_io; - IOStream* created_stream; + std::unique_ptr created_stream; }; } // end namespace Assimp From ad18cd96609cefb487980b0beed63ec72b36765d Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 22 Jan 2019 11:13:26 +0100 Subject: [PATCH 120/472] Update MemoryIOWrapper.h Fix leak. --- include/assimp/MemoryIOWrapper.h | 50 +++++++++++++++++--------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/include/assimp/MemoryIOWrapper.h b/include/assimp/MemoryIOWrapper.h index 33be00393..4ac9d1c70 100644 --- a/include/assimp/MemoryIOWrapper.h +++ b/include/assimp/MemoryIOWrapper.h @@ -57,20 +57,16 @@ namespace Assimp { // ---------------------------------------------------------------------------------- /** Implementation of IOStream to read directly from a memory buffer */ // ---------------------------------------------------------------------------------- -class MemoryIOStream : public IOStream -{ - //friend class MemoryIOSystem; +class MemoryIOStream : public IOStream { public: MemoryIOStream (const uint8_t* buff, size_t len, bool own = false) - : buffer (buff) - , length(len) - , pos((size_t)0) - , own(own) - { + : buffer (buff) + , length(len) + , pos((size_t)0) + , own(own) { + // empty } -public: - ~MemoryIOStream () { if(own) { delete[] buffer; @@ -80,8 +76,8 @@ public: // ------------------------------------------------------------------- // Read from stream size_t Read(void* pvBuffer, size_t pSize, size_t pCount) { - ai_assert(pvBuffer); - ai_assert(pSize); + ai_assert(nullptr != pvBuffer); + ai_assert(0 != pSize); const size_t cnt = std::min(pCount,(length-pos)/pSize), ofs = pSize*cnt; memcpy(pvBuffer,buffer+pos,ofs); @@ -105,14 +101,12 @@ public: return AI_FAILURE; } pos = pOffset; - } - else if (aiOrigin_END == pOrigin) { + } else if (aiOrigin_END == pOrigin) { if (pOffset > length) { return AI_FAILURE; } pos = length-pOffset; - } - else { + } else { if (pOffset+pos > length) { return AI_FAILURE; } @@ -147,15 +141,21 @@ private: // --------------------------------------------------------------------------- /** Dummy IO system to read from a memory buffer */ -class MemoryIOSystem : public IOSystem -{ +class MemoryIOSystem : public IOSystem { public: /** Constructor. */ MemoryIOSystem(const uint8_t* buff, size_t len, IOSystem* io) - : buffer(buff), length(len), existing_io(io), created_stream() {} + : buffer(buff) + , length(len) + , existing_io(io) + , created_stream() { + // empty + } /** Destructor. */ ~MemoryIOSystem() { + delete created_stream; + created_stream = nullptr; } // ------------------------------------------------------------------- @@ -178,8 +178,8 @@ public: /** Open a new file with a given path. */ IOStream* Open(const char* pFile, const char* pMode = "rb") override { if (!strncmp(pFile,AI_MEMORYIO_MAGIC_FILENAME,AI_MEMORYIO_MAGIC_FILENAME_LENGTH)) { - created_stream.reset(new MemoryIOStream(buffer, length)); - return created_stream.get(); + created_stream = new MemoryIOStream(buffer, length); + return created_stream; } return existing_io ? existing_io->Open(pFile, pMode) : NULL; } @@ -187,8 +187,9 @@ public: // ------------------------------------------------------------------- /** Closes the given file and releases all resources associated with it. */ void Close( IOStream* pFile) override { - if (pFile == created_stream.get()) { - created_stream.reset(); + if (pFile == created_stream) { + delete created_stream; + created_stream = nullptr; } else if (existing_io) { existing_io->Close(pFile); } @@ -233,8 +234,9 @@ private: const uint8_t* buffer; size_t length; IOSystem* existing_io; - std::unique_ptr created_stream; + IOStream *created_stream; }; + } // end namespace Assimp #endif From f8a23e128bfbd9fe300005a7338952cfbf9a9ceb Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 22 Jan 2019 20:47:24 +0100 Subject: [PATCH 121/472] Update MemoryIOWrapper.h Make code more readable. --- include/assimp/MemoryIOWrapper.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/include/assimp/MemoryIOWrapper.h b/include/assimp/MemoryIOWrapper.h index 4ac9d1c70..7b0ea0dbc 100644 --- a/include/assimp/MemoryIOWrapper.h +++ b/include/assimp/MemoryIOWrapper.h @@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include namespace Assimp { + #define AI_MEMORYIO_MAGIC_FILENAME "$$$___magic___$$$" #define AI_MEMORYIO_MAGIC_FILENAME_LENGTH 17 @@ -78,9 +79,11 @@ public: size_t Read(void* pvBuffer, size_t pSize, size_t pCount) { ai_assert(nullptr != pvBuffer); ai_assert(0 != pSize); - const size_t cnt = std::min(pCount,(length-pos)/pSize), ofs = pSize*cnt; + + const size_t cnt = std::min( pCount, (length-pos) / pSize); + const size_t ofs = pSize * cnt; - memcpy(pvBuffer,buffer+pos,ofs); + ::memcpy(pvBuffer,buffer+pos,ofs); pos += ofs; return cnt; @@ -161,7 +164,7 @@ public: // ------------------------------------------------------------------- /** Tests for the existence of a file at the given path. */ bool Exists(const char* pFile) const override { - if (!strncmp(pFile,AI_MEMORYIO_MAGIC_FILENAME,AI_MEMORYIO_MAGIC_FILENAME_LENGTH)) { + if (0 == strncmp( pFile, AI_MEMORYIO_MAGIC_FILENAME, AI_MEMORYIO_MAGIC_FILENAME_LENGTH ) ) { return true; } return existing_io ? existing_io->Exists(pFile) : false; @@ -177,7 +180,7 @@ public: // ------------------------------------------------------------------- /** Open a new file with a given path. */ IOStream* Open(const char* pFile, const char* pMode = "rb") override { - if (!strncmp(pFile,AI_MEMORYIO_MAGIC_FILENAME,AI_MEMORYIO_MAGIC_FILENAME_LENGTH)) { + if ( 0 == strncmp( pFile, AI_MEMORYIO_MAGIC_FILENAME, AI_MEMORYIO_MAGIC_FILENAME_LENGTH ) ) { created_stream = new MemoryIOStream(buffer, length); return created_stream; } From b04ed672886c672a45d12bbd900ba5d2b9694314 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 22 Jan 2019 20:47:24 +0100 Subject: [PATCH 122/472] Update MemoryIOWrapper.h Make code more readable. --- include/assimp/MemoryIOWrapper.h | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/include/assimp/MemoryIOWrapper.h b/include/assimp/MemoryIOWrapper.h index 4ac9d1c70..a9a78c319 100644 --- a/include/assimp/MemoryIOWrapper.h +++ b/include/assimp/MemoryIOWrapper.h @@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include namespace Assimp { + #define AI_MEMORYIO_MAGIC_FILENAME "$$$___magic___$$$" #define AI_MEMORYIO_MAGIC_FILENAME_LENGTH 17 @@ -78,9 +79,11 @@ public: size_t Read(void* pvBuffer, size_t pSize, size_t pCount) { ai_assert(nullptr != pvBuffer); ai_assert(0 != pSize); - const size_t cnt = std::min(pCount,(length-pos)/pSize), ofs = pSize*cnt; + + const size_t cnt = std::min( pCount, (length-pos) / pSize); + const size_t ofs = pSize * cnt; - memcpy(pvBuffer,buffer+pos,ofs); + ::memcpy(pvBuffer,buffer+pos,ofs); pos += ofs; return cnt; @@ -148,20 +151,18 @@ public: : buffer(buff) , length(len) , existing_io(io) - , created_stream() { + , created_streams() { // empty } /** Destructor. */ ~MemoryIOSystem() { - delete created_stream; - created_stream = nullptr; } // ------------------------------------------------------------------- /** Tests for the existence of a file at the given path. */ bool Exists(const char* pFile) const override { - if (!strncmp(pFile,AI_MEMORYIO_MAGIC_FILENAME,AI_MEMORYIO_MAGIC_FILENAME_LENGTH)) { + if (0 == strncmp( pFile, AI_MEMORYIO_MAGIC_FILENAME, AI_MEMORYIO_MAGIC_FILENAME_LENGTH ) ) { return true; } return existing_io ? existing_io->Exists(pFile) : false; @@ -177,9 +178,9 @@ public: // ------------------------------------------------------------------- /** Open a new file with a given path. */ IOStream* Open(const char* pFile, const char* pMode = "rb") override { - if (!strncmp(pFile,AI_MEMORYIO_MAGIC_FILENAME,AI_MEMORYIO_MAGIC_FILENAME_LENGTH)) { - created_stream = new MemoryIOStream(buffer, length); - return created_stream; + if ( 0 == strncmp( pFile, AI_MEMORYIO_MAGIC_FILENAME, AI_MEMORYIO_MAGIC_FILENAME_LENGTH ) ) { + created_streams.emplace_back(new MemoryIOStream(buffer, length)); + return created_streams.back(); } return existing_io ? existing_io->Open(pFile, pMode) : NULL; } @@ -187,9 +188,10 @@ public: // ------------------------------------------------------------------- /** Closes the given file and releases all resources associated with it. */ void Close( IOStream* pFile) override { - if (pFile == created_stream) { - delete created_stream; - created_stream = nullptr; + auto it = std::find(created_streams.begin(), created_streams.end(), pFile); + if (it != created_streams.end()) { + delete pFile; + created_streams.erase(it); } else if (existing_io) { existing_io->Close(pFile); } @@ -234,7 +236,7 @@ private: const uint8_t* buffer; size_t length; IOSystem* existing_io; - IOStream *created_stream; + std::vector created_streams; }; } // end namespace Assimp From 5d6fc7a5574e16d276159cca6952542689c6d765 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 27 Jan 2019 21:05:58 +0100 Subject: [PATCH 123/472] Closes https://github.com/assimp/assimp/issues/2251: introduce AI_CONFIG_PP_FID_IGNORE_TEXTURECOORDS to avoid removing textures. --- code/FindInvalidDataProcess.cpp | 36 +++++++++++++++++++-------------- code/FindInvalidDataProcess.h | 20 +++++++++--------- include/assimp/config.h.in | 7 +++++++ 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/code/FindInvalidDataProcess.cpp b/code/FindInvalidDataProcess.cpp index b1a296a54..19dd420a1 100644 --- a/code/FindInvalidDataProcess.cpp +++ b/code/FindInvalidDataProcess.cpp @@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // internal headers #include "FindInvalidDataProcess.h" #include "ProcessHelper.h" + #include #include #include @@ -60,8 +61,8 @@ using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer FindInvalidDataProcess::FindInvalidDataProcess() - : configEpsilon(0.0) -{ +: configEpsilon(0.0) +, mIgnoreTexCoods( false ){ // nothing to do here } @@ -85,6 +86,7 @@ void FindInvalidDataProcess::SetupProperties(const Importer* pImp) { // Get the current value of AI_CONFIG_PP_FID_ANIM_ACCURACY configEpsilon = (0 != pImp->GetPropertyFloat(AI_CONFIG_PP_FID_ANIM_ACCURACY,0.f)); + mIgnoreTexCoods = pImp->GetPropertyBool(AI_CONFIG_PP_FID_IGNORE_TEXTURECOORDS, false); } // ------------------------------------------------------------------------------------------------ @@ -171,7 +173,8 @@ void FindInvalidDataProcess::Execute( aiScene* pScene) // ------------------------------------------------------------------------------------------------ template -inline const char* ValidateArrayContents(const T* /*arr*/, unsigned int /*size*/, +inline +const char* ValidateArrayContents(const T* /*arr*/, unsigned int /*size*/, const std::vector& /*dirtyMask*/, bool /*mayBeIdentical = false*/, bool /*mayBeZero = true*/) { return NULL; @@ -179,7 +182,8 @@ inline const char* ValidateArrayContents(const T* /*arr*/, unsigned int /*size*/ // ------------------------------------------------------------------------------------------------ template <> -inline const char* ValidateArrayContents(const aiVector3D* arr, unsigned int size, +inline +const char* ValidateArrayContents(const aiVector3D* arr, unsigned int size, const std::vector& dirtyMask, bool mayBeIdentical , bool mayBeZero ) { bool b = false; @@ -251,8 +255,8 @@ bool EpsilonCompare(const aiQuatKey& n, const aiQuatKey& s, ai_real e // ------------------------------------------------------------------------------------------------ template -inline bool AllIdentical(T* in, unsigned int num, ai_real epsilon) -{ +inline +bool AllIdentical(T* in, unsigned int num, ai_real epsilon) { if (num <= 1) { return true; } @@ -361,17 +365,19 @@ int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh) // 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)) { - pMesh->mNumUVComponents[i] = 0; + if (!mIgnoreTexCoods) { + 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; - pMesh->mNumUVComponents[a] = 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; + pMesh->mNumUVComponents[a] = 0; + } + + ret = true; } - - ret = true; } } diff --git a/code/FindInvalidDataProcess.h b/code/FindInvalidDataProcess.h index 00dfef145..f5a49f496 100644 --- a/code/FindInvalidDataProcess.h +++ b/code/FindInvalidDataProcess.h @@ -41,7 +41,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file Defines a post processing step to search an importer's output - for data that is obviously invalid */ + * for data that is obviously invalid + */ #ifndef AI_FINDINVALIDDATA_H_INC #define AI_FINDINVALIDDATA_H_INC @@ -50,7 +51,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include struct aiMesh; + class FindInvalidDataProcessTest; + namespace Assimp { // --------------------------------------------------------------------------- @@ -59,15 +62,11 @@ namespace Assimp { * * Originally this was a workaround for some models written by Blender * which have zero normal vectors. */ -class ASSIMP_API FindInvalidDataProcess : public BaseProcess -{ +class ASSIMP_API FindInvalidDataProcess : public BaseProcess { public: - FindInvalidDataProcess(); ~FindInvalidDataProcess(); -public: - // ------------------------------------------------------------------- // bool IsActive( unsigned int pFlags) const; @@ -80,26 +79,25 @@ public: // Run the step void Execute( aiScene* pScene); -public: - // ------------------------------------------------------------------- - /** Executes the postprocessing step on the given mesh + /** Executes the post-processing step on the given mesh * @param pMesh The mesh to process. * @return 0 - nothing, 1 - removed sth, 2 - please delete me */ int ProcessMesh( aiMesh* pMesh); // ------------------------------------------------------------------- - /** Executes the postprocessing step on the given animation + /** Executes the post-processing step on the given animation * @param anim The animation to process. */ void ProcessAnimation (aiAnimation* anim); // ------------------------------------------------------------------- - /** Executes the postprocessing step on the given anim channel + /** Executes the post-processing step on the given anim channel * @param anim The animation channel to process.*/ void ProcessAnimationChannel (aiNodeAnim* anim); private: ai_real configEpsilon; + bool mIgnoreTexCoods; }; } // end of namespace Assimp diff --git a/include/assimp/config.h.in b/include/assimp/config.h.in index fd828bc6e..a37ff0b8c 100644 --- a/include/assimp/config.h.in +++ b/include/assimp/config.h.in @@ -498,6 +498,13 @@ enum aiComponent #define AI_CONFIG_PP_FID_ANIM_ACCURACY \ "PP_FID_ANIM_ACCURACY" +// --------------------------------------------------------------------------- +/** @brief Input parameter to the #aiProcess_FindInvalidData step: + * Set to true to ignore texture coordinates. This may be useful if you have + * to assign different kind of textures like one for the summer or one for the winter. + */ +#define AI_CONFIG_PP_FID_IGNORE_TEXTURECOORDS \ + "PP_FID_IGNORE_TEXTURECOORDS" // TransformUVCoords evaluates UV scalings #define AI_UVTRAFO_SCALING 0x1 From 2432abacc70eb225fc917883405f188f190ac414 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 27 Jan 2019 21:11:52 +0100 Subject: [PATCH 124/472] Update README.md Update doc. --- port/AndroidJNI/README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/port/AndroidJNI/README.md b/port/AndroidJNI/README.md index 570ca4fb3..7998fa3ef 100644 --- a/port/AndroidJNI/README.md +++ b/port/AndroidJNI/README.md @@ -1,7 +1,7 @@ Build Asset Importer Lib for Android ==================================== -This module provides a fascade for the io-stream-access to files behind the -android-asset-management within an Android native application. +This module provides a fascade for the io-stream-access to files behind the android-asset-management within +an Android-native application. - It is built as a static library - It requires Android NDK with android API > 9 support. @@ -20,6 +20,8 @@ A small example how to wrap assimp for Android: #include Assimp::Importer* importer = new Assimp::Importer(); -Assimp::AndroidJNIIOSystem* ioSystem = new Assimp::AndroidJNIIOSystem(app->activity); -importer->SetIOHandler(ioSystem); +Assimp::AndroidJNIIOSystem *ioSystem = new Assimp::AndroidJNIIOSystem(app->activity); +if ( nullptr != iosSystem ) { + importer->SetIOHandler(ioSystem); +} ``` From b35331b92ae90b6d7d5932721f203a7bd6bb2933 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 28 Jan 2019 10:50:36 +0100 Subject: [PATCH 125/472] Update FindInvalidDataProcess.cpp -Fix some review findings. --- code/FindInvalidDataProcess.cpp | 80 ++++++++++++++------------------- 1 file changed, 33 insertions(+), 47 deletions(-) diff --git a/code/FindInvalidDataProcess.cpp b/code/FindInvalidDataProcess.cpp index 19dd420a1..c775187e9 100644 --- a/code/FindInvalidDataProcess.cpp +++ b/code/FindInvalidDataProcess.cpp @@ -68,22 +68,19 @@ FindInvalidDataProcess::FindInvalidDataProcess() // ------------------------------------------------------------------------------------------------ // Destructor, private as well -FindInvalidDataProcess::~FindInvalidDataProcess() -{ +FindInvalidDataProcess::~FindInvalidDataProcess() { // nothing to do here } // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool FindInvalidDataProcess::IsActive( unsigned int pFlags) const -{ +bool FindInvalidDataProcess::IsActive( unsigned int pFlags) const { return 0 != (pFlags & aiProcess_FindInvalidData); } // ------------------------------------------------------------------------------------------------ // Setup import configuration -void FindInvalidDataProcess::SetupProperties(const Importer* pImp) -{ +void FindInvalidDataProcess::SetupProperties(const Importer* pImp) { // Get the current value of AI_CONFIG_PP_FID_ANIM_ACCURACY configEpsilon = (0 != pImp->GetPropertyFloat(AI_CONFIG_PP_FID_ANIM_ACCURACY,0.f)); mIgnoreTexCoods = pImp->GetPropertyBool(AI_CONFIG_PP_FID_IGNORE_TEXTURECOORDS, false); @@ -91,8 +88,7 @@ void FindInvalidDataProcess::SetupProperties(const Importer* pImp) // ------------------------------------------------------------------------------------------------ // Update mesh references in the node graph -void UpdateMeshReferences(aiNode* node, const std::vector& meshMapping) -{ +void UpdateMeshReferences(aiNode* node, const std::vector& meshMapping) { if (node->mNumMeshes) { unsigned int out = 0; for (unsigned int a = 0; a < node->mNumMeshes;++a) { @@ -118,8 +114,7 @@ void UpdateMeshReferences(aiNode* node, const std::vector& meshMap // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void FindInvalidDataProcess::Execute( aiScene* pScene) -{ +void FindInvalidDataProcess::Execute( aiScene* pScene) { ASSIMP_LOG_DEBUG("FindInvalidDataProcess begin"); bool out = false; @@ -175,17 +170,16 @@ 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*/) + const std::vector& /*dirtyMask*/, bool /*mayBeIdentical = false*/, bool /*mayBeZero = true*/) { - return NULL; + return nullptr; } // ------------------------------------------------------------------------------------------------ template <> inline const char* ValidateArrayContents(const aiVector3D* arr, unsigned int size, - const std::vector& dirtyMask, bool mayBeIdentical , bool mayBeZero ) -{ + const std::vector& dirtyMask, bool mayBeIdentical , bool mayBeZero ) { bool b = false; unsigned int cnt = 0; for (unsigned int i = 0; i < size;++i) { @@ -207,14 +201,14 @@ const char* ValidateArrayContents(const aiVector3D* arr, unsigned in if (cnt > 1 && !b && !mayBeIdentical) { return "All vectors are identical"; } - return NULL; + return nullptr; } // ------------------------------------------------------------------------------------------------ template -inline bool ProcessArray(T*& in, unsigned int num,const char* name, - const std::vector& dirtyMask, bool mayBeIdentical = false, bool mayBeZero = true) -{ +inline +bool ProcessArray(T*& in, unsigned int num,const char* name, + const std::vector& dirtyMask, bool mayBeIdentical = false, bool mayBeZero = true) { const char* err = ValidateArrayContents(in,num,dirtyMask,mayBeIdentical,mayBeZero); if (err) { ASSIMP_LOG_ERROR_F( "FindInvalidDataProcess fails on mesh ", name, ": ", err); @@ -261,17 +255,14 @@ bool AllIdentical(T* in, unsigned int num, ai_real epsilon) { return true; } - if (epsilon > 0.f) { + if (fabs(epsilon) > 0.f) { for (unsigned int i = 0; i < num-1;++i) { - if (!EpsilonCompare(in[i],in[i+1],epsilon)) { return false; } } - } - else { + } else { for (unsigned int i = 0; i < num-1;++i) { - if (in[i] != in[i+1]) { return false; } @@ -282,27 +273,24 @@ bool AllIdentical(T* in, unsigned int num, ai_real epsilon) { // ------------------------------------------------------------------------------------------------ // Search an animation for invalid content -void FindInvalidDataProcess::ProcessAnimation (aiAnimation* anim) -{ +void FindInvalidDataProcess::ProcessAnimation (aiAnimation* anim) { // Process all animation channels - for (unsigned int a = 0; a < anim->mNumChannels;++a) { + for ( unsigned int a = 0; a < anim->mNumChannels; ++a ) { ProcessAnimationChannel( anim->mChannels[a]); } } // ------------------------------------------------------------------------------------------------ -void FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim) -{ - int i = 0; - - // ScenePreprocessor's work ... - ai_assert((0 != anim->mPositionKeys && 0 != anim->mRotationKeys && 0 != anim->mScalingKeys)); +void FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim) { + ai_assert( 0 != anim->mPositionKeys ); + ai_assert( 0 != anim->mRotationKeys ); + ai_assert( 0 != anim->mScalingKeys ); // Check whether all values in a tracks are identical - in this case // we can remove al keys except one. // POSITIONS - if (anim->mNumPositionKeys > 1 && AllIdentical(anim->mPositionKeys,anim->mNumPositionKeys,configEpsilon)) - { + int i = 0; + if (anim->mNumPositionKeys > 1 && AllIdentical(anim->mPositionKeys,anim->mNumPositionKeys,configEpsilon)) { aiVectorKey v = anim->mPositionKeys[0]; // Reallocate ... we need just ONE element, it makes no sense to reuse the array @@ -313,8 +301,7 @@ void FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim) } // ROTATIONS - if (anim->mNumRotationKeys > 1 && AllIdentical(anim->mRotationKeys,anim->mNumRotationKeys,configEpsilon)) - { + if (anim->mNumRotationKeys > 1 && AllIdentical(anim->mRotationKeys,anim->mNumRotationKeys,configEpsilon)) { aiQuatKey v = anim->mRotationKeys[0]; // Reallocate ... we need just ONE element, it makes no sense to reuse the array @@ -325,8 +312,7 @@ void FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim) } // SCALINGS - if (anim->mNumScalingKeys > 1 && AllIdentical(anim->mScalingKeys,anim->mNumScalingKeys,configEpsilon)) - { + if (anim->mNumScalingKeys > 1 && AllIdentical(anim->mScalingKeys,anim->mNumScalingKeys,configEpsilon)) { aiVectorKey v = anim->mScalingKeys[0]; // Reallocate ... we need just ONE element, it makes no sense to reuse the array @@ -335,8 +321,9 @@ void FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim) anim->mScalingKeys[0] = v; i = 1; } - if (1 == i) + if ( 1 == i ) { ASSIMP_LOG_WARN("Simplified dummy tracks with just one key"); + } } // ------------------------------------------------------------------------------------------------ @@ -364,8 +351,8 @@ int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh) } // process texture coordinates - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS && pMesh->mTextureCoords[i]; ++i) { - if (!mIgnoreTexCoods) { + if (!mIgnoreTexCoods) { + 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; @@ -394,13 +381,11 @@ int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh) aiPrimitiveType_POLYGON & pMesh->mPrimitiveTypes) { // We need to update the lookup-table - for (unsigned int m = 0; m < pMesh->mNumFaces;++m) - { - const aiFace& f = pMesh->mFaces[m]; + for (unsigned int m = 0; m < pMesh->mNumFaces;++m) { + const aiFace& f = pMesh->mFaces[ m ]; if (f.mNumIndices < 3) { dirtyMask[f.mIndices[0]] = true; - if (f.mNumIndices == 2) { dirtyMask[f.mIndices[1]] = true; } @@ -409,7 +394,9 @@ int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh) } // Normals, tangents and bitangents are undefined for // the whole mesh (and should not even be there) - else return ret; + else { + return ret; + } } // Process mesh normals @@ -432,5 +419,4 @@ int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh) return ret ? 1 : 0; } - #endif // !! ASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS From 38bebaf4d3356a0d4544c44f9001fbe104e2aae9 Mon Sep 17 00:00:00 2001 From: FRICOTEAUX Date: Mon, 28 Jan 2019 16:02:09 +0100 Subject: [PATCH 126/472] Fix glTF2 export with no texture coordinates --- code/glTF2Exporter.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index d513dc45d..c8dfd8f4b 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -732,6 +732,9 @@ void glTF2Exporter::ExportMeshes() /************** Texture coordinates **************/ for (int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { + if (!aim->HasTextureCoords(i)) + continue; + // Flip UV y coords if (aim -> mNumUVComponents[i] > 1) { for (unsigned int j = 0; j < aim->mNumVertices; ++j) { @@ -967,7 +970,7 @@ void glTF2Exporter::ExportMetadata() inline Ref GetSamplerInputRef(Asset& asset, std::string& animId, Ref& buffer, std::vector& times) { - return ExportData(asset, animId, buffer, times.size(), ×[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_FLOAT); + return ExportData(asset, animId, buffer, (unsigned int)times.size(), ×[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_FLOAT); } inline void ExtractTranslationSampler(Asset& asset, std::string& animId, Ref& buffer, const aiNodeAnim* nodeChannel, float ticksPerSecond, Animation::Sampler& sampler) From a06133ab52cc49d611f2616a55840dfdb7522d09 Mon Sep 17 00:00:00 2001 From: kimkulling Date: Wed, 30 Jan 2019 09:41:39 +0100 Subject: [PATCH 127/472] Update copyrights. --- CMakeLists.txt | 2 +- code/3DSConverter.cpp | 2 +- code/3DSExporter.cpp | 2 +- code/3DSExporter.h | 2 +- code/3DSHelper.h | 2 +- code/3DSLoader.cpp | 2 +- code/3DSLoader.h | 2 +- code/3MFXmlTags.h | 2 +- code/ACLoader.cpp | 2 +- code/ACLoader.h | 2 +- code/AMFImporter.cpp | 2 +- code/AMFImporter.hpp | 2 +- code/AMFImporter_Geometry.cpp | 2 +- code/AMFImporter_Macro.hpp | 2 +- code/AMFImporter_Material.cpp | 2 +- code/AMFImporter_Node.hpp | 2 +- code/AMFImporter_Postprocess.cpp | 2 +- code/ASELoader.cpp | 2 +- code/ASELoader.h | 2 +- code/ASEParser.cpp | 2 +- code/ASEParser.h | 2 +- code/AssbinExporter.cpp | 2 +- code/AssbinExporter.h | 2 +- code/AssbinLoader.cpp | 2 +- code/AssbinLoader.h | 2 +- code/Assimp.cpp | 2 +- code/AssimpCExport.cpp | 2 +- code/AssxmlExporter.cpp | 2 +- code/AssxmlExporter.h | 2 +- code/B3DImporter.cpp | 2 +- code/B3DImporter.h | 2 +- code/BVHLoader.cpp | 2 +- code/BVHLoader.h | 2 +- code/BaseImporter.cpp | 2 +- code/BaseProcess.cpp | 2 +- code/BaseProcess.h | 2 +- code/Bitmap.cpp | 2 +- code/BlenderDNA.cpp | 2 +- code/BlenderDNA.h | 2 +- code/BlenderDNA.inl | 2 +- code/BlenderIntermediate.h | 2 +- code/BlenderLoader.cpp | 2 +- code/BlenderLoader.h | 2 +- code/BlenderModifier.cpp | 2 +- code/BlenderModifier.h | 2 +- code/BlenderScene.h | 2 +- code/BlenderTessellator.cpp | 2 +- code/BlenderTessellator.h | 2 +- code/CInterfaceIOWrapper.cpp | 2 +- code/CInterfaceIOWrapper.h | 2 +- code/CMakeLists.txt | 2 +- code/COBLoader.cpp | 2 +- code/COBLoader.h | 2 +- code/COBScene.h | 2 +- code/CSMLoader.cpp | 2 +- code/CSMLoader.h | 2 +- code/CalcTangentsProcess.cpp | 2 +- code/CalcTangentsProcess.h | 2 +- code/ColladaExporter.cpp | 2 +- code/ColladaExporter.h | 2 +- code/ColladaHelper.h | 2 +- code/ColladaLoader.cpp | 2 +- code/ColladaLoader.h | 2 +- code/ColladaParser.cpp | 2 +- code/ColladaParser.h | 2 +- code/ComputeUVMappingProcess.cpp | 2 +- code/ComputeUVMappingProcess.h | 2 +- code/ConvertToLHProcess.cpp | 2 +- code/ConvertToLHProcess.h | 2 +- code/D3MFExporter.cpp | 2 +- code/D3MFExporter.h | 2 +- code/D3MFImporter.cpp | 2 +- code/D3MFImporter.h | 2 +- code/D3MFOpcPackage.cpp | 2 +- code/D3MFOpcPackage.h | 2 +- code/DXFHelper.h | 2 +- code/DXFLoader.cpp | 2 +- code/DXFLoader.h | 2 +- code/DeboneProcess.cpp | 2 +- code/DeboneProcess.h | 2 +- code/DefaultIOStream.cpp | 2 +- code/DefaultIOSystem.cpp | 2 +- code/DefaultLogger.cpp | 2 +- code/DefaultProgressHandler.h | 2 +- code/DropFaceNormalsProcess.cpp | 2 +- code/DropFaceNormalsProcess.h | 2 +- code/EmbedTexturesProcess.cpp | 2 +- code/EmbedTexturesProcess.h | 2 +- code/Exporter.cpp | 2 +- code/FBXAnimation.cpp | 2 +- code/FBXBinaryTokenizer.cpp | 2 +- code/FBXCommon.h | 2 +- code/FBXCompileConfig.h | 2 +- code/FBXConverter.cpp | 2 +- code/FBXConverter.h | 2 +- code/FBXDeformer.cpp | 2 +- code/FBXDocument.cpp | 2 +- code/FBXDocument.h | 2 +- code/FBXDocumentUtil.cpp | 2 +- code/FBXExportNode.cpp | 2 +- code/FBXExportNode.h | 2 +- code/FBXExportProperty.cpp | 2 +- code/FBXExportProperty.h | 2 +- code/FBXExporter.cpp | 2 +- code/FBXExporter.h | 2 +- code/FBXImportSettings.h | 2 +- code/FBXImporter.cpp | 2 +- code/FBXImporter.h | 2 +- code/FBXMaterial.cpp | 2 +- code/FBXMeshGeometry.cpp | 2 +- code/FBXMeshGeometry.h | 2 +- code/FBXModel.cpp | 2 +- code/FBXNodeAttribute.cpp | 2 +- code/FBXParser.cpp | 2 +- code/FBXParser.h | 2 +- code/FBXProperties.cpp | 2 +- code/FBXProperties.h | 2 +- code/FBXTokenizer.cpp | 2 +- code/FBXTokenizer.h | 2 +- code/FBXUtil.cpp | 2 +- code/FBXUtil.h | 2 +- code/FIReader.cpp | 2 +- code/FIReader.hpp | 2 +- code/FileLogStream.h | 2 +- code/FindDegenerates.cpp | 2 +- code/FindDegenerates.h | 2 +- code/FindInstancesProcess.cpp | 2 +- code/FindInstancesProcess.h | 2 +- code/FindInvalidDataProcess.cpp | 2 +- code/FindInvalidDataProcess.h | 2 +- code/FixNormalsStep.cpp | 2 +- code/FixNormalsStep.h | 2 +- code/GenFaceNormalsProcess.cpp | 2 +- code/GenFaceNormalsProcess.h | 2 +- code/GenVertexNormalsProcess.cpp | 2 +- code/GenVertexNormalsProcess.h | 2 +- code/HMPFileData.h | 2 +- code/HMPLoader.cpp | 2 +- code/HMPLoader.h | 2 +- code/HalfLifeFileData.h | 2 +- code/IRRLoader.cpp | 2 +- code/IRRLoader.h | 2 +- code/IRRMeshLoader.cpp | 2 +- code/IRRMeshLoader.h | 2 +- code/IRRShared.cpp | 2 +- code/Importer.cpp | 2 +- code/Importer.h | 2 +- code/Importer/IFC/IFCCurve.cpp | 2 +- code/Importer/IFC/IFCLoader.cpp | 2 +- code/Importer/IFC/IFCLoader.h | 2 +- code/Importer/IFC/IFCMaterial.cpp | 2 +- code/Importer/IFC/IFCProfile.cpp | 2 +- code/Importer/IFC/IFCUtil.cpp | 2 +- code/Importer/IFC/IFCUtil.h | 2 +- code/Importer/STEPParser/STEPFileEncoding.cpp | 2 +- code/Importer/STEPParser/STEPFileEncoding.h | 2 +- code/Importer/STEPParser/STEPFileReader.cpp | 96 ++++++++++--------- code/Importer/STEPParser/STEPFileReader.h | 4 +- code/Importer/StepFile/StepFileImporter.cpp | 2 +- code/Importer/StepFile/StepFileImporter.h | 2 +- code/ImporterRegistry.cpp | 2 +- code/ImproveCacheLocality.cpp | 2 +- code/ImproveCacheLocality.h | 2 +- code/JoinVerticesProcess.cpp | 2 +- code/JoinVerticesProcess.h | 2 +- code/LWOAnimation.cpp | 2 +- code/LWOAnimation.h | 2 +- code/LWOBLoader.cpp | 2 +- code/LWOFileData.h | 2 +- code/LWOLoader.cpp | 2 +- code/LWOLoader.h | 2 +- code/LWOMaterial.cpp | 2 +- code/LWSLoader.cpp | 2 +- code/LWSLoader.h | 2 +- code/LimitBoneWeightsProcess.cpp | 2 +- code/LimitBoneWeightsProcess.h | 2 +- code/MD2FileData.h | 2 +- code/MD2Loader.cpp | 2 +- code/MD2Loader.h | 2 +- code/MD2NormalTable.h | 2 +- code/MD3FileData.h | 2 +- code/MD3Loader.cpp | 2 +- code/MD3Loader.h | 2 +- code/MD5Loader.cpp | 2 +- code/MD5Loader.h | 2 +- code/MD5Parser.cpp | 2 +- code/MD5Parser.h | 2 +- code/MDCFileData.h | 2 +- code/MDCLoader.cpp | 2 +- code/MDCLoader.h | 2 +- code/MDLDefaultColorMap.h | 2 +- code/MDLFileData.h | 2 +- code/MDLLoader.cpp | 2 +- code/MDLLoader.h | 2 +- code/MDLMaterialLoader.cpp | 2 +- code/MMDCpp14.h | 2 +- code/MMDPmdParser.h | 2 +- code/MMDPmxParser.cpp | 2 +- code/MMDPmxParser.h | 2 +- code/MMDVmdParser.h | 2 +- code/MS3DLoader.cpp | 2 +- code/MS3DLoader.h | 2 +- code/MakeVerboseFormat.cpp | 2 +- code/MakeVerboseFormat.h | 2 +- code/MaterialSystem.cpp | 2 +- code/MaterialSystem.h | 2 +- code/NDOLoader.cpp | 2 +- code/NFFLoader.cpp | 2 +- code/NFFLoader.h | 2 +- code/OFFLoader.cpp | 2 +- code/OFFLoader.h | 2 +- code/ObjExporter.cpp | 2 +- code/ObjExporter.h | 2 +- code/ObjFileData.h | 2 +- code/ObjFileImporter.cpp | 2 +- code/ObjFileImporter.h | 2 +- code/ObjFileMtlImporter.cpp | 2 +- code/ObjFileMtlImporter.h | 2 +- code/ObjFileParser.cpp | 2 +- code/ObjFileParser.h | 2 +- code/ObjTools.h | 2 +- code/OgreBinarySerializer.cpp | 2 +- code/OgreBinarySerializer.h | 2 +- code/OgreImporter.cpp | 2 +- code/OgreImporter.h | 2 +- code/OgreMaterial.cpp | 2 +- code/OgreParsingUtils.h | 2 +- code/OgreStructs.cpp | 2 +- code/OgreStructs.h | 2 +- code/OgreXmlSerializer.cpp | 2 +- code/OgreXmlSerializer.h | 2 +- code/OpenGEXExporter.cpp | 2 +- code/OpenGEXExporter.h | 2 +- code/OpenGEXImporter.cpp | 2 +- code/OpenGEXImporter.h | 2 +- code/OpenGEXStructs.h | 2 +- code/OptimizeGraph.cpp | 2 +- code/OptimizeGraph.h | 2 +- code/OptimizeMeshes.cpp | 2 +- code/OptimizeMeshes.h | 2 +- code/PlyExporter.cpp | 2 +- code/PlyExporter.h | 2 +- code/PlyLoader.cpp | 2 +- code/PlyLoader.h | 2 +- code/PlyParser.cpp | 2 +- code/PlyParser.h | 2 +- code/PolyTools.h | 2 +- code/PostStepRegistry.cpp | 2 +- code/PretransformVertices.cpp | 2 +- code/PretransformVertices.h | 2 +- code/ProcessHelper.cpp | 2 +- code/ProcessHelper.h | 2 +- code/Q3BSPFileData.h | 2 +- code/Q3BSPFileImporter.cpp | 2 +- code/Q3BSPFileImporter.h | 2 +- code/Q3BSPFileParser.cpp | 2 +- code/Q3BSPFileParser.h | 2 +- code/Q3BSPZipArchive.cpp | 2 +- code/Q3BSPZipArchive.h | 2 +- code/Q3DLoader.cpp | 2 +- code/Q3DLoader.h | 2 +- code/RawLoader.cpp | 2 +- code/RawLoader.h | 2 +- code/RemoveComments.cpp | 2 +- code/RemoveRedundantMaterials.cpp | 2 +- code/RemoveRedundantMaterials.h | 2 +- code/RemoveVCProcess.cpp | 2 +- code/RemoveVCProcess.h | 2 +- code/SGSpatialSort.cpp | 2 +- code/SIBImporter.cpp | 2 +- code/SIBImporter.h | 2 +- code/SMDLoader.cpp | 2 +- code/SMDLoader.h | 2 +- code/STEPFile.h | 2 +- code/STLExporter.cpp | 2 +- code/STLExporter.h | 2 +- code/STLLoader.cpp | 2 +- code/STLLoader.h | 2 +- code/ScaleProcess.cpp | 2 +- code/ScaleProcess.h | 2 +- code/SceneCombiner.cpp | 2 +- code/ScenePreprocessor.cpp | 2 +- code/ScenePreprocessor.h | 2 +- code/ScenePrivate.h | 2 +- code/SkeletonMeshBuilder.cpp | 2 +- code/SortByPTypeProcess.cpp | 2 +- code/SortByPTypeProcess.h | 2 +- code/SpatialSort.cpp | 2 +- code/SplitByBoneCountProcess.cpp | 2 +- code/SplitByBoneCountProcess.h | 2 +- code/SplitLargeMeshes.cpp | 2 +- code/SplitLargeMeshes.h | 2 +- code/StandardShapes.cpp | 2 +- code/StdOStreamLogStream.h | 2 +- code/StepExporter.cpp | 2 +- code/StepExporter.h | 2 +- code/Subdivision.cpp | 2 +- code/TargetAnimation.cpp | 2 +- code/TargetAnimation.h | 2 +- code/TerragenLoader.cpp | 2 +- code/TerragenLoader.h | 2 +- code/TextureTransform.cpp | 2 +- code/TextureTransform.h | 2 +- code/TriangulateProcess.cpp | 2 +- code/TriangulateProcess.h | 2 +- code/UnrealLoader.cpp | 2 +- code/UnrealLoader.h | 2 +- code/ValidateDataStructure.cpp | 2 +- code/ValidateDataStructure.h | 2 +- code/Version.cpp | 2 +- code/VertexTriangleAdjacency.cpp | 2 +- code/VertexTriangleAdjacency.h | 2 +- code/Win32DebugLogStream.h | 2 +- code/X3DImporter.cpp | 2 +- code/X3DImporter.hpp | 2 +- code/X3DImporter_Geometry2D.cpp | 2 +- code/X3DImporter_Geometry3D.cpp | 2 +- code/X3DImporter_Group.cpp | 2 +- code/X3DImporter_Light.cpp | 2 +- code/X3DImporter_Macro.hpp | 2 +- code/X3DImporter_Metadata.cpp | 2 +- code/X3DImporter_Networking.cpp | 2 +- code/X3DImporter_Node.hpp | 2 +- code/X3DImporter_Postprocess.cpp | 2 +- code/X3DImporter_Rendering.cpp | 2 +- code/X3DImporter_Shape.cpp | 2 +- code/X3DImporter_Texturing.cpp | 2 +- code/X3DVocabulary.cpp | 2 +- code/XFileExporter.cpp | 2 +- code/XFileExporter.h | 2 +- code/XFileHelper.h | 2 +- code/XFileImporter.cpp | 2 +- code/XFileImporter.h | 2 +- code/XFileParser.cpp | 2 +- code/XFileParser.h | 2 +- code/XGLLoader.cpp | 2 +- code/XGLLoader.h | 2 +- code/glTF2Asset.h | 2 +- code/glTF2Asset.inl | 2 +- code/glTF2AssetWriter.h | 2 +- code/glTF2AssetWriter.inl | 2 +- code/glTF2Exporter.cpp | 2 +- code/glTF2Exporter.h | 2 +- code/glTF2Importer.cpp | 2 +- code/glTF2Importer.h | 2 +- code/glTFAsset.h | 2 +- code/glTFAsset.inl | 2 +- code/glTFAssetWriter.h | 2 +- code/glTFAssetWriter.inl | 2 +- code/glTFExporter.cpp | 2 +- code/glTFExporter.h | 2 +- code/glTFImporter.cpp | 2 +- code/glTFImporter.h | 2 +- code/scene.cpp | 2 +- code/simd.cpp | 2 +- code/simd.h | 2 +- include/assimp/BaseImporter.h | 2 +- include/assimp/Bitmap.h | 2 +- include/assimp/BlobIOSystem.h | 2 +- include/assimp/ByteSwapper.h | 2 +- include/assimp/CreateAnimMesh.h | 2 +- include/assimp/DefaultIOStream.h | 2 +- include/assimp/DefaultIOSystem.h | 2 +- include/assimp/DefaultLogger.hpp | 2 +- include/assimp/Exporter.hpp | 2 +- include/assimp/GenericProperty.h | 2 +- include/assimp/Hash.h | 2 +- include/assimp/IOStream.hpp | 2 +- include/assimp/IOStreamBuffer.h | 2 +- include/assimp/IOSystem.hpp | 2 +- include/assimp/Importer.hpp | 2 +- include/assimp/LineSplitter.h | 2 +- include/assimp/LogAux.h | 2 +- include/assimp/LogStream.hpp | 2 +- include/assimp/Logger.hpp | 2 +- include/assimp/Macros.h | 2 +- include/assimp/MemoryIOWrapper.h | 2 +- include/assimp/NullLogger.hpp | 2 +- include/assimp/ParsingUtils.h | 2 +- include/assimp/Profiler.h | 2 +- include/assimp/ProgressHandler.hpp | 2 +- include/assimp/RemoveComments.h | 2 +- include/assimp/SGSpatialSort.h | 2 +- include/assimp/SceneCombiner.h | 2 +- include/assimp/SkeletonMeshBuilder.h | 2 +- include/assimp/SmoothingGroups.h | 2 +- include/assimp/SpatialSort.h | 2 +- include/assimp/StandardShapes.h | 2 +- include/assimp/StreamReader.h | 2 +- include/assimp/StreamWriter.h | 2 +- include/assimp/StringComparison.h | 2 +- include/assimp/StringUtils.h | 2 +- include/assimp/Subdivision.h | 2 +- include/assimp/TinyFormatter.h | 2 +- include/assimp/Vertex.h | 2 +- include/assimp/XMLTools.h | 2 +- include/assimp/ai_assert.h | 2 +- include/assimp/anim.h | 2 +- include/assimp/camera.h | 2 +- include/assimp/cfileio.h | 2 +- include/assimp/cimport.h | 2 +- include/assimp/color4.h | 2 +- include/assimp/color4.inl | 2 +- include/assimp/defs.h | 2 +- include/assimp/importerdesc.h | 2 +- include/assimp/irrXMLWrapper.h | 2 +- include/assimp/light.h | 2 +- include/assimp/material.h | 2 +- include/assimp/material.inl | 2 +- include/assimp/matrix3x3.h | 2 +- include/assimp/matrix3x3.inl | 2 +- include/assimp/matrix4x4.h | 2 +- include/assimp/matrix4x4.inl | 2 +- include/assimp/mesh.h | 2 +- include/assimp/metadata.h | 2 +- include/assimp/pbrmaterial.h | 2 +- include/assimp/postprocess.h | 2 +- include/assimp/qnan.h | 2 +- include/assimp/quaternion.h | 2 +- include/assimp/quaternion.inl | 2 +- include/assimp/scene.h | 2 +- include/assimp/texture.h | 2 +- include/assimp/types.h | 2 +- include/assimp/vector2.h | 2 +- include/assimp/vector2.inl | 2 +- include/assimp/vector3.h | 2 +- include/assimp/vector3.inl | 2 +- include/assimp/version.h | 2 +- test/CMakeLists.txt | 2 +- test/unit/AbstractImportExportBase.cpp | 2 +- test/unit/AssimpAPITest.cpp | 2 +- test/unit/Common/utLineSplitter.cpp | 2 +- test/unit/ImportExport/utCOBImportExport.cpp | 2 +- test/unit/ImportExport/utExporter.cpp | 2 +- test/unit/ImportExport/utNFFImportExport.cpp | 2 +- test/unit/ImportExport/utOFFImportExport.cpp | 2 +- test/unit/ImportExport/utOgreImportExport.cpp | 2 +- .../ImportExport/utQ3BSPFileImportExport.cpp | 2 +- test/unit/ImportExport/utXGLImportExport.cpp | 2 +- test/unit/SceneDiffer.cpp | 2 +- test/unit/SceneDiffer.h | 2 +- test/unit/TestIOSystem.h | 2 +- test/unit/TestModelFactory.h | 2 +- test/unit/UTLogStream.h | 2 +- test/unit/ut3DImportExport.cpp | 2 +- test/unit/ut3DSImportExport.cpp | 2 +- test/unit/utACImportExport.cpp | 2 +- test/unit/utAMFImportExport.cpp | 2 +- test/unit/utASEImportExport.cpp | 2 +- test/unit/utAnim.cpp | 2 +- test/unit/utAssbinImportExport.cpp | 2 +- test/unit/utB3DImportExport.cpp | 2 +- test/unit/utBVHImportExport.cpp | 2 +- test/unit/utBatchLoader.cpp | 2 +- test/unit/utBlendImportAreaLight.cpp | 2 +- test/unit/utBlendImportMaterials.cpp | 2 +- test/unit/utBlenderImportExport.cpp | 2 +- test/unit/utBlenderIntermediate.cpp | 2 +- test/unit/utBlenderWork.cpp | 2 +- test/unit/utCSMImportExport.cpp | 2 +- test/unit/utColladaExportCamera.cpp | 2 +- test/unit/utColladaExportLight.cpp | 2 +- test/unit/utColladaImportExport.cpp | 2 +- test/unit/utD3MFImportExport.cpp | 2 +- test/unit/utDXFImporterExporter.cpp | 2 +- test/unit/utDefaultIOStream.cpp | 2 +- test/unit/utFBXImporterExporter.cpp | 2 +- test/unit/utFastAtof.cpp | 2 +- test/unit/utFindDegenerates.cpp | 2 +- test/unit/utFindInvalidData.cpp | 2 +- test/unit/utFixInfacingNormals.cpp | 2 +- test/unit/utGenNormals.cpp | 2 +- test/unit/utHMPImportExport.cpp | 2 +- test/unit/utIFCImportExport.cpp | 2 +- test/unit/utIOStreamBuffer.cpp | 2 +- test/unit/utIOSystem.cpp | 2 +- test/unit/utImporter.cpp | 2 +- test/unit/utImproveCacheLocality.cpp | 2 +- test/unit/utIssues.cpp | 2 +- test/unit/utJoinVertices.cpp | 2 +- test/unit/utLWOImportExport.cpp | 2 +- test/unit/utLWSImportExport.cpp | 2 +- test/unit/utLimitBoneWeights.cpp | 2 +- test/unit/utMDCImportExport.cpp | 2 +- test/unit/utMaterialSystem.cpp | 2 +- test/unit/utMatrix3x3.cpp | 2 +- test/unit/utMatrix4x4.cpp | 2 +- test/unit/utMetadata.cpp | 2 +- test/unit/utObjImportExport.cpp | 2 +- test/unit/utObjTools.cpp | 2 +- test/unit/utOpenGEXImportExport.cpp | 2 +- test/unit/utPLYImportExport.cpp | 2 +- test/unit/utPretransformVertices.cpp | 2 +- test/unit/utProfiler.cpp | 2 +- test/unit/utQ3DImportExport.cpp | 2 +- test/unit/utRemoveComments.cpp | 2 +- test/unit/utRemoveComponent.cpp | 2 +- test/unit/utRemoveRedundantMaterials.cpp | 2 +- test/unit/utRemoveVCProcess.cpp | 2 +- test/unit/utSIBImporter.cpp | 2 +- test/unit/utSMDImportExport.cpp | 2 +- test/unit/utSTLImportExport.cpp | 2 +- test/unit/utScaleProcess.cpp | 2 +- test/unit/utSceneCombiner.cpp | 2 +- test/unit/utScenePreprocessor.cpp | 2 +- test/unit/utSharedPPData.cpp | 2 +- test/unit/utSimd.cpp | 2 +- test/unit/utSortByPType.cpp | 2 +- test/unit/utSplitLargeMeshes.cpp | 2 +- test/unit/utStringUtils.cpp | 2 +- test/unit/utTargetAnimation.cpp | 2 +- test/unit/utTextureTransform.cpp | 2 +- test/unit/utTriangulate.cpp | 2 +- test/unit/utTypes.cpp | 2 +- test/unit/utVector3.cpp | 2 +- test/unit/utVersion.cpp | 2 +- test/unit/utVertexTriangleAdjacency.cpp | 2 +- test/unit/utX3DImportExport.cpp | 2 +- test/unit/utXImporterExporter.cpp | 2 +- test/unit/utglTF2ImportExport.cpp | 2 +- test/unit/utglTFImportExport.cpp | 2 +- tools/assimp_cmd/CMakeLists.txt | 2 +- tools/assimp_cmd/CompareDump.cpp | 2 +- tools/assimp_cmd/Export.cpp | 2 +- tools/assimp_cmd/ImageExtractor.cpp | 2 +- tools/assimp_cmd/Info.cpp | 2 +- tools/assimp_cmd/Main.cpp | 2 +- tools/assimp_cmd/WriteDumb.cpp | 2 +- tools/assimp_view/AnimEvaluator.cpp | 2 +- tools/assimp_view/CMakeLists.txt | 2 +- tools/assimp_view/assimp_view.cpp | 2 +- tools/assimp_view/assimp_view.h | 2 +- 532 files changed, 584 insertions(+), 576 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a97174de4..14c65c188 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ # Open Asset Import Library (assimp) # ---------------------------------------------------------------------- -# Copyright (c) 2006-2018, assimp team +# Copyright (c) 2006-2019, assimp team # All rights reserved. # diff --git a/code/3DSConverter.cpp b/code/3DSConverter.cpp index 7ec79ba64..e6865a809 100644 --- a/code/3DSConverter.cpp +++ b/code/3DSConverter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/3DSExporter.cpp b/code/3DSExporter.cpp index 53976b16f..2501d4049 100644 --- a/code/3DSExporter.cpp +++ b/code/3DSExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/3DSExporter.h b/code/3DSExporter.h index 5db58a4cb..035b562cf 100644 --- a/code/3DSExporter.h +++ b/code/3DSExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/3DSHelper.h b/code/3DSHelper.h index d67a7c14c..8eb4cd97c 100644 --- a/code/3DSHelper.h +++ b/code/3DSHelper.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/3DSLoader.cpp b/code/3DSLoader.cpp index 34066e44b..24626d936 100644 --- a/code/3DSLoader.cpp +++ b/code/3DSLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/3DSLoader.h b/code/3DSLoader.h index eb311a81b..f57e6a8e3 100644 --- a/code/3DSLoader.h +++ b/code/3DSLoader.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/3MFXmlTags.h b/code/3MFXmlTags.h index e869c33c1..ea6aeede0 100644 --- a/code/3MFXmlTags.h +++ b/code/3MFXmlTags.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/ACLoader.cpp b/code/ACLoader.cpp index 7b8afbe9b..2eb839553 100644 --- a/code/ACLoader.cpp +++ b/code/ACLoader.cpp @@ -4,7 +4,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/ACLoader.h b/code/ACLoader.h index 86af9afb6..cab2c3ae5 100644 --- a/code/ACLoader.h +++ b/code/ACLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/AMFImporter.cpp b/code/AMFImporter.cpp index e5b41b3ad..d173bd0f5 100644 --- a/code/AMFImporter.cpp +++ b/code/AMFImporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/AMFImporter.hpp b/code/AMFImporter.hpp index b7e58362c..2b8086a06 100644 --- a/code/AMFImporter.hpp +++ b/code/AMFImporter.hpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/AMFImporter_Geometry.cpp b/code/AMFImporter_Geometry.cpp index d4d648fbd..f1538e3fb 100644 --- a/code/AMFImporter_Geometry.cpp +++ b/code/AMFImporter_Geometry.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/AMFImporter_Macro.hpp b/code/AMFImporter_Macro.hpp index ea8c17850..f60c5fbbb 100644 --- a/code/AMFImporter_Macro.hpp +++ b/code/AMFImporter_Macro.hpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/AMFImporter_Material.cpp b/code/AMFImporter_Material.cpp index c9190bb92..2f36df061 100644 --- a/code/AMFImporter_Material.cpp +++ b/code/AMFImporter_Material.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/AMFImporter_Node.hpp b/code/AMFImporter_Node.hpp index 22b8f58cb..a1bf9f008 100644 --- a/code/AMFImporter_Node.hpp +++ b/code/AMFImporter_Node.hpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/AMFImporter_Postprocess.cpp b/code/AMFImporter_Postprocess.cpp index a6ee8fa2f..2bfe3f78c 100644 --- a/code/AMFImporter_Postprocess.cpp +++ b/code/AMFImporter_Postprocess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/ASELoader.cpp b/code/ASELoader.cpp index 1808f25e2..321e8548a 100644 --- a/code/ASELoader.cpp +++ b/code/ASELoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/ASELoader.h b/code/ASELoader.h index 7f71bf49d..33406e3e5 100644 --- a/code/ASELoader.h +++ b/code/ASELoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/ASEParser.cpp b/code/ASEParser.cpp index 298c6fe61..e8d6febc2 100644 --- a/code/ASEParser.cpp +++ b/code/ASEParser.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/ASEParser.h b/code/ASEParser.h index 305a3f3d6..b8c820632 100644 --- a/code/ASEParser.h +++ b/code/ASEParser.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/AssbinExporter.cpp b/code/AssbinExporter.cpp index f49389f78..77c8d1118 100644 --- a/code/AssbinExporter.cpp +++ b/code/AssbinExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/AssbinExporter.h b/code/AssbinExporter.h index ee70d78b6..3e13639bb 100644 --- a/code/AssbinExporter.h +++ b/code/AssbinExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/AssbinLoader.cpp b/code/AssbinLoader.cpp index 321a0cfec..7adb8db6f 100644 --- a/code/AssbinLoader.cpp +++ b/code/AssbinLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/AssbinLoader.h b/code/AssbinLoader.h index 37799a2c8..9f2dde125 100644 --- a/code/AssbinLoader.h +++ b/code/AssbinLoader.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/Assimp.cpp b/code/Assimp.cpp index 87f436602..41e1a4800 100644 --- a/code/Assimp.cpp +++ b/code/Assimp.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/AssimpCExport.cpp b/code/AssimpCExport.cpp index caf51a08c..5121ce39c 100644 --- a/code/AssimpCExport.cpp +++ b/code/AssimpCExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/AssxmlExporter.cpp b/code/AssxmlExporter.cpp index c9e125d0d..fafee0e80 100644 --- a/code/AssxmlExporter.cpp +++ b/code/AssxmlExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/AssxmlExporter.h b/code/AssxmlExporter.h index 3db496db2..8ca887eea 100644 --- a/code/AssxmlExporter.h +++ b/code/AssxmlExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/B3DImporter.cpp b/code/B3DImporter.cpp index ce8bd5159..e48646de9 100644 --- a/code/B3DImporter.cpp +++ b/code/B3DImporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/B3DImporter.h b/code/B3DImporter.h index 3cb66e5c7..d52dac34a 100644 --- a/code/B3DImporter.h +++ b/code/B3DImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/BVHLoader.cpp b/code/BVHLoader.cpp index cba58d056..cd9ab0843 100644 --- a/code/BVHLoader.cpp +++ b/code/BVHLoader.cpp @@ -4,7 +4,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/BVHLoader.h b/code/BVHLoader.h index a18ad81d9..33b4e2453 100644 --- a/code/BVHLoader.h +++ b/code/BVHLoader.h @@ -4,7 +4,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/BaseImporter.cpp b/code/BaseImporter.cpp index f03db189f..4803c6d6f 100644 --- a/code/BaseImporter.cpp +++ b/code/BaseImporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/BaseProcess.cpp b/code/BaseProcess.cpp index 154b586d2..18872c369 100644 --- a/code/BaseProcess.cpp +++ b/code/BaseProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/BaseProcess.h b/code/BaseProcess.h index b09fc732e..4d5c7a76b 100644 --- a/code/BaseProcess.h +++ b/code/BaseProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/Bitmap.cpp b/code/Bitmap.cpp index 903a13fb1..b22b71ea9 100644 --- a/code/Bitmap.cpp +++ b/code/Bitmap.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/BlenderDNA.cpp b/code/BlenderDNA.cpp index f84c45601..f274e02f9 100644 --- a/code/BlenderDNA.cpp +++ b/code/BlenderDNA.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/BlenderDNA.h b/code/BlenderDNA.h index ecf606a3b..5d3a4f6ea 100644 --- a/code/BlenderDNA.h +++ b/code/BlenderDNA.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/BlenderDNA.inl b/code/BlenderDNA.inl index 89c94e7bf..65bc1374c 100644 --- a/code/BlenderDNA.inl +++ b/code/BlenderDNA.inl @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/BlenderIntermediate.h b/code/BlenderIntermediate.h index f3d34d1b2..95fdf0f03 100644 --- a/code/BlenderIntermediate.h +++ b/code/BlenderIntermediate.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/BlenderLoader.cpp b/code/BlenderLoader.cpp index b0d273a5f..90065ceee 100644 --- a/code/BlenderLoader.cpp +++ b/code/BlenderLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/BlenderLoader.h b/code/BlenderLoader.h index 9f452a0aa..d85a82842 100644 --- a/code/BlenderLoader.h +++ b/code/BlenderLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/BlenderModifier.cpp b/code/BlenderModifier.cpp index 1f32ee410..cc7acc929 100644 --- a/code/BlenderModifier.cpp +++ b/code/BlenderModifier.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/BlenderModifier.h b/code/BlenderModifier.h index b8797691b..c260ba1f6 100644 --- a/code/BlenderModifier.h +++ b/code/BlenderModifier.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/BlenderScene.h b/code/BlenderScene.h index b74d7b198..8e4223eb1 100644 --- a/code/BlenderScene.h +++ b/code/BlenderScene.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/BlenderTessellator.cpp b/code/BlenderTessellator.cpp index afedbfb53..d98c2e865 100644 --- a/code/BlenderTessellator.cpp +++ b/code/BlenderTessellator.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/BlenderTessellator.h b/code/BlenderTessellator.h index dab3ba8aa..8675b4e57 100644 --- a/code/BlenderTessellator.h +++ b/code/BlenderTessellator.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/CInterfaceIOWrapper.cpp b/code/CInterfaceIOWrapper.cpp index 41dbba772..5a3a49565 100644 --- a/code/CInterfaceIOWrapper.cpp +++ b/code/CInterfaceIOWrapper.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/CInterfaceIOWrapper.h b/code/CInterfaceIOWrapper.h index 6f0eb7957..216232030 100644 --- a/code/CInterfaceIOWrapper.h +++ b/code/CInterfaceIOWrapper.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index b9b9c211b..1726fda72 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -1,7 +1,7 @@ # Open Asset Import Library (assimp) # ---------------------------------------------------------------------- # -# Copyright (c) 2006-2018, assimp team +# Copyright (c) 2006-2019, assimp team # All rights reserved. diff --git a/code/COBLoader.cpp b/code/COBLoader.cpp index a8e41dbbc..efb22e08b 100644 --- a/code/COBLoader.cpp +++ b/code/COBLoader.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/COBLoader.h b/code/COBLoader.h index 156c8d911..40fed324b 100644 --- a/code/COBLoader.h +++ b/code/COBLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/COBScene.h b/code/COBScene.h index 2473c42a5..90349be70 100644 --- a/code/COBScene.h +++ b/code/COBScene.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/CSMLoader.cpp b/code/CSMLoader.cpp index 777b6cf1b..9dbb38467 100644 --- a/code/CSMLoader.cpp +++ b/code/CSMLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/CSMLoader.h b/code/CSMLoader.h index ea82bb87a..31a814b52 100644 --- a/code/CSMLoader.h +++ b/code/CSMLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/CalcTangentsProcess.cpp b/code/CalcTangentsProcess.cpp index 54e55fc5a..b30f39c27 100644 --- a/code/CalcTangentsProcess.cpp +++ b/code/CalcTangentsProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/CalcTangentsProcess.h b/code/CalcTangentsProcess.h index 4cac2ed9f..18775abcc 100644 --- a/code/CalcTangentsProcess.h +++ b/code/CalcTangentsProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/ColladaExporter.cpp b/code/ColladaExporter.cpp index 9d66741eb..37a6ba4e0 100644 --- a/code/ColladaExporter.cpp +++ b/code/ColladaExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/ColladaExporter.h b/code/ColladaExporter.h index d1a307532..8244b61aa 100644 --- a/code/ColladaExporter.h +++ b/code/ColladaExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/ColladaHelper.h b/code/ColladaHelper.h index fe6674b93..ffab6226d 100644 --- a/code/ColladaHelper.h +++ b/code/ColladaHelper.h @@ -4,7 +4,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/ColladaLoader.cpp b/code/ColladaLoader.cpp index af04e9a16..0c87330a9 100644 --- a/code/ColladaLoader.cpp +++ b/code/ColladaLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/ColladaLoader.h b/code/ColladaLoader.h index d61845b24..72c2dd8e7 100644 --- a/code/ColladaLoader.h +++ b/code/ColladaLoader.h @@ -4,7 +4,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index 052cd51c4..4d599a0c7 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/ColladaParser.h b/code/ColladaParser.h index 21f741551..232d85654 100644 --- a/code/ColladaParser.h +++ b/code/ColladaParser.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- - Copyright (c) 2006-2018, assimp team + Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/ComputeUVMappingProcess.cpp b/code/ComputeUVMappingProcess.cpp index 3b0577b2d..bb571a551 100644 --- a/code/ComputeUVMappingProcess.cpp +++ b/code/ComputeUVMappingProcess.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/ComputeUVMappingProcess.h b/code/ComputeUVMappingProcess.h index 41e25f99f..24f6bb721 100644 --- a/code/ComputeUVMappingProcess.h +++ b/code/ComputeUVMappingProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/ConvertToLHProcess.cpp b/code/ConvertToLHProcess.cpp index 1831739ac..b7cd4f0bc 100644 --- a/code/ConvertToLHProcess.cpp +++ b/code/ConvertToLHProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/ConvertToLHProcess.h b/code/ConvertToLHProcess.h index f219d6ca2..63351568d 100644 --- a/code/ConvertToLHProcess.h +++ b/code/ConvertToLHProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/D3MFExporter.cpp b/code/D3MFExporter.cpp index 99e2ff3f5..e8da91ba9 100644 --- a/code/D3MFExporter.cpp +++ b/code/D3MFExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/D3MFExporter.h b/code/D3MFExporter.h index 110862b99..e82120247 100644 --- a/code/D3MFExporter.h +++ b/code/D3MFExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index de5708149..c218f4005 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/D3MFImporter.h b/code/D3MFImporter.h index 701d056e2..3dbdf07bf 100644 --- a/code/D3MFImporter.h +++ b/code/D3MFImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/D3MFOpcPackage.cpp b/code/D3MFOpcPackage.cpp index 8161a31e4..2545a2750 100644 --- a/code/D3MFOpcPackage.cpp +++ b/code/D3MFOpcPackage.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/D3MFOpcPackage.h b/code/D3MFOpcPackage.h index 6d7b3d478..47c67f45f 100644 --- a/code/D3MFOpcPackage.h +++ b/code/D3MFOpcPackage.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/DXFHelper.h b/code/DXFHelper.h index daf2f97e2..0ec8e130b 100644 --- a/code/DXFHelper.h +++ b/code/DXFHelper.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/DXFLoader.cpp b/code/DXFLoader.cpp index 6710597df..ab86f89ae 100644 --- a/code/DXFLoader.cpp +++ b/code/DXFLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/DXFLoader.h b/code/DXFLoader.h index e7f534e98..044cf6bcb 100644 --- a/code/DXFLoader.h +++ b/code/DXFLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/DeboneProcess.cpp b/code/DeboneProcess.cpp index bc6afa36e..83b8336bc 100644 --- a/code/DeboneProcess.cpp +++ b/code/DeboneProcess.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/DeboneProcess.h b/code/DeboneProcess.h index 3da861362..ba77aba70 100644 --- a/code/DeboneProcess.h +++ b/code/DeboneProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/DefaultIOStream.cpp b/code/DefaultIOStream.cpp index 3b0a672a7..1c100b618 100644 --- a/code/DefaultIOStream.cpp +++ b/code/DefaultIOStream.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/DefaultIOSystem.cpp b/code/DefaultIOSystem.cpp index 67fd82f17..d40b67de3 100644 --- a/code/DefaultIOSystem.cpp +++ b/code/DefaultIOSystem.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/DefaultLogger.cpp b/code/DefaultLogger.cpp index 2871a4131..de3528d2b 100644 --- a/code/DefaultLogger.cpp +++ b/code/DefaultLogger.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/DefaultProgressHandler.h b/code/DefaultProgressHandler.h index 851c17be6..bd2cce00b 100644 --- a/code/DefaultProgressHandler.h +++ b/code/DefaultProgressHandler.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/DropFaceNormalsProcess.cpp b/code/DropFaceNormalsProcess.cpp index 57e8b972b..b11615bb8 100644 --- a/code/DropFaceNormalsProcess.cpp +++ b/code/DropFaceNormalsProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/DropFaceNormalsProcess.h b/code/DropFaceNormalsProcess.h index 6dbfe0397..0d116663b 100644 --- a/code/DropFaceNormalsProcess.h +++ b/code/DropFaceNormalsProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/EmbedTexturesProcess.cpp b/code/EmbedTexturesProcess.cpp index a6dd8457e..739382a05 100644 --- a/code/EmbedTexturesProcess.cpp +++ b/code/EmbedTexturesProcess.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/EmbedTexturesProcess.h b/code/EmbedTexturesProcess.h index ce9821652..cdf40bef7 100644 --- a/code/EmbedTexturesProcess.h +++ b/code/EmbedTexturesProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/Exporter.cpp b/code/Exporter.cpp index 0acde75bf..8848e87f5 100644 --- a/code/Exporter.cpp +++ b/code/Exporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/FBXAnimation.cpp b/code/FBXAnimation.cpp index 871d62578..874914431 100644 --- a/code/FBXAnimation.cpp +++ b/code/FBXAnimation.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXBinaryTokenizer.cpp b/code/FBXBinaryTokenizer.cpp index b81a9f945..f12a5c5b2 100644 --- a/code/FBXBinaryTokenizer.cpp +++ b/code/FBXBinaryTokenizer.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXCommon.h b/code/FBXCommon.h index 60b040552..fcb20a5ca 100644 --- a/code/FBXCommon.h +++ b/code/FBXCommon.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXCompileConfig.h b/code/FBXCompileConfig.h index 2e7336e85..3a3841fa5 100644 --- a/code/FBXCompileConfig.h +++ b/code/FBXCompileConfig.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index fd4986a3c..d88a3cacd 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXConverter.h b/code/FBXConverter.h index 796b3e2f0..398baa445 100644 --- a/code/FBXConverter.h +++ b/code/FBXConverter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXDeformer.cpp b/code/FBXDeformer.cpp index fc8b38e57..692755345 100644 --- a/code/FBXDeformer.cpp +++ b/code/FBXDeformer.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXDocument.cpp b/code/FBXDocument.cpp index deac89ca0..2e0d00a79 100644 --- a/code/FBXDocument.cpp +++ b/code/FBXDocument.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXDocument.h b/code/FBXDocument.h index 02accf92e..cbc6d60cd 100644 --- a/code/FBXDocument.h +++ b/code/FBXDocument.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXDocumentUtil.cpp b/code/FBXDocumentUtil.cpp index 6f1e18e42..f84691479 100644 --- a/code/FBXDocumentUtil.cpp +++ b/code/FBXDocumentUtil.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXExportNode.cpp b/code/FBXExportNode.cpp index a1171eca8..ace6a6ac2 100644 --- a/code/FBXExportNode.cpp +++ b/code/FBXExportNode.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXExportNode.h b/code/FBXExportNode.h index b9cd5156f..e1ebc3696 100644 --- a/code/FBXExportNode.h +++ b/code/FBXExportNode.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXExportProperty.cpp b/code/FBXExportProperty.cpp index 431750274..9981d6b1c 100644 --- a/code/FBXExportProperty.cpp +++ b/code/FBXExportProperty.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXExportProperty.h b/code/FBXExportProperty.h index cb3b0113f..9c9d37c36 100644 --- a/code/FBXExportProperty.h +++ b/code/FBXExportProperty.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index ce00deee3..acb122714 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXExporter.h b/code/FBXExporter.h index c27d1a8ce..71fb55c57 100644 --- a/code/FBXExporter.h +++ b/code/FBXExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXImportSettings.h b/code/FBXImportSettings.h index e612fddef..d5e1c2060 100644 --- a/code/FBXImportSettings.h +++ b/code/FBXImportSettings.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXImporter.cpp b/code/FBXImporter.cpp index b004bcd8c..72f8eea8e 100644 --- a/code/FBXImporter.cpp +++ b/code/FBXImporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXImporter.h b/code/FBXImporter.h index 870f1c49b..c365b2cdd 100644 --- a/code/FBXImporter.h +++ b/code/FBXImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXMaterial.cpp b/code/FBXMaterial.cpp index 75b2e3b4b..f5f6fda03 100644 --- a/code/FBXMaterial.cpp +++ b/code/FBXMaterial.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXMeshGeometry.cpp b/code/FBXMeshGeometry.cpp index faa5de75c..d75476b82 100644 --- a/code/FBXMeshGeometry.cpp +++ b/code/FBXMeshGeometry.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXMeshGeometry.h b/code/FBXMeshGeometry.h index 641461a69..d6d451217 100644 --- a/code/FBXMeshGeometry.h +++ b/code/FBXMeshGeometry.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXModel.cpp b/code/FBXModel.cpp index c16ca841c..589af36ac 100644 --- a/code/FBXModel.cpp +++ b/code/FBXModel.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXNodeAttribute.cpp b/code/FBXNodeAttribute.cpp index 1064151b3..b72e5637e 100644 --- a/code/FBXNodeAttribute.cpp +++ b/code/FBXNodeAttribute.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXParser.cpp b/code/FBXParser.cpp index 96d113bd1..b255c4734 100644 --- a/code/FBXParser.cpp +++ b/code/FBXParser.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXParser.h b/code/FBXParser.h index 389da3fed..7b0cf7203 100644 --- a/code/FBXParser.h +++ b/code/FBXParser.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXProperties.cpp b/code/FBXProperties.cpp index ca89743ca..8d7036b6a 100644 --- a/code/FBXProperties.cpp +++ b/code/FBXProperties.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXProperties.h b/code/FBXProperties.h index 404e04deb..58755542f 100644 --- a/code/FBXProperties.h +++ b/code/FBXProperties.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXTokenizer.cpp b/code/FBXTokenizer.cpp index c9dd1697a..252cce355 100644 --- a/code/FBXTokenizer.cpp +++ b/code/FBXTokenizer.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXTokenizer.h b/code/FBXTokenizer.h index e93982617..2af29743f 100644 --- a/code/FBXTokenizer.h +++ b/code/FBXTokenizer.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXUtil.cpp b/code/FBXUtil.cpp index 992c30efc..c184c4a00 100644 --- a/code/FBXUtil.cpp +++ b/code/FBXUtil.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FBXUtil.h b/code/FBXUtil.h index caea7f115..1a37d346b 100644 --- a/code/FBXUtil.h +++ b/code/FBXUtil.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FIReader.cpp b/code/FIReader.cpp index bdc447b34..2116316ca 100755 --- a/code/FIReader.cpp +++ b/code/FIReader.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FIReader.hpp b/code/FIReader.hpp index 9ff752d5c..29e3ddb1b 100644 --- a/code/FIReader.hpp +++ b/code/FIReader.hpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FileLogStream.h b/code/FileLogStream.h index 9966091d2..740c50319 100644 --- a/code/FileLogStream.h +++ b/code/FileLogStream.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FindDegenerates.cpp b/code/FindDegenerates.cpp index c0c0de08b..365f5d744 100644 --- a/code/FindDegenerates.cpp +++ b/code/FindDegenerates.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/FindDegenerates.h b/code/FindDegenerates.h index c234c57f5..880f5f16a 100644 --- a/code/FindDegenerates.h +++ b/code/FindDegenerates.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FindInstancesProcess.cpp b/code/FindInstancesProcess.cpp index 25dcc51e8..23f9d1581 100644 --- a/code/FindInstancesProcess.cpp +++ b/code/FindInstancesProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/FindInstancesProcess.h b/code/FindInstancesProcess.h index fb2ac6eb6..ab4a371c7 100644 --- a/code/FindInstancesProcess.h +++ b/code/FindInstancesProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FindInvalidDataProcess.cpp b/code/FindInvalidDataProcess.cpp index c775187e9..c99a98865 100644 --- a/code/FindInvalidDataProcess.cpp +++ b/code/FindInvalidDataProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/FindInvalidDataProcess.h b/code/FindInvalidDataProcess.h index f5a49f496..8504fb7b1 100644 --- a/code/FindInvalidDataProcess.h +++ b/code/FindInvalidDataProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/FixNormalsStep.cpp b/code/FixNormalsStep.cpp index 668b50c24..bbbe6899b 100644 --- a/code/FixNormalsStep.cpp +++ b/code/FixNormalsStep.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/FixNormalsStep.h b/code/FixNormalsStep.h index 389e6e1a6..6be27faef 100644 --- a/code/FixNormalsStep.h +++ b/code/FixNormalsStep.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/GenFaceNormalsProcess.cpp b/code/GenFaceNormalsProcess.cpp index 43960ac3b..028334dec 100644 --- a/code/GenFaceNormalsProcess.cpp +++ b/code/GenFaceNormalsProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/GenFaceNormalsProcess.h b/code/GenFaceNormalsProcess.h index e2f41e07f..c80ec9fdd 100644 --- a/code/GenFaceNormalsProcess.h +++ b/code/GenFaceNormalsProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/GenVertexNormalsProcess.cpp b/code/GenVertexNormalsProcess.cpp index 1778ef513..3f6c2f86b 100644 --- a/code/GenVertexNormalsProcess.cpp +++ b/code/GenVertexNormalsProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/GenVertexNormalsProcess.h b/code/GenVertexNormalsProcess.h index 2efafa302..9142ad26f 100644 --- a/code/GenVertexNormalsProcess.h +++ b/code/GenVertexNormalsProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/HMPFileData.h b/code/HMPFileData.h index 962f2f9c7..ab4100174 100644 --- a/code/HMPFileData.h +++ b/code/HMPFileData.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/HMPLoader.cpp b/code/HMPLoader.cpp index 7f53f9b54..7c1d0b65f 100644 --- a/code/HMPLoader.cpp +++ b/code/HMPLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/HMPLoader.h b/code/HMPLoader.h index 4e513aee6..d0a34bfb7 100644 --- a/code/HMPLoader.h +++ b/code/HMPLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/HalfLifeFileData.h b/code/HalfLifeFileData.h index 7c55657d4..ef328edf8 100644 --- a/code/HalfLifeFileData.h +++ b/code/HalfLifeFileData.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/IRRLoader.cpp b/code/IRRLoader.cpp index 9432eff61..6bc4b8ce4 100644 --- a/code/IRRLoader.cpp +++ b/code/IRRLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/IRRLoader.h b/code/IRRLoader.h index 3bd39092a..e245a0a6f 100644 --- a/code/IRRLoader.h +++ b/code/IRRLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/IRRMeshLoader.cpp b/code/IRRMeshLoader.cpp index 85de42195..f3aed5943 100644 --- a/code/IRRMeshLoader.cpp +++ b/code/IRRMeshLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/IRRMeshLoader.h b/code/IRRMeshLoader.h index ef6a8a11b..d8b42d78d 100644 --- a/code/IRRMeshLoader.h +++ b/code/IRRMeshLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/IRRShared.cpp b/code/IRRShared.cpp index 1e69f1d09..ecac031ab 100644 --- a/code/IRRShared.cpp +++ b/code/IRRShared.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/Importer.cpp b/code/Importer.cpp index da395edb2..65b16471c 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/Importer.h b/code/Importer.h index c6628c428..a439d99c2 100644 --- a/code/Importer.h +++ b/code/Importer.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/Importer/IFC/IFCCurve.cpp b/code/Importer/IFC/IFCCurve.cpp index af58e7b10..b0a1fdaa9 100644 --- a/code/Importer/IFC/IFCCurve.cpp +++ b/code/Importer/IFC/IFCCurve.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/Importer/IFC/IFCLoader.cpp b/code/Importer/IFC/IFCLoader.cpp index 2c95872d3..368f98ec0 100644 --- a/code/Importer/IFC/IFCLoader.cpp +++ b/code/Importer/IFC/IFCLoader.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/Importer/IFC/IFCLoader.h b/code/Importer/IFC/IFCLoader.h index 99e3e8ed9..678c60343 100644 --- a/code/Importer/IFC/IFCLoader.h +++ b/code/Importer/IFC/IFCLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/Importer/IFC/IFCMaterial.cpp b/code/Importer/IFC/IFCMaterial.cpp index 423d1471e..5fda0a1de 100644 --- a/code/Importer/IFC/IFCMaterial.cpp +++ b/code/Importer/IFC/IFCMaterial.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/Importer/IFC/IFCProfile.cpp b/code/Importer/IFC/IFCProfile.cpp index 2236d0d9b..daafc9afe 100644 --- a/code/Importer/IFC/IFCProfile.cpp +++ b/code/Importer/IFC/IFCProfile.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/Importer/IFC/IFCUtil.cpp b/code/Importer/IFC/IFCUtil.cpp index 06cc4405a..b9a8538b0 100644 --- a/code/Importer/IFC/IFCUtil.cpp +++ b/code/Importer/IFC/IFCUtil.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/Importer/IFC/IFCUtil.h b/code/Importer/IFC/IFCUtil.h index 194206d4b..17051210e 100644 --- a/code/Importer/IFC/IFCUtil.h +++ b/code/Importer/IFC/IFCUtil.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/Importer/STEPParser/STEPFileEncoding.cpp b/code/Importer/STEPParser/STEPFileEncoding.cpp index 70d5f4e4b..1d7ac3418 100644 --- a/code/Importer/STEPParser/STEPFileEncoding.cpp +++ b/code/Importer/STEPParser/STEPFileEncoding.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/Importer/STEPParser/STEPFileEncoding.h b/code/Importer/STEPParser/STEPFileEncoding.h index 232cb81ba..09f16ba33 100644 --- a/code/Importer/STEPParser/STEPFileEncoding.h +++ b/code/Importer/STEPParser/STEPFileEncoding.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/Importer/STEPParser/STEPFileReader.cpp b/code/Importer/STEPParser/STEPFileReader.cpp index c7cad05ae..1707899a1 100644 --- a/code/Importer/STEPParser/STEPFileReader.cpp +++ b/code/Importer/STEPParser/STEPFileReader.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -63,7 +63,6 @@ std::string AddLineNumber(const std::string& s,uint64_t line /*= LINE_NOT_SPECIF return line == STEP::SyntaxError::LINE_NOT_SPECIFIED ? prefix+s : static_cast( (Formatter::format(),prefix,"(line ",line,") ",s) ); } - // ------------------------------------------------------------------------------------------------ std::string AddEntityID(const std::string& s,uint64_t entity /*= ENTITY_NOT_SPECIFIED*/, const std::string& prefix = "") { @@ -243,7 +242,6 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, std::string::size_type n2 = s.find_last_of(')'); if (n2 == std::string::npos || n2 < n1 || n2 == s.length() - 1 || s[n2 + 1] != ';') { - has_next = true; bool ok = false; for( ++splitter; splitter; ++splitter) { @@ -251,14 +249,14 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, if (snext.empty()) { continue; } + // the next line doesn't start an entity, so maybe it is // just a continuation for this line, keep going if (!IsEntityDef(snext)) { s.append(snext); n2 = s.find_last_of(')'); ok = !(n2 == std::string::npos || n2 < n1 || n2 == s.length() - 1 || s[n2 + 1] != ';'); - } - else { + } else { break; } } @@ -424,10 +422,8 @@ std::shared_ptr EXPRESS::DataType::Parse(const char*& i return std::make_shared(neg?-num:num); } - // ------------------------------------------------------------------------------------------------ -std::shared_ptr EXPRESS::LIST::Parse(const char*& inout,uint64_t line, const EXPRESS::ConversionSchema* schema /*= NULL*/) -{ +std::shared_ptr EXPRESS::LIST::Parse(const char*& inout,uint64_t line, const EXPRESS::ConversionSchema* schema /*= NULL*/) { const std::shared_ptr list = std::make_shared(); EXPRESS::LIST::MemberList& members = list->members; @@ -468,61 +464,73 @@ std::shared_ptr EXPRESS::LIST::Parse(const char*& inout,uin return list; } +// ------------------------------------------------------------------------------------------------ +static void handleSkippedDepthFromToken(const char *a, int64_t &skip_depth ) { + if (*a == '(') { + ++skip_depth; + } else if (*a == ')') { + --skip_depth; + } +} + +// ------------------------------------------------------------------------------------------------ +static int64_t getIdFromToken(const char *a) { + const char *tmp; + const int64_t num = static_cast(strtoul10_64(a + 1, &tmp)); + + return num; +} // ------------------------------------------------------------------------------------------------ STEP::LazyObject::LazyObject(DB& db, uint64_t id,uint64_t /*line*/, const char* const type,const char* args) - : id(id) - , type(type) - , db(db) - , args(args) - , obj() -{ +: id(id) +, type(type) +, db(db) +, args(args) +, obj() { // find any external references and store them in the database. // this helps us emulate STEPs INVERSE fields. - if (db.KeepInverseIndicesForType(type)) { - const char* a = args; + if (!db.KeepInverseIndicesForType(type)) { + return; + } - // do a quick scan through the argument tuple and watch out for entity references - int64_t skip_depth = 0; - while(*a) { - if (*a == '(') { - ++skip_depth; - } - else if (*a == ')') { - --skip_depth; - } + // do a quick scan through the argument tuple and watch out for entity references + const char *a( args ); + int64_t skip_depth( 0 ); + while ( *a ) { + handleSkippedDepthFromToken(a, skip_depth); + /*if (*a == '(') { + ++skip_depth; + } else if (*a == ')') { + --skip_depth; + }*/ - if (skip_depth >= 1 && *a=='#') { - if (*(a + 1) != '#') - { - const char* tmp; - const int64_t num = static_cast(strtoul10_64(a + 1, &tmp)); - db.MarkRef(num, id); - } - else - { - ++a; - } - } - ++a; + if (skip_depth >= 1 && *a=='#') { + if (*(a + 1) != '#') { + /*const char *tmp; + const int64_t num = static_cast(strtoul10_64(a + 1, &tmp)); + db.MarkRef(num, id);*/ + db.MarkRef(getIdFromToken(a), id); + } else { + ++a; + } } - + ++a; } } // ------------------------------------------------------------------------------------------------ -STEP::LazyObject::~LazyObject() -{ +STEP::LazyObject::~LazyObject() { // make sure the right dtor/operator delete get called if (obj) { delete obj; + } else { + delete[] args; } - else delete[] args; } // ------------------------------------------------------------------------------------------------ -void STEP::LazyObject::LazyInit() const -{ +void STEP::LazyObject::LazyInit() const { const EXPRESS::ConversionSchema& schema = db.GetSchema(); STEP::ConvertObjectProc proc = schema.GetConverterProc(type); diff --git a/code/Importer/STEPParser/STEPFileReader.h b/code/Importer/STEPParser/STEPFileReader.h index 667d28bfd..8fc462749 100644 --- a/code/Importer/STEPParser/STEPFileReader.h +++ b/code/Importer/STEPParser/STEPFileReader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -68,4 +68,4 @@ void ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, const char* const } // ! STEP } // ! Assimp -#endif +#endif // INCLUDED_AI_STEPFILEREADER_H diff --git a/code/Importer/StepFile/StepFileImporter.cpp b/code/Importer/StepFile/StepFileImporter.cpp index edfe30754..26c456ac9 100644 --- a/code/Importer/StepFile/StepFileImporter.cpp +++ b/code/Importer/StepFile/StepFileImporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/Importer/StepFile/StepFileImporter.h b/code/Importer/StepFile/StepFileImporter.h index 68d5a09ad..70f65fdcf 100644 --- a/code/Importer/StepFile/StepFileImporter.h +++ b/code/Importer/StepFile/StepFileImporter.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/ImporterRegistry.cpp b/code/ImporterRegistry.cpp index e6cf8299e..747815fa6 100644 --- a/code/ImporterRegistry.cpp +++ b/code/ImporterRegistry.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/ImproveCacheLocality.cpp b/code/ImproveCacheLocality.cpp index adcbc92fe..be6452dda 100644 --- a/code/ImproveCacheLocality.cpp +++ b/code/ImproveCacheLocality.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/ImproveCacheLocality.h b/code/ImproveCacheLocality.h index 18eb5e460..1b29ee0d6 100644 --- a/code/ImproveCacheLocality.h +++ b/code/ImproveCacheLocality.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/JoinVerticesProcess.cpp b/code/JoinVerticesProcess.cpp index b91f44048..914ec05b4 100644 --- a/code/JoinVerticesProcess.cpp +++ b/code/JoinVerticesProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/JoinVerticesProcess.h b/code/JoinVerticesProcess.h index a7366efbe..66fa362de 100644 --- a/code/JoinVerticesProcess.h +++ b/code/JoinVerticesProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/LWOAnimation.cpp b/code/LWOAnimation.cpp index ff02a8eab..3a0d2c392 100644 --- a/code/LWOAnimation.cpp +++ b/code/LWOAnimation.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/LWOAnimation.h b/code/LWOAnimation.h index f7b0f177b..dd29695cc 100644 --- a/code/LWOAnimation.h +++ b/code/LWOAnimation.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/LWOBLoader.cpp b/code/LWOBLoader.cpp index fabf99cad..b24957072 100644 --- a/code/LWOBLoader.cpp +++ b/code/LWOBLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/LWOFileData.h b/code/LWOFileData.h index b3a963199..a702d9363 100644 --- a/code/LWOFileData.h +++ b/code/LWOFileData.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/LWOLoader.cpp b/code/LWOLoader.cpp index fbefe4a1e..d1c2641e8 100644 --- a/code/LWOLoader.cpp +++ b/code/LWOLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/LWOLoader.h b/code/LWOLoader.h index 4d42eb2d2..05b958fd2 100644 --- a/code/LWOLoader.h +++ b/code/LWOLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/LWOMaterial.cpp b/code/LWOMaterial.cpp index 15c210460..55d0e23f1 100644 --- a/code/LWOMaterial.cpp +++ b/code/LWOMaterial.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/LWSLoader.cpp b/code/LWSLoader.cpp index 6f8cbe78d..d0811625c 100644 --- a/code/LWSLoader.cpp +++ b/code/LWSLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/LWSLoader.h b/code/LWSLoader.h index 9f1636f21..3c24b59ea 100644 --- a/code/LWSLoader.h +++ b/code/LWSLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/LimitBoneWeightsProcess.cpp b/code/LimitBoneWeightsProcess.cpp index cc87e407c..d560f1928 100644 --- a/code/LimitBoneWeightsProcess.cpp +++ b/code/LimitBoneWeightsProcess.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/LimitBoneWeightsProcess.h b/code/LimitBoneWeightsProcess.h index 2161b89a8..3602fd8ed 100644 --- a/code/LimitBoneWeightsProcess.h +++ b/code/LimitBoneWeightsProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/MD2FileData.h b/code/MD2FileData.h index 4b893bbb1..9fcb8b0e2 100644 --- a/code/MD2FileData.h +++ b/code/MD2FileData.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/MD2Loader.cpp b/code/MD2Loader.cpp index cfd5458e7..a26f70533 100644 --- a/code/MD2Loader.cpp +++ b/code/MD2Loader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/MD2Loader.h b/code/MD2Loader.h index f26b31736..a3863f366 100644 --- a/code/MD2Loader.h +++ b/code/MD2Loader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/MD2NormalTable.h b/code/MD2NormalTable.h index dd2c837b4..f82b57683 100644 --- a/code/MD2NormalTable.h +++ b/code/MD2NormalTable.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/MD3FileData.h b/code/MD3FileData.h index 910813fc4..0978e548d 100644 --- a/code/MD3FileData.h +++ b/code/MD3FileData.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/MD3Loader.cpp b/code/MD3Loader.cpp index d12f2d5fd..0faffd5f9 100644 --- a/code/MD3Loader.cpp +++ b/code/MD3Loader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/MD3Loader.h b/code/MD3Loader.h index 8ac3cdc68..01b840228 100644 --- a/code/MD3Loader.h +++ b/code/MD3Loader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/MD5Loader.cpp b/code/MD5Loader.cpp index a4285ba03..346b59504 100644 --- a/code/MD5Loader.cpp +++ b/code/MD5Loader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/MD5Loader.h b/code/MD5Loader.h index 1ba5fea68..e15cc3fb9 100644 --- a/code/MD5Loader.h +++ b/code/MD5Loader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/MD5Parser.cpp b/code/MD5Parser.cpp index 6f942228c..2770226a9 100644 --- a/code/MD5Parser.cpp +++ b/code/MD5Parser.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/MD5Parser.h b/code/MD5Parser.h index 853268424..f7ff5303f 100644 --- a/code/MD5Parser.h +++ b/code/MD5Parser.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/MDCFileData.h b/code/MDCFileData.h index c599a930a..052473158 100644 --- a/code/MDCFileData.h +++ b/code/MDCFileData.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/MDCLoader.cpp b/code/MDCLoader.cpp index 03b3336de..42947f123 100644 --- a/code/MDCLoader.cpp +++ b/code/MDCLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/MDCLoader.h b/code/MDCLoader.h index 5bbe2b666..a21b8a55a 100644 --- a/code/MDCLoader.h +++ b/code/MDCLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/MDLDefaultColorMap.h b/code/MDLDefaultColorMap.h index b96a60a06..58f642884 100644 --- a/code/MDLDefaultColorMap.h +++ b/code/MDLDefaultColorMap.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/MDLFileData.h b/code/MDLFileData.h index f9be6761b..f33a57731 100644 --- a/code/MDLFileData.h +++ b/code/MDLFileData.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/MDLLoader.cpp b/code/MDLLoader.cpp index eb067a1c9..256d79a2c 100644 --- a/code/MDLLoader.cpp +++ b/code/MDLLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/MDLLoader.h b/code/MDLLoader.h index f1504beea..7009d5ba4 100644 --- a/code/MDLLoader.h +++ b/code/MDLLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/MDLMaterialLoader.cpp b/code/MDLMaterialLoader.cpp index 2c21b188b..0a196761f 100644 --- a/code/MDLMaterialLoader.cpp +++ b/code/MDLMaterialLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/MMDCpp14.h b/code/MMDCpp14.h index 5ec2fd975..638b0bfd2 100644 --- a/code/MMDCpp14.h +++ b/code/MMDCpp14.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/MMDPmdParser.h b/code/MMDPmdParser.h index d61a355fb..d2f2224aa 100644 --- a/code/MMDPmdParser.h +++ b/code/MMDPmdParser.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/MMDPmxParser.cpp b/code/MMDPmxParser.cpp index 2c5bd9a8d..7425ceac2 100644 --- a/code/MMDPmxParser.cpp +++ b/code/MMDPmxParser.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/MMDPmxParser.h b/code/MMDPmxParser.h index 43cad5899..cf523a129 100644 --- a/code/MMDPmxParser.h +++ b/code/MMDPmxParser.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/MMDVmdParser.h b/code/MMDVmdParser.h index 600959e94..947c3a242 100644 --- a/code/MMDVmdParser.h +++ b/code/MMDVmdParser.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/MS3DLoader.cpp b/code/MS3DLoader.cpp index c659d2ec7..c0d0eddbe 100644 --- a/code/MS3DLoader.cpp +++ b/code/MS3DLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/MS3DLoader.h b/code/MS3DLoader.h index 2efa3be5f..3e39dc79f 100644 --- a/code/MS3DLoader.h +++ b/code/MS3DLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/MakeVerboseFormat.cpp b/code/MakeVerboseFormat.cpp index b6f5cabd9..50ff5ed93 100644 --- a/code/MakeVerboseFormat.cpp +++ b/code/MakeVerboseFormat.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/MakeVerboseFormat.h b/code/MakeVerboseFormat.h index 292d9bea6..d12db63ae 100644 --- a/code/MakeVerboseFormat.h +++ b/code/MakeVerboseFormat.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/MaterialSystem.cpp b/code/MaterialSystem.cpp index e9ca475fb..03d5a18a3 100644 --- a/code/MaterialSystem.cpp +++ b/code/MaterialSystem.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/MaterialSystem.h b/code/MaterialSystem.h index d6f2cea46..67d53578c 100644 --- a/code/MaterialSystem.h +++ b/code/MaterialSystem.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/NDOLoader.cpp b/code/NDOLoader.cpp index 17c9e135b..d33f40c75 100644 --- a/code/NDOLoader.cpp +++ b/code/NDOLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/NFFLoader.cpp b/code/NFFLoader.cpp index 1c7283db6..10a7d1aff 100644 --- a/code/NFFLoader.cpp +++ b/code/NFFLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/NFFLoader.h b/code/NFFLoader.h index 1e3f0bd26..bc4840e14 100644 --- a/code/NFFLoader.h +++ b/code/NFFLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/OFFLoader.cpp b/code/OFFLoader.cpp index a72e6d9d4..afd44a539 100644 --- a/code/OFFLoader.cpp +++ b/code/OFFLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/OFFLoader.h b/code/OFFLoader.h index ed1ed98c1..3fca77e1b 100644 --- a/code/OFFLoader.h +++ b/code/OFFLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/ObjExporter.cpp b/code/ObjExporter.cpp index 1542efebf..08cba43f7 100644 --- a/code/ObjExporter.cpp +++ b/code/ObjExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/ObjExporter.h b/code/ObjExporter.h index bd745b593..0d2b48d6b 100644 --- a/code/ObjExporter.h +++ b/code/ObjExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/ObjFileData.h b/code/ObjFileData.h index 38786e6f4..5ff9db68c 100644 --- a/code/ObjFileData.h +++ b/code/ObjFileData.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/ObjFileImporter.cpp b/code/ObjFileImporter.cpp index 93b2de6f4..782b62a73 100644 --- a/code/ObjFileImporter.cpp +++ b/code/ObjFileImporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/ObjFileImporter.h b/code/ObjFileImporter.h index f564fe22b..0df2ef731 100644 --- a/code/ObjFileImporter.h +++ b/code/ObjFileImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/ObjFileMtlImporter.cpp b/code/ObjFileMtlImporter.cpp index 16bde1b43..dd9cc3ce2 100644 --- a/code/ObjFileMtlImporter.cpp +++ b/code/ObjFileMtlImporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/ObjFileMtlImporter.h b/code/ObjFileMtlImporter.h index d6a7b1f1a..731952359 100644 --- a/code/ObjFileMtlImporter.h +++ b/code/ObjFileMtlImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/ObjFileParser.cpp b/code/ObjFileParser.cpp index d3bb6f50f..d303cb8b9 100644 --- a/code/ObjFileParser.cpp +++ b/code/ObjFileParser.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/ObjFileParser.h b/code/ObjFileParser.h index 7cf06ae05..e00382f4c 100644 --- a/code/ObjFileParser.h +++ b/code/ObjFileParser.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/ObjTools.h b/code/ObjTools.h index 842efd749..3f4c41033 100644 --- a/code/ObjTools.h +++ b/code/ObjTools.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/OgreBinarySerializer.cpp b/code/OgreBinarySerializer.cpp index 8948844d0..b2326e244 100644 --- a/code/OgreBinarySerializer.cpp +++ b/code/OgreBinarySerializer.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/OgreBinarySerializer.h b/code/OgreBinarySerializer.h index a31047c70..8bab00ce9 100644 --- a/code/OgreBinarySerializer.h +++ b/code/OgreBinarySerializer.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/OgreImporter.cpp b/code/OgreImporter.cpp index e77654d7b..c2c328a47 100644 --- a/code/OgreImporter.cpp +++ b/code/OgreImporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/OgreImporter.h b/code/OgreImporter.h index 8f088a3cc..321d58763 100644 --- a/code/OgreImporter.h +++ b/code/OgreImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/OgreMaterial.cpp b/code/OgreMaterial.cpp index ceca04da1..47cb17eb0 100644 --- a/code/OgreMaterial.cpp +++ b/code/OgreMaterial.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/OgreParsingUtils.h b/code/OgreParsingUtils.h index c6b6e0caf..8786521e4 100644 --- a/code/OgreParsingUtils.h +++ b/code/OgreParsingUtils.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/OgreStructs.cpp b/code/OgreStructs.cpp index b2ad8e089..7962202c1 100644 --- a/code/OgreStructs.cpp +++ b/code/OgreStructs.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/OgreStructs.h b/code/OgreStructs.h index dfe0346dc..6ea211e10 100644 --- a/code/OgreStructs.h +++ b/code/OgreStructs.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/OgreXmlSerializer.cpp b/code/OgreXmlSerializer.cpp index 5805a528d..19fd3ad61 100644 --- a/code/OgreXmlSerializer.cpp +++ b/code/OgreXmlSerializer.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/OgreXmlSerializer.h b/code/OgreXmlSerializer.h index c0f09096c..7e5e83fec 100644 --- a/code/OgreXmlSerializer.h +++ b/code/OgreXmlSerializer.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/OpenGEXExporter.cpp b/code/OpenGEXExporter.cpp index ea2f64e8f..635174185 100644 --- a/code/OpenGEXExporter.cpp +++ b/code/OpenGEXExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/OpenGEXExporter.h b/code/OpenGEXExporter.h index 76d2418a4..b9b54c208 100644 --- a/code/OpenGEXExporter.h +++ b/code/OpenGEXExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/OpenGEXImporter.cpp b/code/OpenGEXImporter.cpp index 2de0aabc0..a7a143035 100644 --- a/code/OpenGEXImporter.cpp +++ b/code/OpenGEXImporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/OpenGEXImporter.h b/code/OpenGEXImporter.h index 8e86a4aa8..22b5cabef 100644 --- a/code/OpenGEXImporter.h +++ b/code/OpenGEXImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/OpenGEXStructs.h b/code/OpenGEXStructs.h index 6cd7488e9..2c83e8660 100644 --- a/code/OpenGEXStructs.h +++ b/code/OpenGEXStructs.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/OptimizeGraph.cpp b/code/OptimizeGraph.cpp index 59a764d5c..add9ab79e 100644 --- a/code/OptimizeGraph.cpp +++ b/code/OptimizeGraph.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/OptimizeGraph.h b/code/OptimizeGraph.h index 6781ec534..e5bbed767 100644 --- a/code/OptimizeGraph.h +++ b/code/OptimizeGraph.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/OptimizeMeshes.cpp b/code/OptimizeMeshes.cpp index 25575b049..3f6765f6c 100644 --- a/code/OptimizeMeshes.cpp +++ b/code/OptimizeMeshes.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/OptimizeMeshes.h b/code/OptimizeMeshes.h index 3ebe60cd8..9f46f349b 100644 --- a/code/OptimizeMeshes.h +++ b/code/OptimizeMeshes.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/PlyExporter.cpp b/code/PlyExporter.cpp index 31c64a4d1..4f9fa6c6f 100644 --- a/code/PlyExporter.cpp +++ b/code/PlyExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/PlyExporter.h b/code/PlyExporter.h index 060aa7ceb..b82498cbd 100644 --- a/code/PlyExporter.h +++ b/code/PlyExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/PlyLoader.cpp b/code/PlyLoader.cpp index 7e55e6c3e..3924305cb 100644 --- a/code/PlyLoader.cpp +++ b/code/PlyLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/PlyLoader.h b/code/PlyLoader.h index 9199e17d7..201c463b2 100644 --- a/code/PlyLoader.h +++ b/code/PlyLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/PlyParser.cpp b/code/PlyParser.cpp index b51b6ac71..2a6f00ad6 100644 --- a/code/PlyParser.cpp +++ b/code/PlyParser.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/PlyParser.h b/code/PlyParser.h index b544c3b04..a11b411d1 100644 --- a/code/PlyParser.h +++ b/code/PlyParser.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/PolyTools.h b/code/PolyTools.h index f43bd9de1..fbbda0e7d 100644 --- a/code/PolyTools.h +++ b/code/PolyTools.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/PostStepRegistry.cpp b/code/PostStepRegistry.cpp index 646aeaeb0..469a8ef39 100644 --- a/code/PostStepRegistry.cpp +++ b/code/PostStepRegistry.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/PretransformVertices.cpp b/code/PretransformVertices.cpp index 9745abd60..52001a057 100644 --- a/code/PretransformVertices.cpp +++ b/code/PretransformVertices.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/PretransformVertices.h b/code/PretransformVertices.h index a8196289d..b7329af13 100644 --- a/code/PretransformVertices.h +++ b/code/PretransformVertices.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/ProcessHelper.cpp b/code/ProcessHelper.cpp index 7f3e4ba72..59869fdff 100644 --- a/code/ProcessHelper.cpp +++ b/code/ProcessHelper.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/ProcessHelper.h b/code/ProcessHelper.h index dcf71e853..c59f3217b 100644 --- a/code/ProcessHelper.h +++ b/code/ProcessHelper.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/Q3BSPFileData.h b/code/Q3BSPFileData.h index d814837c2..4e05bebf1 100644 --- a/code/Q3BSPFileData.h +++ b/code/Q3BSPFileData.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/Q3BSPFileImporter.cpp b/code/Q3BSPFileImporter.cpp index 8b9e3c037..6a3b95bb8 100644 --- a/code/Q3BSPFileImporter.cpp +++ b/code/Q3BSPFileImporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/Q3BSPFileImporter.h b/code/Q3BSPFileImporter.h index 5f3e31157..5af9fb7bc 100644 --- a/code/Q3BSPFileImporter.h +++ b/code/Q3BSPFileImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/Q3BSPFileParser.cpp b/code/Q3BSPFileParser.cpp index f7038adeb..5bac5ae76 100644 --- a/code/Q3BSPFileParser.cpp +++ b/code/Q3BSPFileParser.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/Q3BSPFileParser.h b/code/Q3BSPFileParser.h index 747d1d494..143e42b15 100644 --- a/code/Q3BSPFileParser.h +++ b/code/Q3BSPFileParser.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/Q3BSPZipArchive.cpp b/code/Q3BSPZipArchive.cpp index 3e1087b9a..0b6664842 100644 --- a/code/Q3BSPZipArchive.cpp +++ b/code/Q3BSPZipArchive.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/Q3BSPZipArchive.h b/code/Q3BSPZipArchive.h index 606f7b183..2fdc781f8 100644 --- a/code/Q3BSPZipArchive.h +++ b/code/Q3BSPZipArchive.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/Q3DLoader.cpp b/code/Q3DLoader.cpp index 1aa7cb72f..b8c8de716 100644 --- a/code/Q3DLoader.cpp +++ b/code/Q3DLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/Q3DLoader.h b/code/Q3DLoader.h index bdb104df3..954d3105c 100644 --- a/code/Q3DLoader.h +++ b/code/Q3DLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/RawLoader.cpp b/code/RawLoader.cpp index 1bc508759..d0da247e4 100644 --- a/code/RawLoader.cpp +++ b/code/RawLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/RawLoader.h b/code/RawLoader.h index f6e894fdd..8bfe8ef98 100644 --- a/code/RawLoader.h +++ b/code/RawLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/RemoveComments.cpp b/code/RemoveComments.cpp index 3ba3c60be..91700a769 100644 --- a/code/RemoveComments.cpp +++ b/code/RemoveComments.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/RemoveRedundantMaterials.cpp b/code/RemoveRedundantMaterials.cpp index 7194d3c8e..632bdca3f 100644 --- a/code/RemoveRedundantMaterials.cpp +++ b/code/RemoveRedundantMaterials.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/RemoveRedundantMaterials.h b/code/RemoveRedundantMaterials.h index 314bbf345..dbd4d44cc 100644 --- a/code/RemoveRedundantMaterials.h +++ b/code/RemoveRedundantMaterials.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/RemoveVCProcess.cpp b/code/RemoveVCProcess.cpp index 81249eab2..99fd47a3a 100644 --- a/code/RemoveVCProcess.cpp +++ b/code/RemoveVCProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/RemoveVCProcess.h b/code/RemoveVCProcess.h index 597de8584..617d7b9b2 100644 --- a/code/RemoveVCProcess.h +++ b/code/RemoveVCProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/SGSpatialSort.cpp b/code/SGSpatialSort.cpp index d74c57ed5..120070b0a 100644 --- a/code/SGSpatialSort.cpp +++ b/code/SGSpatialSort.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/SIBImporter.cpp b/code/SIBImporter.cpp index 7a69dd175..cfa65520e 100644 --- a/code/SIBImporter.cpp +++ b/code/SIBImporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/SIBImporter.h b/code/SIBImporter.h index 9437af588..bb88c2255 100644 --- a/code/SIBImporter.h +++ b/code/SIBImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/SMDLoader.cpp b/code/SMDLoader.cpp index c6ec61624..00d92e0b4 100644 --- a/code/SMDLoader.cpp +++ b/code/SMDLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/SMDLoader.h b/code/SMDLoader.h index a791e7dde..85dac97d1 100644 --- a/code/SMDLoader.h +++ b/code/SMDLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/STEPFile.h b/code/STEPFile.h index f5b56c31f..ac3280c21 100644 --- a/code/STEPFile.h +++ b/code/STEPFile.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/STLExporter.cpp b/code/STLExporter.cpp index e4a1dbb66..00fced6ff 100644 --- a/code/STLExporter.cpp +++ b/code/STLExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/STLExporter.h b/code/STLExporter.h index 6e8f90915..cb5238e60 100644 --- a/code/STLExporter.h +++ b/code/STLExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/STLLoader.cpp b/code/STLLoader.cpp index f8c4bb7db..c615561a8 100644 --- a/code/STLLoader.cpp +++ b/code/STLLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/STLLoader.h b/code/STLLoader.h index 3b87f70a3..ca1011cb8 100644 --- a/code/STLLoader.h +++ b/code/STLLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/ScaleProcess.cpp b/code/ScaleProcess.cpp index facc39d7d..6d458c4b1 100644 --- a/code/ScaleProcess.cpp +++ b/code/ScaleProcess.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/ScaleProcess.h b/code/ScaleProcess.h index 0621220a8..55146ae06 100644 --- a/code/ScaleProcess.h +++ b/code/ScaleProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/SceneCombiner.cpp b/code/SceneCombiner.cpp index 2271194ca..e445bd743 100644 --- a/code/SceneCombiner.cpp +++ b/code/SceneCombiner.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/ScenePreprocessor.cpp b/code/ScenePreprocessor.cpp index 1228ab2c2..432a3d766 100644 --- a/code/ScenePreprocessor.cpp +++ b/code/ScenePreprocessor.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/ScenePreprocessor.h b/code/ScenePreprocessor.h index 3900a237b..3f4c8d7c3 100644 --- a/code/ScenePreprocessor.h +++ b/code/ScenePreprocessor.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/ScenePrivate.h b/code/ScenePrivate.h index 775b9cb52..f336aafc9 100644 --- a/code/ScenePrivate.h +++ b/code/ScenePrivate.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/SkeletonMeshBuilder.cpp b/code/SkeletonMeshBuilder.cpp index ecfe8586f..06cfe034e 100644 --- a/code/SkeletonMeshBuilder.cpp +++ b/code/SkeletonMeshBuilder.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/SortByPTypeProcess.cpp b/code/SortByPTypeProcess.cpp index b67da5b95..87bbe5257 100644 --- a/code/SortByPTypeProcess.cpp +++ b/code/SortByPTypeProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/SortByPTypeProcess.h b/code/SortByPTypeProcess.h index 27bfa2155..c9d9924d8 100644 --- a/code/SortByPTypeProcess.h +++ b/code/SortByPTypeProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/SpatialSort.cpp b/code/SpatialSort.cpp index b0ab6e412..a4f3a4e4b 100644 --- a/code/SpatialSort.cpp +++ b/code/SpatialSort.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/SplitByBoneCountProcess.cpp b/code/SplitByBoneCountProcess.cpp index 6faf11086..2ef66a9af 100644 --- a/code/SplitByBoneCountProcess.cpp +++ b/code/SplitByBoneCountProcess.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/SplitByBoneCountProcess.h b/code/SplitByBoneCountProcess.h index b46dd6b0f..6c904a9df 100644 --- a/code/SplitByBoneCountProcess.h +++ b/code/SplitByBoneCountProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/SplitLargeMeshes.cpp b/code/SplitLargeMeshes.cpp index 5cd3afe48..1797b28d5 100644 --- a/code/SplitLargeMeshes.cpp +++ b/code/SplitLargeMeshes.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/SplitLargeMeshes.h b/code/SplitLargeMeshes.h index 7a977ff07..77f089ce7 100644 --- a/code/SplitLargeMeshes.h +++ b/code/SplitLargeMeshes.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/StandardShapes.cpp b/code/StandardShapes.cpp index 7d2319401..f262b6bac 100644 --- a/code/StandardShapes.cpp +++ b/code/StandardShapes.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/StdOStreamLogStream.h b/code/StdOStreamLogStream.h index 43b8d7de2..893e261a2 100644 --- a/code/StdOStreamLogStream.h +++ b/code/StdOStreamLogStream.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/StepExporter.cpp b/code/StepExporter.cpp index 4368201b7..02e521247 100644 --- a/code/StepExporter.cpp +++ b/code/StepExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/StepExporter.h b/code/StepExporter.h index f1323bee8..f96a0d2b5 100644 --- a/code/StepExporter.h +++ b/code/StepExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/Subdivision.cpp b/code/Subdivision.cpp index 2f2f09596..19db223a5 100644 --- a/code/Subdivision.cpp +++ b/code/Subdivision.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/TargetAnimation.cpp b/code/TargetAnimation.cpp index 2834b1f10..b8062499f 100644 --- a/code/TargetAnimation.cpp +++ b/code/TargetAnimation.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/TargetAnimation.h b/code/TargetAnimation.h index bb37e6008..91634ab5a 100644 --- a/code/TargetAnimation.h +++ b/code/TargetAnimation.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/TerragenLoader.cpp b/code/TerragenLoader.cpp index 0eb22cef6..9b0873c68 100644 --- a/code/TerragenLoader.cpp +++ b/code/TerragenLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/TerragenLoader.h b/code/TerragenLoader.h index a02889de1..a478c0dcd 100644 --- a/code/TerragenLoader.h +++ b/code/TerragenLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/TextureTransform.cpp b/code/TextureTransform.cpp index c7adbe7a9..8ae2ba721 100644 --- a/code/TextureTransform.cpp +++ b/code/TextureTransform.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/TextureTransform.h b/code/TextureTransform.h index 99d5acf1e..c556ff5d8 100644 --- a/code/TextureTransform.h +++ b/code/TextureTransform.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/TriangulateProcess.cpp b/code/TriangulateProcess.cpp index b2ea46ef7..0f68f47dd 100644 --- a/code/TriangulateProcess.cpp +++ b/code/TriangulateProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/TriangulateProcess.h b/code/TriangulateProcess.h index e6300085d..47bd2115a 100644 --- a/code/TriangulateProcess.h +++ b/code/TriangulateProcess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/UnrealLoader.cpp b/code/UnrealLoader.cpp index 64bfbb9e0..778aef59d 100644 --- a/code/UnrealLoader.cpp +++ b/code/UnrealLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/UnrealLoader.h b/code/UnrealLoader.h index 4095aa142..f846eb43a 100644 --- a/code/UnrealLoader.h +++ b/code/UnrealLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/ValidateDataStructure.cpp b/code/ValidateDataStructure.cpp index 931c52822..7db05a4e3 100644 --- a/code/ValidateDataStructure.cpp +++ b/code/ValidateDataStructure.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/ValidateDataStructure.h b/code/ValidateDataStructure.h index 4e1636bfa..bd21e8854 100644 --- a/code/ValidateDataStructure.h +++ b/code/ValidateDataStructure.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/Version.cpp b/code/Version.cpp index b823abd68..cc94340ac 100644 --- a/code/Version.cpp +++ b/code/Version.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/VertexTriangleAdjacency.cpp b/code/VertexTriangleAdjacency.cpp index b41fd029d..7cfd1a350 100644 --- a/code/VertexTriangleAdjacency.cpp +++ b/code/VertexTriangleAdjacency.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/VertexTriangleAdjacency.h b/code/VertexTriangleAdjacency.h index 23624a5be..f3be47612 100644 --- a/code/VertexTriangleAdjacency.h +++ b/code/VertexTriangleAdjacency.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/Win32DebugLogStream.h b/code/Win32DebugLogStream.h index 7bbe8002a..a6063a261 100644 --- a/code/Win32DebugLogStream.h +++ b/code/Win32DebugLogStream.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/X3DImporter.cpp b/code/X3DImporter.cpp index e6c915e90..1f4d3f916 100644 --- a/code/X3DImporter.cpp +++ b/code/X3DImporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/X3DImporter.hpp b/code/X3DImporter.hpp index 1c9dc5486..a4afc1463 100644 --- a/code/X3DImporter.hpp +++ b/code/X3DImporter.hpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/X3DImporter_Geometry2D.cpp b/code/X3DImporter_Geometry2D.cpp index 5229017b3..b29c80b04 100644 --- a/code/X3DImporter_Geometry2D.cpp +++ b/code/X3DImporter_Geometry2D.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/X3DImporter_Geometry3D.cpp b/code/X3DImporter_Geometry3D.cpp index b6d130098..2eecc079d 100644 --- a/code/X3DImporter_Geometry3D.cpp +++ b/code/X3DImporter_Geometry3D.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/X3DImporter_Group.cpp b/code/X3DImporter_Group.cpp index 0c2e820de..de3610caf 100644 --- a/code/X3DImporter_Group.cpp +++ b/code/X3DImporter_Group.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/X3DImporter_Light.cpp b/code/X3DImporter_Light.cpp index 4ffea4411..842fffc04 100644 --- a/code/X3DImporter_Light.cpp +++ b/code/X3DImporter_Light.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/X3DImporter_Macro.hpp b/code/X3DImporter_Macro.hpp index d1172798c..a6aca33fb 100644 --- a/code/X3DImporter_Macro.hpp +++ b/code/X3DImporter_Macro.hpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/X3DImporter_Metadata.cpp b/code/X3DImporter_Metadata.cpp index a566f0aa9..f888ac2b9 100644 --- a/code/X3DImporter_Metadata.cpp +++ b/code/X3DImporter_Metadata.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/X3DImporter_Networking.cpp b/code/X3DImporter_Networking.cpp index 9c15c4ac4..89010ae08 100644 --- a/code/X3DImporter_Networking.cpp +++ b/code/X3DImporter_Networking.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/X3DImporter_Node.hpp b/code/X3DImporter_Node.hpp index cb1317582..85208223d 100644 --- a/code/X3DImporter_Node.hpp +++ b/code/X3DImporter_Node.hpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/X3DImporter_Postprocess.cpp b/code/X3DImporter_Postprocess.cpp index c439a4004..e7686b41e 100644 --- a/code/X3DImporter_Postprocess.cpp +++ b/code/X3DImporter_Postprocess.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/X3DImporter_Rendering.cpp b/code/X3DImporter_Rendering.cpp index 1b44f8c19..d0c58030d 100644 --- a/code/X3DImporter_Rendering.cpp +++ b/code/X3DImporter_Rendering.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/X3DImporter_Shape.cpp b/code/X3DImporter_Shape.cpp index 43089c698..126d5905a 100644 --- a/code/X3DImporter_Shape.cpp +++ b/code/X3DImporter_Shape.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/X3DImporter_Texturing.cpp b/code/X3DImporter_Texturing.cpp index 807d19ff8..b4e42025a 100644 --- a/code/X3DImporter_Texturing.cpp +++ b/code/X3DImporter_Texturing.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/X3DVocabulary.cpp b/code/X3DVocabulary.cpp index dc361b7aa..c6ee113b3 100644 --- a/code/X3DVocabulary.cpp +++ b/code/X3DVocabulary.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/XFileExporter.cpp b/code/XFileExporter.cpp index 1510ae6d4..baa478226 100644 --- a/code/XFileExporter.cpp +++ b/code/XFileExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/XFileExporter.h b/code/XFileExporter.h index fc480f40b..322440af8 100644 --- a/code/XFileExporter.h +++ b/code/XFileExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/XFileHelper.h b/code/XFileHelper.h index c51e2eba9..0365280f0 100644 --- a/code/XFileHelper.h +++ b/code/XFileHelper.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/XFileImporter.cpp b/code/XFileImporter.cpp index ae847eef8..e9335cfaa 100644 --- a/code/XFileImporter.cpp +++ b/code/XFileImporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/XFileImporter.h b/code/XFileImporter.h index b3c06eab1..d1b8d3f47 100644 --- a/code/XFileImporter.h +++ b/code/XFileImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/XFileParser.cpp b/code/XFileParser.cpp index e7bf8518c..ed715a19d 100644 --- a/code/XFileParser.cpp +++ b/code/XFileParser.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/XFileParser.h b/code/XFileParser.h index 24eb6104d..993bae6a1 100644 --- a/code/XFileParser.h +++ b/code/XFileParser.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/XGLLoader.cpp b/code/XGLLoader.cpp index 2dfd51284..32cfd72ca 100644 --- a/code/XGLLoader.cpp +++ b/code/XGLLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/XGLLoader.h b/code/XGLLoader.h index 8ae05836a..bba2a643c 100644 --- a/code/XGLLoader.h +++ b/code/XGLLoader.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 6672dd7a9..897db7474 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index ed37937f4..97ad6df57 100755 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/glTF2AssetWriter.h b/code/glTF2AssetWriter.h index 493ca1c0a..928b6e71b 100644 --- a/code/glTF2AssetWriter.h +++ b/code/glTF2AssetWriter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl index 75726fd08..0d61d23e5 100644 --- a/code/glTF2AssetWriter.inl +++ b/code/glTF2AssetWriter.inl @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index d513dc45d..aae8a6c30 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/glTF2Exporter.h b/code/glTF2Exporter.h index 06bc5ad40..2dc083709 100644 --- a/code/glTF2Exporter.h +++ b/code/glTF2Exporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index c73e1eabb..be3a9a96f 100755 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/glTF2Importer.h b/code/glTF2Importer.h index 7414e2f95..091b61ee6 100644 --- a/code/glTF2Importer.h +++ b/code/glTF2Importer.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/glTFAsset.h b/code/glTFAsset.h index b04692901..463c69be4 100644 --- a/code/glTFAsset.h +++ b/code/glTFAsset.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/glTFAsset.inl b/code/glTFAsset.inl index 267cbd4a3..f545b809c 100644 --- a/code/glTFAsset.inl +++ b/code/glTFAsset.inl @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/glTFAssetWriter.h b/code/glTFAssetWriter.h index bbe89fc77..03aee7d4c 100644 --- a/code/glTFAssetWriter.h +++ b/code/glTFAssetWriter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/glTFAssetWriter.inl b/code/glTFAssetWriter.inl index fd29a96b4..259ad03f6 100644 --- a/code/glTFAssetWriter.inl +++ b/code/glTFAssetWriter.inl @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/glTFExporter.cpp b/code/glTFExporter.cpp index 5d00c9178..9daf202cb 100644 --- a/code/glTFExporter.cpp +++ b/code/glTFExporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/glTFExporter.h b/code/glTFExporter.h index 061dac5e8..d6c2e7f04 100644 --- a/code/glTFExporter.h +++ b/code/glTFExporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/glTFImporter.cpp b/code/glTFImporter.cpp index c68969dc6..57566b463 100755 --- a/code/glTFImporter.cpp +++ b/code/glTFImporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/glTFImporter.h b/code/glTFImporter.h index 064d6dc1a..ce8a000dc 100644 --- a/code/glTFImporter.h +++ b/code/glTFImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/code/scene.cpp b/code/scene.cpp index 676051163..2acb348d8 100644 --- a/code/scene.cpp +++ b/code/scene.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/simd.cpp b/code/simd.cpp index 9e2a83a60..04615f408 100644 --- a/code/simd.cpp +++ b/code/simd.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/code/simd.h b/code/simd.h index 19117569d..3eecdd458 100644 --- a/code/simd.h +++ b/code/simd.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/BaseImporter.h b/include/assimp/BaseImporter.h index b218d06ff..48dfc8ed8 100644 --- a/include/assimp/BaseImporter.h +++ b/include/assimp/BaseImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/Bitmap.h b/include/assimp/Bitmap.h index 209116863..e6b5fb132 100644 --- a/include/assimp/Bitmap.h +++ b/include/assimp/Bitmap.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/BlobIOSystem.h b/include/assimp/BlobIOSystem.h index a0ed7209f..d005e5c11 100644 --- a/include/assimp/BlobIOSystem.h +++ b/include/assimp/BlobIOSystem.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/ByteSwapper.h b/include/assimp/ByteSwapper.h index 322a242de..20a2463fb 100644 --- a/include/assimp/ByteSwapper.h +++ b/include/assimp/ByteSwapper.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/CreateAnimMesh.h b/include/assimp/CreateAnimMesh.h index ad625cb9f..a60173588 100644 --- a/include/assimp/CreateAnimMesh.h +++ b/include/assimp/CreateAnimMesh.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/DefaultIOStream.h b/include/assimp/DefaultIOStream.h index e0e010ecb..994d728ff 100644 --- a/include/assimp/DefaultIOStream.h +++ b/include/assimp/DefaultIOStream.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/DefaultIOSystem.h b/include/assimp/DefaultIOSystem.h index a5d45c692..2dd5c801b 100644 --- a/include/assimp/DefaultIOSystem.h +++ b/include/assimp/DefaultIOSystem.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/DefaultLogger.hpp b/include/assimp/DefaultLogger.hpp index 1f0c899be..1946e250a 100644 --- a/include/assimp/DefaultLogger.hpp +++ b/include/assimp/DefaultLogger.hpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/Exporter.hpp b/include/assimp/Exporter.hpp index 4e0843b60..bf0096e7e 100644 --- a/include/assimp/Exporter.hpp +++ b/include/assimp/Exporter.hpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/GenericProperty.h b/include/assimp/GenericProperty.h index 7b75cb1c8..183ecd519 100644 --- a/include/assimp/GenericProperty.h +++ b/include/assimp/GenericProperty.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/Hash.h b/include/assimp/Hash.h index eb5df757d..30657be19 100644 --- a/include/assimp/Hash.h +++ b/include/assimp/Hash.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/IOStream.hpp b/include/assimp/IOStream.hpp index 52b80cc15..0623d0f70 100644 --- a/include/assimp/IOStream.hpp +++ b/include/assimp/IOStream.hpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/IOStreamBuffer.h b/include/assimp/IOStreamBuffer.h index be5e4d0c5..58abd97a0 100644 --- a/include/assimp/IOStreamBuffer.h +++ b/include/assimp/IOStreamBuffer.h @@ -4,7 +4,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/IOSystem.hpp b/include/assimp/IOSystem.hpp index a36e22508..78139c283 100644 --- a/include/assimp/IOSystem.hpp +++ b/include/assimp/IOSystem.hpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/Importer.hpp b/include/assimp/Importer.hpp index 1d1dac19f..4941df412 100644 --- a/include/assimp/Importer.hpp +++ b/include/assimp/Importer.hpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/LineSplitter.h b/include/assimp/LineSplitter.h index eb6b6e46c..4afe45b92 100644 --- a/include/assimp/LineSplitter.h +++ b/include/assimp/LineSplitter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/LogAux.h b/include/assimp/LogAux.h index cf6d50014..558485272 100644 --- a/include/assimp/LogAux.h +++ b/include/assimp/LogAux.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/LogStream.hpp b/include/assimp/LogStream.hpp index e0eb8d505..d0281e2d0 100644 --- a/include/assimp/LogStream.hpp +++ b/include/assimp/LogStream.hpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/Logger.hpp b/include/assimp/Logger.hpp index 6a9928735..89cade6c3 100644 --- a/include/assimp/Logger.hpp +++ b/include/assimp/Logger.hpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/Macros.h b/include/assimp/Macros.h index 3aaed4e97..651530337 100644 --- a/include/assimp/Macros.h +++ b/include/assimp/Macros.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/MemoryIOWrapper.h b/include/assimp/MemoryIOWrapper.h index a9a78c319..c52278718 100644 --- a/include/assimp/MemoryIOWrapper.h +++ b/include/assimp/MemoryIOWrapper.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/NullLogger.hpp b/include/assimp/NullLogger.hpp index 776f301ab..c45d01bd4 100644 --- a/include/assimp/NullLogger.hpp +++ b/include/assimp/NullLogger.hpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/ParsingUtils.h b/include/assimp/ParsingUtils.h index 4553072db..ca30ce13b 100644 --- a/include/assimp/ParsingUtils.h +++ b/include/assimp/ParsingUtils.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/Profiler.h b/include/assimp/Profiler.h index da5af2726..6ff9d41c0 100644 --- a/include/assimp/Profiler.h +++ b/include/assimp/Profiler.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/ProgressHandler.hpp b/include/assimp/ProgressHandler.hpp index f295eac39..4e47f1d0a 100644 --- a/include/assimp/ProgressHandler.hpp +++ b/include/assimp/ProgressHandler.hpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/RemoveComments.h b/include/assimp/RemoveComments.h index 08299f22b..404b49671 100644 --- a/include/assimp/RemoveComments.h +++ b/include/assimp/RemoveComments.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/SGSpatialSort.h b/include/assimp/SGSpatialSort.h index 3c95d0b51..5b4f3f41f 100644 --- a/include/assimp/SGSpatialSort.h +++ b/include/assimp/SGSpatialSort.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/SceneCombiner.h b/include/assimp/SceneCombiner.h index ec2788245..679a2acea 100644 --- a/include/assimp/SceneCombiner.h +++ b/include/assimp/SceneCombiner.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/SkeletonMeshBuilder.h b/include/assimp/SkeletonMeshBuilder.h index 993d9c84d..f9b8d9f55 100644 --- a/include/assimp/SkeletonMeshBuilder.h +++ b/include/assimp/SkeletonMeshBuilder.h @@ -4,7 +4,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/SmoothingGroups.h b/include/assimp/SmoothingGroups.h index 88345c66a..92d65cea0 100644 --- a/include/assimp/SmoothingGroups.h +++ b/include/assimp/SmoothingGroups.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/SpatialSort.h b/include/assimp/SpatialSort.h index 8fb450841..61b345bcb 100644 --- a/include/assimp/SpatialSort.h +++ b/include/assimp/SpatialSort.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/StandardShapes.h b/include/assimp/StandardShapes.h index fdf1b034d..3791569b8 100644 --- a/include/assimp/StandardShapes.h +++ b/include/assimp/StandardShapes.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/StreamReader.h b/include/assimp/StreamReader.h index 4e5d2ddfa..9116c1426 100644 --- a/include/assimp/StreamReader.h +++ b/include/assimp/StreamReader.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/StreamWriter.h b/include/assimp/StreamWriter.h index deb35fb4d..c7cf6c0d7 100644 --- a/include/assimp/StreamWriter.h +++ b/include/assimp/StreamWriter.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/StringComparison.h b/include/assimp/StringComparison.h index aea7f001a..8acef277b 100644 --- a/include/assimp/StringComparison.h +++ b/include/assimp/StringComparison.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/StringUtils.h b/include/assimp/StringUtils.h index 906898b53..d68b7fa47 100644 --- a/include/assimp/StringUtils.h +++ b/include/assimp/StringUtils.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/Subdivision.h b/include/assimp/Subdivision.h index 84aff68f1..43feb73b3 100644 --- a/include/assimp/Subdivision.h +++ b/include/assimp/Subdivision.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/TinyFormatter.h b/include/assimp/TinyFormatter.h index 2ddc227e9..1226b482e 100644 --- a/include/assimp/TinyFormatter.h +++ b/include/assimp/TinyFormatter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/Vertex.h b/include/assimp/Vertex.h index f1c02ee07..2a7f0256a 100644 --- a/include/assimp/Vertex.h +++ b/include/assimp/Vertex.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/XMLTools.h b/include/assimp/XMLTools.h index 4b76c4483..b0d327687 100644 --- a/include/assimp/XMLTools.h +++ b/include/assimp/XMLTools.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/ai_assert.h b/include/assimp/ai_assert.h index 7752763db..daae23454 100644 --- a/include/assimp/ai_assert.h +++ b/include/assimp/ai_assert.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/anim.h b/include/assimp/anim.h index 8a0984192..02e92739e 100644 --- a/include/assimp/anim.h +++ b/include/assimp/anim.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/camera.h b/include/assimp/camera.h index 6fea5a7d7..99daf6993 100644 --- a/include/assimp/camera.h +++ b/include/assimp/camera.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/cfileio.h b/include/assimp/cfileio.h index a7a56f81c..8f7ca4546 100644 --- a/include/assimp/cfileio.h +++ b/include/assimp/cfileio.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/cimport.h b/include/assimp/cimport.h index eb1e6e0d4..dbd10f137 100644 --- a/include/assimp/cimport.h +++ b/include/assimp/cimport.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/color4.h b/include/assimp/color4.h index fddd1b638..3c97c8eda 100644 --- a/include/assimp/color4.h +++ b/include/assimp/color4.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/color4.inl b/include/assimp/color4.inl index 6e27292b9..3192d55f3 100644 --- a/include/assimp/color4.inl +++ b/include/assimp/color4.inl @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/defs.h b/include/assimp/defs.h index e651a1f7b..4a177e3c3 100644 --- a/include/assimp/defs.h +++ b/include/assimp/defs.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/importerdesc.h b/include/assimp/importerdesc.h index 36b773e45..36e387f01 100644 --- a/include/assimp/importerdesc.h +++ b/include/assimp/importerdesc.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/irrXMLWrapper.h b/include/assimp/irrXMLWrapper.h index 296f26a32..ec8ee7c76 100644 --- a/include/assimp/irrXMLWrapper.h +++ b/include/assimp/irrXMLWrapper.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/light.h b/include/assimp/light.h index dc0b8a4b6..1667cfb8c 100644 --- a/include/assimp/light.h +++ b/include/assimp/light.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/material.h b/include/assimp/material.h index 45b4844a3..81b5fb05f 100644 --- a/include/assimp/material.h +++ b/include/assimp/material.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/material.inl b/include/assimp/material.inl index 3d4b07c06..b05d6af6c 100644 --- a/include/assimp/material.inl +++ b/include/assimp/material.inl @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/matrix3x3.h b/include/assimp/matrix3x3.h index 4bb55ad21..22b69561f 100644 --- a/include/assimp/matrix3x3.h +++ b/include/assimp/matrix3x3.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/matrix3x3.inl b/include/assimp/matrix3x3.inl index ab2cc410b..d9d45a3e9 100644 --- a/include/assimp/matrix3x3.inl +++ b/include/assimp/matrix3x3.inl @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/matrix4x4.h b/include/assimp/matrix4x4.h index bfa9d3865..046bb535f 100644 --- a/include/assimp/matrix4x4.h +++ b/include/assimp/matrix4x4.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/matrix4x4.inl b/include/assimp/matrix4x4.inl index 680d7666d..ebc67a06e 100644 --- a/include/assimp/matrix4x4.inl +++ b/include/assimp/matrix4x4.inl @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/mesh.h b/include/assimp/mesh.h index f9c2c1e67..8d539c59e 100644 --- a/include/assimp/mesh.h +++ b/include/assimp/mesh.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/metadata.h b/include/assimp/metadata.h index 498e2f6d1..3a1dd1442 100644 --- a/include/assimp/metadata.h +++ b/include/assimp/metadata.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/pbrmaterial.h b/include/assimp/pbrmaterial.h index 723957300..ce5f82217 100644 --- a/include/assimp/pbrmaterial.h +++ b/include/assimp/pbrmaterial.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/postprocess.h b/include/assimp/postprocess.h index a0ae0a1bc..c23a5490a 100644 --- a/include/assimp/postprocess.h +++ b/include/assimp/postprocess.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/qnan.h b/include/assimp/qnan.h index 251688989..0918bde5e 100644 --- a/include/assimp/qnan.h +++ b/include/assimp/qnan.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/quaternion.h b/include/assimp/quaternion.h index e2479f2ed..96574d24b 100644 --- a/include/assimp/quaternion.h +++ b/include/assimp/quaternion.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/include/assimp/quaternion.inl b/include/assimp/quaternion.inl index 0a2c92937..c26648215 100644 --- a/include/assimp/quaternion.inl +++ b/include/assimp/quaternion.inl @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/scene.h b/include/assimp/scene.h index 867e87de0..de0239702 100644 --- a/include/assimp/scene.h +++ b/include/assimp/scene.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/texture.h b/include/assimp/texture.h index 575f5754f..dc6cbef65 100644 --- a/include/assimp/texture.h +++ b/include/assimp/texture.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/types.h b/include/assimp/types.h index 660479f8a..748e4851f 100644 --- a/include/assimp/types.h +++ b/include/assimp/types.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/vector2.h b/include/assimp/vector2.h index 85ca6d0a4..d5ef00154 100644 --- a/include/assimp/vector2.h +++ b/include/assimp/vector2.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/vector2.inl b/include/assimp/vector2.inl index 46c6c9d27..3b7a7beab 100644 --- a/include/assimp/vector2.inl +++ b/include/assimp/vector2.inl @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/vector3.h b/include/assimp/vector3.h index 33ae7d22f..7ff25cf0a 100644 --- a/include/assimp/vector3.h +++ b/include/assimp/vector3.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/vector3.inl b/include/assimp/vector3.inl index ebe2f82e9..2fce6edde 100644 --- a/include/assimp/vector3.inl +++ b/include/assimp/vector3.inl @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/include/assimp/version.h b/include/assimp/version.h index 470166edf..c62a40e11 100644 --- a/include/assimp/version.h +++ b/include/assimp/version.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 210d95550..03c4ac6a1 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,7 +1,7 @@ # Open Asset Import Library (assimp) # ---------------------------------------------------------------------- # -# Copyright (c) 2006-2018, assimp team +# Copyright (c) 2006-2019, assimp team # All rights reserved. diff --git a/test/unit/AbstractImportExportBase.cpp b/test/unit/AbstractImportExportBase.cpp index c09ec0fd7..bf89fa5d4 100644 --- a/test/unit/AbstractImportExportBase.cpp +++ b/test/unit/AbstractImportExportBase.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/AssimpAPITest.cpp b/test/unit/AssimpAPITest.cpp index faf551f7c..3e1d97314 100644 --- a/test/unit/AssimpAPITest.cpp +++ b/test/unit/AssimpAPITest.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/Common/utLineSplitter.cpp b/test/unit/Common/utLineSplitter.cpp index ad050ea73..2aa581add 100644 --- a/test/unit/Common/utLineSplitter.cpp +++ b/test/unit/Common/utLineSplitter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/ImportExport/utCOBImportExport.cpp b/test/unit/ImportExport/utCOBImportExport.cpp index 854f27cbb..d80757e53 100644 --- a/test/unit/ImportExport/utCOBImportExport.cpp +++ b/test/unit/ImportExport/utCOBImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/ImportExport/utExporter.cpp b/test/unit/ImportExport/utExporter.cpp index 9ce4bfdd7..c46a55b00 100644 --- a/test/unit/ImportExport/utExporter.cpp +++ b/test/unit/ImportExport/utExporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/ImportExport/utNFFImportExport.cpp b/test/unit/ImportExport/utNFFImportExport.cpp index aca9e0392..d2fc1df5f 100644 --- a/test/unit/ImportExport/utNFFImportExport.cpp +++ b/test/unit/ImportExport/utNFFImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/ImportExport/utOFFImportExport.cpp b/test/unit/ImportExport/utOFFImportExport.cpp index a355beab6..eadd48b12 100644 --- a/test/unit/ImportExport/utOFFImportExport.cpp +++ b/test/unit/ImportExport/utOFFImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/ImportExport/utOgreImportExport.cpp b/test/unit/ImportExport/utOgreImportExport.cpp index 1950fc90a..608d0b068 100644 --- a/test/unit/ImportExport/utOgreImportExport.cpp +++ b/test/unit/ImportExport/utOgreImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/ImportExport/utQ3BSPFileImportExport.cpp b/test/unit/ImportExport/utQ3BSPFileImportExport.cpp index ba12652b4..70d89f1d2 100644 --- a/test/unit/ImportExport/utQ3BSPFileImportExport.cpp +++ b/test/unit/ImportExport/utQ3BSPFileImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/ImportExport/utXGLImportExport.cpp b/test/unit/ImportExport/utXGLImportExport.cpp index 8f82ba48d..89e780e20 100644 --- a/test/unit/ImportExport/utXGLImportExport.cpp +++ b/test/unit/ImportExport/utXGLImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/SceneDiffer.cpp b/test/unit/SceneDiffer.cpp index 30b6e9086..fb000db29 100644 --- a/test/unit/SceneDiffer.cpp +++ b/test/unit/SceneDiffer.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/SceneDiffer.h b/test/unit/SceneDiffer.h index 5c9ce2c3b..2a8bdae33 100644 --- a/test/unit/SceneDiffer.h +++ b/test/unit/SceneDiffer.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/TestIOSystem.h b/test/unit/TestIOSystem.h index f984baa13..5749df45b 100644 --- a/test/unit/TestIOSystem.h +++ b/test/unit/TestIOSystem.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/test/unit/TestModelFactory.h b/test/unit/TestModelFactory.h index 6afbe5685..f1ef1701f 100644 --- a/test/unit/TestModelFactory.h +++ b/test/unit/TestModelFactory.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/UTLogStream.h b/test/unit/UTLogStream.h index 6e24fc5ed..e679249df 100644 --- a/test/unit/UTLogStream.h +++ b/test/unit/UTLogStream.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/test/unit/ut3DImportExport.cpp b/test/unit/ut3DImportExport.cpp index 1268fa360..a3a3197cc 100644 --- a/test/unit/ut3DImportExport.cpp +++ b/test/unit/ut3DImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/ut3DSImportExport.cpp b/test/unit/ut3DSImportExport.cpp index 0f91e0f7d..edec1d793 100644 --- a/test/unit/ut3DSImportExport.cpp +++ b/test/unit/ut3DSImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utACImportExport.cpp b/test/unit/utACImportExport.cpp index 937c0afb4..192de16a0 100644 --- a/test/unit/utACImportExport.cpp +++ b/test/unit/utACImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utAMFImportExport.cpp b/test/unit/utAMFImportExport.cpp index 332d5b929..dc2c9b99b 100644 --- a/test/unit/utAMFImportExport.cpp +++ b/test/unit/utAMFImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utASEImportExport.cpp b/test/unit/utASEImportExport.cpp index 28c498dca..28168de7d 100644 --- a/test/unit/utASEImportExport.cpp +++ b/test/unit/utASEImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utAnim.cpp b/test/unit/utAnim.cpp index 40c840d7e..7d4cff7d1 100644 --- a/test/unit/utAnim.cpp +++ b/test/unit/utAnim.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/test/unit/utAssbinImportExport.cpp b/test/unit/utAssbinImportExport.cpp index bbfb9421b..6def04796 100644 --- a/test/unit/utAssbinImportExport.cpp +++ b/test/unit/utAssbinImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utB3DImportExport.cpp b/test/unit/utB3DImportExport.cpp index 6795f8cba..d51ca51a6 100644 --- a/test/unit/utB3DImportExport.cpp +++ b/test/unit/utB3DImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utBVHImportExport.cpp b/test/unit/utBVHImportExport.cpp index eebfe1439..c4ed43cf8 100644 --- a/test/unit/utBVHImportExport.cpp +++ b/test/unit/utBVHImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utBatchLoader.cpp b/test/unit/utBatchLoader.cpp index ce95727ee..d38f83b35 100644 --- a/test/unit/utBatchLoader.cpp +++ b/test/unit/utBatchLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utBlendImportAreaLight.cpp b/test/unit/utBlendImportAreaLight.cpp index c2f6c0be3..a259294aa 100644 --- a/test/unit/utBlendImportAreaLight.cpp +++ b/test/unit/utBlendImportAreaLight.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utBlendImportMaterials.cpp b/test/unit/utBlendImportMaterials.cpp index f36ffdb18..cefacbe27 100644 --- a/test/unit/utBlendImportMaterials.cpp +++ b/test/unit/utBlendImportMaterials.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utBlenderImportExport.cpp b/test/unit/utBlenderImportExport.cpp index 5634b33a8..b2d268497 100644 --- a/test/unit/utBlenderImportExport.cpp +++ b/test/unit/utBlenderImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utBlenderIntermediate.cpp b/test/unit/utBlenderIntermediate.cpp index 55490e613..c1b53bbfd 100644 --- a/test/unit/utBlenderIntermediate.cpp +++ b/test/unit/utBlenderIntermediate.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utBlenderWork.cpp b/test/unit/utBlenderWork.cpp index a17764673..65fefde28 100644 --- a/test/unit/utBlenderWork.cpp +++ b/test/unit/utBlenderWork.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utCSMImportExport.cpp b/test/unit/utCSMImportExport.cpp index 4da51f089..7f6ae0f4e 100644 --- a/test/unit/utCSMImportExport.cpp +++ b/test/unit/utCSMImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utColladaExportCamera.cpp b/test/unit/utColladaExportCamera.cpp index 3219dbf0c..3c7412e0b 100644 --- a/test/unit/utColladaExportCamera.cpp +++ b/test/unit/utColladaExportCamera.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utColladaExportLight.cpp b/test/unit/utColladaExportLight.cpp index 71f404c29..502cecf3a 100644 --- a/test/unit/utColladaExportLight.cpp +++ b/test/unit/utColladaExportLight.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utColladaImportExport.cpp b/test/unit/utColladaImportExport.cpp index c7ad6f906..78a74d973 100644 --- a/test/unit/utColladaImportExport.cpp +++ b/test/unit/utColladaImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utD3MFImportExport.cpp b/test/unit/utD3MFImportExport.cpp index c5fdd003b..9d97f0f19 100644 --- a/test/unit/utD3MFImportExport.cpp +++ b/test/unit/utD3MFImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utDXFImporterExporter.cpp b/test/unit/utDXFImporterExporter.cpp index e0e764ea6..af57ffc79 100644 --- a/test/unit/utDXFImporterExporter.cpp +++ b/test/unit/utDXFImporterExporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utDefaultIOStream.cpp b/test/unit/utDefaultIOStream.cpp index cf51ed56a..bfc82a620 100644 --- a/test/unit/utDefaultIOStream.cpp +++ b/test/unit/utDefaultIOStream.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utFBXImporterExporter.cpp b/test/unit/utFBXImporterExporter.cpp index 1d6cdf883..5aca810a0 100644 --- a/test/unit/utFBXImporterExporter.cpp +++ b/test/unit/utFBXImporterExporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utFastAtof.cpp b/test/unit/utFastAtof.cpp index 10284a1de..ef1e72202 100644 --- a/test/unit/utFastAtof.cpp +++ b/test/unit/utFastAtof.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utFindDegenerates.cpp b/test/unit/utFindDegenerates.cpp index 5fd016b2c..d6ef803fa 100644 --- a/test/unit/utFindDegenerates.cpp +++ b/test/unit/utFindDegenerates.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utFindInvalidData.cpp b/test/unit/utFindInvalidData.cpp index 2313555b8..953c6728c 100644 --- a/test/unit/utFindInvalidData.cpp +++ b/test/unit/utFindInvalidData.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utFixInfacingNormals.cpp b/test/unit/utFixInfacingNormals.cpp index 742b12013..40b962dcb 100644 --- a/test/unit/utFixInfacingNormals.cpp +++ b/test/unit/utFixInfacingNormals.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utGenNormals.cpp b/test/unit/utGenNormals.cpp index 253d76742..65ab7c833 100644 --- a/test/unit/utGenNormals.cpp +++ b/test/unit/utGenNormals.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utHMPImportExport.cpp b/test/unit/utHMPImportExport.cpp index 1e1a4bcd2..35f4583aa 100644 --- a/test/unit/utHMPImportExport.cpp +++ b/test/unit/utHMPImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utIFCImportExport.cpp b/test/unit/utIFCImportExport.cpp index 01132435b..3f7cf7c8c 100644 --- a/test/unit/utIFCImportExport.cpp +++ b/test/unit/utIFCImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utIOStreamBuffer.cpp b/test/unit/utIOStreamBuffer.cpp index 41575fa59..6c6153135 100644 --- a/test/unit/utIOStreamBuffer.cpp +++ b/test/unit/utIOStreamBuffer.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utIOSystem.cpp b/test/unit/utIOSystem.cpp index c5c02bd45..80165fe79 100644 --- a/test/unit/utIOSystem.cpp +++ b/test/unit/utIOSystem.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utImporter.cpp b/test/unit/utImporter.cpp index b76c96d2a..3e88e3ff4 100644 --- a/test/unit/utImporter.cpp +++ b/test/unit/utImporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utImproveCacheLocality.cpp b/test/unit/utImproveCacheLocality.cpp index 01f99ebb9..8564bb01d 100644 --- a/test/unit/utImproveCacheLocality.cpp +++ b/test/unit/utImproveCacheLocality.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utIssues.cpp b/test/unit/utIssues.cpp index e526c2b82..6a974d7b9 100644 --- a/test/unit/utIssues.cpp +++ b/test/unit/utIssues.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utJoinVertices.cpp b/test/unit/utJoinVertices.cpp index 522cec4af..067c0558c 100644 --- a/test/unit/utJoinVertices.cpp +++ b/test/unit/utJoinVertices.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utLWOImportExport.cpp b/test/unit/utLWOImportExport.cpp index 7e03ee2e4..c8655b664 100644 --- a/test/unit/utLWOImportExport.cpp +++ b/test/unit/utLWOImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utLWSImportExport.cpp b/test/unit/utLWSImportExport.cpp index e34cfc90e..b04424b48 100644 --- a/test/unit/utLWSImportExport.cpp +++ b/test/unit/utLWSImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utLimitBoneWeights.cpp b/test/unit/utLimitBoneWeights.cpp index 1ce1cff1b..48da66df0 100644 --- a/test/unit/utLimitBoneWeights.cpp +++ b/test/unit/utLimitBoneWeights.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utMDCImportExport.cpp b/test/unit/utMDCImportExport.cpp index 19b8e68d2..30a4cfad1 100644 --- a/test/unit/utMDCImportExport.cpp +++ b/test/unit/utMDCImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utMaterialSystem.cpp b/test/unit/utMaterialSystem.cpp index 55ee6e2a0..c2a9b520b 100644 --- a/test/unit/utMaterialSystem.cpp +++ b/test/unit/utMaterialSystem.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utMatrix3x3.cpp b/test/unit/utMatrix3x3.cpp index bc15f780d..bff8ca1cd 100644 --- a/test/unit/utMatrix3x3.cpp +++ b/test/unit/utMatrix3x3.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utMatrix4x4.cpp b/test/unit/utMatrix4x4.cpp index b11f0b43d..e94bf500c 100644 --- a/test/unit/utMatrix4x4.cpp +++ b/test/unit/utMatrix4x4.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utMetadata.cpp b/test/unit/utMetadata.cpp index c2cd6e1ef..64b7dfe4c 100644 --- a/test/unit/utMetadata.cpp +++ b/test/unit/utMetadata.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utObjImportExport.cpp b/test/unit/utObjImportExport.cpp index f0b20fb7f..916f4713c 100644 --- a/test/unit/utObjImportExport.cpp +++ b/test/unit/utObjImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utObjTools.cpp b/test/unit/utObjTools.cpp index 6604dfd59..e08b5de79 100644 --- a/test/unit/utObjTools.cpp +++ b/test/unit/utObjTools.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utOpenGEXImportExport.cpp b/test/unit/utOpenGEXImportExport.cpp index 313a7210e..4e154f50f 100644 --- a/test/unit/utOpenGEXImportExport.cpp +++ b/test/unit/utOpenGEXImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utPLYImportExport.cpp b/test/unit/utPLYImportExport.cpp index 540996b21..bb8ba64d9 100644 --- a/test/unit/utPLYImportExport.cpp +++ b/test/unit/utPLYImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/test/unit/utPretransformVertices.cpp b/test/unit/utPretransformVertices.cpp index d8f7de165..0bf6245c6 100644 --- a/test/unit/utPretransformVertices.cpp +++ b/test/unit/utPretransformVertices.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utProfiler.cpp b/test/unit/utProfiler.cpp index 49c9a855c..b86f1952c 100644 --- a/test/unit/utProfiler.cpp +++ b/test/unit/utProfiler.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utQ3DImportExport.cpp b/test/unit/utQ3DImportExport.cpp index 6f840cfc9..51fa4b70a 100644 --- a/test/unit/utQ3DImportExport.cpp +++ b/test/unit/utQ3DImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utRemoveComments.cpp b/test/unit/utRemoveComments.cpp index e236b1d30..cd3175f5a 100644 --- a/test/unit/utRemoveComments.cpp +++ b/test/unit/utRemoveComments.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utRemoveComponent.cpp b/test/unit/utRemoveComponent.cpp index 5fb9656d1..1b13989dd 100644 --- a/test/unit/utRemoveComponent.cpp +++ b/test/unit/utRemoveComponent.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utRemoveRedundantMaterials.cpp b/test/unit/utRemoveRedundantMaterials.cpp index 312302846..c3497595b 100644 --- a/test/unit/utRemoveRedundantMaterials.cpp +++ b/test/unit/utRemoveRedundantMaterials.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utRemoveVCProcess.cpp b/test/unit/utRemoveVCProcess.cpp index 8c726de4a..1eedf9842 100644 --- a/test/unit/utRemoveVCProcess.cpp +++ b/test/unit/utRemoveVCProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utSIBImporter.cpp b/test/unit/utSIBImporter.cpp index da51b14af..4d6a09783 100644 --- a/test/unit/utSIBImporter.cpp +++ b/test/unit/utSIBImporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utSMDImportExport.cpp b/test/unit/utSMDImportExport.cpp index ea315db83..500277099 100644 --- a/test/unit/utSMDImportExport.cpp +++ b/test/unit/utSMDImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utSTLImportExport.cpp b/test/unit/utSTLImportExport.cpp index 77602a882..b5518de23 100644 --- a/test/unit/utSTLImportExport.cpp +++ b/test/unit/utSTLImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utScaleProcess.cpp b/test/unit/utScaleProcess.cpp index e01f822b9..13a184249 100644 --- a/test/unit/utScaleProcess.cpp +++ b/test/unit/utScaleProcess.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utSceneCombiner.cpp b/test/unit/utSceneCombiner.cpp index 3e7ba0146..e9be598e1 100644 --- a/test/unit/utSceneCombiner.cpp +++ b/test/unit/utSceneCombiner.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utScenePreprocessor.cpp b/test/unit/utScenePreprocessor.cpp index 788ee1d34..5e1af334c 100644 --- a/test/unit/utScenePreprocessor.cpp +++ b/test/unit/utScenePreprocessor.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utSharedPPData.cpp b/test/unit/utSharedPPData.cpp index 94f2a5678..380235c58 100644 --- a/test/unit/utSharedPPData.cpp +++ b/test/unit/utSharedPPData.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utSimd.cpp b/test/unit/utSimd.cpp index 33358c0da..e7779a0ee 100644 --- a/test/unit/utSimd.cpp +++ b/test/unit/utSimd.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/test/unit/utSortByPType.cpp b/test/unit/utSortByPType.cpp index 7affd56f1..4d9240c93 100644 --- a/test/unit/utSortByPType.cpp +++ b/test/unit/utSortByPType.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utSplitLargeMeshes.cpp b/test/unit/utSplitLargeMeshes.cpp index 496049d65..fced5df4b 100644 --- a/test/unit/utSplitLargeMeshes.cpp +++ b/test/unit/utSplitLargeMeshes.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utStringUtils.cpp b/test/unit/utStringUtils.cpp index ab053fd6f..3791e8622 100644 --- a/test/unit/utStringUtils.cpp +++ b/test/unit/utStringUtils.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utTargetAnimation.cpp b/test/unit/utTargetAnimation.cpp index 6bbc1f418..bbcacd2cb 100644 --- a/test/unit/utTargetAnimation.cpp +++ b/test/unit/utTargetAnimation.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utTextureTransform.cpp b/test/unit/utTextureTransform.cpp index 6bbc1f418..bbcacd2cb 100644 --- a/test/unit/utTextureTransform.cpp +++ b/test/unit/utTextureTransform.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utTriangulate.cpp b/test/unit/utTriangulate.cpp index e421d40b1..8c42000cd 100644 --- a/test/unit/utTriangulate.cpp +++ b/test/unit/utTriangulate.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utTypes.cpp b/test/unit/utTypes.cpp index a67154f7c..6289c75e7 100644 --- a/test/unit/utTypes.cpp +++ b/test/unit/utTypes.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utVector3.cpp b/test/unit/utVector3.cpp index 387b4614d..adeb70615 100644 --- a/test/unit/utVector3.cpp +++ b/test/unit/utVector3.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/test/unit/utVersion.cpp b/test/unit/utVersion.cpp index 4886377f8..5cfc91ccd 100644 --- a/test/unit/utVersion.cpp +++ b/test/unit/utVersion.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utVertexTriangleAdjacency.cpp b/test/unit/utVertexTriangleAdjacency.cpp index dc109f519..f15b0d21f 100644 --- a/test/unit/utVertexTriangleAdjacency.cpp +++ b/test/unit/utVertexTriangleAdjacency.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utX3DImportExport.cpp b/test/unit/utX3DImportExport.cpp index aeee72318..2aa0ae3cc 100644 --- a/test/unit/utX3DImportExport.cpp +++ b/test/unit/utX3DImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utXImporterExporter.cpp b/test/unit/utXImporterExporter.cpp index d4c742e6f..53e156bcc 100644 --- a/test/unit/utXImporterExporter.cpp +++ b/test/unit/utXImporterExporter.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utglTF2ImportExport.cpp b/test/unit/utglTF2ImportExport.cpp index 08fa9d989..3ad02645d 100644 --- a/test/unit/utglTF2ImportExport.cpp +++ b/test/unit/utglTF2ImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/test/unit/utglTFImportExport.cpp b/test/unit/utglTFImportExport.cpp index 17aa94d31..562cb05b9 100644 --- a/test/unit/utglTFImportExport.cpp +++ b/test/unit/utglTFImportExport.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/tools/assimp_cmd/CMakeLists.txt b/tools/assimp_cmd/CMakeLists.txt index ae38b5f11..5ea4e1a24 100644 --- a/tools/assimp_cmd/CMakeLists.txt +++ b/tools/assimp_cmd/CMakeLists.txt @@ -1,7 +1,7 @@ # Open Asset Import Library (assimp) # ---------------------------------------------------------------------- # -# Copyright (c) 2006-2018, assimp team +# Copyright (c) 2006-2019, assimp team # All rights reserved. diff --git a/tools/assimp_cmd/CompareDump.cpp b/tools/assimp_cmd/CompareDump.cpp index d8304f020..0ea0893f9 100644 --- a/tools/assimp_cmd/CompareDump.cpp +++ b/tools/assimp_cmd/CompareDump.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/tools/assimp_cmd/Export.cpp b/tools/assimp_cmd/Export.cpp index 03f896822..e29936e38 100644 --- a/tools/assimp_cmd/Export.cpp +++ b/tools/assimp_cmd/Export.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/tools/assimp_cmd/ImageExtractor.cpp b/tools/assimp_cmd/ImageExtractor.cpp index ce472dcb3..f9d55b8e8 100644 --- a/tools/assimp_cmd/ImageExtractor.cpp +++ b/tools/assimp_cmd/ImageExtractor.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/tools/assimp_cmd/Info.cpp b/tools/assimp_cmd/Info.cpp index 050dbf989..cb7ac86cf 100644 --- a/tools/assimp_cmd/Info.cpp +++ b/tools/assimp_cmd/Info.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/tools/assimp_cmd/Main.cpp b/tools/assimp_cmd/Main.cpp index 2a18bf33a..af372582c 100644 --- a/tools/assimp_cmd/Main.cpp +++ b/tools/assimp_cmd/Main.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/tools/assimp_cmd/WriteDumb.cpp b/tools/assimp_cmd/WriteDumb.cpp index b05adf249..0bcd5321c 100644 --- a/tools/assimp_cmd/WriteDumb.cpp +++ b/tools/assimp_cmd/WriteDumb.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/tools/assimp_view/AnimEvaluator.cpp b/tools/assimp_view/AnimEvaluator.cpp index 94c581df4..23e3c0e7d 100644 --- a/tools/assimp_view/AnimEvaluator.cpp +++ b/tools/assimp_view/AnimEvaluator.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/tools/assimp_view/CMakeLists.txt b/tools/assimp_view/CMakeLists.txt index f75937eff..f5365e11a 100644 --- a/tools/assimp_view/CMakeLists.txt +++ b/tools/assimp_view/CMakeLists.txt @@ -1,7 +1,7 @@ # Open Asset Import Library (assimp) # ---------------------------------------------------------------------- # -# Copyright (c) 2006-2018, assimp team +# Copyright (c) 2006-2019, assimp team # All rights reserved. diff --git a/tools/assimp_view/assimp_view.cpp b/tools/assimp_view/assimp_view.cpp index 746a4836f..d96e5ac97 100644 --- a/tools/assimp_view/assimp_view.cpp +++ b/tools/assimp_view/assimp_view.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team diff --git a/tools/assimp_view/assimp_view.h b/tools/assimp_view/assimp_view.h index 9317495c1..bed4c64c3 100644 --- a/tools/assimp_view/assimp_view.h +++ b/tools/assimp_view/assimp_view.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2018, assimp team +Copyright (c) 2006-2019, assimp team From de02fb212962cae39966e92466d17145773166fa Mon Sep 17 00:00:00 2001 From: kimkulling Date: Wed, 30 Jan 2019 16:07:40 +0100 Subject: [PATCH 128/472] Fix review findings. --- tools/assimp_view/AnimEvaluator.cpp | 81 ++-- tools/assimp_view/AnimEvaluator.h | 32 +- tools/assimp_view/Background.cpp | 2 +- tools/assimp_view/Display.cpp | 2 +- tools/assimp_view/HelpDialog.cpp | 49 +- tools/assimp_view/Input.cpp | 2 +- tools/assimp_view/LogDisplay.cpp | 74 ++- tools/assimp_view/LogWindow.cpp | 61 +-- tools/assimp_view/Material.cpp | 3 +- tools/assimp_view/MeshRenderer.cpp | 8 +- tools/assimp_view/MessageProc.cpp | 685 ++++++++++------------------ tools/assimp_view/Normals.cpp | 60 +-- tools/assimp_view/SceneAnimator.cpp | 102 ++--- tools/assimp_view/SceneAnimator.h | 32 +- tools/assimp_view/Shaders.cpp | 2 +- 15 files changed, 464 insertions(+), 731 deletions(-) diff --git a/tools/assimp_view/AnimEvaluator.cpp b/tools/assimp_view/AnimEvaluator.cpp index 23e3c0e7d..9d9481a77 100644 --- a/tools/assimp_view/AnimEvaluator.cpp +++ b/tools/assimp_view/AnimEvaluator.cpp @@ -47,17 +47,21 @@ using namespace AssimpView; // ------------------------------------------------------------------------------------------------ // Constructor on a given animation. -AnimEvaluator::AnimEvaluator( const aiAnimation* pAnim) -{ - mAnim = pAnim; - mLastTime = 0.0; +AnimEvaluator::AnimEvaluator( const aiAnimation *pAnim ) +: mAnim(pAnim) +, mLastTime(0.0) { mLastPositions.resize( pAnim->mNumChannels, std::make_tuple( 0, 0, 0)); } +// ------------------------------------------------------------------------------------------------ +// Destructor. +AnimEvaluator::~AnimEvaluator() { + // empty +} + // ------------------------------------------------------------------------------------------------ // Evaluates the animation tracks for a given time stamp. -void AnimEvaluator::Evaluate( double pTime) -{ +void AnimEvaluator::Evaluate( double pTime ) { // extract ticks per second. Assume default value if not given double ticksPerSecond = mAnim->mTicksPerSecond != 0.0 ? mAnim->mTicksPerSecond : 25.0; // every following time calculation happens in ticks @@ -65,29 +69,29 @@ void AnimEvaluator::Evaluate( double pTime) // map into anim's duration double time = 0.0f; - if( mAnim->mDuration > 0.0) - time = fmod( pTime, mAnim->mDuration); + if (mAnim->mDuration > 0.0) { + time = fmod(pTime, mAnim->mDuration); + } - if( mTransforms.size() != mAnim->mNumChannels) - mTransforms.resize( mAnim->mNumChannels); + if (mTransforms.size() != mAnim->mNumChannels) { + mTransforms.resize(mAnim->mNumChannels); + } // calculate the transformations for each animation channel - for( unsigned int a = 0; a < mAnim->mNumChannels; a++) - { + for( unsigned int a = 0; a < mAnim->mNumChannels; ++a ) { const aiNodeAnim* channel = mAnim->mChannels[a]; // ******** Position ***** aiVector3D presentPosition( 0, 0, 0); - if( channel->mNumPositionKeys > 0) - { + if( channel->mNumPositionKeys > 0) { // Look for present frame number. Search from last position if time is after the last time, else from beginning // Should be much quicker than always looking from start for the average use case. unsigned int frame = (time >= mLastTime) ? std::get<0>(mLastPositions[a]) : 0; - while( frame < channel->mNumPositionKeys - 1) - { - if( time < channel->mPositionKeys[frame+1].mTime) + while( frame < channel->mNumPositionKeys - 1) { + if (time < channel->mPositionKeys[frame + 1].mTime) { break; - frame++; + } + ++frame; } // interpolate between this frame's value and next frame's value @@ -95,14 +99,13 @@ void AnimEvaluator::Evaluate( double pTime) const aiVectorKey& key = channel->mPositionKeys[frame]; const aiVectorKey& nextKey = channel->mPositionKeys[nextFrame]; double diffTime = nextKey.mTime - key.mTime; - if( diffTime < 0.0) + if (diffTime < 0.0) { diffTime += mAnim->mDuration; - if( diffTime > 0) - { + } + if( diffTime > 0) { float factor = float( (time - key.mTime) / diffTime); presentPosition = key.mValue + (nextKey.mValue - key.mValue) * factor; - } else - { + } else { presentPosition = key.mValue; } @@ -111,14 +114,13 @@ void AnimEvaluator::Evaluate( double pTime) // ******** Rotation ********* aiQuaternion presentRotation( 1, 0, 0, 0); - if( channel->mNumRotationKeys > 0) - { + if( channel->mNumRotationKeys > 0) { unsigned int frame = (time >= mLastTime) ? std::get<1>(mLastPositions[a]) : 0; - while( frame < channel->mNumRotationKeys - 1) - { - if( time < channel->mRotationKeys[frame+1].mTime) + while( frame < channel->mNumRotationKeys - 1) { + if (time < channel->mRotationKeys[frame + 1].mTime) { break; - frame++; + } + ++frame; } // interpolate between this frame's value and next frame's value @@ -126,14 +128,13 @@ void AnimEvaluator::Evaluate( double pTime) const aiQuatKey& key = channel->mRotationKeys[frame]; const aiQuatKey& nextKey = channel->mRotationKeys[nextFrame]; double diffTime = nextKey.mTime - key.mTime; - if( diffTime < 0.0) + if (diffTime < 0.0) { diffTime += mAnim->mDuration; - if( diffTime > 0) - { + } + if( diffTime > 0) { float factor = float( (time - key.mTime) / diffTime); aiQuaternion::Interpolate( presentRotation, key.mValue, nextKey.mValue, factor); - } else - { + } else { presentRotation = key.mValue; } @@ -142,14 +143,13 @@ void AnimEvaluator::Evaluate( double pTime) // ******** Scaling ********** aiVector3D presentScaling( 1, 1, 1); - if( channel->mNumScalingKeys > 0) - { + if( channel->mNumScalingKeys > 0) { unsigned int frame = (time >= mLastTime) ? std::get<2>(mLastPositions[a]) : 0; - while( frame < channel->mNumScalingKeys - 1) - { - if( time < channel->mScalingKeys[frame+1].mTime) + while( frame < channel->mNumScalingKeys - 1) { + if (time < channel->mScalingKeys[frame + 1].mTime) { break; - frame++; + } + ++frame; } // TODO: (thom) interpolation maybe? This time maybe even logarithmic, not linear @@ -164,7 +164,6 @@ void AnimEvaluator::Evaluate( double pTime) mat.a2 *= presentScaling.y; mat.b2 *= presentScaling.y; mat.c2 *= presentScaling.y; mat.a3 *= presentScaling.z; mat.b3 *= presentScaling.z; mat.c3 *= presentScaling.z; mat.a4 = presentPosition.x; mat.b4 = presentPosition.y; mat.c4 = presentPosition.z; - //mat.Transpose(); } mLastTime = time; diff --git a/tools/assimp_view/AnimEvaluator.h b/tools/assimp_view/AnimEvaluator.h index 417a02935..1b4d54186 100644 --- a/tools/assimp_view/AnimEvaluator.h +++ b/tools/assimp_view/AnimEvaluator.h @@ -4,7 +4,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2012, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -46,22 +46,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -namespace AssimpView -{ +namespace AssimpView { -/** Calculates transformations for a given timestamp from a set of animation tracks. Not directly useful, - * better use the AnimPlayer class. +/** + * @brief Calculates transformations for a given timestamp from a set of animation tracks. Not directly useful, + * better use the AnimPlayer class. */ -class AnimEvaluator -{ +class AnimEvaluator { public: - /** Constructor on a given animation. The animation is fixed throughout the lifetime of - * the object. - * @param pAnim The animation to calculate poses for. Ownership of the animation object stays - * at the caller, the evaluator just keeps a reference to it as long as it persists. - */ + /// @brief Constructor on a given animation. The animation is fixed throughout the lifetime of + /// the object. + /// @param pAnim The animation to calculate poses for. Ownership of the animation object stays + /// at the caller, the evaluator just keeps a reference to it as long as it persists. AnimEvaluator( const aiAnimation* pAnim); + /// @brief The class destructor. + ~AnimEvaluator(); + /** Evaluates the animation tracks for a given time stamp. The calculated pose can be retrieved as a * array of transformation matrices afterwards by calling GetTransformations(). * @param pTime The time for which you want to evaluate the animation, in seconds. Will be mapped into the animation cycle, so @@ -74,16 +75,9 @@ public: const std::vector& GetTransformations() const { return mTransforms; } protected: - /** The animation we're working on */ const aiAnimation* mAnim; - - /** At which frame the last evaluation happened for each channel. - * Useful to quickly find the corresponding frame for slightly increased time stamps - */ double mLastTime; std::vector > mLastPositions; - - /** The array to store the transformations results of the evaluation */ std::vector mTransforms; }; diff --git a/tools/assimp_view/Background.cpp b/tools/assimp_view/Background.cpp index 14bf5b90d..b356a245b 100644 --- a/tools/assimp_view/Background.cpp +++ b/tools/assimp_view/Background.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2015, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/tools/assimp_view/Display.cpp b/tools/assimp_view/Display.cpp index 041ab34c5..196e8a2ac 100644 --- a/tools/assimp_view/Display.cpp +++ b/tools/assimp_view/Display.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2015, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/tools/assimp_view/HelpDialog.cpp b/tools/assimp_view/HelpDialog.cpp index 7b2ebf7b6..1a9f08f5f 100644 --- a/tools/assimp_view/HelpDialog.cpp +++ b/tools/assimp_view/HelpDialog.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2015, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -48,14 +48,10 @@ namespace AssimpView { //------------------------------------------------------------------------------- // Message procedure for the help dialog //------------------------------------------------------------------------------- -INT_PTR CALLBACK HelpDialogProc(HWND hwndDlg,UINT uMsg, - WPARAM wParam,LPARAM lParam) - { - (void)lParam; - switch (uMsg) - { +INT_PTR CALLBACK HelpDialogProc(HWND hwndDlg,UINT uMsg, WPARAM wParam,LPARAM ) { + switch (uMsg) { case WM_INITDIALOG: - { + { // load the help file ... HRSRC res = FindResource(NULL,MAKEINTRESOURCE(IDR_TEXT1),"TEXT"); HGLOBAL hg = LoadResource(NULL,res); @@ -70,39 +66,38 @@ INT_PTR CALLBACK HelpDialogProc(HWND hwndDlg,UINT uMsg, FreeResource(hg); return TRUE; - } + } case WM_CLOSE: EndDialog(hwndDlg,0); return TRUE; case WM_COMMAND: - - if (IDOK == LOWORD(wParam)) - { + if (IDOK == LOWORD(wParam)) { EndDialog(hwndDlg,0); return TRUE; - } + } case WM_PAINT: { - PAINTSTRUCT sPaint; - HDC hdc = BeginPaint(hwndDlg,&sPaint); + PAINTSTRUCT sPaint; + HDC hdc = BeginPaint(hwndDlg,&sPaint); - HBRUSH hBrush = CreateSolidBrush(RGB(0xFF,0xFF,0xFF)); + HBRUSH hBrush = CreateSolidBrush(RGB(0xFF,0xFF,0xFF)); - RECT sRect; - sRect.left = 0; - sRect.top = 26; - sRect.right = 1000; - sRect.bottom = 507; - FillRect(hdc, &sRect, hBrush); + RECT sRect; + sRect.left = 0; + sRect.top = 26; + sRect.right = 1000; + sRect.bottom = 507; + FillRect(hdc, &sRect, hBrush); - EndPaint(hwndDlg,&sPaint); - return TRUE; + EndPaint(hwndDlg,&sPaint); + return TRUE; } - }; - return FALSE; } -}; \ No newline at end of file + return FALSE; +} + +} diff --git a/tools/assimp_view/Input.cpp b/tools/assimp_view/Input.cpp index 7a9582fb2..56007bdf1 100644 --- a/tools/assimp_view/Input.cpp +++ b/tools/assimp_view/Input.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2015, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. diff --git a/tools/assimp_view/LogDisplay.cpp b/tools/assimp_view/LogDisplay.cpp index bf0c190b6..d24b9bf20 100644 --- a/tools/assimp_view/LogDisplay.cpp +++ b/tools/assimp_view/LogDisplay.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2015, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -46,32 +46,26 @@ namespace AssimpView { CLogDisplay CLogDisplay::s_cInstance; //------------------------------------------------------------------------------- -void CLogDisplay::AddEntry(const std::string& szText, - const D3DCOLOR clrColor) - { +void CLogDisplay::AddEntry(const std::string& szText, const D3DCOLOR clrColor) { SEntry sNew; sNew.clrColor = clrColor; sNew.szText = szText; sNew.dwStartTicks = (DWORD)GetTickCount(); this->asEntries.push_back(sNew); - } +} //------------------------------------------------------------------------------- -void CLogDisplay::ReleaseNativeResource() - { - if (this->piFont) - { +void CLogDisplay::ReleaseNativeResource() { + if (this->piFont) { this->piFont->Release(); - this->piFont = NULL; - } + this->piFont = nullptr; } +} //------------------------------------------------------------------------------- -void CLogDisplay::RecreateNativeResource() - { - if (!this->piFont) - { +void CLogDisplay::RecreateNativeResource() { + if (!this->piFont) { if (FAILED(D3DXCreateFont(g_piDevice, 16, //Font height 0, //Font width @@ -84,20 +78,17 @@ void CLogDisplay::RecreateNativeResource() 5, //Quality DEFAULT_PITCH|FF_DONTCARE, //PitchAndFamily "Verdana", //pFacename, - &this->piFont))) - { + &this->piFont))) { CLogDisplay::Instance().AddEntry("Unable to load font",D3DCOLOR_ARGB(0xFF,0xFF,0,0)); - this->piFont = NULL; + this->piFont = nullptr; return; - } } - return; } +} //------------------------------------------------------------------------------- -void CLogDisplay::OnRender() - { +void CLogDisplay::OnRender() { DWORD dwTick = (DWORD) GetTickCount(); DWORD dwLimit = dwTick - 8000; DWORD dwLimit2 = dwLimit + 3000; @@ -117,9 +108,8 @@ void CLogDisplay::OnRender() sRect.bottom = sWndRect.bottom; // if no asset is loaded draw a "no asset loaded" text in the center - if (!g_pcAsset) - { - const char* szText = "Nothing to display ... \r\nTry [Viewer | Open asset] to load an asset"; + if (!g_pcAsset) { + const char* szText = "Nothing to display ... \r\nTry [Viewer | Open asset] to load an asset"; // shadow RECT sCopy; @@ -151,38 +141,34 @@ void CLogDisplay::OnRender() // text this->piFont->DrawText(NULL,szText , -1,&sWndRect,DT_CENTER | DT_VCENTER,D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0xFF)); - } + } // update all elements in the queue and render them for (std::list::iterator - i = this->asEntries.begin(); - i != this->asEntries.end();++i,++iCnt) - { - if ((*i).dwStartTicks < dwLimit) - { + i = this->asEntries.begin(); + i != this->asEntries.end();++i,++iCnt) { + if ((*i).dwStartTicks < dwLimit) { i = this->asEntries.erase(i); - if(i == this->asEntries.end())break; + if (i == this->asEntries.end()) { + break; } - else if (NULL != this->piFont) - { + } else if (nullptr != this->piFont) { float fAlpha = 1.0f; - if ((*i).dwStartTicks <= dwLimit2) - { + if ((*i).dwStartTicks <= dwLimit2) { // linearly interpolate to create the fade out effect fAlpha = 1.0f - (float)(dwLimit2 - (*i).dwStartTicks) / 3000.0f; - } + } D3DCOLOR& clrColor = (*i).clrColor; clrColor &= ~(0xFFu << 24); clrColor |= (((unsigned char)(fAlpha * 255.0f)) & 0xFFu) << 24; const char* szText = (*i).szText.c_str(); - if (sRect.top + 30 > sWndRect.bottom) - { + if (sRect.top + 30 > sWndRect.bottom) { // end of window. send a special message szText = "... too many errors"; clrColor = D3DCOLOR_ARGB(0xFF,0xFF,100,0x0); - } + } // draw the black shadow RECT sCopy; @@ -225,9 +211,11 @@ void CLogDisplay::OnRender() sRect.top += iPX; sRect.bottom += iPX; - if (szText != (*i).szText.c_str())break; + if (szText != (*i).szText.c_str()) { + break; } } - return; } -}; \ No newline at end of file +} + +} diff --git a/tools/assimp_view/LogWindow.cpp b/tools/assimp_view/LogWindow.cpp index dba70ee71..ca9b88f95 100644 --- a/tools/assimp_view/LogWindow.cpp +++ b/tools/assimp_view/LogWindow.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2015, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -101,13 +101,11 @@ INT_PTR CALLBACK LogDialogProc(HWND hwndDlg,UINT uMsg, } //------------------------------------------------------------------------------- -void CLogWindow::Init () -{ +void CLogWindow::Init () { this->hwnd = ::CreateDialog(g_hInstance,MAKEINTRESOURCE(IDD_LOGVIEW), NULL,&LogDialogProc); - if (!this->hwnd) - { + if (!this->hwnd) { CLogDisplay::Instance().AddEntry("[ERROR] Unable to create logger window", D3DCOLOR_ARGB(0xFF,0,0xFF,0)); } @@ -116,11 +114,10 @@ void CLogWindow::Init () this->szText = AI_VIEW_RTF_LOG_HEADER;; this->szPlainText = ""; } + //------------------------------------------------------------------------------- -void CLogWindow::Show() -{ - if (this->hwnd) - { +void CLogWindow::Show() { + if (this->hwnd) { ShowWindow(this->hwnd,SW_SHOW); this->bIsVisible = true; @@ -128,24 +125,23 @@ void CLogWindow::Show() this->Update(); } } + //------------------------------------------------------------------------------- -void CMyLogStream::write(const char* message) -{ +void CMyLogStream::write(const char* message) { CLogWindow::Instance().WriteLine(message); } + //------------------------------------------------------------------------------- -void CLogWindow::Clear() -{ +void CLogWindow::Clear() { this->szText = AI_VIEW_RTF_LOG_HEADER;; this->szPlainText = ""; this->Update(); } + //------------------------------------------------------------------------------- -void CLogWindow::Update() -{ - if (this->bIsVisible) - { +void CLogWindow::Update() { + if (this->bIsVisible) { SETTEXTEX sInfo; sInfo.flags = ST_DEFAULT; sInfo.codepage = CP_ACP; @@ -154,20 +150,16 @@ void CLogWindow::Update() EM_SETTEXTEX,(WPARAM)&sInfo,( LPARAM)this->szText.c_str()); } } + //------------------------------------------------------------------------------- -void CLogWindow::Save() -{ +void CLogWindow::Save() { char szFileName[MAX_PATH]; DWORD dwTemp = MAX_PATH; - if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"LogDestination",NULL,NULL, - (BYTE*)szFileName,&dwTemp)) - { + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"LogDestination",NULL,NULL,(BYTE*)szFileName,&dwTemp)) { // Key was not found. Use C: strcpy(szFileName,""); - } - else - { + } else { // need to remove the file name char* sz = strrchr(szFileName,'\\'); if (!sz) @@ -196,14 +188,13 @@ void CLogWindow::Save() CLogDisplay::Instance().AddEntry("[INFO] The log file has been saved", D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0)); } + //------------------------------------------------------------------------------- -void CLogWindow::WriteLine(const char* message) -{ +void CLogWindow::WriteLine(const char* message) { this->szPlainText.append(message); this->szPlainText.append("\r\n"); - if (0 != this->szText.length()) - { + if (0 != this->szText.length()) { this->szText.resize(this->szText.length()-1); } @@ -231,12 +222,10 @@ void CLogWindow::WriteLine(const char* message) } std::string _message = message; - for (unsigned int i = 0; i < _message.length();++i) - { + for (unsigned int i = 0; i < _message.length();++i) { if ('\\' == _message[i] || '}' == _message[i] || - '{' == _message[i]) - { + '{' == _message[i]) { _message.insert(i++,"\\"); } } @@ -244,8 +233,7 @@ void CLogWindow::WriteLine(const char* message) this->szText.append(_message); this->szText.append("\\par}}"); - if (this->bIsVisible && this->bUpdate) - { + if (this->bIsVisible && this->bUpdate) { SETTEXTEX sInfo; sInfo.flags = ST_DEFAULT; sInfo.codepage = CP_ACP; @@ -253,7 +241,6 @@ void CLogWindow::WriteLine(const char* message) SendDlgItemMessage(this->hwnd,IDC_EDIT1, EM_SETTEXTEX,(WPARAM)&sInfo,( LPARAM)this->szText.c_str()); } - return; } -}; //! AssimpView \ No newline at end of file +} //! AssimpView diff --git a/tools/assimp_view/Material.cpp b/tools/assimp_view/Material.cpp index 1fb13f5a8..2c5316d81 100644 --- a/tools/assimp_view/Material.cpp +++ b/tools/assimp_view/Material.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2015, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -136,7 +136,6 @@ extern float g_smoothAngle /*= 80.f*/; extern unsigned int ppsteps, ppstepsdefault; extern bool nopointslines; - CMaterialManager CMaterialManager::s_cInstance; //------------------------------------------------------------------------------- diff --git a/tools/assimp_view/MeshRenderer.cpp b/tools/assimp_view/MeshRenderer.cpp index 834c5a9e2..dfa249735 100644 --- a/tools/assimp_view/MeshRenderer.cpp +++ b/tools/assimp_view/MeshRenderer.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2015, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -49,8 +49,7 @@ namespace AssimpView { CMeshRenderer CMeshRenderer::s_cInstance; //------------------------------------------------------------------------------- -int CMeshRenderer::DrawUnsorted(unsigned int iIndex) -{ +int CMeshRenderer::DrawUnsorted(unsigned int iIndex) { ai_assert(iIndex < g_pcAsset->pcScene->mNumMeshes); // set vertex and index buffer @@ -77,8 +76,7 @@ int CMeshRenderer::DrawUnsorted(unsigned int iIndex) return 1; } //------------------------------------------------------------------------------- -int CMeshRenderer::DrawSorted(unsigned int iIndex,const aiMatrix4x4& mWorld) -{ +int CMeshRenderer::DrawSorted(unsigned int iIndex,const aiMatrix4x4& mWorld) { ai_assert(iIndex < g_pcAsset->pcScene->mNumMeshes); AssetHelper::MeshHelper* pcHelper = g_pcAsset->apcMeshes[iIndex]; diff --git a/tools/assimp_view/MessageProc.cpp b/tools/assimp_view/MessageProc.cpp index 5a9cfd0ed..f9bcf2e9d 100644 --- a/tools/assimp_view/MessageProc.cpp +++ b/tools/assimp_view/MessageProc.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2015, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -47,9 +47,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #ifdef __MINGW32__ -#include +# include #else -#include +# include #endif namespace AssimpView { @@ -92,31 +92,29 @@ void MakeFileAssociations() { GetModuleFileName(NULL,szTemp2,MAX_PATH); sprintf(szTemp,"%s %%1",szTemp2); - HKEY g_hRegistry; + HKEY hRegistry = NULL; aiString list, tmp; aiGetExtensionList(&list); tmp = list; const char* sz = strtok(list.data,";"); - do - { + do { char buf[256]; ai_assert(sz[0] == '*'); sprintf(buf,"Software\\Classes\\%s",sz+1); - RegCreateKeyEx(HKEY_CURRENT_USER,buf,0,NULL,0,KEY_ALL_ACCESS, NULL, &g_hRegistry,NULL); - RegSetValueEx(g_hRegistry,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); - RegCloseKey(g_hRegistry); - } - while ((sz = strtok(NULL,";"))); + RegCreateKeyEx(HKEY_CURRENT_USER,buf,0,NULL,0,KEY_ALL_ACCESS, NULL, &hRegistry,NULL); + RegSetValueEx(hRegistry,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); + RegCloseKey(hRegistry); + } while ((sz = strtok(NULL,";"))); - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\ASSIMPVIEW_CLASS",0,NULL,0,KEY_ALL_ACCESS, NULL, &g_hRegistry,NULL); - RegCloseKey(g_hRegistry); + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\ASSIMPVIEW_CLASS",0,NULL,0,KEY_ALL_ACCESS, NULL, &hRegistry,NULL); + RegCloseKey(hRegistry); - RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\ASSIMPVIEW_CLASS\\shell\\open\\command",0,NULL,0,KEY_ALL_ACCESS, NULL, &g_hRegistry,NULL); - RegSetValueEx(g_hRegistry,"",0,REG_SZ,(const BYTE*)szTemp,(DWORD)strlen(szTemp)+1); - RegCloseKey(g_hRegistry); + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\ASSIMPVIEW_CLASS\\shell\\open\\command",0,NULL,0,KEY_ALL_ACCESS, NULL, &hRegistry,NULL); + RegSetValueEx(hRegistry,"",0,REG_SZ,(const BYTE*)szTemp,(DWORD)strlen(szTemp)+1); + RegCloseKey(hRegistry); CLogDisplay::Instance().AddEntry("[OK] File assocations have been registered", D3DCOLOR_ARGB(0xFF,0,0xFF,0)); @@ -124,19 +122,19 @@ void MakeFileAssociations() { CLogDisplay::Instance().AddEntry(tmp.data,D3DCOLOR_ARGB(0xFF,0,0xFF,0)); } - //------------------------------------------------------------------------------- // Handle command line parameters // // The function loads an asset specified on the command line as first argument // Other command line parameters are not handled //------------------------------------------------------------------------------- -void HandleCommandLine(char* p_szCommand) -{ +void HandleCommandLine(char* p_szCommand) { char* sz = p_szCommand; //bool bQuak = false; - if (strlen(sz) < 2)return; + if (strlen(sz) < 2) { + return; + } if (*sz == '\"') { char* sz2 = strrchr(sz,'\"'); @@ -157,8 +155,7 @@ void HandleCommandLine(char* p_szCommand) //------------------------------------------------------------------------------- // Load the light colors from the registry //------------------------------------------------------------------------------- -void LoadLightColors() -{ +void LoadLightColors() { DWORD dwTemp = 4; RegQueryValueEx(g_hRegistry,"LightColor0",NULL,NULL, (BYTE*)&g_avLightColors[0],&dwTemp); RegQueryValueEx(g_hRegistry,"LightColor1",NULL,NULL, (BYTE*)&g_avLightColors[1],&dwTemp); @@ -168,8 +165,7 @@ void LoadLightColors() //------------------------------------------------------------------------------- // Save the light colors to the registry //------------------------------------------------------------------------------- -void SaveLightColors() -{ +void SaveLightColors() { RegSetValueExA(g_hRegistry,"LightColor0",0,REG_DWORD,(const BYTE*)&g_avLightColors[0],4); RegSetValueExA(g_hRegistry,"LightColor1",0,REG_DWORD,(const BYTE*)&g_avLightColors[1],4); RegSetValueExA(g_hRegistry,"LightColor2",0,REG_DWORD,(const BYTE*)&g_avLightColors[2],4); @@ -178,8 +174,7 @@ void SaveLightColors() //------------------------------------------------------------------------------- // Save the checker pattern colors to the registry //------------------------------------------------------------------------------- -void SaveCheckerPatternColors() -{ +void SaveCheckerPatternColors() { // we have it as float4. save it as binary value --. RegSetValueExA(g_hRegistry,"CheckerPattern0",0,REG_BINARY, (const BYTE*)CDisplay::Instance().GetFirstCheckerColor(), @@ -193,8 +188,7 @@ void SaveCheckerPatternColors() //------------------------------------------------------------------------------- // Load the checker pattern colors from the registry //------------------------------------------------------------------------------- -void LoadCheckerPatternColors() -{ +void LoadCheckerPatternColors() { DWORD dwTemp = sizeof(D3DXVECTOR3); RegQueryValueEx(g_hRegistry,"CheckerPattern0",NULL,NULL, (BYTE*) /* jep, this is evil */ CDisplay::Instance().GetFirstCheckerColor(),&dwTemp); @@ -206,8 +200,7 @@ void LoadCheckerPatternColors() //------------------------------------------------------------------------------- // Changed pp setup //------------------------------------------------------------------------------- -void UpdatePPSettings() -{ +void UpdatePPSettings() { DWORD dwValue = ppsteps; RegSetValueExA(g_hRegistry,"PostProcessing",0,REG_DWORD,(const BYTE*)&dwValue,4); UpdateWindow(g_hDlg); @@ -216,8 +209,7 @@ void UpdatePPSettings() //------------------------------------------------------------------------------- // Toggle the "Display Normals" state //------------------------------------------------------------------------------- -void ToggleNormals() -{ +void ToggleNormals() { g_sOptions.bRenderNormals = !g_sOptions.bRenderNormals; // store this in the registry, too @@ -226,97 +218,72 @@ void ToggleNormals() RegSetValueExA(g_hRegistry,"RenderNormals",0,REG_DWORD,(const BYTE*)&dwValue,4); } +static void storeRegKey(bool option, LPCSTR name) { + // store this in the registry, too + DWORD dwValue = 0; + if (option) { + dwValue = 1; + } + RegSetValueExA(g_hRegistry, name, 0, REG_DWORD, (const BYTE*)&dwValue, 4); + +} //------------------------------------------------------------------------------- // Toggle the "AutoRotate" state //------------------------------------------------------------------------------- -void ToggleAutoRotate() -{ +void ToggleAutoRotate() { g_sOptions.bRotate = !g_sOptions.bRotate; - - // store this in the registry, too - DWORD dwValue = 0; - if (g_sOptions.bRotate)dwValue = 1; - RegSetValueExA(g_hRegistry,"AutoRotate",0,REG_DWORD,(const BYTE*)&dwValue,4); + storeRegKey(g_sOptions.bRotate, "AutoRotate"); UpdateWindow(g_hDlg); } //------------------------------------------------------------------------------- // Toggle the "FPS" state //------------------------------------------------------------------------------- -void ToggleFPSView() -{ +void ToggleFPSView() { g_bFPSView = !g_bFPSView; SetupFPSView(); - - // store this in the registry, too - DWORD dwValue = 0; - if (g_bFPSView)dwValue = 1; - RegSetValueExA(g_hRegistry,"FPSView",0,REG_DWORD,(const BYTE*)&dwValue,4); + storeRegKey(g_bFPSView, "FPSView"); } //------------------------------------------------------------------------------- // Toggle the "2 Light sources" state //------------------------------------------------------------------------------- -void ToggleMultipleLights() -{ +void ToggleMultipleLights() { g_sOptions.b3Lights = !g_sOptions.b3Lights; - - // store this in the registry, too - DWORD dwValue = 0; - if (g_sOptions.b3Lights)dwValue = 1; - RegSetValueExA(g_hRegistry,"MultipleLights",0,REG_DWORD,(const BYTE*)&dwValue,4); + storeRegKey(g_sOptions.b3Lights, "MultipleLights"); } //------------------------------------------------------------------------------- // Toggle the "LightRotate" state //------------------------------------------------------------------------------- -void ToggleLightRotate() -{ +void ToggleLightRotate() { g_sOptions.bLightRotate = !g_sOptions.bLightRotate; - - // store this in the registry, too - DWORD dwValue = 0; - if (g_sOptions.bLightRotate)dwValue = 1; - RegSetValueExA(g_hRegistry,"LightRotate",0,REG_DWORD,(const BYTE*)&dwValue,4); + storeRegKey(g_sOptions.bLightRotate, "LightRotate"); } //------------------------------------------------------------------------------- // Toggle the "NoTransparency" state //------------------------------------------------------------------------------- -void ToggleTransparency() -{ +void ToggleTransparency() { g_sOptions.bNoAlphaBlending = !g_sOptions.bNoAlphaBlending; - - // store this in the registry, too - DWORD dwValue = 0; - if (g_sOptions.bNoAlphaBlending)dwValue = 1; - RegSetValueExA(g_hRegistry,"NoTransparency",0,REG_DWORD,(const BYTE*)&dwValue,4); + storeRegKey(g_sOptions.bNoAlphaBlending, "NoTransparency"); } //------------------------------------------------------------------------------- // Toggle the "LowQuality" state //------------------------------------------------------------------------------- -void ToggleLowQuality() -{ +void ToggleLowQuality() { g_sOptions.bLowQuality = !g_sOptions.bLowQuality; - - // store this in the registry, too - DWORD dwValue = 0; - if (g_sOptions.bLowQuality)dwValue = 1; - RegSetValueExA(g_hRegistry,"LowQuality",0,REG_DWORD,(const BYTE*)&dwValue,4); + storeRegKey(g_sOptions.bLowQuality, "LowQuality"); } //------------------------------------------------------------------------------- // Toggle the "Specular" state //------------------------------------------------------------------------------- -void ToggleSpecular() -{ +void ToggleSpecular() { g_sOptions.bNoSpecular = !g_sOptions.bNoSpecular; - // store this in the registry, too - DWORD dwValue = 0; - if (g_sOptions.bNoSpecular)dwValue = 1; - RegSetValueExA(g_hRegistry,"NoSpecular",0,REG_DWORD,(const BYTE*)&dwValue,4); + storeRegKey(g_sOptions.bNoSpecular, "NoSpecular"); // update all specular materials CMaterialManager::Instance().UpdateSpecularMaterials(); @@ -325,14 +292,10 @@ void ToggleSpecular() //------------------------------------------------------------------------------- // Toggle the "RenderMats" state //------------------------------------------------------------------------------- -void ToggleMats() -{ +void ToggleMats() { g_sOptions.bRenderMats = !g_sOptions.bRenderMats; - // store this in the registry, too - DWORD dwValue = 0; - if (g_sOptions.bRenderMats)dwValue = 1; - RegSetValueExA(g_hRegistry,"RenderMats",0,REG_DWORD,(const BYTE*)&dwValue,4); + storeRegKey(g_sOptions.bRenderMats, "RenderMats"); // update all specular materials CMaterialManager::Instance().UpdateSpecularMaterials(); @@ -341,45 +304,32 @@ void ToggleMats() //------------------------------------------------------------------------------- // Toggle the "Culling" state //------------------------------------------------------------------------------- -void ToggleCulling() -{ +void ToggleCulling() { g_sOptions.bCulling = !g_sOptions.bCulling; - - // store this in the registry, too - DWORD dwValue = 0; - if (g_sOptions.bCulling)dwValue = 1; - RegSetValueExA(g_hRegistry,"Culling",0,REG_DWORD,(const BYTE*)&dwValue,4); + storeRegKey(g_sOptions.bCulling, "Culling"); } //------------------------------------------------------------------------------- // Toggle the "Skeleton" state //------------------------------------------------------------------------------- -void ToggleSkeleton() -{ +void ToggleSkeleton() { g_sOptions.bSkeleton = !g_sOptions.bSkeleton; - - // store this in the registry, too - DWORD dwValue = 0; - if (g_sOptions.bCulling)dwValue = 1; - RegSetValueExA(g_hRegistry,"Skeleton",0,REG_DWORD,(const BYTE*)&dwValue,4); + storeRegKey(g_sOptions.bSkeleton, "Skeleton"); } //------------------------------------------------------------------------------- // Toggle the "WireFrame" state //------------------------------------------------------------------------------- -void ToggleWireFrame() -{ - if (g_sOptions.eDrawMode == RenderOptions::WIREFRAME) +void ToggleWireFrame() { + if (g_sOptions.eDrawMode == RenderOptions::WIREFRAME) { g_sOptions.eDrawMode = RenderOptions::NORMAL; - else g_sOptions.eDrawMode = RenderOptions::WIREFRAME; + } else { + g_sOptions.eDrawMode = RenderOptions::WIREFRAME; + } - // store this in the registry, too - DWORD dwValue = 0; - if (RenderOptions::WIREFRAME == g_sOptions.eDrawMode)dwValue = 1; - RegSetValueExA(g_hRegistry,"Wireframe",0,REG_DWORD,(const BYTE*)&dwValue,4); + storeRegKey(RenderOptions::WIREFRAME == g_sOptions.eDrawMode, "Wireframe"); } - //------------------------------------------------------------------------------- // Toggle the "MultiSample" state //------------------------------------------------------------------------------- @@ -388,8 +338,7 @@ void ToggleMS() g_sOptions.bMultiSample = !g_sOptions.bMultiSample; DeleteAssetData(); ShutdownDevice(); - if (0 == CreateDevice()) - { + if (0 == CreateDevice()) { CLogDisplay::Instance().AddEntry( "[ERROR] Failed to toggle MultiSampling mode"); g_sOptions.bMultiSample = !g_sOptions.bMultiSample; @@ -397,28 +346,21 @@ void ToggleMS() } CreateAssetData(); - if (g_sOptions.bMultiSample) - { + if (g_sOptions.bMultiSample) { CLogDisplay::Instance().AddEntry( "[OK] Changed MultiSampling mode to the maximum value for this device"); - } - else - { + } else { CLogDisplay::Instance().AddEntry( "[OK] MultiSampling has been disabled"); } - // store this in the registry, too - DWORD dwValue = 0; - if (g_sOptions.bMultiSample)dwValue = 1; - RegSetValueExA(g_hRegistry,"MultiSampling",0,REG_DWORD,(const BYTE*)&dwValue,4); + storeRegKey(g_sOptions.bMultiSample, "MultiSampling"); } //------------------------------------------------------------------------------- // Expand or collapse the UI //------------------------------------------------------------------------------- -void ToggleUIState() -{ +void ToggleUIState() { // adjust the size RECT sRect; GetWindowRect(g_hDlg,&sRect); @@ -430,46 +372,33 @@ void ToggleUIState() sRect2.left -= sRect.left; sRect2.top -= sRect.top; - DWORD dwValue; - if (BST_UNCHECKED == IsDlgButtonChecked(g_hDlg,IDC_BLUBB)) - { + if (BST_UNCHECKED == IsDlgButtonChecked(g_hDlg,IDC_BLUBB)) { SetWindowPos(g_hDlg,NULL,0,0,sRect.right-214,sRect.bottom, SWP_NOMOVE | SWP_NOZORDER); - dwValue = 0; SetWindowText(GetDlgItem(g_hDlg,IDC_BLUBB),">>"); - RegSetValueExA(g_hRegistry,"LastUIState",0,REG_DWORD,(const BYTE*)&dwValue,4); - } - else - { + storeRegKey(false, "MultiSampling"); + } else { SetWindowPos(g_hDlg,NULL,0,0,sRect.right+214,sRect.bottom, SWP_NOMOVE | SWP_NOZORDER); - dwValue = 1; + storeRegKey(true, "LastUIState"); SetWindowText(GetDlgItem(g_hDlg,IDC_BLUBB),"<<"); - RegSetValueExA(g_hRegistry,"LastUIState",0,REG_DWORD,(const BYTE*)&dwValue,4); } UpdateWindow(g_hDlg); - return; } - //------------------------------------------------------------------------------- // Load the background texture for the cviewer //------------------------------------------------------------------------------- -void LoadBGTexture() -{ +void LoadBGTexture() { char szFileName[MAX_PATH]; DWORD dwTemp = MAX_PATH; - if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"TextureSrc",NULL,NULL, - (BYTE*)szFileName,&dwTemp)) - { + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"TextureSrc",NULL,NULL, (BYTE*)szFileName,&dwTemp)) { // Key was not found. Use C: strcpy(szFileName,""); - } - else - { + } else { // need to remove the file name char* sz = strrchr(szFileName,'\\'); if (!sz) @@ -495,14 +424,12 @@ void LoadBGTexture() RegSetValueExA(g_hRegistry,"LastSkyBoxSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); CBackgroundPainter::Instance().SetTextureBG(szFileName); - return; } //------------------------------------------------------------------------------- // Reset the background color to a smart and nice grey //------------------------------------------------------------------------------- -void ClearBG() -{ +void ClearBG() { D3DCOLOR clrColor = D3DCOLOR_ARGB(0xFF,100,100,100); CBackgroundPainter::Instance().SetColor(clrColor); @@ -510,14 +437,12 @@ void ClearBG() RegSetValueExA(g_hRegistry,"LastTextureSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); RegSetValueExA(g_hRegistry,"Color",0,REG_DWORD,(const BYTE*)&clrColor,4); - return; } //------------------------------------------------------------------------------- // Let the user choose a color in a windows standard color dialog //------------------------------------------------------------------------------- -void DisplayColorDialog(D3DCOLOR* pclrResult) -{ +void DisplayColorDialog(D3DCOLOR* pclrResult) { CHOOSECOLOR clr; clr.lStructSize = sizeof(CHOOSECOLOR); clr.hwndOwner = g_hDlg; @@ -534,15 +459,12 @@ void DisplayColorDialog(D3DCOLOR* pclrResult) GetRValue(clr.rgbResult), GetGValue(clr.rgbResult), GetBValue(clr.rgbResult)); - return; } - //------------------------------------------------------------------------------- // Let the user choose a color in a windows standard color dialog //------------------------------------------------------------------------------- -void DisplayColorDialog(D3DXVECTOR4* pclrResult) -{ +void DisplayColorDialog(D3DXVECTOR4* pclrResult) { CHOOSECOLOR clr; clr.lStructSize = sizeof(CHOOSECOLOR); clr.hwndOwner = g_hDlg; @@ -560,14 +482,12 @@ void DisplayColorDialog(D3DXVECTOR4* pclrResult) pclrResult->x = GetRValue(clr.rgbResult) / 255.0f; pclrResult->y = GetGValue(clr.rgbResult) / 255.0f; pclrResult->z = GetBValue(clr.rgbResult) / 255.0f; - return; } //------------------------------------------------------------------------------- -// Let the user choose the baclground color for the viewer +// Let the user choose the background color for the viewer //------------------------------------------------------------------------------- -void ChooseBGColor() -{ +void ChooseBGColor() { RegSetValueExA(g_hRegistry,"LastSkyBoxSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); RegSetValueExA(g_hRegistry,"LastTextureSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); @@ -576,14 +496,12 @@ void ChooseBGColor() CBackgroundPainter::Instance().SetColor(clrColor); RegSetValueExA(g_hRegistry,"Color",0,REG_DWORD,(const BYTE*)&clrColor,4); - return; } //------------------------------------------------------------------------------- // Display the OpenFile dialog and let the user choose a new slybox as bg //------------------------------------------------------------------------------- -void LoadSkybox() -{ +void LoadSkybox() { char szFileName[MAX_PATH]; DWORD dwTemp = MAX_PATH; @@ -622,23 +540,26 @@ void LoadSkybox() return; } +template +inline +void SaveRelease(T **iface ) { + if (nullptr != iface) { + (*iface)->Release(); + *iface = nullptr; + } +} //------------------------------------------------------------------------------- -// Sace a screenshot to an user-defined file +// Save a screenshot to an user-defined file //------------------------------------------------------------------------------- -void SaveScreenshot() -{ +void SaveScreenshot() { char szFileName[MAX_PATH]; DWORD dwTemp = MAX_PATH; - if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"ScreenShot",NULL,NULL, - (BYTE*)szFileName,&dwTemp)) - { + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"ScreenShot",NULL,NULL, (BYTE*)szFileName,&dwTemp)) { // Key was not found. Use C: strcpy(szFileName,""); - } - else - { + } else { // need to remove the file name char* sz = strrchr(szFileName,'\\'); if (!sz) @@ -662,49 +583,42 @@ void SaveScreenshot() IDirect3DSurface9* pi = NULL; g_piDevice->GetRenderTarget(0,&pi); - if(!pi || FAILED(D3DXSaveSurfaceToFile(szFileName,D3DXIFF_PNG,pi,NULL,NULL))) - { + if(!pi || FAILED(D3DXSaveSurfaceToFile(szFileName,D3DXIFF_PNG,pi,NULL,NULL))) { CLogDisplay::Instance().AddEntry("[ERROR] Unable to save screenshot", D3DCOLOR_ARGB(0xFF,0xFF,0,0)); - } - else - { + } else { CLogDisplay::Instance().AddEntry("[INFO] The screenshot has been saved", D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0)); } - if(pi)pi->Release(); - return; + SaveRelease(&pi); } //------------------------------------------------------------------------------- // Get the amount of memory required for textures //------------------------------------------------------------------------------- -void AddTextureMem(IDirect3DTexture9* pcTex, unsigned int& out) -{ - if (!pcTex)return; +void AddTextureMem(IDirect3DTexture9* pcTex, unsigned int& out) { + if (!pcTex) { + return; + } D3DSURFACE_DESC sDesc; pcTex->GetLevelDesc(0,&sDesc); out += (sDesc.Width * sDesc.Height) << 2; - return; } //------------------------------------------------------------------------------- // Display memory statistics //------------------------------------------------------------------------------- -void DisplayMemoryConsumption() -{ +void DisplayMemoryConsumption() { // first get the memory consumption for the aiScene - if (! g_pcAsset ||!g_pcAsset->pcScene) - { + if (! g_pcAsset ||!g_pcAsset->pcScene) { MessageBox(g_hDlg,"No asset is loaded. Can you guess how much memory I need to store nothing?", "Memory consumption",MB_OK); return; } unsigned int iScene = sizeof(aiScene); - for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) - { + for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) { iScene += sizeof(aiMesh); if (g_pcAsset->pcScene->mMeshes[i]->HasPositions()) iScene += sizeof(aiVector3D) * g_pcAsset->pcScene->mMeshes[i]->mNumVertices; @@ -715,22 +629,20 @@ void DisplayMemoryConsumption() if (g_pcAsset->pcScene->mMeshes[i]->HasTangentsAndBitangents()) iScene += sizeof(aiVector3D) * g_pcAsset->pcScene->mMeshes[i]->mNumVertices * 2; - for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS;++a) - { - if (g_pcAsset->pcScene->mMeshes[i]->HasVertexColors(a)) + for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS;++a) { + if (g_pcAsset->pcScene->mMeshes[i]->HasVertexColors(a)) { iScene += sizeof(aiColor4D) * g_pcAsset->pcScene->mMeshes[i]->mNumVertices; - else break; + } else { + break; + } } - for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a) - { + for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a) { if (g_pcAsset->pcScene->mMeshes[i]->HasTextureCoords(a)) iScene += sizeof(aiVector3D) * g_pcAsset->pcScene->mMeshes[i]->mNumVertices; else break; } - if (g_pcAsset->pcScene->mMeshes[i]->HasBones()) - { - for (unsigned int p = 0; p < g_pcAsset->pcScene->mMeshes[i]->mNumBones;++p) - { + if (g_pcAsset->pcScene->mMeshes[i]->HasBones()) { + for (unsigned int p = 0; p < g_pcAsset->pcScene->mMeshes[i]->mNumBones;++p) { iScene += sizeof(aiBone); iScene += g_pcAsset->pcScene->mMeshes[i]->mBones[p]->mNumWeights * sizeof(aiVertexWeight); } @@ -738,22 +650,20 @@ void DisplayMemoryConsumption() iScene += (sizeof(aiFace) + 3 * sizeof(unsigned int))*g_pcAsset->pcScene->mMeshes[i]->mNumFaces; } // add all embedded textures - for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumTextures;++i) - { + for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumTextures;++i) { const aiTexture* pc = g_pcAsset->pcScene->mTextures[i]; - if (0 != pc->mHeight) - { + if (0 != pc->mHeight) { iScene += 4 * pc->mHeight * pc->mWidth; + } else { + iScene += pc->mWidth; } - else iScene += pc->mWidth; } // add 30k for each material ... a string has 4k for example iScene += g_pcAsset->pcScene->mNumMaterials * 30 * 1024; // now get the memory consumption required by D3D, first all textures unsigned int iTexture = 0; - for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) - { + for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) { AssetHelper::MeshHelper* pc = g_pcAsset->apcMeshes[i]; AddTextureMem(pc->piDiffuseTexture,iTexture); @@ -767,15 +677,13 @@ void DisplayMemoryConsumption() unsigned int iVRAM = iTexture; // now get the memory consumption of all vertex/index buffers - unsigned int iVB = 0; - unsigned int iIB = 0; - for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) - { + unsigned int iVB( 0 ), iIB(0); + for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) { AssetHelper:: MeshHelper* pc = g_pcAsset->apcMeshes[i]; union{ - D3DVERTEXBUFFER_DESC sDesc; - D3DINDEXBUFFER_DESC sDesc2; + D3DVERTEXBUFFER_DESC sDesc; + D3DINDEXBUFFER_DESC sDesc2; }; if (pc->piVB) @@ -814,36 +722,30 @@ void DisplayMemoryConsumption() iScene / 1024,iTexture / 1024,iVB / 1024,iIB / 1024,iVRAM / 1024, (iScene + iTexture + iVB + iIB + iVRAM) / 1024); MessageBox(g_hDlg,szOut,"Memory consumption",MB_OK); - return; } //------------------------------------------------------------------------------- // Save the list of recent files to the registry //------------------------------------------------------------------------------- -void SaveHistory() -{ - for (unsigned int i = 0; i < AI_VIEW_NUM_RECENT_FILES;++i) - { +void SaveHistory() { + for (unsigned int i = 0; i < AI_VIEW_NUM_RECENT_FILES;++i) { char szName[66]; sprintf(szName,"Recent%i",i+1); RegSetValueEx(g_hRegistry,szName,0,REG_SZ, (const BYTE*)g_aPreviousFiles[i].c_str(),(DWORD)g_aPreviousFiles[i].length()); } - return; } //------------------------------------------------------------------------------- // Recover the file history //------------------------------------------------------------------------------- -void LoadHistory() -{ +void LoadHistory() { g_aPreviousFiles.resize(AI_VIEW_NUM_RECENT_FILES); char szFileName[MAX_PATH]; - for (unsigned int i = 0; i < AI_VIEW_NUM_RECENT_FILES;++i) - { + for (unsigned int i = 0; i < AI_VIEW_NUM_RECENT_FILES;++i) { char szName[66]; sprintf(szName,"Recent%i",i+1); @@ -851,20 +753,17 @@ void LoadHistory() szFileName[0] ='\0'; if(ERROR_SUCCESS == RegQueryValueEx(g_hRegistry,szName,NULL,NULL, - (BYTE*)szFileName,&dwTemp)) - { + (BYTE*)szFileName,&dwTemp)) { g_aPreviousFiles[i] = std::string(szFileName); } } // add sub items for all recent files g_hHistoryMenu = CreateMenu(); - for (int i = AI_VIEW_NUM_RECENT_FILES-1; i >= 0;--i) - { + for (int i = AI_VIEW_NUM_RECENT_FILES-1; i >= 0;--i) { const char* szText = g_aPreviousFiles[i].c_str(); UINT iFlags = 0; - if ('\0' == *szText) - { + if ('\0' == *szText) { szText = ""; iFlags = MF_GRAYED | MF_DISABLED; } @@ -873,19 +772,17 @@ void LoadHistory() ModifyMenu(GetMenu(g_hDlg),ID_VIEWER_RECENTFILES,MF_BYCOMMAND | MF_POPUP, (UINT_PTR)g_hHistoryMenu,"Recent files"); - return; } //------------------------------------------------------------------------------- // Clear the file history //------------------------------------------------------------------------------- -void ClearHistory() -{ - for(unsigned int i = 0; i < AI_VIEW_NUM_RECENT_FILES;++i) +void ClearHistory() { + for (unsigned int i = 0; i < AI_VIEW_NUM_RECENT_FILES; ++i) { g_aPreviousFiles[i] = std::string(""); + } - for (int i = AI_VIEW_NUM_RECENT_FILES-1; i >= 0;--i) - { + for (int i = AI_VIEW_NUM_RECENT_FILES-1; i >= 0;--i) { ModifyMenu(g_hHistoryMenu,AI_VIEW_RECENT_FILE_ID(i), MF_STRING | MF_BYCOMMAND | MF_GRAYED | MF_DISABLED,AI_VIEW_RECENT_FILE_ID(i),""); } @@ -896,50 +793,44 @@ void ClearHistory() //------------------------------------------------------------------------------- // Update the file history //------------------------------------------------------------------------------- -void UpdateHistory() -{ - if(!g_hHistoryMenu)return; +void UpdateHistory() { + if (!g_hHistoryMenu) { + return; + } std::string sz = std::string(g_szFileName); - if (g_aPreviousFiles[AI_VIEW_NUM_RECENT_FILES-1] == sz)return; + if (g_aPreviousFiles[AI_VIEW_NUM_RECENT_FILES - 1] == sz) { + return; + } // add the new asset to the list of recent files - for (unsigned int i = 0; i < AI_VIEW_NUM_RECENT_FILES-1;++i) - { + for (unsigned int i = 0; i < AI_VIEW_NUM_RECENT_FILES-1;++i) { g_aPreviousFiles[i] = g_aPreviousFiles[i+1]; } g_aPreviousFiles[AI_VIEW_NUM_RECENT_FILES-1] = sz; - for (int i = AI_VIEW_NUM_RECENT_FILES-1; i >= 0;--i) - { + for (int i = AI_VIEW_NUM_RECENT_FILES-1; i >= 0;--i) { const char* szText = g_aPreviousFiles[i].c_str(); UINT iFlags = 0; - if ('\0' == *szText) - { + if ('\0' == *szText) { szText = ""; iFlags = MF_GRAYED | MF_DISABLED; } ModifyMenu(g_hHistoryMenu,AI_VIEW_RECENT_FILE_ID(i), MF_STRING | MF_BYCOMMAND | iFlags,AI_VIEW_RECENT_FILE_ID(i),szText); } - return; } //------------------------------------------------------------------------------- // Open a new asset //------------------------------------------------------------------------------- -void OpenAsset() -{ +void OpenAsset() { char szFileName[MAX_PATH]; DWORD dwTemp = MAX_PATH; - if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"CurrentApp",NULL,NULL, - (BYTE*)szFileName,&dwTemp)) - { + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"CurrentApp",NULL,NULL, (BYTE*)szFileName,&dwTemp)) { // Key was not found. Use C: strcpy(szFileName,""); - } - else - { + } else { // need to remove the file name char* sz = strrchr(szFileName,'\\'); if (!sz) @@ -970,13 +861,14 @@ void OpenAsset() OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, 0, 1, ".x", 0, NULL, NULL }; - if(GetOpenFileName(&sFilename1) == 0) return; + if (GetOpenFileName(&sFilename1) == 0) { + return; + } // Now store the file in the registry RegSetValueExA(g_hRegistry,"CurrentApp",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); - if (0 != strcmp(g_szFileName,szFileName)) - { + if (0 != strcmp(g_szFileName,szFileName)) { strcpy(g_szFileName, szFileName); DeleteAssetData(); DeleteAsset(); @@ -988,13 +880,10 @@ void OpenAsset() // Save the list of previous files to the registry SaveHistory(); } - return; } //------------------------------------------------------------------------------- -void SetupPPUIState() -{ - +void SetupPPUIState() { // that's ugly. anyone willing to rewrite me from scratch? HMENU hMenu = GetMenu(g_hDlg); CheckMenuItem(hMenu,ID_VIEWER_PP_JIV,ppsteps & aiProcess_JoinIdenticalVertices ? MF_CHECKED : MF_UNCHECKED); @@ -1018,13 +907,11 @@ void SetupPPUIState() //------------------------------------------------------------------------------- // Fill the 'export' top level menu with a list of all supported export formats //------------------------------------------------------------------------------- -void PopulateExportMenu() -{ +void PopulateExportMenu() { // add sub items for all recent files Exporter exp; HMENU hm = ::CreateMenu(); - for(size_t i = 0; i < exp.GetExportFormatCount(); ++i) - { + for(size_t i = 0; i < exp.GetExportFormatCount(); ++i) { const aiExportFormatDesc* const e = exp.GetExportFormatDescription(i); char tmp[256]; sprintf(tmp,"%s (%s)",e->description,e->id); @@ -1038,8 +925,7 @@ void PopulateExportMenu() //------------------------------------------------------------------------------- //------------------------------------------------------------------------------- -void DoExport(size_t formatId) -{ +void DoExport(size_t formatId) { if (!g_szFileName[0]) { MessageBox(g_hDlg, "No model loaded", "Export", MB_ICONERROR); return; @@ -1122,8 +1008,7 @@ void DoExport(size_t formatId) //------------------------------------------------------------------------------- // Initialize the user interface //------------------------------------------------------------------------------- -void InitUI() -{ +void InitUI() { SetDlgItemText(g_hDlg,IDC_EVERT,"0"); SetDlgItemText(g_hDlg,IDC_EFACE,"0"); SetDlgItemText(g_hDlg,IDC_EMAT,"0"); @@ -1147,13 +1032,10 @@ void InitUI() RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\ASSIMP\\Viewer", 0,NULL,0,KEY_ALL_ACCESS, NULL, &g_hRegistry,NULL); - if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"LastUIState",NULL,NULL, - (BYTE*)&dwValue,&dwTemp)) - { + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"LastUIState",NULL,NULL, (BYTE*)&dwValue,&dwTemp)) { dwValue = 1; } - if (0 == dwValue) - { + if (0 == dwValue) { // collapse the viewer // adjust the size RECT sRect; @@ -1169,22 +1051,17 @@ void InitUI() SetWindowPos(g_hDlg,NULL,0,0,sRect.right-214,sRect.bottom, SWP_NOMOVE | SWP_NOZORDER); SetWindowText(GetDlgItem(g_hDlg,IDC_BLUBB),">>"); - } - else - { + } else { CheckDlgButton(g_hDlg,IDC_BLUBB,BST_CHECKED); } // AutoRotate if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"AutoRotate",NULL,NULL, (BYTE*)&dwValue,&dwTemp))dwValue = 0; - if (0 == dwValue) - { + if (0 == dwValue) { g_sOptions.bRotate = false; CheckDlgButton(g_hDlg,IDC_AUTOROTATE,BST_UNCHECKED); - } - else - { + } else { g_sOptions.bRotate = true; CheckDlgButton(g_hDlg,IDC_AUTOROTATE,BST_CHECKED); } @@ -1192,13 +1069,10 @@ void InitUI() // MultipleLights if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"MultipleLights",NULL,NULL, (BYTE*)&dwValue,&dwTemp))dwValue = 0; - if (0 == dwValue) - { + if (0 == dwValue) { g_sOptions.b3Lights = false; CheckDlgButton(g_hDlg,IDC_3LIGHTS,BST_UNCHECKED); - } - else - { + } else { g_sOptions.b3Lights = true; CheckDlgButton(g_hDlg,IDC_3LIGHTS,BST_CHECKED); } @@ -1206,27 +1080,22 @@ void InitUI() // Light rotate if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"LightRotate",NULL,NULL, (BYTE*)&dwValue,&dwTemp))dwValue = 0; - if (0 == dwValue) - { + if (0 == dwValue) { g_sOptions.bLightRotate = false; CheckDlgButton(g_hDlg,IDC_LIGHTROTATE,BST_UNCHECKED); - } - else - { + } else { g_sOptions.bLightRotate = true; CheckDlgButton(g_hDlg,IDC_LIGHTROTATE,BST_CHECKED); } // NoSpecular - if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"NoSpecular",NULL,NULL, - (BYTE*)&dwValue,&dwTemp))dwValue = 0; - if (0 == dwValue) - { + if (ERROR_SUCCESS != RegQueryValueEx(g_hRegistry, "NoSpecular", NULL, NULL, (BYTE*)&dwValue, &dwTemp)) { + dwValue = 0; + } + if (0 == dwValue) { g_sOptions.bNoSpecular = false; CheckDlgButton(g_hDlg,IDC_NOSPECULAR,BST_UNCHECKED); - } - else - { + } else { g_sOptions.bNoSpecular = true; CheckDlgButton(g_hDlg,IDC_NOSPECULAR,BST_CHECKED); } @@ -1234,13 +1103,10 @@ void InitUI() // LowQuality if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"LowQuality",NULL,NULL, (BYTE*)&dwValue,&dwTemp))dwValue = 0; - if (0 == dwValue) - { + if (0 == dwValue) { g_sOptions.bLowQuality = false; CheckDlgButton(g_hDlg,IDC_LOWQUALITY,BST_UNCHECKED); - } - else - { + } else { g_sOptions.bLowQuality = true; CheckDlgButton(g_hDlg,IDC_LOWQUALITY,BST_CHECKED); } @@ -1248,13 +1114,10 @@ void InitUI() // LowQuality if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"NoTransparency",NULL,NULL, (BYTE*)&dwValue,&dwTemp))dwValue = 0; - if (0 == dwValue) - { + if (0 == dwValue) { g_sOptions.bNoAlphaBlending = false; CheckDlgButton(g_hDlg,IDC_NOAB,BST_UNCHECKED); - } - else - { + } else { g_sOptions.bNoAlphaBlending = true; CheckDlgButton(g_hDlg,IDC_NOAB,BST_CHECKED); } @@ -1262,27 +1125,23 @@ void InitUI() // DisplayNormals if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"RenderNormals",NULL,NULL, (BYTE*)&dwValue,&dwTemp))dwValue = 0; - if (0 == dwValue) - { + if (0 == dwValue) { g_sOptions.bRenderNormals = false; CheckDlgButton(g_hDlg,IDC_TOGGLENORMALS,BST_UNCHECKED); - } - else - { + } else { g_sOptions.bRenderNormals = true; CheckDlgButton(g_hDlg,IDC_TOGGLENORMALS,BST_CHECKED); } // NoMaterials - if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"RenderMats",NULL,NULL, - (BYTE*)&dwValue,&dwTemp))dwValue = 1; - if (0 == dwValue) - { + if (ERROR_SUCCESS != RegQueryValueEx(g_hRegistry, "RenderMats", NULL, NULL, + (BYTE*)&dwValue, &dwTemp)) { + dwValue = 1; + } + if (0 == dwValue) { g_sOptions.bRenderMats = false; CheckDlgButton(g_hDlg,IDC_TOGGLEMAT,BST_CHECKED); - } - else - { + } else { g_sOptions.bRenderMats = true; CheckDlgButton(g_hDlg,IDC_TOGGLEMAT,BST_UNCHECKED); } @@ -1294,9 +1153,7 @@ void InitUI() { g_sOptions.bMultiSample = false; CheckDlgButton(g_hDlg,IDC_TOGGLEMS,BST_UNCHECKED); - } - else - { + } else { g_sOptions.bMultiSample = true; CheckDlgButton(g_hDlg,IDC_TOGGLEMS,BST_CHECKED); } @@ -1304,13 +1161,10 @@ void InitUI() // FPS Mode if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"FPSView",NULL,NULL, (BYTE*)&dwValue,&dwTemp))dwValue = 0; - if (0 == dwValue) - { + if (0 == dwValue) { g_bFPSView = false; CheckDlgButton(g_hDlg,IDC_ZOOM,BST_CHECKED); - } - else - { + } else { g_bFPSView = true; CheckDlgButton(g_hDlg,IDC_ZOOM,BST_UNCHECKED); } @@ -1338,22 +1192,20 @@ void InitUI() SendDlgItemMessage(g_hDlg,IDC_SLIDERANIM,TBM_SETRANGEMIN,TRUE,0); SendDlgItemMessage(g_hDlg,IDC_SLIDERANIM,TBM_SETRANGEMAX,TRUE,10000); - return; } //------------------------------------------------------------------------------- -// Message prcoedure for the smooth normals dialog +// Message procedure for the smooth normals dialog //------------------------------------------------------------------------------- -INT_PTR CALLBACK SMMessageProc(HWND hwndDlg,UINT uMsg, - WPARAM wParam,LPARAM lParam) -{ +INT_PTR CALLBACK SMMessageProc(HWND hwndDlg,UINT uMsg, WPARAM wParam,LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); - switch (uMsg) - { + switch (uMsg) { case WM_INITDIALOG: - char s[30]; - ::sprintf(s,"%.2f",g_smoothAngle); - SetDlgItemText(hwndDlg,IDC_EDITSM,s); + { + char s[30]; + ::sprintf(s, "%.2f", g_smoothAngle); + SetDlgItemText(hwndDlg, IDC_EDITSM, s); + } return TRUE; case WM_CLOSE: @@ -1361,16 +1213,16 @@ INT_PTR CALLBACK SMMessageProc(HWND hwndDlg,UINT uMsg, return TRUE; case WM_COMMAND: + { + if (IDOK == LOWORD(wParam)) { + char s[30]; + GetDlgItemText(hwndDlg, IDC_EDITSM, s, 30); + g_smoothAngle = (float)atof(s); - if (IDOK == LOWORD(wParam)) { - char s[30]; - GetDlgItemText(hwndDlg,IDC_EDITSM,s,30); - g_smoothAngle = (float)atof(s); - - EndDialog(hwndDlg,0); - } - else if (IDCANCEL == LOWORD(wParam)) { - EndDialog(hwndDlg,1); + EndDialog(hwndDlg, 0); + } else if (IDCANCEL == LOWORD(wParam)) { + EndDialog(hwndDlg, 1); + } } return TRUE; } @@ -1385,9 +1237,7 @@ INT_PTR CALLBACK SMMessageProc(HWND hwndDlg,UINT uMsg, // NOTE: Due to the impossibility to process WM_CHAR messages in dialogs // properly the code for all hotkeys has been moved to the WndMain //------------------------------------------------------------------------------- -INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, - WPARAM wParam,LPARAM lParam) - { +INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, WPARAM wParam,LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); UNREFERENCED_PARAMETER(wParam); @@ -1830,13 +1680,10 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, case WM_COMMAND: HMENU hMenu = GetMenu(g_hDlg); - if (ID_VIEWER_QUIT == LOWORD(wParam)) - { + if (ID_VIEWER_QUIT == LOWORD(wParam)) { PostQuitMessage(0); DestroyWindow(hwndDlg); - } - else if (IDC_COMBO1 == LOWORD(wParam)) - { + } else if (IDC_COMBO1 == LOWORD(wParam)) { if(HIWORD(wParam) == CBN_SELCHANGE) { const size_t sel = static_cast(ComboBox_GetCurSel(GetDlgItem(hwndDlg,IDC_COMBO1))); if(g_pcAsset) { @@ -1844,9 +1691,7 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, SendDlgItemMessage(hwndDlg,IDC_SLIDERANIM,TBM_SETPOS,TRUE,0); } } - } - else if (ID_VIEWER_RESETVIEW == LOWORD(wParam)) - { + } else if (ID_VIEWER_RESETVIEW == LOWORD(wParam)) { g_sCamera.vPos = aiVector3D(0.0f,0.0f,-10.0f); g_sCamera.vLookAt = aiVector3D(0.0f,0.0f,1.0f); g_sCamera.vUp = aiVector3D(0.0f,1.0f,0.0f); @@ -1856,63 +1701,35 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, // don't forget to reset the st CBackgroundPainter::Instance().ResetSB(); - } - else if (ID__HELP == LOWORD(wParam)) - { + } else if (ID__HELP == LOWORD(wParam)) { DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_AVHELP), hwndDlg,&HelpDialogProc); - } - else if (ID__ABOUT == LOWORD(wParam)) - { + } else if (ID__ABOUT == LOWORD(wParam)) { DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_ABOUTBOX), hwndDlg,&AboutMessageProc); - } - else if (ID_TOOLS_LOGWINDOW == LOWORD(wParam)) - { - CLogWindow::Instance().Show(); - } - else if (ID__WEBSITE == LOWORD(wParam)) - { - ShellExecute(NULL,"open","http://assimp.sourceforge.net","","",SW_SHOW); - } - else if (ID__WEBSITESF == LOWORD(wParam)) - { - ShellExecute(NULL,"open","https://sourceforge.net/projects/assimp","","",SW_SHOW); - } - else if (ID_REPORTBUG == LOWORD(wParam)) - { - ShellExecute(NULL,"open","https://sourceforge.net/tracker/?func=add&group_id=226462&atid=1067632","","",SW_SHOW); - } - else if (ID_FR == LOWORD(wParam)) - { - ShellExecute(NULL,"open","https://sourceforge.net/forum/forum.php?forum_id=817653","","",SW_SHOW); - } - else if (ID_TOOLS_CLEARLOG == LOWORD(wParam)) - { - CLogWindow::Instance().Clear(); - } - else if (ID_TOOLS_SAVELOGTOFILE == LOWORD(wParam)) - { - CLogWindow::Instance().Save(); - } - else if (ID_VIEWER_MEMORYCONSUMATION == LOWORD(wParam)) - { - DisplayMemoryConsumption(); - } - else if (ID_VIEWER_H == LOWORD(wParam)) - { + } else if (ID_TOOLS_LOGWINDOW == LOWORD(wParam)) { + CLogWindow::Instance().Show(); + } else if (ID__WEBSITE == LOWORD(wParam)) { + ShellExecute(NULL,"open","http://assimp.sourceforge.net","","",SW_SHOW); + } else if (ID__WEBSITESF == LOWORD(wParam)) { + ShellExecute(NULL,"open","https://sourceforge.net/projects/assimp","","",SW_SHOW); + } else if (ID_REPORTBUG == LOWORD(wParam)) { + ShellExecute(NULL,"open","https://sourceforge.net/tracker/?func=add&group_id=226462&atid=1067632","","",SW_SHOW); + } else if (ID_FR == LOWORD(wParam)) { + ShellExecute(NULL,"open","https://sourceforge.net/forum/forum.php?forum_id=817653","","",SW_SHOW); + } else if (ID_TOOLS_CLEARLOG == LOWORD(wParam)) { + CLogWindow::Instance().Clear(); + } else if (ID_TOOLS_SAVELOGTOFILE == LOWORD(wParam)) { + CLogWindow::Instance().Save(); + } else if (ID_VIEWER_MEMORYCONSUMATION == LOWORD(wParam)) { + DisplayMemoryConsumption(); + } else if (ID_VIEWER_H == LOWORD(wParam)) { MakeFileAssociations(); - } - else if (ID_BACKGROUND_CLEAR == LOWORD(wParam)) - { + } else if (ID_BACKGROUND_CLEAR == LOWORD(wParam)) { ClearBG(); - } - else if (ID_BACKGROUND_SETCOLOR == LOWORD(wParam)) - { + } else if (ID_BACKGROUND_SETCOLOR == LOWORD(wParam)) { ChooseBGColor(); - } - else if (ID_BACKGROUND_LOADTEXTURE == LOWORD(wParam)) - { + } else if (ID_BACKGROUND_LOADTEXTURE == LOWORD(wParam)) { LoadBGTexture(); } else if (ID_BACKGROUND_LOADSKYBOX == LOWORD(wParam)) @@ -2071,34 +1888,25 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, { g_sOptions.bStereoView =! g_sOptions.bStereoView; - HMENU hMenu = GetMenu(g_hDlg); - if (g_sOptions.bStereoView) - { - ModifyMenu(hMenu,ID_TOOLS_STEREOVIEW, + HMENU menu = ::GetMenu(g_hDlg); + if (g_sOptions.bStereoView) { + ::ModifyMenu(menu,ID_TOOLS_STEREOVIEW, MF_BYCOMMAND | MF_CHECKED | MF_STRING,ID_TOOLS_STEREOVIEW,"Stereo view"); CLogDisplay::Instance().AddEntry("[INFO] Switched to stereo mode", D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0)); - } - else - { - ModifyMenu(hMenu,ID_TOOLS_STEREOVIEW, + } else { + ModifyMenu(menu,ID_TOOLS_STEREOVIEW, MF_BYCOMMAND | MF_UNCHECKED | MF_STRING,ID_TOOLS_STEREOVIEW,"Stereo view"); CLogDisplay::Instance().AddEntry("[INFO] Switched to mono mode", D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0)); } - } - else if (ID_TOOLS_SETANGLELIMIT == LOWORD(wParam)) - { + } else if (ID_TOOLS_SETANGLELIMIT == LOWORD(wParam)) { DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_DIALOGSMOOTH),g_hDlg,&SMMessageProc); - } - else if (ID_VIEWER_CLEARHISTORY == LOWORD(wParam)) - { + } else if (ID_VIEWER_CLEARHISTORY == LOWORD(wParam)) { ClearHistory(); - } - else if (ID_VIEWER_CLOSEASSET == LOWORD(wParam)) - { + } else if (ID_VIEWER_CLOSEASSET == LOWORD(wParam)) { DeleteAssetData(); DeleteAsset(); } @@ -2420,36 +2228,34 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, SetFocus(g_hDlg); // recover background skyboxes/textures from the last session - HKEY g_hRegistry; - union - { + HKEY hRegistry; + union { char szFileName[MAX_PATH]; D3DCOLOR clrColor; - }; + }; DWORD dwTemp = MAX_PATH; RegCreateKeyEx(HKEY_CURRENT_USER, - "Software\\ASSIMP\\Viewer",0,NULL,0,KEY_ALL_ACCESS, NULL, &g_hRegistry,NULL); - if(ERROR_SUCCESS == RegQueryValueEx(g_hRegistry,"LastSkyBoxSrc",NULL,NULL, + "Software\\ASSIMP\\Viewer",0,NULL,0,KEY_ALL_ACCESS, NULL, &hRegistry,NULL); + if(ERROR_SUCCESS == RegQueryValueEx(hRegistry,"LastSkyBoxSrc",NULL,NULL, (BYTE*)szFileName,&dwTemp) && '\0' != szFileName[0]) { CBackgroundPainter::Instance().SetCubeMapBG(szFileName); } - else if(ERROR_SUCCESS == RegQueryValueEx(g_hRegistry,"LastTextureSrc",NULL,NULL, + else if(ERROR_SUCCESS == RegQueryValueEx(hRegistry,"LastTextureSrc",NULL,NULL, (BYTE*)szFileName,&dwTemp) && '\0' != szFileName[0]) { CBackgroundPainter::Instance().SetTextureBG(szFileName); } - else if(ERROR_SUCCESS == RegQueryValueEx(g_hRegistry,"Color",NULL,NULL, + else if(ERROR_SUCCESS == RegQueryValueEx(hRegistry,"Color",NULL,NULL, (BYTE*)&clrColor,&dwTemp)) { CBackgroundPainter::Instance().SetColor(clrColor); } - RegCloseKey(g_hRegistry); + RegCloseKey(hRegistry); // now handle command line arguments HandleCommandLine(lpCmdLine); - double adLast[30]; for (int i = 0; i < 30;++i)adLast[i] = 0.0f; int iCurrent = 0; @@ -2608,7 +2414,6 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, // render the scene CDisplay::Instance().OnRender(); - // measure FPS, average it out g_dCurTime = timeGetTime(); g_fElpasedTime = (float)((g_dCurTime - g_dLastTime) * 0.001); @@ -2617,26 +2422,26 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, adLast[iCurrent++] = 1.0f / g_fElpasedTime; double dFPS = 0.0; - for (int i = 0;i < 30;++i) - dFPS += adLast[i]; + for (int i = 0; i < 30; ++i) { + dFPS += adLast[ i ]; + } dFPS /= 30.0; - if (30 == iCurrent) - { + if (30 == iCurrent) { iCurrent = 0; - if (dFPS != g_fFPS) - { + if (dFPS != g_fFPS) { g_fFPS = dFPS; char szOut[256]; sprintf(szOut,"%i",(int)floorf((float)dFPS+0.5f)); SetDlgItemText(g_hDlg,IDC_EFPS,szOut); - } } } + } DeleteAsset(); Assimp::DefaultLogger::kill(); ShutdownDevice(); ShutdownD3D(); + return 0; - } \ No newline at end of file +} diff --git a/tools/assimp_view/Normals.cpp b/tools/assimp_view/Normals.cpp index 240825905..4ce706c6a 100644 --- a/tools/assimp_view/Normals.cpp +++ b/tools/assimp_view/Normals.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2015, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -39,11 +39,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------- */ - #include "assimp_view.h" -// note: these are no longer part of the public API, but they are -// exported on Windows to keep AssimpView alive. #include "GenFaceNormalsProcess.h" #include "GenVertexNormalsProcess.h" #include "JoinVerticesProcess.h" @@ -60,15 +57,14 @@ float g_smoothAngle = 80.f; //------------------------------------------------------------------------------- // Flip all normal vectors //------------------------------------------------------------------------------- -void AssetHelper::FlipNormalsInt() -{ +void AssetHelper::FlipNormalsInt() { // invert all normal vectors - for (unsigned int i = 0; i < this->pcScene->mNumMeshes;++i) - { + for (unsigned int i = 0; i < this->pcScene->mNumMeshes;++i) { aiMesh* pcMesh = this->pcScene->mMeshes[i]; - if (!pcMesh->mNormals) + if (!pcMesh->mNormals) { continue; + } for (unsigned int a = 0; a < pcMesh->mNumVertices;++a){ pcMesh->mNormals[a] *= -1.0f; @@ -77,8 +73,7 @@ void AssetHelper::FlipNormalsInt() } //------------------------------------------------------------------------------- -void AssetHelper::FlipNormals() -{ +void AssetHelper::FlipNormals() { FlipNormalsInt(); // recreate native data @@ -90,53 +85,42 @@ void AssetHelper::FlipNormals() //------------------------------------------------------------------------------- // Set the normal set of the scene //------------------------------------------------------------------------------- -void AssetHelper::SetNormalSet(unsigned int iSet) -{ +void AssetHelper::SetNormalSet(unsigned int iSet) { // we need to build an unique set of vertices for this ... { MakeVerboseFormatProcess* pcProcess = new MakeVerboseFormatProcess(); pcProcess->Execute(pcScene); delete pcProcess; - for (unsigned int i = 0; i < pcScene->mNumMeshes;++i) - { - if (!apcMeshes[i]->pvOriginalNormals) - { + for (unsigned int i = 0; i < pcScene->mNumMeshes;++i) { + if (!apcMeshes[i]->pvOriginalNormals) { apcMeshes[i]->pvOriginalNormals = new aiVector3D[pcScene->mMeshes[i]->mNumVertices]; memcpy( apcMeshes[i]->pvOriginalNormals,pcScene->mMeshes[i]->mNormals, pcScene->mMeshes[i]->mNumVertices * sizeof(aiVector3D)); } delete[] pcScene->mMeshes[i]->mNormals; - pcScene->mMeshes[i]->mNormals = NULL; + pcScene->mMeshes[i]->mNormals = nullptr; } } - // now we can start to calculate a new set of normals - if (HARD == iSet) - { + if (HARD == iSet) { GenFaceNormalsProcess* pcProcess = new GenFaceNormalsProcess(); pcProcess->Execute(pcScene); FlipNormalsInt(); delete pcProcess; - } - else if (SMOOTH == iSet) - { + } else if (SMOOTH == iSet) { GenVertexNormalsProcess* pcProcess = new GenVertexNormalsProcess(); pcProcess->SetMaxSmoothAngle((float)AI_DEG_TO_RAD(g_smoothAngle)); pcProcess->Execute(pcScene); FlipNormalsInt(); delete pcProcess; - } - else if (ORIGINAL == iSet) - { - for (unsigned int i = 0; i < pcScene->mNumMeshes;++i) - { - if (apcMeshes[i]->pvOriginalNormals) - { + } else if (ORIGINAL == iSet) { + for (unsigned int i = 0; i < pcScene->mNumMeshes;++i) { + if (apcMeshes[i]->pvOriginalNormals) { delete[] pcScene->mMeshes[i]->mNormals; pcScene->mMeshes[i]->mNormals = apcMeshes[i]->pvOriginalNormals; - apcMeshes[i]->pvOriginalNormals = NULL; + apcMeshes[i]->pvOriginalNormals = nullptr; } } } @@ -153,14 +137,11 @@ void AssetHelper::SetNormalSet(unsigned int iSet) iNormalSet = iSet; - if (g_bWasFlipped) - { + if (g_bWasFlipped) { // invert all normal vectors - for (unsigned int i = 0; i < pcScene->mNumMeshes;++i) - { + for (unsigned int i = 0; i < pcScene->mNumMeshes;++i) { aiMesh* pcMesh = pcScene->mMeshes[i]; - for (unsigned int a = 0; a < pcMesh->mNumVertices;++a) - { + for (unsigned int a = 0; a < pcMesh->mNumVertices;++a) { pcMesh->mNormals[a] *= -1.0f; } } @@ -169,7 +150,6 @@ void AssetHelper::SetNormalSet(unsigned int iSet) // recreate native data DeleteAssetData(true); CreateAssetData(); - return; } -}; \ No newline at end of file +} diff --git a/tools/assimp_view/SceneAnimator.cpp b/tools/assimp_view/SceneAnimator.cpp index 6e507cb41..c2ebeacb3 100644 --- a/tools/assimp_view/SceneAnimator.cpp +++ b/tools/assimp_view/SceneAnimator.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2015, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -47,21 +47,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace AssimpView; +const aiMatrix4x4 IdentityMatrix; + // ------------------------------------------------------------------------------------------------ // Constructor for a given scene. SceneAnimator::SceneAnimator( const aiScene* pScene, size_t pAnimIndex) -{ - mScene = pScene; - mCurrentAnimIndex = -1; - mAnimEvaluator = NULL; - mRootNode = NULL; - +: mScene( pScene ) +, mCurrentAnimIndex( -1 ) +, mAnimEvaluator( nullptr ) +, mRootNode( nullptr ) { // build the nodes-for-bones table - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - { + for (unsigned int i = 0; i < pScene->mNumMeshes;++i) { const aiMesh* mesh = pScene->mMeshes[i]; - for (unsigned int n = 0; n < mesh->mNumBones;++n) - { + for (unsigned int n = 0; n < mesh->mNumBones;++n) { const aiBone* bone = mesh->mBones[n]; mBoneNodesByName[bone->mName.data] = pScene->mRootNode->FindNode(bone->mName); @@ -74,34 +72,34 @@ SceneAnimator::SceneAnimator( const aiScene* pScene, size_t pAnimIndex) // ------------------------------------------------------------------------------------------------ // Destructor -SceneAnimator::~SceneAnimator() -{ +SceneAnimator::~SceneAnimator() { delete mRootNode; delete mAnimEvaluator; } // ------------------------------------------------------------------------------------------------ // Sets the animation to use for playback. -void SceneAnimator::SetAnimIndex( size_t pAnimIndex) -{ +void SceneAnimator::SetAnimIndex( size_t pAnimIndex) { // no change - if( pAnimIndex == mCurrentAnimIndex) + if (pAnimIndex == static_cast( mCurrentAnimIndex ) ) { return; + } // kill data of the previous anim - delete mRootNode; mRootNode = NULL; - delete mAnimEvaluator; mAnimEvaluator = NULL; + delete mRootNode; mRootNode = nullptr; + delete mAnimEvaluator; mAnimEvaluator = nullptr; mNodesByName.clear(); mCurrentAnimIndex = pAnimIndex; // create the internal node tree. Do this even in case of invalid animation index // so that the transformation matrices are properly set up to mimic the current scene - mRootNode = CreateNodeTree( mScene->mRootNode, NULL); + mRootNode = CreateNodeTree( mScene->mRootNode, nullptr); // invalid anim index - if( mCurrentAnimIndex >= mScene->mNumAnimations) + if (static_cast( mCurrentAnimIndex )>= mScene->mNumAnimations) { return; + } // create an evaluator for this animation mAnimEvaluator = new AnimEvaluator( mScene->mAnimations[mCurrentAnimIndex]); @@ -109,11 +107,11 @@ void SceneAnimator::SetAnimIndex( size_t pAnimIndex) // ------------------------------------------------------------------------------------------------ // Calculates the node transformations for the scene. -void SceneAnimator::Calculate( double pTime) -{ +void SceneAnimator::Calculate( double pTime) { // invalid anim - if( !mAnimEvaluator) + if (!mAnimEvaluator) { return; + } // calculate current local transformations mAnimEvaluator->Evaluate( pTime); @@ -124,36 +122,35 @@ void SceneAnimator::Calculate( double pTime) // ------------------------------------------------------------------------------------------------ // Retrieves the most recent local transformation matrix for the given node. -const aiMatrix4x4& SceneAnimator::GetLocalTransform( const aiNode* node) const -{ +const aiMatrix4x4& SceneAnimator::GetLocalTransform( const aiNode* node) const { NodeMap::const_iterator it = mNodesByName.find( node); - if( it == mNodesByName.end()) - return mIdentityMatrix; + if (it == mNodesByName.end()) { + return IdentityMatrix; + } return it->second->mLocalTransform; } // ------------------------------------------------------------------------------------------------ // Retrieves the most recent global transformation matrix for the given node. -const aiMatrix4x4& SceneAnimator::GetGlobalTransform( const aiNode* node) const -{ +const aiMatrix4x4& SceneAnimator::GetGlobalTransform( const aiNode* node) const { NodeMap::const_iterator it = mNodesByName.find( node); - if( it == mNodesByName.end()) - return mIdentityMatrix; + if (it == mNodesByName.end()) { + return IdentityMatrix; + } return it->second->mGlobalTransform; } // ------------------------------------------------------------------------------------------------ // Calculates the bone matrices for the given mesh. -const std::vector& SceneAnimator::GetBoneMatrices( const aiNode* pNode, size_t pMeshIndex /* = 0 */) -{ +const std::vector& SceneAnimator::GetBoneMatrices( const aiNode* pNode, size_t pMeshIndex /* = 0 */) { ai_assert( pMeshIndex < pNode->mNumMeshes); size_t meshIndex = pNode->mMeshes[pMeshIndex]; ai_assert( meshIndex < mScene->mNumMeshes); const aiMesh* mesh = mScene->mMeshes[meshIndex]; - // resize array and initialise it with identity matrices + // resize array and initialize it with identity matrices mTransforms.resize( mesh->mNumBones, aiMatrix4x4()); // calculate the mesh's inverse global transform @@ -162,8 +159,7 @@ const std::vector& SceneAnimator::GetBoneMatrices( const aiNode* pN // Bone matrices transform from mesh coordinates in bind pose to mesh coordinates in skinned pose // Therefore the formula is offsetMatrix * currentGlobalTransform * inverseCurrentMeshTransform - for( size_t a = 0; a < mesh->mNumBones; ++a) - { + for( size_t a = 0; a < mesh->mNumBones; ++a) { const aiBone* bone = mesh->mBones[a]; const aiMatrix4x4& currentGlobalTransform = GetGlobalTransform( mBoneNodesByName[ bone->mName.data ]); mTransforms[a] = globalInverseMeshTransform * currentGlobalTransform * bone->mOffsetMatrix; @@ -175,8 +171,7 @@ const std::vector& SceneAnimator::GetBoneMatrices( const aiNode* pN // ------------------------------------------------------------------------------------------------ // Recursively creates an internal node structure matching the current scene and animation. -SceneAnimNode* SceneAnimator::CreateNodeTree( aiNode* pNode, SceneAnimNode* pParent) -{ +SceneAnimNode* SceneAnimator::CreateNodeTree( aiNode* pNode, SceneAnimNode* pParent) { // create a node SceneAnimNode* internalNode = new SceneAnimNode( pNode->mName.data); internalNode->mParent = pParent; @@ -187,14 +182,11 @@ SceneAnimNode* SceneAnimator::CreateNodeTree( aiNode* pNode, SceneAnimNode* pPar CalculateGlobalTransform( internalNode); // find the index of the animation track affecting this node, if any - if( mCurrentAnimIndex < mScene->mNumAnimations) - { + if(static_cast( mCurrentAnimIndex ) < mScene->mNumAnimations) { internalNode->mChannelIndex = -1; const aiAnimation* currentAnim = mScene->mAnimations[mCurrentAnimIndex]; - for( unsigned int a = 0; a < currentAnim->mNumChannels; a++) - { - if( currentAnim->mChannels[a]->mNodeName.data == internalNode->mName) - { + for( unsigned int a = 0; a < currentAnim->mNumChannels; a++) { + if( currentAnim->mChannels[a]->mNodeName.data == internalNode->mName) { internalNode->mChannelIndex = a; break; } @@ -202,8 +194,7 @@ SceneAnimNode* SceneAnimator::CreateNodeTree( aiNode* pNode, SceneAnimNode* pPar } // continue for all child nodes and assign the created internal nodes as our children - for( unsigned int a = 0; a < pNode->mNumChildren; a++) - { + for( unsigned int a = 0; a < pNode->mNumChildren; ++a ) { SceneAnimNode* childNode = CreateNodeTree( pNode->mChildren[a], internalNode); internalNode->mChildren.push_back( childNode); } @@ -213,12 +204,10 @@ SceneAnimNode* SceneAnimator::CreateNodeTree( aiNode* pNode, SceneAnimNode* pPar // ------------------------------------------------------------------------------------------------ // Recursively updates the internal node transformations from the given matrix array -void SceneAnimator::UpdateTransforms( SceneAnimNode* pNode, const std::vector& pTransforms) -{ +void SceneAnimator::UpdateTransforms( SceneAnimNode* pNode, const std::vector& pTransforms) { // update node local transform - if( pNode->mChannelIndex != -1) - { - ai_assert( pNode->mChannelIndex < pTransforms.size()); + if( pNode->mChannelIndex != -1) { + ai_assert(static_cast( pNode->mChannelIndex ) < pTransforms.size()); pNode->mLocalTransform = pTransforms[pNode->mChannelIndex]; } @@ -226,19 +215,18 @@ void SceneAnimator::UpdateTransforms( SceneAnimNode* pNode, const std::vector::iterator it = pNode->mChildren.begin(); it != pNode->mChildren.end(); ++it) - UpdateTransforms( *it, pTransforms); + for (std::vector::iterator it = pNode->mChildren.begin(); it != pNode->mChildren.end(); ++it) { + UpdateTransforms(*it, pTransforms); + } } // ------------------------------------------------------------------------------------------------ // Calculates the global transformation matrix for the given internal node -void SceneAnimator::CalculateGlobalTransform( SceneAnimNode* pInternalNode) -{ +void SceneAnimator::CalculateGlobalTransform( SceneAnimNode* pInternalNode) { // concatenate all parent transforms to get the global transform for this node pInternalNode->mGlobalTransform = pInternalNode->mLocalTransform; SceneAnimNode* node = pInternalNode->mParent; - while( node) - { + while( node) { pInternalNode->mGlobalTransform = node->mLocalTransform * pInternalNode->mGlobalTransform; node = node->mParent; } diff --git a/tools/assimp_view/SceneAnimator.h b/tools/assimp_view/SceneAnimator.h index afcbac925..00d9832b6 100644 --- a/tools/assimp_view/SceneAnimator.h +++ b/tools/assimp_view/SceneAnimator.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2012, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -49,15 +49,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -namespace AssimpView { +namespace AssimpView { // --------------------------------------------------------------------------------- /** A little tree structure to match the scene's node structure, but holding * additional data. Needs to be public to allow using it in templates at * certain compilers. */ -struct SceneAnimNode -{ +struct SceneAnimNode { std::string mName; SceneAnimNode* mParent; std::vector mChildren; @@ -69,12 +68,15 @@ struct SceneAnimNode aiMatrix4x4 mGlobalTransform; //! index in the current animation's channel array. -1 if not animated. - size_t mChannelIndex; + int mChannelIndex; //! Default construction SceneAnimNode() : mName() - , mParent(NULL) + , mParent(nullptr) + , mChildren() + , mLocalTransform() + , mGlobalTransform() , mChannelIndex(-1) { // empty } @@ -82,8 +84,11 @@ struct SceneAnimNode //! Construction from a given name SceneAnimNode( const std::string& pName) : mName( pName) - , mParent(NULL) - , mChannelIndex( -1 ) { + , mParent(nullptr) + , mChildren() + , mLocalTransform() + , mGlobalTransform() + , mChannelIndex(-1) { // empty } @@ -105,8 +110,7 @@ struct SceneAnimNode * GetGlobalTransform(). A full set of bone matrices can be retrieved by * GetBoneMatrices() for a given mesh. */ -class SceneAnimator -{ +class SceneAnimator { public: // ---------------------------------------------------------------------------- @@ -186,7 +190,6 @@ public: const std::vector& GetBoneMatrices( const aiNode* pNode, size_t pMeshIndex = 0); - // ---------------------------------------------------------------------------- /** @brief Get the current animation index */ @@ -198,7 +201,7 @@ public: /** @brief Get the current animation or NULL */ aiAnimation* CurrentAnim() const { - return mCurrentAnimIndex < mScene->mNumAnimations ? mScene->mAnimations[ mCurrentAnimIndex ] : NULL; + return static_cast( mCurrentAnimIndex ) < mScene->mNumAnimations ? mScene->mAnimations[ mCurrentAnimIndex ] : NULL; } protected: @@ -221,7 +224,7 @@ protected: const aiScene* mScene; /** Current animation index */ - size_t mCurrentAnimIndex; + int mCurrentAnimIndex; /** The AnimEvaluator we use to calculate the current pose for the current animation */ AnimEvaluator* mAnimEvaluator; @@ -239,9 +242,6 @@ protected: /** Array to return transformations results inside. */ std::vector mTransforms; - - /** Identity matrix to return a reference to in case of error */ - aiMatrix4x4 mIdentityMatrix; }; } // end of namespace AssimpView diff --git a/tools/assimp_view/Shaders.cpp b/tools/assimp_view/Shaders.cpp index 1b6f3dc88..49ec5320d 100644 --- a/tools/assimp_view/Shaders.cpp +++ b/tools/assimp_view/Shaders.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2015, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. From 1ac86476fe0df95bc7f3ba8575aae0752b88321e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9verin=20Lemaignan?= Date: Wed, 30 Jan 2019 22:41:01 +0000 Subject: [PATCH 129/472] [pyassimp] Bumped to 4.1.4 Main changes: - Support for metadata fields (Vincent Fazio, Wojciech Matyjewicz) - added support for aiExportSceneToBlob (Vincent Fazio) - a few bug fix + code beautification --- port/PyAssimp/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/port/PyAssimp/setup.py b/port/PyAssimp/setup.py index e19e497f0..a3497d657 100644 --- a/port/PyAssimp/setup.py +++ b/port/PyAssimp/setup.py @@ -8,7 +8,7 @@ def readme(): return f.read() setup(name='pyassimp', - version='4.1.3', + version='4.1.4', license='ISC', description='Python bindings for the Open Asset Import Library (ASSIMP)', long_description=readme(), From 4347ce4311cee8e88ba2a73385f38a92dc75ec25 Mon Sep 17 00:00:00 2001 From: kimkulling Date: Thu, 31 Jan 2019 17:24:08 +0100 Subject: [PATCH 130/472] Some more findings. --- tools/assimp_cmd/Main.h | 11 +++---- tools/assimp_view/MessageProc.cpp | 53 ++++++++++--------------------- 2 files changed, 21 insertions(+), 43 deletions(-) diff --git a/tools/assimp_cmd/Main.h b/tools/assimp_cmd/Main.h index 56b06d57e..5dc4f7d28 100644 --- a/tools/assimp_cmd/Main.h +++ b/tools/assimp_cmd/Main.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2015, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -89,9 +89,8 @@ extern Assimp::Exporter* globalExporter; #endif // ------------------------------------------------------------------------------ -/** Defines common import parameters */ -struct ImportData -{ +/// Defines common import parameters +struct ImportData { ImportData() : ppFlags (0) , showLog (false) @@ -99,11 +98,9 @@ struct ImportData , log (false) {} - /** Postprocessing flags - */ + /// Post-processing flags unsigned int ppFlags; - // Log to std::err? bool showLog; diff --git a/tools/assimp_view/MessageProc.cpp b/tools/assimp_view/MessageProc.cpp index f9bcf2e9d..823edc643 100644 --- a/tools/assimp_view/MessageProc.cpp +++ b/tools/assimp_view/MessageProc.cpp @@ -1597,21 +1597,17 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, WPARAM wParam,LPARAM lParam case WM_DROPFILES: { HDROP hDrop = (HDROP)wParam; - char szFile[MAX_PATH]; DragQueryFile(hDrop,0,szFile,sizeof(szFile)); - const char* sz = strrchr(szFile,'.'); - if (!sz) + if (!sz) { sz = szFile; + } - if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode()) - { + if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode()) { // replace the selected texture with the new one ... CDisplay::Instance().ReplaceCurrentTexture(szFile); - } - else - { + } else { // check whether it is a typical texture file format ... ++sz; if (0 == ASSIMP_stricmp(sz,"png") || @@ -1653,19 +1649,17 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, WPARAM wParam,LPARAM lParam fseek(pFile,112,SEEK_SET); fread(&dwCaps,4,1,pFile); - if (dwCaps & 0x00000400L /* DDSCAPS2_CUBEMAP_POSITIVEX */) - { + if (dwCaps & 0x00000400L /* DDSCAPS2_CUBEMAP_POSITIVEX */) { CLogDisplay::Instance().AddEntry( "[INFO] Assuming this dds file is a skybox ...", D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0)); CBackgroundPainter::Instance().SetCubeMapBG(szFile); + } else { + CBackgroundPainter::Instance().SetTextureBG(szFile); } - else CBackgroundPainter::Instance().SetTextureBG(szFile); fclose(pFile); - } - else - { + } else { strcpy(g_szFileName,szFile); DeleteAsset(); @@ -1731,44 +1725,31 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, WPARAM wParam,LPARAM lParam ChooseBGColor(); } else if (ID_BACKGROUND_LOADTEXTURE == LOWORD(wParam)) { LoadBGTexture(); - } - else if (ID_BACKGROUND_LOADSKYBOX == LOWORD(wParam)) - { + } else if (ID_BACKGROUND_LOADSKYBOX == LOWORD(wParam)) { LoadSkybox(); - } - else if (ID_VIEWER_SAVESCREENSHOTTOFILE == LOWORD(wParam)) - { + } else if (ID_VIEWER_SAVESCREENSHOTTOFILE == LOWORD(wParam)) { SaveScreenshot(); - } - else if (ID_VIEWER_OPEN == LOWORD(wParam)) - { + } else if (ID_VIEWER_OPEN == LOWORD(wParam)) { OpenAsset(); - } - else if (ID_TOOLS_FLIPNORMALS == LOWORD(wParam)) - { - if (g_pcAsset && g_pcAsset->pcScene) - { + } else if (ID_TOOLS_FLIPNORMALS == LOWORD(wParam)) { + if (g_pcAsset && g_pcAsset->pcScene) { g_pcAsset->FlipNormals(); - } } - + } // this is ugly. anyone willing to rewrite it from scratch using wxwidgets or similar? else if (ID_VIEWER_PP_JIV == LOWORD(wParam)) { ppsteps ^= aiProcess_JoinIdenticalVertices; CheckMenuItem(hMenu,ID_VIEWER_PP_JIV,ppsteps & aiProcess_JoinIdenticalVertices ? MF_CHECKED : MF_UNCHECKED); UpdatePPSettings(); - } - else if (ID_VIEWER_PP_CTS == LOWORD(wParam)) { + } else if (ID_VIEWER_PP_CTS == LOWORD(wParam)) { ppsteps ^= aiProcess_CalcTangentSpace; CheckMenuItem(hMenu,ID_VIEWER_PP_CTS,ppsteps & aiProcess_CalcTangentSpace ? MF_CHECKED : MF_UNCHECKED); UpdatePPSettings(); - } - else if (ID_VIEWER_PP_FD == LOWORD(wParam)) { + } else if (ID_VIEWER_PP_FD == LOWORD(wParam)) { ppsteps ^= aiProcess_FindDegenerates; CheckMenuItem(hMenu,ID_VIEWER_PP_FD,ppsteps & aiProcess_FindDegenerates ? MF_CHECKED : MF_UNCHECKED); UpdatePPSettings(); - } - else if (ID_VIEWER_PP_FID == LOWORD(wParam)) { + } else if (ID_VIEWER_PP_FID == LOWORD(wParam)) { ppsteps ^= aiProcess_FindInvalidData; CheckMenuItem(hMenu,ID_VIEWER_PP_FID,ppsteps & aiProcess_FindInvalidData ? MF_CHECKED : MF_UNCHECKED); UpdatePPSettings(); From 996fb4aae713d374840c3c6b15c006fb8c7f1110 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 3 Feb 2019 11:32:56 +0100 Subject: [PATCH 131/472] closes https://github.com/assimp/assimp/issues/2297: introduce obj-unittest to validate working importer. --- test/unit/utObjImportExport.cpp | 35 ++++++++++++++++++------------- tools/assimp_view/MessageProc.cpp | 5 +++-- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/test/unit/utObjImportExport.cpp b/test/unit/utObjImportExport.cpp index f0b20fb7f..23bbd7fc7 100644 --- a/test/unit/utObjImportExport.cpp +++ b/test/unit/utObjImportExport.cpp @@ -78,7 +78,7 @@ static const float VertComponents[ 24 * 3 ] = { 0.500000, -0.500000, 0.500000f }; -static const std::string ObjModel = +static const char *ObjModel = "o 1\n" "\n" "# Vertex list\n" @@ -105,7 +105,7 @@ static const std::string ObjModel = "\n" "# End of file\n"; -static const std::string ObjModel_Issue1111 = +static const char *ObjModel_Issue1111 = "o 1\n" "\n" "# Vertex list\n" @@ -231,7 +231,7 @@ TEST_F( utObjImportExport, exportObjFromFileTest ) { #endif // ASSIMP_BUILD_NO_EXPORT TEST_F( utObjImportExport, obj_import_test ) { - const aiScene *scene = m_im->ReadFileFromMemory( (void*) ObjModel.c_str(), ObjModel.size(), 0 ); + const aiScene *scene = m_im->ReadFileFromMemory( (void*) ObjModel, strlen(ObjModel), 0 ); aiScene *expected = createScene(); EXPECT_NE( nullptr, scene ); @@ -252,7 +252,7 @@ TEST_F( utObjImportExport, obj_import_test ) { } TEST_F( utObjImportExport, issue1111_no_mat_name_Test ) { - const aiScene *scene = m_im->ReadFileFromMemory( ( void* ) ObjModel_Issue1111.c_str(), ObjModel_Issue1111.size(), 0 ); + const aiScene *scene = m_im->ReadFileFromMemory( ( void* ) ObjModel_Issue1111, strlen(ObjModel_Issue1111), 0 ); EXPECT_NE( nullptr, scene ); } @@ -290,7 +290,7 @@ TEST_F( utObjImportExport, issue1923_vertex_color_Test ) { } TEST_F( utObjImportExport, issue1453_segfault ) { - static const std::string ObjModel = + static const char *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" @@ -301,12 +301,12 @@ TEST_F( utObjImportExport, issue1453_segfault ) { "v 1.0 1.0 1.0\nB"; Assimp::Importer myimporter; - const aiScene *scene = myimporter.ReadFileFromMemory( ObjModel.c_str(), ObjModel.size(), aiProcess_ValidateDataStructure ); + const aiScene *scene = myimporter.ReadFileFromMemory( ObjModel, strlen(ObjModel), aiProcess_ValidateDataStructure ); EXPECT_EQ( nullptr, scene ); } TEST_F(utObjImportExport, relative_indices_Test) { - static const std::string ObjModel = + static const char *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" @@ -314,7 +314,7 @@ TEST_F(utObjImportExport, relative_indices_Test) { "f -4 -3 -2 -1\nB"; Assimp::Importer myimporter; - const aiScene *scene = myimporter.ReadFileFromMemory(ObjModel.c_str(), ObjModel.size(), aiProcess_ValidateDataStructure); + const aiScene *scene = myimporter.ReadFileFromMemory(ObjModel, strlen(ObjModel), aiProcess_ValidateDataStructure); EXPECT_NE(nullptr, scene); EXPECT_EQ(scene->mNumMeshes, 1U); @@ -331,14 +331,14 @@ TEST_F(utObjImportExport, relative_indices_Test) { } TEST_F(utObjImportExport, homogeneous_coordinates_Test) { - static const std::string ObjModel = + static const char *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); + const aiScene *scene = myimporter.ReadFileFromMemory(ObjModel, strlen(ObjModel), aiProcess_ValidateDataStructure); EXPECT_NE(nullptr, scene); EXPECT_EQ(scene->mNumMeshes, 1U); @@ -354,26 +354,26 @@ TEST_F(utObjImportExport, homogeneous_coordinates_Test) { } TEST_F(utObjImportExport, homogeneous_coordinates_divide_by_zero_Test) { - static const std::string ObjModel = + static const char *ObjModel = "v -0.500000 0.000000 0.400000 0.\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); + const aiScene *scene = myimporter.ReadFileFromMemory(ObjModel, strlen(ObjModel), aiProcess_ValidateDataStructure); EXPECT_EQ(nullptr, scene); } TEST_F(utObjImportExport, 0based_array_Test) { - static const std::string ObjModel = + static const char *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); + Assimp::Importer myImporter; + const aiScene *scene = myImporter.ReadFileFromMemory(ObjModel, strlen(ObjModel), 0); EXPECT_EQ(nullptr, scene); } @@ -396,3 +396,8 @@ TEST_F(utObjImportExport, import_point_cloud) { ASSERT_NE(nullptr, scene); } +TEST_F(utObjImportExport, import_without_linend) { + Assimp::Importer myImporter; + const aiScene *scene = myImporter.ReadFile(ASSIMP_TEST_MODELS_DIR "/OBJ/box_without_lineending.obj", 0); + ASSERT_NE(nullptr, scene); +} diff --git a/tools/assimp_view/MessageProc.cpp b/tools/assimp_view/MessageProc.cpp index 5a9cfd0ed..2720ef066 100644 --- a/tools/assimp_view/MessageProc.cpp +++ b/tools/assimp_view/MessageProc.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2015, assimp team +Copyright (c) 2006-2019, assimp team All rights reserved. @@ -2639,4 +2639,5 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, ShutdownDevice(); ShutdownD3D(); return 0; - } \ No newline at end of file +} + From 971ba308b38b9c42617331dd37383ac948eb7506 Mon Sep 17 00:00:00 2001 From: Mike Samsonov Date: Wed, 23 Jan 2019 17:07:44 +0000 Subject: [PATCH 132/472] Merged PR 2811682: buffer grow changes and large files support Buffer grow changes: The exporting of relatevely large data could take a few days, because reallocation of a buffer every time for a few new bytes is overkill. I've introduced standard capacity member for the buffer and growth it by 1.5 times every time. That helps a lot, descrease exporting to a minute (from a few days). Large file support: glTF is a json file, all lengths and offsets don't have a type, just numbers, but code was always reading it as uint32, this doesn't work for files bigger than int32 (almost all files we have as an example). So, I've changed it to be reading as size_t. Specification doesn't specify the type for it, so it's not against spec. --- code/glTF2Asset.h | 5 +++-- code/glTF2Asset.inl | 28 +++++++++++++++++++++++----- code/glTF2Exporter.cpp | 6 +++--- code/glTF2Importer.cpp | 24 ++++++++++++------------ code/glTFAsset.h | 2 +- code/glTFAsset.inl | 28 +++++++++++++++++++++++----- 6 files changed, 65 insertions(+), 28 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 897db7474..0015197c2 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -430,9 +430,9 @@ namespace glTF2 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) + size_t 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) + size_t 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. @@ -529,6 +529,7 @@ namespace glTF2 //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") + size_t capacity = 0; //!< The capacity of the buffer in bytes. (default: 0) Type type; diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 97ad6df57..b51975c77 100755 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -85,6 +85,14 @@ namespace { return val.IsString() ? (out = std::string(val.GetString(), val.GetStringLength()), true) : false; }}; + template<> struct ReadHelper { static bool Read(Value& val, uint64_t& out) { + return val.IsUint64() ? out = val.GetUint64(), true : false; + }}; + + template<> struct ReadHelper { static bool Read(Value& val, int64_t& out) { + return val.IsInt64() ? out = val.GetInt64(), true : false; + }}; + template struct ReadHelper< Nullable > { static bool Read(Value& val, Nullable& out) { return out.isPresent = ReadHelper::Read(val, out.value); }}; @@ -520,7 +528,17 @@ inline size_t Buffer::AppendData(uint8_t* data, size_t length) inline void Buffer::Grow(size_t amount) { if (amount <= 0) return; - uint8_t* b = new uint8_t[byteLength + amount]; + if (capacity >= byteLength + amount) + { + byteLength += amount; + return; + } + + // Shift operation is standard way to divide integer by 2, it doesn't cast it to float back and forth, also works for odd numbers, + // originally it would look like: static_cast(capacity * 1.5f) + capacity = std::max(capacity + (capacity >> 1), byteLength + amount); + + uint8_t* b = new uint8_t[capacity]; if (mData) memcpy(b, mData.get(), byteLength); mData.reset(b, std::default_delete()); byteLength += amount; @@ -537,8 +555,8 @@ inline void BufferView::Read(Value& obj, Asset& r) buffer = r.buffers.Retrieve(bufferVal->GetUint()); } - byteOffset = MemberOrDefault(obj, "byteOffset", 0u); - byteLength = MemberOrDefault(obj, "byteLength", 0u); + byteOffset = MemberOrDefault(obj, "byteOffset", size_t(0)); + byteLength = MemberOrDefault(obj, "byteLength", size_t(0)); byteStride = MemberOrDefault(obj, "byteStride", 0u); } @@ -553,9 +571,9 @@ inline void Accessor::Read(Value& obj, Asset& r) bufferView = r.bufferViews.Retrieve(bufferViewVal->GetUint()); } - byteOffset = MemberOrDefault(obj, "byteOffset", 0u); + byteOffset = MemberOrDefault(obj, "byteOffset", size_t(0)); componentType = MemberOrDefault(obj, "componentType", ComponentType_BYTE); - count = MemberOrDefault(obj, "count", 0u); + count = MemberOrDefault(obj, "count", size_t(0)); const char* typestr; type = ReadMember(obj, "type", typestr) ? AttribType::FromString(typestr) : AttribType::SCALAR; diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index 01e606ed3..655b4fc7d 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -156,7 +156,7 @@ static void IdentityMatrix4(mat4& o) { } 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) + size_t count, void* data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, bool isIndices = false) { if (!count || !data) { return Ref(); @@ -176,7 +176,7 @@ inline Ref ExportData(Asset& a, std::string& meshName, Ref& bu // bufferView Ref bv = a.bufferViews.Create(a.FindUniqueID(meshName, "view")); bv->buffer = buffer; - bv->byteOffset = unsigned(offset); + bv->byteOffset = 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; @@ -768,7 +768,7 @@ void glTF2Exporter::ExportMeshes() } } - p.indices = ExportData(*mAsset, meshId, b, unsigned(indices.size()), &indices[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_UNSIGNED_INT, true); + p.indices = ExportData(*mAsset, meshId, b, indices.size(), &indices[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_UNSIGNED_INT, true); } switch (aim->mPrimitiveTypes) { diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index be3a9a96f..0eafe227f 100755 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -412,7 +412,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r) Mesh::Primitive::Attributes& attr = prim.attributes; if (attr.position.size() > 0 && attr.position[0]) { - aim->mNumVertices = attr.position[0]->count; + aim->mNumVertices = static_cast(attr.position[0]->count); attr.position[0]->ExtractData(aim->mVertices); } @@ -511,10 +511,10 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r) aiFace* faces = 0; - unsigned int nFaces = 0; + size_t nFaces = 0; if (prim.indices) { - unsigned int count = prim.indices->count; + size_t count = prim.indices->count; Accessor::Indexer data = prim.indices->GetIndexer(); ai_assert(data.IsValid()); @@ -665,7 +665,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r) if (faces) { aim->mFaces = faces; - aim->mNumFaces = nFaces; + aim->mNumFaces = static_cast(nFaces); ai_assert(CheckValidFacesIndices(faces, nFaces, aim->mNumVertices)); } @@ -751,7 +751,7 @@ static void BuildVertexWeightMapping(Mesh::Primitive& primitive, std::vectorcount; + size_t num_vertices = attr.weight[0]->count; struct Weights { float values[4]; }; Weights* weights = nullptr; @@ -822,7 +822,7 @@ aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector& if (node.skin) { for (int primitiveNo = 0; primitiveNo < count; ++primitiveNo) { aiMesh* mesh = pScene->mMeshes[meshOffsets[mesh_idx]+primitiveNo]; - mesh->mNumBones = node.skin->jointNames.size(); + mesh->mNumBones = static_cast(node.skin->jointNames.size()); mesh->mBones = new aiBone*[mesh->mNumBones]; // GLTF and Assimp choose to store bone weights differently. @@ -837,7 +837,7 @@ aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector& std::vector> weighting(mesh->mNumBones); BuildVertexWeightMapping(node.meshes[0]->primitives[primitiveNo], weighting); - for (size_t i = 0; i < mesh->mNumBones; ++i) { + for (uint32_t i = 0; i < mesh->mNumBones; ++i) { aiBone* bone = new aiBone(); Ref joint = node.skin->jointNames[i]; @@ -854,7 +854,7 @@ aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector& std::vector& weights = weighting[i]; - bone->mNumWeights = weights.size(); + bone->mNumWeights = static_cast(weights.size()); if (bone->mNumWeights > 0) { bone->mWeights = new aiVertexWeight[bone->mNumWeights]; memcpy(bone->mWeights, weights.data(), bone->mNumWeights * sizeof(aiVertexWeight)); @@ -930,7 +930,7 @@ aiNodeAnim* CreateNodeAnim(glTF2::Asset& r, Node& node, AnimationSamplers& sampl samplers.translation->input->ExtractData(times); aiVector3D* values = nullptr; samplers.translation->output->ExtractData(values); - anim->mNumPositionKeys = samplers.translation->input->count; + anim->mNumPositionKeys = static_cast(samplers.translation->input->count); anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys]; for (unsigned int i = 0; i < anim->mNumPositionKeys; ++i) { anim->mPositionKeys[i].mTime = times[i] * kMillisecondsFromSeconds; @@ -952,7 +952,7 @@ aiNodeAnim* CreateNodeAnim(glTF2::Asset& r, Node& node, AnimationSamplers& sampl samplers.rotation->input->ExtractData(times); aiQuaternion* values = nullptr; samplers.rotation->output->ExtractData(values); - anim->mNumRotationKeys = samplers.rotation->input->count; + anim->mNumRotationKeys = static_cast(samplers.rotation->input->count); anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys]; for (unsigned int i = 0; i < anim->mNumRotationKeys; ++i) { anim->mRotationKeys[i].mTime = times[i] * kMillisecondsFromSeconds; @@ -978,7 +978,7 @@ aiNodeAnim* CreateNodeAnim(glTF2::Asset& r, Node& node, AnimationSamplers& sampl samplers.scale->input->ExtractData(times); aiVector3D* values = nullptr; samplers.scale->output->ExtractData(values); - anim->mNumScalingKeys = samplers.scale->input->count; + anim->mNumScalingKeys = static_cast(samplers.scale->input->count); anim->mScalingKeys = new aiVectorKey[anim->mNumScalingKeys]; for (unsigned int i = 0; i < anim->mNumScalingKeys; ++i) { anim->mScalingKeys[i].mTime = times[i] * kMillisecondsFromSeconds; @@ -1042,7 +1042,7 @@ void glTF2Importer::ImportAnimations(glTF2::Asset& r) std::unordered_map samplers = GatherSamplers(anim); - ai_anim->mNumChannels = samplers.size(); + ai_anim->mNumChannels = static_cast(samplers.size()); if (ai_anim->mNumChannels > 0) { ai_anim->mChannels = new aiNodeAnim*[ai_anim->mNumChannels]; int j = 0; diff --git a/code/glTFAsset.h b/code/glTFAsset.h index 463c69be4..92b7dd9d1 100644 --- a/code/glTFAsset.h +++ b/code/glTFAsset.h @@ -537,7 +537,7 @@ namespace glTF shared_ptr mData; //!< Pointer to the data bool mIsSpecial; //!< Set to true for special cases (e.g. the body buffer) - + size_t capacity = 0; //!< The capacity of the buffer in bytes. (default: 0) /// \var EncodedRegion_List /// List of encoded regions. std::list EncodedRegion_List; diff --git a/code/glTFAsset.inl b/code/glTFAsset.inl index f545b809c..7b7acd705 100644 --- a/code/glTFAsset.inl +++ b/code/glTFAsset.inl @@ -95,6 +95,14 @@ namespace { return out.isPresent = ReadHelper::Read(val, out.value); }}; + template<> struct ReadHelper { static bool Read(Value& val, uint64_t& out) { + return val.IsUint64() ? out = val.GetUint64(), true : false; + }}; + + template<> struct ReadHelper { static bool Read(Value& val, int64_t& out) { + return val.IsInt64() ? out = val.GetInt64(), true : false; + }}; + template inline static bool ReadValue(Value& val, T& out) { @@ -311,7 +319,7 @@ inline void Buffer::Read(Value& obj, Asset& r) " bytes, but found " + to_string(dataURI.dataLength)); } - this->mData.reset(new uint8_t[dataURI.dataLength]); + this->mData.reset(new uint8_t[dataURI.dataLength], std::default_delete()); memcpy( this->mData.get(), dataURI.data, dataURI.dataLength ); } } @@ -417,7 +425,7 @@ uint8_t* new_data; // 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); + mData.reset(new_data, std::default_delete()); byteLength = new_data_size; return true; @@ -434,9 +442,19 @@ inline size_t Buffer::AppendData(uint8_t* data, size_t length) inline void Buffer::Grow(size_t amount) { if (amount <= 0) return; - uint8_t* b = new uint8_t[byteLength + amount]; + if (capacity >= byteLength + amount) + { + byteLength += amount; + return; + } + + // Shift operation is standard way to divide integer by 2, it doesn't cast it to float back and forth, also works for odd numbers, + // originally it would look like: static_cast(capacity * 1.5f) + capacity = std::max(capacity + (capacity >> 1), byteLength + amount); + + uint8_t* b = new uint8_t[capacity]; if (mData) memcpy(b, mData.get(), byteLength); - mData.reset(b); + mData.reset(b, std::default_delete()); byteLength += amount; } @@ -1445,7 +1463,7 @@ inline std::string Asset::FindUniqueID(const std::string& str, const char* suffi if (it == mUsedIds.end()) return id; - char buffer[256]; + char buffer[1024]; int offset = ai_snprintf(buffer, sizeof(buffer), "%s_", id.c_str()); for (int i = 0; it != mUsedIds.end(); ++i) { ai_snprintf(buffer + offset, sizeof(buffer) - offset, "%d", i); From 5ce1cfedfea01d432fe7469025312769d6e166aa Mon Sep 17 00:00:00 2001 From: Mike Samsonov Date: Mon, 4 Feb 2019 16:15:52 +0000 Subject: [PATCH 133/472] warning fix for gcc --- code/glTF2Importer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 0eafe227f..4228db23f 100755 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -666,7 +666,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r) if (faces) { aim->mFaces = faces; aim->mNumFaces = static_cast(nFaces); - ai_assert(CheckValidFacesIndices(faces, nFaces, aim->mNumVertices)); + ai_assert(CheckValidFacesIndices(faces, static_cast(nFaces), aim->mNumVertices)); } if (prim.material) { @@ -773,13 +773,13 @@ static void BuildVertexWeightMapping(Mesh::Primitive& primitive, std::vector 0 && bone < map.size()) { map[bone].reserve(8); - map[bone].emplace_back(i, weight); + map[bone].emplace_back(static_cast(i), weight); } } } From f5ef0788345d55e2b9c1e4ea7d09ac1f901e3026 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 4 Feb 2019 22:15:15 +0100 Subject: [PATCH 134/472] fix openfiledialog in modelviewer. --- tools/assimp_view/Display.cpp | 7 ++--- tools/assimp_view/Input.cpp | 2 +- tools/assimp_view/MessageProc.cpp | 50 +++++++++++++++++++++++++++---- tools/assimp_view/assimp_view.cpp | 25 +++++++--------- 4 files changed, 58 insertions(+), 26 deletions(-) diff --git a/tools/assimp_view/Display.cpp b/tools/assimp_view/Display.cpp index 196e8a2ac..ab29c1d3e 100644 --- a/tools/assimp_view/Display.cpp +++ b/tools/assimp_view/Display.cpp @@ -102,17 +102,16 @@ void GetNodeCount(aiNode* pcNode, unsigned int* piCnt) } //------------------------------------------------------------------------------- -int CDisplay::EnableAnimTools(BOOL hm) -{ +int CDisplay::EnableAnimTools(BOOL hm) { EnableWindow(GetDlgItem(g_hDlg,IDC_PLAY),hm); EnableWindow(GetDlgItem(g_hDlg,IDC_SLIDERANIM),hm); + return 1; } //------------------------------------------------------------------------------- // Fill animation combo box -int CDisplay::FillAnimList(void) -{ +int CDisplay::FillAnimList(void) { if (0 != g_pcAsset->pcScene->mNumAnimations) { // now fill in all animation names diff --git a/tools/assimp_view/Input.cpp b/tools/assimp_view/Input.cpp index 56007bdf1..88e04b437 100644 --- a/tools/assimp_view/Input.cpp +++ b/tools/assimp_view/Input.cpp @@ -194,7 +194,7 @@ void HandleMouseInputSkyBox( void ) //------------------------------------------------------------------------------- //------------------------------------------------------------------------------- -void HandleMouseInputLightIntensityAndColor( void ) +void HandleMouseInputLightIntensityAndColor() { POINT mousePos; GetCursorPos( &mousePos ); diff --git a/tools/assimp_view/MessageProc.cpp b/tools/assimp_view/MessageProc.cpp index 823edc643..8afecd602 100644 --- a/tools/assimp_view/MessageProc.cpp +++ b/tools/assimp_view/MessageProc.cpp @@ -333,8 +333,7 @@ void ToggleWireFrame() { //------------------------------------------------------------------------------- // Toggle the "MultiSample" state //------------------------------------------------------------------------------- -void ToggleMS() -{ +void ToggleMS() { g_sOptions.bMultiSample = !g_sOptions.bMultiSample; DeleteAssetData(); ShutdownDevice(); @@ -389,7 +388,7 @@ void ToggleUIState() { } //------------------------------------------------------------------------------- -// Load the background texture for the cviewer +// Load the background texture for the viewer //------------------------------------------------------------------------------- void LoadBGTexture() { char szFileName[MAX_PATH]; @@ -853,14 +852,53 @@ void OpenAsset() { strcpy(szCur,"*.*"); szCur[4] = 0; - OPENFILENAME sFilename1 = { + /*DWORD lStructSize; + HWND hwndOwner; + HINSTANCE hInstance; + LPCWSTR lpstrFilter; + LPWSTR lpstrCustomFilter; + DWORD nMaxCustFilter; + DWORD nFilterIndex; + LPWSTR lpstrFile; + DWORD nMaxFile; + LPWSTR lpstrFileTitle; + DWORD nMaxFileTitle; + LPCWSTR lpstrInitialDir; + LPCWSTR lpstrTitle; + DWORD Flags; + WORD nFileOffset; + WORD nFileExtension; + LPCWSTR lpstrDefExt; + LPARAM lCustData; + LPOFNHOOKPROC lpfnHook; + LPCWSTR lpTemplateName; +#ifdef _MAC + LPEDITMENU lpEditInfo; + LPCSTR lpstrPrompt;*/ + + + OPENFILENAME sFilename1; + ZeroMemory(&sFilename1, sizeof(sFilename1)); + sFilename1.lStructSize = sizeof(sFilename1); + sFilename1.hwndOwner = g_hDlg; + sFilename1.hInstance = GetModuleHandle(NULL); + sFilename1.lpstrFile = szFileName; + sFilename1.lpstrFile[0] = '\0'; + sFilename1.nMaxFile = sizeof(szList); + sFilename1.lpstrFilter = szList; + sFilename1.nFilterIndex = 1; + sFilename1.lpstrFileTitle = NULL; + sFilename1.nMaxFileTitle = 0; + sFilename1.lpstrInitialDir = NULL; + sFilename1.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR; + /*OPENFILENAME sFilename1 = { sizeof(OPENFILENAME), - g_hDlg,GetModuleHandle(NULL), szList, NULL, 0, 1, + g_hDlg, GetModuleHandle(NULL), szList, NULL, 0, 1, szFileName, MAX_PATH, NULL, 0, NULL, "Import Asset into ASSIMP", OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, 0, 1, ".x", 0, NULL, NULL - }; + };*/ if (GetOpenFileName(&sFilename1) == 0) { return; } diff --git a/tools/assimp_view/assimp_view.cpp b/tools/assimp_view/assimp_view.cpp index d96e5ac97..355287e0d 100644 --- a/tools/assimp_view/assimp_view.cpp +++ b/tools/assimp_view/assimp_view.cpp @@ -47,9 +47,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #ifdef __MINGW32__ -#include +# include #else -#include +# include #endif using namespace std; @@ -310,9 +310,10 @@ int LoadAsset() // Delete the loaded asset // The function does nothing is no asset is loaded //------------------------------------------------------------------------------- -int DeleteAsset(void) -{ - if (!g_pcAsset)return 0; +int DeleteAsset(void) { + if (!g_pcAsset) { + return 0; + } // don't anymore know why this was necessary ... CDisplay::Instance().OnRender(); @@ -349,9 +350,7 @@ int DeleteAsset(void) // p_avOut Receives the min/max boundaries. Must point to 2 vec3s // piMatrix Transformation matrix of the graph at this position //------------------------------------------------------------------------------- -int CalculateBounds(aiNode* piNode, aiVector3D* p_avOut, - const aiMatrix4x4& piMatrix) -{ +int CalculateBounds(aiNode* piNode, aiVector3D* p_avOut, const aiMatrix4x4& piMatrix) { ai_assert(NULL != piNode); ai_assert(NULL != p_avOut); @@ -739,7 +738,7 @@ int DeleteAssetData(bool bNoMaterials) //------------------------------------------------------------------------------- -// Switch beetween zoom/rotate view and the standatd FPS view +// Switch between zoom/rotate view and the standard FPS view // g_bFPSView specifies the view mode to setup //------------------------------------------------------------------------------- int SetupFPSView() @@ -982,7 +981,7 @@ int CreateDevice (bool p_bMultiSample,bool p_bSuperSample,bool bHW /*= true*/) sParams.MultiSampleType = sMSOut; } - // preget the device capabilities. If the hardware vertex shader is too old, we prefer software vertex processing + // get the device capabilities. If the hardware vertex shader is too old, we prefer software vertex processing g_piD3D->GetDeviceCaps( 0, D3DDEVTYPE_HAL, &g_sCaps); DWORD creationFlags = D3DCREATE_MULTITHREADED; if( g_sCaps.VertexShaderVersion >= D3DVS_VERSION( 2, 0)) @@ -1099,17 +1098,13 @@ int CreateDevice (bool p_bMultiSample,bool p_bSuperSample,bool bHW /*= true*/) return 1; } - //------------------------------------------------------------------------------- -//------------------------------------------------------------------------------- -int CreateDevice (void) +int CreateDevice() { return CreateDevice(g_sOptions.bMultiSample, g_sOptions.bSuperSample); } - -//------------------------------------------------------------------------------- //------------------------------------------------------------------------------- int GetProjectionMatrix (aiMatrix4x4& p_mOut) { From afb779e59d379f1329ee3d29f5872f15ca85dfc6 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 5 Feb 2019 00:36:07 +0100 Subject: [PATCH 135/472] remove dead code --- tools/assimp_view/MessageProc.cpp | 33 ------------------------------- 1 file changed, 33 deletions(-) diff --git a/tools/assimp_view/MessageProc.cpp b/tools/assimp_view/MessageProc.cpp index 8afecd602..5f34692d9 100644 --- a/tools/assimp_view/MessageProc.cpp +++ b/tools/assimp_view/MessageProc.cpp @@ -852,31 +852,6 @@ void OpenAsset() { strcpy(szCur,"*.*"); szCur[4] = 0; - /*DWORD lStructSize; - HWND hwndOwner; - HINSTANCE hInstance; - LPCWSTR lpstrFilter; - LPWSTR lpstrCustomFilter; - DWORD nMaxCustFilter; - DWORD nFilterIndex; - LPWSTR lpstrFile; - DWORD nMaxFile; - LPWSTR lpstrFileTitle; - DWORD nMaxFileTitle; - LPCWSTR lpstrInitialDir; - LPCWSTR lpstrTitle; - DWORD Flags; - WORD nFileOffset; - WORD nFileExtension; - LPCWSTR lpstrDefExt; - LPARAM lCustData; - LPOFNHOOKPROC lpfnHook; - LPCWSTR lpTemplateName; -#ifdef _MAC - LPEDITMENU lpEditInfo; - LPCSTR lpstrPrompt;*/ - - OPENFILENAME sFilename1; ZeroMemory(&sFilename1, sizeof(sFilename1)); sFilename1.lStructSize = sizeof(sFilename1); @@ -891,14 +866,6 @@ void OpenAsset() { sFilename1.nMaxFileTitle = 0; sFilename1.lpstrInitialDir = NULL; sFilename1.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR; - /*OPENFILENAME sFilename1 = { - sizeof(OPENFILENAME), - g_hDlg, GetModuleHandle(NULL), szList, NULL, 0, 1, - szFileName, MAX_PATH, NULL, 0, NULL, - "Import Asset into ASSIMP", - OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, - 0, 1, ".x", 0, NULL, NULL - };*/ if (GetOpenFileName(&sFilename1) == 0) { return; } From 216008d230971bce5110b8d23b3911f9b6cc36a1 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 5 Feb 2019 20:16:53 +0100 Subject: [PATCH 136/472] Update Readme.md closes https://github.com/assimp/assimp/issues/2248: Add lgtm badge. --- Readme.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 7f42fb75c..efb8ecc2b 100644 --- a/Readme.md +++ b/Readme.md @@ -1,7 +1,7 @@ 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 ### +### Current project 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) @@ -12,6 +12,7 @@ A library to import and export various 3d-model-formats including scene-post-pro [![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) [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Average time to resolve an issue") [![Codacy Badge](https://api.codacy.com/project/badge/Grade/5be56faac64f46fc941ac890fb4febef)](https://www.codacy.com/app/kimkulling/assimp?utm_source=github.com&utm_medium=referral&utm_content=assimp/assimp&utm_campaign=Badge_Grade) +[![Total alerts](https://img.shields.io/lgtm/alerts/g/assimp/assimp.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/assimp/assimp/alerts/)
    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. From 6e39c22554d47bfd4d519227e317f536a4daf9a2 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 5 Feb 2019 22:05:52 +0100 Subject: [PATCH 137/472] Fix potential security issues. --- code/AssbinExporter.cpp | 5 +++++ code/AssimpCExport.cpp | 1 - code/AssxmlExporter.cpp | 9 ++++++-- code/ColladaParser.cpp | 2 +- code/ValidateDataStructure.cpp | 28 ++++++++++++------------- tools/assimp_cmd/WriteDumb.cpp | 16 +++++++++++++-- tools/assimp_view/MessageProc.cpp | 34 +------------------------------ 7 files changed, 41 insertions(+), 54 deletions(-) diff --git a/code/AssbinExporter.cpp b/code/AssbinExporter.cpp index 77c8d1118..03b0368ce 100644 --- a/code/AssbinExporter.cpp +++ b/code/AssbinExporter.cpp @@ -760,7 +760,12 @@ public: if (!out) return; time_t tt = time(NULL); +#if _WIN32 tm* p = gmtime(&tt); +#else + struct tm now; + tm* p = gmtime_r(&tt, &now); +#endif // header char s[64]; diff --git a/code/AssimpCExport.cpp b/code/AssimpCExport.cpp index 5121ce39c..beb3ec3c5 100644 --- a/code/AssimpCExport.cpp +++ b/code/AssimpCExport.cpp @@ -60,7 +60,6 @@ ASSIMP_API size_t aiGetExportFormatCount(void) return Exporter().GetExportFormatCount(); } - // ------------------------------------------------------------------------------------------------ ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t index) { diff --git a/code/AssxmlExporter.cpp b/code/AssxmlExporter.cpp index fafee0e80..fc9a6bae5 100644 --- a/code/AssxmlExporter.cpp +++ b/code/AssxmlExporter.cpp @@ -184,8 +184,13 @@ static std::string encodeXML(const std::string& data) { static void WriteDump(const aiScene* scene, IOStream* io, bool shortened) { time_t tt = ::time( NULL ); - tm* p = ::gmtime( &tt ); - ai_assert( nullptr != p ); +#if _WIN32 + tm* p = gmtime(&tt); +#else + struct tm now; + tm* p = gmtime_r(&tt, &now); +#endif + ai_assert(nullptr != p); // write header std::string header( diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index 4d599a0c7..0fa59362b 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -2362,7 +2362,7 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pP if( expectedPointCount > 0 && indices.size() != expectedPointCount * numOffsets) { if (pPrimType == Prim_Lines) { // HACK: We just fix this number since SketchUp 15.3.331 writes the wrong 'count' for 'lines' - ReportWarning( "Expected different index count in

    element, %d instead of %d.", indices.size(), expectedPointCount * numOffsets); + ReportWarning( "Expected different index count in

    element, %zu instead of %zu.", indices.size(), expectedPointCount * numOffsets); pNumPrimitives = (indices.size() / numOffsets) / 2; } else ThrowException( "Expected different index count in

    element."); diff --git a/code/ValidateDataStructure.cpp b/code/ValidateDataStructure.cpp index 7db05a4e3..405670bdd 100644 --- a/code/ValidateDataStructure.cpp +++ b/code/ValidateDataStructure.cpp @@ -180,23 +180,21 @@ inline void ValidateDSProcess::DoValidationEx(T** parray, unsigned int size, // ------------------------------------------------------------------------------------------------ template -inline void ValidateDSProcess::DoValidationWithNameCheck(T** array, - unsigned int size, const char* firstName, - const char* secondName) -{ +inline +void ValidateDSProcess::DoValidationWithNameCheck(T** array, unsigned int size, const char* firstName, const char* secondName) { // validate all entries DoValidationEx(array,size,firstName,secondName); - for (unsigned int i = 0; i < size;++i) - { + for (unsigned int i = 0; i < size;++i) { int res = HasNameMatch(array[i]->mName,mScene->mRootNode); - if (!res) { + if (0 == res) { + const std::string name = static_cast(array[i]->mName.data); ReportError("aiScene::%s[%i] has no corresponding node in the scene graph (%s)", - firstName,i,array[i]->mName.data); - } - else if (1 != res) { + firstName,i, name.c_str()); + } else if (1 != res) { + const std::string name = static_cast(array[i]->mName.data); ReportError("aiScene::%s[%i]: there are more than one nodes with %s as name", - firstName,i,array[i]->mName.data); + firstName,i, name.c_str()); } } } @@ -699,7 +697,7 @@ void ValidateDSProcess::Validate( const aiMaterial* pMaterial) if (prop->mDataLength < 5 || prop->mDataLength < 4 + (*reinterpret_cast(prop->mData)) + 1) { ReportError("aiMaterial::mProperties[%i].mDataLength is " "too small to contain a string (%i, needed: %i)", - i,prop->mDataLength,sizeof(aiString)); + i,prop->mDataLength,static_cast(sizeof(aiString))); } if(prop->mData[prop->mDataLength-1]) { ReportError("Missing null-terminator in string material property"); @@ -710,14 +708,14 @@ void ValidateDSProcess::Validate( const aiMaterial* pMaterial) if (prop->mDataLength < sizeof(float)) { ReportError("aiMaterial::mProperties[%i].mDataLength is " "too small to contain a float (%i, needed: %i)", - i,prop->mDataLength,sizeof(float)); + i,prop->mDataLength, static_cast(sizeof(float))); } } else if (aiPTI_Integer == prop->mType) { if (prop->mDataLength < sizeof(int)) { ReportError("aiMaterial::mProperties[%i].mDataLength is " "too small to contain an integer (%i, needed: %i)", - i,prop->mDataLength,sizeof(int)); + i,prop->mDataLength, static_cast(sizeof(int))); } } // TODO: check whether there is a key with an unknown name ... @@ -955,7 +953,7 @@ void ValidateDSProcess::Validate( const aiString* pString) { if (pString->length > MAXLEN) { - this->ReportError("aiString::length is too large (%i, maximum is %i)", + this->ReportError("aiString::length is too large (%i, maximum is %lu)", pString->length,MAXLEN); } const char* sz = pString->data; diff --git a/tools/assimp_cmd/WriteDumb.cpp b/tools/assimp_cmd/WriteDumb.cpp index 0bcd5321c..569749994 100644 --- a/tools/assimp_cmd/WriteDumb.cpp +++ b/tools/assimp_cmd/WriteDumb.cpp @@ -679,7 +679,13 @@ void WriteBinaryDump(const aiScene* scene, FILE* _out, const char* src, const ch shortened = _shortened; time_t tt = time(NULL); - tm* p = gmtime(&tt); +#if _WIN32 + tm* p = gmtime(&tt); +#else + struct tm now; + tm* p = gmtime_r(&tt, &now); +#endif + ai_assert(nullptr != p); // header fprintf(out,"ASSIMP.binary-dump.%s",asctime(p)); @@ -861,7 +867,13 @@ static std::string encodeXML(const std::string& data) { void WriteDump(const aiScene* scene, FILE* out, const char* src, const char* cmd, bool shortened) { time_t tt = ::time(NULL); - tm* p = ::gmtime(&tt); +#if _WIN32 + tm* p = gmtime(&tt); +#else + struct tm now; + tm* p = gmtime_r(&tt, &now); +#endif + ai_assert(nullptr != p); std::string c = cmd; std::string::size_type s; diff --git a/tools/assimp_view/MessageProc.cpp b/tools/assimp_view/MessageProc.cpp index 8afecd602..2855c1fa7 100644 --- a/tools/assimp_view/MessageProc.cpp +++ b/tools/assimp_view/MessageProc.cpp @@ -852,31 +852,6 @@ void OpenAsset() { strcpy(szCur,"*.*"); szCur[4] = 0; - /*DWORD lStructSize; - HWND hwndOwner; - HINSTANCE hInstance; - LPCWSTR lpstrFilter; - LPWSTR lpstrCustomFilter; - DWORD nMaxCustFilter; - DWORD nFilterIndex; - LPWSTR lpstrFile; - DWORD nMaxFile; - LPWSTR lpstrFileTitle; - DWORD nMaxFileTitle; - LPCWSTR lpstrInitialDir; - LPCWSTR lpstrTitle; - DWORD Flags; - WORD nFileOffset; - WORD nFileExtension; - LPCWSTR lpstrDefExt; - LPARAM lCustData; - LPOFNHOOKPROC lpfnHook; - LPCWSTR lpTemplateName; -#ifdef _MAC - LPEDITMENU lpEditInfo; - LPCSTR lpstrPrompt;*/ - - OPENFILENAME sFilename1; ZeroMemory(&sFilename1, sizeof(sFilename1)); sFilename1.lStructSize = sizeof(sFilename1); @@ -891,14 +866,7 @@ void OpenAsset() { sFilename1.nMaxFileTitle = 0; sFilename1.lpstrInitialDir = NULL; sFilename1.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR; - /*OPENFILENAME sFilename1 = { - sizeof(OPENFILENAME), - g_hDlg, GetModuleHandle(NULL), szList, NULL, 0, 1, - szFileName, MAX_PATH, NULL, 0, NULL, - "Import Asset into ASSIMP", - OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, - 0, 1, ".x", 0, NULL, NULL - };*/ + if (GetOpenFileName(&sFilename1) == 0) { return; } From f9014d7410a67ce4c9a4816ec21304d0e3e50970 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Tue, 5 Feb 2019 14:36:49 +0000 Subject: [PATCH 138/472] Add tokenization of 'c' type arrays, both compressed and uncompressed. --- code/FBXBinaryTokenizer.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/code/FBXBinaryTokenizer.cpp b/code/FBXBinaryTokenizer.cpp index f12a5c5b2..4f5f5d870 100644 --- a/code/FBXBinaryTokenizer.cpp +++ b/code/FBXBinaryTokenizer.cpp @@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include + namespace Assimp { namespace FBX { @@ -83,7 +84,7 @@ namespace FBX { // 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_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, @@ -276,8 +277,8 @@ void ReadData(const char*& sbegin_out, const char*& send_out, const char* input, case 'f': case 'd': case 'l': - case 'i': { - + case 'i': + case 'c': { const uint32_t length = ReadWord(input, cursor, end); const uint32_t encoding = ReadWord(input, cursor, end); @@ -298,6 +299,10 @@ void ReadData(const char*& sbegin_out, const char*& send_out, const char* input, stride = 8; break; + case 'c': + stride = 1; + break; + default: ai_assert(false); }; From 02a5f6b62f89042a6b46f8c1eb1111355094ce43 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Tue, 5 Feb 2019 15:54:33 +0000 Subject: [PATCH 139/472] Remove unneeded newline. --- code/FBXBinaryTokenizer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/code/FBXBinaryTokenizer.cpp b/code/FBXBinaryTokenizer.cpp index 4f5f5d870..7138df431 100644 --- a/code/FBXBinaryTokenizer.cpp +++ b/code/FBXBinaryTokenizer.cpp @@ -54,7 +54,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include - namespace Assimp { namespace FBX { From 56374666a700a27f23fe23a39e50040e29db5187 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Tue, 5 Feb 2019 16:43:03 +0000 Subject: [PATCH 140/472] Add two test files which require 'c' handling to be tokenized correctly. --- test/models/FBX/boxWithCompressedCTypeArray.FBX | Bin 0 -> 13824 bytes .../FBX/boxWithUncompressedCTypeArray.FBX | Bin 0 -> 26021 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/models/FBX/boxWithCompressedCTypeArray.FBX create mode 100644 test/models/FBX/boxWithUncompressedCTypeArray.FBX diff --git a/test/models/FBX/boxWithCompressedCTypeArray.FBX b/test/models/FBX/boxWithCompressedCTypeArray.FBX new file mode 100644 index 0000000000000000000000000000000000000000..2f71bc7ee9383cc8db4615b1c15067625a26b6be GIT binary patch literal 13824 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 literal 0 HcmV?d00001 From cc276c3180ef312d555388f8748412e163537126 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lassi=20L=C3=A4=C3=A4ti?= Date: Wed, 6 Feb 2019 21:14:22 +0200 Subject: [PATCH 141/472] cast size_t to unsigned int --- code/glTF2AssetWriter.inl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl index 0d61d23e5..bec88ceb8 100644 --- a/code/glTF2AssetWriter.inl +++ b/code/glTF2AssetWriter.inl @@ -97,10 +97,10 @@ namespace glTF2 { 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("byteOffset", (unsigned int)a.byteOffset, w.mAl); obj.AddMember("componentType", int(a.componentType), w.mAl); - obj.AddMember("count", a.count, w.mAl); + obj.AddMember("count", (unsigned int)a.count, w.mAl); obj.AddMember("type", StringRef(AttribType::ToString(a.type)), w.mAl); Value vTmpMax, vTmpMin; From 3f9a25df5a4527cbb3debc2f7f0bf197e5a011bf Mon Sep 17 00:00:00 2001 From: kimkulling Date: Thu, 7 Feb 2019 17:09:05 +0100 Subject: [PATCH 142/472] Devil: replace this by header-only lib. --- .../stb_image}/stb_image.h | 0 samples/DevIL/AUTHORS | 4 - samples/DevIL/COPYING | 506 ------------- samples/DevIL/CREDITS | 264 ------- samples/DevIL/ChangeLog | 604 --------------- samples/DevIL/DevIL Website.url | 5 - samples/DevIL/Libraries.txt | 40 - samples/DevIL/README | 176 ----- samples/DevIL/README.win | 44 -- samples/DevIL/include/IL/config.h | 140 ---- samples/DevIL/include/IL/config.h.win | 79 -- .../DevIL/include/IL/devil_internal_exports.h | 161 ---- samples/DevIL/include/IL/il.h | 644 ---------------- samples/DevIL/include/IL/il_wrap.h | 205 ----- samples/DevIL/include/IL/ilu.h | 195 ----- samples/DevIL/include/IL/ilu_region.h | 25 - samples/DevIL/include/IL/ilut.h | 390 ---------- samples/DevIL/include/IL/ilut_config.h | 26 - samples/DevIL/lib/DevIL.lib | Bin 30802 -> 0 bytes samples/DevIL/lib/ILU.lib | Bin 11630 -> 0 bytes samples/DevIL/lib/ILUT.lib | Bin 10564 -> 0 bytes samples/SimpleOpenGL/CMakeLists.txt | 6 +- samples/SimpleTexturedOpenGL/CMakeLists.txt | 6 +- .../src/model_loading.cpp | 64 +- samples/bin/DevIL.dll | Bin 764382 -> 0 bytes samples/bin/ILU.dll | Bin 28663 -> 0 bytes samples/bin/ILUT.dll | Bin 17400 -> 0 bytes samples/bin/ShowDwarf.bat | 1 - samples/bin/ShowWuson.bat | 1 - samples/bin/glut32.dll | Bin 237536 -> 0 bytes samples/glut/GL/glut.h | 716 ------------------ samples/glut/README-win32.txt | 613 --------------- samples/glut/glut.def | 126 --- samples/glut/glut32.lib | Bin 28728 -> 0 bytes tools/assimp_qt_viewer/CMakeLists.txt | 5 +- tools/assimp_qt_viewer/glview.cpp | 4 +- 36 files changed, 42 insertions(+), 5008 deletions(-) rename {tools/assimp_qt_viewer => contrib/stb_image}/stb_image.h (100%) delete mode 100644 samples/DevIL/AUTHORS delete mode 100644 samples/DevIL/COPYING delete mode 100644 samples/DevIL/CREDITS delete mode 100644 samples/DevIL/ChangeLog delete mode 100644 samples/DevIL/DevIL Website.url delete mode 100644 samples/DevIL/Libraries.txt delete mode 100644 samples/DevIL/README delete mode 100644 samples/DevIL/README.win delete mode 100644 samples/DevIL/include/IL/config.h delete mode 100644 samples/DevIL/include/IL/config.h.win delete mode 100644 samples/DevIL/include/IL/devil_internal_exports.h delete mode 100644 samples/DevIL/include/IL/il.h delete mode 100644 samples/DevIL/include/IL/il_wrap.h delete mode 100644 samples/DevIL/include/IL/ilu.h delete mode 100644 samples/DevIL/include/IL/ilu_region.h delete mode 100644 samples/DevIL/include/IL/ilut.h delete mode 100644 samples/DevIL/include/IL/ilut_config.h delete mode 100644 samples/DevIL/lib/DevIL.lib delete mode 100644 samples/DevIL/lib/ILU.lib delete mode 100644 samples/DevIL/lib/ILUT.lib delete mode 100644 samples/bin/DevIL.dll delete mode 100644 samples/bin/ILU.dll delete mode 100644 samples/bin/ILUT.dll delete mode 100644 samples/bin/ShowDwarf.bat delete mode 100644 samples/bin/ShowWuson.bat delete mode 100644 samples/bin/glut32.dll delete mode 100644 samples/glut/GL/glut.h delete mode 100644 samples/glut/README-win32.txt delete mode 100644 samples/glut/glut.def delete mode 100644 samples/glut/glut32.lib diff --git a/tools/assimp_qt_viewer/stb_image.h b/contrib/stb_image/stb_image.h similarity index 100% rename from tools/assimp_qt_viewer/stb_image.h rename to contrib/stb_image/stb_image.h diff --git a/samples/DevIL/AUTHORS b/samples/DevIL/AUTHORS deleted file mode 100644 index 0f80b3c4a..000000000 --- a/samples/DevIL/AUTHORS +++ /dev/null @@ -1,4 +0,0 @@ -The main programmer is Denton Woods, but this could not have been possible -without contributions and some pieces of code from other projects. - -For contributors and credits, read the CREDITS file. diff --git a/samples/DevIL/COPYING b/samples/DevIL/COPYING deleted file mode 100644 index 30c8ca213..000000000 --- a/samples/DevIL/COPYING +++ /dev/null @@ -1,506 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - - - diff --git a/samples/DevIL/CREDITS b/samples/DevIL/CREDITS deleted file mode 100644 index b30dc4685..000000000 --- a/samples/DevIL/CREDITS +++ /dev/null @@ -1,264 +0,0 @@ -Credits as of 02/06/2009 ------------------------- - -If I inadvertently omitted anyone's name from this list, please e-mail me at -doomwiz@users.sourceforge.net to remedy the problem. - - -James Joplin, alias jayjay (rjoplin@webzone.net) -for all his invaluable help and encouragement with DevIL. - -Edouard Gomez for his invaluable help. - -All the #flipCode gang for their support. - -All my friends at uni for their support. - -SoftImage .pic support based off of code obtained from -http://www.swin.edu.au/astronomy/pbourke/dataformats/ - -TestPic, used in TestIL -http://www.paintlib.de/paintlib/testpic.zip - -Png Test Images -http://www.schaik.com/pngsuite/pngsuite.html - -John Villar (john.villar@eliaschev.com) for making the suggestion of not -letting the user use ILimage structs but instead binding images like OpenGL. -He also made a suggestion on how to load luminance .jpg images, along with -other suggestions. - -http://www.opengl.org/Coding/KilgardTechniques/oglpitfall/oglpitfall.html -section 6 for the values the NTSC uses, so I could convert from coloured -images to luminance values. - -Kodak Photo CD code from the .pcd link on http://www.wotsit.org. - -Foper (foper@hotmail.com) from #flipCode for supplying the excellent -flipcode.jpg in testil\in. The original can be found at -http://webpatterns.com/flip/flipshow.htm - -Lightman (cdthompson@home.net) from #flipCode for restructuring the project -into /bin, /obj, etc. - -Alexander Blach (alexander@abee.de) from #flipCode for creating the Delphi -headers and test app. He figured out that we needed to use .def files to -prevent name decoration of the dlls. He has contributed multiple ideas and -found flaws. Alexander also created a lovely documentation database to help -with documenting DevIL. - -Randy Heit for finding problems in my Doom texture code. - -Oliver Kurowski (oliver.kurowski@gmx.de) for locating a bug in ilut's -DllMain() and another very harmful bug with ilDeleteImages(). - -Ender Wiggin's article on "Elementary Digital Filtering", -found at http://www.gamedev.net/reference/programming/features/edf/ -for many filters in DevIL. - -SGI's "Graphica Obscura" site at http://www.sgi.com/grafica/matrix/index.html -for several filters in DevIL. - -The http://bae.fse.missouri.edu/luw/course/image/project1/project1.html -page for help in determining filter code for Graphica Obscura's interpolation -article at http://www.sgi.com/grafica/interp/index.html. - -Matt Denham for suggesting optimizations in ilNegativeImage(), -iluEdgeDetectS() and iluEdgeDetectP(). - -Timo Heister (Timo-Heister@gmx.de) from #flipCode for creating the original -Visual Basic headers and test apps for VB. - -The OpenGL SuperBible for code for ilutGetHPal(). - -DJ Luminescent (luminescent@uswest.net) for finding a couple of bugs in the -.bmp-loading code and diligently beta testing. - -Lionel Brits, alias Zaewo from #flipCode for slapping me around and telling -me how Microsoft does their .bmp padding. He then wrote most of the -iluEqualize() code from the base code on -http://www.manning.com/Kabir/Files.html . - -Joel Wilsson, alias Siigron (siigron@hotmail.com) for pointing-out several -design flaws that I (Denton) had introduced and posing very useful -suggestions. - -Sean Montgomery, alias Vapor (sean@astralfx.com) for patiently listening to -my endless drivel about DevIL. - -Perlin Noise site http://freespace.virgin.net/hugo.elias/models/m_perlin.htm -for information on interpolation used in iluScale(). - -Shimon Shvartsbroit, alias MasterBoy (cobra11@netvision.net.il) from #flipCode -for explaining bilinear interpolation to me. - -Lbm source from http://www.wotsit.org - -Eran Kampf, alias ttentacle (ekampf@internet-zahav.net) for giving me -resource-loading code for ilutLoadResource and helping with the Windows -clipboard functions. - -Strumpf from #flipCode for writing a really good DirectDraw class for me to -use in the DDraw test, which is based off of his test, too. - -NullSoft (http://www.nullsoft.com), for their SuperPiMP installer. It is -extremely easy to learn to use and very powerful. - -Serun from #flipCode for noticing that Quake2 .pcx files sometimes don't have -the checksum byte for palette'd .pcx files. - -Conor Stokes, aka DirtyPunk from #flipCode for helping explain several things -to me. - -Half-Life model viewer sources (at http://www.swissquake.ch/chumbalum-soft/) -for specs for the Half-Life model format. - -Rich Schwab, alias endura (endura29@hotmail.com) for contributing -girlfriend.cpp. - -The Djgpp libc sources (http://www.delorie.com/djgpp), from where I copied -several functions. - -Roman Podobedov (romka@ut.ee) of Romka Graphics (http://romka.demonews.com) -for his colour quantization sources, which he was kind enough to let me use. - -Pcx document on http://www.wotsit.org for .pcx saving code. - -http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue2.html#Insight -for iluWave(). - -.lif specs from http://www.infinite-mass.com/bob/files/lifed.zip and - http://www.infinite-mass.com/bob/files/lif.zip - -Rune Kock (rune@vupti.com) for writing the new Visual Basic headers and for -finding a return bug in iluScaleAdvanced. - -Julien Verchere and Xavier Decoret for suggesting that I use const char*'s -instead of char*'s as function parameters. - -Jason Reeve (jason@retribution-entertainment.com) for finding a bug in iluCrop, -several origin-related problems, and helping me bring my targa-loading code up -to spec. - -Darren Adams for telling me the #pragmas to use in MSVC++ to disable the -console window in a "console app". - -David Gould for getting onto me about my crappy Linux support. - -David Galeano for his DX8 Surface to TGA code, modified to save to any texture. -The original can be found at http://rt000s2p.eresmas.net/downloads.htm - -RLE code from TrueVision's TGA sample code available as Tgautils.zip at -ftp://ftp.truevision.com/pub/TGA.File.Format.Spec/PC.Version/ - -Jeroen Janssen for creating a Mandrake RPM patch for DevIL. - -Greg Priem for his help with supporting libungif and some various other things. - -Nelson Rush for SDL surface support and finding several bugs with DevIL. - -George McBay for his wonderful help finding bugs in my mipmapping code. - -Marco Kögler for finding bugs in my .jpg and .png code. - -Falco Kleinschmidt for fixing problems with the Linux makefiles. - -Olivier Bucher for finding a bug in saving 8-bit .bmp files. - -Derek Wills for noticing a problem with ilutGLScreenie when the screen width is -not a multiple of 4. - -Dale Schumacher's "Filtered Image Rescaling" code in Graphic Gems III for some -scaling algorithms in ILU. - -Kevin Park for making some suggestions on the ilImage C++ wrapper. - -Alessandro Pedretti for finding a bug in my TIFF code and making suggestions -about portability issues. - -boostrlns from #flipCode for finding the ilutGLLoadImage bug in the 1.1.5 -release. - -Ismo Kärkkäinen (iak@cs.joensuu.fi) for making some really nice new makefiles -for Linux. - -Kishan (http://www.hackorama.com) for the nice directions on how to compile -the external libraries under Linux. - -Wojciech Sobczuk for creating FreeBSD versions of the makefiles. - -nVidia for code to load .DDS files available at -http://www.nvidia.com/view.asp?IO=dxtc_decompression_code - -PixiGreg for noticing that many viewers don't like .bmp files with negative -heights (flipped), even though the specs say that it is valid. - -Matthias Stiller and Andre Normann for their invaluable help with getting -DevIL to work on Big Endian machines. - -Jean-Francois Richard for the Python bindings of DevIL. - -Nick Marley for post-build information in MSVC++. - -Kenneth Hurley for his help in expanding and fixing my DDS code. - -Mark Callow for EXIF-loading and saving code, along with il[Load/Save]FromJpegStruct - -Sam for several fixes to my .bmp and .jpg loaders. - -chris79 for his help debugging my .psp and .gif code in several versions. - -Nick Marley for his MSVC++ post-build fixes. - -Marc Gregoire for sending images that DevIL would not load. - -Alberto Barbati for noticing that the IL_NEU_QUANT_SAMPLE mode wasn't being used properly. - -Ryan Butterfoss for his contributions to the DDS saving code. - -Computer Graphics (C Version) book by Hearn and Baker for the arbitrary polygon filling code. - -Nicolas Weber - -Meloni Dario - -Erick Tryzelaar - -Matej Tyc for completely redoing the Linux makefile system and rewriting the documentation. - -Matevz Tadel for fixing makefile for Scientific Linux. - -Richard Sim for contributing several fixes, especially for .psd loading - -robin_charlton for contributing a patch for Windows BMP support in ILUT. - -Vincent Richomme for DirectX Mobile support - -Antibyte for DDS save bugfix - -Stefan Cornelius, Secunia Research, for finding some buffer overflow vulnerabilities. - -Nico Golde for finding that my fix for the above vulnerability was not totally complete. - -GAIA (Group for Artificial Intelligence Applications) for contributions including .iff-loading -and redoing the ilutConvertToHBitmap code. Their changes are at -http://gaia.fdi.ucm.es/grupo/projects/javy/devzone.html#DevILNotes. - -Jesse Maurais for support of X11 component - - -Translations: -------------- - -Carlos Aragonés, for Spanish translation - -Bart De Lathouwer, for Danish translation - -Osamu Ohara, for English translation - -Abdullah Alshammari, for Arabic translation - -Osamu Ohara, for Japanese translation - -Andreas Stöckel, for German translation - diff --git a/samples/DevIL/ChangeLog b/samples/DevIL/ChangeLog deleted file mode 100644 index eabed1920..000000000 --- a/samples/DevIL/ChangeLog +++ /dev/null @@ -1,604 +0,0 @@ -2009-03-08 Matěj Týč - * docs/Makefile.am: Fixed distcheck by overriding dvi target. - * lib/Makefile.am: Renoved ilu_mipmap.h file - * configure.ac: Added option to disable checks for 'nvidia texture tools' and - 'libsquish' - -2009-03-08 Denton Woods - * il_ilbm.c:410: Changed to IL_BGR from IL_RGB. - * il_iff.c (ilLoadIffF/ilLoadIffL): Changed to call Lbm loading functions - if Iff loading fails, since they both can have the .iff extension. - * il_ilbm.c:416: Added origin reference. - * configure.ac: Added more file formats to the format checks. - * Makefile.am: Removed ilu_mipmap.h. Added ilu_error-french.h. - -2009-03-07 Denton Woods - * Updated version numbers to 1.7.8 project-wide. - * DevIL_manual.texi: Added several file formats to the appendix. - * il_io.c: Updated Doxygen comments for loading/saving functions. - * libraries.txt: Updated with new libraries. - * il_io.c (ilTypeFromExt): Changed return value of FITS files to IL_FITS. - Added DICOM, FTX, Rot and Texture checks. - * il_states.c/.h: Updated with newer file formats. - * il_blp.c:649: Fixed ilNewImageFull call to use color index. - 659: Fixed memcpy from base image to new mipmap. - * il_dcx.c, il_exr.cpp and many more: Checks return value of ilFixImage now. - * il_iff.c:271: Got rid of ilConvertImage call. - -2009-03-06 Denton Woods - * Updated VC8 projects to use il_mp3.c. - * il.h: Added description to IL_WDP. - -2009-03-05 Denton Woods - * il_mp3.c: Added this file. - * il_io.c: Added loading calls for .mp3 files. - * il_internal.h: Added .mp3 loading declarations. - * Makefile.am: Added il_mp3.c to source line. - * il.h: Added IL_MP3 define. - -2009-03-04 Denton Woods - * il_utx.cpp: Started cleanup of file using C++ constructs. - * Updated VC8 projects to use il_utx.cpp. - -2009-03-03 Denton Woods - * ilu_error-french.h: Added French translation of errors. - * ilu.h: Added ILU_FRENCH define. - * Changed il_utx.c to il_utx.cpp. - -2009-03-02 Denton Woods - * il_utx.c: Added DXT1 loading in UTX files. - * il_utx.h: Added this file. - * lib/Makefile.am: Added il_utx.h to include line. - * il_utx.c: Fixed loading of larger images. - * windows_example.rc: Fixed accelerator for menu. - -2009-03-01 Denton Woods - * il_utx.c: Added this file. - * lib/Makefile.am: Added il_utx.c to source line. - * il_internal.h: Added .utx loading declarations. - * il_io.c: Added loading calls for .utx files. - -2009-02-28 Denton Woods - * il_states.c / il_states.h: Added ilVtfCompression to IL_STATES. - * il_vtf.c: Added more formats to saving. - * il.h: Added IL_VTF_COMP define. - * il_io.c: Added saving calls for .vtf files. - * il_dds.c: Added DecompressARGB16 to load a2r10g10b10 and a2b10g10r10 formats. - * il_convbuff (iSwitchTypes): Added several missing break statements. - * il_convbuff:1988: Changed to check types instead of bpc. - -2009-02-27 Denton Woods - * il_dpx.c / il_dpx.h: Got basic dpx loading working. - * WindowsTest.cpp: Fixed memory leak when loading files. - * il_vtf.c (iGetVtfHead): Added support for headers of 64 bytes. - * il_iwi.c (iLoadIwiInternal): Added IL_INVALID_FILE_HEADER error. - * il_vtf.c: Added VTF writing functions. - -2009-02-26 Denton Woods - * configure.ac, lib/Makefile.am, il.h, il_internal.h, il_ilbm.c, il_io.c: Added - patch from Ben Campbell for ILBM files at - https://sourceforge.net/tracker2/index.php?func=detail&aid=2635333&group_id=4470&atid=304470. - * il_dpx.c / il_dpx.h: Added these files. - * lib/Makefile.am: Added il_dpx.c and il_dpx.h to source/include lines. - * il_internal.h: Added .dpx loading declarations. - * il_io.c: Added loading calls for .dpx files. - -2009-02-25 Denton Woods - * il_iwi.c:329: Changed IL_MAX parameter from 16 to 8 (copy+paste error). - * WindowsTest.cpp: Added mipmap functionality to 0-9 keys (0 goes to main image). - -2009-02-24 Denton Woods - * vc9 Unicode projects: Changed settings to use x64 and x86 directories for .obj files. - * test/in: Removed this directory. - * Added "Test Images" to SVN. - * il_dds.c (DecompressFloat): Added proper support for G16B16, G32B32, R16 and R32 images. - -2009-02-23 Denton Woods - * il_pnm.c: Fixed bug at https://sourceforge.net/forum/message.php?msg_id=6491617 - - Changed order of lines 448 and 450. - -2009-02-22 Denton Woods - * il_internal.h: Added IL_NO_EXTLIBS define. - * il_dds-save.c: Removed unused variables. - * ilu_mipmap.c: Finished redoing all mipmap functions. - * ilu_mipmap.h: Removed this file. - -2009-02-21 Denton Woods - * ilu_mipmap.c: Redid mipmap functions to use iluScale functions instead of nearest. - -2009-02-20 Matěj Týč - * docs/Makefile.am,docs/Devil_manual.texi: Added new ILU images to the - manual, set the manual license to GFDL. - * testil, ilur: Licensed under GPL v3 - -2009-02-19 Denton Woods - * windows_example\resources: Added DevIL Logo.ico, removed OpenIL Logo.ico. - * windows_example\resource.h: Changed to use DevIL Logo.ico. - * il_io.c (ilSaveL): Fixed bug where return type was cast to 1 byte. - -2009-02-18 Denton Woods - * configure.ac: Added descriptions of more image formats. - * il_ftx.c (iLoadFtxInternal): Changed to load all FTX images as RGBA. - -2009-02-17 Denton Woods - * ilu_mipmap.c: Changed all references of Next to Mipmaps to fix bug noticed at - https://sourceforge.net/forum/message.php?msg_id=6443698. - * Added support for IL_NO_GAMES in il_internal.h. - -2009-02-17 Matěj Týč - * configure.ac, m4/devil-definitions.m4 (TEST_FORMAT): Added an option - to describe image formats. - -2009-02-16 Matěj Týč - * src-ILU/ilur: Made ilur independent on regex.h - * autogen.sh: Simplified autotools invocation to autoreconf only - * configure.ac: Added support for IL_NO_GAMES if users don't want - support for game formats - * docs/DevIL_manual.texi: Fixed errors causing trouble when making - info files + some minor syntax enhancements. - -2009-02-16 Denton Woods - * il_manip.c (ilGetAlpha): Added IL_ALPHA case. - * il_manip.c (ilSetAlpha): Cleaned up formatting. Added IL_ALPHA case. - Fixed casting issue in integer case. - * il_texture.c: Added this file and the simple .texture loading. - * lib/Makefile.am and src-IL/src/Makefile.am: Added il_texture.c to source line. - * il.h: Added IL_TEXTURE define. - * il_internal.h: Added .texture loading declarations. - * DevIL.nb: Removed the test image from the notebook to drop it from over 9MB to 4.5KB. - -2009-02-15 Denton Woods - * il_blp.c (iLoadBlpInternal): Finished testing and fixed BLP2 RAW with 1-bit alpha. - * il_dicom.c: Added this file. - * config.h.win: Added defines for new image formats. - * il_io.c / il_jp2.c: Added .jpx, .j2k and .j2c extensions for JPEG 2000. - * il_io.c / il_jpeg.c: Added .jif and .jfif extensions for JPEG. - * il_dicom.c: Added DICOM loading for uncompressed formats and little endian data. - * lib/Makefile.am and src-IL/src/Makefile.am: Added il_dicom.c to source line. - * il_dicom.c: Added DICOM support for big endian data. - * test/in/tiff: Removed this directory. - * il_rot.c: Added this file. Added .rot loading. - * lib/Makefile.am and src-IL/src/Makefile.am: Added il_rot.c to source line. - * il.h: Added IL_ROT define. - * il_internal.h: Added Rot loading declarations. - -2009-02-15 Matěj Týč - * src-ILU/ilur: Added the ilur - commandline ILU frontend - * bin, examples/Makefile.am: Moved examples's Makefile.am to bin - directory. Added ilur to it. - * docs/DevIL_manual.texi: Made slight syntax corrections, fixed the - sample program and added functions index - -2009-02-14 Denton Woods - * il_blp.c (iLoadBlp1): Support for mipmaps added. - * il_gif.h: Moved iCopyPalette declaration out of here into il_internal.h. - * il_gif.c: Moved iCopyPalette definition out of here into il_pal.c. - * projects/Mathematica: Added this folder. - * il_fits.c (iCheckFits): Implemented this. - * il_fits.c (iLoadFitsInternal): Renormalized float and double data. - * il_blp.c (iLoadBlp1): Added seeks to image data (not necessarily following palette). - * il_blp.c (iLoadBlpInternal): Added loading for BLP2 RAW with 1-bit alpha. - -2009-02-13 Denton Woods - * WindowsTest.cpp: Added slideshow capabilities with Page Up and Page Down. - * il_jpeg.c:357: Added ilFixImage call. - * il_jpeg.c (ilLoadFromJpegStruct): Changed return value to the return of ilFixImage. - * il_blp.c:466-467: Fixed to read these images properly. - * WindowsTest Project: Changed x64 debug to use runtime library debug DLLs. - -2009-02-12 Denton Woods - * il_ftx.c: Added this file. - * lib/Makefile.am and src-IL/src/Makefile.am: Added il_ftx.c to source line. - * il_io.c: Added Ftx loading function calls. - * il_blp.c: Added BLP1-loading functions. - -2009-02-11 Denton Woods - * il_jpeg.c (ilSaveJpegL): Changed the itellw call to after iSetOutputLump - (was returning bad values, since the lump was not set yet). - * il_io.c (ilSaveL): Changed return value to Ret and got rid of IL_FALSE check. - * il_bmp.c, il_dds-save.c, il_hdr.c, il_jp2.c, il_pcx.c, il_png.c, il_pnm.c, il_psd.c, il_raw.c, - il_sgi.c, il_wbmp.c: Fixed same problem that il_jpeg.c had with saving lumps. - * il_sgi.c: Put header on file. - * il_iwi.c:337: Removed this line, which called iread a second time for CompData. - -2009-02-10 Denton Woods - * il_io.c: Added ilLoadBlp calls in il_io.c. - * VC9 projects: Turned off x64 incremental linking to prevent debugging problems described here: - http://stackoverflow.com/questions/218747/msvcr90ddll-not-found-in-debug-mode-with-visual-c-2008 - * il_blp.c: Added code to read BLP2 files. - -2009-02-09 Denton Woods - * ilu_scale2d.c (iluScale2DBilinear_): Started rewrite, since results were really ugly. - * il_iwi.c / il_vtf.c: Changed max references to IL_MAX. - * il_wdp.c: Redid all of the code so that it actually works now. - * il_internal.h:42-46: Added lines to define IL_NO_WDP if not in Windows. - * il_io.c: Added Iwi and Fits loading calls. - * il.h: Added IL_BLP and IL_DICOM. Switched IL_DICOM and IL_IWI defines. - * il_internal.h: Added Blp and Dicom function defines. - * il_blp.c: Added this file and started code. - * lib/Makefile.am and src-IL/src/Makefile.am: Added il_blp.c to source line. - -2009-02-09 Matěj Týč - * tests/testil.c: Added checks what IL loading/saving routines ended - * build system: Removed --enable-monolithic option. - -2009-02-07/08 Denton Woods - * il_iwi.c: Added this file and code to load .iwi files. - * il_vtf.c (iLoadVtfInternal): Added checks for CompData == NULL. - * il_dds.c/il_dds.h: Changed CompFormat to a local variable. Renamed Decompress to DdsDecompress. - * ChangeLog (this file): Changed order to newest at the top. - * il.h: Added IL_FITS and IL_IWI defines. - * config.h.win: Added IL_FITS, IL_IWI, IL_SUN and IL_TPL. - * lib/Makefile.am and src-IL/src/Makefile.am: Added il_fits.c and il_iwi.c to source line. - - ---- 1.7.7 release --- - -2009-02-06 Matěj Týč - * configure.ac, lib/Makefile.am: Added explicit linking with libm - library + fixed the ilut_x11.c file conditions of compilation - * examples/Makefile.am + IL examples, test/Makefile.am + testil: Added - conditional compilation option when compiling only with IL (without - ILU, iluErrorString() absence workaround) - -2009-02-06 Denton Woods - * README.win and README.unix: Updated with Cygwin/MinGW instructions. - -2009-02-05 Denton Woods - * il_tga.c: Fixed bug loading malformed RLE Targa images. - * il_rle.c:20: Changed size_t cast to ILint to resolve compiler warning. - * il.def: Added definitions. - * Updated version numbers to 1.7.7 everywhere. - -2009-02-04 Denton Woods - * ilut_opengl.c:160: Changed checks to see if less than 0. - * il_fits.c: Got this reading FITS files properly. - -2009-02-04 Matěj Týč - * configure.ac: Corrected handling of --enable-debug options, added - working install support for pkg-config - * data/Makefile.am, *.pc.in: Corrected pkg-config files - -2009-02-03 Denton Woods - * il_io.c: Updated Doxygen comments. - * il_fits.c: Added this file (not in any projects yet). - * il_fits.c: Wrote beginning of FITS loading code. - -2009-02-02 Denton Woods - * il_manip.c (ilCopyPixels):311: Added check for destination format of color index. - * il_convbuff.c (ilConvertBuffer): Changed to accept the source image palette. Added code to - convert from buffers that are related to a palette before the large switch. - * il_alloc.c (ifree): Changed so that if Ptr == NULL, it does not try to free the pointer. - * il_nvidia.cpp/il_squish.cpp: Added empty functions if nVidia or libsquish support is not - compiled in. - * test/format_test/testil.c:5: Added _USE_MATH_DEFINES. - -2009-02-01 Matěj Týč - * test/format_test: Tweaked the script to use wine if cross-compiling - to run the tests, extended testil capabilities - * m4/devil-definitions.m4: Fixed bugs that caused that you couldn't - disable support for some formats no matter what :-) - * m4/devil-api-checks.m4: Added Xrender build support (by Jesse Maurais) - -2009-02-01 Denton Woods - * devil_internal_exports.h: Commented members of ILimage struct using Doxygen-style comments. - Removed deprecated, commented-out members (NumNext, NumLayers, NumMips). - * Updated several functions with appropriate Doxygen comments. - * il.h: Updated IL_XXX file format defines with Doxygen comments. - * ilu_rotate.c: Changed min/max calls to IL_MIN/IL_MAX. - * ilut_states.c (ilutSetInteger): Fixed ILUT_MAXTEX_DEPTH call and added checks around first - three calls for Param >= 1. - -2009-01-31 Denton Woods - * Added newlines to the end of several files to keep gcc quiet. - * Added new MSVC++ projects for examples. - * il_bmp.c:556: Changed to Header->biWidth from iCurImage->Width. iCurImage->Width was not - updated to the new width at this point. - * il_rotate.c (iluRotate_): Rewrote to fix 1 pixel shifting issue. - * Updated DevIL Manual with new ilSaveL information. - * il_stack.c (ilCloseImage): Added missing delete of Faces member. - * il_dds-save.c (ilCompressDXT): Added this function. - * il.h: Removed ilNVidiaCompressDXT and ilSquishCompressDXT - moved to il_internal.h. - * il_dds-save.c:151: Changed to Faces from Images. - * il_dds-save.c (CompressTo565): Added IL_ALPHA case. - * Updated DevIL Manual with new DXTC information. - -2009-01-30 Denton Woods - * Added DevIL.NET to projects folder. - * il_dds.c: Changed Image->Next code for cubemaps to read Image->Faces. Also changed Image->Next - code for mipmaps to read Image->Mipmaps, even further down the chain. - * il_dds.c (ilTexImageDxtc): Added call to ilCloseImage for Image->Faces. - * il_endian.h:113: Fixed bug #2545848 - inline GCC ASM changed. - * ilut_directx9.c (ilutD3D9CubeTexture): Changed ->Next to ->Faces. - * ilut_directx9.c (iD3D9CreateMipmaps): Changed ->Next to ->Mipmaps. - * il_states.c:605: Changed from ->Next to ->Mipmaps. - * il_states.c (iGetActiveNum): Rewrote to not use ->Next pointer for everything. - * il_vtf.c (VtfInitMipmaps): Changed to reflect the new mipmap arrangement as well. - * il_wal.c:141,142: Changed ->Next to ->Mipmaps. - * il_wal.c: Cleaned up the formatting a bit. - * il_stack.c (ilActiveMipmap): Changed ->Next to ->Mipmaps. - * il_stack.c (ilActiveImage/Mipmap/Face/Layer): Added another check for NULL, changed error. - Changed order of statements in for loop. This leads to much much less in the way of - ilSetError calls, since we do not have iCurImage == NULL. - * il_vtf.h:43: Changed to ILuint from ILint. - * il_vtf.c: Changed VtfInitMipmaps calls to VtfInitFacesMipmaps calls and changed iLoadVtfInternal - to support environment maps. - * il.h:384: Added IL_SPHEREMAP. - * il_hdr.c:467: Changed to char* to get OS X to stop issuing a warning. - * il_size.c:53: Changed return value to ILuint. - * devil_cpp_wrapper.hpp: Removed MSVC++ #pragma at the top for deprecated lib. - -2009-01-28 Denton Woods - * il_tpl.c: Added line 219. - -2009-01-27 Denton Woods - * il_bits.c (bseek): Changed check for return values of iseek. - * il_tpl.c: Added support for many more TPL data formats. - * il_tpl.c: Added support for color indexed data formats. - * il_tpl.c: Added support for multiple images in a file. - * il_sdl.c (ilutConvertToSDLSurface): Overhauled this code. - * ilut_opengl.c: Removed iGLSetMaxW/H/D and MaxTexW/H/D. - * ilut_states.h/ilut_states.c: Added MaxTexW/H/D to ILUT_STATES. - * ilut_states.c (ilutGetIntegerv): Added ILUT_MAXTEX_WIDTH/HEIGHT/DEPTH. - -2009-01-26 Denton Woods - * projects/win mobile: Added Windows Mobile projects. - * Removed .cvsignore files from SVN. - * il_bits.c:65: Commented out icloser call. - * include/IL/DevIL.i: Removed IL/ prefix on header filenames. - * include/IL/build-python and build-lua: Updated paths. - * projects folder: Renamed msvc to msvc9. - * il_tpl.c: Added for TPL support. - * il_io.c: Added function calls for TPL support. - * il_internal.h: Added declarations for TPL support. - -2009-01-25 Denton Woods - * ilut_internal.h:63-67: Redid definitions of IL_TEXT to coincide with il_internal.h. - * il_states.c: Updated _ilLoadExt/_ilSaveExt with all extensions. - * il_states.h: Updated with all extensions. - * All image formats with saving: Changed return values of ilSaveXxxF and ilSaveXxxL to be - an integer stating the number of bytes written. This is what ilSaveF/L have been - trying to return all along. - * il_pal.c:1075: Added error condition. - * lib/Makefile.am: Added il_size.c. - * simple.c: Added iluInit call. - * il_dds-save.c (GetAlphaBlock): Applied code from GetBlock, since it was still reading out of bounds. - * il_psd.c (ParseResources):808: Added check for ResourceSize being too small. - 834-837: Added check to insure that we are not copying from past the end of Resource. - * il_hdr.c:527-528: Changed order so that beg_run+run_count is tested first. - * il_psd.c:829: Subtracted an additional 4 for the Size obtained in the lines before. - * il_jp2.c:792-792: Added cleanup code if failure. 676-680: Added call to jas_init. - Added code throughout to prevent from having to initialize Jasper more than once. - * il_internal.h/il_internal.c: Added strdup for Windows CE. - * il_internal.h:105-107: Added so that we do not try to compile inline ASM with Windows Mobile. - -2009-01-24 Denton Woods - * il_internal.h,il_tiff.c: Changed ilSaveTiffL to void* instead of const void*. - * il_tiff.c: Added _tiffFileReadProcW. Changed _tiffFileSeekProc(W) to return the - result of itellw instead of tOff. This allows us to finally overload the TIFF - writing code. - * il_internal.h: Removed #pragma comments, which were commented out anyway. - * il_io.c (ilSaveL): Added call to ilDetermineSize. - * il_size.c: Added this file. - * il_manip.c:14: Removed #include . - * il_jpeg.c:53: Added check for IL_USE_IJL. - * il_exr.cpp:319,329: Changed to write functions instead of read. - * il_files.c: Added iSetOutputFake. - * il_files.c (iSetOutputLump): Added check for NULL to accommodate ilDetermineSize function. - * il_hdr.c:457: Changed from char* to ILbyte*. - * il_icns.h:24,30: Changed from ILbyte to char. - * il_size.c: Added #ifdefs for when user has declared IL_NO_XXX. Changed error to ENUM instead of PARAM. - * Updated MSVC8 projects with il_size.c. - * src-IL/src/Makefile.am: Added il_size.c. - * il_jp2.c: Added ilIsValidJp2* functions. - * il.h: Added ilDetermineType and ilDetermineTypeL to declarations. - * il_io.c: Changed ilDetermineTypeL to be exported. - * il_pcx.c: Formatting issues fixed. - * il_mdl.c: Added ilIsValidJp2* functions. - * il_io.c: Added JP2, MDL and XPM support to ilDetermineType and ilIsValid functions. - * il_icon.c/il_png.c: Renamed color_type to ico_color_type and png_color_type to avoid name conflicts. - * il_iff.c: Changed all malloc->ialloc and free->ifree. Added checks for ialloc failure. - * il_io.c (ilDetermineTypeL): Changed VTF check to return IL_VTF instead of the miscopied IL_SUN. - * il_size.c (ilDetermineSize): Now calls iTargaSize for Targa files. - * il_tga.c: Added iTargaSize. - -2009-01-22 Denton Woods - * ilut_internal.h:66: Changed to compile under Cygwin. - * ilut_opengl.c:108: Replaced _MSC_VER with _WIN32 and _WIN64. - * il_dds-save.c:343: Fixed bug #1067590 - Removed this line, which caused crashes. - * il_pic.c (iLoadPicInternal): Fixed ilTexImage call, moved it after channel information read. - * il_pic.c (readScanline):294-295: Added check for alpha channel. - * il_pic.c: Added ilSetError calls throughout. - * il_sgi.c (iLoadSgiInternal): Fixed bug #1060946 - Removed IL_LUMINANCE_ALPHA filetype. - * WindowsTest.cpp:52,53: Changed border size to accommodate Windows Vista/7. - * il_endian.h:20: Changed to give __BIG_ENDIAN__ a value of 1. The Google cached page of - http://74.125.47.132/search?q=cache:YfSl36C2pAQJ:patch-tracking.debian.net/patch/series/view/devil/1.7.2-1/00_endian_and_ILvoid_fixes.diff+devil+big+endian&hl=en&ct=clnk&cd=11&gl=us&lr=lang_en - has this patch (Nov. 24, 2008 cache). - * devil_internal_exports.h:34: Uncommented and commented line 30. - -2009-01-20 Matěj Týč - * test/format_test: Added a program and script as 'make check' target. - Those will test whether IL is capable of saving and loading images and whether the saved and - loaded image is similar to the original. - * configure.ac, lib/Makefile.am: Added support to IFF compilation. - * docs/DevIL_manual.texi: Added missing documentation about getting - image data + fixed some typos. - * include/IL/devil_cpp_wrapper.hpp: Fixed a typo that caused - compilation error - -2009-01-20 Denton Woods - * ilut_opengl.c (ilutGLScreen): Added glPixelStorei call. - * Added il_iff.c from GAIA. - * Added "x64 DLL Install.exe" to SVN. - * il_internal.h: Renamed ilIsValidJpg* functions to ilIsValidJpeg*. Added Iff functions. - * il_io.c: Added checks for Iff-loading. - * ilut_win32.c (ilutConvertSliceToHBitmap): Added better error handling. - * src-IL/src/Makefile.am: Added il_iff.c. - * ilu_rotate.c (iluRotate_): Changed ilResizeImage call. - * Added ilut_config.h. - * ilut.h: Added reference to ilut_config.h for Windows. - * il_files.c/il_icon.c/il_png.c/il_mng.c: Fixed typecasting warnings. - * il_jp2.c/il_wbmp.c (ilSaveJp2L/ilSaveWbmpL): Removed const qualifier. - -2009-01-19 Denton Woods - * il_hdr.c: Changed line 73 to have space for terminating NULL. - * src-IL/src/Makefile.am: Added il_vtf.c and *.cpp files. - * Fixed the MSVC++ 9 solutions pointing to the MSVC++ 8 project files. - * devil_cpp_wrapper.hpp: Updated to use ILconst_string instead of char*. - * il.h: Changed definition of IL_ALPHA to match OpenGL's GL_ALPHA. - * src-IL/include/Makefile.am: Added il_exr.h. - * il_dds.c/il.h: Readded DXT extension code. - * il_internal.h: Added declaration of ilFixCur. - -2009-01-16 Denton Woods - * Updated x64 projects - -2009-01-15 Matěj Týč - * il_io.h, include/IL/il.h, il_states.h: Changed some normal strings to constant - strings (in ilSave, ilIsValid and ilGetString) - * configure.ac, lib/Makefile.am: Added wbmp compilation support - * il_jp2.c, il_wbmp.c: Fixed a typo that prevented compilation - * include/IL/devil_cpp_wrapper.hpp: Added a hopefully harmless solution for - the initialization of DevIL. - -2009-01-15 Denton Woods - * il_manip.c / il.h: Added ilClampNTSC function. - * il_squish.cpp: Added file. - * il_dds-save.c: Added line 688. - * il_states.c: Added lines for libsquish support. - * il_dds-save.c (Compress): Added libsquish compression. - * il_io.c (ilDetermineTypeF/L and ilIsValid/F/L): Added VTF, SUN and EXR. - * il_io.c (ilIsValidF/L): Added TIF - * il_jp2.c:131-137: Added these lines to take care of erroneous error generated by JasPer's buffering. - * il_jp2.c: Added functions to save JPEG 2000 images. - * il_utility.c (ilGetBppFormat): Added IL_ALPHA. - * il_jp2.c (iLoadJp2Internal): Added 1 and 2 channel format loading. - * il_dds-save.c:700-701: Changed to IL_RGBA. - * il_dds-save.c (ChooseEndpoints): Changed to use norm squared instead of a sum of the components. - * il_dds-save.c (GetBlock): Changed to copy adjacent data if it goes beyond the bounds of the image. - * il_icon.c: Removed extra whitespace. - * il_icns.c / il_internal.h: Added ilIsValidIcns*. - * il_icns.h: Changed comments on ICNSDATA. - * il_exr.c: Added ilIsValidExr*. - * il_io.c (ilLoadF): Uncommented ilLoadJp2F. - * il_dds-save.c (CompressTo565): Changed 24-bit to 16-bit code based on Charles Bloom's rant. - * il_dds.c (DxtcReadColor/DxtcReadColors): Changed conversion to copy high bits to lowest bits as well. - * il_io.c: Reenabled PhotoCD support. - * il_pcd.c (iLoadPcdInternal): Added check for end-of-file. - * il_exr.c: Added EXR saving functions. - -2009-01-13 Denton Woods - * Converted source repository to SVN from CVS. - -2009-01-12 Denton Woods - * ilut_directx9.c: Cleared up formatting some. - -2009-01-11 Denton Woods - * MSVC9 Unicode projects: Updated to work better in 64-bit Windows. - * il_vtf.c: Removed commented lines 238-242. - * Created application to copy DLL files to the System32 directory. - -2009-01-10 Matěj Týč - * m4/devil-definitions.m4, m4/devil-reports.m4: Added a report saying - what libraries were linked with DevIL (should be helpful to packagers - who need to know DevIL dependencies) - * il_endian.h (iGwapUShort/iSwapUInt): Finished fixing bug #2023453 - (inline GCC asm, there was a typo left) - * src_IL/src/il_tiff.c (ilSaveTiff): Fixed a typo that was causing - conflicting declarations error - * configure.ac:264: Added IL_NO_WBMP since the Wbmp loading functions - that are referenced, but not implemented, caused linking errors - -2009-01-09 Denton Woods - * ilut_opengl.h: Moved ILGLCOMPRESSEDTEXIMAGE2DARBPROC typedef out of #ifdefs. - * ilut_opengl.c: Added ilutGLSetTex2D and ilutGLSetTex3D. Changed ilutGLSetTex to - just call ilutGLSetTex2D. Did the same thing for ilutGLSubTex. Added checks for - volume image extensions. Renamed MakeGLCompliant to MakeGLCompliant2D. Added - MakeGLCompliant3D. - * ilut_opengl.c (ilutGLScreen): Added check for ilTexImage failing. - * il_vtf.c (iLoadVtfInternal): Added BGRA4444 support. - * il_alloc.c / ilu_scale.c: Cleaned up formatting some. - * devil_internal_exports.h: Added Faces member to ILimage. - * il_devil.c (iCopySubImages): Added support for faces. - * il_register.c: Added ilRegisterNumFaces. - * il_convert.c (ilFixImage): Added support for faces. - * il_stack.c: Added ilActiveFace. - * ilut_directx9:63,779: Added ILboolean typecast. - * ilut_win32:102: Added ILboolean typecast. - * il_jpeg.c:987: Commented out pragma warning at the end. - * il_mng.c: Added #pragma warning at the top to get rid of redefinition warning when compiling. - * il_nvidia.cpp (ilNVidiaCompressDXT): Added check for Data being NULL. - * ilut_win32.c (ilutConvertSliceToHBitmap): Fixed bug #2496509 - added line 117 and - added DataSize member. - * il_hdr.c (iGetHdrHead): Fixed bug #2496518 - Added check for count. Changed - sscanf to use %2s format specifier to prevent buffer overruns in x and y. - * il_pnm.c (iGetWord): Fixed bug mentioned in #2496518 - igetc was moved back - into the while loop. Added a check for WordPos to prevent buffer overflow. - Restructured the while loop to work properly. - * il_convert.c (iConvertPalette): Changed references of iCurImage to Image. - * il_gif.c (GifGetData): Added DataPtr and changed line 636 to use Data instead of Image->Data. - * il_gif.c (iGetPalette / GetImages): Changed to better deal with local palettes. - -2009-01-08 Matěj Týč - * TODO: Added some tasks that I would like to undertake - * ChangeLog, NEWS: Copied old ChangeLog entries to NEWS file - * lib/Makefile.am: Added two new files to the list of IL sources - (il_sun.c, il_nvidia.cpp) - * examples/iller: Made empty files where the ILU frontend will be in - the future. - * configure.ac, m4/devil-reports.m4: Put the report stage of the - configure script to a separate m4 file. - -2009-01-08 Denton Woods - * opengl_example/gltest.c (main): Added iluInit/ilutInit calls. - * ilut_opengl.c (ilutGLFormat): Added IL_ALPHA support. - * il_bmp.c: Minor formatting issues fixed. - * il.h: Added IL_NVIDIA_COMPRESS #define. - * il_states.h: Added ilUseNVidiaDXT to IL_STATES. - * il_state.c: Added IL_NVIDIA_COMPRESS support. - * il_dds-save.c (Compress): Changed to use NVTT if needed. - * il_nvidia.cpp: Added ilNVidiaCompressDXTFile and Depth parameter to ilNVidiaCompressDXT. - -2009-01-06/07 Denton Woods - * Added il_sun.c (Sun Raster file support) - * ilut_opengl.c (ilutGLInit): Changed Linux ilGLCompressed2D pointer casting - to coincide with the old SVN version. - * il_tiff.c / il_alloc.c: Fixed a few pointer casts that were fixed in SVN. - * test/DDrawTest: Fixed extra whitespace in all files in this project. - * il_endian.h (iGwapUShort/iSwapUInt): Fixed bug #2023453 (inline GCC asm). - * ilut_win32.c (ilutConvertSliceToBitmap): Fixed bug #1775036 (definition of buff). - * il_psd.c (PsdGetData): Fixed bug #2219350 (16-bit luminance images not loading properly). - * il_manip.c: Cleared up some minor formatting issues. - * il_png.c (iSavePngInternal): Fixed bug #1680577 (some metadata not written correctly). - * il_nvidia.cpp (ilnVidiaCompressDXT1): Disabled mipmap generation and added code to - ilOutputHandler constructor to determine the proper size of the buffer. - * il.h: Added IL_DXT1A define for nVidia Texture Tools. - * il_nvidia.cpp: Added DXT1a, DXT3 and DXT5 support. Renamed ilnVidiaCompressDXT to - ilnVidiaCompressDXT and added the DxtType parameter. - * il_internal.c: Cleaned up extra whitespace toward end. - -2009-01-02 Matěj Týč - * src-{IL,ILU,ILUT}/src/*_internal.c: Hopefully resolved the - HAVE_CONFIG_H thing once for all :-) - * src-IL/src/il_exr.cpp: Undefined OPENEXR_DLL if we are not on - Windows (=> when HAVE_CONFIG_H is not defined) - * src-IL/src/il_io.c:765: Fixed a typo - * src-IL/src/il_vtf.c: Added min and max macros to the beginning - * docs/Devil_manual.texi: Corrected typos and missing @code and other - formatting stuff, corrected image names and incorrect usage of @xref - etc. that prevented compilation - * build setup (Makefile.am and configure.ac): Added support for - compilation of EXR and WDP formats + various other tweaks. - -Up to 2009-01-02 (since 1.7.5 release) Denton Woods - * Readded EXR code. - * Redefined clamping values in il.h. - * Added 64-bit integer types. - * Fixed bug in iRegisterLoad (https://sourceforge.net/forum/message.php?msg_id=5973761). - * Changed seek functions in il_files.c to return ILint. - * Added rpcsal.h and sal.h #includes to ilut.h for DX10. - * Added IL_MAX_QUANT_INDICES to use instead of IL_MAX_QUANT_INDEXS (misspelled). - * Added WBMP support (loading and saving). - * EXR files can now be loaded as file streams and lumps. - * Changed iNeuQuant to take number of colors in palette. - * Compiled MNG support back in. diff --git a/samples/DevIL/DevIL Website.url b/samples/DevIL/DevIL Website.url deleted file mode 100644 index e002d0636..000000000 --- a/samples/DevIL/DevIL Website.url +++ /dev/null @@ -1,5 +0,0 @@ -[InternetShortcut] -URL=http://openil.sf.net/ -IDList= -[{000214A0-0000-0000-C000-000000000046}] -Prop3=19,2 diff --git a/samples/DevIL/Libraries.txt b/samples/DevIL/Libraries.txt deleted file mode 100644 index 727652ade..000000000 --- a/samples/DevIL/Libraries.txt +++ /dev/null @@ -1,40 +0,0 @@ -Libraries needed to compile DevIL* : ----------------------------------- - -(Most of these are optional) - - -Libpng for .png (and some .ico) support available at http://www.libpng.org/pub/png/libpng.html -ZLib for .png (and some .ico) support available at http://www.gzip.org/zlib/ -Libjpeg for .jpg (and some .blp) support from http://www.ijg.org/ -Libtiff for .tif support from http://www.libtiff.org/ -Libmng for .mng and .jng support from http://www.libmng.com/ -JasPer for .jp2 (and some .icns) support available at http://www.ece.uvic.ca/~mdadams/jasper/ -HD Photo Device Porting Kit for .wdp/.hdp support from http://www.microsoft.com/Downloads/details.aspx?FamilyID=285eeffd-d86c-48c3-ab93-3abd5ee7f1ce&displaylang=en. -Little CMS for color profiles (ILU) from http://www.littlecms.com/ -Colour Picker lib for WindowsTest from http://www.fluidstudios.com/freeware.html -Freeglut (or glut) for GLTest from http://freeglut.sourceforge.net -glext.h from http://oss.sgi.com/projects/ogl-sample/ABI/glext.h (as if using OpenGL) -libsquish for DXT compression from http://code.google.com/p/libsquish/ -nVidia Texture Tools for DXT compression from http://developer.nvidia.com/object/nv_texture_tools.html. - -MSVC++ precompiled versions of libpng, zlib, libjpeg, libtiff, lcms and JasPer can be found -at http://openil.sourceforge.net/libs/LibCompiled-vc8.zip or -http://openil.sourceforge.net/libs/LibCompiled-vc9.zip. - -Sources of libpng, zlib, libjpeg, libmng, libungif, libtiff, lcms and JasPer can be -found at http://openil.sourceforge.net/libs/LibSrc.zip - -Intel Jpeg Library from - http://developer.intel.com/software/products/perflib/ijl/index.htm - - -MAC OS X -These library are not still uploaded! -To learn how to install these libraries, read README.macosx - -Source of external framework, downloaded from the previous sites -http://openil.sourceforge.net/libs/ExternFrameworksSrc.sitx - -Complete Compiled Library -http://openil.sourceforge.net/libs/OpenILBin.sitx \ No newline at end of file diff --git a/samples/DevIL/README b/samples/DevIL/README deleted file mode 100644 index a043a64ee..000000000 --- a/samples/DevIL/README +++ /dev/null @@ -1,176 +0,0 @@ -Developer's Image Library version 1.7.8 Readme, Notes and Quick Use -------------------------------------------------------------------- - - DevIL song: "la la la, a cross-platform image library utilizing a - simple syntax to load, save, convert, manipulate, filter and display - a variety of images with ease, la la la" - - -What is it? ------------ - -DevIL is an Open Source image library whose distribution is done under the -terms of the GNU LGPL license. See the COPYING file for more details. -DevIL offers you a simple way to implement loading, manipulating, filtering, -converting, displaying, saving from/to several different image formats in your -own project. - - -Where can I find it? --------------------- - -DevIL can be found at http://openil.sourceforge.net - - -How do I build and install the 3 libraries ? ------------------------------------------ - -*nix users should read README.unix -VisualC users should read README.win -Cygwin users should read README.cygwin -MacOSX users should read README.macosx - -PS: *nix stands for GNU/Linux, *BSD, SunOS/Solaris and perhaps some more. - - -More Extensive Documentation ----------------------------- - -This file is only a quick guide to point you to more detailed information on -how to use DevIL. More extensive documentation can currently be found on the -DevIL site at http://openil.sf.net and in the /Docs directory in a normal -install. - - -Why the hell another image library? ------------------------------------ - -I have never seen an image library that can do everything DevIL does. Sure, -various different libraries can do part of what DevIL can do as well or even -better, but I wanted a simple to use library that encompassed all of these -features. I also wanted an extremely portable image library that could be used -from a variety of languages and utilized the OpenGL syntax. - - -Basic Readme ------------- - -Most anything stated in this document applies to DevIL as well as DevILU and -DevILUT, unless otherwise stated. (This file is best viewed with word wrap on.) - - -Errors: -------- - -All errors generated inside DevIL, along with illegal parameters passed to -DevIL functions are caught and passed to ilSetError(), an internal library -function. The calling program can call ilGetError() to get the value of the -error generated. Error types are defined in il.h, using the 0x501 - 0x5FF -range. ilGetError() will return 0 (IL_NO_ERROR) if no error has occurred. - - -Basic Usage: ------- - -This demonstrates loading an image through DevIL for OpenGL. Don't forget to -call ilInit before you before you do anything: - -#include -#include -#include - -... - -ILuint devilError; - - -ilInit(); - -devilError = ilGetError(); - -if (devilError != IL_NO_ERROR) { - printf ("Devil Error (ilInit: %s\n", iluGetErrorString (devilError)); - exit (2); -} - -.... - -ILuint devilID; - - -ilGenImages(1, &devilID); -ilBindImage(devilID); -ilLoadImage("default1.tga"); // Loads into the current bound image -devilError = ilGetError(); - -if (devilError != IL_NO_ERROR) { - printf ("Devil Error (ilLoadImage: %s\n", iluGetErrorString (devilError)); - exit (2); -} - -.... - -ilutRenderer(IL_OPENGL); // Switch the renderer - -.... - -GLuint openglID, openglError; - - -openglID = ilutGLBindTexImage(); // This generates the texture for you -devilError = ilGetError(); - -if (devilError != IL_NO_ERROR) { - printf ("Error: %s\n", iluGetErrorString (devilError)); - exit (2); -} - -if (openglError != GL_NO_ERROR) { - printf ("Opengl Error (ilutGLBindTexImage): %s\n", gluGetErrorString (openglError)); - exit (2); -} - - - -// Make sure to close the image when you are done with it (though DevIL -// automatically deletes them when the program exits): - -glDeleteTextures(1, &openglID); -ilDeleteImages (1, &devilID); - - -More Examples: ---------- - -The TestIL project is included to test features of DevIL. - -DevIL includes a project called GLTest. This is a simple test of DevIL's -capabilities. All it does it load any image and displays it in a window -created by FreeGlut, which is available on http://freeglut.sourceforge.net. It -is also included to let the user have an idea of what the library can really -be used for. - -Several other test projects are included to test support with various display -APIs. The WindowsTest project is a basic image program that only runs in -Windows right now but showcases several of DevIL's features through various -menus. - -If you want more in-depth tutorials, you can find them on -http://openil.sf.net, or they may be in your installation under the /examples -directory. Documents are also available in the /docs directory. - - -Additional Reading ------------------- - -All image formats used in DevIL have corresponding documents on -http://www.wotsit.org, under the Graphics Files section. These documents -proved invaluable for the creation of this library when there was no library -already available for that image format. - - -Legalese --------- - -All contents of this file are intellectual property of Denton Woods, -copyright 2001-2008. diff --git a/samples/DevIL/README.win b/samples/DevIL/README.win deleted file mode 100644 index 57e3e90eb..000000000 --- a/samples/DevIL/README.win +++ /dev/null @@ -1,44 +0,0 @@ -Where do I find the project files ? ------------------------------------------ - -MSVC++ projects are in DevIL\projects\vc8 and DevIL\projects\vc9. -If compiling with Cygwin or MinGW, use the instructions in README.unix. - - -The IL_NO_XXX #define's: ------------------------- - -A user can recompile this library without complete image support in it. For -example, if your project does not use .jpg files, you can uncomment -#define IL_NO_JPG at the top of il/il.h, recompile the library, and no .jpg -support will be added, meaning quicker compiles and a smaller library. - - -The ILUT_USE_XXX #define's: ---------------------------- - -To disable support for a specific API, edit IL/ilut.h and comment the -corresponding #define. Per example, to disable OpenGL functions support, - add // in front of the line that reads: - -#define ILUT_USE_OPENGL - - -Libraries needed to compile DevIL* : ------------------------------------ - -Libraries.txt (included with the DevIL distribution) lists all libraries needed -to properly compile DevIL. - -Precompiled versions and sources of all libraries needed to compile DevIL are -available at http://openil.sourceforge.net/libs/LibCompiled.zip and -http://openil.sourceforge.net/libs/LibSrc.zip , respectively. - - -Installation: -------------- - -Just unzip and compile other libs included if needed. - -Please also refer to MSVC++.txt for further instructions if you are using -Microsoft Visual C++. diff --git a/samples/DevIL/include/IL/config.h b/samples/DevIL/include/IL/config.h deleted file mode 100644 index 933759038..000000000 --- a/samples/DevIL/include/IL/config.h +++ /dev/null @@ -1,140 +0,0 @@ -/* include/IL/config.h. Generated by configure. */ -/* include/IL/config.h.in. Generated from configure.in by autoheader. */ -#ifndef __CONFIG_H__ -#define __CONFIG_H__ - -#define IL_USE_PRAGMA_LIBS - -// Supported image formats (IL) - -// #define IL_NO_BLP -// #define IL_NO_BMP -// #define IL_NO_CUT -// #define IL_NO_CHEAD -// #define IL_NO_DCX -// #define IL_NO_DDS -// #define IL_NO_DICOM -// #define IL_NO_DOOM -// #define IL_NO_EXR -// #define IL_NO_FITS -// #define IL_NO_FTX -// #define IL_NO_GIF -// #define IL_NO_HDR -// #define IL_NO_ICO -// #define IL_NO_ICNS -// #define IL_NO_IWI -// #define IL_NO_JP2 -// #define IL_NO_JPG -// #define IL_NO_LCMS -// #define IL_NO_LIF -// #define IL_NO_MDL -// #define IL_NO_MNG -// #define IL_NO_PCD -// #define IL_NO_PCX -// #define IL_NO_PIC -// #define IL_NO_PIX -// #define IL_NO_PNG -// #define IL_NO_PNM -// #define IL_NO_PSD -// #define IL_NO_PSP -// #define IL_NO_PXR -// #define IL_NO_RAW -// #define IL_NO_ROT -// #define IL_NO_SGI -// #define IL_NO_SUN -// #define IL_NO_TGA -// #define IL_NO_TIF -// #define IL_NO_TPL -// #define IL_NO_WAL -// #define IL_NO_WDP -// #define IL_NO_XPM -#define IL_USE_JPEGLIB_UNMODIFIED 1 -//#define IL_USE_DXTC_NVIDIA -#define IL_USE_DXTC_SQUISH - -/* Supported api (ilut) */ - - -// -// sorry just -// can't get this one to work under windows -// have disabled for the now -// -// will look at it some more later -// -// Kriss -// -#undef ILUT_USE_ALLEGRO - -#undef ILUT_USE_DIRECTX8 -//#define ILUT_USE_DIRECTX9 -//#define ILUT_USE_DIRECTX10 -//#define ILUT_USE_OPENGL -//#define ILUT_USE_SDL -//#define ILUT_USE_WIN32 - - -/* Define to 1 if you have the header file. */ -//#define HAVE_DLFCN_H 1 - -/* Define to 1 if you have the header file. */ -//#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the header file. */ -//#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the header file. */ -//#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -//#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the header file. */ -//#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -//#define HAVE_STRING_H 1 - -/* Define to 1 if you have the header file. */ -//#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -//#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -//#define HAVE_UNISTD_H 1 - -/* Name of package */ -#define IL_PACKAGE "DevIL" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define IL_PACKAGE_NAME "" - -/* Define to the full name and version of this package. */ -#define IL_PACKAGE_STRING "" - -/* Define to the one symbol short name of this package. */ -#define IL_PACKAGE_TARNAME "" - -/* Define to the version of this package. */ -#define IL_PACKAGE_VERSION "" - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Version number of package */ -//#define IL_VERSION "1.7.3" - -/* Define to 1 if your processor stores words with the most significant byte - first (like Motorola and SPARC, unlike Intel and VAX). */ -/* #undef WORDS_BIGENDIAN */ - -/* If using Mac OS X uncomment this line */ -/* #include "macconfig.h" */ - -/* Define to 1 if the X Window System is missing or not being used. */ -/* #undef X_DISPLAY_MISSING */ -#endif /* __CONFIG_H__ */ diff --git a/samples/DevIL/include/IL/config.h.win b/samples/DevIL/include/IL/config.h.win deleted file mode 100644 index 0090b9b51..000000000 --- a/samples/DevIL/include/IL/config.h.win +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef __CONFIG_H__ -#define __CONFIG_H__ - -#define IL_USE_PRAGMA_LIBS // Links to only the libraries that are requested. -#define IL_INLINE_ASM 1 // Define if you can support at least some ASM - -// Supported images formats (IL) - -// #define IL_NO_BLP -// #define IL_NO_BMP -// #define IL_NO_CUT -// #define IL_NO_CHEAD -// #define IL_NO_DCX -// #define IL_NO_DDS -// #define IL_NO_DICOM -// #define IL_NO_DOOM -// #define IL_NO_EXR -// #define IL_NO_FITS -// #define IL_NO_FTX -// #define IL_NO_GIF -// #define IL_NO_HDR -// #define IL_NO_ICO -// #define IL_NO_ICNS -// #define IL_NO_IWI -// #define IL_NO_JP2 -// #define IL_NO_JPG -// #define IL_NO_LCMS -// #define IL_NO_LIF -// #define IL_NO_MDL -// #define IL_NO_MNG -// #define IL_NO_PCD -// #define IL_NO_PCX -// #define IL_NO_PIC -// #define IL_NO_PIX -// #define IL_NO_PNG -// #define IL_NO_PNM -// #define IL_NO_PSD -// #define IL_NO_PSP -// #define IL_NO_PXR -// #define IL_NO_RAW -// #define IL_NO_ROT -// #define IL_NO_SGI -// #define IL_NO_SUN -// #define IL_NO_TGA -// #define IL_NO_TIF -// #define IL_NO_TPL -// #define IL_NO_WAL -// #define IL_NO_WDP -// #define IL_NO_XPM - -#define IL_USE_JPEGLIB_UNMODIFIED 1 -#define IL_USE_DXTC_NVIDIA -#define IL_USE_DXTC_SQUISH - -//#define IL_NO_GAMES - -/* Supported api (ilut) */ - - -// -// sorry just -// can't get this one to work under windows -// have disabled for the now -// -// will look at it some more later -// -// Kriss -// -#undef ILUT_USE_ALLEGRO - -#undef ILUT_USE_DIRECTX8 -#define ILUT_USE_DIRECTX9 -#define ILUT_USE_DIRECTX10 -#define ILUT_USE_OPENGL -#define ILUT_USE_SDL -#define ILUT_USE_WIN32 - - -#endif /* __CONFIG_H__ */ diff --git a/samples/DevIL/include/IL/devil_internal_exports.h b/samples/DevIL/include/IL/devil_internal_exports.h deleted file mode 100644 index 30b7aaab4..000000000 --- a/samples/DevIL/include/IL/devil_internal_exports.h +++ /dev/null @@ -1,161 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 01/06/2009 -// -// Filename: IL/devil_internal_exports.h -// -// Description: Internal stuff for DevIL (IL, ILU and ILUT) -// -//----------------------------------------------------------------------------- - -#ifndef IL_EXPORTS_H -#define IL_EXPORTS_H - -#include "IL/il.h" - -#ifdef DEBUG - #include -#else - #define assert(x) -#endif - -//#ifndef NOINLINE -#ifndef INLINE -#if defined(__GNUC__) - #define INLINE extern inline -#elif defined(_MSC_VER) //@TODO: Get this working in MSVC++. - // http://www.greenend.org.uk/rjk/2003/03/inline.html - #define NOINLINE - //#define INLINE - /*#ifndef _WIN64 // Cannot use inline assembly in x64 target platform. - #define USE_WIN32_ASM - #endif//_WIN64*/ - #define INLINE __inline -#else - #define INLINE inline -#endif -#endif -//#else -//#define INLINE -//#endif //NOINLINE - -#ifdef __cplusplus -extern "C" { -#endif - -#define IL_MAX(a,b) (((a) > (b)) ? (a) : (b)) -#define IL_MIN(a,b) (((a) < (b)) ? (a) : (b)) - - -//! Basic Palette struct -typedef struct ILpal -{ - ILubyte* Palette; //!< the image palette (if any) - ILuint PalSize; //!< size of the palette (in bytes) - ILenum PalType; //!< the palette types in il.h (0x0500 range) -} ILpal; - - -//! The Fundamental Image structure -/*! Every bit of information about an image is stored in this internal structure.*/ -typedef struct ILimage -{ - ILuint Width; //!< the image's width - ILuint Height; //!< the image's height - ILuint Depth; //!< the image's depth - ILubyte Bpp; //!< bytes per pixel (now number of channels) - ILubyte Bpc; //!< bytes per channel - ILuint Bps; //!< bytes per scanline (components for IL) - ILubyte* Data; //!< the image data - ILuint SizeOfData; //!< the total size of the data (in bytes) - ILuint SizeOfPlane; //!< SizeOfData in a 2d image, size of each plane slice in a 3d image (in bytes) - ILenum Format; //!< image format (in IL enum style) - ILenum Type; //!< image type (in IL enum style) - ILenum Origin; //!< origin of the image - ILpal Pal; //!< palette details - ILuint Duration; //!< length of the time to display this "frame" - ILenum CubeFlags; //!< cube map flags for sides present in chain - struct ILimage* Mipmaps; //!< mipmapped versions of this image terminated by a NULL - usu. NULL - struct ILimage* Next; //!< next image in the chain - usu. NULL - struct ILimage* Faces; //!< next cubemap face in the chain - usu. NULL - struct ILimage* Layers; //!< subsequent layers in the chain - usu. NULL - ILuint* AnimList; //!< animation list - ILuint AnimSize; //!< animation list size - void* Profile; //!< colour profile - ILuint ProfileSize; //!< colour profile size - ILuint OffX; //!< x-offset of the image - ILuint OffY; //!< y-offset of the image - ILubyte* DxtcData; //!< compressed data - ILenum DxtcFormat; //!< compressed data format - ILuint DxtcSize; //!< compressed data size -} ILimage; - - -// Memory functions -ILAPI void* ILAPIENTRY ialloc(const ILsizei Size); -ILAPI void ILAPIENTRY ifree(const void *Ptr); -ILAPI void* ILAPIENTRY icalloc(const ILsizei Size, const ILsizei Num); -#ifdef ALTIVEC_GCC -ILAPI void* ILAPIENTRY ivec_align_buffer(void *buffer, const ILuint size); -#endif - -// Internal library functions in IL -ILAPI ILimage* ILAPIENTRY ilGetCurImage(void); -ILAPI void ILAPIENTRY ilSetCurImage(ILimage *Image); -ILAPI void ILAPIENTRY ilSetError(ILenum Error); -ILAPI void ILAPIENTRY ilSetPal(ILpal *Pal); - -// -// Utility functions -// -ILAPI ILubyte ILAPIENTRY ilGetBppFormat(ILenum Format); -ILAPI ILenum ILAPIENTRY ilGetFormatBpp(ILubyte Bpp); -ILAPI ILubyte ILAPIENTRY ilGetBpcType(ILenum Type); -ILAPI ILenum ILAPIENTRY ilGetTypeBpc(ILubyte Bpc); -ILAPI ILubyte ILAPIENTRY ilGetBppPal(ILenum PalType); -ILAPI ILenum ILAPIENTRY ilGetPalBaseType(ILenum PalType); -ILAPI ILuint ILAPIENTRY ilNextPower2(ILuint Num); -ILAPI ILenum ILAPIENTRY ilTypeFromExt(ILconst_string FileName); -ILAPI void ILAPIENTRY ilReplaceCurImage(ILimage *Image); -ILAPI void ILAPIENTRY iMemSwap(ILubyte *, ILubyte *, const ILuint); - -// -// Image functions -// -ILAPI void ILAPIENTRY iBindImageTemp (void); -ILAPI ILboolean ILAPIENTRY ilClearImage_ (ILimage *Image); -ILAPI void ILAPIENTRY ilCloseImage (ILimage *Image); -ILAPI void ILAPIENTRY ilClosePal (ILpal *Palette); -ILAPI ILpal* ILAPIENTRY iCopyPal (void); -ILAPI ILboolean ILAPIENTRY ilCopyImageAttr (ILimage *Dest, ILimage *Src); -ILAPI ILimage* ILAPIENTRY ilCopyImage_ (ILimage *Src); -ILAPI void ILAPIENTRY ilGetClear (void *Colours, ILenum Format, ILenum Type); -ILAPI ILuint ILAPIENTRY ilGetCurName (void); -ILAPI ILboolean ILAPIENTRY ilIsValidPal (ILpal *Palette); -ILAPI ILimage* ILAPIENTRY ilNewImage (ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp, ILubyte Bpc); -ILAPI ILimage* ILAPIENTRY ilNewImageFull (ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp, ILenum Format, ILenum Type, void *Data); -ILAPI ILboolean ILAPIENTRY ilInitImage (ILimage *Image, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp, ILenum Format, ILenum Type, void *Data); -ILAPI ILboolean ILAPIENTRY ilResizeImage (ILimage *Image, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp, ILubyte Bpc); -ILAPI ILboolean ILAPIENTRY ilTexImage_ (ILimage *Image, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp, ILenum Format, ILenum Type, void *Data); -ILAPI ILboolean ILAPIENTRY ilTexSubImage_ (ILimage *Image, void *Data); -ILAPI void* ILAPIENTRY ilConvertBuffer (ILuint SizeOfData, ILenum SrcFormat, ILenum DestFormat, ILenum SrcType, ILenum DestType, ILpal *SrcPal, void *Buffer); -ILAPI ILimage* ILAPIENTRY iConvertImage (ILimage *Image, ILenum DestFormat, ILenum DestType); -ILAPI ILpal* ILAPIENTRY iConvertPal (ILpal *Pal, ILenum DestFormat); -ILAPI ILubyte* ILAPIENTRY iGetFlipped (ILimage *Image); -ILAPI ILboolean ILAPIENTRY iMirror(); -ILAPI void ILAPIENTRY iFlipBuffer(ILubyte *buff, ILuint depth, ILuint line_size, ILuint line_num); -ILubyte* iFlipNewBuffer(ILubyte *buff, ILuint depth, ILuint line_size, ILuint line_num); -ILAPI void ILAPIENTRY iGetIntegervImage(ILimage *Image, ILenum Mode, ILint *Param); - -// Internal library functions in ILU -ILAPI ILimage* ILAPIENTRY iluRotate_(ILimage *Image, ILfloat Angle); -ILAPI ILimage* ILAPIENTRY iluRotate3D_(ILimage *Image, ILfloat x, ILfloat y, ILfloat z, ILfloat Angle); -ILAPI ILimage* ILAPIENTRY iluScale_(ILimage *Image, ILuint Width, ILuint Height, ILuint Depth); - -#ifdef __cplusplus -} -#endif - -#endif//IL_EXPORTS_H diff --git a/samples/DevIL/include/IL/il.h b/samples/DevIL/include/IL/il.h deleted file mode 100644 index 540a56eb3..000000000 --- a/samples/DevIL/include/IL/il.h +++ /dev/null @@ -1,644 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: IL/il.h -// -// Description: The main include file for DevIL -// -//----------------------------------------------------------------------------- - -// Doxygen comment -/*! \file il.h - The main include file for DevIL -*/ - -#ifndef __il_h_ -#ifndef __IL_H__ - -#define __il_h_ -#define __IL_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//this define controls if floats and doubles are clampled to [0..1] -//during conversion. It takes a little more time, but it is the correct -//way of doing this. If you are sure your floats are always valid, -//you can undefine this value... -#define CLAMP_HALF 1 -#define CLAMP_FLOATS 1 -#define CLAMP_DOUBLES 1 - -/*#ifdef _WIN32_WCE - #define IL_NO_EXR - #define IL_NO_GIF - #define IL_NO_JP2 - #define IL_NO_JPG - #define IL_NO_MNG - #define IL_NO_PNG - #define IL_NO_TIF - #define IL_NO_LCMS -#endif //_WIN32_WCE - -#ifdef DJGPP - #define IL_NO_EXR - #define IL_NO_GIF - #define IL_NO_JP2 - #define IL_NO_JPG - #define IL_NO_MNG - #define IL_NO_PNG - #define IL_NO_TIF - #define IL_NO_LCMS -#endif //DJGPP*/ - -#ifdef _WIN32 - #if (defined(IL_USE_PRAGMA_LIBS)) && (!defined(_IL_BUILD_LIBRARY)) - #if defined(_MSC_VER) || defined(__BORLANDC__) - #pragma comment(lib, "DevIL.lib") - #endif - #endif -#endif - -#ifdef RESTRICT_KEYWORD -#define RESTRICT restrict -#define CONST_RESTRICT const restrict -#else -#define RESTRICT -#define CONST_RESTRICT const -#endif - -#include - -typedef unsigned int ILenum; -typedef unsigned char ILboolean; -typedef unsigned int ILbitfield; -typedef signed char ILbyte; -typedef signed short ILshort; -typedef int ILint; -typedef size_t ILsizei; -typedef unsigned char ILubyte; -typedef unsigned short ILushort; -typedef unsigned int ILuint; -typedef float ILfloat; -typedef float ILclampf; -typedef double ILdouble; -typedef double ILclampd; - -#ifdef _MSC_VER -typedef __int64 ILint64; -typedef unsigned __int64 ILuint64; -#else -typedef long long int ILint64; -typedef long long unsigned int ILuint64; -#endif - - -#include -#ifdef _UNICODE - #ifndef _WIN32_WCE - #include - #endif - //if we use a define instead of a typedef, - //ILconst_string works as intended - #define ILchar wchar_t - #define ILstring wchar_t* - #define ILconst_string wchar_t const * -#else - //if we use a define instead of a typedef, - //ILconst_string works as intended - #define ILchar char - #define ILstring char* - #define ILconst_string char const * -#endif //_UNICODE - -#define IL_FALSE 0 -#define IL_TRUE 1 - -// Matches OpenGL's right now. -//! Data formats \link Formats Formats\endlink -#define IL_COLOUR_INDEX 0x1900 -#define IL_COLOR_INDEX 0x1900 -#define IL_ALPHA 0x1906 -#define IL_RGB 0x1907 -#define IL_RGBA 0x1908 -#define IL_BGR 0x80E0 -#define IL_BGRA 0x80E1 -#define IL_LUMINANCE 0x1909 -#define IL_LUMINANCE_ALPHA 0x190A - -//! Data types \link Types Types\endlink -#define IL_BYTE 0x1400 -#define IL_UNSIGNED_BYTE 0x1401 -#define IL_SHORT 0x1402 -#define IL_UNSIGNED_SHORT 0x1403 -#define IL_INT 0x1404 -#define IL_UNSIGNED_INT 0x1405 -#define IL_FLOAT 0x1406 -#define IL_DOUBLE 0x140A -#define IL_HALF 0x140B - - -#define IL_MAX_BYTE SCHAR_MAX -#define IL_MAX_UNSIGNED_BYTE UCHAR_MAX -#define IL_MAX_SHORT SHRT_MAX -#define IL_MAX_UNSIGNED_SHORT USHRT_MAX -#define IL_MAX_INT INT_MAX -#define IL_MAX_UNSIGNED_INT UINT_MAX - -#define IL_LIMIT(x,m,M) (xM?M:x)) -#define IL_CLAMP(x) IL_LIMIT(x,0,1) - -#define IL_VENDOR 0x1F00 -#define IL_LOAD_EXT 0x1F01 -#define IL_SAVE_EXT 0x1F02 - - -// -// IL-specific #define's -// - -#define IL_VERSION_1_7_8 1 -#define IL_VERSION 178 - - -// Attribute Bits -#define IL_ORIGIN_BIT 0x00000001 -#define IL_FILE_BIT 0x00000002 -#define IL_PAL_BIT 0x00000004 -#define IL_FORMAT_BIT 0x00000008 -#define IL_TYPE_BIT 0x00000010 -#define IL_COMPRESS_BIT 0x00000020 -#define IL_LOADFAIL_BIT 0x00000040 -#define IL_FORMAT_SPECIFIC_BIT 0x00000080 -#define IL_ALL_ATTRIB_BITS 0x000FFFFF - - -// Palette types -#define IL_PAL_NONE 0x0400 -#define IL_PAL_RGB24 0x0401 -#define IL_PAL_RGB32 0x0402 -#define IL_PAL_RGBA32 0x0403 -#define IL_PAL_BGR24 0x0404 -#define IL_PAL_BGR32 0x0405 -#define IL_PAL_BGRA32 0x0406 - - -// Image types -#define IL_TYPE_UNKNOWN 0x0000 -#define IL_BMP 0x0420 //!< Microsoft Windows Bitmap - .bmp extension -#define IL_CUT 0x0421 //!< Dr. Halo - .cut extension -#define IL_DOOM 0x0422 //!< DooM walls - no specific extension -#define IL_DOOM_FLAT 0x0423 //!< DooM flats - no specific extension -#define IL_ICO 0x0424 //!< Microsoft Windows Icons and Cursors - .ico and .cur extensions -#define IL_JPG 0x0425 //!< JPEG - .jpg, .jpe and .jpeg extensions -#define IL_JFIF 0x0425 //!< -#define IL_ILBM 0x0426 //!< Amiga IFF (FORM ILBM) - .iff, .ilbm, .lbm extensions -#define IL_PCD 0x0427 //!< Kodak PhotoCD - .pcd extension -#define IL_PCX 0x0428 //!< ZSoft PCX - .pcx extension -#define IL_PIC 0x0429 //!< PIC - .pic extension -#define IL_PNG 0x042A //!< Portable Network Graphics - .png extension -#define IL_PNM 0x042B //!< Portable Any Map - .pbm, .pgm, .ppm and .pnm extensions -#define IL_SGI 0x042C //!< Silicon Graphics - .sgi, .bw, .rgb and .rgba extensions -#define IL_TGA 0x042D //!< TrueVision Targa File - .tga, .vda, .icb and .vst extensions -#define IL_TIF 0x042E //!< Tagged Image File Format - .tif and .tiff extensions -#define IL_CHEAD 0x042F //!< C-Style Header - .h extension -#define IL_RAW 0x0430 //!< Raw Image Data - any extension -#define IL_MDL 0x0431 //!< Half-Life Model Texture - .mdl extension -#define IL_WAL 0x0432 //!< Quake 2 Texture - .wal extension -#define IL_LIF 0x0434 //!< Homeworld Texture - .lif extension -#define IL_MNG 0x0435 //!< Multiple-image Network Graphics - .mng extension -#define IL_JNG 0x0435 //!< -#define IL_GIF 0x0436 //!< Graphics Interchange Format - .gif extension -#define IL_DDS 0x0437 //!< DirectDraw Surface - .dds extension -#define IL_DCX 0x0438 //!< ZSoft Multi-PCX - .dcx extension -#define IL_PSD 0x0439 //!< Adobe PhotoShop - .psd extension -#define IL_EXIF 0x043A //!< -#define IL_PSP 0x043B //!< PaintShop Pro - .psp extension -#define IL_PIX 0x043C //!< PIX - .pix extension -#define IL_PXR 0x043D //!< Pixar - .pxr extension -#define IL_XPM 0x043E //!< X Pixel Map - .xpm extension -#define IL_HDR 0x043F //!< Radiance High Dynamic Range - .hdr extension -#define IL_ICNS 0x0440 //!< Macintosh Icon - .icns extension -#define IL_JP2 0x0441 //!< Jpeg 2000 - .jp2 extension -#define IL_EXR 0x0442 //!< OpenEXR - .exr extension -#define IL_WDP 0x0443 //!< Microsoft HD Photo - .wdp and .hdp extension -#define IL_VTF 0x0444 //!< Valve Texture Format - .vtf extension -#define IL_WBMP 0x0445 //!< Wireless Bitmap - .wbmp extension -#define IL_SUN 0x0446 //!< Sun Raster - .sun, .ras, .rs, .im1, .im8, .im24 and .im32 extensions -#define IL_IFF 0x0447 //!< Interchange File Format - .iff extension -#define IL_TPL 0x0448 //!< Gamecube Texture - .tpl extension -#define IL_FITS 0x0449 //!< Flexible Image Transport System - .fit and .fits extensions -#define IL_DICOM 0x044A //!< Digital Imaging and Communications in Medicine (DICOM) - .dcm and .dicom extensions -#define IL_IWI 0x044B //!< Call of Duty Infinity Ward Image - .iwi extension -#define IL_BLP 0x044C //!< Blizzard Texture Format - .blp extension -#define IL_FTX 0x044D //!< Heavy Metal: FAKK2 Texture - .ftx extension -#define IL_ROT 0x044E //!< Homeworld 2 - Relic Texture - .rot extension -#define IL_TEXTURE 0x044F //!< Medieval II: Total War Texture - .texture extension -#define IL_DPX 0x0450 //!< Digital Picture Exchange - .dpx extension -#define IL_UTX 0x0451 //!< Unreal (and Unreal Tournament) Texture - .utx extension -#define IL_MP3 0x0452 //!< MPEG-1 Audio Layer 3 - .mp3 extension - - -#define IL_JASC_PAL 0x0475 //!< PaintShop Pro Palette - - -// Error Types -#define IL_NO_ERROR 0x0000 -#define IL_INVALID_ENUM 0x0501 -#define IL_OUT_OF_MEMORY 0x0502 -#define IL_FORMAT_NOT_SUPPORTED 0x0503 -#define IL_INTERNAL_ERROR 0x0504 -#define IL_INVALID_VALUE 0x0505 -#define IL_ILLEGAL_OPERATION 0x0506 -#define IL_ILLEGAL_FILE_VALUE 0x0507 -#define IL_INVALID_FILE_HEADER 0x0508 -#define IL_INVALID_PARAM 0x0509 -#define IL_COULD_NOT_OPEN_FILE 0x050A -#define IL_INVALID_EXTENSION 0x050B -#define IL_FILE_ALREADY_EXISTS 0x050C -#define IL_OUT_FORMAT_SAME 0x050D -#define IL_STACK_OVERFLOW 0x050E -#define IL_STACK_UNDERFLOW 0x050F -#define IL_INVALID_CONVERSION 0x0510 -#define IL_BAD_DIMENSIONS 0x0511 -#define IL_FILE_READ_ERROR 0x0512 // 05/12/2002: Addition by Sam. -#define IL_FILE_WRITE_ERROR 0x0512 - -#define IL_LIB_GIF_ERROR 0x05E1 -#define IL_LIB_JPEG_ERROR 0x05E2 -#define IL_LIB_PNG_ERROR 0x05E3 -#define IL_LIB_TIFF_ERROR 0x05E4 -#define IL_LIB_MNG_ERROR 0x05E5 -#define IL_LIB_JP2_ERROR 0x05E6 -#define IL_LIB_EXR_ERROR 0x05E7 -#define IL_UNKNOWN_ERROR 0x05FF - - -// Origin Definitions -#define IL_ORIGIN_SET 0x0600 -#define IL_ORIGIN_LOWER_LEFT 0x0601 -#define IL_ORIGIN_UPPER_LEFT 0x0602 -#define IL_ORIGIN_MODE 0x0603 - - -// Format and Type Mode Definitions -#define IL_FORMAT_SET 0x0610 -#define IL_FORMAT_MODE 0x0611 -#define IL_TYPE_SET 0x0612 -#define IL_TYPE_MODE 0x0613 - - -// File definitions -#define IL_FILE_OVERWRITE 0x0620 -#define IL_FILE_MODE 0x0621 - - -// Palette definitions -#define IL_CONV_PAL 0x0630 - - -// Load fail definitions -#define IL_DEFAULT_ON_FAIL 0x0632 - - -// Key colour and alpha definitions -#define IL_USE_KEY_COLOUR 0x0635 -#define IL_USE_KEY_COLOR 0x0635 -#define IL_BLIT_BLEND 0x0636 - - -// Interlace definitions -#define IL_SAVE_INTERLACED 0x0639 -#define IL_INTERLACE_MODE 0x063A - - -// Quantization definitions -#define IL_QUANTIZATION_MODE 0x0640 -#define IL_WU_QUANT 0x0641 -#define IL_NEU_QUANT 0x0642 -#define IL_NEU_QUANT_SAMPLE 0x0643 -#define IL_MAX_QUANT_INDEXS 0x0644 //XIX : ILint : Maximum number of colors to reduce to, default of 256. and has a range of 2-256 -#define IL_MAX_QUANT_INDICES 0x0644 // Redefined, since the above #define is misspelled - - -// Hints -#define IL_FASTEST 0x0660 -#define IL_LESS_MEM 0x0661 -#define IL_DONT_CARE 0x0662 -#define IL_MEM_SPEED_HINT 0x0665 -#define IL_USE_COMPRESSION 0x0666 -#define IL_NO_COMPRESSION 0x0667 -#define IL_COMPRESSION_HINT 0x0668 - - -// Compression -#define IL_NVIDIA_COMPRESS 0x0670 -#define IL_SQUISH_COMPRESS 0x0671 - - -// Subimage types -#define IL_SUB_NEXT 0x0680 -#define IL_SUB_MIPMAP 0x0681 -#define IL_SUB_LAYER 0x0682 - - -// Compression definitions -#define IL_COMPRESS_MODE 0x0700 -#define IL_COMPRESS_NONE 0x0701 -#define IL_COMPRESS_RLE 0x0702 -#define IL_COMPRESS_LZO 0x0703 -#define IL_COMPRESS_ZLIB 0x0704 - - -// File format-specific values -#define IL_TGA_CREATE_STAMP 0x0710 -#define IL_JPG_QUALITY 0x0711 -#define IL_PNG_INTERLACE 0x0712 -#define IL_TGA_RLE 0x0713 -#define IL_BMP_RLE 0x0714 -#define IL_SGI_RLE 0x0715 -#define IL_TGA_ID_STRING 0x0717 -#define IL_TGA_AUTHNAME_STRING 0x0718 -#define IL_TGA_AUTHCOMMENT_STRING 0x0719 -#define IL_PNG_AUTHNAME_STRING 0x071A -#define IL_PNG_TITLE_STRING 0x071B -#define IL_PNG_DESCRIPTION_STRING 0x071C -#define IL_TIF_DESCRIPTION_STRING 0x071D -#define IL_TIF_HOSTCOMPUTER_STRING 0x071E -#define IL_TIF_DOCUMENTNAME_STRING 0x071F -#define IL_TIF_AUTHNAME_STRING 0x0720 -#define IL_JPG_SAVE_FORMAT 0x0721 -#define IL_CHEAD_HEADER_STRING 0x0722 -#define IL_PCD_PICNUM 0x0723 -#define IL_PNG_ALPHA_INDEX 0x0724 //XIX : ILint : the color in the palette at this index value (0-255) is considered transparent, -1 for no trasparent color -#define IL_JPG_PROGRESSIVE 0x0725 -#define IL_VTF_COMP 0x0726 - - -// DXTC definitions -#define IL_DXTC_FORMAT 0x0705 -#define IL_DXT1 0x0706 -#define IL_DXT2 0x0707 -#define IL_DXT3 0x0708 -#define IL_DXT4 0x0709 -#define IL_DXT5 0x070A -#define IL_DXT_NO_COMP 0x070B -#define IL_KEEP_DXTC_DATA 0x070C -#define IL_DXTC_DATA_FORMAT 0x070D -#define IL_3DC 0x070E -#define IL_RXGB 0x070F -#define IL_ATI1N 0x0710 -#define IL_DXT1A 0x0711 // Normally the same as IL_DXT1, except for nVidia Texture Tools. - -// Environment map definitions -#define IL_CUBEMAP_POSITIVEX 0x00000400 -#define IL_CUBEMAP_NEGATIVEX 0x00000800 -#define IL_CUBEMAP_POSITIVEY 0x00001000 -#define IL_CUBEMAP_NEGATIVEY 0x00002000 -#define IL_CUBEMAP_POSITIVEZ 0x00004000 -#define IL_CUBEMAP_NEGATIVEZ 0x00008000 -#define IL_SPHEREMAP 0x00010000 - - -// Values -#define IL_VERSION_NUM 0x0DE2 -#define IL_IMAGE_WIDTH 0x0DE4 -#define IL_IMAGE_HEIGHT 0x0DE5 -#define IL_IMAGE_DEPTH 0x0DE6 -#define IL_IMAGE_SIZE_OF_DATA 0x0DE7 -#define IL_IMAGE_BPP 0x0DE8 -#define IL_IMAGE_BYTES_PER_PIXEL 0x0DE8 -#define IL_IMAGE_BPP 0x0DE8 -#define IL_IMAGE_BITS_PER_PIXEL 0x0DE9 -#define IL_IMAGE_FORMAT 0x0DEA -#define IL_IMAGE_TYPE 0x0DEB -#define IL_PALETTE_TYPE 0x0DEC -#define IL_PALETTE_SIZE 0x0DED -#define IL_PALETTE_BPP 0x0DEE -#define IL_PALETTE_NUM_COLS 0x0DEF -#define IL_PALETTE_BASE_TYPE 0x0DF0 -#define IL_NUM_FACES 0x0DE1 -#define IL_NUM_IMAGES 0x0DF1 -#define IL_NUM_MIPMAPS 0x0DF2 -#define IL_NUM_LAYERS 0x0DF3 -#define IL_ACTIVE_IMAGE 0x0DF4 -#define IL_ACTIVE_MIPMAP 0x0DF5 -#define IL_ACTIVE_LAYER 0x0DF6 -#define IL_ACTIVE_FACE 0x0E00 -#define IL_CUR_IMAGE 0x0DF7 -#define IL_IMAGE_DURATION 0x0DF8 -#define IL_IMAGE_PLANESIZE 0x0DF9 -#define IL_IMAGE_BPC 0x0DFA -#define IL_IMAGE_OFFX 0x0DFB -#define IL_IMAGE_OFFY 0x0DFC -#define IL_IMAGE_CUBEFLAGS 0x0DFD -#define IL_IMAGE_ORIGIN 0x0DFE -#define IL_IMAGE_CHANNELS 0x0DFF - -# if defined __GNUC__ && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 0)) -// __attribute__((deprecated)) is supported by GCC 3.1 and later. -# define DEPRECATED(D) D __attribute__((deprecated)) -# elif defined _MSC_VER && _MSC_VER >= 1300 -// __declspec(deprecated) is supported by MSVC 7.0 and later. -# define DEPRECATED(D) __declspec(deprecated) D -# else -# define DEPRECATED (D) D -# endif - -// -// Section shamelessly modified from the glut header. -// - -// This is from Win32's -#if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) || defined(__BORLANDC__) || defined(__LCC__) - #define ILAPIENTRY __stdcall - #define IL_PACKSTRUCT -//#elif defined(linux) || defined(MACOSX) || defined(__CYGWIN__) //fix bug 840364 -#elif defined( __GNUC__ ) - // this should work for any of the above commented platforms - // plus any platform using GCC - #ifdef __MINGW32__ - #define ILAPIENTRY __stdcall - #else - #define ILAPIENTRY - #endif - #define IL_PACKSTRUCT __attribute__ ((packed)) -#else - #define ILAPIENTRY - #define IL_PACKSTRUCT -#endif - -// This is from Win32's and -#if defined(__LCC__) - #define ILAPI __stdcall -#elif defined(_WIN32) //changed 20031221 to fix bug 840421 - #ifdef IL_STATIC_LIB - #define ILAPI - #else - #ifdef _IL_BUILD_LIBRARY - #define ILAPI __declspec(dllexport) - #else - #define ILAPI __declspec(dllimport) - #endif - #endif -#elif __APPLE__ - #define ILAPI extern -#else - #define ILAPI -#endif - - -#define IL_SEEK_SET 0 -#define IL_SEEK_CUR 1 -#define IL_SEEK_END 2 -#define IL_EOF -1 - - -// Callback functions for file reading -typedef void* ILHANDLE; -typedef void (ILAPIENTRY *fCloseRProc)(ILHANDLE); -typedef ILboolean (ILAPIENTRY *fEofProc) (ILHANDLE); -typedef ILint (ILAPIENTRY *fGetcProc) (ILHANDLE); -typedef ILHANDLE (ILAPIENTRY *fOpenRProc) (ILconst_string); -typedef ILint (ILAPIENTRY *fReadProc) (void*, ILuint, ILuint, ILHANDLE); -typedef ILint (ILAPIENTRY *fSeekRProc) (ILHANDLE, ILint, ILint); -typedef ILint (ILAPIENTRY *fTellRProc) (ILHANDLE); - -// Callback functions for file writing -typedef void (ILAPIENTRY *fCloseWProc)(ILHANDLE); -typedef ILHANDLE (ILAPIENTRY *fOpenWProc) (ILconst_string); -typedef ILint (ILAPIENTRY *fPutcProc) (ILubyte, ILHANDLE); -typedef ILint (ILAPIENTRY *fSeekWProc) (ILHANDLE, ILint, ILint); -typedef ILint (ILAPIENTRY *fTellWProc) (ILHANDLE); -typedef ILint (ILAPIENTRY *fWriteProc) (const void*, ILuint, ILuint, ILHANDLE); - -// Callback functions for allocation and deallocation -typedef void* (ILAPIENTRY *mAlloc)(const ILsizei); -typedef void (ILAPIENTRY *mFree) (const void* CONST_RESTRICT); - -// Registered format procedures -typedef ILenum (ILAPIENTRY *IL_LOADPROC)(ILconst_string); -typedef ILenum (ILAPIENTRY *IL_SAVEPROC)(ILconst_string); - - -// ImageLib Functions -ILAPI ILboolean ILAPIENTRY ilActiveFace(ILuint Number); -ILAPI ILboolean ILAPIENTRY ilActiveImage(ILuint Number); -ILAPI ILboolean ILAPIENTRY ilActiveLayer(ILuint Number); -ILAPI ILboolean ILAPIENTRY ilActiveMipmap(ILuint Number); -ILAPI ILboolean ILAPIENTRY ilApplyPal(ILconst_string FileName); -ILAPI ILboolean ILAPIENTRY ilApplyProfile(ILstring InProfile, ILstring OutProfile); -ILAPI void ILAPIENTRY ilBindImage(ILuint Image); -ILAPI ILboolean ILAPIENTRY ilBlit(ILuint Source, ILint DestX, ILint DestY, ILint DestZ, ILuint SrcX, ILuint SrcY, ILuint SrcZ, ILuint Width, ILuint Height, ILuint Depth); -ILAPI ILboolean ILAPIENTRY ilClampNTSC(void); -ILAPI void ILAPIENTRY ilClearColour(ILclampf Red, ILclampf Green, ILclampf Blue, ILclampf Alpha); -ILAPI ILboolean ILAPIENTRY ilClearImage(void); -ILAPI ILuint ILAPIENTRY ilCloneCurImage(void); -ILAPI ILubyte* ILAPIENTRY ilCompressDXT(ILubyte *Data, ILuint Width, ILuint Height, ILuint Depth, ILenum DXTCFormat, ILuint *DXTCSize); -ILAPI ILboolean ILAPIENTRY ilCompressFunc(ILenum Mode); -ILAPI ILboolean ILAPIENTRY ilConvertImage(ILenum DestFormat, ILenum DestType); -ILAPI ILboolean ILAPIENTRY ilConvertPal(ILenum DestFormat); -ILAPI ILboolean ILAPIENTRY ilCopyImage(ILuint Src); -ILAPI ILuint ILAPIENTRY ilCopyPixels(ILuint XOff, ILuint YOff, ILuint ZOff, ILuint Width, ILuint Height, ILuint Depth, ILenum Format, ILenum Type, void *Data); -ILAPI ILuint ILAPIENTRY ilCreateSubImage(ILenum Type, ILuint Num); -ILAPI ILboolean ILAPIENTRY ilDefaultImage(void); -ILAPI void ILAPIENTRY ilDeleteImage(const ILuint Num); -ILAPI void ILAPIENTRY ilDeleteImages(ILsizei Num, const ILuint *Images); -ILAPI ILenum ILAPIENTRY ilDetermineType(ILconst_string FileName); -ILAPI ILenum ILAPIENTRY ilDetermineTypeF(ILHANDLE File); -ILAPI ILenum ILAPIENTRY ilDetermineTypeL(const void *Lump, ILuint Size); -ILAPI ILboolean ILAPIENTRY ilDisable(ILenum Mode); -ILAPI ILboolean ILAPIENTRY ilDxtcDataToImage(void); -ILAPI ILboolean ILAPIENTRY ilDxtcDataToSurface(void); -ILAPI ILboolean ILAPIENTRY ilEnable(ILenum Mode); -ILAPI void ILAPIENTRY ilFlipSurfaceDxtcData(void); -ILAPI ILboolean ILAPIENTRY ilFormatFunc(ILenum Mode); -ILAPI void ILAPIENTRY ilGenImages(ILsizei Num, ILuint *Images); -ILAPI ILuint ILAPIENTRY ilGenImage(void); -ILAPI ILubyte* ILAPIENTRY ilGetAlpha(ILenum Type); -ILAPI ILboolean ILAPIENTRY ilGetBoolean(ILenum Mode); -ILAPI void ILAPIENTRY ilGetBooleanv(ILenum Mode, ILboolean *Param); -ILAPI ILubyte* ILAPIENTRY ilGetData(void); -ILAPI ILuint ILAPIENTRY ilGetDXTCData(void *Buffer, ILuint BufferSize, ILenum DXTCFormat); -ILAPI ILenum ILAPIENTRY ilGetError(void); -ILAPI ILint ILAPIENTRY ilGetInteger(ILenum Mode); -ILAPI void ILAPIENTRY ilGetIntegerv(ILenum Mode, ILint *Param); -ILAPI ILuint ILAPIENTRY ilGetLumpPos(void); -ILAPI ILubyte* ILAPIENTRY ilGetPalette(void); -ILAPI ILconst_string ILAPIENTRY ilGetString(ILenum StringName); -ILAPI void ILAPIENTRY ilHint(ILenum Target, ILenum Mode); -ILAPI ILboolean ILAPIENTRY ilInvertSurfaceDxtcDataAlpha(void); -ILAPI void ILAPIENTRY ilInit(void); -ILAPI ILboolean ILAPIENTRY ilImageToDxtcData(ILenum Format); -ILAPI ILboolean ILAPIENTRY ilIsDisabled(ILenum Mode); -ILAPI ILboolean ILAPIENTRY ilIsEnabled(ILenum Mode); -ILAPI ILboolean ILAPIENTRY ilIsImage(ILuint Image); -ILAPI ILboolean ILAPIENTRY ilIsValid(ILenum Type, ILconst_string FileName); -ILAPI ILboolean ILAPIENTRY ilIsValidF(ILenum Type, ILHANDLE File); -ILAPI ILboolean ILAPIENTRY ilIsValidL(ILenum Type, void *Lump, ILuint Size); -ILAPI void ILAPIENTRY ilKeyColour(ILclampf Red, ILclampf Green, ILclampf Blue, ILclampf Alpha); -ILAPI ILboolean ILAPIENTRY ilLoad(ILenum Type, ILconst_string FileName); -ILAPI ILboolean ILAPIENTRY ilLoadF(ILenum Type, ILHANDLE File); -ILAPI ILboolean ILAPIENTRY ilLoadImage(ILconst_string FileName); -ILAPI ILboolean ILAPIENTRY ilLoadL(ILenum Type, const void *Lump, ILuint Size); -ILAPI ILboolean ILAPIENTRY ilLoadPal(ILconst_string FileName); -ILAPI void ILAPIENTRY ilModAlpha(ILdouble AlphaValue); -ILAPI ILboolean ILAPIENTRY ilOriginFunc(ILenum Mode); -ILAPI ILboolean ILAPIENTRY ilOverlayImage(ILuint Source, ILint XCoord, ILint YCoord, ILint ZCoord); -ILAPI void ILAPIENTRY ilPopAttrib(void); -ILAPI void ILAPIENTRY ilPushAttrib(ILuint Bits); -ILAPI void ILAPIENTRY ilRegisterFormat(ILenum Format); -ILAPI ILboolean ILAPIENTRY ilRegisterLoad(ILconst_string Ext, IL_LOADPROC Load); -ILAPI ILboolean ILAPIENTRY ilRegisterMipNum(ILuint Num); -ILAPI ILboolean ILAPIENTRY ilRegisterNumFaces(ILuint Num); -ILAPI ILboolean ILAPIENTRY ilRegisterNumImages(ILuint Num); -ILAPI void ILAPIENTRY ilRegisterOrigin(ILenum Origin); -ILAPI void ILAPIENTRY ilRegisterPal(void *Pal, ILuint Size, ILenum Type); -ILAPI ILboolean ILAPIENTRY ilRegisterSave(ILconst_string Ext, IL_SAVEPROC Save); -ILAPI void ILAPIENTRY ilRegisterType(ILenum Type); -ILAPI ILboolean ILAPIENTRY ilRemoveLoad(ILconst_string Ext); -ILAPI ILboolean ILAPIENTRY ilRemoveSave(ILconst_string Ext); -ILAPI void ILAPIENTRY ilResetMemory(void); // Deprecated -ILAPI void ILAPIENTRY ilResetRead(void); -ILAPI void ILAPIENTRY ilResetWrite(void); -ILAPI ILboolean ILAPIENTRY ilSave(ILenum Type, ILconst_string FileName); -ILAPI ILuint ILAPIENTRY ilSaveF(ILenum Type, ILHANDLE File); -ILAPI ILboolean ILAPIENTRY ilSaveImage(ILconst_string FileName); -ILAPI ILuint ILAPIENTRY ilSaveL(ILenum Type, void *Lump, ILuint Size); -ILAPI ILboolean ILAPIENTRY ilSavePal(ILconst_string FileName); -ILAPI ILboolean ILAPIENTRY ilSetAlpha(ILdouble AlphaValue); -ILAPI ILboolean ILAPIENTRY ilSetData(void *Data); -ILAPI ILboolean ILAPIENTRY ilSetDuration(ILuint Duration); -ILAPI void ILAPIENTRY ilSetInteger(ILenum Mode, ILint Param); -ILAPI void ILAPIENTRY ilSetMemory(mAlloc, mFree); -ILAPI void ILAPIENTRY ilSetPixels(ILint XOff, ILint YOff, ILint ZOff, ILuint Width, ILuint Height, ILuint Depth, ILenum Format, ILenum Type, void *Data); -ILAPI void ILAPIENTRY ilSetRead(fOpenRProc, fCloseRProc, fEofProc, fGetcProc, fReadProc, fSeekRProc, fTellRProc); -ILAPI void ILAPIENTRY ilSetString(ILenum Mode, const char *String); -ILAPI void ILAPIENTRY ilSetWrite(fOpenWProc, fCloseWProc, fPutcProc, fSeekWProc, fTellWProc, fWriteProc); -ILAPI void ILAPIENTRY ilShutDown(void); -ILAPI ILboolean ILAPIENTRY ilSurfaceToDxtcData(ILenum Format); -ILAPI ILboolean ILAPIENTRY ilTexImage(ILuint Width, ILuint Height, ILuint Depth, ILubyte NumChannels, ILenum Format, ILenum Type, void *Data); -ILAPI ILboolean ILAPIENTRY ilTexImageDxtc(ILint w, ILint h, ILint d, ILenum DxtFormat, const ILubyte* data); -ILAPI ILenum ILAPIENTRY ilTypeFromExt(ILconst_string FileName); -ILAPI ILboolean ILAPIENTRY ilTypeFunc(ILenum Mode); -ILAPI ILboolean ILAPIENTRY ilLoadData(ILconst_string FileName, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp); -ILAPI ILboolean ILAPIENTRY ilLoadDataF(ILHANDLE File, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp); -ILAPI ILboolean ILAPIENTRY ilLoadDataL(void *Lump, ILuint Size, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp); -ILAPI ILboolean ILAPIENTRY ilSaveData(ILconst_string FileName); - -// For all those weirdos that spell "colour" without the 'u'. -#define ilClearColor ilClearColour -#define ilKeyColor ilKeyColour - -#define imemclear(x,y) memset(x,0,y); - -#ifdef __cplusplus -} -#endif - -#endif // __IL_H__ -#endif // __il_h__ diff --git a/samples/DevIL/include/IL/il_wrap.h b/samples/DevIL/include/IL/il_wrap.h deleted file mode 100644 index 5cf9b0e0a..000000000 --- a/samples/DevIL/include/IL/il_wrap.h +++ /dev/null @@ -1,205 +0,0 @@ -#ifndef WRAPPER_H -#define WRAPPER_H - -/*#include -#include */ -#include // Probably only have to #include this one - -#ifdef _MSC_VER - #ifndef _IL_WRAP_BUILD_LIB - #pragma comment(lib, "il_wrap.lib") - #endif -#endif - -class ilImage -{ -public: - ilImage(); - ilImage(char *); - ilImage(const ilImage &); - virtual ~ilImage(); - - ILboolean Load(char *); - ILboolean Load(char *, ILenum); - ILboolean Save(char *); - ILboolean Save(char *, ILenum); - - - // ImageLib functions - ILboolean ActiveImage(ILuint); - ILboolean ActiveLayer(ILuint); - ILboolean ActiveMipmap(ILuint); - ILboolean Clear(void); - ILvoid ClearColour(ILclampf, ILclampf, ILclampf, ILclampf); - ILboolean Convert(ILenum); - ILboolean Copy(ILuint); - ILboolean Default(void); - ILboolean Flip(void); - ILboolean SwapColours(void); - ILboolean Resize(ILuint, ILuint, ILuint); - ILboolean TexImage(ILuint, ILuint, ILuint, ILubyte, ILenum, ILenum, ILvoid*); - - - // Image handling - ILvoid Bind(void) const; - ILvoid Bind(ILuint); - ILvoid Close(void) { this->Delete(); } - ILvoid Delete(void); - ILvoid iGenBind(); - ILenum PaletteAlphaIndex(); - - // Image characteristics - ILuint Width(void); - ILuint Height(void); - ILuint Depth(void); - ILubyte Bpp(void); - ILubyte Bitpp(void); - ILenum PaletteType(void); - ILenum Format(void); - ILenum Type(void); - ILuint NumImages(void); - ILuint NumMipmaps(void); - ILuint GetId(void) const; - ILenum GetOrigin(void); - ILubyte *GetData(void); - ILubyte *GetPalette(void); - - - // Rendering - ILuint BindImage(void); - ILuint BindImage(ILenum); - - - // Operators - ilImage& operator = (ILuint); - ilImage& operator = (const ilImage &); - - -protected: - ILuint Id; - -private: - ILvoid iStartUp(); - - -}; - - -class ilFilters -{ -public: - static ILboolean Alienify(ilImage &); - static ILboolean BlurAvg(ilImage &, ILuint Iter); - static ILboolean BlurGaussian(ilImage &, ILuint Iter); - static ILboolean Contrast(ilImage &, ILfloat Contrast); - static ILboolean EdgeDetectE(ilImage &); - static ILboolean EdgeDetectP(ilImage &); - static ILboolean EdgeDetectS(ilImage &); - static ILboolean Emboss(ilImage &); - static ILboolean Gamma(ilImage &, ILfloat Gamma); - static ILboolean Negative(ilImage &); - static ILboolean Noisify(ilImage &, ILubyte Factor); - static ILboolean Pixelize(ilImage &, ILuint PixSize); - static ILboolean Saturate(ilImage &, ILfloat Saturation); - static ILboolean Saturate(ilImage &, ILfloat r, ILfloat g, ILfloat b, ILfloat Saturation); - static ILboolean ScaleColours(ilImage &, ILfloat r, ILfloat g, ILfloat b); - static ILboolean Sharpen(ilImage &, ILfloat Factor, ILuint Iter); -}; - - -#ifdef ILUT_USE_OPENGL -class ilOgl -{ -public: - static ILvoid Init(void); - static GLuint BindTex(ilImage &); - static ILboolean Upload(ilImage &, ILuint); - static GLuint Mipmap(ilImage &); - static ILboolean Screen(void); - static ILboolean Screenie(void); -}; -#endif//ILUT_USE_OPENGL - - -#ifdef ILUT_USE_ALLEGRO -class ilAlleg -{ -public: - static ILvoid Init(void); - static BITMAP *Convert(ilImage &); -}; -#endif//ILUT_USE_ALLEGRO - - -#ifdef ILUT_USE_WIN32 -class ilWin32 -{ -public: - static ILvoid Init(void); - static HBITMAP Convert(ilImage &); - static ILboolean GetClipboard(ilImage &); - static ILvoid GetInfo(ilImage &, BITMAPINFO *Info); - static ILubyte *GetPadData(ilImage &); - static HPALETTE GetPal(ilImage &); - static ILboolean GetResource(ilImage &, HINSTANCE hInst, ILint ID, char *ResourceType); - static ILboolean GetResource(ilImage &, HINSTANCE hInst, ILint ID, char *ResourceType, ILenum Type); - static ILboolean SetClipboard(ilImage &); -}; -#endif//ILUT_USE_WIN32 - - -class ilValidate -{ -public: - static ILboolean Valid(ILenum, char *); - static ILboolean Valid(ILenum, FILE *); - static ILboolean Valid(ILenum, ILvoid *, ILuint); - -protected: - -private: - -}; - - -class ilState -{ -public: - static ILboolean Disable(ILenum); - static ILboolean Enable(ILenum); - static ILvoid Get(ILenum, ILboolean &); - static ILvoid Get(ILenum, ILint &); - static ILboolean GetBool(ILenum); - static ILint GetInt(ILenum); - static const char *GetString(ILenum); - static ILboolean IsDisabled(ILenum); - static ILboolean IsEnabled(ILenum); - static ILboolean Origin(ILenum); - static ILvoid Pop(void); - static ILvoid Push(ILuint); - - -protected: - -private: - -}; - - -class ilError -{ -public: - static ILvoid Check(ILvoid (*Callback)(const char*)); - static ILvoid Check(ILvoid (*Callback)(ILenum)); - static ILenum Get(void); - static const char *String(void); - static const char *String(ILenum); - -protected: - -private: - -}; - - -#endif//WRAPPER_H diff --git a/samples/DevIL/include/IL/ilu.h b/samples/DevIL/include/IL/ilu.h deleted file mode 100644 index 49871d79f..000000000 --- a/samples/DevIL/include/IL/ilu.h +++ /dev/null @@ -1,195 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Utility Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: IL/ilu.h -// -// Description: The main include file for ILU -// -//----------------------------------------------------------------------------- - -// Doxygen comment -/*! \file ilu.h - The main include file for ILU -*/ - -#ifndef __ilu_h_ -#ifndef __ILU_H__ - -#define __ilu_h_ -#define __ILU_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -#ifdef _WIN32 - #if (defined(IL_USE_PRAGMA_LIBS)) && (!defined(_IL_BUILD_LIBRARY)) - #if defined(_MSC_VER) || defined(__BORLANDC__) - #pragma comment(lib, "ILU.lib") - #endif - #endif -#endif - - -#define ILU_VERSION_1_7_8 1 -#define ILU_VERSION 178 - - -#define ILU_FILTER 0x2600 -#define ILU_NEAREST 0x2601 -#define ILU_LINEAR 0x2602 -#define ILU_BILINEAR 0x2603 -#define ILU_SCALE_BOX 0x2604 -#define ILU_SCALE_TRIANGLE 0x2605 -#define ILU_SCALE_BELL 0x2606 -#define ILU_SCALE_BSPLINE 0x2607 -#define ILU_SCALE_LANCZOS3 0x2608 -#define ILU_SCALE_MITCHELL 0x2609 - - -// Error types -#define ILU_INVALID_ENUM 0x0501 -#define ILU_OUT_OF_MEMORY 0x0502 -#define ILU_INTERNAL_ERROR 0x0504 -#define ILU_INVALID_VALUE 0x0505 -#define ILU_ILLEGAL_OPERATION 0x0506 -#define ILU_INVALID_PARAM 0x0509 - - -// Values -#define ILU_PLACEMENT 0x0700 -#define ILU_LOWER_LEFT 0x0701 -#define ILU_LOWER_RIGHT 0x0702 -#define ILU_UPPER_LEFT 0x0703 -#define ILU_UPPER_RIGHT 0x0704 -#define ILU_CENTER 0x0705 -#define ILU_CONVOLUTION_MATRIX 0x0710 - -#define ILU_VERSION_NUM IL_VERSION_NUM -#define ILU_VENDOR IL_VENDOR - - -// Languages -#define ILU_ENGLISH 0x0800 -#define ILU_ARABIC 0x0801 -#define ILU_DUTCH 0x0802 -#define ILU_JAPANESE 0x0803 -#define ILU_SPANISH 0x0804 -#define ILU_GERMAN 0x0805 -#define ILU_FRENCH 0x0806 - - -// Filters -/* -#define ILU_FILTER_BLUR 0x0803 -#define ILU_FILTER_GAUSSIAN_3x3 0x0804 -#define ILU_FILTER_GAUSSIAN_5X5 0x0805 -#define ILU_FILTER_EMBOSS1 0x0807 -#define ILU_FILTER_EMBOSS2 0x0808 -#define ILU_FILTER_LAPLACIAN1 0x080A -#define ILU_FILTER_LAPLACIAN2 0x080B -#define ILU_FILTER_LAPLACIAN3 0x080C -#define ILU_FILTER_LAPLACIAN4 0x080D -#define ILU_FILTER_SHARPEN1 0x080E -#define ILU_FILTER_SHARPEN2 0x080F -#define ILU_FILTER_SHARPEN3 0x0810 -*/ - - -typedef struct ILinfo -{ - ILuint Id; // the image's id - ILubyte *Data; // the image's data - ILuint Width; // the image's width - ILuint Height; // the image's height - ILuint Depth; // the image's depth - ILubyte Bpp; // bytes per pixel (not bits) of the image - ILuint SizeOfData; // the total size of the data (in bytes) - ILenum Format; // image format (in IL enum style) - ILenum Type; // image type (in IL enum style) - ILenum Origin; // origin of the image - ILubyte *Palette; // the image's palette - ILenum PalType; // palette type - ILuint PalSize; // palette size - ILenum CubeFlags; // flags for what cube map sides are present - ILuint NumNext; // number of images following - ILuint NumMips; // number of mipmaps - ILuint NumLayers; // number of layers -} ILinfo; - - -typedef struct ILpointf { - ILfloat x; - ILfloat y; -} ILpointf; - -typedef struct ILpointi { - ILint x; - ILint y; -} ILpointi; - -ILAPI ILboolean ILAPIENTRY iluAlienify(void); -ILAPI ILboolean ILAPIENTRY iluBlurAvg(ILuint Iter); -ILAPI ILboolean ILAPIENTRY iluBlurGaussian(ILuint Iter); -ILAPI ILboolean ILAPIENTRY iluBuildMipmaps(void); -ILAPI ILuint ILAPIENTRY iluColoursUsed(void); -ILAPI ILboolean ILAPIENTRY iluCompareImage(ILuint Comp); -ILAPI ILboolean ILAPIENTRY iluContrast(ILfloat Contrast); -ILAPI ILboolean ILAPIENTRY iluCrop(ILuint XOff, ILuint YOff, ILuint ZOff, ILuint Width, ILuint Height, ILuint Depth); -ILAPI void ILAPIENTRY iluDeleteImage(ILuint Id); // Deprecated -ILAPI ILboolean ILAPIENTRY iluEdgeDetectE(void); -ILAPI ILboolean ILAPIENTRY iluEdgeDetectP(void); -ILAPI ILboolean ILAPIENTRY iluEdgeDetectS(void); -ILAPI ILboolean ILAPIENTRY iluEmboss(void); -ILAPI ILboolean ILAPIENTRY iluEnlargeCanvas(ILuint Width, ILuint Height, ILuint Depth); -ILAPI ILboolean ILAPIENTRY iluEnlargeImage(ILfloat XDim, ILfloat YDim, ILfloat ZDim); -ILAPI ILboolean ILAPIENTRY iluEqualize(void); -ILAPI ILconst_string ILAPIENTRY iluErrorString(ILenum Error); -ILAPI ILboolean ILAPIENTRY iluConvolution(ILint *matrix, ILint scale, ILint bias); -ILAPI ILboolean ILAPIENTRY iluFlipImage(void); -ILAPI ILboolean ILAPIENTRY iluGammaCorrect(ILfloat Gamma); -ILAPI ILuint ILAPIENTRY iluGenImage(void); // Deprecated -ILAPI void ILAPIENTRY iluGetImageInfo(ILinfo *Info); -ILAPI ILint ILAPIENTRY iluGetInteger(ILenum Mode); -ILAPI void ILAPIENTRY iluGetIntegerv(ILenum Mode, ILint *Param); -ILAPI ILstring ILAPIENTRY iluGetString(ILenum StringName); -ILAPI void ILAPIENTRY iluImageParameter(ILenum PName, ILenum Param); -ILAPI void ILAPIENTRY iluInit(void); -ILAPI ILboolean ILAPIENTRY iluInvertAlpha(void); -ILAPI ILuint ILAPIENTRY iluLoadImage(ILconst_string FileName); -ILAPI ILboolean ILAPIENTRY iluMirror(void); -ILAPI ILboolean ILAPIENTRY iluNegative(void); -ILAPI ILboolean ILAPIENTRY iluNoisify(ILclampf Tolerance); -ILAPI ILboolean ILAPIENTRY iluPixelize(ILuint PixSize); -ILAPI void ILAPIENTRY iluRegionfv(ILpointf *Points, ILuint n); -ILAPI void ILAPIENTRY iluRegioniv(ILpointi *Points, ILuint n); -ILAPI ILboolean ILAPIENTRY iluReplaceColour(ILubyte Red, ILubyte Green, ILubyte Blue, ILfloat Tolerance); -ILAPI ILboolean ILAPIENTRY iluRotate(ILfloat Angle); -ILAPI ILboolean ILAPIENTRY iluRotate3D(ILfloat x, ILfloat y, ILfloat z, ILfloat Angle); -ILAPI ILboolean ILAPIENTRY iluSaturate1f(ILfloat Saturation); -ILAPI ILboolean ILAPIENTRY iluSaturate4f(ILfloat r, ILfloat g, ILfloat b, ILfloat Saturation); -ILAPI ILboolean ILAPIENTRY iluScale(ILuint Width, ILuint Height, ILuint Depth); -ILAPI ILboolean ILAPIENTRY iluScaleAlpha(ILfloat scale); -ILAPI ILboolean ILAPIENTRY iluScaleColours(ILfloat r, ILfloat g, ILfloat b); -ILAPI ILboolean ILAPIENTRY iluSetLanguage(ILenum Language); -ILAPI ILboolean ILAPIENTRY iluSharpen(ILfloat Factor, ILuint Iter); -ILAPI ILboolean ILAPIENTRY iluSwapColours(void); -ILAPI ILboolean ILAPIENTRY iluWave(ILfloat Angle); - -#define iluColorsUsed iluColoursUsed -#define iluSwapColors iluSwapColours -#define iluReplaceColor iluReplaceColour -#define iluScaleColor iluScaleColour - -#ifdef __cplusplus -} -#endif - -#endif // __ILU_H__ -#endif // __ilu_h_ diff --git a/samples/DevIL/include/IL/ilu_region.h b/samples/DevIL/include/IL/ilu_region.h deleted file mode 100644 index b5b3adc2d..000000000 --- a/samples/DevIL/include/IL/ilu_region.h +++ /dev/null @@ -1,25 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Utility Sources -// Copyright (C) 2000-2002 by Denton Woods -// Last modified: 07/09/2002 <--Y2K Compliant! =] -// -// Filename: src-ILU/src/ilu_region.h -// -// Description: Creates an image region. -// -//----------------------------------------------------------------------------- - -#ifndef ILU_REGION_H -#define ILU_REGION_H - -typedef struct Edge -{ - ILint yUpper; - ILfloat xIntersect, dxPerScan; - struct Edge *next; -} Edge; - - -#endif//ILU_REGION_H - diff --git a/samples/DevIL/include/IL/ilut.h b/samples/DevIL/include/IL/ilut.h deleted file mode 100644 index 4a84b845d..000000000 --- a/samples/DevIL/include/IL/ilut.h +++ /dev/null @@ -1,390 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Utility Toolkit Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: IL/ilut.h -// -// Description: The main include file for ILUT -// -//----------------------------------------------------------------------------- - -// Doxygen comment -/*! \file ilut.h - The main include file for ILUT -*/ - -#ifndef __ilut_h_ -#ifndef __ILUT_H__ - -#define __ilut_h_ -#define __ILUT_H__ - -#include -#include - - -//----------------------------------------------------------------------------- -// Defines -//----------------------------------------------------------------------------- - -#define ILUT_VERSION_1_7_8 1 -#define ILUT_VERSION 178 - - -// Attribute Bits -#define ILUT_OPENGL_BIT 0x00000001 -#define ILUT_D3D_BIT 0x00000002 -#define ILUT_ALL_ATTRIB_BITS 0x000FFFFF - - -// Error Types -#define ILUT_INVALID_ENUM 0x0501 -#define ILUT_OUT_OF_MEMORY 0x0502 -#define ILUT_INVALID_VALUE 0x0505 -#define ILUT_ILLEGAL_OPERATION 0x0506 -#define ILUT_INVALID_PARAM 0x0509 -#define ILUT_COULD_NOT_OPEN_FILE 0x050A -#define ILUT_STACK_OVERFLOW 0x050E -#define ILUT_STACK_UNDERFLOW 0x050F -#define ILUT_BAD_DIMENSIONS 0x0511 -#define ILUT_NOT_SUPPORTED 0x0550 - - -// State Definitions -#define ILUT_PALETTE_MODE 0x0600 -#define ILUT_OPENGL_CONV 0x0610 -#define ILUT_D3D_MIPLEVELS 0x0620 -#define ILUT_MAXTEX_WIDTH 0x0630 -#define ILUT_MAXTEX_HEIGHT 0x0631 -#define ILUT_MAXTEX_DEPTH 0x0632 -#define ILUT_GL_USE_S3TC 0x0634 -#define ILUT_D3D_USE_DXTC 0x0634 -#define ILUT_GL_GEN_S3TC 0x0635 -#define ILUT_D3D_GEN_DXTC 0x0635 -#define ILUT_S3TC_FORMAT 0x0705 -#define ILUT_DXTC_FORMAT 0x0705 -#define ILUT_D3D_POOL 0x0706 -#define ILUT_D3D_ALPHA_KEY_COLOR 0x0707 -#define ILUT_D3D_ALPHA_KEY_COLOUR 0x0707 -#define ILUT_FORCE_INTEGER_FORMAT 0x0636 - -//This new state does automatic texture target detection -//if enabled. Currently, only cubemap detection is supported. -//if the current image is no cubemap, the 2d texture is chosen. -#define ILUT_GL_AUTODETECT_TEXTURE_TARGET 0x0807 - - -// Values -#define ILUT_VERSION_NUM IL_VERSION_NUM -#define ILUT_VENDOR IL_VENDOR - -// The different rendering api's...more to be added later? -#define ILUT_OPENGL 0 -#define ILUT_ALLEGRO 1 -#define ILUT_WIN32 2 -#define ILUT_DIRECT3D8 3 -#define ILUT_DIRECT3D9 4 -#define ILUT_X11 5 -#define ILUT_DIRECT3D10 6 - -/* -// Includes specific config -#ifdef DJGPP - #define ILUT_USE_ALLEGRO -#elif _WIN32_WCE - #define ILUT_USE_WIN32 -#elif _WIN32 - //#ifdef __GNUC__ //__CYGWIN32__ (Cygwin seems to not define this with DevIL builds) - #define ILUT_USE_WIN32 - #include "IL/config.h" - - // Temporary fix for the SDL main() linker bug. - //#ifdef ILUT_USE_SDL - //#undef ILUT_USE_SDL - //#endif//ILUT_USE_SDL - - //#else - // #define ILUT_USE_WIN32 - // #define ILUT_USE_OPENGL - // #define ILUT_USE_SDL - // #define ILUT_USE_DIRECTX8 - //#endif -#elif BEOS // Don't know the #define - #define ILUT_USE_BEOS - #define ILUT_USE_OPENGL -#elif MACOSX - #define ILUT_USE_OPENGL -#else - - // We are surely using a *nix so the configure script - // may have written the configured config.h header - #include "IL/config.h" -#endif -*/ - -#if (defined(_WIN32) || defined(_WIN64)) - #if (defined(IL_USE_PRAGMA_LIBS)) && (!defined(_IL_BUILD_LIBRARY)) - #if defined(_MSC_VER) || defined(__BORLANDC__) - #pragma comment(lib, "ILUT.lib") - #endif - #endif - - #include -#endif - - - -//this should remain private and hidden -//#include "IL/config.h" - -////////////// -// OpenGL -////////////// - -#ifdef ILUT_USE_OPENGL - #if defined(_MSC_VER) || defined(_WIN32) - //#define WIN32_LEAN_AND_MEAN - #include - #endif//_MSC_VER - - #ifdef __APPLE__ - #include - #include - #else - #include - #include - #endif//__APPLE__ -#endif - - -#ifdef ILUT_USE_WIN32 - //#define WIN32_LEAN_AND_MEAN - #ifdef _DEBUG - #define _CRTDBG_MAP_ALLOC - #include - #ifndef _WIN32_WCE - #include - #endif - #endif - #include -#endif - - -// -// If we can avoid including these in all cases thing tend to break less -// and we can keep all of them defined as available -// -// Kriss -// - -// ImageLib Utility Toolkit's Allegro Functions -#ifdef ILUT_USE_ALLEGRO -// #include -#endif//ILUT_USE_ALLEGRO - -#ifdef ILUT_USE_SDL -// #include -#endif - -#ifdef ILUT_USE_DIRECTX8 - #include -#endif//ILUT_USE_DIRECTX9 - -#ifdef ILUT_USE_DIRECTX9 - #include -#endif//ILUT_USE_DIRECTX9 - -#ifdef ILUT_USE_DIRECTX10 - #pragma warning(push) - #pragma warning(disable : 4201) // Disables 'nonstandard extension used : nameless struct/union' warning - #include - #include - #include - #pragma warning(pop) -#endif//ILUT_USE_DIRECTX10 - -#ifdef ILUT_USE_X11 - #include - #include -#ifdef ILUT_USE_XSHM - #include - #include - #include -#endif//ILUT_USE_XSHM -#endif//ILUT_USE_X11 - - - -//----------------------------------------------------------------------------- -// Functions -//----------------------------------------------------------------------------- - -#ifdef __cplusplus -extern "C" { -#endif - -// ImageLib Utility Toolkit Functions -ILAPI ILboolean ILAPIENTRY ilutDisable(ILenum Mode); -ILAPI ILboolean ILAPIENTRY ilutEnable(ILenum Mode); -ILAPI ILboolean ILAPIENTRY ilutGetBoolean(ILenum Mode); -ILAPI void ILAPIENTRY ilutGetBooleanv(ILenum Mode, ILboolean *Param); -ILAPI ILint ILAPIENTRY ilutGetInteger(ILenum Mode); -ILAPI void ILAPIENTRY ilutGetIntegerv(ILenum Mode, ILint *Param); -ILAPI ILstring ILAPIENTRY ilutGetString(ILenum StringName); -ILAPI void ILAPIENTRY ilutInit(void); -ILAPI ILboolean ILAPIENTRY ilutIsDisabled(ILenum Mode); -ILAPI ILboolean ILAPIENTRY ilutIsEnabled(ILenum Mode); -ILAPI void ILAPIENTRY ilutPopAttrib(void); -ILAPI void ILAPIENTRY ilutPushAttrib(ILuint Bits); -ILAPI void ILAPIENTRY ilutSetInteger(ILenum Mode, ILint Param); - -ILAPI ILboolean ILAPIENTRY ilutRenderer(ILenum Renderer); - - -// ImageLib Utility Toolkit's OpenGL Functions -#ifdef ILUT_USE_OPENGL - ILAPI GLuint ILAPIENTRY ilutGLBindTexImage(); - ILAPI GLuint ILAPIENTRY ilutGLBindMipmaps(void); - ILAPI ILboolean ILAPIENTRY ilutGLBuildMipmaps(void); - ILAPI GLuint ILAPIENTRY ilutGLLoadImage(ILstring FileName); - ILAPI ILboolean ILAPIENTRY ilutGLScreen(void); - ILAPI ILboolean ILAPIENTRY ilutGLScreenie(void); - ILAPI ILboolean ILAPIENTRY ilutGLSaveImage(ILstring FileName, GLuint TexID); - ILAPI ILboolean ILAPIENTRY ilutGLSubTex2D(GLuint TexID, ILuint XOff, ILuint YOff); - ILAPI ILboolean ILAPIENTRY ilutGLSubTex3D(GLuint TexID, ILuint XOff, ILuint YOff, ILuint ZOff); - ILAPI ILboolean ILAPIENTRY ilutGLSetTex2D(GLuint TexID); - ILAPI ILboolean ILAPIENTRY ilutGLSetTex3D(GLuint TexID); - ILAPI ILboolean ILAPIENTRY ilutGLTexImage(GLuint Level); - ILAPI ILboolean ILAPIENTRY ilutGLSubTex(GLuint TexID, ILuint XOff, ILuint YOff); - - ILAPI ILboolean ILAPIENTRY ilutGLSetTex(GLuint TexID); // Deprecated - use ilutGLSetTex2D. - ILAPI ILboolean ILAPIENTRY ilutGLSubTex(GLuint TexID, ILuint XOff, ILuint YOff); // Use ilutGLSubTex2D. -#endif//ILUT_USE_OPENGL - - -// ImageLib Utility Toolkit's Allegro Functions -#ifdef ILUT_USE_ALLEGRO - #ifdef __cplusplus - extern "C" { - #endif - #include - #ifdef __cplusplus - } - #endif - - ILAPI BITMAP* ILAPIENTRY ilutAllegLoadImage(ILstring FileName); - ILAPI BITMAP* ILAPIENTRY ilutConvertToAlleg(PALETTE Pal); -#endif//ILUT_USE_ALLEGRO - - -// ImageLib Utility Toolkit's SDL Functions -#ifdef ILUT_USE_SDL - ILAPI struct SDL_Surface* ILAPIENTRY ilutConvertToSDLSurface(unsigned int flags); - ILAPI struct SDL_Surface* ILAPIENTRY ilutSDLSurfaceLoadImage(ILstring FileName); - ILAPI ILboolean ILAPIENTRY ilutSDLSurfaceFromBitmap(struct SDL_Surface *Bitmap); -#endif//ILUT_USE_SDL - - -// ImageLib Utility Toolkit's BeOS Functions -#ifdef ILUT_USE_BEOS - ILAPI BBitmap ILAPIENTRY ilutConvertToBBitmap(void); -#endif//ILUT_USE_BEOS - - -// ImageLib Utility Toolkit's Win32 GDI Functions -#ifdef ILUT_USE_WIN32 - ILAPI HBITMAP ILAPIENTRY ilutConvertToHBitmap(HDC hDC); - ILAPI HBITMAP ILAPIENTRY ilutConvertSliceToHBitmap(HDC hDC, ILuint slice); - ILAPI void ILAPIENTRY ilutFreePaddedData(ILubyte *Data); - ILAPI void ILAPIENTRY ilutGetBmpInfo(BITMAPINFO *Info); - ILAPI HPALETTE ILAPIENTRY ilutGetHPal(void); - ILAPI ILubyte* ILAPIENTRY ilutGetPaddedData(void); - ILAPI ILboolean ILAPIENTRY ilutGetWinClipboard(void); - ILAPI ILboolean ILAPIENTRY ilutLoadResource(HINSTANCE hInst, ILint ID, ILstring ResourceType, ILenum Type); - ILAPI ILboolean ILAPIENTRY ilutSetHBitmap(HBITMAP Bitmap); - ILAPI ILboolean ILAPIENTRY ilutSetHPal(HPALETTE Pal); - ILAPI ILboolean ILAPIENTRY ilutSetWinClipboard(void); - ILAPI HBITMAP ILAPIENTRY ilutWinLoadImage(ILstring FileName, HDC hDC); - ILAPI ILboolean ILAPIENTRY ilutWinLoadUrl(ILstring Url); - ILAPI ILboolean ILAPIENTRY ilutWinPrint(ILuint XPos, ILuint YPos, ILuint Width, ILuint Height, HDC hDC); - ILAPI ILboolean ILAPIENTRY ilutWinSaveImage(ILstring FileName, HBITMAP Bitmap); -#endif//ILUT_USE_WIN32 - -// ImageLib Utility Toolkit's DirectX 8 Functions -#ifdef ILUT_USE_DIRECTX8 -// ILAPI void ILAPIENTRY ilutD3D8MipFunc(ILuint NumLevels); - ILAPI struct IDirect3DTexture8* ILAPIENTRY ilutD3D8Texture(struct IDirect3DDevice8 *Device); - ILAPI struct IDirect3DVolumeTexture8* ILAPIENTRY ilutD3D8VolumeTexture(struct IDirect3DDevice8 *Device); - ILAPI ILboolean ILAPIENTRY ilutD3D8TexFromFile(struct IDirect3DDevice8 *Device, char *FileName, struct IDirect3DTexture8 **Texture); - ILAPI ILboolean ILAPIENTRY ilutD3D8VolTexFromFile(struct IDirect3DDevice8 *Device, char *FileName, struct IDirect3DVolumeTexture8 **Texture); - ILAPI ILboolean ILAPIENTRY ilutD3D8TexFromFileInMemory(struct IDirect3DDevice8 *Device, void *Lump, ILuint Size, struct IDirect3DTexture8 **Texture); - ILAPI ILboolean ILAPIENTRY ilutD3D8VolTexFromFileInMemory(struct IDirect3DDevice8 *Device, void *Lump, ILuint Size, struct IDirect3DVolumeTexture8 **Texture); - ILAPI ILboolean ILAPIENTRY ilutD3D8TexFromFileHandle(struct IDirect3DDevice8 *Device, ILHANDLE File, struct IDirect3DTexture8 **Texture); - ILAPI ILboolean ILAPIENTRY ilutD3D8VolTexFromFileHandle(struct IDirect3DDevice8 *Device, ILHANDLE File, struct IDirect3DVolumeTexture8 **Texture); - // These two are not tested yet. - ILAPI ILboolean ILAPIENTRY ilutD3D8TexFromResource(struct IDirect3DDevice8 *Device, HMODULE SrcModule, char *SrcResource, struct IDirect3DTexture8 **Texture); - ILAPI ILboolean ILAPIENTRY ilutD3D8VolTexFromResource(struct IDirect3DDevice8 *Device, HMODULE SrcModule, char *SrcResource, struct IDirect3DVolumeTexture8 **Texture); - ILAPI ILboolean ILAPIENTRY ilutD3D8LoadSurface(struct IDirect3DDevice8 *Device, struct IDirect3DSurface8 *Surface); -#endif//ILUT_USE_DIRECTX8 - -#ifdef ILUT_USE_DIRECTX9 - #pragma warning(push) - #pragma warning(disable : 4115) // Disables 'named type definition in parentheses' warning -// ILAPI void ILAPIENTRY ilutD3D9MipFunc(ILuint NumLevels); - ILAPI struct IDirect3DTexture9* ILAPIENTRY ilutD3D9Texture (struct IDirect3DDevice9* Device); - ILAPI struct IDirect3DVolumeTexture9* ILAPIENTRY ilutD3D9VolumeTexture (struct IDirect3DDevice9* Device); - ILAPI struct IDirect3DCubeTexture9* ILAPIENTRY ilutD3D9CubeTexture (struct IDirect3DDevice9* Device); - - ILAPI ILboolean ILAPIENTRY ilutD3D9CubeTexFromFile(struct IDirect3DDevice9 *Device, ILconst_string FileName, struct IDirect3DCubeTexture9 **Texture); - ILAPI ILboolean ILAPIENTRY ilutD3D9CubeTexFromFileInMemory(struct IDirect3DDevice9 *Device, void *Lump, ILuint Size, struct IDirect3DCubeTexture9 **Texture); - ILAPI ILboolean ILAPIENTRY ilutD3D9CubeTexFromFileHandle(struct IDirect3DDevice9 *Device, ILHANDLE File, struct IDirect3DCubeTexture9 **Texture); - ILAPI ILboolean ILAPIENTRY ilutD3D9CubeTexFromResource(struct IDirect3DDevice9 *Device, HMODULE SrcModule, ILconst_string SrcResource, struct IDirect3DCubeTexture9 **Texture); - - ILAPI ILboolean ILAPIENTRY ilutD3D9TexFromFile(struct IDirect3DDevice9 *Device, ILconst_string FileName, struct IDirect3DTexture9 **Texture); - ILAPI ILboolean ILAPIENTRY ilutD3D9VolTexFromFile(struct IDirect3DDevice9 *Device, ILconst_string FileName, struct IDirect3DVolumeTexture9 **Texture); - ILAPI ILboolean ILAPIENTRY ilutD3D9TexFromFileInMemory(struct IDirect3DDevice9 *Device, void *Lump, ILuint Size, struct IDirect3DTexture9 **Texture); - ILAPI ILboolean ILAPIENTRY ilutD3D9VolTexFromFileInMemory(struct IDirect3DDevice9 *Device, void *Lump, ILuint Size, struct IDirect3DVolumeTexture9 **Texture); - ILAPI ILboolean ILAPIENTRY ilutD3D9TexFromFileHandle(struct IDirect3DDevice9 *Device, ILHANDLE File, struct IDirect3DTexture9 **Texture); - ILAPI ILboolean ILAPIENTRY ilutD3D9VolTexFromFileHandle(struct IDirect3DDevice9 *Device, ILHANDLE File, struct IDirect3DVolumeTexture9 **Texture); - - // These three are not tested yet. - ILAPI ILboolean ILAPIENTRY ilutD3D9TexFromResource(struct IDirect3DDevice9 *Device, HMODULE SrcModule, ILconst_string SrcResource, struct IDirect3DTexture9 **Texture); - ILAPI ILboolean ILAPIENTRY ilutD3D9VolTexFromResource(struct IDirect3DDevice9 *Device, HMODULE SrcModule, ILconst_string SrcResource, struct IDirect3DVolumeTexture9 **Texture); - ILAPI ILboolean ILAPIENTRY ilutD3D9LoadSurface(struct IDirect3DDevice9 *Device, struct IDirect3DSurface9 *Surface); - #pragma warning(pop) -#endif//ILUT_USE_DIRECTX9 - -#ifdef ILUT_USE_DIRECTX10 - ILAPI ID3D10Texture2D* ILAPIENTRY ilutD3D10Texture(ID3D10Device *Device); - ILAPI ILboolean ILAPIENTRY ilutD3D10TexFromFile(ID3D10Device *Device, ILconst_string FileName, ID3D10Texture2D **Texture); - ILAPI ILboolean ILAPIENTRY ilutD3D10TexFromFileInMemory(ID3D10Device *Device, void *Lump, ILuint Size, ID3D10Texture2D **Texture); - ILAPI ILboolean ILAPIENTRY ilutD3D10TexFromResource(ID3D10Device *Device, HMODULE SrcModule, ILconst_string SrcResource, ID3D10Texture2D **Texture); - ILAPI ILboolean ILAPIENTRY ilutD3D10TexFromFileHandle(ID3D10Device *Device, ILHANDLE File, ID3D10Texture2D **Texture); -#endif//ILUT_USE_DIRECTX10 - - - -#ifdef ILUT_USE_X11 - ILAPI XImage * ILAPIENTRY ilutXCreateImage( Display* ); - ILAPI Pixmap ILAPIENTRY ilutXCreatePixmap( Display*,Drawable ); - ILAPI XImage * ILAPIENTRY ilutXLoadImage( Display*,char* ); - ILAPI Pixmap ILAPIENTRY ilutXLoadPixmap( Display*,Drawable,char* ); -#ifdef ILUT_USE_XSHM - ILAPI XImage * ILAPIENTRY ilutXShmCreateImage( Display*,XShmSegmentInfo* ); - ILAPI void ILAPIENTRY ilutXShmDestroyImage( Display*,XImage*,XShmSegmentInfo* ); - ILAPI Pixmap ILAPIENTRY ilutXShmCreatePixmap( Display*,Drawable,XShmSegmentInfo* ); - ILAPI void ILAPIENTRY ilutXShmFreePixmap( Display*,Pixmap,XShmSegmentInfo* ); - ILAPI XImage * ILAPIENTRY ilutXShmLoadImage( Display*,char*,XShmSegmentInfo* ); - ILAPI Pixmap ILAPIENTRY ilutXShmLoadPixmap( Display*,Drawable,char*,XShmSegmentInfo* ); -#endif//ILUT_USE_XSHM -#endif//ILUT_USE_X11 - - -#ifdef __cplusplus -} -#endif - -#endif // __ILUT_H__ -#endif // __ilut_h_ diff --git a/samples/DevIL/include/IL/ilut_config.h b/samples/DevIL/include/IL/ilut_config.h deleted file mode 100644 index bd9cbc694..000000000 --- a/samples/DevIL/include/IL/ilut_config.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef __ILUT_CONFIG_H__ -#define __ILUT_CONFIG_H__ - -#define IL_USE_PRAGMA_LIBS - -// Supported APIs (ILUT) - -// -// sorry just -// can't get this one to work under windows -// have disabled for the now -// -// will look at it some more later -// -// Kriss -// -#undef ILUT_USE_ALLEGRO - -#undef ILUT_USE_DIRECTX8 -//#define ILUT_USE_DIRECTX9 -//#define ILUT_USE_DIRECTX10 -#define ILUT_USE_OPENGL -//#define ILUT_USE_SDL -#define ILUT_USE_WIN32 - -#endif//__ILUT_CONFIG_H__ diff --git a/samples/DevIL/lib/DevIL.lib b/samples/DevIL/lib/DevIL.lib deleted file mode 100644 index 1aa82d0476426a80c2daa4938edaf956b58c869c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30802 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 diff --git a/samples/DevIL/lib/ILU.lib b/samples/DevIL/lib/ILU.lib deleted file mode 100644 index 5124172e2965eb41c9a6918a807314845934fc6b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11630 zcmds7J!~9h8h&jP!Yv^fk~oR&Bx}d)5`;;23My(Mf5R!5*&%jd%BE zXMJ}$iEAlN6bMmV6oso0Jjr97P z_nl|wneTU=_Ztu0bb_tjTbXNF`;x$mJI7_^fnu`T3kUeLDjH6@b%4fIc7K z>?444KMFg)3Bc`hEYbQ$rG1Dc+Q4IB{ZG+H8`u>#coTpd-fIx;0&;K*v1Il{*u}d5 z+&;w;?b4vM_pxO5ld$Xq0A@oo(muu#ZTLH3*{|?A+Hkittj93gTHuWyEa(VUM##_bB^72Y)skpka`Bt&Kx^^GR<@Nh( zYpoaIuXt5l+q`>!{mt_7;^rcvy}dgA@tcdj=T^O)KNn^p>MG1_zZopMhoW=Lb3p1*z1tM57WhGe}R2`TJS&960s#{Gu7EuoQ!fvoP={ATFYs)e~6 zf6%3x9Wtm7K5{;C<$HWHZ=- z7F>RZ?ngiw(a0^wm$gt+zZ8wxXj&mSj63#qF>FL1aEuCQoExq=)k;$@(8wU6a{cbFMv|E<}K0)h6h4K*Xd$hY( z06s(OLxuPr+7D>!V*nqF1AKwyg9(7I(SDi4`=Wh>_IL{5^=W(_w9Hk2pAkEP_AbW% zUk=tkUC<5B!7+Fqj>8L(ffwO7Z~|U}lkhV1!YlA9oPyJE2Kt~M&cZnufI&D97vLgX zf-DTdFkFTaxB{av1{08nahQimn1ZV?1JiIFuE8wKLGFLT(StfNp&D&3Jk_k|L|bZb zhpJKipd*oIpbwIdhe_w(;&D8>bd#M<` z@r71s3AYsjac^^dhj@7)UVR#U_={a*4}Wn-vRY$V!IYPIW@gGlk);GfkwlY6>>QDY zbUG;9mL!xG3%nf3`!Et&AgoAhW~VYZm7K93v@8TVC?q%KUdH5S5Ic3kh&AESzZ042 zEELU{>`aIwDDRLODw2o@h)#>pZ=J?0XyzT()WwTd`hdQkuIQL)0dsWVdy6{B!lWEiV1fYV^+u46t9aI{>OJcGio3 zkMT1}0fjBxSHg!J`{pn3>#xMc(ClDO)eThF0sw!`U5fBpF^(RJeVz6b2YW|GdP+>JS-&BSc_78&B&EM_*Tp}@u;n@#3n%%(iW8SX#i z$nxmgwv+b6#I^kfcH*|o&&#IFvTq!0F0OU4)d|yNJWlY98ACPD1WwK)v+-<%rw>`W zB#)LOM3Z!6sL2#z!K5BXhp0_N<`7l#8qvgU!_`Avwth;_rM^(vy@VSUxWb0>DfrgM(V^A*2^}V%Cd+|mYt9DnDwETxODbLG|5{qWHIi7PfVT8C>|^EPS16{ zeLpeX)n{<2Z;U6SE$jmpm<78$_0P^vxf@ zb_#o{pV-8nNotOKOdky>4s$bxsAPF0eKaVU%uSxuJTY&k3zA1|9uZ06zKP2%E=m?- zS1LVEOm1Jtl1M0Cb7#*REg^p(?65MM7!5SlDs}K<88`hp>6T>Ofd?7 z+GL`C8^P}=M3%ViVn*FnlZ)@;r)G&63p2!GeIH286jPsT#H7AEq-Ke!&n&T6-!sxO P#i^?~$t1s%5Jl#{MXWxM diff --git a/samples/DevIL/lib/ILUT.lib b/samples/DevIL/lib/ILUT.lib deleted file mode 100644 index 99bfb61240124767cdc2c9fe628c9e5e29b2bc88..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10564 zcmcIp&u<(>7Jjw^2CpH(aR_l@d;BAD!e+hBc*Y4*v`iec$%u)uY=_leFk??A9%(!? z8jr0=E3sD&hyw@2i340XAr33J=ENZ!HquIn+e#ey3lP$Z{i?fO)vNAyyT{|S{9N6y zzpAgQ`c>6eH4`_>t*!094E#CcUe~ho3;Epj?EIYT=f`aJja=~N{Q)BSJJHZS(eS54 zXPyw9{aD*;NMZO3Y#XVvr-6-MCGzbvq_E5hZB3-gehO@2iO9EakisU%w0($F*{^|3 zy+`C5>M#YH&INX^K;+xkNMR$$?;GklqU^W8&OadX?I}{&=x|^cZW8(S6;jyPyMc{< zfcMIN32f{!{IKaS0=qa!#zf_98rGKi|!OQi#_m|(^Sh}@-3-Ibr6aQ*^ z?c0s|zSnB6H|{Q0+dJiEAx8)LBe~XU)h*9vz2RhyzO?z5s=MXQn#W|~(PG}JONf24 zh`+WxZ>3zRc$KAcyUc|}y*9@kuf4d_EY=@180~soWTR2@%5{mfo;c)wLHB?vG=Tap z2YYv=Tr124Jp~*;I+$X;?LG8bf?0Utkdj$Lqs*eKEWhh?%3f=?s`ZDW64v41{#LEu zu2q|xjdH6ZS{8QOJjHso%|N~vZ+CS#RG7NxcqB523IP-jiz_wCl~r%IvDe!23fC5b zzK=L9{!VGJTCd!zHZdM{xuOwg7{Bg4D(;jYdTs{kb#m-gYcUidugsw;91!RsdZ*;L zBzCR5?*&+n$dco7uv-{LbzAE-^BhH0Me71w;Bk;%8;#~~cc-*wo};MjQWzI_qR9CO zGVnOay-me@EvrXYY0WyKI535g+7-oui{l0j@=Mh&i8bHad?4wu$dyL(RvUwBlRMpU z2;AQ8wg&1FR~(N;u6p%~*RnH)e6}cjiO?+XdR(NMr!=jC=|=~{vyu)nz=X#^h9?8H z^Z*`q+dOz1*srknrceef zH%(MHNAxvpYy@S(euF(YkMdx{qeM3^5Pb!E7y9P|JpTfFjQcN;ckm+7BiPTdZRxC1U*mv^a8y~XHoHUG(zX;0*%o)jnV{7Qii7JMH-+# z&>+1;FVjgnMX%5hou*+rL(_DTF3}8%zCy3lAL%OniDsWsseRBqooc73N=lM6aYD+5 z(;*7S0u$9scwMsDg4M}PH;8TLUD{+6;S}Rf|H;#O6t89;$Lr6zht1E? z9R3t9-KL9N0!J4Lyb*Gt3K@S?W*w&JoYGT@H78F>8D{ewrm+NaH=Tg8IZ`cM7M^Bd zvgj1+jswO7?I=qplaYQJ3lTseU+AVd_$q zocVs}UUjS0*lj#$XD+W^$&`xAZ~Je<|8QdD=Ts#?{K5Jmn+U>4-7yE~w;DT5)N|(h zf6(v0Gn>MzOI56wxVZ(WJmuMDkKZs=zdrWl6b259$y<-|Ln)d|l|^KF2lu^H!vD@i zR(yC2a5K}!M>cmu#7D0mAK&@a!avB>xcI2}uk1e&AM@;0@$n@;=v2kWGx+XlzNh*I z2cGqH+-KLLW9mO32tICnpCyc`Ja>}{K{cl2CB{^a{R;PQe$eSL_HCN}#O~;TBhro| zFwX&)QRm@mK$d#cEQL)JuEFG^QT}vhc&Cl~Jb%IvE4GN(qq(e7f*8V%+nLjQ*i48K z8&*V)X0+nQ5b;ggmgNp;nc5`xF^^GATsn2!p8PdEafI444xSUt6VYQ`@bM2QAwF!v zF~#ft3oAWC$2VzvF{yRWyKF{h&6y}X-rnpNe6Bd$KsL`&rYhV;#rClFR&t*#%cZ zWSog|sXe$Ma5`5y>nM_kS7d$WV@Qs56ptDf zd79J(SHia%vt0I^%24r5+Od@sgX7E;J^*8q&PQ@WyE4osPu7mklrU#Z7$*6ft)c2X zG7>b#By)+wz%G~)S~bN?&M{*bTnV%LwB!nYel|pWlQsgARPIH=!?U|susZ%yNi)+W z!F6mi(;M+Kp*k#@VZP8|F8ALNc3cV3aXG{m920lJl`xX82rhE~ZK(Jrb$lfB;p>7a Ic5^rIf8MW-8vp #include #include -#include + +#define STB_IMAGE_IMPLEMENTATION +#include "contrib/stb_image/stb_image.h" #include @@ -25,19 +27,17 @@ #include #include - // assimp include files. These three are usually needed. -#include "assimp/Importer.hpp" //OO version Header! -#include "assimp/postprocess.h" -#include "assimp/scene.h" -#include "assimp/DefaultLogger.hpp" -#include "assimp/LogStream.hpp" +#include +#include +#include +#include +#include // The default hard-coded path. Can be overridden by supplying a path through the command line. static std::string modelpath = "../../test/models/OBJ/spider.obj"; - HGLRC hRC=NULL; // Permanent Rendering Context HDC hDC=NULL; // Private GDI Device Context HWND hWnd=NULL; // Holds Window Handle @@ -75,7 +75,6 @@ GLuint* textureIds; // pointer to texture Array // Create an instance of the Importer class Assimp::Importer importer; - void createAILogger() { // Change this line to normal if you not want to analyse the import process @@ -173,21 +172,22 @@ std::string getBasePath(const std::string& path) int LoadGLTextures(const aiScene* scene) { - ILboolean success; + //ILboolean success; /* Before calling ilInit() version should be checked. */ - if (ilGetInteger(IL_VERSION_NUM) < IL_VERSION) + /*if (ilGetInteger(IL_VERSION_NUM) < IL_VERSION) { /// wrong DevIL version /// std::string err_msg = "Wrong DevIL version. Old devil.dll in system32/SysWow64?"; char* cErr_msg = (char *) err_msg.c_str(); abortGLInit(cErr_msg); return -1; - } + }*/ - ilInit(); /* Initialization of DevIL */ + //ilInit(); /* Initialization of DevIL */ - if (scene->HasTextures()) abortGLInit("Support for meshes with embedded textures is not implemented"); + if (scene->HasTextures()) return 1; + //abortGLInit("Support for meshes with embedded textures is not implemented"); /* getTexture Filenames and Numb of Textures */ for (unsigned int m=0; mmNumMaterials; m++) @@ -207,12 +207,13 @@ int LoadGLTextures(const aiScene* scene) int numTextures = textureIdMap.size(); + /* array with DevIL image IDs */ - ILuint* imageIds = NULL; - imageIds = new ILuint[numTextures]; + //ILuint* imageIds = NULL; +// imageIds = new ILuint[numTextures]; /* generate DevIL Image IDs */ - ilGenImages(numTextures, imageIds); /* Generation of numTextures image names */ +// ilGenImages(numTextures, imageIds); /* Generation of numTextures image names */ /* create and fill array with GL texture ids */ textureIds = new GLuint[numTextures]; @@ -231,21 +232,22 @@ int LoadGLTextures(const aiScene* scene) itr++; // next texture - ilBindImage(imageIds[i]); /* Binding of DevIL image name */ + //ilBindImage(imageIds[i]); /* Binding of DevIL image name */ std::string fileloc = basepath + filename; /* Loading of image */ - success = ilLoadImage(fileloc.c_str()); + //success = ilLoadImage(fileloc.c_str()); + int x, y, n; + unsigned char *data = stbi_load(fileloc.c_str(), &x, &y, &n, STBI_rgb_alpha); - if (success) /* If no error occurred: */ + if (nullptr != data ) { // Convert every colour component into unsigned byte.If your image contains // alpha channel you can replace IL_RGB with IL_RGBA - success = ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE); - if (!success) + //success = ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE); + /*if (!success) { - /* Error occurred */ abortGLInit("Couldn't convert image"); return -1; - } + }*/ // Binding of texture name glBindTexture(GL_TEXTURE_2D, textureIds[i]); // redefine standard texture values @@ -254,15 +256,15 @@ int LoadGLTextures(const aiScene* scene) // We will use linear interpolation for minifying filter glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); // Texture specification - glTexImage2D(GL_TEXTURE_2D, 0, ilGetInteger(IL_IMAGE_BPP), ilGetInteger(IL_IMAGE_WIDTH), - ilGetInteger(IL_IMAGE_HEIGHT), 0, ilGetInteger(IL_IMAGE_FORMAT), GL_UNSIGNED_BYTE, - ilGetData()); + glTexImage2D(GL_TEXTURE_2D, 0, n, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);// Texture specification. + // we also want to be able to deal with odd texture dimensions glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 ); glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 ); glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 ); - } + stbi_image_free(data); + } else { /* Error occurred */ @@ -270,11 +272,11 @@ int LoadGLTextures(const aiScene* scene) } } // Because we have already copied image data into texture data we can release memory used by image. - ilDeleteImages(numTextures, imageIds); +// ilDeleteImages(numTextures, imageIds); // Cleanup - delete [] imageIds; - imageIds = NULL; + //delete [] imageIds; + //imageIds = NULL; return TRUE; } diff --git a/samples/bin/DevIL.dll b/samples/bin/DevIL.dll deleted file mode 100644 index 689b3d4de9dfdb1dcfd9f96c1c7dbc681fb76d68..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 764382 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

    >VxK-mzI(5qy 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