Browse Source

jassimp initial import

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@1297 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
scholza 13 years ago
parent
commit
9687531b20
39 changed files with 10544 additions and 0 deletions
  1. 52 0
      port/jassimp/README
  2. 45 0
      port/jassimp/build.xml
  3. 1408 0
      port/jassimp/jassimp-native/src/jassimp.cpp
  4. 31 0
      port/jassimp/jassimp-native/src/jassimp.h
  5. 112 0
      port/jassimp/jassimp/src/jassimp/AiAnimBehavior.java
  6. 179 0
      port/jassimp/jassimp/src/jassimp/AiAnimation.java
  7. 117 0
      port/jassimp/jassimp/src/jassimp/AiBlendMode.java
  8. 137 0
      port/jassimp/jassimp/src/jassimp/AiBone.java
  9. 88 0
      port/jassimp/jassimp/src/jassimp/AiBoneWeight.java
  10. 84 0
      port/jassimp/jassimp/src/jassimp/AiBuiltInWrapperProvider.java
  11. 303 0
      port/jassimp/jassimp/src/jassimp/AiCamera.java
  12. 162 0
      port/jassimp/jassimp/src/jassimp/AiColor.java
  13. 15 0
      port/jassimp/jassimp/src/jassimp/AiConfig.java
  14. 663 0
      port/jassimp/jassimp/src/jassimp/AiConfigOptions.java
  15. 387 0
      port/jassimp/jassimp/src/jassimp/AiLight.java
  16. 112 0
      port/jassimp/jassimp/src/jassimp/AiLightType.java
  17. 1202 0
      port/jassimp/jassimp/src/jassimp/AiMaterial.java
  18. 133 0
      port/jassimp/jassimp/src/jassimp/AiMatrix4f.java
  19. 1429 0
      port/jassimp/jassimp/src/jassimp/AiMesh.java
  20. 49 0
      port/jassimp/jassimp/src/jassimp/AiMeshAnim.java
  21. 228 0
      port/jassimp/jassimp/src/jassimp/AiNode.java
  22. 502 0
      port/jassimp/jassimp/src/jassimp/AiNodeAnim.java
  23. 571 0
      port/jassimp/jassimp/src/jassimp/AiPostProcessSteps.java
  24. 113 0
      port/jassimp/jassimp/src/jassimp/AiPrimitiveType.java
  25. 166 0
      port/jassimp/jassimp/src/jassimp/AiQuaternion.java
  26. 251 0
      port/jassimp/jassimp/src/jassimp/AiScene.java
  27. 153 0
      port/jassimp/jassimp/src/jassimp/AiSceneFlag.java
  28. 168 0
      port/jassimp/jassimp/src/jassimp/AiShadingMode.java
  29. 224 0
      port/jassimp/jassimp/src/jassimp/AiTextureInfo.java
  30. 113 0
      port/jassimp/jassimp/src/jassimp/AiTextureMapMode.java
  31. 78 0
      port/jassimp/jassimp/src/jassimp/AiTextureMapping.java
  32. 137 0
      port/jassimp/jassimp/src/jassimp/AiTextureOp.java
  33. 212 0
      port/jassimp/jassimp/src/jassimp/AiTextureType.java
  34. 195 0
      port/jassimp/jassimp/src/jassimp/AiVector.java
  35. 149 0
      port/jassimp/jassimp/src/jassimp/AiWrapperProvider.java
  36. 209 0
      port/jassimp/jassimp/src/jassimp/JaiDebug.java
  37. 256 0
      port/jassimp/jassimp/src/jassimp/Jassimp.java
  38. 66 0
      port/jassimp/jassimp/src/jassimp/JassimpConfig.java
  39. 45 0
      port/jassimp/jassimp/src/jassimp/package-info.java

+ 52 - 0
port/jassimp/README

@@ -0,0 +1,52 @@
+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
+
+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
+* no support for the custom I/O API of assimp
+* some texture related material properties are not exposed via the API but only 
+  accessible by traversing the list of properties. However this limitation is
+  also present in the c-API ...
+
+
+License
+-------
+
+The license for jassimp is the same as the main Assimp license.
+

