summaryrefslogtreecommitdiff
path: root/libs/assimp/port
diff options
context:
space:
mode:
authorsanine <sanine.not@pm.me>2022-04-16 11:55:09 -0500
committersanine <sanine.not@pm.me>2022-04-16 11:55:09 -0500
commitdb81b925d776103326128bf629cbdda576a223e7 (patch)
tree58bea8155c686733310009f6bed7363f91fbeb9d /libs/assimp/port
parent55860037b14fb3893ba21cf2654c83d349cc1082 (diff)
move 3rd-party librarys into libs/ and add built-in honeysuckle
Diffstat (limited to 'libs/assimp/port')
-rw-r--r--libs/assimp/port/AndroidJNI/AndroidJNIIOSystem.cpp210
-rw-r--r--libs/assimp/port/AndroidJNI/BundledAssetIOSystem.cpp80
-rw-r--r--libs/assimp/port/AndroidJNI/CMakeLists.txt16
-rw-r--r--libs/assimp/port/AndroidJNI/README.md32
-rw-r--r--libs/assimp/port/AssimpDelphi/Readme.txt6
-rw-r--r--libs/assimp/port/AssimpDelphi/aiColor4D.pas17
-rw-r--r--libs/assimp/port/AssimpDelphi/aiMaterial.pas153
-rw-r--r--libs/assimp/port/AssimpDelphi/aiMatrix3x3.pas16
-rw-r--r--libs/assimp/port/AssimpDelphi/aiMatrix4x4.pas16
-rw-r--r--libs/assimp/port/AssimpDelphi/aiMesh.pas71
-rw-r--r--libs/assimp/port/AssimpDelphi/aiQuaternion.pas12
-rw-r--r--libs/assimp/port/AssimpDelphi/aiScene.pas46
-rw-r--r--libs/assimp/port/AssimpDelphi/aiTexture.pas26
-rw-r--r--libs/assimp/port/AssimpDelphi/aiTypes.pas53
-rw-r--r--libs/assimp/port/AssimpDelphi/aiVector2D.pas13
-rw-r--r--libs/assimp/port/AssimpDelphi/aiVector3D.pas16
-rw-r--r--libs/assimp/port/AssimpDelphi/assimp.pas58
-rw-r--r--libs/assimp/port/AssimpNET/Readme.md1
-rw-r--r--libs/assimp/port/AssimpPascal/Readme.md1
-rw-r--r--libs/assimp/port/PyAssimp/3d_viewer_screenshot.pngbin0 -> 51610 bytes
-rw-r--r--libs/assimp/port/PyAssimp/README.md86
-rw-r--r--libs/assimp/port/PyAssimp/README.rst93
-rw-r--r--libs/assimp/port/PyAssimp/gen/materialgen.py96
-rw-r--r--libs/assimp/port/PyAssimp/gen/structsgen.py290
-rw-r--r--libs/assimp/port/PyAssimp/pyassimp/__init__.py1
-rw-r--r--libs/assimp/port/PyAssimp/pyassimp/core.py556
-rw-r--r--libs/assimp/port/PyAssimp/pyassimp/errors.py11
-rw-r--r--libs/assimp/port/PyAssimp/pyassimp/formats.py41
-rw-r--r--libs/assimp/port/PyAssimp/pyassimp/helper.py283
-rw-r--r--libs/assimp/port/PyAssimp/pyassimp/material.py89
-rw-r--r--libs/assimp/port/PyAssimp/pyassimp/postprocess.py530
-rw-r--r--libs/assimp/port/PyAssimp/pyassimp/structs.py1135
-rwxr-xr-xlibs/assimp/port/PyAssimp/scripts/3d_viewer.py1318
-rwxr-xr-xlibs/assimp/port/PyAssimp/scripts/3d_viewer_py3.py1316
-rw-r--r--libs/assimp/port/PyAssimp/scripts/README.md13
-rwxr-xr-xlibs/assimp/port/PyAssimp/scripts/fixed_pipeline_3d_viewer.py372
-rwxr-xr-xlibs/assimp/port/PyAssimp/scripts/quicktest.py53
-rwxr-xr-xlibs/assimp/port/PyAssimp/scripts/sample.py89
-rw-r--r--libs/assimp/port/PyAssimp/scripts/transformations.py1705
-rw-r--r--libs/assimp/port/PyAssimp/setup.py26
-rw-r--r--libs/assimp/port/assimp_rs/Cargo.lock6
-rw-r--r--libs/assimp/port/assimp_rs/Cargo.toml9
-rw-r--r--libs/assimp/port/assimp_rs/src/camera/mod.rs1
-rw-r--r--libs/assimp/port/assimp_rs/src/core/mod.rs0
-rw-r--r--libs/assimp/port/assimp_rs/src/errors/mod.rs0
-rw-r--r--libs/assimp/port/assimp_rs/src/formats/mod.rs0
-rw-r--r--libs/assimp/port/assimp_rs/src/lib.rs17
-rw-r--r--libs/assimp/port/assimp_rs/src/material/mod.rs0
-rw-r--r--libs/assimp/port/assimp_rs/src/postprocess/mod.rs0
-rw-r--r--libs/assimp/port/assimp_rs/src/shims/mod.rs0
-rw-r--r--libs/assimp/port/assimp_rs/src/socket/mod.rs0
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/anim/anim.rs44
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/anim/mod.rs6
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/blob/blob.rs0
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/blob/mod.rs2
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/bone/bone.rs0
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/bone/mod.rs2
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/camera/camera.rs0
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/camera/mod.rs2
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/color/color.rs27
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/color/mod.rs5
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/face/face.rs0
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/face/mod.rs2
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/key/key.rs0
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/key/mod.rs2
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/light/light.rs0
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/light/mod.rs2
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/material/material.rs0
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/material/mod.rs2
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/matrix/matrix.rs64
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/matrix/mod.rs4
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/memory/memory.rs35
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/memory/mod.rs2
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/mesh/mesh.rs0
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/mesh/mod.rs3
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/meta/meta.rs0
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/meta/mod.rs2
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/mod.rs61
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/node/mod.rs2
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/node/node.rs0
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/plane/mod.rs2
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/plane/plane.rs23
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/quaternion/mod.rs3
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/quaternion/quaternion.rs7
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/ray/mod.rs2
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/ray/ray.rs0
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/scene/mod.rs2
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/scene/scene.rs0
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/string/mod.rs3
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/string/string.rs41
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/texture/mod.rs3
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/texture/texture.rs19
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/transform/mod.rs2
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/transform/transform.rs0
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/vec/mod.rs2
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/vec/vec.rs48
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/vertex/mod.rs2
-rw-r--r--libs/assimp/port/assimp_rs/src/structs/vertex/vertex.rs0
-rw-r--r--libs/assimp/port/dAssimp/README13
-rw-r--r--libs/assimp/port/dAssimp/assimp/animation.d240
-rw-r--r--libs/assimp/port/dAssimp/assimp/api.d686
-rw-r--r--libs/assimp/port/dAssimp/assimp/assimp.d63
-rw-r--r--libs/assimp/port/dAssimp/assimp/camera.d182
-rw-r--r--libs/assimp/port/dAssimp/assimp/config.d705
-rw-r--r--libs/assimp/port/dAssimp/assimp/fileIO.d140
-rw-r--r--libs/assimp/port/dAssimp/assimp/light.d215
-rw-r--r--libs/assimp/port/dAssimp/assimp/loader.d193
-rw-r--r--libs/assimp/port/dAssimp/assimp/material.d641
-rw-r--r--libs/assimp/port/dAssimp/assimp/math.d155
-rw-r--r--libs/assimp/port/dAssimp/assimp/mesh.d465
-rw-r--r--libs/assimp/port/dAssimp/assimp/postprocess.d597
-rw-r--r--libs/assimp/port/dAssimp/assimp/scene.d306
-rw-r--r--libs/assimp/port/dAssimp/assimp/texture.d122
-rw-r--r--libs/assimp/port/dAssimp/assimp/types.d249
-rw-r--r--libs/assimp/port/dAssimp/assimp/versionInfo.d72
-rw-r--r--libs/assimp/port/iOS/IPHONEOS_ARM64E_TOOLCHAIN.cmake17
-rw-r--r--libs/assimp/port/iOS/IPHONEOS_ARM64_TOOLCHAIN.cmake17
-rw-r--r--libs/assimp/port/iOS/IPHONEOS_ARMV6_TOOLCHAIN.cmake17
-rw-r--r--libs/assimp/port/iOS/IPHONEOS_ARMV7S_TOOLCHAIN.cmake17
-rw-r--r--libs/assimp/port/iOS/IPHONEOS_ARMV7_TOOLCHAIN.cmake17
-rw-r--r--libs/assimp/port/iOS/IPHONEOS_I386_TOOLCHAIN.cmake17
-rw-r--r--libs/assimp/port/iOS/IPHONEOS_X86_64_TOOLCHAIN.cmake17
-rw-r--r--libs/assimp/port/iOS/README.md39
-rwxr-xr-xlibs/assimp/port/iOS/build.sh205
-rw-r--r--libs/assimp/port/jassimp/README56
-rw-r--r--libs/assimp/port/jassimp/build.xml54
-rw-r--r--libs/assimp/port/jassimp/jassimp-native/Android.mk13
-rw-r--r--libs/assimp/port/jassimp/jassimp-native/src/jassimp.cpp1995
-rw-r--r--libs/assimp/port/jassimp/jassimp-native/src/jassimp.h47
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiAnimBehavior.java112
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiAnimation.java175
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiBlendMode.java117
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiBone.java136
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiBoneWeight.java88
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiBuiltInWrapperProvider.java84
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiCamera.java303
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiClassLoaderIOSystem.java153
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiColor.java160
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiConfig.java15
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiConfigOptions.java663
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiIOStream.java80
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiIOSystem.java79
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiInputStreamIOStream.java127
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiLight.java387
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiLightType.java123
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiMaterial.java1199
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiMatrix4f.java133
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiMesh.java1421
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiMeshAnim.java49
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiMetadataEntry.java118
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiNode.java246
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiNodeAnim.java501
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiPostProcessSteps.java571
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiPrimitiveType.java113
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiProgressHandler.java46
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiQuaternion.java165
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiScene.java251
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiSceneFlag.java151
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiShadingMode.java168
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiTextureInfo.java224
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiTextureMapMode.java113
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiTextureMapping.java78
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiTextureOp.java137
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiTextureType.java218
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiVector.java195
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/AiWrapperProvider.java149
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/JaiDebug.java209
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/Jassimp.java402
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/JassimpConfig.java66
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/JassimpLibraryLoader.java65
-rw-r--r--libs/assimp/port/jassimp/jassimp/src/jassimp/package-info.java45
-rw-r--r--libs/assimp/port/swig/DONOTUSEYET1
-rw-r--r--libs/assimp/port/swig/assimp.i140
-rwxr-xr-xlibs/assimp/port/swig/d/build.sh2
-rwxr-xr-xlibs/assimp/port/swig/d/generate.sh4
-rw-r--r--libs/assimp/port/swig/interface/DefaultLogger.i5
-rw-r--r--libs/assimp/port/swig/interface/IOStream.i5
-rw-r--r--libs/assimp/port/swig/interface/IOSystem.i11
-rw-r--r--libs/assimp/port/swig/interface/LogStream.i5
-rw-r--r--libs/assimp/port/swig/interface/Logger.i5
-rw-r--r--libs/assimp/port/swig/interface/NullLogger.i5
-rw-r--r--libs/assimp/port/swig/interface/aiAnim.i8
-rw-r--r--libs/assimp/port/swig/interface/aiAssert.i5
-rw-r--r--libs/assimp/port/swig/interface/aiCamera.i5
-rw-r--r--libs/assimp/port/swig/interface/aiColor4D.i5
-rw-r--r--libs/assimp/port/swig/interface/aiConfig.i5
-rw-r--r--libs/assimp/port/swig/interface/aiDefines.i5
-rw-r--r--libs/assimp/port/swig/interface/aiFileIO.i5
-rw-r--r--libs/assimp/port/swig/interface/aiLight.i5
-rw-r--r--libs/assimp/port/swig/interface/aiMaterial.i33
-rw-r--r--libs/assimp/port/swig/interface/aiMatrix3x3.i5
-rw-r--r--libs/assimp/port/swig/interface/aiMatrix4x4.i5
-rw-r--r--libs/assimp/port/swig/interface/aiMesh.i29
-rw-r--r--libs/assimp/port/swig/interface/aiPostProcess.i7
-rw-r--r--libs/assimp/port/swig/interface/aiQuaternion.i5
-rw-r--r--libs/assimp/port/swig/interface/aiScene.i17
-rw-r--r--libs/assimp/port/swig/interface/aiTexture.i5
-rw-r--r--libs/assimp/port/swig/interface/aiTypes.i8
-rw-r--r--libs/assimp/port/swig/interface/aiVector2D.i5
-rw-r--r--libs/assimp/port/swig/interface/aiVector3D.i5
-rw-r--r--libs/assimp/port/swig/interface/aiVersion.i5
-rw-r--r--libs/assimp/port/swig/interface/assimp.i45
202 files changed, 27214 insertions, 0 deletions
diff --git a/libs/assimp/port/AndroidJNI/AndroidJNIIOSystem.cpp b/libs/assimp/port/AndroidJNI/AndroidJNIIOSystem.cpp
new file mode 100644
index 0000000..e0f8123
--- /dev/null
+++ b/libs/assimp/port/AndroidJNI/AndroidJNIIOSystem.cpp
@@ -0,0 +1,210 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2021, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Android extension of DefaultIOSystem using the standard C file functions */
+
+
+#include <assimp/config.h>
+#include <android/api-level.h>
+#if __ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT)
+
+#include <libgen.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <android/log.h>
+#include <android/asset_manager.h>
+#include <android/asset_manager_jni.h>
+#include <android/native_activity.h>
+#include <assimp/ai_assert.h>
+#include <assimp/port/AndroidJNI/AndroidJNIIOSystem.h>
+#include <assimp/DefaultIOStream.h>
+#include <fstream>
+
+using namespace Assimp;
+
+// ------------------------------------------------------------------------------------------------
+// Constructor.
+AndroidJNIIOSystem::AndroidJNIIOSystem(ANativeActivity* activity)
+{
+ AndroidActivityInit(activity);
+}
+
+AndroidJNIIOSystem::AndroidJNIIOSystem(const char *internalPath, AAssetManager* assetManager) :
+ mApkWorkspacePath(internalPath),
+ mApkAssetManager(assetManager) {
+ // empty
+}
+
+// ------------------------------------------------------------------------------------------------
+// Destructor.
+AndroidJNIIOSystem::~AndroidJNIIOSystem() {
+ // nothing to do here
+}
+
+// ------------------------------------------------------------------------------------------------
+// Tests for the existence of a file at the given path.
+bool AndroidJNIIOSystem::Exists( const char* pFile) const {
+ AAsset* asset = AAssetManager_open(mApkAssetManager, pFile, AASSET_MODE_UNKNOWN);
+ FILE* file = ::fopen( (mApkWorkspacePath + getOsSeparator() + std::string(pFile)).c_str(), "rb");
+
+ if (!asset && !file) {
+ __android_log_print(ANDROID_LOG_ERROR, "Assimp", "Asset manager can not find: %s", pFile);
+ return false;
+ }
+
+ __android_log_print(ANDROID_LOG_ERROR, "Assimp", "Asset exists");
+ if (file) {
+ ::fclose( file);
+ }
+
+ return true;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Inits Android extractor
+void AndroidJNIIOSystem::AndroidActivityInit(ANativeActivity* activity) {
+ if (activity == nullptr) {
+ return;
+ }
+ mApkWorkspacePath = activity->internalDataPath;
+ mApkAssetManager = activity->assetManager;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Create the directory for the extracted resource
+static int mkpath(std::string path, mode_t mode) {
+ if (mkdir(path.c_str(), mode) == -1) {
+ switch(errno) {
+ case ENOENT:
+ if (mkpath(path.substr(0, path.find_last_of('/')), mode) == -1)
+ return -1;
+ else
+ return mkdir(path.c_str(), mode);
+ case EEXIST:
+ return 0;
+ default:
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Extracts android asset
+bool AndroidJNIIOSystem::AndroidExtractAsset(std::string name) {
+ std::string newPath = mApkWorkspacePath + getOsSeparator() + name;
+
+ DefaultIOSystem io;
+
+ // Do not extract if extracted already
+ if ( io.Exists(newPath.c_str()) ) {
+ __android_log_print(ANDROID_LOG_DEFAULT, "Assimp", "Asset already extracted");
+ return true;
+ }
+
+ // Open file
+ AAsset* asset = AAssetManager_open(mApkAssetManager, name.c_str(),
+ AASSET_MODE_UNKNOWN);
+ std::vector<char> assetContent;
+
+ if (asset != NULL) {
+ // Find size
+ off_t assetSize = AAsset_getLength(asset);
+
+ // Prepare input buffer
+ assetContent.resize(assetSize);
+
+ // Store input buffer
+ AAsset_read(asset, &assetContent[0], assetSize);
+
+ // Close
+ AAsset_close(asset);
+
+ // Prepare directory for output buffer
+ std::string directoryNewPath = newPath;
+ directoryNewPath = dirname(&directoryNewPath[0]);
+
+ if (mkpath(directoryNewPath, S_IRUSR | S_IWUSR | S_IXUSR) == -1) {
+ __android_log_print(ANDROID_LOG_ERROR, "assimp", "Can not create the directory for the output file");
+ }
+
+ // Prepare output buffer
+ std::ofstream assetExtracted(newPath.c_str(), std::ios::out | std::ios::binary);
+ if (!assetExtracted) {
+ __android_log_print(ANDROID_LOG_ERROR, "assimp", "Can not open output file");
+ }
+
+ // Write output buffer into a file
+ assetExtracted.write(&assetContent[0], assetContent.size());
+ assetExtracted.close();
+
+ __android_log_print(ANDROID_LOG_DEFAULT, "Assimp", "Asset extracted");
+ } else {
+ __android_log_print(ANDROID_LOG_ERROR, "assimp", "Asset not found: %s", name.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Open a new file with a given path.
+IOStream* AndroidJNIIOSystem::Open( const char* strFile, const char* strMode) {
+ ai_assert(nullptr != strFile);
+ ai_assert(nullptr != strMode);
+
+ std::string fullPath(mApkWorkspacePath + getOsSeparator() + std::string(strFile));
+ if (Exists(strFile)) {
+ AndroidExtractAsset(std::string(strFile));
+ }
+
+ FILE* file = ::fopen( fullPath.c_str(), strMode);
+ if (nullptr == file) {
+ return nullptr;
+ }
+
+ __android_log_print(ANDROID_LOG_ERROR, "assimp", "AndroidIOSystem: file %s opened", fullPath.c_str());
+ return new DefaultIOStream(file, fullPath);
+}
+
+#undef PATHLIMIT
+#endif // __ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT)
diff --git a/libs/assimp/port/AndroidJNI/BundledAssetIOSystem.cpp b/libs/assimp/port/AndroidJNI/BundledAssetIOSystem.cpp
new file mode 100644
index 0000000..39daf99
--- /dev/null
+++ b/libs/assimp/port/AndroidJNI/BundledAssetIOSystem.cpp
@@ -0,0 +1,80 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2021, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Android extension of DefaultIOSystem using the standard C file functions */
+
+#include <assimp/ai_assert.h>
+#include <android/asset_manager.h>
+#include <assimp/DefaultIOStream.h>
+
+#if __ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT)
+
+#include <assimp/port/AndroidJNI/BundledAssetIOSystem.h>
+
+using namespace Assimp;
+
+/** Tests for the existence of a file at the given path. */
+bool BundledAssetIOSystem::Exists(const char* pFile) const {
+ ai_assert(NULL != mApkAssetManager);
+ AAsset * asset = AAssetManager_open(mApkAssetManager, pFile, AASSET_MODE_UNKNOWN);
+ if (!asset) { return false; }
+ if (asset) AAsset_close(asset);
+ return true;
+}
+
+// -------------------------------------------------------------------
+/** Open a new file with a given path. */
+Assimp::IOStream* BundledAssetIOSystem::Open(const char* pFile, const char* pMode) {
+ ai_assert(NULL != mApkAssetManager);
+ AAsset * asset = AAssetManager_open(mApkAssetManager, pFile, AASSET_MODE_UNKNOWN);
+ if (!asset) { return NULL; }
+
+ return new AssetIOStream(asset);
+}
+
+// -------------------------------------------------------------------
+/** Closes the given file and releases all resources associated with it. */
+void BundledAssetIOSystem::Close(Assimp::IOStream* pFile) {
+ delete reinterpret_cast<AssetIOStream *>(pFile);
+}
+
+#endif // __ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT)
+
diff --git a/libs/assimp/port/AndroidJNI/CMakeLists.txt b/libs/assimp/port/AndroidJNI/CMakeLists.txt
new file mode 100644
index 0000000..8c821c7
--- /dev/null
+++ b/libs/assimp/port/AndroidJNI/CMakeLists.txt
@@ -0,0 +1,16 @@
+cmake_minimum_required(VERSION 3.10)
+
+include_directories(./)
+include_directories(./../../)
+add_library( # Defines the name of the library.
+ android_jniiosystem
+
+ # Implements a static library.
+ STATIC
+
+ # relative path to source file(s).
+ AndroidJNIIOSystem.cpp
+ BundledAssetIOSystem.cpp
+)
+TARGET_LINK_LIBRARIES(android_jniiosystem android log)
+INSTALL(TARGETS android_jniiosystem EXPORT "${TARGETS_EXPORT_NAME}")
diff --git a/libs/assimp/port/AndroidJNI/README.md b/libs/assimp/port/AndroidJNI/README.md
new file mode 100644
index 0000000..003b1da
--- /dev/null
+++ b/libs/assimp/port/AndroidJNI/README.md
@@ -0,0 +1,32 @@
+Build Asset Importer Lib for Android
+====================================
+This module provides a facade 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.
+
+### Building ###
+To use this module please provide following cmake defines:
+```
+-DASSIMP_ANDROID_JNIIOSYSTEM=ON
+-DCMAKE_TOOLCHAIN_FILE=$SOME_PATH/android.toolchain.cmake
+```
+
+"SOME_PATH" is a path to your cmake android toolchain script.
+
+
+The build script for this port is based on [android-cmake](https://github.com/taka-no-me/android-cmake).
+See its documentation for more Android-specific cmake options (e.g. -DANDROID_ABI for the target ABI).
+Check [Asset-Importer-Docs](https://assimp-docs.readthedocs.io/en/latest/) for more information.
+
+### Code ###
+A small example how to wrap assimp for Android:
+```cpp
+#include <assimp/port/AndroidJNI/AndroidJNIIOSystem.h>
+
+Assimp::Importer* importer = new Assimp::Importer();
+Assimp::AndroidJNIIOSystem *ioSystem = new Assimp::AndroidJNIIOSystem(app->activity);
+if ( nullptr != iosSystem ) {
+ importer->SetIOHandler(ioSystem);
+}
+```
diff --git a/libs/assimp/port/AssimpDelphi/Readme.txt b/libs/assimp/port/AssimpDelphi/Readme.txt
new file mode 100644
index 0000000..1ec6d21
--- /dev/null
+++ b/libs/assimp/port/AssimpDelphi/Readme.txt
@@ -0,0 +1,6 @@
+This is a set of Delphi units for using the Assimp C DLL. This was created for use with Delphi 7, but should be usable as-is or with minimal modifications with later Delphi versions.
+
+This set of headers is enough to load and display a model with external textures. Since I'm not familiar with animated models and some of the other functionality of the assimp library, I did not convert the headers for those features.
+
+See http://sourceforge.net/tracker/?func=detail&aid=3212646&group_id=226462&atid=1067634 for the original patch
+
diff --git a/libs/assimp/port/AssimpDelphi/aiColor4D.pas b/libs/assimp/port/AssimpDelphi/aiColor4D.pas
new file mode 100644
index 0000000..0bc5d2a
--- /dev/null
+++ b/libs/assimp/port/AssimpDelphi/aiColor4D.pas
@@ -0,0 +1,17 @@
+unit aiColor4D;
+
+interface
+
+const AI_MAX_NUMBER_OF_COLOR_SETS = $04;
+
+type TaiColor4D = packed record
+ r, g, b, a: single;
+end;
+type PaiColor4D = ^TaiColor4D;
+
+type TaiColor4DArray = array[0..0] of TaiColor4D;
+type PTaiColor4DArray = ^TaiColor4DArray;
+
+implementation
+
+end.
diff --git a/libs/assimp/port/AssimpDelphi/aiMaterial.pas b/libs/assimp/port/AssimpDelphi/aiMaterial.pas
new file mode 100644
index 0000000..ffd8109
--- /dev/null
+++ b/libs/assimp/port/AssimpDelphi/aiMaterial.pas
@@ -0,0 +1,153 @@
+unit aiMaterial;
+
+interface
+
+uses aiTypes, aiVector2D, aiVector3D;
+
+{This following directive causes enums to be stored as double words (32bit), to be compatible with
+ the assimp C Dll}
+{$Z4}
+
+type TaiTextureOp = (
+ aiTextureOp_Multiply = $0,
+ aiTextureOp_Add = $1,
+ aiTextureOp_Subtract = $2,
+ aiTextureOp_Divide = $3,
+ aiTextureOp_SmoothAdd = $4,
+ aiTextureOp_SignedAdd = $5
+ //_aiTextureOp_Force32Bit = 0x9fffffff
+);
+
+type TaiTextureMapMode = (
+ aiTextureMapMode_Wrap = $0,
+ aiTextureMapMode_Clamp = $1,
+ aiTextureMapMode_Decal = $3,
+ aiTextureMapMode_Mirror = $2
+ //_aiTextureMapMode_Force32Bit = 0x9fffffff
+);
+
+type TaiTextureMapping = (
+ aiTextureMapping_UV = $0,
+ aiTextureMapping_SPHERE = $1,
+ aiTextureMapping_CYLINDER = $2,
+ aiTextureMapping_BOX = $3,
+ aiTextureMapping_PLANE = $4,
+ aiTextureMapping_OTHER = $5
+ //_aiTextureMapping_Force32Bit = 0x9fffffff
+);
+
+type TaiTextureType = (
+ aiTextureType_NONE = $0,
+ aiTextureType_DIFFUSE = $1,
+ aiTextureType_SPECULAR = $2,
+ aiTextureType_AMBIENT = $3,
+ aiTextureType_EMISSIVE = $4,
+ aiTextureType_HEIGHT = $5,
+ aiTextureType_NORMALS = $6,
+ aiTextureType_SHININESS = $7,
+ aiTextureType_OPACITY = $8,
+ aiTextureType_DISPLACEMENT = $9,
+ aiTextureType_LIGHTMAP = $A,
+ aiTextureType_REFLECTION = $B,
+ aiTextureType_UNKNOWN = $C
+ //_aiTextureType_Force32Bit = 0x9fffffff
+);
+
+const AI_TEXTURE_TYPE_MAX = aiTextureType_UNKNOWN;
+
+type TaiShadingMode = (
+ aiShadingMode_Flat = $1,
+ aiShadingMode_Gouraud = $2,
+ aiShadingMode_Phong = $3,
+ aiShadingMode_Blinn = $4,
+ aiShadingMode_Toon = $5,
+ aiShadingMode_OrenNayar = $6,
+ aiShadingMode_Minnaert = $7,
+ aiShadingMode_CookTorrance = $8,
+ aiShadingMode_NoShading = $9,
+ aiShadingMode_Fresnel = $A
+ //_aiShadingMode_Force32Bit = 0x9fffffff
+);
+
+
+type TaiTextureFlags = (
+ aiTextureFlags_Invert = $1,
+ aiTextureFlags_UseAlpha = $2,
+ aiTextureFlags_IgnoreAlpha = $4
+ //_aiTextureFlags_Force32Bit = 0x9fffffff
+);
+
+type TaiBlendMode = (
+ aiBlendMode_Default = $0,
+ aiBlendMode_Additive = $1
+ //_aiBlendMode_Force32Bit = 0x9fffffff
+);
+
+type TaiUVTransform = packed record
+ mTranslation: TaiVector2D;
+ mScaling: TaiVector2D;
+ mRotation: single;
+end;
+
+type TaiPropertyTypeInfo = (
+ aiPTI_Float = $1,
+ aiPTI_String = $3,
+ aiPTI_Integer = $4,
+ aiPTI_Buffer = $5
+ // _aiPTI_Force32Bit = 0x9fffffff
+);
+
+type TaiMaterialProperty = packed record
+ mKey: aiString;
+ mSemantic: Cardinal;
+ mIndex: Cardinal;
+ mDataLength: Cardinal;
+ mType: TaiPropertyTypeInfo;
+ mData: PChar;
+end;
+type PaiMaterialProperty = ^TaiMaterialProperty;
+
+type TaiMaterial = packed record
+ mProperties: pointer;
+ mNumProperties: Cardinal;
+ mNumAllocated: Cardinal;
+end;
+type PaiMaterial = ^TaiMaterial;
+type PaiMaterialArray = array[0..0] of PaiMaterial;
+type PPaiMaterialArray = ^PaiMaterialArray;
+
+const AI_MATKEY_NAME = '?mat.name';
+const AI_MATKEY_TWOSIDED = '$mat.twosided';
+const AI_MATKEY_SHADING_MODEL = '$mat.shadingm';
+const AI_MATKEY_ENABLE_WIREFRAME = '$mat.wireframe';
+const AI_MATKEY_BLEND_FUNC = '$mat.blend';
+const AI_MATKEY_OPACITY = '$mat.opacity';
+const AI_MATKEY_BUMPSCALING = '$mat.bumpscaling';
+const AI_MATKEY_SHININESS = '$mat.shininess';
+const AI_MATKEY_REFLECTIVITY = '$mat.reflectivity';
+const AI_MATKEY_SHININESS_STRENGTH = '$mat.shinpercent';
+const AI_MATKEY_REFRACTI = '$mat.refracti';
+const AI_MATKEY_COLOR_DIFFUSE = '$clr.diffuse';
+const AI_MATKEY_COLOR_AMBIENT = '$clr.ambient';
+const AI_MATKEY_COLOR_SPECULAR = '$clr.specular';
+const AI_MATKEY_COLOR_EMISSIVE = '$clr.emissive';
+const AI_MATKEY_COLOR_TRANSPARENT = '$clr.transparent';
+const AI_MATKEY_COLOR_REFLECTIVE = '$clr.reflective';
+const AI_MATKEY_GLOBAL_BACKGROUND_IMAGE = '?bg.global';
+
+const _AI_MATKEY_TEXTURE_BASE = '$tex.file';
+const _AI_MATKEY_UVWSRC_BASE = '$tex.uvwsrc';
+const _AI_MATKEY_TEXOP_BASE = '$tex.op';
+const _AI_MATKEY_MAPPING_BASE = '$tex.mapping';
+const _AI_MATKEY_TEXBLEND_BASE = '$tex.blend';
+const _AI_MATKEY_MAPPINGMODE_U_BASE = '$tex.mapmodeu';
+const _AI_MATKEY_MAPPINGMODE_V_BASE = '$tex.mapmodev';
+const _AI_MATKEY_TEXMAP_AXIS_BASE = '$tex.mapaxis';
+const _AI_MATKEY_UVTRANSFORM_BASE = '$tex.uvtrafo';
+const _AI_MATKEY_TEXFLAGS_BASE = '$tex.flags';
+
+
+
+implementation
+
+end.
diff --git a/libs/assimp/port/AssimpDelphi/aiMatrix3x3.pas b/libs/assimp/port/AssimpDelphi/aiMatrix3x3.pas
new file mode 100644
index 0000000..a90f11f
--- /dev/null
+++ b/libs/assimp/port/AssimpDelphi/aiMatrix3x3.pas
@@ -0,0 +1,16 @@
+unit aiMatrix3x3;
+
+interface
+
+type TaiMatrix3x3 = packed record
+ a1, a2, a3, a4: single;
+ b1, b2, b3, b4: single;
+ c1, c2, c3, c4: single;
+end;
+PaiMatrix3x3 = ^TaiMatrix3x3;
+
+
+
+implementation
+
+end.
diff --git a/libs/assimp/port/AssimpDelphi/aiMatrix4x4.pas b/libs/assimp/port/AssimpDelphi/aiMatrix4x4.pas
new file mode 100644
index 0000000..45e0faf
--- /dev/null
+++ b/libs/assimp/port/AssimpDelphi/aiMatrix4x4.pas
@@ -0,0 +1,16 @@
+unit aiMatrix4x4;
+
+interface
+
+type TaiMatrix4x4 = packed record
+ a1, a2, a3, a4: single;
+ b1, b2, b3, b4: single;
+ c1, c2, c3, c4: single;
+ d1, d2, d3, d4: single;
+end;
+PaiMatrix4x4 = ^TaiMatrix4x4;
+
+
+implementation
+
+end.
diff --git a/libs/assimp/port/AssimpDelphi/aiMesh.pas b/libs/assimp/port/AssimpDelphi/aiMesh.pas
new file mode 100644
index 0000000..a05a0f2
--- /dev/null
+++ b/libs/assimp/port/AssimpDelphi/aiMesh.pas
@@ -0,0 +1,71 @@
+unit aiMesh;
+
+interface
+
+uses aiTypes, aiMatrix4x4, aiVector3D, aiColor4D;
+
+const
+ AI_MAX_NUMBER_OF_COLOR_SETS = $4;
+ AI_MAX_NUMBER_OF_TEXTURECOORDS = $4;
+
+type TaiFace = packed record
+ mNumIndicies: cardinal;
+ mIndices: PCardinalArray;
+end;
+type PaiFace = ^TaiFace;
+type PaiFaceArray = array [0..0] of PaiFace;
+
+type TaiFaceArray = array [0..0] of TaiFace;
+type PTaiFaceArray = ^TaiFaceArray;
+
+type TaiVertexWeight = packed record
+ mVertexId: cardinal;
+ mWeight: single;
+end;
+
+type TaiBone = packed record
+ mName: aiString;
+ mNumWeights: cardinal;
+ mWeights: Pointer;
+ mOffsetMatrix: TaiMatrix4x4;
+end;
+type PaiBone = ^TaiBone;
+
+type TaiPrimitiveType =
+ (
+ aiPrimitiveType_POINT = $1,
+ aiPrimitiveType_LINE = $2,
+ aiPrimitiveType_TRIANGLE = $4,
+ aiPrimitiveType_POLYGON = $8
+ //,_aiPrimitiveType_Force32Bit = $9fffffff
+ );
+
+type TaiMesh = packed record
+ mPrimitiveTypes: cardinal;
+ mNumVertices: cardinal;
+ mNumFaces: cardinal;
+ mVertices: PTaiVector3DArray;
+ mNormals: PTaiVector3DArray;
+ mTangents: PaiVector3DArray;
+ mBitangents: PaiVector3DArray;
+ mColors: array[0..3] of PTaiColor4Darray; //array [0..3] of PaiColor4DArray; //array of 4
+ mTextureCoords: array [0..3] of PTaiVector3DArray; //array of 4
+ mNumUVComponents: array[0..AI_MAX_NUMBER_OF_TEXTURECOORDS -1] of cardinal;
+ mFaces: PTaiFaceArray;
+ mNumBones: cardinal;
+ mBones: PaiBone;
+ mMaterialIndex: cardinal;
+ mName: aiString;
+ mNumAniMeshes: cardinal;
+ mAniMeshes: pointer;
+end;
+type PaiMesh = ^TaiMesh;
+type PPaiMesh = ^PaiMesh;
+type PaiMeshArray = array [0..0] of PaiMesh;
+type PPaiMeshArray = ^PaiMeshArray;
+
+
+
+implementation
+
+end.
diff --git a/libs/assimp/port/AssimpDelphi/aiQuaternion.pas b/libs/assimp/port/AssimpDelphi/aiQuaternion.pas
new file mode 100644
index 0000000..d5550de
--- /dev/null
+++ b/libs/assimp/port/AssimpDelphi/aiQuaternion.pas
@@ -0,0 +1,12 @@
+unit aiQuaternion;
+
+interface
+
+type TaiQuaternion = packed record
+ w, x, y, z: single;
+end;
+type PaiQuaternion = ^TaiQuaternion;
+
+implementation
+
+end.
diff --git a/libs/assimp/port/AssimpDelphi/aiScene.pas b/libs/assimp/port/AssimpDelphi/aiScene.pas
new file mode 100644
index 0000000..28cebf1
--- /dev/null
+++ b/libs/assimp/port/AssimpDelphi/aiScene.pas
@@ -0,0 +1,46 @@
+unit aiScene;
+
+interface
+
+uses aiTypes, aiMatrix4x4, aiMesh, aiMaterial, aiTexture;
+
+
+type
+ PaiNode = ^TaiNode;
+ PPaiNode = ^PaiNode;
+ PaiNodeArray = array[0..0] of PaiNode;
+ PPaiNodeArray = ^PaiNodeArray;
+
+ TaiNode = packed record
+ mName: aiString;
+ mTransformation: TaiMatrix4x4;
+ mParent: PPaiNode;
+ mNumChildren: cardinal;
+ mChildren: PPaiNodeArray;
+ mNumMeshes: cardinal;
+ mMeshes: PCardinalArray;
+ end;
+
+
+
+type TaiScene = packed record
+ mFlags: cardinal;
+ mRootNode: PaiNode;
+ mNumMeshes: Cardinal;
+ mMeshes: PPaiMeshArray; //?
+ mNumMaterials: Cardinal;
+ mMaterials: PPaiMaterialArray;
+ mNumAnimations: Cardinal;
+ mAnimations: Pointer;
+ mNumTextures: Cardinal;
+ mTextures: PPaiTextureArray;
+ mNumLights: Cardinal;
+ mLights: Pointer;
+ mNumCameras: Cardinal;
+ mCameras: Pointer;
+end;
+type PaiScene = ^TaiScene;
+
+implementation
+
+end.
diff --git a/libs/assimp/port/AssimpDelphi/aiTexture.pas b/libs/assimp/port/AssimpDelphi/aiTexture.pas
new file mode 100644
index 0000000..55e246f
--- /dev/null
+++ b/libs/assimp/port/AssimpDelphi/aiTexture.pas
@@ -0,0 +1,26 @@
+unit aiTexture;
+
+interface
+
+type TaiTexel = packed record
+ b, g, r, a: byte;
+end;
+PaiTexel = ^TaiTexel;
+TaiTexelArray = array[0..0] of TaiTexel;
+PaiTexelArray = ^TaiTexelArray;
+
+type TaiTexture = packed record
+ mWidth: Cardinal; //width in pixels, OR total embedded file size if texture is a jpg/png/etc
+ mHeight: Cardinal; //0 if texture is an embedded file
+ achFormatHint: array[0..3] of byte;
+ pcData: PaiTexelArray;
+end;
+PaiTexture = ^TaiTexture;
+PaiTextureArray = array [0..0] of PaiTexture;
+PPaiTextureArray = ^PaiTextureArray;
+
+
+
+implementation
+
+end.
diff --git a/libs/assimp/port/AssimpDelphi/aiTypes.pas b/libs/assimp/port/AssimpDelphi/aiTypes.pas
new file mode 100644
index 0000000..b7924e8
--- /dev/null
+++ b/libs/assimp/port/AssimpDelphi/aiTypes.pas
@@ -0,0 +1,53 @@
+unit aiTypes;
+
+interface
+
+//added for Delphi interface
+type
+ TCardinalArray = array [0..0] of Cardinal;
+ PCardinalArray = ^TCardinalArray;
+
+ TSingleArray = array[0..0] of Single;
+ PSingleArray = ^TSingleArray;
+
+type aiString = packed record
+ length: Cardinal;
+ data: array [0..1023] of char;
+end;
+type PaiString = ^aiString;
+
+type aiReturn = (
+ aiReturn_SUCCESS = $0,
+ aiReturn_FAILURE = -$1,
+ aiReturn_OUTOFMEMORY = -$3,
+ _AI_ENFORCE_ENUM_SIZE = $7fffffff
+);
+
+const AI_SUCCESS = aiReturn_SUCCESS;
+const AI_FAILURE = aiReturn_FAILURE;
+const AI_OUTOFMEMORY = aiReturn_OUTOFMEMORY;
+
+
+
+
+function aiStringToDelphiString( a: aiString): AnsiString;
+
+
+implementation
+
+function aiStringToDelphiString( a: aiString): AnsiString;
+var
+ i: integer;
+begin
+ result := '';
+ if a.length > 0 then
+ begin
+ SetLength( result, a.length);
+ for i := 1 to a.length do
+ begin
+ result[i] := a.data[i-1];
+ end;
+ end;
+end;
+
+end.
diff --git a/libs/assimp/port/AssimpDelphi/aiVector2D.pas b/libs/assimp/port/AssimpDelphi/aiVector2D.pas
new file mode 100644
index 0000000..1e88209
--- /dev/null
+++ b/libs/assimp/port/AssimpDelphi/aiVector2D.pas
@@ -0,0 +1,13 @@
+unit aiVector2D;
+
+interface
+
+type TaiVector2D = packed record
+ x, y: single;
+end;
+type PaiVector2D = ^TaiVector2D;
+
+
+implementation
+
+end.
diff --git a/libs/assimp/port/AssimpDelphi/aiVector3D.pas b/libs/assimp/port/AssimpDelphi/aiVector3D.pas
new file mode 100644
index 0000000..2081bb4
--- /dev/null
+++ b/libs/assimp/port/AssimpDelphi/aiVector3D.pas
@@ -0,0 +1,16 @@
+unit aiVector3D;
+
+interface
+
+type TaiVector3D = packed record
+ x, y, z: single;
+end;
+type PaiVector3D = ^TaiVector3D;
+type PaiVector3DArray = array [0..0] of PaiVector3D;
+
+type TaiVector3DArray = array[0..0] of TaiVector3D;
+type PTaiVector3DArray = ^TaiVector3DArray;
+
+implementation
+
+end.
diff --git a/libs/assimp/port/AssimpDelphi/assimp.pas b/libs/assimp/port/AssimpDelphi/assimp.pas
new file mode 100644
index 0000000..d5bf31d
--- /dev/null
+++ b/libs/assimp/port/AssimpDelphi/assimp.pas
@@ -0,0 +1,58 @@
+unit assimp;
+
+interface
+
+uses aiTypes, aiMatrix4x4, aiMatrix3x3, aiMesh, aiScene, aiMaterial, aiColor4d, aiVector3D;
+
+const ASSIMP_DLL = 'assimp32.dll';
+
+function aiImportFile(filename: pchar; pFlags: integer): PaiScene; cdecl; external ASSIMP_DLL;
+procedure aiReleaseImport( pScene: pointer); cdecl; external ASSIMP_DLL;
+function aiGetErrorString(): PChar; cdecl; external ASSIMP_DLL;
+
+//procedure aiDecomposeMatrix( var mat: TaiMatrix4x4; var scaling: TaiVector3D; var rotation: TaiQuaternion; var position: TaiVector3D); cdecl; external ASSIMP_DLL;
+procedure aiTransposeMatrix4( var mat: TaiMatrix4x4); cdecl; external ASSIMP_DLL;
+procedure aiTransposeMatrix3( var mat: TaiMatrix3x3); cdecl; external ASSIMP_DLL;
+procedure aiTransformVecByMatrix3( var vec: TaiVector3D; var mat: TaiMatrix3x3); cdecl; external ASSIMP_DLL;
+procedure aiTransformVecByMatrix4( var vec: TaiVector3D; var mat: TaiMatrix4x4); cdecl; external ASSIMP_DLL;
+
+procedure aiMultiplyMatrix4(var dst: TaiMatrix4x4; var src: TaiMatrix4x4); cdecl; external ASSIMP_DLL;
+procedure aiMultiplyMatrix3(var dst: TaiMatrix3x3; var src: TaiMatrix3x3); cdecl; external ASSIMP_DLL;
+
+
+procedure aiIdentityMatrix3(var mat: TaiMatrix3x3); cdecl; external ASSIMP_DLL;
+procedure aiIdentityMatrix4(var mat: TaiMatrix4x4); cdecl; external ASSIMP_DLL;
+
+
+//----- from aiMaterial.h
+function aiGetMaterialProperty( pMat: PaiMaterial; pKey: PChar; nType: Cardinal; nIndex: Cardinal; pPropOut: pointer): aiReturn; cdecl; external ASSIMP_DLL;
+function aiGetMaterialFloatArray( var pMat: TaiMaterial; pKey: PChar; nType: Cardinal; nIndex: Cardinal; var pOut: Single; var pMax: Cardinal): aiReturn; cdecl; external ASSIMP_DLL;
+function aiGetMaterialFloat( var pMat: TaiMaterial; pKey: PChar; nType: Cardinal; nIndex: Cardinal; var pOut: Single): aiReturn;
+function aiGetMaterialIntegerArray(var pMat: TaiMaterial; pKey: PChar; nType: Cardinal; nIndex: Cardinal; var pOut: Integer; var pMax: Cardinal): aiReturn; cdecl; external ASSIMP_DLL;
+function aiGetMaterialInteger(var pMat: TaiMaterial; pKey: PChar; nType: Cardinal; nIndex: Cardinal; var pOut: Integer): aiReturn;
+function aiGetMaterialColor(var pMat: TaiMaterial; pKey: PChar; nType: Cardinal; nIndex: Cardinal; var pOut: TaiColor4d): aiReturn; cdecl; external ASSIMP_DLL;
+function aiGetMaterialString(var pMat: TaiMaterial; pKey: PChar; nType: Cardinal; nIndex: Cardinal; var pOut: aiString): aiReturn; cdecl; external ASSIMP_DLL;
+function aiGetMaterialTextureCount(var pMat: TaiMaterial; nType: TaiTextureType): Cardinal; cdecl; external ASSIMP_DLL;
+function aiGetMaterialTexture(var mat: TaiMaterial; nType: TaiTextureType; nIndex: Cardinal; var path: aiString; var mapping: TaiTextureMapping; var uvindex: Cardinal; var blend: single; var op: TaiTextureOp; var mapmode: TaiTextureMapMode; var flags: Cardinal): aiReturn; cdecl; external ASSIMP_DLL;
+
+
+
+implementation
+
+function aiGetMaterialFloat( var pMat: TaiMaterial; pKey: PChar; nType: Cardinal; nIndex: Cardinal; var pOut: Single): aiReturn;
+var
+ n: cardinal;
+begin
+ n := 0;
+ result := aiGetMaterialFloatArray( pMat, pKey, nType, nIndex, pOut, n);
+end;
+
+function aiGetMaterialInteger(var pMat: TaiMaterial; pKey: PChar; nType: Cardinal; nIndex: Cardinal; var pOut: integer): aiReturn;
+var
+ n: cardinal;
+begin
+ n := 0;
+ result := aiGetMaterialIntegerArray( pMat, pKey, nType, nIndex, pOut, n);
+end;
+
+end.
diff --git a/libs/assimp/port/AssimpNET/Readme.md b/libs/assimp/port/AssimpNET/Readme.md
new file mode 100644
index 0000000..814cab3
--- /dev/null
+++ b/libs/assimp/port/AssimpNET/Readme.md
@@ -0,0 +1 @@
+Please check the following git-repo for the source: https://github.com/kebby/assimp-net
diff --git a/libs/assimp/port/AssimpPascal/Readme.md b/libs/assimp/port/AssimpPascal/Readme.md
new file mode 100644
index 0000000..9dfc652
--- /dev/null
+++ b/libs/assimp/port/AssimpPascal/Readme.md
@@ -0,0 +1 @@
+See the [AssimpPascal headers here](https://github.com/ev1313/Pascal-Assimp-Headers) (by Tim Blume / ev1313).
diff --git a/libs/assimp/port/PyAssimp/3d_viewer_screenshot.png b/libs/assimp/port/PyAssimp/3d_viewer_screenshot.png
new file mode 100644
index 0000000..2031faf
--- /dev/null
+++ b/libs/assimp/port/PyAssimp/3d_viewer_screenshot.png
Binary files differ
diff --git a/libs/assimp/port/PyAssimp/README.md b/libs/assimp/port/PyAssimp/README.md
new file mode 100644
index 0000000..c9944f7
--- /dev/null
+++ b/libs/assimp/port/PyAssimp/README.md
@@ -0,0 +1,86 @@
+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`:
+
+```console
+$ cd scripts
+$ python ./3D-viewer <path to your model>
+```
+
+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 load
+with load('hello.3ds') as scene:
+
+ assert len(scene.meshes)
+ mesh = scene.meshes[0]
+
+ assert len(mesh.vertices)
+ print(mesh.vertices[0])
+
+```
+
+Another example to list the 'top nodes' in a
+scene:
+
+```python
+
+from pyassimp import load
+with load('hello.3ds') as scene:
+
+ for c in scene.rootnode.children:
+ print(str(c))
+
+```
+
+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`
+
+To build that library, refer to the Assimp master `INSTALL`
+instructions. To look in more places, edit `./pyassimp/helper.py`.
+There's an `additional_dirs` list waiting for your entries.
diff --git a/libs/assimp/port/PyAssimp/README.rst b/libs/assimp/port/PyAssimp/README.rst
new file mode 100644
index 0000000..03b7968
--- /dev/null
+++ b/libs/assimp/port/PyAssimp/README.rst
@@ -0,0 +1,93 @@
+PyAssimp: Python bindings for libassimp
+=======================================
+
+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.
+
+.. figure:: 3d_viewer_screenshot.png
+ :alt: Screenshot
+
+ Screenshot
+
+To use it, from within ``/port/PyAssimp``:
+
+::
+
+ $ cd scripts
+ $ python ./3D-viewer <path to your model>
+
+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 ...):
+
+.. code:: python
+
+
+ from pyassimp import load
+ with load('hello.3ds') as scene:
+
+ assert len(scene.meshes)
+ mesh = scene.meshes[0]
+
+ assert len(mesh.vertices)
+ print(mesh.vertices[0])
+
+
+Another example to list the 'top nodes' in a scene:
+
+.. code:: python
+
+
+ from pyassimp import load
+ with load('hello.3ds') as scene:
+
+ for c in scene.rootnode.children:
+ print(str(c))
+
+
+INSTALL
+-------
+
+Install ``pyassimp`` by running:
+
+::
+
+ $ python setup.py install
+
+PyAssimp requires a assimp dynamic library (``DLL`` on windows, ``.so``
+on linux, ``.dynlib`` on macOS) in order to work. The default search
+directories are:
+
+- the current directory
+- on linux additionally: ``/usr/lib``, ``/usr/local/lib``,
+ ``/usr/lib/x86_64-linux-gnu``
+
+To build that library, refer to the Assimp master ``INSTALL``
+instructions. To look in more places, edit ``./pyassimp/helper.py``.
+There's an ``additional_dirs`` list waiting for your entries.
diff --git a/libs/assimp/port/PyAssimp/gen/materialgen.py b/libs/assimp/port/PyAssimp/gen/materialgen.py
new file mode 100644
index 0000000..ef32d8e
--- /dev/null
+++ b/libs/assimp/port/PyAssimp/gen/materialgen.py
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+# -*- Coding: UTF-8 -*-
+
+# ---------------------------------------------------------------------------
+# Open Asset Import Library (ASSIMP)
+# ---------------------------------------------------------------------------
+#
+# Copyright (c) 2006-2020, ASSIMP Development 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 Development 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.
+# ---------------------------------------------------------------------------
+
+"""Update PyAssimp's texture type constants C/C++ headers.
+
+This script is meant to be executed in the source tree, directly from
+port/PyAssimp/gen
+"""
+
+import os
+import re
+
+REenumTextureType = re.compile(r''
+ r'enum\saiTextureType' # enum aiTextureType
+ r'[^{]*?\{' # {
+ r'(?P<code>.*?)' # code
+ r'\};' # };
+ , re.IGNORECASE + re.DOTALL + re.MULTILINE)
+
+# Replace comments
+RErpcom = re.compile(r''
+ r'\s*(/\*+\s|\*+/|\B\*\s?|///?!?)' # /**
+ r'(?P<line>.*?)' # * line
+ , re.IGNORECASE + re.DOTALL)
+
+# Remove trailing commas
+RErmtrailcom = re.compile(r',$', re.IGNORECASE + re.DOTALL)
+
+# Remove #ifdef __cplusplus
+RErmifdef = re.compile(r''
+ r'#ifndef SWIG' # #ifndef SWIG
+ r'(?P<code>.*)' # code
+ r'#endif(\s*//\s*!?\s*SWIG)*' # #endif
+ , re.IGNORECASE + re.DOTALL)
+
+path = '../../../include/assimp'
+
+files = os.listdir (path)
+enumText = ''
+for fileName in files:
+ if fileName.endswith('.h'):
+ text = open(os.path.join(path, fileName)).read()
+ for enum in REenumTextureType.findall(text):
+ enumText = enum
+
+text = ''
+for line in enumText.split('\n'):
+ line = line.lstrip().rstrip()
+ line = RErmtrailcom.sub('', line)
+ text += RErpcom.sub('# \g<line>', line) + '\n'
+text = RErmifdef.sub('', text)
+
+file = open('material.py', 'w')
+file.write(text)
+file.close()
+
+print("Generation done. You can now review the file 'material.py' and merge it.")
diff --git a/libs/assimp/port/PyAssimp/gen/structsgen.py b/libs/assimp/port/PyAssimp/gen/structsgen.py
new file mode 100644
index 0000000..f34ec19
--- /dev/null
+++ b/libs/assimp/port/PyAssimp/gen/structsgen.py
@@ -0,0 +1,290 @@
+#!/usr/bin/env python
+# -*- Coding: UTF-8 -*-
+
+# ---------------------------------------------------------------------------
+# Open Asset Import Library (ASSIMP)
+# ---------------------------------------------------------------------------
+#
+# Copyright (c) 2006-2020, ASSIMP Development 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 Development 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.
+# ---------------------------------------------------------------------------
+
+"""Update PyAssimp's data structures to keep up with the
+C/C++ headers.
+
+This script is meant to be executed in the source tree, directly from
+port/PyAssimp/gen
+"""
+
+import os
+import re
+
+#==[regexps]=================================================
+
+# Clean desc
+REdefine = re.compile(r''
+ r'(?P<desc>)' # /** *desc */
+ r'#\s*define\s(?P<name>[^(\n]+?)\s(?P<code>.+)$' # #define name value
+ , re.MULTILINE)
+
+# Get structs
+REstructs = re.compile(r''
+ #r'//\s?[\-]*\s(?P<desc>.*?)\*/\s' # /** *desc */
+ #r'//\s?[\-]*(?P<desc>.*?)\*/(?:.*?)' # garbage
+ r'//\s?[\-]*\s(?P<desc>.*?)\*/\W*?' # /** *desc */
+ r'struct\s(?:ASSIMP_API\s)?(?P<name>[a-z][a-z0-9_]\w+\b)' # struct name
+ r'[^{]*?\{' # {
+ r'(?P<code>.*?)' # code
+ r'\}\s*(PACK_STRUCT)?;' # };
+ , re.IGNORECASE + re.DOTALL + re.MULTILINE)
+
+# Clean desc
+REdesc = re.compile(r''
+ r'^\s*?([*]|/\*\*)(?P<line>.*?)' # * line
+ , re.IGNORECASE + re.DOTALL + re.MULTILINE)
+
+# Remove #ifdef __cplusplus
+RErmifdef = re.compile(r''
+ r'#ifdef __cplusplus' # #ifdef __cplusplus
+ r'(?P<code>.*)' # code
+ r'#endif(\s*//\s*!?\s*__cplusplus)*' # #endif
+ , re.IGNORECASE + re.DOTALL)
+
+# Replace comments
+RErpcom = re.compile(r''
+ r'\s*(/\*+\s|\*+/|\B\*\s|///?!?)' # /**
+ r'(?P<line>.*?)' # * line
+ , re.IGNORECASE + re.DOTALL)
+
+# Restructure
+def GetType(type, prefix='c_'):
+ t = type
+ while t.endswith('*'):
+ t = t[:-1]
+ if t[:5] == 'const':
+ t = t[5:]
+
+ # skip some types
+ if t in skiplist:
+ return None
+
+ t = t.strip()
+ types = {'unsigned int':'uint', 'unsigned char':'ubyte',}
+ if t in types:
+ t = types[t]
+ t = prefix + t
+ while type.endswith('*'):
+ t = "POINTER(" + t + ")"
+ type = type[:-1]
+ return t
+
+def restructure( match ):
+ type = match.group("type")
+ if match.group("struct") == "":
+ type = GetType(type)
+ elif match.group("struct") == "C_ENUM ":
+ type = "c_uint"
+ else:
+ type = GetType(type[2:], '')
+ if type is None:
+ return ''
+ if match.group("index"):
+ type = type + "*" + match.group("index")
+
+ result = ""
+ for name in match.group("name").split(','):
+ result += "(\"" + name.strip() + "\", "+ type + "),"
+
+ return result
+
+RErestruc = re.compile(r''
+ r'(?P<struct>C_STRUCT\s|C_ENUM\s|)' # [C_STRUCT]
+ r'(?P<type>\w+\s?\w+?[*]*)\s' # type
+ #r'(?P<name>\w+)' # name
+ r'(?P<name>\w+|[a-z0-9_, ]+)' # name
+ r'(:?\[(?P<index>\w+)\])?;' # []; (optional)
+ , re.DOTALL)
+#==[template]================================================
+template = """
+class $NAME$(Structure):
+ \"\"\"
+$DESCRIPTION$
+ \"\"\"
+$DEFINES$
+ _fields_ = [
+ $FIELDS$
+ ]
+"""
+
+templateSR = """
+class $NAME$(Structure):
+ \"\"\"
+$DESCRIPTION$
+ \"\"\"
+$DEFINES$
+
+$NAME$._fields_ = [
+ $FIELDS$
+ ]
+"""
+
+skiplist = ("FileIO", "File", "locateFromAssimpHeap",'LogStream','MeshAnim','AnimMesh')
+
+#============================================================
+def Structify(fileName):
+ file = open(fileName, 'r')
+ text = file.read()
+ result = []
+
+ # Get defines.
+ defs = REdefine.findall(text)
+ # Create defines
+ defines = "\n"
+ for define in defs:
+ # Clean desc
+ desc = REdesc.sub('', define[0])
+ # Replace comments
+ desc = RErpcom.sub('#\g<line>', desc)
+ defines += desc
+ if len(define[2].strip()):
+ # skip non-integral defines, we can support them right now
+ try:
+ int(define[2],0)
+ except:
+ continue
+ defines += " "*4 + define[1] + " = " + define[2] + "\n"
+
+
+ # Get structs
+ rs = REstructs.finditer(text)
+
+ fileName = os.path.basename(fileName)
+ print fileName
+ for r in rs:
+ name = r.group('name')[2:]
+ desc = r.group('desc')
+
+ # Skip some structs
+ if name in skiplist:
+ continue
+
+ text = r.group('code')
+
+ # Clean desc
+ desc = REdesc.sub('', desc)
+
+ desc = "See '"+ fileName +"' for details." #TODO
+
+ # Remove #ifdef __cplusplus
+ text = RErmifdef.sub('', text)
+
+ # Whether the struct contains more than just POD
+ primitive = text.find('C_STRUCT') == -1
+
+ # Restructure
+ text = RErestruc.sub(restructure, text)
+ # Replace comments
+ text = RErpcom.sub('# \g<line>', text)
+ text = text.replace("),#", "),\n#")
+ text = text.replace("#", "\n#")
+ text = "".join([l for l in text.splitlines(True) if not l.strip().endswith("#")]) # remove empty comment lines
+
+ # Whether it's selfreferencing: ex. struct Node { Node* parent; };
+ selfreferencing = text.find('POINTER('+name+')') != -1
+
+ complex = name == "Scene"
+
+ # Create description
+ description = ""
+ for line in desc.split('\n'):
+ description += " "*4 + line.strip() + "\n"
+ description = description.rstrip()
+
+ # Create fields
+ fields = ""
+ for line in text.split('\n'):
+ fields += " "*12 + line.strip() + "\n"
+ fields = fields.strip()
+
+ if selfreferencing:
+ templ = templateSR
+ else:
+ templ = template
+
+ # Put it all together
+ text = templ.replace('$NAME$', name)
+ text = text.replace('$DESCRIPTION$', description)
+ text = text.replace('$FIELDS$', fields)
+
+ if ((name.lower() == fileName.split('.')[0][2:].lower()) and (name != 'Material')) or name == "String":
+ text = text.replace('$DEFINES$', defines)
+ else:
+ text = text.replace('$DEFINES$', '')
+
+
+ result.append((primitive, selfreferencing, complex, text))
+
+ return result
+
+text = "#-*- coding: UTF-8 -*-\n\n"
+text += "from ctypes import POINTER, c_int, c_uint, c_size_t, c_char, c_float, Structure, c_char_p, c_double, c_ubyte\n\n"
+
+structs1 = ""
+structs2 = ""
+structs3 = ""
+structs4 = ""
+
+path = '../../../include/assimp'
+files = os.listdir (path)
+#files = ["aiScene.h", "aiTypes.h"]
+for fileName in files:
+ if fileName.endswith('.h'):
+ for struct in Structify(os.path.join(path, fileName)):
+ primitive, sr, complex, struct = struct
+ if primitive:
+ structs1 += struct
+ elif sr:
+ structs2 += struct
+ elif complex:
+ structs4 += struct
+ else:
+ structs3 += struct
+
+text += structs1 + structs2 + structs3 + structs4
+
+file = open('structs.py', 'w')
+file.write(text)
+file.close()
+
+print("Generation done. You can now review the file 'structs.py' and merge it.")
diff --git a/libs/assimp/port/PyAssimp/pyassimp/__init__.py b/libs/assimp/port/PyAssimp/pyassimp/__init__.py
new file mode 100644
index 0000000..bb67a43
--- /dev/null
+++ b/libs/assimp/port/PyAssimp/pyassimp/__init__.py
@@ -0,0 +1 @@
+from .core import *
diff --git a/libs/assimp/port/PyAssimp/pyassimp/core.py b/libs/assimp/port/PyAssimp/pyassimp/core.py
new file mode 100644
index 0000000..35ad882
--- /dev/null
+++ b/libs/assimp/port/PyAssimp/pyassimp/core.py
@@ -0,0 +1,556 @@
+"""
+PyAssimp
+
+This is the main-module of PyAssimp.
+"""
+
+import sys
+if sys.version_info < (2,6):
+ raise RuntimeError('pyassimp: need python 2.6 or newer')
+
+# xrange was renamed range in Python 3 and the original range from Python 2 was removed.
+# To keep compatibility with both Python 2 and 3, xrange is set to range for version 3.0 and up.
+if sys.version_info >= (3,0):
+ xrange = range
+
+
+try:
+ import numpy
+except ImportError:
+ numpy = None
+import logging
+import ctypes
+from contextlib import contextmanager
+logger = logging.getLogger("pyassimp")
+# attach default null handler to logger so it doesn't complain
+# even if you don't attach another handler to logger
+logger.addHandler(logging.NullHandler())
+
+from . import structs
+from . import helper
+from . import postprocess
+from .errors import AssimpError
+
+class AssimpLib(object):
+ """
+ Assimp-Singleton
+ """
+ load, load_mem, export, export_blob, release, dll = helper.search_library()
+_assimp_lib = AssimpLib()
+
+def make_tuple(ai_obj, type = None):
+ res = None
+
+ #notes:
+ # ai_obj._fields_ = [ ("attr", c_type), ... ]
+ # getattr(ai_obj, e[0]).__class__ == float
+
+ if isinstance(ai_obj, structs.Matrix4x4):
+ if numpy:
+ res = numpy.array([getattr(ai_obj, e[0]) for e in ai_obj._fields_]).reshape((4,4))
+ #import pdb;pdb.set_trace()
+ else:
+ res = [getattr(ai_obj, e[0]) for e in ai_obj._fields_]
+ res = [res[i:i+4] for i in xrange(0,16,4)]
+ elif isinstance(ai_obj, structs.Matrix3x3):
+ if numpy:
+ res = numpy.array([getattr(ai_obj, e[0]) for e in ai_obj._fields_]).reshape((3,3))
+ else:
+ res = [getattr(ai_obj, e[0]) for e in ai_obj._fields_]
+ res = [res[i:i+3] for i in xrange(0,9,3)]
+ else:
+ if numpy:
+ res = numpy.array([getattr(ai_obj, e[0]) for e in ai_obj._fields_])
+ else:
+ res = [getattr(ai_obj, e[0]) for e in ai_obj._fields_]
+
+ return res
+
+# Returns unicode object for Python 2, and str object for Python 3.
+def _convert_assimp_string(assimp_string):
+ if sys.version_info >= (3, 0):
+ return str(assimp_string.data, errors='ignore')
+ else:
+ return unicode(assimp_string.data, errors='ignore')
+
+# It is faster and more correct to have an init function for each assimp class
+def _init_face(aiFace):
+ aiFace.indices = [aiFace.mIndices[i] for i in range(aiFace.mNumIndices)]
+assimp_struct_inits = { structs.Face : _init_face }
+
+def call_init(obj, caller = None):
+ if helper.hasattr_silent(obj,'contents'): #pointer
+ _init(obj.contents, obj, caller)
+ else:
+ _init(obj,parent=caller)
+
+def _is_init_type(obj):
+
+ if obj and helper.hasattr_silent(obj,'contents'): #pointer
+ return _is_init_type(obj[0])
+ # null-pointer case that arises when we reach a mesh attribute
+ # like mBitangents which use mNumVertices rather than mNumBitangents
+ # so it breaks the 'is iterable' check.
+ # Basically:
+ # FIXME!
+ elif not bool(obj):
+ return False
+ tname = obj.__class__.__name__
+ return not (tname[:2] == 'c_' or tname == 'Structure' \
+ or tname == 'POINTER') and not isinstance(obj, (int, str, bytes))
+
+def _init(self, target = None, parent = None):
+ """
+ Custom initialize() for C structs, adds safely accessible member functionality.
+
+ :param target: set the object which receive the added methods. Useful when manipulating
+ pointers, to skip the intermediate 'contents' deferencing.
+ """
+ if not target:
+ target = self
+
+ dirself = dir(self)
+ for m in dirself:
+
+ if m.startswith("_"):
+ continue
+
+ if m.startswith('mNum'):
+ if 'm' + m[4:] in dirself:
+ continue # will be processed later on
+ else:
+ name = m[1:].lower()
+
+ obj = getattr(self, m)
+ setattr(target, name, obj)
+ continue
+
+ if m == 'mName':
+ target.name = str(_convert_assimp_string(self.mName))
+ target.__class__.__repr__ = lambda x: str(x.__class__) + "(" + getattr(x, 'name','') + ")"
+ target.__class__.__str__ = lambda x: getattr(x, 'name', '')
+ continue
+
+ name = m[1:].lower()
+
+ obj = getattr(self, m)
+
+ # Create tuples
+ if isinstance(obj, structs.assimp_structs_as_tuple):
+ setattr(target, name, make_tuple(obj))
+ logger.debug(str(self) + ": Added array " + str(getattr(target, name)) + " as self." + name.lower())
+ continue
+
+ if m.startswith('m') and len(m) > 1 and m[1].upper() == m[1]:
+
+ if name == "parent":
+ setattr(target, name, parent)
+ logger.debug("Added a parent as self." + name)
+ continue
+
+ if helper.hasattr_silent(self, 'mNum' + m[1:]):
+
+ length = getattr(self, 'mNum' + m[1:])
+
+ # -> special case: properties are
+ # stored as a dict.
+ if m == 'mProperties':
+ setattr(target, name, _get_properties(obj, length))
+ continue
+
+
+ if not length: # empty!
+ setattr(target, name, [])
+ logger.debug(str(self) + ": " + name + " is an empty list.")
+ continue
+
+
+ try:
+ if obj._type_ in structs.assimp_structs_as_tuple:
+ if numpy:
+ setattr(target, name, numpy.array([make_tuple(obj[i]) for i in range(length)], dtype=numpy.float32))
+
+ logger.debug(str(self) + ": Added an array of numpy arrays (type "+ str(type(obj)) + ") as self." + name)
+ else:
+ setattr(target, name, [make_tuple(obj[i]) for i in range(length)])
+
+ logger.debug(str(self) + ": Added a list of lists (type "+ str(type(obj)) + ") as self." + name)
+
+ else:
+ setattr(target, name, [obj[i] for i in range(length)]) #TODO: maybe not necessary to recreate an array?
+
+ logger.debug(str(self) + ": Added list of " + str(obj) + " " + name + " as self." + name + " (type: " + str(type(obj)) + ")")
+
+ # initialize array elements
+ try:
+ init = assimp_struct_inits[type(obj[0])]
+ except KeyError:
+ if _is_init_type(obj[0]):
+ for e in getattr(target, name):
+ call_init(e, target)
+ else:
+ for e in getattr(target, name):
+ init(e)
+
+
+ except IndexError:
+ logger.error("in " + str(self) +" : mismatch between mNum" + name + " and the actual amount of data in m" + name + ". This may be due to version mismatch between libassimp and pyassimp. Quitting now.")
+ sys.exit(1)
+
+ except ValueError as e:
+
+ logger.error("In " + str(self) + "->" + name + ": " + str(e) + ". Quitting now.")
+ if "setting an array element with a sequence" in str(e):
+ logger.error("Note that pyassimp does not currently "
+ "support meshes with mixed triangles "
+ "and quads. Try to load your mesh with"
+ " a post-processing to triangulate your"
+ " faces.")
+ raise e
+
+
+
+ else: # starts with 'm' but not iterable
+ setattr(target, m, obj)
+ logger.debug("Added " + name + " as self." + name + " (type: " + str(type(obj)) + ")")
+
+ if _is_init_type(obj):
+ call_init(obj, target)
+
+ if isinstance(self, structs.Mesh):
+ _finalize_mesh(self, target)
+
+ if isinstance(self, structs.Texture):
+ _finalize_texture(self, target)
+
+ if isinstance(self, structs.Metadata):
+ _finalize_metadata(self, target)
+
+
+ return self
+
+
+def pythonize_assimp(type, obj, scene):
+ """ This method modify the Assimp data structures
+ to make them easier to work with in Python.
+
+ Supported operations:
+ - MESH: replace a list of mesh IDs by reference to these meshes
+ - ADDTRANSFORMATION: add a reference to an object's transformation taken from their associated node.
+
+ :param type: the type of modification to operate (cf above)
+ :param obj: the input object to modify
+ :param scene: a reference to the whole scene
+ """
+
+ if type == "MESH":
+ meshes = []
+ for i in obj:
+ meshes.append(scene.meshes[i])
+ return meshes
+
+ if type == "ADDTRANSFORMATION":
+ def getnode(node, name):
+ if node.name == name: return node
+ for child in node.children:
+ n = getnode(child, name)
+ if n: return n
+
+ node = getnode(scene.rootnode, obj.name)
+ if not node:
+ raise AssimpError("Object " + str(obj) + " has no associated node!")
+ setattr(obj, "transformation", node.transformation)
+
+def recur_pythonize(node, scene):
+ '''
+ Recursively call pythonize_assimp on
+ nodes tree to apply several post-processing to
+ pythonize the assimp datastructures.
+ '''
+ node.meshes = pythonize_assimp("MESH", node.meshes, scene)
+ for mesh in node.meshes:
+ mesh.material = scene.materials[mesh.materialindex]
+ for cam in scene.cameras:
+ pythonize_assimp("ADDTRANSFORMATION", cam, scene)
+ for c in node.children:
+ recur_pythonize(c, scene)
+
+def release(scene):
+ '''
+ Release resources of a loaded scene.
+ '''
+ _assimp_lib.release(ctypes.pointer(scene))
+
+@contextmanager
+def load(filename,
+ file_type = None,
+ processing = postprocess.aiProcess_Triangulate):
+ '''
+ Load a model into a scene. On failure throws AssimpError.
+
+ Arguments
+ ---------
+ filename: Either a filename or a file object to load model from.
+ If a file object is passed, file_type MUST be specified
+ Otherwise Assimp has no idea which importer to use.
+ This is named 'filename' so as to not break legacy code.
+ processing: assimp postprocessing parameters. Verbose keywords are imported
+ from postprocessing, and the parameters can be combined bitwise to
+ generate the final processing value. Note that the default value will
+ triangulate quad faces. Example of generating other possible values:
+ processing = (pyassimp.postprocess.aiProcess_Triangulate |
+ pyassimp.postprocess.aiProcess_OptimizeMeshes)
+ file_type: string of file extension, such as 'stl'
+
+ Returns
+ ---------
+ Scene object with model data
+ '''
+
+ if hasattr(filename, 'read'):
+ # This is the case where a file object has been passed to load.
+ # It is calling the following function:
+ # const aiScene* aiImportFileFromMemory(const char* pBuffer,
+ # unsigned int pLength,
+ # unsigned int pFlags,
+ # const char* pHint)
+ if file_type is None:
+ raise AssimpError('File type must be specified when passing file objects!')
+ data = filename.read()
+ model = _assimp_lib.load_mem(data,
+ len(data),
+ processing,
+ file_type)
+ else:
+ # a filename string has been passed
+ model = _assimp_lib.load(filename.encode(sys.getfilesystemencoding()), processing)
+
+ if not model:
+ raise AssimpError('Could not import file!')
+ scene = _init(model.contents)
+ recur_pythonize(scene.rootnode, scene)
+ try:
+ yield scene
+ finally:
+ release(scene)
+
+def export(scene,
+ filename,
+ file_type = None,
+ processing = postprocess.aiProcess_Triangulate):
+ '''
+ Export a scene. On failure throws AssimpError.
+
+ Arguments
+ ---------
+ scene: scene to export.
+ filename: Filename that the scene should be exported to.
+ file_type: string of file exporter to use. For example "collada".
+ processing: assimp postprocessing parameters. Verbose keywords are imported
+ from postprocessing, and the parameters can be combined bitwise to
+ generate the final processing value. Note that the default value will
+ triangulate quad faces. Example of generating other possible values:
+ processing = (pyassimp.postprocess.aiProcess_Triangulate |
+ pyassimp.postprocess.aiProcess_OptimizeMeshes)
+
+ '''
+
+ exportStatus = _assimp_lib.export(ctypes.pointer(scene), file_type.encode("ascii"), filename.encode(sys.getfilesystemencoding()), processing)
+
+ if exportStatus != 0:
+ raise AssimpError('Could not export scene!')
+
+def export_blob(scene,
+ file_type = None,
+ processing = postprocess.aiProcess_Triangulate):
+ '''
+ Export a scene and return a blob in the correct format. On failure throws AssimpError.
+
+ Arguments
+ ---------
+ scene: scene to export.
+ file_type: string of file exporter to use. For example "collada".
+ processing: assimp postprocessing parameters. Verbose keywords are imported
+ from postprocessing, and the parameters can be combined bitwise to
+ generate the final processing value. Note that the default value will
+ triangulate quad faces. Example of generating other possible values:
+ processing = (pyassimp.postprocess.aiProcess_Triangulate |
+ pyassimp.postprocess.aiProcess_OptimizeMeshes)
+ Returns
+ ---------
+ Pointer to structs.ExportDataBlob
+ '''
+ exportBlobPtr = _assimp_lib.export_blob(ctypes.pointer(scene), file_type.encode("ascii"), processing)
+
+ if exportBlobPtr == 0:
+ raise AssimpError('Could not export scene to blob!')
+ return exportBlobPtr
+
+def _finalize_texture(tex, target):
+ setattr(target, "achformathint", tex.achFormatHint)
+ if numpy:
+ data = numpy.array([make_tuple(getattr(tex, "pcData")[i]) for i in range(tex.mWidth * tex.mHeight)])
+ else:
+ data = [make_tuple(getattr(tex, "pcData")[i]) for i in range(tex.mWidth * tex.mHeight)]
+ setattr(target, "data", data)
+
+def _finalize_mesh(mesh, target):
+ """ Building of meshes is a bit specific.
+
+ We override here the various datasets that can
+ not be process as regular fields.
+
+ For instance, the length of the normals array is
+ mNumVertices (no mNumNormals is available)
+ """
+ nb_vertices = getattr(mesh, "mNumVertices")
+
+ def fill(name):
+ mAttr = getattr(mesh, name)
+ if numpy:
+ if mAttr:
+ data = numpy.array([make_tuple(getattr(mesh, name)[i]) for i in range(nb_vertices)], dtype=numpy.float32)
+ setattr(target, name[1:].lower(), data)
+ else:
+ setattr(target, name[1:].lower(), numpy.array([], dtype="float32"))
+ else:
+ if mAttr:
+ data = [make_tuple(getattr(mesh, name)[i]) for i in range(nb_vertices)]
+ setattr(target, name[1:].lower(), data)
+ else:
+ setattr(target, name[1:].lower(), [])
+
+ def fillarray(name):
+ mAttr = getattr(mesh, name)
+
+ data = []
+ for index, mSubAttr in enumerate(mAttr):
+ if mSubAttr:
+ data.append([make_tuple(getattr(mesh, name)[index][i]) for i in range(nb_vertices)])
+
+ if numpy:
+ setattr(target, name[1:].lower(), numpy.array(data, dtype=numpy.float32))
+ else:
+ setattr(target, name[1:].lower(), data)
+
+ fill("mNormals")
+ fill("mTangents")
+ fill("mBitangents")
+
+ fillarray("mColors")
+ fillarray("mTextureCoords")
+
+ # prepare faces
+ if numpy:
+ faces = numpy.array([f.indices for f in target.faces], dtype=numpy.int32)
+ else:
+ faces = [f.indices for f in target.faces]
+ setattr(target, 'faces', faces)
+
+def _init_metadata_entry(entry):
+ entry.type = entry.mType
+ if entry.type == structs.MetadataEntry.AI_BOOL:
+ entry.data = ctypes.cast(entry.mData, ctypes.POINTER(ctypes.c_bool)).contents.value
+ elif entry.type == structs.MetadataEntry.AI_INT32:
+ entry.data = ctypes.cast(entry.mData, ctypes.POINTER(ctypes.c_int32)).contents.value
+ elif entry.type == structs.MetadataEntry.AI_UINT64:
+ entry.data = ctypes.cast(entry.mData, ctypes.POINTER(ctypes.c_uint64)).contents.value
+ elif entry.type == structs.MetadataEntry.AI_FLOAT:
+ entry.data = ctypes.cast(entry.mData, ctypes.POINTER(ctypes.c_float)).contents.value
+ elif entry.type == structs.MetadataEntry.AI_DOUBLE:
+ entry.data = ctypes.cast(entry.mData, ctypes.POINTER(ctypes.c_double)).contents.value
+ elif entry.type == structs.MetadataEntry.AI_AISTRING:
+ assimp_string = ctypes.cast(entry.mData, ctypes.POINTER(structs.String)).contents
+ entry.data = _convert_assimp_string(assimp_string)
+ elif entry.type == structs.MetadataEntry.AI_AIVECTOR3D:
+ assimp_vector = ctypes.cast(entry.mData, ctypes.POINTER(structs.Vector3D)).contents
+ entry.data = make_tuple(assimp_vector)
+
+ return entry
+
+def _finalize_metadata(metadata, target):
+ """ Building the metadata object is a bit specific.
+
+ Firstly, there are two separate arrays: one with metadata keys and one
+ with metadata values, and there are no corresponding mNum* attributes,
+ so the C arrays are not converted to Python arrays using the generic
+ code in the _init function.
+
+ Secondly, a metadata entry value has to be cast according to declared
+ metadata entry type.
+ """
+ length = metadata.mNumProperties
+ setattr(target, 'keys', [str(_convert_assimp_string(metadata.mKeys[i])) for i in range(length)])
+ setattr(target, 'values', [_init_metadata_entry(metadata.mValues[i]) for i in range(length)])
+
+class PropertyGetter(dict):
+ def __getitem__(self, key):
+ semantic = 0
+ if isinstance(key, tuple):
+ key, semantic = key
+
+ return dict.__getitem__(self, (key, semantic))
+
+ def keys(self):
+ for k in dict.keys(self):
+ yield k[0]
+
+ def __iter__(self):
+ return self.keys()
+
+ def items(self):
+ for k, v in dict.items(self):
+ yield k[0], v
+
+
+def _get_properties(properties, length):
+ """
+ Convenience Function to get the material properties as a dict
+ and values in a python format.
+ """
+ result = {}
+ #read all properties
+ for p in [properties[i] for i in range(length)]:
+ #the name
+ p = p.contents
+ key = str(_convert_assimp_string(p.mKey))
+ key = (key.split('.')[1], p.mSemantic)
+
+ #the data
+ if p.mType == 1:
+ arr = ctypes.cast(p.mData,
+ ctypes.POINTER(ctypes.c_float * int(p.mDataLength/ctypes.sizeof(ctypes.c_float)))
+ ).contents
+ value = [x for x in arr]
+ elif p.mType == 3: #string can't be an array
+ value = _convert_assimp_string(ctypes.cast(p.mData, ctypes.POINTER(structs.MaterialPropertyString)).contents)
+
+ elif p.mType == 4:
+ arr = ctypes.cast(p.mData,
+ ctypes.POINTER(ctypes.c_int * int(p.mDataLength/ctypes.sizeof(ctypes.c_int)))
+ ).contents
+ value = [x for x in arr]
+ else:
+ value = p.mData[:p.mDataLength]
+
+ if len(value) == 1:
+ [value] = value
+
+ result[key] = value
+
+ return PropertyGetter(result)
+
+def decompose_matrix(matrix):
+ if not isinstance(matrix, structs.Matrix4x4):
+ raise AssimpError("pyassimp.decompose_matrix failed: Not a Matrix4x4!")
+
+ scaling = structs.Vector3D()
+ rotation = structs.Quaternion()
+ position = structs.Vector3D()
+
+ _assimp_lib.dll.aiDecomposeMatrix(ctypes.pointer(matrix),
+ ctypes.byref(scaling),
+ ctypes.byref(rotation),
+ ctypes.byref(position))
+ return scaling._init(), rotation._init(), position._init()
+
diff --git a/libs/assimp/port/PyAssimp/pyassimp/errors.py b/libs/assimp/port/PyAssimp/pyassimp/errors.py
new file mode 100644
index 0000000..e017b51
--- /dev/null
+++ b/libs/assimp/port/PyAssimp/pyassimp/errors.py
@@ -0,0 +1,11 @@
+#-*- coding: UTF-8 -*-
+
+"""
+All possible errors.
+"""
+
+class AssimpError(BaseException):
+ """
+ If an internal error occurs.
+ """
+ pass
diff --git a/libs/assimp/port/PyAssimp/pyassimp/formats.py b/libs/assimp/port/PyAssimp/pyassimp/formats.py
new file mode 100644
index 0000000..5d454e5
--- /dev/null
+++ b/libs/assimp/port/PyAssimp/pyassimp/formats.py
@@ -0,0 +1,41 @@
+FORMATS = ["CSM",
+ "LWS",
+ "B3D",
+ "COB",
+ "PLY",
+ "IFC",
+ "OFF",
+ "SMD",
+ "IRRMESH",
+ "3D",
+ "DAE",
+ "MDL",
+ "HMP",
+ "TER",
+ "WRL",
+ "XML",
+ "NFF",
+ "AC",
+ "OBJ",
+ "3DS",
+ "STL",
+ "IRR",
+ "Q3O",
+ "Q3D",
+ "MS3D",
+ "Q3S",
+ "ZGL",
+ "MD2",
+ "X",
+ "BLEND",
+ "XGL",
+ "MD5MESH",
+ "MAX",
+ "LXO",
+ "DXF",
+ "BVH",
+ "LWO",
+ "NDO"]
+
+def available_formats():
+ return FORMATS
diff --git a/libs/assimp/port/PyAssimp/pyassimp/helper.py b/libs/assimp/port/PyAssimp/pyassimp/helper.py
new file mode 100644
index 0000000..7c14f60
--- /dev/null
+++ b/libs/assimp/port/PyAssimp/pyassimp/helper.py
@@ -0,0 +1,283 @@
+#-*- coding: UTF-8 -*-
+
+"""
+Some fancy helper functions.
+"""
+
+import os
+import ctypes
+import operator
+
+from distutils.sysconfig import get_python_lib
+import re
+import sys
+
+try: import numpy
+except ImportError: numpy = None
+
+import logging;logger = logging.getLogger("pyassimp")
+
+from .errors import AssimpError
+
+additional_dirs, ext_whitelist = [],[]
+
+# populate search directories and lists of allowed file extensions
+# depending on the platform we're running on.
+if os.name=='posix':
+ additional_dirs.append('./')
+ additional_dirs.append('/usr/lib/')
+ additional_dirs.append('/usr/lib/x86_64-linux-gnu/')
+ additional_dirs.append('/usr/lib/aarch64-linux-gnu/')
+ additional_dirs.append('/usr/local/lib/')
+
+ if 'LD_LIBRARY_PATH' in os.environ:
+ additional_dirs.extend([item for item in os.environ['LD_LIBRARY_PATH'].split(':') if item])
+
+ # check if running from anaconda.
+ anaconda_keywords = ("conda", "continuum")
+ if any(k in sys.version.lower() for k in anaconda_keywords):
+ cur_path = get_python_lib()
+ pattern = re.compile('.*\/lib\/')
+ conda_lib = pattern.match(cur_path).group()
+ logger.info("Adding Anaconda lib path:"+ conda_lib)
+ additional_dirs.append(conda_lib)
+
+ # note - this won't catch libassimp.so.N.n, but
+ # currently there's always a symlink called
+ # libassimp.so in /usr/local/lib.
+ ext_whitelist.append('.so')
+ # libassimp.dylib in /usr/local/lib
+ ext_whitelist.append('.dylib')
+
+elif os.name=='nt':
+ ext_whitelist.append('.dll')
+ path_dirs = os.environ['PATH'].split(';')
+ additional_dirs.extend(path_dirs)
+
+def vec2tuple(x):
+ """ Converts a VECTOR3D to a Tuple """
+ return (x.x, x.y, x.z)
+
+def transform(vector3, matrix4x4):
+ """ Apply a transformation matrix on a 3D vector.
+
+ :param vector3: array with 3 elements
+ :param matrix4x4: 4x4 matrix
+ """
+ if numpy:
+ return numpy.dot(matrix4x4, numpy.append(vector3, 1.))
+ else:
+ m0,m1,m2,m3 = matrix4x4; x,y,z = vector3
+ return [
+ m0[0]*x + m0[1]*y + m0[2]*z + m0[3],
+ m1[0]*x + m1[1]*y + m1[2]*z + m1[3],
+ m2[0]*x + m2[1]*y + m2[2]*z + m2[3],
+ m3[0]*x + m3[1]*y + m3[2]*z + m3[3]
+ ]
+
+def _inv(matrix4x4):
+ m0,m1,m2,m3 = matrix4x4
+
+ det = m0[3]*m1[2]*m2[1]*m3[0] - m0[2]*m1[3]*m2[1]*m3[0] - \
+ m0[3]*m1[1]*m2[2]*m3[0] + m0[1]*m1[3]*m2[2]*m3[0] + \
+ m0[2]*m1[1]*m2[3]*m3[0] - m0[1]*m1[2]*m2[3]*m3[0] - \
+ m0[3]*m1[2]*m2[0]*m3[1] + m0[2]*m1[3]*m2[0]*m3[1] + \
+ m0[3]*m1[0]*m2[2]*m3[1] - m0[0]*m1[3]*m2[2]*m3[1] - \
+ m0[2]*m1[0]*m2[3]*m3[1] + m0[0]*m1[2]*m2[3]*m3[1] + \
+ m0[3]*m1[1]*m2[0]*m3[2] - m0[1]*m1[3]*m2[0]*m3[2] - \
+ m0[3]*m1[0]*m2[1]*m3[2] + m0[0]*m1[3]*m2[1]*m3[2] + \
+ m0[1]*m1[0]*m2[3]*m3[2] - m0[0]*m1[1]*m2[3]*m3[2] - \
+ m0[2]*m1[1]*m2[0]*m3[3] + m0[1]*m1[2]*m2[0]*m3[3] + \
+ m0[2]*m1[0]*m2[1]*m3[3] - m0[0]*m1[2]*m2[1]*m3[3] - \
+ m0[1]*m1[0]*m2[2]*m3[3] + m0[0]*m1[1]*m2[2]*m3[3]
+
+ return[[( m1[2]*m2[3]*m3[1] - m1[3]*m2[2]*m3[1] + m1[3]*m2[1]*m3[2] - m1[1]*m2[3]*m3[2] - m1[2]*m2[1]*m3[3] + m1[1]*m2[2]*m3[3]) /det,
+ ( m0[3]*m2[2]*m3[1] - m0[2]*m2[3]*m3[1] - m0[3]*m2[1]*m3[2] + m0[1]*m2[3]*m3[2] + m0[2]*m2[1]*m3[3] - m0[1]*m2[2]*m3[3]) /det,
+ ( m0[2]*m1[3]*m3[1] - m0[3]*m1[2]*m3[1] + m0[3]*m1[1]*m3[2] - m0[1]*m1[3]*m3[2] - m0[2]*m1[1]*m3[3] + m0[1]*m1[2]*m3[3]) /det,
+ ( m0[3]*m1[2]*m2[1] - m0[2]*m1[3]*m2[1] - m0[3]*m1[1]*m2[2] + m0[1]*m1[3]*m2[2] + m0[2]*m1[1]*m2[3] - m0[1]*m1[2]*m2[3]) /det],
+ [( m1[3]*m2[2]*m3[0] - m1[2]*m2[3]*m3[0] - m1[3]*m2[0]*m3[2] + m1[0]*m2[3]*m3[2] + m1[2]*m2[0]*m3[3] - m1[0]*m2[2]*m3[3]) /det,
+ ( m0[2]*m2[3]*m3[0] - m0[3]*m2[2]*m3[0] + m0[3]*m2[0]*m3[2] - m0[0]*m2[3]*m3[2] - m0[2]*m2[0]*m3[3] + m0[0]*m2[2]*m3[3]) /det,
+ ( m0[3]*m1[2]*m3[0] - m0[2]*m1[3]*m3[0] - m0[3]*m1[0]*m3[2] + m0[0]*m1[3]*m3[2] + m0[2]*m1[0]*m3[3] - m0[0]*m1[2]*m3[3]) /det,
+ ( m0[2]*m1[3]*m2[0] - m0[3]*m1[2]*m2[0] + m0[3]*m1[0]*m2[2] - m0[0]*m1[3]*m2[2] - m0[2]*m1[0]*m2[3] + m0[0]*m1[2]*m2[3]) /det],
+ [( m1[1]*m2[3]*m3[0] - m1[3]*m2[1]*m3[0] + m1[3]*m2[0]*m3[1] - m1[0]*m2[3]*m3[1] - m1[1]*m2[0]*m3[3] + m1[0]*m2[1]*m3[3]) /det,
+ ( m0[3]*m2[1]*m3[0] - m0[1]*m2[3]*m3[0] - m0[3]*m2[0]*m3[1] + m0[0]*m2[3]*m3[1] + m0[1]*m2[0]*m3[3] - m0[0]*m2[1]*m3[3]) /det,
+ ( m0[1]*m1[3]*m3[0] - m0[3]*m1[1]*m3[0] + m0[3]*m1[0]*m3[1] - m0[0]*m1[3]*m3[1] - m0[1]*m1[0]*m3[3] + m0[0]*m1[1]*m3[3]) /det,
+ ( m0[3]*m1[1]*m2[0] - m0[1]*m1[3]*m2[0] - m0[3]*m1[0]*m2[1] + m0[0]*m1[3]*m2[1] + m0[1]*m1[0]*m2[3] - m0[0]*m1[1]*m2[3]) /det],
+ [( m1[2]*m2[1]*m3[0] - m1[1]*m2[2]*m3[0] - m1[2]*m2[0]*m3[1] + m1[0]*m2[2]*m3[1] + m1[1]*m2[0]*m3[2] - m1[0]*m2[1]*m3[2]) /det,
+ ( m0[1]*m2[2]*m3[0] - m0[2]*m2[1]*m3[0] + m0[2]*m2[0]*m3[1] - m0[0]*m2[2]*m3[1] - m0[1]*m2[0]*m3[2] + m0[0]*m2[1]*m3[2]) /det,
+ ( m0[2]*m1[1]*m3[0] - m0[1]*m1[2]*m3[0] - m0[2]*m1[0]*m3[1] + m0[0]*m1[2]*m3[1] + m0[1]*m1[0]*m3[2] - m0[0]*m1[1]*m3[2]) /det,
+ ( m0[1]*m1[2]*m2[0] - m0[2]*m1[1]*m2[0] + m0[2]*m1[0]*m2[1] - m0[0]*m1[2]*m2[1] - m0[1]*m1[0]*m2[2] + m0[0]*m1[1]*m2[2]) /det]]
+
+def get_bounding_box(scene):
+ bb_min = [1e10, 1e10, 1e10] # x,y,z
+ bb_max = [-1e10, -1e10, -1e10] # x,y,z
+ inv = numpy.linalg.inv if numpy else _inv
+ return get_bounding_box_for_node(scene.rootnode, bb_min, bb_max, inv(scene.rootnode.transformation))
+
+def get_bounding_box_for_node(node, bb_min, bb_max, transformation):
+
+ if numpy:
+ transformation = numpy.dot(transformation, node.transformation)
+ else:
+ t0,t1,t2,t3 = transformation
+ T0,T1,T2,T3 = node.transformation
+ transformation = [ [
+ t0[0]*T0[0] + t0[1]*T1[0] + t0[2]*T2[0] + t0[3]*T3[0],
+ t0[0]*T0[1] + t0[1]*T1[1] + t0[2]*T2[1] + t0[3]*T3[1],
+ t0[0]*T0[2] + t0[1]*T1[2] + t0[2]*T2[2] + t0[3]*T3[2],
+ t0[0]*T0[3] + t0[1]*T1[3] + t0[2]*T2[3] + t0[3]*T3[3]
+ ],[
+ t1[0]*T0[0] + t1[1]*T1[0] + t1[2]*T2[0] + t1[3]*T3[0],
+ t1[0]*T0[1] + t1[1]*T1[1] + t1[2]*T2[1] + t1[3]*T3[1],
+ t1[0]*T0[2] + t1[1]*T1[2] + t1[2]*T2[2] + t1[3]*T3[2],
+ t1[0]*T0[3] + t1[1]*T1[3] + t1[2]*T2[3] + t1[3]*T3[3]
+ ],[
+ t2[0]*T0[0] + t2[1]*T1[0] + t2[2]*T2[0] + t2[3]*T3[0],
+ t2[0]*T0[1] + t2[1]*T1[1] + t2[2]*T2[1] + t2[3]*T3[1],
+ t2[0]*T0[2] + t2[1]*T1[2] + t2[2]*T2[2] + t2[3]*T3[2],
+ t2[0]*T0[3] + t2[1]*T1[3] + t2[2]*T2[3] + t2[3]*T3[3]
+ ],[
+ t3[0]*T0[0] + t3[1]*T1[0] + t3[2]*T2[0] + t3[3]*T3[0],
+ t3[0]*T0[1] + t3[1]*T1[1] + t3[2]*T2[1] + t3[3]*T3[1],
+ t3[0]*T0[2] + t3[1]*T1[2] + t3[2]*T2[2] + t3[3]*T3[2],
+ t3[0]*T0[3] + t3[1]*T1[3] + t3[2]*T2[3] + t3[3]*T3[3]
+ ] ]
+
+ for mesh in node.meshes:
+ for v in mesh.vertices:
+ v = transform(v, transformation)
+ bb_min[0] = min(bb_min[0], v[0])
+ bb_min[1] = min(bb_min[1], v[1])
+ bb_min[2] = min(bb_min[2], v[2])
+ bb_max[0] = max(bb_max[0], v[0])
+ bb_max[1] = max(bb_max[1], v[1])
+ bb_max[2] = max(bb_max[2], v[2])
+
+
+ for child in node.children:
+ bb_min, bb_max = get_bounding_box_for_node(child, bb_min, bb_max, transformation)
+
+ return bb_min, bb_max
+
+def try_load_functions(library_path, dll):
+ '''
+ Try to bind to aiImportFile and aiReleaseImport
+
+ Arguments
+ ---------
+ library_path: path to current lib
+ dll: ctypes handle to library
+
+ Returns
+ ---------
+ If unsuccessful:
+ None
+ If successful:
+ Tuple containing (library_path,
+ load from filename function,
+ load from memory function,
+ export to filename function,
+ export to blob function,
+ release function,
+ ctypes handle to assimp library)
+ '''
+
+ try:
+ load = dll.aiImportFile
+ release = dll.aiReleaseImport
+ load_mem = dll.aiImportFileFromMemory
+ export = dll.aiExportScene
+ export2blob = dll.aiExportSceneToBlob
+ except AttributeError:
+ #OK, this is a library, but it doesn't have the functions we need
+ return None
+
+ # library found!
+ from .structs import Scene, ExportDataBlob
+ load.restype = ctypes.POINTER(Scene)
+ load_mem.restype = ctypes.POINTER(Scene)
+ export2blob.restype = ctypes.POINTER(ExportDataBlob)
+ return (library_path, load, load_mem, export, export2blob, release, dll)
+
+def search_library():
+ '''
+ Loads the assimp library.
+ Throws exception AssimpError if no library_path is found
+
+ Returns: tuple, (load from filename function,
+ load from memory function,
+ export to filename function,
+ export to blob function,
+ release function,
+ dll)
+ '''
+ #this path
+ folder = os.path.dirname(__file__)
+
+ # silence 'DLL not found' message boxes on win
+ try:
+ ctypes.windll.kernel32.SetErrorMode(0x8007)
+ except AttributeError:
+ pass
+
+ candidates = []
+ # test every file
+ for curfolder in [folder]+additional_dirs:
+ if os.path.isdir(curfolder):
+ for filename in os.listdir(curfolder):
+ # our minimum requirement for candidates is that
+ # they should contain 'assimp' somewhere in
+ # their name
+ if filename.lower().find('assimp')==-1 :
+ continue
+ is_out=1
+ for et in ext_whitelist:
+ if et in filename.lower():
+ is_out=0
+ break
+ if is_out:
+ continue
+
+ library_path = os.path.join(curfolder, filename)
+ logger.debug('Try ' + library_path)
+ try:
+ dll = ctypes.cdll.LoadLibrary(library_path)
+ except Exception as e:
+ logger.warning(str(e))
+ # OK, this except is evil. But different OSs will throw different
+ # errors. So just ignore any errors.
+ continue
+ # see if the functions we need are in the dll
+ loaded = try_load_functions(library_path, dll)
+ if loaded: candidates.append(loaded)
+
+ if not candidates:
+ # no library found
+ raise AssimpError("assimp library not found")
+ else:
+ # get the newest library_path
+ candidates = map(lambda x: (os.lstat(x[0])[-2], x), candidates)
+ res = max(candidates, key=operator.itemgetter(0))[1]
+ logger.debug('Using assimp library located at ' + res[0])
+
+ # XXX: if there are 1000 dll/so files containing 'assimp'
+ # in their name, do we have all of them in our address
+ # space now until gc kicks in?
+
+ # XXX: take version postfix of the .so on linux?
+ return res[1:]
+
+def hasattr_silent(object, name):
+ """
+ Calls hasttr() with the given parameters and preserves the legacy (pre-Python 3.2)
+ functionality of silently catching exceptions.
+
+ Returns the result of hasatter() or False if an exception was raised.
+ """
+
+ try:
+ if not object:
+ return False
+ return hasattr(object, name)
+ except AttributeError:
+ return False
diff --git a/libs/assimp/port/PyAssimp/pyassimp/material.py b/libs/assimp/port/PyAssimp/pyassimp/material.py
new file mode 100644
index 0000000..a36e50a
--- /dev/null
+++ b/libs/assimp/port/PyAssimp/pyassimp/material.py
@@ -0,0 +1,89 @@
+# Dummy value.
+#
+# No texture, but the value to be used as 'texture semantic'
+# (#aiMaterialProperty::mSemantic) for all material properties
+# # not* related to textures.
+#
+aiTextureType_NONE = 0x0
+
+# The texture is combined with the result of the diffuse
+# lighting equation.
+#
+aiTextureType_DIFFUSE = 0x1
+
+# The texture is combined with the result of the specular
+# lighting equation.
+#
+aiTextureType_SPECULAR = 0x2
+
+# The texture is combined with the result of the ambient
+# lighting equation.
+#
+aiTextureType_AMBIENT = 0x3
+
+# The texture is added to the result of the lighting
+# calculation. It isn't influenced by incoming light.
+#
+aiTextureType_EMISSIVE = 0x4
+
+# The texture is a height map.
+#
+# By convention, higher gray-scale values stand for
+# higher elevations from the base height.
+#
+aiTextureType_HEIGHT = 0x5
+
+# The texture is a (tangent space) normal-map.
+#
+# Again, there are several conventions for tangent-space
+# normal maps. Assimp does (intentionally) not
+# distinguish here.
+#
+aiTextureType_NORMALS = 0x6
+
+# The texture defines the glossiness of the material.
+#
+# The glossiness is in fact the exponent of the specular
+# (phong) lighting equation. Usually there is a conversion
+# function defined to map the linear color values in the
+# texture to a suitable exponent. Have fun.
+#
+aiTextureType_SHININESS = 0x7
+
+# The texture defines per-pixel opacity.
+#
+# Usually 'white' means opaque and 'black' means
+# 'transparency'. Or quite the opposite. Have fun.
+#
+aiTextureType_OPACITY = 0x8
+
+# Displacement texture
+#
+# The exact purpose and format is application-dependent.
+# Higher color values stand for higher vertex displacements.
+#
+aiTextureType_DISPLACEMENT = 0x9
+
+# Lightmap texture (aka Ambient Occlusion)
+#
+# Both 'Lightmaps' and dedicated 'ambient occlusion maps' are
+# covered by this material property. The texture contains a
+# scaling value for the final color value of a pixel. Its
+# intensity is not affected by incoming light.
+#
+aiTextureType_LIGHTMAP = 0xA
+
+# Reflection texture
+#
+# Contains the color of a perfect mirror reflection.
+# Rarely used, almost never for real-time applications.
+#
+aiTextureType_REFLECTION = 0xB
+
+# Unknown texture
+#
+# A texture reference that does not match any of the definitions
+# above is considered to be 'unknown'. It is still imported
+# but is excluded from any further postprocessing.
+#
+aiTextureType_UNKNOWN = 0xC
diff --git a/libs/assimp/port/PyAssimp/pyassimp/postprocess.py b/libs/assimp/port/PyAssimp/pyassimp/postprocess.py
new file mode 100644
index 0000000..0c55d67
--- /dev/null
+++ b/libs/assimp/port/PyAssimp/pyassimp/postprocess.py
@@ -0,0 +1,530 @@
+# <hr>Calculates the tangents and bitangents for the imported meshes.
+#
+# Does nothing if a mesh does not have normals. You might want this post
+# processing step to be executed if you plan to use tangent space calculations
+# such as normal mapping applied to the meshes. There's a config setting,
+# <tt>#AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE<tt>, which allows you to specify
+# a maximum smoothing angle for the algorithm. However, usually you'll
+# want to leave it at the default value.
+#
+aiProcess_CalcTangentSpace = 0x1
+
+## <hr>Identifies and joins identical vertex data sets within all
+# imported meshes.
+#
+# After this step is run, each mesh contains unique vertices,
+# so a vertex may be used by multiple faces. You usually want
+# to use this post processing step. If your application deals with
+# indexed geometry, this step is compulsory or you'll just waste rendering
+# time. <b>If this flag is not specified<b>, no vertices are referenced by
+# more than one face and <b>no index buffer is required<b> for rendering.
+#
+aiProcess_JoinIdenticalVertices = 0x2
+
+## <hr>Converts all the imported data to a left-handed coordinate space.
+#
+# By default the data is returned in a right-handed coordinate space (which
+# OpenGL prefers). In this space, +X points to the right,
+# +Z points towards the viewer, and +Y points upwards. In the DirectX
+# coordinate space +X points to the right, +Y points upwards, and +Z points
+# away from the viewer.
+#
+# You'll probably want to consider this flag if you use Direct3D for
+# rendering. The #aiProcess_ConvertToLeftHanded flag supersedes this
+# setting and bundles all conversions typically required for D3D-based
+# applications.
+#
+aiProcess_MakeLeftHanded = 0x4
+
+## <hr>Triangulates all faces of all meshes.
+#
+# By default the imported mesh data might contain faces with more than 3
+# indices. For rendering you'll usually want all faces to be triangles.
+# This post processing step splits up faces with more than 3 indices into
+# triangles. Line and point primitives are #not# modified! If you want
+# 'triangles only' with no other kinds of primitives, try the following
+# solution:
+# <ul>
+# <li>Specify both #aiProcess_Triangulate and #aiProcess_SortByPType <li>
+# <li>Ignore all point and line meshes when you process assimp's output<li>
+# <ul>
+#
+aiProcess_Triangulate = 0x8
+
+## <hr>Removes some parts of the data structure (animations, materials,
+# light sources, cameras, textures, vertex components).
+#
+# The components to be removed are specified in a separate
+# configuration option, <tt>#AI_CONFIG_PP_RVC_FLAGS<tt>. This is quite useful
+# if you don't need all parts of the output structure. Vertex colors
+# are rarely used today for example... Calling this step to remove unneeded
+# data from the pipeline as early as possible results in increased
+# performance and a more optimized output data structure.
+# This step is also useful if you want to force Assimp to recompute
+# normals or tangents. The corresponding steps don't recompute them if
+# they're already there (loaded from the source asset). By using this
+# step you can make sure they are NOT there.
+#
+# This flag is a poor one, mainly because its purpose is usually
+# misunderstood. Consider the following case: a 3D model has been exported
+# from a CAD app, and it has per-face vertex colors. Vertex positions can't be
+# shared, thus the #aiProcess_JoinIdenticalVertices step fails to
+# optimize the data because of these nasty little vertex colors.
+# Most apps don't even process them, so it's all for nothing. By using
+# this step, unneeded components are excluded as early as possible
+# thus opening more room for internal optimizations.
+#
+aiProcess_RemoveComponent = 0x10
+
+## <hr>Generates normals for all faces of all meshes.
+#
+# This is ignored if normals are already there at the time this flag
+# is evaluated. Model importers try to load them from the source file, so
+# they're usually already there. Face normals are shared between all points
+# of a single face, so a single point can have multiple normals, which
+# forces the library to duplicate vertices in some cases.
+# #aiProcess_JoinIdenticalVertices is #senseless# then.
+#
+# This flag may not be specified together with #aiProcess_GenSmoothNormals.
+#
+aiProcess_GenNormals = 0x20
+
+## <hr>Generates smooth normals for all vertices in the mesh.
+#
+# This is ignored if normals are already there at the time this flag
+# is evaluated. Model importers try to load them from the source file, so
+# they're usually already there.
+#
+# This flag may not be specified together with
+# #aiProcess_GenNormals. There's a configuration option,
+# <tt>#AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE<tt> which allows you to specify
+# an angle maximum for the normal smoothing algorithm. Normals exceeding
+# this limit are not smoothed, resulting in a 'hard' seam between two faces.
+# Using a decent angle here (e.g. 80 degrees) results in very good visual
+# appearance.
+#
+aiProcess_GenSmoothNormals = 0x40
+
+## <hr>Splits large meshes into smaller sub-meshes.
+#
+# This is quite useful for real-time rendering, where the number of triangles
+# which can be maximally processed in a single draw-call is limited
+# by the video driverhardware. The maximum vertex buffer is usually limited
+# too. Both requirements can be met with this step: you may specify both a
+# triangle and vertex limit for a single mesh.
+#
+# The split limits can (and should!) be set through the
+# <tt>#AI_CONFIG_PP_SLM_VERTEX_LIMIT<tt> and <tt>#AI_CONFIG_PP_SLM_TRIANGLE_LIMIT<tt>
+# settings. The default values are <tt>#AI_SLM_DEFAULT_MAX_VERTICES<tt> and
+# <tt>#AI_SLM_DEFAULT_MAX_TRIANGLES<tt>.
+#
+# Note that splitting is generally a time-consuming task, but only if there's
+# something to split. The use of this step is recommended for most users.
+#
+aiProcess_SplitLargeMeshes = 0x80
+
+## <hr>Removes the node graph and pre-transforms all vertices with
+# the local transformation matrices of their nodes.
+#
+# The output scene still contains nodes, however there is only a
+# root node with children, each one referencing only one mesh,
+# and each mesh referencing one material. For rendering, you can
+# simply render all meshes in order - you don't need to pay
+# attention to local transformations and the node hierarchy.
+# Animations are removed during this step.
+# This step is intended for applications without a scenegraph.
+# The step CAN cause some problems: if e.g. a mesh of the asset
+# contains normals and another, using the same material index, does not,
+# they will be brought together, but the first meshes's part of
+# the normal list is zeroed. However, these artifacts are rare.
+# @note The <tt>#AI_CONFIG_PP_PTV_NORMALIZE<tt> configuration property
+# can be set to normalize the scene's spatial dimension to the -1...1
+# range.
+#
+aiProcess_PreTransformVertices = 0x100
+
+## <hr>Limits the number of bones simultaneously affecting a single vertex
+# to a maximum value.
+#
+# If any vertex is affected by more than the maximum number of bones, the least
+# important vertex weights are removed and the remaining vertex weights are
+# renormalized so that the weights still sum up to 1.
+# The default bone weight limit is 4 (defined as <tt>#AI_LMW_MAX_WEIGHTS<tt> in
+# config.h), but you can use the <tt>#AI_CONFIG_PP_LBW_MAX_WEIGHTS<tt> setting to
+# supply your own limit to the post processing step.
+#
+# If you intend to perform the skinning in hardware, this post processing
+# step might be of interest to you.
+#
+aiProcess_LimitBoneWeights = 0x200
+
+## <hr>Validates the imported scene data structure.
+# This makes sure that all indices are valid, all animations and
+# bones are linked correctly, all material references are correct .. etc.
+#
+# It is recommended that you capture Assimp's log output if you use this flag,
+# so you can easily find out what's wrong if a file fails the
+# validation. The validator is quite strict and will find #all#
+# inconsistencies in the data structure... It is recommended that plugin
+# developers use it to debug their loaders. There are two types of
+# validation failures:
+# <ul>
+# <li>Error: There's something wrong with the imported data. Further
+# postprocessing is not possible and the data is not usable at all.
+# The import fails. #Importer::GetErrorString() or #aiGetErrorString()
+# carry the error message around.<li>
+# <li>Warning: There are some minor issues (e.g. 1000000 animation
+# keyframes with the same time), but further postprocessing and use
+# of the data structure is still safe. Warning details are written
+# to the log file, <tt>#AI_SCENE_FLAGS_VALIDATION_WARNING<tt> is set
+# in #aiScene::mFlags<li>
+# <ul>
+#
+# This post-processing step is not time-consuming. Its use is not
+# compulsory, but recommended.
+#
+aiProcess_ValidateDataStructure = 0x400
+
+## <hr>Reorders triangles for better vertex cache locality.
+#
+# The step tries to improve the ACMR (average post-transform vertex cache
+# miss ratio) for all meshes. The implementation runs in O(n) and is
+# roughly based on the 'tipsify' algorithm (see <a href="
+# http:www.cs.princeton.edugfxpubsSander_2007_%3ETRtipsy.pdf">this
+# paper<a>).
+#
+# If you intend to render huge models in hardware, this step might
+# be of interest to you. The <tt>#AI_CONFIG_PP_ICL_PTCACHE_SIZE<tt>config
+# setting can be used to fine-tune the cache optimization.
+#
+aiProcess_ImproveCacheLocality = 0x800
+
+## <hr>Searches for redundantunreferenced materials and removes them.
+#
+# This is especially useful in combination with the
+# #aiProcess_PretransformVertices and #aiProcess_OptimizeMeshes flags.
+# Both join small meshes with equal characteristics, but they can't do
+# their work if two meshes have different materials. Because several
+# material settings are lost during Assimp's import filters,
+# (and because many exporters don't check for redundant materials), huge
+# models often have materials which are are defined several times with
+# exactly the same settings.
+#
+# Several material settings not contributing to the final appearance of
+# a surface are ignored in all comparisons (e.g. the material name).
+# So, if you're passing additional information through the
+# content pipeline (probably using #magic# material names), don't
+# specify this flag. Alternatively take a look at the
+# <tt>#AI_CONFIG_PP_RRM_EXCLUDE_LIST<tt> setting.
+#
+aiProcess_RemoveRedundantMaterials = 0x1000
+
+## <hr>This step tries to determine which meshes have normal vectors
+# that are facing inwards and inverts them.
+#
+# The algorithm is simple but effective:
+# the bounding box of all vertices + their normals is compared against
+# the volume of the bounding box of all vertices without their normals.
+# This works well for most objects, problems might occur with planar
+# surfaces. However, the step tries to filter such cases.
+# The step inverts all in-facing normals. Generally it is recommended
+# to enable this step, although the result is not always correct.
+#
+aiProcess_FixInfacingNormals = 0x2000
+
+## <hr>This step splits meshes with more than one primitive type in
+# homogeneous sub-meshes.
+#
+# The step is executed after the triangulation step. After the step
+# returns, just one bit is set in aiMesh::mPrimitiveTypes. This is
+# especially useful for real-time rendering where point and line
+# primitives are often ignored or rendered separately.
+# You can use the <tt>#AI_CONFIG_PP_SBP_REMOVE<tt> option to specify which
+# primitive types you need. This can be used to easily exclude
+# lines and points, which are rarely used, from the import.
+#
+aiProcess_SortByPType = 0x8000
+
+## <hr>This step searches all meshes for degenerate primitives and
+# converts them to proper lines or points.
+#
+# A face is 'degenerate' if one or more of its points are identical.
+# To have the degenerate stuff not only detected and collapsed but
+# removed, try one of the following procedures:
+# <br><b>1.<b> (if you support lines and points for rendering but don't
+# want the degenerates)<br>
+# <ul>
+# <li>Specify the #aiProcess_FindDegenerates flag.
+# <li>
+# <li>Set the <tt>AI_CONFIG_PP_FD_REMOVE<tt> option to 1. This will
+# cause the step to remove degenerate triangles from the import
+# as soon as they're detected. They won't pass any further
+# pipeline steps.
+# <li>
+# <ul>
+# <br><b>2.<b>(if you don't support lines and points at all)<br>
+# <ul>
+# <li>Specify the #aiProcess_FindDegenerates flag.
+# <li>
+# <li>Specify the #aiProcess_SortByPType flag. This moves line and
+# point primitives to separate meshes.
+# <li>
+# <li>Set the <tt>AI_CONFIG_PP_SBP_REMOVE<tt> option to
+# @code aiPrimitiveType_POINTS | aiPrimitiveType_LINES
+# @endcode to cause SortByPType to reject point
+# and line meshes from the scene.
+# <li>
+# <ul>
+# @note Degenerate polygons are not necessarily evil and that's why
+# they're not removed by default. There are several file formats which
+# don't support lines or points, and some exporters bypass the
+# format specification and write them as degenerate triangles instead.
+#
+aiProcess_FindDegenerates = 0x10000
+
+## <hr>This step searches all meshes for invalid data, such as zeroed
+# normal vectors or invalid UV coords and removesfixes them. This is
+# intended to get rid of some common exporter errors.
+#
+# This is especially useful for normals. If they are invalid, and
+# the step recognizes this, they will be removed and can later
+# be recomputed, i.e. by the #aiProcess_GenSmoothNormals flag.<br>
+# The step will also remove meshes that are infinitely small and reduce
+# animation tracks consisting of hundreds if redundant keys to a single
+# key. The <tt>AI_CONFIG_PP_FID_ANIM_ACCURACY<tt> config property decides
+# the accuracy of the check for duplicate animation tracks.
+#
+aiProcess_FindInvalidData = 0x20000
+
+## <hr>This step converts non-UV mappings (such as spherical or
+# cylindrical mapping) to proper texture coordinate channels.
+#
+# Most applications will support UV mapping only, so you will
+# probably want to specify this step in every case. Note that Assimp is not
+# always able to match the original mapping implementation of the
+# 3D app which produced a model perfectly. It's always better to let the
+# modelling app compute the UV channels - 3ds max, Maya, Blender,
+# LightWave, and Modo do this for example.
+#
+# @note If this step is not requested, you'll need to process the
+# <tt>#AI_MATKEY_MAPPING<tt> material property in order to display all assets
+# properly.
+#
+aiProcess_GenUVCoords = 0x40000
+
+## <hr>This step applies per-texture UV transformations and bakes
+# them into stand-alone vtexture coordinate channels.
+#
+# UV transformations are specified per-texture - see the
+# <tt>#AI_MATKEY_UVTRANSFORM<tt> material key for more information.
+# This step processes all textures with
+# transformed input UV coordinates and generates a new (pre-transformed) UV channel
+# which replaces the old channel. Most applications won't support UV
+# transformations, so you will probably want to specify this step.
+#
+# @note UV transformations are usually implemented in real-time apps by
+# transforming texture coordinates at vertex shader stage with a 3x3
+# (homogenous) transformation matrix.
+#
+aiProcess_TransformUVCoords = 0x80000
+
+## <hr>This step searches for duplicate meshes and replaces them
+# with references to the first mesh.
+#
+# This step takes a while, so don't use it if speed is a concern.
+# Its main purpose is to workaround the fact that many export
+# file formats don't support instanced meshes, so exporters need to
+# duplicate meshes. This step removes the duplicates again. Please
+# note that Assimp does not currently support per-node material
+# assignment to meshes, which means that identical meshes with
+# different materials are currently #not# joined, although this is
+# planned for future versions.
+#
+aiProcess_FindInstances = 0x100000
+
+## <hr>A postprocessing step to reduce the number of meshes.
+#
+# This will, in fact, reduce the number of draw calls.
+#
+# This is a very effective optimization and is recommended to be used
+# together with #aiProcess_OptimizeGraph, if possible. The flag is fully
+# compatible with both #aiProcess_SplitLargeMeshes and #aiProcess_SortByPType.
+#
+aiProcess_OptimizeMeshes = 0x200000
+
+
+## <hr>A postprocessing step to optimize the scene hierarchy.
+#
+# Nodes without animations, bones, lights or cameras assigned are
+# collapsed and joined.
+#
+# Node names can be lost during this step. If you use special 'tag nodes'
+# to pass additional information through your content pipeline, use the
+# <tt>#AI_CONFIG_PP_OG_EXCLUDE_LIST<tt> setting to specify a list of node
+# names you want to be kept. Nodes matching one of the names in this list won't
+# be touched or modified.
+#
+# Use this flag with caution. Most simple files will be collapsed to a
+# single node, so complex hierarchies are usually completely lost. This is not
+# useful for editor environments, but probably a very effective
+# optimization if you just want to get the model data, convert it to your
+# own format, and render it as fast as possible.
+#
+# This flag is designed to be used with #aiProcess_OptimizeMeshes for best
+# results.
+#
+# @note 'Crappy' scenes with thousands of extremely small meshes packed
+# in deeply nested nodes exist for almost all file formats.
+# #aiProcess_OptimizeMeshes in combination with #aiProcess_OptimizeGraph
+# usually fixes them all and makes them renderable.
+#
+aiProcess_OptimizeGraph = 0x400000
+
+## <hr>This step flips all UV coordinates along the y-axis and adjusts
+# material settings and bitangents accordingly.
+#
+# <b>Output UV coordinate system:<b>
+# @code
+# 0y|0y ---------- 1x|0y
+# | |
+# | |
+# | |
+# 0x|1y ---------- 1x|1y
+# @endcode
+#
+# You'll probably want to consider this flag if you use Direct3D for
+# rendering. The #aiProcess_ConvertToLeftHanded flag supersedes this
+# setting and bundles all conversions typically required for D3D-based
+# applications.
+#
+aiProcess_FlipUVs = 0x800000
+
+## <hr>This step adjusts the output face winding order to be CW.
+#
+# The default face winding order is counter clockwise (CCW).
+#
+# <b>Output face order:<b>
+# @code
+# x2
+#
+# x0
+# x1
+# @endcode
+#
+aiProcess_FlipWindingOrder = 0x1000000
+
+## <hr>This step splits meshes with many bones into sub-meshes so that each
+# su-bmesh has fewer or as many bones as a given limit.
+#
+aiProcess_SplitByBoneCount = 0x2000000
+
+## <hr>This step removes bones losslessly or according to some threshold.
+#
+# In some cases (i.e. formats that require it) exporters are forced to
+# assign dummy bone weights to otherwise static meshes assigned to
+# animated meshes. Full, weight-based skinning is expensive while
+# animating nodes is extremely cheap, so this step is offered to clean up
+# the data in that regard.
+#
+# Use <tt>#AI_CONFIG_PP_DB_THRESHOLD<tt> to control this.
+# Use <tt>#AI_CONFIG_PP_DB_ALL_OR_NONE<tt> if you want bones removed if and
+# only if all bones within the scene qualify for removal.
+#
+aiProcess_Debone = 0x4000000
+
+aiProcess_GenEntityMeshes = 0x100000
+aiProcess_OptimizeAnimations = 0x200000
+aiProcess_FixTexturePaths = 0x200000
+aiProcess_EmbedTextures = 0x10000000,
+
+## @def aiProcess_ConvertToLeftHanded
+ # @brief Shortcut flag for Direct3D-based applications.
+ #
+ # Supersedes the #aiProcess_MakeLeftHanded and #aiProcess_FlipUVs and
+ # #aiProcess_FlipWindingOrder flags.
+ # The output data matches Direct3D's conventions: left-handed geometry, upper-left
+ # origin for UV coordinates and finally clockwise face order, suitable for CCW culling.
+ #
+ # @deprecated
+ #
+aiProcess_ConvertToLeftHanded = ( \
+ aiProcess_MakeLeftHanded | \
+ aiProcess_FlipUVs | \
+ aiProcess_FlipWindingOrder | \
+ 0 )
+
+
+## @def aiProcessPreset_TargetRealtimeUse_Fast
+ # @brief Default postprocess configuration optimizing the data for real-time rendering.
+ #
+ # Applications would want to use this preset to load models on end-user PCs,
+ # maybe for direct use in game.
+ #
+ # If you're using DirectX, don't forget to combine this value with
+ # the #aiProcess_ConvertToLeftHanded step. If you don't support UV transformations
+ # in your application apply the #aiProcess_TransformUVCoords step, too.
+ # @note Please take the time to read the docs for the steps enabled by this preset.
+ # Some of them offer further configurable properties, while some of them might not be of
+ # use for you so it might be better to not specify them.
+ #
+aiProcessPreset_TargetRealtime_Fast = ( \
+ aiProcess_CalcTangentSpace | \
+ aiProcess_GenNormals | \
+ aiProcess_JoinIdenticalVertices | \
+ aiProcess_Triangulate | \
+ aiProcess_GenUVCoords | \
+ aiProcess_SortByPType | \
+ 0 )
+
+ ## @def aiProcessPreset_TargetRealtime_Quality
+ # @brief Default postprocess configuration optimizing the data for real-time rendering.
+ #
+ # Unlike #aiProcessPreset_TargetRealtime_Fast, this configuration
+ # performs some extra optimizations to improve rendering speed and
+ # to minimize memory usage. It could be a good choice for a level editor
+ # environment where import speed is not so important.
+ #
+ # If you're using DirectX, don't forget to combine this value with
+ # the #aiProcess_ConvertToLeftHanded step. If you don't support UV transformations
+ # in your application apply the #aiProcess_TransformUVCoords step, too.
+ # @note Please take the time to read the docs for the steps enabled by this preset.
+ # Some of them offer further configurable properties, while some of them might not be
+ # of use for you so it might be better to not specify them.
+ #
+aiProcessPreset_TargetRealtime_Quality = ( \
+ aiProcess_CalcTangentSpace | \
+ aiProcess_GenSmoothNormals | \
+ aiProcess_JoinIdenticalVertices | \
+ aiProcess_ImproveCacheLocality | \
+ aiProcess_LimitBoneWeights | \
+ aiProcess_RemoveRedundantMaterials | \
+ aiProcess_SplitLargeMeshes | \
+ aiProcess_Triangulate | \
+ aiProcess_GenUVCoords | \
+ aiProcess_SortByPType | \
+ aiProcess_FindDegenerates | \
+ aiProcess_FindInvalidData | \
+ 0 )
+
+ ## @def aiProcessPreset_TargetRealtime_MaxQuality
+ # @brief Default postprocess configuration optimizing the data for real-time rendering.
+ #
+ # This preset enables almost every optimization step to achieve perfectly
+ # optimized data. It's your choice for level editor environments where import speed
+ # is not important.
+ #
+ # If you're using DirectX, don't forget to combine this value with
+ # the #aiProcess_ConvertToLeftHanded step. If you don't support UV transformations
+ # in your application, apply the #aiProcess_TransformUVCoords step, too.
+ # @note Please take the time to read the docs for the steps enabled by this preset.
+ # Some of them offer further configurable properties, while some of them might not be
+ # of use for you so it might be better to not specify them.
+ #
+aiProcessPreset_TargetRealtime_MaxQuality = ( \
+ aiProcessPreset_TargetRealtime_Quality | \
+ aiProcess_FindInstances | \
+ aiProcess_ValidateDataStructure | \
+ aiProcess_OptimizeMeshes | \
+ 0 )
+
+
diff --git a/libs/assimp/port/PyAssimp/pyassimp/structs.py b/libs/assimp/port/PyAssimp/pyassimp/structs.py
new file mode 100644
index 0000000..e1fba19
--- /dev/null
+++ b/libs/assimp/port/PyAssimp/pyassimp/structs.py
@@ -0,0 +1,1135 @@
+#-*- coding: utf-8 -*-
+
+from ctypes import POINTER, c_void_p, c_uint, c_char, c_float, Structure, c_double, c_ubyte, c_size_t, c_uint32
+
+
+class Vector2D(Structure):
+ """
+ See 'vector2.h' for details.
+ """
+
+
+ _fields_ = [
+ ("x", c_float),("y", c_float),
+ ]
+
+class Matrix3x3(Structure):
+ """
+ See 'matrix3x3.h' for details.
+ """
+
+
+ _fields_ = [
+ ("a1", c_float),("a2", c_float),("a3", c_float),
+ ("b1", c_float),("b2", c_float),("b3", c_float),
+ ("c1", c_float),("c2", c_float),("c3", c_float),
+ ]
+
+class Texel(Structure):
+ """
+ See 'texture.h' for details.
+ """
+
+ _fields_ = [
+ ("b", c_ubyte),("g", c_ubyte),("r", c_ubyte),("a", c_ubyte),
+ ]
+
+class Color4D(Structure):
+ """
+ See 'color4.h' for details.
+ """
+
+
+ _fields_ = [
+ # Red, green, blue and alpha color values
+ ("r", c_float),("g", c_float),("b", c_float),("a", c_float),
+ ]
+
+class Plane(Structure):
+ """
+ See 'types.h' for details.
+ """
+
+ _fields_ = [
+ # Plane equation
+ ("a", c_float),("b", c_float),("c", c_float),("d", c_float),
+ ]
+
+class Color3D(Structure):
+ """
+ See 'types.h' for details.
+ """
+
+ _fields_ = [
+ # Red, green and blue color values
+ ("r", c_float),("g", c_float),("b", c_float),
+ ]
+
+class String(Structure):
+ """
+ See 'types.h' for details.
+ """
+
+ MAXLEN = 1024
+
+ _fields_ = [
+ # Binary length of the string excluding the terminal 0. This is NOT the
+ # logical length of strings containing UTF-8 multibyte sequences! It's
+ # the number of bytes from the beginning of the string to its end.
+ ("length", c_uint32),
+
+ # String buffer. Size limit is MAXLEN
+ ("data", c_char*MAXLEN),
+ ]
+
+class MaterialPropertyString(Structure):
+ """
+ See 'MaterialSystem.cpp' for details.
+
+ The size of length is truncated to 4 bytes on 64-bit platforms when used as a
+ material property (see MaterialSystem.cpp aiMaterial::AddProperty() for details).
+ """
+
+ MAXLEN = 1024
+
+ _fields_ = [
+ # Binary length of the string excluding the terminal 0. This is NOT the
+ # logical length of strings containing UTF-8 multibyte sequences! It's
+ # the number of bytes from the beginning of the string to its end.
+ ("length", c_uint32),
+
+ # String buffer. Size limit is MAXLEN
+ ("data", c_char*MAXLEN),
+ ]
+
+class MemoryInfo(Structure):
+ """
+ See 'types.h' for details.
+ """
+
+ _fields_ = [
+ # Storage allocated for texture data
+ ("textures", c_uint),
+
+ # Storage allocated for material data
+ ("materials", c_uint),
+
+ # Storage allocated for mesh data
+ ("meshes", c_uint),
+
+ # Storage allocated for node data
+ ("nodes", c_uint),
+
+ # Storage allocated for animation data
+ ("animations", c_uint),
+
+ # Storage allocated for camera data
+ ("cameras", c_uint),
+
+ # Storage allocated for light data
+ ("lights", c_uint),
+
+ # Total storage allocated for the full import.
+ ("total", c_uint),
+ ]
+
+class Quaternion(Structure):
+ """
+ See 'quaternion.h' for details.
+ """
+
+
+ _fields_ = [
+ # w,x,y,z components of the quaternion
+ ("w", c_float),("x", c_float),("y", c_float),("z", c_float),
+ ]
+
+class Face(Structure):
+ """
+ See 'mesh.h' for details.
+ """
+
+ _fields_ = [
+ # Number of indices defining this face.
+ # The maximum value for this member is
+ #AI_MAX_FACE_INDICES.
+ ("mNumIndices", c_uint),
+
+ # Pointer to the indices array. Size of the array is given in numIndices.
+ ("mIndices", POINTER(c_uint)),
+ ]
+
+class VertexWeight(Structure):
+ """
+ See 'mesh.h' for details.
+ """
+
+ _fields_ = [
+ # Index of the vertex which is influenced by the bone.
+ ("mVertexId", c_uint),
+
+ # The strength of the influence in the range (0...1).
+ # The influence from all bones at one vertex amounts to 1.
+ ("mWeight", c_float),
+ ]
+
+class Matrix4x4(Structure):
+ """
+ See 'matrix4x4.h' for details.
+ """
+
+
+ _fields_ = [
+ ("a1", c_float),("a2", c_float),("a3", c_float),("a4", c_float),
+ ("b1", c_float),("b2", c_float),("b3", c_float),("b4", c_float),
+ ("c1", c_float),("c2", c_float),("c3", c_float),("c4", c_float),
+ ("d1", c_float),("d2", c_float),("d3", c_float),("d4", c_float),
+ ]
+
+class Vector3D(Structure):
+ """
+ See 'vector3.h' for details.
+ """
+
+
+ _fields_ = [
+ ("x", c_float),("y", c_float),("z", c_float),
+ ]
+
+class MeshKey(Structure):
+ """
+ See 'anim.h' for details.
+ """
+
+ _fields_ = [
+ # The time of this key
+ ("mTime", c_double),
+
+ # Index into the aiMesh::mAnimMeshes array of the
+ # mesh corresponding to the
+ #aiMeshAnim hosting this
+ # key frame. The referenced anim mesh is evaluated
+ # according to the rules defined in the docs for
+ #aiAnimMesh.
+ ("mValue", c_uint),
+ ]
+
+class MetadataEntry(Structure):
+ """
+ See 'metadata.h' for details
+ """
+ AI_BOOL = 0
+ AI_INT32 = 1
+ AI_UINT64 = 2
+ AI_FLOAT = 3
+ AI_DOUBLE = 4
+ AI_AISTRING = 5
+ AI_AIVECTOR3D = 6
+ AI_META_MAX = 7
+ _fields_ = [
+ # The type field uniquely identifies the underlying type of the data field
+ ("mType", c_uint),
+ ("mData", c_void_p),
+ ]
+
+class Metadata(Structure):
+ """
+ See 'metadata.h' for details
+ """
+ _fields_ = [
+ # Length of the mKeys and mValues arrays, respectively
+ ("mNumProperties", c_uint),
+
+ # Arrays of keys, may not be NULL. Entries in this array may not be NULL
+ # as well.
+ ("mKeys", POINTER(String)),
+
+ # Arrays of values, may not be NULL. Entries in this array may be NULL
+ # if the corresponding property key has no assigned value.
+ ("mValues", POINTER(MetadataEntry)),
+ ]
+
+class Node(Structure):
+ """
+ See 'scene.h' for details.
+ """
+
+
+Node._fields_ = [
+ # The name of the node.
+ # The name might be empty (length of zero) but all nodes which
+ # need to be accessed afterwards by bones or anims are usually named.
+ # Multiple nodes may have the same name, but nodes which are accessed
+ # by bones (see
+ #aiBone and
+ #aiMesh::mBones) *must* be unique.
+ # Cameras and lights are assigned to a specific node name - if there
+ # are multiple nodes with this name, they're assigned to each of them.
+ # <br>
+ # There are no limitations regarding the characters contained in
+ # this text. You should be able to handle stuff like whitespace, tabs,
+ # linefeeds, quotation marks, ampersands, ... .
+ ("mName", String),
+
+ # The transformation relative to the node's parent.
+ ("mTransformation", Matrix4x4),
+
+ # Parent node. NULL if this node is the root node.
+ ("mParent", POINTER(Node)),
+
+ # The number of child nodes of this node.
+ ("mNumChildren", c_uint),
+
+ # The child nodes of this node. NULL if mNumChildren is 0.
+ ("mChildren", POINTER(POINTER(Node))),
+
+ # The number of meshes of this node.
+ ("mNumMeshes", c_uint),
+
+ # The meshes of this node. Each entry is an index into the mesh
+ ("mMeshes", POINTER(c_uint)),
+
+ # Metadata associated with this node or NULL if there is no metadata.
+ # Whether any metadata is generated depends on the source file format.
+ ("mMetadata", POINTER(Metadata)),
+ ]
+
+class Light(Structure):
+ """
+ See 'light.h' for details.
+ """
+
+
+ _fields_ = [
+ # The name of the light source.
+ # There must be a node in the scenegraph with the same name.
+ # This node specifies the position of the light in the scene
+ # hierarchy and can be animated.
+ ("mName", String),
+
+ # The type of the light source.
+ # aiLightSource_UNDEFINED is not a valid value for this member.
+ ("mType", c_uint),
+
+ # Position of the light source in space. Relative to the
+ # transformation of the node corresponding to the light.
+ # The position is undefined for directional lights.
+ ("mPosition", Vector3D),
+
+ # Direction of the light source in space. Relative to the
+ # transformation of the node corresponding to the light.
+ # The direction is undefined for point lights. The vector
+ # may be normalized, but it needn't.
+ ("mDirection", Vector3D),
+
+ # Up direction of the light source in space. Relative to the
+ # transformation of the node corresponding to the light.
+ #
+ # The direction is undefined for point lights. The vector
+ # may be normalized, but it needn't.
+ ("mUp", Vector3D),
+
+ # Constant light attenuation factor.
+ # The intensity of the light source at a given distance 'd' from
+ # the light's position is
+ # @code
+ # Atten = 1/( att0 + att1
+ # d + att2
+ # d*d)
+ # @endcode
+ # This member corresponds to the att0 variable in the equation.
+ # Naturally undefined for directional lights.
+ ("mAttenuationConstant", c_float),
+
+ # Linear light attenuation factor.
+ # The intensity of the light source at a given distance 'd' from
+ # the light's position is
+ # @code
+ # Atten = 1/( att0 + att1
+ # d + att2
+ # d*d)
+ # @endcode
+ # This member corresponds to the att1 variable in the equation.
+ # Naturally undefined for directional lights.
+ ("mAttenuationLinear", c_float),
+
+ # Quadratic light attenuation factor.
+ # The intensity of the light source at a given distance 'd' from
+ # the light's position is
+ # @code
+ # Atten = 1/( att0 + att1
+ # d + att2
+ # d*d)
+ # @endcode
+ # This member corresponds to the att2 variable in the equation.
+ # Naturally undefined for directional lights.
+ ("mAttenuationQuadratic", c_float),
+
+ # Diffuse color of the light source
+ # The diffuse light color is multiplied with the diffuse
+ # material color to obtain the final color that contributes
+ # to the diffuse shading term.
+ ("mColorDiffuse", Color3D),
+
+ # Specular color of the light source
+ # The specular light color is multiplied with the specular
+ # material color to obtain the final color that contributes
+ # to the specular shading term.
+ ("mColorSpecular", Color3D),
+
+ # Ambient color of the light source
+ # The ambient light color is multiplied with the ambient
+ # material color to obtain the final color that contributes
+ # to the ambient shading term. Most renderers will ignore
+ # this value it, is just a remaining of the fixed-function pipeline
+ # that is still supported by quite many file formats.
+ ("mColorAmbient", Color3D),
+
+ # Inner angle of a spot light's light cone.
+ # The spot light has maximum influence on objects inside this
+ # angle. The angle is given in radians. It is 2PI for point
+ # lights and undefined for directional lights.
+ ("mAngleInnerCone", c_float),
+
+ # Outer angle of a spot light's light cone.
+ # The spot light does not affect objects outside this angle.
+ # The angle is given in radians. It is 2PI for point lights and
+ # undefined for directional lights. The outer angle must be
+ # greater than or equal to the inner angle.
+ # It is assumed that the application uses a smooth
+ # interpolation between the inner and the outer cone of the
+ # spot light.
+ ("mAngleOuterCone", c_float),
+
+ # Size of area light source.
+ ("mSize", Vector2D),
+ ]
+
+class Texture(Structure):
+ """
+ See 'texture.h' for details.
+ """
+
+
+ _fields_ = [
+ # Width of the texture, in pixels
+ # If mHeight is zero the texture is compressed in a format
+ # like JPEG. In this case mWidth specifies the size of the
+ # memory area pcData is pointing to, in bytes.
+ ("mWidth", c_uint),
+
+ # Height of the texture, in pixels
+ # If this value is zero, pcData points to an compressed texture
+ # in any format (e.g. JPEG).
+ ("mHeight", c_uint),
+
+ # A hint from the loader to make it easier for applications
+ # to determine the type of embedded textures.
+ #
+ # If mHeight != 0 this member is show how data is packed. Hint will consist of
+ # two parts: channel order and channel bitness (count of the bits for every
+ # color channel). For simple parsing by the viewer it's better to not omit
+ # absent color channel and just use 0 for bitness. For example:
+ # 1. Image contain RGBA and 8 bit per channel, achFormatHint == "rgba8888";
+ # 2. Image contain ARGB and 8 bit per channel, achFormatHint == "argb8888";
+ # 3. Image contain RGB and 5 bit for R and B channels and 6 bit for G channel,
+ # achFormatHint == "rgba5650";
+ # 4. One color image with B channel and 1 bit for it, achFormatHint == "rgba0010";
+ # If mHeight == 0 then achFormatHint is set set to '\\0\\0\\0\\0' if the loader has no additional
+ # information about the texture file format used OR the
+ # file extension of the format without a trailing dot. If there
+ # are multiple file extensions for a format, the shortest
+ # extension is chosen (JPEG maps to 'jpg', not to 'jpeg').
+ # E.g. 'dds\\0', 'pcx\\0', 'jpg\\0'. All characters are lower-case.
+ # The fourth character will always be '\\0'.
+ ("achFormatHint", c_char*9),
+
+ # Data of the texture.
+ # Points to an array of mWidth
+ # mHeight aiTexel's.
+ # The format of the texture data is always ARGB8888 to
+ # make the implementation for user of the library as easy
+ # as possible. If mHeight = 0 this is a pointer to a memory
+ # buffer of size mWidth containing the compressed texture
+ # data. Good luck, have fun!
+ ("pcData", POINTER(Texel)),
+
+ # Texture original filename
+ # Used to get the texture reference
+ ("mFilename", String),
+ ]
+
+class Ray(Structure):
+ """
+ See 'types.h' for details.
+ """
+
+ _fields_ = [
+ # Position and direction of the ray
+ ("pos", Vector3D),("dir", Vector3D),
+ ]
+
+class UVTransform(Structure):
+ """
+ See 'material.h' for details.
+ """
+
+ _fields_ = [
+ # Translation on the u and v axes.
+ # The default value is (0|0).
+ ("mTranslation", Vector2D),
+
+ # Scaling on the u and v axes.
+ # The default value is (1|1).
+ ("mScaling", Vector2D),
+
+ # Rotation - in counter-clockwise direction.
+ # The rotation angle is specified in radians. The
+ # rotation center is 0.5f|0.5f. The default value
+ # 0.f.
+ ("mRotation", c_float),
+ ]
+
+class MaterialProperty(Structure):
+ """
+ See 'material.h' for details.
+ """
+
+ _fields_ = [
+ # Specifies the name of the property (key)
+ # Keys are generally case insensitive.
+ ("mKey", String),
+
+ # Textures: Specifies their exact usage semantic.
+ # For non-texture properties, this member is always 0
+ # (or, better-said,
+ #aiTextureType_NONE).
+ ("mSemantic", c_uint),
+
+ # Textures: Specifies the index of the texture.
+ # For non-texture properties, this member is always 0.
+ ("mIndex", c_uint),
+
+ # Size of the buffer mData is pointing to, in bytes.
+ # This value may not be 0.
+ ("mDataLength", c_uint),
+
+ # Type information for the property.
+ # Defines the data layout inside the data buffer. This is used
+ # by the library internally to perform debug checks and to
+ # utilize proper type conversions.
+ # (It's probably a hacky solution, but it works.)
+ ("mType", c_uint),
+
+ # Binary buffer to hold the property's value.
+ # The size of the buffer is always mDataLength.
+ ("mData", POINTER(c_char)),
+ ]
+
+class Material(Structure):
+ """
+ See 'material.h' for details.
+ """
+
+ _fields_ = [
+ # List of all material properties loaded.
+ ("mProperties", POINTER(POINTER(MaterialProperty))),
+
+ # Number of properties in the data base
+ ("mNumProperties", c_uint),
+
+ # Storage allocated
+ ("mNumAllocated", c_uint),
+ ]
+
+class Bone(Structure):
+ """
+ See 'mesh.h' for details.
+ """
+
+ _fields_ = [
+ # The name of the bone.
+ ("mName", String),
+
+ # The number of vertices affected by this bone
+ # The maximum value for this member is
+ #AI_MAX_BONE_WEIGHTS.
+ ("mNumWeights", c_uint),
+
+ # The vertices affected by this bone
+ ("mWeights", POINTER(VertexWeight)),
+
+ # Matrix that transforms from mesh space to bone space in bind pose
+ ("mOffsetMatrix", Matrix4x4),
+ ]
+
+
+class AnimMesh(Structure):
+ """
+ See 'mesh.h' for details.
+ """
+
+ AI_MAX_NUMBER_OF_TEXTURECOORDS = 0x8
+ AI_MAX_NUMBER_OF_COLOR_SETS = 0x8
+
+ _fields_ = [
+ # Anim Mesh name
+ ("mName", String),
+
+ # 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
+ # meshes may neither add or nor remove vertex components (if
+ # a replacement array is NULL and the corresponding source
+ # array is not, the source data is taken instead)
+ ("mVertices", POINTER(Vector3D)),
+
+ # Replacement for aiMesh::mNormals.
+ ("mNormals", POINTER(Vector3D)),
+
+ # Replacement for aiMesh::mTangents.
+ ("mTangents", POINTER(Vector3D)),
+
+ # Replacement for aiMesh::mBitangents.
+ ("mBitangents", POINTER(Vector3D)),
+
+ # Replacement for aiMesh::mColors
+ ("mColors", POINTER(Color4D) * AI_MAX_NUMBER_OF_COLOR_SETS),
+
+ # Replacement for aiMesh::mTextureCoords
+ ("mTextureCoords", POINTER(Vector3D) * AI_MAX_NUMBER_OF_TEXTURECOORDS),
+
+ # The number of vertices in the aiAnimMesh, and thus the length of all
+ # the member arrays.
+ #
+ # This has always the same value as the mNumVertices property in the
+ # corresponding aiMesh. It is duplicated here merely to make the length
+ # of the member arrays accessible even if the aiMesh is not known, e.g.
+ # from language bindings.
+ ("mNumVertices", c_uint),
+
+ # Weight of the AnimMesh.
+ ("mWeight", c_float),
+ ]
+
+
+class Mesh(Structure):
+ """
+ See 'mesh.h' for details.
+ """
+
+ AI_MAX_FACE_INDICES = 0x7fff
+ AI_MAX_BONE_WEIGHTS = 0x7fffffff
+ AI_MAX_VERTICES = 0x7fffffff
+ AI_MAX_FACES = 0x7fffffff
+ AI_MAX_NUMBER_OF_COLOR_SETS = 0x8
+ AI_MAX_NUMBER_OF_TEXTURECOORDS = 0x8
+
+ _fields_ = [ # Bitwise combination of the members of the
+ #aiPrimitiveType enum.
+ # This specifies which types of primitives are present in the mesh.
+ # The "SortByPrimitiveType"-Step can be used to make sure the
+ # output meshes consist of one primitive type each.
+ ("mPrimitiveTypes", c_uint),
+
+ # The number of vertices in this mesh.
+ # This is also the size of all of the per-vertex data arrays.
+ # The maximum value for this member is
+ #AI_MAX_VERTICES.
+ ("mNumVertices", c_uint),
+
+ # The number of primitives (triangles, polygons, lines) in this mesh.
+ # This is also the size of the mFaces array.
+ # The maximum value for this member is
+ #AI_MAX_FACES.
+ ("mNumFaces", c_uint),
+
+ # Vertex positions.
+ # This array is always present in a mesh. The array is
+ # mNumVertices in size.
+ ("mVertices", POINTER(Vector3D)),
+
+ # Vertex normals.
+ # The array contains normalized vectors, NULL if not present.
+ # The array is mNumVertices in size. Normals are undefined for
+ # point and line primitives. A mesh consisting of points and
+ # lines only may not have normal vectors. Meshes with mixed
+ # primitive types (i.e. lines and triangles) may have normals,
+ # but the normals for vertices that are only referenced by
+ # point or line primitives are undefined and set to QNaN (WARN:
+ # qNaN compares to inequal to *everything*, even to qNaN itself.
+ # Using code like this to check whether a field is qnan is:
+ # @code
+ #define IS_QNAN(f) (f != f)
+ # @endcode
+ # still dangerous because even 1.f == 1.f could evaluate to false! (
+ # remember the subtleties of IEEE754 artithmetics). Use stuff like
+ # @c fpclassify instead.
+ # @note Normal vectors computed by Assimp are always unit-length.
+ # However, this needn't apply for normals that have been taken
+ # directly from the model file.
+ ("mNormals", POINTER(Vector3D)),
+
+ # Vertex tangents.
+ # The tangent of a vertex points in the direction of the positive
+ # X texture axis. The array contains normalized vectors, NULL if
+ # not present. The array is mNumVertices in size. A mesh consisting
+ # of points and lines only may not have normal vectors. Meshes with
+ # mixed primitive types (i.e. lines and triangles) may have
+ # normals, but the normals for vertices that are only referenced by
+ # point or line primitives are undefined and set to qNaN. See
+ # the
+ #mNormals member for a detailed discussion of qNaNs.
+ # @note If the mesh contains tangents, it automatically also
+ # contains bitangents (the bitangent is just the cross product of
+ # tangent and normal vectors).
+ ("mTangents", POINTER(Vector3D)),
+
+ # Vertex bitangents.
+ # The bitangent of a vertex points in the direction of the positive
+ # Y texture axis. The array contains normalized vectors, NULL if not
+ # present. The array is mNumVertices in size.
+ # @note If the mesh contains tangents, it automatically also contains
+ # bitangents.
+ ("mBitangents", POINTER(Vector3D)),
+
+ # Vertex color sets.
+ # A mesh may contain 0 to
+ #AI_MAX_NUMBER_OF_COLOR_SETS vertex
+ # colors per vertex. NULL if not present. Each array is
+ # mNumVertices in size if present.
+ ("mColors", POINTER(Color4D)*AI_MAX_NUMBER_OF_COLOR_SETS),
+
+ # Vertex texture coords, also known as UV channels.
+ # A mesh may contain 0 to AI_MAX_NUMBER_OF_TEXTURECOORDS per
+ # vertex. NULL if not present. The array is mNumVertices in size.
+ ("mTextureCoords", POINTER(Vector3D)*AI_MAX_NUMBER_OF_TEXTURECOORDS),
+
+ # Specifies the number of components for a given UV channel.
+ # Up to three channels are supported (UVW, for accessing volume
+ # or cube maps). If the value is 2 for a given channel n, the
+ # component p.z of mTextureCoords[n][p] is set to 0.0f.
+ # If the value is 1 for a given channel, p.y is set to 0.0f, too.
+ # @note 4D coords are not supported
+ ("mNumUVComponents", c_uint*AI_MAX_NUMBER_OF_TEXTURECOORDS),
+
+ # The faces the mesh is constructed from.
+ # Each face refers to a number of vertices by their indices.
+ # This array is always present in a mesh, its size is given
+ # in mNumFaces. If the
+ #AI_SCENE_FLAGS_NON_VERBOSE_FORMAT
+ # is NOT set each face references an unique set of vertices.
+ ("mFaces", POINTER(Face)),
+
+ # The number of bones this mesh contains.
+ # Can be 0, in which case the mBones array is NULL.
+ ("mNumBones", c_uint),
+
+ # The bones of this mesh.
+ # A bone consists of a name by which it can be found in the
+ # frame hierarchy and a set of vertex weights.
+ ("mBones", POINTER(POINTER(Bone))),
+
+ # The material used by this mesh.
+ # A mesh does use only a single material. If an imported model uses
+ # multiple materials, the import splits up the mesh. Use this value
+ # as index into the scene's material list.
+ ("mMaterialIndex", c_uint),
+
+ # Name of the mesh. Meshes can be named, but this is not a
+ # requirement and leaving this field empty is totally fine.
+ # There are mainly three uses for mesh names:
+ # - some formats name nodes and meshes independently.
+ # - importers tend to split meshes up to meet the
+ # one-material-per-mesh requirement. Assigning
+ # the same (dummy) name to each of the result meshes
+ # aids the caller at recovering the original mesh
+ # partitioning.
+ # - Vertex animations refer to meshes by their names.
+ ("mName", String),
+
+ # The number of attachment meshes. Note! Currently only works with Collada loader.
+ ("mNumAnimMeshes", c_uint),
+
+ # Attachment meshes for this mesh, for vertex-based animation.
+ # Attachment meshes carry replacement data for some of the
+ # mesh'es vertex components (usually positions, normals).
+ # Note! Currently only works with Collada loader.
+ ("mAnimMeshes", POINTER(POINTER(AnimMesh))),
+
+ # Method of morphing when animeshes are specified.
+ ("mMethod", c_uint),
+
+ ]
+
+class Camera(Structure):
+ """
+ See 'camera.h' for details.
+ """
+
+
+ _fields_ = [
+ # The name of the camera.
+ # There must be a node in the scenegraph with the same name.
+ # This node specifies the position of the camera in the scene
+ # hierarchy and can be animated.
+ ("mName", String),
+
+ # Position of the camera relative to the coordinate space
+ # defined by the corresponding node.
+ # The default value is 0|0|0.
+ ("mPosition", Vector3D),
+
+ # 'Up' - vector of the camera coordinate system relative to
+ # the coordinate space defined by the corresponding node.
+ # The 'right' vector of the camera coordinate system is
+ # the cross product of the up and lookAt vectors.
+ # The default value is 0|1|0. The vector
+ # may be normalized, but it needn't.
+ ("mUp", Vector3D),
+
+ # 'LookAt' - vector of the camera coordinate system relative to
+ # the coordinate space defined by the corresponding node.
+ # This is the viewing direction of the user.
+ # The default value is 0|0|1. The vector
+ # may be normalized, but it needn't.
+ ("mLookAt", Vector3D),
+
+ # Half horizontal field of view angle, in radians.
+ # The field of view angle is the angle between the center
+ # line of the screen and the left or right border.
+ # The default value is 1/4PI.
+ ("mHorizontalFOV", c_float),
+
+ # Distance of the near clipping plane from the camera.
+ # The value may not be 0.f (for arithmetic reasons to prevent
+ # a division through zero). The default value is 0.1f.
+ ("mClipPlaneNear", c_float),
+
+ # Distance of the far clipping plane from the camera.
+ # The far clipping plane must, of course, be further away than the
+ # near clipping plane. The default value is 1000.f. The ratio
+ # between the near and the far plane should not be too
+ # large (between 1000-10000 should be ok) to avoid floating-point
+ # inaccuracies which could lead to z-fighting.
+ ("mClipPlaneFar", c_float),
+
+ # Screen aspect ratio.
+ # This is the ration between the width and the height of the
+ # screen. Typical values are 4/3, 1/2 or 1/1. This value is
+ # 0 if the aspect ratio is not defined in the source file.
+ # 0 is also the default value.
+ ("mAspect", c_float),
+ ]
+
+class VectorKey(Structure):
+ """
+ See 'anim.h' for details.
+ """
+
+ _fields_ = [
+ # The time of this key
+ ("mTime", c_double),
+
+ # The value of this key
+ ("mValue", Vector3D),
+ ]
+
+class QuatKey(Structure):
+ """
+ See 'anim.h' for details.
+ """
+
+ _fields_ = [
+ # The time of this key
+ ("mTime", c_double),
+
+ # The value of this key
+ ("mValue", Quaternion),
+ ]
+
+class MeshMorphKey(Structure):
+ """
+ See 'anim.h' for details.
+ """
+
+ _fields_ = [
+ # The time of this key
+ ("mTime", c_double),
+
+ # The values and weights at the time of this key
+ ("mValues", POINTER(c_uint)),
+ ("mWeights", POINTER(c_double)),
+
+ # The number of values and weights
+ ("mNumValuesAndWeights", c_uint),
+
+ ]
+
+class NodeAnim(Structure):
+ """
+ See 'anim.h' for details.
+ """
+
+ _fields_ = [
+ # The name of the node affected by this animation. The node
+ # must exist and it must be unique.
+ ("mNodeName", String),
+
+ # The number of position keys
+ ("mNumPositionKeys", c_uint),
+
+ # The position keys of this animation channel. Positions are
+ # specified as 3D vector. The array is mNumPositionKeys in size.
+ # If there are position keys, there will also be at least one
+ # scaling and one rotation key.
+ ("mPositionKeys", POINTER(VectorKey)),
+
+ # The number of rotation keys
+ ("mNumRotationKeys", c_uint),
+
+ # The rotation keys of this animation channel. Rotations are
+ # given as quaternions, which are 4D vectors. The array is
+ # mNumRotationKeys in size.
+ # If there are rotation keys, there will also be at least one
+ # scaling and one position key.
+ ("mRotationKeys", POINTER(QuatKey)),
+
+ # The number of scaling keys
+ ("mNumScalingKeys", c_uint),
+
+ # The scaling keys of this animation channel. Scalings are
+ # specified as 3D vector. The array is mNumScalingKeys in size.
+ # If there are scaling keys, there will also be at least one
+ # position and one rotation key.
+ ("mScalingKeys", POINTER(VectorKey)),
+
+ # Defines how the animation behaves before the first
+ # key is encountered.
+ # The default value is aiAnimBehaviour_DEFAULT (the original
+ # transformation matrix of the affected node is used).
+ ("mPreState", c_uint),
+
+ # Defines how the animation behaves after the last
+ # key was processed.
+ # The default value is aiAnimBehaviour_DEFAULT (the original
+ # transformation matrix of the affected node is taken).
+ ("mPostState", c_uint),
+ ]
+
+class MeshAnim(Structure):
+ """
+ See 'anim.h' for details.
+ """
+
+ _fields_ = [
+ # Name of the mesh to be animated. An empty string is not allowed,
+ # animated meshes need to be named (not necessarily uniquely,
+ # the name can basically serve as wild-card to select a group
+ # of meshes with similar animation setup)
+ ("mName", String),
+
+ # Size of the #mKeys array. Must be 1, at least.
+ ("mNumKeys", c_uint),
+
+ # Key frames of the animation. May not be NULL.
+ ("mKeys", POINTER(MeshKey)),
+ ]
+
+class MeshMorphAnim(Structure):
+ """
+ See 'anim.h' for details.
+ """
+
+ _fields_ = [
+ # Name of the mesh to be animated. An empty string is not allowed,
+ # animated meshes need to be named (not necessarily uniquely,
+ # the name can basically serve as wildcard to select a group
+ # of meshes with similar animation setup)
+ ("mName", String),
+
+ # Size of the #mKeys array. Must be 1, at least.
+ ("mNumKeys", c_uint),
+
+ # Key frames of the animation. May not be NULL.
+ ("mKeys", POINTER(MeshMorphKey)),
+ ]
+
+
+class Animation(Structure):
+ """
+ See 'anim.h' for details.
+ """
+
+ _fields_ = [
+ # The name of the animation. If the modeling package this data was
+ # exported from does support only a single animation channel, this
+ # name is usually empty (length is zero).
+ ("mName", String),
+
+ # Duration of the animation in ticks.
+ ("mDuration", c_double),
+
+ # Ticks per second. 0 if not specified in the imported file
+ ("mTicksPerSecond", c_double),
+
+ # The number of bone animation channels. Each channel affects
+ # a single node.
+ ("mNumChannels", c_uint),
+
+ # The node animation channels. Each channel affects a single node.
+ # The array is mNumChannels in size.
+ ("mChannels", POINTER(POINTER(NodeAnim))),
+
+ # The number of mesh animation channels. Each channel affects
+ # a single mesh and defines vertex-based animation.
+ ("mNumMeshChannels", c_uint),
+
+ # The mesh animation channels. Each channel affects a single mesh.
+ # The array is mNumMeshChannels in size.
+ ("mMeshChannels", POINTER(POINTER(MeshAnim))),
+
+ # The number of mesh animation channels. Each channel affects
+ # a single mesh and defines morphing animation.
+ ("mNumMorphMeshChannels", c_uint),
+
+ # The morph mesh animation channels. Each channel affects a single mesh.
+ # The array is mNumMorphMeshChannels in size.
+ ("mMorphMeshChannels", POINTER(POINTER(MeshMorphAnim))),
+
+ ]
+
+class ExportDataBlob(Structure):
+ """
+ See 'cexport.h' for details.
+
+ Note that the '_fields_' definition is outside the class to allow the 'next' field to be recursive
+ """
+ pass
+
+ExportDataBlob._fields_ = [
+ # Size of the data in bytes
+ ("size", c_size_t),
+
+ # The data.
+ ("data", c_void_p),
+
+ # Name of the blob. An empty string always
+ # indicates the first (and primary) blob,
+ # which contains the actual file data.
+ # Any other blobs are auxiliary files produced
+ # by exporters (i.e. material files). Existence
+ # of such files depends on the file format. Most
+ # formats don't split assets across multiple files.
+ #
+ # If used, blob names usually contain the file
+ # extension that should be used when writing
+ # the data to disc.
+ ("name", String),
+
+ # Pointer to the next blob in the chain or NULL if there is none.
+ ("next", POINTER(ExportDataBlob)),
+ ]
+
+
+class Scene(Structure):
+ """
+ See 'aiScene.h' for details.
+ """
+
+ AI_SCENE_FLAGS_INCOMPLETE = 0x1
+ AI_SCENE_FLAGS_VALIDATED = 0x2
+ AI_SCENE_FLAGS_VALIDATION_WARNING = 0x4
+ AI_SCENE_FLAGS_NON_VERBOSE_FORMAT = 0x8
+ AI_SCENE_FLAGS_TERRAIN = 0x10
+ AI_SCENE_FLAGS_ALLOW_SHARED = 0x20
+
+ _fields_ = [
+ # Any combination of the AI_SCENE_FLAGS_XXX flags. By default
+ # this value is 0, no flags are set. Most applications will
+ # want to reject all scenes with the AI_SCENE_FLAGS_INCOMPLETE
+ # bit set.
+ ("mFlags", c_uint),
+
+ # The root node of the hierarchy.
+ # There will always be at least the root node if the import
+ # was successful (and no special flags have been set).
+ # Presence of further nodes depends on the format and content
+ # of the imported file.
+ ("mRootNode", POINTER(Node)),
+
+ # The number of meshes in the scene.
+ ("mNumMeshes", c_uint),
+
+ # The array of meshes.
+ # Use the indices given in the aiNode structure to access
+ # this array. The array is mNumMeshes in size. If the
+ # AI_SCENE_FLAGS_INCOMPLETE flag is not set there will always
+ # be at least ONE material.
+ ("mMeshes", POINTER(POINTER(Mesh))),
+
+ # The number of materials in the scene.
+ ("mNumMaterials", c_uint),
+
+ # The array of materials.
+ # Use the index given in each aiMesh structure to access this
+ # array. The array is mNumMaterials in size. If the
+ # AI_SCENE_FLAGS_INCOMPLETE flag is not set there will always
+ # be at least ONE material.
+ ("mMaterials", POINTER(POINTER(Material))),
+
+ # The number of animations in the scene.
+ ("mNumAnimations", c_uint),
+
+ # The array of animations.
+ # All animations imported from the given file are listed here.
+ # The array is mNumAnimations in size.
+ ("mAnimations", POINTER(POINTER(Animation))),
+
+ # The number of textures embedded into the file
+ ("mNumTextures", c_uint),
+
+ # The array of embedded textures.
+ # Not many file formats embed their textures into the file.
+ # An example is Quake's MDL format (which is also used by
+ # some GameStudio versions)
+ ("mTextures", POINTER(POINTER(Texture))),
+
+ # The number of light sources in the scene. Light sources
+ # are fully optional, in most cases this attribute will be 0
+ ("mNumLights", c_uint),
+
+ # The array of light sources.
+ # All light sources imported from the given file are
+ # listed here. The array is mNumLights in size.
+ ("mLights", POINTER(POINTER(Light))),
+
+ # The number of cameras in the scene. Cameras
+ # are fully optional, in most cases this attribute will be 0
+ ("mNumCameras", c_uint),
+
+ # The array of cameras.
+ # All cameras imported from the given file are listed here.
+ # The array is mNumCameras in size. The first camera in the
+ # array (if existing) is the default camera view into
+ # the scene.
+ ("mCameras", POINTER(POINTER(Camera))),
+
+ # This data contains global metadata which belongs to the scene like
+ # unit-conversions, versions, vendors or other model-specific data. This
+ # can be used to store format-specific metadata as well.
+ ("mMetadata", POINTER(Metadata)),
+
+ # Internal data, do not touch
+ ("mPrivate", POINTER(c_char)),
+ ]
+
+assimp_structs_as_tuple = (Matrix4x4,
+ Matrix3x3,
+ Vector2D,
+ Vector3D,
+ Color3D,
+ Color4D,
+ Quaternion,
+ Plane,
+ Texel)
diff --git a/libs/assimp/port/PyAssimp/scripts/3d_viewer.py b/libs/assimp/port/PyAssimp/scripts/3d_viewer.py
new file mode 100755
index 0000000..08a6266
--- /dev/null
+++ b/libs/assimp/port/PyAssimp/scripts/3d_viewer.py
@@ -0,0 +1,1318 @@
+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+
+""" This program loads a model with PyASSIMP, and display it.
+
+Based on:
+- pygame code from http://3dengine.org/Spectator_%28PyOpenGL%29
+- http://www.lighthouse3d.com/tutorials
+- http://www.songho.ca/opengl/gl_transform.html
+- http://code.activestate.com/recipes/325391/
+- ASSIMP's C++ SimpleOpenGL viewer
+
+Authors: Séverin Lemaignan, 2012-2016
+"""
+import sys
+import logging
+
+logger = logging.getLogger("pyassimp")
+gllogger = logging.getLogger("OpenGL")
+gllogger.setLevel(logging.WARNING)
+logging.basicConfig(level=logging.INFO)
+
+import OpenGL
+
+OpenGL.ERROR_CHECKING = False
+OpenGL.ERROR_LOGGING = False
+# OpenGL.ERROR_ON_COPY = True
+# OpenGL.FULL_LOGGING = True
+from OpenGL.GL import *
+from OpenGL.arrays import vbo
+from OpenGL.GL import shaders
+
+import pygame
+import pygame.font
+import pygame.image
+
+import math, random
+from numpy import linalg
+
+import pyassimp
+from pyassimp.postprocess import *
+from pyassimp.helper import *
+import transformations
+
+ROTATION_180_X = numpy.array([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]], dtype=numpy.float32)
+
+# rendering mode
+BASE = "BASE"
+COLORS = "COLORS"
+SILHOUETTE = "SILHOUETTE"
+HELPERS = "HELPERS"
+
+# Entities type
+ENTITY = "entity"
+CAMERA = "camera"
+MESH = "mesh"
+
+FLAT_VERTEX_SHADER_120 = """
+#version 120
+
+uniform mat4 u_viewProjectionMatrix;
+uniform mat4 u_modelMatrix;
+
+uniform vec4 u_materialDiffuse;
+
+attribute vec3 a_vertex;
+
+varying vec4 v_color;
+
+void main(void)
+{
+ v_color = u_materialDiffuse;
+ gl_Position = u_viewProjectionMatrix * u_modelMatrix * vec4(a_vertex, 1.0);
+}
+"""
+
+FLAT_VERTEX_SHADER_130 = """
+#version 130
+
+uniform mat4 u_viewProjectionMatrix;
+uniform mat4 u_modelMatrix;
+
+uniform vec4 u_materialDiffuse;
+
+in vec3 a_vertex;
+
+out vec4 v_color;
+
+void main(void)
+{
+ v_color = u_materialDiffuse;
+ gl_Position = u_viewProjectionMatrix * u_modelMatrix * vec4(a_vertex, 1.0);
+}
+"""
+
+BASIC_VERTEX_SHADER_120 = """
+#version 120
+
+uniform mat4 u_viewProjectionMatrix;
+uniform mat4 u_modelMatrix;
+uniform mat3 u_normalMatrix;
+uniform vec3 u_lightPos;
+
+uniform vec4 u_materialDiffuse;
+
+attribute vec3 a_vertex;
+attribute vec3 a_normal;
+
+varying vec4 v_color;
+
+void main(void)
+{
+ // Now the normal is in world space, as we pass the light in world space.
+ vec3 normal = u_normalMatrix * a_normal;
+
+ float dist = distance(a_vertex, u_lightPos);
+
+ // go to https://www.desmos.com/calculator/nmnaud1hrw to play with the parameters
+ // att is not used for now
+ float att=1.0/(1.0+0.8*dist*dist);
+
+ vec3 surf2light = normalize(u_lightPos - a_vertex);
+ vec3 norm = normalize(normal);
+ float dcont=max(0.0,dot(norm,surf2light));
+
+ float ambient = 0.3;
+ float intensity = dcont + 0.3 + ambient;
+
+ v_color = u_materialDiffuse * intensity;
+
+ gl_Position = u_viewProjectionMatrix * u_modelMatrix * vec4(a_vertex, 1.0);
+}
+"""
+
+BASIC_VERTEX_SHADER_130 = """
+#version 130
+
+uniform mat4 u_viewProjectionMatrix;
+uniform mat4 u_modelMatrix;
+uniform mat3 u_normalMatrix;
+uniform vec3 u_lightPos;
+
+uniform vec4 u_materialDiffuse;
+
+in vec3 a_vertex;
+in vec3 a_normal;
+
+out vec4 v_color;
+
+void main(void)
+{
+ // Now the normal is in world space, as we pass the light in world space.
+ vec3 normal = u_normalMatrix * a_normal;
+
+ float dist = distance(a_vertex, u_lightPos);
+
+ // go to https://www.desmos.com/calculator/nmnaud1hrw to play with the parameters
+ // att is not used for now
+ float att=1.0/(1.0+0.8*dist*dist);
+
+ vec3 surf2light = normalize(u_lightPos - a_vertex);
+ vec3 norm = normalize(normal);
+ float dcont=max(0.0,dot(norm,surf2light));
+
+ float ambient = 0.3;
+ float intensity = dcont + 0.3 + ambient;
+
+ v_color = u_materialDiffuse * intensity;
+
+ gl_Position = u_viewProjectionMatrix * u_modelMatrix * vec4(a_vertex, 1.0);
+}
+"""
+
+BASIC_FRAGMENT_SHADER_120 = """
+#version 120
+
+varying vec4 v_color;
+
+void main() {
+ gl_FragColor = v_color;
+}
+"""
+
+BASIC_FRAGMENT_SHADER_130 = """
+#version 130
+
+in vec4 v_color;
+
+void main() {
+ gl_FragColor = v_color;
+}
+"""
+
+GOOCH_VERTEX_SHADER_120 = """
+#version 120
+
+// attributes
+attribute vec3 a_vertex; // xyz - position
+attribute vec3 a_normal; // xyz - normal
+
+// uniforms
+uniform mat4 u_modelMatrix;
+uniform mat4 u_viewProjectionMatrix;
+uniform mat3 u_normalMatrix;
+uniform vec3 u_lightPos;
+uniform vec3 u_camPos;
+
+// output data from vertex to fragment shader
+varying vec3 o_normal;
+varying vec3 o_lightVector;
+
+///////////////////////////////////////////////////////////////////
+
+void main(void)
+{
+ // transform position and normal to world space
+ vec4 positionWorld = u_modelMatrix * vec4(a_vertex, 1.0);
+ vec3 normalWorld = u_normalMatrix * a_normal;
+
+ // calculate and pass vectors required for lighting
+ o_lightVector = u_lightPos - positionWorld.xyz;
+ o_normal = normalWorld;
+
+ // project world space position to the screen and output it
+ gl_Position = u_viewProjectionMatrix * positionWorld;
+}
+"""
+
+GOOCH_VERTEX_SHADER_130 = """
+#version 130
+
+// attributes
+in vec3 a_vertex; // xyz - position
+in vec3 a_normal; // xyz - normal
+
+// uniforms
+uniform mat4 u_modelMatrix;
+uniform mat4 u_viewProjectionMatrix;
+uniform mat3 u_normalMatrix;
+uniform vec3 u_lightPos;
+uniform vec3 u_camPos;
+
+// output data from vertex to fragment shader
+out vec3 o_normal;
+out vec3 o_lightVector;
+
+///////////////////////////////////////////////////////////////////
+
+void main(void)
+{
+ // transform position and normal to world space
+ vec4 positionWorld = u_modelMatrix * vec4(a_vertex, 1.0);
+ vec3 normalWorld = u_normalMatrix * a_normal;
+
+ // calculate and pass vectors required for lighting
+ o_lightVector = u_lightPos - positionWorld.xyz;
+ o_normal = normalWorld;
+
+ // project world space position to the screen and output it
+ gl_Position = u_viewProjectionMatrix * positionWorld;
+}
+"""
+
+GOOCH_FRAGMENT_SHADER_120 = """
+#version 120
+
+// data from vertex shader
+varying vec3 o_normal;
+varying vec3 o_lightVector;
+
+// diffuse color of the object
+uniform vec4 u_materialDiffuse;
+// cool color of gooch shading
+uniform vec3 u_coolColor;
+// warm color of gooch shading
+uniform vec3 u_warmColor;
+// how much to take from object color in final cool color
+uniform float u_alpha;
+// how much to take from object color in final warm color
+uniform float u_beta;
+
+///////////////////////////////////////////////////////////
+
+void main(void)
+{
+ // normlize vectors for lighting
+ vec3 normalVector = normalize(o_normal);
+ vec3 lightVector = normalize(o_lightVector);
+ // intensity of diffuse lighting [-1, 1]
+ float diffuseLighting = dot(lightVector, normalVector);
+ // map intensity of lighting from range [-1; 1] to [0, 1]
+ float interpolationValue = (1.0 + diffuseLighting)/2;
+
+ //////////////////////////////////////////////////////////////////
+
+ // cool color mixed with color of the object
+ vec3 coolColorMod = u_coolColor + vec3(u_materialDiffuse) * u_alpha;
+ // warm color mixed with color of the object
+ vec3 warmColorMod = u_warmColor + vec3(u_materialDiffuse) * u_beta;
+ // interpolation of cool and warm colors according
+ // to lighting intensity. The lower the light intensity,
+ // the larger part of the cool color is used
+ vec3 colorOut = mix(coolColorMod, warmColorMod, interpolationValue);
+
+ //////////////////////////////////////////////////////////////////
+
+ // save color
+ gl_FragColor.rgb = colorOut;
+ gl_FragColor.a = 1;
+}
+"""
+
+GOOCH_FRAGMENT_SHADER_130 = """
+#version 130
+
+// data from vertex shader
+in vec3 o_normal;
+in vec3 o_lightVector;
+
+// diffuse color of the object
+uniform vec4 u_materialDiffuse;
+// cool color of gooch shading
+uniform vec3 u_coolColor;
+// warm color of gooch shading
+uniform vec3 u_warmColor;
+// how much to take from object color in final cool color
+uniform float u_alpha;
+// how much to take from object color in final warm color
+uniform float u_beta;
+
+// output to framebuffer
+out vec4 resultingColor;
+
+///////////////////////////////////////////////////////////
+
+void main(void)
+{
+ // normlize vectors for lighting
+ vec3 normalVector = normalize(o_normal);
+ vec3 lightVector = normalize(o_lightVector);
+ // intensity of diffuse lighting [-1, 1]
+ float diffuseLighting = dot(lightVector, normalVector);
+ // map intensity of lighting from range [-1; 1] to [0, 1]
+ float interpolationValue = (1.0 + diffuseLighting)/2;
+
+ //////////////////////////////////////////////////////////////////
+
+ // cool color mixed with color of the object
+ vec3 coolColorMod = u_coolColor + vec3(u_materialDiffuse) * u_alpha;
+ // warm color mixed with color of the object
+ vec3 warmColorMod = u_warmColor + vec3(u_materialDiffuse) * u_beta;
+ // interpolation of cool and warm colors according
+ // to lighting intensity. The lower the light intensity,
+ // the larger part of the cool color is used
+ vec3 colorOut = mix(coolColorMod, warmColorMod, interpolationValue);
+
+ //////////////////////////////////////////////////////////////////
+
+ // save color
+ resultingColor.rgb = colorOut;
+ resultingColor.a = 1;
+}
+"""
+
+SILHOUETTE_VERTEX_SHADER_120 = """
+#version 120
+
+attribute vec3 a_vertex; // xyz - position
+attribute vec3 a_normal; // xyz - normal
+
+uniform mat4 u_modelMatrix;
+uniform mat4 u_viewProjectionMatrix;
+uniform mat4 u_modelViewMatrix;
+uniform vec4 u_materialDiffuse;
+uniform float u_bordersize; // width of the border
+
+varying vec4 v_color;
+
+void main(void){
+ v_color = u_materialDiffuse;
+ float distToCamera = -(u_modelViewMatrix * vec4(a_vertex, 1.0)).z;
+ vec4 tPos = vec4(a_vertex + a_normal * u_bordersize * distToCamera, 1.0);
+ gl_Position = u_viewProjectionMatrix * u_modelMatrix * tPos;
+}
+"""
+
+SILHOUETTE_VERTEX_SHADER_130 = """
+#version 130
+
+in vec3 a_vertex; // xyz - position
+in vec3 a_normal; // xyz - normal
+
+uniform mat4 u_modelMatrix;
+uniform mat4 u_viewProjectionMatrix;
+uniform mat4 u_modelViewMatrix;
+uniform vec4 u_materialDiffuse;
+uniform float u_bordersize; // width of the border
+
+out vec4 v_color;
+
+void main(void){
+ v_color = u_materialDiffuse;
+ float distToCamera = -(u_modelViewMatrix * vec4(a_vertex, 1.0)).z;
+ vec4 tPos = vec4(a_vertex + a_normal * u_bordersize * distToCamera, 1.0);
+ gl_Position = u_viewProjectionMatrix * u_modelMatrix * tPos;
+}
+"""
+DEFAULT_CLIP_PLANE_NEAR = 0.001
+DEFAULT_CLIP_PLANE_FAR = 1000.0
+
+
+def get_world_transform(scene, node):
+ if node == scene.rootnode:
+ return numpy.identity(4, dtype=numpy.float32)
+
+ parents = reversed(_get_parent_chain(scene, node, []))
+ parent_transform = reduce(numpy.dot, [p.transformation for p in parents])
+ return numpy.dot(parent_transform, node.transformation)
+
+
+def _get_parent_chain(scene, node, parents):
+ parent = node.parent
+
+ parents.append(parent)
+
+ if parent == scene.rootnode:
+ return parents
+
+ return _get_parent_chain(scene, parent, parents)
+
+
+class DefaultCamera:
+ def __init__(self, w, h, fov):
+ self.name = "default camera"
+ self.type = CAMERA
+ self.clipplanenear = DEFAULT_CLIP_PLANE_NEAR
+ self.clipplanefar = DEFAULT_CLIP_PLANE_FAR
+ self.aspect = w / h
+ self.horizontalfov = fov * math.pi / 180
+ self.transformation = numpy.array([[0.68, -0.32, 0.65, 7.48],
+ [0.73, 0.31, -0.61, -6.51],
+ [-0.01, 0.89, 0.44, 5.34],
+ [0., 0., 0., 1.]], dtype=numpy.float32)
+
+ self.transformation = numpy.dot(self.transformation, ROTATION_180_X)
+
+ def __str__(self):
+ return self.name
+
+
+class PyAssimp3DViewer:
+ base_name = "PyASSIMP 3D viewer"
+
+ def __init__(self, model, w=1024, h=768):
+
+ self.w = w
+ self.h = h
+
+ pygame.init()
+ pygame.display.set_caption(self.base_name)
+ pygame.display.set_mode((w, h), pygame.OPENGL | pygame.DOUBLEBUF)
+
+ glClearColor(0.18, 0.18, 0.18, 1.0)
+
+ shader_compilation_succeeded = False
+ try:
+ self.set_shaders_v130()
+ self.prepare_shaders()
+ except RuntimeError, message:
+ sys.stderr.write("%s\n" % message)
+ sys.stdout.write("Could not compile shaders in version 1.30, trying version 1.20\n")
+
+ if not shader_compilation_succeeded:
+ self.set_shaders_v120()
+ self.prepare_shaders()
+
+ self.scene = None
+ self.meshes = {} # stores the OpenGL vertex/faces/normals buffers pointers
+
+ self.node2colorid = {} # stores a color ID for each node. Useful for mouse picking and visibility checking
+ self.colorid2node = {} # reverse dict of node2colorid
+
+ self.currently_selected = None
+ self.moving = False
+ self.moving_situation = None
+
+ self.default_camera = DefaultCamera(self.w, self.h, fov=70)
+ self.cameras = [self.default_camera]
+
+ self.current_cam_index = 0
+ self.current_cam = self.default_camera
+ self.set_camera_projection()
+
+ self.load_model(model)
+
+ # user interactions
+ self.focal_point = [0, 0, 0]
+ self.is_rotating = False
+ self.is_panning = False
+ self.is_zooming = False
+
+ def set_shaders_v120(self):
+ self.BASIC_VERTEX_SHADER = BASIC_VERTEX_SHADER_120
+ self.FLAT_VERTEX_SHADER = FLAT_VERTEX_SHADER_120
+ self.SILHOUETTE_VERTEX_SHADER = SILHOUETTE_VERTEX_SHADER_120
+ self.GOOCH_VERTEX_SHADER = GOOCH_VERTEX_SHADER_120
+
+ self.BASIC_FRAGMENT_SHADER = BASIC_FRAGMENT_SHADER_120
+ self.GOOCH_FRAGMENT_SHADER = GOOCH_FRAGMENT_SHADER_120
+
+ def set_shaders_v130(self):
+ self.BASIC_VERTEX_SHADER = BASIC_VERTEX_SHADER_130
+ self.FLAT_VERTEX_SHADER = FLAT_VERTEX_SHADER_130
+ self.SILHOUETTE_VERTEX_SHADER = SILHOUETTE_VERTEX_SHADER_130
+ self.GOOCH_VERTEX_SHADER = GOOCH_VERTEX_SHADER_130
+
+ self.BASIC_FRAGMENT_SHADER = BASIC_FRAGMENT_SHADER_130
+ self.GOOCH_FRAGMENT_SHADER = GOOCH_FRAGMENT_SHADER_130
+
+ def prepare_shaders(self):
+
+ ### Base shader
+ vertex = shaders.compileShader(self.BASIC_VERTEX_SHADER, GL_VERTEX_SHADER)
+ fragment = shaders.compileShader(self.BASIC_FRAGMENT_SHADER, GL_FRAGMENT_SHADER)
+
+ self.shader = shaders.compileProgram(vertex, fragment)
+
+ self.set_shader_accessors(('u_modelMatrix',
+ 'u_viewProjectionMatrix',
+ 'u_normalMatrix',
+ 'u_lightPos',
+ 'u_materialDiffuse'),
+ ('a_vertex',
+ 'a_normal'), self.shader)
+
+ ### Flat shader
+ flatvertex = shaders.compileShader(self.FLAT_VERTEX_SHADER, GL_VERTEX_SHADER)
+ self.flatshader = shaders.compileProgram(flatvertex, fragment)
+
+ self.set_shader_accessors(('u_modelMatrix',
+ 'u_viewProjectionMatrix',
+ 'u_materialDiffuse',),
+ ('a_vertex',), self.flatshader)
+
+ ### Silhouette shader
+ silh_vertex = shaders.compileShader(self.SILHOUETTE_VERTEX_SHADER, GL_VERTEX_SHADER)
+ self.silhouette_shader = shaders.compileProgram(silh_vertex, fragment)
+
+ self.set_shader_accessors(('u_modelMatrix',
+ 'u_viewProjectionMatrix',
+ 'u_modelViewMatrix',
+ 'u_materialDiffuse',
+ 'u_bordersize' # width of the silhouette
+ ),
+ ('a_vertex',
+ 'a_normal'), self.silhouette_shader)
+
+ ### Gooch shader
+ gooch_vertex = shaders.compileShader(self.GOOCH_VERTEX_SHADER, GL_VERTEX_SHADER)
+ gooch_fragment = shaders.compileShader(self.GOOCH_FRAGMENT_SHADER, GL_FRAGMENT_SHADER)
+ self.gooch_shader = shaders.compileProgram(gooch_vertex, gooch_fragment)
+
+ self.set_shader_accessors(('u_modelMatrix',
+ 'u_viewProjectionMatrix',
+ 'u_normalMatrix',
+ 'u_lightPos',
+ 'u_materialDiffuse',
+ 'u_coolColor',
+ 'u_warmColor',
+ 'u_alpha',
+ 'u_beta'
+ ),
+ ('a_vertex',
+ 'a_normal'), self.gooch_shader)
+
+ @staticmethod
+ def set_shader_accessors(uniforms, attributes, shader):
+ # add accessors to the shaders uniforms and attributes
+ for uniform in uniforms:
+ location = glGetUniformLocation(shader, uniform)
+ if location in (None, -1):
+ raise RuntimeError('No uniform: %s (maybe it is not used '
+ 'anymore and has been optimized out by'
+ ' the shader compiler)' % uniform)
+ setattr(shader, uniform, location)
+
+ for attribute in attributes:
+ location = glGetAttribLocation(shader, attribute)
+ if location in (None, -1):
+ raise RuntimeError('No attribute: %s' % attribute)
+ setattr(shader, attribute, location)
+
+ @staticmethod
+ def prepare_gl_buffers(mesh):
+
+ mesh.gl = {}
+
+ # Fill the buffer for vertex and normals positions
+ v = numpy.array(mesh.vertices, 'f')
+ n = numpy.array(mesh.normals, 'f')
+
+ mesh.gl["vbo"] = vbo.VBO(numpy.hstack((v, n)))
+
+ # Fill the buffer for vertex positions
+ mesh.gl["faces"] = glGenBuffers(1)
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.gl["faces"])
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER,
+ numpy.array(mesh.faces, dtype=numpy.int32),
+ GL_STATIC_DRAW)
+
+ mesh.gl["nbfaces"] = len(mesh.faces)
+
+ # Unbind buffers
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
+
+ @staticmethod
+ def get_rgb_from_colorid(colorid):
+ r = (colorid >> 0) & 0xff
+ g = (colorid >> 8) & 0xff
+ b = (colorid >> 16) & 0xff
+
+ return r, g, b
+
+ def get_color_id(self):
+ id = random.randint(0, 256 * 256 * 256)
+ if id not in self.colorid2node:
+ return id
+ else:
+ return self.get_color_id()
+
+ def glize(self, scene, node):
+
+ logger.info("Loading node <%s>" % node)
+ node.selected = True if self.currently_selected and self.currently_selected == node else False
+
+ node.transformation = node.transformation.astype(numpy.float32)
+
+ if node.meshes:
+ node.type = MESH
+ colorid = self.get_color_id()
+ self.colorid2node[colorid] = node
+ self.node2colorid[node.name] = colorid
+
+ elif node.name in [c.name for c in scene.cameras]:
+
+ # retrieve the ASSIMP camera object
+ [cam] = [c for c in scene.cameras if c.name == node.name]
+ node.type = CAMERA
+ logger.info("Added camera <%s>" % node.name)
+ logger.info("Camera position: %.3f, %.3f, %.3f" % tuple(node.transformation[:, 3][:3].tolist()))
+ self.cameras.append(node)
+ node.clipplanenear = cam.clipplanenear
+ node.clipplanefar = cam.clipplanefar
+
+ if numpy.allclose(cam.lookat, [0, 0, -1]) and numpy.allclose(cam.up, [0, 1, 0]): # Cameras in .blend files
+
+ # Rotate by 180deg around X to have Z pointing forward
+ node.transformation = numpy.dot(node.transformation, ROTATION_180_X)
+ else:
+ raise RuntimeError(
+ "I do not know how to normalize this camera orientation: lookat=%s, up=%s" % (cam.lookat, cam.up))
+
+ if cam.aspect == 0.0:
+ logger.warning("Camera aspect not set. Setting to default 4:3")
+ node.aspect = 1.333
+ else:
+ node.aspect = cam.aspect
+
+ node.horizontalfov = cam.horizontalfov
+
+ else:
+ node.type = ENTITY
+
+ for child in node.children:
+ self.glize(scene, child)
+
+ def load_model(self, path, postprocess=aiProcessPreset_TargetRealtime_MaxQuality):
+ logger.info("Loading model:" + path + "...")
+
+ if postprocess:
+ self.scene = pyassimp.load(path, processing=postprocess)
+ else:
+ self.scene = pyassimp.load(path)
+ logger.info("Done.")
+
+ scene = self.scene
+ # log some statistics
+ logger.info(" meshes: %d" % len(scene.meshes))
+ logger.info(" total faces: %d" % sum([len(mesh.faces) for mesh in scene.meshes]))
+ logger.info(" materials: %d" % len(scene.materials))
+ self.bb_min, self.bb_max = get_bounding_box(self.scene)
+ logger.info(" bounding box:" + str(self.bb_min) + " - " + str(self.bb_max))
+
+ self.scene_center = [(a + b) / 2. for a, b in zip(self.bb_min, self.bb_max)]
+
+ for index, mesh in enumerate(scene.meshes):
+ self.prepare_gl_buffers(mesh)
+
+ self.glize(scene, scene.rootnode)
+
+ # Finally release the model
+ pyassimp.release(scene)
+ logger.info("Ready for 3D rendering!")
+
+ def cycle_cameras(self):
+
+ self.current_cam_index = (self.current_cam_index + 1) % len(self.cameras)
+ self.current_cam = self.cameras[self.current_cam_index]
+ self.set_camera_projection(self.current_cam)
+ logger.info("Switched to camera <%s>" % self.current_cam)
+
+ def set_overlay_projection(self):
+ glViewport(0, 0, self.w, self.h)
+ glMatrixMode(GL_PROJECTION)
+ glLoadIdentity()
+ glOrtho(0.0, self.w - 1.0, 0.0, self.h - 1.0, -1.0, 1.0)
+ glMatrixMode(GL_MODELVIEW)
+ glLoadIdentity()
+
+ def set_camera_projection(self, camera=None):
+
+ if not camera:
+ camera = self.current_cam
+
+ znear = camera.clipplanenear or DEFAULT_CLIP_PLANE_NEAR
+ zfar = camera.clipplanefar or DEFAULT_CLIP_PLANE_FAR
+ aspect = camera.aspect
+ fov = camera.horizontalfov
+
+ glMatrixMode(GL_PROJECTION)
+ glLoadIdentity()
+
+ # Compute gl frustrum
+ tangent = math.tan(fov / 2.)
+ h = znear * tangent
+ w = h * aspect
+
+ # params: left, right, bottom, top, near, far
+ glFrustum(-w, w, -h, h, znear, zfar)
+ # equivalent to:
+ # gluPerspective(fov * 180/math.pi, aspect, znear, zfar)
+
+ self.projection_matrix = glGetFloatv(GL_PROJECTION_MATRIX).transpose()
+
+ glMatrixMode(GL_MODELVIEW)
+ glLoadIdentity()
+
+ def render_colors(self):
+
+ glEnable(GL_DEPTH_TEST)
+ glDepthFunc(GL_LEQUAL)
+
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
+ glEnable(GL_CULL_FACE)
+
+ glUseProgram(self.flatshader)
+
+ glUniformMatrix4fv(self.flatshader.u_viewProjectionMatrix, 1, GL_TRUE,
+ numpy.dot(self.projection_matrix, self.view_matrix))
+
+ self.recursive_render(self.scene.rootnode, self.flatshader, mode=COLORS)
+
+ glUseProgram(0)
+
+ def get_hovered_node(self, mousex, mousey):
+ """
+ Attention: The performances of this method relies heavily on the size of the display!
+ """
+
+ # mouse out of the window?
+ if mousex < 0 or mousex >= self.w or mousey < 0 or mousey >= self.h:
+ return None
+
+ self.render_colors()
+ # Capture image from the OpenGL buffer
+ buf = (GLubyte * (3 * self.w * self.h))(0)
+ glReadPixels(0, 0, self.w, self.h, GL_RGB, GL_UNSIGNED_BYTE, buf)
+
+ # Reinterpret the RGB pixel buffer as a 1-D array of 24bits colors
+ a = numpy.ndarray(len(buf), numpy.dtype('>u1'), buf)
+ colors = numpy.zeros(len(buf) / 3, numpy.dtype('<u4'))
+ for i in range(3):
+ colors.view(dtype='>u1')[i::4] = a.view(dtype='>u1')[i::3]
+
+ colorid = colors[mousex + mousey * self.w]
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
+
+ if colorid in self.colorid2node:
+ return self.colorid2node[colorid]
+
+ def render(self, wireframe=False, twosided=False):
+
+ glEnable(GL_DEPTH_TEST)
+ glDepthFunc(GL_LEQUAL)
+
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE if wireframe else GL_FILL)
+ glDisable(GL_CULL_FACE) if twosided else glEnable(GL_CULL_FACE)
+
+ self.render_grid()
+
+ self.recursive_render(self.scene.rootnode, None, mode=HELPERS)
+
+ ### First, the silhouette
+
+ if False:
+ shader = self.silhouette_shader
+
+ # glDepthMask(GL_FALSE)
+ glCullFace(GL_FRONT) # cull front faces
+
+ glUseProgram(shader)
+ glUniform1f(shader.u_bordersize, 0.01)
+
+ glUniformMatrix4fv(shader.u_viewProjectionMatrix, 1, GL_TRUE,
+ numpy.dot(self.projection_matrix, self.view_matrix))
+
+ self.recursive_render(self.scene.rootnode, shader, mode=SILHOUETTE)
+
+ glUseProgram(0)
+
+ ### Then, inner shading
+ # glDepthMask(GL_TRUE)
+ glCullFace(GL_BACK)
+
+ use_gooch = False
+ if use_gooch:
+ shader = self.gooch_shader
+
+ glUseProgram(shader)
+ glUniform3f(shader.u_lightPos, -.5, -.5, .5)
+
+ ##### GOOCH specific
+ glUniform3f(shader.u_coolColor, 159.0 / 255, 148.0 / 255, 255.0 / 255)
+ glUniform3f(shader.u_warmColor, 255.0 / 255, 75.0 / 255, 75.0 / 255)
+ glUniform1f(shader.u_alpha, .25)
+ glUniform1f(shader.u_beta, .25)
+ #########
+ else:
+ shader = self.shader
+ glUseProgram(shader)
+ glUniform3f(shader.u_lightPos, -.5, -.5, .5)
+
+ glUniformMatrix4fv(shader.u_viewProjectionMatrix, 1, GL_TRUE,
+ numpy.dot(self.projection_matrix, self.view_matrix))
+
+ self.recursive_render(self.scene.rootnode, shader)
+
+ glUseProgram(0)
+
+ def render_axis(self,
+ transformation=numpy.identity(4, dtype=numpy.float32),
+ label=None,
+ size=0.2,
+ selected=False):
+ m = transformation.transpose() # OpenGL row major
+
+ glPushMatrix()
+ glMultMatrixf(m)
+
+ glLineWidth(3 if selected else 1)
+
+ size = 2 * size if selected else size
+
+ glBegin(GL_LINES)
+
+ # draw line for x axis
+ glColor3f(1.0, 0.0, 0.0)
+ glVertex3f(0.0, 0.0, 0.0)
+ glVertex3f(size, 0.0, 0.0)
+
+ # draw line for y axis
+ glColor3f(0.0, 1.0, 0.0)
+ glVertex3f(0.0, 0.0, 0.0)
+ glVertex3f(0.0, size, 0.0)
+
+ # draw line for Z axis
+ glColor3f(0.0, 0.0, 1.0)
+ glVertex3f(0.0, 0.0, 0.0)
+ glVertex3f(0.0, 0.0, size)
+
+ glEnd()
+
+ if label:
+ self.showtext(label)
+
+ glPopMatrix()
+
+ @staticmethod
+ def render_camera(camera, transformation):
+
+ m = transformation.transpose() # OpenGL row major
+
+ aspect = camera.aspect
+
+ u = 0.1 # unit size (in m)
+ l = 3 * u # length of the camera cone
+ f = 3 * u # aperture of the camera cone
+
+ glPushMatrix()
+ glMultMatrixf(m)
+
+ glLineWidth(2)
+ glBegin(GL_LINE_STRIP)
+
+ glColor3f(.2, .2, .2)
+
+ glVertex3f(u, u, -u)
+ glVertex3f(u, -u, -u)
+ glVertex3f(-u, -u, -u)
+ glVertex3f(-u, u, -u)
+ glVertex3f(u, u, -u)
+
+ glVertex3f(u, u, 0.0)
+ glVertex3f(u, -u, 0.0)
+ glVertex3f(-u, -u, 0.0)
+ glVertex3f(-u, u, 0.0)
+ glVertex3f(u, u, 0.0)
+
+ glVertex3f(f * aspect, f, l)
+ glVertex3f(f * aspect, -f, l)
+ glVertex3f(-f * aspect, -f, l)
+ glVertex3f(-f * aspect, f, l)
+ glVertex3f(f * aspect, f, l)
+
+ glEnd()
+
+ glBegin(GL_LINE_STRIP)
+ glVertex3f(u, -u, -u)
+ glVertex3f(u, -u, 0.0)
+ glVertex3f(f * aspect, -f, l)
+ glEnd()
+
+ glBegin(GL_LINE_STRIP)
+ glVertex3f(-u, -u, -u)
+ glVertex3f(-u, -u, 0.0)
+ glVertex3f(-f * aspect, -f, l)
+ glEnd()
+
+ glBegin(GL_LINE_STRIP)
+ glVertex3f(-u, u, -u)
+ glVertex3f(-u, u, 0.0)
+ glVertex3f(-f * aspect, f, l)
+ glEnd()
+
+ glPopMatrix()
+
+ @staticmethod
+ def render_grid():
+
+ glLineWidth(1)
+ glColor3f(0.5, 0.5, 0.5)
+ glBegin(GL_LINES)
+ for i in range(-10, 11):
+ glVertex3f(i, -10.0, 0.0)
+ glVertex3f(i, 10.0, 0.0)
+
+ for i in range(-10, 11):
+ glVertex3f(-10.0, i, 0.0)
+ glVertex3f(10.0, i, 0.0)
+ glEnd()
+
+ def recursive_render(self, node, shader, mode=BASE, with_normals=True):
+ """ Main recursive rendering method.
+ """
+
+ normals = with_normals
+
+ if mode == COLORS:
+ normals = False
+
+
+ if not hasattr(node, "selected"):
+ node.selected = False
+
+ m = get_world_transform(self.scene, node)
+
+ # HELPERS mode
+ ###
+ if mode == HELPERS:
+ # if node.type == ENTITY:
+ self.render_axis(m,
+ label=node.name if node != self.scene.rootnode else None,
+ selected=node.selected if hasattr(node, "selected") else False)
+
+ if node.type == CAMERA:
+ self.render_camera(node, m)
+
+ for child in node.children:
+ self.recursive_render(child, shader, mode)
+
+ return
+
+ # Mesh rendering modes
+ ###
+ if node.type == MESH:
+
+ for mesh in node.meshes:
+
+ stride = 24 # 6 * 4 bytes
+
+ if node.selected and mode == SILHOUETTE:
+ glUniform4f(shader.u_materialDiffuse, 1.0, 0.0, 0.0, 1.0)
+ glUniformMatrix4fv(shader.u_modelViewMatrix, 1, GL_TRUE,
+ numpy.dot(self.view_matrix, m))
+
+ else:
+ if mode == COLORS:
+ colorid = self.node2colorid[node.name]
+ r, g, b = self.get_rgb_from_colorid(colorid)
+ glUniform4f(shader.u_materialDiffuse, r / 255.0, g / 255.0, b / 255.0, 1.0)
+ elif mode == SILHOUETTE:
+ glUniform4f(shader.u_materialDiffuse, .0, .0, .0, 1.0)
+ else:
+ if node.selected:
+ diffuse = (1.0, 0.0, 0.0, 1.0) # selected nodes in red
+ else:
+ diffuse = mesh.material.properties["diffuse"]
+ if len(diffuse) == 3: # RGB instead of expected RGBA
+ diffuse.append(1.0)
+ glUniform4f(shader.u_materialDiffuse, *diffuse)
+ # if ambient:
+ # glUniform4f( shader.Material_ambient, *mat["ambient"] )
+
+ if mode == BASE: # not in COLORS or SILHOUETTE
+ normal_matrix = linalg.inv(numpy.dot(self.view_matrix, m)[0:3, 0:3]).transpose()
+ glUniformMatrix3fv(shader.u_normalMatrix, 1, GL_TRUE, normal_matrix)
+
+ glUniformMatrix4fv(shader.u_modelMatrix, 1, GL_TRUE, m)
+
+ vbo = mesh.gl["vbo"]
+ vbo.bind()
+
+ glEnableVertexAttribArray(shader.a_vertex)
+ if normals:
+ glEnableVertexAttribArray(shader.a_normal)
+
+ glVertexAttribPointer(
+ shader.a_vertex,
+ 3, GL_FLOAT, False, stride, vbo
+ )
+
+ if normals:
+ glVertexAttribPointer(
+ shader.a_normal,
+ 3, GL_FLOAT, False, stride, vbo + 12
+ )
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.gl["faces"])
+ glDrawElements(GL_TRIANGLES, mesh.gl["nbfaces"] * 3, GL_UNSIGNED_INT, None)
+
+ vbo.unbind()
+ glDisableVertexAttribArray(shader.a_vertex)
+
+ if normals:
+ glDisableVertexAttribArray(shader.a_normal)
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
+
+ for child in node.children:
+ self.recursive_render(child, shader, mode)
+
+
+ def switch_to_overlay(self):
+ glPushMatrix()
+ self.set_overlay_projection()
+
+ def switch_from_overlay(self):
+ self.set_camera_projection()
+ glPopMatrix()
+
+ def select_node(self, node):
+ self.currently_selected = node
+ self.update_node_select(self.scene.rootnode)
+
+ def update_node_select(self, node):
+ if node is self.currently_selected:
+ node.selected = True
+ else:
+ node.selected = False
+
+ for child in node.children:
+ self.update_node_select(child)
+
+ def loop(self):
+
+ pygame.display.flip()
+
+ if not self.process_events():
+ return False # ESC has been pressed
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
+
+ return True
+
+ def process_events(self):
+
+ LEFT_BUTTON = 1
+ MIDDLE_BUTTON = 2
+ RIGHT_BUTTON = 3
+ WHEEL_UP = 4
+ WHEEL_DOWN = 5
+
+ dx, dy = pygame.mouse.get_rel()
+ mousex, mousey = pygame.mouse.get_pos()
+
+ zooming_one_shot = False
+
+ ok = True
+
+ for evt in pygame.event.get():
+ if evt.type == pygame.MOUSEBUTTONDOWN and evt.button == LEFT_BUTTON:
+ hovered = self.get_hovered_node(mousex, self.h - mousey)
+ if hovered:
+ if self.currently_selected and self.currently_selected == hovered:
+ self.select_node(None)
+ else:
+ logger.info("Node %s selected" % hovered)
+ self.select_node(hovered)
+ else:
+ self.is_rotating = True
+ if evt.type == pygame.MOUSEBUTTONUP and evt.button == LEFT_BUTTON:
+ self.is_rotating = False
+
+ if evt.type == pygame.MOUSEBUTTONDOWN and evt.button == MIDDLE_BUTTON:
+ self.is_panning = True
+ if evt.type == pygame.MOUSEBUTTONUP and evt.button == MIDDLE_BUTTON:
+ self.is_panning = False
+
+ if evt.type == pygame.MOUSEBUTTONDOWN and evt.button == RIGHT_BUTTON:
+ self.is_zooming = True
+ if evt.type == pygame.MOUSEBUTTONUP and evt.button == RIGHT_BUTTON:
+ self.is_zooming = False
+
+ if evt.type == pygame.MOUSEBUTTONDOWN and evt.button in [WHEEL_UP, WHEEL_DOWN]:
+ zooming_one_shot = True
+ self.is_zooming = True
+ dy = -10 if evt.button == WHEEL_UP else 10
+
+ if evt.type == pygame.KEYDOWN:
+ ok = (ok and self.process_keystroke(evt.key, evt.mod))
+
+ self.controls_3d(dx, dy, zooming_one_shot)
+
+ return ok
+
+ def process_keystroke(self, key, mod):
+
+ # process arrow keys if an object is selected
+ if self.currently_selected:
+ up = 0
+ strafe = 0
+
+ if key == pygame.K_UP:
+ up = 1
+ if key == pygame.K_DOWN:
+ up = -1
+ if key == pygame.K_LEFT:
+ strafe = -1
+ if key == pygame.K_RIGHT:
+ strafe = 1
+
+ self.move_selected_node(up, strafe)
+
+ if key == pygame.K_f:
+ pygame.display.toggle_fullscreen()
+
+ if key == pygame.K_TAB:
+ self.cycle_cameras()
+
+ if key in [pygame.K_ESCAPE, pygame.K_q]:
+ return False
+
+ return True
+
+ def controls_3d(self, dx, dy, zooming_one_shot=False):
+
+ CAMERA_TRANSLATION_FACTOR = 0.01
+ CAMERA_ROTATION_FACTOR = 0.01
+
+ if not (self.is_rotating or self.is_panning or self.is_zooming):
+ return
+
+ current_pos = self.current_cam.transformation[:3, 3].copy()
+ distance = numpy.linalg.norm(self.focal_point - current_pos)
+
+ if self.is_rotating:
+ """ Orbiting the camera is implemented the following way:
+
+ - the rotation is split into a rotation around the *world* Z axis
+ (controlled by the horizontal mouse motion along X) and a
+ rotation around the *X* axis of the camera (pitch) *shifted to
+ the focal origin* (the world origin for now). This is controlled
+ by the vertical motion of the mouse (Y axis).
+
+ - as a result, the resulting transformation of the camera in the
+ world frame C' is:
+ C' = (T · Rx · T⁻¹ · (Rz · C)⁻¹)⁻¹
+
+ where:
+ - C is the original camera transformation in the world frame,
+ - Rz is the rotation along the Z axis (in the world frame)
+ - T is the translation camera -> world (ie, the inverse of the
+ translation part of C
+ - Rx is the rotation around X in the (translated) camera frame
+ """
+
+ rotation_camera_x = dy * CAMERA_ROTATION_FACTOR
+ rotation_world_z = dx * CAMERA_ROTATION_FACTOR
+ world_z_rotation = transformations.euler_matrix(0, 0, rotation_world_z)
+ cam_x_rotation = transformations.euler_matrix(rotation_camera_x, 0, 0)
+
+ after_world_z_rotation = numpy.dot(world_z_rotation, self.current_cam.transformation)
+
+ inverse_transformation = transformations.inverse_matrix(after_world_z_rotation)
+
+ translation = transformations.translation_matrix(
+ transformations.decompose_matrix(inverse_transformation)[3])
+ inverse_translation = transformations.inverse_matrix(translation)
+
+ new_inverse = numpy.dot(inverse_translation, inverse_transformation)
+ new_inverse = numpy.dot(cam_x_rotation, new_inverse)
+ new_inverse = numpy.dot(translation, new_inverse)
+
+ self.current_cam.transformation = transformations.inverse_matrix(new_inverse).astype(numpy.float32)
+
+ if self.is_panning:
+ tx = -dx * CAMERA_TRANSLATION_FACTOR * distance
+ ty = dy * CAMERA_TRANSLATION_FACTOR * distance
+ cam_transform = transformations.translation_matrix((tx, ty, 0)).astype(numpy.float32)
+ self.current_cam.transformation = numpy.dot(self.current_cam.transformation, cam_transform)
+
+ if self.is_zooming:
+ tz = dy * CAMERA_TRANSLATION_FACTOR * distance
+ cam_transform = transformations.translation_matrix((0, 0, tz)).astype(numpy.float32)
+ self.current_cam.transformation = numpy.dot(self.current_cam.transformation, cam_transform)
+
+ if zooming_one_shot:
+ self.is_zooming = False
+
+ self.update_view_camera()
+
+ def update_view_camera(self):
+
+ self.view_matrix = linalg.inv(self.current_cam.transformation)
+
+ # Rotate by 180deg around X to have Z pointing backward (OpenGL convention)
+ self.view_matrix = numpy.dot(ROTATION_180_X, self.view_matrix)
+
+ glMatrixMode(GL_MODELVIEW)
+ glLoadIdentity()
+ glMultMatrixf(self.view_matrix.transpose())
+
+ def move_selected_node(self, up, strafe):
+ self.currently_selected.transformation[0][3] += strafe
+ self.currently_selected.transformation[2][3] += up
+
+ @staticmethod
+ def showtext(text, x=0, y=0, z=0, size=20):
+
+ # TODO: alpha blending does not work...
+ # glEnable(GL_BLEND)
+ # glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
+
+ font = pygame.font.Font(None, size)
+ text_surface = font.render(text, True, (10, 10, 10, 255),
+ (255 * 0.18, 255 * 0.18, 255 * 0.18, 0))
+ text_data = pygame.image.tostring(text_surface, "RGBA", True)
+ glRasterPos3d(x, y, z)
+ glDrawPixels(text_surface.get_width(),
+ text_surface.get_height(),
+ GL_RGBA, GL_UNSIGNED_BYTE,
+ text_data)
+
+ # glDisable(GL_BLEND)
+
+
+def main(model, width, height):
+ app = PyAssimp3DViewer(model, w=width, h=height)
+
+ clock = pygame.time.Clock()
+
+ while app.loop():
+
+ app.update_view_camera()
+
+ ## Main rendering
+ app.render()
+
+ ## GUI text display
+ app.switch_to_overlay()
+ app.showtext("Active camera: %s" % str(app.current_cam), 10, app.h - 30)
+ if app.currently_selected:
+ app.showtext("Selected node: %s" % app.currently_selected, 10, app.h - 50)
+ pos = app.h - 70
+
+ app.showtext("(%sm, %sm, %sm)" % (app.currently_selected.transformation[0, 3],
+ app.currently_selected.transformation[1, 3],
+ app.currently_selected.transformation[2, 3]), 30, pos)
+
+ app.switch_from_overlay()
+
+ # Make sure we do not go over 30fps
+ clock.tick(30)
+
+ logger.info("Quitting! Bye bye!")
+
+
+#########################################################################
+#########################################################################
+
+if __name__ == '__main__':
+ if not len(sys.argv) > 1:
+ print("Usage: " + __file__ + " <model>")
+ sys.exit(2)
+
+ main(model=sys.argv[1], width=1024, height=768)
diff --git a/libs/assimp/port/PyAssimp/scripts/3d_viewer_py3.py b/libs/assimp/port/PyAssimp/scripts/3d_viewer_py3.py
new file mode 100755
index 0000000..fcee637
--- /dev/null
+++ b/libs/assimp/port/PyAssimp/scripts/3d_viewer_py3.py
@@ -0,0 +1,1316 @@
+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+
+""" This program loads a model with PyASSIMP, and display it.
+
+Based on:
+- pygame code from http://3dengine.org/Spectator_%28PyOpenGL%29
+- http://www.lighthouse3d.com/tutorials
+- http://www.songho.ca/opengl/gl_transform.html
+- http://code.activestate.com/recipes/325391/
+- ASSIMP's C++ SimpleOpenGL viewer
+
+Authors: Séverin Lemaignan, 2012-2016
+"""
+import sys
+import logging
+
+from functools import reduce
+
+logger = logging.getLogger("pyassimp")
+gllogger = logging.getLogger("OpenGL")
+gllogger.setLevel(logging.WARNING)
+logging.basicConfig(level=logging.INFO)
+
+import OpenGL
+
+OpenGL.ERROR_CHECKING = False
+OpenGL.ERROR_LOGGING = False
+# OpenGL.ERROR_ON_COPY = True
+# OpenGL.FULL_LOGGING = True
+from OpenGL.GL import *
+from OpenGL.arrays import vbo
+from OpenGL.GL import shaders
+
+import pygame
+import pygame.font
+import pygame.image
+
+import math, random
+from numpy import linalg
+
+import pyassimp
+from pyassimp.postprocess import *
+from pyassimp.helper import *
+import transformations
+
+ROTATION_180_X = numpy.array([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]], dtype=numpy.float32)
+
+# rendering mode
+BASE = "BASE"
+COLORS = "COLORS"
+SILHOUETTE = "SILHOUETTE"
+HELPERS = "HELPERS"
+
+# Entities type
+ENTITY = "entity"
+CAMERA = "camera"
+MESH = "mesh"
+
+FLAT_VERTEX_SHADER_120 = """
+#version 120
+
+uniform mat4 u_viewProjectionMatrix;
+uniform mat4 u_modelMatrix;
+
+uniform vec4 u_materialDiffuse;
+
+attribute vec3 a_vertex;
+
+varying vec4 v_color;
+
+void main(void)
+{
+ v_color = u_materialDiffuse;
+ gl_Position = u_viewProjectionMatrix * u_modelMatrix * vec4(a_vertex, 1.0);
+}
+"""
+
+FLAT_VERTEX_SHADER_130 = """
+#version 130
+
+uniform mat4 u_viewProjectionMatrix;
+uniform mat4 u_modelMatrix;
+
+uniform vec4 u_materialDiffuse;
+
+in vec3 a_vertex;
+
+out vec4 v_color;
+
+void main(void)
+{
+ v_color = u_materialDiffuse;
+ gl_Position = u_viewProjectionMatrix * u_modelMatrix * vec4(a_vertex, 1.0);
+}
+"""
+
+BASIC_VERTEX_SHADER_120 = """
+#version 120
+
+uniform mat4 u_viewProjectionMatrix;
+uniform mat4 u_modelMatrix;
+uniform mat3 u_normalMatrix;
+uniform vec3 u_lightPos;
+
+uniform vec4 u_materialDiffuse;
+
+attribute vec3 a_vertex;
+attribute vec3 a_normal;
+
+varying vec4 v_color;
+
+void main(void)
+{
+ // Now the normal is in world space, as we pass the light in world space.
+ vec3 normal = u_normalMatrix * a_normal;
+
+ float dist = distance(a_vertex, u_lightPos);
+
+ // go to https://www.desmos.com/calculator/nmnaud1hrw to play with the parameters
+ // att is not used for now
+ float att=1.0/(1.0+0.8*dist*dist);
+
+ vec3 surf2light = normalize(u_lightPos - a_vertex);
+ vec3 norm = normalize(normal);
+ float dcont=max(0.0,dot(norm,surf2light));
+
+ float ambient = 0.3;
+ float intensity = dcont + 0.3 + ambient;
+
+ v_color = u_materialDiffuse * intensity;
+
+ gl_Position = u_viewProjectionMatrix * u_modelMatrix * vec4(a_vertex, 1.0);
+}
+"""
+
+BASIC_VERTEX_SHADER_130 = """
+#version 130
+
+uniform mat4 u_viewProjectionMatrix;
+uniform mat4 u_modelMatrix;
+uniform mat3 u_normalMatrix;
+uniform vec3 u_lightPos;
+
+uniform vec4 u_materialDiffuse;
+
+in vec3 a_vertex;
+in vec3 a_normal;
+
+out vec4 v_color;
+
+void main(void)
+{
+ // Now the normal is in world space, as we pass the light in world space.
+ vec3 normal = u_normalMatrix * a_normal;
+
+ float dist = distance(a_vertex, u_lightPos);
+
+ // go to https://www.desmos.com/calculator/nmnaud1hrw to play with the parameters
+ // att is not used for now
+ float att=1.0/(1.0+0.8*dist*dist);
+
+ vec3 surf2light = normalize(u_lightPos - a_vertex);
+ vec3 norm = normalize(normal);
+ float dcont=max(0.0,dot(norm,surf2light));
+
+ float ambient = 0.3;
+ float intensity = dcont + 0.3 + ambient;
+
+ v_color = u_materialDiffuse * intensity;
+
+ gl_Position = u_viewProjectionMatrix * u_modelMatrix * vec4(a_vertex, 1.0);
+}
+"""
+
+BASIC_FRAGMENT_SHADER_120 = """
+#version 120
+
+varying vec4 v_color;
+
+void main() {
+ gl_FragColor = v_color;
+}
+"""
+
+BASIC_FRAGMENT_SHADER_130 = """
+#version 130
+
+in vec4 v_color;
+
+void main() {
+ gl_FragColor = v_color;
+}
+"""
+
+GOOCH_VERTEX_SHADER_120 = """
+#version 120
+
+// attributes
+attribute vec3 a_vertex; // xyz - position
+attribute vec3 a_normal; // xyz - normal
+
+// uniforms
+uniform mat4 u_modelMatrix;
+uniform mat4 u_viewProjectionMatrix;
+uniform mat3 u_normalMatrix;
+uniform vec3 u_lightPos;
+uniform vec3 u_camPos;
+
+// output data from vertex to fragment shader
+varying vec3 o_normal;
+varying vec3 o_lightVector;
+
+///////////////////////////////////////////////////////////////////
+
+void main(void)
+{
+ // transform position and normal to world space
+ vec4 positionWorld = u_modelMatrix * vec4(a_vertex, 1.0);
+ vec3 normalWorld = u_normalMatrix * a_normal;
+
+ // calculate and pass vectors required for lighting
+ o_lightVector = u_lightPos - positionWorld.xyz;
+ o_normal = normalWorld;
+
+ // project world space position to the screen and output it
+ gl_Position = u_viewProjectionMatrix * positionWorld;
+}
+"""
+
+GOOCH_VERTEX_SHADER_130 = """
+#version 130
+
+// attributes
+in vec3 a_vertex; // xyz - position
+in vec3 a_normal; // xyz - normal
+
+// uniforms
+uniform mat4 u_modelMatrix;
+uniform mat4 u_viewProjectionMatrix;
+uniform mat3 u_normalMatrix;
+uniform vec3 u_lightPos;
+uniform vec3 u_camPos;
+
+// output data from vertex to fragment shader
+out vec3 o_normal;
+out vec3 o_lightVector;
+
+///////////////////////////////////////////////////////////////////
+
+void main(void)
+{
+ // transform position and normal to world space
+ vec4 positionWorld = u_modelMatrix * vec4(a_vertex, 1.0);
+ vec3 normalWorld = u_normalMatrix * a_normal;
+
+ // calculate and pass vectors required for lighting
+ o_lightVector = u_lightPos - positionWorld.xyz;
+ o_normal = normalWorld;
+
+ // project world space position to the screen and output it
+ gl_Position = u_viewProjectionMatrix * positionWorld;
+}
+"""
+
+GOOCH_FRAGMENT_SHADER_120 = """
+#version 120
+
+// data from vertex shader
+varying vec3 o_normal;
+varying vec3 o_lightVector;
+
+// diffuse color of the object
+uniform vec4 u_materialDiffuse;
+// cool color of gooch shading
+uniform vec3 u_coolColor;
+// warm color of gooch shading
+uniform vec3 u_warmColor;
+// how much to take from object color in final cool color
+uniform float u_alpha;
+// how much to take from object color in final warm color
+uniform float u_beta;
+
+///////////////////////////////////////////////////////////
+
+void main(void)
+{
+ // normlize vectors for lighting
+ vec3 normalVector = normalize(o_normal);
+ vec3 lightVector = normalize(o_lightVector);
+ // intensity of diffuse lighting [-1, 1]
+ float diffuseLighting = dot(lightVector, normalVector);
+ // map intensity of lighting from range [-1; 1] to [0, 1]
+ float interpolationValue = (1.0 + diffuseLighting)/2;
+
+ //////////////////////////////////////////////////////////////////
+
+ // cool color mixed with color of the object
+ vec3 coolColorMod = u_coolColor + vec3(u_materialDiffuse) * u_alpha;
+ // warm color mixed with color of the object
+ vec3 warmColorMod = u_warmColor + vec3(u_materialDiffuse) * u_beta;
+ // interpolation of cool and warm colors according
+ // to lighting intensity. The lower the light intensity,
+ // the larger part of the cool color is used
+ vec3 colorOut = mix(coolColorMod, warmColorMod, interpolationValue);
+
+ //////////////////////////////////////////////////////////////////
+
+ // save color
+ gl_FragColor.rgb = colorOut;
+ gl_FragColor.a = 1;
+}
+"""
+
+GOOCH_FRAGMENT_SHADER_130 = """
+#version 130
+
+// data from vertex shader
+in vec3 o_normal;
+in vec3 o_lightVector;
+
+// diffuse color of the object
+uniform vec4 u_materialDiffuse;
+// cool color of gooch shading
+uniform vec3 u_coolColor;
+// warm color of gooch shading
+uniform vec3 u_warmColor;
+// how much to take from object color in final cool color
+uniform float u_alpha;
+// how much to take from object color in final warm color
+uniform float u_beta;
+
+// output to framebuffer
+out vec4 resultingColor;
+
+///////////////////////////////////////////////////////////
+
+void main(void)
+{
+ // normlize vectors for lighting
+ vec3 normalVector = normalize(o_normal);
+ vec3 lightVector = normalize(o_lightVector);
+ // intensity of diffuse lighting [-1, 1]
+ float diffuseLighting = dot(lightVector, normalVector);
+ // map intensity of lighting from range [-1; 1] to [0, 1]
+ float interpolationValue = (1.0 + diffuseLighting)/2;
+
+ //////////////////////////////////////////////////////////////////
+
+ // cool color mixed with color of the object
+ vec3 coolColorMod = u_coolColor + vec3(u_materialDiffuse) * u_alpha;
+ // warm color mixed with color of the object
+ vec3 warmColorMod = u_warmColor + vec3(u_materialDiffuse) * u_beta;
+ // interpolation of cool and warm colors according
+ // to lighting intensity. The lower the light intensity,
+ // the larger part of the cool color is used
+ vec3 colorOut = mix(coolColorMod, warmColorMod, interpolationValue);
+
+ //////////////////////////////////////////////////////////////////
+
+ // save color
+ resultingColor.rgb = colorOut;
+ resultingColor.a = 1;
+}
+"""
+
+SILHOUETTE_VERTEX_SHADER_120 = """
+#version 120
+
+attribute vec3 a_vertex; // xyz - position
+attribute vec3 a_normal; // xyz - normal
+
+uniform mat4 u_modelMatrix;
+uniform mat4 u_viewProjectionMatrix;
+uniform mat4 u_modelViewMatrix;
+uniform vec4 u_materialDiffuse;
+uniform float u_bordersize; // width of the border
+
+varying vec4 v_color;
+
+void main(void){
+ v_color = u_materialDiffuse;
+ float distToCamera = -(u_modelViewMatrix * vec4(a_vertex, 1.0)).z;
+ vec4 tPos = vec4(a_vertex + a_normal * u_bordersize * distToCamera, 1.0);
+ gl_Position = u_viewProjectionMatrix * u_modelMatrix * tPos;
+}
+"""
+
+SILHOUETTE_VERTEX_SHADER_130 = """
+#version 130
+
+in vec3 a_vertex; // xyz - position
+in vec3 a_normal; // xyz - normal
+
+uniform mat4 u_modelMatrix;
+uniform mat4 u_viewProjectionMatrix;
+uniform mat4 u_modelViewMatrix;
+uniform vec4 u_materialDiffuse;
+uniform float u_bordersize; // width of the border
+
+out vec4 v_color;
+
+void main(void){
+ v_color = u_materialDiffuse;
+ float distToCamera = -(u_modelViewMatrix * vec4(a_vertex, 1.0)).z;
+ vec4 tPos = vec4(a_vertex + a_normal * u_bordersize * distToCamera, 1.0);
+ gl_Position = u_viewProjectionMatrix * u_modelMatrix * tPos;
+}
+"""
+DEFAULT_CLIP_PLANE_NEAR = 0.001
+DEFAULT_CLIP_PLANE_FAR = 1000.0
+
+
+def get_world_transform(scene, node):
+ if node == scene.rootnode:
+ return numpy.identity(4, dtype=numpy.float32)
+
+ parents = reversed(_get_parent_chain(scene, node, []))
+ parent_transform = reduce(numpy.dot, [p.transformation for p in parents])
+ return numpy.dot(parent_transform, node.transformation)
+
+
+def _get_parent_chain(scene, node, parents):
+ parent = node.parent
+
+ parents.append(parent)
+
+ if parent == scene.rootnode:
+ return parents
+
+ return _get_parent_chain(scene, parent, parents)
+
+
+class DefaultCamera:
+ def __init__(self, w, h, fov):
+ self.name = "default camera"
+ self.type = CAMERA
+ self.clipplanenear = DEFAULT_CLIP_PLANE_NEAR
+ self.clipplanefar = DEFAULT_CLIP_PLANE_FAR
+ self.aspect = w / h
+ self.horizontalfov = fov * math.pi / 180
+ self.transformation = numpy.array([[0.68, -0.32, 0.65, 7.48],
+ [0.73, 0.31, -0.61, -6.51],
+ [-0.01, 0.89, 0.44, 5.34],
+ [0., 0., 0., 1.]], dtype=numpy.float32)
+
+ self.transformation = numpy.dot(self.transformation, ROTATION_180_X)
+
+ def __str__(self):
+ return self.name
+
+
+class PyAssimp3DViewer:
+ base_name = "PyASSIMP 3D viewer"
+
+ def __init__(self, model, w=1024, h=768):
+
+ self.w = w
+ self.h = h
+
+ pygame.init()
+ pygame.display.set_caption(self.base_name)
+ pygame.display.set_mode((w, h), pygame.OPENGL | pygame.DOUBLEBUF)
+
+ glClearColor(0.18, 0.18, 0.18, 1.0)
+
+ shader_compilation_succeeded = False
+ try:
+ self.set_shaders_v130()
+ self.prepare_shaders()
+ except RuntimeError as message:
+ sys.stderr.write("%s\n" % message)
+ sys.stdout.write("Could not compile shaders in version 1.30, trying version 1.20\n")
+
+ if not shader_compilation_succeeded:
+ self.set_shaders_v120()
+ self.prepare_shaders()
+
+ self.scene = None
+ self.meshes = {} # stores the OpenGL vertex/faces/normals buffers pointers
+
+ self.node2colorid = {} # stores a color ID for each node. Useful for mouse picking and visibility checking
+ self.colorid2node = {} # reverse dict of node2colorid
+
+ self.currently_selected = None
+ self.moving = False
+ self.moving_situation = None
+
+ self.default_camera = DefaultCamera(self.w, self.h, fov=70)
+ self.cameras = [self.default_camera]
+
+ self.current_cam_index = 0
+ self.current_cam = self.default_camera
+ self.set_camera_projection()
+
+ self.load_model(model)
+
+ # user interactions
+ self.focal_point = [0, 0, 0]
+ self.is_rotating = False
+ self.is_panning = False
+ self.is_zooming = False
+
+ def set_shaders_v120(self):
+ self.BASIC_VERTEX_SHADER = BASIC_VERTEX_SHADER_120
+ self.FLAT_VERTEX_SHADER = FLAT_VERTEX_SHADER_120
+ self.SILHOUETTE_VERTEX_SHADER = SILHOUETTE_VERTEX_SHADER_120
+ self.GOOCH_VERTEX_SHADER = GOOCH_VERTEX_SHADER_120
+
+ self.BASIC_FRAGMENT_SHADER = BASIC_FRAGMENT_SHADER_120
+ self.GOOCH_FRAGMENT_SHADER = GOOCH_FRAGMENT_SHADER_120
+
+ def set_shaders_v130(self):
+ self.BASIC_VERTEX_SHADER = BASIC_VERTEX_SHADER_130
+ self.FLAT_VERTEX_SHADER = FLAT_VERTEX_SHADER_130
+ self.SILHOUETTE_VERTEX_SHADER = SILHOUETTE_VERTEX_SHADER_130
+ self.GOOCH_VERTEX_SHADER = GOOCH_VERTEX_SHADER_130
+
+ self.BASIC_FRAGMENT_SHADER = BASIC_FRAGMENT_SHADER_130
+ self.GOOCH_FRAGMENT_SHADER = GOOCH_FRAGMENT_SHADER_130
+
+ def prepare_shaders(self):
+
+ ### Base shader
+ vertex = shaders.compileShader(self.BASIC_VERTEX_SHADER, GL_VERTEX_SHADER)
+ fragment = shaders.compileShader(self.BASIC_FRAGMENT_SHADER, GL_FRAGMENT_SHADER)
+
+ self.shader = shaders.compileProgram(vertex, fragment)
+
+ self.set_shader_accessors(('u_modelMatrix',
+ 'u_viewProjectionMatrix',
+ 'u_normalMatrix',
+ 'u_lightPos',
+ 'u_materialDiffuse'),
+ ('a_vertex',
+ 'a_normal'), self.shader)
+
+ ### Flat shader
+ flatvertex = shaders.compileShader(self.FLAT_VERTEX_SHADER, GL_VERTEX_SHADER)
+ self.flatshader = shaders.compileProgram(flatvertex, fragment)
+
+ self.set_shader_accessors(('u_modelMatrix',
+ 'u_viewProjectionMatrix',
+ 'u_materialDiffuse',),
+ ('a_vertex',), self.flatshader)
+
+ ### Silhouette shader
+ silh_vertex = shaders.compileShader(self.SILHOUETTE_VERTEX_SHADER, GL_VERTEX_SHADER)
+ self.silhouette_shader = shaders.compileProgram(silh_vertex, fragment)
+
+ self.set_shader_accessors(('u_modelMatrix',
+ 'u_viewProjectionMatrix',
+ 'u_modelViewMatrix',
+ 'u_materialDiffuse',
+ 'u_bordersize' # width of the silhouette
+ ),
+ ('a_vertex',
+ 'a_normal'), self.silhouette_shader)
+
+ ### Gooch shader
+ gooch_vertex = shaders.compileShader(self.GOOCH_VERTEX_SHADER, GL_VERTEX_SHADER)
+ gooch_fragment = shaders.compileShader(self.GOOCH_FRAGMENT_SHADER, GL_FRAGMENT_SHADER)
+ self.gooch_shader = shaders.compileProgram(gooch_vertex, gooch_fragment)
+
+ self.set_shader_accessors(('u_modelMatrix',
+ 'u_viewProjectionMatrix',
+ 'u_normalMatrix',
+ 'u_lightPos',
+ 'u_materialDiffuse',
+ 'u_coolColor',
+ 'u_warmColor',
+ 'u_alpha',
+ 'u_beta'
+ ),
+ ('a_vertex',
+ 'a_normal'), self.gooch_shader)
+
+ @staticmethod
+ def set_shader_accessors(uniforms, attributes, shader):
+ # add accessors to the shaders uniforms and attributes
+ for uniform in uniforms:
+ location = glGetUniformLocation(shader, uniform)
+ if location in (None, -1):
+ raise RuntimeError('No uniform: %s (maybe it is not used '
+ 'anymore and has been optimized out by'
+ ' the shader compiler)' % uniform)
+ setattr(shader, uniform, location)
+
+ for attribute in attributes:
+ location = glGetAttribLocation(shader, attribute)
+ if location in (None, -1):
+ raise RuntimeError('No attribute: %s' % attribute)
+ setattr(shader, attribute, location)
+
+ @staticmethod
+ def prepare_gl_buffers(mesh):
+
+ mesh.gl = {}
+
+ # Fill the buffer for vertex and normals positions
+ v = numpy.array(mesh.vertices, 'f')
+ n = numpy.array(mesh.normals, 'f')
+
+ mesh.gl["vbo"] = vbo.VBO(numpy.hstack((v, n)))
+
+ # Fill the buffer for vertex positions
+ mesh.gl["faces"] = glGenBuffers(1)
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.gl["faces"])
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER,
+ numpy.array(mesh.faces, dtype=numpy.int32),
+ GL_STATIC_DRAW)
+
+ mesh.gl["nbfaces"] = len(mesh.faces)
+
+ # Unbind buffers
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
+
+ @staticmethod
+ def get_rgb_from_colorid(colorid):
+ r = (colorid >> 0) & 0xff
+ g = (colorid >> 8) & 0xff
+ b = (colorid >> 16) & 0xff
+
+ return r, g, b
+
+ def get_color_id(self):
+ id = random.randint(0, 256 * 256 * 256)
+ if id not in self.colorid2node:
+ return id
+ else:
+ return self.get_color_id()
+
+ def glize(self, scene, node):
+
+ logger.info("Loading node <%s>" % node)
+ node.selected = True if self.currently_selected and self.currently_selected == node else False
+
+ node.transformation = node.transformation.astype(numpy.float32)
+
+ if node.meshes:
+ node.type = MESH
+ colorid = self.get_color_id()
+ self.colorid2node[colorid] = node
+ self.node2colorid[node.name] = colorid
+
+ elif node.name in [c.name for c in scene.cameras]:
+
+ # retrieve the ASSIMP camera object
+ [cam] = [c for c in scene.cameras if c.name == node.name]
+ node.type = CAMERA
+ logger.info("Added camera <%s>" % node.name)
+ logger.info("Camera position: %.3f, %.3f, %.3f" % tuple(node.transformation[:, 3][:3].tolist()))
+ self.cameras.append(node)
+ node.clipplanenear = cam.clipplanenear
+ node.clipplanefar = cam.clipplanefar
+
+ if numpy.allclose(cam.lookat, [0, 0, -1]) and numpy.allclose(cam.up, [0, 1, 0]): # Cameras in .blend files
+
+ # Rotate by 180deg around X to have Z pointing forward
+ node.transformation = numpy.dot(node.transformation, ROTATION_180_X)
+ else:
+ raise RuntimeError(
+ "I do not know how to normalize this camera orientation: lookat=%s, up=%s" % (cam.lookat, cam.up))
+
+ if cam.aspect == 0.0:
+ logger.warning("Camera aspect not set. Setting to default 4:3")
+ node.aspect = 1.333
+ else:
+ node.aspect = cam.aspect
+
+ node.horizontalfov = cam.horizontalfov
+
+ else:
+ node.type = ENTITY
+
+ for child in node.children:
+ self.glize(scene, child)
+
+ def load_model(self, path, postprocess=aiProcessPreset_TargetRealtime_MaxQuality):
+ logger.info("Loading model:" + path + "...")
+
+ if postprocess:
+ self.scene = pyassimp.load(path, processing=postprocess)
+ else:
+ self.scene = pyassimp.load(path)
+ logger.info("Done.")
+
+ scene = self.scene
+ # log some statistics
+ logger.info(" meshes: %d" % len(scene.meshes))
+ logger.info(" total faces: %d" % sum([len(mesh.faces) for mesh in scene.meshes]))
+ logger.info(" materials: %d" % len(scene.materials))
+ self.bb_min, self.bb_max = get_bounding_box(self.scene)
+ logger.info(" bounding box:" + str(self.bb_min) + " - " + str(self.bb_max))
+
+ self.scene_center = [(a + b) / 2. for a, b in zip(self.bb_min, self.bb_max)]
+
+ for index, mesh in enumerate(scene.meshes):
+ self.prepare_gl_buffers(mesh)
+
+ self.glize(scene, scene.rootnode)
+
+ # Finally release the model
+ pyassimp.release(scene)
+ logger.info("Ready for 3D rendering!")
+
+ def cycle_cameras(self):
+
+ self.current_cam_index = (self.current_cam_index + 1) % len(self.cameras)
+ self.current_cam = self.cameras[self.current_cam_index]
+ self.set_camera_projection(self.current_cam)
+ logger.info("Switched to camera <%s>" % self.current_cam)
+
+ def set_overlay_projection(self):
+ glViewport(0, 0, self.w, self.h)
+ glMatrixMode(GL_PROJECTION)
+ glLoadIdentity()
+ glOrtho(0.0, self.w - 1.0, 0.0, self.h - 1.0, -1.0, 1.0)
+ glMatrixMode(GL_MODELVIEW)
+ glLoadIdentity()
+
+ def set_camera_projection(self, camera=None):
+
+ if not camera:
+ camera = self.current_cam
+
+ znear = camera.clipplanenear or DEFAULT_CLIP_PLANE_NEAR
+ zfar = camera.clipplanefar or DEFAULT_CLIP_PLANE_FAR
+ aspect = camera.aspect
+ fov = camera.horizontalfov
+
+ glMatrixMode(GL_PROJECTION)
+ glLoadIdentity()
+
+ # Compute gl frustrum
+ tangent = math.tan(fov / 2.)
+ h = znear * tangent
+ w = h * aspect
+
+ # params: left, right, bottom, top, near, far
+ glFrustum(-w, w, -h, h, znear, zfar)
+ # equivalent to:
+ # gluPerspective(fov * 180/math.pi, aspect, znear, zfar)
+
+ self.projection_matrix = glGetFloatv(GL_PROJECTION_MATRIX).transpose()
+
+ glMatrixMode(GL_MODELVIEW)
+ glLoadIdentity()
+
+ def render_colors(self):
+
+ glEnable(GL_DEPTH_TEST)
+ glDepthFunc(GL_LEQUAL)
+
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
+ glEnable(GL_CULL_FACE)
+
+ glUseProgram(self.flatshader)
+
+ glUniformMatrix4fv(self.flatshader.u_viewProjectionMatrix, 1, GL_TRUE,
+ numpy.dot(self.projection_matrix, self.view_matrix))
+
+ self.recursive_render(self.scene.rootnode, self.flatshader, mode=COLORS)
+
+ glUseProgram(0)
+
+ def get_hovered_node(self, mousex, mousey):
+ """
+ Attention: The performances of this method relies heavily on the size of the display!
+ """
+
+ # mouse out of the window?
+ if mousex < 0 or mousex >= self.w or mousey < 0 or mousey >= self.h:
+ return None
+
+ self.render_colors()
+ # Capture image from the OpenGL buffer
+ buf = (GLubyte * (3 * self.w * self.h))(0)
+ glReadPixels(0, 0, self.w, self.h, GL_RGB, GL_UNSIGNED_BYTE, buf)
+
+ # Reinterpret the RGB pixel buffer as a 1-D array of 24bits colors
+ a = numpy.ndarray(len(buf), numpy.dtype('>u1'), buf)
+ colors = numpy.zeros(len(buf) // 3, numpy.dtype('<u4'))
+ for i in range(3):
+ colors.view(dtype='>u1')[i::4] = a.view(dtype='>u1')[i::3]
+
+ colorid = colors[mousex + mousey * self.w]
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
+
+ if colorid in self.colorid2node:
+ return self.colorid2node[colorid]
+
+ def render(self, wireframe=False, twosided=False):
+
+ glEnable(GL_DEPTH_TEST)
+ glDepthFunc(GL_LEQUAL)
+
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE if wireframe else GL_FILL)
+ glDisable(GL_CULL_FACE) if twosided else glEnable(GL_CULL_FACE)
+
+ self.render_grid()
+
+ self.recursive_render(self.scene.rootnode, None, mode=HELPERS)
+
+ ### First, the silhouette
+
+ if False:
+ shader = self.silhouette_shader
+
+ # glDepthMask(GL_FALSE)
+ glCullFace(GL_FRONT) # cull front faces
+
+ glUseProgram(shader)
+ glUniform1f(shader.u_bordersize, 0.01)
+
+ glUniformMatrix4fv(shader.u_viewProjectionMatrix, 1, GL_TRUE,
+ numpy.dot(self.projection_matrix, self.view_matrix))
+
+ self.recursive_render(self.scene.rootnode, shader, mode=SILHOUETTE)
+
+ glUseProgram(0)
+
+ ### Then, inner shading
+ # glDepthMask(GL_TRUE)
+ glCullFace(GL_BACK)
+
+ use_gooch = False
+ if use_gooch:
+ shader = self.gooch_shader
+
+ glUseProgram(shader)
+ glUniform3f(shader.u_lightPos, -.5, -.5, .5)
+
+ ##### GOOCH specific
+ glUniform3f(shader.u_coolColor, 159.0 / 255, 148.0 / 255, 255.0 / 255)
+ glUniform3f(shader.u_warmColor, 255.0 / 255, 75.0 / 255, 75.0 / 255)
+ glUniform1f(shader.u_alpha, .25)
+ glUniform1f(shader.u_beta, .25)
+ #########
+ else:
+ shader = self.shader
+ glUseProgram(shader)
+ glUniform3f(shader.u_lightPos, -.5, -.5, .5)
+
+ glUniformMatrix4fv(shader.u_viewProjectionMatrix, 1, GL_TRUE,
+ numpy.dot(self.projection_matrix, self.view_matrix))
+
+ self.recursive_render(self.scene.rootnode, shader)
+
+ glUseProgram(0)
+
+ def render_axis(self,
+ transformation=numpy.identity(4, dtype=numpy.float32),
+ label=None,
+ size=0.2,
+ selected=False):
+ m = transformation.transpose() # OpenGL row major
+
+ glPushMatrix()
+ glMultMatrixf(m)
+
+ glLineWidth(3 if selected else 1)
+
+ size = 2 * size if selected else size
+
+ glBegin(GL_LINES)
+
+ # draw line for x axis
+ glColor3f(1.0, 0.0, 0.0)
+ glVertex3f(0.0, 0.0, 0.0)
+ glVertex3f(size, 0.0, 0.0)
+
+ # draw line for y axis
+ glColor3f(0.0, 1.0, 0.0)
+ glVertex3f(0.0, 0.0, 0.0)
+ glVertex3f(0.0, size, 0.0)
+
+ # draw line for Z axis
+ glColor3f(0.0, 0.0, 1.0)
+ glVertex3f(0.0, 0.0, 0.0)
+ glVertex3f(0.0, 0.0, size)
+
+ glEnd()
+
+ if label:
+ self.showtext(label)
+
+ glPopMatrix()
+
+ @staticmethod
+ def render_camera(camera, transformation):
+
+ m = transformation.transpose() # OpenGL row major
+
+ aspect = camera.aspect
+
+ u = 0.1 # unit size (in m)
+ l = 3 * u # length of the camera cone
+ f = 3 * u # aperture of the camera cone
+
+ glPushMatrix()
+ glMultMatrixf(m)
+
+ glLineWidth(2)
+ glBegin(GL_LINE_STRIP)
+
+ glColor3f(.2, .2, .2)
+
+ glVertex3f(u, u, -u)
+ glVertex3f(u, -u, -u)
+ glVertex3f(-u, -u, -u)
+ glVertex3f(-u, u, -u)
+ glVertex3f(u, u, -u)
+
+ glVertex3f(u, u, 0.0)
+ glVertex3f(u, -u, 0.0)
+ glVertex3f(-u, -u, 0.0)
+ glVertex3f(-u, u, 0.0)
+ glVertex3f(u, u, 0.0)
+
+ glVertex3f(f * aspect, f, l)
+ glVertex3f(f * aspect, -f, l)
+ glVertex3f(-f * aspect, -f, l)
+ glVertex3f(-f * aspect, f, l)
+ glVertex3f(f * aspect, f, l)
+
+ glEnd()
+
+ glBegin(GL_LINE_STRIP)
+ glVertex3f(u, -u, -u)
+ glVertex3f(u, -u, 0.0)
+ glVertex3f(f * aspect, -f, l)
+ glEnd()
+
+ glBegin(GL_LINE_STRIP)
+ glVertex3f(-u, -u, -u)
+ glVertex3f(-u, -u, 0.0)
+ glVertex3f(-f * aspect, -f, l)
+ glEnd()
+
+ glBegin(GL_LINE_STRIP)
+ glVertex3f(-u, u, -u)
+ glVertex3f(-u, u, 0.0)
+ glVertex3f(-f * aspect, f, l)
+ glEnd()
+
+ glPopMatrix()
+
+ @staticmethod
+ def render_grid():
+
+ glLineWidth(1)
+ glColor3f(0.5, 0.5, 0.5)
+ glBegin(GL_LINES)
+ for i in range(-10, 11):
+ glVertex3f(i, -10.0, 0.0)
+ glVertex3f(i, 10.0, 0.0)
+
+ for i in range(-10, 11):
+ glVertex3f(-10.0, i, 0.0)
+ glVertex3f(10.0, i, 0.0)
+ glEnd()
+
+ def recursive_render(self, node, shader, mode=BASE, with_normals=True):
+ """ Main recursive rendering method.
+ """
+
+ normals = with_normals
+
+ if mode == COLORS:
+ normals = False
+
+
+ if not hasattr(node, "selected"):
+ node.selected = False
+
+ m = get_world_transform(self.scene, node)
+
+ # HELPERS mode
+ ###
+ if mode == HELPERS:
+ # if node.type == ENTITY:
+ self.render_axis(m,
+ label=node.name if node != self.scene.rootnode else None,
+ selected=node.selected if hasattr(node, "selected") else False)
+
+ if node.type == CAMERA:
+ self.render_camera(node, m)
+
+ for child in node.children:
+ self.recursive_render(child, shader, mode)
+
+ return
+
+ # Mesh rendering modes
+ ###
+ if node.type == MESH:
+
+ for mesh in node.meshes:
+
+ stride = 24 # 6 * 4 bytes
+
+ if node.selected and mode == SILHOUETTE:
+ glUniform4f(shader.u_materialDiffuse, 1.0, 0.0, 0.0, 1.0)
+ glUniformMatrix4fv(shader.u_modelViewMatrix, 1, GL_TRUE,
+ numpy.dot(self.view_matrix, m))
+
+ else:
+ if mode == COLORS:
+ colorid = self.node2colorid[node.name]
+ r, g, b = self.get_rgb_from_colorid(colorid)
+ glUniform4f(shader.u_materialDiffuse, r / 255.0, g / 255.0, b / 255.0, 1.0)
+ elif mode == SILHOUETTE:
+ glUniform4f(shader.u_materialDiffuse, .0, .0, .0, 1.0)
+ else:
+ if node.selected:
+ diffuse = (1.0, 0.0, 0.0, 1.0) # selected nodes in red
+ else:
+ diffuse = mesh.material.properties["diffuse"]
+ if len(diffuse) == 3: # RGB instead of expected RGBA
+ diffuse.append(1.0)
+ glUniform4f(shader.u_materialDiffuse, *diffuse)
+ # if ambient:
+ # glUniform4f( shader.Material_ambient, *mat["ambient"] )
+
+ if mode == BASE: # not in COLORS or SILHOUETTE
+ normal_matrix = linalg.inv(numpy.dot(self.view_matrix, m)[0:3, 0:3]).transpose()
+ glUniformMatrix3fv(shader.u_normalMatrix, 1, GL_TRUE, normal_matrix)
+
+ glUniformMatrix4fv(shader.u_modelMatrix, 1, GL_TRUE, m)
+
+ vbo = mesh.gl["vbo"]
+ vbo.bind()
+
+ glEnableVertexAttribArray(shader.a_vertex)
+ if normals:
+ glEnableVertexAttribArray(shader.a_normal)
+
+ glVertexAttribPointer(
+ shader.a_vertex,
+ 3, GL_FLOAT, False, stride, vbo
+ )
+
+ if normals:
+ glVertexAttribPointer(
+ shader.a_normal,
+ 3, GL_FLOAT, False, stride, vbo + 12
+ )
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.gl["faces"])
+ glDrawElements(GL_TRIANGLES, mesh.gl["nbfaces"] * 3, GL_UNSIGNED_INT, None)
+
+ vbo.unbind()
+ glDisableVertexAttribArray(shader.a_vertex)
+
+ if normals:
+ glDisableVertexAttribArray(shader.a_normal)
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
+
+ for child in node.children:
+ self.recursive_render(child, shader, mode)
+
+
+ def switch_to_overlay(self):
+ glPushMatrix()
+ self.set_overlay_projection()
+
+ def switch_from_overlay(self):
+ self.set_camera_projection()
+ glPopMatrix()
+
+ def select_node(self, node):
+ self.currently_selected = node
+ self.update_node_select(self.scene.rootnode)
+
+ def update_node_select(self, node):
+ if node is self.currently_selected:
+ node.selected = True
+ else:
+ node.selected = False
+
+ for child in node.children:
+ self.update_node_select(child)
+
+ def loop(self):
+
+ pygame.display.flip()
+
+ if not self.process_events():
+ return False # ESC has been pressed
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
+
+ return True
+
+ def process_events(self):
+
+ LEFT_BUTTON = 1
+ MIDDLE_BUTTON = 2
+ RIGHT_BUTTON = 3
+ WHEEL_UP = 4
+ WHEEL_DOWN = 5
+
+ dx, dy = pygame.mouse.get_rel()
+ mousex, mousey = pygame.mouse.get_pos()
+
+ zooming_one_shot = False
+
+ ok = True
+
+ for evt in pygame.event.get():
+ if evt.type == pygame.MOUSEBUTTONDOWN and evt.button == LEFT_BUTTON:
+ hovered = self.get_hovered_node(mousex, self.h - mousey)
+ if hovered:
+ if self.currently_selected and self.currently_selected == hovered:
+ self.select_node(None)
+ else:
+ logger.info("Node %s selected" % hovered)
+ self.select_node(hovered)
+ else:
+ self.is_rotating = True
+ if evt.type == pygame.MOUSEBUTTONUP and evt.button == LEFT_BUTTON:
+ self.is_rotating = False
+
+ if evt.type == pygame.MOUSEBUTTONDOWN and evt.button == MIDDLE_BUTTON:
+ self.is_panning = True
+ if evt.type == pygame.MOUSEBUTTONUP and evt.button == MIDDLE_BUTTON:
+ self.is_panning = False
+
+ if evt.type == pygame.MOUSEBUTTONDOWN and evt.button == RIGHT_BUTTON:
+ self.is_zooming = True
+ if evt.type == pygame.MOUSEBUTTONUP and evt.button == RIGHT_BUTTON:
+ self.is_zooming = False
+
+ if evt.type == pygame.MOUSEBUTTONDOWN and evt.button in [WHEEL_UP, WHEEL_DOWN]:
+ zooming_one_shot = True
+ self.is_zooming = True
+ dy = -10 if evt.button == WHEEL_UP else 10
+
+ if evt.type == pygame.KEYDOWN:
+ ok = (ok and self.process_keystroke(evt.key, evt.mod))
+
+ self.controls_3d(dx, dy, zooming_one_shot)
+
+ return ok
+
+ def process_keystroke(self, key, mod):
+
+ # process arrow keys if an object is selected
+ if self.currently_selected:
+ up = 0
+ strafe = 0
+
+ if key == pygame.K_UP:
+ up = 1
+ if key == pygame.K_DOWN:
+ up = -1
+ if key == pygame.K_LEFT:
+ strafe = -1
+ if key == pygame.K_RIGHT:
+ strafe = 1
+
+ self.move_selected_node(up, strafe)
+
+ if key == pygame.K_f:
+ pygame.display.toggle_fullscreen()
+
+ if key == pygame.K_TAB:
+ self.cycle_cameras()
+
+ if key in [pygame.K_ESCAPE, pygame.K_q]:
+ return False
+
+ return True
+
+ def controls_3d(self, dx, dy, zooming_one_shot=False):
+ """ 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
+
+ if not (self.is_rotating or self.is_panning or self.is_zooming):
+ return
+
+ current_pos = self.current_cam.transformation[:3, 3].copy()
+ distance = numpy.linalg.norm(self.focal_point - current_pos)
+
+ if self.is_rotating:
+ rotation_camera_x = dy * CAMERA_ROTATION_FACTOR
+ rotation_world_z = dx * CAMERA_ROTATION_FACTOR
+ world_z_rotation = transformations.euler_matrix(0, 0, rotation_world_z)
+ cam_x_rotation = transformations.euler_matrix(rotation_camera_x, 0, 0)
+
+ after_world_z_rotation = numpy.dot(world_z_rotation, self.current_cam.transformation)
+
+ inverse_transformation = transformations.inverse_matrix(after_world_z_rotation)
+
+ translation = transformations.translation_matrix(
+ transformations.decompose_matrix(inverse_transformation)[3])
+ inverse_translation = transformations.inverse_matrix(translation)
+
+ new_inverse = numpy.dot(inverse_translation, inverse_transformation)
+ new_inverse = numpy.dot(cam_x_rotation, new_inverse)
+ new_inverse = numpy.dot(translation, new_inverse)
+
+ self.current_cam.transformation = transformations.inverse_matrix(new_inverse).astype(numpy.float32)
+
+ if self.is_panning:
+ tx = -dx * CAMERA_TRANSLATION_FACTOR * distance
+ ty = dy * CAMERA_TRANSLATION_FACTOR * distance
+ cam_transform = transformations.translation_matrix((tx, ty, 0)).astype(numpy.float32)
+ self.current_cam.transformation = numpy.dot(self.current_cam.transformation, cam_transform)
+
+ if self.is_zooming:
+ tz = dy * CAMERA_TRANSLATION_FACTOR * distance
+ cam_transform = transformations.translation_matrix((0, 0, tz)).astype(numpy.float32)
+ self.current_cam.transformation = numpy.dot(self.current_cam.transformation, cam_transform)
+
+ if zooming_one_shot:
+ self.is_zooming = False
+
+ self.update_view_camera()
+
+ def update_view_camera(self):
+
+ self.view_matrix = linalg.inv(self.current_cam.transformation)
+
+ # Rotate by 180deg around X to have Z pointing backward (OpenGL convention)
+ self.view_matrix = numpy.dot(ROTATION_180_X, self.view_matrix)
+
+ glMatrixMode(GL_MODELVIEW)
+ glLoadIdentity()
+ glMultMatrixf(self.view_matrix.transpose())
+
+ def move_selected_node(self, up, strafe):
+ self.currently_selected.transformation[0][3] += strafe
+ self.currently_selected.transformation[2][3] += up
+
+ @staticmethod
+ def showtext(text, x=0, y=0, z=0, size=20):
+
+ # TODO: alpha blending does not work...
+ # glEnable(GL_BLEND)
+ # glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
+
+ font = pygame.font.Font(None, size)
+ text_surface = font.render(text, True, (10, 10, 10, 255),
+ (255 * 0.18, 255 * 0.18, 255 * 0.18, 0))
+ text_data = pygame.image.tostring(text_surface, "RGBA", True)
+ glRasterPos3d(x, y, z)
+ glDrawPixels(text_surface.get_width(),
+ text_surface.get_height(),
+ GL_RGBA, GL_UNSIGNED_BYTE,
+ text_data)
+
+ # glDisable(GL_BLEND)
+
+
+def main(model, width, height):
+ app = PyAssimp3DViewer(model, w=width, h=height)
+
+ clock = pygame.time.Clock()
+
+ while app.loop():
+
+ app.update_view_camera()
+
+ ## Main rendering
+ app.render()
+
+ ## GUI text display
+ app.switch_to_overlay()
+ app.showtext("Active camera: %s" % str(app.current_cam), 10, app.h - 30)
+ if app.currently_selected:
+ app.showtext("Selected node: %s" % app.currently_selected, 10, app.h - 50)
+ pos = app.h - 70
+
+ app.showtext("(%sm, %sm, %sm)" % (app.currently_selected.transformation[0, 3],
+ app.currently_selected.transformation[1, 3],
+ app.currently_selected.transformation[2, 3]), 30, pos)
+
+ app.switch_from_overlay()
+
+ # Make sure we do not go over 30fps
+ clock.tick(30)
+
+ logger.info("Quitting! Bye bye!")
+
+
+#########################################################################
+#########################################################################
+
+if __name__ == '__main__':
+ if not len(sys.argv) > 1:
+ print("Usage: " + __file__ + " <model>")
+ sys.exit(2)
+
+ main(model=sys.argv[1], width=1024, height=768)
diff --git a/libs/assimp/port/PyAssimp/scripts/README.md b/libs/assimp/port/PyAssimp/scripts/README.md
new file mode 100644
index 0000000..42caa27
--- /dev/null
+++ b/libs/assimp/port/PyAssimp/scripts/README.md
@@ -0,0 +1,13 @@
+pyassimp examples
+=================
+
+- `sample.py`: shows how to load a model with pyassimp, and display some statistics.
+- `3d_viewer.py`: an OpenGL 3D viewer that requires shaders
+- `fixed_pipeline_3d_viewer`: an OpenGL 3D viewer using the old fixed-pipeline.
+ Only for illustration example. Base new projects on `3d_viewer.py`.
+
+
+Requirements for the 3D viewers:
+
+- `pyopengl` (on Ubuntu/Debian, `sudo apt-get install python-opengl`)
+- `pygame` (on Ubuntu/Debian, `sudo apt-get install python-pygame`)
diff --git a/libs/assimp/port/PyAssimp/scripts/fixed_pipeline_3d_viewer.py b/libs/assimp/port/PyAssimp/scripts/fixed_pipeline_3d_viewer.py
new file mode 100755
index 0000000..c2f6ceb
--- /dev/null
+++ b/libs/assimp/port/PyAssimp/scripts/fixed_pipeline_3d_viewer.py
@@ -0,0 +1,372 @@
+#!/usr/bin/env python
+#-*- coding: UTF-8 -*-
+
+""" This program demonstrates the use of pyassimp to load and
+render objects with OpenGL.
+
+'c' cycles between cameras (if any available)
+'q' to quit
+
+This example mixes 'old' OpenGL fixed-function pipeline with
+Vertex Buffer Objects.
+
+Materials are supported but textures are currently ignored.
+
+For a more advanced example (with shaders + keyboard/mouse
+controls), check scripts/sdl_viewer.py
+
+Author: Séverin Lemaignan, 2012
+
+This sample is based on several sources, including:
+ - http://www.lighthouse3d.com/tutorials
+ - http://www.songho.ca/opengl/gl_transform.html
+ - http://code.activestate.com/recipes/325391/
+ - ASSIMP's C++ SimpleOpenGL viewer
+"""
+
+import sys
+from OpenGL.GLUT import *
+from OpenGL.GLU import *
+from OpenGL.GL import *
+
+import logging
+logger = logging.getLogger("pyassimp_opengl")
+logging.basicConfig(level=logging.INFO)
+
+import math
+import numpy
+
+import pyassimp
+from pyassimp.postprocess import *
+from pyassimp.helper import *
+
+
+name = 'pyassimp OpenGL viewer'
+height = 600
+width = 900
+
+class GLRenderer():
+ def __init__(self):
+
+ self.scene = None
+
+ self.using_fixed_cam = False
+ self.current_cam_index = 0
+
+ # store the global scene rotation
+ self.angle = 0.
+
+ # for FPS calculation
+ self.prev_time = 0
+ self.prev_fps_time = 0
+ self.frames = 0
+
+ def prepare_gl_buffers(self, mesh):
+ """ Creates 3 buffer objets for each mesh,
+ to store the vertices, the normals, and the faces
+ indices.
+ """
+
+ mesh.gl = {}
+
+ # Fill the buffer for vertex positions
+ mesh.gl["vertices"] = glGenBuffers(1)
+ glBindBuffer(GL_ARRAY_BUFFER, mesh.gl["vertices"])
+ glBufferData(GL_ARRAY_BUFFER,
+ mesh.vertices,
+ GL_STATIC_DRAW)
+
+ # Fill the buffer for normals
+ mesh.gl["normals"] = glGenBuffers(1)
+ glBindBuffer(GL_ARRAY_BUFFER, mesh.gl["normals"])
+ glBufferData(GL_ARRAY_BUFFER,
+ mesh.normals,
+ GL_STATIC_DRAW)
+
+
+ # Fill the buffer for vertex positions
+ mesh.gl["triangles"] = glGenBuffers(1)
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.gl["triangles"])
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER,
+ mesh.faces,
+ GL_STATIC_DRAW)
+
+ # Unbind buffers
+ glBindBuffer(GL_ARRAY_BUFFER,0)
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0)
+
+ def load_model(self, path, postprocess = None):
+ logger.info("Loading model:" + path + "...")
+
+ if postprocess:
+ self.scene = pyassimp.load(path, processing=postprocess)
+ else:
+ self.scene = pyassimp.load(path)
+ logger.info("Done.")
+
+ scene = self.scene
+ #log some statistics
+ logger.info(" meshes: %d" % len(scene.meshes))
+ logger.info(" total faces: %d" % sum([len(mesh.faces) for mesh in scene.meshes]))
+ logger.info(" materials: %d" % len(scene.materials))
+ self.bb_min, self.bb_max = get_bounding_box(self.scene)
+ logger.info(" bounding box:" + str(self.bb_min) + " - " + str(self.bb_max))
+
+ self.scene_center = [(a + b) / 2. for a, b in zip(self.bb_min, self.bb_max)]
+
+ for index, mesh in enumerate(scene.meshes):
+ self.prepare_gl_buffers(mesh)
+
+ # Finally release the model
+ pyassimp.release(scene)
+
+ def cycle_cameras(self):
+ self.current_cam_index
+ if not self.scene.cameras:
+ return None
+ self.current_cam_index = (self.current_cam_index + 1) % len(self.scene.cameras)
+ cam = self.scene.cameras[self.current_cam_index]
+ logger.info("Switched to camera " + str(cam))
+ return cam
+
+ def set_default_camera(self):
+
+ if not self.using_fixed_cam:
+ glLoadIdentity()
+
+ gluLookAt(0.,0.,3.,
+ 0.,0.,-5.,
+ 0.,1.,0.)
+
+
+
+ def set_camera(self, camera):
+
+ if not camera:
+ return
+
+ self.using_fixed_cam = True
+
+ znear = camera.clipplanenear
+ zfar = camera.clipplanefar
+ aspect = camera.aspect
+ fov = camera.horizontalfov
+
+ glMatrixMode(GL_PROJECTION)
+ glLoadIdentity()
+
+ # Compute gl frustrum
+ tangent = math.tan(fov/2.)
+ h = znear * tangent
+ w = h * aspect
+
+ # params: left, right, bottom, top, near, far
+ glFrustum(-w, w, -h, h, znear, zfar)
+ # equivalent to:
+ #gluPerspective(fov * 180/math.pi, aspect, znear, zfar)
+
+ glMatrixMode(GL_MODELVIEW)
+ glLoadIdentity()
+
+ cam = transform(camera.position, camera.transformation)
+ at = transform(camera.lookat, camera.transformation)
+ gluLookAt(cam[0], cam[2], -cam[1],
+ at[0], at[2], -at[1],
+ 0, 1, 0)
+
+ def fit_scene(self, restore = False):
+ """ Compute a scale factor and a translation to fit and center
+ the whole geometry on the screen.
+ """
+
+ x_max = self.bb_max[0] - self.bb_min[0]
+ y_max = self.bb_max[1] - self.bb_min[1]
+ tmp = max(x_max, y_max)
+ z_max = self.bb_max[2] - self.bb_min[2]
+ tmp = max(z_max, tmp)
+
+ if not restore:
+ tmp = 1. / tmp
+
+ logger.info("Scaling the scene by %.03f" % tmp)
+ glScalef(tmp, tmp, tmp)
+
+ # center the model
+ direction = -1 if not restore else 1
+ glTranslatef( direction * self.scene_center[0],
+ direction * self.scene_center[1],
+ direction * self.scene_center[2] )
+
+ return x_max, y_max, z_max
+
+ def apply_material(self, mat):
+ """ Apply an OpenGL, using one OpenGL display list per material to cache
+ the operation.
+ """
+
+ if not hasattr(mat, "gl_mat"): # evaluate once the mat properties, and cache the values in a glDisplayList.
+ diffuse = numpy.array(mat.properties.get("diffuse", [0.8, 0.8, 0.8, 1.0]))
+ specular = numpy.array(mat.properties.get("specular", [0., 0., 0., 1.0]))
+ ambient = numpy.array(mat.properties.get("ambient", [0.2, 0.2, 0.2, 1.0]))
+ emissive = numpy.array(mat.properties.get("emissive", [0., 0., 0., 1.0]))
+ shininess = min(mat.properties.get("shininess", 1.0), 128)
+ wireframe = mat.properties.get("wireframe", 0)
+ twosided = mat.properties.get("twosided", 1)
+
+ setattr(mat, "gl_mat", glGenLists(1))
+ glNewList(mat.gl_mat, GL_COMPILE)
+
+ glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse)
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular)
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient)
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, emissive)
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess)
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE if wireframe else GL_FILL)
+ glDisable(GL_CULL_FACE) if twosided else glEnable(GL_CULL_FACE)
+
+ glEndList()
+
+ glCallList(mat.gl_mat)
+
+
+
+ def do_motion(self):
+
+ gl_time = glutGet(GLUT_ELAPSED_TIME)
+
+ self.angle = (gl_time - self.prev_time) * 0.1
+
+ self.prev_time = gl_time
+
+ # Compute FPS
+ self.frames += 1
+ if gl_time - self.prev_fps_time >= 1000:
+ current_fps = self.frames * 1000 / (gl_time - self.prev_fps_time)
+ logger.info('%.0f fps' % current_fps)
+ self.frames = 0
+ self.prev_fps_time = gl_time
+
+ glutPostRedisplay()
+
+ def recursive_render(self, node):
+ """ Main recursive rendering method.
+ """
+
+ # save model matrix and apply node transformation
+ glPushMatrix()
+ m = node.transformation.transpose() # OpenGL row major
+ glMultMatrixf(m)
+
+ for mesh in node.meshes:
+ self.apply_material(mesh.material)
+
+ glBindBuffer(GL_ARRAY_BUFFER, mesh.gl["vertices"])
+ glEnableClientState(GL_VERTEX_ARRAY)
+ glVertexPointer(3, GL_FLOAT, 0, None)
+
+ glBindBuffer(GL_ARRAY_BUFFER, mesh.gl["normals"])
+ glEnableClientState(GL_NORMAL_ARRAY)
+ glNormalPointer(GL_FLOAT, 0, None)
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.gl["triangles"])
+ glDrawElements(GL_TRIANGLES,len(mesh.faces) * 3, GL_UNSIGNED_INT, None)
+
+ glDisableClientState(GL_VERTEX_ARRAY)
+ glDisableClientState(GL_NORMAL_ARRAY)
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
+
+ for child in node.children:
+ self.recursive_render(child)
+
+ glPopMatrix()
+
+
+ def display(self):
+ """ GLUT callback to redraw OpenGL surface
+ """
+ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
+
+ glRotatef(self.angle,0.,1.,0.)
+ self.recursive_render(self.scene.rootnode)
+
+ glutSwapBuffers()
+ self.do_motion()
+ return
+
+ ####################################################################
+ ## GLUT keyboard and mouse callbacks ##
+ ####################################################################
+ def onkeypress(self, key, x, y):
+ if key == 'c':
+ self.fit_scene(restore = True)
+ self.set_camera(self.cycle_cameras())
+ if key == 'q':
+ sys.exit(0)
+
+ def render(self, filename=None, fullscreen = False, autofit = True, postprocess = None):
+ """
+
+ :param autofit: if true, scale the scene to fit the whole geometry
+ in the viewport.
+ """
+
+ # First initialize the openGL context
+ glutInit(sys.argv)
+ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)
+ if not fullscreen:
+ glutInitWindowSize(width, height)
+ glutCreateWindow(name)
+ else:
+ glutGameModeString("1024x768")
+ if glutGameModeGet(GLUT_GAME_MODE_POSSIBLE):
+ glutEnterGameMode()
+ else:
+ print("Fullscreen mode not available!")
+ sys.exit(1)
+
+ self.load_model(filename, postprocess = postprocess)
+
+
+ glClearColor(0.1,0.1,0.1,1.)
+ #glShadeModel(GL_SMOOTH)
+
+ glEnable(GL_LIGHTING)
+
+ glEnable(GL_CULL_FACE)
+ glEnable(GL_DEPTH_TEST)
+
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE)
+ glEnable(GL_NORMALIZE)
+ glEnable(GL_LIGHT0)
+
+ glutDisplayFunc(self.display)
+
+
+ glMatrixMode(GL_PROJECTION)
+ glLoadIdentity()
+ gluPerspective(35.0, width/float(height) , 0.10, 100.0)
+ glMatrixMode(GL_MODELVIEW)
+ self.set_default_camera()
+
+ if autofit:
+ # scale the whole asset to fit into our view frustum·
+ self.fit_scene()
+
+ glPushMatrix()
+
+ glutKeyboardFunc(self.onkeypress)
+ glutIgnoreKeyRepeat(1)
+
+ glutMainLoop()
+
+
+if __name__ == '__main__':
+ if not len(sys.argv) > 1:
+ print("Usage: " + __file__ + " <model>")
+ sys.exit(0)
+
+ glrender = GLRenderer()
+ glrender.render(sys.argv[1], fullscreen = False, postprocess = aiProcessPreset_TargetRealtime_MaxQuality)
+
diff --git a/libs/assimp/port/PyAssimp/scripts/quicktest.py b/libs/assimp/port/PyAssimp/scripts/quicktest.py
new file mode 100755
index 0000000..cbeccb4
--- /dev/null
+++ b/libs/assimp/port/PyAssimp/scripts/quicktest.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+#-*- coding: UTF-8 -*-
+
+"""
+This module uses the sample.py script to load all test models it finds.
+
+Note: this is not an exhaustive test suite, it does not check the
+data structures in detail. It just verifies whether basic
+loading and querying of 3d models using pyassimp works.
+"""
+
+import os
+import sys
+
+# Make the development (ie. GIT repo) version of PyAssimp available for import.
+sys.path.insert(0, '..')
+
+import sample
+from pyassimp import errors
+
+# Paths to model files.
+basepaths = [os.path.join('..', '..', '..', 'test', 'models'),
+ os.path.join('..', '..', '..', 'test', 'models-nonbsd')]
+
+# Valid extensions for 3D model files.
+extensions = ['.3ds', '.x', '.lwo', '.obj', '.md5mesh', '.dxf', '.ply', '.stl',
+ '.dae', '.md5anim', '.lws', '.irrmesh', '.nff', '.off', '.blend']
+
+
+def run_tests():
+ ok, err = 0, 0
+ for path in basepaths:
+ print("Looking for models in %s..." % path)
+ for root, dirs, files in os.walk(path):
+ for afile in files:
+ base, ext = os.path.splitext(afile)
+ if ext in extensions:
+ try:
+ sample.main(os.path.join(root, afile))
+ ok += 1
+ except errors.AssimpError as error:
+ # Assimp error is fine; this is a controlled case.
+ print(error)
+ err += 1
+ except Exception:
+ print("Error encountered while loading <%s>"
+ % os.path.join(root, afile))
+ print('** Loaded %s models, got controlled errors for %s files'
+ % (ok, err))
+
+
+if __name__ == '__main__':
+ run_tests()
diff --git a/libs/assimp/port/PyAssimp/scripts/sample.py b/libs/assimp/port/PyAssimp/scripts/sample.py
new file mode 100755
index 0000000..3cd4b3e
--- /dev/null
+++ b/libs/assimp/port/PyAssimp/scripts/sample.py
@@ -0,0 +1,89 @@
+#!/usr/bin/env python
+#-*- coding: UTF-8 -*-
+
+"""
+This module demonstrates the functionality of PyAssimp.
+"""
+
+import sys
+import logging
+logging.basicConfig(level=logging.INFO)
+
+import pyassimp
+import pyassimp.postprocess
+
+def recur_node(node,level = 0):
+ print(" " + "\t" * level + "- " + str(node))
+ for child in node.children:
+ recur_node(child, level + 1)
+
+
+def main(filename=None):
+
+ scene = pyassimp.load(filename, processing=pyassimp.postprocess.aiProcess_Triangulate)
+
+ #the model we load
+ print("MODEL:" + filename)
+ print
+
+ #write some statistics
+ print("SCENE:")
+ print(" meshes:" + str(len(scene.meshes)))
+ print(" materials:" + str(len(scene.materials)))
+ print(" textures:" + str(len(scene.textures)))
+ print
+
+ print("NODES:")
+ recur_node(scene.rootnode)
+
+ print
+ print("MESHES:")
+ for index, mesh in enumerate(scene.meshes):
+ print(" MESH" + str(index+1))
+ print(" material id:" + str(mesh.materialindex+1))
+ print(" vertices:" + str(len(mesh.vertices)))
+ print(" first 3 verts:\n" + str(mesh.vertices[:3]))
+ if mesh.normals.any():
+ print(" first 3 normals:\n" + str(mesh.normals[:3]))
+ else:
+ print(" no normals")
+ print(" colors:" + str(len(mesh.colors)))
+ tcs = mesh.texturecoords
+ if tcs.any():
+ for tc_index, tc in enumerate(tcs):
+ print(" texture-coords "+ str(tc_index) + ":" + str(len(tcs[tc_index])) + "first3:" + str(tcs[tc_index][:3]))
+
+ else:
+ print(" no texture coordinates")
+ print(" uv-component-count:" + str(len(mesh.numuvcomponents)))
+ print(" faces:" + str(len(mesh.faces)) + " -> first:\n" + str(mesh.faces[:3]))
+ print(" bones:" + str(len(mesh.bones)) + " -> first:" + str([str(b) for b in mesh.bones[:3]]))
+ print
+
+ print("MATERIALS:")
+ for index, material in enumerate(scene.materials):
+ print(" MATERIAL (id:" + str(index+1) + ")")
+ for key, value in material.properties.items():
+ print(" %s: %s" % (key, value))
+ print
+
+ print("TEXTURES:")
+ for index, texture in enumerate(scene.textures):
+ print(" TEXTURE" + str(index+1))
+ print(" width:" + str(texture.width))
+ print(" height:" + str(texture.height))
+ print(" hint:" + str(texture.achformathint))
+ print(" data (size):" + str(len(texture.data)))
+
+ # Finally release the model
+ pyassimp.release(scene)
+
+def usage():
+ print("Usage: sample.py <3d model>")
+
+if __name__ == "__main__":
+
+ if len(sys.argv) != 2:
+ usage()
+ else:
+ main(sys.argv[1])
diff --git a/libs/assimp/port/PyAssimp/scripts/transformations.py b/libs/assimp/port/PyAssimp/scripts/transformations.py
new file mode 100644
index 0000000..bf0cac9
--- /dev/null
+++ b/libs/assimp/port/PyAssimp/scripts/transformations.py
@@ -0,0 +1,1705 @@
+# -*- coding: utf-8 -*-
+# transformations.py
+
+# Copyright (c) 2006, Christoph Gohlke
+# Copyright (c) 2006-2009, The Regents of the University of California
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the copyright holders nor the names of any
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+"""Homogeneous Transformation Matrices and Quaternions.
+
+A library for calculating 4x4 matrices for translating, rotating, reflecting,
+scaling, shearing, projecting, orthogonalizing, and superimposing arrays of
+3D homogeneous coordinates as well as for converting between rotation matrices,
+Euler angles, and quaternions. Also includes an Arcball control object and
+functions to decompose transformation matrices.
+
+:Authors:
+ `Christoph Gohlke <http://www.lfd.uci.edu/~gohlke/>`__,
+ Laboratory for Fluorescence Dynamics, University of California, Irvine
+
+:Version: 20090418
+
+Requirements
+------------
+
+* `Python 2.6 <http://www.python.org>`__
+* `Numpy 1.3 <http://numpy.scipy.org>`__
+* `transformations.c 20090418 <http://www.lfd.uci.edu/~gohlke/>`__
+ (optional implementation of some functions in C)
+
+Notes
+-----
+
+Matrices (M) can be inverted using numpy.linalg.inv(M), concatenated using
+numpy.dot(M0, M1), or used to transform homogeneous coordinates (v) using
+numpy.dot(M, v) for shape (4, \*) "point of arrays", respectively
+numpy.dot(v, M.T) for shape (\*, 4) "array of points".
+
+Calculations are carried out with numpy.float64 precision.
+
+This Python implementation is not optimized for speed.
+
+Vector, point, quaternion, and matrix function arguments are expected to be
+"array like", i.e. tuple, list, or numpy arrays.
+
+Return types are numpy arrays unless specified otherwise.
+
+Angles are in radians unless specified otherwise.
+
+Quaternions ix+jy+kz+w are represented as [x, y, z, w].
+
+Use the transpose of transformation matrices for OpenGL glMultMatrixd().
+
+A triple of Euler angles can be applied/interpreted in 24 ways, which can
+be specified using a 4 character string or encoded 4-tuple:
+
+ *Axes 4-string*: e.g. 'sxyz' or 'ryxy'
+
+ - first character : rotations are applied to 's'tatic or 'r'otating frame
+ - remaining characters : successive rotation axis 'x', 'y', or 'z'
+
+ *Axes 4-tuple*: e.g. (0, 0, 0, 0) or (1, 1, 1, 1)
+
+ - inner axis: code of axis ('x':0, 'y':1, 'z':2) of rightmost matrix.
+ - parity : even (0) if inner axis 'x' is followed by 'y', 'y' is followed
+ by 'z', or 'z' is followed by 'x'. Otherwise odd (1).
+ - repetition : first and last axis are same (1) or different (0).
+ - frame : rotations are applied to static (0) or rotating (1) frame.
+
+References
+----------
+
+(1) Matrices and transformations. Ronald Goldman.
+ In "Graphics Gems I", pp 472-475. Morgan Kaufmann, 1990.
+(2) More matrices and transformations: shear and pseudo-perspective.
+ Ronald Goldman. In "Graphics Gems II", pp 320-323. Morgan Kaufmann, 1991.
+(3) Decomposing a matrix into simple transformations. Spencer Thomas.
+ In "Graphics Gems II", pp 320-323. Morgan Kaufmann, 1991.
+(4) Recovering the data from the transformation matrix. Ronald Goldman.
+ In "Graphics Gems II", pp 324-331. Morgan Kaufmann, 1991.
+(5) Euler angle conversion. Ken Shoemake.
+ In "Graphics Gems IV", pp 222-229. Morgan Kaufmann, 1994.
+(6) Arcball rotation control. Ken Shoemake.
+ In "Graphics Gems IV", pp 175-192. Morgan Kaufmann, 1994.
+(7) Representing attitude: Euler angles, unit quaternions, and rotation
+ vectors. James Diebel. 2006.
+(8) A discussion of the solution for the best rotation to relate two sets
+ of vectors. W Kabsch. Acta Cryst. 1978. A34, 827-828.
+(9) Closed-form solution of absolute orientation using unit quaternions.
+ BKP Horn. J Opt Soc Am A. 1987. 4(4), 629-642.
+(10) Quaternions. Ken Shoemake.
+ http://www.sfu.ca/~jwa3/cmpt461/files/quatut.pdf
+(11) From quaternion to matrix and back. JMP van Waveren. 2005.
+ http://www.intel.com/cd/ids/developer/asmo-na/eng/293748.htm
+(12) Uniform random rotations. Ken Shoemake.
+ In "Graphics Gems III", pp 124-132. Morgan Kaufmann, 1992.
+
+
+Examples
+--------
+
+>>> alpha, beta, gamma = 0.123, -1.234, 2.345
+>>> origin, xaxis, yaxis, zaxis = (0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1)
+>>> I = identity_matrix()
+>>> Rx = rotation_matrix(alpha, xaxis)
+>>> Ry = rotation_matrix(beta, yaxis)
+>>> Rz = rotation_matrix(gamma, zaxis)
+>>> R = concatenate_matrices(Rx, Ry, Rz)
+>>> euler = euler_from_matrix(R, 'rxyz')
+>>> numpy.allclose([alpha, beta, gamma], euler)
+True
+>>> Re = euler_matrix(alpha, beta, gamma, 'rxyz')
+>>> is_same_transform(R, Re)
+True
+>>> al, be, ga = euler_from_matrix(Re, 'rxyz')
+>>> is_same_transform(Re, euler_matrix(al, be, ga, 'rxyz'))
+True
+>>> qx = quaternion_about_axis(alpha, xaxis)
+>>> qy = quaternion_about_axis(beta, yaxis)
+>>> qz = quaternion_about_axis(gamma, zaxis)
+>>> q = quaternion_multiply(qx, qy)
+>>> q = quaternion_multiply(q, qz)
+>>> Rq = quaternion_matrix(q)
+>>> is_same_transform(R, Rq)
+True
+>>> S = scale_matrix(1.23, origin)
+>>> T = translation_matrix((1, 2, 3))
+>>> Z = shear_matrix(beta, xaxis, origin, zaxis)
+>>> R = random_rotation_matrix(numpy.random.rand(3))
+>>> M = concatenate_matrices(T, R, Z, S)
+>>> scale, shear, angles, trans, persp = decompose_matrix(M)
+>>> numpy.allclose(scale, 1.23)
+True
+>>> numpy.allclose(trans, (1, 2, 3))
+True
+>>> numpy.allclose(shear, (0, math.tan(beta), 0))
+True
+>>> is_same_transform(R, euler_matrix(axes='sxyz', *angles))
+True
+>>> M1 = compose_matrix(scale, shear, angles, trans, persp)
+>>> is_same_transform(M, M1)
+True
+
+"""
+
+from __future__ import division
+
+import warnings
+import math
+
+import numpy
+
+# Documentation in HTML format can be generated with Epydoc
+__docformat__ = "restructuredtext en"
+
+
+def identity_matrix():
+ """Return 4x4 identity/unit matrix.
+
+ >>> I = identity_matrix()
+ >>> numpy.allclose(I, numpy.dot(I, I))
+ True
+ >>> numpy.sum(I), numpy.trace(I)
+ (4.0, 4.0)
+ >>> numpy.allclose(I, numpy.identity(4, dtype=numpy.float64))
+ True
+
+ """
+ return numpy.identity(4, dtype=numpy.float64)
+
+
+def translation_matrix(direction):
+ """Return matrix to translate by direction vector.
+
+ >>> v = numpy.random.random(3) - 0.5
+ >>> numpy.allclose(v, translation_matrix(v)[:3, 3])
+ True
+
+ """
+ M = numpy.identity(4)
+ M[:3, 3] = direction[:3]
+ return M
+
+
+def translation_from_matrix(matrix):
+ """Return translation vector from translation matrix.
+
+ >>> v0 = numpy.random.random(3) - 0.5
+ >>> v1 = translation_from_matrix(translation_matrix(v0))
+ >>> numpy.allclose(v0, v1)
+ True
+
+ """
+ return numpy.array(matrix, copy=False)[:3, 3].copy()
+
+
+def reflection_matrix(point, normal):
+ """Return matrix to mirror at plane defined by point and normal vector.
+
+ >>> v0 = numpy.random.random(4) - 0.5
+ >>> v0[3] = 1.0
+ >>> v1 = numpy.random.random(3) - 0.5
+ >>> R = reflection_matrix(v0, v1)
+ >>> numpy.allclose(2., numpy.trace(R))
+ True
+ >>> numpy.allclose(v0, numpy.dot(R, v0))
+ True
+ >>> v2 = v0.copy()
+ >>> v2[:3] += v1
+ >>> v3 = v0.copy()
+ >>> v2[:3] -= v1
+ >>> numpy.allclose(v2, numpy.dot(R, v3))
+ True
+
+ """
+ normal = unit_vector(normal[:3])
+ M = numpy.identity(4)
+ M[:3, :3] -= 2.0 * numpy.outer(normal, normal)
+ M[:3, 3] = (2.0 * numpy.dot(point[:3], normal)) * normal
+ return M
+
+
+def reflection_from_matrix(matrix):
+ """Return mirror plane point and normal vector from reflection matrix.
+
+ >>> v0 = numpy.random.random(3) - 0.5
+ >>> v1 = numpy.random.random(3) - 0.5
+ >>> M0 = reflection_matrix(v0, v1)
+ >>> point, normal = reflection_from_matrix(M0)
+ >>> M1 = reflection_matrix(point, normal)
+ >>> is_same_transform(M0, M1)
+ True
+
+ """
+ M = numpy.array(matrix, dtype=numpy.float64, copy=False)
+ # normal: unit eigenvector corresponding to eigenvalue -1
+ l, V = numpy.linalg.eig(M[:3, :3])
+ i = numpy.where(abs(numpy.real(l) + 1.0) < 1e-8)[0]
+ if not len(i):
+ raise ValueError("no unit eigenvector corresponding to eigenvalue -1")
+ normal = numpy.real(V[:, i[0]]).squeeze()
+ # point: any unit eigenvector corresponding to eigenvalue 1
+ l, V = numpy.linalg.eig(M)
+ i = numpy.where(abs(numpy.real(l) - 1.0) < 1e-8)[0]
+ if not len(i):
+ raise ValueError("no unit eigenvector corresponding to eigenvalue 1")
+ point = numpy.real(V[:, i[-1]]).squeeze()
+ point /= point[3]
+ return point, normal
+
+
+def rotation_matrix(angle, direction, point=None):
+ """Return matrix to rotate about axis defined by point and direction.
+
+ >>> angle = (random.random() - 0.5) * (2*math.pi)
+ >>> direc = numpy.random.random(3) - 0.5
+ >>> point = numpy.random.random(3) - 0.5
+ >>> R0 = rotation_matrix(angle, direc, point)
+ >>> R1 = rotation_matrix(angle-2*math.pi, direc, point)
+ >>> is_same_transform(R0, R1)
+ True
+ >>> R0 = rotation_matrix(angle, direc, point)
+ >>> R1 = rotation_matrix(-angle, -direc, point)
+ >>> is_same_transform(R0, R1)
+ True
+ >>> I = numpy.identity(4, numpy.float64)
+ >>> numpy.allclose(I, rotation_matrix(math.pi*2, direc))
+ True
+ >>> numpy.allclose(2., numpy.trace(rotation_matrix(math.pi/2,
+ ... direc, point)))
+ True
+
+ """
+ sina = math.sin(angle)
+ cosa = math.cos(angle)
+ direction = unit_vector(direction[:3])
+ # rotation matrix around unit vector
+ R = numpy.array(((cosa, 0.0, 0.0),
+ (0.0, cosa, 0.0),
+ (0.0, 0.0, cosa)), dtype=numpy.float64)
+ R += numpy.outer(direction, direction) * (1.0 - cosa)
+ direction *= sina
+ R += numpy.array((( 0.0, -direction[2], direction[1]),
+ ( direction[2], 0.0, -direction[0]),
+ (-direction[1], direction[0], 0.0)),
+ dtype=numpy.float64)
+ M = numpy.identity(4)
+ M[:3, :3] = R
+ if point is not None:
+ # rotation not around origin
+ point = numpy.array(point[:3], dtype=numpy.float64, copy=False)
+ M[:3, 3] = point - numpy.dot(R, point)
+ return M
+
+
+def rotation_from_matrix(matrix):
+ """Return rotation angle and axis from rotation matrix.
+
+ >>> angle = (random.random() - 0.5) * (2*math.pi)
+ >>> direc = numpy.random.random(3) - 0.5
+ >>> point = numpy.random.random(3) - 0.5
+ >>> R0 = rotation_matrix(angle, direc, point)
+ >>> angle, direc, point = rotation_from_matrix(R0)
+ >>> R1 = rotation_matrix(angle, direc, point)
+ >>> is_same_transform(R0, R1)
+ True
+
+ """
+ R = numpy.array(matrix, dtype=numpy.float64, copy=False)
+ R33 = R[:3, :3]
+ # direction: unit eigenvector of R33 corresponding to eigenvalue of 1
+ l, W = numpy.linalg.eig(R33.T)
+ i = numpy.where(abs(numpy.real(l) - 1.0) < 1e-8)[0]
+ if not len(i):
+ raise ValueError("no unit eigenvector corresponding to eigenvalue 1")
+ direction = numpy.real(W[:, i[-1]]).squeeze()
+ # point: unit eigenvector of R33 corresponding to eigenvalue of 1
+ l, Q = numpy.linalg.eig(R)
+ i = numpy.where(abs(numpy.real(l) - 1.0) < 1e-8)[0]
+ if not len(i):
+ raise ValueError("no unit eigenvector corresponding to eigenvalue 1")
+ point = numpy.real(Q[:, i[-1]]).squeeze()
+ point /= point[3]
+ # rotation angle depending on direction
+ cosa = (numpy.trace(R33) - 1.0) / 2.0
+ if abs(direction[2]) > 1e-8:
+ sina = (R[1, 0] + (cosa-1.0)*direction[0]*direction[1]) / direction[2]
+ elif abs(direction[1]) > 1e-8:
+ sina = (R[0, 2] + (cosa-1.0)*direction[0]*direction[2]) / direction[1]
+ else:
+ sina = (R[2, 1] + (cosa-1.0)*direction[1]*direction[2]) / direction[0]
+ angle = math.atan2(sina, cosa)
+ return angle, direction, point
+
+
+def scale_matrix(factor, origin=None, direction=None):
+ """Return matrix to scale by factor around origin in direction.
+
+ Use factor -1 for point symmetry.
+
+ >>> v = (numpy.random.rand(4, 5) - 0.5) * 20.0
+ >>> v[3] = 1.0
+ >>> S = scale_matrix(-1.234)
+ >>> numpy.allclose(numpy.dot(S, v)[:3], -1.234*v[:3])
+ True
+ >>> factor = random.random() * 10 - 5
+ >>> origin = numpy.random.random(3) - 0.5
+ >>> direct = numpy.random.random(3) - 0.5
+ >>> S = scale_matrix(factor, origin)
+ >>> S = scale_matrix(factor, origin, direct)
+
+ """
+ if direction is None:
+ # uniform scaling
+ M = numpy.array(((factor, 0.0, 0.0, 0.0),
+ (0.0, factor, 0.0, 0.0),
+ (0.0, 0.0, factor, 0.0),
+ (0.0, 0.0, 0.0, 1.0)), dtype=numpy.float64)
+ if origin is not None:
+ M[:3, 3] = origin[:3]
+ M[:3, 3] *= 1.0 - factor
+ else:
+ # nonuniform scaling
+ direction = unit_vector(direction[:3])
+ factor = 1.0 - factor
+ M = numpy.identity(4)
+ M[:3, :3] -= factor * numpy.outer(direction, direction)
+ if origin is not None:
+ M[:3, 3] = (factor * numpy.dot(origin[:3], direction)) * direction
+ return M
+
+
+def scale_from_matrix(matrix):
+ """Return scaling factor, origin and direction from scaling matrix.
+
+ >>> factor = random.random() * 10 - 5
+ >>> origin = numpy.random.random(3) - 0.5
+ >>> direct = numpy.random.random(3) - 0.5
+ >>> S0 = scale_matrix(factor, origin)
+ >>> factor, origin, direction = scale_from_matrix(S0)
+ >>> S1 = scale_matrix(factor, origin, direction)
+ >>> is_same_transform(S0, S1)
+ True
+ >>> S0 = scale_matrix(factor, origin, direct)
+ >>> factor, origin, direction = scale_from_matrix(S0)
+ >>> S1 = scale_matrix(factor, origin, direction)
+ >>> is_same_transform(S0, S1)
+ True
+
+ """
+ M = numpy.array(matrix, dtype=numpy.float64, copy=False)
+ M33 = M[:3, :3]
+ factor = numpy.trace(M33) - 2.0
+ try:
+ # direction: unit eigenvector corresponding to eigenvalue factor
+ l, V = numpy.linalg.eig(M33)
+ i = numpy.where(abs(numpy.real(l) - factor) < 1e-8)[0][0]
+ direction = numpy.real(V[:, i]).squeeze()
+ direction /= vector_norm(direction)
+ except IndexError:
+ # uniform scaling
+ factor = (factor + 2.0) / 3.0
+ direction = None
+ # origin: any eigenvector corresponding to eigenvalue 1
+ l, V = numpy.linalg.eig(M)
+ i = numpy.where(abs(numpy.real(l) - 1.0) < 1e-8)[0]
+ if not len(i):
+ raise ValueError("no eigenvector corresponding to eigenvalue 1")
+ origin = numpy.real(V[:, i[-1]]).squeeze()
+ origin /= origin[3]
+ return factor, origin, direction
+
+
+def projection_matrix(point, normal, direction=None,
+ perspective=None, pseudo=False):
+ """Return matrix to project onto plane defined by point and normal.
+
+ Using either perspective point, projection direction, or none of both.
+
+ If pseudo is True, perspective projections will preserve relative depth
+ such that Perspective = dot(Orthogonal, PseudoPerspective).
+
+ >>> P = projection_matrix((0, 0, 0), (1, 0, 0))
+ >>> numpy.allclose(P[1:, 1:], numpy.identity(4)[1:, 1:])
+ True
+ >>> point = numpy.random.random(3) - 0.5
+ >>> normal = numpy.random.random(3) - 0.5
+ >>> direct = numpy.random.random(3) - 0.5
+ >>> persp = numpy.random.random(3) - 0.5
+ >>> P0 = projection_matrix(point, normal)
+ >>> P1 = projection_matrix(point, normal, direction=direct)
+ >>> P2 = projection_matrix(point, normal, perspective=persp)
+ >>> P3 = projection_matrix(point, normal, perspective=persp, pseudo=True)
+ >>> is_same_transform(P2, numpy.dot(P0, P3))
+ True
+ >>> P = projection_matrix((3, 0, 0), (1, 1, 0), (1, 0, 0))
+ >>> v0 = (numpy.random.rand(4, 5) - 0.5) * 20.0
+ >>> v0[3] = 1.0
+ >>> v1 = numpy.dot(P, v0)
+ >>> numpy.allclose(v1[1], v0[1])
+ True
+ >>> numpy.allclose(v1[0], 3.0-v1[1])
+ True
+
+ """
+ M = numpy.identity(4)
+ point = numpy.array(point[:3], dtype=numpy.float64, copy=False)
+ normal = unit_vector(normal[:3])
+ if perspective is not None:
+ # perspective projection
+ perspective = numpy.array(perspective[:3], dtype=numpy.float64,
+ copy=False)
+ M[0, 0] = M[1, 1] = M[2, 2] = numpy.dot(perspective-point, normal)
+ M[:3, :3] -= numpy.outer(perspective, normal)
+ if pseudo:
+ # preserve relative depth
+ M[:3, :3] -= numpy.outer(normal, normal)
+ M[:3, 3] = numpy.dot(point, normal) * (perspective+normal)
+ else:
+ M[:3, 3] = numpy.dot(point, normal) * perspective
+ M[3, :3] = -normal
+ M[3, 3] = numpy.dot(perspective, normal)
+ elif direction is not None:
+ # parallel projection
+ direction = numpy.array(direction[:3], dtype=numpy.float64, copy=False)
+ scale = numpy.dot(direction, normal)
+ M[:3, :3] -= numpy.outer(direction, normal) / scale
+ M[:3, 3] = direction * (numpy.dot(point, normal) / scale)
+ else:
+ # orthogonal projection
+ M[:3, :3] -= numpy.outer(normal, normal)
+ M[:3, 3] = numpy.dot(point, normal) * normal
+ return M
+
+
+def projection_from_matrix(matrix, pseudo=False):
+ """Return projection plane and perspective point from projection matrix.
+
+ Return values are same as arguments for projection_matrix function:
+ point, normal, direction, perspective, and pseudo.
+
+ >>> point = numpy.random.random(3) - 0.5
+ >>> normal = numpy.random.random(3) - 0.5
+ >>> direct = numpy.random.random(3) - 0.5
+ >>> persp = numpy.random.random(3) - 0.5
+ >>> P0 = projection_matrix(point, normal)
+ >>> result = projection_from_matrix(P0)
+ >>> P1 = projection_matrix(*result)
+ >>> is_same_transform(P0, P1)
+ True
+ >>> P0 = projection_matrix(point, normal, direct)
+ >>> result = projection_from_matrix(P0)
+ >>> P1 = projection_matrix(*result)
+ >>> is_same_transform(P0, P1)
+ True
+ >>> P0 = projection_matrix(point, normal, perspective=persp, pseudo=False)
+ >>> result = projection_from_matrix(P0, pseudo=False)
+ >>> P1 = projection_matrix(*result)
+ >>> is_same_transform(P0, P1)
+ True
+ >>> P0 = projection_matrix(point, normal, perspective=persp, pseudo=True)
+ >>> result = projection_from_matrix(P0, pseudo=True)
+ >>> P1 = projection_matrix(*result)
+ >>> is_same_transform(P0, P1)
+ True
+
+ """
+ M = numpy.array(matrix, dtype=numpy.float64, copy=False)
+ M33 = M[:3, :3]
+ l, V = numpy.linalg.eig(M)
+ i = numpy.where(abs(numpy.real(l) - 1.0) < 1e-8)[0]
+ if not pseudo and len(i):
+ # point: any eigenvector corresponding to eigenvalue 1
+ point = numpy.real(V[:, i[-1]]).squeeze()
+ point /= point[3]
+ # direction: unit eigenvector corresponding to eigenvalue 0
+ l, V = numpy.linalg.eig(M33)
+ i = numpy.where(abs(numpy.real(l)) < 1e-8)[0]
+ if not len(i):
+ raise ValueError("no eigenvector corresponding to eigenvalue 0")
+ direction = numpy.real(V[:, i[0]]).squeeze()
+ direction /= vector_norm(direction)
+ # normal: unit eigenvector of M33.T corresponding to eigenvalue 0
+ l, V = numpy.linalg.eig(M33.T)
+ i = numpy.where(abs(numpy.real(l)) < 1e-8)[0]
+ if len(i):
+ # parallel projection
+ normal = numpy.real(V[:, i[0]]).squeeze()
+ normal /= vector_norm(normal)
+ return point, normal, direction, None, False
+ else:
+ # orthogonal projection, where normal equals direction vector
+ return point, direction, None, None, False
+ else:
+ # perspective projection
+ i = numpy.where(abs(numpy.real(l)) > 1e-8)[0]
+ if not len(i):
+ raise ValueError(
+ "no eigenvector not corresponding to eigenvalue 0")
+ point = numpy.real(V[:, i[-1]]).squeeze()
+ point /= point[3]
+ normal = - M[3, :3]
+ perspective = M[:3, 3] / numpy.dot(point[:3], normal)
+ if pseudo:
+ perspective -= normal
+ return point, normal, None, perspective, pseudo
+
+
+def clip_matrix(left, right, bottom, top, near, far, perspective=False):
+ """Return matrix to obtain normalized device coordinates from frustrum.
+
+ The frustrum bounds are axis-aligned along x (left, right),
+ y (bottom, top) and z (near, far).
+
+ Normalized device coordinates are in range [-1, 1] if coordinates are
+ inside the frustrum.
+
+ If perspective is True the frustrum is a truncated pyramid with the
+ perspective point at origin and direction along z axis, otherwise an
+ orthographic canonical view volume (a box).
+
+ Homogeneous coordinates transformed by the perspective clip matrix
+ need to be dehomogenized (divided by w coordinate).
+
+ >>> frustrum = numpy.random.rand(6)
+ >>> frustrum[1] += frustrum[0]
+ >>> frustrum[3] += frustrum[2]
+ >>> frustrum[5] += frustrum[4]
+ >>> M = clip_matrix(*frustrum, perspective=False)
+ >>> numpy.dot(M, [frustrum[0], frustrum[2], frustrum[4], 1.0])
+ array([-1., -1., -1., 1.])
+ >>> numpy.dot(M, [frustrum[1], frustrum[3], frustrum[5], 1.0])
+ array([ 1., 1., 1., 1.])
+ >>> M = clip_matrix(*frustrum, perspective=True)
+ >>> v = numpy.dot(M, [frustrum[0], frustrum[2], frustrum[4], 1.0])
+ >>> v / v[3]
+ array([-1., -1., -1., 1.])
+ >>> v = numpy.dot(M, [frustrum[1], frustrum[3], frustrum[4], 1.0])
+ >>> v / v[3]
+ array([ 1., 1., -1., 1.])
+
+ """
+ if left >= right or bottom >= top or near >= far:
+ raise ValueError("invalid frustrum")
+ if perspective:
+ if near <= _EPS:
+ raise ValueError("invalid frustrum: near <= 0")
+ t = 2.0 * near
+ M = ((-t/(right-left), 0.0, (right+left)/(right-left), 0.0),
+ (0.0, -t/(top-bottom), (top+bottom)/(top-bottom), 0.0),
+ (0.0, 0.0, -(far+near)/(far-near), t*far/(far-near)),
+ (0.0, 0.0, -1.0, 0.0))
+ else:
+ M = ((2.0/(right-left), 0.0, 0.0, (right+left)/(left-right)),
+ (0.0, 2.0/(top-bottom), 0.0, (top+bottom)/(bottom-top)),
+ (0.0, 0.0, 2.0/(far-near), (far+near)/(near-far)),
+ (0.0, 0.0, 0.0, 1.0))
+ return numpy.array(M, dtype=numpy.float64)
+
+
+def shear_matrix(angle, direction, point, normal):
+ """Return matrix to shear by angle along direction vector on shear plane.
+
+ The shear plane is defined by a point and normal vector. The direction
+ vector must be orthogonal to the plane's normal vector.
+
+ A point P is transformed by the shear matrix into P" such that
+ the vector P-P" is parallel to the direction vector and its extent is
+ given by the angle of P-P'-P", where P' is the orthogonal projection
+ of P onto the shear plane.
+
+ >>> angle = (random.random() - 0.5) * 4*math.pi
+ >>> direct = numpy.random.random(3) - 0.5
+ >>> point = numpy.random.random(3) - 0.5
+ >>> normal = numpy.cross(direct, numpy.random.random(3))
+ >>> S = shear_matrix(angle, direct, point, normal)
+ >>> numpy.allclose(1.0, numpy.linalg.det(S))
+ True
+
+ """
+ normal = unit_vector(normal[:3])
+ direction = unit_vector(direction[:3])
+ if abs(numpy.dot(normal, direction)) > 1e-6:
+ raise ValueError("direction and normal vectors are not orthogonal")
+ angle = math.tan(angle)
+ M = numpy.identity(4)
+ M[:3, :3] += angle * numpy.outer(direction, normal)
+ M[:3, 3] = -angle * numpy.dot(point[:3], normal) * direction
+ return M
+
+
+def shear_from_matrix(matrix):
+ """Return shear angle, direction and plane from shear matrix.
+
+ >>> angle = (random.random() - 0.5) * 4*math.pi
+ >>> direct = numpy.random.random(3) - 0.5
+ >>> point = numpy.random.random(3) - 0.5
+ >>> normal = numpy.cross(direct, numpy.random.random(3))
+ >>> S0 = shear_matrix(angle, direct, point, normal)
+ >>> angle, direct, point, normal = shear_from_matrix(S0)
+ >>> S1 = shear_matrix(angle, direct, point, normal)
+ >>> is_same_transform(S0, S1)
+ True
+
+ """
+ M = numpy.array(matrix, dtype=numpy.float64, copy=False)
+ M33 = M[:3, :3]
+ # normal: cross independent eigenvectors corresponding to the eigenvalue 1
+ l, V = numpy.linalg.eig(M33)
+ i = numpy.where(abs(numpy.real(l) - 1.0) < 1e-4)[0]
+ if len(i) < 2:
+ raise ValueError("No two linear independent eigenvectors found %s" % l)
+ V = numpy.real(V[:, i]).squeeze().T
+ lenorm = -1.0
+ for i0, i1 in ((0, 1), (0, 2), (1, 2)):
+ n = numpy.cross(V[i0], V[i1])
+ l = vector_norm(n)
+ if l > lenorm:
+ lenorm = l
+ normal = n
+ normal /= lenorm
+ # direction and angle
+ direction = numpy.dot(M33 - numpy.identity(3), normal)
+ angle = vector_norm(direction)
+ direction /= angle
+ angle = math.atan(angle)
+ # point: eigenvector corresponding to eigenvalue 1
+ l, V = numpy.linalg.eig(M)
+ i = numpy.where(abs(numpy.real(l) - 1.0) < 1e-8)[0]
+ if not len(i):
+ raise ValueError("no eigenvector corresponding to eigenvalue 1")
+ point = numpy.real(V[:, i[-1]]).squeeze()
+ point /= point[3]
+ return angle, direction, point, normal
+
+
+def decompose_matrix(matrix):
+ """Return sequence of transformations from transformation matrix.
+
+ matrix : array_like
+ Non-degenerative homogeneous transformation matrix
+
+ Return tuple of:
+ scale : vector of 3 scaling factors
+ shear : list of shear factors for x-y, x-z, y-z axes
+ angles : list of Euler angles about static x, y, z axes
+ translate : translation vector along x, y, z axes
+ perspective : perspective partition of matrix
+
+ Raise ValueError if matrix is of wrong type or degenerative.
+
+ >>> T0 = translation_matrix((1, 2, 3))
+ >>> scale, shear, angles, trans, persp = decompose_matrix(T0)
+ >>> T1 = translation_matrix(trans)
+ >>> numpy.allclose(T0, T1)
+ True
+ >>> S = scale_matrix(0.123)
+ >>> scale, shear, angles, trans, persp = decompose_matrix(S)
+ >>> scale[0]
+ 0.123
+ >>> R0 = euler_matrix(1, 2, 3)
+ >>> scale, shear, angles, trans, persp = decompose_matrix(R0)
+ >>> R1 = euler_matrix(*angles)
+ >>> numpy.allclose(R0, R1)
+ True
+
+ """
+ M = numpy.array(matrix, dtype=numpy.float64, copy=True).T
+ if abs(M[3, 3]) < _EPS:
+ raise ValueError("M[3, 3] is zero")
+ M /= M[3, 3]
+ P = M.copy()
+ P[:, 3] = 0, 0, 0, 1
+ if not numpy.linalg.det(P):
+ raise ValueError("Matrix is singular")
+
+ scale = numpy.zeros((3, ), dtype=numpy.float64)
+ shear = [0, 0, 0]
+ angles = [0, 0, 0]
+
+ if any(abs(M[:3, 3]) > _EPS):
+ perspective = numpy.dot(M[:, 3], numpy.linalg.inv(P.T))
+ M[:, 3] = 0, 0, 0, 1
+ else:
+ perspective = numpy.array((0, 0, 0, 1), dtype=numpy.float64)
+
+ translate = M[3, :3].copy()
+ M[3, :3] = 0
+
+ row = M[:3, :3].copy()
+ scale[0] = vector_norm(row[0])
+ row[0] /= scale[0]
+ shear[0] = numpy.dot(row[0], row[1])
+ row[1] -= row[0] * shear[0]
+ scale[1] = vector_norm(row[1])
+ row[1] /= scale[1]
+ shear[0] /= scale[1]
+ shear[1] = numpy.dot(row[0], row[2])
+ row[2] -= row[0] * shear[1]
+ shear[2] = numpy.dot(row[1], row[2])
+ row[2] -= row[1] * shear[2]
+ scale[2] = vector_norm(row[2])
+ row[2] /= scale[2]
+ shear[1:] /= scale[2]
+
+ if numpy.dot(row[0], numpy.cross(row[1], row[2])) < 0:
+ scale *= -1
+ row *= -1
+
+ angles[1] = math.asin(-row[0, 2])
+ if math.cos(angles[1]):
+ angles[0] = math.atan2(row[1, 2], row[2, 2])
+ angles[2] = math.atan2(row[0, 1], row[0, 0])
+ else:
+ #angles[0] = math.atan2(row[1, 0], row[1, 1])
+ angles[0] = math.atan2(-row[2, 1], row[1, 1])
+ angles[2] = 0.0
+
+ return scale, shear, angles, translate, perspective
+
+
+def compose_matrix(scale=None, shear=None, angles=None, translate=None,
+ perspective=None):
+ """Return transformation matrix from sequence of transformations.
+
+ This is the inverse of the decompose_matrix function.
+
+ Sequence of transformations:
+ scale : vector of 3 scaling factors
+ shear : list of shear factors for x-y, x-z, y-z axes
+ angles : list of Euler angles about static x, y, z axes
+ translate : translation vector along x, y, z axes
+ perspective : perspective partition of matrix
+
+ >>> scale = numpy.random.random(3) - 0.5
+ >>> shear = numpy.random.random(3) - 0.5
+ >>> angles = (numpy.random.random(3) - 0.5) * (2*math.pi)
+ >>> trans = numpy.random.random(3) - 0.5
+ >>> persp = numpy.random.random(4) - 0.5
+ >>> M0 = compose_matrix(scale, shear, angles, trans, persp)
+ >>> result = decompose_matrix(M0)
+ >>> M1 = compose_matrix(*result)
+ >>> is_same_transform(M0, M1)
+ True
+
+ """
+ M = numpy.identity(4)
+ if perspective is not None:
+ P = numpy.identity(4)
+ P[3, :] = perspective[:4]
+ M = numpy.dot(M, P)
+ if translate is not None:
+ T = numpy.identity(4)
+ T[:3, 3] = translate[:3]
+ M = numpy.dot(M, T)
+ if angles is not None:
+ R = euler_matrix(angles[0], angles[1], angles[2], 'sxyz')
+ M = numpy.dot(M, R)
+ if shear is not None:
+ Z = numpy.identity(4)
+ Z[1, 2] = shear[2]
+ Z[0, 2] = shear[1]
+ Z[0, 1] = shear[0]
+ M = numpy.dot(M, Z)
+ if scale is not None:
+ S = numpy.identity(4)
+ S[0, 0] = scale[0]
+ S[1, 1] = scale[1]
+ S[2, 2] = scale[2]
+ M = numpy.dot(M, S)
+ M /= M[3, 3]
+ return M
+
+
+def orthogonalization_matrix(lengths, angles):
+ """Return orthogonalization matrix for crystallographic cell coordinates.
+
+ Angles are expected in degrees.
+
+ The de-orthogonalization matrix is the inverse.
+
+ >>> O = orthogonalization_matrix((10., 10., 10.), (90., 90., 90.))
+ >>> numpy.allclose(O[:3, :3], numpy.identity(3, float) * 10)
+ True
+ >>> O = orthogonalization_matrix([9.8, 12.0, 15.5], [87.2, 80.7, 69.7])
+ >>> numpy.allclose(numpy.sum(O), 43.063229)
+ True
+
+ """
+ a, b, c = lengths
+ angles = numpy.radians(angles)
+ sina, sinb, _ = numpy.sin(angles)
+ cosa, cosb, cosg = numpy.cos(angles)
+ co = (cosa * cosb - cosg) / (sina * sinb)
+ return numpy.array((
+ ( a*sinb*math.sqrt(1.0-co*co), 0.0, 0.0, 0.0),
+ (-a*sinb*co, b*sina, 0.0, 0.0),
+ ( a*cosb, b*cosa, c, 0.0),
+ ( 0.0, 0.0, 0.0, 1.0)),
+ dtype=numpy.float64)
+
+
+def superimposition_matrix(v0, v1, scaling=False, usesvd=True):
+ """Return matrix to transform given vector set into second vector set.
+
+ v0 and v1 are shape (3, \*) or (4, \*) arrays of at least 3 vectors.
+
+ If usesvd is True, the weighted sum of squared deviations (RMSD) is
+ minimized according to the algorithm by W. Kabsch [8]. Otherwise the
+ quaternion based algorithm by B. Horn [9] is used (slower when using
+ this Python implementation).
+
+ The returned matrix performs rotation, translation and uniform scaling
+ (if specified).
+
+ >>> v0 = numpy.random.rand(3, 10)
+ >>> M = superimposition_matrix(v0, v0)
+ >>> numpy.allclose(M, numpy.identity(4))
+ True
+ >>> R = random_rotation_matrix(numpy.random.random(3))
+ >>> v0 = ((1,0,0), (0,1,0), (0,0,1), (1,1,1))
+ >>> v1 = numpy.dot(R, v0)
+ >>> M = superimposition_matrix(v0, v1)
+ >>> numpy.allclose(v1, numpy.dot(M, v0))
+ True
+ >>> v0 = (numpy.random.rand(4, 100) - 0.5) * 20.0
+ >>> v0[3] = 1.0
+ >>> v1 = numpy.dot(R, v0)
+ >>> M = superimposition_matrix(v0, v1)
+ >>> numpy.allclose(v1, numpy.dot(M, v0))
+ True
+ >>> S = scale_matrix(random.random())
+ >>> T = translation_matrix(numpy.random.random(3)-0.5)
+ >>> M = concatenate_matrices(T, R, S)
+ >>> v1 = numpy.dot(M, v0)
+ >>> v0[:3] += numpy.random.normal(0.0, 1e-9, 300).reshape(3, -1)
+ >>> M = superimposition_matrix(v0, v1, scaling=True)
+ >>> numpy.allclose(v1, numpy.dot(M, v0))
+ True
+ >>> M = superimposition_matrix(v0, v1, scaling=True, usesvd=False)
+ >>> numpy.allclose(v1, numpy.dot(M, v0))
+ True
+ >>> v = numpy.empty((4, 100, 3), dtype=numpy.float64)
+ >>> v[:, :, 0] = v0
+ >>> M = superimposition_matrix(v0, v1, scaling=True, usesvd=False)
+ >>> numpy.allclose(v1, numpy.dot(M, v[:, :, 0]))
+ True
+
+ """
+ v0 = numpy.array(v0, dtype=numpy.float64, copy=False)[:3]
+ v1 = numpy.array(v1, dtype=numpy.float64, copy=False)[:3]
+
+ if v0.shape != v1.shape or v0.shape[1] < 3:
+ raise ValueError("Vector sets are of wrong shape or type.")
+
+ # move centroids to origin
+ t0 = numpy.mean(v0, axis=1)
+ t1 = numpy.mean(v1, axis=1)
+ v0 = v0 - t0.reshape(3, 1)
+ v1 = v1 - t1.reshape(3, 1)
+
+ if usesvd:
+ # Singular Value Decomposition of covariance matrix
+ u, s, vh = numpy.linalg.svd(numpy.dot(v1, v0.T))
+ # rotation matrix from SVD orthonormal bases
+ R = numpy.dot(u, vh)
+ if numpy.linalg.det(R) < 0.0:
+ # R does not constitute right handed system
+ R -= numpy.outer(u[:, 2], vh[2, :]*2.0)
+ s[-1] *= -1.0
+ # homogeneous transformation matrix
+ M = numpy.identity(4)
+ M[:3, :3] = R
+ else:
+ # compute symmetric matrix N
+ xx, yy, zz = numpy.sum(v0 * v1, axis=1)
+ xy, yz, zx = numpy.sum(v0 * numpy.roll(v1, -1, axis=0), axis=1)
+ xz, yx, zy = numpy.sum(v0 * numpy.roll(v1, -2, axis=0), axis=1)
+ N = ((xx+yy+zz, yz-zy, zx-xz, xy-yx),
+ (yz-zy, xx-yy-zz, xy+yx, zx+xz),
+ (zx-xz, xy+yx, -xx+yy-zz, yz+zy),
+ (xy-yx, zx+xz, yz+zy, -xx-yy+zz))
+ # quaternion: eigenvector corresponding to most positive eigenvalue
+ l, V = numpy.linalg.eig(N)
+ q = V[:, numpy.argmax(l)]
+ q /= vector_norm(q) # unit quaternion
+ q = numpy.roll(q, -1) # move w component to end
+ # homogeneous transformation matrix
+ M = quaternion_matrix(q)
+
+ # scale: ratio of rms deviations from centroid
+ if scaling:
+ v0 *= v0
+ v1 *= v1
+ M[:3, :3] *= math.sqrt(numpy.sum(v1) / numpy.sum(v0))
+
+ # translation
+ M[:3, 3] = t1
+ T = numpy.identity(4)
+ T[:3, 3] = -t0
+ M = numpy.dot(M, T)
+ return M
+
+
+def euler_matrix(ai, aj, ak, axes='sxyz'):
+ """Return homogeneous rotation matrix from Euler angles and axis sequence.
+
+ ai, aj, ak : Euler's roll, pitch and yaw angles
+ axes : One of 24 axis sequences as string or encoded tuple
+
+ >>> R = euler_matrix(1, 2, 3, 'syxz')
+ >>> numpy.allclose(numpy.sum(R[0]), -1.34786452)
+ True
+ >>> R = euler_matrix(1, 2, 3, (0, 1, 0, 1))
+ >>> numpy.allclose(numpy.sum(R[0]), -0.383436184)
+ True
+ >>> ai, aj, ak = (4.0*math.pi) * (numpy.random.random(3) - 0.5)
+ >>> for axes in _AXES2TUPLE.keys():
+ ... R = euler_matrix(ai, aj, ak, axes)
+ >>> for axes in _TUPLE2AXES.keys():
+ ... R = euler_matrix(ai, aj, ak, axes)
+
+ """
+ try:
+ firstaxis, parity, repetition, frame = _AXES2TUPLE[axes]
+ except (AttributeError, KeyError):
+ _ = _TUPLE2AXES[axes]
+ firstaxis, parity, repetition, frame = axes
+
+ i = firstaxis
+ j = _NEXT_AXIS[i+parity]
+ k = _NEXT_AXIS[i-parity+1]
+
+ if frame:
+ ai, ak = ak, ai
+ if parity:
+ ai, aj, ak = -ai, -aj, -ak
+
+ si, sj, sk = math.sin(ai), math.sin(aj), math.sin(ak)
+ ci, cj, ck = math.cos(ai), math.cos(aj), math.cos(ak)
+ cc, cs = ci*ck, ci*sk
+ sc, ss = si*ck, si*sk
+
+ M = numpy.identity(4)
+ if repetition:
+ M[i, i] = cj
+ M[i, j] = sj*si
+ M[i, k] = sj*ci
+ M[j, i] = sj*sk
+ M[j, j] = -cj*ss+cc
+ M[j, k] = -cj*cs-sc
+ M[k, i] = -sj*ck
+ M[k, j] = cj*sc+cs
+ M[k, k] = cj*cc-ss
+ else:
+ M[i, i] = cj*ck
+ M[i, j] = sj*sc-cs
+ M[i, k] = sj*cc+ss
+ M[j, i] = cj*sk
+ M[j, j] = sj*ss+cc
+ M[j, k] = sj*cs-sc
+ M[k, i] = -sj
+ M[k, j] = cj*si
+ M[k, k] = cj*ci
+ return M
+
+
+def euler_from_matrix(matrix, axes='sxyz'):
+ """Return Euler angles from rotation matrix for specified axis sequence.
+
+ axes : One of 24 axis sequences as string or encoded tuple
+
+ Note that many Euler angle triplets can describe one matrix.
+
+ >>> R0 = euler_matrix(1, 2, 3, 'syxz')
+ >>> al, be, ga = euler_from_matrix(R0, 'syxz')
+ >>> R1 = euler_matrix(al, be, ga, 'syxz')
+ >>> numpy.allclose(R0, R1)
+ True
+ >>> angles = (4.0*math.pi) * (numpy.random.random(3) - 0.5)
+ >>> for axes in _AXES2TUPLE.keys():
+ ... R0 = euler_matrix(axes=axes, *angles)
+ ... R1 = euler_matrix(axes=axes, *euler_from_matrix(R0, axes))
+ ... if not numpy.allclose(R0, R1): print axes, "failed"
+
+ """
+ try:
+ firstaxis, parity, repetition, frame = _AXES2TUPLE[axes.lower()]
+ except (AttributeError, KeyError):
+ _ = _TUPLE2AXES[axes]
+ firstaxis, parity, repetition, frame = axes
+
+ i = firstaxis
+ j = _NEXT_AXIS[i+parity]
+ k = _NEXT_AXIS[i-parity+1]
+
+ M = numpy.array(matrix, dtype=numpy.float64, copy=False)[:3, :3]
+ if repetition:
+ sy = math.sqrt(M[i, j]*M[i, j] + M[i, k]*M[i, k])
+ if sy > _EPS:
+ ax = math.atan2( M[i, j], M[i, k])
+ ay = math.atan2( sy, M[i, i])
+ az = math.atan2( M[j, i], -M[k, i])
+ else:
+ ax = math.atan2(-M[j, k], M[j, j])
+ ay = math.atan2( sy, M[i, i])
+ az = 0.0
+ else:
+ cy = math.sqrt(M[i, i]*M[i, i] + M[j, i]*M[j, i])
+ if cy > _EPS:
+ ax = math.atan2( M[k, j], M[k, k])
+ ay = math.atan2(-M[k, i], cy)
+ az = math.atan2( M[j, i], M[i, i])
+ else:
+ ax = math.atan2(-M[j, k], M[j, j])
+ ay = math.atan2(-M[k, i], cy)
+ az = 0.0
+
+ if parity:
+ ax, ay, az = -ax, -ay, -az
+ if frame:
+ ax, az = az, ax
+ return ax, ay, az
+
+
+def euler_from_quaternion(quaternion, axes='sxyz'):
+ """Return Euler angles from quaternion for specified axis sequence.
+
+ >>> angles = euler_from_quaternion([0.06146124, 0, 0, 0.99810947])
+ >>> numpy.allclose(angles, [0.123, 0, 0])
+ True
+
+ """
+ return euler_from_matrix(quaternion_matrix(quaternion), axes)
+
+
+def quaternion_from_euler(ai, aj, ak, axes='sxyz'):
+ """Return quaternion from Euler angles and axis sequence.
+
+ ai, aj, ak : Euler's roll, pitch and yaw angles
+ axes : One of 24 axis sequences as string or encoded tuple
+
+ >>> q = quaternion_from_euler(1, 2, 3, 'ryxz')
+ >>> numpy.allclose(q, [0.310622, -0.718287, 0.444435, 0.435953])
+ True
+
+ """
+ try:
+ firstaxis, parity, repetition, frame = _AXES2TUPLE[axes.lower()]
+ except (AttributeError, KeyError):
+ _ = _TUPLE2AXES[axes]
+ firstaxis, parity, repetition, frame = axes
+
+ i = firstaxis
+ j = _NEXT_AXIS[i+parity]
+ k = _NEXT_AXIS[i-parity+1]
+
+ if frame:
+ ai, ak = ak, ai
+ if parity:
+ aj = -aj
+
+ ai /= 2.0
+ aj /= 2.0
+ ak /= 2.0
+ ci = math.cos(ai)
+ si = math.sin(ai)
+ cj = math.cos(aj)
+ sj = math.sin(aj)
+ ck = math.cos(ak)
+ sk = math.sin(ak)
+ cc = ci*ck
+ cs = ci*sk
+ sc = si*ck
+ ss = si*sk
+
+ quaternion = numpy.empty((4, ), dtype=numpy.float64)
+ if repetition:
+ quaternion[i] = cj*(cs + sc)
+ quaternion[j] = sj*(cc + ss)
+ quaternion[k] = sj*(cs - sc)
+ quaternion[3] = cj*(cc - ss)
+ else:
+ quaternion[i] = cj*sc - sj*cs
+ quaternion[j] = cj*ss + sj*cc
+ quaternion[k] = cj*cs - sj*sc
+ quaternion[3] = cj*cc + sj*ss
+ if parity:
+ quaternion[j] *= -1
+
+ return quaternion
+
+
+def quaternion_about_axis(angle, axis):
+ """Return quaternion for rotation about axis.
+
+ >>> q = quaternion_about_axis(0.123, (1, 0, 0))
+ >>> numpy.allclose(q, [0.06146124, 0, 0, 0.99810947])
+ True
+
+ """
+ quaternion = numpy.zeros((4, ), dtype=numpy.float64)
+ quaternion[:3] = axis[:3]
+ qlen = vector_norm(quaternion)
+ if qlen > _EPS:
+ quaternion *= math.sin(angle/2.0) / qlen
+ quaternion[3] = math.cos(angle/2.0)
+ return quaternion
+
+
+def quaternion_matrix(quaternion):
+ """Return homogeneous rotation matrix from quaternion.
+
+ >>> R = quaternion_matrix([0.06146124, 0, 0, 0.99810947])
+ >>> numpy.allclose(R, rotation_matrix(0.123, (1, 0, 0)))
+ True
+
+ """
+ q = numpy.array(quaternion[:4], dtype=numpy.float64, copy=True)
+ nq = numpy.dot(q, q)
+ if nq < _EPS:
+ return numpy.identity(4)
+ q *= math.sqrt(2.0 / nq)
+ q = numpy.outer(q, q)
+ return numpy.array((
+ (1.0-q[1, 1]-q[2, 2], q[0, 1]-q[2, 3], q[0, 2]+q[1, 3], 0.0),
+ ( q[0, 1]+q[2, 3], 1.0-q[0, 0]-q[2, 2], q[1, 2]-q[0, 3], 0.0),
+ ( q[0, 2]-q[1, 3], q[1, 2]+q[0, 3], 1.0-q[0, 0]-q[1, 1], 0.0),
+ ( 0.0, 0.0, 0.0, 1.0)
+ ), dtype=numpy.float64)
+
+
+def quaternion_from_matrix(matrix):
+ """Return quaternion from rotation matrix.
+
+ >>> R = rotation_matrix(0.123, (1, 2, 3))
+ >>> q = quaternion_from_matrix(R)
+ >>> numpy.allclose(q, [0.0164262, 0.0328524, 0.0492786, 0.9981095])
+ True
+
+ """
+ q = numpy.empty((4, ), dtype=numpy.float64)
+ M = numpy.array(matrix, dtype=numpy.float64, copy=False)[:4, :4]
+ t = numpy.trace(M)
+ if t > M[3, 3]:
+ q[3] = t
+ q[2] = M[1, 0] - M[0, 1]
+ q[1] = M[0, 2] - M[2, 0]
+ q[0] = M[2, 1] - M[1, 2]
+ else:
+ i, j, k = 0, 1, 2
+ if M[1, 1] > M[0, 0]:
+ i, j, k = 1, 2, 0
+ if M[2, 2] > M[i, i]:
+ i, j, k = 2, 0, 1
+ t = M[i, i] - (M[j, j] + M[k, k]) + M[3, 3]
+ q[i] = t
+ q[j] = M[i, j] + M[j, i]
+ q[k] = M[k, i] + M[i, k]
+ q[3] = M[k, j] - M[j, k]
+ q *= 0.5 / math.sqrt(t * M[3, 3])
+ return q
+
+
+def quaternion_multiply(quaternion1, quaternion0):
+ """Return multiplication of two quaternions.
+
+ >>> q = quaternion_multiply([1, -2, 3, 4], [-5, 6, 7, 8])
+ >>> numpy.allclose(q, [-44, -14, 48, 28])
+ True
+
+ """
+ x0, y0, z0, w0 = quaternion0
+ x1, y1, z1, w1 = quaternion1
+ return numpy.array((
+ x1*w0 + y1*z0 - z1*y0 + w1*x0,
+ -x1*z0 + y1*w0 + z1*x0 + w1*y0,
+ x1*y0 - y1*x0 + z1*w0 + w1*z0,
+ -x1*x0 - y1*y0 - z1*z0 + w1*w0), dtype=numpy.float64)
+
+
+def quaternion_conjugate(quaternion):
+ """Return conjugate of quaternion.
+
+ >>> q0 = random_quaternion()
+ >>> q1 = quaternion_conjugate(q0)
+ >>> q1[3] == q0[3] and all(q1[:3] == -q0[:3])
+ True
+
+ """
+ return numpy.array((-quaternion[0], -quaternion[1],
+ -quaternion[2], quaternion[3]), dtype=numpy.float64)
+
+
+def quaternion_inverse(quaternion):
+ """Return inverse of quaternion.
+
+ >>> q0 = random_quaternion()
+ >>> q1 = quaternion_inverse(q0)
+ >>> numpy.allclose(quaternion_multiply(q0, q1), [0, 0, 0, 1])
+ True
+
+ """
+ return quaternion_conjugate(quaternion) / numpy.dot(quaternion, quaternion)
+
+
+def quaternion_slerp(quat0, quat1, fraction, spin=0, shortestpath=True):
+ """Return spherical linear interpolation between two quaternions.
+
+ >>> q0 = random_quaternion()
+ >>> q1 = random_quaternion()
+ >>> q = quaternion_slerp(q0, q1, 0.0)
+ >>> numpy.allclose(q, q0)
+ True
+ >>> q = quaternion_slerp(q0, q1, 1.0, 1)
+ >>> numpy.allclose(q, q1)
+ True
+ >>> q = quaternion_slerp(q0, q1, 0.5)
+ >>> angle = math.acos(numpy.dot(q0, q))
+ >>> numpy.allclose(2.0, math.acos(numpy.dot(q0, q1)) / angle) or \
+ numpy.allclose(2.0, math.acos(-numpy.dot(q0, q1)) / angle)
+ True
+
+ """
+ q0 = unit_vector(quat0[:4])
+ q1 = unit_vector(quat1[:4])
+ if fraction == 0.0:
+ return q0
+ elif fraction == 1.0:
+ return q1
+ d = numpy.dot(q0, q1)
+ if abs(abs(d) - 1.0) < _EPS:
+ return q0
+ if shortestpath and d < 0.0:
+ # invert rotation
+ d = -d
+ q1 *= -1.0
+ angle = math.acos(d) + spin * math.pi
+ if abs(angle) < _EPS:
+ return q0
+ isin = 1.0 / math.sin(angle)
+ q0 *= math.sin((1.0 - fraction) * angle) * isin
+ q1 *= math.sin(fraction * angle) * isin
+ q0 += q1
+ return q0
+
+
+def random_quaternion(rand=None):
+ """Return uniform random unit quaternion.
+
+ rand: array like or None
+ Three independent random variables that are uniformly distributed
+ between 0 and 1.
+
+ >>> q = random_quaternion()
+ >>> numpy.allclose(1.0, vector_norm(q))
+ True
+ >>> q = random_quaternion(numpy.random.random(3))
+ >>> q.shape
+ (4,)
+
+ """
+ if rand is None:
+ rand = numpy.random.rand(3)
+ else:
+ assert len(rand) == 3
+ r1 = numpy.sqrt(1.0 - rand[0])
+ r2 = numpy.sqrt(rand[0])
+ pi2 = math.pi * 2.0
+ t1 = pi2 * rand[1]
+ t2 = pi2 * rand[2]
+ return numpy.array((numpy.sin(t1)*r1,
+ numpy.cos(t1)*r1,
+ numpy.sin(t2)*r2,
+ numpy.cos(t2)*r2), dtype=numpy.float64)
+
+
+def random_rotation_matrix(rand=None):
+ """Return uniform random rotation matrix.
+
+ rnd: array like
+ Three independent random variables that are uniformly distributed
+ between 0 and 1 for each returned quaternion.
+
+ >>> R = random_rotation_matrix()
+ >>> numpy.allclose(numpy.dot(R.T, R), numpy.identity(4))
+ True
+
+ """
+ return quaternion_matrix(random_quaternion(rand))
+
+
+class Arcball(object):
+ """Virtual Trackball Control.
+
+ >>> ball = Arcball()
+ >>> ball = Arcball(initial=numpy.identity(4))
+ >>> ball.place([320, 320], 320)
+ >>> ball.down([500, 250])
+ >>> ball.drag([475, 275])
+ >>> R = ball.matrix()
+ >>> numpy.allclose(numpy.sum(R), 3.90583455)
+ True
+ >>> ball = Arcball(initial=[0, 0, 0, 1])
+ >>> ball.place([320, 320], 320)
+ >>> ball.setaxes([1,1,0], [-1, 1, 0])
+ >>> ball.setconstrain(True)
+ >>> ball.down([400, 200])
+ >>> ball.drag([200, 400])
+ >>> R = ball.matrix()
+ >>> numpy.allclose(numpy.sum(R), 0.2055924)
+ True
+ >>> ball.next()
+
+ """
+
+ def __init__(self, initial=None):
+ """Initialize virtual trackball control.
+
+ initial : quaternion or rotation matrix
+
+ """
+ self._axis = None
+ self._axes = None
+ self._radius = 1.0
+ self._center = [0.0, 0.0]
+ self._vdown = numpy.array([0, 0, 1], dtype=numpy.float64)
+ self._constrain = False
+
+ if initial is None:
+ self._qdown = numpy.array([0, 0, 0, 1], dtype=numpy.float64)
+ else:
+ initial = numpy.array(initial, dtype=numpy.float64)
+ if initial.shape == (4, 4):
+ self._qdown = quaternion_from_matrix(initial)
+ elif initial.shape == (4, ):
+ initial /= vector_norm(initial)
+ self._qdown = initial
+ else:
+ raise ValueError("initial not a quaternion or matrix.")
+
+ self._qnow = self._qpre = self._qdown
+
+ def place(self, center, radius):
+ """Place Arcball, e.g. when window size changes.
+
+ center : sequence[2]
+ Window coordinates of trackball center.
+ radius : float
+ Radius of trackball in window coordinates.
+
+ """
+ self._radius = float(radius)
+ self._center[0] = center[0]
+ self._center[1] = center[1]
+
+ def setaxes(self, *axes):
+ """Set axes to constrain rotations."""
+ if axes is None:
+ self._axes = None
+ else:
+ self._axes = [unit_vector(axis) for axis in axes]
+
+ def setconstrain(self, constrain):
+ """Set state of constrain to axis mode."""
+ self._constrain = constrain == True
+
+ def getconstrain(self):
+ """Return state of constrain to axis mode."""
+ return self._constrain
+
+ def down(self, point):
+ """Set initial cursor window coordinates and pick constrain-axis."""
+ self._vdown = arcball_map_to_sphere(point, self._center, self._radius)
+ self._qdown = self._qpre = self._qnow
+
+ if self._constrain and self._axes is not None:
+ self._axis = arcball_nearest_axis(self._vdown, self._axes)
+ self._vdown = arcball_constrain_to_axis(self._vdown, self._axis)
+ else:
+ self._axis = None
+
+ def drag(self, point):
+ """Update current cursor window coordinates."""
+ vnow = arcball_map_to_sphere(point, self._center, self._radius)
+
+ if self._axis is not None:
+ vnow = arcball_constrain_to_axis(vnow, self._axis)
+
+ self._qpre = self._qnow
+
+ t = numpy.cross(self._vdown, vnow)
+ if numpy.dot(t, t) < _EPS:
+ self._qnow = self._qdown
+ else:
+ q = [t[0], t[1], t[2], numpy.dot(self._vdown, vnow)]
+ self._qnow = quaternion_multiply(q, self._qdown)
+
+ def next(self, acceleration=0.0):
+ """Continue rotation in direction of last drag."""
+ q = quaternion_slerp(self._qpre, self._qnow, 2.0+acceleration, False)
+ self._qpre, self._qnow = self._qnow, q
+
+ def matrix(self):
+ """Return homogeneous rotation matrix."""
+ return quaternion_matrix(self._qnow)
+
+
+def arcball_map_to_sphere(point, center, radius):
+ """Return unit sphere coordinates from window coordinates."""
+ v = numpy.array(((point[0] - center[0]) / radius,
+ (center[1] - point[1]) / radius,
+ 0.0), dtype=numpy.float64)
+ n = v[0]*v[0] + v[1]*v[1]
+ if n > 1.0:
+ v /= math.sqrt(n) # position outside of sphere
+ else:
+ v[2] = math.sqrt(1.0 - n)
+ return v
+
+
+def arcball_constrain_to_axis(point, axis):
+ """Return sphere point perpendicular to axis."""
+ v = numpy.array(point, dtype=numpy.float64, copy=True)
+ a = numpy.array(axis, dtype=numpy.float64, copy=True)
+ v -= a * numpy.dot(a, v) # on plane
+ n = vector_norm(v)
+ if n > _EPS:
+ if v[2] < 0.0:
+ v *= -1.0
+ v /= n
+ return v
+ if a[2] == 1.0:
+ return numpy.array([1, 0, 0], dtype=numpy.float64)
+ return unit_vector([-a[1], a[0], 0])
+
+
+def arcball_nearest_axis(point, axes):
+ """Return axis, which arc is nearest to point."""
+ point = numpy.array(point, dtype=numpy.float64, copy=False)
+ nearest = None
+ mx = -1.0
+ for axis in axes:
+ t = numpy.dot(arcball_constrain_to_axis(point, axis), point)
+ if t > mx:
+ nearest = axis
+ mx = t
+ return nearest
+
+
+# epsilon for testing whether a number is close to zero
+_EPS = numpy.finfo(float).eps * 4.0
+
+# axis sequences for Euler angles
+_NEXT_AXIS = [1, 2, 0, 1]
+
+# map axes strings to/from tuples of inner axis, parity, repetition, frame
+_AXES2TUPLE = {
+ 'sxyz': (0, 0, 0, 0), 'sxyx': (0, 0, 1, 0), 'sxzy': (0, 1, 0, 0),
+ 'sxzx': (0, 1, 1, 0), 'syzx': (1, 0, 0, 0), 'syzy': (1, 0, 1, 0),
+ 'syxz': (1, 1, 0, 0), 'syxy': (1, 1, 1, 0), 'szxy': (2, 0, 0, 0),
+ 'szxz': (2, 0, 1, 0), 'szyx': (2, 1, 0, 0), 'szyz': (2, 1, 1, 0),
+ 'rzyx': (0, 0, 0, 1), 'rxyx': (0, 0, 1, 1), 'ryzx': (0, 1, 0, 1),
+ 'rxzx': (0, 1, 1, 1), 'rxzy': (1, 0, 0, 1), 'ryzy': (1, 0, 1, 1),
+ 'rzxy': (1, 1, 0, 1), 'ryxy': (1, 1, 1, 1), 'ryxz': (2, 0, 0, 1),
+ 'rzxz': (2, 0, 1, 1), 'rxyz': (2, 1, 0, 1), 'rzyz': (2, 1, 1, 1)}
+
+_TUPLE2AXES = dict((v, k) for k, v in _AXES2TUPLE.items())
+
+# helper functions
+
+def vector_norm(data, axis=None, out=None):
+ """Return length, i.e. eucledian norm, of ndarray along axis.
+
+ >>> v = numpy.random.random(3)
+ >>> n = vector_norm(v)
+ >>> numpy.allclose(n, numpy.linalg.norm(v))
+ True
+ >>> v = numpy.random.rand(6, 5, 3)
+ >>> n = vector_norm(v, axis=-1)
+ >>> numpy.allclose(n, numpy.sqrt(numpy.sum(v*v, axis=2)))
+ True
+ >>> n = vector_norm(v, axis=1)
+ >>> numpy.allclose(n, numpy.sqrt(numpy.sum(v*v, axis=1)))
+ True
+ >>> v = numpy.random.rand(5, 4, 3)
+ >>> n = numpy.empty((5, 3), dtype=numpy.float64)
+ >>> vector_norm(v, axis=1, out=n)
+ >>> numpy.allclose(n, numpy.sqrt(numpy.sum(v*v, axis=1)))
+ True
+ >>> vector_norm([])
+ 0.0
+ >>> vector_norm([1.0])
+ 1.0
+
+ """
+ data = numpy.array(data, dtype=numpy.float64, copy=True)
+ if out is None:
+ if data.ndim == 1:
+ return math.sqrt(numpy.dot(data, data))
+ data *= data
+ out = numpy.atleast_1d(numpy.sum(data, axis=axis))
+ numpy.sqrt(out, out)
+ return out
+ else:
+ data *= data
+ numpy.sum(data, axis=axis, out=out)
+ numpy.sqrt(out, out)
+
+
+def unit_vector(data, axis=None, out=None):
+ """Return ndarray normalized by length, i.e. eucledian norm, along axis.
+
+ >>> v0 = numpy.random.random(3)
+ >>> v1 = unit_vector(v0)
+ >>> numpy.allclose(v1, v0 / numpy.linalg.norm(v0))
+ True
+ >>> v0 = numpy.random.rand(5, 4, 3)
+ >>> v1 = unit_vector(v0, axis=-1)
+ >>> v2 = v0 / numpy.expand_dims(numpy.sqrt(numpy.sum(v0*v0, axis=2)), 2)
+ >>> numpy.allclose(v1, v2)
+ True
+ >>> v1 = unit_vector(v0, axis=1)
+ >>> v2 = v0 / numpy.expand_dims(numpy.sqrt(numpy.sum(v0*v0, axis=1)), 1)
+ >>> numpy.allclose(v1, v2)
+ True
+ >>> v1 = numpy.empty((5, 4, 3), dtype=numpy.float64)
+ >>> unit_vector(v0, axis=1, out=v1)
+ >>> numpy.allclose(v1, v2)
+ True
+ >>> list(unit_vector([]))
+ []
+ >>> list(unit_vector([1.0]))
+ [1.0]
+
+ """
+ if out is None:
+ data = numpy.array(data, dtype=numpy.float64, copy=True)
+ if data.ndim == 1:
+ data /= math.sqrt(numpy.dot(data, data))
+ return data
+ else:
+ if out is not data:
+ out[:] = numpy.array(data, copy=False)
+ data = out
+ length = numpy.atleast_1d(numpy.sum(data*data, axis))
+ numpy.sqrt(length, length)
+ if axis is not None:
+ length = numpy.expand_dims(length, axis)
+ data /= length
+ if out is None:
+ return data
+
+
+def random_vector(size):
+ """Return array of random doubles in the half-open interval [0.0, 1.0).
+
+ >>> v = random_vector(10000)
+ >>> numpy.all(v >= 0.0) and numpy.all(v < 1.0)
+ True
+ >>> v0 = random_vector(10)
+ >>> v1 = random_vector(10)
+ >>> numpy.any(v0 == v1)
+ False
+
+ """
+ return numpy.random.random(size)
+
+
+def inverse_matrix(matrix):
+ """Return inverse of square transformation matrix.
+
+ >>> M0 = random_rotation_matrix()
+ >>> M1 = inverse_matrix(M0.T)
+ >>> numpy.allclose(M1, numpy.linalg.inv(M0.T))
+ True
+ >>> for size in range(1, 7):
+ ... M0 = numpy.random.rand(size, size)
+ ... M1 = inverse_matrix(M0)
+ ... if not numpy.allclose(M1, numpy.linalg.inv(M0)): print size
+
+ """
+ return numpy.linalg.inv(matrix)
+
+
+def concatenate_matrices(*matrices):
+ """Return concatenation of series of transformation matrices.
+
+ >>> M = numpy.random.rand(16).reshape((4, 4)) - 0.5
+ >>> numpy.allclose(M, concatenate_matrices(M))
+ True
+ >>> numpy.allclose(numpy.dot(M, M.T), concatenate_matrices(M, M.T))
+ True
+
+ """
+ M = numpy.identity(4)
+ for i in matrices:
+ M = numpy.dot(M, i)
+ return M
+
+
+def is_same_transform(matrix0, matrix1):
+ """Return True if two matrices perform same transformation.
+
+ >>> is_same_transform(numpy.identity(4), numpy.identity(4))
+ True
+ >>> is_same_transform(numpy.identity(4), random_rotation_matrix())
+ False
+
+ """
+ matrix0 = numpy.array(matrix0, dtype=numpy.float64, copy=True)
+ matrix0 /= matrix0[3, 3]
+ matrix1 = numpy.array(matrix1, dtype=numpy.float64, copy=True)
+ matrix1 /= matrix1[3, 3]
+ return numpy.allclose(matrix0, matrix1)
+
+
+def _import_module(module_name, warn=True, prefix='_py_', ignore='_'):
+ """Try import all public attributes from module into global namespace.
+
+ Existing attributes with name clashes are renamed with prefix.
+ Attributes starting with underscore are ignored by default.
+
+ Return True on successful import.
+
+ """
+ try:
+ module = __import__(module_name)
+ except ImportError:
+ if warn:
+ warnings.warn("Failed to import module " + module_name)
+ else:
+ for attr in dir(module):
+ if ignore and attr.startswith(ignore):
+ continue
+ if prefix:
+ if attr in globals():
+ globals()[prefix + attr] = globals()[attr]
+ elif warn:
+ warnings.warn("No Python implementation of " + attr)
+ globals()[attr] = getattr(module, attr)
+ return True
diff --git a/libs/assimp/port/PyAssimp/setup.py b/libs/assimp/port/PyAssimp/setup.py
new file mode 100644
index 0000000..a3497d6
--- /dev/null
+++ b/libs/assimp/port/PyAssimp/setup.py
@@ -0,0 +1,26 @@
+ #!/usr/bin/env python
+ # -*- coding: utf-8 -*-
+import os
+from distutils.core import setup
+
+def readme():
+ with open('README.rst') as f:
+ return f.read()
+
+setup(name='pyassimp',
+ version='4.1.4',
+ license='ISC',
+ description='Python bindings for the Open Asset Import Library (ASSIMP)',
+ long_description=readme(),
+ url='https://github.com/assimp/assimp',
+ author='ASSIMP developers',
+ author_email='assimp-discussions@lists.sourceforge.net',
+ maintainer='Séverin Lemaignan',
+ maintainer_email='severin@guakamole.org',
+ packages=['pyassimp'],
+ data_files=[
+ ('share/pyassimp', ['README.rst']),
+ ('share/examples/pyassimp', ['scripts/' + f for f in os.listdir('scripts/')])
+ ],
+ requires=['numpy']
+ )
diff --git a/libs/assimp/port/assimp_rs/Cargo.lock b/libs/assimp/port/assimp_rs/Cargo.lock
new file mode 100644
index 0000000..4f571f3
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/Cargo.lock
@@ -0,0 +1,6 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "assimp_rs"
+version = "0.1.0"
+
diff --git a/libs/assimp/port/assimp_rs/Cargo.toml b/libs/assimp/port/assimp_rs/Cargo.toml
new file mode 100644
index 0000000..073a2b2
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "assimp_rs"
+version = "0.1.0"
+authors = ["David Golembiowski <dmgolembiowski@gmail.com>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/libs/assimp/port/assimp_rs/src/camera/mod.rs b/libs/assimp/port/assimp_rs/src/camera/mod.rs
new file mode 100644
index 0000000..26ca118
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/camera/mod.rs
@@ -0,0 +1 @@
+pub use self::structs::{Camera};
diff --git a/libs/assimp/port/assimp_rs/src/core/mod.rs b/libs/assimp/port/assimp_rs/src/core/mod.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/core/mod.rs
diff --git a/libs/assimp/port/assimp_rs/src/errors/mod.rs b/libs/assimp/port/assimp_rs/src/errors/mod.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/errors/mod.rs
diff --git a/libs/assimp/port/assimp_rs/src/formats/mod.rs b/libs/assimp/port/assimp_rs/src/formats/mod.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/formats/mod.rs
diff --git a/libs/assimp/port/assimp_rs/src/lib.rs b/libs/assimp/port/assimp_rs/src/lib.rs
new file mode 100644
index 0000000..dbb6488
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/lib.rs
@@ -0,0 +1,17 @@
+pub mod camera;
+pub mod core;
+pub mod errors;
+pub mod formats;
+pub mod material;
+pub mod postprocess;
+pub mod shims;
+pub mod socket;
+pub mod structs;
+
+#[cfg(test)]
+mod tests {
+ #[test]
+ fn it_works() {
+ assert_eq!(true, true);
+ }
+}
diff --git a/libs/assimp/port/assimp_rs/src/material/mod.rs b/libs/assimp/port/assimp_rs/src/material/mod.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/material/mod.rs
diff --git a/libs/assimp/port/assimp_rs/src/postprocess/mod.rs b/libs/assimp/port/assimp_rs/src/postprocess/mod.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/postprocess/mod.rs
diff --git a/libs/assimp/port/assimp_rs/src/shims/mod.rs b/libs/assimp/port/assimp_rs/src/shims/mod.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/shims/mod.rs
diff --git a/libs/assimp/port/assimp_rs/src/socket/mod.rs b/libs/assimp/port/assimp_rs/src/socket/mod.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/socket/mod.rs
diff --git a/libs/assimp/port/assimp_rs/src/structs/anim/anim.rs b/libs/assimp/port/assimp_rs/src/structs/anim/anim.rs
new file mode 100644
index 0000000..5374151
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/anim/anim.rs
@@ -0,0 +1,44 @@
+pub struct Animation<'mA, 'mMA, 'nA> {
+ /* The name of the animation. If the modeling package this data was
+ * exported from does support only a single animation channel, this
+ * name is usually empty (length is zero).
+ */
+ m_name: Option<String>,
+ // Duration of the animation in ticks
+ m_duration: f64,
+ // Ticks per second. Zero (0.000... ticks/second) if not
+ // specified in the imported file
+ m_ticks_per_second: Option<f64>,
+ /* Number of bone animation channels.
+ Each channel affects a single node.
+ */
+ m_num_channels: u64,
+ /* Node animation channels. Each channel
+ affects a single node.
+ ?? -> The array is m_num_channels in size.
+ (maybe refine to a derivative type of usize?)
+ */
+ m_channels: &'nA NodeAnim,
+ /* Number of mesh animation channels. Each
+ channel affects a single mesh and defines
+ vertex-based animation.
+ */
+ m_num_mesh_channels: u64,
+ /* The mesh animation channels. Each channel
+ affects a single mesh.
+ The array is m_num_mesh_channels in size
+ (maybe refine to a derivative of usize?)
+ */
+ m_mesh_channels: &'mA MeshAnim,
+ /* The number of mesh animation channels. Each channel
+ affects a single mesh and defines some morphing animation.
+ */
+ m_num_morph_mesh_channels: u64,
+ /* The morph mesh animation channels. Each channel affects a single mesh.
+ The array is mNumMorphMeshChannels in size.
+ */
+ m_morph_mesh_channels: &'mMA MeshMorphAnim
+}
+pub struct NodeAnim {}
+pub struct MeshAnim {}
+pub struct MeshMorphAnim {}
diff --git a/libs/assimp/port/assimp_rs/src/structs/anim/mod.rs b/libs/assimp/port/assimp_rs/src/structs/anim/mod.rs
new file mode 100644
index 0000000..a0d4b7d
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/anim/mod.rs
@@ -0,0 +1,6 @@
+mod anim;
+pub use self::anim::{
+ Animation,
+ NodeAnim,
+ MeshAnim,
+ MeshMorphAnim};
diff --git a/libs/assimp/port/assimp_rs/src/structs/blob/blob.rs b/libs/assimp/port/assimp_rs/src/structs/blob/blob.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/blob/blob.rs
diff --git a/libs/assimp/port/assimp_rs/src/structs/blob/mod.rs b/libs/assimp/port/assimp_rs/src/structs/blob/mod.rs
new file mode 100644
index 0000000..ad7612c
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/blob/mod.rs
@@ -0,0 +1,2 @@
+mod blob;
+
diff --git a/libs/assimp/port/assimp_rs/src/structs/bone/bone.rs b/libs/assimp/port/assimp_rs/src/structs/bone/bone.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/bone/bone.rs
diff --git a/libs/assimp/port/assimp_rs/src/structs/bone/mod.rs b/libs/assimp/port/assimp_rs/src/structs/bone/mod.rs
new file mode 100644
index 0000000..758a15a
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/bone/mod.rs
@@ -0,0 +1,2 @@
+mod bone;
+
diff --git a/libs/assimp/port/assimp_rs/src/structs/camera/camera.rs b/libs/assimp/port/assimp_rs/src/structs/camera/camera.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/camera/camera.rs
diff --git a/libs/assimp/port/assimp_rs/src/structs/camera/mod.rs b/libs/assimp/port/assimp_rs/src/structs/camera/mod.rs
new file mode 100644
index 0000000..d4d79d0
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/camera/mod.rs
@@ -0,0 +1,2 @@
+mod camera;
+
diff --git a/libs/assimp/port/assimp_rs/src/structs/color/color.rs b/libs/assimp/port/assimp_rs/src/structs/color/color.rs
new file mode 100644
index 0000000..0b5fc64
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/color/color.rs
@@ -0,0 +1,27 @@
+#[derive(Clone, Debug, Copy)]
+struct Color3D {
+ r: f32,
+ g: f32,
+ b: f32
+}
+
+impl Color3D {
+ pub fn new(r_f32: f32, g_f32: f32, b_f32: f32) -> Color3D {
+ Color3D {r: r_f32, g: g_f32, b: b_f32 }
+ }
+}
+
+#[derive(Clone, Debug, Copy)]
+struct Color4D {
+ r: f32,
+ g: f32,
+ b: f32,
+ a: f32
+}
+
+impl Color4D {
+ pub fn new(r_f32: f32, g_f32: f32, b_f32: f32, a_f32: f32) -> Color4D {
+ Color4D {r: r_f32, g: g_f32, b: b_f32, a: a_f32 }
+ }
+}
+
diff --git a/libs/assimp/port/assimp_rs/src/structs/color/mod.rs b/libs/assimp/port/assimp_rs/src/structs/color/mod.rs
new file mode 100644
index 0000000..d88527e
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/color/mod.rs
@@ -0,0 +1,5 @@
+mod color;
+pub use self::color::{
+ Color3D,
+ Color4D
+};
diff --git a/libs/assimp/port/assimp_rs/src/structs/face/face.rs b/libs/assimp/port/assimp_rs/src/structs/face/face.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/face/face.rs
diff --git a/libs/assimp/port/assimp_rs/src/structs/face/mod.rs b/libs/assimp/port/assimp_rs/src/structs/face/mod.rs
new file mode 100644
index 0000000..ae5aa5b
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/face/mod.rs
@@ -0,0 +1,2 @@
+mod face;
+
diff --git a/libs/assimp/port/assimp_rs/src/structs/key/key.rs b/libs/assimp/port/assimp_rs/src/structs/key/key.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/key/key.rs
diff --git a/libs/assimp/port/assimp_rs/src/structs/key/mod.rs b/libs/assimp/port/assimp_rs/src/structs/key/mod.rs
new file mode 100644
index 0000000..b23779d
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/key/mod.rs
@@ -0,0 +1,2 @@
+mod key;
+
diff --git a/libs/assimp/port/assimp_rs/src/structs/light/light.rs b/libs/assimp/port/assimp_rs/src/structs/light/light.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/light/light.rs
diff --git a/libs/assimp/port/assimp_rs/src/structs/light/mod.rs b/libs/assimp/port/assimp_rs/src/structs/light/mod.rs
new file mode 100644
index 0000000..a68b519
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/light/mod.rs
@@ -0,0 +1,2 @@
+mod light;
+
diff --git a/libs/assimp/port/assimp_rs/src/structs/material/material.rs b/libs/assimp/port/assimp_rs/src/structs/material/material.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/material/material.rs
diff --git a/libs/assimp/port/assimp_rs/src/structs/material/mod.rs b/libs/assimp/port/assimp_rs/src/structs/material/mod.rs
new file mode 100644
index 0000000..54de8b3
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/material/mod.rs
@@ -0,0 +1,2 @@
+mod material;
+
diff --git a/libs/assimp/port/assimp_rs/src/structs/matrix/matrix.rs b/libs/assimp/port/assimp_rs/src/structs/matrix/matrix.rs
new file mode 100644
index 0000000..4673b2d
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/matrix/matrix.rs
@@ -0,0 +1,64 @@
+#[derive(Clone, Debug, Copy)]
+struct Matrix3x3 {
+ a1: f32,
+ a2: f32,
+ a3: f32,
+ b1: f32,
+ b2: f32,
+ b3: f32,
+ c1: f32,
+ c2: f32,
+ c3: f32
+}
+
+#[derive(Clone, Debug, Copy)]
+struct Matrix4x4 {
+ a1: f32,
+ a2: f32,
+ a3: f32,
+ a4: f32,
+ b1: f32,
+ b2: f32,
+ b3: f32,
+ b4: f32,
+ c1: f32,
+ c2: f32,
+ c3: f32,
+ c4: f32,
+ d1: f32,
+ d2: f32,
+ d3: f32,
+ d4: f32
+}
+
+impl Matrix3x3 {
+ pub fn new(
+ a1_f32: f32, a2_f32: f32, a3_f32: f32,
+ b1_f32: f32, b2_f32: f32, b3_f32: f32,
+ c1_f32: f32, c2_f32: f32, c3_f32: f32
+ ) -> Matrix3x3 {
+ Matrix3x3 {
+ a1: a1_f32, a2: a2_f32, a3: a3_f32,
+ b1: b1_f32, b2: b2_f32, b3: b3_f32,
+ c1: c1_f32, c2: c2_f32, c3: c3_f32
+ }
+ }
+}
+
+impl Matrix4x4 {
+ pub fn new(
+ a1_f32: f32, a2_f32: f32, a3_f32: f32, a4_f32: f32,
+ b1_f32: f32, b2_f32: f32, b3_f32: f32, b4_f32: f32,
+ c1_f32: f32, c2_f32: f32, c3_f32: f32, c4_f32: f32,
+ d1_f32: f32, d2_f32: f32, d3_f32: f32, d4_f32: f32
+ ) -> Matrix4x4 {
+ Matrix4x4 {
+ a1: a1_f32, a2: a2_f32, a3: a3_f32, a4: a4_f32,
+ b1: b1_f32, b2: b2_f32, b3: b3_f32, b4: b4_f32,
+ c1: c1_f32, c2: c2_f32, c3: c3_f32, c4: c4_f32,
+ d1: d1_f32, d2: d2_f32, d3: d3_f32, d4: d4_f32
+ }
+ }
+}
+
+
diff --git a/libs/assimp/port/assimp_rs/src/structs/matrix/mod.rs b/libs/assimp/port/assimp_rs/src/structs/matrix/mod.rs
new file mode 100644
index 0000000..b0fb1e1
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/matrix/mod.rs
@@ -0,0 +1,4 @@
+mod matrix;
+pub use self::matrix::{
+ Matrix3x3,
+ Matrix4x4};
diff --git a/libs/assimp/port/assimp_rs/src/structs/memory/memory.rs b/libs/assimp/port/assimp_rs/src/structs/memory/memory.rs
new file mode 100644
index 0000000..c076f17
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/memory/memory.rs
@@ -0,0 +1,35 @@
+#[derive(Clone, Debug, Copy)]
+struct MemoryInfo {
+ textures: u32,
+ materials: u32,
+ meshes: u32,
+ nodes: u32,
+ animations: u32,
+ cameras: u32,
+ lights: u32,
+ total: u32
+}
+
+impl MemoryInfo {
+ pub fn new(
+ textures_uint: u32,
+ materials_uint: u32,
+ meshes_uint: u32,
+ nodes_uint: u32,
+ animations_uint: u32,
+ cameras_uint: u32,
+ lights_uint: u32,
+ total_uint: u32) -> MemoryInfo {
+
+ MemoryInfo {
+ textures: textures_uint,
+ materials: materials_uint,
+ meshes: meshes_uint,
+ nodes: nodes_uint,
+ animations: animations_uint,
+ cameras: cameras_uint,
+ lights: lights_uint,
+ total: total_uint
+ }
+ }
+}
diff --git a/libs/assimp/port/assimp_rs/src/structs/memory/mod.rs b/libs/assimp/port/assimp_rs/src/structs/memory/mod.rs
new file mode 100644
index 0000000..8c8c31c
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/memory/mod.rs
@@ -0,0 +1,2 @@
+mod memory;
+pub use self::memory::MemoryInfo;
diff --git a/libs/assimp/port/assimp_rs/src/structs/mesh/mesh.rs b/libs/assimp/port/assimp_rs/src/structs/mesh/mesh.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/mesh/mesh.rs
diff --git a/libs/assimp/port/assimp_rs/src/structs/mesh/mod.rs b/libs/assimp/port/assimp_rs/src/structs/mesh/mod.rs
new file mode 100644
index 0000000..1c3ef65
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/mesh/mod.rs
@@ -0,0 +1,3 @@
+mod mesh;
+
+
diff --git a/libs/assimp/port/assimp_rs/src/structs/meta/meta.rs b/libs/assimp/port/assimp_rs/src/structs/meta/meta.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/meta/meta.rs
diff --git a/libs/assimp/port/assimp_rs/src/structs/meta/mod.rs b/libs/assimp/port/assimp_rs/src/structs/meta/mod.rs
new file mode 100644
index 0000000..0452947
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/meta/mod.rs
@@ -0,0 +1,2 @@
+mod meta;
+
diff --git a/libs/assimp/port/assimp_rs/src/structs/mod.rs b/libs/assimp/port/assimp_rs/src/structs/mod.rs
new file mode 100644
index 0000000..fd90876
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/mod.rs
@@ -0,0 +1,61 @@
+mod anim;
+/* Animation
+ * NodeAnim
+ * MeshAnim
+ * MeshMorphAnim
+ */
+mod blob;
+/* ExportDataBlob
+ */
+mod vec;
+/* Vector2d
+ * Vector3d
+ * */
+mod matrix;
+/* Matrix3by3
+ * Matrix4by4
+ */
+mod camera;
+/* Camera */
+mod color;
+/* Color3d
+ * Color4d
+ */
+mod key;
+/* MeshKey
+ * MeshMorphKey
+ * QuatKey
+ * VectorKey
+ */
+mod texel;
+mod plane;
+mod string;
+/* String
+ */
+mod material;
+/* Material
+ * MaterialPropery
+ * MaterialPropertyString
+ */
+mod mem;
+mod quaternion;
+mod face;
+mod vertex_weight;
+mod mesh;
+/* Mesh
+ */
+mod meta;
+/* Metadata
+ * MetadataEntry
+ */
+mod node;
+/* Node
+ * */
+mod light;
+mod texture;
+mod ray;
+mod transform;
+/* UVTransform */
+mod bone;
+mod scene;
+/* Scene */
diff --git a/libs/assimp/port/assimp_rs/src/structs/node/mod.rs b/libs/assimp/port/assimp_rs/src/structs/node/mod.rs
new file mode 100644
index 0000000..c1fc34c
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/node/mod.rs
@@ -0,0 +1,2 @@
+mod node;
+
diff --git a/libs/assimp/port/assimp_rs/src/structs/node/node.rs b/libs/assimp/port/assimp_rs/src/structs/node/node.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/node/node.rs
diff --git a/libs/assimp/port/assimp_rs/src/structs/plane/mod.rs b/libs/assimp/port/assimp_rs/src/structs/plane/mod.rs
new file mode 100644
index 0000000..c73a8ed
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/plane/mod.rs
@@ -0,0 +1,2 @@
+mod plane;
+
diff --git a/libs/assimp/port/assimp_rs/src/structs/plane/plane.rs b/libs/assimp/port/assimp_rs/src/structs/plane/plane.rs
new file mode 100644
index 0000000..2b0b744
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/plane/plane.rs
@@ -0,0 +1,23 @@
+#[derive(Clone, Debug, Copy)]
+struct Plane {
+ a: f32,
+ b: f32,
+ c: f32,
+ d: f32
+}
+
+impl Plane {
+ pub fn new(
+ a_f32: f32,
+ b_f32: f32,
+ c_f32: f32,
+ d_f32: f32
+ ) -> Plane {
+ Plane {
+ a: a_f32,
+ b: b_f32,
+ c: b_f32,
+ d: d_f32
+ }
+ }
+}
diff --git a/libs/assimp/port/assimp_rs/src/structs/quaternion/mod.rs b/libs/assimp/port/assimp_rs/src/structs/quaternion/mod.rs
new file mode 100644
index 0000000..bb2c061
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/quaternion/mod.rs
@@ -0,0 +1,3 @@
+mod quaternion;
+
+pub use self::quaternion::Quaternion;
diff --git a/libs/assimp/port/assimp_rs/src/structs/quaternion/quaternion.rs b/libs/assimp/port/assimp_rs/src/structs/quaternion/quaternion.rs
new file mode 100644
index 0000000..970f5cc
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/quaternion/quaternion.rs
@@ -0,0 +1,7 @@
+use crate::vec;
+
+#[derive(Clone, Debug, Copy)]
+pub struct Quaternion {
+ _coordinates: vec::Vector4d
+
+}
diff --git a/libs/assimp/port/assimp_rs/src/structs/ray/mod.rs b/libs/assimp/port/assimp_rs/src/structs/ray/mod.rs
new file mode 100644
index 0000000..7f0be07
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/ray/mod.rs
@@ -0,0 +1,2 @@
+mod ray;
+
diff --git a/libs/assimp/port/assimp_rs/src/structs/ray/ray.rs b/libs/assimp/port/assimp_rs/src/structs/ray/ray.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/ray/ray.rs
diff --git a/libs/assimp/port/assimp_rs/src/structs/scene/mod.rs b/libs/assimp/port/assimp_rs/src/structs/scene/mod.rs
new file mode 100644
index 0000000..5aea638
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/scene/mod.rs
@@ -0,0 +1,2 @@
+mod scene;
+
diff --git a/libs/assimp/port/assimp_rs/src/structs/scene/scene.rs b/libs/assimp/port/assimp_rs/src/structs/scene/scene.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/scene/scene.rs
diff --git a/libs/assimp/port/assimp_rs/src/structs/string/mod.rs b/libs/assimp/port/assimp_rs/src/structs/string/mod.rs
new file mode 100644
index 0000000..f599ba7
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/string/mod.rs
@@ -0,0 +1,3 @@
+mod string;
+pub use self::string::MAXLEN;
+pub use self::string::Str;
diff --git a/libs/assimp/port/assimp_rs/src/structs/string/string.rs b/libs/assimp/port/assimp_rs/src/structs/string/string.rs
new file mode 100644
index 0000000..b88457d
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/string/string.rs
@@ -0,0 +1,41 @@
+pub const MAXLEN: usize = 1024;
+
+/// Want to consider replacing `Vec<char>`
+/// with a comparable definition at
+/// https://doc.rust-lang.org/src/alloc/string.rs.html#415-417
+#[derive(Clone, Debug)]
+struct Str {
+ length: usize,
+ data: Vec<char>
+}
+
+impl Str {
+ pub fn new(len_u32: usize, data_string: String) -> Str {
+ Str {
+ length: len_u32,
+ data: data_string.chars().collect()
+ }
+ }
+}
+
+/// MaterialPropertyStr
+/// The size of length is truncated to 4 bytes on a 64-bit platform when used as a
+/// material property (see MaterialSystem.cpp, as aiMaterial::AddProperty() ).
+#[derive(Clone, Debug)]
+struct MaterialPropertyStr {
+ length: usize,
+ data: Vec<char>
+}
+
+
+impl MaterialPropertyStr {
+ pub fn new(len_u32: usize, data_string: String) -> MaterialPropertyStr {
+ MaterialPropertyStr {
+ length: len_u32,
+ data: data_string.chars().collect()
+ }
+ }
+}
+
+
+
diff --git a/libs/assimp/port/assimp_rs/src/structs/texture/mod.rs b/libs/assimp/port/assimp_rs/src/structs/texture/mod.rs
new file mode 100644
index 0000000..1b5c930
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/texture/mod.rs
@@ -0,0 +1,3 @@
+mod texture;
+pub use self::texture::Texel;
+
diff --git a/libs/assimp/port/assimp_rs/src/structs/texture/texture.rs b/libs/assimp/port/assimp_rs/src/structs/texture/texture.rs
new file mode 100644
index 0000000..b2c72f3
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/texture/texture.rs
@@ -0,0 +1,19 @@
+#[derive(Clone, Debug, Copy)]
+struct Texel {
+ b: u32,
+ g: u32,
+ r: u32,
+ a: u32
+}
+
+impl Texel {
+ pub fn new(b_u32: u32, g_u32: u32,
+ r_u32: u32, a_u32: u32) -> Texel {
+ Texel {
+ b: b_u32,
+ g: g_u32,
+ r: r_u32,
+ a: a_u32
+ }
+ }
+}
diff --git a/libs/assimp/port/assimp_rs/src/structs/transform/mod.rs b/libs/assimp/port/assimp_rs/src/structs/transform/mod.rs
new file mode 100644
index 0000000..b80c43d
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/transform/mod.rs
@@ -0,0 +1,2 @@
+mod transform;
+
diff --git a/libs/assimp/port/assimp_rs/src/structs/transform/transform.rs b/libs/assimp/port/assimp_rs/src/structs/transform/transform.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/transform/transform.rs
diff --git a/libs/assimp/port/assimp_rs/src/structs/vec/mod.rs b/libs/assimp/port/assimp_rs/src/structs/vec/mod.rs
new file mode 100644
index 0000000..3613d5d
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/vec/mod.rs
@@ -0,0 +1,2 @@
+mod vec;
+
diff --git a/libs/assimp/port/assimp_rs/src/structs/vec/vec.rs b/libs/assimp/port/assimp_rs/src/structs/vec/vec.rs
new file mode 100644
index 0000000..ee0d194
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/vec/vec.rs
@@ -0,0 +1,48 @@
+struct Vector2d {
+ x: f32,
+ y: f32
+}
+
+struct Vector3d {
+ x: f32,
+ y: f32,
+ z: f32
+}
+
+struct Vector4d {
+ x: f32,
+ y: f32,
+ z: f32,
+ w: f32
+}
+
+impl Vector2d {
+ pub fn new(x_f32: f32, y_f32: f32) -> Vector2d {
+ Vector2d {
+ x: x_f32,
+ y: y_f32
+ }
+ }
+}
+
+impl Vector3d {
+ pub fn new(x_f32: f32, y_f32: f32, z_f32: f32) -> Vector3d {
+ Vector3d {
+ x: x_f32,
+ y: y_f32,
+ z: z_f32
+ }
+ }
+}
+
+impl Vector4d {
+ pub fn new(x_f32: f32, y_f32: f32, z_f32: f32, w_f32: f32) -> Vector4d {
+ Vector4d {
+ x: x_f32,
+ y: y_f32,
+ z: z_f32,
+ w: w_f32
+ }
+ }
+}
+
diff --git a/libs/assimp/port/assimp_rs/src/structs/vertex/mod.rs b/libs/assimp/port/assimp_rs/src/structs/vertex/mod.rs
new file mode 100644
index 0000000..97ae3ec
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/vertex/mod.rs
@@ -0,0 +1,2 @@
+mod vertex;
+// pub use self::vertex::
diff --git a/libs/assimp/port/assimp_rs/src/structs/vertex/vertex.rs b/libs/assimp/port/assimp_rs/src/structs/vertex/vertex.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libs/assimp/port/assimp_rs/src/structs/vertex/vertex.rs
diff --git a/libs/assimp/port/dAssimp/README b/libs/assimp/port/dAssimp/README
new file mode 100644
index 0000000..af82cb1
--- /dev/null
+++ b/libs/assimp/port/dAssimp/README
@@ -0,0 +1,13 @@
+D bindings for the Assimp library (http://assimp.sf.net).
+---
+
+These bindings provide access to Assimp's C API. They were directly created
+from the C header files.
+
+You should be able to create sufficient DDoc documentation for the bindings
+using your favourite build tool (such as Rebuild). Please refer to the main
+(Doxygen-generated) documentation for general topics.
+
+Please note that the bindings have only been tested on 32 bit systems, they have
+yet to be adapted for the different size of the integer types in 64 bit builds
+of Assimp.
diff --git a/libs/assimp/port/dAssimp/assimp/animation.d b/libs/assimp/port/dAssimp/assimp/animation.d
new file mode 100644
index 0000000..9a36940
--- /dev/null
+++ b/libs/assimp/port/dAssimp/assimp/animation.d
@@ -0,0 +1,240 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, ASSIMP Development 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 Development 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.
+---------------------------------------------------------------------------
+*/
+
+/**
+ * The data structures which are used to store the imported animation data.
+ */
+module assimp.animation;
+
+import assimp.math;
+import assimp.types;
+
+extern ( C ) {
+ /**
+ * A time-value pair specifying a certain 3D vector for the given time.
+ */
+ struct aiVectorKey {
+ /**
+ * The time of this key.
+ */
+ double mTime;
+
+ /**
+ * The value of this key.
+ */
+ aiVector3D mValue;
+ }
+
+ /**
+ * A time-value pair specifying a rotation for the given time. For joint
+ * animations, the rotation is usually expressed using a quaternion.
+ */
+ struct aiQuatKey {
+ /**
+ * The time of this key.
+ */
+ double mTime;
+
+ /**
+ * The value of this key.
+ */
+ aiQuaternion mValue;
+ }
+
+ /**
+ * Defines how an animation channel behaves outside the defined time
+ * range. This corresponds to <code>aiNodeAnim.mPreState</code> and
+ * <code>aiNodeAnim.mPostState</code>.
+ */
+ enum aiAnimBehaviour : uint {
+ /**
+ * The value from the default node transformation is used.
+ */
+ DEFAULT = 0x0,
+
+ /**
+ * The nearest key value is used without interpolation.
+ */
+ CONSTANT = 0x1,
+
+ /**
+ * The value of the nearest two keys is linearly extrapolated for the
+ * current time value.
+ */
+ LINEAR = 0x2,
+
+ /**
+ * The animation is repeated.
+ *
+ * If the animation key go from n to m and the current time is t, use the
+ * value at (t-n) % (|m-n|).
+ */
+ REPEAT = 0x3
+ }
+
+ /**
+ * Describes the animation of a single node.
+ *
+ * The name specifies the bone/node which is affected by this animation
+ * channel. The keyframes are given in three separate series of values, one
+ * each for position, rotation and scaling. The transformation matrix
+ * computed from these values replaces the node's original transformation
+ * matrix at a specific time. This means all keys are absolute and not
+ * relative to the bone default pose.
+ *
+ * The order in which the transformations are applied is –
+ * as usual – scaling, rotation, translation.
+ *
+ * Note: All keys are returned in their correct, chronological order.
+ * Duplicate keys don't pass the validation step. Most likely there will
+ * be no negative time values, but they are not forbidden (so
+ * implementations need to cope with them!).
+ */
+ struct aiNodeAnim {
+ /**
+ * The name of the node affected by this animation. The node must exist
+ * and it must be unique.
+ */
+ aiString mNodeName;
+
+ /**
+ * The number of position keys.
+ */
+ uint mNumPositionKeys;
+
+ /**
+ * The position keys of this animation channel. Positions are specified
+ * as 3D vectors. The array is <code>mNumPositionKeys</code> in size.
+ *
+ * If there are position keys, there will also be at least one scaling
+ * and one rotation key.
+ */
+ aiVectorKey* mPositionKeys;
+
+ /**
+ * The number of rotation keys.
+ */
+ uint mNumRotationKeys;
+
+ /**
+ * The rotation keys of this animation channel. Rotations are given as
+ * quaternions. The array is <code>mNumRotationKeys</code> in size.
+ *
+ * If there are rotation keys, there will also be at least one scaling
+ * and one position key.
+ */
+ aiQuatKey* mRotationKeys;
+
+
+ /**
+ * The number of scaling keys.
+ */
+ uint mNumScalingKeys;
+
+ /**
+ * The scaling keys of this animation channel. Scalings are specified as
+ * 3D vectors. The array is <code>mNumScalingKeys</code> in size.
+ *
+ * If there are scaling keys, there will also be at least one position
+ * and one rotation key.
+ */
+ aiVectorKey* mScalingKeys;
+
+
+ /**
+ * Defines how the animation behaves before the first key is encountered.
+ *
+ * The default value is <code>aiAnimBehaviour.DEFAULT</code> (the original
+ * transformation matrix of the affected node is used).
+ */
+ aiAnimBehaviour mPreState;
+
+ /**
+ * Defines how the animation behaves after the last key was processed.
+ *
+ * The default value is <code>aiAnimBehaviour.DEFAULT</code> (the original
+ * transformation matrix of the affected node is used).
+ */
+ aiAnimBehaviour mPostState;
+ }
+
+ /**
+ * An animation consists of keyframe data for a number of nodes.
+ *
+ * For each node affected by the animation, a separate series of data is
+ * given.
+ */
+ struct aiAnimation {
+ /**
+ * The name of the animation.
+ *
+ * If the modeling package this data was
+ * exported from does support only a single animation channel, this
+ * name is usually empty (length is zero).
+ */
+ aiString mName;
+
+ /**
+ * Duration of the animation in ticks.
+ */
+ double mDuration;
+
+ /**
+ * Ticks per second. 0 if not specified in the imported file.
+ */
+ double mTicksPerSecond;
+
+ /**
+ * The number of bone animation channels.
+ *
+ * Each channel affects a single node.
+ */
+ uint mNumChannels;
+
+ /**
+ * The node animation channels. The array is <code>mNumChannels</code>
+ * in size.
+ *
+ * Each channel affects a single node.
+ */
+ aiNodeAnim** mChannels;
+ }
+} \ No newline at end of file
diff --git a/libs/assimp/port/dAssimp/assimp/api.d b/libs/assimp/port/dAssimp/assimp/api.d
new file mode 100644
index 0000000..bc7a157
--- /dev/null
+++ b/libs/assimp/port/dAssimp/assimp/api.d
@@ -0,0 +1,686 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, ASSIMP Development 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 Development 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.
+---------------------------------------------------------------------------
+*/
+
+/**
+ * The C-style interface to the Open Asset import library.
+ *
+ * All functions of the C API have been collected in this module as function
+ * pointers, which are set by the dynamic library loader
+ * (<code>assimp.loader</code>).
+ */
+module assimp.api;
+
+import assimp.fileIO;
+import assimp.material;
+import assimp.math;
+import assimp.scene;
+import assimp.types;
+
+extern ( C ) {
+ /**
+ * Reads the given file and returns its content.
+ *
+ * If the call succeeds, the imported data is returned in an <code>aiScene</code>
+ * structure. The data is intended to be read-only, it stays property of the
+ * Assimp library and will be stable until <code>aiReleaseImport()</code> is
+ * called. After you're done with it, call <code>aiReleaseImport()</code> to
+ * free the resources associated with this file.
+ *
+ * If an error is encountered, null is returned instead. Call
+ * <code>aiGetErrorString()</code> to retrieve a human-readable error
+ * description.
+ *
+ * Params:
+ * pFile = Path and filename of the file to be imported,
+ * expected to be a null-terminated C-string. null is not a valid value.
+ * pFlags = Optional post processing steps to be executed after a
+ * successful import. Provide a bitwise combination of the
+ * <code>aiPostProcessSteps</code> flags. If you wish to inspect the
+ * imported scene first in order to fine-tune your post-processing
+ * setup, consider to use <code>aiApplyPostProcessing()</code>.
+ *
+ * Returns:
+ * A pointer to the imported data, null if the import failed.
+ */
+ aiScene* function( char* pFile, uint pFile ) aiImportFile;
+
+ /**
+ * Reads the given file using user-defined I/O functions and returns its
+ * content.
+ *
+ * If the call succeeds, the imported data is returned in an <code>aiScene</code>
+ * structure. The data is intended to be read-only, it stays property of the
+ * Assimp library and will be stable until <code>aiReleaseImport()</code> is
+ * called. After you're done with it, call <code>aiReleaseImport()</code> to
+ * free the resources associated with this file.
+ *
+ * If an error is encountered, null is returned instead. Call
+ * <code>aiGetErrorString()</code> to retrieve a human-readable error
+ * description.
+ *
+ * Params:
+ * pFile = Path and filename of the file to be imported,
+ * expected to be a null-terminated C-string. null is not a valid value.
+ * pFlags = Optional post processing steps to be executed after a
+ * successful import. Provide a bitwise combination of the
+ * <code>aiPostProcessSteps</code> flags. If you wish to inspect the
+ * imported scene first in order to fine-tune your post-processing
+ * setup, consider to use <code>aiApplyPostProcessing()</code>.
+ * pFS = An aiFileIO which will be used to open the model file itself
+ * and any other files the loader needs to open.
+ *
+ * Returns:
+ * A pointer to the imported data, null if the import failed.
+ */
+ aiScene* function( char* pFile, uint pFlags, aiFileIO* pFS ) aiImportFileEx;
+
+ /**
+ * Reads the scene from the given memory buffer.
+ *
+ * Reads the given file using user-defined I/O functions and returns its
+ * content.
+ *
+ * If the call succeeds, the imported data is returned in an <code>aiScene</code>
+ * structure. The data is intended to be read-only, it stays property of the
+ * Assimp library and will be stable until <code>aiReleaseImport()</code> is
+ * called. After you're done with it, call <code>aiReleaseImport()</code> to
+ * free the resources associated with this file.
+ *
+ * If an error is encountered, null is returned instead. Call
+ * <code>aiGetErrorString()</code> to retrieve a human-readable error
+ * description.
+ *
+ * Params:
+ * pBuffer = Pointer to the scene data.
+ * pLength = Size of pBuffer in bytes.
+ * pFlags = Optional post processing steps to be executed after a
+ * successful import. Provide a bitwise combination of the
+ * <code>aiPostProcessSteps</code> flags. If you wish to inspect the
+ * imported scene first in order to fine-tune your post-processing
+ * setup, consider to use <code>aiApplyPostProcessing()</code>.
+ * pHint = An additional hint to the library. If this is a non empty
+ * string, the library looks for a loader to support the file
+ * extension specified and passes the file to the first matching
+ * loader. If this loader is unable to complete the request, the
+ * library continues and tries to determine the file format on its
+ * own, a task that may or may not be successful.
+ *
+ * Returns:
+ * A pointer to the imported data, null if the import failed.
+ *
+ * Note:
+ * This is a straightforward way to decode models from memory buffers,
+ * but it doesn't handle model formats spreading their data across
+ * multiple files or even directories. Examples include OBJ or MD3, which
+ * outsource parts of their material stuff into external scripts. If you
+ * need the full functionality, provide a custom IOSystem to make Assimp
+ * find these files.
+ */
+ aiScene* function(
+ char* pBuffer,
+ uint pLength,
+ uint pFlags,
+ char* pHint
+ ) aiImportFileFromMemory;
+
+ /**
+ * Apply post-processing to an already-imported scene.
+ *
+ * This is strictly equivalent to calling <code>aiImportFile()</code> or
+ * <code>aiImportFileEx()</code> with the same flags. However, you can use
+ * this separate function to inspect the imported scene first to fine-tune
+ * your post-processing setup.
+ *
+ * Params:
+ * pScene = Scene to work on.
+ * pFlags = Provide a bitwise combination of the
+ * <code>aiPostProcessSteps</code> flags.
+ *
+ * Returns:
+ * A pointer to the post-processed data. Post processing is done in-place,
+ * meaning this is still the same <code>aiScene</code> which you passed
+ * for pScene. However, if post-processing failed, the scene could now be
+ * null. That's quite a rare case, post processing steps are not really
+ * designed to fail. To be exact, <code>aiProcess.ValidateDS</code> is
+ * currently the only post processing step which can actually cause the
+ * scene to be reset to null.
+ */
+ aiScene* function( aiScene* pScene, uint pFlags ) aiApplyPostProcessing;
+
+ /**
+ * Get one of the predefined log streams. This is the quick'n'easy solution
+ * to access Assimp's log system. Attaching a log stream can slightly reduce
+ * Assimp's overall import performance.
+ *
+ * Examples:
+ * ---
+ * aiLogStream stream = aiGetPredefinedLogStream(
+ * aiDefaultLogStream.FILE, "assimp.log.txt" );
+ * if ( stream.callback !is null ) {
+ * aiAttachLogStream( &stream );
+ * }
+ * ---
+ *
+ * Params:
+ * pStreams = The log stream destination.
+ * file = Solely for the <code>aiDefaultLogStream.FILE</code> flag:
+ * specifies the file to write to. Pass null for all other flags.
+ *
+ * Returns:
+ * The log stream, null if something went wrong.
+ */
+ aiLogStream function( aiDefaultLogStream pStreams, char* file ) aiGetPredefinedLogStream;
+
+ /**
+ * Attach a custom log stream to the libraries' logging system.
+ *
+ * Attaching a log stream can slightly reduce Assimp's overall import
+ * performance. Multiple log-streams can be attached.
+ *
+ * Params:
+ * stream = Describes the new log stream.
+ *
+ * Note: To ensure proper destruction of the logging system, you need to
+ * manually call <code>aiDetachLogStream()</code> on every single log
+ * stream you attach. Alternatively, <code>aiDetachAllLogStreams()</code>
+ * is provided.
+ */
+ void function( aiLogStream* stream ) aiAttachLogStream;
+
+ /**
+ * Enable verbose logging.
+ *
+ * Verbose logging includes debug-related stuff and detailed import
+ * statistics. This can have severe impact on import performance and memory
+ * consumption. However, it might be useful to find out why a file is not
+ * read correctly.
+ *
+ * Param:
+ * d = Whether verbose logging should be enabled.
+ */
+ void function( aiBool d ) aiEnableVerboseLogging;
+
+ /**
+ * Detach a custom log stream from the libraries' logging system.
+ *
+ * This is the counterpart of #aiAttachPredefinedLogStream. If you attached a stream,
+ * don't forget to detach it again.
+ *
+ * Params:
+ * stream = The log stream to be detached.
+ *
+ * Returns:
+ * <code>aiReturn.SUCCESS</code> if the log stream has been detached
+ * successfully.
+ *
+ * See: <code>aiDetachAllLogStreams</code>
+ */
+ aiReturn function( aiLogStream* stream ) aiDetachLogStream;
+
+ /**
+ * Detach all active log streams from the libraries' logging system.
+ *
+ * This ensures that the logging system is terminated properly and all
+ * resources allocated by it are actually freed. If you attached a stream,
+ * don't forget to detach it again.
+ *
+ * See: <code>aiAttachLogStream</code>, <code>aiDetachLogStream</code>
+ */
+ void function() aiDetachAllLogStreams;
+
+ /**
+ * Releases all resources associated with the given import process.
+ *
+ * Call this function after you're done with the imported data.
+ *
+ * Params:
+ * pScene = The imported data to release. null is a valid value.
+ */
+ void function( aiScene* pScene ) aiReleaseImport;
+
+ /**
+ * Returns the error text of the last failed import process.
+ *
+ * Returns:
+ * A textual description of the error that occurred at the last importing
+ * process. null if there was no error. There can't be an error if you
+ * got a non-null <code>aiScene</code> from
+ * <code>aiImportFile()/aiImportFileEx()/aiApplyPostProcessing()</code>.
+ */
+ char* function() aiGetErrorString;
+
+ /**
+ * Returns whether a given file extension is supported by this Assimp build.
+ *
+ * Params:
+ * szExtension = Extension for which to query support. Must include a
+ * leading dot '.'. Example: ".3ds", ".md3"
+ *
+ * Returns:
+ * <code>TRUE</code> if the file extension is supported.
+ */
+ aiBool function( char* szExtension ) aiIsExtensionSupported;
+
+ /**
+ * Gets a list of all file extensions supported by ASSIMP.
+ *
+ * Format of the list: "*.3ds;*.obj;*.dae".
+ *
+ * If a file extension is contained in the list this does, of course, not
+ * mean that Assimp is able to load all files with this extension.
+ *
+ * Params:
+ * szOut = String to receive the extension list. null is not a valid
+ * parameter.
+ */
+ void function( aiString* szOut ) aiGetExtensionList;
+
+ /**
+ * Gets the storage required by an imported asset
+ *
+ * Params:
+ * pIn = Asset to query storage size for.
+ * info = Data structure to be filled.
+ */
+ void function( aiScene* pIn, aiMemoryInfo* info ) aiGetMemoryRequirements;
+
+ /**
+ * Sets an integer property.
+ *
+ * Properties are always shared by all imports. It is not possible to
+ * specify them per import.
+ *
+ * Params:
+ * szName = Name of the configuration property to be set. All supported
+ * public properties are defined in the <code>config</code> module.
+ * value = New value for the property.
+ */
+ void function( char* szName, int value ) aiSetImportPropertyInteger;
+
+ /**
+ * Sets a floating-point property.
+ *
+ * Properties are always shared by all imports. It is not possible to
+ * specify them per import.
+ *
+ * Params:
+ * szName = Name of the configuration property to be set. All supported
+ * public properties are defined in the <code>config</code> module.
+ * value = New value for the property.
+ */
+ void function( char* szName, float value ) aiSetImportPropertyFloat;
+
+ /**
+ * Sets a string property.
+ *
+ * Properties are always shared by all imports. It is not possible to
+ * specify them per import.
+ *
+ * Params:
+ * szName = Name of the configuration property to be set. All supported
+ * public properties are defined in the <code>config</code> module.
+ * st = New value for the property.
+ */
+ void function( char* szName, aiString* st ) aiSetImportPropertyString;
+
+
+ /*
+ * Mathematical helper functions.
+ */
+
+ /**
+ * Constructs a quaternion from a 3x3 rotation matrix.
+ *
+ * Params:
+ * quat = Receives the output quaternion.
+ * mat = Matrix to 'quaternionize'.
+ */
+ void function( aiQuaternion* quat, aiMatrix3x3* mat ) aiCreateQuaternionFromMatrix;
+
+ /**
+ * Decomposes a transformation matrix into its rotational, translational and
+ * scaling components.
+ *
+ * Params:
+ * mat = Matrix to decompose.
+ * scaling = Receives the scaling component.
+ * rotation = Receives the rotational component.
+ * position = Receives the translational component.
+ */
+ void function(
+ aiMatrix4x4* mat,
+ aiVector3D* scaling,
+ aiQuaternion* rotation,
+ aiVector3D* position
+ ) aiDecomposeMatrix;
+
+ /**
+ * Transposes a 4x4 matrix (in-place).
+ *
+ * Params:
+ * mat = The matrix to be transposed.
+ */
+ void function( aiMatrix4x4* mat ) aiTransposeMatrix4;
+
+ /**
+ * Transposes a 3x3 matrix (in-place).
+ *
+ * Params:
+ * mat = The matrix to be transposed.
+ */
+ void function( aiMatrix3x3* mat ) aiTransposeMatrix3;
+
+ /**
+ * Transforms a vector by a 3x3 matrix (in-place).
+ *
+ * Params:
+ * vec = Vector to be transformed.
+ * mat = Matrix to transform the vector with.
+ */
+ void function( aiVector3D* vec, aiMatrix3x3* mat ) aiTransformVecByMatrix3;
+
+ /**
+ * Transforms a vector by a 4x4 matrix (in-place).
+ *
+ * Params:
+ * vec = Vector to be transformed.
+ * mat = Matrix to transform the vector with.
+ */
+ void function( aiVector3D* vec, aiMatrix4x4* mat ) aiTransformVecByMatrix4;
+
+ /**
+ * Multiplies two 4x4 matrices.
+ *
+ * Params:
+ * dst = First factor, receives result.
+ * src = Matrix to be multiplied with 'dst'.
+ */
+ void function( aiMatrix4x4* dst, aiMatrix4x4* src ) aiMultiplyMatrix4;
+
+ /**
+ * Multiplies two 3x3 matrices.
+ *
+ * Params:
+ * dst = First factor, receives result.
+ * src = Matrix to be multiplied with 'dst'.
+ */
+ void function( aiMatrix3x3* dst, aiMatrix3x3* src ) aiMultiplyMatrix3;
+
+ /**
+ * Constructs a 3x3 identity matrix.
+ *
+ * Params:
+ * mat = Matrix to receive its personal identity.
+ */
+ void function( aiMatrix3x3* mat ) aiIdentityMatrix3;
+
+ /**
+ * Constructs a 4x4 identity matrix.
+ *
+ * Params:
+ * mat = Matrix to receive its personal identity.
+ */
+ void function( aiMatrix4x4* mat ) aiIdentityMatrix4;
+
+
+ /*
+ * Material system functions.
+ */
+
+ /**
+ * Retrieves a material property with a specific key from the material.
+ *
+ * Params:
+ * pMat = Pointer to the input material. May not be null.
+ * pKey = Key to search for. One of the <code>AI_MATKEY_XXX</code>
+ * constants.
+ * type = Specifies the <code>aiTextureType</code> of the texture to be
+ * retrieved, 0 for non-texture properties.
+ * index = Index of the texture to be retrieved,
+ * 0 for non-texture properties.
+ * pPropOut = Pointer to receive a pointer to a valid
+ * <code>aiMaterialProperty</code> structure or null if the key has
+ * not been found.
+ */
+ aiReturn function(
+ aiMaterial* pMat,
+ char* pKey,
+ uint type,
+ uint index,
+ aiMaterialProperty** pPropOut
+ ) aiGetMaterialProperty;
+
+ /**
+ * Retrieves a single float value or an array of float values from the
+ * material.
+ *
+ * Examples:
+ * ---
+ * const FLOATS_IN_UV_TRANSFORM = ( aiUVTransform.sizeof / float.sizeof );
+ * uint valuesRead = FLOATS_IN_UV_TRANSFORM;
+ * bool success =
+ * ( aiGetMaterialFloatArray( &material, AI_MATKEY_UVTRANSFORM,
+ * aiTextureType.DIFFUSE, 0, cast( float* ) &trafo, &valuesRead ) ==
+ * aiReturn.SUCCESS ) &&
+ * ( valuesRead == FLOATS_IN_UV_TRANSFORM );
+ * ---
+ *
+ * Params:
+ * pMat = Pointer to the input material. May not be null.
+ * pKey = Key to search for. One of the AI_MATKEY_XXX constants.
+ * type = Specifies the <code>aiTextureType</code> of the texture to be
+ * retrieved, 0 for non-texture properties.
+ * index = Index of the texture to be retrieved,
+ * 0 for non-texture properties.
+ * pOut = Pointer to a buffer to receive the result.
+ * pMax = Specifies the size of the given buffer in floats. Receives the
+ * number of values (not bytes!) read. null to read a scalar property.
+ *
+ * Returns:
+ * Specifies whether the key has been found. If not, the output arrays
+ * remains unmodified and pMax is set to 0.
+ */
+ aiReturn function(
+ aiMaterial* pMat,
+ char* pKey,
+ uint type,
+ uint index,
+ float* pOut,
+ uint* pMax = null
+ ) aiGetMaterialFloatArray;
+
+ /**
+ * Convenience alias for <code>aiGetMaterialFloatArray()</code>.
+ */
+ alias aiGetMaterialFloatArray aiGetMaterialFloat;
+
+ /**
+ * Retrieves a single integer value or an array of integer values from the
+ * material.
+ *
+ * See: <code>aiGetMaterialFloatArray()</code>
+ */
+ aiReturn function(
+ aiMaterial* pMat,
+ char* pKey,
+ uint type,
+ uint index,
+ int* pOut,
+ uint* pMax = null
+ ) aiGetMaterialIntegerArray;
+
+ /**
+ * Convenience alias for <code>aiGetMaterialIntegerArray()</code>.
+ */
+ alias aiGetMaterialIntegerArray aiGetMaterialInteger;
+
+ /**
+ * Retrieves a color value from the material.
+ *
+ * See: <code>aiGetMaterialFloatArray()</code>
+ */
+ aiReturn function(
+ aiMaterial* pMat,
+ char* pKey,
+ uint type,
+ uint index,
+ aiColor4D* pOut
+ ) aiGetMaterialColor;
+
+ /**
+ * Retrieves a string value from the material.
+ *
+ * See: <code>aiGetMaterialFloatArray()</code>
+ */
+ aiReturn function(
+ aiMaterial* pMat,
+ char* pKey,
+ uint type,
+ uint index,
+ aiString* pOut
+ ) aiGetMaterialString;
+
+ /**
+ * Get the number of textures for a particular texture type.
+ *
+ * Params:
+ * pMat = Pointer to the input material. May not be NULL
+ * type = Texture type to check for
+ *
+ * Returns:
+ * Number of textures for this type.
+ */
+ uint function( aiMaterial* pMat, aiTextureType type ) aiGetMaterialTextureCount;
+
+ /**
+ * Helper function to get all values pertaining to a particular texture slot
+ * from a material structure.
+ *
+ * This function is provided just for convenience. You could also read the
+ * texture by parsing all of its properties manually. This function bundles
+ * all of them in a huge function monster.
+ *
+ * Params:
+ * mat = Pointer to the input material. May not be null.
+ * type = Specifies the texture stack (<code>aiTextureType</code>) to
+ * read from.
+ * index = Index of the texture. The function fails if the requested
+ * index is not available for this texture type.
+ * <code>aiGetMaterialTextureCount()</code> can be used to determine
+ * the number of textures in a particular texture stack.
+ * path = Receives the output path. null is not a valid value.
+ * mapping = Receives the texture mapping mode to be used.
+ * Pass null if you are not interested in this information.
+ * uvindex = For UV-mapped textures: receives the index of the UV source
+ * channel. Unmodified otherwise. Pass null if you are not interested
+ * in this information.
+ * blend = Receives the blend factor for the texture.
+ * Pass null if you are not interested in this information.
+ * op = Receives the texture blend operation to be perform between this
+ * texture and the previous texture. Pass null if you are not
+ * interested in this information.
+ * mapmode = Receives the mapping modes to be used for the texture. Pass
+ * a pointer to an array of two aiTextureMapMode's (one for each axis,
+ * UV order) or null if you are not interested in this information.
+ *
+ * Returns:
+ * <code>aiReturn.SUCCESS</code> on success, otherwise something else.
+ */
+ aiReturn function(
+ aiMaterial* mat,
+ aiTextureType type,
+ uint index,
+ aiString* path,
+ aiTextureMapping* mapping = null,
+ uint* uvindex = null,
+ float* blend = null,
+ aiTextureOp* op = null,
+ aiTextureMapMode* mapmode = null
+ ) aiGetMaterialTexture;
+
+
+ /*
+ * Versioning functions.
+ */
+
+ /**
+ * Returns a string with legal copyright and licensing information about
+ * Assimp.
+ *
+ * The string may include multiple lines.
+ *
+ * Returns:
+ * Pointer to static string.
+ */
+ char* function() aiGetLegalString;
+
+ /**
+ * Returns the current minor version number of the Assimp library.
+ *
+ * Returns:
+ * Minor version of the Assimp library.
+ */
+ uint function() aiGetVersionMinor;
+
+ /**
+ * Returns the current major version number of the Assimp library.
+ *
+ * Returns:
+ * Major version of the Assimp library.
+ */
+ uint function() aiGetVersionMajor;
+
+ /**
+ * Returns the repository revision of the Assimp library.
+ *
+ * Returns:
+ * SVN Repository revision number of the Assimp library.
+ */
+ uint function() aiGetVersionRevision;
+
+ /**
+ * Returns the flags Assimp was compiled with.
+ *
+ * Returns:
+ * Any bitwise combination of the ASSIMP_CFLAGS_xxx constants.
+ */
+ uint function() aiGetCompileFlags;
+}
diff --git a/libs/assimp/port/dAssimp/assimp/assimp.d b/libs/assimp/port/dAssimp/assimp/assimp.d
new file mode 100644
index 0000000..a147ee2
--- /dev/null
+++ b/libs/assimp/port/dAssimp/assimp/assimp.d
@@ -0,0 +1,63 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, ASSIMP Development 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 Development 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-all module provided for convenience.
+ */
+module assimp.assimp;
+
+public {
+ import assimp.animation;
+ import assimp.api;
+ import assimp.camera;
+ import assimp.config;
+ import assimp.fileIO;
+ import assimp.light;
+ import assimp.loader;
+ import assimp.material;
+ import assimp.math;
+ import assimp.mesh;
+ import assimp.postprocess;
+ import assimp.scene;
+ import assimp.texture;
+ import assimp.types;
+ import assimp.versionInfo;
+}
diff --git a/libs/assimp/port/dAssimp/assimp/camera.d b/libs/assimp/port/dAssimp/assimp/camera.d
new file mode 100644
index 0000000..5567be2
--- /dev/null
+++ b/libs/assimp/port/dAssimp/assimp/camera.d
@@ -0,0 +1,182 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, ASSIMP Development 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 Development 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.
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Contains the data structure which is used to store the imported information
+ * about the virtual cameras in the scene.
+ */
+module assimp.camera;
+
+import assimp.math;
+import assimp.types;
+
+extern ( C ) {
+ /**
+ * Helper structure to describe a virtual camera.
+ *
+ * Cameras have a representation in the node graph and can be animated.
+ * An important aspect is that the camera itself is also part of the
+ * scenegraph. This means, any values such as the look-at vector are not
+ * absolute, they're <em>relative</em> to the coordinate system defined
+ * by the node which corresponds to the camera. This allows for camera
+ * animations. Static cameras parameters like the look-at or up vectors are
+ * usually specified directly in the class members, but beware, they could
+ * also be encoded in the node transformation. The following (pseudo)code
+ * sample shows how to do it.
+ *
+ * Examples:
+ * ---
+ * // Get the camera matrix for a camera at a specific time
+ * // if the node hierarchy for the camera does not contain
+ * // at least one animated node this is a static computation
+ * get-camera-matrix (node sceneRoot, camera cam) : matrix
+ * {
+ * node cnd = find-node-for-camera(cam)
+ * matrix cmt = identity()
+ *
+ * // as usual - get the absolute camera transformation for this frame
+ * for each node nd in hierarchy from sceneRoot to cnd
+ * matrix cur
+ * if (is-animated(nd))
+ * cur = eval-animation(nd)
+ * else cur = nd->mTransformation;
+ * cmt = mult-matrices( cmt, cur )
+ * end for
+ *
+ * // now multiply with the camera's own local transform
+ * cam = mult-matrices (cam, get-camera-matrix(cmt) )
+ * }
+ * ---
+ *
+ * Note: Some file formats (such as 3DS, ASE) export a "target point" – the
+ * point the camera is looking at (it can even be animated). Assimp
+ * writes the target point as a subnode of the camera's main node, called
+ * "<camName>.Target". However, this is just additional information; the
+ * transformation applied to the main camera node already makes the
+ * camera face the right direction.
+ */
+ struct aiCamera {
+ /**
+ * The name of the camera.
+ *
+ * There must be a node in the scenegraph with the same name. This node
+ * specifies the position of the camera in the scene hierarchy and can
+ * be animated.
+ */
+ aiString mName;
+
+
+ /**
+ * Position of the camera relative to the coordinate space defined by the
+ * corresponding node.
+ *
+ * The default value is 0|0|0.
+ */
+ aiVector3D mPosition;
+
+ /**
+ * Up vector of the camera coordinate system relative to the
+ * coordinate space defined by the corresponding node.
+ *
+ * The right vector of the camera coordinate system is the cross
+ * product of the up and lookAt vectors.
+ *
+ * The default value is 0|1|0. The vector may be normalized, but it
+ * needn't.
+ */
+ aiVector3D mUp;
+
+ /**
+ * Look-at vector of the camera coordinate system relative to the
+ * coordinate space defined by the corresponding node.
+ *
+ * This is the viewing direction of the user.
+ *
+ * The default value is 0|0|1. The vector may be normalized, but it
+ * needn't.
+ */
+ aiVector3D mLookAt;
+
+
+ /**
+ * Half horizontal field of view angle, in radians.
+ *
+ * The field of view angle is the angle between the center line of the
+ * screen and the left or right border.
+ *
+ * The default value is PI/4.
+ */
+ float mHorizontalFOV;
+
+ /**
+ * Distance of the near clipping plane from the camera.
+ *
+ * The value may not be 0.f (for arithmetic reasons to prevent
+ * a division through zero).
+ *
+ * The default value is 0.1f.
+ */
+ float mClipPlaneNear;
+
+ /**
+ * Distance of the far clipping plane from the camera.
+ *
+ * The far clipping plane must, of course, be further away than the
+ * near clipping plane. The ratio between the near and the far plane
+ * should not be too large (between 1000-10000 should be ok) to avoid
+ * floating-point inaccuracies which could lead to z-fighting.
+ *
+ * The default value is 1000.f.
+ */
+ float mClipPlaneFar;
+
+ /**
+ * Screen aspect ratio.
+ *
+ * This is the ration between the width and the height of the
+ * screen. Typical values are 4/3, 1/2 or 1/1. This value is
+ * 0 if the aspect ratio is not defined in the source file.
+ *
+ * 0 is also the default value.
+ */
+ float mAspect;
+ }
+}
diff --git a/libs/assimp/port/dAssimp/assimp/config.d b/libs/assimp/port/dAssimp/assimp/config.d
new file mode 100644
index 0000000..761156b
--- /dev/null
+++ b/libs/assimp/port/dAssimp/assimp/config.d
@@ -0,0 +1,705 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, ASSIMP Development 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 Development 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.
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Defines constants for configurable properties for the library.
+ *
+ * These are set via <code>aiSetImportPropertyInteger()</code>,
+ * <code>aiSetImportPropertyFloat()</code> and
+ * <code>aiSetImportPropertyString()</code>.
+ */
+module assimp.config;
+
+extern ( C ) {
+ /*
+ * Library settings.
+ *
+ * General, global settings.
+ */
+
+ /**
+ * Enables time measurements.
+ *
+ * If enabled, measures the time needed for each part of the loading
+ * process (i.e. IO time, importing, postprocessing, ..) and dumps these
+ * timings to the DefaultLogger. See the performance page in the main
+ * Assimp docs information on this topic.
+ *
+ * Property type: bool. Default value: false.
+ */
+ const char* AI_CONFIG_GLOB_MEASURE_TIME = "GLOB_MEASURE_TIME";
+
+ version( none ) { // not implemented yet
+ /**
+ * Set Assimp's multithreading policy.
+ *
+ * This setting is ignored if Assimp was built without boost.thread support
+ * (<code>ASSIMP_BUILD_NO_THREADING</code>, which is implied by
+ * <code>ASSIMP_BUILD_BOOST_WORKAROUND</code>).
+ *
+ * Possible values are: -1 to let Assimp decide what to do, 0 to disable
+ * multithreading entirely and any number larger than 0 to force a specific
+ * number of threads. Assimp is always free to ignore this settings, which
+ * is merely a hint. Usually, the default value (-1) will be fine. However,
+ * if Assimp is used concurrently from multiple user threads, it might be
+ * useful to limit each Importer instance to a specific number of cores.
+ *
+ * For more information, see the threading page in the main Assimp docs.
+ *
+ * Property type: int, default value: -1.
+ */
+ const char* AI_CONFIG_GLOB_MULTITHREADING = "GLOB_MULTITHREADING";
+ }
+
+
+ /*
+ * Post processing settings.
+ *
+ * Various options to fine-tune the behavior of a specific post processing step.
+ */
+
+ /**
+ * Specifies the maximum angle that may be between two vertex tangents that
+ * their tangents and bitangents are smoothed.
+ *
+ * This applies to the <code>CalcTangentSpace</code> step. The angle is
+ * specified in degrees, so 180 corresponds to PI radians.
+ *
+ * The default value is 45, the maximum value is 175.
+ *
+ * Property type: float.
+ */
+ const char* AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE = "PP_CT_MAX_SMOOTHING_ANGLE";
+
+ /**
+ * Specifies the maximum angle that may be between two face normals at the
+ * same vertex position that their are smoothed together. Sometimes referred
+ * to as 'crease angle'.
+ *
+ * This applies to the <code>GenSmoothNormals</code> step. The angle is
+ * specified in degrees, so 180 corresponds to PI radians.
+ *
+ * The default value is 175 degrees (all vertex normals are smoothed), the
+ * maximum value is 175, too.
+ *
+ * Property type: float.
+ *
+ * Warning:
+ * Setting this option may cause a severe loss of performance. The
+ * performance is unaffected if the <code>AI_CONFIG_FAVOUR_SPEED</code>
+ * flag is set but the output quality may be reduced.
+ */
+ const char* AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE = "PP_GSN_MAX_SMOOTHING_ANGLE";
+
+ /**
+ * Sets the colormap (= palette) to be used to decode embedded textures in
+ * MDL (Quake or 3DGS) files.
+ *
+ * This must be a valid path to a file. The file is 768 (256*3) bytes large
+ * and contains RGB triplets for each of the 256 palette entries. The
+ * default value is colormap.lmp. If the file is not found, a default
+ * palette (from Quake 1) is used.
+ *
+ * Property type: string.
+ */
+ const char* AI_CONFIG_IMPORT_MDL_COLORMAP = "IMPORT_MDL_COLORMAP";
+
+ /**
+ * Configures the <code>RemoveRedundantMaterials</code> step to keep
+ * materials matching a name in a given list.
+ *
+ * This is a list of 1 to n strings, ' ' serves as delimiter character.
+ * Identifiers containing whitespaces must be enclosed in <em>single</em>
+ * quotation marks. For example: <code>
+ * "keep-me and_me_to anotherMaterialToBeKept \'name with whitespace\'"</code>.
+ * Linefeeds, tabs or carriage returns are treated as whitespace.
+ *
+ * If a material matches on of these names, it will not be modified or
+ * removed by the postprocessing step nor will other materials be replaced
+ * by a reference to it.
+ *
+ * This option might be useful if you are using some magic material names
+ * to pass additional semantics through the content pipeline. This ensures
+ * they won't be optimized away, but a general optimization is still
+ * performed for materials not contained in the list.
+ *
+ * Default value: n/a
+ *
+ * Property type: string.
+ *
+ * Note: Material names are case sensitive.
+ */
+ const char* AI_CONFIG_PP_RRM_EXCLUDE_LIST = "PP_RRM_EXCLUDE_LIST";
+
+ /**
+ * Configures the <code>PretransformVertices</code> step to keep the scene
+ * hierarchy. Meshes are moved to worldspace, but no optimization is
+ * performed (meshes with equal materials are not joined, the total number
+ * of meshes will not change).
+ *
+ * This option could be of use for you if the scene hierarchy contains
+ * important additional information which you intend to parse.
+ * For rendering, you can still render all meshes in the scene without
+ * any transformations.
+ *
+ * Default value: false.
+ *
+ * Property type: bool.
+ */
+ const char* AI_CONFIG_PP_PTV_KEEP_HIERARCHY = "PP_PTV_KEEP_HIERARCHY";
+
+ /**
+ * Configures the <code>PretransformVertices</code> step to normalize all
+ * vertex components into the -1...1 range. That is, a bounding box for the
+ * whole scene is computed, the maximum component is taken and all meshes
+ * are scaled appropriately (uniformly of course!).
+ *
+ * This might be useful if you don't know the spatial dimension of the input
+ * data.
+ */
+ const char* AI_CONFIG_PP_PTV_NORMALIZE = "PP_PTV_NORMALIZE";
+
+ /**
+ * Configures the <code>FindDegenerates</code> step to remove degenerated
+ * primitives from the import – immediately.
+ *
+ * The default behaviour converts degenerated triangles to lines and
+ * degenerated lines to points. See the documentation to the
+ * <code>FindDegenerates</code> step for a detailed example of the various
+ * ways to get rid of these lines and points if you don't want them.
+ *
+ * Default value: false.
+ *
+ * Property type: bool.
+ */
+ const char* AI_CONFIG_PP_FD_REMOVE = "PP_FD_REMOVE";
+
+ /**
+ * Configures the <code>OptimizeGraph</code> step to preserve nodes matching
+ * a name in a given list.
+ *
+ * This is a list of 1 to n strings, ' ' serves as delimiter character.
+ * Identifiers containing whitespaces must be enclosed in <em>single</em>
+ * quotation marks. For example: <code>
+ * "keep-me and_me_to anotherMaterialToBeKept \'name with whitespace\'"</code>.
+ * Linefeeds, tabs or carriage returns are treated as whitespace.
+ *
+ * If a node matches on of these names, it will not be modified or
+ * removed by the postprocessing step.
+ *
+ * This option might be useful if you are using some magic node names
+ * to pass additional semantics through the content pipeline. This ensures
+ * they won't be optimized away, but a general optimization is still
+ * performed for nodes not contained in the list.
+ *
+ * Default value: n/a
+ *
+ * Property type: string.
+ *
+ * Note: Node names are case sensitive.
+ */
+ const char* AI_CONFIG_PP_OG_EXCLUDE_LIST = "PP_OG_EXCLUDE_LIST";
+
+ /**
+ * Sets the maximum number of triangles in a mesh.
+ *
+ * This is used by the <code>SplitLargeMeshes</code> step to determine
+ * whether a mesh must be split or not.
+ *
+ * Default value: AI_SLM_DEFAULT_MAX_TRIANGLES.
+ *
+ * Property type: integer.
+ */
+ const char* AI_CONFIG_PP_SLM_TRIANGLE_LIMIT = "PP_SLM_TRIANGLE_LIMIT";
+
+ /**
+ * The default value for the AI_CONFIG_PP_SLM_TRIANGLE_LIMIT setting.
+ */
+ const AI_SLM_DEFAULT_MAX_TRIANGLES = 1000000;
+
+ /**
+ * Sets the maximum number of vertices in a mesh.
+ *
+ * This is used by the <code>SplitLargeMeshes</code> step to determine
+ * whether a mesh must be split or not.
+ *
+ * Default value: AI_SLM_DEFAULT_MAX_VERTICES
+ *
+ * Property type: integer.
+ */
+ const char* AI_CONFIG_PP_SLM_VERTEX_LIMIT = "PP_SLM_VERTEX_LIMIT";
+
+ /**
+ * The default value for the AI_CONFIG_PP_SLM_VERTEX_LIMIT setting.
+ */
+ const AI_SLM_DEFAULT_MAX_VERTICES = 1000000;
+
+ /**
+ * Sets the maximum number of bones affecting a single vertex.
+ *
+ * This is used by the <code>LimitBoneWeights</code> step.
+ *
+ * Default value: AI_LBW_MAX_WEIGHTS
+ *
+ * Property type: integer.
+ */
+ const char* AI_CONFIG_PP_LBW_MAX_WEIGHTS = "PP_LBW_MAX_WEIGHTS";
+
+ /**
+ * The default value for the AI_CONFIG_PP_LBW_MAX_WEIGHTS setting.
+ */
+ const AI_LMW_MAX_WEIGHTS = 0x4;
+
+ /**
+ * Sets the size of the post-transform vertex cache to optimize the
+ * vertices for. This configures the <code>ImproveCacheLocality</code> step.
+ *
+ * The size is given in vertices. Of course you can't know how the vertex
+ * format will exactly look like after the import returns, but you can still
+ * guess what your meshes will probably have.
+ *
+ * The default value results in slight performance improvements for most
+ * nVidia/AMD cards since 2002.
+ *
+ * Default value: PP_ICL_PTCACHE_SIZE
+ *
+ * Property type: integer.
+ */
+ const char* AI_CONFIG_PP_ICL_PTCACHE_SIZE = "PP_ICL_PTCACHE_SIZE";
+
+ /**
+ * The default value for the AI_CONFIG_PP_ICL_PTCACHE_SIZE config option.
+ */
+ const PP_ICL_PTCACHE_SIZE = 12;
+
+ /**
+ * Components of the <code>aiScene</code> and <code>aiMesh</code> data
+ * structures that can be excluded from the import by using the
+ * <code>RemoveComponent</code> step.
+ *
+ * See the documentation to <code>RemoveComponent</code> for more details.
+ */
+ enum aiComponent : uint {
+ /**
+ * Normal vectors.
+ */
+ NORMALS = 0x2,
+
+ /**
+ * Tangents and bitangents.
+ */
+ TANGENTS_AND_BITANGENTS = 0x4,
+
+ /**
+ * <em>All</em> color sets.
+ *
+ * Use aiComponent_COLORSn( N ) to specify the N'th set.
+ */
+ COLORS = 0x8,
+
+ /**
+ * <em>All</em> texture UV coordinate sets.
+ *
+ * Use aiComponent_TEXCOORDn( N ) to specify the N'th set.
+ */
+ TEXCOORDS = 0x10,
+
+ /**
+ * Bone weights from all meshes.
+ *
+ * The corresponding scenegraph nodes are <em>not</em> removed. Use the
+ * <code>OptimizeGraph</code> step to do this.
+ */
+ BONEWEIGHTS = 0x20,
+
+ /**
+ * Node animations (<code>aiScene.mAnimations</code>).
+ *
+ * The corresponding scenegraph nodes are <em>not</em> removed. Use the
+ * <code>OptimizeGraph</code> step to do this.
+ */
+ ANIMATIONS = 0x40,
+
+ /**
+ * Embedded textures (<code>aiScene.mTextures</code>).
+ */
+ TEXTURES = 0x80,
+
+ /**
+ * Light sources (<code>aiScene.mLights</code>).
+ *
+ * The corresponding scenegraph nodes are <em>not</em> removed. Use the
+ * <code>OptimizeGraph</code> step to do this.
+ */
+ LIGHTS = 0x100,
+
+ /**
+ * Cameras (<code>aiScene.mCameras</code>).
+ *
+ * The corresponding scenegraph nodes are <em>not</em> removed. Use the
+ * <code>OptimizeGraph</code> step to do this.
+ */
+ CAMERAS = 0x200,
+
+ /**
+ * Meshes (<code>aiScene.mMeshes</code>).
+ */
+ MESHES = 0x400,
+
+ /** Materials.
+ *
+ * One default material will be generated, so
+ * <code>aiScene.mNumMaterials</code> will be 1.
+ */
+ MATERIALS = 0x800
+ }
+
+ /**
+ * Specifies a certain color channel to remove.
+ */
+ uint aiComponent_COLORSn( uint n ) { return 1u << ( n + 20u ); }
+
+ /**
+ * Specifies a certain UV coordinate channel to remove.
+ */
+ uint aiComponent_TEXCOORDSn( uint n ) { return 1u << ( n + 25u ); }
+
+ /**
+ * Input parameter to the <code>RemoveComponent</code> step:
+ * Specifies the parts of the data structure to be removed.
+ *
+ * See the documentation to this step for further details.
+ *
+ * Default value: 0
+ *
+ * Property type: integer (bitwise combination of <code>aiComponent</code>
+ * flags).
+ *
+ * Note: If no valid mesh is remaining after the step has been executed, the
+ * import <em>fails</em>, because there is no data to work on anymore.
+ */
+ const char* AI_CONFIG_PP_RVC_FLAGS = "PP_RVC_FLAGS";
+
+ /**
+ * Input parameter to the <code>SortByPType</code> step:
+ * Specifies which primitive types are removed by the step.
+ *
+ * This is a bitwise combination of the <code>aiPrimitiveType</code> flags.
+ * Specifying all of them is illegal, of course. A typical use would be to
+ * exclude all line and point meshes from the import.
+ *
+ * Default value: 0
+ *
+ * Property type: integer.
+ */
+ const char* AI_CONFIG_PP_SBP_REMOVE = "PP_SBP_REMOVE";
+
+ /**
+ * Input parameter to the <code>FindInvalidData</code> step:
+ * Specifies the floating-point accuracy for animation values.
+ *
+ * The step checks for animation tracks where all frame values are
+ * absolutely equal and removes them. This tweakable controls the epsilon
+ * for floating-point comparisons – two keys are considered equal if the
+ * invariant abs(n0-n1) > epsilon holds true for all vector respectively
+ * quaternion components.
+ *
+ * Default value: 0 (exact comparison).
+ *
+ * Property type: float.
+ */
+ const char* AI_CONFIG_PP_FID_ANIM_ACCURACY = "PP_FID_ANIM_ACCURACY";
+
+ /**
+ * The <code>TransformUVCoords</code> step evaluates UV scalings.
+ */
+ const AI_UVTRAFO_SCALING = 0x1;
+
+ /**
+ * The <code>TransformUVCoords</code> step evaluates UV rotations.
+ */
+ const AI_UVTRAFO_ROTATION = 0x2;
+
+ /**
+ * The <code>TransformUVCoords</code> step evaluates UV translation.
+ */
+ const AI_UVTRAFO_TRANSLATION = 0x4;
+
+ /**
+ * The <code>TransformUVCoords</code> step evaluates all UV translations.
+ */
+ const AI_UVTRAFO_ALL =
+ AI_UVTRAFO_SCALING
+ | AI_UVTRAFO_ROTATION
+ | AI_UVTRAFO_TRANSLATION;
+
+ /**
+ * Input parameter to the <code>TransformUVCoords</code> step: Specifies
+ * which UV transformations are evaluated.
+ *
+ * Default value: AI_UVTRAFO_ALL.
+ *
+ * Property type: integer (bitwise combination of the
+ * <code>AI_UVTRAFO_XXX<code> flag).
+ */
+ const char* AI_CONFIG_PP_TUV_EVALUATE = "PP_TUV_EVALUATE";
+
+ /**
+ * A hint to assimp to favour speed against import quality.
+ *
+ * Enabling this option may result in faster loading, but it needn't.
+ * It represents just a hint to loaders and post-processing steps to use
+ * faster code paths, if possible.
+ *
+ * Default value: false.
+ *
+ * Property type: bool.
+ */
+ const char* AI_CONFIG_FAVOUR_SPEED = "FAVOUR_SPEED";
+
+
+ /*
+ * Importer settings.
+ *
+ * Various stuff to fine-tune the behaviour of specific importer plugins.
+ */
+
+ /**
+ * Set the vertex animation keyframe to be imported.
+ *
+ * Assimp does not support vertex keyframes (only bone animation is
+ * supported). The library reads only one frame of models with vertex
+ * animations.
+ *
+ * Default value: 0 (first frame).
+ *
+ * Property type: integer.
+ *
+ * Note: This option applies to all importers. However, it is also possible
+ * to override the global setting for a specific loader. You can use the
+ * AI_CONFIG_IMPORT_XXX_KEYFRAME options (where XXX is a placeholder for
+ * the file format for which you want to override the global setting).
+ */
+ const char* AI_CONFIG_IMPORT_GLOBAL_KEYFRAME = "IMPORT_GLOBAL_KEYFRAME";
+
+ const char* AI_CONFIG_IMPORT_MD3_KEYFRAME = "IMPORT_MD3_KEYFRAME";
+ const char* AI_CONFIG_IMPORT_MD2_KEYFRAME = "IMPORT_MD2_KEYFRAME";
+ const char* AI_CONFIG_IMPORT_MDL_KEYFRAME = "IMPORT_MDL_KEYFRAME";
+ const char* AI_CONFIG_IMPORT_MDC_KEYFRAME = "IMPORT_MDC_KEYFRAME";
+ const char* AI_CONFIG_IMPORT_SMD_KEYFRAME = "IMPORT_SMD_KEYFRAME";
+ const char* AI_CONFIG_IMPORT_UNREAL_KEYFRAME = "IMPORT_UNREAL_KEYFRAME";
+
+
+ /**
+ * Configures the AC loader to collect all surfaces which have the
+ * "Backface cull" flag set in separate meshes.
+ *
+ * Default value: true.
+ *
+ * Property type: bool.
+ */
+ const char* AI_CONFIG_IMPORT_AC_SEPARATE_BFCULL = "IMPORT_AC_SEPARATE_BFCULL";
+
+ /**
+ * Configures the UNREAL 3D loader to separate faces with different surface
+ * flags (e.g. two-sided vs. single-sided).
+ *
+ * Default value: true.
+ *
+ * Property type: bool.
+ */
+ const char* AI_CONFIG_IMPORT_UNREAL_HANDLE_FLAGS = "UNREAL_HANDLE_FLAGS";
+
+ /**
+ * Configures the terragen import plugin to compute uv's for terrains, if
+ * not given. Furthermore, a default texture is assigned.
+ *
+ * UV coordinates for terrains are so simple to compute that you'll usually
+ * want to compute them on your own, if you need them. This option is intended
+ * for model viewers which want to offer an easy way to apply textures to
+ * terrains.
+ *
+ * Default value: false.
+ *
+ * Property type: bool.
+ */
+ const char* AI_CONFIG_IMPORT_TER_MAKE_UVS = "IMPORT_TER_MAKE_UVS";
+
+ /**
+ * Configures the ASE loader to always reconstruct normal vectors basing on
+ * the smoothing groups loaded from the file.
+ *
+ * Many ASE files have invalid normals (they're not orthonormal).
+ *
+ * Default value: true.
+ *
+ * Property type: bool.
+ */
+ const char* AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS = "IMPORT_ASE_RECONSTRUCT_NORMALS";
+
+ /**
+ * Configures the M3D loader to detect and process multi-part Quake player
+ * models.
+ *
+ * These models usually consist of three files, <code>lower.md3</code>,
+ * <code>upper.md3</code> and <code>head.md3</code>. If this property is set
+ * to true, Assimp will try to load and combine all three files if one of
+ * them is loaded.
+ *
+ * Default value: true.
+ *
+ * Property type: bool.
+ */
+ const char* AI_CONFIG_IMPORT_MD3_HANDLE_MULTIPART = "IMPORT_MD3_HANDLE_MULTIPART";
+
+ /**
+ * Tells the MD3 loader which skin files to load.
+ *
+ * When loading MD3 files, Assimp checks whether a file
+ * <code><md3_file_name>_<skin_name>.skin</code> is existing. These files
+ * are used by Quake 3 to be able to assign different skins (e.g. red and
+ * blue team) to models. 'default', 'red', 'blue' are typical skin names.
+ *
+ * Default value: "default".
+ *
+ * Property type: string.
+ */
+ const char* AI_CONFIG_IMPORT_MD3_SKIN_NAME = "IMPORT_MD3_SKIN_NAME";
+
+ /**
+ * Specify the Quake 3 shader file to be used for a particular MD3 file.
+ * This can also be a search path.
+ *
+ * By default Assimp's behaviour is as follows: If a MD3 file
+ * <code>[any_path]/models/[any_q3_subdir]/[model_name]/[file_name].md3</code>
+ * is loaded, the library tries to locate the corresponding shader file in
+ * <code>[any_path]/scripts/[model_name].shader</code>. This property
+ * overrides this behaviour. It can either specify a full path to the shader
+ * to be loaded or alternatively the path (relative or absolute) to the
+ * directory where the shaders for all MD3s to be loaded reside. Assimp
+ * attempts to open <code>[dir]/[model_name].shader</code> first,
+ * <code>[dir]/[file_name].shader</code> is the fallback file. Note that
+ * <code>[dir]</code> should have a terminal (back)slash.
+ *
+ * Default value: n/a.
+ *
+ * Property type: string.
+ */
+ const char* AI_CONFIG_IMPORT_MD3_SHADER_SRC = "IMPORT_MD3_SHADER_SRC";
+
+ /**
+ * Configures the LWO loader to load just one layer from the model.
+ *
+ * LWO files consist of layers and in some cases it could be useful to load
+ * only one of them. This property can be either a string – which specifies
+ * the name of the layer – or an integer – the index of the layer. If the
+ * property is not set the whole LWO model is loaded. Loading fails if the
+ * requested layer is not available. The layer index is zero-based and the
+ * layer name may not be empty.
+ *
+ * Default value: all layers are loaded.
+ *
+ * Property type: integer/string.
+ */
+ const char* AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY = "IMPORT_LWO_ONE_LAYER_ONLY";
+
+ /**
+ * Configures the MD5 loader to not load the MD5ANIM file for a MD5MESH file
+ * automatically.
+ *
+ * The default strategy is to look for a file with the same name but the
+ * MD5ANIM extension in the same directory. If it is found, it is loaded
+ * and combined with the MD5MESH file. This configuration option can be
+ * used to disable this behaviour.
+ *
+ * Default value: false.
+ *
+ * Property type: bool.
+ */
+ const char* AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD = "IMPORT_MD5_NO_ANIM_AUTOLOAD";
+
+ /**
+ * Defines the begin of the time range for which the LWS loader evaluates
+ * animations and computes <code>aiNodeAnim</code>s.
+ *
+ * Assimp provides full conversion of LightWave's envelope system, including
+ * pre and post conditions. The loader computes linearly subsampled animation
+ * chanels with the frame rate given in the LWS file. This property defines
+ * the start time. Note: animation channels are only generated if a node
+ * has at least one envelope with more tan one key assigned. This property.
+ * is given in frames, '0' is the first frame. By default, if this property
+ * is not set, the importer takes the animation start from the input LWS
+ * file ('FirstFrame' line).
+ *
+ * Default value: read from file.
+ *
+ * Property type: integer.
+ *
+ * See: <code>AI_CONFIG_IMPORT_LWS_ANIM_END</code> – end of the imported
+ * time range
+ */
+ const char* AI_CONFIG_IMPORT_LWS_ANIM_START = "IMPORT_LWS_ANIM_START";
+ const char* AI_CONFIG_IMPORT_LWS_ANIM_END = "IMPORT_LWS_ANIM_END";
+
+ /**
+ * Defines the output frame rate of the IRR loader.
+ *
+ * IRR animations are difficult to convert for Assimp and there will always
+ * be a loss of quality. This setting defines how many keys per second are
+ * returned by the converter.
+ *
+ * Default value: 100.
+ *
+ * Property type: integer.
+ */
+ const char* AI_CONFIG_IMPORT_IRR_ANIM_FPS = "IMPORT_IRR_ANIM_FPS";
+
+ /**
+ * Ogre Importer will try to load this material file.
+ *
+ * Ogre Mehs contain only the material name, not the material file. If there
+ * is no material file with the same name as the material, Ogre Importer
+ * will try to load this file and search the material in it.
+ *
+ * Property type: string. Default value: "Scene.material".
+ */
+ const char* AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE = "IMPORT_OGRE_MATERIAL_FILE";
+}
diff --git a/libs/assimp/port/dAssimp/assimp/fileIO.d b/libs/assimp/port/dAssimp/assimp/fileIO.d
new file mode 100644
index 0000000..108d883
--- /dev/null
+++ b/libs/assimp/port/dAssimp/assimp/fileIO.d
@@ -0,0 +1,140 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, ASSIMP Development 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 Development 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.
+---------------------------------------------------------------------------
+*/
+
+/**
+ * The data structures necessary to use Assimip with a custom IO system.
+ */
+module assimp.fileIO;
+
+import assimp.types;
+
+extern ( C ) {
+ // aiFile callbacks
+ alias size_t function( aiFile*, char*, size_t, size_t ) aiFileWriteProc;
+ alias size_t function( aiFile*, char*, size_t, size_t ) aiFileReadProc;
+ alias size_t function( aiFile* ) aiFileTellProc;
+ alias void function( aiFile* ) aiFileFlushProc;
+ alias aiReturn function( aiFile*, size_t, aiOrigin ) aiFileSeek;
+
+ // aiFileIO callbacks
+ alias aiFile* function( aiFileIO*, char*, char* ) aiFileOpenProc;
+ alias void function( aiFileIO*, aiFile* ) aiFileCloseProc;
+
+ /**
+ * Represents user-defined data.
+ */
+ alias char* aiUserData;
+
+ /**
+ * File system callbacks.
+ *
+ * Provided are functions to open and close files. Supply a custom structure
+ * to the import function. If you don't, a default implementation is used.
+ * Use custom file systems to enable reading from other sources, such as
+ * ZIPs or memory locations.
+ */
+ struct aiFileIO {
+ /**
+ * Function used to open a new file
+ */
+ aiFileOpenProc OpenProc;
+
+ /**
+ * Function used to close an existing file
+ */
+ aiFileCloseProc CloseProc;
+
+ /**
+ * User-defined, opaque data.
+ */
+ aiUserData UserData;
+ }
+
+ /**
+ * File callbacks.
+ *
+ * Actually, it's a data structure to wrap a set of <code>fXXXX</code>
+ * (e.g <code>fopen()</code>) replacement functions.
+ *
+ * The default implementation of the functions utilizes the <code>fXXX</code>
+ * functions from the CRT. However, you can supply a custom implementation
+ * to Assimp by passing a custom <code>aiFileIO</code>. Use this to enable
+ * reading from other sources such as ZIP archives or memory locations.
+ */
+ struct aiFile {
+ /**
+ * Callback to read from a file.
+ */
+ aiFileReadProc ReadProc;
+
+ /**
+ * Callback to write to a file.
+ */
+ aiFileWriteProc WriteProc;
+
+ /**
+ * Callback to retrieve the current position of the file cursor
+ * (<code>ftell()</code>).
+ */
+ aiFileTellProc TellProc;
+
+ /**
+ * Callback to retrieve the size of the file, in bytes.
+ */
+ aiFileTellProc FileSizeProc;
+
+ /**
+ * Callback to set the current position of the file cursor
+ * (<code>fseek()</code>).
+ */
+ aiFileSeek SeekProc;
+
+ /**
+ * Callback to flush the file contents.
+ */
+ aiFileFlushProc FlushProc;
+
+ /**
+ * User-defined, opaque data.
+ */
+ aiUserData UserData;
+ }
+}
diff --git a/libs/assimp/port/dAssimp/assimp/light.d b/libs/assimp/port/dAssimp/assimp/light.d
new file mode 100644
index 0000000..0842d67
--- /dev/null
+++ b/libs/assimp/port/dAssimp/assimp/light.d
@@ -0,0 +1,215 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, ASSIMP Development 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 Development 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.
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Contains the data structures which are used to store the imported information
+ * about the light sources in the scene.
+ */
+module assimp.light;
+
+import assimp.math;
+import assimp.types;
+
+extern ( C ) {
+ /**
+ * Enumerates all supported types of light sources.
+ */
+ enum aiLightSourceType : uint {
+ UNDEFINED = 0x0,
+
+ /**
+ * A directional light source has a well-defined direction but is
+ * infinitely far away. That's quite a good approximation for sun light.
+ */
+ DIRECTIONAL = 0x1,
+
+ /**
+ * A point light source has a well-defined position in space but no
+ * direction – it emits light in all directions. A normal bulb is a point
+ * light.
+ */
+ POINT = 0x2,
+
+ /**
+ * A spot light source emits light in a specific angle. It has a position
+ * and a direction it is pointing to. A good example for a spot light is
+ * a light spot in sport arenas.
+ */
+ SPOT = 0x3
+ }
+
+ /**
+ * Helper structure to describe a light source.
+ *
+ * Assimp supports multiple sorts of light sources, including directional,
+ * point and spot lights. All of them are defined with just a single
+ * structure and distinguished by their parameters.
+ *
+ * Note: Some file formats (such as 3DS, ASE) export a "target point" – the
+ * point a spot light is looking at (it can even be animated). Assimp
+ * writes the target point as a subnode of a spotlights's main node, called
+ * <code>[spotName].Target</code>. However, this is just additional
+ * information then, the transformation tracks of the main node make the
+ * spot light already point in the right direction.
+ */
+ struct aiLight {
+ /**
+ * The name of the light source.
+ *
+ * There must be a node in the scenegraph with the same name. This node
+ * specifies the position of the light in the scenehierarchy and can be
+ * animated.
+ */
+ aiString mName;
+
+ /**
+ * The type of the light source.
+ *
+ * <code>aiLightSource.UNDEFINED</code> is not a valid value for this
+ * member.
+ */
+ aiLightSourceType mType;
+
+ /**
+ * Position of the light source in space. Relative to the transformation
+ * of the node corresponding to the light.
+ *
+ * The position is undefined for directional lights.
+ */
+ aiVector3D mPosition;
+
+ /**
+ * Direction of the light source in space. Relative to the transformation
+ * of the node corresponding to the light.
+ *
+ * The direction is undefined for point lights. The vector may be
+ * normalized, but it needn't.
+ */
+ aiVector3D mDirection;
+
+ /**
+ * Constant light attenuation factor.
+ *
+ * The intensity of the light source at a given distance
+ * <code>d</code> from the light's position is
+ * <code>1/( att0 + att1 * d + att2 * d * d )</code>. This member
+ * corresponds to the <code>att0</code> variable in the equation.
+ *
+ * Naturally undefined for directional lights.
+ */
+ float mAttenuationConstant;
+
+ /**
+ * Linear light attenuation factor.
+ *
+ * The intensity of the light source at a given distance
+ * <code>d</code> from the light's position is
+ * <code>1/( att0 + att1 * d + att2 * d * d )</code>. This member
+ * corresponds to the <code>att1</code> variable in the equation.
+ *
+ * Naturally undefined for directional lights.
+ */
+ float mAttenuationLinear;
+
+ /**
+ * Quadratic light attenuation factor.
+ *
+ * The intensity of the light source at a given distance
+ * <code>d</code> from the light's position is
+ * <code>1/( att0 + att1 * d + att2 * d * d )</code>. This member
+ * corresponds to the <code>att2</code> variable in the equation.
+ *
+ * Naturally undefined for directional lights.
+ */
+ float mAttenuationQuadratic;
+
+ /**
+ * Diffuse color of the light source
+ *
+ * The diffuse light color is multiplied with the diffuse material color
+ * to obtain the final color that contributes to the diffuse shading term.
+ */
+ aiColor3D mColorDiffuse;
+
+ /**
+ * Specular color of the light source
+ *
+ * The specular light color is multiplied with the specular material
+ * color to obtain the final color that contributes to the specular
+ * shading term.
+ */
+ aiColor3D mColorSpecular;
+
+ /**
+ * Ambient color of the light source
+ *
+ * The ambient light color is multiplied with the ambient material color
+ * to obtain the final color that contributes to the ambient shading term.
+ *
+ * Most renderers will ignore this value it, is just a remaining of the
+ * fixed-function pipeline that is still supported by quite many file
+ * formats.
+ */
+ aiColor3D mColorAmbient;
+
+ /**
+ * Inner angle of a spot light's light cone.
+ *
+ * The spot light has maximum influence on objects inside this angle. The
+ * angle is given in radians. It is 2PI for point lights and undefined
+ * for directional lights.
+ */
+ float mAngleInnerCone;
+
+ /**
+ * Outer angle of a spot light's light cone.
+ *
+ * The spot light does not affect objects outside this angle. The angle
+ * is given in radians. It is 2PI for point lights and undefined for
+ * directional lights. The outer angle must be greater than or equal to
+ * the inner angle.
+ *
+ * It is assumed that the application uses a smooth interpolation between
+ * the inner and the outer cone of the spot light.
+ */
+ float mAngleOuterCone;
+ }
+}
diff --git a/libs/assimp/port/dAssimp/assimp/loader.d b/libs/assimp/port/dAssimp/assimp/loader.d
new file mode 100644
index 0000000..279f0a7
--- /dev/null
+++ b/libs/assimp/port/dAssimp/assimp/loader.d
@@ -0,0 +1,193 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, ASSIMP Development 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 Development 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.
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Provides facilities for dynamically loading the Assimp library.
+ *
+ * Currently requires Tango, but there is no reason why Phobos could not be
+ * supported too.
+ */
+module assimp.loader;
+
+import assimp.api;
+import tango.io.Stdout;
+import tango.sys.SharedLib;
+
+const uint ASSIMP_BINDINGS_MAJOR = 2;
+const uint ASSIMP_BINDINGS_MINOR = 0;
+
+/**
+ * Loader class for dynamically loading the Assimp library.
+ *
+ * The library is »reference-counted«, meaning that the library is not
+ * unloaded on a call to <code>unload()</code> if there are still other
+ * references to it.
+ */
+struct Assimp {
+public:
+ /**
+ * Loads the library if it is not already loaded and increases the
+ * reference counter.
+ *
+ * The library file (<code>libassimp.so</code> on POSIX systems,
+ * <code>Assimp32.dll</code> on Win32) is loaded via Tango's SharedLib
+ * class.
+ */
+ static void load() {
+ if ( m_sRefCount == 0 ) {
+ version ( Posix ) {
+ version ( OSX ) {
+ m_sLibrary = SharedLib.load( "libassimp.dylib" );
+ } else {
+ m_sLibrary = SharedLib.load( "libassimp.so" );
+ }
+ }
+ version ( Win32 ) {
+ m_sLibrary = SharedLib.load( "Assimp32.dll" );
+ }
+
+ // Versioning
+ mixin( bindCode( "aiGetLegalString" ) );
+ mixin( bindCode( "aiGetVersionMinor" ) );
+ mixin( bindCode( "aiGetVersionMajor" ) );
+ mixin( bindCode( "aiGetVersionRevision" ) );
+ mixin( bindCode( "aiGetCompileFlags" ) );
+
+ // Check for version mismatch between the external, dynamically loaded
+ // library and the version the bindings were created against.
+ uint libMajor = aiGetVersionMajor();
+ uint libMinor = aiGetVersionMinor();
+
+ if ( ( libMajor < ASSIMP_BINDINGS_MAJOR ) ||
+ ( libMinor < ASSIMP_BINDINGS_MINOR ) ) {
+ Stdout.format(
+ "WARNING: Assimp version too old (loaded library: {}.{}, " ~
+ "bindings: {}.{})!",
+ libMajor,
+ libMinor,
+ ASSIMP_BINDINGS_MAJOR,
+ ASSIMP_BINDINGS_MINOR
+ ).newline;
+ }
+
+ if ( libMajor > ASSIMP_BINDINGS_MAJOR ) {
+ Stdout.format(
+ "WARNING: Assimp version too new (loaded library: {}.{}, " ~
+ "bindings: {}.{})!",
+ libMajor,
+ libMinor,
+ ASSIMP_BINDINGS_MAJOR,
+ ASSIMP_BINDINGS_MINOR
+ ).newline;
+ }
+
+ // General API
+ mixin( bindCode( "aiImportFile" ) );
+ mixin( bindCode( "aiImportFileEx" ) );
+ mixin( bindCode( "aiImportFileFromMemory" ) );
+ mixin( bindCode( "aiApplyPostProcessing" ) );
+ mixin( bindCode( "aiGetPredefinedLogStream" ) );
+ mixin( bindCode( "aiAttachLogStream" ) );
+ mixin( bindCode( "aiEnableVerboseLogging" ) );
+ mixin( bindCode( "aiDetachLogStream" ) );
+ mixin( bindCode( "aiDetachAllLogStreams" ) );
+ mixin( bindCode( "aiReleaseImport" ) );
+ mixin( bindCode( "aiGetErrorString" ) );
+ mixin( bindCode( "aiIsExtensionSupported" ) );
+ mixin( bindCode( "aiGetExtensionList" ) );
+ mixin( bindCode( "aiGetMemoryRequirements" ) );
+ mixin( bindCode( "aiSetImportPropertyInteger" ) );
+ mixin( bindCode( "aiSetImportPropertyFloat" ) );
+ mixin( bindCode( "aiSetImportPropertyString" ) );
+
+ // Mathematical functions
+ mixin( bindCode( "aiCreateQuaternionFromMatrix" ) );
+ mixin( bindCode( "aiDecomposeMatrix" ) );
+ mixin( bindCode( "aiTransposeMatrix4" ) );
+ mixin( bindCode( "aiTransposeMatrix3" ) );
+ mixin( bindCode( "aiTransformVecByMatrix3" ) );
+ mixin( bindCode( "aiTransformVecByMatrix4" ) );
+ mixin( bindCode( "aiMultiplyMatrix4" ) );
+ mixin( bindCode( "aiMultiplyMatrix3" ) );
+ mixin( bindCode( "aiIdentityMatrix3" ) );
+ mixin( bindCode( "aiIdentityMatrix4" ) );
+
+ // Material system
+ mixin( bindCode( "aiGetMaterialProperty" ) );
+ mixin( bindCode( "aiGetMaterialFloatArray" ) );
+ mixin( bindCode( "aiGetMaterialIntegerArray" ) );
+ mixin( bindCode( "aiGetMaterialColor" ) );
+ mixin( bindCode( "aiGetMaterialString" ) );
+ mixin( bindCode( "aiGetMaterialTextureCount" ) );
+ mixin( bindCode( "aiGetMaterialTexture" ) );
+ }
+ ++m_sRefCount;
+ }
+
+ /**
+ * Decreases the reference counter and unloads the library if this was the
+ * last reference.
+ */
+ static void unload() {
+ assert( m_sRefCount > 0 );
+ --m_sRefCount;
+
+ if ( m_sRefCount == 0 ) {
+ m_sLibrary.unload();
+ }
+ }
+
+private:
+ /// Current number of references to the library.
+ static uint m_sRefCount;
+
+ /// Library handle.
+ static SharedLib m_sLibrary;
+}
+
+/**
+ * Private helper function which constructs the bind command for a symbol to
+ * keep the code DRY.
+ */
+private char[] bindCode( char[] symbol ) {
+ return symbol ~ " = cast( typeof( " ~ symbol ~
+ " ) )m_sLibrary.getSymbol( `" ~ symbol ~ "` );";
+}
diff --git a/libs/assimp/port/dAssimp/assimp/material.d b/libs/assimp/port/dAssimp/assimp/material.d
new file mode 100644
index 0000000..f0eae86
--- /dev/null
+++ b/libs/assimp/port/dAssimp/assimp/material.d
@@ -0,0 +1,641 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, ASSIMP Development 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 Development 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.
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Contains the material system which stores the imported material information.
+ */
+module assimp.material;
+
+import assimp.math;
+import assimp.types;
+
+extern ( C ) {
+ /**
+ * Default material names for meshes without UV coordinates.
+ */
+ const char* AI_DEFAULT_MATERIAL_NAME = "aiDefaultMat";
+
+ /**
+ * Default material names for meshes with UV coordinates.
+ */
+ const char* AI_DEFAULT_TEXTURED_MATERIAL_NAME = "TexturedDefaultMaterial";
+
+ /**
+ * Defines how the Nth texture of a specific type is combined with the
+ * result of all previous layers.
+ *
+ * Example (left: key, right: value):
+ * <pre> DiffColor0 - gray
+ * DiffTextureOp0 - aiTextureOpMultiply
+ * DiffTexture0 - tex1.png
+ * DiffTextureOp0 - aiTextureOpAdd
+ * DiffTexture1 - tex2.png</pre>
+ * Written as equation, the final diffuse term for a specific pixel would be:
+ * <pre>diffFinal = DiffColor0 * sampleTex( DiffTexture0, UV0 ) +
+ * sampleTex( DiffTexture1, UV0 ) * diffContrib;</pre>
+ * where <code>diffContrib</code> is the intensity of the incoming light for
+ * that pixel.
+ */
+ enum aiTextureOp : uint {
+ /**
+ * <code>T = T1 * T2</code>
+ */
+ Multiply = 0x0,
+
+ /**
+ * <code>T = T1 + T2</code>
+ */
+ Add = 0x1,
+
+ /**
+ * <code>T = T1 - T2</code>
+ */
+ Subtract = 0x2,
+
+ /**
+ * <code>T = T1 / T2</code>
+ */
+ Divide = 0x3,
+
+ /**
+ * <code>T = ( T1 + T2 ) - ( T1 * T2 )</code>
+ */
+ SmoothAdd = 0x4,
+
+ /**
+ * <code>T = T1 + ( T2 - 0.5 )</code>
+ */
+ SignedAdd = 0x5
+ }
+
+ /**
+ * Defines how UV coordinates outside the <code>[0..1]</code> range are
+ * handled.
+ *
+ * Commonly referred to as 'wrapping mode'.
+ */
+ enum aiTextureMapMode : uint {
+ /**
+ * A texture coordinate <code>u | v</code> is translated to
+ * <code>(u%1) | (v%1)</code>.
+ */
+ Wrap = 0x0,
+
+ /**
+ * Texture coordinates are clamped to the nearest valid value.
+ */
+ Clamp = 0x1,
+
+ /**
+ * If the texture coordinates for a pixel are outside
+ * <code>[0..1]</code>, the texture is not applied to that pixel.
+ */
+ Decal = 0x3,
+
+ /**
+ * A texture coordinate <code>u | v</code> becomes
+ * <code>(u%1) | (v%1)</code> if <code>(u-(u%1))%2</code> is
+ * zero and <code>(1-(u%1)) | (1-(v%1))</code> otherwise.
+ */
+ Mirror = 0x2
+ }
+
+ /**
+ * Defines how the mapping coords for a texture are generated.
+ *
+ * Real-time applications typically require full UV coordinates, so the use of
+ * the <code>aiProcess.GenUVCoords</code> step is highly recommended. It
+ * generates proper UV channels for non-UV mapped objects, as long as an
+ * accurate description how the mapping should look like (e.g spherical) is
+ * given. See the <code>AI_MATKEY_MAPPING</code> property for more details.
+ */
+ enum aiTextureMapping : uint {
+ /**
+ * The mapping coordinates are taken from an UV channel.
+ *
+ * The <code>AI_MATKEY_UVSRC</code> key specifies from which (remember,
+ * meshes can have more than one UV channel).
+ */
+ UV = 0x0,
+
+ /**
+ * Spherical mapping.
+ */
+ SPHERE = 0x1,
+
+ /**
+ * Cylindrical mapping.
+ */
+ CYLINDER = 0x2,
+
+ /**
+ * Cubic mapping.
+ */
+ BOX = 0x3,
+
+ /**
+ * Planar mapping.
+ */
+ PLANE = 0x4,
+
+ /**
+ * Undefined mapping.
+ */
+ OTHER = 0x5
+ }
+
+ /**
+ * Defines the purpose of a texture
+ *
+ * This is a very difficult topic. Different 3D packages support different
+ * kinds of textures. For very common texture types, such as bumpmaps, the
+ * rendering results depend on implementation details in the rendering
+ * pipelines of these applications. Assimp loads all texture references from
+ * the model file and tries to determine which of the predefined texture
+ * types below is the best choice to match the original use of the texture
+ * as closely as possible.
+ *
+ * In content pipelines you'll usually define how textures have to be
+ * handled, and the artists working on models have to conform to this
+ * specification, regardless which 3D tool they're using.
+ */
+ enum aiTextureType : uint {
+ /**
+ * No texture, but the value to be used for
+ * <code>aiMaterialProperty.mSemantic</code> for all material properties
+ * <em>not</em> related to textures.
+ */
+ NONE = 0x0,
+
+ /**
+ * The texture is combined with the result of the diffuse lighting
+ * equation.
+ */
+ DIFFUSE = 0x1,
+
+ /**
+ * The texture is combined with the result of the specular lighting
+ * equation.
+ */
+ SPECULAR = 0x2,
+
+ /**
+ * The texture is combined with the result of the ambient lighting
+ * equation.
+ */
+ AMBIENT = 0x3,
+
+ /**
+ * The texture is added to the result of the lighting calculation. It
+ * isn't influenced by incoming light.
+ */
+ EMISSIVE = 0x4,
+
+ /**
+ * The texture is a height map.
+ *
+ * By convention, higher grey-scale values stand for higher elevations
+ * from the base height.
+ */
+ HEIGHT = 0x5,
+
+ /**
+ * The texture is a (tangent space) normal-map.
+ *
+ * Again, there are several conventions for tangent-space normal maps.
+ * Assimp does (intentionally) not differenciate here.
+ */
+ NORMALS = 0x6,
+
+ /**
+ * The texture defines the glossiness of the material.
+ *
+ * The glossiness is in fact the exponent of the specular (phong)
+ * lighting equation. Usually there is a conversion function defined to
+ * map the linear color values in the texture to a suitable exponent.
+ */
+ SHININESS = 0x7,
+
+ /**
+ * The texture defines per-pixel opacity.
+ *
+ * Usually white means opaque and black means transparent.
+ */
+ OPACITY = 0x8,
+
+ /**
+ * Displacement texture.
+ *
+ * The exact purpose and format is application-dependent. Higher color
+ * values stand for higher vertex displacements.
+ */
+ DISPLACEMENT = 0x9,
+
+ /**
+ * Lightmap or ambient occlusion texture.
+ *
+ * Both lightmaps and dedicated ambient occlusion maps are covered by
+ * this material property. The texture contains a scaling value for the
+ * final color value of a pixel. Its intensity is not affected by
+ * incoming light.
+ */
+ LIGHTMAP = 0xA,
+
+ /**
+ * Reflection texture.
+ *
+ * Contains the color of a perfect mirror reflection. Rarely used, almost
+ * never for real-time applications.
+ */
+ REFLECTION = 0xB,
+
+ /**
+ * Unknown texture.
+ *
+ * A texture reference that does not match any of the definitions above is
+ * considered to be 'unknown'. It is still imported, but is excluded from
+ * any further postprocessing.
+ */
+ UNKNOWN = 0xC
+ }
+
+ /**
+ * Defines all shading models supported by the library
+ *
+ * The list of shading modes has been taken from Blender. See Blender
+ * documentation for more information. The API does not distinguish between
+ * "specular" and "diffuse" shaders (thus the specular term for diffuse
+ * shading models like Oren-Nayar remains undefined).
+ *
+ * Again, this value is just a hint. Assimp tries to select the shader whose
+ * most common implementation matches the original rendering results of the
+ * 3D modeller which wrote a particular model as closely as possible.
+ */
+ enum aiShadingMode : uint {
+ /**
+ * Flat shading.
+ *
+ * Shading is done on per-face base diffuse only. Also known as
+ * »faceted shading«.
+ */
+ Flat = 0x1,
+
+ /**
+ * Simple Gouraud shading.
+ */
+ Gouraud = 0x2,
+
+ /**
+ * Phong-Shading.
+ */
+ Phong = 0x3,
+
+ /**
+ * Phong-Blinn-Shading.
+ */
+ Blinn = 0x4,
+
+ /**
+ * Per-pixel toon shading.
+ *
+ * Often referred to as »comic shading«.
+ */
+ Toon = 0x5,
+
+ /**
+ * Per-pixel Oren-Nayar shading.
+ *
+ * Extension to standard Lambertian shading, taking the roughness of the
+ * material into account.
+ */
+ OrenNayar = 0x6,
+
+ /**
+ * Per-pixel Minnaert shading.
+ *
+ * Extension to standard Lambertian shading, taking the "darkness" of the
+ * material into account.
+ */
+ Minnaert = 0x7,
+
+ /**
+ * Per-pixel Cook-Torrance shading.
+ *
+ * Special shader for metallic surfaces.
+ */
+ CookTorrance = 0x8,
+
+ /**
+ * No shading at all.
+ *
+ * Constant light influence of 1.
+ */
+ NoShading = 0x9,
+
+ /**
+ * Fresnel shading.
+ */
+ Fresnel = 0xa
+ }
+
+ /**
+ * Defines some mixed flags for a particular texture.
+ *
+ * Usually you'll instruct your cg artists how textures have to look like
+ * and how they will be processed in your application. However, if you use
+ * Assimp for completely generic loading purposes you might also need to
+ * process these flags in order to display as many 'unknown' 3D models as
+ * possible correctly.
+ *
+ * This corresponds to the <code>AI_MATKEY_TEXFLAGS</code> property.
+ */
+ enum aiTextureFlags : uint {
+ /**
+ * The texture's color values have to be inverted (i.e. <code>1-n</code>
+ * component-wise).
+ */
+ Invert = 0x1,
+
+ /**
+ * Explicit request to the application to process the alpha channel of the
+ * texture.
+ *
+ * Mutually exclusive with <code>IgnoreAlpha</code>. These flags are
+ * set if the library can say for sure that the alpha channel is used/is
+ * not used. If the model format does not define this, it is left to the
+ * application to decide whether the texture alpha channel – if any – is
+ * evaluated or not.
+ */
+ UseAlpha = 0x2,
+
+ /**
+ * Explicit request to the application to ignore the alpha channel of the
+ * texture.
+ *
+ * Mutually exclusive with <code>UseAlpha</code>.
+ */
+ IgnoreAlpha = 0x4
+ }
+
+
+ /**
+ * Defines alpha-blend flags.
+ *
+ * If you're familiar with OpenGL or D3D, these flags aren't new to you.
+ * They define how the final color value of a pixel is computed, based on
+ * the previous color at that pixel and the new color value from the
+ * material.
+ *
+ * The basic blending formula is
+ * <code>SourceColor * SourceBlend + DestColor * DestBlend</code>,
+ * where <code>DestColor</code> is the previous color in the framebuffer at
+ * this position and <code>SourceColor</code> is the material color before
+ * the transparency calculation.
+ *
+ * This corresponds to the <code>AI_MATKEY_BLEND_FUNC</code> property.
+ */
+ enum aiBlendMode :uint {
+ /**
+ * Formula:
+ * <code>SourceColor * SourceAlpha + DestColor * (1 - SourceAlpha)</code>
+ */
+ Default = 0x0,
+
+ /**
+ * Additive blending.
+ *
+ * Formula: <code>SourceColor*1 + DestColor*1</code>
+ */
+ Additive = 0x1
+ }
+
+ /**
+ * Defines how an UV channel is transformed.
+ *
+ * This is just a helper structure for the <code>AI_MATKEY_UVTRANSFORM</code>
+ * key. See its documentation for more details.
+ */
+ struct aiUVTransform {
+ align ( 1 ) :
+ /**
+ * Translation on the u and v axes.
+ *
+ * The default value is (0|0).
+ */
+ aiVector2D mTranslation;
+
+ /**
+ * Scaling on the u and v axes.
+ *
+ * The default value is (1|1).
+ */
+ aiVector2D mScaling;
+
+ /**
+ * Rotation - in counter-clockwise direction.
+ *
+ * The rotation angle is specified in radians. The rotation center is
+ * 0.5|0.5. The default value is 0.
+ */
+ float mRotation;
+ }
+
+ /**
+ * A very primitive RTTI system to store the data type of a material
+ * property.
+ */
+ enum aiPropertyTypeInfo : uint {
+ /**
+ * Array of single-precision (32 bit) floats.
+ *
+ * It is possible to use <code>aiGetMaterialInteger[Array]()</code> to
+ * query properties stored in floating-point format. The material system
+ * performs the type conversion automatically.
+ */
+ Float = 0x1,
+
+ /**
+ * aiString property.
+ *
+ * Arrays of strings aren't possible, <code>aiGetMaterialString()</code>
+ * must be used to query a string property.
+ */
+ String = 0x3,
+
+ /**
+ * Array of (32 bit) integers.
+ *
+ * It is possible to use <code>aiGetMaterialFloat[Array]()</code> to
+ * query properties stored in integer format. The material system
+ * performs the type conversion automatically.
+ */
+ Integer = 0x4,
+
+ /**
+ * Simple binary buffer, content undefined. Not convertible to anything.
+ */
+ Buffer = 0x5
+ }
+
+ /**
+ * Data structure for a single material property.
+ *
+ * As an user, you'll probably never need to deal with this data structure.
+ * Just use the provided <code>aiGetMaterialXXX()</code> functions to query
+ * material properties easily. Processing them manually is faster, but it is
+ * not the recommended way. It isn't worth the effort.
+ *
+ * Material property names follow a simple scheme:
+ *
+ * <code>$[name]</code>: A public property, there must be a corresponding
+ * AI_MATKEY_XXX constant.
+ *
+ * <code>?[name]</code>: Also public, but ignored by the
+ * <code>aiProcess.RemoveRedundantMaterials</code> post-processing step.
+ *
+ * <code>~[name]</code>: A temporary property for internal use.
+ */
+ struct aiMaterialProperty {
+ /**
+ * Specifies the name of the property (key).
+ *
+ * Keys are generally case insensitive.
+ */
+ aiString mKey;
+
+ /**
+ * For texture properties, this specifies the exact usage semantic.
+ *
+ * For non-texture properties, this member is always 0 (or rather
+ * <code>aiTextureType.NONE</code>).
+ */
+ uint mSemantic;
+
+ /**
+ * For texture properties, this specifies the index of the texture.
+ *
+ * For non-texture properties, this member is always 0.
+ */
+ uint mIndex;
+
+ /**
+ * Size of the buffer <code>mData</code> is pointing to (in bytes).
+ *
+ * This value may not be 0.
+ */
+ uint mDataLength;
+
+ /**
+ * Type information for the property.
+ *
+ * Defines the data layout inside the data buffer. This is used by the
+ * library internally to perform debug checks and to utilize proper type
+ * conversions.
+ */
+ aiPropertyTypeInfo mType;
+
+ /**
+ * Binary buffer to hold the property's value.
+ *
+ * The size of the buffer is always <code>mDataLength</code>.
+ */
+ char* mData;
+ }
+
+ /**
+ * Data structure for a material
+ *
+ * Material data is stored using a key-value structure. A single key-value
+ * pair is called a <em>material property</em>. The properties can be
+ * queried using the <code>aiMaterialGetXXX</code> family of functions. The
+ * library defines a set of standard keys (AI_MATKEY_XXX).
+ */
+ struct aiMaterial {
+ /**
+ * List of all material properties loaded.
+ */
+ aiMaterialProperty** mProperties;
+
+ /**
+ * Number of properties loaded.
+ */
+ uint mNumProperties;
+ uint mNumAllocated; /// ditto
+ }
+
+ /**
+ * Standard material property keys. Always pass 0 for texture type and index
+ * when querying these keys.
+ */
+ const char* AI_MATKEY_NAME = "?mat.name";
+ const char* AI_MATKEY_TWOSIDED = "$mat.twosided"; /// ditto
+ const char* AI_MATKEY_SHADING_MODEL = "$mat.shadingm"; /// ditto
+ const char* AI_MATKEY_ENABLE_WIREFRAME = "$mat.wireframe"; /// ditto
+ const char* AI_MATKEY_BLEND_FUNC = "$mat.blend"; /// ditto
+ const char* AI_MATKEY_OPACITY = "$mat.opacity"; /// ditto
+ const char* AI_MATKEY_BUMPSCALING = "$mat.bumpscaling"; /// ditto
+ const char* AI_MATKEY_SHININESS = "$mat.shininess"; /// ditto
+ const char* AI_MATKEY_REFLECTIVITY = "$mat.reflectivity"; /// ditto
+ const char* AI_MATKEY_SHININESS_STRENGTH = "$mat.shinpercent"; /// ditto
+ const char* AI_MATKEY_REFRACTI = "$mat.refracti"; /// ditto
+ const char* AI_MATKEY_COLOR_DIFFUSE = "$clr.diffuse"; /// ditto
+ const char* AI_MATKEY_COLOR_AMBIENT = "$clr.ambient"; /// ditto
+ const char* AI_MATKEY_COLOR_SPECULAR = "$clr.specular"; /// ditto
+ const char* AI_MATKEY_COLOR_EMISSIVE = "$clr.emissive"; /// ditto
+ const char* AI_MATKEY_COLOR_TRANSPARENT = "$clr.transparent"; /// ditto
+ const char* AI_MATKEY_COLOR_REFLECTIVE = "$clr.reflective"; /// ditto
+ const char* AI_MATKEY_GLOBAL_BACKGROUND_IMAGE = "?bg.global"; /// ditto
+
+ /**
+ * Texture material property keys. Do not forget to specify texture type and
+ * index for these keys.
+ */
+ const char* AI_MATKEY_TEXTURE = "$tex.file";
+ const char* AI_MATKEY_UVWSRC = "$tex.uvwsrc"; /// ditto
+ const char* AI_MATKEY_TEXOP = "$tex.op"; /// ditto
+ const char* AI_MATKEY_MAPPING = "$tex.mapping"; /// ditto
+ const char* AI_MATKEY_TEXBLEND = "$tex.blend"; /// ditto
+ const char* AI_MATKEY_MAPPINGMODE_U = "$tex.mapmodeu"; /// ditto
+ const char* AI_MATKEY_MAPPINGMODE_V = "$tex.mapmodev"; /// ditto
+ const char* AI_MATKEY_TEXMAP_AXIS = "$tex.mapaxis"; /// ditto
+ const char* AI_MATKEY_UVTRANSFORM = "$tex.uvtrafo"; /// ditto
+ const char* AI_MATKEY_TEXFLAGS = "$tex.flags"; /// ditto
+}
diff --git a/libs/assimp/port/dAssimp/assimp/math.d b/libs/assimp/port/dAssimp/assimp/math.d
new file mode 100644
index 0000000..057bbd5
--- /dev/null
+++ b/libs/assimp/port/dAssimp/assimp/math.d
@@ -0,0 +1,155 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, ASSIMP Development 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 Development 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.
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Mathematical structures in which the imported data is stored.
+ */
+module assimp.math;
+
+extern( C ) {
+ /**
+ * Represents a two-dimensional vector.
+ */
+ struct aiVector2D {
+ align ( 1 ):
+ float x, y;
+ }
+
+ /**
+ * Represents a three-dimensional vector.
+ */
+ struct aiVector3D {
+ align ( 1 ):
+ float x, y, z;
+ }
+
+ /**
+ * Represents a quaternion.
+ */
+ struct aiQuaternion {
+ float w, x, y, z;
+ }
+
+ /**
+ * Represents a row-major 3x3 matrix
+ *
+ * There is much confusion about matrix layouts (column vs. row order). This
+ * is <em>always</em> a row-major matrix, even when using the
+ * <code>ConvertToLeftHanded</code> post processing step.
+ */
+ struct aiMatrix3x3 {
+ float a1, a2, a3;
+ float b1, b2, b3;
+ float c1, c2, c3;
+ }
+
+ /**
+ * Represents a row-major 3x3 matrix
+ *
+ * There is much confusion about matrix layouts (column vs. row order). This
+ * is <em>always</em> a row-major matrix, even when using the
+ * <code>ConvertToLeftHanded</code> post processing step.
+ */
+ struct aiMatrix4x4 {
+ align ( 1 ):
+ float a1, a2, a3, a4;
+ float b1, b2, b3, b4;
+ float c1, c2, c3, c4;
+ float d1, d2, d3, d4;
+ }
+
+ /**
+ * Represents a plane in a three-dimensional, euclidean space
+ */
+ struct aiPlane {
+ align ( 1 ):
+ /**
+ * Coefficients of the plane equation (<code>ax + by + cz = d</code>).
+ */
+ float a;
+ float b; /// ditto
+ float c; /// ditto
+ float d; /// ditto
+ }
+
+ /**
+ * Represents a ray.
+ */
+ struct aiRay {
+ align ( 1 ):
+ /**
+ * Origin of the ray.
+ */
+ aiVector3D pos;
+
+ /**
+ * Direction of the ray.
+ */
+ aiVector3D dir;
+ }
+
+ /**
+ * Represents a color in RGB space.
+ */
+ struct aiColor3D {
+ align ( 1 ):
+ /**
+ * Red, green and blue values.
+ */
+ float r;
+ float g; /// ditto
+ float b; /// ditto
+ }
+
+ /**
+ * Represents a color in RGB space including an alpha component.
+ */
+ struct aiColor4D {
+ align ( 1 ):
+ /**
+ * Red, green, blue and alpha values.
+ */
+ float r;
+ float g; /// ditto
+ float b; /// ditto
+ float a; /// ditto
+ }
+}
diff --git a/libs/assimp/port/dAssimp/assimp/mesh.d b/libs/assimp/port/dAssimp/assimp/mesh.d
new file mode 100644
index 0000000..48162b7
--- /dev/null
+++ b/libs/assimp/port/dAssimp/assimp/mesh.d
@@ -0,0 +1,465 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, ASSIMP Development 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 Development 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.
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Contains the data structures in which the imported geometry is returned by
+ * Assimp.
+ */
+module assimp.mesh;
+
+import assimp.math;
+import assimp.types;
+
+extern ( C ) {
+ /*
+ * These limits are required to match the settings Assimp was compiled
+ * against. Therefore, do not redefine them unless you build the library
+ * from source using the same definitions.
+ */
+
+ /**
+ * Maximum number of indices per face (polygon).
+ */
+ const AI_MAX_FACE_INDICES = 0x7fff;
+
+ /**
+ * Maximum number of indices per face (polygon).
+ */
+ const AI_MAX_BONE_WEIGHTS = 0x7fffffff;
+
+ /**
+ * Maximum number of vertices per mesh.
+ */
+ const AI_MAX_VERTICES = 0x7fffffff;
+
+ /**
+ * Maximum number of faces per mesh.
+ */
+ const AI_MAX_FACES = 0x7fffffff;
+
+ /**
+ * Supported number of vertex color sets per mesh.
+ */
+ const AI_MAX_NUMBER_OF_COLOR_SETS = 0x4;
+
+ /**
+ * Supported number of texture coord sets (UV(W) channels) per mesh.
+ */
+ const AI_MAX_NUMBER_OF_TEXTURECOORDS = 0x4;
+
+
+ /**
+ * A single face in a mesh, referring to multiple vertices.
+ *
+ * If <code>mNumIndices</code> is 3, we call the face <em>triangle</em>, for
+ * for <code>mNumIndices > 3</code> it's called <em>polygon</em>.
+ *
+ * <code>aiMesh.mPrimitiveTypes</code> can be queried to quickly examine
+ * which types of primitive are actually present in a mesh. The
+ * <code>aiProcess.SortByPType</code> flag post-processing step splits
+ * meshes containing different primitive types (e.g. lines and triangles) in
+ * several "clean" submeshes.
+ *
+ * Furthermore, there is a configuration option
+ * (<code>AI_CONFIG_PP_SBP_REMOVE</code>) to force <code>SortByPType</code>
+ * to completely remove specific kinds of primitives from the imported scene.
+ * In many cases you'll probably want to set this setting to
+ * <code>aiPrimitiveType.LINE | aiPrimitiveType.POINT</code>. Together with
+ * the <code>aiProcess.Triangulate</code> flag you can then be sure that
+ * <code>mNumIndices</code> is always 3.
+ */
+ struct aiFace {
+ /**
+ * Number of indices defining this face.
+ *
+ * The maximum value for this member is <code>AI_MAX_FACE_INDICES</code>.
+ */
+ uint mNumIndices;
+
+ /**
+ * Array of the indices defining the face.
+ *
+ * The size is given in <code>mNumIndices</code>.
+ */
+ uint* mIndices;
+ }
+
+ /**
+ * A single influence of a bone on a vertex.
+ */
+ struct aiVertexWeight {
+ /**
+ * Index of the vertex which is influenced by the bone.
+ */
+ uint mVertexId;
+
+ /**
+ * The strength of the influence in the range <code>[0..1]</code>.
+ *
+ * The influence from all bones at one vertex sums up to 1.
+ */
+ float mWeight;
+ }
+
+ /**
+ * A single bone of a mesh.
+ *
+ * A bone has a name by which it can be found in the frame hierarchy and by
+ * which it can be addressed by animations. In addition it has a number of
+ * influences on vertices.
+ */
+ struct aiBone {
+ /**
+ * The name of the bone.
+ */
+ aiString mName;
+
+ /**
+ * The number of vertices affected by this bone.
+ *
+ * The maximum value for this member is <code>AI_MAX_BONE_WEIGHTS</code>.
+ */
+ uint mNumWeights;
+
+ /**
+ * The vertices affected by this bone.
+ *
+ * This array is <code>mNumWeights</code> entries in size.
+ */
+ aiVertexWeight* mWeights;
+
+ /**
+ * Matrix that transforms from mesh space to bone space (in the bind
+ * pose).
+ */
+ aiMatrix4x4 mOffsetMatrix;
+ }
+
+ /**
+ * Enumerates the types of geometric primitives supported by Assimp.
+ *
+ * See: <code>aiFace</code>, <code>aiProcess.SortByPType</code>,
+ * <code>aiProcess.Triangulate</code>,
+ * <code>AI_CONFIG_PP_SBP_REMOVE</code>.
+ */
+ enum aiPrimitiveType : uint {
+ /** A point primitive.
+ *
+ * This is just a single vertex in the virtual world,
+ * <code>aiFace</code> contains just one index for such a primitive.
+ */
+ POINT = 0x1,
+
+ /** A line primitive.
+ *
+ * This is a line defined through a start and an end position.
+ * <code>aiFace</code> contains exactly two indices for such a primitive.
+ */
+ LINE = 0x2,
+
+ /** A triangular primitive.
+ *
+ * A triangle consists of three indices.
+ */
+ TRIANGLE = 0x4,
+
+ /** A higher-level polygon with more than 3 edges.
+ *
+ * A triangle is a polygon, but in this context, polygon means
+ * "all polygons that are not triangles". The <code>Triangulate</code>
+ * post processing step is provided for your convenience, it splits all
+ * polygons in triangles (which are much easier to handle).
+ */
+ POLYGON = 0x8
+ }
+
+ // Note: The AI_PRIMITIVE_TYPE_FOR_N_INDICES(n) macro from the C headers is
+ // missing since there is probably not much use for it when just reading
+ // scene files.
+
+ /**
+ * NOT CURRENTLY IN USE. An AnimMesh is an attachment to an #aiMesh stores
+ * per-vertex animations for a particular frame.
+ *
+ * You may think of an <code>aiAnimMesh</code> as a `patch` for the host
+ * mesh, which replaces only certain vertex data streams at a particular
+ * time.
+ *
+ * Each mesh stores n attached attached meshes (<code>aiMesh.mAnimMeshes</code>).
+ * The actual relationship between the time line and anim meshes is
+ * established by #aiMeshAnim, which references singular mesh attachments
+ * by their ID and binds them to a time offset.
+ */
+ struct aiAnimMesh {
+ /**
+ * 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 meshes may neither add or nor remove vertex components (if
+ * a replacement array is NULL and the corresponding source array is
+ * not, the source data is taken instead).
+ */
+ aiVector3D* mVertices;
+
+ /// Replacement for <code>aiMesh.mNormals</code>.
+ aiVector3D* mNormals;
+
+ /// Replacement for <code>aiMesh.mTangents</code>.
+ aiVector3D* mTangents;
+
+ /// Replacement for <code>aiMesh.mBitangents</code>.
+ aiVector3D* mBitangents;
+
+ /// Replacement for <code>aiMesh.mColors</code>.
+ aiColor4D* mColors[ AI_MAX_NUMBER_OF_COLOR_SETS ];
+
+ /// Replacement for <code>aiMesh.mTextureCoords</code>.
+ aiVector3D* mTextureCoords[ AI_MAX_NUMBER_OF_TEXTURECOORDS ];
+
+ /**
+ * The number of vertices in the aiAnimMesh, and thus the length of all
+ * the member arrays.
+ *
+ * This has always the same value as the mNumVertices property in the
+ * corresponding aiMesh. It is duplicated here merely to make the length
+ * of the member arrays accessible even if the aiMesh is not known, e.g.
+ * from language bindings.
+ */
+ uint mNumVertices;
+ }
+
+ /**
+ * A mesh represents a geometry or model with a single material.
+ *
+ * It usually consists of a number of vertices and a series
+ * primitives/faces referencing the vertices. In addition there might be a
+ * series of bones, each of them addressing a number of vertices with a
+ * certain weight. Vertex data is presented in channels with each channel
+ * containing a single per-vertex information such as a set of texture
+ * coords or a normal vector. If a data pointer is non-null, the
+ * corresponding data stream is present.
+ *
+ * A mesh uses only a single material which is referenced by a material ID.
+ *
+ * Note: The <code>mPositions</code> member is usually not optional.
+ * However, vertex positions <em>could</em> be missing if the
+ * <code>AI_SCENE_FLAGS_INCOMPLETE</code> flag is set in
+ * <code>aiScene.mFlags</code>.
+ */
+ struct aiMesh {
+ /**
+ * Bitwise combination of <code>aiPrimitiveType</code> members.
+ *
+ * This specifies which types of primitives are present in the mesh.
+ * The <code>SortByPrimitiveType</code> post processing step can be used
+ * to make sure the output meshes consist of one primitive type each.
+ */
+ uint mPrimitiveTypes;
+
+ /**
+ * The number of vertices in this mesh.
+ *
+ * This is also the size of all of the per-vertex data arrays. The
+ * maximum value for this member is <code>AI_MAX_VERTICES</code>.
+ */
+ uint mNumVertices;
+
+ /**
+ * The number of primitives (triangles, polygons, lines) in this mesh.
+ *
+ * This is also the size of the <code>mFaces</code> array. The maximum
+ * value for this member is <code>AI_MAX_FACES</code>.
+ */
+ uint mNumFaces;
+
+ /**
+ * Vertex positions.
+ *
+ * This array is always present in a mesh. The array is
+ * <code>mNumVertices</code> in size.
+ */
+ aiVector3D* mVertices;
+
+ /**
+ * Vertex normals.
+ *
+ * The array contains normalized vectors, null if not present.
+ * The array is <code>mNumVertices</code> in size.
+ *
+ * Normals are undefined for point and line primitives. A mesh
+ * consisting of points and lines only may not have normal vectors.
+ * Meshes with mixed primitive types (i.e. lines and triangles) may have
+ * normals, but the normals for vertices that are only referenced by
+ * point or line primitives are undefined and set to <code>QNAN</code>.
+ *
+ * Note: Normal vectors computed by Assimp are always unit-length.
+ * However, this needn't apply for normals that have been taken
+ * directly from the model file.
+ */
+ aiVector3D* mNormals;
+
+ /**
+ * Vertex tangents.
+ *
+ * The tangent of a vertex points in the direction of the positive x
+ * texture axis. The array contains normalized vectors, null if
+ * not present. The array is <code>mNumVertices</code> in size.
+ *
+ * A mesh consisting of points and lines only may not have normal
+ * vectors. Meshes with mixed primitive types (i.e. lines and triangles)
+ * may have normals, but the normals for vertices that are only
+ * referenced by point or line primitives are undefined and set to
+ * <code>QNAN</code>.
+ *
+ * Note: If the mesh contains tangents, it automatically also contains
+ * bitangents (the bitangent is just the cross product of tangent and
+ * normal vectors).
+ */
+ aiVector3D* mTangents;
+
+ /**
+ * Vertex bitangents.
+ *
+ * The bitangent of a vertex points in the direction of the positive Y
+ * texture axis. The array contains normalized vectors, null if not
+ * present. The array is <code>mNumVertices</code> in size.
+ *
+ * Note: If the mesh contains tangents, it automatically also contains
+ * bitangents.
+ */
+ aiVector3D* mBitangents;
+
+ /**
+ * Vertex color sets.
+ *
+ * A mesh may contain 0 to <code>AI_MAX_NUMBER_OF_COLOR_SETS</code>
+ * vertex colors per vertex. null if not present.
+ *
+ * Each array is <code>mNumVertices</code> in size if present.
+ */
+ aiColor4D* mColors[ AI_MAX_NUMBER_OF_COLOR_SETS ];
+
+ /**
+ * Vertex texture coords, also known as UV channels.
+ * A mesh may contain 0 to <code>AI_MAX_NUMBER_OF_TEXTURECOORDS</code>
+ * per vertex. null if not present.
+ *
+ * Each array is <code>mNumVertices</code> in size.
+ */
+ aiVector3D* mTextureCoords[ AI_MAX_NUMBER_OF_TEXTURECOORDS ];
+
+ /**
+ * Specifies the number of components for a given UV channel.
+ *
+ * Up to three channels are supported (UVW, for accessing volume or cube
+ * maps). If the value is 2 for a given channel <code>n</code>, the
+ * component <code>p.z</code> of <code>mTextureCoords[n][p]</code> is set
+ * to 0. If the value is 1 for a given channel, <code>p.y</code> is set
+ * to 0, too. If this value is 0, 2 should be assumed.
+ *
+ * Note: 4D coords are not supported.
+ */
+ uint mNumUVComponents[ AI_MAX_NUMBER_OF_TEXTURECOORDS ];
+
+ /**
+ * The faces the mesh is contstructed from.
+ *
+ * Each face refers to a number of vertices by their indices.
+ * This array is always present in a mesh, its size is given
+ * in <code>mNumFaces</code>. If the
+ * <code>AI_SCENE_FLAGS_NON_VERBOSE_FORMAT</code> is <em>not</em> set,
+ * each face references an unique set of vertices.
+ */
+ aiFace* mFaces;
+
+ /**
+ * The number of bones this mesh contains.
+ *
+ * Can be 0, in which case the <code>mBones</code> array is null.
+ */
+ uint mNumBones;
+
+ /**
+ * The bones of this mesh.
+ *
+ * A bone consists of a name by which it can be found in the frame
+ * hierarchy and a set of vertex weights.
+ */
+ aiBone** mBones;
+
+ /**
+ * The material used by this mesh.
+ *
+ * A mesh does use only a single material. If an imported model uses
+ * multiple materials, the import splits up the mesh. Use this value as
+ * index into the scene's material list.
+ */
+ uint mMaterialIndex;
+
+ /**
+ * Name of the mesh.
+ *
+ * Meshes can be named, but this is not a requirement and leaving this
+ * field empty is totally fine.
+ *
+ * There are mainly three uses for mesh names:
+ * - Some formats name nodes and meshes independently.
+ * - Importers tend to split meshes up to meet the one-material-per-mesh
+ * requirement. Assigning the same (dummy) name to each of the result
+ * meshes aids the caller at recovering the original mesh partitioning.
+ * - Vertex animations refer to meshes by their names.
+ */
+ aiString mName;
+
+ /// NOT CURRENTLY IN USE. The number of attachment meshes.
+ uint mNumAnimMeshes;
+
+ /**
+ * NOT CURRENTLY IN USE. Attachment meshes for this mesh, for vertex-
+ * based animation.
+ *
+ * Attachment meshes carry replacement data for some of the mesh's
+ * vertex components (usually positions, normals).
+ */
+ aiAnimMesh** mAnimMeshes;
+ }
+}
diff --git a/libs/assimp/port/dAssimp/assimp/postprocess.d b/libs/assimp/port/dAssimp/assimp/postprocess.d
new file mode 100644
index 0000000..343bb36
--- /dev/null
+++ b/libs/assimp/port/dAssimp/assimp/postprocess.d
@@ -0,0 +1,597 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, ASSIMP Development 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 Development 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.
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Definitions for import post processing steps.
+ */
+module assimp.postprocess;
+
+extern ( C ) {
+ /**
+ * Defines the flags for all possible post processing steps.
+ *
+ * See: <code>aiImportFile</code>, <code>aiImportFileEx</code>
+ */
+ enum aiPostProcessSteps {
+ /**
+ * Calculates the tangents and bitangents for the imported meshes.
+ *
+ * Does nothing if a mesh does not have normals. You might want this post
+ * processing step to be executed if you plan to use tangent space
+ * calculations such as normal mapping applied to the meshes. There is a
+ * config setting, <code>AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE</code>,
+ * which allows you to specify a maximum smoothing angle for the
+ * algorithm. However, usually you will want to use the default value.
+ */
+ CalcTangentSpace = 0x1,
+
+ /**
+ * Identifies and joins identical vertex data sets within all imported
+ * meshes.
+ *
+ * After this step is run each mesh does contain only unique vertices
+ * anymore, so a vertex is possibly used by multiple faces. You usually
+ * want to use this post processing step. If your application deals with
+ * indexed geometry, this step is compulsory or you will just waste
+ * rendering time. <em>If this flag is not specified</em>, no vertices
+ * are referenced by more than one face and <em>no index buffer is
+ * required</em> for rendering.
+ */
+ JoinIdenticalVertices = 0x2,
+
+ /**
+ * Converts all the imported data to a left-handed coordinate space.
+ *
+ * By default the data is returned in a right-handed coordinate space
+ * which for example OpenGL prefers. In this space, +X points to the
+ * right, +Z points towards the viewer and and +Y points upwards. In the
+ * DirectX coordinate space +X points to the right, +Y points upwards and
+ * +Z points away from the viewer.
+ *
+ * You will probably want to consider this flag if you use Direct3D for
+ * rendering. The <code>ConvertToLeftHanded</code> flag supersedes this
+ * setting and bundles all conversions typically required for D3D-based
+ * applications.
+ */
+ MakeLeftHanded = 0x4,
+
+ /**
+ * Triangulates all faces of all meshes.
+ *
+ * By default the imported mesh data might contain faces with more than 3
+ * indices. For rendering you'll usually want all faces to be triangles.
+ * This post processing step splits up all higher faces to triangles.
+ * Line and point primitives are <em>not</em> modified!.
+ *
+ * If you want »triangles only« with no other kinds of primitives,
+ * specify both <code>Triangulate</code> and <code>SortByPType</code> and
+ * ignore all point and line meshes when you process Assimp's output.
+ */
+ Triangulate = 0x8,
+
+ /**
+ * Removes some parts of the data structure (animations, materials, light
+ * sources, cameras, textures, vertex components).
+ *
+ * The components to be removed are specified in a separate configuration
+ * option, <code>AI_CONFIG_PP_RVC_FLAGS</code>. This is quite useful if
+ * you don't need all parts of the output structure. Especially vertex
+ * colors are rarely used today.
+ *
+ * Calling this step to remove unrequired stuff from the pipeline as
+ * early as possible results in an increased performance and a better
+ * optimized output data structure.
+ *
+ * This step is also useful if you want to force Assimp to recompute
+ * normals or tangents since the corresponding steps don't recompute them
+ * if they have already been loaded from the source asset.
+ *
+ * This flag is a poor one, mainly because its purpose is usually
+ * misunderstood. Consider the following case: a 3d model has been exported
+ * from a CAD app, it has per-face vertex colors. Because of the vertex
+ * colors (which are not even used by most apps),
+ * <code>JoinIdenticalVertices</code> cannot join vertices at the same
+ * position. By using this step, unneeded components are excluded as
+ * early as possible thus opening more room for internal optimzations.
+ */
+ RemoveComponent = 0x10,
+
+ /**
+ * Generates normals for all faces of all meshes.
+ *
+ * This is ignored if normals are already there at the time where this
+ * flag is evaluated. Model importers try to load them from the source
+ * file, so they are usually already there. Face normals are shared
+ * between all points of a single face, so a single point can have
+ * multiple normals, which, in other words, enforces the library to
+ * duplicate vertices in some cases. <code>JoinIdenticalVertices</code>
+ * is <em>useless</em> then.
+ *
+ * This flag may not be specified together with
+ * <code>GenSmoothNormals</code>.
+ */
+ GenNormals = 0x20,
+
+ /**
+ * Generates smooth normals for all vertices in the mesh.
+ *
+ * This is ignored if normals are already there at the time where this
+ * flag is evaluated. Model importers try to load them from the source file, so
+ * they are usually already there.
+ *
+ * There is a configuration option,
+ * <code>AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE</code> which allows you to
+ * specify an angle maximum for the normal smoothing algorithm. Normals
+ * exceeding this limit are not smoothed, resulting in a »hard« seam
+ * between two faces. Using a decent angle here (e.g. 80°) results in
+ * very good visual appearance.
+ */
+ GenSmoothNormals = 0x40,
+
+ /**
+ * Splits large meshes into smaller submeshes.
+ *
+ * This is quite useful for realtime rendering where the number of triangles
+ * which can be maximally processed in a single draw-call is usually limited
+ * by the video driver/hardware. The maximum vertex buffer is usually limited,
+ * too. Both requirements can be met with this step: you may specify both a
+ * triangle and vertex limit for a single mesh.
+ *
+ * The split limits can (and should!) be set through the
+ * <code>AI_CONFIG_PP_SLM_VERTEX_LIMIT</code> and
+ * <code>AI_CONFIG_PP_SLM_TRIANGLE_LIMIT</code> settings. The default
+ * values are <code>AI_SLM_DEFAULT_MAX_VERTICES</code> and
+ * <code>AI_SLM_DEFAULT_MAX_TRIANGLES</code>.
+ *
+ * Note that splitting is generally a time-consuming task, but not if
+ * there's nothing to split. The use of this step is recommended for most
+ * users.
+ */
+ SplitLargeMeshes = 0x80,
+
+ /**
+ * Removes the node graph and pre-transforms all vertices with the local
+ * transformation matrices of their nodes.
+ *
+ * The output scene does still contain nodes, however, there is only a
+ * root node with children, each one referencing only one mesh, each
+ * mesh referencing one material. For rendering, you can simply render
+ * all meshes in order, you don't need to pay attention to local
+ * transformations and the node hierarchy. Animations are removed during
+ * this step.
+ *
+ * This step is intended for applications that have no scenegraph.
+ *
+ * The step <em>can</em> cause some problems: if e.g. a mesh of the asset
+ * contains normals and another, using the same material index, does not,
+ * they will be brought together, but the first meshes's part of the
+ * normal list is zeroed. However, these artifacts are rare.
+ *
+ * Note: The <code>AI_CONFIG_PP_PTV_NORMALIZE</code> configuration
+ * property can be set to normalize the scene's spatial dimension
+ * to the -1...1 range.
+ */
+ PreTransformVertices = 0x100,
+
+ /**
+ * Limits the number of bones simultaneously affecting a single vertex to
+ * a maximum value.
+ *
+ * If any vertex is affected by more than that number of bones, the least
+ * important vertex weights are removed and the remaining vertex weights
+ * are renormalized so that the weights still sum up to 1.
+ *
+ * The default bone weight limit is 4 (<code>AI_LMW_MAX_WEIGHTS</code>),
+ * but you can use the <code>#AI_CONFIG_PP_LBW_MAX_WEIGHTS</code> setting
+ * to supply your own limit to the post processing step.
+ *
+ * If you intend to perform the skinning in hardware, this post processing
+ * step might be of interest for you.
+ */
+ LimitBoneWeights = 0x200,
+
+ /**
+ * Validates the imported scene data structure.
+ *
+ * This makes sure that all indices are valid, all animations and
+ * bones are linked correctly, all material references are correct, etc.
+ *
+ * It is recommended to capture Assimp's log output if you use this flag,
+ * so you can easily find ot what's actually wrong if a file fails the
+ * validation. The validator is quite rude and will find <em>all</em>
+ * inconsistencies in the data structure.
+ *
+ * Plugin developers are recommended to use it to debug their loaders.
+ *
+ * There are two types of validation failures:
+ * <ul>
+ * <li>Error: There's something wrong with the imported data. Further
+ * postprocessing is not possible and the data is not usable at all.
+ * The import fails, see <code>aiGetErrorString()</code> for the
+ * error message.</li>
+ * <li>Warning: There are some minor issues (e.g. 1000000 animation
+ * keyframes with the same time), but further postprocessing and use
+ * of the data structure is still safe. Warning details are written
+ * to the log file, <code>AI_SCENE_FLAGS_VALIDATION_WARNING</code> is
+ * set in <code>aiScene::mFlags</code></li>
+ * </ul>
+ *
+ * This post-processing step is not time-consuming. It's use is not
+ * compulsory, but recommended.
+ */
+ ValidateDataStructure = 0x400,
+
+ /**
+ * Reorders triangles for better vertex cache locality.
+ *
+ * The step tries to improve the ACMR (average post-transform vertex cache
+ * miss ratio) for all meshes. The implementation runs in O(n) and is
+ * roughly based on the 'tipsify' algorithm (see
+ * <tt>http://www.cs.princeton.edu/gfx/pubs/Sander_2007_%3ETR/tipsy.pdf</tt>).
+ *
+ * If you intend to render huge models in hardware, this step might
+ * be of interest for you. The <code>AI_CONFIG_PP_ICL_PTCACHE_SIZE</code>
+ * config setting can be used to fine-tune the cache optimization.
+ */
+ ImproveCacheLocality = 0x800,
+
+ /**
+ * Searches for redundant/unreferenced materials and removes them.
+ *
+ * This is especially useful in combination with the
+ * <code>PretransformVertices</code> and <code>OptimizeMeshes</code>
+ * flags. Both join small meshes with equal characteristics, but they
+ * can't do their work if two meshes have different materials. Because
+ * several material settings are always lost during Assimp's import
+ * filters, (and because many exporters don't check for redundant
+ * materials), huge models often have materials which are are defined
+ * several times with exactly the same settings.
+ *
+ * Several material settings not contributing to the final appearance of
+ * a surface are ignored in all comparisons; the material name is one of
+ * them. So, if you are passing additional information through the
+ * content pipeline (probably using »magic« material names), don't
+ * specify this flag. Alternatively take a look at the
+ * <code>AI_CONFIG_PP_RRM_EXCLUDE_LIST</code> setting.
+ */
+ RemoveRedundantMaterials = 0x1000,
+
+ /**
+ * This step tries to determine which meshes have normal vectors that are
+ * acing inwards.
+ *
+ * The algorithm is simple but effective: The bounding box of all
+ * vertices and their normals is compared against the volume of the
+ * bounding box of all vertices without their normals. This works well
+ * for most objects, problems might occur with planar surfaces. However,
+ * the step tries to filter such cases.
+ *
+ * The step inverts all in-facing normals. Generally it is recommended to
+ * enable this step, although the result is not always correct.
+ */
+ FixInfacingNormals = 0x2000,
+
+ /**
+ * This step splits meshes with more than one primitive type in
+ * homogeneous submeshes.
+ *
+ * The step is executed after the triangulation step. After the step
+ * returns, just one bit is set in <code>aiMesh.mPrimitiveTypes</code>.
+ * This is especially useful for real-time rendering where point and line
+ * primitives are often ignored or rendered separately.
+ *
+ * You can use the <code>AI_CONFIG_PP_SBP_REMOVE</code> option to
+ * specify which primitive types you need. This can be used to easily
+ * exclude lines and points, which are rarely used, from the import.
+ */
+ SortByPType = 0x8000,
+
+ /**
+ * This step searches all meshes for degenerated primitives and converts
+ * them to proper lines or points.
+ *
+ * A face is »degenerated« if one or more of its points are identical.
+ * To have the degenerated stuff not only detected and collapsed but also
+ * removed, try one of the following procedures:
+ *
+ * <b>1.</b> (if you support lines and points for rendering but don't
+ * want the degenerates)
+ * <ul>
+ * <li>Specify the <code>FindDegenerates</code> flag.</li>
+ * <li>Set the <code>AI_CONFIG_PP_FD_REMOVE</code> option to 1. This will
+ * cause the step to remove degenerated triangles from the import
+ * as soon as they're detected. They won't pass any further
+ * pipeline steps.</li>
+ * </ul>
+ *
+ * <b>2.</b>(if you don't support lines and points at all ...)
+ * <ul>
+ * <li>Specify the <code>FindDegenerates</code> flag.</li>
+ * <li>Specify the <code>SortByPType</code> flag. This moves line and
+ * point primitives to separate meshes.</li>
+ * <li>Set the <code>AI_CONFIG_PP_SBP_REMOVE</codet> option to
+ * <code>aiPrimitiveType_POINTS | aiPrimitiveType_LINES</code>
+ * to cause SortByPType to reject point and line meshes from the
+ * scene.</li>
+ * </ul>
+ *
+ * Note: Degenerated polygons are not necessarily bad and that's why
+ * they're not removed by default. There are several file formats
+ * which don't support lines or points. Some exporters bypass the
+ * format specification and write them as degenerated triangle
+ * instead.
+ */
+ FindDegenerates = 0x10000,
+
+ /**
+ * This step searches all meshes for invalid data, such as zeroed normal
+ * vectors or invalid UV coords and removes/fixes them. This is intended
+ * to get rid of some common exporter errors.
+ *
+ * This is especially useful for normals. If they are invalid, and the
+ * step recognizes this, they will be removed and can later be
+ * recomputed, e.g. by the <code>GenSmoothNormals</code> step.
+ *
+ * The step will also remove meshes that are infinitely small and reduce
+ * animation tracks consisting of hundreds if redundant keys to a single
+ * key. The <code>AI_CONFIG_PP_FID_ANIM_ACCURACY</code> config property
+ * decides the accuracy of the check for duplicate animation tracks.
+ */
+ FindInvalidData = 0x20000,
+
+ /**
+ * This step converts non-UV mappings (such as spherical or cylindrical
+ * mapping) to proper texture coordinate channels.
+ *
+ * Most applications will support UV mapping only, so you will probably
+ * want to specify this step in every case. Note tha Assimp is not always
+ * able to match the original mapping implementation of the 3d app which
+ * produced a model perfectly. It's always better to let the father app
+ * compute the UV channels, at least 3ds max, maja, blender, lightwave,
+ * modo, ... are able to achieve this.
+ *
+ * Note: If this step is not requested, you'll need to process the
+ * <code>AI_MATKEY_MAPPING</code> material property in order to
+ * display all assets properly.
+ */
+ GenUVCoords = 0x40000,
+
+ /**
+ * This step applies per-texture UV transformations and bakes them to
+ * stand-alone vtexture coordinate channelss.
+ *
+ * UV transformations are specified per-texture – see the
+ * <code>AI_MATKEY_UVTRANSFORM</code> material key for more information.
+ * This step processes all textures with transformed input UV coordinates
+ * and generates new (pretransformed) UV channel which replace the old
+ * channel. Most applications won't support UV transformations, so you
+ * will probably want to specify this step.
+ *
+ * Note: UV transformations are usually implemented in realtime apps by
+ * transforming texture coordinates at vertex shader stage with a 3x3
+ * (homogenous) transformation matrix.
+ */
+ TransformUVCoords = 0x80000,
+
+ /**
+ * This step searches for duplicate meshes and replaces duplicates with
+ * references to the first mesh.
+ *
+ * This step takes a while, don't use it if you have no time. Its main
+ * purpose is to workaround the limitation that many export file formats
+ * don't support instanced meshes, so exporters need to duplicate meshes.
+ * This step removes the duplicates again. Please note that Assimp does
+ * currently not support per-node material assignment to meshes, which
+ * means that identical meshes with differnent materials are currently
+ * <em>not</em> joined, although this is planned for future versions.
+ */
+ FindInstances = 0x100000,
+
+ /**
+ * A postprocessing step to reduce the number of meshes.
+ *
+ * In fact, it will reduce the number of drawcalls.
+ *
+ * This is a very effective optimization and is recommended to be used
+ * together with <code>OptimizeGraph</code>, if possible. The flag is
+ * fully compatible with both <code>SplitLargeMeshes</code> and
+ * <code>SortByPType</code>.
+ */
+ OptimizeMeshes = 0x200000,
+
+ /**
+ * A postprocessing step to optimize the scene hierarchy.
+ *
+ * Nodes with no animations, bones, lights or cameras assigned are
+ * collapsed and joined.
+ *
+ * Node names can be lost during this step. If you use special tag nodes
+ * to pass additional information through your content pipeline, use the
+ * <code>AI_CONFIG_PP_OG_EXCLUDE_LIST</code> setting to specify a list of
+ * node names you want to be kept. Nodes matching one of the names in
+ * this list won't be touched or modified.
+ *
+ * Use this flag with caution. Most simple files will be collapsed to a
+ * single node, complex hierarchies are usually completely lost. That's
+ * note the right choice for editor environments, but probably a very
+ * effective optimization if you just want to get the model data, convert
+ * it to your own format and render it as fast as possible.
+ *
+ * This flag is designed to be used with <code>OptimizeMeshes</code> for
+ * best results.
+ *
+ * Note: »Crappy« scenes with thousands of extremely small meshes packed
+ * in deeply nested nodes exist for almost all file formats.
+ * <code>OptimizeMeshes</code> in combination with
+ * <code>OptimizeGraph</code> usually fixes them all and makes them
+ * renderable.
+ */
+ OptimizeGraph = 0x400000,
+
+ /** This step flips all UV coordinates along the y-axis and adjusts
+ * material settings and bitangents accordingly.
+ *
+ * Output UV coordinate system:
+ * <pre> 0y|0y ---------- 1x|0y
+ * | |
+ * | |
+ * | |
+ * 0x|1y ---------- 1x|1y</pre>
+ * You'll probably want to consider this flag if you use Direct3D for
+ * rendering. The <code>AI_PROCESS_CONVERT_TO_LEFT_HANDED</code> flag
+ * supersedes this setting and bundles all conversions typically required
+ * for D3D-based applications.
+ */
+ FlipUVs = 0x800000,
+
+ /**
+ * This step adjusts the output face winding order to be clockwise.
+ *
+ * The default face winding order is counter clockwise.
+ *
+ * Output face order:
+ * <pre> x2
+ *
+ * x0
+ * x1</pre>
+ */
+ FlipWindingOrder = 0x1000000
+ }
+
+ /**
+ * Abbrevation for convenience.
+ */
+ alias aiPostProcessSteps aiProcess;
+
+ /**
+ * Shortcut flag for Direct3D-based applications.
+ *
+ * Combines the <code>MakeLeftHanded</code>, <code>FlipUVs</code> and
+ * <code>FlipWindingOrder</code> flags. The output data matches Direct3D's
+ * conventions: left-handed geometry, upper-left origin for UV coordinates
+ * and clockwise face order, suitable for CCW culling.
+ */
+ const aiPostProcessSteps AI_PROCESS_CONVERT_TO_LEFT_HANDED =
+ aiProcess.MakeLeftHanded |
+ aiProcess.FlipUVs |
+ aiProcess.FlipWindingOrder;
+
+ /**
+ * Default postprocess configuration optimizing the data for real-time rendering.
+ *
+ * Applications would want to use this preset to load models on end-user
+ * PCs, maybe for direct use in game.
+ *
+ * If you're using DirectX, don't forget to combine this value with
+ * the <code>ConvertToLeftHanded</code> step. If you don't support UV
+ * transformations in your application, apply the
+ * <code>TransformUVCoords</code> step, too.
+ *
+ * Note: Please take the time to read the doc for the steps enabled by this
+ * preset. Some of them offer further configurable properties, some of
+ * them might not be of use for you so it might be better to not specify
+ * them.
+ */
+ const aiPostProcessSteps AI_PROCESS_PRESET_TARGET_REALTIME_FAST =
+ aiProcess.CalcTangentSpace |
+ aiProcess.GenNormals |
+ aiProcess.JoinIdenticalVertices |
+ aiProcess.Triangulate |
+ aiProcess.GenUVCoords |
+ aiProcess.SortByPType;
+
+ /**
+ * Default postprocess configuration optimizing the data for real-time
+ * rendering.
+ *
+ * Unlike <code>AI_PROCESS_PRESET_TARGET_REALTIME_FAST</code>, this
+ * configuration performs some extra optimizations to improve rendering
+ * speed and to minimize memory usage. It could be a good choice for a
+ * level editor environment where import speed is not so important.
+ *
+ * If you're using DirectX, don't forget to combine this value with
+ * the <code>ConvertToLeftHanded</code> step. If you don't support UV
+ * transformations in your application, apply the
+ * <code>TransformUVCoords</code> step, too.
+ *
+ * Note: Please take the time to read the doc for the steps enabled by this
+ * preset. Some of them offer further configurable properties, some of
+ * them might not be of use for you so it might be better to not specify
+ * them.
+ */
+ const aiPostProcessSteps AI_PROCESS_PRESET_TARGET_REALTIME_QUALITY =
+ aiProcess.CalcTangentSpace |
+ aiProcess.GenSmoothNormals |
+ aiProcess.JoinIdenticalVertices |
+ aiProcess.ImproveCacheLocality |
+ aiProcess.LimitBoneWeights |
+ aiProcess.RemoveRedundantMaterials |
+ aiProcess.SplitLargeMeshes |
+ aiProcess.Triangulate |
+ aiProcess.GenUVCoords |
+ aiProcess.SortByPType |
+ aiProcess.FindDegenerates |
+ aiProcess.FindInvalidData;
+
+ /**
+ * Default postprocess configuration optimizing the data for real-time
+ * rendering.
+ *
+ * This preset enables almost every optimization step to achieve perfectly
+ * optimized data. It's your choice for level editor environments where
+ * import speed is not important.
+ *
+ * If you're using DirectX, don't forget to combine this value with
+ * the <code>ConvertToLeftHanded</code> step. If you don't support UV
+ * transformations in your application, apply the
+ * <code>TransformUVCoords</code> step, too.
+ *
+ * Note: Please take the time to read the doc for the steps enabled by this
+ * preset. Some of them offer further configurable properties, some of
+ * them might not be of use for you so it might be better to not specify
+ * them.
+ */
+ const aiPostProcessSteps AI_PROCESS_PRESET_TARGET_REALTIME_MAX_QUALITY =
+ AI_PROCESS_PRESET_TARGET_REALTIME_QUALITY |
+ aiProcess.FindInstances |
+ aiProcess.ValidateDataStructure |
+ aiProcess.OptimizeMeshes;
+}
diff --git a/libs/assimp/port/dAssimp/assimp/scene.d b/libs/assimp/port/dAssimp/assimp/scene.d
new file mode 100644
index 0000000..deee75a
--- /dev/null
+++ b/libs/assimp/port/dAssimp/assimp/scene.d
@@ -0,0 +1,306 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, ASSIMP Development 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 Development 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.
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Contains the data structures which store the hierarchy fo the imported data.
+ */
+module assimp.scene;
+
+import assimp.animation;
+import assimp.camera;
+import assimp.light;
+import assimp.math;
+import assimp.mesh;
+import assimp.material;
+import assimp.texture;
+import assimp.types;
+
+extern ( C ) {
+ /**
+ * A node in the imported hierarchy.
+ *
+ * Each node has name, a parent node (except for the root node), a
+ * transformation relative to its parent and possibly several child nodes.
+ * Simple file formats don't support hierarchical structures, for these
+ * formats the imported scene does consist of only a single root node with
+ * no childs.
+ */
+ struct aiNode {
+ /**
+ * The name of the node.
+ *
+ * The name might be empty (length of zero) but all nodes which need to
+ * be accessed afterwards by bones or animations are usually named.
+ * Multiple nodes may have the same name, but nodes which are accessed
+ * by bones (see <code>aiBone</code> and <code>aiMesh.mBones</code>)
+ * <em>must</em> be unique.
+ *
+ * Cameras and lights are assigned to a specific node name – if there are
+ * multiple nodes with this name, they are assigned to each of them.
+ *
+ * There are no limitations regarding the characters contained in this
+ * string. You should be able to handle stuff like whitespace, tabs,
+ * linefeeds, quotation marks, ampersands, …
+ */
+ aiString mName;
+
+ /**
+ * The transformation relative to the node's parent.
+ */
+ aiMatrix4x4 mTransformation;
+
+ /**
+ * Parent node.
+ *
+ * null if this node is the root node.
+ */
+ aiNode* mParent;
+
+ /**
+ * The number of child nodes of this node.
+ */
+ uint mNumChildren;
+
+ /**
+ * The child nodes of this node.
+ *
+ * null if <code>mNumChildren</code> is 0.
+ */
+ aiNode** mChildren;
+
+ /**
+ * The number of meshes of this node.
+ */
+ int mNumMeshes;
+
+ /**
+ * The meshes of this node.
+ *
+ * Each entry is an index for <code>aiScene.mMeshes</code>.
+ */
+ uint* mMeshes;
+ }
+
+ /**
+ * Flags which are combinated in <code>aiScene.mFlags</code> to store
+ * auxiliary information about the imported scene.
+ */
+ enum aiSceneFlags : uint {
+ /**
+ * Specifies that the scene data structure that was imported is not
+ * complete.
+ *
+ * This flag bypasses some internal validations and allows the import of
+ * animation skeletons, material libraries or camera animation paths
+ * using Assimp. Most applications won't support such data.
+ */
+ INCOMPLETE = 0x1,
+
+ /**
+ * This flag is set by the validation post-processing step
+ * (<code>aiProcess.ValidateDS</code>) if the validation was successful.
+ *
+ * In a validated scene you can be sure that any cross references in the
+ * data structure (e.g. vertex indices) are valid.
+ */
+ VALIDATED = 0x2,
+
+ /**
+ * This flag is set by the validation post-processing step
+ * (<code>aiProcess.ValidateDS</code>) if the validation is successful
+ * but some issues have been found.
+ *
+ * This can for example mean that a texture that does not exist is
+ * referenced by a material or that the bone weights for a vertex don't
+ * sum to 1. In most cases you should still be able to use the import.
+ *
+ * This flag could be useful for applications which don't capture
+ * Assimp's log output.
+ */
+ VALIDATION_WARNING = 0x4,
+
+ /**
+ * This flag is currently only set by the
+ * <code>aiProcess.JoinIdenticalVertices</code> post-processing step. It
+ * indicates that the vertices of the output meshes aren't in the
+ * internal verbose format anymore. In the verbose format all vertices
+ * are unique, no vertex is ever referenced by more than one face.
+ */
+ NON_VERBOSE_FORMAT = 0x8,
+
+ /**
+ * Denotes pure height-map terrain data. Pure terrains usually consist of
+ * quads, sometimes triangles, in a regular grid. The x,y coordinates of
+ * all vertex positions refer to the x,y coordinates on the terrain
+ * height map, the z-axis stores the elevation at a specific point.
+ *
+ * TER (Terragen) and HMP (3D Game Studio) are height map formats.
+ *
+ * Note: Assimp is probably not the best choice for loading <em>huge</em>
+ * terrains – fully triangulated data takes extremely much storage
+ * space and should be avoided as long as possible (typically you will
+ * perform the triangulation when you actually need to render it).
+ */
+ FLAGS_TERRAIN = 0x10
+ }
+
+ /**
+ * The root structure of the imported data.
+ *
+ * Everything that was imported from the given file can be accessed from here.
+ * Objects of this class are generally maintained and owned by Assimp, not
+ * by the caller. You shouldn't want to instance it, nor should you ever try to
+ * delete a given scene on your own.
+ */
+ struct aiScene {
+ /**
+ * Any combination of the <code>aiSceneFlags</code>. By default, this
+ * value is 0, no flags are set.
+ *
+ * Most applications will want to reject all scenes with the
+ * <code>aiSceneFlags.INCOMPLETE</code> bit set.
+ */
+ uint mFlags;
+
+ /**
+ * The root node of the hierarchy.
+ *
+ * There will always be at least the root node if the import was
+ * successful (and no special flags have been set). Presence of further
+ * nodes depends on the format and contents of the imported file.
+ */
+ aiNode* mRootNode;
+
+ /**
+ * The number of meshes in the scene.
+ */
+ uint mNumMeshes;
+
+ /**
+ * The array of meshes.
+ *
+ * Use the indices given in the <code>aiNode</code> structure to access
+ * this array. The array is <code>mNumMeshes</code> in size.
+ *
+ * If the <code>aiSceneFlags.INCOMPLETE</code> flag is not set, there
+ * will always be at least one mesh.
+ */
+ aiMesh** mMeshes;
+
+ /**
+ * The number of materials in the scene.
+ */
+ uint mNumMaterials;
+
+ /**
+ * The array of meshes.
+ *
+ * Use the indices given in the <code>aiMesh</code> structure to access
+ * this array. The array is <code>mNumMaterials</code> in size.
+ *
+ * If the <code>aiSceneFlags.INCOMPLETE</code> flag is not set, there
+ * will always be at least one material.
+ */
+ aiMaterial** mMaterials;
+
+ /**
+ * The number of animations in the scene.
+ */
+ uint mNumAnimations;
+
+ /**
+ * The array of animations.
+ *
+ * All animations imported from the given file are listed here. The array
+ * is <code>mNumAnimations</code> in size.
+ */
+ aiAnimation** mAnimations;
+
+ /**
+ * The number of textures embedded into the file.
+ */
+ uint mNumTextures;
+
+ /**
+ * The array of embedded textures.
+ *
+ * Not many file formats embed their textures into the file. An example
+ * is Quake's <code>MDL</code> format (which is also used by some
+ * GameStudio versions).
+ */
+ aiTexture** mTextures;
+
+ /**
+ * The number of light sources in the scene.
+ *
+ * Light sources are fully optional, in most cases this attribute will be
+ * 0.
+ */
+ uint mNumLights;
+
+ /**
+ * The array of light sources.
+ *
+ * All light sources imported from the given file are listed here. The
+ * array is <code>mNumLights</code> in size.
+ */
+ aiLight** mLights;
+
+ /**
+ * The number of cameras in the scene.
+ *
+ * Cameras are fully optional, in most cases this attribute
+ * will be 0.
+ */
+ uint mNumCameras;
+
+ /**
+ * The array of cameras.
+ *
+ * All cameras imported from the given file are listed here. The array is
+ * <code>mNumCameras</code> in size.
+ *
+ * The first camera in the array (if existing) is the default camera view
+ * at the scene.
+ */
+ aiCamera** mCameras;
+ }
+}
diff --git a/libs/assimp/port/dAssimp/assimp/texture.d b/libs/assimp/port/dAssimp/assimp/texture.d
new file mode 100644
index 0000000..83453b9
--- /dev/null
+++ b/libs/assimp/port/dAssimp/assimp/texture.d
@@ -0,0 +1,122 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, ASSIMP Development 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 Development 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.
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Contains helper structures to handle textures in Assimp.
+ *
+ * Used for file formats which embed their textures into the model file.
+ * Supported are both normal textures, which are stored as uncompressed pixels,
+ * and "compressed" textures, which are stored in a file format such as PNG or
+ * TGA.
+ */
+module assimp.texture;
+
+extern ( C ) {
+ /**
+ * Helper structure to represent a texel in a ARGB8888 format.
+ *
+ * Used by aiTexture.
+ */
+ struct aiTexel {
+ align ( 1 ):
+ ubyte b, g, r, a;
+ }
+
+ /**
+ * Helper structure to describe an embedded texture.
+ *
+ * Usually textures are contained in external files but some file formats
+ * embed them directly in the model file. There are two types of
+ * embedded textures:
+ *
+ * <em>1. Uncompressed textures</em>: The color data is given in an
+ * uncompressed format.
+ *
+ * <em>2. Compressed textures</em> stored in a file format like PNG or JPEG.
+ * The raw file bytes are given so the application must utilize an image
+ * decoder (e.g. DevIL) to get access to the actual color data.
+ */
+ struct aiTexture {
+ /**
+ * Width of the texture, in pixels.
+ *
+ * If <code>mHeight</code> is zero the texture is compressed in a format
+ * like JPEG. In this case, this value specifies the size of the memory
+ * area <code>pcData</code> is pointing to, in bytes.
+ */
+ uint mWidth;
+
+ /**
+ * Height of the texture, in pixels.
+ *
+ * If this value is zero, <code>pcData</code> points to an compressed
+ * texture in any format (e.g. JPEG).
+ */
+ uint mHeight;
+
+ /**
+ * A hint from the loader to make it easier for applications to determine
+ * the type of embedded compressed textures.
+ *
+ * If <code>mHeight</code> is not 0, this member is undefined. Otherwise
+ * it is set set to '\0\0\0\0' if the loader has no additional
+ * information about the texture file format used, or the file extension
+ * of the format without a trailing dot. If there are multiple file
+ * extensions for a format, the shortest extension is chosen (JPEG maps
+ * to 'jpg', not to 'jpeg'). E.g. 'dds\0', 'pcx\0', 'jpg\0'. All
+ * characters are lower-case. The fourth byte will always be '\0'.
+ */
+ char achFormatHint[4];
+
+ /**
+ * Data of the texture.
+ *
+ * Points to an array of <code>mWidth * mHeight</code>
+ * <code>aiTexel</code>s. The format of the texture data is always
+ * ARGB8888 to make the implementation for user of the library as easy as
+ * possible.
+ *
+ * If <code>mHeight</code> is 0, this is a pointer to a memory buffer of
+ * size <code>mWidth</code> containing the compressed texture data.
+ */
+ aiTexel* pcData;
+ }
+}
diff --git a/libs/assimp/port/dAssimp/assimp/types.d b/libs/assimp/port/dAssimp/assimp/types.d
new file mode 100644
index 0000000..5aa4d54
--- /dev/null
+++ b/libs/assimp/port/dAssimp/assimp/types.d
@@ -0,0 +1,249 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, ASSIMP Development 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 Development 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.
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Contains miscellaneous types used in Assimp's C API.
+ */
+module assimp.types;
+
+extern ( C ) {
+ /**
+ * Our own C boolean type.
+ */
+ enum aiBool : int {
+ FALSE = 0,
+ TRUE = 1
+ }
+
+ /**
+ * Type definition for log stream callback function pointers.
+ */
+ alias void function( char* message, char* user ) aiLogStreamCallback;
+
+ /**
+ * Represents a log stream. A log stream receives all log messages and
+ * streams them somewhere.
+ *
+ * See: <code>aiGetPredefinedLogStream</code>,
+ * <code>aiAttachLogStream</code> and <code>aiDetachLogStream</code>.
+ */
+ struct aiLogStream {
+ /**
+ * Callback function to be called when a new message arrives.
+ */
+ aiLogStreamCallback callback;
+
+ /**
+ * User data to be passed to the callback.
+ */
+ char* user;
+ }
+
+ /**
+ * Maximum dimension for <code>aiString</code>s.
+ *
+ * Assimp strings are zero terminated.
+ */
+ const size_t MAXLEN = 1024;
+
+ /**
+ * Represents an UTF-8 string, zero byte terminated.
+ *
+ * The length of such a string is limited to <code>MAXLEN</code> bytes
+ * (excluding the terminal \0).
+ *
+ * The character set of an aiString is explicitly defined to be UTF-8. This
+ * Unicode transformation was chosen in the belief that most strings in 3d
+ * model files are limited to ASCII characters, thus the character set
+ * needed to be ASCII compatible.
+ *
+ * Most text file loaders provide proper Unicode input file handling,
+ * special unicode characters are correctly transcoded to UTF-8 and are kept
+ * throughout the libraries' import pipeline.
+ *
+ * For most applications, it will be absolutely sufficient to interpret the
+ * aiString as ASCII data and work with it as one would work with a plain
+ * char[].
+ *
+ * To access an aiString from D you might want to use something like the
+ * following piece of code:
+ * ---
+ * char[] importAiString( aiString* s ) {
+ * return s.data[ 0 .. s.length ];
+ * }
+ * ---
+ */
+ struct aiString {
+ /**
+ * Length of the string (excluding the terminal \0).
+ *
+ * This is <em>not</em> the logical length of strings containing UTF-8
+ * multibyte sequences, but the number of bytes from the beginning of the
+ * string to its end.
+ */
+ size_t length;
+
+ /**
+ * String buffer.
+ *
+ * Size limit is <code>MAXLEN</code>.
+ */
+ char data[ MAXLEN ];
+ }
+
+ /**
+ * Standard return type for some library functions.
+ */
+ enum aiReturn : uint {
+ /**
+ * Indicates that a function was successful.
+ */
+ SUCCESS = 0x0,
+
+ /**
+ * Indicates that a function failed.
+ */
+ FAILURE = -0x1,
+
+ /**
+ * Indicates that not enough memory was available to perform the
+ * requested operation.
+ */
+ OUTOFMEMORY = -0x3
+ }
+
+ /**
+ * Seek origins (for the virtual file system API).
+ */
+ enum aiOrigin : uint {
+ /**
+ * Beginning of the file.
+ */
+ SET = 0x0,
+
+ /**
+ * Current position of the file pointer.
+ */
+ CUR = 0x1,
+
+ /**
+ * End of the file.
+ *
+ * Offsets must be negative.
+ */
+ END = 0x2
+ }
+
+ /**
+ * Enumerates predefined log streaming destinations.
+ *
+ * Logging to these streams can be enabled with a single call to
+ * <code>aiAttachPredefinedLogStream()</code>.
+ */
+ enum aiDefaultLogStream :uint {
+ /**
+ * Stream the log to a file.
+ */
+ FILE = 0x1,
+
+ /**
+ * Stream the log to standard output.
+ */
+ STDOUT = 0x2,
+
+ /**
+ * Stream the log to standard error.
+ */
+ STDERR = 0x4,
+
+ /**
+ * MSVC only: Stream the log the the debugger (this relies on
+ * <code>OutputDebugString</code> from the Win32 SDK).
+ */
+ DEBUGGER = 0x8
+ }
+
+ /**
+ * Stores the memory requirements for different components (e.g. meshes,
+ * materials, animations) of an import. All sizes are in bytes.
+ */
+ struct aiMemoryInfo {
+ /**
+ * Storage allocated for texture data.
+ */
+ uint textures;
+
+ /**
+ * Storage allocated for material data.
+ */
+ uint materials;
+
+ /**
+ * Storage allocated for mesh data.
+ */
+ uint meshes;
+
+ /**
+ * Storage allocated for node data.
+ */
+ uint nodes;
+
+ /**
+ * Storage allocated for animation data.
+ */
+ uint animations;
+
+ /**
+ * Storage allocated for camera data.
+ */
+ uint cameras;
+
+ /**
+ * Storage allocated for light data.
+ */
+ uint lights;
+
+ /**
+ * Total storage allocated for the full import.
+ */
+ uint total;
+ }
+}
diff --git a/libs/assimp/port/dAssimp/assimp/versionInfo.d b/libs/assimp/port/dAssimp/assimp/versionInfo.d
new file mode 100644
index 0000000..5a7e9b9
--- /dev/null
+++ b/libs/assimp/port/dAssimp/assimp/versionInfo.d
@@ -0,0 +1,72 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, ASSIMP Development 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 Development 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.
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Flags returned by <code>aiGetCompileFlags()</code>.
+ */
+module assimp.versionInfo;
+
+extern ( C ) {
+ /**
+ * Assimp was compiled as a shared object (Windows: DLL).
+ */
+ const uint ASSIMP_CFLAGS_SHARED = 0x1;
+
+ /**
+ * Assimp was compiled against STLport.
+ */
+ const uint ASSIMP_CFLAGS_STLPORT = 0x2;
+
+ /**
+ * Assimp was compiled as a debug build.
+ */
+ const uint ASSIMP_CFLAGS_DEBUG = 0x4;
+
+ /**
+ * Assimp was compiled with ASSIMP_BUILD_BOOST_WORKAROUND defined.
+ */
+ const uint ASSIMP_CFLAGS_NOBOOST = 0x8;
+
+ /**
+ * Assimp was compiled with ASSIMP_BUILD_SINGLETHREADED defined.
+ */
+ const uint ASSIMP_CFLAGS_SINGLETHREADED = 0x10;
+}
diff --git a/libs/assimp/port/iOS/IPHONEOS_ARM64E_TOOLCHAIN.cmake b/libs/assimp/port/iOS/IPHONEOS_ARM64E_TOOLCHAIN.cmake
new file mode 100644
index 0000000..0cf2b6b
--- /dev/null
+++ b/libs/assimp/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/libs/assimp/port/iOS/IPHONEOS_ARM64_TOOLCHAIN.cmake b/libs/assimp/port/iOS/IPHONEOS_ARM64_TOOLCHAIN.cmake
new file mode 100644
index 0000000..0f476f1
--- /dev/null
+++ b/libs/assimp/port/iOS/IPHONEOS_ARM64_TOOLCHAIN.cmake
@@ -0,0 +1,17 @@
+INCLUDE(CMakeForceCompiler)
+
+SET (CMAKE_CROSSCOMPILING TRUE)
+SET (CMAKE_SYSTEM_NAME "Darwin")
+SET (CMAKE_SYSTEM_PROCESSOR "arm64")
+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/libs/assimp/port/iOS/IPHONEOS_ARMV6_TOOLCHAIN.cmake b/libs/assimp/port/iOS/IPHONEOS_ARMV6_TOOLCHAIN.cmake
new file mode 100644
index 0000000..2f5d969
--- /dev/null
+++ b/libs/assimp/port/iOS/IPHONEOS_ARMV6_TOOLCHAIN.cmake
@@ -0,0 +1,17 @@
+INCLUDE(CMakeForceCompiler)
+
+SET (CMAKE_CROSSCOMPILING TRUE)
+SET (CMAKE_SYSTEM_NAME "Darwin")
+SET (CMAKE_SYSTEM_PROCESSOR "armv6")
+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/libs/assimp/port/iOS/IPHONEOS_ARMV7S_TOOLCHAIN.cmake b/libs/assimp/port/iOS/IPHONEOS_ARMV7S_TOOLCHAIN.cmake
new file mode 100644
index 0000000..325d483
--- /dev/null
+++ b/libs/assimp/port/iOS/IPHONEOS_ARMV7S_TOOLCHAIN.cmake
@@ -0,0 +1,17 @@
+INCLUDE(CMakeForceCompiler)
+
+SET (CMAKE_CROSSCOMPILING TRUE)
+SET (CMAKE_SYSTEM_NAME "Darwin")
+SET (CMAKE_SYSTEM_PROCESSOR "armv7s")
+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/libs/assimp/port/iOS/IPHONEOS_ARMV7_TOOLCHAIN.cmake b/libs/assimp/port/iOS/IPHONEOS_ARMV7_TOOLCHAIN.cmake
new file mode 100644
index 0000000..73087e0
--- /dev/null
+++ b/libs/assimp/port/iOS/IPHONEOS_ARMV7_TOOLCHAIN.cmake
@@ -0,0 +1,17 @@
+INCLUDE(CMakeForceCompiler)
+
+SET (CMAKE_CROSSCOMPILING TRUE)
+SET (CMAKE_SYSTEM_NAME "Darwin")
+SET (CMAKE_SYSTEM_PROCESSOR "armv7")
+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/libs/assimp/port/iOS/IPHONEOS_I386_TOOLCHAIN.cmake b/libs/assimp/port/iOS/IPHONEOS_I386_TOOLCHAIN.cmake
new file mode 100644
index 0000000..dc35d37
--- /dev/null
+++ b/libs/assimp/port/iOS/IPHONEOS_I386_TOOLCHAIN.cmake
@@ -0,0 +1,17 @@
+INCLUDE(CMakeForceCompiler)
+
+SET (CMAKE_CROSSCOMPILING TRUE)
+SET (CMAKE_SYSTEM_NAME "Darwin")
+SET (CMAKE_SYSTEM_PROCESSOR "i386")
+SET (IOS TRUE)
+
+SET (IOS_SDK_DEVICE iPhoneSimulator)
+
+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/libs/assimp/port/iOS/IPHONEOS_X86_64_TOOLCHAIN.cmake b/libs/assimp/port/iOS/IPHONEOS_X86_64_TOOLCHAIN.cmake
new file mode 100644
index 0000000..a9ed2b8
--- /dev/null
+++ b/libs/assimp/port/iOS/IPHONEOS_X86_64_TOOLCHAIN.cmake
@@ -0,0 +1,17 @@
+INCLUDE(CMakeForceCompiler)
+
+SET (CMAKE_CROSSCOMPILING TRUE)
+SET (CMAKE_SYSTEM_NAME "Darwin")
+SET (CMAKE_SYSTEM_PROCESSOR "x86_64")
+SET (IOS TRUE)
+
+SET (IOS_SDK_DEVICE iPhoneSimulator)
+
+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/libs/assimp/port/iOS/README.md b/libs/assimp/port/iOS/README.md
new file mode 100644
index 0000000..ca5632a
--- /dev/null
+++ b/libs/assimp/port/iOS/README.md
@@ -0,0 +1,39 @@
+# assimp for iOS
+(deployment target 6.0+, 32/64bit)
+
+Builds assimp libraries for several iOS CPU architectures at once, and outputs a fat binary from the result.
+
+Run the **build.sh** script from the ```./port/iOS/``` directory. See **./build.sh --help** for information about command line options.
+
+```bash
+shadeds-Mac:iOS arul$ ./build.sh --help
+[!] ./build.sh - assimp iOS build script
+ - don't build fat library (--no-fat)
+ - supported architectures(--archs): armv7, armv7s, arm64, i386, x86_64
+ - supported C++ STD libs.(--stdlib): libc++, libstdc++
+```
+Example:
+```bash
+cd ./port/iOS/
+./build.sh --stdlib=libc++ --archs="armv7 arm64 i386"
+```
+Supported architectures/devices:
+
+### Simulator
+- i386
+- x86_64
+
+### Device
+- ~~ARMv6 (dropped after iOS 6.0)~~
+- ARMv7
+- ARMv7-s
+- ARM64
+
+### Building with older iOS SDK versions
+The script should work out of the box for the iOS 8.x SDKs and probably newer releases as well.
+If you are using SDK version 7.x or older, you need to specify the exact SDK version inside **build.sh**, for example:
+```
+IOS_SDK_VERSION=7.1
+```
+### Optimization
+By default, no compiler optimizations are specified inside the build script. For an optimized build, add the corresponding flags to the CFLAGS definition inside **build.sh**.
diff --git a/libs/assimp/port/iOS/build.sh b/libs/assimp/port/iOS/build.sh
new file mode 100755
index 0000000..335b450
--- /dev/null
+++ b/libs/assimp/port/iOS/build.sh
@@ -0,0 +1,205 @@
+#!/bin/bash
+
+#
+# Written and maintained by the.arul@gmail.com (2014)
+#
+
+BUILD_DIR="./lib/iOS"
+
+###################################
+# SDK Version
+###################################
+IOS_SDK_VERSION=$(xcodebuild -version -sdk iphoneos | grep SDKVersion | cut -f2 -d ':' | tr -d '[[:space:]]')
+###################################
+
+###################################
+# BUILD Configuration
+###################################
+
+BUILD_SHARED_LIBS=OFF
+BUILD_TYPE=Release
+
+################################################
+# Minimum iOS deployment target version
+################################################
+MIN_IOS_VERSION="10.0"
+
+IOS_SDK_TARGET=$MIN_IOS_VERSION
+XCODE_ROOT_DIR=$(xcode-select --print-path)
+TOOLCHAIN=$XCODE_ROOT_DIR/Toolchains/XcodeDefault.xctoolchain
+
+CMAKE_C_COMPILER=$(xcrun -find cc)
+CMAKE_CXX_COMPILER=$(xcrun -find c++)
+
+BUILD_ARCHS_DEVICE="arm64e arm64 armv7s armv7"
+BUILD_ARCHS_SIMULATOR="x86_64 i386"
+BUILD_ARCHS_ALL=($BUILD_ARCHS_DEVICE $BUILD_ARCHS_SIMULATOR)
+
+CPP_DEV_TARGET_LIST=(miphoneos-version-min mios-simulator-version-min)
+CPP_DEV_TARGET=
+CPP_STD_LIB_LIST=(libc++ libstdc++)
+CPP_STD_LIB=
+CPP_STD_LIST=(c++11 c++14)
+CPP_STD=c++11
+
+function join { local IFS="$1"; shift; echo "$*"; }
+
+build_arch()
+{
+ IOS_SDK_DEVICE=iPhoneOS
+ CPP_DEV_TARGET=${CPP_DEV_TARGET_LIST[0]}
+
+ if [[ "$BUILD_ARCHS_SIMULATOR" =~ "$1" ]]
+ then
+ echo '[!] Target SDK set to SIMULATOR.'
+ IOS_SDK_DEVICE=iPhoneSimulator
+ CPP_DEV_TARGET=${CPP_DEV_TARGET_LIST[1]}
+ else
+ echo '[!] Target SDK set to DEVICE.'
+ fi
+
+ unset DEVROOT SDKROOT CFLAGS LDFLAGS CPPFLAGS CXXFLAGS CMAKE_CLI_INPUT
+
+ export CC="$(xcrun -sdk iphoneos -find clang)"
+ export CPP="$CC -E"
+ export DEVROOT=$XCODE_ROOT_DIR/Platforms/$IOS_SDK_DEVICE.platform/Developer
+ export SDKROOT=$DEVROOT/SDKs/$IOS_SDK_DEVICE$IOS_SDK_VERSION.sdk
+ export CFLAGS="-arch $1 -pipe -no-cpp-precomp -stdlib=$CPP_STD_LIB -isysroot $SDKROOT -I$SDKROOT/usr/include/ -miphoneos-version-min=$IOS_SDK_TARGET"
+ if [[ "$BUILD_TYPE" =~ "Debug" ]]; then
+ export CFLAGS="$CFLAGS -Og"
+ else
+ export CFLAGS="$CFLAGS -O3"
+ fi
+ export LDFLAGS="-arch $1 -isysroot $SDKROOT -L$SDKROOT/usr/lib/"
+ export CPPFLAGS="$CFLAGS"
+ export CXXFLAGS="$CFLAGS -std=$CPP_STD"
+
+ rm CMakeCache.txt
+
+ CMAKE_CLI_INPUT="-DCMAKE_C_COMPILER=$CMAKE_C_COMPILER -DCMAKE_CXX_COMPILER=$CMAKE_CXX_COMPILER -DCMAKE_TOOLCHAIN_FILE=./port/iOS/IPHONEOS_$(echo $1 | tr '[:lower:]' '[:upper:]')_TOOLCHAIN.cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DENABLE_BOOST_WORKAROUND=ON -DBUILD_SHARED_LIBS=$BUILD_SHARED_LIBS"
+
+ echo "[!] Running CMake with -G 'Unix Makefiles' $CMAKE_CLI_INPUT"
+
+ cmake -G 'Unix Makefiles' ${CMAKE_CLI_INPUT}
+
+ echo "[!] Building $1 library"
+
+ xcrun -run make clean
+ xcrun -run make assimp -j 8 -l
+
+ if [[ "$BUILD_SHARED_LIBS" =~ "ON" ]]; then
+ echo "[!] Moving built dynamic libraries into: $BUILD_DIR/$1/"
+ mv ./lib/*.dylib $BUILD_DIR/$1/
+ fi
+
+ echo "[!] Moving built static libraries into: $BUILD_DIR/$1/"
+ mv ./lib/*.a $BUILD_DIR/$1/
+}
+
+echo "[!] $0 - assimp iOS build script"
+
+CPP_STD_LIB=${CPP_STD_LIB_LIST[0]}
+CPP_STD=${CPP_STD_LIST[0]}
+DEPLOY_ARCHS=${BUILD_ARCHS_ALL[*]}
+DEPLOY_FAT=1
+
+for i in "$@"; do
+ case $i in
+ -s=*|--std=*)
+ CPP_STD=`echo $i | sed 's/[-a-zA-Z0-9]*=//'`
+ echo "[!] Selecting c++ standard: $CPP_STD"
+ ;;
+ -l=*|--stdlib=*)
+ CPP_STD_LIB=`echo $i | sed 's/[-a-zA-Z0-9]*=//'`
+ echo "[!] Selecting c++ std lib: $CPP_STD_LIB"
+ ;;
+ -a=*|--archs=*)
+ DEPLOY_ARCHS=`echo $i | sed 's/[-a-zA-Z0-9]*=//'`
+ echo "[!] Selecting architectures: $DEPLOY_ARCHS"
+ ;;
+ --debug)
+ BUILD_TYPE=Debug
+ echo "[!] Selecting build type: Debug"
+ ;;
+ --shared-lib)
+ BUILD_SHARED_LIBS=ON
+ echo "[!] Will generate dynamic libraries"
+ ;;
+ -n|--no-fat)
+ DEPLOY_FAT=0
+ echo "[!] Fat binary will not be created."
+ ;;
+ -h|--help)
+ echo " - don't build fat library (--no-fat)."
+ echo " - Include debug information and symbols, no compiler optimizations (--debug)."
+ echo " - generate dynamic libraries rather than static ones (--shared-lib)."
+ echo " - supported architectures (--archs): $(echo $(join , ${BUILD_ARCHS_ALL[*]}) | sed 's/,/, /g')"
+ echo " - supported C++ STD libs (--stdlib): $(echo $(join , ${CPP_STD_LIB_LIST[*]}) | sed 's/,/, /g')"
+ echo " - supported C++ standards (--std): $(echo $(join , ${CPP_STD_LIST[*]}) | sed 's/,/, /g')"
+ exit
+ ;;
+ *)
+ ;;
+ esac
+done
+
+cd ../../
+rm -rf $BUILD_DIR
+
+for ARCH_TARGET in $DEPLOY_ARCHS; do
+ echo "Creating folder: $BUILD_DIR/$ARCH_TARGET"
+ mkdir -p $BUILD_DIR/$ARCH_TARGET
+ echo "Building for arc: $ARCH_TARGET"
+ build_arch $ARCH_TARGET
+ #rm ./lib/libassimp.a
+done
+
+
+make_fat_static_or_shared_binary()
+{
+ LIB_NAME=$1
+ LIPO_ARGS=''
+ for ARCH_TARGET in $DEPLOY_ARCHS; do
+ if [[ "$BUILD_SHARED_LIBS" =~ "ON" ]]; then
+ LIPO_ARGS="$LIPO_ARGS-arch $ARCH_TARGET $BUILD_DIR/$ARCH_TARGET/$LIB_NAME.dylib "
+ else
+ LIPO_ARGS="$LIPO_ARGS-arch $ARCH_TARGET $BUILD_DIR/$ARCH_TARGET/$LIB_NAME.a "
+ fi
+ done
+ if [[ "$BUILD_SHARED_LIBS" =~ "ON" ]]; then
+ LIPO_ARGS="$LIPO_ARGS -create -output $BUILD_DIR/$LIB_NAME-fat.dylib"
+ else
+ LIPO_ARGS="$LIPO_ARGS -create -output $BUILD_DIR/$LIB_NAME-fat.a"
+ fi
+ lipo $LIPO_ARGS
+}
+
+make_fat_static_binary()
+{
+ LIB_NAME=$1
+ LIPO_ARGS=''
+ for ARCH_TARGET in $DEPLOY_ARCHS; do
+ LIPO_ARGS="$LIPO_ARGS-arch $ARCH_TARGET $BUILD_DIR/$ARCH_TARGET/$LIB_NAME.a "
+ done
+ LIPO_ARGS="$LIPO_ARGS -create -output $BUILD_DIR/$LIB_NAME-fat.a"
+ lipo $LIPO_ARGS
+}
+
+if [[ "$DEPLOY_FAT" -eq 1 ]]; then
+ echo '[+] Creating fat binaries ...'
+
+ if [[ "$BUILD_TYPE" =~ "Debug" ]]; then
+ make_fat_static_or_shared_binary 'libassimpd'
+ make_fat_static_binary 'libIrrXMLd'
+ make_fat_static_binary 'libzlibstaticd'
+ else
+ make_fat_static_or_shared_binary 'libassimp'
+ make_fat_static_binary 'libIrrXML'
+ make_fat_static_binary 'libzlibstatic'
+ fi
+
+ echo "[!] Done! The fat binaries can be found at $BUILD_DIR"
+fi
+
+
+
diff --git a/libs/assimp/port/jassimp/README b/libs/assimp/port/jassimp/README
new file mode 100644
index 0000000..a642f75
--- /dev/null
+++ b/libs/assimp/port/jassimp/README
@@ -0,0 +1,56 @@
+jassimp
+-------
+
+Java binding for assimp.
+
+The class model used by jassimp is not a one-to-one mapping of assimps class/
+structure model (due to performance considerations). Please read the javadoc
+descriptions of AiMesh and AiWrapperProvider.
+
+The jassimp.lwjgl package contains a LWJGL specific wrapper provider and some
+application examples using this wrapper
+
+
+
+How To Build
+------------
+
+ I) native library, for example by issuing this command in jassimp-native/src:
+
+ $ gcc jassimp.cpp -I/usr/lib/jvm/default/include/ \
+ -I/usr/lib/jvm/default/include/linux -lassimp -shared -fPIC -o libjassimp.so
+
+ libjassimp.so is required at runtime and must be located in java.library.path.
+
+II) Java binding
+ The java library is built using ant. Executing "ant" in the port/jassimp
+ directory should be sufficient to build the library including docs. You
+ still need to build the native library separately, see above
+
+ The java build is configured to create java 1.6 classes
+
+
+
+Limitations
+-----------
+
+Not all data imports have been tested yet, especially the countless texture
+parameters. If you find bugs please report them.
+
+jassimp supports most of assimps features. Current limitations are
+* only importing scenes is supported. There are some methods that allow a
+ modification of the returned objects, but these should be considered as
+ work in progress. Full blown export support is planned for a future release
+* no support for mesh animations
+* no support for embedded textures
+* no support for importer configurations
+* some texture related material properties are not exposed via the API but only
+ accessible by traversing the list of properties. However this limitation is
+ also present in the c-API ...
+
+
+License
+-------
+
+The license for jassimp is the same as the main Assimp license.
+
diff --git a/libs/assimp/port/jassimp/build.xml b/libs/assimp/port/jassimp/build.xml
new file mode 100644
index 0000000..1352e3f
--- /dev/null
+++ b/libs/assimp/port/jassimp/build.xml
@@ -0,0 +1,54 @@
+<project name="jassimp" basedir="." default="all">
+ <property name="native-src.dir" value="jassimp-native/src" />
+ <property name="src.dir" value="jassimp/src" />
+ <property name="jassimp.lwjgl-src.dir" value="jassimp.lwjgl/src" />
+ <property name="build.dir" value="jassimp/bin" />
+ <property name="dist.dir" value="dist" />
+ <property name="doc.dir" value="doc" />
+ <property environment="env"/>
+ <property name="ndk.dir" value="${env.NDK_HOME}" />
+ <property name="my.dir" value="${env.PWD}" />
+
+ <path id="classpath">
+ </path>
+
+ <target name="compile">
+ <delete dir="${build.dir}" />
+ <mkdir dir="${build.dir}" />
+ <javac classpathref="classpath" destdir="${build.dir}" srcdir="${src.dir}"
+ source="1.6" target="1.6" includeantruntime="false">
+ </javac>
+ </target>
+
+ <target name="jni_header">
+ <mkdir dir="${native-src.dir}" />
+ <javah outputfile="${native-src.dir}/jassimp.h" force="yes">
+ <classpath>
+ <pathelement path="${build.dir}" />
+ </classpath>
+ <class name="jassimp.Jassimp" />
+ </javah>
+ </target>
+
+ <target name="ndk-jni" depends="package">
+ <exec executable="${ndk.dir}/ndk-build">
+ <arg line="all NDK_PROJECT_PATH=${my.dir}/workspaces/Android-NDK"/>
+ </exec>
+ </target>
+
+ <target name="package" depends="compile">
+ <jar destfile="${dist.dir}/jassimp.jar" basedir="${build.dir}">
+ </jar>
+ </target>
+
+
+ <target name="doc">
+ <delete dir="${doc.dir}" />
+ <javadoc access="public" author="false" destdir="${doc.dir}"
+ sourcepath="${src.dir}">
+ </javadoc>
+ </target>
+
+ <target name="all" depends="package, doc">
+ </target>
+</project>
diff --git a/libs/assimp/port/jassimp/jassimp-native/Android.mk b/libs/assimp/port/jassimp/jassimp-native/Android.mk
new file mode 100644
index 0000000..94b233b
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp-native/Android.mk
@@ -0,0 +1,13 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := jassimp
+LOCAL_SRC_FILES := src/jassimp.cpp
+
+LOCAL_CFLAGS += -DJNI_LOG
+
+#LOCAL_STATIC_LIBRARIES := assimp_static
+LOCAL_SHARED_LIBRARIES := assimp
+LOCAL_LDLIBS := -llog
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/assimp/port/jassimp/jassimp-native/src/jassimp.cpp b/libs/assimp/port/jassimp/jassimp-native/src/jassimp.cpp
new file mode 100644
index 0000000..6661ce9
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp-native/src/jassimp.cpp
@@ -0,0 +1,1995 @@
+#include "jassimp.h"
+
+#include <assimp/Importer.hpp>
+#include <assimp/ProgressHandler.hpp>
+#include <assimp/scene.h>
+#include <assimp/IOStream.hpp>
+#include <assimp/IOSystem.hpp>
+
+
+#ifdef JNI_LOG
+#ifdef ANDROID
+#include <android/log.h>
+#define lprintf(...) __android_log_print(ANDROID_LOG_VERBOSE, __func__, __VA_ARGS__)
+#else
+#define lprintf(...) printf (__VA_ARGS__)
+#endif /* ANDROID */
+#else
+#define lprintf
+#endif
+
+static std::string gLastErrorString;
+
+// Automatically deletes a local ref when it goes out of scope
+class SmartLocalRef {
+private:
+ JNIEnv* mJniEnv;
+ jobject& mJavaObj;
+ SmartLocalRef(const SmartLocalRef&); // non construction-copyable
+ SmartLocalRef& operator=(const SmartLocalRef&); // non copyable
+
+public:
+ template<class T> SmartLocalRef(JNIEnv* env, T& object)
+ : mJniEnv(env)
+ , mJavaObj((jobject&)object)
+ {
+ };
+
+ ~SmartLocalRef() {
+ if (mJavaObj != NULL) {
+ mJniEnv->DeleteLocalRef(mJavaObj);
+ }
+ }
+};
+
+static bool createInstance(JNIEnv *env, const char* className, jobject& newInstance)
+{
+ jclass clazz = env->FindClass(className);
+ SmartLocalRef clazzRef(env, clazz);
+
+ if (NULL == clazz)
+ {
+ lprintf("could not find class %s\n", className);
+ return false;
+ }
+
+ jmethodID ctr_id = env->GetMethodID(clazz, "<init>", "()V");
+
+ if (NULL == ctr_id)
+ {
+ lprintf("could not find no-arg constructor for class %s\n", className);
+ return false;
+ }
+
+ newInstance = env->NewObject(clazz, ctr_id);
+
+ if (NULL == newInstance)
+ {
+ lprintf("error calling no-arg constructor for class %s\n", className);
+ return false;
+ }
+
+ return true;
+}
+
+
+static bool createInstance(JNIEnv *env, const char* className, const char* signature,/* const*/ jvalue* params, jobject& newInstance)
+{
+ jclass clazz = env->FindClass(className);
+ SmartLocalRef clazzRef(env, clazz);
+
+ if (NULL == clazz)
+ {
+ lprintf("could not find class %s\n", className);
+ return false;
+ }
+
+ jmethodID ctr_id = env->GetMethodID(clazz, "<init>", signature);
+
+ if (NULL == ctr_id)
+ {
+ lprintf("could not find no-arg constructor for class %s\n", className);
+ return false;
+ }
+
+ newInstance = env->NewObjectA(clazz, ctr_id, params);
+
+ if (NULL == newInstance)
+ {
+ lprintf("error calling constructor for class %s, signature %s\n", className, signature);
+ return false;
+ }
+
+ return true;
+}
+
+
+static bool getField(JNIEnv *env, jobject object, const char* fieldName, const char* signature, jobject& field)
+{
+ jclass clazz = env->GetObjectClass(object);
+ SmartLocalRef clazzRef(env, clazz);
+
+ if (NULL == clazz)
+ {
+ lprintf("could not get class for object\n");
+ return false;
+ }
+
+ jfieldID fieldId = env->GetFieldID(clazz, fieldName, signature);
+
+ if (NULL == fieldId)
+ {
+ lprintf("could not get field %s with signature %s\n", fieldName, signature);
+ return false;
+ }
+
+ field = env->GetObjectField(object, fieldId);
+
+ return true;
+}
+
+
+static bool setIntField(JNIEnv *env, jobject object, const char* fieldName, jint value)
+{
+ jclass clazz = env->GetObjectClass(object);
+ SmartLocalRef clazzRef(env, clazz);
+
+ if (NULL == clazz)
+ {
+ lprintf("could not get class for object\n");
+ return false;
+ }
+
+ jfieldID fieldId = env->GetFieldID(clazz, fieldName, "I");
+
+ if (NULL == fieldId)
+ {
+ lprintf("could not get field %s with signature I\n", fieldName);
+ return false;
+ }
+
+ env->SetIntField(object, fieldId, value);
+
+ return true;
+}
+
+
+static bool setFloatField(JNIEnv *env, jobject object, const char* fieldName, jfloat value)
+{
+ jclass clazz = env->GetObjectClass(object);
+ SmartLocalRef clazzRef(env, clazz);
+
+ if (NULL == clazz)
+ {
+ lprintf("could not get class for object\n");
+ return false;
+ }
+
+ jfieldID fieldId = env->GetFieldID(clazz, fieldName, "F");
+
+ if (NULL == fieldId)
+ {
+ lprintf("could not get field %s with signature F\n", fieldName);
+ return false;
+ }
+
+ env->SetFloatField(object, fieldId, value);
+
+ return true;
+}
+
+
+static bool setObjectField(JNIEnv *env, jobject object, const char* fieldName, const char* signature, jobject value)
+{
+ jclass clazz = env->GetObjectClass(object);
+ SmartLocalRef clazzRef(env, clazz);
+
+ if (NULL == clazz)
+ {
+ lprintf("could not get class for object\n");
+ return false;
+ }
+
+ jfieldID fieldId = env->GetFieldID(clazz, fieldName, signature);
+
+ if (NULL == fieldId)
+ {
+ lprintf("could not get field %s with signature %s\n", fieldName, signature);
+ return false;
+ }
+
+ env->SetObjectField(object, fieldId, value);
+
+ return true;
+}
+
+
+static bool getStaticField(JNIEnv *env, const char* className, const char* fieldName, const char* signature, jobject& field)
+{
+ jclass clazz = env->FindClass(className);
+ SmartLocalRef clazzRef(env, clazz);
+
+ if (NULL == clazz)
+ {
+ lprintf("could not find class %s\n", className);
+ return false;
+ }
+
+ jfieldID fieldId = env->GetStaticFieldID(clazz, fieldName, signature);
+
+ if (NULL == fieldId)
+ {
+ lprintf("could not get field %s with signature %s\n", fieldName, signature);
+ return false;
+ }
+
+ field = env->GetStaticObjectField(clazz, fieldId);
+
+ return true;
+}
+
+
+static bool call(JNIEnv *env, jobject object, const char* typeName, const char* methodName,
+ const char* signature,/* const*/ jvalue* params)
+{
+ jclass clazz = env->FindClass(typeName);
+ SmartLocalRef clazzRef(env, clazz);
+
+ if (NULL == clazz)
+ {
+ lprintf("could not find class %s\n", typeName);
+ return false;
+ }
+
+ jmethodID mid = env->GetMethodID(clazz, methodName, signature);
+
+ if (NULL == mid)
+ {
+ lprintf("could not find method %s with signature %s in type %s\n", methodName, signature, typeName);
+ return false;
+ }
+
+ jboolean jReturnValue = env->CallBooleanMethodA(object, mid, params);
+
+ return (bool)jReturnValue;
+}
+static bool callv(JNIEnv *env, jobject object, const char* typeName,
+ const char* methodName, const char* signature,/* const*/ jvalue* params) {
+ jclass clazz = env->FindClass(typeName);
+ SmartLocalRef clazzRef(env, clazz);
+
+ if (NULL == clazz) {
+ lprintf("could not find class %s\n", typeName);
+ return false;
+ }
+
+ jmethodID mid = env->GetMethodID(clazz, methodName, signature);
+
+ if (NULL == mid) {
+ lprintf("could not find method %s with signature %s in type %s\n", methodName, signature, typeName);
+ return false;
+ }
+
+ env->CallVoidMethodA(object, mid, params);
+
+ return true;
+}
+
+static jobject callo(JNIEnv *env, jobject object, const char* typeName, const char* methodName,
+ const char* signature,/* const*/ jvalue* params)
+{
+ jclass clazz = env->FindClass(typeName);
+ SmartLocalRef clazzRef(env, clazz);
+
+ if (NULL == clazz)
+ {
+ lprintf("could not find class %s\n", typeName);
+ return NULL;
+ }
+
+ jmethodID mid = env->GetMethodID(clazz, methodName, signature);
+
+ if (NULL == mid)
+ {
+ lprintf("could not find method %s with signature %s in type %s\n", methodName, signature, typeName);
+ return NULL;
+ }
+
+ jobject jReturnValue = env->CallObjectMethodA(object, mid, params);
+
+ return jReturnValue;
+}
+
+static int calli(JNIEnv *env, jobject object, const char* typeName, const char* methodName,
+ const char* signature)
+{
+ jclass clazz = env->FindClass(typeName);
+ SmartLocalRef clazzRef(env, clazz);
+
+ if (NULL == clazz)
+ {
+ lprintf("could not find class %s\n", typeName);
+ return false;
+ }
+
+ jmethodID mid = env->GetMethodID(clazz, methodName, signature);
+
+ if (NULL == mid)
+ {
+ lprintf("could not find method %s with signature %s in type %s\n", methodName, signature, typeName);
+ return false;
+ }
+
+ jint jReturnValue = env->CallIntMethod(object, mid);
+
+ return (int) jReturnValue;
+}
+
+static int callc(JNIEnv *env, jobject object, const char* typeName, const char* methodName,
+ const char* signature)
+{
+ jclass clazz = env->FindClass(typeName);
+ SmartLocalRef clazzRef(env, clazz);
+
+ if (NULL == clazz)
+ {
+ lprintf("could not find class %s\n", typeName);
+ return false;
+ }
+
+ jmethodID mid = env->GetMethodID(clazz, methodName, signature);
+
+ if (NULL == mid)
+ {
+ lprintf("could not find method %s with signature %s in type %s\n", methodName, signature, typeName);
+ return false;
+ }
+
+ jint jReturnValue = env->CallCharMethod(object, mid);
+
+ return (int) jReturnValue;
+}
+
+
+static bool callStaticObject(JNIEnv *env, const char* typeName, const char* methodName,
+ const char* signature,/* const*/ jvalue* params, jobject& returnValue)
+{
+ jclass clazz = env->FindClass(typeName);
+ SmartLocalRef clazzRef(env, clazz);
+
+ if (NULL == clazz)
+ {
+ lprintf("could not find class %s\n", typeName);
+ return false;
+ }
+
+ jmethodID mid = env->GetStaticMethodID(clazz, methodName, signature);
+
+ if (NULL == mid)
+ {
+ lprintf("could not find method %s with signature %s in type %s\n", methodName, signature, typeName);
+ return false;
+ }
+
+ returnValue = env->CallStaticObjectMethodA(clazz, mid, params);
+
+ return true;
+}
+
+
+static bool copyBuffer(JNIEnv *env, jobject jMesh, const char* jBufferName, void* cData, size_t size)
+{
+ jobject jBuffer = NULL;
+ SmartLocalRef bufferRef(env, jBuffer);
+
+ if (!getField(env, jMesh, jBufferName, "Ljava/nio/ByteBuffer;", jBuffer))
+ {
+ return false;
+ }
+
+ if (env->GetDirectBufferCapacity(jBuffer) != size)
+ {
+ lprintf("invalid direct buffer, expected %u, got %llu\n", size, env->GetDirectBufferCapacity(jBuffer));
+ return false;
+ }
+
+ void* jBufferPtr = env->GetDirectBufferAddress(jBuffer);
+
+ if (NULL == jBufferPtr)
+ {
+ lprintf("could not access direct buffer\n");
+ return false;
+ }
+
+ memcpy(jBufferPtr, cData, size);
+
+ return true;
+}
+
+
+static bool copyBufferArray(JNIEnv *env, jobject jMesh, const char* jBufferName, int index, void* cData, size_t size)
+{
+ jobject jBufferArray = NULL;
+ SmartLocalRef bufferArrayRef(env, jBufferArray);
+
+ if (!getField(env, jMesh, jBufferName, "[Ljava/nio/ByteBuffer;", jBufferArray))
+ {
+ return false;
+ }
+
+ jobject jBuffer = env->GetObjectArrayElement((jobjectArray) jBufferArray, index);
+ SmartLocalRef bufferRef(env, jBuffer);
+
+ if (env->GetDirectBufferCapacity(jBuffer) != size)
+ {
+ lprintf("invalid direct buffer, expected %u, got %llu\n", size, env->GetDirectBufferCapacity(jBuffer));
+ return false;
+ }
+
+ void* jBufferPtr = env->GetDirectBufferAddress(jBuffer);
+
+ if (NULL == jBufferPtr)
+ {
+ lprintf("could not access direct buffer\n");
+ return false;
+ }
+
+ memcpy(jBufferPtr, cData, size);
+
+ return true;
+}
+
+class JavaIOStream : public Assimp::IOStream
+{
+private:
+ size_t pos;
+ size_t size;
+ char* buffer;
+ jobject jIOStream;
+
+
+public:
+ JavaIOStream(size_t size, char* buffer, jobject jIOStream) :
+ pos(0),
+ size(size),
+ buffer(buffer),
+ jIOStream(jIOStream)
+ {};
+
+
+ ~JavaIOStream(void)
+ {
+ free(buffer);
+ };
+
+ size_t Read(void* pvBuffer, size_t pSize, size_t pCount)
+ {
+ const size_t cnt = std::min(pCount,(size - pos)/pSize);
+ const size_t ofs = pSize*cnt;
+
+ memcpy(pvBuffer, buffer + pos, ofs);
+ pos += ofs;
+
+ return cnt;
+ };
+ size_t Write(const void* pvBuffer, size_t pSize, size_t pCount)
+ {
+ return 0;
+ };
+
+ aiReturn Seek(size_t pOffset, aiOrigin pOrigin)
+ {
+ if (aiOrigin_SET == pOrigin) {
+ if (pOffset >= size) {
+ return AI_FAILURE;
+ }
+ pos = pOffset;
+ }
+ else if (aiOrigin_END == pOrigin) {
+ if (pOffset >= size) {
+ return AI_FAILURE;
+ }
+ pos = size-pOffset;
+ }
+ else {
+ if (pOffset + pos >= size) {
+ return AI_FAILURE;
+ }
+ pos += pOffset;
+ }
+ return AI_SUCCESS;
+ };
+
+ size_t Tell(void) const
+ {
+ return pos;
+ };
+
+ size_t FileSize() const
+ {
+ return size;
+ };
+
+ void Flush() {};
+
+
+ jobject javaObject()
+ {
+ return jIOStream;
+ };
+
+
+};
+
+
+class JavaIOSystem : public Assimp::IOSystem {
+ private:
+ JNIEnv* mJniEnv;
+ jobject& mJavaIOSystem;
+
+ public:
+ JavaIOSystem(JNIEnv* env, jobject& javaIOSystem) :
+ mJniEnv(env),
+ mJavaIOSystem(javaIOSystem)
+ {};
+
+ bool Exists( const char* pFile) const
+ {
+ jvalue params[1];
+ params[0].l = mJniEnv->NewStringUTF(pFile);
+ return call(mJniEnv, mJavaIOSystem, "jassimp/AiIOSystem", "exists", "(Ljava/lang/String;)Z", params);
+
+ };
+ char getOsSeparator() const
+ {
+ return (char) callc(mJniEnv, mJavaIOSystem, "jassimp/AiIOSystem", "getOsSeparator", "()C");
+ };
+
+ Assimp::IOStream* Open(const char* pFile,const char* pMode = "rb")
+ {
+ jvalue params[2];
+ params[0].l = mJniEnv->NewStringUTF(pFile);
+ params[1].l = mJniEnv->NewStringUTF(pMode);
+
+
+ jobject jStream = callo(mJniEnv, mJavaIOSystem, "jassimp/AiIOSystem", "open", "(Ljava/lang/String;Ljava/lang/String;)Ljassimp/AiIOStream;", params);
+ if(NULL == jStream)
+ {
+ lprintf("NULL object from AiIOSystem.open\n");
+ return NULL;
+ }
+
+ size_t size = calli(mJniEnv, jStream, "jassimp/AiIOStream", "getFileSize", "()I");
+ lprintf("Model file size is %d\n", size);
+
+ char* buffer = (char*)malloc(size);
+ jobject javaBuffer = mJniEnv->NewDirectByteBuffer(buffer, size);
+
+ jvalue readParams[1];
+ readParams[0].l = javaBuffer;
+ if(call(mJniEnv, jStream, "jassimp/AiIOStream", "read", "(Ljava/nio/ByteBuffer;)Z", readParams))
+ {
+ return new JavaIOStream(size, buffer, jStream);
+ }
+ else
+ {
+ lprintf("Read failure on AiIOStream.read");
+ free(buffer);
+ return NULL;
+ }
+
+ };
+ void Close( Assimp::IOStream* pFile)
+ {
+
+ jvalue params[1];
+ params[0].l = ((JavaIOStream*) pFile)->javaObject();
+ callv(mJniEnv, mJavaIOSystem, "jassimp/AiIOSystem", "close", "(Ljassimp/AiIOStream;)V", params);
+ delete pFile;
+ };
+
+
+
+};
+
+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)
+{
+ for (unsigned int meshNr = 0; meshNr < cScene->mNumMeshes; meshNr++)
+ {
+ const aiMesh *cMesh = cScene->mMeshes[meshNr];
+
+ lprintf("converting mesh %s ...\n", cMesh->mName.C_Str());
+
+ /* create mesh */
+ jobject jMesh = NULL;
+ SmartLocalRef refMesh(env, jMesh);
+
+ if (!createInstance(env, "jassimp/AiMesh", jMesh))
+ {
+ return false;
+ }
+
+
+ /* add mesh to m_meshes java.util.List */
+ jobject jMeshes = NULL;
+ SmartLocalRef refMeshes(env, jMeshes);
+
+ if (!getField(env, jScene, "m_meshes", "Ljava/util/List;", jMeshes))
+ {
+ return false;
+ }
+
+ jvalue addParams[1];
+ addParams[0].l = jMesh;
+ if (!call(env, jMeshes, "java/util/Collection", "add", "(Ljava/lang/Object;)Z", addParams))
+ {
+ return false;
+ }
+
+
+ /* set general mesh data in java */
+ jvalue setTypesParams[1];
+ setTypesParams[0].i = cMesh->mPrimitiveTypes;
+ if (!callv(env, jMesh, "jassimp/AiMesh", "setPrimitiveTypes", "(I)V", setTypesParams))
+ {
+ return false;
+ }
+
+
+ if (!setIntField(env, jMesh, "m_materialIndex", cMesh->mMaterialIndex))
+ {
+ return false;
+ }
+
+ jstring nameString = env->NewStringUTF(cMesh->mName.C_Str());
+ SmartLocalRef refNameString(env, nameString);
+ if (!setObjectField(env, jMesh, "m_name", "Ljava/lang/String;", nameString))
+ {
+ return false;
+ }
+
+
+ /* determine face buffer size */
+ bool isPureTriangle = cMesh->mPrimitiveTypes == aiPrimitiveType_TRIANGLE;
+ size_t faceBufferSize;
+ if (isPureTriangle)
+ {
+ faceBufferSize = cMesh->mNumFaces * 3 * sizeof(unsigned int);
+ }
+ else
+ {
+ int numVertexReferences = 0;
+ for (unsigned int face = 0; face < cMesh->mNumFaces; face++)
+ {
+ numVertexReferences += cMesh->mFaces[face].mNumIndices;
+ }
+
+ faceBufferSize = numVertexReferences * sizeof(unsigned int);
+ }
+
+
+ /* allocate buffers - we do this from java so they can be garbage collected */
+ jvalue allocateBuffersParams[4];
+ allocateBuffersParams[0].i = cMesh->mNumVertices;
+ allocateBuffersParams[1].i = cMesh->mNumFaces;
+ allocateBuffersParams[2].z = isPureTriangle;
+ allocateBuffersParams[3].i = (jint) faceBufferSize;
+ if (!callv(env, jMesh, "jassimp/AiMesh", "allocateBuffers", "(IIZI)V", allocateBuffersParams))
+ {
+ return false;
+ }
+
+
+ if (cMesh->mNumVertices > 0)
+ {
+ /* push vertex data to java */
+ if (!copyBuffer(env, jMesh, "m_vertices", cMesh->mVertices, cMesh->mNumVertices * sizeof(aiVector3D)))
+ {
+ lprintf("could not copy vertex data\n");
+ return false;
+ }
+
+ lprintf(" with %u vertices\n", cMesh->mNumVertices);
+ }
+
+
+ /* push face data to java */
+ if (cMesh->mNumFaces > 0)
+ {
+ if (isPureTriangle)
+ {
+ char* faceBuffer = (char*) malloc(faceBufferSize);
+
+ size_t faceDataSize = 3 * sizeof(unsigned int);
+ for (unsigned int face = 0; face < cMesh->mNumFaces; face++)
+ {
+ memcpy(faceBuffer + face * faceDataSize, cMesh->mFaces[face].mIndices, faceDataSize);
+ }
+
+ bool res = copyBuffer(env, jMesh, "m_faces", faceBuffer, faceBufferSize);
+
+ free(faceBuffer);
+
+ if (!res)
+ {
+ lprintf("could not copy face data\n");
+ return false;
+ }
+ }
+ else
+ {
+ char* faceBuffer = (char*) malloc(faceBufferSize);
+ char* offsetBuffer = (char*) malloc(cMesh->mNumFaces * sizeof(unsigned int));
+
+ size_t faceBufferPos = 0;
+ for (unsigned int face = 0; face < cMesh->mNumFaces; face++)
+ {
+ size_t faceBufferOffset = faceBufferPos / sizeof(unsigned int);
+ memcpy(offsetBuffer + face * sizeof(unsigned int), &faceBufferOffset, sizeof(unsigned int));
+
+ size_t faceDataSize = cMesh->mFaces[face].mNumIndices * sizeof(unsigned int);
+ memcpy(faceBuffer + faceBufferPos, cMesh->mFaces[face].mIndices, faceDataSize);
+ faceBufferPos += faceDataSize;
+ }
+
+ if (faceBufferPos != faceBufferSize)
+ {
+ /* this should really not happen */
+ lprintf("faceBufferPos %u, faceBufferSize %u\n", faceBufferPos, faceBufferSize);
+ env->FatalError("error copying face data");
+ exit(-1);
+ }
+
+
+ bool res = copyBuffer(env, jMesh, "m_faces", faceBuffer, faceBufferSize);
+ res &= copyBuffer(env, jMesh, "m_faceOffsets", offsetBuffer, cMesh->mNumFaces * sizeof(unsigned int));
+
+ free(faceBuffer);
+ free(offsetBuffer);
+
+ if (!res)
+ {
+ lprintf("could not copy face data\n");
+ return false;
+ }
+ }
+
+ lprintf(" with %u faces\n", cMesh->mNumFaces);
+ }
+
+
+ /* push normals to java */
+ if (cMesh->HasNormals())
+ {
+ jvalue allocateDataChannelParams[2];
+ allocateDataChannelParams[0].i = 0;
+ allocateDataChannelParams[1].i = 0;
+ if (!callv(env, jMesh, "jassimp/AiMesh", "allocateDataChannel", "(II)V", allocateDataChannelParams))
+ {
+ lprintf("could not allocate normal data channel\n");
+ return false;
+ }
+ if (!copyBuffer(env, jMesh, "m_normals", cMesh->mNormals, cMesh->mNumVertices * 3 * sizeof(float)))
+ {
+ lprintf("could not copy normal data\n");
+ return false;
+ }
+
+ lprintf(" with normals\n");
+ }
+
+
+ /* push tangents to java */
+ if (cMesh->mTangents != NULL)
+ {
+ jvalue allocateDataChannelParams[2];
+ allocateDataChannelParams[0].i = 1;
+ allocateDataChannelParams[1].i = 0;
+ if (!callv(env, jMesh, "jassimp/AiMesh", "allocateDataChannel", "(II)V", allocateDataChannelParams))
+ {
+ lprintf("could not allocate tangents data channel\n");
+ return false;
+ }
+ if (!copyBuffer(env, jMesh, "m_tangents", cMesh->mTangents, cMesh->mNumVertices * 3 * sizeof(float)))
+ {
+ lprintf("could not copy tangents data\n");
+ return false;
+ }
+
+ lprintf(" with tangents\n");
+ }
+
+
+ /* push bitangents to java */
+ if (cMesh->mBitangents != NULL)
+ {
+ jvalue allocateDataChannelParams[2];
+ allocateDataChannelParams[0].i = 2;
+ allocateDataChannelParams[1].i = 0;
+ if (!callv(env, jMesh, "jassimp/AiMesh", "allocateDataChannel", "(II)V", allocateDataChannelParams))
+ {
+ lprintf("could not allocate bitangents data channel\n");
+ return false;
+ }
+ if (!copyBuffer(env, jMesh, "m_bitangents", cMesh->mBitangents, cMesh->mNumVertices * 3 * sizeof(float)))
+ {
+ lprintf("could not copy bitangents data\n");
+ return false;
+ }
+
+ lprintf(" with bitangents\n");
+ }
+
+
+ /* push color sets to java */
+ for (int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS; c++)
+ {
+ if (cMesh->mColors[c] != NULL)
+ {
+ jvalue allocateDataChannelParams[2];
+ allocateDataChannelParams[0].i = 3;
+ allocateDataChannelParams[1].i = c;
+ if (!callv(env, jMesh, "jassimp/AiMesh", "allocateDataChannel", "(II)V", allocateDataChannelParams))
+ {
+ lprintf("could not allocate colorset data channel\n");
+ return false;
+ }
+ if (!copyBufferArray(env, jMesh, "m_colorsets", c, cMesh->mColors[c], cMesh->mNumVertices * 4 * sizeof(float)))
+ {
+ lprintf("could not copy colorset data\n");
+ return false;
+ }
+
+ lprintf(" with colorset[%d]\n", c);
+ }
+ }
+
+
+ /* push tex coords to java */
+ for (int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; c++)
+ {
+ if (cMesh->mTextureCoords[c] != NULL)
+ {
+ jvalue allocateDataChannelParams[2];
+
+ switch (cMesh->mNumUVComponents[c])
+ {
+ case 1:
+ allocateDataChannelParams[0].i = 4;
+ break;
+ case 2:
+ allocateDataChannelParams[0].i = 5;
+ break;
+ case 3:
+ allocateDataChannelParams[0].i = 6;
+ break;
+ default:
+ return false;
+ }
+
+ allocateDataChannelParams[1].i = c;
+ if (!callv(env, jMesh, "jassimp/AiMesh", "allocateDataChannel", "(II)V", allocateDataChannelParams))
+ {
+ lprintf("could not allocate texture coordinates data channel\n");
+ return false;
+ }
+
+ /* gather data */
+ size_t coordBufferSize = cMesh->mNumVertices * cMesh->mNumUVComponents[c] * sizeof(float);
+ char* coordBuffer = (char*) malloc(coordBufferSize);
+ size_t coordBufferOffset = 0;
+
+ for (unsigned int v = 0; v < cMesh->mNumVertices; v++)
+ {
+ memcpy(coordBuffer + coordBufferOffset, &cMesh->mTextureCoords[c][v], cMesh->mNumUVComponents[c] * sizeof(float));
+ coordBufferOffset += cMesh->mNumUVComponents[c] * sizeof(float);
+ }
+
+ if (coordBufferOffset != coordBufferSize)
+ {
+ /* this should really not happen */
+ lprintf("coordBufferPos %u, coordBufferSize %u\n", coordBufferOffset, coordBufferSize);
+ env->FatalError("error copying coord data");
+ exit(-1);
+ }
+
+ bool res = copyBufferArray(env, jMesh, "m_texcoords", c, coordBuffer, coordBufferSize);
+
+ free(coordBuffer);
+
+ if (!res)
+ {
+ lprintf("could not copy texture coordinates data\n");
+ return false;
+ }
+
+ lprintf(" with %uD texcoord[%d]\n", cMesh->mNumUVComponents[c], c);
+ }
+ }
+
+
+ for (unsigned int b = 0; b < cMesh->mNumBones; b++)
+ {
+ aiBone *cBone = cMesh->mBones[b];
+
+ jobject jBone;
+ SmartLocalRef refBone(env, jBone);
+ if (!createInstance(env, "jassimp/AiBone", jBone))
+ {
+ return false;
+ }
+
+ /* add bone to bone list */
+ jobject jBones = NULL;
+ SmartLocalRef refBones(env, jBones);
+ if (!getField(env, jMesh, "m_bones", "Ljava/util/List;", jBones))
+ {
+ return false;
+ }
+
+ jvalue addParams[1];
+ addParams[0].l = jBone;
+ if (!call(env, jBones, "java/util/Collection", "add", "(Ljava/lang/Object;)Z", addParams))
+ {
+ return false;
+ }
+
+ /* set bone data */
+ jstring boneNameString = env->NewStringUTF(cBone->mName.C_Str());
+ SmartLocalRef refNameString(env, boneNameString);
+ if (!setObjectField(env, jBone, "m_name", "Ljava/lang/String;", boneNameString))
+ {
+ return false;
+ }
+
+ /* add bone weights */
+ for (unsigned int w = 0; w < cBone->mNumWeights; w++)
+ {
+ jobject jBoneWeight;
+ SmartLocalRef refBoneWeight(env, jBoneWeight);
+ if (!createInstance(env, "jassimp/AiBoneWeight", jBoneWeight))
+ {
+ return false;
+ }
+
+ /* add boneweight to bone list */
+ jobject jBoneWeights = NULL;
+ SmartLocalRef refBoneWeights(env, jBoneWeights);
+ if (!getField(env, jBone, "m_boneWeights", "Ljava/util/List;", jBoneWeights))
+ {
+ return false;
+ }
+
+ /* copy offset matrix */
+ jfloatArray jMatrixArr = env->NewFloatArray(16);
+ SmartLocalRef refMatrixArr(env, jMatrixArr);
+ env->SetFloatArrayRegion(jMatrixArr, 0, 16, (jfloat*) &cBone->mOffsetMatrix);
+
+ jvalue wrapParams[1];
+ wrapParams[0].l = jMatrixArr;
+ jobject jMatrix;
+ SmartLocalRef refMatrix(env, jMatrix);
+
+ if (!callStaticObject(env, "jassimp/Jassimp", "wrapMatrix", "([F)Ljava/lang/Object;", wrapParams, jMatrix))
+ {
+ return false;
+ }
+
+ if (!setObjectField(env, jBone, "m_offsetMatrix", "Ljava/lang/Object;", jMatrix))
+ {
+ return false;
+ }
+
+
+ jvalue addBwParams[1];
+ addBwParams[0].l = jBoneWeight;
+ if (!call(env, jBoneWeights, "java/util/Collection", "add", "(Ljava/lang/Object;)Z", addBwParams))
+ {
+ return false;
+ }
+
+
+ if (!setIntField(env, jBoneWeight, "m_vertexId", cBone->mWeights[w].mVertexId))
+ {
+ return false;
+ }
+
+ if (!setFloatField(env, jBoneWeight, "m_weight", cBone->mWeights[w].mWeight))
+ {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+static bool loadMetadata(JNIEnv *env, const aiNode* cNode, jobject& jNode)
+{
+ aiMetadata *cMetadata = cNode->mMetaData;
+
+ for(unsigned i = 0; i<cMetadata->mNumProperties; i++) {
+
+ aiString& metaDataKey = cMetadata->mKeys[i];
+ void* cData = cMetadata->mValues[i].mData;
+ aiMetadataType cMetadataType = cMetadata->mValues[i].mType;
+
+ jobject jAiMetadataEntry = NULL;
+ SmartLocalRef refMetadataEntry(env, jAiMetadataEntry);
+
+ if(!createInstance(env, "jassimp/AiMetadataEntry", jAiMetadataEntry)) {
+ return false;
+ }
+
+ jobject jAiMetadataTypeEnumValue = NULL;
+ SmartLocalRef refMetadataTypeEnumValue(env, jAiMetadataTypeEnumValue);
+
+ jobject jMetadataData = NULL;
+ SmartLocalRef refMetadataData(env, jMetadataData);
+
+ bool getMetadataTypeSuccess = false;
+ bool getMetadataDataSuccess = false;
+
+ jvalue boxingMethodArgument[1];
+
+ jboolean exceptionThrown;
+
+ switch (cMetadataType) {
+
+ case AI_BOOL: {
+ getMetadataTypeSuccess = getStaticField(env, "jassimp/AiMetadataEntry$AiMetadataType", "AI_BOOL", "Ljassimp/AiMetadataEntry$AiMetadataType;", jAiMetadataTypeEnumValue);
+ boxingMethodArgument[0].z = (jboolean) *static_cast<bool*>(cData);
+ getMetadataDataSuccess = callStaticObject(env, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", boxingMethodArgument, jMetadataData);
+ break;
+ }
+ case AI_INT32: {
+ getMetadataTypeSuccess = getStaticField(env, "jassimp/AiMetadataEntry$AiMetadataType", "AI_INT32", "Ljassimp/AiMetadataEntry$AiMetadataType;", jAiMetadataTypeEnumValue);
+ boxingMethodArgument[0].i = (jint) *static_cast<int32_t*>(cData);
+ getMetadataDataSuccess = callStaticObject(env, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", boxingMethodArgument, jMetadataData);
+ break;
+ }
+ case AI_UINT64: {
+ getMetadataTypeSuccess = getStaticField(env, "jassimp/AiMetadataEntry$AiMetadataType", "AI_UINT64", "Ljassimp/AiMetadataEntry$AiMetadataType;", jAiMetadataTypeEnumValue);
+ boxingMethodArgument[0].j = (jlong) *static_cast<uint64_t*>(cData);
+ getMetadataDataSuccess = callStaticObject(env, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", boxingMethodArgument, jMetadataData);
+ break;
+ }
+ case AI_FLOAT: {
+ getMetadataTypeSuccess = getStaticField(env, "jassimp/AiMetadataEntry$AiMetadataType", "AI_FLOAT", "Ljassimp/AiMetadataEntry$AiMetadataType;", jAiMetadataTypeEnumValue);
+ boxingMethodArgument[0].f = (jfloat) *static_cast<float*>(cData);
+ getMetadataDataSuccess = callStaticObject(env, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", boxingMethodArgument, jMetadataData);
+ break;
+ }
+ case AI_DOUBLE: {
+ getMetadataTypeSuccess = getStaticField(env, "jassimp/AiMetadataEntry$AiMetadataType", "AI_DOUBLE", "Ljassimp/AiMetadataEntry$AiMetadataType;", jAiMetadataTypeEnumValue);
+ boxingMethodArgument[0].d = (jdouble) *static_cast<double*>(cData);
+ getMetadataDataSuccess = callStaticObject(env, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", boxingMethodArgument, jMetadataData);
+ break;
+ }
+ case AI_AISTRING: {
+ getMetadataTypeSuccess = getStaticField(env, "jassimp/AiMetadataEntry$AiMetadataType", "AI_AISTRING", "Ljassimp/AiMetadataEntry$AiMetadataType;", jAiMetadataTypeEnumValue);
+ jMetadataData = env->NewStringUTF(static_cast<aiString*>(cData)->C_Str());
+ getMetadataDataSuccess = (jMetadataData != NULL);
+ break;
+ }
+ case AI_AIVECTOR3D: {
+ getMetadataTypeSuccess = getStaticField(env, "jassimp/AiMetadataEntry$AiMetadataType", "AI_AIVECTOR3D",
+ "Ljassimp/AiMetadataEntry$AiMetadataType;",
+ jAiMetadataTypeEnumValue);
+ jvalue wrapVec3Args[3];
+ aiVector3D *vector3D = static_cast<aiVector3D *>(cData);
+ wrapVec3Args[0].f = vector3D->x;
+ wrapVec3Args[1].f = vector3D->y;
+ wrapVec3Args[2].f = vector3D->z;
+ getMetadataDataSuccess = callStaticObject(env, "jassimp/Jassimp", "wrapVec3", "(FFF)Ljava/lang/Object;",
+ wrapVec3Args, jMetadataData);
+ break;
+ }
+ default: {
+ getMetadataTypeSuccess = false;
+ getMetadataDataSuccess = false;
+ break;
+ }
+ }
+
+ exceptionThrown = env->ExceptionCheck();
+
+ if(!getMetadataTypeSuccess || !getMetadataDataSuccess) {
+ if(exceptionThrown)
+ {
+ env->ExceptionDescribe();
+ }
+
+ return false;
+ }
+
+ if(!setObjectField(env, jAiMetadataEntry, "mType", "Ljassimp/AiMetadataEntry$AiMetadataType;", jAiMetadataTypeEnumValue)) {
+ exceptionThrown = env->ExceptionCheck();
+
+ if(exceptionThrown)
+ {
+ env->ExceptionDescribe();
+ }
+
+ return false;
+ }
+
+ if(!setObjectField(env, jAiMetadataEntry, "mData", "Ljava/lang/Object;", jMetadataData)) {
+ exceptionThrown = env->ExceptionCheck();
+
+ if(exceptionThrown)
+ {
+ env->ExceptionDescribe();
+ }
+
+ return false;
+ }
+
+ jobject jNodeMetadata = NULL;
+ SmartLocalRef refMetadata(env, jNodeMetadata);
+
+ if(!getField(env, jNode, "m_metaData", "Ljava/util/Map;", jNodeMetadata)) {
+ exceptionThrown = env->ExceptionCheck();
+
+ if(exceptionThrown)
+ {
+ env->ExceptionDescribe();
+ }
+
+ return false;
+ }
+
+ jclass hashMapClass = env->FindClass("java/util/HashMap");
+ jmethodID jHashMapPutMethod = env->GetMethodID(hashMapClass, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
+
+ jstring jKey = env->NewStringUTF(metaDataKey.C_Str());
+ SmartLocalRef keyRef(env, jKey);
+
+ // Only check exception instead of result here because maps will return
+ // null on success if they did not overwrite an existing mapping for the given key.
+ env->CallObjectMethod(jNodeMetadata, jHashMapPutMethod, jKey, jAiMetadataEntry);
+
+ exceptionThrown = env->ExceptionCheck();
+
+ if(exceptionThrown) {
+ env->ExceptionDescribe();
+ return false;
+ }
+
+ }
+
+ return true;
+}
+
+static bool loadSceneNode(JNIEnv *env, const aiNode *cNode, jobject parent, jobject* loadedNode = NULL)
+{
+ lprintf(" converting node %s ...\n", cNode->mName.C_Str());
+
+ /* wrap matrix */
+ jfloatArray jMatrixArr = env->NewFloatArray(16);
+ SmartLocalRef refMatrixArr(env, jMatrixArr);
+ env->SetFloatArrayRegion(jMatrixArr, 0, 16, (jfloat*) &cNode->mTransformation);
+
+ jvalue wrapMatParams[1];
+ wrapMatParams[0].l = jMatrixArr;
+ jobject jMatrix;
+ SmartLocalRef refMatrix(env, jMatrix);
+
+ if (!callStaticObject(env, "jassimp/Jassimp", "wrapMatrix", "([F)Ljava/lang/Object;", wrapMatParams, jMatrix))
+ {
+ return false;
+ }
+
+
+ /* create mesh references array */
+ jintArray jMeshrefArr = env->NewIntArray(cNode->mNumMeshes);
+ SmartLocalRef refMeshrefArr(env, jMeshrefArr);
+
+ jint *temp = (jint*) malloc(sizeof(jint) * cNode->mNumMeshes);
+
+ for (unsigned int i = 0; i < cNode->mNumMeshes; i++)
+ {
+ temp[i] = cNode->mMeshes[i];
+ }
+ env->SetIntArrayRegion(jMeshrefArr, 0, cNode->mNumMeshes, (jint*) temp);
+
+ free(temp);
+
+
+ /* convert name */
+ jstring jNodeName = env->NewStringUTF(cNode->mName.C_Str());
+ SmartLocalRef refNodeName(env, jNodeName);
+
+ /* wrap scene node */
+ jvalue wrapNodeParams[4];
+ wrapNodeParams[0].l = parent;
+ wrapNodeParams[1].l = jMatrix;
+ wrapNodeParams[2].l = jMeshrefArr;
+ wrapNodeParams[3].l = jNodeName;
+ jobject jNode;
+ if (!callStaticObject(env, "jassimp/Jassimp", "wrapSceneNode",
+ "(Ljava/lang/Object;Ljava/lang/Object;[ILjava/lang/String;)Ljava/lang/Object;", wrapNodeParams, jNode))
+ {
+ return false;
+ }
+
+
+ /* and recurse */
+ for (unsigned int c = 0; c < cNode->mNumChildren; c++)
+ {
+ if (!loadSceneNode(env, cNode->mChildren[c], jNode))
+ {
+ return false;
+ }
+ }
+
+ if (NULL != loadedNode)
+ {
+ if(cNode->mMetaData) {
+ if(!loadMetadata(env, cNode, jNode))
+ {
+ return false;
+ }
+ }
+
+ *loadedNode = jNode;
+ } else {
+ env->DeleteLocalRef(jNode);
+ }
+
+ return true;
+}
+
+
+static bool loadSceneGraph(JNIEnv *env, const aiScene* cScene, jobject& jScene)
+{
+ lprintf("converting scene graph ...\n");
+
+ if (NULL != cScene->mRootNode)
+ {
+ jobject jRoot;
+ SmartLocalRef refRoot(env, jRoot);
+
+ if (!loadSceneNode(env, cScene->mRootNode, NULL, &jRoot))
+ {
+ return false;
+ }
+
+ if (!setObjectField(env, jScene, "m_sceneRoot", "Ljava/lang/Object;", jRoot))
+ {
+ return false;
+ }
+ }
+
+ lprintf("converting scene graph finished\n");
+
+ return true;
+}
+
+
+static bool loadMaterials(JNIEnv *env, const aiScene* cScene, jobject& jScene)
+{
+ for (unsigned int m = 0; m < cScene->mNumMaterials; m++)
+ {
+ const aiMaterial* cMaterial = cScene->mMaterials[m];
+
+ lprintf("converting material %d ...\n", m);
+
+ jobject jMaterial = NULL;
+ SmartLocalRef refMaterial(env, jMaterial);
+
+ if (!createInstance(env, "jassimp/AiMaterial", jMaterial))
+ {
+ return false;
+ }
+
+ /* add material to m_materials java.util.List */
+ jobject jMaterials = NULL;
+ SmartLocalRef refMaterials(env, jMaterials);
+
+ if (!getField(env, jScene, "m_materials", "Ljava/util/List;", jMaterials))
+ {
+ return false;
+ }
+
+ jvalue addMatParams[1];
+ addMatParams[0].l = jMaterial;
+ if (!call(env, jMaterials, "java/util/Collection", "add", "(Ljava/lang/Object;)Z", addMatParams))
+ {
+ return false;
+ }
+
+ /* set texture numbers */
+ for (int ttInd = aiTextureType_DIFFUSE; ttInd < aiTextureType_UNKNOWN; ttInd++)
+ {
+ aiTextureType tt = static_cast<aiTextureType>(ttInd);
+
+ unsigned int num = cMaterial->GetTextureCount(tt);
+
+ lprintf(" found %d textures of type %d ...\n", num, ttInd);
+
+ jvalue setNumberParams[2];
+ setNumberParams[0].i = ttInd;
+ setNumberParams[1].i = num;
+
+ if (!callv(env, jMaterial, "jassimp/AiMaterial", "setTextureNumber", "(II)V", setNumberParams))
+ {
+ return false;
+ }
+ }
+
+
+ for (unsigned int p = 0; p < cMaterial->mNumProperties; p++)
+ {
+ //printf("%s - %u - %u\n", cScene->mMaterials[m]->mProperties[p]->mKey.C_Str(),
+ // cScene->mMaterials[m]->mProperties[p]->mSemantic,
+ // cScene->mMaterials[m]->mProperties[p]->mDataLength);
+
+ const aiMaterialProperty* cProperty = cMaterial->mProperties[p];
+
+ lprintf(" converting property %s ...\n", cProperty->mKey.C_Str());
+
+ jobject jProperty = NULL;
+ SmartLocalRef refProperty(env, jProperty);
+
+ jvalue constructorParams[5];
+ jstring keyString = env->NewStringUTF(cProperty->mKey.C_Str());
+ SmartLocalRef refKeyString(env, keyString);
+ constructorParams[0].l = keyString;
+ constructorParams[1].i = cProperty->mSemantic;
+ constructorParams[2].i = cProperty->mIndex;
+ constructorParams[3].i = cProperty->mType;
+
+
+ /* special case conversion for color3 */
+ if (NULL != strstr(cProperty->mKey.C_Str(), "clr") &&
+ cProperty->mType == aiPTI_Float &&
+ cProperty->mDataLength == 3 * sizeof(float))
+ {
+ jobject jData = NULL;
+ SmartLocalRef refData(env, jData);
+
+ /* wrap color */
+ jvalue wrapColorParams[3];
+ wrapColorParams[0].f = ((float*) cProperty->mData)[0];
+ wrapColorParams[1].f = ((float*) cProperty->mData)[1];
+ wrapColorParams[2].f = ((float*) cProperty->mData)[2];
+ if (!callStaticObject(env, "jassimp/Jassimp", "wrapColor3", "(FFF)Ljava/lang/Object;", wrapColorParams, jData))
+ {
+ return false;
+ }
+
+ constructorParams[4].l = jData;
+ if (!createInstance(env, "jassimp/AiMaterial$Property", "(Ljava/lang/String;IIILjava/lang/Object;)V",
+ constructorParams, jProperty))
+ {
+ return false;
+ }
+ }
+ /* special case conversion for color4 */
+ else if (NULL != strstr(cProperty->mKey.C_Str(), "clr") &&
+ cProperty->mType == aiPTI_Float &&
+ cProperty->mDataLength == 4 * sizeof(float))
+ {
+ jobject jData = NULL;
+ SmartLocalRef refData(env, jData);
+
+ /* wrap color */
+ jvalue wrapColorParams[4];
+ wrapColorParams[0].f = ((float*) cProperty->mData)[0];
+ wrapColorParams[1].f = ((float*) cProperty->mData)[1];
+ wrapColorParams[2].f = ((float*) cProperty->mData)[2];
+ wrapColorParams[3].f = ((float*) cProperty->mData)[3];
+ if (!callStaticObject(env, "jassimp/Jassimp", "wrapColor4", "(FFFF)Ljava/lang/Object;", wrapColorParams, jData))
+ {
+ return false;
+ }
+
+ constructorParams[4].l = jData;
+ if (!createInstance(env, "jassimp/AiMaterial$Property", "(Ljava/lang/String;IIILjava/lang/Object;)V",
+ constructorParams, jProperty))
+ {
+ return false;
+ }
+ }
+ else if (cProperty->mType == aiPTI_Float && cProperty->mDataLength == sizeof(float))
+ {
+ jobject jData = NULL;
+ SmartLocalRef refData(env, jData);
+
+ jvalue newFloatParams[1];
+ newFloatParams[0].f = ((float*) cProperty->mData)[0];
+ if (!createInstance(env, "java/lang/Float", "(F)V", newFloatParams, jData))
+ {
+ return false;
+ }
+
+ constructorParams[4].l = jData;
+ if (!createInstance(env, "jassimp/AiMaterial$Property", "(Ljava/lang/String;IIILjava/lang/Object;)V",
+ constructorParams, jProperty))
+ {
+ return false;
+ }
+ }
+ else if (cProperty->mType == aiPTI_Integer && cProperty->mDataLength == sizeof(int))
+ {
+ jobject jData = NULL;
+ SmartLocalRef refData(env, jData);
+
+ jvalue newIntParams[1];
+ newIntParams[0].i = ((int*) cProperty->mData)[0];
+ if (!createInstance(env, "java/lang/Integer", "(I)V", newIntParams, jData))
+ {
+ return false;
+ }
+
+ constructorParams[4].l = jData;
+ if (!createInstance(env, "jassimp/AiMaterial$Property", "(Ljava/lang/String;IIILjava/lang/Object;)V",
+ constructorParams, jProperty))
+ {
+ return false;
+ }
+ }
+ else if (cProperty->mType == aiPTI_String)
+ {
+ /* skip length prefix */
+ jobject jData = env->NewStringUTF(cProperty->mData + 4);
+ SmartLocalRef refData(env, jData);
+
+ constructorParams[4].l = jData;
+ if (!createInstance(env, "jassimp/AiMaterial$Property", "(Ljava/lang/String;IIILjava/lang/Object;)V",
+ constructorParams, jProperty))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ constructorParams[4].i = cProperty->mDataLength;
+
+ /* generic copy code, uses dump ByteBuffer on java side */
+ if (!createInstance(env, "jassimp/AiMaterial$Property", "(Ljava/lang/String;IIII)V", constructorParams, jProperty))
+ {
+ return false;
+ }
+
+ jobject jBuffer = NULL;
+ SmartLocalRef refBuffer(env, jBuffer);
+ if (!getField(env, jProperty, "m_data", "Ljava/lang/Object;", jBuffer))
+ {
+ return false;
+ }
+
+ if (env->GetDirectBufferCapacity(jBuffer) != cProperty->mDataLength)
+ {
+ lprintf("invalid direct buffer\n");
+ return false;
+ }
+
+ void* jBufferPtr = env->GetDirectBufferAddress(jBuffer);
+
+ if (NULL == jBufferPtr)
+ {
+ lprintf("could not access direct buffer\n");
+ return false;
+ }
+
+ memcpy(jBufferPtr, cProperty->mData, cProperty->mDataLength);
+ }
+
+
+ /* add property */
+ jobject jProperties = NULL;
+ SmartLocalRef refProperties(env, jProperties);
+ if (!getField(env, jMaterial, "m_properties", "Ljava/util/List;", jProperties))
+ {
+ return false;
+ }
+
+ jvalue addPropParams[1];
+ addPropParams[0].l = jProperty;
+ if (!call(env, jProperties, "java/util/Collection", "add", "(Ljava/lang/Object;)Z", addPropParams))
+ {
+ return false;
+ }
+ }
+ }
+
+ lprintf("materials finished\n");
+
+ return true;
+}
+
+
+static bool loadAnimations(JNIEnv *env, const aiScene* cScene, jobject& jScene)
+{
+ lprintf("converting %d animations ...\n", cScene->mNumAnimations);
+
+ for (unsigned int a = 0; a < cScene->mNumAnimations; a++)
+ {
+ const aiAnimation *cAnimation = cScene->mAnimations[a];
+
+ lprintf(" converting animation %s ...\n", cAnimation->mName.C_Str());
+
+ jobject jAnimation;
+ SmartLocalRef refAnimation(env, jAnimation);
+
+ jvalue newAnimParams[3];
+ jstring nameString = env->NewStringUTF(cAnimation->mName.C_Str());
+ SmartLocalRef refNameString(env, nameString);
+ newAnimParams[0].l = nameString;
+ newAnimParams[1].d = cAnimation->mDuration;
+ newAnimParams[2].d = cAnimation->mTicksPerSecond;
+
+ if (!createInstance(env, "jassimp/AiAnimation", "(Ljava/lang/String;DD)V", newAnimParams, jAnimation))
+ {
+ return false;
+ }
+
+ /* add animation to m_animations java.util.List */
+ jobject jAnimations = NULL;
+ SmartLocalRef refAnimations(env, jAnimations);
+
+ if (!getField(env, jScene, "m_animations", "Ljava/util/List;", jAnimations))
+ {
+ return false;
+ }
+
+ jvalue addParams[1];
+ addParams[0].l = jAnimation;
+ if (!call(env, jAnimations, "java/util/Collection", "add", "(Ljava/lang/Object;)Z", addParams))
+ {
+ return false;
+ }
+
+
+ for (unsigned int c = 0; c < cAnimation->mNumChannels; c++)
+ {
+ const aiNodeAnim *cNodeAnim = cAnimation->mChannels[c];
+
+ jobject jNodeAnim;
+ SmartLocalRef refNodeAnim(env, jNodeAnim);
+
+ jvalue newNodeAnimParams[6];
+ jstring animationName = env->NewStringUTF(cNodeAnim->mNodeName.C_Str());
+ SmartLocalRef refAnimationName(env, animationName);
+ newNodeAnimParams[0].l = animationName;
+ newNodeAnimParams[1].i = cNodeAnim->mNumPositionKeys;
+ newNodeAnimParams[2].i = cNodeAnim->mNumRotationKeys;
+ newNodeAnimParams[3].i = cNodeAnim->mNumScalingKeys;
+ newNodeAnimParams[4].i = cNodeAnim->mPreState;
+ newNodeAnimParams[5].i = cNodeAnim->mPostState;
+
+ if (!createInstance(env, "jassimp/AiNodeAnim", "(Ljava/lang/String;IIIII)V", newNodeAnimParams, jNodeAnim))
+ {
+ return false;
+ }
+
+
+ /* add nodeanim to m_animations java.util.List */
+ jobject jNodeAnims = NULL;
+ SmartLocalRef refNodeAnims(env, jNodeAnims);
+
+ if (!getField(env, jAnimation, "m_nodeAnims", "Ljava/util/List;", jNodeAnims))
+ {
+ return false;
+ }
+
+ jvalue addParams[1];
+ addParams[0].l = jNodeAnim;
+ if (!call(env, jNodeAnims, "java/util/Collection", "add", "(Ljava/lang/Object;)Z", addParams))
+ {
+ return false;
+ }
+
+ /* copy keys */
+ if (!copyBuffer(env, jNodeAnim, "m_posKeys", cNodeAnim->mPositionKeys,
+ cNodeAnim->mNumPositionKeys * sizeof(aiVectorKey)))
+ {
+ return false;
+ }
+
+ if (!copyBuffer(env, jNodeAnim, "m_rotKeys", cNodeAnim->mRotationKeys,
+ cNodeAnim->mNumRotationKeys * sizeof(aiQuatKey)))
+ {
+ return false;
+ }
+
+ if (!copyBuffer(env, jNodeAnim, "m_scaleKeys", cNodeAnim->mScalingKeys,
+ cNodeAnim->mNumScalingKeys * sizeof(aiVectorKey)))
+ {
+ return false;
+ }
+ }
+ }
+
+ lprintf("converting animations finished\n");
+
+ return true;
+}
+
+
+static bool loadLights(JNIEnv *env, const aiScene* cScene, jobject& jScene)
+{
+ lprintf("converting %d lights ...\n", cScene->mNumLights);
+
+ for (unsigned int l = 0; l < cScene->mNumLights; l++)
+ {
+ const aiLight *cLight = cScene->mLights[l];
+
+ lprintf("converting light %s ...\n", cLight->mName.C_Str());
+
+ /* wrap color nodes */
+ jvalue wrapColorParams[3];
+ wrapColorParams[0].f = cLight->mColorDiffuse.r;
+ wrapColorParams[1].f = cLight->mColorDiffuse.g;
+ wrapColorParams[2].f = cLight->mColorDiffuse.b;
+ jobject jDiffuse;
+ SmartLocalRef refDiffuse(env, jDiffuse);
+ if (!callStaticObject(env, "jassimp/Jassimp", "wrapColor3", "(FFF)Ljava/lang/Object;", wrapColorParams, jDiffuse))
+ {
+ return false;
+ }
+
+ wrapColorParams[0].f = cLight->mColorSpecular.r;
+ wrapColorParams[1].f = cLight->mColorSpecular.g;
+ wrapColorParams[2].f = cLight->mColorSpecular.b;
+ jobject jSpecular;
+ SmartLocalRef refSpecular(env, jSpecular);
+ if (!callStaticObject(env, "jassimp/Jassimp", "wrapColor3", "(FFF)Ljava/lang/Object;", wrapColorParams, jSpecular))
+ {
+ return false;
+ }
+
+ wrapColorParams[0].f = cLight->mColorAmbient.r;
+ wrapColorParams[1].f = cLight->mColorAmbient.g;
+ wrapColorParams[2].f = cLight->mColorAmbient.b;
+ jobject jAmbient;
+ SmartLocalRef refAmbient(env, jAmbient);
+ if (!callStaticObject(env, "jassimp/Jassimp", "wrapColor3", "(FFF)Ljava/lang/Object;", wrapColorParams, jAmbient))
+ {
+ return false;
+ }
+
+
+ /* wrap vec3 nodes */
+ jvalue wrapVec3Params[3];
+ wrapVec3Params[0].f = cLight->mPosition.x;
+ wrapVec3Params[1].f = cLight->mPosition.y;
+ wrapVec3Params[2].f = cLight->mPosition.z;
+ jobject jPosition;
+ SmartLocalRef refPosition(env, jPosition);
+ if (!callStaticObject(env, "jassimp/Jassimp", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapVec3Params, jPosition))
+ {
+ return false;
+ }
+
+ wrapVec3Params[0].f = cLight->mPosition.x;
+ wrapVec3Params[1].f = cLight->mPosition.y;
+ wrapVec3Params[2].f = cLight->mPosition.z;
+ jobject jDirection;
+ SmartLocalRef refDirection(env, jDirection);
+ if (!callStaticObject(env, "jassimp/Jassimp", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapVec3Params, jDirection))
+ {
+ return false;
+ }
+
+
+ jobject jLight;
+ SmartLocalRef refLight(env, jLight);
+ jvalue params[12];
+ jstring lightName = env->NewStringUTF(cLight->mName.C_Str());
+ SmartLocalRef refLightName(env, lightName);
+ params[0].l = lightName;
+ params[1].i = cLight->mType;
+ params[2].l = jPosition;
+ params[3].l = jDirection;
+ params[4].f = cLight->mAttenuationConstant;
+ params[5].f = cLight->mAttenuationLinear;
+ params[6].f = cLight->mAttenuationQuadratic;
+ params[7].l = jDiffuse;
+ params[8].l = jSpecular;
+ params[9].l = jAmbient;
+ params[10].f = cLight->mAngleInnerCone;
+ params[11].f = cLight->mAngleOuterCone;
+
+ if (!createInstance(env, "jassimp/AiLight", "(Ljava/lang/String;ILjava/lang/Object;Ljava/lang/Object;FFFLjava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;FF)V",
+ params, jLight))
+ {
+ return false;
+ }
+
+ /* add light to m_lights java.util.List */
+ jobject jLights = NULL;
+ SmartLocalRef refLights(env, jLights);
+
+ if (!getField(env, jScene, "m_lights", "Ljava/util/List;", jLights))
+ {
+ return false;
+ }
+
+ jvalue addParams[1];
+ addParams[0].l = jLight;
+ if (!call(env, jLights, "java/util/Collection", "add", "(Ljava/lang/Object;)Z", addParams))
+ {
+ return false;
+ }
+ }
+
+ lprintf("converting lights finished ...\n");
+
+ return true;
+}
+
+
+static bool loadCameras(JNIEnv *env, const aiScene* cScene, jobject& jScene)
+{
+ lprintf("converting %d cameras ...\n", cScene->mNumCameras);
+
+ for (unsigned int c = 0; c < cScene->mNumCameras; c++)
+ {
+ const aiCamera *cCamera = cScene->mCameras[c];
+
+ lprintf("converting camera %s ...\n", cCamera->mName.C_Str());
+
+ /* wrap color nodes */
+ jvalue wrapPositionParams[3];
+ wrapPositionParams[0].f = cCamera->mPosition.x;
+ wrapPositionParams[1].f = cCamera->mPosition.y;
+ wrapPositionParams[2].f = cCamera->mPosition.z;
+ jobject jPosition;
+ SmartLocalRef refPosition(env, jPosition);
+ if (!callStaticObject(env, "jassimp/Jassimp", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapPositionParams, jPosition))
+ {
+ return false;
+ }
+
+ wrapPositionParams[0].f = cCamera->mUp.x;
+ wrapPositionParams[1].f = cCamera->mUp.y;
+ wrapPositionParams[2].f = cCamera->mUp.z;
+ jobject jUp;
+ SmartLocalRef refUp(env, jUp);
+ if (!callStaticObject(env, "jassimp/Jassimp", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapPositionParams, jUp))
+ {
+ return false;
+ }
+
+ wrapPositionParams[0].f = cCamera->mLookAt.x;
+ wrapPositionParams[1].f = cCamera->mLookAt.y;
+ wrapPositionParams[2].f = cCamera->mLookAt.z;
+ jobject jLookAt;
+ SmartLocalRef refLookAt(env, jLookAt);
+ if (!callStaticObject(env, "jassimp/Jassimp", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapPositionParams, jLookAt))
+ {
+ return false;
+ }
+
+
+ jobject jCamera;
+ SmartLocalRef refCamera(env, jCamera);
+
+ jvalue params[8];
+ jstring cameraName = env->NewStringUTF(cCamera->mName.C_Str());
+ SmartLocalRef refCameraName(env, cameraName);
+ params[0].l = cameraName;
+ params[1].l = jPosition;
+ params[2].l = jUp;
+ params[3].l = jLookAt;
+ params[4].f = cCamera->mHorizontalFOV;
+ params[5].f = cCamera->mClipPlaneNear;
+ params[6].f = cCamera->mClipPlaneFar;
+ params[7].f = cCamera->mAspect;
+
+ if (!createInstance(env, "jassimp/AiCamera", "(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;FFFF)V",
+ params, jCamera))
+ {
+ return false;
+ }
+
+ /* add camera to m_cameras java.util.List */
+ jobject jCameras = NULL;
+ SmartLocalRef refCameras(env, jCameras);
+ if (!getField(env, jScene, "m_cameras", "Ljava/util/List;", jCameras))
+ {
+ return false;
+ }
+
+ jvalue addParams[1];
+ addParams[0].l = jCamera;
+ if (!call(env, jCameras, "java/util/Collection", "add", "(Ljava/lang/Object;)Z", addParams))
+ {
+ return false;
+ }
+ }
+
+ lprintf("converting cameras finished\n");
+
+ return true;
+}
+
+
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getVKeysize
+ (JNIEnv *env, jclass jClazz)
+{
+ const int res = sizeof(aiVectorKey);
+ return res;
+}
+
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getQKeysize
+ (JNIEnv *env, jclass jClazz)
+{
+ const int res = sizeof(aiQuatKey);
+ return res;
+}
+
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getV3Dsize
+ (JNIEnv *env, jclass jClazz)
+{
+ const int res = sizeof(aiVector3D);
+ return res;
+}
+
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getfloatsize
+ (JNIEnv *env, jclass jClazz)
+{
+ const int res = sizeof(float);
+ return res;
+}
+
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getintsize
+ (JNIEnv *env, jclass jClazz)
+{
+ const int res = sizeof(int);
+ return res;
+}
+
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getuintsize
+ (JNIEnv *env, jclass jClazz)
+{
+ const int res = sizeof(unsigned int);
+ return res;
+}
+
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getdoublesize
+ (JNIEnv *env, jclass jClazz)
+{
+ const int res = sizeof(double);
+ return res;
+}
+
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getlongsize
+ (JNIEnv *env, jclass jClazz)
+{
+ const int res = sizeof(long);
+ return res;
+}
+
+JNIEXPORT jstring JNICALL Java_jassimp_Jassimp_getErrorString
+ (JNIEnv *env, jclass jClazz)
+{
+ const char *err = gLastErrorString.c_str();
+
+ if (NULL == err)
+ {
+ return env->NewStringUTF("");
+ }
+
+ return env->NewStringUTF(err);
+}
+
+
+JNIEXPORT jobject JNICALL Java_jassimp_Jassimp_aiImportFile
+ (JNIEnv *env, jclass jClazz, jstring jFilename, jlong postProcess, jobject ioSystem, jobject progressHandler)
+{
+ jobject jScene = NULL;
+
+ /* convert params */
+ const char* cFilename = env->GetStringUTFChars(jFilename, NULL);
+
+ Assimp::Importer imp;
+
+
+ if(ioSystem != NULL)
+ {
+ imp.SetIOHandler(new JavaIOSystem(env, ioSystem));
+ lprintf("Created aiFileIO\n");
+ }
+
+ if(progressHandler != NULL)
+ {
+ imp.SetProgressHandler(new JavaProgressHandler(env, progressHandler));
+ }
+
+ lprintf("opening file: %s\n", cFilename);
+
+ /* do import */
+ const aiScene *cScene = imp.ReadFile(cFilename, (unsigned int) postProcess);
+
+ if (!cScene)
+ {
+ lprintf("import file returned null\n");
+ goto error;
+ }
+
+ if (!createInstance(env, "jassimp/AiScene", jScene))
+ {
+ goto error;
+ }
+
+ if (!loadMeshes(env, cScene, jScene))
+ {
+ goto error;
+ }
+
+ if (!loadMaterials(env, cScene, jScene))
+ {
+ goto error;
+ }
+
+ if (!loadAnimations(env, cScene, jScene))
+ {
+ goto error;
+ }
+
+ if (!loadLights(env, cScene, jScene))
+ {
+ goto error;
+ }
+
+ if (!loadCameras(env, cScene, jScene))
+ {
+ goto error;
+ }
+
+ if (!loadSceneGraph(env, cScene, jScene))
+ {
+ goto error;
+ }
+
+ /* jump over error handling section */
+ goto end;
+
+error:
+ {
+ jclass exception = env->FindClass("java/io/IOException");
+
+ if (NULL == exception)
+ {
+ /* that's really a problem because we cannot throw in this case */
+ env->FatalError("could not throw java.io.IOException");
+ }
+ gLastErrorString = imp.GetErrorString();
+ env->ThrowNew(exception, gLastErrorString.c_str());
+
+ lprintf("problem detected\n");
+ }
+
+end:
+
+ /* free params */
+ env->ReleaseStringUTFChars(jFilename, cFilename);
+
+ lprintf("return from native\n");
+
+ return jScene;
+}
diff --git a/libs/assimp/port/jassimp/jassimp-native/src/jassimp.h b/libs/assimp/port/jassimp/jassimp-native/src/jassimp.h
new file mode 100644
index 0000000..2a4a845
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp-native/src/jassimp.h
@@ -0,0 +1,47 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+#include <stdlib.h>
+/* Header for class jassimp_Jassimp */
+
+#ifndef _Included_jassimp_Jassimp
+#define _Included_jassimp_Jassimp
+#ifdef __cplusplus
+extern "C" {
+#endif
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getVKeysize
+ (JNIEnv *, jclass);
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getQKeysize
+ (JNIEnv *, jclass);
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getV3Dsize
+ (JNIEnv *, jclass);
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getfloatsize
+ (JNIEnv *, jclass);
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getintsize
+ (JNIEnv *, jclass);
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getuintsize
+ (JNIEnv *, jclass);
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getdoublesize
+ (JNIEnv *, jclass);
+JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getlongsize
+ (JNIEnv *, jclass);
+
+/*
+ * Class: jassimp_Jassimp
+ * Method: getErrorString
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_jassimp_Jassimp_getErrorString
+ (JNIEnv *, jclass);
+
+/*
+ * Class: jassimp_Jassimp
+ * Method: aiImportFile
+ * Signature: (Ljava/lang/String;J)Ljassimp/AiScene;
+ */
+JNIEXPORT jobject JNICALL Java_jassimp_Jassimp_aiImportFile
+ (JNIEnv *, jclass, jstring, jlong, jobject, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiAnimBehavior.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiAnimBehavior.java
new file mode 100644
index 0000000..ae4f04a
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiAnimBehavior.java
@@ -0,0 +1,112 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, 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;
+
+
+/**
+ * Defines how an animation channel behaves outside the defined time range.
+ */
+public enum AiAnimBehavior {
+ /**
+ * The value from the default node transformation is taken.
+ */
+ DEFAULT(0x0),
+
+
+ /**
+ * The nearest key value is used without interpolation.
+ */
+ CONSTANT(0x1),
+
+
+ /**
+ * The value of the nearest two keys is linearly extrapolated for the
+ * current time value.
+ */
+ LINEAR(0x2),
+
+
+ /**
+ * The animation is repeated.<p>
+ *
+ * If the animation key go from n to m and the current time is t, use the
+ * value at (t-n) % (|m-n|).
+ */
+ REPEAT(0x3);
+
+
+ /**
+ * Utility method for converting from c/c++ based integer enums to java
+ * enums.<p>
+ *
+ * This method is intended to be used from JNI and my change based on
+ * implementation needs.
+ *
+ * @param rawValue an integer based enum value (as defined by assimp)
+ * @return the enum value corresponding to rawValue
+ */
+ static AiAnimBehavior fromRawValue(int rawValue) {
+ for (AiAnimBehavior type : AiAnimBehavior.values()) {
+ if (type.m_rawValue == rawValue) {
+ return type;
+ }
+ }
+
+ throw new IllegalArgumentException("unexptected raw value: " +
+ rawValue);
+ }
+
+
+ /**
+ * Constructor.
+ *
+ * @param rawValue maps java enum to c/c++ integer enum values
+ */
+ private AiAnimBehavior(int rawValue) {
+ m_rawValue = rawValue;
+ }
+
+
+ /**
+ * The mapped c/c++ integer enum value.
+ */
+ private final int m_rawValue;
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiAnimation.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiAnimation.java
new file mode 100644
index 0000000..856b918
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiAnimation.java
@@ -0,0 +1,175 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An animation.<p>
+ *
+ * An animation consists of keyframe data for a number of nodes. For
+ * each node affected by the animation a separate series of data is given.<p>
+ *
+ * Like {@link AiMesh}, the animation related classes offer a Buffer API, a
+ * Direct API and a wrapped API. Please consult the documentation of
+ * {@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<AiNodeAnim> m_nodeAnims = new ArrayList<AiNodeAnim>();
+
+ /**
+ * Constructor.
+ *
+ * @param name name
+ * @param duration duration
+ * @param ticksPerSecond ticks per second
+ */
+ AiAnimation(String name, double duration, double ticksPerSecond) {
+ m_name = name;
+ m_duration = duration;
+ m_ticksPerSecond = ticksPerSecond;
+ }
+
+
+ /**
+ * Returns the name of the animation.<p>
+ *
+ * If the modeling package this data was exported from does support only
+ * a single animation channel, this name is usually empty (length is zero).
+ *
+ * @return the name
+ */
+ public String getName() {
+ return m_name;
+ }
+
+
+ /**
+ * Returns the duration of the animation in ticks.
+ *
+ * @return the duration
+ */
+ public double getDuration() {
+ return m_duration;
+ }
+
+
+ /**
+ * Returns the ticks per second.<p>
+ *
+ * 0 if not specified in the imported file
+ *
+ * @return the number of ticks per second
+ */
+ public double getTicksPerSecond() {
+ return m_ticksPerSecond;
+ }
+
+
+ /**
+ * Returns the number of bone animation channels.<p>
+ *
+ * Each channel affects a single node. This method will return the same
+ * value as <code>getChannels().size()</code>
+ *
+ * @return the number of bone animation channels
+ */
+ public int getNumChannels() {
+ return m_nodeAnims.size();
+ }
+
+
+ /**
+ * Returns the list of bone animation channels.<p>
+ *
+ * Each channel affects a single node. The array is mNumChannels in size.
+ *
+ * @return the list of bone animation channels
+ */
+ public List<AiNodeAnim> getChannels() {
+ return m_nodeAnims;
+ }
+
+
+ /**
+ * Returns the number of mesh animation channels.<p>
+ *
+ * Each channel affects a single mesh and defines vertex-based animation.
+ * This method will return the same value as
+ * <code>getMeshChannels().size()</code>
+ *
+ * @return the number of mesh animation channels
+ */
+ public int getNumMeshChannels() {
+ throw new UnsupportedOperationException("not implemented yet");
+ }
+
+
+ /**
+ * Returns the list of mesh animation channels.<p>
+ *
+ * Each channel affects a single mesh.
+ *
+ * @return the list of mesh animation channels
+ */
+ public List<AiMeshAnim> getMeshChannels() {
+ throw new UnsupportedOperationException("not implemented yet");
+ }
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiBlendMode.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiBlendMode.java
new file mode 100644
index 0000000..d3a0e0e
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiBlendMode.java
@@ -0,0 +1,117 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, 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;
+
+
+/**
+ * Defines alpha-blend flags.<p>
+ *
+ * If you're familiar with OpenGL or D3D, these flags aren't new to you.
+ * They define *how* the final color value of a pixel is computed, basing
+ * on the previous color at that pixel and the new color value from the
+ * material. The blend formula is:
+ * <br><code>
+ * SourceColor * SourceBlend + DestColor * DestBlend
+ * </code><br>
+ * where <code>DestColor</code> is the previous color in the framebuffer at
+ * this position and <code>SourceColor</code> is the material color before the
+ * transparency calculation.
+ */
+public enum AiBlendMode {
+ /**
+ * Default blending.<p>
+ *
+ * Formula:
+ * <code>
+ * SourceColor*SourceAlpha + DestColor*(1-SourceAlpha)
+ * </code>
+ */
+ DEFAULT(0x0),
+
+
+ /**
+ * Additive blending.<p>
+ *
+ * Formula:
+ * <code>
+ * SourceColor*1 + DestColor*1
+ * </code>
+ */
+ ADDITIVE(0x1);
+
+
+ /**
+ * Utility method for converting from c/c++ based integer enums to java
+ * enums.<p>
+ *
+ * This method is intended to be used from JNI and my change based on
+ * implementation needs.
+ *
+ * @param rawValue an integer based enum value (as defined by assimp)
+ * @return the enum value corresponding to rawValue
+ */
+ static AiBlendMode fromRawValue(int rawValue) {
+ for (AiBlendMode type : AiBlendMode.values()) {
+ if (type.m_rawValue == rawValue) {
+ return type;
+ }
+ }
+
+ throw new IllegalArgumentException("unexptected raw value: " +
+ rawValue);
+ }
+
+
+ /**
+ * Constructor.
+ *
+ * @param rawValue maps java enum to c/c++ integer enum values
+ */
+ private AiBlendMode(int rawValue) {
+ m_rawValue = rawValue;
+ }
+
+
+ /**
+ * The mapped c/c++ integer enum value.
+ */
+ private final int m_rawValue;
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiBone.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiBone.java
new file mode 100644
index 0000000..eaaf481
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiBone.java
@@ -0,0 +1,136 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * A single bone of a mesh.<p>
+ *
+ * A bone has a name by which it can be found in the frame hierarchy and by
+ * which it can be addressed by animations. In addition it has a number of
+ * influences on vertices.<p>
+ *
+ * This class is designed to be mutable, i.e., the returned collections are
+ * writable and may be modified.
+ */
+public final class AiBone {
+ /**
+ * Name of the bone.
+ */
+ private String m_name;
+
+
+ /**
+ * Bone weights.
+ */
+ private final List<AiBoneWeight> m_boneWeights =
+ new ArrayList<AiBoneWeight>();
+
+
+ /**
+ * Offset matrix.
+ */
+ private Object m_offsetMatrix;
+
+ /**
+ * Constructor.
+ */
+ AiBone() {
+ /* nothing to do */
+ }
+
+
+ /**
+ * Returns the name of the bone.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return m_name;
+ }
+
+
+ /**
+ * Returns the number of bone weights.<p>
+ *
+ * This method exists for compatibility with the native assimp API.
+ * The returned value is identical to <code>getBoneWeights().size()</code>
+ *
+ * @return the number of weights
+ */
+ public int getNumWeights() {
+ return m_boneWeights.size();
+ }
+
+
+ /**
+ * Returns a list of bone weights.
+ *
+ * @return the bone weights
+ */
+ public List<AiBoneWeight> getBoneWeights() {
+ return m_boneWeights;
+ }
+
+
+ /**
+ * Returns the offset matrix.<p>
+ *
+ * The offset matrix is a 4x4 matrix that transforms from mesh space to
+ * bone space in bind pose.<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).
+ *
+ * @param wrapperProvider the wrapper provider (used for type inference)
+ *
+ * @return the offset matrix
+ */
+ @SuppressWarnings("unchecked")
+ public <V3, M4, C, N, Q> M4 getOffsetMatrix(
+ AiWrapperProvider<V3, M4, C, N, Q> wrapperProvider) {
+
+ return (M4) m_offsetMatrix;
+ }
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiBoneWeight.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiBoneWeight.java
new file mode 100644
index 0000000..7d7a183
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiBoneWeight.java
@@ -0,0 +1,88 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, 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;
+
+
+/**
+ * A single influence of a bone on a vertex.
+ */
+public final class AiBoneWeight {
+ /**
+ * Constructor.
+ */
+ AiBoneWeight() {
+ /* nothing to do */
+ }
+
+
+ /**
+ * Index of the vertex which is influenced by the bone.
+ *
+ * @return the vertex index
+ */
+ public int getVertexId() {
+ return m_vertexId;
+ }
+
+
+ /**
+ * The strength of the influence in the range (0...1).<p>
+ *
+ * The influence from all bones at one vertex amounts to 1
+ *
+ * @return the influence
+ */
+ public float getWeight() {
+ return m_weight;
+ }
+
+
+ /**
+ * Vertex index.
+ */
+ private int m_vertexId;
+
+
+ /**
+ * Influence of bone on vertex.
+ */
+ private float m_weight;
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiBuiltInWrapperProvider.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiBuiltInWrapperProvider.java
new file mode 100644
index 0000000..ebc23c0
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiBuiltInWrapperProvider.java
@@ -0,0 +1,84 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+import java.nio.ByteBuffer;
+
+
+/**
+ * Wrapper provider using jassimp built in types.
+ */
+public final class AiBuiltInWrapperProvider implements AiWrapperProvider<
+ AiVector, AiMatrix4f, AiColor, AiNode, AiQuaternion> {
+
+ @Override
+ public AiVector wrapVector3f(ByteBuffer buffer, int offset,
+ int numComponents) {
+
+ return new AiVector(buffer, offset, numComponents);
+ }
+
+
+ @Override
+ public AiMatrix4f wrapMatrix4f(float[] data) {
+ return new AiMatrix4f(data);
+ }
+
+
+ @Override
+ public AiColor wrapColor(ByteBuffer buffer, int offset) {
+ return new AiColor(buffer, offset);
+ }
+
+
+ @Override
+ public AiNode wrapSceneNode(Object parent, Object matrix,
+ int[] meshReferences, String name) {
+
+ return new AiNode((AiNode) parent, matrix, meshReferences, name);
+ }
+
+
+ @Override
+ public AiQuaternion wrapQuaternion(ByteBuffer buffer, int offset) {
+ return new AiQuaternion(buffer, offset);
+ }
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiCamera.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiCamera.java
new file mode 100644
index 0000000..b0f692e
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiCamera.java
@@ -0,0 +1,303 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, 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;
+
+
+/**
+ * Helper structure to describe a virtual camera.<p>
+ *
+ * Cameras have a representation in the node graph and can be animated.
+ * An important aspect is that the camera itself is also part of the
+ * scenegraph. This means, any values such as the look-at vector are not
+ * *absolute*, they're <b>relative</b> to the coordinate system defined
+ * by the node which corresponds to the camera. This allows for camera
+ * animations. For static cameras parameters like the 'look-at' or 'up' vectors
+ * are usually specified directly in aiCamera, but beware, they could also
+ * be encoded in the node transformation. The following (pseudo)code sample
+ * shows how to do it: <p>
+ * <code><pre>
+ * // Get the camera matrix for a camera at a specific time
+ * // if the node hierarchy for the camera does not contain
+ * // at least one animated node this is a static computation
+ * get-camera-matrix (node sceneRoot, camera cam) : matrix
+ * {
+ * node cnd = find-node-for-camera(cam)
+ * matrix cmt = identity()
+ *
+ * // as usual - get the absolute camera transformation for this frame
+ * for each node nd in hierarchy from sceneRoot to cnd
+ * matrix cur
+ * if (is-animated(nd))
+ * cur = eval-animation(nd)
+ * else cur = nd->mTransformation;
+ * cmt = mult-matrices( cmt, cur )
+ * end for
+ *
+ * // now multiply with the camera's own local transform
+ * cam = mult-matrices (cam, get-camera-matrix(cmt) )
+ * }
+ * </pre></code>
+ *
+ * <b>Note:</b> some file formats (such as 3DS, ASE) export a "target point" -
+ * the point the camera is looking at (it can even be animated). Assimp
+ * writes the target point as a subnode of the camera's main node,
+ * called "<camName>.Target". However this is just additional information
+ * then the transformation tracks of the camera main node make the
+ * camera already look in the right direction.
+ */
+public final class AiCamera {
+ /**
+ * Constructor.
+ *
+ * @param name name
+ * @param position position
+ * @param up up vector
+ * @param lookAt look-at vector
+ * @param horizontalFOV field of view
+ * @param clipNear near clip plane
+ * @param clipFar far clip plane
+ * @param aspect aspect ratio
+ */
+ AiCamera(String name, Object position, Object up, Object lookAt,
+ float horizontalFOV, float clipNear, float clipFar, float aspect) {
+
+ m_name = name;
+ m_position = position;
+ m_up = up;
+ m_lookAt = lookAt;
+ m_horizontalFOV = horizontalFOV;
+ m_clipNear = clipNear;
+ m_clipFar = clipFar;
+ m_aspect = aspect;
+ }
+
+
+ /**
+ * Returns the name of the camera.<p>
+ *
+ * There must be a node in the scenegraph with the same name.
+ * This node specifies the position of the camera in the scene
+ * hierarchy and can be animated.
+ */
+ public String getName() {
+ return m_name;
+ }
+
+
+ /**
+ * Returns the position of the camera.<p>
+ *
+ * The returned position is relative to the coordinate space defined by the
+ * corresponding node.<p>
+ *
+ * The default value is 0|0|0.<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).<p>
+ *
+ * The built-in behavior is to return a {@link AiVector}.
+ *
+ * @param wrapperProvider the wrapper provider (used for type inference)
+ * @return the position vector
+ */
+ @SuppressWarnings("unchecked")
+ public <V3, M4, C, N, Q> V3 getPosition(AiWrapperProvider<V3, M4, C, N, Q>
+ wrapperProvider) {
+
+ return (V3) m_position;
+ }
+
+
+ /**
+ * Returns the 'Up' - vector of the camera coordinate system.
+ *
+ * The returned vector is relative to the coordinate space defined by the
+ * corresponding node.<p>
+ *
+ * The 'right' vector of the camera coordinate system is the cross product
+ * of the up and lookAt vectors. The default value is 0|1|0. The vector
+ * may be normalized, but it needn't.<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).<p>
+ *
+ * The built-in behavior is to return a {@link AiVector}.
+ *
+ * @param wrapperProvider the wrapper provider (used for type inference)
+ * @return the 'Up' vector
+ */
+ @SuppressWarnings("unchecked")
+ public <V3, M4, C, N, Q> V3 getUp(AiWrapperProvider<V3, M4, C, N, Q>
+ wrapperProvider) {
+
+ return (V3) m_up;
+ }
+
+
+ /**
+ * Returns the 'LookAt' - vector of the camera coordinate system.<p>
+ *
+ * The returned vector is relative to the coordinate space defined by the
+ * corresponding node.<p>
+ *
+ * This is the viewing direction of the user. The default value is 0|0|1.
+ * The vector may be normalized, but it needn't.<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).<p>
+ *
+ * The built-in behavior is to return a {@link AiVector}.
+ *
+ * @param wrapperProvider the wrapper provider (used for type inference)
+ * @return the 'LookAt' vector
+ */
+ @SuppressWarnings("unchecked")
+ public <V3, M4, C, N, Q> V3 getLookAt(AiWrapperProvider<V3, M4, C, N, Q>
+ wrapperProvider) {
+
+ return (V3) m_lookAt;
+ }
+
+
+ /**
+ * Returns the half horizontal field of view angle, in radians.<p>
+ *
+ * The field of view angle is the angle between the center line of the
+ * screen and the left or right border. The default value is 1/4PI.
+ *
+ * @return the half horizontal field of view angle
+ */
+ public float getHorizontalFOV() {
+ return m_horizontalFOV;
+ }
+
+
+ /**
+ * Returns the distance of the near clipping plane from the camera.<p>
+ *
+ * The value may not be 0.f (for arithmetic reasons to prevent a division
+ * through zero). The default value is 0.1f.
+ *
+ * @return the distance of the near clipping plane
+ */
+ public float getClipPlaneNear() {
+ return m_clipNear;
+ }
+
+
+ /**
+ * Returns the distance of the far clipping plane from the camera.<p>
+ *
+ * The far clipping plane must, of course, be further away than the
+ * near clipping plane. The default value is 1000.0f. The ratio
+ * between the near and the far plane should not be too
+ * large (between 1000-10000 should be ok) to avoid floating-point
+ * inaccuracies which could lead to z-fighting.
+ *
+ * @return the distance of the far clipping plane
+ */
+ public float getClipPlaneFar() {
+ return m_clipFar;
+ }
+
+
+ /**
+ * Returns the screen aspect ratio.<p>
+ *
+ * This is the ration between the width and the height of the
+ * screen. Typical values are 4/3, 1/2 or 1/1. This value is
+ * 0 if the aspect ratio is not defined in the source file.
+ * 0 is also the default value.
+ *
+ * @return the screen aspect ratio
+ */
+ public float getAspect() {
+ return m_aspect;
+ }
+
+
+ /**
+ * Name.
+ */
+ private final String m_name;
+
+
+ /**
+ * Position.
+ */
+ private final Object m_position;
+
+
+ /**
+ * Up vector.
+ */
+ private final Object m_up;
+
+
+ /**
+ * Look-At vector.
+ */
+ private final Object m_lookAt;
+
+
+ /**
+ * FOV.
+ */
+ private final float m_horizontalFOV;
+
+
+ /**
+ * Near clipping plane.
+ */
+ private final float m_clipNear;
+
+
+ /**
+ * Far clipping plane.
+ */
+ private final float m_clipFar;
+
+
+ /**
+ * Aspect ratio.
+ */
+ private final float m_aspect;
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiClassLoaderIOSystem.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiClassLoaderIOSystem.java
new file mode 100644
index 0000000..687e9f3
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiClassLoaderIOSystem.java
@@ -0,0 +1,153 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+/**
+ * IOSystem based on the Java classloader.<p>
+ *
+ * This IOSystem allows loading models directly from the
+ * classpath. No extraction to the file system is
+ * necessary.
+ *
+ * @author Jesper Smith
+ *
+ */
+public class AiClassLoaderIOSystem implements AiIOSystem<AiInputStreamIOStream>
+{
+ private final Class<?> clazz;
+ private final ClassLoader classLoader;
+
+ /**
+ * Construct a new AiClassLoaderIOSystem.<p>
+ *
+ * This constructor uses a ClassLoader to resolve
+ * resources.
+ *
+ * @param classLoader classLoader to resolve resources.
+ */
+ public AiClassLoaderIOSystem(ClassLoader classLoader) {
+ this.clazz = null;
+ this.classLoader = classLoader;
+ }
+
+ /**
+ * Construct a new AiClassLoaderIOSystem.<p>
+ *
+ * This constructor uses a Class to resolve
+ * resources.
+ *
+ * @param class<?> class to resolve resources.
+ */
+ public AiClassLoaderIOSystem(Class<?> clazz) {
+ this.clazz = clazz;
+ this.classLoader = null;
+ }
+
+
+ @Override
+ public AiInputStreamIOStream open(String filename, String ioMode) {
+ try {
+
+ InputStream is;
+
+ if(clazz != null) {
+ is = clazz.getResourceAsStream(filename);
+ }
+ else if (classLoader != null) {
+ is = classLoader.getResourceAsStream(filename);
+ }
+ else {
+ System.err.println("[" + getClass().getSimpleName() +
+ "] No class or classLoader provided to resolve " + filename);
+ return null;
+ }
+
+ if(is != null) {
+ return new AiInputStreamIOStream(is);
+ }
+ else {
+ System.err.println("[" + getClass().getSimpleName() +
+ "] Cannot find " + filename);
+ return null;
+ }
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ @Override
+ public void close(AiInputStreamIOStream file) {
+ }
+
+ @Override
+ public boolean exists(String path)
+ {
+ URL url = null;
+ if(clazz != null) {
+ url = clazz.getResource(path);
+ }
+ else if (classLoader != null) {
+ url = classLoader.getResource(path);
+ }
+
+
+ if(url == null)
+ {
+ return false;
+ }
+
+ return true;
+
+ }
+
+ @Override
+ public char getOsSeparator()
+ {
+ return '/';
+ }
+
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiColor.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiColor.java
new file mode 100644
index 0000000..5cea22a
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiColor.java
@@ -0,0 +1,160 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+import java.nio.ByteBuffer;
+
+
+/**
+ * Wrapper for colors.<p>
+ *
+ * The wrapper is writable, i.e., changes performed via the set-methods will
+ * 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.
+ *
+ * @param buffer the buffer to wrap
+ * @param offset offset into buffer
+ */
+ public AiColor(ByteBuffer buffer, int offset) {
+ m_buffer = buffer;
+ m_offset = offset;
+ }
+
+
+ /**
+ * Returns the red color component.
+ *
+ * @return the red component
+ */
+ public float getRed() {
+ return m_buffer.getFloat(m_offset);
+ }
+
+
+ /**
+ * Returns the green color component.
+ *
+ * @return the green component
+ */
+ public float getGreen() {
+ return m_buffer.getFloat(m_offset + 4);
+ }
+
+
+ /**
+ * Returns the blue color component.
+ *
+ * @return the blue component
+ */
+ public float getBlue() {
+ return m_buffer.getFloat(m_offset + 8);
+ }
+
+
+ /**
+ * Returns the alpha color component.
+ *
+ * @return the alpha component
+ */
+ public float getAlpha() {
+ return m_buffer.getFloat(m_offset + 12);
+ }
+
+
+ /**
+ * Sets the red color component.
+ *
+ * @param red the new value
+ */
+ public void setRed(float red) {
+ m_buffer.putFloat(m_offset, red);
+ }
+
+
+ /**
+ * Sets the green color component.
+ *
+ * @param green the new value
+ */
+ public void setGreen(float green) {
+ m_buffer.putFloat(m_offset + 4, green);
+ }
+
+
+ /**
+ * Sets the blue color component.
+ *
+ * @param blue the new value
+ */
+ public void setBlue(float blue) {
+ m_buffer.putFloat(m_offset + 8, blue);
+ }
+
+
+ /**
+ * Sets the alpha color component.
+ *
+ * @param alpha the new value
+ */
+ public void setAlpha(float alpha) {
+ m_buffer.putFloat(m_offset + 12, alpha);
+ }
+
+
+ @Override
+ public String toString() {
+ return "[" + getRed() + ", " + getGreen() + ", " + getBlue() + ", " +
+ getAlpha() + "]";
+ }
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiConfig.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiConfig.java
new file mode 100644
index 0000000..f49ce86
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiConfig.java
@@ -0,0 +1,15 @@
+/*
+ * $Revision$
+ * $Date$
+ */
+package jassimp;
+
+
+/**
+ * Configuration interface for assimp importer.<p>
+ *
+ * This class is work-in-progress
+ */
+public class AiConfig {
+
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiConfigOptions.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiConfigOptions.java
new file mode 100644
index 0000000..6196598
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiConfigOptions.java
@@ -0,0 +1,663 @@
+/*
+ * $Revision$
+ * $Date$
+ */
+package jassimp;
+
+
+/**
+ * Lists all possible configuration options.<p>
+ *
+ * This class is work-in-progress
+ */
+public enum AiConfigOptions {
+ /**
+ * Maximum bone count per mesh for the SplitbyBoneCount step.<p>
+ *
+ * Meshes are split until the maximum number of bones is reached. The
+ * default value is AI_SBBC_DEFAULT_MAX_BONES, which may be altered at
+ * compile-time. This limit is imposed by the native jassimp library
+ * and typically is 60.<p>
+ *
+ * Property data type: integer.
+ */
+ PP_SBBC_MAX_BONES("PP_SBBC_MAX_BONES"),
+
+
+ /**
+ * Specifies the maximum angle that may be between two vertex tangents
+ * that their tangents and bi-tangents are smoothed.<p>
+ *
+ * This applies to the CalcTangentSpace-Step. The angle is specified
+ * in degrees. The maximum value is 175.<p>
+ *
+ * Property type: float. Default value: 45 degrees
+ */
+ PP_CT_MAX_SMOOTHING_ANGLE("PP_CT_MAX_SMOOTHING_ANGLE"),
+
+
+ /**
+ * Source UV channel for tangent space computation.<p>
+ *
+ * The specified channel must exist or an error will be raised.<p>
+ *
+ * Property type: integer. Default value: 0
+ */
+ PP_CT_TEXTURE_CHANNEL_INDEX("PP_CT_TEXTURE_CHANNEL_INDEX"),
+
+
+ /**
+ * Specifies the maximum angle that may be between two face normals
+ * at the same vertex position that their are smoothed together.<p>
+ *
+ * Sometimes referred to as 'crease angle'. This applies to the
+ * GenSmoothNormals-Step. The angle is specified in degrees, so 180 is PI.
+ * The default value is 175 degrees (all vertex normals are smoothed). The
+ * maximum value is 175, too.<p>
+ *
+ * Property type: float.<p>
+ *
+ * Warning: setting this option may cause a severe loss of performance. The
+ * performance is unaffected if the {@link #CONFIG_FAVOUR_SPEED} flag is
+ * set but the output quality may be reduced.
+ */
+ PP_GSN_MAX_SMOOTHING_ANGLE("PP_GSN_MAX_SMOOTHING_ANGLE"),
+
+
+ /**
+ * Sets the colormap (= palette) to be used to decode embedded textures in
+ * MDL (Quake or 3DGS) files.<p>
+ *
+ * This must be a valid path to a file. The file is 768 (256*3) bytes
+ * large and contains RGB triplets for each of the 256 palette entries.
+ * The default value is colormap.lmp. If the file is not found,
+ * a default palette (from Quake 1) is used.<p>
+ *
+ * Property type: string.
+ */
+ IMPORT_MDL_COLORMAP("IMPORT_MDL_COLORMAP"),
+
+
+ /**
+ * Configures the #aiProcess_RemoveRedundantMaterials step to keep
+ * materials matching a name in a given list.<p>
+ *
+ * This is a list of 1 to n strings, ' ' serves as delimiter character.
+ * Identifiers containing whitespaces must be enclosed in *single*
+ * quotation marks. For example:<tt>
+ * "keep-me and_me_to anotherMaterialToBeKept \'name with whitespace\'"</tt>.
+ * If a material matches on of these names, it will not be modified or
+ * removed by the postprocessing step nor will other materials be replaced
+ * by a reference to it.<p>
+ *
+ * This option might be useful if you are using some magic material names
+ * to pass additional semantics through the content pipeline. This ensures
+ * they won't be optimized away, but a general optimization is still
+ * performed for materials not contained in the list.<p>
+ *
+ * Property type: String. Default value: n/a<p>
+ *
+ * <b>Note:</b>Linefeeds, tabs or carriage returns are treated as
+ * whitespace. Material names are case sensitive.
+ */
+ PP_RRM_EXCLUDE_LIST("PP_RRM_EXCLUDE_LIST"),
+
+
+ /**
+ * Configures the {@link AiPostProcessSteps#PRE_TRANSFORM_VERTICES} step
+ * to keep the scene hierarchy. Meshes are moved to worldspace, but no
+ * optimization is performed (read: meshes with equal materials are not
+ * joined. The total number of meshes won't change).<p>
+ *
+ * This option could be of use for you if the scene hierarchy contains
+ * important additional information which you intend to parse.
+ * For rendering, you can still render all meshes in the scene without
+ * any transformations.<p>
+ *
+ * Property type: bool. Default value: false.
+ */
+ PP_PTV_KEEP_HIERARCHY("PP_PTV_KEEP_HIERARCHY"),
+
+
+ /**
+ * Configures the {@link AiPostProcessSteps#PRE_TRANSFORM_VERTICES} step
+ * to normalize all vertex components into the [-1,1] range.<p>
+ *
+ * That is, a bounding box for the whole scene is computed, the maximum
+ * component is taken and all meshes are scaled appropriately (uniformly
+ * of course!). This might be useful if you don't know the spatial
+ * dimension of the input data.<p>
+ *
+ * Property type: bool. Default value: false.
+ */
+ PP_PTV_NORMALIZE("PP_PTV_NORMALIZE"),
+
+
+ /**
+ * Configures the {@link AiPostProcessSteps#FIND_DEGENERATES} step to
+ * remove degenerated primitives from the import - immediately.<p>
+ *
+ * The default behaviour converts degenerated triangles to lines and
+ * degenerated lines to points. See the documentation to the
+ * {@link AiPostProcessSteps#FIND_DEGENERATES} step for a detailed example
+ * of the various ways to get rid of these lines and points if you don't
+ * want them.<p>
+ *
+ * Property type: bool. Default value: false.
+ */
+ PP_FD_REMOVE("PP_FD_REMOVE")
+
+
+// // ---------------------------------------------------------------------------
+// /** @brief Configures the #aiProcess_OptimizeGraph step to preserve nodes
+// * matching a name in a given list.
+// *
+// * This is a list of 1 to n strings, ' ' serves as delimiter character.
+// * Identifiers containing whitespaces must be enclosed in *single*
+// * quotation marks. For example:<tt>
+// * "keep-me and_me_to anotherNodeToBeKept \'name with whitespace\'"</tt>.
+// * If a node matches on of these names, it will not be modified or
+// * removed by the postprocessing step.<br>
+// * This option might be useful if you are using some magic node names
+// * to pass additional semantics through the content pipeline. This ensures
+// * they won't be optimized away, but a general optimization is still
+// * performed for nodes not contained in the list.
+// * Property type: String. Default value: n/a
+// * @note Linefeeds, tabs or carriage returns are treated as whitespace.
+// * Node names are case sensitive.
+// */
+// #define AI_CONFIG_PP_OG_EXCLUDE_LIST \
+// "PP_OG_EXCLUDE_LIST"
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Set the maximum number of triangles in a mesh.
+// *
+// * This is used by the "SplitLargeMeshes" PostProcess-Step to determine
+// * whether a mesh must be split or not.
+// * @note The default value is AI_SLM_DEFAULT_MAX_TRIANGLES
+// * Property type: integer.
+// */
+// #define AI_CONFIG_PP_SLM_TRIANGLE_LIMIT \
+// "PP_SLM_TRIANGLE_LIMIT"
+//
+// // default value for AI_CONFIG_PP_SLM_TRIANGLE_LIMIT
+// #if (!defined AI_SLM_DEFAULT_MAX_TRIANGLES)
+// # define AI_SLM_DEFAULT_MAX_TRIANGLES 1000000
+// #endif
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Set the maximum number of vertices in a mesh.
+// *
+// * This is used by the "SplitLargeMeshes" PostProcess-Step to determine
+// * whether a mesh must be split or not.
+// * @note The default value is AI_SLM_DEFAULT_MAX_VERTICES
+// * Property type: integer.
+// */
+// #define AI_CONFIG_PP_SLM_VERTEX_LIMIT \
+// "PP_SLM_VERTEX_LIMIT"
+//
+// // default value for AI_CONFIG_PP_SLM_VERTEX_LIMIT
+// #if (!defined AI_SLM_DEFAULT_MAX_VERTICES)
+// # define AI_SLM_DEFAULT_MAX_VERTICES 1000000
+// #endif
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Set the maximum number of bones affecting a single vertex
+// *
+// * This is used by the #aiProcess_LimitBoneWeights PostProcess-Step.
+// * @note The default value is AI_LBW_MAX_WEIGHTS
+// * Property type: integer.*/
+// #define AI_CONFIG_PP_LBW_MAX_WEIGHTS \
+// "PP_LBW_MAX_WEIGHTS"
+//
+// // default value for AI_CONFIG_PP_LBW_MAX_WEIGHTS
+// #if (!defined AI_LMW_MAX_WEIGHTS)
+// # define AI_LMW_MAX_WEIGHTS 0x4
+// #endif // !! AI_LMW_MAX_WEIGHTS
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Lower the deboning threshold in order to remove more bones.
+// *
+// * This is used by the #aiProcess_Debone PostProcess-Step.
+// * @note The default value is AI_DEBONE_THRESHOLD
+// * Property type: float.*/
+// #define AI_CONFIG_PP_DB_THRESHOLD \
+// "PP_DB_THRESHOLD"
+//
+// // default value for AI_CONFIG_PP_LBW_MAX_WEIGHTS
+// #if (!defined AI_DEBONE_THRESHOLD)
+// # define AI_DEBONE_THRESHOLD 1.0f
+// #endif // !! AI_DEBONE_THRESHOLD
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Require all bones qualify for deboning before removing any
+// *
+// * This is used by the #aiProcess_Debone PostProcess-Step.
+// * @note The default value is 0
+// * Property type: bool.*/
+// #define AI_CONFIG_PP_DB_ALL_OR_NONE \
+// "PP_DB_ALL_OR_NONE"
+//
+// /** @brief Default value for the #AI_CONFIG_PP_ICL_PTCACHE_SIZE property
+// */
+// #ifndef PP_ICL_PTCACHE_SIZE
+// # define PP_ICL_PTCACHE_SIZE 12
+// #endif
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Set the size of the post-transform vertex cache to optimize the
+// * vertices for. This configures the #aiProcess_ImproveCacheLocality step.
+// *
+// * The size is given in vertices. Of course you can't know how the vertex
+// * format will exactly look like after the import returns, but you can still
+// * guess what your meshes will probably have.
+// * @note The default value is #PP_ICL_PTCACHE_SIZE. That results in slight
+// * performance improvements for most nVidia/AMD cards since 2002.
+// * Property type: integer.
+// */
+// #define AI_CONFIG_PP_ICL_PTCACHE_SIZE "PP_ICL_PTCACHE_SIZE"
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Enumerates components of the aiScene and aiMesh data structures
+// * that can be excluded from the import using the #aiPrpcess_RemoveComponent step.
+// *
+// * See the documentation to #aiProcess_RemoveComponent for more details.
+// */
+// enum aiComponent
+// {
+// /** Normal vectors */
+// #ifdef SWIG
+// aiComponent_NORMALS = 0x2,
+// #else
+// aiComponent_NORMALS = 0x2u,
+// #endif
+//
+// /** Tangents and bitangents go always together ... */
+// #ifdef SWIG
+// aiComponent_TANGENTS_AND_BITANGENTS = 0x4,
+// #else
+// aiComponent_TANGENTS_AND_BITANGENTS = 0x4u,
+// #endif
+//
+// /** ALL color sets
+// * Use aiComponent_COLORn(N) to specify the N'th set */
+// aiComponent_COLORS = 0x8,
+//
+// /** ALL texture UV sets
+// * aiComponent_TEXCOORDn(N) to specify the N'th set */
+// aiComponent_TEXCOORDS = 0x10,
+//
+// /** Removes all bone weights from all meshes.
+// * The scenegraph nodes corresponding to the bones are NOT removed.
+// * use the #aiProcess_OptimizeGraph step to do this */
+// aiComponent_BONEWEIGHTS = 0x20,
+//
+// /** Removes all node animations (aiScene::mAnimations).
+// * The corresponding scenegraph nodes are NOT removed.
+// * use the #aiProcess_OptimizeGraph step to do this */
+// aiComponent_ANIMATIONS = 0x40,
+//
+// /** Removes all embedded textures (aiScene::mTextures) */
+// aiComponent_TEXTURES = 0x80,
+//
+// /** Removes all light sources (aiScene::mLights).
+// * The corresponding scenegraph nodes are NOT removed.
+// * use the #aiProcess_OptimizeGraph step to do this */
+// aiComponent_LIGHTS = 0x100,
+//
+// /** Removes all light sources (aiScene::mCameras).
+// * The corresponding scenegraph nodes are NOT removed.
+// * use the #aiProcess_OptimizeGraph step to do this */
+// aiComponent_CAMERAS = 0x200,
+//
+// /** Removes all meshes (aiScene::mMeshes). */
+// aiComponent_MESHES = 0x400,
+//
+// /** Removes all materials. One default material will
+// * be generated, so aiScene::mNumMaterials will be 1. */
+// aiComponent_MATERIALS = 0x800,
+//
+//
+// /** This value is not used. It is just there to force the
+// * compiler to map this enum to a 32 Bit integer. */
+// #ifndef SWIG
+// _aiComponent_Force32Bit = 0x9fffffff
+// #endif
+// };
+//
+// // Remove a specific color channel 'n'
+// #define aiComponent_COLORSn(n) (1u << (n+20u))
+//
+// // Remove a specific UV channel 'n'
+// #define aiComponent_TEXCOORDSn(n) (1u << (n+25u))
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Input parameter to the #aiProcess_RemoveComponent step:
+// * Specifies the parts of the data structure to be removed.
+// *
+// * See the documentation to this step for further details. The property
+// * is expected to be an integer, a bitwise combination of the
+// * #aiComponent flags defined above in this header. The default
+// * value is 0. Important: if no valid mesh is remaining after the
+// * step has been executed (e.g you thought it was funny to specify ALL
+// * of the flags defined above) the import FAILS. Mainly because there is
+// * no data to work on anymore ...
+// */
+// #define AI_CONFIG_PP_RVC_FLAGS \
+// "PP_RVC_FLAGS"
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Input parameter to the #aiProcess_SortByPType step:
+// * Specifies which primitive types are removed by the step.
+// *
+// * This is a bitwise combination of the aiPrimitiveType flags.
+// * Specifying all of them is illegal, of course. A typical use would
+// * be to exclude all line and point meshes from the import. This
+// * is an integer property, its default value is 0.
+// */
+// #define AI_CONFIG_PP_SBP_REMOVE \
+// "PP_SBP_REMOVE"
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Input parameter to the #aiProcess_FindInvalidData step:
+// * Specifies the floating-point accuracy for animation values. The step
+// * checks for animation tracks where all frame values are absolutely equal
+// * and removes them. This tweakable controls the epsilon for floating-point
+// * comparisons - two keys are considered equal if the invariant
+// * abs(n0-n1)>epsilon holds true for all vector respectively quaternion
+// * components. The default value is 0.f - comparisons are exact then.
+// */
+// #define AI_CONFIG_PP_FID_ANIM_ACCURACY \
+// "PP_FID_ANIM_ACCURACY"
+//
+//
+// // TransformUVCoords evaluates UV scalings
+// #define AI_UVTRAFO_SCALING 0x1
+//
+// // TransformUVCoords evaluates UV rotations
+// #define AI_UVTRAFO_ROTATION 0x2
+//
+// // TransformUVCoords evaluates UV translation
+// #define AI_UVTRAFO_TRANSLATION 0x4
+//
+// // Everything baked together -> default value
+// #define AI_UVTRAFO_ALL (AI_UVTRAFO_SCALING | AI_UVTRAFO_ROTATION | AI_UVTRAFO_TRANSLATION)
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Input parameter to the #aiProcess_TransformUVCoords step:
+// * Specifies which UV transformations are evaluated.
+// *
+// * This is a bitwise combination of the AI_UVTRAFO_XXX flags (integer
+// * property, of course). By default all transformations are enabled
+// * (AI_UVTRAFO_ALL).
+// */
+// #define AI_CONFIG_PP_TUV_EVALUATE \
+// "PP_TUV_EVALUATE"
+//
+// // ---------------------------------------------------------------------------
+// /** @brief A hint to assimp to favour speed against import quality.
+// *
+// * Enabling this option may result in faster loading, but it needn't.
+// * It represents just a hint to loaders and post-processing steps to use
+// * faster code paths, if possible.
+// * This property is expected to be an integer, != 0 stands for true.
+// * The default value is 0.
+// */
+// #define AI_CONFIG_FAVOUR_SPEED \
+// "FAVOUR_SPEED"
+//
+//
+// // ###########################################################################
+// // IMPORTER SETTINGS
+// // Various stuff to fine-tune the behaviour of specific importer plugins.
+// // ###########################################################################
+//
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Set the vertex animation keyframe to be imported
+// *
+// * ASSIMP does not support vertex keyframes (only bone animation is supported).
+// * The library reads only one frame of models with vertex animations.
+// * By default this is the first frame.
+// * \note The default value is 0. This option applies to all importers.
+// * However, it is also possible to override the global setting
+// * for a specific loader. You can use the AI_CONFIG_IMPORT_XXX_KEYFRAME
+// * options (where XXX is a placeholder for the file format for which you
+// * want to override the global setting).
+// * Property type: integer.
+// */
+// #define AI_CONFIG_IMPORT_GLOBAL_KEYFRAME "IMPORT_GLOBAL_KEYFRAME"
+//
+// #define AI_CONFIG_IMPORT_MD3_KEYFRAME "IMPORT_MD3_KEYFRAME"
+// #define AI_CONFIG_IMPORT_MD2_KEYFRAME "IMPORT_MD2_KEYFRAME"
+// #define AI_CONFIG_IMPORT_MDL_KEYFRAME "IMPORT_MDL_KEYFRAME"
+// #define AI_CONFIG_IMPORT_MDC_KEYFRAME "IMPORT_MDC_KEYFRAME"
+// #define AI_CONFIG_IMPORT_SMD_KEYFRAME "IMPORT_SMD_KEYFRAME"
+// #define AI_CONFIG_IMPORT_UNREAL_KEYFRAME "IMPORT_UNREAL_KEYFRAME"
+//
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Configures the AC loader to collect all surfaces which have the
+// * "Backface cull" flag set in separate meshes.
+// *
+// * Property type: bool. Default value: true.
+// */
+// #define AI_CONFIG_IMPORT_AC_SEPARATE_BFCULL \
+// "IMPORT_AC_SEPARATE_BFCULL"
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Configures whether the AC loader evaluates subdivision surfaces (
+// * indicated by the presence of the 'subdiv' attribute in the file). By
+// * default, Assimp performs the subdivision using the standard
+// * Catmull-Clark algorithm
+// *
+// * * Property type: bool. Default value: true.
+// */
+// #define AI_CONFIG_IMPORT_AC_EVAL_SUBDIVISION \
+// "IMPORT_AC_EVAL_SUBDIVISION"
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Configures the UNREAL 3D loader to separate faces with different
+// * surface flags (e.g. two-sided vs. single-sided).
+// *
+// * * Property type: bool. Default value: true.
+// */
+// #define AI_CONFIG_IMPORT_UNREAL_HANDLE_FLAGS \
+// "UNREAL_HANDLE_FLAGS"
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Configures the terragen import plugin to compute uv's for
+// * terrains, if not given. Furthermore a default texture is assigned.
+// *
+// * UV coordinates for terrains are so simple to compute that you'll usually
+// * want to compute them on your own, if you need them. This option is intended
+// * for model viewers which want to offer an easy way to apply textures to
+// * terrains.
+// * * Property type: bool. Default value: false.
+// */
+// #define AI_CONFIG_IMPORT_TER_MAKE_UVS \
+// "IMPORT_TER_MAKE_UVS"
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Configures the ASE loader to always reconstruct normal vectors
+// * basing on the smoothing groups loaded from the file.
+// *
+// * Some ASE files have carry invalid normals, other don't.
+// * * Property type: bool. Default value: true.
+// */
+// #define AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS \
+// "IMPORT_ASE_RECONSTRUCT_NORMALS"
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Configures the M3D loader to detect and process multi-part
+// * Quake player models.
+// *
+// * These models usually consist of 3 files, lower.md3, upper.md3 and
+// * head.md3. If this property is set to true, Assimp will try to load and
+// * combine all three files if one of them is loaded.
+// * Property type: bool. Default value: true.
+// */
+// #define AI_CONFIG_IMPORT_MD3_HANDLE_MULTIPART \
+// "IMPORT_MD3_HANDLE_MULTIPART"
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Tells the MD3 loader which skin files to load.
+// *
+// * When loading MD3 files, Assimp checks whether a file
+// * <md3_file_name>_<skin_name>.skin is existing. These files are used by
+// * Quake III to be able to assign different skins (e.g. red and blue team)
+// * to models. 'default', 'red', 'blue' are typical skin names.
+// * Property type: String. Default value: "default".
+// */
+// #define AI_CONFIG_IMPORT_MD3_SKIN_NAME \
+// "IMPORT_MD3_SKIN_NAME"
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Specify the Quake 3 shader file to be used for a particular
+// * MD3 file. This can also be a search path.
+// *
+// * By default Assimp's behaviour is as follows: If a MD3 file
+// * <tt><any_path>/models/<any_q3_subdir>/<model_name>/<file_name>.md3</tt> is
+// * loaded, the library tries to locate the corresponding shader file in
+// * <tt><any_path>/scripts/<model_name>.shader</tt>. This property overrides this
+// * behaviour. It can either specify a full path to the shader to be loaded
+// * or alternatively the path (relative or absolute) to the directory where
+// * the shaders for all MD3s to be loaded reside. Assimp attempts to open
+// * <tt><dir>/<model_name>.shader</tt> first, <tt><dir>/<file_name>.shader</tt>
+// * is the fallback file. Note that <dir> should have a terminal (back)slash.
+// * Property type: String. Default value: n/a.
+// */
+// #define AI_CONFIG_IMPORT_MD3_SHADER_SRC \
+// "IMPORT_MD3_SHADER_SRC"
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Configures the LWO loader to load just one layer from the model.
+// *
+// * LWO files consist of layers and in some cases it could be useful to load
+// * only one of them. This property can be either a string - which specifies
+// * the name of the layer - or an integer - the index of the layer. If the
+// * property is not set the whole LWO model is loaded. Loading fails if the
+// * requested layer is not available. The layer index is zero-based and the
+// * layer name may not be empty.<br>
+// * Property type: Integer. Default value: all layers are loaded.
+// */
+// #define AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY \
+// "IMPORT_LWO_ONE_LAYER_ONLY"
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Configures the MD5 loader to not load the MD5ANIM file for
+// * a MD5MESH file automatically.
+// *
+// * The default strategy is to look for a file with the same name but the
+// * MD5ANIM extension in the same directory. If it is found, it is loaded
+// * and combined with the MD5MESH file. This configuration option can be
+// * used to disable this behaviour.
+// *
+// * * Property type: bool. Default value: false.
+// */
+// #define AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD \
+// "IMPORT_MD5_NO_ANIM_AUTOLOAD"
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Defines the begin of the time range for which the LWS loader
+// * evaluates animations and computes aiNodeAnim's.
+// *
+// * Assimp provides full conversion of LightWave's envelope system, including
+// * pre and post conditions. The loader computes linearly subsampled animation
+// * chanels with the frame rate given in the LWS file. This property defines
+// * the start time. Note: animation channels are only generated if a node
+// * has at least one envelope with more tan one key assigned. This property.
+// * is given in frames, '0' is the first frame. By default, if this property
+// * is not set, the importer takes the animation start from the input LWS
+// * file ('FirstFrame' line)<br>
+// * Property type: Integer. Default value: taken from file.
+// *
+// * @see AI_CONFIG_IMPORT_LWS_ANIM_END - end of the imported time range
+// */
+// #define AI_CONFIG_IMPORT_LWS_ANIM_START \
+// "IMPORT_LWS_ANIM_START"
+// #define AI_CONFIG_IMPORT_LWS_ANIM_END \
+// "IMPORT_LWS_ANIM_END"
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Defines the output frame rate of the IRR loader.
+// *
+// * IRR animations are difficult to convert for Assimp and there will
+// * always be a loss of quality. This setting defines how many keys per second
+// * are returned by the converter.<br>
+// * Property type: integer. Default value: 100
+// */
+// #define AI_CONFIG_IMPORT_IRR_ANIM_FPS \
+// "IMPORT_IRR_ANIM_FPS"
+//
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Ogre Importer will try to load this Materialfile.
+// *
+// * Ogre Meshes contain only the MaterialName, not the MaterialFile. If there
+// * is no material file with the same name as the material, Ogre Importer will
+// * try to load this file and search the material in it.
+// * <br>
+// * Property type: String. Default value: guessed.
+// */
+// #define AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE "IMPORT_OGRE_MATERIAL_FILE"
+//
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Ogre Importer detect the texture usage from its filename
+// *
+// * Normally, a texture is loaded as a colormap, if no target is specified in the
+// * materialfile. Is this switch is enabled, texture names ending with _n, _l, _s
+// * are used as normalmaps, lightmaps or specularmaps.
+// * <br>
+// * Property type: Bool. Default value: false.
+// */
+// #define AI_CONFIG_IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME "IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME"
+//
+//
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Specifies whether the IFC loader skips over IfcSpace elements.
+// *
+// * IfcSpace elements (and their geometric representations) are used to
+// * represent, well, free space in a building storey.<br>
+// * Property type: Bool. Default value: true.
+// */
+// #define AI_CONFIG_IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS "IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS"
+//
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Specifies whether the IFC loader skips over
+// * shape representations of type 'Curve2D'.
+// *
+// * A lot of files contain both a faceted mesh representation and a outline
+// * with a presentation type of 'Curve2D'. Currently Assimp doesn't convert those,
+// * so turning this option off just clutters the log with errors.<br>
+// * Property type: Bool. Default value: true.
+// */
+// #define AI_CONFIG_IMPORT_IFC_SKIP_CURVE_REPRESENTATIONS "IMPORT_IFC_SKIP_CURVE_REPRESENTATIONS"
+//
+// // ---------------------------------------------------------------------------
+// /** @brief Specifies whether the IFC loader will use its own, custom triangulation
+// * algorithm to triangulate wall and floor meshes.
+// *
+// * If this property is set to false, walls will be either triangulated by
+// * #aiProcess_Triangulate or will be passed through as huge polygons with
+// * faked holes (i.e. holes that are connected with the outer boundary using
+// * a dummy edge). It is highly recommended to set this property to true
+// * if you want triangulated data because #aiProcess_Triangulate is known to
+// * have problems with the kind of polygons that the IFC loader spits out for
+// * complicated meshes.
+// * Property type: Bool. Default value: true.
+// */
+// #define AI_CONFIG_IMPORT_IFC_CUSTOM_TRIANGULATION "IMPORT_IFC_CUSTOM_TRIANGULATION"
+//
+ ;
+
+ private AiConfigOptions(String name) {
+ m_name = name;
+ }
+
+
+ private final String m_name;
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiIOStream.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiIOStream.java
new file mode 100644
index 0000000..71405e6
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiIOStream.java
@@ -0,0 +1,80 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+import java.nio.ByteBuffer;
+
+
+/**
+ * Interface to allow custom resource loaders for jassimp.<p>
+ *
+ * The design is based on passing the file wholly in memory,
+ * because Java inputstreams do not have to support seek. <p>
+ *
+ * Writing files from Java is unsupported.
+ *
+ *
+ * @author Jesper Smith
+ *
+ */
+public interface AiIOStream
+{
+
+ /**
+ * Read all data into buffer. <p>
+ *
+ * The whole stream should be read into the buffer.
+ * No support is provided for partial reads.
+ *
+ * @param buffer Target buffer for the model data
+ *
+ * @return true if successful, false if an error occurred.
+ */
+ boolean read(ByteBuffer buffer);
+
+ /**
+ * The total size of this stream. <p>
+ *
+ * @return total size of this stream
+ */
+ int getFileSize();
+
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiIOSystem.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiIOSystem.java
new file mode 100644
index 0000000..7e15ee0
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiIOSystem.java
@@ -0,0 +1,79 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+public interface AiIOSystem <T extends AiIOStream>
+{
+ /**
+ *
+ * Open a new file with a given path.
+ * When the access to the file is finished, call close() to release all associated resources
+ *
+ * @param path Path to the file
+ * @param ioMode file I/O mode. Required are: "wb", "w", "wt", "rb", "r", "rt".
+ *
+ * @return AiIOStream or null if an error occurred
+ */
+ public T open(String path, String ioMode);
+
+
+ /**
+ * Tests for the existence of a file at the given path.
+ *
+ * @param path path to the file
+ * @return true if there is a file with this path, else false.
+ */
+ public boolean exists(String path);
+
+ /**
+ * Returns the system specific directory separator.<p>
+ *
+ * @return System specific directory separator
+ */
+ public char getOsSeparator();
+
+ /**
+ * Closes the given file and releases all resources associated with it.
+ *
+ * @param file The file instance previously created by Open().
+ */
+ public void close(T file);
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiInputStreamIOStream.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiInputStreamIOStream.java
new file mode 100644
index 0000000..64aa40a
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiInputStreamIOStream.java
@@ -0,0 +1,127 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+import java.net.URL;
+import java.nio.ByteBuffer;
+
+
+/**
+ * Implementation of AiIOStream reading from a InputStream
+ *
+ * @author Jesper Smith
+ *
+ */
+public class AiInputStreamIOStream implements AiIOStream
+{
+ private final ByteArrayOutputStream os = new ByteArrayOutputStream();
+
+
+ public AiInputStreamIOStream(URI uri) throws IOException {
+ this(uri.toURL());
+ }
+
+ public AiInputStreamIOStream(URL url) throws IOException {
+ this(url.openStream());
+ }
+
+ public AiInputStreamIOStream(InputStream is) throws IOException {
+ int read;
+ byte[] data = new byte[1024];
+ while((read = is.read(data, 0, data.length)) != -1) {
+ os.write(data, 0, read);
+ }
+ os.flush();
+
+ is.close();
+ }
+
+ @Override
+ public int getFileSize() {
+ return os.size();
+ }
+
+ @Override
+ public boolean read(ByteBuffer buffer) {
+ ByteBufferOutputStream bos = new ByteBufferOutputStream(buffer);
+ try
+ {
+ os.writeTo(bos);
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Internal helper class to copy the contents of an OutputStream
+ * into a ByteBuffer. This avoids a copy.
+ *
+ */
+ private static class ByteBufferOutputStream extends OutputStream {
+
+ private final ByteBuffer buffer;
+
+ public ByteBufferOutputStream(ByteBuffer buffer) {
+ this.buffer = buffer;
+ }
+
+ @Override
+ public void write(int b) throws IOException
+ {
+ buffer.put((byte) b);
+ }
+
+ @Override
+ public void write(byte b[], int off, int len) throws IOException {
+ buffer.put(b, off, len);
+ }
+ }
+}
+
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiLight.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiLight.java
new file mode 100644
index 0000000..e0a93db
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiLight.java
@@ -0,0 +1,387 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, 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;
+
+
+/**
+ * Describes a light source.<p>
+ *
+ * Assimp supports multiple sorts of light sources, including
+ * directional, point and spot lights. All of them are defined with just
+ * a single structure and distinguished by their parameters.
+ * Note - some file formats (such as 3DS, ASE) export a "target point" -
+ * the point a spot light is looking at (it can even be animated). Assimp
+ * writes the target point as a subnode of a spotlights's main node,
+ * called "&lt;spotName&gt;.Target". However, this is just additional
+ * information then, the transformation tracks of the main node make the
+ * spot light already point in the right direction.
+ */
+public final class AiLight {
+ /**
+ * Constructor.
+ *
+ * @param name
+ * @param type
+ * @param position
+ * @param direction
+ * @param attenuationConstant
+ * @param attenuationLinear
+ * @param attenuationQuadratic
+ * @param diffuse
+ * @param specular
+ * @param ambient
+ * @param innerCone
+ * @param outerCone
+ */
+ AiLight(String name, int type, Object position, Object direction,
+ float attenuationConstant, float attenuationLinear,
+ float attenuationQuadratic, Object diffuse, Object specular,
+ Object ambient, float innerCone, float outerCone) {
+
+ m_name = name;
+ m_type = AiLightType.fromRawValue(type);
+ m_position = position;
+ m_direction = direction;
+ m_attenuationConstant = attenuationConstant;
+ m_attenuationLinear = attenuationLinear;
+ m_attenuationQuadratic = attenuationQuadratic;
+ m_diffuse = diffuse;
+ m_specular = specular;
+ m_ambient = ambient;
+ m_innerCone = innerCone;
+ m_outerCone = outerCone;
+ }
+
+
+ /**
+ * Returns the name of the light source.<p>
+ *
+ * There must be a node in the scenegraph with the same name.
+ * This node specifies the position of the light in the scene
+ * hierarchy and can be animated.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return m_name;
+ }
+
+
+ /**
+ * Returns The type of the light source.
+ *
+ * @return the type
+ */
+ public AiLightType getType() {
+ return m_type;
+ }
+
+
+ /**
+ * Returns the position of the light.<p>
+ *
+ * The position is relative to the transformation of the scene graph node
+ * corresponding to the light. The position is undefined for directional
+ * lights.<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).<p>
+ *
+ * The built in behavior is to return an {@link AiVector}.
+ *
+ *
+ * @param wrapperProvider the wrapper provider (used for type inference)
+ *
+ * @return the position
+ */
+ @SuppressWarnings("unchecked")
+ public <V3, M4, C, N, Q> V3 getPosition(AiWrapperProvider<V3, M4, C, N, Q>
+ wrapperProvider) {
+
+ return (V3) m_position;
+ }
+
+
+ /**
+ * Returns the direction of the light.<p>
+ *
+ * The direction is relative to the transformation of the scene graph node
+ * corresponding to the light. The direction is undefined for point lights.
+ * The vector may be normalized, but it needn't..<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).<p>
+ *
+ * The built in behavior is to return an {@link AiVector}.
+ *
+ * @param wrapperProvider the wrapper provider (used for type inference)
+ * @return the position
+ */
+ @SuppressWarnings("unchecked")
+ public <V3, M4, C, N, Q> V3 getDirection(AiWrapperProvider<V3, M4, C, N, Q>
+ wrapperProvider) {
+
+ return (V3) m_direction;
+ }
+
+
+ /**
+ * Constant light attenuation factor.<p>
+ *
+ * The intensity of the light source at a given distance 'd' from
+ * the light's position is
+ * <code>Atten = 1/( att0 + att1 * d + att2 * d*d)</code>
+ * This member corresponds to the att0 variable in the equation.
+ * Naturally undefined for directional lights.
+ *
+ * @return the constant light attenuation factor
+ */
+ public float getAttenuationConstant() {
+ return m_attenuationConstant;
+ }
+
+
+ /**
+ * Linear light attenuation factor.<p>
+ *
+ * The intensity of the light source at a given distance 'd' from
+ * the light's position is
+ * <code>Atten = 1/( att0 + att1 * d + att2 * d*d)</code>
+ * This member corresponds to the att1 variable in the equation.
+ * Naturally undefined for directional lights.
+ *
+ * @return the linear light attenuation factor
+ */
+ public float getAttenuationLinear() {
+ return m_attenuationLinear;
+ }
+
+
+ /**
+ * Quadratic light attenuation factor.<p>
+ *
+ * The intensity of the light source at a given distance 'd' from
+ * the light's position is
+ * <code>Atten = 1/( att0 + att1 * d + att2 * d*d)</code>
+ * This member corresponds to the att2 variable in the equation.
+ * Naturally undefined for directional lights.
+ *
+ * @return the quadratic light attenuation factor
+ */
+ public float getAttenuationQuadratic() {
+ return m_attenuationQuadratic;
+ }
+
+
+ /**
+ * Diffuse color of the light source.<p>
+ *
+ * The diffuse light color is multiplied with the diffuse
+ * material color to obtain the final color that contributes
+ * to the diffuse shading term.<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).<p>
+ *
+ * The built in behavior is to return an {@link AiColor}.
+ *
+ * @param wrapperProvider the wrapper provider (used for type inference)
+ * @return the diffuse color (alpha will be 1)
+ */
+ @SuppressWarnings("unchecked")
+ public <V3, M4, C, N, Q> C getColorDiffuse(
+ AiWrapperProvider<V3, M4, C, N, Q> wrapperProvider) {
+
+ return (C) m_diffuse;
+ }
+
+
+ /**
+ * Specular color of the light source.<p>
+ *
+ * The specular light color is multiplied with the specular
+ * material color to obtain the final color that contributes
+ * to the specular shading term.<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).<p>
+ *
+ * The built in behavior is to return an {@link AiColor}.
+ *
+ * @param wrapperProvider the wrapper provider (used for type inference)
+ * @return the specular color (alpha will be 1)
+ */
+ @SuppressWarnings("unchecked")
+ public <V3, M4, C, N, Q> C getColorSpecular(
+ AiWrapperProvider<V3, M4, C, N, Q> wrapperProvider) {
+
+ return (C) m_specular;
+ }
+
+
+ /**
+ * Ambient color of the light source.<p>
+ *
+ * The ambient light color is multiplied with the ambient
+ * material color to obtain the final color that contributes
+ * to the ambient shading term. Most renderers will ignore
+ * this value it, is just a remaining of the fixed-function pipeline
+ * that is still supported by quite many file formats.<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).<p>
+ *
+ * The built in behavior is to return an {@link AiColor}.
+ *
+ * @param wrapperProvider the wrapper provider (used for type inference)
+ * @return the ambient color (alpha will be 1)
+ */
+ @SuppressWarnings("unchecked")
+ public <V3, M4, C, N, Q> C getColorAmbient(
+ AiWrapperProvider<V3, M4, C, N, Q> wrapperProvider) {
+
+ return (C) m_ambient;
+ }
+
+
+ /**
+ * Inner angle of a spot light's light cone.<p>
+ *
+ * The spot light has maximum influence on objects inside this
+ * angle. The angle is given in radians. It is 2PI for point
+ * lights and undefined for directional lights.
+ *
+ * @return the inner angle
+ */
+ public float getAngleInnerCone() {
+ return m_innerCone;
+ }
+
+
+ /**
+ * Outer angle of a spot light's light cone.<p>
+ *
+ * The spot light does not affect objects outside this angle.
+ * The angle is given in radians. It is 2PI for point lights and
+ * undefined for directional lights. The outer angle must be
+ * greater than or equal to the inner angle.
+ * It is assumed that the application uses a smooth
+ * interpolation between the inner and the outer cone of the
+ * spot light.
+ *
+ * @return the outer angle
+ */
+ public float getAngleOuterCone() {
+ return m_outerCone;
+ }
+
+
+ /**
+ * Name.
+ */
+ private final String m_name;
+
+
+ /**
+ * Type.
+ */
+ private final AiLightType m_type;
+
+
+ /**
+ * Position.
+ */
+ private final Object m_position;
+
+
+ /**
+ * Direction.
+ */
+ private final Object m_direction;
+
+
+ /**
+ * Constant attenuation.
+ */
+ private final float m_attenuationConstant;
+
+
+ /**
+ * Linear attenuation.
+ */
+ private final float m_attenuationLinear;
+
+
+ /**
+ * Quadratic attenuation.
+ */
+ private final float m_attenuationQuadratic;
+
+
+ /**
+ * Diffuse color.
+ */
+ private final Object m_diffuse;
+
+
+ /**
+ * Specular color.
+ */
+ private final Object m_specular;
+
+
+ /**
+ * Ambient color.
+ */
+ private final Object m_ambient;
+
+
+ /**
+ * Inner cone of spotlight.
+ */
+ private final float m_innerCone;
+
+
+ /**
+ * Outer cone of spotlight.
+ */
+ private final float m_outerCone;
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiLightType.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiLightType.java
new file mode 100644
index 0000000..33fd722
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiLightType.java
@@ -0,0 +1,123 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, 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;
+
+
+/**
+ * List of light types supported by {@link AiLight}.
+ */
+public enum AiLightType {
+ /**
+ * A directional light source.<p>
+ *
+ * A directional light has a well-defined direction but is infinitely far
+ * away. That's quite a good approximation for sun light.
+ */
+ DIRECTIONAL(0x1),
+
+
+ /**
+ * A point light source.<p>
+ *
+ * A point light has a well-defined position in space but no direction -
+ * it emits light in all directions. A normal bulb is a point light.
+ */
+ POINT(0x2),
+
+
+ /**
+ * A spot light source.<p>
+ *
+ * A spot light emits light in a specific angle. It has a position and a
+ * direction it is pointing to. A good example for a spot light is a light
+ * spot in sport arenas.
+ */
+ SPOT(0x3),
+
+
+ /**
+ * The generic light level of the world, including the bounces of all other
+ * lightsources. <p>
+ *
+ * Typically, there's at most one ambient light in a scene.
+ * This light type doesn't have a valid position, direction, or
+ * other properties, just a color.
+ */
+ AMBIENT(0x4);
+
+
+ /**
+ * Utility method for converting from c/c++ based integer enums to java
+ * enums.<p>
+ *
+ * This method is intended to be used from JNI and my change based on
+ * implementation needs.
+ *
+ * @param rawValue an integer based enum value (as defined by assimp)
+ * @return the enum value corresponding to rawValue
+ */
+ static AiLightType fromRawValue(int rawValue) {
+ for (AiLightType type : AiLightType.values()) {
+ if (type.m_rawValue == rawValue) {
+ return type;
+ }
+ }
+
+ throw new IllegalArgumentException("unexptected raw value: " +
+ rawValue);
+ }
+
+
+ /**
+ * Constructor.
+ *
+ * @param rawValue maps java enum to c/c++ integer enum values
+ */
+ private AiLightType(int rawValue) {
+ m_rawValue = rawValue;
+ }
+
+
+ /**
+ * The mapped c/c++ integer enum value.
+ */
+ private final int m_rawValue;
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiMaterial.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiMaterial.java
new file mode 100644
index 0000000..b571f14
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiMaterial.java
@@ -0,0 +1,1199 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+
+/**
+ * Data structure for a material.<p>
+ *
+ * Depending on the imported scene and scene format, individual properties
+ * might be present or not. A list of all imported properties can be retrieved
+ * via {@link #getProperties()}.<p>
+ *
+ * This class offers <code>getXXX()</code> for all supported properties. These
+ * methods are fail-save, i.e., will return a default value when the
+ * corresponding property is not set. To change the built in default values,
+ * use the <code>setDefaultXXX()</code> methods.<p>
+ *
+ * If your application expects a certain set of properties to be available,
+ * the {@link #hasProperties(Set)} method can be used to check whether all
+ * these properties are actually set. If this check fails, you can still
+ * use this material via the <code>getXXX()</code> methods without special
+ * error handling code as the implementation guarantees to return default
+ * values for missing properties. This check will not work on texture related
+ * properties (i.e., properties starting with <code>TEX_</code>).
+ */
+public final class AiMaterial {
+ /**
+ * List of properties.
+ */
+ private final List<Property> m_properties = new ArrayList<Property>();
+
+ /**
+ * Number of textures for each type.
+ */
+ private final Map<AiTextureType, Integer> m_numTextures =
+ new EnumMap<AiTextureType, Integer>(AiTextureType.class);
+
+ /**
+ * Enumerates all supported material properties.
+ */
+ public static enum PropertyKey {
+ /**
+ * Name.
+ */
+ NAME("?mat.name", String.class),
+
+ /**
+ * Two-sided flag.
+ */
+ TWO_SIDED("$mat.twosided", Integer.class),
+
+ /**
+ * Shading mode.
+ */
+ SHADING_MODE("$mat.shadingm", AiShadingMode.class),
+
+ /**
+ * Wireframe flag.
+ */
+ WIREFRAME("$mat.wireframe", Integer.class),
+
+ /**
+ * Blend mode.
+ */
+ BLEND_MODE("$mat.blend", AiBlendMode.class),
+
+ /**
+ * Opacity.
+ */
+ OPACITY("$mat.opacity", Float.class),
+
+ /**
+ * Bump scaling.
+ */
+ BUMP_SCALING("$mat.bumpscaling", Float.class),
+
+
+ /**
+ * Shininess.
+ */
+ SHININESS("$mat.shininess", Float.class),
+
+
+ /**
+ * Reflectivity.
+ */
+ REFLECTIVITY("$mat.reflectivity", Float.class),
+
+
+ /**
+ * Shininess strength.
+ */
+ SHININESS_STRENGTH("$mat.shinpercent", Float.class),
+
+
+ /**
+ * Refract index.
+ */
+ REFRACTI("$mat.refracti", Float.class),
+
+
+ /**
+ * Diffuse color.
+ */
+ COLOR_DIFFUSE("$clr.diffuse", Object.class),
+
+
+ /**
+ * Ambient color.
+ */
+ COLOR_AMBIENT("$clr.ambient", Object.class),
+
+
+ /**
+ * Ambient color.
+ */
+ COLOR_SPECULAR("$clr.specular", Object.class),
+
+
+ /**
+ * Emissive color.
+ */
+ COLOR_EMISSIVE("$clr.emissive", Object.class),
+
+
+ /**
+ * Transparent color.
+ */
+ COLOR_TRANSPARENT("$clr.transparent", Object.class),
+
+
+ /**
+ * Reflective color.
+ */
+ COLOR_REFLECTIVE("$clr.reflective", Object.class),
+
+
+ /**
+ * Global background image.
+ */
+ GLOBAL_BACKGROUND_IMAGE("?bg.global", String.class),
+
+
+ /**
+ * Texture file path.
+ */
+ TEX_FILE("$tex.file", String.class),
+
+
+ /**
+ * Texture uv index.
+ */
+ TEX_UV_INDEX("$tex.uvwsrc", Integer.class),
+
+
+ /**
+ * Texture blend factor.
+ */
+ TEX_BLEND("$tex.blend", Float.class),
+
+
+ /**
+ * Texture operation.
+ */
+ TEX_OP("$tex.op", AiTextureOp.class),
+
+
+ /**
+ * Texture map mode for u axis.
+ */
+ TEX_MAP_MODE_U("$tex.mapmodeu", AiTextureMapMode.class),
+
+
+ /**
+ * Texture map mode for v axis.
+ */
+ TEX_MAP_MODE_V("$tex.mapmodev", AiTextureMapMode.class),
+
+
+ /**
+ * Texture map mode for w axis.
+ */
+ TEX_MAP_MODE_W("$tex.mapmodew", AiTextureMapMode.class);
+
+ /**
+ * Constructor.
+ *
+ * @param key key name as used by assimp
+ * @param type key type, used for casts and checks
+ */
+ private PropertyKey(String key, Class<?> type) {
+ m_key = key;
+ m_type = type;
+ }
+
+
+ /**
+ * Key.
+ */
+ private final String m_key;
+
+
+ /**
+ * Type.
+ */
+ private final Class<?> m_type;
+ }
+
+
+ /**
+ * A very primitive RTTI system for the contents of material properties.
+ */
+ public static enum PropertyType {
+ /**
+ * Array of single-precision (32 Bit) floats.
+ */
+ FLOAT(0x1),
+
+
+ /**
+ * The material property is a string.
+ */
+ STRING(0x3),
+
+
+ /**
+ * Array of (32 Bit) integers.
+ */
+ INTEGER(0x4),
+
+
+ /**
+ * Simple binary buffer, content undefined. Not convertible to anything.
+ */
+ BUFFER(0x5);
+
+
+ /**
+ * Utility method for converting from c/c++ based integer enums to java
+ * enums.<p>
+ *
+ * This method is intended to be used from JNI and my change based on
+ * implementation needs.
+ *
+ * @param rawValue an integer based enum value (as defined by assimp)
+ * @return the enum value corresponding to rawValue
+ */
+ static PropertyType fromRawValue(int rawValue) {
+ for (PropertyType type : PropertyType.values()) {
+ if (type.m_rawValue == rawValue) {
+ return type;
+ }
+ }
+
+ throw new IllegalArgumentException("unexptected raw value: " +
+ rawValue);
+ }
+
+
+ /**
+ * Constructor.
+ *
+ * @param rawValue maps java enum to c/c++ integer enum values
+ */
+ private PropertyType(int rawValue) {
+ m_rawValue = rawValue;
+ }
+
+
+ /**
+ * The mapped c/c++ integer enum value.
+ */
+ private final int m_rawValue;
+ }
+
+
+ /**
+ * Data structure for a single material property.<p>
+ *
+ * As an user, you'll probably never need to deal with this data structure.
+ * Just use the provided get() family of functions to query material
+ * 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
+ * @param semantic
+ * @param index
+ * @param type
+ * @param data
+ */
+ Property(String key, int semantic, int index, int type,
+ Object data) {
+
+ m_key = key;
+ m_semantic = semantic;
+ m_index = index;
+ m_type = PropertyType.fromRawValue(type);
+ m_data = data;
+ }
+
+
+ /**
+ * Constructor.
+ *
+ * @param key
+ * @param semantic
+ * @param index
+ * @param type
+ * @param dataLen
+ */
+ Property(String key, int semantic, int index, int type,
+ int dataLen) {
+
+ m_key = key;
+ m_semantic = semantic;
+ m_index = index;
+ m_type = PropertyType.fromRawValue(type);
+
+ ByteBuffer b = ByteBuffer.allocateDirect(dataLen);
+ b.order(ByteOrder.nativeOrder());
+
+ m_data = b;
+ }
+
+
+ /**
+ * Returns the key of the property.<p>
+ *
+ * Keys are generally case insensitive.
+ *
+ * @return the key
+ */
+ public String getKey() {
+ return m_key;
+ }
+
+
+ /**
+ * Textures: Specifies their exact usage semantic.
+ * For non-texture properties, this member is always 0
+ * (or, better-said, #aiTextureType_NONE).
+ *
+ * @return the semantic
+ */
+ public int getSemantic() {
+ return m_semantic;
+ }
+
+
+ /**
+ * Textures: Specifies the index of the texture.
+ * For non-texture properties, this member is always 0.
+ *
+ * @return the index
+ */
+ public int getIndex() {
+ return m_index;
+ }
+
+
+ /**
+ * Type information for the property.<p>
+ *
+ * Defines the data layout inside the data buffer. This is used
+ * by the library internally to perform debug checks and to
+ * utilize proper type conversions.
+ * (It's probably a hacky solution, but it works.)
+ *
+ * @return the type
+ */
+ public PropertyType getType() {
+ return m_type;
+ }
+
+
+ /**
+ * Binary buffer to hold the property's value.
+ * The size of the buffer is always mDataLength.
+ *
+ * @return the data
+ */
+ public Object getData() {
+ return m_data;
+ }
+ }
+
+
+ /**
+ * Constructor.
+ */
+ AiMaterial() {
+ /* nothing to do */
+ }
+
+
+ /**
+ * Checks whether the given set of properties is available.
+ *
+ * @param keys the keys to check
+ * @return true if all properties are available, false otherwise
+ */
+ public boolean hasProperties(Set<PropertyKey> keys) {
+ for (PropertyKey key : keys) {
+ if (null == getProperty(key.m_key)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Sets a default value.<p>
+ *
+ * The passed in Object must match the type of the key as returned by
+ * the corresponding <code>getXXX()</code> method.
+ *
+ * @param key the key
+ * @param defaultValue the new default, may not be null
+ * @throws IllegalArgumentException if defaultValue is null or has a wrong
+ * type
+ */
+ public void setDefault(PropertyKey key, Object defaultValue) {
+ if (null == defaultValue) {
+ throw new IllegalArgumentException("defaultValue may not be null");
+ }
+ if (key.m_type != defaultValue.getClass()) {
+ throw new IllegalArgumentException(
+ "defaultValue has wrong type, " +
+ "expected: " + key.m_type + ", found: " +
+ defaultValue.getClass());
+ }
+
+ m_defaults.put(key, defaultValue);
+ }
+
+
+ // {{ Fail-save Getters
+ /**
+ * Returns the name of the material.<p>
+ *
+ * If missing, defaults to empty string
+ *
+ * @return the name
+ */
+ public String getName() {
+ return getTyped(PropertyKey.NAME, String.class);
+ }
+
+
+ /**
+ * Returns the two-sided flag.<p>
+ *
+ * If missing, defaults to 0
+ *
+ * @return the two-sided flag
+ */
+ public int getTwoSided() {
+ return getTyped(PropertyKey.TWO_SIDED, Integer.class);
+ }
+
+
+ /**
+ * Returns the shading mode.<p>
+ *
+ * If missing, defaults to {@link AiShadingMode#FLAT}
+ *
+ * @return the shading mode
+ */
+ public AiShadingMode getShadingMode() {
+ Property p = getProperty(PropertyKey.SHADING_MODE.m_key);
+
+ if (null == p || null == p.getData()) {
+ return (AiShadingMode) m_defaults.get(PropertyKey.SHADING_MODE);
+ }
+
+ return AiShadingMode.fromRawValue((Integer) p.getData());
+ }
+
+
+ /**
+ * Returns the wireframe flag.<p>
+ *
+ * If missing, defaults to 0
+ *
+ * @return the wireframe flag
+ */
+ public int getWireframe() {
+ return getTyped(PropertyKey.WIREFRAME, Integer.class);
+ }
+
+
+ /**
+ * Returns the blend mode.<p>
+ *
+ * If missing, defaults to {@link AiBlendMode#DEFAULT}
+ *
+ * @return the blend mode
+ */
+ public AiBlendMode getBlendMode() {
+ Property p = getProperty(PropertyKey.BLEND_MODE.m_key);
+
+ if (null == p || null == p.getData()) {
+ return (AiBlendMode) m_defaults.get(PropertyKey.BLEND_MODE);
+ }
+
+ return AiBlendMode.fromRawValue((Integer) p.getData());
+ }
+
+
+ /**
+ * Returns the opacity.<p>
+ *
+ * If missing, defaults to 1.0
+ *
+ * @return the opacity
+ */
+ public float getOpacity() {
+ return getTyped(PropertyKey.OPACITY, Float.class);
+ }
+
+
+ /**
+ * Returns the bump scaling factor.<p>
+ *
+ * If missing, defaults to 1.0
+ *
+ * @return the bump scaling factor
+ */
+ public float getBumpScaling() {
+ return getTyped(PropertyKey.BUMP_SCALING, Float.class);
+ }
+
+
+ /**
+ * Returns the shininess.<p>
+ *
+ * If missing, defaults to 1.0
+ *
+ * @return the shininess
+ */
+ public float getShininess() {
+ return getTyped(PropertyKey.SHININESS, Float.class);
+ }
+
+
+ /**
+ * Returns the reflectivity.<p>
+ *
+ * If missing, defaults to 0.0
+ *
+ * @return the reflectivity
+ */
+ public float getReflectivity() {
+ return getTyped(PropertyKey.REFLECTIVITY, Float.class);
+ }
+
+
+ /**
+ * Returns the shininess strength.<p>
+ *
+ * If missing, defaults to 0.0
+ *
+ * @return the shininess strength
+ */
+ public float getShininessStrength() {
+ return getTyped(PropertyKey.SHININESS_STRENGTH, Float.class);
+ }
+
+
+ /**
+ * Returns the refract index.<p>
+ *
+ * If missing, defaults to 0.0
+ *
+ * @return the refract index
+ */
+ public float getRefractIndex() {
+ return getTyped(PropertyKey.REFRACTI, Float.class);
+ }
+
+
+ /**
+ * Returns the diffuse color.<p>
+ *
+ * If missing, defaults to opaque white (1.0, 1.0, 1.0, 1.0)<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).<p>
+ *
+ * The built-in behavior is to return a {@link AiVector}.
+ *
+ * @param wrapperProvider the wrapper provider (used for type inference)
+ * @return the diffuse color
+ */
+ @SuppressWarnings("unchecked")
+ public <V3, M4, C, N, Q> C getDiffuseColor(
+ AiWrapperProvider<V3, M4, C, N, Q> wrapperProvider) {
+
+ Property p = getProperty(PropertyKey.COLOR_DIFFUSE.m_key);
+
+ if (null == p || null == p.getData()) {
+ Object def = m_defaults.get(PropertyKey.COLOR_DIFFUSE);
+ if (def == null) {
+ return (C) Jassimp.wrapColor4(1.0f, 1.0f, 1.0f, 1.0f);
+ }
+
+ return (C) def;
+ }
+
+ return (C) p.getData();
+ }
+
+
+ /**
+ * Returns the ambient color.<p>
+ *
+ * If missing, defaults to opaque white (1.0, 1.0, 1.0, 1.0)<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).<p>
+ *
+ * The built-in behavior is to return a {@link AiVector}.
+ *
+ * @param wrapperProvider the wrapper provider (used for type inference)
+ * @return the ambient color
+ */
+ @SuppressWarnings("unchecked")
+ public <V3, M4, C, N, Q> C getAmbientColor(
+ AiWrapperProvider<V3, M4, C, N, Q> wrapperProvider) {
+
+ Property p = getProperty(PropertyKey.COLOR_AMBIENT.m_key);
+
+ if (null == p || null == p.getData()) {
+ Object def = m_defaults.get(PropertyKey.COLOR_AMBIENT);
+ if (def == null) {
+ return (C) Jassimp.wrapColor4(1.0f, 1.0f, 1.0f, 1.0f);
+ }
+
+ return (C) def;
+ }
+
+ return (C) p.getData();
+ }
+
+
+ /**
+ * Returns the specular color.<p>
+ *
+ * If missing, defaults to opaque white (1.0, 1.0, 1.0, 1.0)<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).<p>
+ *
+ * The built-in behavior is to return a {@link AiVector}.
+ *
+ * @param wrapperProvider the wrapper provider (used for type inference)
+ * @return the specular color
+ */
+ @SuppressWarnings("unchecked")
+ public <V3, M4, C, N, Q> C getSpecularColor(
+ AiWrapperProvider<V3, M4, C, N, Q> wrapperProvider) {
+
+ Property p = getProperty(PropertyKey.COLOR_SPECULAR.m_key);
+
+ if (null == p || null == p.getData()) {
+ Object def = m_defaults.get(PropertyKey.COLOR_SPECULAR);
+ if (def == null) {
+ return (C) Jassimp.wrapColor4(1.0f, 1.0f, 1.0f, 1.0f);
+ }
+
+ return (C) def;
+ }
+
+ return (C) p.getData();
+ }
+
+
+ /**
+ * Returns the emissive color.<p>
+ *
+ * If missing, defaults to opaque white (1.0, 1.0, 1.0, 1.0)<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).<p>
+ *
+ * The built-in behavior is to return a {@link AiVector}.
+ *
+ * @param wrapperProvider the wrapper provider (used for type inference)
+ * @return the emissive color
+ */
+ @SuppressWarnings("unchecked")
+ public <V3, M4, C, N, Q> C getEmissiveColor(
+ AiWrapperProvider<V3, M4, C, N, Q> wrapperProvider) {
+
+ Property p = getProperty(PropertyKey.COLOR_EMISSIVE.m_key);
+
+ if (null == p || null == p.getData()) {
+ Object def = m_defaults.get(PropertyKey.COLOR_EMISSIVE);
+ if (def == null) {
+ return (C) Jassimp.wrapColor4(1.0f, 1.0f, 1.0f, 1.0f);
+ }
+
+ return (C) def;
+ }
+
+ return (C) p.getData();
+ }
+
+
+ /**
+ * Returns the transparent color.<p>
+ *
+ * If missing, defaults to opaque white (1.0, 1.0, 1.0, 1.0)<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).<p>
+ *
+ * The built-in behavior is to return a {@link AiVector}.
+ *
+ * @param wrapperProvider the wrapper provider (used for type inference)
+ * @return the transparent color
+ */
+ @SuppressWarnings("unchecked")
+ public <V3, M4, C, N, Q> C getTransparentColor(
+ AiWrapperProvider<V3, M4, C, N, Q> wrapperProvider) {
+
+ Property p = getProperty(PropertyKey.COLOR_TRANSPARENT.m_key);
+
+ if (null == p || null == p.getData()) {
+ Object def = m_defaults.get(PropertyKey.COLOR_TRANSPARENT);
+ if (def == null) {
+ return (C) Jassimp.wrapColor4(1.0f, 1.0f, 1.0f, 1.0f);
+ }
+
+ return (C) def;
+ }
+
+ return (C) p.getData();
+ }
+
+
+ /**
+ * Returns the reflective color.<p>
+ *
+ * If missing, defaults to opaque white (1.0, 1.0, 1.0, 1.0)<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).<p>
+ *
+ * The built-in behavior is to return a {@link AiVector}.
+ *
+ * @param wrapperProvider the wrapper provider (used for type inference)
+ * @return the reflective color
+ */
+ @SuppressWarnings("unchecked")
+ public <V3, M4, C, N, Q> C getReflectiveColor(
+ AiWrapperProvider<V3, M4, C, N, Q> wrapperProvider) {
+
+ Property p = getProperty(PropertyKey.COLOR_REFLECTIVE.m_key);
+
+ if (null == p || null == p.getData()) {
+ Object def = m_defaults.get(PropertyKey.COLOR_REFLECTIVE);
+ if (def == null) {
+ return (C) Jassimp.wrapColor4(1.0f, 1.0f, 1.0f, 1.0f);
+ }
+
+ return (C) def;
+ }
+
+ return (C) p.getData();
+ }
+
+
+ /**
+ * Returns the global background image.<p>
+ *
+ * If missing, defaults to empty string
+ *
+ * @return the global background image
+ */
+ public String getGlobalBackgroundImage() {
+ return getTyped(PropertyKey.GLOBAL_BACKGROUND_IMAGE, String.class);
+ }
+
+
+ /**
+ * Returns the number of textures of the given type.
+ *
+ * @param type the type
+ * @return the number of textures
+ */
+ public int getNumTextures(AiTextureType type) {
+ return m_numTextures.get(type);
+ }
+
+
+ /**
+ * Returns the texture file.<p>
+ *
+ * If missing, defaults to empty string
+ *
+ * @param type the texture type
+ * @param index the index in the texture stack
+ * @return the file
+ * @throws IndexOutOfBoundsException if index is invalid
+ */
+ public String getTextureFile(AiTextureType type, int index) {
+ checkTexRange(type, index);
+
+ return getTyped(PropertyKey.TEX_FILE, type, index, String.class);
+ }
+
+
+ /**
+ * Returns the index of the UV coordinate set used by the texture.<p>
+ *
+ * If missing, defaults to 0
+ *
+ * @param type the texture type
+ * @param index the index in the texture stack
+ * @return the UV index
+ * @throws IndexOutOfBoundsException if index is invalid
+ */
+ public int getTextureUVIndex(AiTextureType type, int index) {
+ checkTexRange(type, index);
+
+ return getTyped(PropertyKey.TEX_UV_INDEX, type, index, Integer.class);
+ }
+
+
+ /**
+ * Returns the blend factor of the texture.<p>
+ *
+ * If missing, defaults to 1.0
+ *
+ * @param type the texture type
+ * @param index the index in the texture stack
+ * @return the blend factor
+ */
+ public float getBlendFactor(AiTextureType type, int index) {
+ checkTexRange(type, index);
+
+ return getTyped(PropertyKey.TEX_BLEND, type, index, Float.class);
+ }
+
+
+ /**
+ * Returns the texture operation.<p>
+ *
+ * If missing, defaults to {@link AiTextureOp#ADD}
+ *
+ * @param type the texture type
+ * @param index the index in the texture stack
+ * @return the texture operation
+ */
+ public AiTextureOp getTextureOp(AiTextureType type, int index) {
+ checkTexRange(type, index);
+
+ Property p = getProperty(PropertyKey.TEX_OP.m_key);
+
+ if (null == p || null == p.getData()) {
+ return (AiTextureOp) m_defaults.get(PropertyKey.TEX_OP);
+ }
+
+ return AiTextureOp.fromRawValue((Integer) p.getData());
+ }
+
+
+ /**
+ * Returns the texture mapping mode for the u axis.<p>
+ *
+ * If missing, defaults to {@link AiTextureMapMode#CLAMP}
+ *
+ * @param type the texture type
+ * @param index the index in the texture stack
+ * @return the texture mapping mode
+ */
+ public AiTextureMapMode getTextureMapModeU(AiTextureType type, int index) {
+ checkTexRange(type, index);
+
+ Property p = getProperty(PropertyKey.TEX_MAP_MODE_U.m_key);
+
+ if (null == p || null == p.getData()) {
+ return (AiTextureMapMode) m_defaults.get(
+ PropertyKey.TEX_MAP_MODE_U);
+ }
+
+ return AiTextureMapMode.fromRawValue((Integer) p.getData());
+ }
+
+
+ /**
+ * Returns the texture mapping mode for the v axis.<p>
+ *
+ * If missing, defaults to {@link AiTextureMapMode#CLAMP}
+ *
+ * @param type the texture type
+ * @param index the index in the texture stack
+ * @return the texture mapping mode
+ */
+ public AiTextureMapMode getTextureMapModeV(AiTextureType type, int index) {
+ checkTexRange(type, index);
+
+ Property p = getProperty(PropertyKey.TEX_MAP_MODE_V.m_key);
+
+ if (null == p || null == p.getData()) {
+ return (AiTextureMapMode) m_defaults.get(
+ PropertyKey.TEX_MAP_MODE_V);
+ }
+
+ return AiTextureMapMode.fromRawValue((Integer) p.getData());
+ }
+
+
+ /**
+ * Returns the texture mapping mode for the w axis.<p>
+ *
+ * If missing, defaults to {@link AiTextureMapMode#CLAMP}
+ *
+ * @param type the texture type
+ * @param index the index in the texture stack
+ * @return the texture mapping mode
+ */
+ public AiTextureMapMode getTextureMapModeW(AiTextureType type, int index) {
+ checkTexRange(type, index);
+
+ Property p = getProperty(PropertyKey.TEX_MAP_MODE_W.m_key);
+
+ if (null == p || null == p.getData()) {
+ return (AiTextureMapMode) m_defaults.get(
+ PropertyKey.TEX_MAP_MODE_W);
+ }
+
+ return AiTextureMapMode.fromRawValue((Integer) p.getData());
+ }
+
+
+ /**
+ * Returns all information related to a single texture.
+ *
+ * @param type the texture type
+ * @param index the index in the texture stack
+ * @return the texture information
+ */
+ public AiTextureInfo getTextureInfo(AiTextureType type, int index) {
+ return new AiTextureInfo(type, index, getTextureFile(type, index),
+ getTextureUVIndex(type, index), getBlendFactor(type, index),
+ getTextureOp(type, index), getTextureMapModeW(type, index),
+ getTextureMapModeW(type, index),
+ getTextureMapModeW(type, index));
+ }
+ // }}
+
+ // {{ Generic Getters
+ /**
+ * Returns a single property based on its key.
+ *
+ * @param key the key
+ * @return the property or null if the property is not set
+ */
+ public Property getProperty(String key) {
+ for (Property property : m_properties) {
+ if (property.getKey().equals(key)) {
+ return property;
+ }
+ }
+
+ return null;
+ }
+
+
+ /**
+ * Returns a single property based on its key.
+ *
+ * @param key the key
+ * @param semantic the semantic type (texture type)
+ * @param index the index
+ * @return the property or null if the property is not set
+ */
+ public Property getProperty(String key, int semantic, int index) {
+ for (Property property : m_properties) {
+ if (property.getKey().equals(key) &&
+ property.m_semantic == semantic &&
+ property.m_index == index) {
+
+ return property;
+ }
+ }
+
+ return null;
+ }
+
+
+ /**
+ * Returns all properties of the material.
+ *
+ * @return the list of properties
+ */
+ public List<Property> getProperties() {
+ return m_properties;
+ }
+ // }}
+
+
+ /**
+ * Helper method. Returns typed property data.
+ *
+ * @param <T> type
+ * @param key the key
+ * @param clazz type
+ * @return the data
+ */
+ private <T> T getTyped(PropertyKey key, Class<T> clazz) {
+ Property p = getProperty(key.m_key);
+
+ if (null == p || null == p.getData()) {
+ return clazz.cast(m_defaults.get(key));
+ }
+
+ return clazz.cast(p.getData());
+ }
+
+
+ /**
+ * Helper method. Returns typed property data.
+ *
+ * @param <T> type
+ * @param key the key
+ * @param type the texture type
+ * @param index the texture index
+ * @param clazz type
+ * @return the data
+ */
+ private <T> T getTyped(PropertyKey key, AiTextureType type, int index,
+ Class<T> clazz) {
+
+ Property p = getProperty(key.m_key, AiTextureType.toRawValue(type),
+ index);
+
+ if (null == p || null == p.getData()) {
+ return clazz.cast(m_defaults.get(key));
+ }
+
+ return clazz.cast(p.getData());
+ }
+
+
+ /**
+ * Checks that index is valid an throw an exception if not.
+ *
+ * @param type the type
+ * @param index the index to check
+ */
+ private void checkTexRange(AiTextureType type, int index) {
+ if (index < 0 || index > m_numTextures.get(type)) {
+ throw new IndexOutOfBoundsException("Index: " + index + ", Size: " +
+ m_numTextures.get(type));
+ }
+ }
+
+
+ /**
+ * Defaults for missing properties.
+ */
+ private Map<PropertyKey, Object> m_defaults =
+ new EnumMap<PropertyKey, Object>(PropertyKey.class);
+
+ {
+ setDefault(PropertyKey.NAME, "");
+ setDefault(PropertyKey.TWO_SIDED, 0);
+ setDefault(PropertyKey.SHADING_MODE, AiShadingMode.FLAT);
+ setDefault(PropertyKey.WIREFRAME, 0);
+ setDefault(PropertyKey.BLEND_MODE, AiBlendMode.DEFAULT);
+ setDefault(PropertyKey.OPACITY, 1.0f);
+ setDefault(PropertyKey.BUMP_SCALING, 1.0f);
+ setDefault(PropertyKey.SHININESS, 1.0f);
+ setDefault(PropertyKey.REFLECTIVITY, 0.0f);
+ setDefault(PropertyKey.SHININESS_STRENGTH, 0.0f);
+ setDefault(PropertyKey.REFRACTI, 0.0f);
+
+ /* bypass null checks for colors */
+ m_defaults.put(PropertyKey.COLOR_DIFFUSE, null);
+ m_defaults.put(PropertyKey.COLOR_AMBIENT, null);
+ m_defaults.put(PropertyKey.COLOR_SPECULAR, null);
+ m_defaults.put(PropertyKey.COLOR_EMISSIVE, null);
+ m_defaults.put(PropertyKey.COLOR_TRANSPARENT, null);
+ m_defaults.put(PropertyKey.COLOR_REFLECTIVE, null);
+
+ setDefault(PropertyKey.GLOBAL_BACKGROUND_IMAGE, "");
+
+ /* texture related values */
+ setDefault(PropertyKey.TEX_FILE, "");
+ setDefault(PropertyKey.TEX_UV_INDEX, 0);
+ setDefault(PropertyKey.TEX_BLEND, 1.0f);
+ setDefault(PropertyKey.TEX_OP, AiTextureOp.ADD);
+ setDefault(PropertyKey.TEX_MAP_MODE_U, AiTextureMapMode.CLAMP);
+ setDefault(PropertyKey.TEX_MAP_MODE_V, AiTextureMapMode.CLAMP);
+ setDefault(PropertyKey.TEX_MAP_MODE_W, AiTextureMapMode.CLAMP);
+
+ /* ensure we have defaults for everything */
+ for (PropertyKey key : PropertyKey.values()) {
+ if (!m_defaults.containsKey(key)) {
+ throw new IllegalStateException("missing default for: " + key);
+ }
+ }
+ }
+
+
+ /**
+ * This method is used by JNI, do not call or modify.
+ *
+ * @param type the type
+ * @param number the number
+ */
+ @SuppressWarnings("unused")
+ private void setTextureNumber(int type, int number) {
+ m_numTextures.put(AiTextureType.fromRawValue(type), number);
+ }
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiMatrix4f.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiMatrix4f.java
new file mode 100644
index 0000000..f78c951
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiMatrix4f.java
@@ -0,0 +1,133 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+/**
+ * Simple 4x4 matrix of floats.
+ */
+public final class AiMatrix4f {
+ /**
+ * Wraps the given array of floats as matrix.
+ * <p>
+ *
+ * The array must have exactly 16 entries. The data in the array must be in
+ * row-major order.
+ *
+ * @param data
+ * the array to wrap, may not be null
+ */
+ public AiMatrix4f(float[] data) {
+ if (data == null) {
+ throw new IllegalArgumentException("data may not be null");
+ }
+ if (data.length != 16) {
+ throw new IllegalArgumentException("array length is not 16");
+ }
+
+ m_data = data;
+ }
+
+ /**
+ * Gets an element of the matrix.
+ *
+ * @param row
+ * the row
+ * @param col
+ * the column
+ * @return the element at the given position
+ */
+ public float get(int row, int col) {
+ if (row < 0 || row > 3) {
+ throw new IndexOutOfBoundsException("Index: " + row + ", Size: 4");
+ }
+ if (col < 0 || col > 3) {
+ throw new IndexOutOfBoundsException("Index: " + col + ", Size: 4");
+ }
+
+ return m_data[row * 4 + col];
+ }
+
+ /**
+ * Stores the matrix in a new direct ByteBuffer with native byte order.
+ * <p>
+ *
+ * The returned buffer can be passed to rendering APIs such as LWJGL, e.g.,
+ * as parameter for <code>GL20.glUniformMatrix4()</code>. Be sure to set
+ * <code>transpose</code> to <code>true</code> in this case, as OpenGL
+ * expects the matrix in column order.
+ *
+ * @return a new native order, direct ByteBuffer
+ */
+ public FloatBuffer toByteBuffer() {
+ ByteBuffer bbuf = ByteBuffer.allocateDirect(16 * 4);
+ bbuf.order(ByteOrder.nativeOrder());
+ FloatBuffer fbuf = bbuf.asFloatBuffer();
+ fbuf.put(m_data);
+ fbuf.flip();
+
+ return fbuf;
+ }
+
+
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder();
+
+ for (int row = 0; row < 4; row++) {
+ for (int col = 0; col < 4; col++) {
+ buf.append(m_data[row * 4 + col]).append(" ");
+ }
+ buf.append("\n");
+ }
+
+ return buf.toString();
+ }
+
+
+ /**
+ * Data buffer.
+ */
+ private final float[] m_data;
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiMesh.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiMesh.java
new file mode 100644
index 0000000..eb2ff3c
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiMesh.java
@@ -0,0 +1,1421 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Set;
+
+
+/**
+ * A mesh represents a geometry or model with a single material.
+ * <p>
+ *
+ * <h3>Data</h3>
+ * Meshes usually consist of a number of vertices and a series of faces
+ * referencing the vertices. In addition there might be a series of bones, each
+ * of them addressing a number of vertices with a certain weight. Vertex data is
+ * presented in channels with each channel containing a single per-vertex
+ * information such as a set of texture coordinates or a normal vector.<p>
+ *
+ * Faces consist of one or more references to vertices, called vertex indices.
+ * The {@link #getPrimitiveTypes()} method can be used to check what
+ * face types are present in the mesh. Note that a single mesh can possess
+ * faces of different types. The number of indices used by a specific face can
+ * be retrieved with the {@link #getFaceNumIndices(int)} method.
+ *
+ *
+ * <h3>API for vertex and face data</h3>
+ * The jassimp interface for accessing vertex and face data is not a one-to-one
+ * mapping of the c/c++ interface. The c/c++ interface uses an object-oriented
+ * approach to represent data, which provides a considerable
+ * overhead using a naive java based realization (cache locality would be
+ * unpredictable and most likely bad, bulk data transfer would be impossible).
+ * <p>
+ *
+ * The jassimp interface uses flat byte buffers to store vertex and face data.
+ * This data can be accessed through three APIs:
+ * <ul>
+ * <li><b>Buffer API:</b> the <code>getXXXBuffer()</code> methods return
+ * raw data buffers.
+ * <li><b>Direct API:</b> the <code>getXXX()</code> methods allow reading
+ * and writing of individual data values.
+ * <li><b>Wrapped API:</b> the <code>getWrappedXXX()</code> methods provide
+ * an object oriented view on the data.
+ * </ul>
+ *
+ * The Buffer API is optimized for use in conjunction with rendering APIs
+ * such as LWJGL. The returned buffers are guaranteed to have native byte order
+ * and to be direct byte buffers. They can be passed directly to LWJGL
+ * methods, e.g., to fill VBOs with data. Each invocation of a
+ * <code>getXXXBuffer()</code> method will return a new view of the internal
+ * buffer, i.e., if is safe to use the relative byte buffer operations.
+ * The Buffer API provides the best performance of all three APIs, especially
+ * if large data volumes have to be processed.<p>
+ *
+ * The Direct API provides an easy to use interface for reading and writing
+ * individual data values. Its performance is comparable to the Buffer API's
+ * performance for these operations. The main difference to the Buffer API is
+ * the missing support for bulk operations. If you intend to retrieve or modify
+ * large subsets of the raw data consider using the Buffer API, especially
+ * if the subsets are contiguous.
+ * <p>
+ *
+ * The Wrapped API offers an object oriented interface for accessing
+ * and modifying mesh data. As the name implies, this interface is realized
+ * through wrapper objects that provide a view on the raw data. For each
+ * invocation of a <code>getWrappedXXX()</code> method, a new wrapper object
+ * is created. Iterating over mesh data via this interface will create many
+ * short-lived wrapper objects which -depending on usage and virtual machine-
+ * may cause considerable garbage collection overhead. The Wrapped API provides
+ * the worst performance of all three APIs, which may nevertheless still be
+ * good enough to warrant its usage. See {@link AiWrapperProvider} for more
+ * details on wrappers.
+ *
+ *
+ * <h3>API for bones</h3>
+ * As there is no standardized way for doing skinning in different graphics
+ * engines, bones are not represented as flat buffers but as object structure.
+ * Users of this library should convert this structure to the format required
+ * by the specific graphics engine.
+ *
+ *
+ * <h3>Changing Data</h3>
+ * This class is designed to be mutable, i.e., the returned objects and buffers
+ * may be modified. It is not possible to add/remove vertices as this would
+ * require reallocation of the data buffers. Wrapped objects may or may not
+ * propagate changes to the underlying data buffers. Consult the documentation
+ * of your wrapper provider for details. The built in wrappers will propagate
+ * changes.
+ * <p>
+ * Modification of face data is theoretically possible by modifying the face
+ * buffer and the faceOffset buffer however it is strongly disadvised to do so
+ * because it might break all algorithms that depend on the internal consistency
+ * of these two data structures.
+ */
+public final class AiMesh {
+ /**
+ * Number of bytes per float value.
+ */
+ private final int SIZEOF_FLOAT = Jassimp.NATIVE_FLOAT_SIZE;
+
+ /**
+ * Number of bytes per int value.
+ */
+ private final int SIZEOF_INT = Jassimp.NATIVE_INT_SIZE;
+
+ /**
+ * Size of an AiVector3D in the native world.
+ */
+ private final int SIZEOF_V3D = Jassimp.NATIVE_AIVEKTOR3D_SIZE;
+
+
+ /**
+ * The primitive types used by this mesh.
+ */
+ private final Set<AiPrimitiveType> 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.<p>
+ *
+ * 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<AiBone> m_bones = new ArrayList<AiBone>();
+
+ /**
+ * This class is instantiated via JNI, no accessible constructor.
+ */
+ private AiMesh() {
+ /* nothing to do */
+ }
+
+
+ /**
+ * Returns the primitive types used by this mesh.
+ *
+ * @return a set of primitive types used by this mesh
+ */
+ public Set<AiPrimitiveType> getPrimitiveTypes() {
+ return m_primitiveTypes;
+ }
+
+
+ /**
+ * Tells whether the mesh is a pure triangle mesh, i.e., contains only
+ * triangular faces.<p>
+ *
+ * To automatically triangulate meshes the
+ * {@link AiPostProcessSteps#TRIANGULATE} post processing option can be
+ * used when loading the scene
+ *
+ * @return true if the mesh is a pure triangle mesh, false otherwise
+ */
+ public boolean isPureTriangle() {
+ return m_primitiveTypes.contains(AiPrimitiveType.TRIANGLE) &&
+ m_primitiveTypes.size() == 1;
+ }
+
+
+ /**
+ * Tells whether the mesh has vertex positions.<p>
+ *
+ * Meshes almost always contain position data
+ *
+ * @return true if positions are available
+ */
+ public boolean hasPositions() {
+ return m_vertices != null;
+ }
+
+
+ /**
+ * Tells whether the mesh has faces.<p>
+ *
+ * Meshes almost always contain faces
+ *
+ * @return true if faces are available
+ */
+ public boolean hasFaces() {
+ return m_faces != null;
+ }
+
+
+ /**
+ * Tells whether the mesh has normals.
+ *
+ * @return true if normals are available
+ */
+ public boolean hasNormals() {
+ return m_normals != null;
+ }
+
+
+ /**
+ * Tells whether the mesh has tangents and bitangents.<p>
+ *
+ * It is not possible that it contains tangents and no bitangents (or the
+ * other way round). The existence of one of them implies that the second
+ * is there, too.
+ *
+ * @return true if tangents and bitangents are available
+ */
+ public boolean hasTangentsAndBitangents() {
+ return m_tangents != null && m_tangents != null;
+ }
+
+
+ /**
+ * Tells whether the mesh has a vertex color set.
+ *
+ * @param colorset index of the color set
+ * @return true if colors are available
+ */
+ public boolean hasColors(int colorset) {
+ return m_colorsets[colorset] != null;
+ }
+
+
+ /**
+ * Tells whether the mesh has any vertex colors.<p>
+ *
+ * Use {@link #hasColors(int)} to check which color sets are
+ * available.
+ *
+ * @return true if any colors are available
+ */
+ public boolean hasVertexColors() {
+ for (ByteBuffer buf : m_colorsets) {
+ if (buf != null) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Tells whether the mesh has a texture coordinate set.
+ *
+ * @param coords index of the texture coordinate set
+ * @return true if texture coordinates are available
+ */
+ public boolean hasTexCoords(int coords) {
+ return m_texcoords[coords] != null;
+ }
+
+
+ /**
+ * Tells whether the mesh has any texture coordinate sets.<p>
+ *
+ * Use {@link #hasTexCoords(int)} to check which texture coordinate
+ * sets are available
+ *
+ * @return true if any texture coordinates are available
+ */
+ public boolean hasTexCoords() {
+ for (ByteBuffer buf : m_texcoords) {
+ if (buf != null) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Tells whether the mesh has bones.
+ *
+ * @return true if bones are available
+ */
+ public boolean hasBones() {
+ return !m_bones.isEmpty();
+ }
+
+
+ /**
+ * Returns the bones of this mesh.
+ *
+ * @return a list of bones
+ */
+ public List<AiBone> getBones() {
+ return m_bones;
+ }
+
+
+ /**
+ * Returns the number of vertices in this mesh.
+ *
+ * @return the number of vertices.
+ */
+ public int getNumVertices() {
+ return m_numVertices;
+ }
+
+
+ /**
+ * Returns the number of faces in the mesh.
+ *
+ * @return the number of faces
+ */
+ public int getNumFaces() {
+ return m_numFaces;
+ }
+
+
+ /**
+ * Returns the number of vertex indices for a single face.
+ *
+ * @param face the face
+ * @return the number of indices
+ */
+ public int getFaceNumIndices(int face) {
+ if (null == m_faceOffsets) {
+ if (face >= m_numFaces || face < 0) {
+ throw new IndexOutOfBoundsException("Index: " + face +
+ ", Size: " + m_numFaces);
+ }
+ return 3;
+ }
+ else {
+ /*
+ * no need to perform bound checks here as the array access will
+ * throw IndexOutOfBoundsExceptions if the index is invalid
+ */
+
+ if (face == m_numFaces - 1) {
+ return m_faces.capacity() / 4 - m_faceOffsets.getInt(face * 4);
+ }
+
+ return m_faceOffsets.getInt((face + 1) * 4) -
+ m_faceOffsets.getInt(face * 4);
+ }
+ }
+
+
+ /**
+ * Returns the number of UV components for a texture coordinate set.<p>
+ *
+ * Possible values range from 1 to 3 (1D to 3D texture coordinates)
+ *
+ * @param coords the coordinate set
+ * @return the number of components
+ */
+ public int getNumUVComponents(int coords) {
+ return m_numUVComponents[coords];
+ }
+
+
+ /**
+ * Returns the material used by this mesh.<p>
+ *
+ * A mesh does use only a single material. If an imported model uses
+ * multiple materials, the import splits up the mesh. Use this value
+ * as index into the scene's material list.
+ *
+ * @return the material index
+ */
+ public int getMaterialIndex() {
+ return m_materialIndex;
+ }
+
+
+ /**
+ * Returns the name of the mesh.<p>
+ *
+ * Not all meshes have a name, if no name is set an empty string is
+ * returned.
+ *
+ * @return the name or an empty string if no name is set
+ */
+ public String getName() {
+ return m_name;
+ }
+
+
+ // CHECKSTYLE:OFF
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder();
+ buf.append("Mesh(").append(m_numVertices).append(" vertices, ").
+ append(m_numFaces).append(" faces");
+
+ if (hasNormals()) {
+ buf.append(", normals");
+ }
+ if (hasTangentsAndBitangents()) {
+ buf.append(", (bi-)tangents");
+ }
+ if (hasVertexColors()) {
+ buf.append(", colors");
+ }
+ if (hasTexCoords()) {
+ buf.append(", texCoords");
+ }
+
+ buf.append(")");
+ return buf.toString();
+ }
+ // CHECKSTYLE:ON
+
+
+ // {{ Buffer API
+ /**
+ * Returns a buffer containing vertex positions.<p>
+ *
+ * A vertex position consists of a triple of floats, the buffer will
+ * therefore contain <code>3 * getNumVertices()</code> floats
+ *
+ * @return a native-order direct buffer, or null if no data is available
+ */
+ public FloatBuffer getPositionBuffer() {
+ if (m_vertices == null) {
+ return null;
+ }
+
+ return m_vertices.asFloatBuffer();
+ }
+
+
+ /**
+ * Returns a buffer containing face data.<p>
+ *
+ * You should use the {@link #getIndexBuffer()} method if you are
+ * interested in getting an index buffer used by graphics APIs such as
+ * LWJGL.<p>
+ *
+ * The buffer contains all vertex indices from all faces as a flat list. If
+ * the mesh is a pure triangle mesh, the buffer returned by this method is
+ * identical to the buffer returned by {@link #getIndexBuffer()}. For other
+ * meshes, the {@link #getFaceOffsets()} method can be used to retrieve
+ * an index structure that allows addressing individual faces in the list.
+ *
+ * @return a native-order direct buffer, or null if no data is available
+ */
+ public IntBuffer getFaceBuffer() {
+ if (m_faces == null) {
+ return null;
+ }
+
+ return m_faces.asIntBuffer();
+ }
+
+
+ /**
+ * Returns an index structure for the buffer returned by
+ * {@link #getFaceBuffer()}.<p>
+ *
+ * You should use the {@link #getIndexBuffer()} method if you are
+ * interested in getting an index buffer used by graphics APIs such as
+ * LWJGL.<p>
+ *
+ * The returned buffer contains one integer entry for each face. This entry
+ * specifies the offset at which the face's data is located inside the
+ * face buffer. The difference between two subsequent entries can be used
+ * to determine how many vertices belong to a given face (the last face
+ * contains all entries between the offset and the end of the face buffer).
+ *
+ * @return a native-order direct buffer, or null if no data is available
+ */
+ public IntBuffer getFaceOffsets() {
+ if (m_faceOffsets == null) {
+ return null;
+ }
+
+ return m_faceOffsets.asIntBuffer();
+ }
+
+
+
+ /**
+ * Returns a buffer containing vertex indices for the mesh's faces.<p>
+ *
+ * This method may only be called on pure triangle meshes, i.e., meshes
+ * containing only triangles. The {@link #isPureTriangle()} method can be
+ * used to check whether this is the case.<p>
+ *
+ * Indices are stored as integers, the buffer will therefore contain
+ * <code>3 * getNumVertices()</code> integers (3 indices per triangle)
+ *
+ * @return a native-order direct buffer
+ * @throws UnsupportedOperationException
+ * if the mesh is not a pure triangle mesh
+ */
+ public IntBuffer getIndexBuffer() {
+ if (!isPureTriangle()) {
+ throw new UnsupportedOperationException(
+ "mesh is not a pure triangle mesh");
+ }
+
+ return getFaceBuffer();
+ }
+
+
+ /**
+ * Returns a buffer containing normals.<p>
+ *
+ * A normal consists of a triple of floats, the buffer will
+ * therefore contain <code>3 * getNumVertices()</code> floats
+ *
+ * @return a native-order direct buffer
+ */
+ public FloatBuffer getNormalBuffer() {
+ if (m_normals == null) {
+ return null;
+ }
+
+ return m_normals.asFloatBuffer();
+ }
+
+
+ /**
+ * Returns a buffer containing tangents.<p>
+ *
+ * A tangent consists of a triple of floats, the buffer will
+ * therefore contain <code>3 * getNumVertices()</code> floats
+ *
+ * @return a native-order direct buffer
+ */
+ public FloatBuffer getTangentBuffer() {
+ if (m_tangents == null) {
+ return null;
+ }
+
+ return m_tangents.asFloatBuffer();
+ }
+
+
+ /**
+ * Returns a buffer containing bitangents.<p>
+ *
+ * A bitangent consists of a triple of floats, the buffer will
+ * therefore contain <code>3 * getNumVertices()</code> floats
+ *
+ * @return a native-order direct buffer
+ */
+ public FloatBuffer getBitangentBuffer() {
+ if (m_bitangents == null) {
+ return null;
+ }
+
+ return m_bitangents.asFloatBuffer();
+ }
+
+
+ /**
+ * Returns a buffer containing vertex colors for a color set.<p>
+ *
+ * A vertex color consists of 4 floats (red, green, blue and alpha), the
+ * buffer will therefore contain <code>4 * getNumVertices()</code> floats
+ *
+ * @param colorset the color set
+ *
+ * @return a native-order direct buffer, or null if no data is available
+ */
+ public FloatBuffer getColorBuffer(int colorset) {
+ if (m_colorsets[colorset] == null) {
+ return null;
+ }
+
+ return m_colorsets[colorset].asFloatBuffer();
+ }
+
+
+ /**
+ * Returns a buffer containing coordinates for a texture coordinate set.<p>
+ *
+ * A texture coordinate consists of up to 3 floats (u, v, w). The actual
+ * number can be queried via {@link #getNumUVComponents(int)}. The
+ * buffer will contain
+ * <code>getNumUVComponents(coords) * getNumVertices()</code> floats
+ *
+ * @param coords the texture coordinate set
+ *
+ * @return a native-order direct buffer, or null if no data is available
+ */
+ public FloatBuffer getTexCoordBuffer(int coords) {
+ if (m_texcoords[coords] == null) {
+ return null;
+ }
+
+ return m_texcoords[coords].asFloatBuffer();
+ }
+ // }}
+
+
+ // {{ Direct API
+ /**
+ * Returns the x-coordinate of a vertex position.
+ *
+ * @param vertex the vertex index
+ * @return the x coordinate
+ */
+ public float getPositionX(int vertex) {
+ if (!hasPositions()) {
+ throw new IllegalStateException("mesh has no positions");
+ }
+
+ checkVertexIndexBounds(vertex);
+
+ return m_vertices.getFloat(vertex * 3 * SIZEOF_FLOAT);
+ }
+
+
+ /**
+ * Returns the y-coordinate of a vertex position.
+ *
+ * @param vertex the vertex index
+ * @return the y coordinate
+ */
+ public float getPositionY(int vertex) {
+ if (!hasPositions()) {
+ throw new IllegalStateException("mesh has no positions");
+ }
+
+ checkVertexIndexBounds(vertex);
+
+ return m_vertices.getFloat((vertex * 3 + 1) * SIZEOF_FLOAT);
+ }
+
+ /**
+ * Returns the z-coordinate of a vertex position.
+ *
+ * @param vertex the vertex index
+ * @return the z coordinate
+ */
+ public float getPositionZ(int vertex) {
+ if (!hasPositions()) {
+ throw new IllegalStateException("mesh has no positions");
+ }
+
+ checkVertexIndexBounds(vertex);
+
+ return m_vertices.getFloat((vertex * 3 + 2) * SIZEOF_FLOAT);
+ }
+
+
+ /**
+ * Returns a vertex reference from a face.<p>
+ *
+ * A face contains <code>getFaceNumIndices(face)</code> vertex references.
+ * This method returns the n'th of these. The returned index can be passed
+ * directly to the vertex oriented methods, such as
+ * <code>getPosition()</code> etc.
+ *
+ * @param face the face
+ * @param n the reference
+ * @return a vertex index
+ */
+ public int getFaceVertex(int face, int n) {
+ if (!hasFaces()) {
+ throw new IllegalStateException("mesh has no faces");
+ }
+
+ if (face >= m_numFaces || face < 0) {
+ throw new IndexOutOfBoundsException("Index: " + face + ", Size: " +
+ m_numFaces);
+ }
+ if (n >= getFaceNumIndices(face) || n < 0) {
+ throw new IndexOutOfBoundsException("Index: " + n + ", Size: " +
+ getFaceNumIndices(face));
+ }
+
+ int faceOffset = 0;
+ if (m_faceOffsets == null) {
+ faceOffset = 3 * face * SIZEOF_INT;
+ }
+ else {
+ faceOffset = m_faceOffsets.getInt(face * SIZEOF_INT) * SIZEOF_INT;
+ }
+
+ return m_faces.getInt(faceOffset + n * SIZEOF_INT);
+ }
+
+
+ /**
+ * Returns the x-coordinate of a vertex normal.
+ *
+ * @param vertex the vertex index
+ * @return the x coordinate
+ */
+ public float getNormalX(int vertex) {
+ if (!hasNormals()) {
+ throw new IllegalStateException("mesh has no normals");
+ }
+
+ checkVertexIndexBounds(vertex);
+
+ return m_normals.getFloat(vertex * 3 * SIZEOF_FLOAT);
+ }
+
+
+ /**
+ * Returns the y-coordinate of a vertex normal.
+ *
+ * @param vertex the vertex index
+ * @return the y coordinate
+ */
+ public float getNormalY(int vertex) {
+ if (!hasNormals()) {
+ throw new IllegalStateException("mesh has no normals");
+ }
+
+ checkVertexIndexBounds(vertex);
+
+ return m_normals.getFloat((vertex * 3 + 1) * SIZEOF_FLOAT);
+ }
+
+
+ /**
+ * Returns the z-coordinate of a vertex normal.
+ *
+ * @param vertex the vertex index
+ * @return the z coordinate
+ */
+ public float getNormalZ(int vertex) {
+ if (!hasNormals()) {
+ throw new IllegalStateException("mesh has no normals");
+ }
+
+ checkVertexIndexBounds(vertex);
+
+ return m_normals.getFloat((vertex * 3 + 2) * SIZEOF_FLOAT);
+ }
+
+
+ /**
+ * Returns the x-coordinate of a vertex tangent.
+ *
+ * @param vertex the vertex index
+ * @return the x coordinate
+ */
+ public float getTangentX(int vertex) {
+ if (!hasTangentsAndBitangents()) {
+ throw new IllegalStateException("mesh has no tangents");
+ }
+
+ checkVertexIndexBounds(vertex);
+
+ return m_tangents.getFloat(vertex * 3 * SIZEOF_FLOAT);
+ }
+
+
+ /**
+ * Returns the y-coordinate of a vertex bitangent.
+ *
+ * @param vertex the vertex index
+ * @return the y coordinate
+ */
+ public float getTangentY(int vertex) {
+ if (!hasTangentsAndBitangents()) {
+ throw new IllegalStateException("mesh has no bitangents");
+ }
+
+ checkVertexIndexBounds(vertex);
+
+ return m_tangents.getFloat((vertex * 3 + 1) * SIZEOF_FLOAT);
+ }
+
+
+ /**
+ * Returns the z-coordinate of a vertex tangent.
+ *
+ * @param vertex the vertex index
+ * @return the z coordinate
+ */
+ public float getTangentZ(int vertex) {
+ if (!hasTangentsAndBitangents()) {
+ throw new IllegalStateException("mesh has no tangents");
+ }
+
+ checkVertexIndexBounds(vertex);
+
+ return m_tangents.getFloat((vertex * 3 + 2) * SIZEOF_FLOAT);
+ }
+
+
+ /**
+ * Returns the x-coordinate of a vertex tangent.
+ *
+ * @param vertex the vertex index
+ * @return the x coordinate
+ */
+ public float getBitangentX(int vertex) {
+ if (!hasTangentsAndBitangents()) {
+ throw new IllegalStateException("mesh has no bitangents");
+ }
+
+ checkVertexIndexBounds(vertex);
+
+ return m_bitangents.getFloat(vertex * 3 * SIZEOF_FLOAT);
+ }
+
+
+ /**
+ * Returns the y-coordinate of a vertex tangent.
+ *
+ * @param vertex the vertex index
+ * @return the y coordinate
+ */
+ public float getBitangentY(int vertex) {
+ if (!hasTangentsAndBitangents()) {
+ throw new IllegalStateException("mesh has no bitangents");
+ }
+
+ checkVertexIndexBounds(vertex);
+
+ return m_bitangents.getFloat((vertex * 3 + 1) * SIZEOF_FLOAT);
+ }
+
+
+ /**
+ * Returns the z-coordinate of a vertex tangent.
+ *
+ * @param vertex the vertex index
+ * @return the z coordinate
+ */
+ public float getBitangentZ(int vertex) {
+ if (!hasTangentsAndBitangents()) {
+ throw new IllegalStateException("mesh has no bitangents");
+ }
+
+ checkVertexIndexBounds(vertex);
+
+ return m_bitangents.getFloat((vertex * 3 + 2) * SIZEOF_FLOAT);
+ }
+
+
+ /**
+ * Returns the red color component of a color from a vertex color set.
+ *
+ * @param vertex the vertex index
+ * @param colorset the color set
+ * @return the red color component
+ */
+ public float getColorR(int vertex, int colorset) {
+ if (!hasColors(colorset)) {
+ throw new IllegalStateException("mesh has no colorset " + colorset);
+ }
+
+ checkVertexIndexBounds(vertex);
+ /* bound checks for colorset are done by java for us */
+
+ return m_colorsets[colorset].getFloat(vertex * 4 * SIZEOF_FLOAT);
+ }
+
+
+ /**
+ * Returns the green color component of a color from a vertex color set.
+ *
+ * @param vertex the vertex index
+ * @param colorset the color set
+ * @return the green color component
+ */
+ public float getColorG(int vertex, int colorset) {
+ if (!hasColors(colorset)) {
+ throw new IllegalStateException("mesh has no colorset " + colorset);
+ }
+
+ checkVertexIndexBounds(vertex);
+ /* bound checks for colorset are done by java for us */
+
+ return m_colorsets[colorset].getFloat((vertex * 4 + 1) * SIZEOF_FLOAT);
+ }
+
+
+ /**
+ * Returns the blue color component of a color from a vertex color set.
+ *
+ * @param vertex the vertex index
+ * @param colorset the color set
+ * @return the blue color component
+ */
+ public float getColorB(int vertex, int colorset) {
+ if (!hasColors(colorset)) {
+ throw new IllegalStateException("mesh has no colorset " + colorset);
+ }
+
+ checkVertexIndexBounds(vertex);
+ /* bound checks for colorset are done by java for us */
+
+ return m_colorsets[colorset].getFloat((vertex * 4 + 2) * SIZEOF_FLOAT);
+ }
+
+
+ /**
+ * Returns the alpha color component of a color from a vertex color set.
+ *
+ * @param vertex the vertex index
+ * @param colorset the color set
+ * @return the alpha color component
+ */
+ public float getColorA(int vertex, int colorset) {
+ if (!hasColors(colorset)) {
+ throw new IllegalStateException("mesh has no colorset " + colorset);
+ }
+
+ checkVertexIndexBounds(vertex);
+ /* bound checks for colorset are done by java for us */
+
+ return m_colorsets[colorset].getFloat((vertex * 4 + 3) * SIZEOF_FLOAT);
+ }
+
+
+ /**
+ * Returns the u component of a coordinate from a texture coordinate set.
+ *
+ * @param vertex the vertex index
+ * @param coords the texture coordinate set
+ * @return the u component
+ */
+ public float getTexCoordU(int vertex, int coords) {
+ if (!hasTexCoords(coords)) {
+ throw new IllegalStateException(
+ "mesh has no texture coordinate set " + coords);
+ }
+
+ checkVertexIndexBounds(vertex);
+ /* bound checks for coords are done by java for us */
+
+ return m_texcoords[coords].getFloat(
+ vertex * m_numUVComponents[coords] * SIZEOF_FLOAT);
+ }
+
+
+ /**
+ * Returns the v component of a coordinate from a texture coordinate set.<p>
+ *
+ * This method may only be called on 2- or 3-dimensional coordinate sets.
+ * Call <code>getNumUVComponents(coords)</code> to determine how may
+ * coordinate components are available.
+ *
+ * @param vertex the vertex index
+ * @param coords the texture coordinate set
+ * @return the v component
+ */
+ public float getTexCoordV(int vertex, int coords) {
+ if (!hasTexCoords(coords)) {
+ throw new IllegalStateException(
+ "mesh has no texture coordinate set " + coords);
+ }
+
+ checkVertexIndexBounds(vertex);
+
+ /* bound checks for coords are done by java for us */
+
+ if (getNumUVComponents(coords) < 2) {
+ throw new IllegalArgumentException("coordinate set " + coords +
+ " does not contain 2D texture coordinates");
+ }
+
+ return m_texcoords[coords].getFloat(
+ (vertex * m_numUVComponents[coords] + 1) * SIZEOF_FLOAT);
+ }
+
+
+ /**
+ * Returns the w component of a coordinate from a texture coordinate set.<p>
+ *
+ * This method may only be called on 3-dimensional coordinate sets.
+ * Call <code>getNumUVComponents(coords)</code> to determine how may
+ * coordinate components are available.
+ *
+ * @param vertex the vertex index
+ * @param coords the texture coordinate set
+ * @return the w component
+ */
+ public float getTexCoordW(int vertex, int coords) {
+ if (!hasTexCoords(coords)) {
+ throw new IllegalStateException(
+ "mesh has no texture coordinate set " + coords);
+ }
+
+ checkVertexIndexBounds(vertex);
+
+ /* bound checks for coords are done by java for us */
+
+ if (getNumUVComponents(coords) < 3) {
+ throw new IllegalArgumentException("coordinate set " + coords +
+ " does not contain 3D texture coordinates");
+ }
+
+ return m_texcoords[coords].getFloat(
+ (vertex * m_numUVComponents[coords] + 1) * SIZEOF_FLOAT);
+ }
+ // }}
+
+
+ // {{ Wrapped API
+ /**
+ * Returns the vertex position as 3-dimensional vector.<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).<p>
+ *
+ * The built-in behavior is to return a {@link AiVector}.
+ *
+ * @param vertex the vertex index
+ * @param wrapperProvider the wrapper provider (used for type inference)
+ * @return the position wrapped as object
+ */
+ public <V3, M4, C, N, Q> V3 getWrappedPosition(int vertex,
+ AiWrapperProvider<V3, M4, C, N, Q> wrapperProvider) {
+
+ if (!hasPositions()) {
+ throw new IllegalStateException("mesh has no positions");
+ }
+
+ checkVertexIndexBounds(vertex);
+
+ return wrapperProvider.wrapVector3f(m_vertices,
+ vertex * 3 * SIZEOF_FLOAT, 3);
+ }
+
+
+ /**
+ * Returns the vertex normal as 3-dimensional vector.<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).<p>
+ *
+ * The built-in behavior is to return a {@link AiVector}.
+ *
+ * @param vertex the vertex index
+ * @param wrapperProvider the wrapper provider (used for type inference)
+ * @return the normal wrapped as object
+ */
+ public <V3, M4, C, N, Q> V3 getWrappedNormal(int vertex,
+ AiWrapperProvider<V3, M4, C, N, Q> wrapperProvider) {
+
+ if (!hasNormals()) {
+ throw new IllegalStateException("mesh has no positions");
+ }
+
+ checkVertexIndexBounds(vertex);
+
+ return wrapperProvider.wrapVector3f(m_normals,
+ vertex * 3 * SIZEOF_FLOAT, 3);
+ }
+
+
+ /**
+ * Returns the vertex tangent as 3-dimensional vector.<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).<p>
+ *
+ * The built-in behavior is to return a {@link AiVector}.
+ *
+ * @param vertex the vertex index
+ * @param wrapperProvider the wrapper provider (used for type inference)
+ * @return the tangent wrapped as object
+ */
+ public <V3, M4, C, N, Q> V3 getWrappedTangent(int vertex,
+ AiWrapperProvider<V3, M4, C, N, Q> wrapperProvider) {
+
+ if (!hasTangentsAndBitangents()) {
+ throw new IllegalStateException("mesh has no tangents");
+ }
+
+ checkVertexIndexBounds(vertex);
+
+ return wrapperProvider.wrapVector3f(m_tangents,
+ vertex * 3 * SIZEOF_FLOAT, 3);
+ }
+
+
+ /**
+ * Returns the vertex bitangent as 3-dimensional vector.<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).<p>
+ *
+ * The built-in behavior is to return a {@link AiVector}.
+ *
+ * @param vertex the vertex index
+ * @param wrapperProvider the wrapper provider (used for type inference)
+ * @return the bitangent wrapped as object
+ */
+ public <V3, M4, C, N, Q> V3 getWrappedBitangent(int vertex,
+ AiWrapperProvider<V3, M4, C, N, Q> wrapperProvider) {
+
+ if (!hasTangentsAndBitangents()) {
+ throw new IllegalStateException("mesh has no bitangents");
+ }
+
+ checkVertexIndexBounds(vertex);
+
+ return wrapperProvider.wrapVector3f(m_bitangents,
+ vertex * 3 * SIZEOF_FLOAT, 3);
+ }
+
+
+ /**
+ * Returns the vertex color.<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).<p>
+ *
+ * The built-in behavior is to return a {@link AiColor}.
+ *
+ * @param vertex the vertex index
+ * @param colorset the color set
+ * @param wrapperProvider the wrapper provider (used for type inference)
+ * @return the vertex color wrapped as object
+ */
+ public <V3, M4, C, N, Q> C getWrappedColor(int vertex, int colorset,
+ AiWrapperProvider<V3, M4, C, N, Q> wrapperProvider) {
+
+ if (!hasColors(colorset)) {
+ throw new IllegalStateException("mesh has no colorset " + colorset);
+ }
+
+ checkVertexIndexBounds(vertex);
+
+ return wrapperProvider.wrapColor(
+ m_colorsets[colorset], vertex * 4 * SIZEOF_FLOAT);
+ }
+
+
+ /**
+ * Returns the texture coordinates as n-dimensional vector.<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).<p>
+ *
+ * The built-in behavior is to return a {@link AiVector}.
+ *
+ * @param vertex the vertex index
+ * @param coords the texture coordinate set
+ * @param wrapperProvider the wrapper provider (used for type inference)
+ * @return the texture coordinates wrapped as object
+ */
+ public <V3, M4, C, N, Q> V3 getWrappedTexCoords(int vertex, int coords,
+ AiWrapperProvider<V3, M4, C, N, Q> wrapperProvider) {
+
+ if (!hasTexCoords(coords)) {
+ throw new IllegalStateException(
+ "mesh has no texture coordinate set " + coords);
+ }
+
+ checkVertexIndexBounds(vertex);
+
+ return wrapperProvider.wrapVector3f(m_texcoords[coords],
+ vertex * 3 * SIZEOF_FLOAT, getNumUVComponents(coords));
+ }
+ // }}
+
+
+ // {{ Helpers
+ /**
+ * Throws an exception if the vertex index is not in the allowed range.
+ *
+ * @param vertex the index to check
+ */
+ private void checkVertexIndexBounds(int vertex) {
+ if (vertex >= m_numVertices || vertex < 0) {
+ throw new IndexOutOfBoundsException("Index: " + vertex +
+ ", Size: " + m_numVertices);
+ }
+ }
+ // }}
+
+ // {{ JNI interface
+ /*
+ * Channel constants used by allocate data channel. Do not modify or use
+ * as these may change at will
+ */
+ // CHECKSTYLE:OFF
+ private static final int NORMALS = 0;
+ private static final int TANGENTS = 1;
+ private static final int BITANGENTS = 2;
+ private static final int COLORSET = 3;
+ private static final int TEXCOORDS_1D = 4;
+ private static final int TEXCOORDS_2D = 5;
+ private static final int TEXCOORDS_3D = 6;
+ // CHECKSTYLE:ON
+
+
+ /**
+ * This method is used by JNI. Do not call or modify.<p>
+ *
+ * Sets the primitive types enum set
+ *
+ * @param types the bitwise or'ed c/c++ aiPrimitiveType enum values
+ */
+ @SuppressWarnings("unused")
+ private void setPrimitiveTypes(int types) {
+ AiPrimitiveType.fromRawValue(m_primitiveTypes, types);
+ }
+
+
+ /**
+ * This method is used by JNI. Do not call or modify.<p>
+ *
+ * Allocates byte buffers
+ *
+ * @param numVertices the number of vertices in the mesh
+ * @param numFaces the number of faces in the mesh
+ * @param optimizedFaces set true for optimized face representation
+ * @param faceBufferSize size of face buffer for non-optimized face
+ * representation
+ */
+ @SuppressWarnings("unused")
+ private void allocateBuffers(int numVertices, int numFaces,
+ boolean optimizedFaces, int faceBufferSize) {
+ /*
+ * the allocated buffers are native order direct byte buffers, so they
+ * can be passed directly to LWJGL or similar graphics APIs
+ */
+
+ /* ensure face optimization is possible */
+ if (optimizedFaces && !isPureTriangle()) {
+ throw new IllegalArgumentException("mesh is not purely triangular");
+ }
+
+
+ m_numVertices = numVertices;
+ m_numFaces = numFaces;
+
+
+ /* allocate for each vertex 3 floats */
+ if (m_numVertices > 0) {
+ m_vertices = ByteBuffer.allocateDirect(numVertices * 3 *
+ SIZEOF_FLOAT);
+ m_vertices.order(ByteOrder.nativeOrder());
+ }
+
+
+ if (m_numFaces > 0) {
+ /* for optimized faces allocate 3 integers per face */
+ if (optimizedFaces) {
+ m_faces = ByteBuffer.allocateDirect(numFaces * 3 * SIZEOF_INT);
+ m_faces.order(ByteOrder.nativeOrder());
+ }
+ /*
+ * for non-optimized faces allocate the passed in buffer size
+ * and allocate the face index structure
+ */
+ else {
+ m_faces = ByteBuffer.allocateDirect(faceBufferSize);
+ m_faces.order(ByteOrder.nativeOrder());
+
+ m_faceOffsets = ByteBuffer.allocateDirect(numFaces *
+ SIZEOF_INT);
+ m_faceOffsets.order(ByteOrder.nativeOrder());
+ }
+ }
+ }
+
+
+ /**
+ * This method is used by JNI. Do not call or modify.<p>
+ *
+ * Allocates a byte buffer for a vertex data channel
+ *
+ * @param channelType the channel type
+ * @param channelIndex sub-index, used for types that can have multiple
+ * channels, such as texture coordinates
+ */
+ @SuppressWarnings("unused")
+ private void allocateDataChannel(int channelType, int channelIndex) {
+ switch (channelType) {
+ case NORMALS:
+ m_normals = ByteBuffer.allocateDirect(
+ m_numVertices * 3 * SIZEOF_FLOAT);
+ m_normals.order(ByteOrder.nativeOrder());
+ break;
+ case TANGENTS:
+ m_tangents = ByteBuffer.allocateDirect(
+ m_numVertices * 3 * SIZEOF_FLOAT);
+ m_tangents.order(ByteOrder.nativeOrder());
+ break;
+ case BITANGENTS:
+ m_bitangents = ByteBuffer.allocateDirect(
+ m_numVertices * 3 * SIZEOF_FLOAT);
+ m_bitangents.order(ByteOrder.nativeOrder());
+ break;
+ case COLORSET:
+ m_colorsets[channelIndex] = ByteBuffer.allocateDirect(
+ m_numVertices * 4 * SIZEOF_FLOAT);
+ m_colorsets[channelIndex].order(ByteOrder.nativeOrder());
+ break;
+ case TEXCOORDS_1D:
+ m_numUVComponents[channelIndex] = 1;
+ m_texcoords[channelIndex] = ByteBuffer.allocateDirect(
+ m_numVertices * 1 * SIZEOF_FLOAT);
+ m_texcoords[channelIndex].order(ByteOrder.nativeOrder());
+ break;
+ case TEXCOORDS_2D:
+ m_numUVComponents[channelIndex] = 2;
+ m_texcoords[channelIndex] = ByteBuffer.allocateDirect(
+ m_numVertices * 2 * SIZEOF_FLOAT);
+ m_texcoords[channelIndex].order(ByteOrder.nativeOrder());
+ break;
+ case TEXCOORDS_3D:
+ m_numUVComponents[channelIndex] = 3;
+ m_texcoords[channelIndex] = ByteBuffer.allocateDirect(
+ m_numVertices * 3 * SIZEOF_FLOAT);
+ m_texcoords[channelIndex].order(ByteOrder.nativeOrder());
+ break;
+ default:
+ throw new IllegalArgumentException("unsupported channel type");
+ }
+ }
+ // }}
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiMeshAnim.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiMeshAnim.java
new file mode 100644
index 0000000..7c893e0
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiMeshAnim.java
@@ -0,0 +1,49 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, 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;
+
+
+/**
+ * This class is a stub - mesh animations are currently not supported.
+ */
+public class AiMeshAnim {
+
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiMetadataEntry.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiMetadataEntry.java
new file mode 100644
index 0000000..76e6664
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiMetadataEntry.java
@@ -0,0 +1,118 @@
+package jassimp;
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+public class AiMetadataEntry
+{
+ public enum AiMetadataType
+ {
+ AI_BOOL, AI_INT32, AI_UINT64, AI_FLOAT, AI_DOUBLE, AI_AISTRING, AI_AIVECTOR3D
+ }
+
+ private AiMetadataType mType;
+ private Object mData;
+
+ public AiMetadataType getMetaDataType()
+ {
+ return mType;
+ }
+
+ public Object getData()
+ {
+ return mData;
+ }
+
+ public static boolean getAiBoolAsBoolean(AiMetadataEntry metadataEntry)
+ {
+ checkTypeBeforeCasting(metadataEntry, AiMetadataType.AI_BOOL);
+
+ return (boolean) metadataEntry.mData;
+ }
+
+ public static int getAiInt32AsInteger(AiMetadataEntry metadataEntry)
+ {
+ checkTypeBeforeCasting(metadataEntry, AiMetadataType.AI_INT32);
+
+ return (int) metadataEntry.mData;
+ }
+
+ public static long getAiUint64AsLong(AiMetadataEntry metadataEntry)
+ {
+ checkTypeBeforeCasting(metadataEntry, AiMetadataType.AI_UINT64);
+
+ return (long) metadataEntry.mData;
+ }
+
+ public static float getAiFloatAsFloat(AiMetadataEntry metadataEntry)
+ {
+ checkTypeBeforeCasting(metadataEntry, AiMetadataType.AI_FLOAT);
+
+ return (float) metadataEntry.mData;
+ }
+
+ public static double getAiDoubleAsDouble(AiMetadataEntry metadataEntry)
+ {
+ checkTypeBeforeCasting(metadataEntry, AiMetadataType.AI_DOUBLE);
+
+ return (double) metadataEntry.mData;
+ }
+
+ public static String getAiStringAsString(AiMetadataEntry metadataEntry)
+ {
+ checkTypeBeforeCasting(metadataEntry, AiMetadataType.AI_AISTRING);
+
+ return (String) metadataEntry.mData;
+ }
+
+ public static AiVector getAiAiVector3DAsAiVector(AiMetadataEntry metadataEntry)
+ {
+ checkTypeBeforeCasting(metadataEntry, AiMetadataType.AI_AIVECTOR3D);
+
+ return (AiVector) metadataEntry.mData;
+ }
+
+ private static void checkTypeBeforeCasting(AiMetadataEntry entry, AiMetadataType expectedType)
+ {
+ if(entry.mType != expectedType)
+ {
+ throw new RuntimeException("Cannot cast entry of type " + entry.mType.name() + " to " + expectedType.name());
+ }
+ }
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiNode.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiNode.java
new file mode 100644
index 0000000..54baf9c
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiNode.java
@@ -0,0 +1,246 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * A node in the imported hierarchy.<p>
+ *
+ * Each node has name, a parent node (except for the root node),
+ * a transformation relative to its parent and possibly several child nodes.
+ * Simple file formats don't support hierarchical structures - for these formats
+ * 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<AiNode> m_children = new ArrayList<AiNode>();
+
+ /**
+ * List of metadata entries.
+ */
+ private final Map<String, AiMetadataEntry> m_metaData = new HashMap<String, AiMetadataEntry>();
+
+
+ /**
+ * Buffer for transformation matrix.
+ */
+ private final Object m_transformationMatrix;
+
+ /**
+ * Constructor.
+ *
+ * @param parent the parent node, may be null
+ * @param transform the transform matrix
+ * @param meshReferences array of mesh references
+ * @param name the name of the node
+ */
+ AiNode(AiNode parent, Object transform, int[] meshReferences, String name) {
+ m_parent = parent;
+ m_transformationMatrix = transform;
+ m_meshReferences = meshReferences;
+ m_name = name;
+
+ if (null != m_parent) {
+ m_parent.addChild(this);
+ }
+ }
+
+
+ /**
+ * Returns the name of this node.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return m_name;
+ }
+
+
+ /**
+ * Returns the number of child nodes.<p>
+ *
+ * This method exists for compatibility reasons with the native assimp API.
+ * The returned value is identical to <code>getChildren().size()</code>
+ *
+ * @return the number of child nodes
+ */
+ public int getNumChildren() {
+ return getChildren().size();
+ }
+
+
+ /**
+ * Returns a 4x4 matrix that specifies the transformation relative to
+ * the parent node.<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).<p>
+ *
+ * The built in behavior is to return an {@link AiMatrix4f}.
+ *
+ * @param wrapperProvider the wrapper provider (used for type inference)
+ *
+ * @return a matrix
+ */
+ @SuppressWarnings("unchecked")
+ public <V3, M4, C, N, Q> M4 getTransform(AiWrapperProvider<V3, M4, C, N, Q>
+ wrapperProvider) {
+
+ return (M4) m_transformationMatrix;
+ }
+
+
+ /**
+ * Returns the children of this node.
+ *
+ * @return the children, or an empty list if the node has no children
+ */
+ public List<AiNode> getChildren() {
+ return m_children;
+ }
+
+
+ /**
+ * Returns the parent node.
+ *
+ * @return the parent, or null of the node has no parent
+ */
+ public AiNode getParent() {
+ return m_parent;
+ }
+
+
+ /**
+ * Searches the node hierarchy below (and including) this node for a node
+ * with the specified name.
+ *
+ * @param name the name to look for
+ * @return the first node with the given name, or null if no such node
+ * exists
+ */
+ public AiNode findNode(String name) {
+ /* classic recursive depth first search */
+
+ if (m_name.equals(name)) {
+ return this;
+ }
+
+ for (AiNode child : m_children) {
+ if (null != child.findNode(name)) {
+ return child;
+ }
+ }
+
+ return null;
+ }
+
+
+ /**
+ * Returns the number of meshes references by this node.<p>
+ *
+ * This method exists for compatibility with the native assimp API.
+ * The returned value is identical to <code>getMeshes().length</code>
+ *
+ * @return the number of references
+ */
+ public int getNumMeshes() {
+ return m_meshReferences.length;
+ }
+
+
+ /**
+ * Returns the meshes referenced by this node.<p>
+ *
+ * Each entry is an index into the mesh list stored in {@link AiScene}.
+ *
+ * @return an array of indices
+ */
+ public int[] getMeshes() {
+ return m_meshReferences;
+ }
+
+ /**
+ * Returns the metadata entries for this node.<p>
+ *
+ * Consult the original Doxygen for importer_notes to
+ * see which formats have metadata and what to expect.
+ *
+ * @return A map of metadata names to entries.
+ */
+ public Map<String, AiMetadataEntry> getMetadata() {
+ return m_metaData;
+ }
+
+
+ /**
+ * Adds a child node.
+ *
+ * @param child the child to add
+ */
+ void addChild(AiNode child) {
+ m_children.add(child);
+ }
+
+
+ /**
+ * Name.
+ */
+ private final String m_name;
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiNodeAnim.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiNodeAnim.java
new file mode 100644
index 0000000..b07c7ce
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiNodeAnim.java
@@ -0,0 +1,501 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+
+/**
+ * Describes the animation of a single node.<p>
+ *
+ * The node name ({@link #getNodeName()} specifies the bone/node which is
+ * affected by this animation channel. The keyframes are given in three
+ * separate series of values, one each for position, rotation and scaling.
+ * The transformation matrix computed from these values replaces the node's
+ * original transformation matrix at a specific time.<p>
+ *
+ * This means all keys are absolute and not relative to the bone default pose.
+ * The order in which the transformations are applied is - as usual -
+ * scaling, rotation, translation.<p>
+ *
+ * <b>Note:</b> All keys are returned in their correct, chronological order.
+ * Duplicate keys don't pass the validation step. Most likely there
+ * will be no negative time values, but they are not forbidden also (so
+ * implementations need to cope with them!)<p>
+ *
+ * Like {@link AiMesh}, the animation related classes offer a Buffer API, a
+ * Direct API and a wrapped API. Please consult the documentation of
+ * {@link AiMesh} for a description and comparison of these APIs.
+ */
+public final class AiNodeAnim {
+ /**
+ * Size of one position key entry.
+ */
+ private final int POS_KEY_SIZE = Jassimp.NATIVE_AIVEKTORKEY_SIZE;
+
+ /**
+ * Size of one rotation key entry.
+ */
+ private final int ROT_KEY_SIZE = Jassimp.NATIVE_AIQUATKEY_SIZE;
+
+ /**
+ * Size of one scaling key entry.
+ */
+ private final int SCALE_KEY_SIZE = Jassimp.NATIVE_AIVEKTORKEY_SIZE;
+
+
+ /**
+ * Constructor.
+ *
+ * @param nodeName name of corresponding scene graph node
+ * @param numPosKeys number of position keys
+ * @param numRotKeys number of rotation keys
+ * @param numScaleKeys number of scaling keys
+ * @param preBehavior behavior before animation start
+ * @param postBehavior behavior after animation end
+ */
+ AiNodeAnim(String nodeName, int numPosKeys, int numRotKeys,
+ int numScaleKeys, int preBehavior, int postBehavior) {
+
+ m_nodeName = nodeName;
+ m_numPosKeys = numPosKeys;
+ m_numRotKeys = numRotKeys;
+ m_numScaleKeys = numScaleKeys;
+ m_preState = AiAnimBehavior.fromRawValue(preBehavior);
+ m_postState = AiAnimBehavior.fromRawValue(postBehavior);
+
+ m_posKeys = ByteBuffer.allocateDirect(numPosKeys * POS_KEY_SIZE);
+ m_posKeys.order(ByteOrder.nativeOrder());
+
+ m_rotKeys = ByteBuffer.allocateDirect(numRotKeys * ROT_KEY_SIZE);
+ m_rotKeys.order(ByteOrder.nativeOrder());
+
+ m_scaleKeys = ByteBuffer.allocateDirect(numScaleKeys * SCALE_KEY_SIZE);
+ m_scaleKeys.order(ByteOrder.nativeOrder());
+ }
+
+
+ /**
+ * Returns the name of the scene graph node affected by this animation.<p>
+ *
+ * The node must exist and it must be unique.
+ *
+ * @return the name of the affected node
+ */
+ public String getNodeName() {
+ return m_nodeName;
+ }
+
+
+ /**
+ * Returns the number of position keys.
+ *
+ * @return the number of position keys
+ */
+ public int getNumPosKeys() {
+ return m_numPosKeys;
+ }
+
+
+ /**
+ * Returns the buffer with position keys of this animation channel.<p>
+ *
+ * Position keys consist of a time value (double) and a position (3D vector
+ * of floats), resulting in a total of 20 bytes per entry.
+ * The buffer contains {@link #getNumPosKeys()} of these entries.<p>
+ *
+ * If there are position keys, there will also be at least one
+ * scaling and one rotation key.<p>
+ *
+ * @return a native order, direct ByteBuffer
+ */
+ public ByteBuffer getPosKeyBuffer() {
+ ByteBuffer buf = m_posKeys.duplicate();
+ buf.order(ByteOrder.nativeOrder());
+
+ return buf;
+ }
+
+
+ /**
+ * Returns the time component of the specified position key.
+ *
+ * @param keyIndex the index of the position key
+ * @return the time component
+ */
+ public double getPosKeyTime(int keyIndex) {
+ return m_posKeys.getDouble(POS_KEY_SIZE * keyIndex);
+ }
+
+
+ /**
+ * Returns the position x component of the specified position key.
+ *
+ * @param keyIndex the index of the position key
+ * @return the x component
+ */
+ public float getPosKeyX(int keyIndex) {
+ return m_posKeys.getFloat(POS_KEY_SIZE * keyIndex + 8);
+ }
+
+
+ /**
+ * Returns the position y component of the specified position key.
+ *
+ * @param keyIndex the index of the position key
+ * @return the y component
+ */
+ public float getPosKeyY(int keyIndex) {
+ return m_posKeys.getFloat(POS_KEY_SIZE * keyIndex + 12);
+ }
+
+
+ /**
+ * Returns the position z component of the specified position key.
+ *
+ * @param keyIndex the index of the position key
+ * @return the z component
+ */
+ public float getPosKeyZ(int keyIndex) {
+ return m_posKeys.getFloat(POS_KEY_SIZE * keyIndex + 16);
+ }
+
+
+ /**
+ * Returns the position as vector.<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).<p>
+ *
+ * The built in behavior is to return an {@link AiVector}.
+ *
+ * @param wrapperProvider the wrapper provider (used for type inference)
+ *
+ * @return the position as vector
+ */
+ public <V3, M4, C, N, Q> V3 getPosKeyVector(int keyIndex,
+ AiWrapperProvider<V3, M4, C, N, Q> wrapperProvider) {
+
+ return wrapperProvider.wrapVector3f(m_posKeys,
+ POS_KEY_SIZE * keyIndex + 8, 3);
+ }
+
+
+ /**
+ * Returns the number of rotation keys.
+ *
+ * @return the number of rotation keys
+ */
+ public int getNumRotKeys() {
+ return m_numRotKeys;
+ }
+
+
+ /**
+ * Returns the buffer with rotation keys of this animation channel.<p>
+ *
+ * Rotation keys consist of a time value (double) and a quaternion (4D
+ * vector of floats), resulting in a total of 24 bytes per entry. The
+ * buffer contains {@link #getNumRotKeys()} of these entries.<p>
+ *
+ * If there are rotation keys, there will also be at least one
+ * scaling and one position key.
+ *
+ * @return a native order, direct ByteBuffer
+ */
+ public ByteBuffer getRotKeyBuffer() {
+ ByteBuffer buf = m_rotKeys.duplicate();
+ buf.order(ByteOrder.nativeOrder());
+
+ return buf;
+ }
+
+
+ /**
+ * Returns the time component of the specified rotation key.
+ *
+ * @param keyIndex the index of the position key
+ * @return the time component
+ */
+ public double getRotKeyTime(int keyIndex) {
+ return m_rotKeys.getDouble(ROT_KEY_SIZE * keyIndex);
+ }
+
+
+ /**
+ * Returns the rotation w component of the specified rotation key.
+ *
+ * @param keyIndex the index of the position key
+ * @return the w component
+ */
+ public float getRotKeyW(int keyIndex) {
+ return m_rotKeys.getFloat(ROT_KEY_SIZE * keyIndex + 8);
+ }
+
+
+ /**
+ * Returns the rotation x component of the specified rotation key.
+ *
+ * @param keyIndex the index of the position key
+ * @return the x component
+ */
+ public float getRotKeyX(int keyIndex) {
+ return m_rotKeys.getFloat(ROT_KEY_SIZE * keyIndex + 12);
+ }
+
+
+ /**
+ * Returns the rotation y component of the specified rotation key.
+ *
+ * @param keyIndex the index of the position key
+ * @return the y component
+ */
+ public float getRotKeyY(int keyIndex) {
+ return m_rotKeys.getFloat(ROT_KEY_SIZE * keyIndex + 16);
+ }
+
+
+ /**
+ * Returns the rotation z component of the specified rotation key.
+ *
+ * @param keyIndex the index of the position key
+ * @return the z component
+ */
+ public float getRotKeyZ(int keyIndex) {
+ return m_rotKeys.getFloat(ROT_KEY_SIZE * keyIndex + 20);
+ }
+
+
+ /**
+ * Returns the rotation as quaternion.<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).<p>
+ *
+ * The built in behavior is to return an {@link AiQuaternion}.
+ *
+ * @param wrapperProvider the wrapper provider (used for type inference)
+ *
+ * @return the rotation as quaternion
+ */
+ public <V3, M4, C, N, Q> Q getRotKeyQuaternion(int keyIndex,
+ AiWrapperProvider<V3, M4, C, N, Q> wrapperProvider) {
+
+ return wrapperProvider.wrapQuaternion(m_rotKeys,
+ ROT_KEY_SIZE * keyIndex + 8);
+ }
+
+
+ /**
+ * Returns the number of scaling keys.
+ *
+ * @return the number of scaling keys
+ */
+ public int getNumScaleKeys() {
+ return m_numScaleKeys;
+ }
+
+
+ /**
+ * Returns the buffer with scaling keys of this animation channel.<p>
+ *
+ * Scaling keys consist of a time value (double) and a 3D vector of floats,
+ * resulting in a total of 20 bytes per entry. The buffer
+ * contains {@link #getNumScaleKeys()} of these entries.<p>
+ *
+ * If there are scaling keys, there will also be at least one
+ * position and one rotation key.
+ *
+ * @return a native order, direct ByteBuffer
+ */
+ public ByteBuffer getScaleKeyBuffer() {
+ ByteBuffer buf = m_scaleKeys.duplicate();
+ buf.order(ByteOrder.nativeOrder());
+
+ return buf;
+ }
+
+
+ /**
+ * Returns the time component of the specified scaling key.
+ *
+ * @param keyIndex the index of the position key
+ * @return the time component
+ */
+ public double getScaleKeyTime(int keyIndex) {
+ return m_scaleKeys.getDouble(SCALE_KEY_SIZE * keyIndex);
+ }
+
+
+ /**
+ * Returns the scaling x component of the specified scaling key.
+ *
+ * @param keyIndex the index of the position key
+ * @return the x component
+ */
+ public float getScaleKeyX(int keyIndex) {
+ return m_scaleKeys.getFloat(SCALE_KEY_SIZE * keyIndex + 8);
+ }
+
+
+ /**
+ * Returns the scaling y component of the specified scaling key.
+ *
+ * @param keyIndex the index of the position key
+ * @return the y component
+ */
+ public float getScaleKeyY(int keyIndex) {
+ return m_scaleKeys.getFloat(SCALE_KEY_SIZE * keyIndex + 12);
+ }
+
+
+ /**
+ * Returns the scaling z component of the specified scaling key.
+ *
+ * @param keyIndex the index of the position key
+ * @return the z component
+ */
+ public float getScaleKeyZ(int keyIndex) {
+ return m_scaleKeys.getFloat(SCALE_KEY_SIZE * keyIndex + 16);
+ }
+
+
+ /**
+ * Returns the scaling factor as vector.<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).<p>
+ *
+ * The built in behavior is to return an {@link AiVector}.
+ *
+ * @param wrapperProvider the wrapper provider (used for type inference)
+ *
+ * @return the scaling factor as vector
+ */
+ public <V3, M4, C, N, Q> V3 getScaleKeyVector(int keyIndex,
+ AiWrapperProvider<V3, M4, C, N, Q> wrapperProvider) {
+
+ return wrapperProvider.wrapVector3f(m_scaleKeys,
+ SCALE_KEY_SIZE * keyIndex + 8, 3);
+ }
+
+
+ /**
+ * Defines how the animation behaves before the first key is encountered.
+ * <p>
+ *
+ * The default value is {@link AiAnimBehavior#DEFAULT} (the original
+ * transformation matrix of the affected node is used).
+ *
+ * @return the animation behavior before the first key
+ */
+ public AiAnimBehavior getPreState() {
+ return m_preState;
+ }
+
+
+ /**
+ * Defines how the animation behaves after the last key was processed.<p>
+ *
+ * The default value is {@link AiAnimBehavior#DEFAULT} (the original
+ * transformation matrix of the affected node is taken).
+ *
+ * @return the animation behavior before after the last key
+ */
+ public AiAnimBehavior getPostState() {
+ return m_postState;
+ }
+
+
+ /**
+ * Node name.
+ */
+ private final String m_nodeName;
+
+
+ /**
+ * Number of position keys.
+ */
+ private final int m_numPosKeys;
+
+
+ /**
+ * Buffer with position keys.
+ */
+ private ByteBuffer m_posKeys;
+
+
+ /**
+ * Number of rotation keys.
+ */
+ private final int m_numRotKeys;
+
+
+ /**
+ * Buffer for rotation keys.
+ */
+ private ByteBuffer m_rotKeys;
+
+
+ /**
+ * Number of scaling keys.
+ */
+ private final int m_numScaleKeys;
+
+
+ /**
+ * Buffer for scaling keys.
+ */
+ private ByteBuffer m_scaleKeys;
+
+
+ /**
+ * Pre animation behavior.
+ */
+ private final AiAnimBehavior m_preState;
+
+
+ /**
+ * Post animation behavior.
+ */
+ private final AiAnimBehavior m_postState;
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiPostProcessSteps.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiPostProcessSteps.java
new file mode 100644
index 0000000..7bb617b
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiPostProcessSteps.java
@@ -0,0 +1,571 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+import java.util.Set;
+
+/**
+ * Enumerates the post processing steps supported by assimp.
+ */
+public enum AiPostProcessSteps {
+
+ /**
+ * Calculates the tangents and bitangents for the imported meshes.
+ * <p>
+ *
+ * Does nothing if a mesh does not have normals. You might want this post
+ * processing step to be executed if you plan to use tangent space
+ * calculations such as normal mapping applied to the meshes. There's a
+ * config setting, <tt>#AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE</tt>, which
+ * allows you to specify a maximum smoothing angle for the algorithm.
+ * However, usually you'll want to leave it at the default value.
+ */
+ CALC_TANGENT_SPACE(0x1),
+
+
+ /**
+ * Identifies and joins identical vertex data sets within all imported
+ * meshes.<p>
+ *
+ * After this step is run, each mesh contains unique vertices, so a vertex
+ * may be used by multiple faces. You usually want to use this post
+ * processing step. If your application deals with indexed geometry, this
+ * step is compulsory or you'll just waste rendering time. <b>If this flag
+ * is not specified</b>, no vertices are referenced by more than one face
+ * and <b>no index buffer is required</b> for rendering.
+ */
+ JOIN_IDENTICAL_VERTICES(0x2),
+
+
+ /**
+ * Converts all the imported data to a left-handed coordinate space.<p>
+ *
+ * By default the data is returned in a right-handed coordinate space (which
+ * OpenGL prefers). In this space, +X points to the right, +Z points towards
+ * the viewer, and +Y points upwards. In the DirectX coordinate space +X
+ * points to the right, +Y points upwards, and +Z points away from the
+ * viewer.<p>
+ *
+ * You'll probably want to consider this flag if you use Direct3D for
+ * rendering. The #ConvertToLeftHanded flag supersedes this
+ * setting and bundles all conversions typically required for D3D-based
+ * applications.
+ */
+ MAKE_LEFT_HANDED(0x4),
+
+
+ /**
+ * Triangulates all faces of all meshes.<p>
+ *
+ * By default the imported mesh data might contain faces with more than 3
+ * indices. For rendering you'll usually want all faces to be triangles.
+ * This post processing step splits up faces with more than 3 indices into
+ * triangles. Line and point primitives are *not* modified! If you want
+ * 'triangles only' with no other kinds of primitives, try the following
+ * solution:
+ * <ul>
+ * <li>Specify both #Triangulate and #SortByPType
+ * <li>Ignore all point and line meshes when you process assimp's output
+ * </ul>
+ */
+ TRIANGULATE(0x8),
+
+
+ /**
+ * Removes some parts of the data structure (animations, materials, light
+ * sources, cameras, textures, vertex components).<p>
+ *
+ * The components to be removed are specified in a separate configuration
+ * option, <tt>#AI_CONFIG_PP_RVC_FLAGS</tt>. This is quite useful if you
+ * don't need all parts of the output structure. Vertex colors are rarely
+ * used today for example... Calling this step to remove unneeded data from
+ * the pipeline as early as possible results in increased performance and a
+ * more optimized output data structure. This step is also useful if you
+ * want to force Assimp to recompute normals or tangents. The corresponding
+ * steps don't recompute them if they're already there (loaded from the
+ * source asset). By using this step you can make sure they are NOT there.
+ * <p>
+ *
+ * This flag is a poor one, mainly because its purpose is usually
+ * misunderstood. Consider the following case: a 3D model has been exported
+ * from a CAD app, and it has per-face vertex colors. Vertex positions can't
+ * be shared, thus the #JoinIdenticalVertices step fails to
+ * optimize the data because of these nasty little vertex colors. Most apps
+ * don't even process them, so it's all for nothing. By using this step,
+ * unneeded components are excluded as early as possible thus opening more
+ * room for internal optimizations.
+ */
+ REMOVE_COMPONENT(0x10),
+
+
+ /**
+ * Generates normals for all faces of all meshes.<p>
+ *
+ * This is ignored if normals are already there at the time this flag is
+ * evaluated. Model importers try to load them from the source file, so
+ * they're usually already there. Face normals are shared between all points
+ * of a single face, so a single point can have multiple normals, which
+ * forces the library to duplicate vertices in some cases.
+ * #JoinIdenticalVertices is *senseless* then.<p>
+ *
+ * This flag may not be specified together with {@link #GEN_SMOOTH_NORMALS}.
+ */
+ GEN_NORMALS(0x20),
+
+
+ /**
+ * Generates smooth normals for all vertices in the mesh.<p>
+ *
+ * This is ignored if normals are already there at the time this flag is
+ * evaluated. Model importers try to load them from the source file, so
+ * they're usually already there.<p>
+ *
+ * This flag may not be specified together with {@link #GEN_NORMALS}
+ * There's a configuration option,
+ * <tt>#AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE</tt> which allows you to
+ * specify an angle maximum for the normal smoothing algorithm. Normals
+ * exceeding this limit are not smoothed, resulting in a 'hard' seam between
+ * two faces. Using a decent angle here (e.g. 80 degrees) results in very
+ * good visual appearance.
+ */
+ GEN_SMOOTH_NORMALS(0x40),
+
+
+ /**
+ * Splits large meshes into smaller sub-meshes.<p>
+ *
+ * This is quite useful for real-time rendering, where the number of
+ * triangles which can be maximally processed in a single draw-call is
+ * limited by the video driver/hardware. The maximum vertex buffer is
+ * usually limited too. Both requirements can be met with this step: you may
+ * specify both a triangle and vertex limit for a single mesh.<p>
+ *
+ * The split limits can (and should!) be set through the
+ * <tt>#AI_CONFIG_PP_SLM_VERTEX_LIMIT</tt> and
+ * <tt>#AI_CONFIG_PP_SLM_TRIANGLE_LIMIT</tt> settings. The default values
+ * are <tt>#AI_SLM_DEFAULT_MAX_VERTICES</tt> and
+ * <tt>#AI_SLM_DEFAULT_MAX_TRIANGLES</tt>.<p>
+ *
+ * Note that splitting is generally a time-consuming task, but only if
+ * there's something to split. The use of this step is recommended for most
+ * users.
+ */
+ SPLIT_LARGE_MESHES(0x80),
+
+
+ /**
+ * Removes the node graph and pre-transforms all vertices with the local
+ * transformation matrices of their nodes.<p>
+ *
+ * The output scene still contains nodes, however there is only a root node
+ * with children, each one referencing only one mesh, and each mesh
+ * referencing one material. For rendering, you can simply render all meshes
+ * in order - you don't need to pay attention to local transformations and
+ * the node hierarchy. Animations are removed during this step. This step is
+ * intended for applications without a scenegraph. The step CAN cause some
+ * problems: if e.g. a mesh of the asset contains normals and another, using
+ * the same material index, does not, they will be brought together, but the
+ * first meshes's part of the normal list is zeroed. However, these
+ * artifacts are rare.<p>
+ *
+ * <b>Note:</b> The <tt>#AI_CONFIG_PP_PTV_NORMALIZE</tt> configuration
+ * property can be set to normalize the scene's spatial dimension to the
+ * -1...1 range.
+ */
+ PRE_TRANSFORM_VERTICES(0x100),
+
+
+ /**
+ * Limits the number of bones simultaneously affecting a single vertex to a
+ * maximum value.<p>
+ *
+ * If any vertex is affected by more than the maximum number of bones, the
+ * least important vertex weights are removed and the remaining vertex
+ * weights are renormalized so that the weights still sum up to 1. The
+ * default bone weight limit is 4 (defined as <tt>#AI_LMW_MAX_WEIGHTS</tt>
+ * in config.h), but you can use the <tt>#AI_CONFIG_PP_LBW_MAX_WEIGHTS</tt>
+ * setting to supply your own limit to the post processing step.<p>
+ *
+ * If you intend to perform the skinning in hardware, this post processing
+ * step might be of interest to you.
+ */
+ LIMIT_BONE_WEIGHTS(0x200),
+
+
+ /**
+ * Validates the imported scene data structure. This makes sure that all
+ * indices are valid, all animations and bones are linked correctly, all
+ * material references are correct .. etc.<p>
+ *
+ * It is recommended that you capture Assimp's log output if you use this
+ * flag, so you can easily find out what's wrong if a file fails the
+ * validation. The validator is quite strict and will find *all*
+ * inconsistencies in the data structure... It is recommended that plugin
+ * developers use it to debug their loaders. There are two types of
+ * validation failures:
+ * <ul>
+ * <li>Error: There's something wrong with the imported data. Further
+ * postprocessing is not possible and the data is not usable at all. The
+ * import fails. #Importer::GetErrorString() or #aiGetErrorString() carry
+ * the error message around.</li>
+ * <li>Warning: There are some minor issues (e.g. 1000000 animation
+ * keyframes with the same time), but further postprocessing and use of the
+ * data structure is still safe. Warning details are written to the log
+ * file, <tt>#AI_SCENE_FLAGS_VALIDATION_WARNING</tt> is set in
+ * #aiScene::mFlags</li>
+ * </ul>
+ *
+ * This post-processing step is not time-consuming. Its use is not
+ * compulsory, but recommended.
+ */
+ VALIDATE_DATA_STRUCTURE(0x400),
+
+
+ /**
+ * Reorders triangles for better vertex cache locality.<p>
+ *
+ * The step tries to improve the ACMR (average post-transform vertex cache
+ * miss ratio) for all meshes. The implementation runs in O(n) and is
+ * roughly based on the 'tipsify' algorithm (see <a href="
+ * http://www.cs.princeton.edu/gfx/pubs/Sander_2007_%3ETR/tipsy.pdf">this
+ * paper</a>).<p>
+ *
+ * If you intend to render huge models in hardware, this step might be of
+ * interest to you. The <tt>#AI_CONFIG_PP_ICL_PTCACHE_SIZE</tt>config
+ * setting can be used to fine-tune the cache optimization.
+ */
+ IMPROVE_CACHE_LOCALITY(0x800),
+
+
+ /**
+ * Searches for redundant/unreferenced materials and removes them.<p>
+ *
+ * This is especially useful in combination with the
+ * #PretransformVertices and #OptimizeMeshes flags. Both
+ * join small meshes with equal characteristics, but they can't do their
+ * work if two meshes have different materials. Because several material
+ * settings are lost during Assimp's import filters, (and because many
+ * exporters don't check for redundant materials), huge models often have
+ * materials which are are defined several times with exactly the same
+ * settings.<p>
+ *
+ * Several material settings not contributing to the final appearance of a
+ * surface are ignored in all comparisons (e.g. the material name). So, if
+ * you're passing additional information through the content pipeline
+ * (probably using *magic* material names), don't specify this flag.
+ * Alternatively take a look at the <tt>#AI_CONFIG_PP_RRM_EXCLUDE_LIST</tt>
+ * setting.
+ */
+ REMOVE_REDUNDANT_MATERIALS(0x1000),
+
+
+ /**
+ * This step tries to determine which meshes have normal vectors that are
+ * facing inwards and inverts them.<p>
+ *
+ * The algorithm is simple but effective: the bounding box of all vertices +
+ * their normals is compared against the volume of the bounding box of all
+ * vertices without their normals. This works well for most objects,
+ * problems might occur with planar surfaces. However, the step tries to
+ * filter such cases. The step inverts all in-facing normals. Generally it
+ * is recommended to enable this step, although the result is not always
+ * correct.
+ */
+ FIX_INFACING_NORMALS(0x2000),
+
+
+ /**
+ * This step splits meshes with more than one primitive type in homogeneous
+ * sub-meshes.<p>
+ *
+ * The step is executed after the triangulation step. After the step
+ * returns, just one bit is set in aiMesh::mPrimitiveTypes. This is
+ * especially useful for real-time rendering where point and line primitives
+ * are often ignored or rendered separately. You can use the
+ * <tt>#AI_CONFIG_PP_SBP_REMOVE</tt> option to specify which primitive types
+ * you need. This can be used to easily exclude lines and points, which are
+ * rarely used, from the import.
+ */
+ SORT_BY_PTYPE(0x8000),
+
+
+ /**
+ * This step searches all meshes for degenerate primitives and converts them
+ * to proper lines or points.<p>
+ *
+ * A face is 'degenerate' if one or more of its points are identical. To
+ * have the degenerate stuff not only detected and collapsed but removed,
+ * try one of the following procedures: <br>
+ * <b>1.</b> (if you support lines and points for rendering but don't want
+ * the degenerates)</br>
+ * <ul>
+ * <li>Specify the #FindDegenerates flag.</li>
+ * <li>Set the <tt>AI_CONFIG_PP_FD_REMOVE</tt> option to 1. This will cause
+ * the step to remove degenerate triangles from the import as soon as
+ * they're detected. They won't pass any further pipeline steps.</li>
+ * </ul>
+ * <br>
+ * <b>2.</b>(if you don't support lines and points at all)</br>
+ * <ul>
+ * <li>Specify the #FindDegenerates flag.
+ * <li>Specify the #SortByPType flag. This moves line and point
+ * primitives to separate meshes.
+ * <li>Set the <tt>AI_CONFIG_PP_SBP_REMOVE</tt> option to
+ * <code>aiPrimitiveType_POINTS | aiPrimitiveType_LINES</code>
+ * to cause SortByPType to reject point and line meshes from the
+ * scene.
+ * </ul>
+ * <b>Note:</b> Degenerated polygons are not necessarily evil and that's
+ * why they're not removed by default. There are several file formats
+ * which don't support lines or points, and some exporters bypass the
+ * format specification and write them as degenerate triangles instead.
+ */
+ FIND_DEGENERATES(0x10000),
+
+
+ /**
+ * This step searches all meshes for invalid data, such as zeroed normal
+ * vectors or invalid UV coords and removes/fixes them. This is intended to
+ * get rid of some common exporter errors.<p>
+ *
+ * This is especially useful for normals. If they are invalid, and the step
+ * recognizes this, they will be removed and can later be recomputed, i.e.
+ * by the {@link #GEN_SMOOTH_NORMALS} flag.<p>
+ *
+ * The step will also remove meshes that are infinitely small and reduce
+ * animation tracks consisting of hundreds if redundant keys to a single
+ * key. The <tt>AI_CONFIG_PP_FID_ANIM_ACCURACY</tt> config property decides
+ * the accuracy of the check for duplicate animation tracks.
+ */
+ FIND_INVALID_DATA(0x20000),
+
+
+ /**
+ * This step converts non-UV mappings (such as spherical or cylindrical
+ * mapping) to proper texture coordinate channels.<p>
+ *
+ * Most applications will support UV mapping only, so you will probably want
+ * to specify this step in every case. Note that Assimp is not always able
+ * to match the original mapping implementation of the 3D app which produced
+ * a model perfectly. It's always better to let the modelling app compute
+ * the UV channels - 3ds max, Maya, Blender, LightWave, and Modo do this for
+ * example.<p>
+ *
+ * <b>Note:</b> If this step is not requested, you'll need to process the
+ * <tt>MATKEY_MAPPING</tt> material property in order to display all
+ * assets properly.
+ */
+ GEN_UV_COORDS(0x40000),
+
+
+ /**
+ * This step applies per-texture UV transformations and bakes them into
+ * stand-alone vtexture coordinate channels.<p>
+ *
+ * UV transformations are specified per-texture - see the
+ * <tt>MATKEY_UVTRANSFORM</tt> material key for more information. This
+ * step processes all textures with transformed input UV coordinates and
+ * generates a new (pre-transformed) UV channel which replaces the old
+ * channel. Most applications won't support UV transformations, so you will
+ * probably want to specify this step.<p>
+ *
+ * <b>Note:</b> UV transformations are usually implemented in real-time
+ * apps by transforming texture coordinates at vertex shader stage with a
+ * 3x3 (homogenous) transformation matrix.
+ */
+ TRANSFORM_UV_COORDS(0x80000),
+
+
+ /**
+ * This step searches for duplicate meshes and replaces them with references
+ * to the first mesh.<p>
+ *
+ * This step takes a while, so don't use it if speed is a concern. Its main
+ * purpose is to workaround the fact that many export file formats don't
+ * support instanced meshes, so exporters need to duplicate meshes. This
+ * step removes the duplicates again. Please note that Assimp does not
+ * currently support per-node material assignment to meshes, which means
+ * that identical meshes with different materials are currently *not*
+ * joined, although this is planned for future versions.
+ */
+ FIND_INSTANCES(0x100000),
+
+
+ /**
+ * A postprocessing step to reduce the number of meshes.<p>
+ *
+ * This will, in fact, reduce the number of draw calls.<p>
+ *
+ * This is a very effective optimization and is recommended to be used
+ * together with #OptimizeGraph, if possible. The flag is fully
+ * compatible with both {@link #SPLIT_LARGE_MESHES} and
+ * {@link #SORT_BY_PTYPE}.
+ */
+ OPTIMIZE_MESHES(0x200000),
+
+
+ /**
+ * A postprocessing step to optimize the scene hierarchy.<p>
+ *
+ * Nodes without animations, bones, lights or cameras assigned are collapsed
+ * and joined.<p>
+ *
+ * Node names can be lost during this step. If you use special 'tag nodes'
+ * to pass additional information through your content pipeline, use the
+ * <tt>#AI_CONFIG_PP_OG_EXCLUDE_LIST</tt> setting to specify a list of node
+ * names you want to be kept. Nodes matching one of the names in this list
+ * won't be touched or modified.<p>
+ *
+ * Use this flag with caution. Most simple files will be collapsed to a
+ * single node, so complex hierarchies are usually completely lost. This is
+ * not useful for editor environments, but probably a very effective
+ * optimization if you just want to get the model data, convert it to your
+ * own format, and render it as fast as possible.<p>
+ *
+ * This flag is designed to be used with #OptimizeMeshes for best
+ * results.<p>
+ *
+ * <b>Note:</b> 'Crappy' scenes with thousands of extremely small meshes
+ * packed in deeply nested nodes exist for almost all file formats.
+ * {@link #OPTIMIZE_MESHES} in combination with {@link #OPTIMIZE_GRAPH}
+ * usually fixes them all and makes them renderable.
+ */
+ OPTIMIZE_GRAPH(0x400000),
+
+
+ /**
+ * This step flips all UV coordinates along the y-axis and adjusts material
+ * settings and bitangents accordingly.<p>
+ *
+ * <b>Output UV coordinate system:</b><br>
+ * <code><pre>
+ * 0y|0y ---------- 1x|0y
+ * | |
+ * | |
+ * | |
+ * 0x|1y ---------- 1x|1y
+ * </pre></code>
+ * <p>
+ *
+ * You'll probably want to consider this flag if you use Direct3D for
+ * rendering. The {@link #MAKE_LEFT_HANDED} flag supersedes this setting
+ * and bundles all conversions typically required for D3D-based
+ * applications.
+ */
+ FLIP_UVS(0x800000),
+
+
+ /**
+ * This step adjusts the output face winding order to be CW.<p>
+ *
+ * The default face winding order is counter clockwise (CCW).
+ *
+ * <b>Output face order:</b>
+ *
+ * <code><pre>
+ * x2
+ *
+ * x0
+ * x1
+ * </pre></code>
+ */
+ FLIP_WINDING_ORDER(0x1000000),
+
+
+ /**
+ * This step splits meshes with many bones into sub-meshes so that each
+ * sub-mesh has fewer or as many bones as a given limit.<p>
+ */
+ SPLIT_BY_BONE_COUNT(0x2000000),
+
+
+ /**
+ * This step removes bones losslessly or according to some threshold.<p>
+ *
+ * In some cases (i.e. formats that require it) exporters are forced to
+ * assign dummy bone weights to otherwise static meshes assigned to animated
+ * meshes. Full, weight-based skinning is expensive while animating nodes is
+ * extremely cheap, so this step is offered to clean up the data in that
+ * regard.<p>
+ *
+ * Use <tt>#AI_CONFIG_PP_DB_THRESHOLD</tt> to control this. Use
+ * <tt>#AI_CONFIG_PP_DB_ALL_OR_NONE</tt> if you want bones removed if and
+ * only if all bones within the scene qualify for removal.
+ */
+ DEBONE(0x4000000);
+
+
+ /**
+ * Utility method for converting to c/c++ based integer enums from java
+ * enums.<p>
+ *
+ * This method is intended to be used from JNI and my change based on
+ * implementation needs.
+ *
+ * @param set the set to convert
+ * @return an integer based enum value (as defined by assimp)
+ */
+ static long toRawValue(Set<AiPostProcessSteps> set) {
+ long rawValue = 0L;
+
+ for (AiPostProcessSteps step : set) {
+ rawValue |= step.m_rawValue;
+ }
+
+ return rawValue;
+ }
+
+
+ /**
+ * Constructor.
+ *
+ * @param rawValue maps java enum to c/c++ integer enum values
+ */
+ private AiPostProcessSteps(long rawValue) {
+ m_rawValue = rawValue;
+ }
+
+
+ /**
+ * The mapped c/c++ integer enum value.
+ */
+ private final long m_rawValue;
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiPrimitiveType.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiPrimitiveType.java
new file mode 100644
index 0000000..af8aa28
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiPrimitiveType.java
@@ -0,0 +1,113 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+import java.util.Set;
+
+
+/**
+ * Enumerates the types of geometric primitives supported by Assimp.<p>
+ */
+public enum AiPrimitiveType {
+ /**
+ * A point primitive.
+ */
+ POINT(0x1),
+
+
+ /**
+ * A line primitive.
+ */
+ LINE(0x2),
+
+
+ /**
+ * A triangular primitive.
+ */
+ TRIANGLE(0x4),
+
+
+ /**
+ * A higher-level polygon with more than 3 edges.<p>
+ *
+ * A triangle is a polygon, but polygon in this context means
+ * "all polygons that are not triangles". The "Triangulate"-Step is provided
+ * for your convenience, it splits all polygons in triangles (which are much
+ * easier to handle).
+ */
+ POLYGON(0x8);
+
+
+ /**
+ * Utility method for converting from c/c++ based integer enums to java
+ * enums.<p>
+ *
+ * This method is intended to be used from JNI and my change based on
+ * implementation needs.
+ *
+ * @param set the target set to fill
+ * @param rawValue an integer based enum value (as defined by assimp)
+ */
+ static void fromRawValue(Set<AiPrimitiveType> set, int rawValue) {
+
+ for (AiPrimitiveType type : AiPrimitiveType.values()) {
+ if ((type.m_rawValue & rawValue) != 0) {
+ set.add(type);
+ }
+ }
+ }
+
+
+ /**
+ * Constructor.
+ *
+ * @param rawValue maps java enum to c/c++ integer enum values
+ */
+ private AiPrimitiveType(int rawValue) {
+ m_rawValue = rawValue;
+ }
+
+
+ /**
+ * The mapped c/c++ integer enum value.
+ */
+ private final int m_rawValue;
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiProgressHandler.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiProgressHandler.java
new file mode 100644
index 0000000..2987e59
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiProgressHandler.java
@@ -0,0 +1,46 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, 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);
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiQuaternion.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiQuaternion.java
new file mode 100644
index 0000000..a9ca7be
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiQuaternion.java
@@ -0,0 +1,165 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+import java.nio.ByteBuffer;
+
+
+/**
+ * Wrapper for a quaternion.<p>
+ *
+ * The wrapper is writable, i.e., changes performed via the set-methods will
+ * 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.
+ *
+ * @param buffer the buffer to wrap
+ * @param offset offset into buffer
+ */
+ public AiQuaternion(ByteBuffer buffer, int offset) {
+ if (null == buffer) {
+ throw new IllegalArgumentException("buffer may not be null");
+ }
+
+ m_buffer = buffer;
+ m_offset = offset;
+ }
+
+
+ /**
+ * Returns the x value.
+ *
+ * @return the x value
+ */
+ public float getX() {
+ return m_buffer.getFloat(m_offset + 4);
+ }
+
+
+ /**
+ * Returns the y value.
+ *
+ * @return the y value
+ */
+ public float getY() {
+ return m_buffer.getFloat(m_offset + 8);
+ }
+
+
+ /**
+ * Returns the z value.
+ *
+ * @return the z value
+ */
+ public float getZ() {
+ return m_buffer.getFloat(m_offset + 12);
+ }
+
+
+ /**
+ * Returns the w value.
+ *
+ * @return the w value
+ */
+ public float getW() {
+ return m_buffer.getFloat(m_offset);
+ }
+
+
+ /**
+ * Sets the x component.
+ *
+ * @param x the new value
+ */
+ public void setX(float x) {
+ m_buffer.putFloat(m_offset + 4, x);
+ }
+
+
+ /**
+ * Sets the y component.
+ *
+ * @param y the new value
+ */
+ public void setY(float y) {
+ m_buffer.putFloat(m_offset + 8, y);
+ }
+
+
+ /**
+ * Sets the z component.
+ *
+ * @param z the new value
+ */
+ public void setZ(float z) {
+ m_buffer.putFloat(m_offset + 12, z);
+ }
+
+
+ /**
+ * Sets the z component.
+ *
+ * @param w the new value
+ */
+ public void setW(float w) {
+ m_buffer.putFloat(m_offset, w);
+ }
+
+
+ @Override
+ public String toString() {
+ return "[" + getX() + ", " + getY() + ", " + getZ() + ", " +
+ getW() + "]";
+ }
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiScene.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiScene.java
new file mode 100644
index 0000000..b4eed2f
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiScene.java
@@ -0,0 +1,251 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * The root structure of the imported data.<p>
+ *
+ * Everything that was imported from the given file can be accessed from here.
+ * <p>
+ * Jassimp copies all data into "java memory" during import and frees
+ * resources allocated by native code after scene loading is completed. No
+ * special care has to be taken for freeing resources, unreferenced jassimp
+ * objects (including the scene itself) are eligible to garbage collection like
+ * any other java object.
+ */
+public final class AiScene {
+ /**
+ * Constructor.
+ */
+ AiScene() {
+ /* nothing to do */
+ }
+
+
+ /**
+ * Returns the number of meshes contained in the scene.<p>
+ *
+ * This method is provided for completeness reasons. It will return the
+ * same value as <code>getMeshes().size()</code>
+ *
+ * @return the number of meshes
+ */
+ public int getNumMeshes() {
+ return m_meshes.size();
+ }
+
+
+ /**
+ * Returns the meshes contained in the scene.<p>
+ *
+ * If there are no meshes in the scene, an empty collection is returned
+ *
+ * @return the list of meshes
+ */
+ public List<AiMesh> getMeshes() {
+ return m_meshes;
+ }
+
+
+ /**
+ * Returns the number of materials in the scene.<p>
+ *
+ * This method is provided for completeness reasons. It will return the
+ * same value as <code>getMaterials().size()</code>
+ *
+ * @return the number of materials
+ */
+ public int getNumMaterials() {
+ return m_materials.size();
+ }
+
+
+ /**
+ * Returns the list of materials.<p>
+ *
+ * Use the index given in each aiMesh structure to access this
+ * array. If the {@link AiSceneFlag#INCOMPLETE} flag is not set there will
+ * always be at least ONE material.
+ *
+ * @return the list of materials
+ */
+ public List<AiMaterial> getMaterials() {
+ return m_materials;
+ }
+
+
+ /**
+ * Returns the number of animations in the scene.<p>
+ *
+ * This method is provided for completeness reasons. It will return the
+ * same value as <code>getAnimations().size()</code>
+ *
+ * @return the number of materials
+ */
+ public int getNumAnimations() {
+ return m_animations.size();
+ }
+
+
+ /**
+ * Returns the list of animations.
+ *
+ * @return the list of animations
+ */
+ public List<AiAnimation> getAnimations() {
+ return m_animations;
+ }
+
+
+ /**
+ * Returns the number of light sources in the scene.<p>
+ *
+ * This method is provided for completeness reasons. It will return the
+ * same value as <code>getLights().size()</code>
+ *
+ * @return the number of lights
+ */
+ public int getNumLights() {
+ return m_lights.size();
+ }
+
+
+ /**
+ * Returns the list of light sources.<p>
+ *
+ * Light sources are fully optional, the returned list may be empty
+ *
+ * @return a possibly empty list of lights
+ */
+ public List<AiLight> getLights() {
+ return m_lights;
+ }
+
+
+ /**
+ * Returns the number of cameras in the scene.<p>
+ *
+ * This method is provided for completeness reasons. It will return the
+ * same value as <code>getCameras().size()</code>
+ *
+ * @return the number of cameras
+ */
+ public int getNumCameras() {
+ return m_cameras.size();
+ }
+
+
+ /**
+ * Returns the list of cameras.<p>
+ *
+ * Cameras are fully optional, the returned list may be empty
+ *
+ * @return a possibly empty list of cameras
+ */
+ public List<AiCamera> getCameras() {
+ return m_cameras;
+ }
+
+
+ /**
+ * Returns the scene graph root.
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).<p>
+ *
+ * The built-in behavior is to return a {@link AiVector}.
+ *
+ * @param wrapperProvider the wrapper provider (used for type inference)
+ * @return the scene graph root
+ */
+ @SuppressWarnings("unchecked")
+ public <V3, M4, C, N, Q> N getSceneRoot(AiWrapperProvider<V3, M4, C, N, Q>
+ wrapperProvider) {
+
+ return (N) m_sceneRoot;
+ }
+
+
+ @Override
+ public String toString() {
+ return "AiScene (" + m_meshes.size() + " mesh/es)";
+ }
+
+
+ /**
+ * Meshes.
+ */
+ private final List<AiMesh> m_meshes = new ArrayList<AiMesh>();
+
+
+ /**
+ * Materials.
+ */
+ private final List<AiMaterial> m_materials = new ArrayList<AiMaterial>();
+
+
+ /**
+ * Animations.
+ */
+ private final List<AiAnimation> m_animations = new ArrayList<AiAnimation>();
+
+
+ /**
+ * Lights.
+ */
+ private final List<AiLight> m_lights = new ArrayList<AiLight>();
+
+
+ /**
+ * Cameras.
+ */
+ private final List<AiCamera> m_cameras = new ArrayList<AiCamera>();
+
+
+ /**
+ * Scene graph root.
+ */
+ private Object m_sceneRoot;
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiSceneFlag.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiSceneFlag.java
new file mode 100644
index 0000000..772b495
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiSceneFlag.java
@@ -0,0 +1,151 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+import java.util.Set;
+
+
+/**
+ * Status flags for {@link AiScene}s.
+ */
+public enum AiSceneFlag {
+ /**
+ * Specifies that the scene data structure that was imported is not
+ * complete.<p>
+ *
+ * This flag bypasses some internal validations and allows the import
+ * of animation skeletons, material libraries or camera animation paths
+ * using Assimp. Most applications won't support such data.
+ */
+ INCOMPLETE(0x1),
+
+
+ /**
+ * This flag is set by the validation
+ * ({@link AiPostProcessSteps#VALIDATE_DATA_STRUCTURE
+ * VALIDATE_DATA_STRUCTURE})
+ * postprocess-step if the validation is successful.<p>
+ *
+ * In a validated scene you can be sure that any cross references in the
+ * data structure (e.g. vertex indices) are valid.
+ */
+ VALIDATED(0x2),
+
+
+ /**
+ * * This flag is set by the validation
+ * ({@link AiPostProcessSteps#VALIDATE_DATA_STRUCTURE
+ * VALIDATE_DATA_STRUCTURE})
+ * postprocess-step if the validation is successful but some issues have
+ * been found.<p>
+ *
+ * This can for example mean that a texture that does not exist is
+ * referenced by a material or that the bone weights for a vertex don't sum
+ * to 1.0 ... . In most cases you should still be able to use the import.
+ * This flag could be useful for applications which don't capture Assimp's
+ * log output.
+ */
+ VALIDATION_WARNING(0x4),
+
+
+ /**
+ * This flag is currently only set by the
+ * {@link jassimp.AiPostProcessSteps#JOIN_IDENTICAL_VERTICES
+ * JOIN_IDENTICAL_VERTICES}.<p>
+ *
+ * It indicates that the vertices of the output meshes aren't in the
+ * internal verbose format anymore. In the verbose format all vertices are
+ * unique, no vertex is ever referenced by more than one face.
+ */
+ NON_VERBOSE_FORMAT(0x8),
+
+
+ /**
+ * Denotes pure height-map terrain data.<p>
+ *
+ * Pure terrains usually consist of quads, sometimes triangles, in a
+ * regular grid. The x,y coordinates of all vertex positions refer to the
+ * x,y coordinates on the terrain height map, the z-axis stores the
+ * elevation at a specific point.<p>
+ *
+ * TER (Terragen) and HMP (3D Game Studio) are height map formats.
+ * <p>
+ * Assimp is probably not the best choice for loading *huge* terrains -
+ * fully triangulated data takes extremely much free store and should be
+ * avoided as long as possible (typically you'll do the triangulation when
+ * 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.<p>
+ *
+ * This method is intended to be used from JNI and my change based on
+ * implementation needs.
+ *
+ * @param set the target set to fill
+ * @param rawValue an integer based enum value (as defined by assimp)
+ */
+ static void fromRawValue(Set<AiSceneFlag> set, int rawValue) {
+
+ for (AiSceneFlag type : AiSceneFlag.values()) {
+ if ((type.m_rawValue & rawValue) != 0) {
+ set.add(type);
+ }
+ }
+ }
+
+
+ /**
+ * Constructor.
+ *
+ * @param rawValue maps java enum to c/c++ integer enum values
+ */
+ private AiSceneFlag(int rawValue) {
+ m_rawValue = rawValue;
+ }
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiShadingMode.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiShadingMode.java
new file mode 100644
index 0000000..fbf6573
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiShadingMode.java
@@ -0,0 +1,168 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, 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;
+
+
+/**
+ * Defines all shading modes supported by the library.<p>
+ *
+ * The list of shading modes has been taken from Blender.
+ * See Blender documentation for more information. The API does
+ * not distinguish between "specular" and "diffuse" shaders (thus the
+ * specular term for diffuse shading models like Oren-Nayar remains
+ * undefined).<p>
+ * Again, this value is just a hint. Assimp tries to select the shader whose
+ * most common implementation matches the original rendering results of the
+ * 3D modeller which wrote a particular model as closely as possible.
+ */
+public enum AiShadingMode {
+ /**
+ * Flat shading.<p>
+ *
+ * Shading is done on per-face base, diffuse only. Also known as
+ * 'faceted shading'.
+ */
+ FLAT(0x1),
+
+
+ /**
+ * Simple Gouraud shading.
+ */
+ GOURAUD(0x2),
+
+
+ /**
+ * Phong-Shading.
+ */
+ PHONG(0x3),
+
+
+ /**
+ * Phong-Blinn-Shading.
+ */
+ BLINN(0x4),
+
+
+ /**
+ * Toon-Shading per pixel.<p>
+ *
+ * Also known as 'comic' shader.
+ */
+ TOON(0x5),
+
+
+ /**
+ * OrenNayar-Shading per pixel.<p>
+ *
+ * Extension to standard Lambertian shading, taking the roughness of the
+ * material into account
+ */
+ OREN_NAYAR(0x6),
+
+
+ /**
+ * Minnaert-Shading per pixel.<p>
+ *
+ * Extension to standard Lambertian shading, taking the "darkness" of the
+ * material into account
+ */
+ MINNAERT(0x7),
+
+
+ /**
+ * CookTorrance-Shading per pixel.<p>
+ *
+ * Special shader for metallic surfaces.
+ */
+ COOK_TORRANCE(0x8),
+
+
+ /**
+ * No shading at all.<p>
+ *
+ * Constant light influence of 1.0.
+ */
+ NO_SHADING(0x9),
+
+
+ /**
+ * Fresnel shading.
+ */
+ FRESNEL(0xa);
+
+
+ /**
+ * Utility method for converting from c/c++ based integer enums to java
+ * enums.<p>
+ *
+ * This method is intended to be used from JNI and my change based on
+ * implementation needs.
+ *
+ * @param rawValue an integer based enum value (as defined by assimp)
+ * @return the enum value corresponding to rawValue
+ */
+ static AiShadingMode fromRawValue(int rawValue) {
+ for (AiShadingMode type : AiShadingMode.values()) {
+ if (type.m_rawValue == rawValue) {
+ return type;
+ }
+ }
+
+ throw new IllegalArgumentException("unexptected raw value: " +
+ rawValue);
+ }
+
+
+ /**
+ * Constructor.
+ *
+ * @param rawValue maps java enum to c/c++ integer enum values
+ */
+ private AiShadingMode(int rawValue) {
+ m_rawValue = rawValue;
+ }
+
+
+ /**
+ * The mapped c/c++ integer enum value.
+ */
+ private final int m_rawValue;
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiTextureInfo.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiTextureInfo.java
new file mode 100644
index 0000000..5092303
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiTextureInfo.java
@@ -0,0 +1,224 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, 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;
+
+
+/**
+ * Data structure for texture related material properties.
+ */
+public final class AiTextureInfo {
+
+ /**
+ * Constructor.
+ *
+ * @param type type
+ * @param index index
+ * @param file file
+ * @param uvIndex uv index
+ * @param blend blend factor
+ * @param texOp texture operation
+ * @param mmU map mode for u axis
+ * @param mmV map mode for v axis
+ * @param mmW map mode for w axis
+ */
+ AiTextureInfo(AiTextureType type, int index, String file,
+ int uvIndex, float blend, AiTextureOp texOp, AiTextureMapMode mmU,
+ AiTextureMapMode mmV, AiTextureMapMode mmW) {
+
+ m_type = type;
+ m_index = index;
+ m_file = file;
+ m_uvIndex = uvIndex;
+ m_blend = blend;
+ m_textureOp = texOp;
+ m_textureMapModeU = mmU;
+ m_textureMapModeV = mmV;
+ m_textureMapModeW = mmW;
+ }
+
+
+ /**
+ * Specifies the type of the texture (e.g. diffuse, specular, ...).
+ *
+ * @return the type.
+ */
+ public AiTextureType getType() {
+ return m_type;
+ }
+
+
+ /**
+ * Index of the texture in the texture stack.<p>
+ *
+ * Each type maintains a stack of textures, i.e., there may be a diffuse.0,
+ * a diffuse.1, etc
+ *
+ * @return the index
+ */
+ public int getIndex() {
+ return m_index;
+ }
+
+
+ /**
+ * Returns the path to the texture file.
+ *
+ * @return the path
+ */
+ public String getFile() {
+ return m_file;
+ }
+
+
+ /**
+ * Returns the index of the UV coordinate set.
+ *
+ * @return the uv index
+ */
+ public int getUVIndex() {
+ return m_uvIndex;
+ }
+
+
+ /**
+ * Returns the blend factor.
+ *
+ * @return the blend factor
+ */
+ public float getBlend() {
+ return m_blend;
+ }
+
+
+ /**
+ * Returns the texture operation used to combine this texture and the
+ * preceding texture in the stack.
+ *
+ * @return the texture operation
+ */
+ public AiTextureOp getTextureOp() {
+ return m_textureOp;
+ }
+
+
+ /**
+ * Returns the texture map mode for U texture axis.
+ *
+ * @return the texture map mode
+ */
+ public AiTextureMapMode getTextureMapModeU() {
+ return m_textureMapModeU;
+ }
+
+
+ /**
+ * Returns the texture map mode for V texture axis.
+ *
+ * @return the texture map mode
+ */
+ public AiTextureMapMode getTextureMapModeV() {
+ return m_textureMapModeV;
+ }
+
+
+ /**
+ * Returns the texture map mode for W texture axis.
+ *
+ * @return the texture map mode
+ */
+ public AiTextureMapMode getTextureMapModeW() {
+ return m_textureMapModeW;
+ }
+
+
+ /**
+ * Type.
+ */
+ private final AiTextureType m_type;
+
+
+ /**
+ * Index.
+ */
+ private final int m_index;
+
+
+ /**
+ * Path.
+ */
+ private final String m_file;
+
+
+ /**
+ * UV index.
+ */
+ private final int m_uvIndex;
+
+
+ /**
+ * Blend factor.
+ */
+ private final float m_blend;
+
+
+ /**
+ * Texture operation.
+ */
+ private final AiTextureOp m_textureOp;
+
+
+ /**
+ * Map mode U axis.
+ */
+ private final AiTextureMapMode m_textureMapModeU;
+
+
+ /**
+ * Map mode V axis.
+ */
+ private final AiTextureMapMode m_textureMapModeV;
+
+
+ /**
+ * Map mode W axis.
+ */
+ private final AiTextureMapMode m_textureMapModeW;
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiTextureMapMode.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiTextureMapMode.java
new file mode 100644
index 0000000..c08ca10
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiTextureMapMode.java
@@ -0,0 +1,113 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, 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;
+
+
+/**
+ * Defines how UV coordinates outside the [0...1] range are handled.<p>
+ *
+ * Commonly referred to as 'wrapping mode'.
+ */
+public enum AiTextureMapMode {
+ /**
+ * A texture coordinate u|v is translated to u%1|v%1.
+ */
+ WRAP(0x0),
+
+
+ /**
+ * Texture coordinates outside [0...1] are clamped to the nearest
+ * valid value.
+ */
+ CLAMP(0x1),
+
+
+ /**
+ * A texture coordinate u|v becomes u%1|v%1 if (u-(u%1))%2 is zero and
+ * 1-(u%1)|1-(v%1) otherwise.
+ */
+ MIRROR(0x2),
+
+
+ /**
+ * If the texture coordinates for a pixel are outside [0...1] the texture
+ * is not applied to that pixel.
+ */
+ DECAL(0x3);
+
+
+ /**
+ * Utility method for converting from c/c++ based integer enums to java
+ * enums.<p>
+ *
+ * This method is intended to be used from JNI and my change based on
+ * implementation needs.
+ *
+ * @param rawValue an integer based enum value (as defined by assimp)
+ * @return the enum value corresponding to rawValue
+ */
+ static AiTextureMapMode fromRawValue(int rawValue) {
+ for (AiTextureMapMode type : AiTextureMapMode.values()) {
+ if (type.m_rawValue == rawValue) {
+ return type;
+ }
+ }
+
+ throw new IllegalArgumentException("unexptected raw value: " +
+ rawValue);
+ }
+
+
+ /**
+ * Constructor.
+ *
+ * @param rawValue maps java enum to c/c++ integer enum values
+ */
+ private AiTextureMapMode(int rawValue) {
+ m_rawValue = rawValue;
+ }
+
+
+ /**
+ * The mapped c/c++ integer enum value.
+ */
+ private final int m_rawValue;
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiTextureMapping.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiTextureMapping.java
new file mode 100644
index 0000000..48c219d
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiTextureMapping.java
@@ -0,0 +1,78 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, 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;
+
+
+/**
+ * Defines how the mapping coords for a texture are generated.<p>
+ *
+ * Real-time applications typically require full UV coordinates, so the use of
+ * the {@link AiPostProcessSteps#GEN_UV_COORDS} step is highly recommended.
+ * It generates proper UV channels for non-UV mapped objects, as long as an
+ * accurate description how the mapping should look like (e.g spherical) is
+ * given.
+ */
+public enum AiTextureMapping {
+ /**
+ * The mapping coordinates are taken from an UV channel.
+ *
+ * The #AI_MATKEY_UVWSRC key specifies from which UV channel
+ * the texture coordinates are to be taken from (remember,
+ * meshes can have more than one UV channel).
+ */
+// aiTextureMapping_UV = 0x0,
+//
+// /** Spherical mapping */
+// aiTextureMapping_SPHERE = 0x1,
+//
+// /** Cylindrical mapping */
+// aiTextureMapping_CYLINDER = 0x2,
+//
+// /** Cubic mapping */
+// aiTextureMapping_BOX = 0x3,
+//
+// /** Planar mapping */
+// aiTextureMapping_PLANE = 0x4,
+//
+// /** Undefined mapping. Have fun. */
+// aiTextureMapping_OTHER = 0x5,
+
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiTextureOp.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiTextureOp.java
new file mode 100644
index 0000000..df87d96
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiTextureOp.java
@@ -0,0 +1,137 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, 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;
+
+
+/**
+ * Defines how the Nth texture of a specific type is combined with the result
+ * of all previous layers.<p>
+ *
+ * Example (left: key, right: value): <br>
+ * <code><pre>
+ * DiffColor0 - gray
+ * DiffTextureOp0 - aiTextureOpMultiply
+ * DiffTexture0 - tex1.png
+ * DiffTextureOp0 - aiTextureOpAdd
+ * DiffTexture1 - tex2.png
+ * </pre></code>
+ *
+ * Written as equation, the final diffuse term for a specific pixel would be:
+ * <code><pre>
+ * diffFinal = DiffColor0 * sampleTex(DiffTexture0,UV0) +
+ * sampleTex(DiffTexture1,UV0) * diffContrib;
+ * </pre></code>
+ * where 'diffContrib' is the intensity of the incoming light for that pixel.
+ */
+public enum AiTextureOp {
+ /**
+ * <code>T = T1 * T2</code>.
+ */
+ MULTIPLY(0x0),
+
+
+ /**
+ * <code>T = T1 + T2</code>.
+ */
+ ADD(0x1),
+
+
+ /**
+ * <code>T = T1 - T2</code>.
+ */
+ SUBTRACT(0x2),
+
+
+ /**
+ * <code>T = T1 / T2</code>.
+ */
+ DIVIDE(0x3),
+
+
+ /**
+ * <code>T = (T1 + T2) - (T1 * T2)</code> .
+ */
+ SMOOTH_ADD(0x4),
+
+
+ /**
+ * <code>T = T1 + (T2-0.5)</code>.
+ */
+ SIGNED_ADD(0x5);
+
+
+ /**
+ * Utility method for converting from c/c++ based integer enums to java
+ * enums.<p>
+ *
+ * This method is intended to be used from JNI and my change based on
+ * implementation needs.
+ *
+ * @param rawValue an integer based enum value (as defined by assimp)
+ * @return the enum value corresponding to rawValue
+ */
+ static AiTextureOp fromRawValue(int rawValue) {
+ for (AiTextureOp type : AiTextureOp.values()) {
+ if (type.m_rawValue == rawValue) {
+ return type;
+ }
+ }
+
+ throw new IllegalArgumentException("unexptected raw value: " +
+ rawValue);
+ }
+
+
+ /**
+ * Constructor.
+ *
+ * @param rawValue maps java enum to c/c++ integer enum values
+ */
+ private AiTextureOp(int rawValue) {
+ m_rawValue = rawValue;
+ }
+
+
+ /**
+ * The mapped c/c++ integer enum value.
+ */
+ private final int m_rawValue;
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiTextureType.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiTextureType.java
new file mode 100644
index 0000000..9b236ee
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiTextureType.java
@@ -0,0 +1,218 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, 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;
+
+/**
+ * Defines the purpose of a texture.<p>
+ *
+ * This is a very difficult topic. Different 3D packages support different
+ * kinds of textures. For very common texture types, such as bumpmaps, the
+ * rendering results depend on implementation details in the rendering
+ * pipelines of these applications. Assimp loads all texture references from
+ * the model file and tries to determine which of the predefined texture
+ * types below is the best choice to match the original use of the texture
+ * as closely as possible.<p>
+ *
+ * In content pipelines you'll usually define how textures have to be handled,
+ * and the artists working on models have to conform to this specification,
+ * regardless which 3D tool they're using.
+ */
+public enum AiTextureType {
+ /** Dummy value.
+ *
+ * No texture, but the value to be used as 'texture semantic'
+ * (#aiMaterialProperty::mSemantic) for all material properties
+ * *not* related to textures.
+ */
+ NONE(0),
+
+ /** LEGACY API MATERIALS
+ * Legacy refers to materials which
+ * Were originally implemented in the specifications around 2000.
+ * These must never be removed, as most engines support them.
+ */
+
+ /** The texture is combined with the result of the diffuse
+ * lighting equation.
+ */
+ DIFFUSE(1),
+
+ /** The texture is combined with the result of the specular
+ * lighting equation.
+ */
+ SPECULAR(2),
+
+ /** The texture is combined with the result of the ambient
+ * lighting equation.
+ */
+ AMBIENT(3),
+
+ /** The texture is added to the result of the lighting
+ * calculation. It isn't influenced by incoming light.
+ */
+ EMISSIVE(4),
+
+ /** The texture is a height map.
+ *
+ * By convention, higher gray-scale values stand for
+ * higher elevations from the base height.
+ */
+ HEIGHT(5),
+
+ /** The texture is a (tangent space) normal-map.
+ *
+ * Again, there are several conventions for tangent-space
+ * normal maps. Assimp does (intentionally) not
+ * distinguish here.
+ */
+ NORMALS(6),
+
+ /** The texture defines the glossiness of the material.
+ *
+ * The glossiness is in fact the exponent of the specular
+ * (phong) lighting equation. Usually there is a conversion
+ * function defined to map the linear color values in the
+ * texture to a suitable exponent. Have fun.
+ */
+ SHININESS(7),
+
+ /** The texture defines per-pixel opacity.
+ *
+ * Usually 'white' means opaque and 'black' means
+ * 'transparency'. Or quite the opposite. Have fun.
+ */
+ OPACITY(8),
+
+ /** Displacement texture
+ *
+ * The exact purpose and format is application-dependent.
+ * Higher color values stand for higher vertex displacements.
+ */
+ DISPLACEMENT(9),
+
+ /** Lightmap texture (aka Ambient Occlusion)
+ *
+ * Both 'Lightmaps' and dedicated 'ambient occlusion maps' are
+ * covered by this material property. The texture contains a
+ * scaling value for the final color value of a pixel. Its
+ * intensity is not affected by incoming light.
+ */
+ LIGHTMAP(10),
+
+ /** Reflection texture
+ *
+ * Contains the color of a perfect mirror reflection.
+ * Rarely used, almost never for real-time applications.
+ */
+ REFLECTION(11),
+
+ /** PBR Materials
+ * PBR definitions from maya and other modelling packages now use this standard.
+ * This was originally introduced around 2012.
+ * Support for this is in game engines like Godot, Unreal or Unity3D.
+ * Modelling packages which use this are very common now.
+ */
+
+ BASE_COLOR(12),
+ NORMAL_CAMERA(13),
+ EMISSION_COLOR(14),
+ METALNESS(15),
+ DIFFUSE_ROUGHNESS(16),
+ AMBIENT_OCCLUSION(17),
+
+ /** Unknown texture
+ *
+ * A texture reference that does not match any of the definitions
+ * above is considered to be 'unknown'. It is still imported,
+ * but is excluded from any further post-processing.
+ */
+ UNKNOWN(18);
+
+
+ /**
+ * Utility method for converting from c/c++ based integer enums to java
+ * enums.<p>
+ *
+ * This method is intended to be used from JNI and my change based on
+ * implementation needs.
+ *
+ * @param rawValue an integer based enum value (as defined by assimp)
+ * @return the enum value corresponding to rawValue
+ */
+ static AiTextureType fromRawValue(int rawValue) {
+ for (AiTextureType type : AiTextureType.values()) {
+ if (type.m_rawValue == rawValue) {
+ return type;
+ }
+ }
+
+ throw new IllegalArgumentException("unexptected raw value: " +
+ rawValue);
+ }
+
+
+ /**
+ * Utility method for converting from java enums to c/c++ based integer
+ * enums.<p>
+ *
+ * @param type the type to convert, may not be null
+ * @return the rawValue corresponding to type
+ */
+ static int toRawValue(AiTextureType type) {
+ return type.m_rawValue;
+ }
+
+
+ /**
+ * Constructor.
+ *
+ * @param rawValue maps java enum to c/c++ integer enum values
+ */
+ private AiTextureType(int rawValue) {
+ m_rawValue = rawValue;
+ }
+
+
+ /**
+ * The mapped c/c++ integer enum value.
+ */
+ private final int m_rawValue;
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiVector.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiVector.java
new file mode 100644
index 0000000..440be20
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiVector.java
@@ -0,0 +1,195 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+import java.nio.ByteBuffer;
+
+
+/**
+ * Wrapper for 3-dimensional vectors.<p>
+ *
+ * This wrapper is also used to represent 1- and 2-dimensional vectors. In
+ * these cases only the x (or the x and y coordinate) will be used.
+ * Accessing unused components will throw UnsupportedOperationExceptions.<p>
+ *
+ * The wrapper is writable, i.e., changes performed via the set-methods will
+ * modify the underlying mesh.
+ */
+public final class AiVector {
+ /**
+ * Constructor.
+ *
+ * @param buffer the buffer to wrap
+ * @param offset offset into buffer
+ * @param numComponents number vector of components
+ */
+ public AiVector(ByteBuffer buffer, int offset, int numComponents) {
+ if (null == buffer) {
+ throw new IllegalArgumentException("buffer may not be null");
+ }
+
+ m_buffer = buffer;
+ m_offset = offset;
+ m_numComponents = numComponents;
+ }
+
+
+ /**
+ * Returns the x value.
+ *
+ * @return the x value
+ */
+ public float getX() {
+ return m_buffer.getFloat(m_offset);
+ }
+
+
+ /**
+ * Returns the y value.<p>
+ *
+ * May only be called on 2- or 3-dimensional vectors.
+ *
+ * @return the y value
+ */
+ public float getY() {
+ if (m_numComponents <= 1) {
+ throw new UnsupportedOperationException(
+ "vector has only 1 component");
+ }
+
+ return m_buffer.getFloat(m_offset + 4);
+ }
+
+
+ /**
+ * Returns the z value.<p>
+ *
+ * May only be called on 3-dimensional vectors.
+ *
+ * @return the z value
+ */
+ public float getZ() {
+ if (m_numComponents <= 2) {
+ throw new UnsupportedOperationException(
+ "vector has only 2 components");
+ }
+
+ return m_buffer.getFloat(m_offset + 8);
+ }
+
+
+ /**
+ * Sets the x component.
+ *
+ * @param x the new value
+ */
+ public void setX(float x) {
+ m_buffer.putFloat(m_offset, x);
+ }
+
+
+ /**
+ * Sets the y component.<p>
+ *
+ * May only be called on 2- or 3-dimensional vectors.
+ *
+ * @param y the new value
+ */
+ public void setY(float y) {
+ if (m_numComponents <= 1) {
+ throw new UnsupportedOperationException(
+ "vector has only 1 component");
+ }
+
+ m_buffer.putFloat(m_offset + 4, y);
+ }
+
+
+ /**
+ * Sets the z component.<p>
+ *
+ * May only be called on 3-dimensional vectors.
+ *
+ * @param z the new value
+ */
+ public void setZ(float z) {
+ if (m_numComponents <= 2) {
+ throw new UnsupportedOperationException(
+ "vector has only 2 components");
+ }
+
+ m_buffer.putFloat(m_offset + 8, z);
+ }
+
+
+ /**
+ * Returns the number of components in this vector.
+ *
+ * @return the number of components
+ */
+ public int getNumComponents() {
+ return m_numComponents;
+ }
+
+
+ @Override
+ public String toString() {
+ return "[" + getX() + ", " + getY() + ", " + getZ() + "]";
+ }
+
+
+ /**
+ * Wrapped buffer.
+ */
+ private final ByteBuffer m_buffer;
+
+
+ /**
+ * Offset into m_buffer.
+ */
+ private final int m_offset;
+
+
+ /**
+ * Number of components.
+ */
+ private final int m_numComponents;
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/AiWrapperProvider.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiWrapperProvider.java
new file mode 100644
index 0000000..a29f9d1
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/AiWrapperProvider.java
@@ -0,0 +1,149 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+import java.nio.ByteBuffer;
+
+
+/**
+ * Provides wrapper objects for raw data buffers.<p>
+ *
+ * It is likely that applications using Jassimp will already have a scene
+ * graph implementation and/ or the typical math related classes such as
+ * vectors, matrices, etc.<p>
+ *
+ * To ease the integration with existing code, Jassimp can be customized to
+ * represent the scene graph and compound data structures such as vectors and
+ * matrices with user supplied classes.<p>
+ *
+ * All methods returning wrapped objects rely on the AiWrapperProvider to
+ * create individual instances. Custom wrappers can be created by implementing
+ * AiWrapperProvider and registering the implementation via
+ * {@link Jassimp#setWrapperProvider(AiWrapperProvider)} <b>before</b> the
+ * scene is imported.<p>
+ *
+ * The methods returning wrapped types take an AiWrapperProvider instance. This
+ * instance must match the instance set via
+ * {@link Jassimp#setWrapperProvider(AiWrapperProvider)}. The method parameter
+ * is used to infer the type of the returned object. The passed in wrapper
+ * provider is not necessarily used to actually create the wrapped object, as
+ * the object may be cached for performance reasons. <b>It is not possible to
+ * use different AiWrapperProviders throughout the lifetime of an imported
+ * scene.</b>
+ *
+ * @param <V3> the type used to represent vectors
+ * @param <M4> the type used to represent matrices
+ * @param <C> the type used to represent colors
+ * @param <N> the type used to represent scene graph nodes
+ * @param <Q> the type used to represent quaternions
+ */
+public interface AiWrapperProvider<V3, M4, C, N, Q> {
+ /**
+ * Wraps a vector.<p>
+ *
+ * Most vectors are 3-dimensional, i.e., with 3 components. The exception
+ * are texture coordinates, which may be 1- or 2-dimensional. A vector
+ * consists of numComponents floats (x,y,z) starting from offset
+ *
+ * @param buffer the buffer to wrap
+ * @param offset the offset into buffer
+ * @param numComponents the number of components
+ * @return the wrapped vector
+ */
+ V3 wrapVector3f(ByteBuffer buffer, int offset, int numComponents);
+
+
+ /**
+ * Wraps a 4x4 matrix of floats.<p>
+ *
+ * The calling code will allocate a new array for each invocation of this
+ * method. It is safe to store a reference to the passed in array and
+ * use the array to store the matrix data.
+ *
+ * @param data the matrix data in row-major order
+ * @return the wrapped matrix
+ */
+ M4 wrapMatrix4f(float[] data);
+
+
+ /**
+ * Wraps a RGBA color.<p>
+ *
+ * A color consists of 4 float values (r,g,b,a) starting from offset
+ *
+ * @param buffer the buffer to wrap
+ * @param offset the offset into buffer
+ * @return the wrapped color
+ */
+ C wrapColor(ByteBuffer buffer, int offset);
+
+
+ /**
+ * Wraps a scene graph node.<p>
+ *
+ * See {@link AiNode} for a description of the scene graph structure used
+ * by assimp.<p>
+ *
+ * The parent node is either null or an instance returned by this method.
+ * It is therefore safe to cast the passed in parent object to the
+ * implementation specific type
+ *
+ * @param parent the parent node
+ * @param matrix the transformation matrix
+ * @param meshReferences array of mesh references (indexes)
+ * @param name the name of the node
+ * @return the wrapped scene graph node
+ */
+ N wrapSceneNode(Object parent, Object matrix, int[] meshReferences,
+ String name);
+
+
+ /**
+ * Wraps a quaternion.<p>
+ *
+ * A quaternion consists of 4 float values (w,x,y,z) starting from offset
+ *
+ * @param buffer the buffer to wrap
+ * @param offset the offset into buffer
+ * @return the wrapped quaternion
+ */
+ Q wrapQuaternion(ByteBuffer buffer, int offset);
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/JaiDebug.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/JaiDebug.java
new file mode 100644
index 0000000..0ed112a
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/JaiDebug.java
@@ -0,0 +1,209 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+import java.nio.ByteBuffer;
+
+
+/**
+ * Debug/utility methods.
+ */
+public final class JaiDebug {
+
+ /**
+ * Pure static class, no accessible constructor.
+ */
+ private JaiDebug() {
+ /* nothing to do */
+ }
+
+
+ /**
+ * Dumps vertex positions of a mesh to stdout.<p>
+ *
+ * @param mesh the mesh
+ */
+ public static void dumpPositions(AiMesh mesh) {
+ if (!mesh.hasPositions()) {
+ System.out.println("mesh has no vertex positions");
+ return;
+ }
+
+ for (int i = 0; i < mesh.getNumVertices(); i++) {
+ System.out.println("[" +
+ mesh.getPositionX(i) + ", " +
+ mesh.getPositionY(i) + ", " +
+ mesh.getPositionZ(i) + "]"
+ );
+ }
+ }
+
+
+ /**
+ * Dumps faces of a mesh to stdout.<p>
+ *
+ * @param mesh the mesh
+ */
+ public static void dumpFaces(AiMesh mesh) {
+ if (!mesh.hasFaces()) {
+ System.out.println("mesh has no faces");
+ return;
+ }
+
+ for (int face = 0; face < mesh.getNumFaces(); face++) {
+ int faceNumIndices = mesh.getFaceNumIndices(face);
+ System.out.print(faceNumIndices + ": ");
+
+ for (int vertex = 0; vertex < faceNumIndices; vertex++) {
+ int reference = mesh.getFaceVertex(face, vertex);
+
+ System.out.print("[" +
+ mesh.getPositionX(reference) + ", " +
+ mesh.getPositionY(reference) + ", " +
+ mesh.getPositionZ(reference) + "] "
+ );
+ }
+
+ System.out.println();
+ }
+ }
+
+
+ /**
+ * Dumps a vertex color set of a mesh to stdout.<p>
+ *
+ * @param mesh the mesh
+ * @param colorset the color set
+ */
+ public static void dumpColorset(AiMesh mesh, int colorset) {
+ if (!mesh.hasColors(colorset)) {
+ System.out.println("mesh has no vertex color set " + colorset);
+ return;
+ }
+
+ for (int i = 0; i < mesh.getNumVertices(); i++) {
+ System.out.println("[" +
+ mesh.getColorR(i, colorset) + ", " +
+ mesh.getColorG(i, colorset) + ", " +
+ mesh.getColorB(i, colorset) + ", " +
+ mesh.getColorA(i, colorset) + "]"
+ );
+ }
+ }
+
+
+ /**
+ * Dumps a texture coordinate set of a mesh to stdout.
+ *
+ * @param mesh the mesh
+ * @param coords the coordinates
+ */
+ public static void dumpTexCoords(AiMesh mesh, int coords) {
+ if (!mesh.hasTexCoords(coords)) {
+ System.out.println("mesh has no texture coordinate set " + coords);
+ return;
+ }
+
+ for (int i = 0; i < mesh.getNumVertices(); i++) {
+ int numComponents = mesh.getNumUVComponents(coords);
+ System.out.print("[" + mesh.getTexCoordU(i, coords));
+
+ if (numComponents > 1) {
+ System.out.print(", " + mesh.getTexCoordV(i, coords));
+ }
+
+ if (numComponents > 2) {
+ System.out.print(", " + mesh.getTexCoordW(i, coords));
+ }
+
+ System.out.println("]");
+ }
+ }
+
+
+ /**
+ * Dumps a single material property to stdout.
+ *
+ * @param property the property
+ */
+ public static void dumpMaterialProperty(AiMaterial.Property property) {
+ System.out.print(property.getKey() + " " + property.getSemantic() +
+ " " + property.getIndex() + ": ");
+ Object data = property.getData();
+
+ if (data instanceof ByteBuffer) {
+ ByteBuffer buf = (ByteBuffer) data;
+ for (int i = 0; i < buf.capacity(); i++) {
+ System.out.print(Integer.toHexString(buf.get(i) & 0xFF) + " ");
+ }
+
+ System.out.println();
+ }
+ else {
+ System.out.println(data.toString());
+ }
+ }
+
+
+ /**
+ * Dumps all properties of a material to stdout.
+ *
+ * @param material the material
+ */
+ public static void dumpMaterial(AiMaterial material) {
+ for (AiMaterial.Property prop : material.getProperties()) {
+ dumpMaterialProperty(prop);
+ }
+ }
+
+
+ /**
+ * Dumps an animation channel to stdout.
+ *
+ * @param nodeAnim the channel
+ */
+ public static void dumpNodeAnim(AiNodeAnim nodeAnim) {
+ for (int i = 0; i < nodeAnim.getNumPosKeys(); i++) {
+ System.out.println(i + ": " + nodeAnim.getPosKeyTime(i) +
+ " ticks, " + nodeAnim.getPosKeyVector(i, Jassimp.BUILTIN));
+ }
+ }
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/Jassimp.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/Jassimp.java
new file mode 100644
index 0000000..4610fb1
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/Jassimp.java
@@ -0,0 +1,402 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.EnumSet;
+import java.util.Set;
+
+
+
+/**
+ * Entry point to the jassimp library.<p>
+ *
+ * Use {@link #importFile(String, Set)} to load a file.
+ *
+ * <h3>General Notes and Pitfalls</h3>
+ * Due to the loading via JNI, strings (for example as returned by the
+ * <code>getName()</code> methods) are not interned. You should therefore
+ * compare strings the way it should be done, i.e, via <code>equals()</code>.
+ * Pointer comparison will fail.
+ */
+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,
+ AiProgressHandler progressHandler) 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.
+ */
+ public static final AiWrapperProvider<?, ?, ?, ?, ?> BUILTIN =
+ new AiBuiltInWrapperProvider();
+
+
+ /**
+ * Imports a file via assimp without post processing.
+ *
+ * @param filename the file to import
+ * @return the loaded scene
+ * @throws IOException if an error occurs
+ */
+ public static AiScene importFile(String filename) throws IOException {
+
+ return importFile(filename, EnumSet.noneOf(AiPostProcessSteps.class));
+ }
+
+ /**
+ * Imports a file via assimp without post processing.
+ *
+ * @param filename the file to import
+ * @param ioSystem ioSystem to load files, or null for default
+ * @return the loaded scene
+ * @throws IOException if an error occurs
+ */
+ public static AiScene importFile(String filename, AiIOSystem<?> ioSystem)
+ throws IOException {
+
+ return importFile(filename, EnumSet.noneOf(AiPostProcessSteps.class), ioSystem);
+ }
+
+
+ /**
+ * Imports a file via assimp.
+ *
+ * @param filename the file to import
+ * @param postProcessing post processing flags
+ * @return the loaded scene, or null if an error occurred
+ * @throws IOException if an error occurs
+ */
+ public static AiScene importFile(String filename,
+ Set<AiPostProcessSteps> postProcessing)
+ throws IOException {
+ return importFile(filename, postProcessing, null);
+ }
+
+ /**
+ * Imports a file via assimp.
+ *
+ * @param filename the file to import
+ * @param postProcessing post processing flags
+ * @param ioSystem ioSystem to load files, or null for default
+ * @return the loaded scene, or null if an error occurred
+ * @throws IOException if an error occurs
+ */
+ public static AiScene importFile(String filename,
+ Set<AiPostProcessSteps> postProcessing, AiIOSystem<?> ioSystem)
+ throws IOException {
+ 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<AiPostProcessSteps> postProcessing, AiIOSystem<?> ioSystem,
+ AiProgressHandler progressHandler) throws IOException {
+
+ loadLibrary();
+
+ return aiImportFile(filename, AiPostProcessSteps.toRawValue(
+ postProcessing), ioSystem, progressHandler);
+ }
+
+
+ /**
+ * Returns the size of a struct or ptimitive.<p>
+ *
+ * @return the result of sizeof call
+ */
+ public static native int getVKeysize();
+
+ /**
+ * @see #getVKeysize
+ */
+ public static native int getQKeysize();
+
+ /**
+ * @see #getVKeysize
+ */
+ public static native int getV3Dsize();
+
+ /**
+ * @see #getVKeysize
+ */
+ public static native int getfloatsize();
+
+ /**
+ * @see #getVKeysize
+ */
+ public static native int getintsize();
+
+ /**
+ * @see #getVKeysize
+ */
+ public static native int getuintsize();
+
+ /**
+ * @see #getVKeysize
+ */
+ public static native int getdoublesize();
+
+ /**
+ * @see #getVKeysize
+ */
+ public static native int getlongsize();
+
+ /**
+ * Returns a human readable error description.<p>
+ *
+ * This method can be called when one of the import methods fails, i.e.,
+ * throws an exception, to get a human readable error description.
+ *
+ * @return the error string
+ */
+ public static native String getErrorString();
+
+
+ /**
+ * Returns the active wrapper provider.<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).
+ *
+ * @return the active wrapper provider
+ */
+ public static AiWrapperProvider<?, ?, ?, ?, ?> getWrapperProvider() {
+ return s_wrapperProvider;
+ }
+
+
+ /**
+ * Sets a new wrapper provider.<p>
+ *
+ * This method is part of the wrapped API (see {@link AiWrapperProvider}
+ * for details on wrappers).
+ *
+ * @param wrapperProvider the new wrapper provider
+ */
+ public static void setWrapperProvider(AiWrapperProvider<?, ?, ?, ?, ?>
+ wrapperProvider) {
+
+ s_wrapperProvider = wrapperProvider;
+ }
+
+
+ public static void setLibraryLoader(JassimpLibraryLoader libraryLoader) {
+ s_libraryLoader = libraryLoader;
+ }
+
+
+ /**
+ * Helper method for wrapping a matrix.<p>
+ *
+ * Used by JNI, do not modify!
+ *
+ * @param data the matrix data
+ * @return the wrapped matrix
+ */
+ static Object wrapMatrix(float[] data) {
+ return s_wrapperProvider.wrapMatrix4f(data);
+ }
+
+
+ /**
+ * Helper method for wrapping a color (rgb).<p>
+ *
+ * Used by JNI, do not modify!
+ *
+ * @param red red component
+ * @param green green component
+ * @param blue blue component
+ * @return the wrapped color
+ */
+ static Object wrapColor3(float red, float green, float blue) {
+ return wrapColor4(red, green, blue, 1.0f);
+ }
+
+
+ /**
+ * Helper method for wrapping a color (rgba).<p>
+ *
+ * Used by JNI, do not modify!
+ *
+ * @param red red component
+ * @param green green component
+ * @param blue blue component
+ * @param alpha alpha component
+ * @return the wrapped color
+ */
+ static Object wrapColor4(float red, float green, float blue, float alpha) {
+ ByteBuffer temp = ByteBuffer.allocate(4 * 4);
+ temp.putFloat(red);
+ temp.putFloat(green);
+ temp.putFloat(blue);
+ temp.putFloat(alpha);
+ temp.flip();
+ return s_wrapperProvider.wrapColor(temp, 0);
+ }
+
+
+ /**
+ * Helper method for wrapping a vector.<p>
+ *
+ * Used by JNI, do not modify!
+ *
+ * @param x x component
+ * @param y y component
+ * @param z z component
+ * @return the wrapped vector
+ */
+ static Object wrapVec3(float x, float y, float z) {
+ ByteBuffer temp = ByteBuffer.allocate(3 * 4);
+ temp.putFloat(x);
+ temp.putFloat(y);
+ temp.putFloat(z);
+ temp.flip();
+ return s_wrapperProvider.wrapVector3f(temp, 0, 3);
+ }
+
+
+ /**
+ * Helper method for wrapping a scene graph node.<p>
+ *
+ * Used by JNI, do not modify!
+ *
+ * @param parent the parent node
+ * @param matrix the transformation matrix
+ * @param meshRefs array of matrix references
+ * @param name the name of the node
+ * @return the wrapped matrix
+ */
+ static Object wrapSceneNode(Object parent, Object matrix, int[] meshRefs,
+ String name) {
+
+ return s_wrapperProvider.wrapSceneNode(parent, matrix, meshRefs, name);
+ }
+
+ /**
+ * Helper method to load the library using the provided JassimpLibraryLoader.<p>
+ *
+ * Synchronized to avoid race conditions.
+ */
+ private static void loadLibrary()
+ {
+ if(!s_libraryLoaded)
+ {
+ synchronized(s_libraryLoadingLock)
+ {
+ if(!s_libraryLoaded)
+ {
+ s_libraryLoader.loadLibrary();
+ NATIVE_AIVEKTORKEY_SIZE = getVKeysize();
+ NATIVE_AIQUATKEY_SIZE = getQKeysize();
+ NATIVE_AIVEKTOR3D_SIZE = getV3Dsize();
+ NATIVE_FLOAT_SIZE = getfloatsize();
+ NATIVE_INT_SIZE = getintsize();
+ NATIVE_UINT_SIZE = getuintsize();
+ NATIVE_DOUBLE_SIZE = getdoublesize();
+ NATIVE_LONG_SIZE = getlongsize();
+
+ s_libraryLoaded = true;
+ }
+ }
+ }
+ }
+
+ /**
+ * Pure static class, no accessible constructor.
+ */
+ private Jassimp() {
+ /* nothing to do */
+ }
+
+ public static int NATIVE_AIVEKTORKEY_SIZE;
+ public static int NATIVE_AIQUATKEY_SIZE;
+ public static int NATIVE_AIVEKTOR3D_SIZE;
+ public static int NATIVE_FLOAT_SIZE;
+ public static int NATIVE_INT_SIZE;
+ public static int NATIVE_UINT_SIZE;
+ public static int NATIVE_DOUBLE_SIZE;
+ public static int NATIVE_LONG_SIZE;
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/JassimpConfig.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/JassimpConfig.java
new file mode 100644
index 0000000..7591f0e
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/JassimpConfig.java
@@ -0,0 +1,66 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, 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;
+
+
+/**
+ * Global configuration values (limits).
+ */
+public final class JassimpConfig {
+ /**
+ * Maximum number of vertex color sets.
+ */
+ public static final int MAX_NUMBER_COLORSETS = 8;
+
+
+ /**
+ * Maximum number of texture coordinate sets.
+ */
+ public static final int MAX_NUMBER_TEXCOORDS = 8;
+
+
+ /**
+ * Pure static class, no accessible constructor.
+ */
+ private JassimpConfig() {
+ /* nothing to do */
+ }
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/JassimpLibraryLoader.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/JassimpLibraryLoader.java
new file mode 100644
index 0000000..d87cc82
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/JassimpLibraryLoader.java
@@ -0,0 +1,65 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+/**
+ * Library loader for the jassimp library.<p>
+ *
+ * The default implementation uses "System.loadLibrary" to
+ * load the jassimp native library. <p>
+ *
+ * Custom implementations should override the loadLibrary()
+ * function.
+ *
+ */
+public class JassimpLibraryLoader
+{
+ /**
+ * Function to load the native jassimp library.
+ *
+ * Called the first time Jassimp.importFile() is
+ * called.
+ */
+ public void loadLibrary()
+ {
+ System.loadLibrary("jassimp");
+ }
+}
diff --git a/libs/assimp/port/jassimp/jassimp/src/jassimp/package-info.java b/libs/assimp/port/jassimp/jassimp/src/jassimp/package-info.java
new file mode 100644
index 0000000..7ec8c88
--- /dev/null
+++ b/libs/assimp/port/jassimp/jassimp/src/jassimp/package-info.java
@@ -0,0 +1,45 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, 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.
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Java binding for the Open Asset Import Library.
+ */
+package jassimp;
diff --git a/libs/assimp/port/swig/DONOTUSEYET b/libs/assimp/port/swig/DONOTUSEYET
new file mode 100644
index 0000000..87c6e06
--- /dev/null
+++ b/libs/assimp/port/swig/DONOTUSEYET
@@ -0,0 +1 @@
+The interface files are by no means complete yet and only work with the not-yet-released D SWIG backend, although adding support for other languages should not be too much of problem via #ifdefs.
diff --git a/libs/assimp/port/swig/assimp.i b/libs/assimp/port/swig/assimp.i
new file mode 100644
index 0000000..58e1546
--- /dev/null
+++ b/libs/assimp/port/swig/assimp.i
@@ -0,0 +1,140 @@
+%module assimp
+
+// SWIG helpers for std::string and std::vector wrapping.
+%include <std_string.i>
+%include <std_vector.i>
+
+// Globally enable enum prefix stripping.
+%dstripprefix;
+
+
+// PACK_STRUCT is a no-op for SWIG – it does not matter for the generated
+// bindings how the underlying C++ code manages its memory.
+#define PACK_STRUCT
+
+
+// Helper macros for wrapping the pointer-and-length arrays used in the
+// Assimp API.
+
+%define ASSIMP_ARRAY(CLASS, TYPE, NAME, LENGTH)
+%newobject CLASS::NAME;
+%extend CLASS {
+ std::vector<TYPE > *NAME() const {
+ std::vector<TYPE > *result = new std::vector<TYPE >;
+ result->reserve(LENGTH);
+
+ for (unsigned int i = 0; i < LENGTH; ++i) {
+ result->push_back($self->NAME[i]);
+ }
+
+ return result;
+ }
+}
+%ignore CLASS::NAME;
+%enddef
+
+%define ASSIMP_POINTER_ARRAY(CLASS, TYPE, NAME, LENGTH)
+%newobject CLASS::NAME;
+%extend CLASS {
+ std::vector<TYPE *> *NAME() const {
+ std::vector<TYPE *> *result = new std::vector<TYPE *>;
+ result->reserve(LENGTH);
+
+ TYPE *currentValue = $self->NAME;
+ TYPE *valueLimit = $self->NAME + LENGTH;
+ while (currentValue < valueLimit) {
+ result->push_back(currentValue);
+ ++currentValue;
+ }
+
+ return result;
+ }
+}
+%ignore CLASS::NAME;
+%enddef
+
+%define ASSIMP_POINTER_ARRAY_ARRAY(CLASS, TYPE, NAME, OUTER_LENGTH, INNER_LENGTH)
+%newobject CLASS::NAME;
+%extend CLASS {
+ std::vector<std::vector<TYPE *> > *NAME() const {
+ std::vector<std::vector<TYPE *> > *result = new std::vector<std::vector<TYPE *> >;
+ result->reserve(OUTER_LENGTH);
+
+ for (unsigned int i = 0; i < OUTER_LENGTH; ++i) {
+ std::vector<TYPE *> currentElements;
+
+ if ($self->NAME[i] != 0) {
+ currentElements.reserve(INNER_LENGTH);
+
+ TYPE *currentValue = $self->NAME[i];
+ TYPE *valueLimit = $self->NAME[i] + INNER_LENGTH;
+ while (currentValue < valueLimit) {
+ currentElements.push_back(currentValue);
+ ++currentValue;
+ }
+ }
+
+ result->push_back(currentElements);
+ }
+
+ return result;
+ }
+}
+%ignore CLASS::NAME;
+%enddef
+
+
+%include "interface/aiDefines.i"
+%include "interface/aiTypes.i"
+%include "interface/assimp.i"
+%include "interface/aiTexture.i"
+%include "interface/aiMatrix4x4.i"
+%include "interface/aiMatrix3x3.i"
+%include "interface/aiVector3D.i"
+%include "interface/aiVector2D.i"
+%include "interface/aiColor4D.i"
+%include "interface/aiLight.i"
+%include "interface/aiCamera.i"
+%include "interface/aiFileIO.i"
+%include "interface/aiAssert.i"
+%include "interface/aiVersion.i"
+%include "interface/aiAnim.i"
+%include "interface/aiMaterial.i"
+%include "interface/aiMesh.i"
+%include "interface/aiPostProcess.i"
+%include "interface/aiConfig.i"
+%include "interface/assimp.i"
+%include "interface/aiQuaternion.i"
+%include "interface/aiScene.i"
+%include "interface/Logger.i"
+%include "interface/DefaultLogger.i"
+%include "interface/NullLogger.i"
+%include "interface/LogStream.i"
+%include "interface/IOStream.i"
+%include "interface/IOSystem.i"
+
+
+// We have to "instantiate" the templates used by the ASSSIMP_*_ARRAY macros
+// here at the end to avoid running into forward reference issues (SWIG would
+// spit out the helper functions before the header includes for the element
+// types otherwise).
+
+%template(UintVector) std::vector<unsigned int>;
+%template(aiAnimationVector) std::vector<aiAnimation *>;
+%template(aiAnimMeshVector) std::vector<aiAnimMesh *>;
+%template(aiBonesVector) std::vector<aiBone *>;
+%template(aiCameraVector) std::vector<aiCamera *>;
+%template(aiColor4DVector) std::vector<aiColor4D *>;
+%template(aiColor4DVectorVector) std::vector<std::vector<aiColor4D *> >;
+%template(aiFaceVector) std::vector<aiFace *>;
+%template(aiLightVector) std::vector<aiLight *>;
+%template(aiMaterialVector) std::vector<aiMaterial *>;
+%template(aiMaterialPropertyVector) std::vector<aiMaterialProperty *>;
+%template(aiMeshAnimVector) std::vector<aiMeshAnim *>;
+%template(aiMeshVector) std::vector<aiMesh *>;
+%template(aiNodeVector) std::vector<aiNode *>;
+%template(aiNodeAnimVector) std::vector<aiNodeAnim *>;
+%template(aiTextureVector) std::vector<aiTexture *>;
+%template(aiVector3DVector) std::vector<aiVector3D *>;
+%template(aiVector3DVectorVector) std::vector<std::vector<aiVector3D *> >;
+%template(aiVertexWeightVector) std::vector<aiVertexWeight *>;
diff --git a/libs/assimp/port/swig/d/build.sh b/libs/assimp/port/swig/d/build.sh
new file mode 100755
index 0000000..0bf6bff
--- /dev/null
+++ b/libs/assimp/port/swig/d/build.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+gcc -shared -fPIC -g3 -I../../../include/ -lassimp -olibassimp_wrap.so assimp_wrap.cxx
diff --git a/libs/assimp/port/swig/d/generate.sh b/libs/assimp/port/swig/d/generate.sh
new file mode 100755
index 0000000..7de66b1
--- /dev/null
+++ b/libs/assimp/port/swig/d/generate.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+rm -rf assimp/
+mkdir assimp
+swig -c++ -d -outcurrentdir -I../../../include -splitproxy -package assimp $@ ../assimp.i
diff --git a/libs/assimp/port/swig/interface/DefaultLogger.i b/libs/assimp/port/swig/interface/DefaultLogger.i
new file mode 100644
index 0000000..600d28e
--- /dev/null
+++ b/libs/assimp/port/swig/interface/DefaultLogger.i
@@ -0,0 +1,5 @@
+%{
+#include "DefaultLogger.h"
+%}
+
+%include "DefaultLogger.h"
diff --git a/libs/assimp/port/swig/interface/IOStream.i b/libs/assimp/port/swig/interface/IOStream.i
new file mode 100644
index 0000000..baca5ef
--- /dev/null
+++ b/libs/assimp/port/swig/interface/IOStream.i
@@ -0,0 +1,5 @@
+%{
+#include "IOStream.h"
+%}
+
+%include "IOStream.h"
diff --git a/libs/assimp/port/swig/interface/IOSystem.i b/libs/assimp/port/swig/interface/IOSystem.i
new file mode 100644
index 0000000..3e3e04a
--- /dev/null
+++ b/libs/assimp/port/swig/interface/IOSystem.i
@@ -0,0 +1,11 @@
+%{
+#include "IOSystem.h"
+%}
+
+// The const char* overload is used instead.
+%ignore Assimp::IOSystem::Exists(const std::string&) const;
+%ignore Assimp::IOSystem::Open(const std::string& pFile);
+%ignore Assimp::IOSystem::Open(const std::string& pFile, const std::string& pMode);
+%ignore Assimp::IOSystem::ComparePaths(const std::string& one, const std::string& second) const;
+
+%include "IOSystem.h"
diff --git a/libs/assimp/port/swig/interface/LogStream.i b/libs/assimp/port/swig/interface/LogStream.i
new file mode 100644
index 0000000..022f8e5
--- /dev/null
+++ b/libs/assimp/port/swig/interface/LogStream.i
@@ -0,0 +1,5 @@
+%{
+#include "LogStream.h"
+%}
+
+%include "LogStream.h"
diff --git a/libs/assimp/port/swig/interface/Logger.i b/libs/assimp/port/swig/interface/Logger.i
new file mode 100644
index 0000000..cadc50b
--- /dev/null
+++ b/libs/assimp/port/swig/interface/Logger.i
@@ -0,0 +1,5 @@
+%{
+#include "Logger.h"
+%}
+
+%include "Logger.h"
diff --git a/libs/assimp/port/swig/interface/NullLogger.i b/libs/assimp/port/swig/interface/NullLogger.i
new file mode 100644
index 0000000..5cf42ed
--- /dev/null
+++ b/libs/assimp/port/swig/interface/NullLogger.i
@@ -0,0 +1,5 @@
+%{
+#include "NullLogger.h"
+%}
+
+%include "NullLogger.h"
diff --git a/libs/assimp/port/swig/interface/aiAnim.i b/libs/assimp/port/swig/interface/aiAnim.i
new file mode 100644
index 0000000..de49700
--- /dev/null
+++ b/libs/assimp/port/swig/interface/aiAnim.i
@@ -0,0 +1,8 @@
+%{
+#include "aiAnim.h"
+%}
+
+ASSIMP_ARRAY(aiAnimation, aiNodeAnim*, mChannels, $self->mNumChannels);
+ASSIMP_ARRAY(aiAnimation, aiMeshAnim*, mMeshChannels, $self->mNumMeshChannels);
+
+%include "aiAnim.h"
diff --git a/libs/assimp/port/swig/interface/aiAssert.i b/libs/assimp/port/swig/interface/aiAssert.i
new file mode 100644
index 0000000..bc8a9b8
--- /dev/null
+++ b/libs/assimp/port/swig/interface/aiAssert.i
@@ -0,0 +1,5 @@
+%{
+#include "aiAssert.h"
+%}
+
+%include "aiAssert.h"
diff --git a/libs/assimp/port/swig/interface/aiCamera.i b/libs/assimp/port/swig/interface/aiCamera.i
new file mode 100644
index 0000000..5c21245
--- /dev/null
+++ b/libs/assimp/port/swig/interface/aiCamera.i
@@ -0,0 +1,5 @@
+%{
+#include "aiCamera.h"
+%}
+
+%include "aiCamera.h"
diff --git a/libs/assimp/port/swig/interface/aiColor4D.i b/libs/assimp/port/swig/interface/aiColor4D.i
new file mode 100644
index 0000000..3c00916
--- /dev/null
+++ b/libs/assimp/port/swig/interface/aiColor4D.i
@@ -0,0 +1,5 @@
+%{
+#include "aiColor4D.h"
+%}
+
+%include "aiColor4D.h"
diff --git a/libs/assimp/port/swig/interface/aiConfig.i b/libs/assimp/port/swig/interface/aiConfig.i
new file mode 100644
index 0000000..110abb3
--- /dev/null
+++ b/libs/assimp/port/swig/interface/aiConfig.i
@@ -0,0 +1,5 @@
+%{
+#include "aiConfig.h"
+%}
+
+%include "aiConfig.h"
diff --git a/libs/assimp/port/swig/interface/aiDefines.i b/libs/assimp/port/swig/interface/aiDefines.i
new file mode 100644
index 0000000..3a61ea6
--- /dev/null
+++ b/libs/assimp/port/swig/interface/aiDefines.i
@@ -0,0 +1,5 @@
+%{
+#include "aiDefines.h"
+%}
+
+%include "aiDefines.h"
diff --git a/libs/assimp/port/swig/interface/aiFileIO.i b/libs/assimp/port/swig/interface/aiFileIO.i
new file mode 100644
index 0000000..5a1e092
--- /dev/null
+++ b/libs/assimp/port/swig/interface/aiFileIO.i
@@ -0,0 +1,5 @@
+%{
+#include "aiFileIO.h"
+%}
+
+%include "aiFileIO.h"
diff --git a/libs/assimp/port/swig/interface/aiLight.i b/libs/assimp/port/swig/interface/aiLight.i
new file mode 100644
index 0000000..fbefde7
--- /dev/null
+++ b/libs/assimp/port/swig/interface/aiLight.i
@@ -0,0 +1,5 @@
+%{
+#include "aiLight.h"
+%}
+
+%include "aiLight.h"
diff --git a/libs/assimp/port/swig/interface/aiMaterial.i b/libs/assimp/port/swig/interface/aiMaterial.i
new file mode 100644
index 0000000..630e6b7
--- /dev/null
+++ b/libs/assimp/port/swig/interface/aiMaterial.i
@@ -0,0 +1,33 @@
+%{
+#include "aiMaterial.h"
+%}
+
+ASSIMP_ARRAY(aiMaterial, aiMaterialProperty*, mProperties, $self->mNumProperties)
+
+%include <typemaps.i>
+%apply enum SWIGTYPE *OUTPUT { aiTextureMapping* mapping };
+%apply unsigned int *OUTPUT { unsigned int* uvindex };
+%apply float *OUTPUT { float* blend };
+%apply enum SWIGTYPE *OUTPUT { aiTextureOp* op };
+%apply unsigned int *OUTPUT { unsigned int* flags };
+
+%include "aiMaterial.h"
+
+%clear unsigned int* flags;
+%clear aiTextureOp* op;
+%clear float *blend;
+%clear unsigned int* uvindex;
+%clear aiTextureMapping* mapping;
+
+
+%apply int &OUTPUT { int &pOut };
+%apply float &OUTPUT { float &pOut };
+
+%template(GetInteger) aiMaterial::Get<int>;
+%template(GetFloat) aiMaterial::Get<float>;
+%template(GetColor4D) aiMaterial::Get<aiColor4D>;
+%template(GetColor3D) aiMaterial::Get<aiColor3D>;
+%template(GetString) aiMaterial::Get<aiString>;
+
+%clear int &pOut;
+%clear float &pOut;
diff --git a/libs/assimp/port/swig/interface/aiMatrix3x3.i b/libs/assimp/port/swig/interface/aiMatrix3x3.i
new file mode 100644
index 0000000..8336d44
--- /dev/null
+++ b/libs/assimp/port/swig/interface/aiMatrix3x3.i
@@ -0,0 +1,5 @@
+%{
+#include "aiMatrix3x3.h"
+%}
+
+%include "aiMatrix3x3.h"
diff --git a/libs/assimp/port/swig/interface/aiMatrix4x4.i b/libs/assimp/port/swig/interface/aiMatrix4x4.i
new file mode 100644
index 0000000..976c56b
--- /dev/null
+++ b/libs/assimp/port/swig/interface/aiMatrix4x4.i
@@ -0,0 +1,5 @@
+%{
+#include "aiMatrix4x4.h"
+%}
+
+%include "aiMatrix4x4.h"
diff --git a/libs/assimp/port/swig/interface/aiMesh.i b/libs/assimp/port/swig/interface/aiMesh.i
new file mode 100644
index 0000000..141366c
--- /dev/null
+++ b/libs/assimp/port/swig/interface/aiMesh.i
@@ -0,0 +1,29 @@
+%{
+#include "aiMesh.h"
+%}
+
+
+ASSIMP_ARRAY(aiFace, unsigned int, mIndices, $self->mNumIndices);
+
+ASSIMP_POINTER_ARRAY(aiBone, aiVertexWeight, mWeights, $self->mNumWeights);
+
+ASSIMP_POINTER_ARRAY(aiAnimMesh, aiVector3D, mVertices, $self->mNumVertices);
+ASSIMP_POINTER_ARRAY(aiAnimMesh, aiVector3D, mNormals, $self->mNumVertices);
+ASSIMP_POINTER_ARRAY(aiAnimMesh, aiVector3D, mTangents, $self->mNumVertices);
+ASSIMP_POINTER_ARRAY(aiAnimMesh, aiVector3D, mBitangents, $self->mNumVertices);
+ASSIMP_POINTER_ARRAY_ARRAY(aiAnimMesh, aiVector3D, mTextureCoords, AI_MAX_NUMBER_OF_TEXTURECOORDS, $self->mNumVertices);
+ASSIMP_POINTER_ARRAY_ARRAY(aiAnimMesh, aiColor4D, mColors, AI_MAX_NUMBER_OF_COLOR_SETS, $self->mNumVertices);
+
+ASSIMP_ARRAY(aiMesh, aiAnimMesh*, mAnimMeshes, $self->mNumAnimMeshes);
+ASSIMP_ARRAY(aiMesh, aiBone*, mBones, $self->mNumBones);
+ASSIMP_ARRAY(aiMesh, unsigned int, mNumUVComponents, AI_MAX_NUMBER_OF_TEXTURECOORDS);
+ASSIMP_POINTER_ARRAY(aiMesh, aiVector3D, mVertices, $self->mNumVertices);
+ASSIMP_POINTER_ARRAY(aiMesh, aiVector3D, mNormals, $self->mNumVertices);
+ASSIMP_POINTER_ARRAY(aiMesh, aiVector3D, mTangents, $self->mNumVertices);
+ASSIMP_POINTER_ARRAY(aiMesh, aiVector3D, mBitangents, $self->mNumVertices);
+ASSIMP_POINTER_ARRAY(aiMesh, aiFace, mFaces, $self->mNumFaces);
+ASSIMP_POINTER_ARRAY_ARRAY(aiMesh, aiVector3D, mTextureCoords, AI_MAX_NUMBER_OF_TEXTURECOORDS, $self->mNumVertices);
+ASSIMP_POINTER_ARRAY_ARRAY(aiMesh, aiColor4D, mColors, AI_MAX_NUMBER_OF_COLOR_SETS, $self->mNumVertices);
+
+
+%include "aiMesh.h"
diff --git a/libs/assimp/port/swig/interface/aiPostProcess.i b/libs/assimp/port/swig/interface/aiPostProcess.i
new file mode 100644
index 0000000..5f64ec5
--- /dev/null
+++ b/libs/assimp/port/swig/interface/aiPostProcess.i
@@ -0,0 +1,7 @@
+%{
+#include "aiPostProcess.h"
+%}
+
+%feature("d:stripprefix", "aiProcess_") aiPostProcessSteps;
+
+%include "aiPostProcess.h"
diff --git a/libs/assimp/port/swig/interface/aiQuaternion.i b/libs/assimp/port/swig/interface/aiQuaternion.i
new file mode 100644
index 0000000..256057a
--- /dev/null
+++ b/libs/assimp/port/swig/interface/aiQuaternion.i
@@ -0,0 +1,5 @@
+%{
+#include "aiQuaternion.h"
+%}
+
+%include "aiQuaternion.h"
diff --git a/libs/assimp/port/swig/interface/aiScene.i b/libs/assimp/port/swig/interface/aiScene.i
new file mode 100644
index 0000000..7278f33
--- /dev/null
+++ b/libs/assimp/port/swig/interface/aiScene.i
@@ -0,0 +1,17 @@
+%{
+#include "aiScene.h"
+%}
+
+
+ASSIMP_ARRAY(aiScene, aiAnimation*, mAnimations, $self->mNumAnimations);
+ASSIMP_ARRAY(aiScene, aiCamera*, mCameras, $self->mNumCameras);
+ASSIMP_ARRAY(aiScene, aiLight*, mLights, $self->mNumLights);
+ASSIMP_ARRAY(aiScene, aiMaterial*, mMaterials, $self->mNumMaterials);
+ASSIMP_ARRAY(aiScene, aiMesh*, mMeshes, $self->mNumMeshes);
+ASSIMP_ARRAY(aiScene, aiTexture*, mTextures, $self->mNumTextures);
+
+ASSIMP_ARRAY(aiNode, aiNode*, mChildren, $self->mNumChildren);
+ASSIMP_ARRAY(aiNode, unsigned int, mMeshes, $self->mNumMeshes);
+
+
+%include "aiScene.h"
diff --git a/libs/assimp/port/swig/interface/aiTexture.i b/libs/assimp/port/swig/interface/aiTexture.i
new file mode 100644
index 0000000..d07d001
--- /dev/null
+++ b/libs/assimp/port/swig/interface/aiTexture.i
@@ -0,0 +1,5 @@
+%{
+#include "aiTexture.h"
+%}
+
+%include "aiTexture.h"
diff --git a/libs/assimp/port/swig/interface/aiTypes.i b/libs/assimp/port/swig/interface/aiTypes.i
new file mode 100644
index 0000000..a086dfd
--- /dev/null
+++ b/libs/assimp/port/swig/interface/aiTypes.i
@@ -0,0 +1,8 @@
+%{
+#include "aiTypes.h"
+%}
+
+// The const char* overload is used instead.
+%ignore aiString::Set(const std::string& pString);
+
+%include "aiTypes.h"
diff --git a/libs/assimp/port/swig/interface/aiVector2D.i b/libs/assimp/port/swig/interface/aiVector2D.i
new file mode 100644
index 0000000..5db15c0
--- /dev/null
+++ b/libs/assimp/port/swig/interface/aiVector2D.i
@@ -0,0 +1,5 @@
+%{
+#include "aiVector2D.h"
+%}
+
+%include "aiVector2D.h"
diff --git a/libs/assimp/port/swig/interface/aiVector3D.i b/libs/assimp/port/swig/interface/aiVector3D.i
new file mode 100644
index 0000000..2c83f60
--- /dev/null
+++ b/libs/assimp/port/swig/interface/aiVector3D.i
@@ -0,0 +1,5 @@
+%{
+#include "aiVector3D.h"
+%}
+
+%include "aiVector3D.h"
diff --git a/libs/assimp/port/swig/interface/aiVersion.i b/libs/assimp/port/swig/interface/aiVersion.i
new file mode 100644
index 0000000..9ddd532
--- /dev/null
+++ b/libs/assimp/port/swig/interface/aiVersion.i
@@ -0,0 +1,5 @@
+%{
+#include "aiVersion.h"
+%}
+
+%include "aiVersion.h"
diff --git a/libs/assimp/port/swig/interface/assimp.i b/libs/assimp/port/swig/interface/assimp.i
new file mode 100644
index 0000000..a1b1404
--- /dev/null
+++ b/libs/assimp/port/swig/interface/assimp.i
@@ -0,0 +1,45 @@
+%{
+#include "assimp.hpp"
+%}
+
+
+namespace Assimp {
+
+// See docs in assimp.hpp.
+%ignore Importer::ReadFile(const std::string& pFile, unsigned int pFlags);
+%ignore Importer::GetExtensionList(std::string& szOut);
+%ignore Importer::IsExtensionSupported(const std::string& szExtension);
+
+// These are only necessary for extending Assimp with custom importers or post
+// processing steps, which would require wrapping the internal BaseImporter and
+// BaseProcess classes.
+%ignore Importer::RegisterLoader(BaseImporter* pImp);
+%ignore Importer::UnregisterLoader(BaseImporter* pImp);
+%ignore Importer::RegisterPPStep(BaseProcess* pImp);
+%ignore Importer::UnregisterPPStep(BaseProcess* pImp);
+%ignore Importer::FindLoader(const char* szExtension);
+
+}
+
+
+// Each aiScene has to keep a reference to the Importer to prevent it from
+// being garbage collected, whose destructor would release the underlying
+// C++ memory the scene is stored in.
+%typemap(dcode) aiScene "package Object m_importer;"
+%typemap(dout)
+ aiScene* GetScene,
+ aiScene* ReadFile,
+ aiScene* ApplyPostProcessing,
+ aiScene* ReadFileFromMemory {
+ void* cPtr = $wcall;
+ $dclassname ret = (cPtr is null) ? null : new $dclassname(cPtr, $owner);$excode
+ ret.m_importer = this;
+ return ret;
+}
+
+%include <typemaps.i>
+%apply bool *OUTPUT { bool *bWasExisting };
+
+%include "assimp.hpp"
+
+%clear bool *bWasExisting;