+ 45 - 0
port/jassimp/build.xml

@@ -0,0 +1,45 @@
+<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" />
+  
+  <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="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>

+ 1408 - 0
port/jassimp/jassimp-native/src/jassimp.cpp

@@ -0,0 +1,1408 @@
+#include "jassimp.h"
+
+#include <assimp/cimport.h>
+#include <assimp/scene.h>
+
+
+#ifdef JNI_LOG
+#define lprintf(...) printf (__VA_ARGS__)
+#else
+#define lprintf
+#endif
+
+
+static bool createInstance(JNIEnv *env, const char* className, jobject& newInstance)
+{
+	jclass clazz = env->FindClass(className);
+
+	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);
+
+	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);
+
+	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);
+
+	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);
+
+	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);
+
+	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);
+
+	if (NULL == clazz)
+	{
+		lprintf("could not find class %s\n", className);
+		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->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);
+
+	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 bool callStaticObject(JNIEnv *env, const char* typeName, const char* methodName, 
+	const char* signature, const jvalue* params, jobject& returnValue)
+{
+	jclass clazz = env->FindClass(typeName);
+
+	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;
+
+	if (!getField(env, jMesh, jBufferName, "Ljava/nio/ByteBuffer;", jBuffer))
+	{
+		return false;
+	}
+
+	if (env->GetDirectBufferCapacity(jBuffer) != size)
+	{
+		lprintf("invalid direct buffer, expected %u, got %u\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;
+
+	if (!getField(env, jMesh, jBufferName, "[Ljava/nio/ByteBuffer;", jBufferArray))
+	{
+		return false;
+	}
+
+	jobject jBuffer = env->GetObjectArrayElement((jobjectArray) jBufferArray, index);
+
+	if (env->GetDirectBufferCapacity(jBuffer) != size)
+	{
+		lprintf("invalid direct buffer, expected %u, got %u\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 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;
+
+		if (!createInstance(env, "jassimp/AiMesh", jMesh)) 
+		{
+			return false;
+		}
+
+		
+		/* add mesh to m_meshes java.util.List */
+		jobject jMeshes = NULL;
+
+		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 (!call(env, jMesh, "jassimp/AiMesh", "setPrimitiveTypes", "(I)V", setTypesParams))
+		{
+			return false;
+		}
+
+
+		if (!setIntField(env, jMesh, "m_materialIndex", cMesh->mMaterialIndex))
+		{
+			return false;
+		}
+
+		if (!setObjectField(env, jMesh, "m_name", "Ljava/lang/String;", env->NewStringUTF(cMesh->mName.C_Str())))
+		{
+			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 (!call(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 (!call(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 (!call(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 (!call(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 (!call(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 (!call(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;
+			if (!createInstance(env, "jassimp/AiBone", jBone)) 
+			{
+				return false;
+			}
+
+			/* add bone to bone list */
+			jobject jBones = NULL;
+
+			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 */
+			if (!setObjectField(env, jBone, "m_name", "Ljava/lang/String;", env->NewStringUTF(cBone->mName.C_Str())))
+			{
+				return false;
+			}
+
+			/* add bone weights */
+			for (unsigned int w = 0; w < cBone->mNumWeights; w++)
+			{
+				jobject jBoneWeight;
+				if (!createInstance(env, "jassimp/AiBoneWeight", jBoneWeight)) 
+				{
+					return false;
+				}
+
+				/* add boneweight to bone list */
+				jobject jBoneWeights = NULL;
+
+				if (!getField(env, jBone, "m_boneWeights", "Ljava/util/List;", jBoneWeights))
+				{
+					return false;
+				}
+
+
+				/* copy offset matrix */
+				jfloatArray jMatrixArr = env->NewFloatArray(16);
+				env->SetFloatArrayRegion(jMatrixArr, 0, 16, (jfloat*) &cBone->mOffsetMatrix);
+
+				jvalue wrapParams[1];
+				wrapParams[0].l = jMatrixArr;
+				jobject jMatrix;
+				
+				if (!callStaticObject(env, "Ljassimp/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 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);
+	env->SetFloatArrayRegion(jMatrixArr, 0, 16, (jfloat*) &cNode->mTransformation);
+
+	jvalue wrapMatParams[1];
+	wrapMatParams[0].l = jMatrixArr;
+	jobject jMatrix;
+				
+	if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapMatrix", "([F)Ljava/lang/Object;", wrapMatParams, jMatrix)) 
+	{
+		return false;
+	}
+
+
+	/* create mesh references array */
+	jintArray jMeshrefArr = env->NewIntArray(cNode->mNumMeshes);
+	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());
+
+
+	/* 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, "Ljassimp/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)
+	{
+		*loadedNode = jNode;
+	}
+
+	return true;
+}
+
+
+static bool loadSceneGraph(JNIEnv *env, const aiScene* cScene, jobject& jScene)
+{
+	lprintf("converting scene graph ...\n");
+
+	if (NULL != cScene->mRootNode)
+	{
+		jobject 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 ...\n", m);
+
+		jobject jMaterial = NULL;
+
+		if (!createInstance(env, "jassimp/AiMaterial", jMaterial))
+		{
+			return false;
+		}
+
+		/* add material to m_materials java.util.List */
+		jobject jMaterials = NULL;
+
+		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 (!call(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;
+
+			jvalue constructorParams[5];
+			constructorParams[0].l = env->NewStringUTF(cProperty->mKey.C_Str());
+			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;
+
+				/* 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, "Ljassimp/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;
+
+				/* 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, "Ljassimp/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;
+
+				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;
+
+				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);
+
+				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;
+
+				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;
+
+			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;
+		jvalue newAnimParams[3];
+		newAnimParams[0].l = env->NewStringUTF(cAnimation->mName.C_Str());
+		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;
+
+		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;
+			jvalue newNodeAnimParams[6];
+			newNodeAnimParams[0].l = env->NewStringUTF(cNodeAnim->mNodeName.C_Str());
+			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;
+
+			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;
+		if (!callStaticObject(env, "Ljassimp/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;
+		if (!callStaticObject(env, "Ljassimp/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;
+		if (!callStaticObject(env, "Ljassimp/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;
+		if (!callStaticObject(env, "Ljassimp/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;
+		if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapVec3Params, jDirection)) 
+		{
+			return false;
+		}
+
+
+		jobject jLight;
+
+		jvalue params[12];
+		params[0].l = env->NewStringUTF(cLight->mName.C_Str());;
+		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;
+
+		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;
+		if (!callStaticObject(env, "Ljassimp/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;
+		if (!callStaticObject(env, "Ljassimp/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;
+		if (!callStaticObject(env, "Ljassimp/Jassimp;", "wrapVec3", "(FFF)Ljava/lang/Object;", wrapPositionParams, jLookAt)) 
+		{
+			return false;
+		}
+
+
+		jobject jCamera;
+
+		jvalue params[8];
+		params[0].l = env->NewStringUTF(cCamera->mName.C_Str());
+		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;
+
+		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 jstring JNICALL Java_jassimp_Jassimp_getErrorString
+  (JNIEnv *env, jclass jClazz)
+{
+	const char *err = aiGetErrorString();
+
+	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 jScene = NULL; 
+
+	/* convert params */
+	const char* cFilename = env->GetStringUTFChars(jFilename, NULL);
+
+
+	lprintf("opening file: %s\n", cFilename);
+
+	/* do import */
+	const aiScene *cScene = aiImportFile(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)
+	{
+		/* thats really a problem because we cannot throw in this case */
+		env->FatalError("could not throw java.io.IOException");
+	}
+
+	env->ThrowNew(exception, aiGetErrorString());
+
+	lprintf("problem detected\n");
+
+end:
+	/* 
+	 * NOTE: this releases all memory used in the native domain.
+	 * Ensure all data has been passed to java before!
+	 */
+	aiReleaseImport(cScene);
+
+
+	/* free params */
+	env->ReleaseStringUTFChars(jFilename, cFilename);
+
+	lprintf("return from native\n");
+
+	return jScene;
+}

+ 31 - 0
port/jassimp/jassimp-native/src/jassimp.h

@@ -0,0 +1,31 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class jassimp_Jassimp */
+
+#ifndef _Included_jassimp_Jassimp
+#define _Included_jassimp_Jassimp
+#ifdef __cplusplus
+extern "C" {
+#endif
+/* Inaccessible static: BUILTIN */
+/* Inaccessible static: s_wrapperProvider */
+/*
+ * 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);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 112 - 0
port/jassimp/jassimp/src/jassimp/AiAnimBehavior.java

@@ -0,0 +1,112 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+
+/** 
+ * 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;
+}

+ 179 - 0
port/jassimp/jassimp/src/jassimp/AiAnimation.java

@@ -0,0 +1,179 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+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 {
+    /**
+     * 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");
+    }
+    
+    
+    /**
+     * 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>();
+}

+ 117 - 0
port/jassimp/jassimp/src/jassimp/AiBlendMode.java

@@ -0,0 +1,117 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+
+/** 
+ * 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;
+}

+ 137 - 0
port/jassimp/jassimp/src/jassimp/AiBone.java

@@ -0,0 +1,137 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+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 {
+    /**
+     * 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;
+    }
+    
+    
+    /**
+     * 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; 
+}

+ 88 - 0
port/jassimp/jassimp/src/jassimp/AiBoneWeight.java

@@ -0,0 +1,88 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+
+/**
+ * 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;
+}

+ 84 - 0
port/jassimp/jassimp/src/jassimp/AiBuiltInWrapperProvider.java

@@ -0,0 +1,84 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+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);
+    }
+}

+ 303 - 0
port/jassimp/jassimp/src/jassimp/AiCamera.java

@@ -0,0 +1,303 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+
+/** 
+ * 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;
+}

+ 162 - 0
port/jassimp/jassimp/src/jassimp/AiColor.java

@@ -0,0 +1,162 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+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 {
+    /**
+     * 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() + "]";
+    }
+
+
+    /**
+     * Wrapped buffer.
+     */
+    private final ByteBuffer m_buffer;
+    
+    
+    /**
+     * Offset into m_buffer. 
+     */
+    private final int m_offset;
+}

+ 15 - 0
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 {
+
+}

+ 663 - 0
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;
+}

+ 387 - 0
port/jassimp/jassimp/src/jassimp/AiLight.java

@@ -0,0 +1,387 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+
+/**
+ * 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;
+}

+ 112 - 0
port/jassimp/jassimp/src/jassimp/AiLightType.java

@@ -0,0 +1,112 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+
+/**
+ * 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);
+
+    
+    /**
+     * 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;
+}

+ 1202 - 0
port/jassimp/jassimp/src/jassimp/AiMaterial.java

@@ -0,0 +1,1202 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+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 {
+    /**
+     * 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 {
+        /**
+         * 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
+         */
+        Object getData() {
+            return m_data;
+        }
+        
+        
+        /**
+         * Key.
+         */
+        private final String m_key;
+        
+        
+        /**
+         * Semantic.
+         */
+        private final int m_semantic;
+        
+        
+        /**
+         * Index.
+         */
+        private final int m_index;
+        
+        
+        /**
+         * Type.
+         */
+        private final PropertyType m_type;
+        
+        
+        /**
+         * Data.
+         */
+        private final Object m_data;
+    }
+    
+    
+    /**
+     * 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);
+    }
+    
+    
+    /**
+     * 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);
+}

+ 133 - 0
port/jassimp/jassimp/src/jassimp/AiMatrix4f.java

@@ -0,0 +1,133 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+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;
+}

+ 1429 - 0
port/jassimp/jassimp/src/jassimp/AiMesh.java

@@ -0,0 +1,1429 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+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 static final int SIZEOF_FLOAT = 4;
+    
+    
+    /**
+     * Number of bytes per int value.
+     */
+    private static final int SIZEOF_INT = 4;
+    
+    
+    /**
+     * 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 getNumVertives() {
+        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 * getNumVertives()</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 * getNumVertives()</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 * getNumVertives()</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 * getNumVertives()</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 * getNumVertives()</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 * getNumVertives()</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) * getNumVertives()</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");
+        }
+    }
+    // }}
+    
+    
+    /**
+     * 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>();
+}

+ 49 - 0
port/jassimp/jassimp/src/jassimp/AiMeshAnim.java

@@ -0,0 +1,49 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+
+/**
+ * This class is a stub - mesh animations are currently not supported.
+ */
+public class AiMeshAnim {
+
+}

+ 228 - 0
port/jassimp/jassimp/src/jassimp/AiNode.java

@@ -0,0 +1,228 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * 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 {
+    /**
+     * 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;
+    }
+    
+    
+    /**
+     * Adds a child node.
+     * 
+     * @param child the child to add
+     */
+    void addChild(AiNode child) {
+        m_children.add(child);
+    }
+    
+    
+    /**
+     * Name.
+     */
+    private final String m_name;
+    
+    
+    /**
+     * Parent node.
+     */
+    private final AiNode m_parent;
+    
+    
+    /**
+     * Mesh references.
+     */
+    private final int[] m_meshReferences;
+    
+    
+    /**
+     * List of children.
+     */
+    private final List<AiNode> m_children = new ArrayList<AiNode>();
+    
+    
+    /**
+     * Buffer for transformation matrix.
+     */
+    private final Object m_transformationMatrix;
+}

+ 502 - 0
port/jassimp/jassimp/src/jassimp/AiNodeAnim.java

@@ -0,0 +1,502 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+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 (includes padding).
+     */
+    private static final int POS_KEY_SIZE = 24;
+    
+    /**
+     * Size of one rotation key entry.
+     */
+    private static final int ROT_KEY_SIZE = 24;
+    
+    /**
+     * Size of one scaling key entry (includes padding).
+     */
+    private static final int SCALE_KEY_SIZE = 24;
+    
+    
+    /**
+     * 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);
+        
+        /* c data is padded -> 24 bytes with 20 bytes data */
+        m_posKeys = ByteBuffer.allocateDirect(numPosKeys * POS_KEY_SIZE);
+        m_posKeys.order(ByteOrder.nativeOrder());
+        
+        m_rotKeys = ByteBuffer.allocateDirect(numRotKeys * 24);
+        m_rotKeys.order(ByteOrder.nativeOrder());
+        
+        m_scaleKeys = ByteBuffer.allocateDirect(numScaleKeys * 24);
+        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 24 bytes per entry with padding. 
+     * 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 24 bytes per entry with padding. 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;
+}

+ 571 - 0
port/jassimp/jassimp/src/jassimp/AiPostProcessSteps.java

@@ -0,0 +1,571 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+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;
+}

+ 113 - 0
port/jassimp/jassimp/src/jassimp/AiPrimitiveType.java

@@ -0,0 +1,113 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+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;
+}

+ 166 - 0
port/jassimp/jassimp/src/jassimp/AiQuaternion.java

@@ -0,0 +1,166 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+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 {
+    /**
+     * 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() + "]";
+    }
+    
+    
+    /**
+     * Wrapped buffer.
+     */
+    private final ByteBuffer m_buffer;
+    
+    
+    /**
+     * Offset into m_buffer.
+     */
+    private final int m_offset;
+}

+ 251 - 0
port/jassimp/jassimp/src/jassimp/AiScene.java

@@ -0,0 +1,251 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+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;
+}

+ 153 - 0
port/jassimp/jassimp/src/jassimp/AiSceneFlag.java

@@ -0,0 +1,153 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+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);
+    
+    
+    /**
+     * 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;
+    }
+    
+    
+    /**
+     * The mapped c/c++ integer enum value.
+     */
+    private final int m_rawValue;
+}

+ 168 - 0
port/jassimp/jassimp/src/jassimp/AiShadingMode.java

@@ -0,0 +1,168 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+
+/**
+ * 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;
+}

+ 224 - 0
port/jassimp/jassimp/src/jassimp/AiTextureInfo.java

@@ -0,0 +1,224 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+
+/**
+ * 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;
+}

+ 113 - 0
port/jassimp/jassimp/src/jassimp/AiTextureMapMode.java

@@ -0,0 +1,113 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+
+/** 
+ * Defines how UV coordinates outside the [0...1] range are handled.<p>
+ *
+ * Commonly refered 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;
+}

+ 78 - 0
port/jassimp/jassimp/src/jassimp/AiTextureMapping.java

@@ -0,0 +1,78 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+
+/**
+ * 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,
+
+}

+ 137 - 0
port/jassimp/jassimp/src/jassimp/AiTextureOp.java

@@ -0,0 +1,137 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+
+/**
+ * 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;
+}

+ 212 - 0
port/jassimp/jassimp/src/jassimp/AiTextureType.java

@@ -0,0 +1,212 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+/** 
+ * 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 {
+   /** 
+    * 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.<p>
+    *
+    * By convention, higher gray-scale values stand for
+    * higher elevations from the base height.
+    */
+   HEIGHT(0x5),
+
+   
+   /**
+    * The texture is a (tangent space) normal-map.<p>
+    *
+    * Again, there are several conventions for tangent-space
+    * normal maps. Assimp does (intentionally) not distinguish here.
+    */
+   NORMALS(0x6),
+
+   
+   /** 
+    * The texture defines the glossiness of the material.<p>
+    *
+    * 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(0x7),
+
+   
+   /** 
+    * The texture defines per-pixel opacity.<p>
+    *
+    * Usually 'white' means opaque and 'black' means 
+    * 'transparency'. Or quite the opposite. Have fun.
+   */
+   OPACITY(0x8),
+
+   
+   /** 
+    * Displacement texture.<p>
+    *
+    * The exact purpose and format is application-dependent.
+    * Higher color values stand for higher vertex displacements.
+   */
+   DISPLACEMENT(0x9),
+
+   
+   /** 
+    * Lightmap texture (aka Ambient Occlusion).<p>
+    *
+    * 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.<p>
+    *
+    * Contains the color of a perfect mirror reflection.
+    * Rarely used, almost never for real-time applications.
+   */
+   REFLECTION(0xB),
+
+   
+   /** 
+    * Unknown texture.<p>
+    *
+    * 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);
+   
+   
+   /**
+    * 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;
+}

+ 195 - 0
port/jassimp/jassimp/src/jassimp/AiVector.java

@@ -0,0 +1,195 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+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;
+}

+ 149 - 0
port/jassimp/jassimp/src/jassimp/AiWrapperProvider.java

@@ -0,0 +1,149 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+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);
+}

+ 209 - 0
port/jassimp/jassimp/src/jassimp/JaiDebug.java

@@ -0,0 +1,209 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+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.getNumVertives(); 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.getNumVertives(); 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.getNumVertives(); 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));
+        }
+    }
+}

+ 256 - 0
port/jassimp/jassimp/src/jassimp/Jassimp.java

@@ -0,0 +1,256 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+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 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.
+     * 
+     * @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 aiImportFile(filename, AiPostProcessSteps.toRawValue(
+                postProcessing));
+    }
+    
+    
+    /**
+     * 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;
+    }
+    
+    
+    /**
+     * 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);
+    }
+    
+    
+    /**
+     * 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) throws IOException;
+    
+    
+    /**
+     * The active wrapper provider.
+     */
+    private static AiWrapperProvider<?, ?, ?, ?, ?> s_wrapperProvider = 
+            new AiBuiltInWrapperProvider();
+    
+    
+    /**
+     * Pure static class, no accessible constructor.
+     */
+    private Jassimp() {
+        /* nothing to do */
+    }
+    
+    
+    static {
+        System.loadLibrary("jassimp");
+    }
+}

+ 66 - 0
port/jassimp/jassimp/src/jassimp/JassimpConfig.java

@@ -0,0 +1,66 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+package jassimp;
+
+
+/**
+ * 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 */
+    }
+}

+ 45 - 0
port/jassimp/jassimp/src/jassimp/package-info.java

@@ -0,0 +1,45 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library - Java Binding (jassimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Java binding for the Open Asset Import Library.
+ */
+package jassimp;