Quellcode durchsuchen

Added current WIP version of jAssimp

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@83 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
aramis_acg vor 17 Jahren
Ursprung
Commit
e358f6b938
47 geänderte Dateien mit 2784 neuen und 1695 gelöschten Zeilen
  1. 2 8
      port/jAssimp/jni_bridge/BuildHeader.bat
  2. 0 0
      port/jAssimp/jni_bridge/JNIAnimation.cpp
  3. 0 0
      port/jAssimp/jni_bridge/JNIBone.cpp
  4. 0 0
      port/jAssimp/jni_bridge/JNIBoneAnim.cpp
  5. 17 487
      port/jAssimp/jni_bridge/JNICalls.cpp
  6. 51 31
      port/jAssimp/jni_bridge/JNIEnvironment.cpp
  7. 322 7
      port/jAssimp/jni_bridge/JNIEnvironment.h
  8. 0 0
      port/jAssimp/jni_bridge/JNIIOStream.cpp
  9. 0 0
      port/jAssimp/jni_bridge/JNIIOSystem.cpp
  10. 0 0
      port/jAssimp/jni_bridge/JNIMaterial.cpp
  11. 239 0
      port/jAssimp/jni_bridge/JNIMesh.cpp
  12. 46 70
      port/jAssimp/jni_bridge/JNINativeError.cpp
  13. 0 0
      port/jAssimp/jni_bridge/JNINode.cpp
  14. 0 0
      port/jAssimp/jni_bridge/JNIScene.cpp
  15. 0 0
      port/jAssimp/jni_bridge/JNITexture.cpp
  16. 0 13
      port/jAssimp/jni_bridge/assimp_Animation.h
  17. 12 2
      port/jAssimp/jni_bridge/assimp_Importer.h
  18. 13 0
      port/jAssimp/jni_bridge/assimp_Importer_DefaultIOStream.h
  19. 13 0
      port/jAssimp/jni_bridge/assimp_Importer_DefaultIOSystem.h
  20. 13 0
      port/jAssimp/jni_bridge/assimp_Importer_Property.h
  21. 0 13
      port/jAssimp/jni_bridge/assimp_Material.h
  22. 0 133
      port/jAssimp/jni_bridge/assimp_Mesh.h
  23. 0 13
      port/jAssimp/jni_bridge/assimp_Node.h
  24. 0 33
      port/jAssimp/jni_bridge/assimp_PostProcessStep.h
  25. 0 45
      port/jAssimp/jni_bridge/assimp_Scene.h
  26. 0 29
      port/jAssimp/jni_bridge/assimp_Texture.h
  27. 84 0
      port/jAssimp/jni_bridge/res/jAssimp.rc
  28. 62 0
      port/jAssimp/module_assimp.xml
  29. 74 7
      port/jAssimp/src/assimp/Animation.java
  30. 127 5
      port/jAssimp/src/assimp/Bone.java
  31. 149 0
      port/jAssimp/src/assimp/BoneAnim.java
  32. 51 49
      port/jAssimp/src/assimp/CompressedTexture.java
  33. 154 0
      port/jAssimp/src/assimp/ConfigProperty.java
  34. 0 1
      port/jAssimp/src/assimp/IOSystem.java
  35. 142 41
      port/jAssimp/src/assimp/Importer.java
  36. 172 21
      port/jAssimp/src/assimp/Material.java
  37. 149 0
      port/jAssimp/src/assimp/Matrix3x3.java
  38. 179 0
      port/jAssimp/src/assimp/Matrix4x4.java
  39. 102 322
      port/jAssimp/src/assimp/Mesh.java
  40. 3 3
      port/jAssimp/src/assimp/NativeException.java
  41. 44 50
      port/jAssimp/src/assimp/Node.java
  42. 21 72
      port/jAssimp/src/assimp/PostProcessStep.java
  43. 147 0
      port/jAssimp/src/assimp/Quaternion.java
  44. 72 100
      port/jAssimp/src/assimp/Scene.java
  45. 1 1
      port/jAssimp/src/assimp/ShadingMode.java
  46. 41 81
      port/jAssimp/src/assimp/Texture.java
  47. 282 58
      port/jAssimp/src/assimp/test/DumpToFile.java

+ 2 - 8
port/jAssimp/jni_bridge/BuildHeader.bat

@@ -1,8 +1,2 @@
-javah -classpath ".\..\..\port\jAssimp\classes" -d "." "assimp.Importer"
-javah -classpath ".\..\..\port\jAssimp\classes" -d "." "assimp.Material"
-javah -classpath ".\..\..\port\jAssimp\classes" -d "." "assimp.Node"
-javah -classpath ".\..\..\port\jAssimp\classes" -d "." "assimp.Scene"
-javah -classpath ".\..\..\port\jAssimp\classes" -d "." "assimp.Mesh"
-javah -classpath ".\..\..\port\jAssimp\classes" -d "." "assimp.Texture"
-javah -classpath ".\..\..\port\jAssimp\classes" -d "." "assimp.Animation"
-javah -classpath ".\..\..\port\jAssimp\classes" -d "." "assimp.PostProcessStep"
+javah -classpath ".\..\classes" -d "." "assimp.Importer"
+

+ 0 - 0
port/jAssimp/jni_bridge/JNIAnimation.cpp


+ 0 - 0
port/jAssimp/jni_bridge/JNIBone.cpp


+ 0 - 0
port/jAssimp/jni_bridge/JNIBoneAnim.cpp


+ 17 - 487
port/jAssimp/jni_bridge/JNICalls.cpp

@@ -41,15 +41,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 /** @file Implementation of the JNI API for jAssimp */
 
-#if (defined ASSIMP_JNI_EXPORT)
 
 // include the header files generated by javah
 #include "assimp_Importer.h"
-#include "assimp_Animation.h"
-#include "assimp_Node.h"
-#include "assimp_Texture.h"
-#include "assimp_Mesh.h"
-#include "assimp_Material.h"
 
 // include assimp
 #include "../../include/aiTypes.h"
@@ -59,9 +53,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "../../include/aiAssert.h"
 #include "../../include/aiPostProcess.h"
 #include "../../include/assimp.hpp"
-
 #include "../../include/DefaultLogger.h"
 
+// include all jAssimp internal header files
 #include "JNIEnvironment.h"
 #include "JNILogger.h"
 
@@ -165,7 +159,8 @@ JNIEXPORT jlong JNICALL Java_assimp_Importer__1NativeInitContext
 
 	// setup the JNI environment  ...
 	// simply setup the newest JNIEnv*
-	JNIEnvironment::Get()->AttachToCurrentThread(jvmenv);
+	if(!JNIEnvironment::Get()->AttachToCurrentThread(jvmenv))
+		return 0xffffffffffffffffL;
 
 	return context;
 }
@@ -218,10 +213,11 @@ JNIEXPORT jint JNICALL Java_assimp_Importer__1NativeLoad
 	}
 	// get the importer instance from the context
 	Assimp::Importer* pcImp = (Assimp::Importer*)jvmcontext;
+	aiScene* pcOut;
 
 	// and load the file. The aiScene object itself remains accessible
 	// via Importer.GetScene().
-	if(NULL == pcImp->ReadFile(std::string(szPath),(unsigned int)jvmflags))
+	if(!(pcOut = pcImp->ReadFile(std::string(szPath),(unsigned int)jvmflags)))
 	{
 		DefaultLogger::get()->error("[jnibridge] Unable to load asset");
 
@@ -229,492 +225,26 @@ JNIEXPORT jint JNICALL Java_assimp_Importer__1NativeLoad
 		free((void*)szPath);
 		return AI_JNI_ERROR_RETURN;
 	}
+
 	// release the path again
 	free((void*)szPath);
-	return iRet;
-}
-
-// ------------------------------------------------------------------------------------------------
-/*
- * Class:     assimp_PostProcessStep
- * Method:    _NativeSetVertexSplitLimit
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_assimp_PostProcessStep__1NativeSetVertexSplitLimit
-  (JNIEnv *jvmenv, jclass jvmthis, jint jvmlimit)
-{
-	aiSetVertexSplitLimit(jvmlimit);
-}
 
-// ------------------------------------------------------------------------------------------------
-/*
- * Class:     assimp_PostProcessStep
- * Method:    _NativeSetTriangleSplitLimit
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_assimp_PostProcessStep__1NativeSetTriangleSplitLimit
-  (JNIEnv *jvmenv, jclass jvmthis, jint jvmlimit)
-{
-	aiSetTriangleSplitLimit(jvmlimit);
-}
-
-// ------------------------------------------------------------------------------------------------
-/*
- * Class:     assimp_Scene
- * Method:    _NativeGetNumMeshes
- * Signature: (I)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Scene__1NativeGetNumMeshes
-  (JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext)
-{
-	// we need a valid scene for this
-	Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
-	if (!pcImp)return AI_JNI_ERROR_RETURN;
-	return (jint)pcImp->GetScene()->mNumMeshes;
-}
-// ------------------------------------------------------------------------------------------------
-/*
- * Class:     assimp_Scene
- * Method:    _NativeGetNumAnimations
- * Signature: (I)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Scene__1NativeGetNumAnimations
-  (JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext)
-{
-	// we need a valid scene for this
-	Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
-	if (!pcImp)return AI_JNI_ERROR_RETURN;
-	return (jint)pcImp->GetScene()->mNumAnimations;
-}
-// ------------------------------------------------------------------------------------------------
-/*
- * Class:     assimp_Scene
- * Method:    _NativeGetNumTextures
- * Signature: (I)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Scene__1NativeGetNumTextures
-  (JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext)
-{
-	// we need a valid scene for this
-	Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
-	if (!pcImp)return AI_JNI_ERROR_RETURN;
-	return (jint)pcImp->GetScene()->mNumTextures;
-}
-// ------------------------------------------------------------------------------------------------
-/*
- * Class:     assimp_Scene
- * Method:    _NativeGetNumMaterials
- * Signature: (I)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Scene__1NativeGetNumMaterials
-  (JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext)
-{
-	// we need a valid scene for this
-	Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
-	if (!pcImp)return AI_JNI_ERROR_RETURN;
-	return (jint)pcImp->GetScene()->mNumMaterials;
-}
-// ------------------------------------------------------------------------------------------------
-/*
- * Class:     assimp_Mesh
- * Method:    _NativeGetPresenceFlags
- * Signature: (JJ)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeGetPresenceFlags
-  (JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext, jlong jvmindex)
-{
-	// we need a valid scene for this
-	Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
-	if (!pcImp)return AI_JNI_ERROR_RETURN;
-
-	// get the corresponding mesh
-	ai_assert(jvmindex < pcImp->GetScene()->mNumMeshes);
-	aiMesh* pcMesh = pcImp->GetScene()->mMeshes[jvmindex];
+	// allocate a new assimp.Scene object to be returned by the importer
+	jobject jScene;
+	if(!(jScene = jvmenv->AllocObject(AIJ_GET_HANDLE(assimp.Importer.Class))))
+	{
+		DefaultLogger::get()->error("[jnibridge] Unable to allocate output scene");
+		return AI_JNI_ERROR_RETURN;
+	}
 
-	// now build the flag list
-	jint iRet = 0;
-	if (pcMesh->HasPositions())
-		iRet |= assimp_Mesh_PF_POSITION;
-	if (pcMesh->HasBones())
-		iRet |= assimp_Mesh_PF_BONES;
-	if (pcMesh->HasNormals())
-		iRet |= assimp_Mesh_PF_NORMAL;
-	if (pcMesh->HasTangentsAndBitangents())
-		iRet |= assimp_Mesh_PF_TANGENTBITANGENT;
-
-	unsigned int i = 0;
-	while (pcMesh->HasTextureCoords(i))
-		iRet |= assimp_Mesh_PF_UVCOORD << i++;
-	i = 0;
-	while (pcMesh->HasVertexColors(i))
-		iRet |= assimp_Mesh_PF_VERTEXCOLOR << i++;
+	// fill the assimp.Scene instance
+	JNIEnvironment::Get()->assimp.Scene.Fill(jScene,pcOut);
 
+	// and store it in the Importer instance
+	jvmenv->SetObjectField(jvmthis,AIJ_GET_HANDLE(assimp.Importer.scene),jScene);
 	return iRet;
 }
-// ------------------------------------------------------------------------------------------------
-/*
- * Class:     assimp_Mesh
- * Method:    _NativeGetNumVertices
- * Signature: (JJ)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeGetNumVertices
-  (JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext, jlong jvmindex)
-{
-	// we need a valid scene for this
-	Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
-	if (!pcImp)return AI_JNI_ERROR_RETURN;
-
-	// get the corresponding mesh
-	ai_assert(jvmindex < pcImp->GetScene()->mNumMeshes);
-	return pcImp->GetScene()->mMeshes[jvmindex]->mNumVertices;
-}
-// ------------------------------------------------------------------------------------------------
-/*
- * Class:     assimp_Mesh
- * Method:    _NativeGetNumFaces
- * Signature: (JJ)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeGetNumFaces
-  (JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext, jlong jvmindex)
-{
-	// we need a valid scene for this
-	Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
-	if (!pcImp)return AI_JNI_ERROR_RETURN;
-
-	// get the corresponding mesh
-	ai_assert(jvmindex < pcImp->GetScene()->mNumMeshes);
-	return pcImp->GetScene()->mMeshes[jvmindex]->mNumFaces;
-}
-// ------------------------------------------------------------------------------------------------
-/*
- * Class:     assimp_Mesh
- * Method:    _NativeGetNumBones
- * Signature: (JJ)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeGetNumBones
-  (JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext, jlong jvmindex)
-{
-	// we need a valid scene for this
-	Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
-	if (!pcImp)return AI_JNI_ERROR_RETURN;
-
-	// get the corresponding mesh
-	ai_assert(jvmindex < pcImp->GetScene()->mNumMeshes);
-	return pcImp->GetScene()->mMeshes[jvmindex]->mNumBones;
-}
-// ------------------------------------------------------------------------------------------------
-/*
- * Class:     assimp_Mesh
- * Method:    _NativeGetMaterialIndex
- * Signature: (JJ)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeGetMaterialIndex
-  (JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext, jlong jvmindex)
-{
-	// we need a valid scene for this
-	Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
-	if (!pcImp)return AI_JNI_ERROR_RETURN;
-
-	// get the corresponding mesh
-	ai_assert(jvmindex < pcImp->GetScene()->mNumMeshes);
-	return pcImp->GetScene()->mMeshes[jvmindex]->mMaterialIndex;
-}
-// ------------------------------------------------------------------------------------------------
-/*
- * Class:     assimp_Mesh
- * Method:    _NativeGetNumUVComponents
- * Signature: (JJ[I)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeGetNumUVComponents
-  (JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext, jlong jvmindex, jintArray jvmout)
-{
-	ai_assert(AI_MAX_NUMBER_OF_TEXTURECOORDS == jvmenv->GetArrayLength(jvmout) );
-
-	// we need a valid scene for this
-	Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
-	if (!pcImp)return AI_JNI_ERROR_RETURN;
-
-	// get the corresponding mesh
-	ai_assert(jvmindex < pcImp->GetScene()->mNumMeshes);
-	const unsigned int* piArray = pcImp->GetScene()->mMeshes[jvmindex]->mNumUVComponents;
-
-	jint* pArray = jvmenv->GetIntArrayElements(jvmout,NULL);
-	if (NULL == pArray)return AI_JNI_ERROR_RETURN;
-
-	for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
-		pArray[i] = piArray[i];
-
-	jvmenv->ReleaseIntArrayElements(jvmout,pArray,0);
-	return 0;
-}
-// ------------------------------------------------------------------------------------------------
-void CpyVectorToFloatArray(jfloat* pDest, const aiVector3D* pSource, unsigned int iNum)
-{
-	jfloat* pCursor = pDest;
-	const aiVector3D* const pvEnd = pSource + iNum;
-	while (pvEnd != pSource)
-	{
-		*pCursor++ = pSource->x;
-		*pCursor++ = pSource->y;
-		*pCursor++ = pSource->z;
-		++pSource;
-	}
-	return;
-}
-// ------------------------------------------------------------------------------------------------
-/*
- * Class:     assimp_Mesh
- * Method:    _NativeMapVertices
- * Signature: (JJ[F)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapVertices
-  (JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext, jlong jvmindex, jfloatArray jvmout)
-{
-	// we need a valid scene for this
-	Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
-	if (!pcImp)return AI_JNI_ERROR_RETURN;
-
-	// get the corresponding mesh
-	ai_assert(jvmindex < pcImp->GetScene()->mNumMeshes);
-	aiMesh* pcMesh =  (aiMesh*)pcImp->GetScene()->mMeshes[jvmindex];
-	ai_assert(jvmenv->GetArrayLength(jvmout) == pcMesh->mNumVertices * 3);
-	const aiVector3D* pcData = pcMesh->mVertices;
-
-	// now copy the data to the java array
-	jfloat* pArray = jvmenv->GetFloatArrayElements(jvmout,NULL);
-	CpyVectorToFloatArray(pArray,pcData,pcMesh->mNumVertices);
-	jvmenv->ReleaseFloatArrayElements(jvmout,pArray,0);
-
-	// delete the original data
-	delete[] pcMesh->mVertices;
-	pcMesh->mVertices = NULL;
-	return 0;
-}
-// ------------------------------------------------------------------------------------------------
-/*
- * Class:     assimp_Mesh
- * Method:    _NativeMapNormals
- * Signature: (JJ[F)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapNormals
-  (JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext, jlong jvmindex, jfloatArray jvmout)
-{
-	// we need a valid scene for this
-	Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
-	if (!pcImp)return AI_JNI_ERROR_RETURN;
-
-	// get the corresponding mesh
-	ai_assert(jvmindex < pcImp->GetScene()->mNumMeshes);
-	aiMesh* pcMesh =  (aiMesh*)pcImp->GetScene()->mMeshes[jvmindex];
-	ai_assert(jvmenv->GetArrayLength(jvmout) == pcMesh->mNumVertices * 3);
-	const aiVector3D* pcData = pcMesh->mNormals;
-
-	// now copy the data to the java array
-	jfloat* pArray = jvmenv->GetFloatArrayElements(jvmout,NULL);
-	CpyVectorToFloatArray(pArray,pcData,pcMesh->mNumVertices);
-	jvmenv->ReleaseFloatArrayElements(jvmout,pArray,0);
-
-	// delete the original data
-	delete[] pcMesh->mNormals;
-	pcMesh->mNormals = NULL;
-	return 0;
-}
-// ------------------------------------------------------------------------------------------------
-/*
- * Class:     assimp_Mesh
- * Method:    _NativeMapTangents
- * Signature: (JJ[F)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapTangents
-  (JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext, jlong jvmindex, jfloatArray jvmout)
-{
-	// we need a valid scene for this
-	Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
-	if (!pcImp)return AI_JNI_ERROR_RETURN;
-
-	// get the corresponding mesh
-	ai_assert(jvmindex < pcImp->GetScene()->mNumMeshes);
-	aiMesh* pcMesh =  (aiMesh*)pcImp->GetScene()->mMeshes[jvmindex];
-	ai_assert(jvmenv->GetArrayLength(jvmout) == pcMesh->mNumVertices * 3);
-	const aiVector3D* pcData = pcMesh->mTangents;
-
-	// now copy the data to the java array
-	jfloat* pArray = jvmenv->GetFloatArrayElements(jvmout,NULL);
-	CpyVectorToFloatArray(pArray,pcData,pcMesh->mNumVertices);
-	jvmenv->ReleaseFloatArrayElements(jvmout,pArray,0);
-
-	// delete the original data
-	delete[] pcMesh->mNormals;
-	pcMesh->mNormals = NULL;
-	return 0;
-}
-// ------------------------------------------------------------------------------------------------
-/*
- * Class:     assimp_Mesh
- * Method:    _NativeMapBitangents
- * Signature: (JJ[F)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapBitangents
-  (JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext, jlong jvmindex, jfloatArray jvmout)
-{
-	// we need a valid scene for this
-	Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
-	if (!pcImp)return AI_JNI_ERROR_RETURN;
-
-	// get the corresponding mesh
-	ai_assert(jvmindex < pcImp->GetScene()->mNumMeshes);
-	aiMesh* pcMesh =  (aiMesh*)pcImp->GetScene()->mMeshes[jvmindex];
-	ai_assert(jvmenv->GetArrayLength(jvmout) == pcMesh->mNumVertices * 3);
-	const aiVector3D* pcData = pcMesh->mBitangents;
-
-	// now copy the data to the java array
-	jfloat* pArray = jvmenv->GetFloatArrayElements(jvmout,NULL);
-	CpyVectorToFloatArray(pArray,pcData,pcMesh->mNumVertices);
-	jvmenv->ReleaseFloatArrayElements(jvmout,pArray,0);
-
-	// delete the original data
-	delete[] pcMesh->mBitangents;
-	pcMesh->mBitangents = NULL;
-	return 0;
-}
-// ------------------------------------------------------------------------------------------------
-void CpyColorToFloatArray(jfloat* pDest, const aiColor4D* pSource, unsigned int iNum)
-{
-	jfloat* pCursor = pDest;
-	const aiColor4D* const pvEnd = pSource + iNum;
-	while (pvEnd != pSource)
-	{
-		*pCursor++ = pSource->r;
-		*pCursor++ = pSource->g;
-		*pCursor++ = pSource->b;
-		*pCursor++ = pSource->a;
-		++pSource;
-	}
-	return;
-}
-// ------------------------------------------------------------------------------------------------
-void CpyVectorToFloatArray(jfloat* pDest, const aiVector3D* pSource,
-						   unsigned int iNum, unsigned int iNumComponents)
-{
-	jfloat* pCursor = pDest;
-	const aiVector3D* const pvEnd = pSource + iNum;
-	while (pvEnd != pSource)
-	{
-		if (iNumComponents >= 1)*pCursor++ = pSource->x;
-		if (iNumComponents >= 2)*pCursor++ = pSource->y;
-		if (iNumComponents >= 3)*pCursor++ = pSource->z;
-		++pSource;
-	}
-	return;
-}
-// ------------------------------------------------------------------------------------------------
-/*
- * Class:     assimp_Mesh
- * Method:    _NativeMapUVs
- * Signature: (JJI[F)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapUVs
-  (JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext, jlong jvmindex,
-  jint jvmchannel, jfloatArray jvmout)
-{
-	// we need a valid scene for this
-	Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
-	if (!pcImp)return AI_JNI_ERROR_RETURN;
-
-	// get the corresponding mesh
-	ai_assert(jvmindex < pcImp->GetScene()->mNumMeshes);
-	aiMesh* pcMesh =  (aiMesh*)pcImp->GetScene()->mMeshes[jvmindex];
-	ai_assert(jvmenv->GetArrayLength(jvmout) == pcMesh->mNumVertices*pcMesh->mNumUVComponents[jvmchannel]);
-	const aiVector3D* pcData = pcMesh->mTextureCoords[jvmchannel];
-
-	// now copy the data to the java array
-	jfloat* pArray = jvmenv->GetFloatArrayElements(jvmout,NULL);
-	CpyVectorToFloatArray(pArray,pcData,pcMesh->mNumVertices,pcMesh->mNumUVComponents[jvmchannel]);
-	jvmenv->ReleaseFloatArrayElements(jvmout,pArray,0);
-
-	// delete the original data
-	delete[] pcMesh->mTextureCoords[jvmchannel];
-	pcMesh->mTextureCoords[jvmchannel] = NULL;
-	return 0;
-}
-// ------------------------------------------------------------------------------------------------
-/*
- * Class:     assimp_Mesh
- * Method:    _NativeMapColors
- * Signature: (JJI[F)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapColors
-  (JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext, jlong jvmindex, 
-  jint jvmchannel, jfloatArray jvmout)
-{
-	// we need a valid scene for this
-	Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
-	if (!pcImp)return AI_JNI_ERROR_RETURN;
-
-	// get the corresponding mesh
-	ai_assert(jvmindex < pcImp->GetScene()->mNumMeshes);
-	aiMesh* pcMesh =  (aiMesh*)pcImp->GetScene()->mMeshes[jvmindex];
-	ai_assert(jvmenv->GetArrayLength(jvmout) == pcMesh->mNumVertices*4);
-	const aiColor4D* pcData = pcMesh->mColors[jvmchannel];
-
-	// now copy the data to the java array
-	jfloat* pArray = jvmenv->GetFloatArrayElements(jvmout,NULL);
-	CpyColorToFloatArray(pArray,pcData,pcMesh->mNumVertices);
-	jvmenv->ReleaseFloatArrayElements(jvmout,pArray,0);
-
-	// delete the original data
-	delete[] pcMesh->mColors[jvmchannel];
-	pcMesh->mColors[jvmchannel] = NULL;
-	return 0;
-}
-// ------------------------------------------------------------------------------------------------
-void CpyFacesToIntArray(jint* pDest, const aiFace* pSource, unsigned int iNum)
-{
-	// assume that all faces are triangles
-	jint* pCursor = pDest;
-	const aiFace* const pvEnd = pSource + iNum;
-	while (pvEnd != pSource)
-	{
-		*pCursor++ = pSource->mIndices[0];
-		*pCursor++ = pSource->mIndices[1];
-		*pCursor++ = pSource->mIndices[2];
-		++pSource;
-	}
-	return;
-}
-// ------------------------------------------------------------------------------------------------
-/*
- * Class:     assimp_Mesh
- * Method:    _NativeMapFaces
- * Signature: (JJ[I)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapFaces
-  (JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext, jlong jvmindex, jintArray jvmout)
-{
-	// we need a valid scene for this
-	Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
-	if (!pcImp)return AI_JNI_ERROR_RETURN;
-
-	// get the corresponding mesh
-	ai_assert(jvmindex < pcImp->GetScene()->mNumMeshes);
-	aiMesh* pcMesh =  (aiMesh*)pcImp->GetScene()->mMeshes[jvmindex];
-	ai_assert(jvmenv->GetArrayLength(jvmout) == pcMesh->mNumFaces*3);
-	const aiFace* pcData = pcMesh->mFaces;
-
-	// now copy the data to the java array
-	jint* pArray = jvmenv->GetIntArrayElements(jvmout,NULL);
-	CpyFacesToIntArray(pArray,pcData,pcMesh->mNumFaces);
-	jvmenv->ReleaseIntArrayElements(jvmout,pArray,0);
-
-	// delete the original data
-	for (unsigned int i = 0; i < pcMesh->mNumFaces;++i)
-		delete[] pcMesh->mFaces[i].mIndices;
-	delete[] pcMesh->mFaces;
-	pcMesh->mFaces = NULL;
-	return 0;
-}
 
 
 }; //! namespace JNIBridge
 }; //! namespace Assimp
-#endif // !ASSIMP_JNI_EXPORT

+ 51 - 31
port/jAssimp/jni_bridge/JNIEnvironment.cpp

@@ -41,8 +41,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 /** @file Implementation of the JNI API for jAssimp */
 
-#if (defined ASSIMP_JNI_EXPORT)
-
 #include "JNIEnvironment.h"
 #include "JNILogger.h"
 
@@ -51,36 +49,11 @@ using namespace Assimp;
 namespace Assimp	{
 namespace JNIBridge		{
 
-
-/*static*/ jclass JNIEnvironment::Class_java_lang_String = 0;
-/*static*/ jmethodID JNIEnvironment::MID_String_getBytes = 0;
-/*static*/ jmethodID JNIEnvironment::MID_String_init = 0;
-
-
 // ------------------------------------------------------------------------------------------------
 bool JNIEnvironment::AttachToCurrentThread (JNIEnv* pcEnv)
 {
 	ai_assert(NULL != pcEnv);
 
-	// first initialize some members
-	if (0 == Class_java_lang_String)
-	{
-		if( 0 == (Class_java_lang_String = pcEnv->FindClass("java.lang.String")))
-			return false;
-	}
-	if (0 == MID_String_getBytes)
-	{
-		if( 0 == (MID_String_getBytes = pcEnv->GetStaticMethodID(
-			Class_java_lang_String,"getBytes","()[byte")))
-			return false;
-	}
-	if (0 == MID_String_init)
-	{
-		if( 0 == (MID_String_init = pcEnv->GetStaticMethodID(
-			Class_java_lang_String,"String","([byte)V")))
-			return false;
-	}
-	
 	// now initialize the thread-local storage
 	if (NULL == this->ptr.get())
 	{
@@ -97,6 +70,10 @@ bool JNIEnvironment::AttachToCurrentThread (JNIEnv* pcEnv)
 	// attach the logger
 	((JNILogDispatcher*)DefaultLogger::get())->OnAttachToCurrentThread(this->ptr.get());
 
+
+	// get handles to all methods/fields/classes
+	this->Initialize();
+
 	return true;
 }
 // ------------------------------------------------------------------------------------------------
@@ -127,6 +104,33 @@ JNIThreadData* JNIEnvironment::GetThread()
 	return this->ptr.get();
 }
 // ------------------------------------------------------------------------------------------------
+void JNIEnvironment::_java::_lang::_String::Initialize()
+{
+	JNIEnv* pcEnv = JJNIEnvironment::Get()->GetThread()->m_pcEnv;
+
+	// first initialize some members
+	if( !(this->Class = pcEnv->FindClass("java.lang.String")))
+		JNIEnvironment::Get()->ThrowException("Unable to get handle of class java.lang.String");
+	
+	if( !(this->getBytes = pcEnv->GetMethodID(this->Class,"getBytes","()[byte")))
+		JNIEnvironment::Get()->ThrowException("Unable to get handle of class java.lang.String");
+
+	if( !(this->constructor_ByteArray = pcEnv->GetStaticMethodID(
+		this->Class,"<init>","([byte)V")))
+		JNIEnvironment::Get()->ThrowException("Unable to get handle of class java.lang.String");
+}
+// ------------------------------------------------------------------------------------------------
+void JNIEnvironment::_java::_lang::_Array::Initialize()
+{
+	JNIEnv* pcEnv = JJNIEnvironment::Get()->GetThread()->m_pcEnv;
+
+	if( !(this->FloatArray_Class = pcEnv->FindClass("[F")))
+		JNIEnvironment::Get()->ThrowException("Unable to get handle of class float[]");
+
+	if( !(this->IntArray_Class = pcEnv->FindClass("[I")))
+		JNIEnvironment::Get()->ThrowException("Unable to get handle of class int[]");
+}
+// ------------------------------------------------------------------------------------------------
 jstring JNU_NewStringNative(JNIEnv *env, const char *str)
 {
 	jstring result;
@@ -142,8 +146,8 @@ jstring JNU_NewStringNative(JNIEnv *env, const char *str)
 	{
 		env->SetByteArrayRegion(bytes, 0, len,
 			(jbyte *)str);
-		result = (jstring)env->NewObject(JNIEnvironment::Class_java_lang_String,
-			JNIEnvironment::MID_String_init, bytes);
+		result = (jstring)env->NewObject(AIJ_GET_HANDLE(java.lang.String.Class),
+			AIJ_GET_HANDLE(java.lang.String.constructor_ByteArray), bytes);
 		env->DeleteLocalRef(bytes);
 		return result;
 	} /* else fall through */
@@ -160,7 +164,7 @@ char *JNU_GetStringNativeChars(JNIEnv *env, jstring jstr)
 		return 0; /* out of memory error */
 	}
 
-	bytes = (jbyteArray)env->CallObjectMethod(jstr,JNIEnvironment::MID_String_getBytes);
+	bytes = (jbyteArray)env->CallObjectMethod(jstr,AIJ_GET_HANDLE(java.lang.String.getBytes));
 	exc = env->ExceptionOccurred();
 	if (!exc)
 	{
@@ -182,7 +186,23 @@ char *JNU_GetStringNativeChars(JNIEnv *env, jstring jstr)
 	env->DeleteLocalRef(bytes);
 	return result;
 }
+// ------------------------------------------------------------------------------------------------
+JNU_CopyDataToArray(jarray jfl, void* data, unsigned int size)
+{
+	void* pf;
+	jboolean iscopy = FALSE;
+
+	// lock the array and get direct access to its buffer
+	if(!pf = pc->GetPrimitiveArrayCritical(jfl,&iscopy))
+		JNIEnvironment::Get()->ThrowNativeError("Unable to lock array");
+
+	// copy the data to the array
+	::memcpy(pf,data,size);
+
+	// release our reference to the array
+	pc->ReleasePrimitiveArrayCritical(jfl,pf,0);
+}
 
 };};
 
-#endif // ! JNI only
+

+ 322 - 7
port/jAssimp/jni_bridge/JNIEnvironment.h

@@ -48,12 +48,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <vector>
 #include <jni.h>
 
-#include "../../include/aiAssert.h"
+#include "../../../include/aiAssert.h"
+#include "../../../include/aiMesh.h"
+#include "../../../include/aiScene.h"
+
 
 namespace Assimp	{
 namespace JNIBridge		{
 
 
+#define AIJ_GET_HANDLE(__handle__) \
+	(JNIEnvironment::Get()-> __handle__)
+
+#define AIJ_GET_DEFAULT_CTOR_HANDLE (__handle__) \
+	(JNIEnvironment::Get()-> __handle__ . DefaultCtor)
+
+#define AIJ_GET_CLASS_HANDLE (__handle__) \
+	(JNIEnvironment::Get()-> __handle__ . Class)
+
 // ---------------------------------------------------------------------------
 /**	@class	JNIThreadData
  *	@brief	Manages a list of JNI data structures that are
@@ -132,16 +144,310 @@ public:
 	//! Get the thread local data of the current thread
 	JNIThreadData* GetThread();
 
+	//! Throw an NativeEror exception with the specified error message
+	//! The error message is optional.
+	void ThrowNativeError(const char* msg = NULL);
+
 public:
 
-	//! Handle to the java.lang.String class
-	static jclass Class_java_lang_String;
 
-	//! Handle to the java.lang.String.getBytes() class
-	static jmethodID MID_String_getBytes;
 
-	//! Handle to the java.lang.String.String(byte[]) c'tor
-	static jmethodID MID_String_init;
+	struct _java
+	{
+		inline void Initialize()
+		{
+			lang.Initialize();
+		}
+
+		struct _lang
+		{
+			inline void Initialize()
+			{
+				String.Initialize();
+			}
+
+			struct _String
+			{
+				void Initialize();
+
+				//! Handle to the java.lang.String class
+				static jclass Class;
+
+				//! Handle to the java.lang.String.getBytes() class
+				static jmethodID getBytes;
+
+				//! Handle to the java.lang.String.String(byte[]) c'tor
+				static jmethodID constructor_ByteArray;
+
+			} String;
+
+
+			struct _Array
+			{
+				void Initialize();
+
+				jclass FloatArray_Class;
+				jclass IntArray_Class;
+
+			} Array;
+
+		} lang;
+	} java;
+
+
+
+	//! Represents the JNI interface to the package assimp
+	struct _assimp 
+	{
+		//! Initializes the package assimp for use with jAssimp
+		inline void Initialize()
+		{
+			// the NativeError class must be initialized first as it
+			// is used by all other class initializers
+			NativeException.Initialize();
+
+			// now initialize all other classes, the rder doesn't care.
+			Scene.Initialize();
+			Importer.Initialize();
+			Mesh.Initialize();
+			Bone.Initialize();
+			Animation.Initialize();
+			BoneAnim.Initialize();
+			Texture.Initialize();
+			CompressedTexture.Initialize();
+			Matrix3x3.Initialize();
+			Matrix4x4.Initialize();
+			Quaternion.Initialize();
+			Node.Initialize();
+			Material.Initialize();
+		};
+
+		//! Represents the JNI interface to class assimp.NativeException
+		struct _NativeException
+		{
+			void Initialize();
+
+			jclass Class;
+
+		} NativeException;
+
+
+		//! Represents the JNI interface to class assimp.Importer
+		struct _Importer
+		{
+			void Initialize();
+
+			jclass Class;
+
+			jfieldID scene;
+
+		} Importer;
+
+
+		//! Represents the JNI interface to class assimp.Scene
+		struct _Scene
+		{
+			void Initialize();
+
+			jclass Class;
+
+			jmethodID DefaultCtor;
+
+			jfieldID m_vMeshes;
+			jfieldID m_vTextures;
+			jfieldID m_vMaterials;
+			jfieldID m_vAnimations;
+			jfieldID m_rootNode;
+			jfieldID flags;
+
+		} Scene;
+
+
+		//! Represents the JNI interface to class assimp.Mesh
+		struct _Mesh
+		{
+			void Initialize();
+			void Fill(jobject obj,const aiMesh* pcSrc);
+
+			jclass Class;
+
+			jmethodID DefaultCtor;
+
+			jfieldID m_vVertices;
+			jfieldID m_vTangents;
+			jfieldID m_vBitangents;
+			jfieldID m_vNormals;
+			jfieldID m_avUVs;
+			jfieldID m_vFaces;
+			jfieldID m_avColors;
+			jfieldID m_aiNumUVComponents;
+			jfieldID m_vBones;
+			jfieldID m_iMaterialIndex;
+
+		} Mesh;
+
+		//! Represents the JNI interface to class assimp.Bone
+		struct _Bone
+		{
+			void Initialize();
+
+			jclass Class;
+
+			jmethodID DefaultCtor;
+
+			jfieldID name;
+			jfieldID weights;
+
+		} Bone;
+
+		//! Represents the JNI interface to class assimp.Animation
+		struct _Animation
+		{
+			void Initialize();
+
+			jclass Class;
+
+			jmethodID DefaultCtor;
+
+			jfieldID name;
+			jfieldID mDuration;
+			jfieldID mTicksPerSecond;
+			jfieldID boneAnims;
+
+		} Animation;
+
+		//! Represents the JNI interface to class assimp.BoneAnim
+		struct _BoneAnim
+		{
+			void Initialize();
+
+
+			//! Represents the JNI interface to class assimp.BoneAnim.KeyFrame<quak>
+			struct _KeyFrame
+			{
+				jclass Class;
+
+				jmethodID DefaultCtor;
+
+				jfieldID time;
+				jfieldID value;
+
+			} KeyFrame;
+
+			jclass Class;
+
+			jmethodID DefaultCtor;
+
+			jfieldID mName;
+			jfieldID mQuatKeys;
+			jfieldID mPosKeys;
+			jfieldID mScalingKeys;
+
+		} BoneAnim;
+
+		//! Represents the JNI interface to class assimp.Texture
+		struct _Texture
+		{
+			void Initialize();
+
+			jclass Class;
+
+			jmethodID DefaultCtor;
+
+			jfieldID width;
+			jfieldID height;
+			jfieldID data;
+
+		} Texture;
+
+		//! Represents the JNI interface to class assimp.CompressedTexture
+		struct _CompressedTexture
+		{
+			void Initialize();
+
+			jclass Class;
+			jmethodID DefaultCtor;
+			jfieldID m_format;
+
+		} CompressedTexture;
+
+		//! Represents the JNI interface to class assimp.Material
+		struct _Material
+		{
+			void Initialize();
+
+			//! Represents the JNI interface to class assimp.Material.Property
+			struct _Property
+			{
+				jclass Class;
+
+				jfieldID key;
+				jfieldID value;
+
+			} Property;
+
+			jclass Class;
+			jmethodID DefaultCtor;
+			jfieldID properties;
+
+		} Material;
+
+		//! Represents the JNI interface to class assimp.Matrix4x4
+		struct _Matrix4x4
+		{
+			void Initialize();
+
+			jclass Class;
+			jmethodID DefaultCtor;
+			jfieldID coeff;
+
+		} Matrix4x4;
+
+		//! Represents the JNI interface to class assimp.Matrix3x3
+		struct _Matrix3x3
+		{
+			void Initialize();
+
+			jclass Class;
+			jmethodID DefaultCtor;
+			jfieldID coeff;
+
+		} Matrix3x3;
+
+		//! Represents the JNI interface to class assimp.Quaternion
+		struct _Quaternion
+		{
+			void Initialize();
+
+			jclass Class;
+
+			jmethodID DefaultCtor;
+
+			jfieldID x;
+			jfieldID y;
+			jfieldID z;
+			jfieldID w;
+
+		} Quaternion;
+
+		//! Represents the JNI interface to class assimp.Node
+		struct _Node
+		{
+			void Initialize();
+
+			jclass Class;
+
+			jmethodID DefaultCtor;
+
+			jfieldID meshIndices;
+			jfieldID nodeTransform;
+			jfieldID name;
+			jfieldID children;
+			jfieldID parent;
+
+		} Node;
+
+	} assimp;
 
 private:
 
@@ -158,6 +464,15 @@ private:
 };};
 
 
+// ---------------------------------------------------------------------------
+/** @brief Helper function to copy data to a Java array
+ *
+ * @param jfl Java array
+ * @param data Input data
+ * @param size Size of data to be copied, in bytes
+ */
+JNU_CopyDataToArray(jarray jfl, void* data, unsigned int size);
+
 // ---------------------------------------------------------------------------
 /** @brief Helper function to create a java.lang.String from
  *  a native char*.

+ 0 - 0
port/jAssimp/jni_bridge/JNIIOStream.cpp


+ 0 - 0
port/jAssimp/jni_bridge/JNIIOSystem.cpp


+ 0 - 0
port/jAssimp/jni_bridge/JNIMaterial.cpp


+ 239 - 0
port/jAssimp/jni_bridge/JNIMesh.cpp

@@ -0,0 +1,239 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development Team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the ASSIMP team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the ASSIMP Development Team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/** @file Implementation of the JNI API for jAssimp */
+
+#include "JNIEnvironment.h"
+#include "JNILogger.h"
+
+using namespace Assimp;
+
+namespace Assimp	{
+namespace JNIBridge		{
+
+// ------------------------------------------------------------------------------------------------
+void JNIEnvironment::_assimp::_Mesh::Initialize()
+{
+	JNIEnv* pc = JJNIEnvironment::Get()->GetThread()->m_pcEnv;
+
+	// load a handle to the class
+	if(!(this->Class = pc->FindClass("assimp.Mesh")))
+		JNIEnvironment::Get()->ThrowNativeError("Unable to load class assimp.mesh");
+
+	// load all fields of the class
+	this->m_vVertices	= pc->GetFieldID(Class,"m_vVertices","[F");
+	this->m_vNormals	= pc->GetFieldID(Class,"m_vNormals","[F");
+	this->m_vTangents	= pc->GetFieldID(Class,"m_vTangents","[F");
+	this->m_vBitangents = pc->GetFieldID(Class,"m_vBitangents","[F");
+	this->m_avColors	= pc->GetFieldID(Class,"m_avColors","[[F");
+	this->m_avUVs		= pc->GetFieldID(Class,"m_avColors","[[F");
+	this->m_vFaces		= pc->GetFieldID(Class,"m_vFaces","[I");
+	this->m_vBones		= pc->GetFieldID(Class,"m_vBones","[Lassimp.Bone;");
+
+	this->m_aiNumUVComponents	= pc->GetFieldID(Class,"m_aiNumUVComponents","[I");
+	this->m_iMaterialIndex		= pc->GetFieldID(Class,"m_iMaterialIndex","I");
+
+	// check whether all fields have been loaded properly
+	if (!this->m_vVertices		|| !this->m_vNormals	|| !this->m_vTangents ||
+		!this->m_vBitangents	|| !this->m_avColors	|| !this->m_avUVs ||
+		!this->m_vFaces			|| !this->m_vBones		|| !this->m_aiNumUVComponents ||
+		!this->m_iMaterialIndex)
+	{
+		JNIEnvironment::Get()->ThrowNativeError("Unable to load all fields of class assimp.mesh");
+	}
+}
+// ------------------------------------------------------------------------------------------------
+void JNIEnvironment::_assimp::_Mesh::Fill(jobject obj,const aiMesh* pcSrc)
+{
+	JNIEnv* pc = JJNIEnvironment::Get()->GetThread()->m_pcEnv;
+	
+	// set the material index
+	pc->SetIntField(obj,this->m_iMaterialIndex,pcSrc->mMaterialIndex);
+
+
+	// allocate the arrays and fill them
+	float* pf;
+	const unsigned int size = pcSrc->mNumVertices*12;
+	const unsigned int size2 = pcSrc->mNumVertices*3;
+
+	// copy vertex positions
+	if (pcSrc->HasPositions())
+	{
+		// allocate and copy data
+		jfloatArray jfl = pc->NewFloatArray(size2);	
+		JNU_CopyDataToArray(jfl,pcSrc->mVertices,size);
+
+		// set the corresponding field in the java object
+		pc->SetObjectField(obj,this->m_vVertices,jfl);
+	}
+	// copy vertex normals
+	if (pcSrc->HasNormals())
+	{
+		// allocate and copy data
+		jfloatArray jfl = pc->NewFloatArray(size2);	
+		JNU_CopyDataToArray(jfl,pcSrc->mNormals,size);
+
+		// set the corresponding field in the java object
+		pc->SetObjectField(obj,this->m_vNormals,jfl);	
+	}
+	// copy tangents and bitangents
+	if (pcSrc->HasTangentsAndBitangents())
+	{
+		// allocate and copy data
+		jfloatArray jfl = pc->NewFloatArray(size2);	
+		JNU_CopyDataToArray(jfl,pcSrc->mTangents,size);
+
+		// set the corresponding field in the java object
+		pc->SetObjectField(obj,this->m_vTangents,jfl);
+
+		jfl = pc->NewFloatArray(size2);	
+		JNU_CopyDataToArray(jfl,pcSrc->mBitangents,size);
+
+		// set the corresponding field in the java object
+		pc->SetObjectField(obj,this->m_vBitangents,jfl);
+	}
+	// copy texture coordinates
+	if (pcSrc->HasTextureCoords(0))
+	{
+		jobjectArray jobjarr = pc->NewObjectArray(AI_MAX_NUMBER_OF_TEXTURECOORDS,
+			AIJ_GET_HANDLE(java.lang.Array.FloatArray_Class),0);
+
+		unsigned int channel = 0;
+		while (pcSrc->HasTextureCoords(channel))
+		{
+			jfloatArray jfl = pc->NewFloatArray(size2);	
+			JNU_CopyDataToArray(jfl,pcSrc->mTextureCoords[channel],size);
+
+			pc->SetObjectArrayElement(jobjarr,channel,jfl)
+			++channel;
+		}
+
+		// set the corresponding field in the java object
+		pc->SetObjectField(obj,this->m_avUVs,jobjarr);
+
+		jobjarr = (jobjectArray)  pc->NewIntArray(AI_MAX_NUMBER_OF_TEXTURECOORDS);
+		pc->SetIntArrayRegion((jintArray)jobjarr,0,channel,&pcSrc->mNumUVComponents);
+		pc->SetObjectField(obj,this->m_aiNumUVComponents,jobjarr);
+	}
+	// copy vertex colors
+	if (pcSrc->HasVertexColors(0))
+	{
+		const unsigned int size = pcSrc->mNumVertices<<4;
+		const unsigned int size2 = pcSrc->mNumVertices<<2;
+
+		jobjectArray jobjarr = pc->NewObjectArray(AI_MAX_NUMBER_OF_COLOR_SETS,
+			AIJ_GET_HANDLE(java.lang.Array.FloatArray_Class),0);
+
+		unsigned int channel = 0;
+		while (pcSrc->HasVertexColors(channel))
+		{
+			jfloatArray jfl = pc->NewFloatArray(size2);	
+			JNU_CopyDataToArray(jfl,pcSrc->mColors[channel],size);
+
+			pc->SetObjectArrayElement(jobjarr,channel,jfl);
+			++channel;
+		}
+
+		// set the corresponding field in the java object
+		pc->SetObjectField(obj,this->m_avColors,jobjarr);
+	}
+
+
+	// copy faces
+	if (0 < pcSrc->mNumFaces) // just for safety
+	{
+		const unsigned int size = pcSrc->mNumFaces*12;
+		const unsigned int size2 = pcSrc->mNumFaces*3;
+
+		// allocate and copy data
+		jintArray jil = pc->NewIntArray(size2);	
+
+		int* pf;
+		jboolean iscopy = FALSE;
+
+		// lock the array and get direct access to its buffer
+		if(!pf = pc->GetPrimitiveArrayCritical(jil,&iscopy))
+			JNIEnvironment::Get()->ThrowNativeError("Unable to lock face array");
+
+		// copy the data to the array - face by face
+		const aiFace** const pcEnd = pcSrc->mFaces+pcSrc->mNumFaces;
+		for (const aiFace* pcCur = pcSrc->mFaces;pcCur != pcEnd;++pcCur)
+		{
+			ai_assert(3 == pcCur->mNumIndices);
+			*pf++ = pcCur->mIndices[0];
+			*pf++ = pcCur->mIndices[1];
+			*pf++ = pcCur->mIndices[2];
+		}
+
+		// release our reference to the array
+		pc->ReleasePrimitiveArrayCritical(jil,pf,0);
+
+		// set the corresponding field in the java object
+		pc->SetObjectField(obj,this->m_vFaces,jil);
+	}
+
+	// copy bones
+	if (0 < pcSrc->mNumBones)
+	{
+		// allocate the array
+		jobjectArray jarr = pc->NewObjectArray(pcSrc->mNumBones,
+			AIJ_GET_HANDLE(assimp.Bone.Class),0);
+
+		// and fill all members
+		for (unsigned int i = 0; i < pcSrc->mNumBones;++i)
+		{
+			// allocate the array element
+			jobject jobj = pc->NewObject(AIJ_GET_CLASS_HANDLE(assimp.Bone),
+				AIJ_GET_DEFAULT_CTOR_HANDLE(assimp.Bone));
+
+			// fill it from the native data
+			JNIEnvironment::Get()->assimp.Bone.Fill(jobj,pcSrc->mBones[i]);
+
+			// and set the corresponding array entry
+			pc->SetObjectArrayElement(jarr,i,jobj);
+		}
+
+		// set the corresponding field in the java object
+		pc->SetObjectField(obj,this->m_vBones,jil);
+	}
+}
+
+}}

+ 46 - 70
port/jAssimp/src/assimp/Mappable.java → port/jAssimp/jni_bridge/JNINativeError.cpp

@@ -7,8 +7,8 @@ Copyright (c) 2006-2008, ASSIMP Development Team
 
 All rights reserved.
 
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the following
+Redistribution and use of this software in source and binary forms, 
+with or without modification, are permitted provided that the following 
 conditions are met:
 
 * Redistributions of source code must retain the above
@@ -25,80 +25,56 @@ conditions are met:
   derived from this software without specific prior
   written permission of the ASSIMP Development Team.
 
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ---------------------------------------------------------------------------
 */
 
+/** @file Implementation of the JNI API for jAssimp */
 
-package assimp;
-
-
-/**
- * Defines base behaviour for all sub objects of <code>Mesh</code>.
- *
- * @author Aramis (Alexander Gessler)
- * @version 1.0
- */
-public abstract class Mappable {
-
-    /**
-     * Index of the mapped object in the parent Mesh
-     */
-    private int m_iArrayIndex = 0;
-
-    /**
-     * Reference to the parent of the object
-     */
-    private Object m_parent = null;
-
-
-    /**
-     * Construction from a given parent object and array index
-     *
-     * @param parent Must be valid, null is not allowed
-     * @param index  Valied index in the parent's list
-     */
-    public Mappable(Object parent, int index) {
-        m_parent = parent;
-        m_iArrayIndex = index;
-    }
-
-    /**
-     * Called as a request to the object to map all of its
-     * data into the address space of the Java virtual machine.
-     * After this method has been called the class instance must
-     * be ready to be used without an underyling native aiScene
-     *
-     * @throws NativeError
-     */
-    protected abstract void onMap() throws NativeError;
-
-
-    /**
-     * Retrieve the index ofthe mappable object in the parent mesh
-     *
-     * @return Value between 0 and n-1
-     */
-    public int getArrayIndex() {
-        return m_iArrayIndex;
-    }
-
-    /**
-     * Provide access to the parent
-     *
-     * @return Never null ...
-     */
-    public Object getParent() {
-        return m_parent;
-    }
+#include "JNIEnvironment.h"
+#include "JNILogger.h"
+
+using namespace Assimp;
+
+namespace Assimp	{
+namespace JNIBridge		{
+
+// ------------------------------------------------------------------------------------------------
+JNIEnvironment::_assimp::_NativeException::Initialize()
+{
+	// get a handle to the JNI context for this thread
+	JNIEnv* pc = JJNIEnvironment::Get()->GetThread()->m_pcEnv;
+
+	// load a handle to the class
+	if(!(this->Class = pc->FindClass("assimp.NativeException")))
+	{
+		// if this fails we have no exception class we could use ...
+		// throw an java.lang.Error instance
+		this->Class = pc->FindClass("java.lang.Exception");
+		pc->ThrowNew(this->Class,"Unable to load class assimp.NativeException (severe failure!)");
+		this->Class = NULL;
+	}
 }
+
+
+// ------------------------------------------------------------------------------------------------
+void JNIEnvironment::ThrowNativeError(const char* msg /*= NULL*/)
+{
+	// get a handle to the JNI context for this thread
+	JNIEnv* pc = this->GetThread()->m_pcEnv;
+
+	// throw a new NativeException
+	pc->ThrowNew(this->assimp.NativeException.Class,
+		msg ? msg 
+		: "An unspecified error occured in the native interface to Assimp.");
+}

+ 0 - 0
port/jAssimp/jni_bridge/JNINode.cpp


+ 0 - 0
port/jAssimp/jni_bridge/JNIScene.cpp


+ 0 - 0
port/jAssimp/jni_bridge/JNITexture.cpp


+ 0 - 13
port/jAssimp/jni_bridge/assimp_Animation.h

@@ -1,13 +0,0 @@
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include <jni.h>
-/* Header for class assimp_Animation */
-
-#ifndef _Included_assimp_Animation
-#define _Included_assimp_Animation
-#ifdef __cplusplus
-extern "C" {
-#endif
-#ifdef __cplusplus
-}
-#endif
-#endif

+ 12 - 2
port/jAssimp/jni_bridge/assimp_Importer.h

@@ -7,13 +7,15 @@
 #ifdef __cplusplus
 extern "C" {
 #endif
+#undef assimp_Importer_PROPERTY_WAS_NOT_EXISTING
+#define assimp_Importer_PROPERTY_WAS_NOT_EXISTING -1L
 /*
  * Class:     assimp_Importer
  * Method:    _NativeInitContext
- * Signature: ()I
+ * Signature: (I)I
  */
 JNIEXPORT jint JNICALL Java_assimp_Importer__1NativeInitContext
-  (JNIEnv *, jobject);
+  (JNIEnv *, jobject, jint);
 
 /*
  * Class:     assimp_Importer
@@ -31,6 +33,14 @@ JNIEXPORT jint JNICALL Java_assimp_Importer__1NativeFreeContext
 JNIEXPORT jint JNICALL Java_assimp_Importer__1NativeLoad
   (JNIEnv *, jobject, jstring, jint, jlong);
 
+/*
+ * Class:     assimp_Importer
+ * Method:    _NativeSetPropertyInt
+ * Signature: (Ljava/lang/String;IJ)I
+ */
+JNIEXPORT jint JNICALL Java_assimp_Importer__1NativeSetPropertyInt
+  (JNIEnv *, jobject, jstring, jint, jlong);
+
 #ifdef __cplusplus
 }
 #endif

+ 13 - 0
port/jAssimp/jni_bridge/assimp_Importer_DefaultIOStream.h

@@ -0,0 +1,13 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class assimp_Importer_DefaultIOStream */
+
+#ifndef _Included_assimp_Importer_DefaultIOStream
+#define _Included_assimp_Importer_DefaultIOStream
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 13 - 0
port/jAssimp/jni_bridge/assimp_Importer_DefaultIOSystem.h

@@ -0,0 +1,13 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class assimp_Importer_DefaultIOSystem */
+
+#ifndef _Included_assimp_Importer_DefaultIOSystem
+#define _Included_assimp_Importer_DefaultIOSystem
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 13 - 0
port/jAssimp/jni_bridge/assimp_Importer_Property.h

@@ -0,0 +1,13 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class assimp_Importer_Property */
+
+#ifndef _Included_assimp_Importer_Property
+#define _Included_assimp_Importer_Property
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 0 - 13
port/jAssimp/jni_bridge/assimp_Material.h

@@ -1,13 +0,0 @@
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include <jni.h>
-/* Header for class assimp_Material */
-
-#ifndef _Included_assimp_Material
-#define _Included_assimp_Material
-#ifdef __cplusplus
-extern "C" {
-#endif
-#ifdef __cplusplus
-}
-#endif
-#endif

+ 0 - 133
port/jAssimp/jni_bridge/assimp_Mesh.h

@@ -1,133 +0,0 @@
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include <jni.h>
-/* Header for class assimp_Mesh */
-
-#ifndef _Included_assimp_Mesh
-#define _Included_assimp_Mesh
-#ifdef __cplusplus
-extern "C" {
-#endif
-#undef assimp_Mesh_MAX_NUMBER_OF_TEXTURECOORDS
-#define assimp_Mesh_MAX_NUMBER_OF_TEXTURECOORDS 4L
-#undef assimp_Mesh_MAX_NUMBER_OF_COLOR_SETS
-#define assimp_Mesh_MAX_NUMBER_OF_COLOR_SETS 4L
-#undef assimp_Mesh_PF_POSITION
-#define assimp_Mesh_PF_POSITION 1L
-#undef assimp_Mesh_PF_NORMAL
-#define assimp_Mesh_PF_NORMAL 2L
-#undef assimp_Mesh_PF_TANGENTBITANGENT
-#define assimp_Mesh_PF_TANGENTBITANGENT 4L
-#undef assimp_Mesh_PF_BONES
-#define assimp_Mesh_PF_BONES 8L
-#undef assimp_Mesh_PF_VERTEXCOLOR
-#define assimp_Mesh_PF_VERTEXCOLOR 4096L
-#undef assimp_Mesh_PF_UVCOORD
-#define assimp_Mesh_PF_UVCOORD 65536L
-/*
- * Class:     assimp_Mesh
- * Method:    _NativeGetPresenceFlags
- * Signature: (JJ)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeGetPresenceFlags
-  (JNIEnv *, jobject, jlong, jlong);
-
-/*
- * Class:     assimp_Mesh
- * Method:    _NativeGetNumVertices
- * Signature: (JJ)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeGetNumVertices
-  (JNIEnv *, jobject, jlong, jlong);
-
-/*
- * Class:     assimp_Mesh
- * Method:    _NativeGetNumFaces
- * Signature: (JJ)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeGetNumFaces
-  (JNIEnv *, jobject, jlong, jlong);
-
-/*
- * Class:     assimp_Mesh
- * Method:    _NativeGetNumBones
- * Signature: (JJ)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeGetNumBones
-  (JNIEnv *, jobject, jlong, jlong);
-
-/*
- * Class:     assimp_Mesh
- * Method:    _NativeGetMaterialIndex
- * Signature: (JJ)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeGetMaterialIndex
-  (JNIEnv *, jobject, jlong, jlong);
-
-/*
- * Class:     assimp_Mesh
- * Method:    _NativeGetNumUVComponents
- * Signature: (JJ[I)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeGetNumUVComponents
-  (JNIEnv *, jobject, jlong, jlong, jintArray);
-
-/*
- * Class:     assimp_Mesh
- * Method:    _NativeMapVertices
- * Signature: (JJ[F)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapVertices
-  (JNIEnv *, jobject, jlong, jlong, jfloatArray);
-
-/*
- * Class:     assimp_Mesh
- * Method:    _NativeMapNormals
- * Signature: (JJ[F)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapNormals
-  (JNIEnv *, jobject, jlong, jlong, jfloatArray);
-
-/*
- * Class:     assimp_Mesh
- * Method:    _NativeMapTangents
- * Signature: (JJ[F)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapTangents
-  (JNIEnv *, jobject, jlong, jlong, jfloatArray);
-
-/*
- * Class:     assimp_Mesh
- * Method:    _NativeMapBitangents
- * Signature: (JJ[F)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapBitangents
-  (JNIEnv *, jobject, jlong, jlong, jfloatArray);
-
-/*
- * Class:     assimp_Mesh
- * Method:    _NativeMapUVs
- * Signature: (JJI[F)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapUVs
-  (JNIEnv *, jobject, jlong, jlong, jint, jfloatArray);
-
-/*
- * Class:     assimp_Mesh
- * Method:    _NativeMapColors
- * Signature: (JJI[F)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapColors
-  (JNIEnv *, jobject, jlong, jlong, jint, jfloatArray);
-
-/*
- * Class:     assimp_Mesh
- * Method:    _NativeMapFaces
- * Signature: (JJ[I)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Mesh__1NativeMapFaces
-  (JNIEnv *, jobject, jlong, jlong, jintArray);
-
-#ifdef __cplusplus
-}
-#endif
-#endif

+ 0 - 13
port/jAssimp/jni_bridge/assimp_Node.h

@@ -1,13 +0,0 @@
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include <jni.h>
-/* Header for class assimp_Node */
-
-#ifndef _Included_assimp_Node
-#define _Included_assimp_Node
-#ifdef __cplusplus
-extern "C" {
-#endif
-#ifdef __cplusplus
-}
-#endif
-#endif

+ 0 - 33
port/jAssimp/jni_bridge/assimp_PostProcessStep.h

@@ -1,33 +0,0 @@
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include <jni.h>
-/* Header for class assimp_PostProcessStep */
-
-#ifndef _Included_assimp_PostProcessStep
-#define _Included_assimp_PostProcessStep
-#ifdef __cplusplus
-extern "C" {
-#endif
-#undef assimp_PostProcessStep_DEFAULT_VERTEX_SPLIT_LIMIT
-#define assimp_PostProcessStep_DEFAULT_VERTEX_SPLIT_LIMIT 1000000L
-#undef assimp_PostProcessStep_DEFAULT_TRIANGLE_SPLIT_LIMIT
-#define assimp_PostProcessStep_DEFAULT_TRIANGLE_SPLIT_LIMIT 1000000L
-/*
- * Class:     assimp_PostProcessStep
- * Method:    _NativeSetVertexSplitLimit
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_assimp_PostProcessStep__1NativeSetVertexSplitLimit
-  (JNIEnv *, jclass, jint);
-
-/*
- * Class:     assimp_PostProcessStep
- * Method:    _NativeSetTriangleSplitLimit
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_assimp_PostProcessStep__1NativeSetTriangleSplitLimit
-  (JNIEnv *, jclass, jint);
-
-#ifdef __cplusplus
-}
-#endif
-#endif

+ 0 - 45
port/jAssimp/jni_bridge/assimp_Scene.h

@@ -1,45 +0,0 @@
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include <jni.h>
-/* Header for class assimp_Scene */
-
-#ifndef _Included_assimp_Scene
-#define _Included_assimp_Scene
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class:     assimp_Scene
- * Method:    _NativeGetNumMeshes
- * Signature: (J)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Scene__1NativeGetNumMeshes
-  (JNIEnv *, jobject, jlong);
-
-/*
- * Class:     assimp_Scene
- * Method:    _NativeGetNumAnimations
- * Signature: (J)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Scene__1NativeGetNumAnimations
-  (JNIEnv *, jobject, jlong);
-
-/*
- * Class:     assimp_Scene
- * Method:    _NativeGetNumTextures
- * Signature: (J)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Scene__1NativeGetNumTextures
-  (JNIEnv *, jobject, jlong);
-
-/*
- * Class:     assimp_Scene
- * Method:    _NativeGetNumMaterials
- * Signature: (J)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Scene__1NativeGetNumMaterials
-  (JNIEnv *, jobject, jlong);
-
-#ifdef __cplusplus
-}
-#endif
-#endif

+ 0 - 29
port/jAssimp/jni_bridge/assimp_Texture.h

@@ -1,29 +0,0 @@
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include <jni.h>
-/* Header for class assimp_Texture */
-
-#ifndef _Included_assimp_Texture
-#define _Included_assimp_Texture
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class:     assimp_Texture
- * Method:    _NativeMapColorData
- * Signature: (JJ[B)I
- */
-JNIEXPORT jint JNICALL Java_assimp_Texture__1NativeMapColorData
-  (JNIEnv *, jobject, jlong, jlong, jbyteArray);
-
-/*
- * Class:     assimp_Texture
- * Method:    _NativeGetTextureInfo
- * Signature: (JJ)J
- */
-JNIEXPORT jlong JNICALL Java_assimp_Texture__1NativeGetTextureInfo
-  (JNIEnv *, jobject, jlong, jlong);
-
-#ifdef __cplusplus
-}
-#endif
-#endif

+ 84 - 0
port/jAssimp/jni_bridge/res/jAssimp.rc

@@ -0,0 +1,84 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#define APSTUDIO_HIDDEN_SYMBOLS
+#include "windows.h"
+#undef APSTUDIO_HIDDEN_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Deutsch (Deutschland) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)
+#ifdef _WIN32
+LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
+#pragma code_page(1252)
+#endif //_WIN32
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+#if (defined ASSIMP_JNI_EXPORT)
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x7L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040704b0"
+        BEGIN
+            VALUE "Comments", "Licensed under a 3-clause BSD license"
+            VALUE "CompanyName", "ASSIMP Development Team"
+            VALUE "FileDescription", "ASSIMP-JNI bridge module"
+            VALUE "FileVersion", "1, 0, 0, 0"
+            VALUE "InternalName", "jassimp"
+            VALUE "LegalCopyright", "Copyright (C) 2008"
+            VALUE "OriginalFilename", "jAssimpNN.dll"
+            VALUE "ProductName", "ASSIMP-JNI bridge module"
+            VALUE "ProductVersion", "1, 0, 0, 0"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x407, 1200
+    END
+END
+
+#endif // !!ASSIMP_JNI_EXPORT 
+
+#endif    // Deutsch (Deutschland) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+

+ 62 - 0
port/jAssimp/module_assimp.xml

@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="module_assimp" default="compile.module.assimp">
+  <dirname property="module.assimp.basedir" file="${ant.file.module_assimp}"/>
+  
+  <property name="module.jdk.home.assimp" value="${project.jdk.home}"/>
+  <property name="module.jdk.classpath.assimp" value="${project.jdk.classpath}"/>
+  
+  <property name="compiler.args.assimp" value="${compiler.args}"/>
+  
+  <property name="assimp.output.dir" value="${module.assimp.basedir}/classes"/>
+  <property name="assimp.testoutput.dir" value="${module.assimp.basedir}/classes"/>
+  
+  <path id="assimp.module.bootclasspath">
+    <!-- Paths to be included in compilation bootclasspath -->
+  </path>
+  
+  <path id="assimp.module.classpath">
+    <path refid="${module.jdk.classpath.assimp}"/>
+  </path>
+  
+  
+  <patternset id="excluded.from.module.assimp">
+    <patternset refid="ignored.files"/>
+  </patternset>
+  
+  <patternset id="excluded.from.compilation.assimp">
+    <patternset refid="excluded.from.module.assimp"/>
+  </patternset>
+  
+  <path id="assimp.module.sourcepath">
+    <dirset dir="${module.assimp.basedir}">
+      <include name="src"/>
+    </dirset>
+  </path>
+  
+  
+  <target name="compile.module.assimp" depends="compile.module.assimp.production,compile.module.assimp.tests" description="Compile module assimp"/>
+  
+  <target name="compile.module.assimp.production" description="Compile module assimp; production classes">
+    <mkdir dir="${assimp.output.dir}"/>
+    <javac2 destdir="${assimp.output.dir}" debug="${compiler.debug}" nowarn="${compiler.generate.no.warnings}" memoryMaximumSize="${compiler.max.memory}" fork="true" executable="${module.jdk.home.assimp}/bin/javac">
+      <compilerarg line="${compiler.args.assimp}"/>
+      <bootclasspath refid="assimp.module.bootclasspath"/>
+      <classpath refid="assimp.module.classpath"/>
+      <src refid="assimp.module.sourcepath"/>
+    </javac2>
+    
+    <copy todir="${assimp.output.dir}">
+      <fileset dir="${module.assimp.basedir}/src">
+        <patternset refid="compiler.resources"/>
+        <type type="file"/>
+      </fileset>
+    </copy>
+  </target>
+  
+  <target name="compile.module.assimp.tests" depends="compile.module.assimp.production" description="compile module assimp; test classes" unless="skip.tests"/>
+  
+  <target name="clean.module.assimp" description="cleanup module">
+    <delete dir="${assimp.output.dir}"/>
+    <delete dir="${assimp.testoutput.dir}"/>
+  </target>
+</project>

+ 74 - 7
port/jAssimp/src/assimp/Animation.java

@@ -50,18 +50,85 @@ package assimp;
  * @author Aramis (Alexander Gessler)
  * @version 1.0
  */
-public class Animation extends Mappable {
+public class Animation {
+
+    /**
+     * The name of the animation.
+     */
+    private String name = "";
+
+    /**
+     * Duration of the animation in ticks.
+     */
+    private double mDuration = 0.0;
+
+    /**
+     * Ticks per second. 0 if not specified in the imported file
+     */
+    private double mTicksPerSecond = 0.0;
+
+    /**
+     * Bone animation channels
+     */
+    private BoneAnim[] boneAnims = null;
+
+
     /**
-     * Construction from a given object and array index
+     * Returns the name of the animation channel
      *
-     * @param parent Must be valid, null is not allowed
-     * @param index  Valied index in the parent's list
+     * @return If the modelling package this data was exported from does support
+     *         only a single animation channel, this name is usually <code>""</code>
      */
-    public Animation(Object parent, int index) {
-        super(parent, index);
+    public final String getName() {
+        return name;
     }
 
-    protected void onMap() throws NativeError {
+    /**
+     * Returns the total duration of the animation, in ticks
+     *
+     * @return Total duration
+     */
+    public final double getDuration() {
+        return mDuration;
+    }
 
+    /**
+     * Returns the ticks per second count.
+     *
+     * @return 0 if not specified in the imported file
+     */
+    public final double getTicksPerSecond() {
+        return mTicksPerSecond;
+    }
+
+
+    /**
+     * Returns the number of bone animation channels
+     * @return This value is never 0
+     */
+    public final int getNumBoneAnimChannels() {
+        assert(null != boneAnims);
+        return boneAnims.length;
+    }
+
+    /**
+     * Returns the list of all bone animation channels
+     * @return This value is never <code>null</code>
+     */
+    public final BoneAnim[] getBoneAnimChannels() {
+       assert(null != boneAnims);
+        return boneAnims;
+    }
+
+
+    /**
+     * Returns a specific bone animation channel
+     * @param i Index of the animation channel. Must be between
+     * 0 and the value returned by <code>getNumBoneAnimChannels</code>
+     * @return This value is never <code>null</code>
+     */
+    public final BoneAnim getBoneAnimChannel(int i) {
+       assert(null != boneAnims && i < boneAnims.length);
+        return boneAnims[i];
     }
 }

+ 127 - 5
port/jAssimp/src/assimp/Bone.java

@@ -1,11 +1,133 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development Team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the ASSIMP team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the ASSIMP Development Team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+
 package assimp;
 
+
 /**
- * Created by IntelliJ IDEA.
- * User: Alex
- * Date: 08.06.2008
- * Time: 15:31:01
- * To change this template use File | Settings | File Templates.
+ * A bone belongs to a mesh stores a list of vertex weights.
+ * It represents a joint of the skeleton. The bone hierarchy
+ * is contained in the node graph.
+ *
+ * @author Aramis (Alexander Gessler)
+ * @version 1.0
  */
 public class Bone {
+
+
+    /**
+     * Represents a single vertex weight
+     */
+    public class Weight {
+
+
+        public Weight() {
+            index = 0;
+            weight = 1.0f;
+        }
+
+        /**
+         * Index of the vertex in the corresponding <code>Mesh</code>
+         */
+        public int index;
+
+
+        /**
+         * Weight of the vertex. All weights for a vertex sum up to
+         * 1.0
+         */
+        public float weight;
+    }
+
+    /**
+     * Name of the bone
+     */
+    private String name = "";
+
+
+    /**
+     * List of vertex weights for the bone
+     */
+    private Weight[] weights = null;
+
+
+    /**
+     * Retrieves the name of the node
+     * @return Normally bones are never unnamed
+     */
+    public final String getName() {
+        return this.name;
+    }
+
+
+    /**
+     * Returns a reference to the array of weights
+     * @return <code>Weight</code> array
+     */
+    public final Weight[] getWeightsArray() {
+        assert(null != weights);
+        return weights;
+    }
+
+
+    /**
+     * Returns the number of bone weights.
+     * @return There should at least be one vertex weights (the
+     * validation step would complain otherwise)
+     */
+    public final int getNumWeights() {
+        assert(null != weights);
+        return weights.length;
+    }
+
+
+    /**
+     * Returns one specific vertex weights
+     * @param weight Index of the vertex weights. Must be between
+     * 0 and <code>getNumWeights()-1</code>
+     * @return Vertex weight
+     */
+    public final Weight getWeight(int weight) {
+        assert(null != weights && weight < this.weights.length);
+        return this.weights[weight];
+    }
 }

+ 149 - 0
port/jAssimp/src/assimp/BoneAnim.java

@@ -0,0 +1,149 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development Team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the ASSIMP team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the ASSIMP Development Team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+
+package assimp;
+
+
+/**
+ * A bone animation channel defines the animation keyframes for
+ * a single bone in the mesh hierarchy.
+ *
+ * @author Aramis (Alexander Gessler)
+ * @version 1.0
+ */
+public class BoneAnim {
+
+    /**
+     * Describes a keyframe
+     */
+    public class KeyFrame<Type> {
+
+        /**
+         * Time line position of *this* keyframe, in "ticks"
+         */
+        public double time;
+
+        /**
+         * Current value of the property being animated
+         */
+        public Type value;
+    }
+
+    /**
+     * Rotation keyframes
+     */
+    private KeyFrame<Quaternion>[] mQuatKeys;
+
+    /**
+     * Position keyframes. Component ordering is x,y,z
+     */
+    private KeyFrame<float[]>[] mPosKeys;
+
+    /**
+     * scaling keyframes. Component ordering is x,y,z
+     */
+    private KeyFrame<float[]>[] mScalingKeys;
+
+
+    /**
+     * Name of the bone affected by this animation channel
+     */
+    private String mName;
+
+
+    /**
+     * Returns the name of the bone affected by this animation channel
+     * @return Bone name
+     */
+    public final String getName() {
+        return mName;
+    }
+
+    /**
+     * Returns the number of rotation keyframes
+     * @return This can be 0.
+     */
+    public final int getNumQuatKeys() {
+        return null == mQuatKeys ? 0 : mQuatKeys.length;
+    }
+
+     /**
+     * Returns the number of position keyframes
+     * @return This can be 0.
+     */
+    public final int getNumPosKeys() {
+        return null == mPosKeys ? 0 : mPosKeys.length;
+    }
+
+     /**
+     * Returns the number of scaling keyframes
+     * @return This can be 0.
+     */
+    public final int getNumScalingKeys() {
+        return null == mScalingKeys ? 0 : mScalingKeys.length;
+    }
+
+    /**
+     * Get a reference to the list of all rotation keyframes
+     * @return Could be <code>null</code> if there are no rotation keys
+     */
+    public final KeyFrame<Quaternion>[] getQuatKeys() {
+        return mQuatKeys;
+    }
+
+    /**
+     * Get a reference to the list of all position keyframes
+     * @return Could be <code>null</code> if there are no position keys
+     */
+    public final KeyFrame<float[]>[] getPosKeys() {
+        return mPosKeys;
+    }
+
+     /**
+     * Get a reference to the list of all scaling keyframes
+     * @return Could be <code>null</code> if there are no scaling keys
+     */
+    public final KeyFrame<float[]>[] getScalingKeys() {
+        return mScalingKeys;
+    }
+
+}

+ 51 - 49
port/jAssimp/src/assimp/CompressedTexture.java

@@ -42,7 +42,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 package assimp;
 
+import javax.imageio.ImageIO;
+import javax.imageio.stream.ImageInputStream;
 import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.io.ByteArrayInputStream;
 
 /**
  * Represents an embedded compressed texture that is stored in a format
@@ -59,23 +64,6 @@ public class CompressedTexture extends Texture {
 
     private String m_format = "";
 
-
-    /**
-     * Construction from a given parent object and array index
-     *
-     * @param parent Must be valid, null is not allowed
-     * @param index  Valied index in the parent's list
-     */
-    public CompressedTexture(Object parent, int index) throws NativeError {
-        super(parent, index);
-
-        // need to get the format of the texture via the JNI
-        if ((m_format = this._NativeGetCTextureFormat(((Scene) this.getParent()).
-                getImporter().getContext(), this.getArrayIndex())).equals("")) {
-            throw new NativeError("Unable to get the format of the compressed texture");
-        }
-    }
-
     /**
      * Retrieves the format of the texture data. This is
      * the most common file extension of the format (without a
@@ -84,7 +72,7 @@ public class CompressedTexture extends Texture {
      * @return Extension string or null if the format of the texture
      *         data is not known to ASSIMP.
      */
-    public String getFormat() {
+    public final String getFormat() {
         return m_format;
     }
 
@@ -93,15 +81,7 @@ public class CompressedTexture extends Texture {
      *
      * @return Data poiner
      */
-    public byte[] getData() {
-        if (null == data) {
-            try {
-                this.onMap();
-            } catch (NativeError nativeError) {
-                DefaultLogger.get().error(nativeError.getMessage());
-                return null;
-            }
-        }
+    public final byte[] getData() {
         return (byte[]) data;
     }
 
@@ -110,7 +90,7 @@ public class CompressedTexture extends Texture {
      *
      * @return Data poiner
      */
-    public int getLength() {
+    public final int getLength() {
         return width;
     }
 
@@ -120,7 +100,7 @@ public class CompressedTexture extends Texture {
      * @return n/a
      */
     @Override
-    public int getHeight() {
+    public final int getHeight() {
         return 0;
     }
 
@@ -130,7 +110,7 @@ public class CompressedTexture extends Texture {
      * @return n/a
      */
     @Override
-    public int getWidth() {
+    public final int getWidth() {
         return 0;
     }
 
@@ -150,33 +130,55 @@ public class CompressedTexture extends Texture {
      * @return n/a
      */
     @Override
-    public Color[] getColorArray() {
+    public final Color[] getColorArray() {
         return null;
     }
 
+
     /**
-     * Internal helper function to map the native texture data into
-     * a <code>byte</code> array in the memory of the JVM
+     * @return The return value is <code>true</code> of the
+     *         file format can't be recognized.
+     * @see <code>Texture.hasAlphaChannel()</code>
      */
-    @Override
-    protected void onMap() throws NativeError {
-
-        // first allocate the output array
-        data = new byte[this.width];
+    public boolean hasAlphaChannel() {
 
-        // now allocate a temporary output array
-        byte[] temp = new byte[this.width];
+        // try to determine it from the file format sequence
+        if (m_format.equals("bmp") || m_format.equals("dib")) return false;
+        if (m_format.equals("tif") || m_format.equals("tiff")) return false;
+        if (m_format.equals("jpg") || m_format.equals("jpeg")) return false;
 
-        // and copy the native color data to it
-        if (0xffffffff == this._NativeMapColorData(
-                ((Scene) this.getParent()).getImporter().getContext(),
-                this.getArrayIndex(), temp)) {
-            throw new NativeError("Unable to map compressed aiTexture into the Java-VM");
-        }
-        DefaultLogger.get().debug("CompressedTexture.onMap successful");
+        // todo: add more
 
-        return;
+        return true;
     }
 
-    private native String _NativeGetCTextureFormat(long context, int arrayIndex);
+
+    /**
+     * Convert the texture into a <code>java.awt.BufferedImage</code>
+     *
+     * @return <code>java.awt.BufferedImage</code> object containing
+     *         a copy of the texture image. The return value is <code>null</code>
+     *         if the file format is not known.
+     */
+    public BufferedImage convertToImage() {
+
+        BufferedImage img = null;
+        try {
+
+            // create an input stream and attach it to an image input stream
+            ImageInputStream stream = ImageIO.createImageInputStream(
+                    new ByteArrayInputStream((byte[])data));
+
+            // and use the stream to decode the file
+            img = ImageIO.read(stream);
+
+        } catch (IOException e) {
+
+            DefaultLogger.get().error("Unable to decode compressed embedded texture +" +
+                    "(Format hint: " + m_format + ")" );
+
+        }
+        // return the created image to the caller
+        return img;
+    }
 }

+ 154 - 0
port/jAssimp/src/assimp/ConfigProperty.java

@@ -0,0 +1,154 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development Team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the ASSIMP team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the ASSIMP Development Team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+
+package assimp;
+
+/**
+ * Defines configuration properties.
+ *
+ * Static helper class, can't be instanced. It defines configuration
+ * property keys to be used with <code> Importer.setPropertyInt</code>
+ *
+ * @author Aramis (Alexander Gessler)
+ * @version 1.0
+ */
+public class ConfigProperty {
+
+    private ConfigProperty() {
+    }
+
+
+
+    /**
+     * Default value for the <code>CONFIG_PP_SLM_TRIANGLE_LIMIT</code>
+     * configuration property.
+     */
+    public static final int DEFAULT_SLM_MAX_TRIANGLES = 1000000;
+
+
+    /**
+     * Default value for the <code>CONFIG_PP_SLM_VERTEX_LIMIT</code>
+     * configuration property.
+     */
+    public static final int DEFAULT_SLM_MAX_VERTICES = 1000000;
+
+
+    /**
+     * Default value for the <code>CONFIG_PP_LBW_MAX_WEIGHTS</code>
+     * configuration property.
+     */
+    public static final int DEFAULT_LBW_MAX_WEIGHTS = 4;
+
+
+
+
+
+    /**
+     * Set the maximum number of vertices in a mesh.
+     * <p/>
+     * This is used by the "SplitLargeMeshes" PostProcess-Step to determine
+     * whether a mesh must be splitted or not.
+     * \note The default value is <code>DEFAULT_SLM_MAX_TRIANGLES</code>
+     */
+    public static final String CONFIG_PP_SLM_TRIANGLE_LIMIT
+            = "pp.slm.triangle_limit";
+
+
+    /**
+     * Set the maximum number of triangles in a mesh.
+     * <p/>
+     * This is used by the "SplitLargeMeshes" PostProcess-Step to determine
+     * whether a mesh must be splitted or not.
+     * \note The default value is <code>DEFAULT_SLM_MAX_VERTICES</code>
+     */
+    public static final String CONFIG_PP_SLM_VERTEX_LIMIT
+            = "pp.slm.vertex_limit";
+
+
+    /**
+     * Set the maximum number of bones affecting a single vertex
+     * <p/>
+     * This is used by the aiProcess_LimitBoneWeights PostProcess-Step.
+     * \note The default value is <code>DEFAULT_LBW_MAX_WEIGHTS</code>
+     */
+    public static final String CONFIG_PP_LBW_MAX_WEIGHTS
+            = "pp.lbw.weights_limit";
+
+
+    /**
+     * Set the vertex animation keyframe to be imported
+     * <p/>
+     * 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
+     * <code>CONFIG_IMPORT_XXX_KEYFRAME</code> options (where XXX is a
+     * placeholder for the file format for which you want to override the
+     * global setting).
+     */
+    public static final String CONFIG_IMPORT_GLOBAL_KEYFRAME
+            = "imp.global.kf";
+
+    public static final String CONFIG_IMPORT_MD3_KEYFRAME = "imp.md3.kf";
+    public static final String CONFIG_IMPORT_MD2_KEYFRAME = "imp.md2.kf";
+    public static final String CONFIG_IMPORT_MDL_KEYFRAME = "imp.mdl.kf";
+    public static final String CONFIG_IMPORT_MDC_KEYFRAME = "imp.mdc.kf";
+    public static final String CONFIG_IMPORT_MDR_KEYFRAME = "imp.mdr.kf";
+    public static final String CONFIG_IMPORT_SMD_KEYFRAME = "imp.smd.kf";
+
+
+    /**
+     * Causes the 3DS loader to ignore pivot points in the file
+     * <p/>
+     * There are some faulty 3DS files on the internet which look
+     * only correctly with pivot points disabled. By default,
+     * this option is disabled.
+     */
+    public static final String CONFIG_IMPORT_3DS_IGNORE_PIVOT
+            = "imp.3ds.nopivot";
+
+    public static final String CONFIG_PP_OG_MAX_DEPTH = "pp.og.max_depth";
+    public static final String CONFIG_PP_OG_MIN_TRIS_PER_NODE = "pp.og.min_tris";
+    public static final String CONFIG_PP_OG_MAXIMALLY_SMALL = "pp.og.maximally_small";
+}

+ 0 - 1
port/jAssimp/src/assimp/IOSystem.java

@@ -42,7 +42,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 package assimp;
 
-import java.io.InputStream;
 import java.io.FileNotFoundException;
 
 

+ 142 - 41
port/jAssimp/src/assimp/Importer.java

@@ -45,9 +45,7 @@ package assimp;
 import java.util.Vector;
 import java.io.FileNotFoundException;
 import java.io.FileReader;
-import java.io.IOException;
 import java.io.File;
-import java.lang.ref.Reference;
 
 /**
  * Main class of jAssimp. The class is a simple wrapper for the native
@@ -64,6 +62,15 @@ import java.lang.ref.Reference;
  */
 public class Importer {
 
+
+    /**
+     * Represents a property (key-value)
+     */
+    private class Property<Type> {
+        String key;
+        Type value;
+    }
+
     /**
      * Default implementation of <code>IOStream</code>.
      * <br>
@@ -84,6 +91,7 @@ public class Importer {
 
         /**
          * Construction with a given path
+         *
          * @param file Path to the file to be opened
          * @throws FileNotFoundException If the file isn't accessible at all
          */
@@ -152,6 +160,24 @@ public class Importer {
      */
     private IOSystem ioSystem = null;
 
+    /**
+     * List of config properties
+     */
+    private Vector<Property<Integer>> properties;
+
+
+    /**
+     * Specifies whether the native jAssimp library is currently
+     * in a loaded state.
+     */
+    private static boolean bLibInitialized = false;
+
+
+    private static final String JASSIMP_RUNTIME_NAME_X64 = "jAssimp64";
+    private static final String JASSIMP_RUNTIME_NAME_X86 = "jAssimp32";
+
+    public static final int PROPERTY_WAS_NOT_EXISTING = 0xffffffff;
+
     /**
      * Public constructor. Initialises the JNI bridge to the native
      * ASSIMP library. A native Assimp::Importer object is constructed and
@@ -159,47 +185,50 @@ public class Importer {
      * is initialized.
      *
      * @param iVersion Version of the JNI interface to be used.
-     * @throws NativeError Thrown if the jassimp library could not be loaded
+     * @throws NativeException Thrown if the jassimp library could not be loaded
      *                     or if the entry point to the module wasn't found. if this exception
      *                     is not thrown, you can assume that jAssimp is fully available.
      */
-    public Importer(int iVersion) throws NativeError {
+    public Importer(int iVersion) throws NativeException {
 
         // allocate a default I/O system
         ioSystem = new DefaultIOSystem();
 
-        /** try to load the jassimp library. First try to load the
-         * x64 version, in case of failure the x86 version
-         */
-        try {
-            System.loadLibrary("jassimp64");
-        }
-        catch (UnsatisfiedLinkError exc) {
+        if (!bLibInitialized) {
+
+            /** try to load the jassimp library. First try to load the
+             * x64 version, in case of failure the x86 version
+             */
             try {
-                System.loadLibrary("jassimp32");
+                System.loadLibrary(JASSIMP_RUNTIME_NAME_X64);
             }
-            catch (UnsatisfiedLinkError exc2) {
-                throw new NativeError("Unable to load the jassimp library");
+            catch (UnsatisfiedLinkError exc) {
+                try {
+                    System.loadLibrary(JASSIMP_RUNTIME_NAME_X86);
+                }
+                catch (UnsatisfiedLinkError exc2) {
+                    throw new NativeException("Unable to load the jAssimp library");
+                }
             }
+            bLibInitialized = true;
         }
         // now create the native Importer class and setup our internal
         // data structures outside the VM.
         try {
             if (0xffffffffffffffffl == (this.m_iNativeHandle = _NativeInitContext(iVersion))) {
-                throw new NativeError(
+                throw new NativeException(
                         "Unable to initialize the native library context." +
                                 "The initialization routine has failed");
             }
         }
         catch (UnsatisfiedLinkError exc) {
-            throw new NativeError(
+            throw new NativeException(
                     "Unable to initialize the native library context." +
                             "The initialization routine has not been found");
         }
-        return;
     }
 
-    public Importer() throws NativeError {
+    public Importer() throws NativeException {
         this(0);
     }
 
@@ -208,21 +237,23 @@ public class Importer {
      * assets. If no custom implementation was provided via <code>setIoSystem()</code>
      * a default implementation will be used. Use <code>isDefaultIoSystem()</code>
      * to check this.
+     *
      * @return Always a valid <code>IOSystem</code> object, never null.
      */
-    public IOSystem getIoSystem() {
+    public final IOSystem getIoSystem() {
         return ioSystem;
     }
 
-    
+
     /**
      * Checks whether a default IO system is currently being used to load
      * assets. Using the default IO system has many performance benefits,
      * but it is possible to provide a custom IO system (<code>setIoSystem()</code>).
      * This allows applications to add support for archives like ZIP.
+     *
      * @return true if a default <code>IOSystem</code> is active,
      */
-    public boolean isDefaultIoSystem() {
+    public final boolean isDefaultIoSystem() {
         return ioSystem instanceof DefaultIOSystem;
     }
 
@@ -235,7 +266,7 @@ public class Importer {
      * @return true if the step has been added successfully
      * @see PostProcessStep
      */
-    public boolean addPostProcessStep(PostProcessStep p_Step) {
+    public final boolean addPostProcessStep(PostProcessStep p_Step) {
 
         if (isPostProcessStepActive(p_Step)) return false;
         this.m_vPPSteps.add(p_Step);
@@ -253,7 +284,7 @@ public class Importer {
      * @return true if the step is active
      * @see PostProcessStep
      */
-    public boolean isPostProcessStepActive(PostProcessStep p_Step) {
+    public final boolean isPostProcessStepActive(PostProcessStep p_Step) {
 
         for (PostProcessStep step : m_vPPSteps) {
             if (step.equals(p_Step)) return true;
@@ -272,7 +303,7 @@ public class Importer {
      *         it was not existing
      * @see PostProcessStep
      */
-    public boolean removePostProcessStep(PostProcessStep p_Step) {
+    public final boolean removePostProcessStep(PostProcessStep p_Step) {
 
         return this.m_vPPSteps.remove(p_Step);
     }
@@ -287,10 +318,10 @@ public class Importer {
      *
      * @param path Path to the file to be read
      * @return null if the import failed, otherwise a valid Scene instance
-     * @throws NativeError This exception is thrown when an unknown error
+     * @throws NativeException This exception is thrown when an unknown error
      *                     occurs in the JNI bridge module.
      */
-    public Scene readFile(String path) throws NativeError {
+    public final Scene readFile(String path) throws NativeException {
         this.scene = new Scene(this);
         this.path = path;
 
@@ -315,24 +346,18 @@ public class Importer {
             else if (step.equals(PostProcessStep.PreTransformVertices)) flags |= 0x100;
             else if (step.equals(PostProcessStep.LimitBoneWeights)) flags |= 0x200;
             else if (step.equals(PostProcessStep.ValidateDataStructure)) flags |= 0x400;
+            else if (step.equals(PostProcessStep.FixInfacingNormals)) flags |= 0x800;
+            else if (step.equals(PostProcessStep.ImproveVertexLocality)) flags |= 0x1600;
         }
 
         // now load the mesh
         if (0xffffffff == this._NativeLoad(this.path, flags, this.m_iNativeHandle)) {
             this.scene = null;
             this.path = null;
-            throw new NativeError("Failed to load the mesh");
+            throw new NativeException("Failed to load the mesh");
         }
-        // and setup our Scene object
-        try {
-            this.scene.construct();
-        }
-        catch (NativeError exc) {
-
-            // delete everything ...
-            this.scene = null;
-            this.path = null;
-            throw exc;
+        if (null == this.scene) {
+            throw new NativeException("Failed to copy the data into the Java VM");
         }
         return this.scene;
     }
@@ -344,7 +369,7 @@ public class Importer {
      * @param o Object to be compred with *this*
      * @return true if *this* is equal to o
      */
-    public boolean equals(Object o) {
+    public final boolean equals(Object o) {
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
 
@@ -358,7 +383,7 @@ public class Importer {
      * Implementation of <code>java.lang.Object.finalize()</code>
      * We override this to make sure that all native resources are
      * deleted properly. This will free the native Assimp::Importer object
-     * and its associated aiScene instance. A NativeError is thrown
+     * and its associated aiScene instance. A NativeException is thrown
      * if the destruction failed. This means that not all resources have
      * been deallocated and memory leaks are remaining.
      */
@@ -368,7 +393,7 @@ public class Importer {
 
         // be sure that native resources are deallocated properly
         if (0xffffffff == _NativeFreeContext(this.m_iNativeHandle)) {
-            throw new NativeError("Unable to destroy the native library context");
+            throw new NativeException("Unable to destroy the native library context");
         }
     }
 
@@ -387,13 +412,79 @@ public class Importer {
     }
 
 
+    /**
+     * Set an integer property. All supported config properties are
+     * defined as constants in the <code>ConfigProperty</code> class
+     *
+     * @param prop Name of the config property
+     * @param val  New value for the config property
+     * @return Old value of the property or <code>PROPERTY_WAS_NOT_EXISTING</code>
+     *         if the property has not yet been set.
+     */
+    public final int setPropertyInt(final String prop, int val) {
+
+        for (Property<Integer> i : this.properties) {
+            if (i.key.equals(prop)) {
+                int old = i.value;
+                i.value = val;
+
+                // make sure all changes are sent to the native implementation
+                this._NativeSetPropertyInt(prop, val, this.getContext());
+                return old;
+            }
+        }
+
+        Property<Integer> propNew = new Property<Integer>();
+        propNew.key = prop;
+        propNew.value = val;
+        this.properties.add(propNew);
+
+        // make sure all changes are sent to the native implementation
+        this._NativeSetPropertyInt(prop, val, this.getContext());
+        return PROPERTY_WAS_NOT_EXISTING;
+    }
+
+
+    /**
+     * Gets an integer config property  that has been set using
+     * <code>setPropertyInt</code>. All supported config properties are
+     * defined as constants in the <code>ConfigProperty</code> class
+     *
+     * @param prop         Name of the config property
+     * @param error_return Default return value if the property isn't there
+     * @return Current value of the config property or
+     *         error_return if the property has not yet been set
+     */
+    public final int getPropertyInt(final String prop, int error_return) {
+
+        for (Property<Integer> i : this.properties) {
+            if (i.key.equals(prop)) {
+                return i.value;
+            }
+        }
+        return error_return;
+    }
+
+    /**
+     * Gets an integer config property  that has been set using
+     * <code>setPropertyInt</code>. All supported config properties are
+     * defined as constants in the <code>ConfigProperty</code> class
+     *
+     * @param prop Name of the config property
+     * @return Current of the property or <code>PROPERTY_WAS_NOT_EXISTING</code>
+     *         if the property has not yet been set.
+     */
+    public final int getPropertyInt(final String prop) {
+        return getPropertyInt(prop, PROPERTY_WAS_NOT_EXISTING);
+    }
+
     /**
      * Retrieves the native context of the class. This is normally the
      * address of the native Importer object.
      *
      * @return Native context
      */
-    public long getContext() {
+    public final long getContext() {
         return m_iNativeHandle;
     }
 
@@ -430,4 +521,14 @@ public class Importer {
      * @return 0xffffffff if an error occured
      */
     private native int _NativeLoad(String path, int flags, long iContext);
+
+    /**
+     * JNI bridge call. For internal use only
+     * The method sets a property
+     *
+     * @param name Name of the property
+     * @param prop New value for the property
+     * @return 0xffffffff if an error occured
+     */
+    private native int _NativeSetPropertyInt(String name, int prop, long iContext);
 }

+ 172 - 21
port/jAssimp/src/assimp/Material.java

@@ -47,16 +47,179 @@ package assimp;
 /**
  * Class to wrap materials. Materials are represented in ASSIMP as a list of
  * key/value pairs, the key being a <code>String</code> and the value being
- * a binary buffer.
+ * a binary buffer. The class provides several get methods to access
+ * material properties easily.
  *
  * @author Aramis (Alexander Gessler)
  * @version 1.0
  */
-public class Material extends Mappable {
+public class Material {
 
 
+    /**
+     * Internal representation of a material property
+     */
+    private class Property {
+        String key;
+        Object value;
+    }
+
+    /**
+     * List of all properties for this material
+     */
+    public Property[] properties;
+
+
+    /**
+     * Special exception class which is thrown if a material property
+     * could not be found.
+     */
+    public class PropertyNotFoundException extends Exception {
+
+        public final String property_key;
+
+        /**
+         * Constructs a new exception
+         * @param message Error message
+         * @param property_key Name of the property that wasn't found
+         */
+        public PropertyNotFoundException(String message, String property_key) {
+            super(message);
+            this.property_key = property_key;
+        }
+    }
+
+
+    /**
+     * Get a property with a specific name as generic <code>Object</code>
+     * @param key MATKEY_XXX key constant
+     * @return  null if the property wasn't there or hasn't
+     * the desired output type. The returned <code>Object</code> can be
+     * casted to the expected data type for the property. Primitive
+     * types are represented by their boxed variants.
+     */
+    public Object getProperty(String key) throws PropertyNotFoundException {
+
+        for (Property prop : properties)  {
+            if (prop.key.equals(key)){
+                return prop.value;
+            }
+        }
+        throw new PropertyNotFoundException("Unable to find material property: ",key);
+    }
+
+   /**
+     * Get a material property as float array
+     * @param key MATKEY_XXX key constant
+      * @throws PropertyNotFoundException - if the property can't be found
+      * or if it has the wrong data type.
+     */
+    public float[] getPropertyAsFloatArray(String key) throws PropertyNotFoundException {
+
+        Object obj = getProperty(key);
+        if (obj instanceof float[]) {
+            return (float[]) obj;
+        }
+        String msg = "The data type requested (float[]) doesn't match the " +
+            "real data type of the material property";
+        DefaultLogger.get().error(msg);
+       throw new PropertyNotFoundException(msg,key);
+    }
+
+
+     /**
+     * Get a floating-point material property
+     * @param key MATKEY_XXX key constant
+     * @return The value of the property.
+      * @throws PropertyNotFoundException - if the property can't be found
+      * or if it has the wrong data type.
+     */
+    public float getPropertyAsFloat(String key) throws PropertyNotFoundException {
+
+        Object obj = getProperty(key);
+        if (obj instanceof Float) {
+            return (Float) obj;
+        }
+        String msg = "The data type requested (Float) doesn't match the " +
+            "real data type of the material property";
+        DefaultLogger.get().error(msg);
+       throw new PropertyNotFoundException(msg,key);
+    }
+
+
+    /**
+     * Get an integer material property
+     * @param key MATKEY_XXX key constant
+     * @return The value of the property.
+      * @throws PropertyNotFoundException - if the property can't be found
+      * or if it has the wrong data type.
+     */
+    public int getPropertyAsInt(String key) throws PropertyNotFoundException {
+
+        Object obj = getProperty(key);
+        if (obj instanceof Integer) {
+            return (Integer) obj;
+        }
+        String msg = "The data type requested (Integer) doesn't match the " +
+            "real data type of the material property";
+        DefaultLogger.get().error(msg);
+       throw new PropertyNotFoundException(msg,key);
+    }
+
+
+    /**
+     * Get a material property string
+     * @param key MATKEY_XXX key constant
+     * @return The value of the property.
+      * @throws PropertyNotFoundException - if the property can't be found
+      * or if it has the wrong data type.
+     */
+    public String getPropertyAsString(String key) throws PropertyNotFoundException {
+
+        Object obj = getProperty(key);
+        if (obj instanceof String) {
+            return (String) obj;
+        }
+        String msg = "The data type requested (java.lang.String) doesn't match the " +
+            "real data type of the material property";
+        DefaultLogger.get().error(msg);
+       throw new PropertyNotFoundException(msg,key);
+    }
+
+
+    /**
+     * Material key: defines the name of the material
+     * The type of this material property is <code>String</code>
+     */
     public static final String MATKEY_NAME = "$mat.name";
 
+    /**
+     * Material key: defines the diffuse base color of the material
+     * The type of this material property is <code>float[]</code>.
+     * The array has 4 or 3 components in RGB(A) order.
+     */
+    public static final String MATKEY_COLOR_DIFFUSE = "$clr.diffuse";
+
+    /**
+     * Material key: defines the specular base color of the material
+     * The type of this material property is <code>float[]</code>.
+     * The array has 4 or 3 components in RGB(A) order.
+     */
+    public static final String MATKEY_COLOR_SPECULAR = "$clr.specular";
+
+    /**
+     * Material key: defines the ambient base color of the material
+     * The type of this material property is <code>float[]</code>.
+     * The array has 4 or 3 components in RGB(A) order.
+     */
+    public static final String MATKEY_COLOR_AMBIENT = "$clr.ambient";
+
+    /**
+     * Material key: defines the emissive base color of the material
+     * The type of this material property is <code>float[]</code>.
+     * The array has 4 or 3 components in RGB(A) order.
+     */
+    public static final String MATKEY_COLOR_EMISSIVE = "$clr.emissive";
 
     /**
      * Specifies the blend operation to be used to combine the Nth
@@ -72,66 +235,54 @@ public class Material extends Mappable {
     }
 
     /**
-     * @see MATKEY_TEXOP_DIFFUSE()
+     * @see <code>MATKEY_TEXOP_DIFFUSE</code>
      */
     public static String MATKEY_TEXOP_SPECULAR(int N) {
         return "$tex.op.specular[" + N + "]";
     }
 
     /**
-     * @see MATKEY_TEXOP_DIFFUSE()
+     * @see <code>MATKEY_TEXOP_DIFFUSE</code>
      */
     public static String MATKEY_TEXOP_AMBIENT(int N) {
         return "$tex.op.ambient[" + N + "]";
     }
 
     /**
-     * @see MATKEY_TEXOP_DIFFUSE()
+     * @see <code>MATKEY_TEXOP_DIFFUSE</code>
      */
     public static String MATKEY_TEXOP_EMISSIVE(int N) {
         return "$tex.op.emissive[" + N + "]";
     }
 
     /**
-     * @see MATKEY_TEXOP_DIFFUSE()
+     * @see <code>MATKEY_TEXOP_DIFFUSE</code>
      */
     public static String MATKEY_TEXOP_NORMALS(int N) {
         return "$tex.op.normals[" + N + "]";
     }
 
     /**
-     * @see MATKEY_TEXOP_DIFFUSE()
+     * @see <code>MATKEY_TEXOP_DIFFUSE</code>
      */
     public static String MATKEY_TEXOP_HEIGHT(int N) {
         return "$tex.op.height[" + N + "]";
     }
 
     /**
-     * @see MATKEY_TEXOP_DIFFUSE()
+     * @see <code>MATKEY_TEXOP_DIFFUSE</code>
      */
     public static String MATKEY_TEXOP_SHININESS(int N) {
         return "$tex.op.shininess[" + N + "]";
     }
 
     /**
-     * @see MATKEY_TEXOP_DIFFUSE()
+     * @see <code>MATKEY_TEXOP_DIFFUSE</code>
      */
     public static String MATKEY_TEXOP_OPACITY(int N) {
         return "$tex.op.opacity[" + N + "]";
     }
 
 
-    /**
-     * Construction from a given parent object and array index
-     *
-     * @param parent Must be valid, null is not allowed
-     * @param index  Valied index in the parent's list
-     */
-    public Material(Object parent, int index) {
-        super(parent, index);
-    }
-
-    protected void onMap() throws NativeError {
 
-    }
 }

+ 149 - 0
port/jAssimp/src/assimp/Matrix3x3.java

@@ -0,0 +1,149 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development Team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the ASSIMP team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the ASSIMP Development Team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+package assimp;
+
+/**
+ * Represents a 3x3 row major matrix
+ *
+ * @author Aramis (Alexander Gessler)
+ * @version 1.0
+ */
+public class Matrix3x3  {
+
+
+    /**
+     * Default constructor. Initializes the matrix with its identity
+     */
+    public  Matrix3x3() {
+        coeff[0] = coeff[4] = coeff[8] = 1.0f;
+    }
+
+    /**
+     * Copy constructor
+     * @param other Matrix to be copied
+     */
+    public  Matrix3x3 ( Matrix3x3 other) {
+        System.arraycopy(other.coeff, 0, this.coeff, 0, 9);
+    }
+
+    /**
+     * Construction from nine given coefficents
+     * @param a1
+     * @param a2
+     * @param a3
+     * @param b1
+     * @param b2
+     * @param b3
+     * @param c1
+     * @param c2
+     * @param c3
+     */
+    public Matrix3x3 (float a1, float a2, float a3,
+                      float b1, float b2, float b3,
+                      float c1, float c2, float c3) {
+
+        coeff[0] = a1;
+        coeff[1] = a2;
+        coeff[2] = a3;
+        coeff[3] = b1;
+        coeff[4] = b2;
+        coeff[5] = b3;
+        coeff[6] = c1;
+        coeff[7] = c2;
+        coeff[8] = c3;
+    }
+
+
+    /**
+     * Copy constructor (construction from a 4x4 matrix)
+     * @param other Matrix to be copied
+     */
+    public  Matrix3x3 ( Matrix4x4 other) {
+        coeff[0] = other.coeff[0];
+        coeff[1] = other.coeff[1];
+        coeff[2] = other.coeff[2];
+        coeff[3] = other.coeff[4];
+        coeff[4] = other.coeff[5];
+        coeff[5] = other.coeff[6];
+        coeff[6] = other.coeff[8];
+        coeff[7] = other.coeff[9];
+        coeff[8] = other.coeff[10];
+    }
+
+
+    /**
+     * The coefficients of the matrix
+     */
+    public float[] coeff = new float[9];
+
+
+    /**
+     * Returns a field in the matrix
+     * @param row Row index
+     * @param column Column index
+     * @return The corresponding field value
+     */
+    public final float get(int row, int column) {
+        assert(row <= 2 && column <= 2);
+        return coeff[row*3+column];
+    }
+
+
+    /**
+     * Multiplies *this* matrix with another matrix
+     * @param m Matrix to multiply with
+     * @return Output matrix
+     */
+    public final Matrix3x3 Mul(Matrix3x3 m) {
+
+        return new Matrix3x3(
+            m.coeff[0] * coeff[0] + m.coeff[3] * coeff[1] + m.coeff[6] * coeff[2],
+		    m.coeff[1] * coeff[0] + m.coeff[4] * coeff[1] + m.coeff[7] * coeff[2],
+		    m.coeff[2] * coeff[0] + m.coeff[5] * coeff[1] + m.coeff[8] * coeff[2],
+		    m.coeff[0] * coeff[3] + m.coeff[3] * coeff[4] + m.coeff[6] * coeff[5],
+		    m.coeff[1] * coeff[3] + m.coeff[4] * coeff[4] + m.coeff[7] * coeff[5],
+		    m.coeff[2] * coeff[3] + m.coeff[5] * coeff[4] + m.coeff[8] * coeff[5],
+		    m.coeff[0] * coeff[6] + m.coeff[3] * coeff[7] + m.coeff[6] * coeff[8],
+		    m.coeff[1] * coeff[6] + m.coeff[4] * coeff[7] + m.coeff[7] * coeff[8],
+		    m.coeff[2] * coeff[6] + m.coeff[5] * coeff[7] + m.coeff[8] * coeff[8]);
+    }
+}

+ 179 - 0
port/jAssimp/src/assimp/Matrix4x4.java

@@ -0,0 +1,179 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development Team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the ASSIMP team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the ASSIMP Development Team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+package assimp;
+
+/**
+ * Represents a 4x4 row major matrix
+ *
+ * @author Aramis (Alexander Gessler)
+ * @version 1.0
+ */
+public class Matrix4x4  {
+
+
+    /**
+     * Default constructor. Initializes the matrix with its identity
+     */
+    public  Matrix4x4() {
+        coeff[0] = coeff[5] = coeff[10] = coeff[15] = 1.0f;
+    }
+
+    /**
+     * Copy constructor
+     * @param other Matrix to be copied
+     */
+    public  Matrix4x4 ( Matrix4x4 other) {
+        System.arraycopy(other.coeff, 0, this.coeff, 0, 16);
+    }
+
+
+    /**
+     * Construction from 16 given coefficents
+     * @param a1
+     * @param a2
+     * @param a3
+     * @param a4
+     * @param b1
+     * @param b2
+     * @param b3
+     * @param b4
+     * @param c1
+     * @param c2
+     * @param c3
+     * @param c4
+     * @param d1
+     * @param d2
+     * @param d3
+     * @param d4
+     */
+    public Matrix4x4 (float a1, float a2, float a3, float a4,
+                      float b1, float b2, float b3, float b4,
+                      float c1, float c2, float c3, float c4,
+                      float d1, float d2, float d3, float d4) {
+
+        coeff[0] = a1;
+        coeff[1] = a2;
+        coeff[2] = a3;
+        coeff[3] = a4;
+        coeff[4] = b1;
+        coeff[5] = b2;
+        coeff[6] = b3;
+        coeff[7] = b4;
+        coeff[8] = c1;
+        coeff[9] = c2;
+        coeff[10] = c3;
+        coeff[11] = c4;
+        coeff[12] = d1;
+        coeff[13] = d2;
+        coeff[14] = d3;
+        coeff[15] = d4;
+    }
+
+
+    /**
+     * Copy constructor (construction from a 4x4 matrix)
+     * @param other Matrix to be copied
+     */
+    public  Matrix4x4 ( Matrix3x3 other) {
+        coeff[0] = other.coeff[0];
+        coeff[1] = other.coeff[1];
+        coeff[2] = other.coeff[2];
+        coeff[4] = other.coeff[3];
+        coeff[5] = other.coeff[4];
+        coeff[6] = other.coeff[5];
+        coeff[8] = other.coeff[6];
+        coeff[9] = other.coeff[7];
+        coeff[10] = other.coeff[8];
+        coeff[15] = 1.0f;
+    }
+
+
+    /**
+     * The coefficients of the matrix
+     */
+    public float[] coeff = new float[16];
+
+
+    /**
+     * Returns a field in the matrix
+     * @param row Row index
+     * @param column Column index
+     * @return The corresponding field value
+     */
+    public final float get(int row, int column) {
+        assert(row <= 3 && column <= 3);
+        return coeff[row*4+column];
+    }
+
+
+    /**
+     * Computes the transpose of the matrix. *this* matrix
+     * will be modified!
+     */
+    public final Matrix4x4 transpose()  {
+
+       float fTemp = coeff[1*4 +0];
+       coeff[1*4 +0] = coeff[0*4 +1];
+       coeff[0*4 +1] = fTemp;
+
+       fTemp = coeff[2*4 +0];
+       coeff[2*4 +0] = coeff[0*4 +2];
+       coeff[0*4 +2] = fTemp;
+
+       fTemp = coeff[2*4 +1];
+       coeff[2*4 +1] = coeff[1*4 +2];
+       coeff[1*4 +2] = fTemp;
+
+       fTemp = coeff[3*4 +0];
+       coeff[3*4 +0] = coeff[0*4 +3];
+       coeff[0*4 +3] = fTemp;
+
+       fTemp = coeff[3*4 +1];
+       coeff[3*4 +1] = coeff[1*4 +3];
+       coeff[1*4 +3] = fTemp;
+
+       fTemp = coeff[3*4 +2];
+       coeff[3*4 +2] = coeff[2*4 +3];
+       coeff[2*4 +3] = fTemp;
+       return this;
+    }
+}

+ 102 - 322
port/jAssimp/src/assimp/Mesh.java

@@ -60,48 +60,23 @@ import java.awt.*;
  * @author Aramis (Alexander Gessler)
  * @version 1.0
  */
-public class Mesh extends Mappable {
+public class Mesh {
 
     /**
      * Defines the maximum number of UV(W) channels that are available
      * for a mesh. If a loader finds more channels in a file, some
      * will be skipped
      */
-    private static final int MAX_NUMBER_OF_TEXTURECOORDS = 0x4;
+    public static final int MAX_NUMBER_OF_TEXTURECOORDS = 0x4;
 
     /**
      * Defines the maximum number of vertex color channels that are
      * available for a mesh. If a loader finds more channels in a file,
      * some will be skipped
      */
-    private static final int MAX_NUMBER_OF_COLOR_SETS = 0x4;
+    public static final int MAX_NUMBER_OF_COLOR_SETS = 0x4;
 
 
-    /**
-     * Specifies which vertex components are existing in
-     * the native implementation. If a member is null here,
-     * although it is existing, it hasn't yet been mapped
-     * into memory
-     */
-    private int m_iPresentFlags = 0;
-
-    private static final int PF_POSITION = 0x1;
-    private static final int PF_NORMAL = 0x2;
-    private static final int PF_TANGENTBITANGENT = 0x4;
-    private static final int PF_BONES = 0x8;
-    private static final int PF_VERTEXCOLOR = 0x1000;
-    private static final int PF_UVCOORD = 0x10000;
-
-    private static int PF_VERTEXCOLORn(int n) {
-        assert(n <= MAX_NUMBER_OF_COLOR_SETS);
-        return PF_VERTEXCOLOR << n;
-    }
-
-    private static int PF_UVCOORDn(int n) {
-        assert(n <= MAX_NUMBER_OF_TEXTURECOORDS);
-        return PF_UVCOORD << n;
-    }
-
     /**
      * Contains the vertices loaded from the model
      */
@@ -150,53 +125,28 @@ public class Mesh extends Mappable {
      */
     private int[] m_vFaces = null;
 
-    /**
-     * Number of vertices in the mesh
-     */
-    private int m_iNumVertices;
 
     /**
-     * Number of faces in the mesh
+     * Bones which are influencing the mesh
      */
-    private int m_iNumFaces;
-
-    /**
-     * Number of bones in the mesh
-     */
-    private int m_iNumBones;
+    private Bone[] m_vBones = null;
 
     /**
      * Material index of the mesh
      */
-    private int m_iMaterialIndex;
-
-
-    /**
-     * Construction from a given parent object and array index
-     *
-     * @param parent Parent object
-     * @param index  Valied index in the parent's list
-     */
-    public Mesh(Object parent, int index) throws NativeError {
-        super(parent, index);
-
-        assert (parent instanceof Scene);
+    private int m_iMaterialIndex = 0;
 
-        Scene sc = (Scene) parent;
-        if (0xffffffff == this._NativeInitMembers(
-                sc.getImporter().getContext(), this.getArrayIndex())) {
-            throw new NativeError("Unable to intiailise class members via JNI");
-        }
-    }
 
     /**
      * Check whether there are vertex positions in the model
-     * <code>getVertex()</code> will assert this.
+     * <code>getPosition()</code> will assert this.
      *
-     * @return true if vertex positions are available.
+     * @return true if vertex positions are available. This is
+     *         guaranteed to be always true, except for scenes which contain only
+     *         animation skeletons.
      */
-    public boolean hasPositions() {
-        return 0 != (this.m_iPresentFlags & PF_POSITION);
+    public final boolean hasPositions() {
+        return null != this.m_vVertices;
     }
 
     /**
@@ -205,8 +155,8 @@ public class Mesh extends Mappable {
      *
      * @return true if vertex normals are available.
      */
-    public boolean hasNormals() {
-        return 0 != (this.m_iPresentFlags & PF_NORMAL);
+    public final boolean hasNormals() {
+        return null != this.m_vNormals;
     }
 
     /**
@@ -215,8 +165,8 @@ public class Mesh extends Mappable {
      *
      * @return true if vertex normals are available.
      */
-    public boolean hasBones() {
-        return 0 != (this.m_iPresentFlags & PF_BONES);
+    public final boolean hasBones() {
+        return null != this.m_vBones;
     }
 
     /**
@@ -225,8 +175,8 @@ public class Mesh extends Mappable {
      *
      * @return true if vertex tangents and bitangents are available.
      */
-    public boolean hasTangentsAndBitangents() {
-        return 0 != (this.m_iPresentFlags & PF_TANGENTBITANGENT);
+    public final boolean hasTangentsAndBitangents() {
+        return null != this.m_vBitangents && null != this.m_vTangents;
     }
 
     /**
@@ -236,8 +186,8 @@ public class Mesh extends Mappable {
      * @param n UV coordinate set index
      * @return true the uv coordinate set is available.
      */
-    public boolean hasUVCoords(int n) {
-        return 0 != (this.m_iPresentFlags & PF_UVCOORDn(n));
+    public final boolean hasUVCoords(int n) {
+        return n < this.m_avUVs.length && null != this.m_avUVs[n];
     }
 
     /**
@@ -247,8 +197,8 @@ public class Mesh extends Mappable {
      * @param n Vertex color set index
      * @return true the vertex color set is available.
      */
-    public boolean hasVertexColors(int n) {
-        return 0 != (this.m_iPresentFlags & PF_VERTEXCOLORn(n));
+    public final boolean hasVertexColors(int n) {
+        return n < this.m_avColors.length && null != this.m_avColors[n];
     }
 
 
@@ -258,8 +208,8 @@ public class Mesh extends Mappable {
      * @return Number of vertices in the model. This could be 0 in some
      *         extreme cases although loaders should filter such cases out
      */
-    public int getNumVertices() {
-        return m_iNumVertices;
+    public final int getNumVertices() {
+        return m_vVertices.length;
     }
 
 
@@ -269,8 +219,8 @@ public class Mesh extends Mappable {
      * @return Number of faces in the model. This could be 0 in some
      *         extreme cases although loaders should filter such cases out
      */
-    public int getNumFaces() {
-        return m_iNumFaces;
+    public final int getNumFaces() {
+        return m_vFaces.length;
     }
 
     /**
@@ -278,8 +228,8 @@ public class Mesh extends Mappable {
      *
      * @return Number of bones in the model.
      */
-    public int getNumBones() {
-        return m_iNumBones;
+    public final int getNumBones() {
+        return m_vBones.length;
     }
 
     /**
@@ -287,7 +237,7 @@ public class Mesh extends Mappable {
      *
      * @return Zero-based material index
      */
-    public int getMaterialIndex() {
+    public final int getMaterialIndex() {
         return m_iMaterialIndex;
     }
 
@@ -298,12 +248,10 @@ public class Mesh extends Mappable {
      * @param afOut  Output array, size must at least be 3
      *               Receives the vertex position components in x,y,z order
      */
-    public void getPosition(int iIndex, float[] afOut) {
-        assert(this.hasPositions());
-        assert(afOut.length >= 3);
-        assert(iIndex < this.getNumVertices()); // explicitly assert here, no AIOOBE
-
-        if (null == this.m_vVertices) this.mapVertices();
+    public final void getPosition(int iIndex, float[] afOut) {
+        assert(hasPositions() &&
+                afOut.length >= 3 &&
+                iIndex < this.getNumVertices());
 
         iIndex *= 3;
         afOut[0] = this.m_vVertices[iIndex];
@@ -319,13 +267,10 @@ public class Mesh extends Mappable {
      * @param iOutBase Start index in the output array
      *                 Receives the vertex position components in x,y,z order
      */
-    public void getPosition(int iIndex, float[] afOut, int iOutBase) {
-        assert(this.hasPositions());
-        assert(afOut.length >= 3);
-        assert(iOutBase + 3 <= afOut.length);
-        assert(iIndex < this.getNumVertices()); // explicitly assert here, no AIOOBE
-
-        if (null == this.m_vVertices) this.mapVertices();
+    public final void getPosition(int iIndex, float[] afOut, int iOutBase) {
+        assert(hasPositions() &&
+                iOutBase + 3 <= afOut.length &&
+                iIndex < this.getNumVertices());
 
         iIndex *= 3;
         afOut[iOutBase] = this.m_vVertices[iIndex];
@@ -340,9 +285,7 @@ public class Mesh extends Mappable {
      * @return Array of floats, size is numverts * 3. Component ordering
      *         is xyz.
      */
-    public float[] getPositionArray() {
-        assert(this.hasPositions());
-        if (null == this.m_vVertices) this.mapVertices();
+    public final float[] getPositionArray() {
         return this.m_vVertices;
     }
 
@@ -353,17 +296,15 @@ public class Mesh extends Mappable {
      * @param afOut  Output array, size must at least be 3
      *               Receives the vertex normal components in x,y,z order
      */
-    public void getNormal(int iIndex, float[] afOut) {
-        assert(this.hasNormals());
-        assert(afOut.length >= 3);
-        assert(iIndex < this.getNumVertices()); // explicitly assert here, no AIOOBE
-
-        if (null == this.m_vNormals) this.mapNormals();
+    public final void getNormal(int iIndex, float[] afOut) {
+        assert(hasNormals() &&
+                afOut.length >= 3 &&
+                iIndex < this.getNumVertices());
 
         iIndex *= 3;
-        afOut[0] = this.m_vNormals[iIndex];
-        afOut[1] = this.m_vNormals[iIndex + 1];
-        afOut[2] = this.m_vNormals[iIndex + 2];
+        afOut[0] = this.m_vTangents[iIndex];
+        afOut[1] = this.m_vTangents[iIndex + 1];
+        afOut[2] = this.m_vTangents[iIndex + 2];
     }
 
     /**
@@ -374,13 +315,10 @@ public class Mesh extends Mappable {
      * @param iOutBase Start index in the output array
      *                 Receives the vertex normal components in x,y,z order
      */
-    public void getNormal(int iIndex, float[] afOut, int iOutBase) {
-        assert(this.hasNormals());
-        assert(afOut.length >= 3);
-        assert(iOutBase + 3 <= afOut.length);
-        assert(iIndex < this.getNumVertices()); // explicitly assert here, no AIOOBE
-
-        if (null == this.m_vNormals) this.mapNormals();
+    public final void getNormal(int iIndex, float[] afOut, int iOutBase) {
+        assert(hasNormals() &&
+                iOutBase + 3 <= afOut.length &&
+                iIndex < this.getNumVertices());
 
         iIndex *= 3;
         afOut[iOutBase] = this.m_vNormals[iIndex];
@@ -395,9 +333,7 @@ public class Mesh extends Mappable {
      * @return Array of floats, size is numverts * 3. Component ordering
      *         is xyz.
      */
-    public float[] getNormalArray() {
-        assert(this.hasNormals());
-        if (null == this.m_vNormals) this.mapNormals();
+    public final float[] getNormalArray() {
         return this.m_vNormals;
     }
 
@@ -408,12 +344,10 @@ public class Mesh extends Mappable {
      * @param afOut  Output array, size must at least be 3
      *               Receives the vertex tangent components in x,y,z order
      */
-    public void getTangent(int iIndex, float[] afOut) {
-        assert(this.hasTangentsAndBitangents());
-        assert(afOut.length >= 3);
-        assert(iIndex < this.getNumVertices()); // explicitly assert here, no AIOOBE
-
-        if (null == this.m_vTangents) this.mapTangents();
+    public final void getTangent(int iIndex, float[] afOut) {
+        assert(hasTangentsAndBitangents() &&
+                afOut.length >= 3 &&
+                iIndex < this.getNumVertices());
 
         iIndex *= 3;
         afOut[0] = this.m_vTangents[iIndex];
@@ -429,13 +363,10 @@ public class Mesh extends Mappable {
      * @param iOutBase Start index in the output array
      *                 Receives the vertex tangent components in x,y,z order
      */
-    public void getTangent(int iIndex, float[] afOut, int iOutBase) {
-        assert(this.hasTangentsAndBitangents());
-        assert(afOut.length >= 3);
-        assert(iOutBase + 3 <= afOut.length);
-        assert(iIndex < this.getNumVertices()); // explicitly assert here, no AIOOBE
-
-        if (null == this.m_vTangents) this.mapTangents();
+    public final void getTangent(int iIndex, float[] afOut, int iOutBase) {
+        assert(hasTangentsAndBitangents() &&
+                iOutBase + 3 <= afOut.length &&
+                iIndex < this.getNumVertices());
 
         iIndex *= 3;
         afOut[iOutBase] = this.m_vTangents[iIndex];
@@ -450,9 +381,7 @@ public class Mesh extends Mappable {
      * @return Array of floats, size is numverts * 3. Component ordering
      *         is xyz.
      */
-    public float[] getTangentArray() {
-        assert(this.hasTangentsAndBitangents());
-        if (null == this.m_vTangents) this.mapTangents();
+    public final float[] getTangentArray() {
         return this.m_vTangents;
     }
 
@@ -463,12 +392,10 @@ public class Mesh extends Mappable {
      * @param afOut  Output array, size must at least be 3
      *               Receives the vertex bitangent components in x,y,z order
      */
-    public void getBitangent(int iIndex, float[] afOut) {
-        assert(this.hasTangentsAndBitangents());
-        assert(afOut.length >= 3);
-        assert(iIndex < this.getNumVertices()); // explicitly assert here, no AIOOBE
-
-        if (null == this.m_vBitangents) this.mapBitangents();
+    public final void getBitangent(int iIndex, float[] afOut) {
+        assert(hasTangentsAndBitangents() &&
+                afOut.length >= 3 && 3 >= afOut.length &&
+                iIndex < this.getNumVertices());
 
         iIndex *= 3;
         afOut[0] = this.m_vBitangents[iIndex];
@@ -484,13 +411,10 @@ public class Mesh extends Mappable {
      * @param iOutBase Start index in the output array
      *                 Receives the vertex bitangent components in x,y,z order
      */
-    public void getBitangent(int iIndex, float[] afOut, int iOutBase) {
-        assert(this.hasTangentsAndBitangents());
-        assert(afOut.length >= 3);
-        assert(iOutBase + 3 <= afOut.length);
-        assert(iIndex < this.getNumVertices()); // explicitly assert here, no AIOOBE
-
-        if (null == this.m_vBitangents) this.mapBitangents();
+    public final void getBitangent(int iIndex, float[] afOut, int iOutBase) {
+        assert(hasTangentsAndBitangents() &&
+                iOutBase + 3 <= afOut.length &&
+                iIndex < this.getNumVertices());
 
         iIndex *= 3;
         afOut[iOutBase] = this.m_vBitangents[iIndex];
@@ -505,9 +429,8 @@ public class Mesh extends Mappable {
      * @return Array of floats, size is numverts * 3. Component ordering
      *         is xyz.
      */
-    public float[] getBitangentArray() {
+    public final float[] getBitangentArray() {
         assert(this.hasTangentsAndBitangents());
-        if (null == this.m_vBitangents) this.mapBitangents();
         return this.m_vBitangents;
     }
 
@@ -521,12 +444,9 @@ public class Mesh extends Mappable {
      *                <code>getNumUVComponents</code> returns for <code>channel</code>
      *                Receives the vertex texture coordinate, components are in u,v,w order
      */
-    public void getTexCoord(int channel, int iIndex, float[] afOut) {
-        assert(this.hasUVCoords(channel));
-        assert(afOut.length >= this.m_aiNumUVComponents[channel]);
-        assert(iIndex < this.getNumVertices()); // explicitly assert here, no AIOOBE
-
-        if (null == this.m_avUVs[channel]) this.mapUVs(channel);
+    public final void getTexCoord(int channel, int iIndex, float[] afOut) {
+        assert(this.hasUVCoords(channel) && afOut.length >= 4 &&
+                4 >= afOut.length && iIndex < this.getNumVertices());
 
         iIndex *= this.m_aiNumUVComponents[channel];
         for (int i = 0; i < this.m_aiNumUVComponents[channel]; ++i) {
@@ -544,13 +464,9 @@ public class Mesh extends Mappable {
      *                 Receives the vertex texture coordinate, components are in u,v,w order
      * @param iOutBase Start index in the output array
      */
-    public void getTexCoord(int channel, int iIndex, float[] afOut, int iOutBase) {
-        assert(this.hasUVCoords(channel));
-        assert(afOut.length >= this.m_aiNumUVComponents[channel]);
-        assert(iOutBase + this.m_aiNumUVComponents[channel] <= afOut.length);
-        assert(iIndex < this.getNumVertices()); // explicitly assert here, no AIOOBE
-
-        if (null == this.m_avUVs[channel]) this.mapUVs(channel);
+    public final void getTexCoord(int channel, int iIndex, float[] afOut, int iOutBase) {
+        assert(this.hasUVCoords(channel) && afOut.length >= 4 &&
+                iOutBase + 4 <= afOut.length && iIndex < this.getNumVertices());
 
         iIndex *= this.m_aiNumUVComponents[channel];
         for (int i = 0; i < this.m_aiNumUVComponents[channel]; ++i) {
@@ -565,9 +481,8 @@ public class Mesh extends Mappable {
      * @return Array of floats, size is numverts * <code>getNumUVComponents
      *         (channel)</code>. Component ordering is uvw.
      */
-    public float[] getTexCoordArray(int channel) {
-        assert(this.hasUVCoords(channel));
-        if (null == this.m_avUVs[channel]) this.mapUVs(channel);
+    public final float[] getTexCoordArray(int channel) {
+        assert(channel < MAX_NUMBER_OF_TEXTURECOORDS);
         return this.m_avUVs[channel];
     }
 
@@ -579,12 +494,9 @@ public class Mesh extends Mappable {
      * @param afOut   Output array, size must at least be 4
      *                Receives the vertex color components in r,g,b,a order
      */
-    public void getVertexColor(int channel, int iIndex, float[] afOut) {
-        assert(this.hasVertexColors(channel));
-        assert(afOut.length >= 4);
-        assert(iIndex < this.getNumVertices()); // explicitly assert here, no AIOOBE
-
-        if (null == this.m_avColors[channel]) this.mapColors(channel);
+    public final void getVertexColor(int channel, int iIndex, float[] afOut) {
+        assert(this.hasVertexColors(channel) && afOut.length >= 4 &&
+                iIndex < this.getNumVertices());
 
         iIndex *= 4;   // RGBA order
         afOut[0] = this.m_avColors[channel][iIndex];
@@ -600,7 +512,7 @@ public class Mesh extends Mappable {
      * @param iIndex  Zero-based index of the vertex
      * @return Vertex color value packed as <code>java.awt.Color</code>
      */
-    public Color getVertexColor(int channel, int iIndex) {
+    public final Color getVertexColor(int channel, int iIndex) {
 
         float[] afColor = new float[4];
         this.getVertexColor(channel, iIndex, afColor);
@@ -616,13 +528,9 @@ public class Mesh extends Mappable {
      *                 Receives the vertex color components in r,g,b,a order
      * @param iOutBase Start index in the output array
      */
-    public void getVertexColor(int channel, int iIndex, float[] afOut, int iOutBase) {
-        assert(this.hasVertexColors(channel));
-        assert(afOut.length >= 4);
-        assert(iOutBase + 4 <= afOut.length);
-        assert(iIndex < this.getNumVertices()); // explicitly assert here, no AIOOBE
-
-        if (null == this.m_avColors[channel]) this.mapColors(channel);
+    public final void getVertexColor(int channel, int iIndex, float[] afOut, int iOutBase) {
+        assert(this.hasVertexColors(channel) && afOut.length >= 4 &&
+                iOutBase + 4 <= afOut.length && iIndex < this.getNumVertices());
 
         iIndex *= 4;   // RGBA order
         afOut[iOutBase] = this.m_avColors[channel][iIndex];
@@ -638,9 +546,8 @@ public class Mesh extends Mappable {
      * @return Array of floats, size is numverts * 3. Component ordering
      *         is xyz.
      */
-    public float[] getVertexColorArray(int channel) {
-        assert(this.hasVertexColors(channel));
-        if (null == this.m_avColors[channel]) this.mapColors(channel);
+    public final float[] getVertexColorArray(int channel) {
+        assert(channel < MAX_NUMBER_OF_COLOR_SETS);
         return this.m_avColors[channel];
     }
 
@@ -652,9 +559,8 @@ public class Mesh extends Mappable {
      *               returned by <code>getNumFaces()</code>
      * @param aiOut  Output array, size must at least be 3
      */
-    public void getFace(int iIndex, int[] aiOut) {
+    public final void getFace(int iIndex, int[] aiOut) {
         assert(aiOut.length >= 3);
-        if (null == this.m_vFaces) this.mapFaces();
         iIndex *= 3;
         aiOut[0] = this.m_vFaces[iIndex];
         aiOut[1] = this.m_vFaces[iIndex + 1];
@@ -669,9 +575,8 @@ public class Mesh extends Mappable {
      * @param aiOut    Output array, size must at least be 3
      * @param iOutBase Start index in the output array
      */
-    public void getFace(int iIndex, int[] aiOut, int iOutBase) {
+    public final void getFace(int iIndex, int[] aiOut, int iOutBase) {
         assert(aiOut.length >= 3);
-        if (null == this.m_vFaces) this.mapFaces();
         iIndex *= 3;
         aiOut[0] = this.m_vFaces[iIndex];
         aiOut[iOutBase + 1] = this.m_vFaces[iIndex + 1];
@@ -687,156 +592,31 @@ public class Mesh extends Mappable {
      *         of three indices (higher level polygons are automatically
      *         triangulated by the library)
      */
-    public int[] getFaceArray() {
-        if (null == this.m_vFaces) this.mapFaces();
+    public final int[] getFaceArray() {
         return this.m_vFaces;
     }
 
 
-    protected void onMap() throws NativeError {
-        // map all vertex component arrays into JVM memory
-        if (this.hasPositions()) this.mapVertices();
-        if (this.hasNormals()) this.mapNormals();
-        if (this.hasTangentsAndBitangents()) {
-            this.mapTangents();
-            this.mapBitangents();
-        }
-        for (int i = 0; i < MAX_NUMBER_OF_COLOR_SETS; ++i) {
-            if (this.hasVertexColors(i)) this.mapColors(i);
-        }
-        for (int i = 0; i < MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
-            if (this.hasUVCoords(i)) this.mapUVs(i);
-        }
-        DefaultLogger.get().debug("Mesh.onMap successful");
-    }
-
-
-    private void mapVertices() {
-        this.m_vVertices = new float[this.getNumVertices() * 3];
-        if (0xffffffff == this._NativeMapVertices(((Scene) this.getParent()).
-                getImporter().getContext(), this.getArrayIndex(),
-                this.m_vVertices)) {
-            // this should occur rarely. No need to throw an exception,
-            // simply write to log and let the array at 0.0f
-            DefaultLogger.get().error("Unable to map vertices into JVM memory");
-        }
-    }
-
-    private void mapNormals() {
-        this.m_vNormals = new float[this.getNumVertices() * 3];
-        if (0xffffffff == this._NativeMapNormals(((Scene) this.getParent()).
-                getImporter().getContext(), this.getArrayIndex(),
-                this.m_vNormals)) {
-            // this should occur rarely. No need to throw an exception,
-            // simply write to log and let the array at 0.0f
-            DefaultLogger.get().error("Unable to map normals into JVM memory");
-        }
-    }
-
-    private void mapTangents() {
-        this.m_vTangents = new float[this.getNumVertices() * 3];
-        if (0xffffffff == this._NativeMapTangents(((Scene) this.getParent()).
-                getImporter().getContext(), this.getArrayIndex(),
-                this.m_vTangents)) {
-            // this should occur rarely. No need to throw an exception,
-            // simply write to log and let the array at 0.0f
-            DefaultLogger.get().error("Unable to map tangents into JVM memory");
-        }
-    }
-
-    private void mapBitangents() {
-        this.m_vBitangents = new float[this.getNumVertices() * 3];
-        if (0xffffffff == this._NativeMapBitangents(((Scene) this.getParent()).
-                getImporter().getContext(), this.getArrayIndex(),
-                this.m_vBitangents)) {
-            // this should occur rarely. No need to throw an exception,
-            // simply write to log and let the array at 0.0f
-            DefaultLogger.get().error("Unable to map bitangents into JVM memory");
-        }
-    }
-
-    private void mapFaces() {
-        this.m_vFaces = new int[this.getNumFaces() * 3];
-        if (0xffffffff == this._NativeMapFaces(((Scene) this.getParent()).
-                getImporter().getContext(), this.getArrayIndex(),
-                this.m_vFaces)) {
-            // this should occur rarely. No need to throw an exception,
-            // simply write to log and let the array at 0
-            DefaultLogger.get().error("Unable to map faces into JVM memory");
-        }
-    }
-
-    private void mapUVs(int channel) {
-        this.m_avUVs[channel] = new float[this.getNumVertices() * this.m_aiNumUVComponents[channel]];
-        if (0xffffffff == this._NativeMapUVs(((Scene) this.getParent()).
-                getImporter().getContext(), this.getArrayIndex(),
-                channel, this.m_avUVs[channel])) {
-            // this should occur rarely. No need to throw an exception,
-            // simply write to log and let the array at 0.0f
-            DefaultLogger.get().error("Unable to map UV coordinate set " + channel + " into JVM memory");
-        }
-    }
-
-    private void mapColors(int channel) {
-        this.m_avColors[channel] = new float[this.getNumVertices() * 4];
-        if (0xffffffff == this._NativeMapColors(((Scene) this.getParent()).
-                getImporter().getContext(), this.getArrayIndex(),
-                channel, this.m_avColors[channel])) {
-            // this should occur rarely. No need to throw an exception,
-            // simply write to log and let the array at 0.0f
-            DefaultLogger.get().error("Unable to map vertex color channel " + channel + " into JVM memory");
-        }
-    }
-
-
     /**
-     * JNI bridge function - for internal use only
-     * Retrieve a bit combination which indicates which vertex
-     * components are existing in the model.
+     * Provides access to the array of all bones influencing this
+     * mesh.
      *
-     * @param context Current importer context (imp.hashCode)
-     * @return Combination of the PF_XXX constants
+     * @return Bone array
      */
-    private native int _NativeGetPresenceFlags(long context, long index);
+    public final Bone[] getBonesArray() {
+        assert (null != this.m_vBones);
+        return this.m_vBones;
+    }
 
-    /**
-     * JNI bridge function - for internal use only
-     * Initialise class members
-     *
-     * @param context Current importer context (imp.hashCode)
-     * @return Number of vertices in the mesh
-     */
-    private native int _NativeInitMembers(long context, long index);
 
     /**
-     * JNI bridge function - for internal use only
-     * Retrieve the number of uvw components for a channel
+     * Get a bone influencing the mesh
      *
-     * @param context Current importer context (imp.hashCode)
-     * @param out     Output array. Size must be MAX_NUMBER_OF_TEXTURECOORDS.
-     * @return 0xffffffff if an error occured
+     * @param i Index of the bone
+     * @return Bone
      */
-    private native int _NativeGetNumUVComponents(long context, long index, int[] out);
-
-    /**
-     * JNI bridge function - for internal use only
-     * Map the position component of the mesh's vertices into memory
-     *
-     * @param context Current importer context (imp.hashCode)
-     * @param out     Output array. Must be large enough
-     * @return 0xffffffff if an error occured
-     */
-    private native int _NativeMapVertices(long context, long index, float[] out);
-
-    private native int _NativeMapNormals(long context, long index, float[] out);
-
-    private native int _NativeMapTangents(long context, long index, float[] out);
-
-    private native int _NativeMapBitangents(long context, long index, float[] out);
-
-    private native int _NativeMapUVs(long context, long index, int channel, float[] out);
-
-    private native int _NativeMapColors(long context, long index, int channel, float[] out);
-
-    private native int _NativeMapFaces(long context, long index, int[] out);
+    public final Bone getBone(int i) {
+        assert (null != this.m_vBones && i < this.m_vBones.length);
+        return this.m_vBones[i];
+    }
 }

+ 3 - 3
port/jAssimp/src/assimp/NativeError.java → port/jAssimp/src/assimp/NativeException.java

@@ -45,13 +45,13 @@ package assimp;
  * Exception class used by jAssimp. It is thrown whenever an unknown error
  * occurs in the JNI bridge between the native Assimp library and the Java VM.
  */
-public class NativeError extends Exception {
+public class NativeException extends Exception {
 
-    public NativeError() {
+    public NativeException() {
         super("Unknown error");
     }
 
-    public NativeError(String sz) {
+    public NativeException(String sz) {
         super(sz);
     }
 }

+ 44 - 50
port/jAssimp/src/assimp/Node.java

@@ -70,7 +70,7 @@ public class Node {
      * Local transformation matrix of the node
      * Stored in row-major order.
      */
-    private float[] nodeTransform = null;
+    private Matrix4x4 nodeTransform = null;
 
 
     /**
@@ -85,15 +85,9 @@ public class Node {
      * List of all child nodes
      * May be empty
      */
-    private Vector<Node> children = null;
-    private int numChildren = 0; // temporary
-
-    /**
-     * Parent scene
-     */
-    private Scene parentScene = null;
-
+    private Node[] children = null;
 
+ 
     /**
      * Parent node or null if we're the root node of the scene
      */
@@ -101,31 +95,29 @@ public class Node {
 
     /**
      * Constructs a new node and initializes it
-     * @param parentScene Parent scene object
      * @param parentNode Parent node or null for root nodes
-     * @param index Unique index of the node
      */
-    public Node(Scene parentScene, Node parentNode, int index) {
+    public Node(Node parentNode) {
 
-        this.parentScene = parentScene;
         this.parent = parentNode;
+    }
 
-        // Initialize JNI class members, including numChildren
-        this._NativeInitMembers(parentScene.getImporter().getContext(),index);
 
-        // get all children of the node
-        for (int i = 0; i < numChildren;++i) {
-            this.children.add(new Node(parentScene, this,  ++index));
-        }
+    /**
+     * Returns the number of meshes of this node
+     * @return Number of meshes
+     */
+    public final int getNumMeshes() {
+        return meshIndices.length;
     }
 
-
     /**
      * Get a list of all meshes of this node
      *
-     * @return Array containing indices into the Scene's mesh list
+     * @return Array containing indices into the Scene's mesh list.
+     * If there are no meshes, the array is <code>null</code>
      */
-    int[] getMeshes() {
+    public final int[] getMeshes() {
         return meshIndices;
     }
 
@@ -142,7 +134,7 @@ public class Node {
      *
      * @return Row-major transformation matrix
      */
-    float[] getTransformRowMajor() {
+    public final Matrix4x4 getTransformRowMajor() {
         return nodeTransform;
     }
 
@@ -159,26 +151,10 @@ public class Node {
      *
      * @return Column-major transformation matrix
      */
-    float[] getTransformColumnMajor() {
-
-        float[] transform = new float[16];
-        transform[0] = nodeTransform[0];
-        transform[1] = nodeTransform[4];
-        transform[2] = nodeTransform[8];
-        transform[3] = nodeTransform[12];
-        transform[4] = nodeTransform[1];
-        transform[5] = nodeTransform[5];
-        transform[6] = nodeTransform[9];
-        transform[7] = nodeTransform[13];
-        transform[8] = nodeTransform[2];
-        transform[9] = nodeTransform[6];
-        transform[10] = nodeTransform[10];
-        transform[11] = nodeTransform[14];
-        transform[12] = nodeTransform[3];
-        transform[13] = nodeTransform[7];
-        transform[15] = nodeTransform[11];
-        transform[16] = nodeTransform[15];
-        return transform;
+    public final Matrix4x4 getTransformColumnMajor() {
+
+       Matrix4x4 m = new Matrix4x4( nodeTransform );
+       return m.transpose();
     }
 
 
@@ -192,7 +168,7 @@ public class Node {
      *
      * @return Node name
      */
-    public String getName() {
+    public final String getName() {
         return name;
     }
 
@@ -201,23 +177,41 @@ public class Node {
      * Get the list of all child nodes of *this* node
      * @return List of children. May be empty.
      */
-    public Vector<Node> getChildren() {
+    public final  Node[] getChildren() {
         return children;
     }
 
+    /**
+     * Get the number of child nodes of *this* node
+     * @return May be 0
+     */
+    public final int getNumChildren()  {
+        return children.length;
+    }
+
     /**
      * Get the parent node of the node
      * @return Parent node
      */
-    public Node getParent() {
+    public final Node getParent() {
         return parent;
     }
 
+
     /**
-     * Get the parent scene of the node
-     * @return Never null
+     * Searches this node and recursively all sub nodes
+     * for a node with a specific name
+     * @param _name Name of the node to search for
+     * @return Either a reference to the node or <code>null</code>
+     * if no node with this name was found.
      */
-    public Scene getParentScene() {
-        return parentScene;
+    public final Node findNode(String _name) {
+
+        if (_name.equals(name))return this;
+        for (Node node : children) {
+            Node out;
+            if (null != (out = node.findNode(_name)))return out;
+        }
+        return null;
     }
 }

+ 21 - 72
port/jAssimp/src/assimp/PostProcessStep.java

@@ -187,78 +187,27 @@ public class PostProcessStep {
             new PostProcessStep("ValidateDataStructure");
 
 
-    /**
-     * Set the vertex split limit for the "SplitLargeMeshes" process
-     * If a mesh exceeds this limit it will be splitted
-     *
-     * @param limit New vertex split limit. Pass 0xffffffff to disable
-     *              a vertex split limit. However, splitting by triangles is still active
-     *              then.
-     * @return Old vertex split limit
-     */
-    public static synchronized int setVertexSplitLimit(int limit) {
-        if (s_iVertexSplitLimit != limit) {
-            // send to the JNI bridge ...
-            s_iVertexSplitLimit = limit;
-            _NativeSetVertexSplitLimit(limit);
-        }
-        return limit;
-    }
-
-    /**
-     * Set the triangle split limit for the "SplitLargeMeshes" process
-     * If a mesh exceeds this limit it will be splitted
-     *
-     * @param limit new triangle split limit. Pass 0xffffffff to disable
-     *              a triangle split limit. However, splitting by vertices is still active
-     *              then.
-     * @return Old triangle split limit
-     */
-    public static synchronized int setTriangleSplitLimit(int limit) {
-        if (s_iTriangleSplitLimit != limit) {
-            // send to the JNI bridge ...
-            s_iTriangleSplitLimit = limit;
-            _NativeSetTriangleSplitLimit(limit);
-        }
-        return limit;
-    }
-
-    /**
-     * Set the bone weight limit for the "LimitBoneWeights" process
-     * If a mesh exceeds this limit it will be splitted
-     *
-     * @param limit new bone weight limit. Pass 0xffffffff to disable it.
-     * @return Old bone weight limit
-     */
-    public static synchronized int setSetBoneWeightLimit(int limit) {
-        if (s_iBoneWeightLimit != limit) {
-            // send to the JNI bridge ...
-            s_iBoneWeightLimit = limit;
-            _NativeSetBoneWeightLimit(limit);
-        }
-        return limit;
-    }
-
-    /**
-     * JNI bridge call. For internal use only
-     *
-     * @param limit New vertex split limit
-     */
-    private native static void _NativeSetVertexSplitLimit(int limit);
-
-    /**
-     * JNI bridge call. For internal use only
-     *
-     * @param limit New triangle split limit
-     */
-    private native static void _NativeSetTriangleSplitLimit(int limit);
-
-    /**
-     * JNI bridge call. For internal use only
-     *
-     * @param limit New bone weight limit
-     */
-    private native static void _NativeSetBoneWeightLimit(int limit);
+    /** This step tries to determine which meshes have normal vectors
+	 * that are facing inwards. 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 out.
+	 * The step inverts all infacing normals. Generally it is recommended
+	 * to enable this step.
+	*/
+    public static final PostProcessStep FixInfacingNormals =
+            new PostProcessStep("FixInfacingNormals");
+
+
+    /** Reorders triangles for vertex cache locality and thus better performance.
+	 * The step tries to improve the ACMR (average post-transform vertex cache
+	 * miss ratio) for all meshes. The step runs in O(n) and is roughly
+	 * basing on the algorithm described in this paper:
+	 * <url>http://www.cs.princeton.edu/gfx/pubs/Sander_2007_%3ETR/tipsy.pdf</url>
+	 */
+	 public static final PostProcessStep ImproveVertexLocality =
+            new PostProcessStep("ImproveVertexLocality");
 
 
     private final String myName; // for debug only

+ 147 - 0
port/jAssimp/src/assimp/Quaternion.java

@@ -0,0 +1,147 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (ASSIMP)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2008, ASSIMP Development Team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the ASSIMP team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the ASSIMP Development Team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+package assimp;
+
+
+/**
+ * Represents a rotation quaternion
+ *
+ * @author Aramis (Alexander Gessler)
+ * @version 1.0
+ */
+public class Quaternion {
+
+    public float x, y, z, w;
+
+
+    /**
+     * Construction from euler angles
+     *
+     * @param fPitch Rotation around the x axis
+     * @param fYaw   Rotation around the y axis
+     * @param fRoll  Rotation around the z axis
+     */
+    public Quaternion(float fPitch, float fYaw, float fRoll) {
+        float fSinPitch = (float) Math.sin(fPitch * 0.5F);
+        float fCosPitch = (float) Math.cos(fPitch * 0.5F);
+        float fSinYaw = (float) Math.sin(fYaw * 0.5F);
+        float fCosYaw = (float) Math.cos(fYaw * 0.5F);
+        float fSinRoll = (float) Math.sin(fRoll * 0.5F);
+        float fCosRoll = (float) Math.cos(fRoll * 0.5F);
+        float fCosPitchCosYaw = (fCosPitch * fCosYaw);
+        float fSinPitchSinYaw = (fSinPitch * fSinYaw);
+        x = fSinRoll * fCosPitchCosYaw - fCosRoll * fSinPitchSinYaw;
+        y = fCosRoll * fSinPitch * fCosYaw + fSinRoll * fCosPitch * fSinYaw;
+        z = fCosRoll * fCosPitch * fSinYaw - fSinRoll * fSinPitch * fCosYaw;
+        w = fCosRoll * fCosPitchCosYaw + fSinRoll * fSinPitchSinYaw;
+    }
+
+    /**
+     * Construction from an existing rotation matrix
+     *
+     * @param pRotMatrix Matrix to be converted to a quaternion
+     */
+    public Quaternion(Matrix3x3 pRotMatrix) {
+
+        float t = 1 + pRotMatrix.coeff[0] + pRotMatrix.coeff[4] + pRotMatrix.coeff[8];
+
+        // large enough
+        if (t > 0.00001f) {
+            float s = (float) Math.sqrt(t) * 2.0f;
+            x = (pRotMatrix.coeff[8] - pRotMatrix.coeff[7]) / s;
+            y = (pRotMatrix.coeff[6] - pRotMatrix.coeff[2]) / s;
+            z = (pRotMatrix.coeff[1] - pRotMatrix.coeff[3]) / s;
+            w = 0.25f * s;
+        } // else we have to check several cases
+        else if (pRotMatrix.coeff[0] > pRotMatrix.coeff[4] &&
+                pRotMatrix.coeff[0] > pRotMatrix.coeff[8]) {
+            // Column 0:
+            float s = (float) Math.sqrt(1.0f + pRotMatrix.coeff[0] -
+                    pRotMatrix.coeff[4] - pRotMatrix.coeff[8]) * 2.0f;
+            x = -0.25f * s;
+            y = (pRotMatrix.coeff[1] + pRotMatrix.coeff[3]) / s;
+            z = (pRotMatrix.coeff[6] + pRotMatrix.coeff[2]) / s;
+            w = (pRotMatrix.coeff[7] - pRotMatrix.coeff[5]) / s;
+        }
+        else if (pRotMatrix.coeff[4] > pRotMatrix.coeff[8]) {
+            // Column 1:
+            float s = (float) Math.sqrt(1.0f + pRotMatrix.coeff[4] -
+                    pRotMatrix.coeff[0] - pRotMatrix.coeff[8]) * 2.0f;
+            x = (pRotMatrix.coeff[1] + pRotMatrix.coeff[3]) / s;
+            y = -0.25f * s;
+            z = (pRotMatrix.coeff[5] + pRotMatrix.coeff[7]) / s;
+            w = (pRotMatrix.coeff[2] - pRotMatrix.coeff[6]) / s;
+        }
+        else {
+            // Column 2:
+            float s = (float) Math.sqrt(1.0f + pRotMatrix.coeff[8] -
+                    pRotMatrix.coeff[0] - pRotMatrix.coeff[4]) * 2.0f;
+            x = (pRotMatrix.coeff[6] + pRotMatrix.coeff[2]) / s;
+            y = (pRotMatrix.coeff[5] + pRotMatrix.coeff[7]) / s;
+            z = -0.25f * s;
+            w = (pRotMatrix.coeff[3] - pRotMatrix.coeff[1]) / s;
+        }
+    }
+
+
+    /**
+     * Convert the quaternion to a rotation matrix
+     *
+     * @return 3x3 rotation matrix
+     */
+    public Matrix3x3 getMatrix() {
+
+        Matrix3x3 resMatrix = new Matrix3x3();
+        resMatrix.coeff[0] = 1.0f - 2.0f * (y * y + z * z);
+        resMatrix.coeff[1] = 2.0f * (x * y + z * w);
+        resMatrix.coeff[2] = 2.0f * (x * z - y * w);
+        resMatrix.coeff[3] = 2.0f * (x * y - z * w);
+        resMatrix.coeff[4] = 1.0f - 2.0f * (x * x + z * z);
+        resMatrix.coeff[5] = 2.0f * (y * z + x * w);
+        resMatrix.coeff[6] = 2.0f * (x * z + y * w);
+        resMatrix.coeff[7] = 2.0f * (y * z - x * w);
+        resMatrix.coeff[8] = 1.0f - 2.0f * (x * x + y * y);
+
+        return resMatrix;
+    }
+
+}

+ 72 - 100
port/jAssimp/src/assimp/Scene.java

@@ -42,8 +42,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 package assimp;
 
-import java.util.Vector;
-
 /**
  * Represents the asset data that has been loaded. A scene consists of
  * multiple meshes, animations, materials and embedded textures.
@@ -57,13 +55,13 @@ import java.util.Vector;
  */
 public class Scene {
 
-    // NOTE: use Vector's to be able to use the constructor for initialisation
-    private Vector<Mesh> m_vMeshes;
-    private Vector<Texture> m_vTextures;
-    private Vector<Material> m_vMaterials;
-    private Vector<Animation> m_vAnimations;
+    private Mesh[] m_vMeshes = null;
+    private Texture[] m_vTextures = null;
+    private Material[] m_vMaterials = null;
+    private Animation[] m_vAnimations = null;
     private Node m_rootNode = null;
     private Importer imp = null;
+    private int flags;
 
     private Scene() {
     }
@@ -76,138 +74,112 @@ public class Scene {
         return this.imp;
     }
 
+
+    /**
+     * Specifies that no full model but only an animation skeleton has been
+     * imported. There are no materials in this case. There are no
+     * textures in this case. But there is a node graph, animation channels
+     * and propably meshes with bones.
+     */
+    public static final int FLAG_ANIM_SKELETON_ONLY	= 0x1;
+
+
+    /**
+     * Get the scene flags. This can be any combination of the
+     * FLAG_XXX constants defined int this scope
+     * @return Scene flags.
+     */
+    public final int getFlags() {
+        return flags;
+    }
+
     /**
      * Get the mesh list
      *
      * @return mesh list
      */
-    public final Vector<Mesh> getMeshes() {
+    public final Mesh[] getMeshes() {
         return m_vMeshes;
     }
 
     /**
-     * Get the texture list
-     *
-     * @return Texture list
+     * Get the number of meshes in the scene
+     * @return this value can be 0 if the <code>ANIMATION_SKELETON_ONLY</code>
+     * flag is set.
      */
-    public final Vector<Texture> getTextures() {
-        return m_vTextures;
+    public final int getNumMeshes() {
+        return m_vMeshes.length;
     }
 
     /**
-     * Get the material list
-     *
-     * @return Material list
+     * Get a mesh from the scene
+     * @param i Index of the mesh
+     * @return scene.mesh[i]
      */
-    public final Vector<Material> getMaterials() {
-        return m_vMaterials;
+    public final Mesh getMesh(int i) {
+        assert(i < m_vMeshes.length);
+        return m_vMeshes[i];
     }
 
     /**
-     * Get the animation list
+     * Get the texture list
      *
-     * @return Animation list
+     * @return Texture list
      */
-    public final Vector<Animation> getAnimations() {
-        return m_vAnimations;
+    public final Texture[] getTextures() {
+        return m_vTextures;
     }
 
-    /**
-     * Get the root node of the scenegraph
-     *
-     * @return Root node
+     /**
+     * Get the number of textures in the scene
+     * @return this value is often 0 since most texture's arent' embedded
      */
-    public final Node getRootNode() {
-        return m_rootNode;
+    public int getNumTextures() {
+        return m_vTextures.length;
     }
 
     /**
-     * Used to initialize the class instance. Called by Importer. Will maybe
-     * be replaced with a RAII solution ...
+     * Get an embedded texture from the scene
+     * @param i Index of the mesh
+     * @return scene.texture[i]
      */
-    protected void construct() throws NativeError {
-
-        int i;
-
-        // Mesh, Animation, Texture, Material and Node constructors
-        // throw exceptions if they fail
-
-        // load all meshes
-        int iTemp = this._NativeGetNumMeshes(imp.hashCode());
-        if (0xffffffff == iTemp) throw new NativeError("Unable to obtain number of meshes in the scene");
-        this.m_vMeshes.setSize(iTemp);
-
-        for (i = 0; i < iTemp; ++i) {
-            this.m_vMeshes.set(i, new Mesh(this, i));
-        }
-
-        // load all animations
-        iTemp = this._NativeGetNumAnimations(imp.getContext());
-        if (0xffffffff == iTemp) throw new NativeError("Unable to obtain number of animations in the scene");
-        this.m_vAnimations.setSize(iTemp);
-
-        for (i = 0; i < iTemp; ++i) {
-            this.m_vAnimations.set(i, new Animation(this, i));
-        }
-
-        // load all textures
-        iTemp = this._NativeGetNumTextures(imp.getContext());
-        if (0xffffffff == iTemp) throw new NativeError("Unable to obtain number of textures in the scene");
-        this.m_vTextures.setSize(iTemp);
-
-        for (i = 0; i < iTemp; ++i) {
-            this.m_vTextures.set(i, new Texture(this, i));
-        }
-
-        // load all materials
-        iTemp = this._NativeGetNumMaterials(imp.getContext());
-        if (0xffffffff == iTemp) throw new NativeError("Unable to obtain number of materials in the scene");
-        this.m_vMaterials.setSize(iTemp);
-
-        for (i = 0; i < iTemp; ++i) {
-            this.m_vMaterials.set(i, new Material(this, i));
-        }
-
-        // now load all nodes
-        //this.m_rootNode = new Node(this, 0xffffffff);
-
-
-        return;
+    public final Texture getTexture(int i) {
+        assert(i < m_vTextures.length);
+        return m_vTextures[i];
     }
 
     /**
-     * JNI bridge function - for internal use only
-     * Retrieve the number of meshes in a scene
+     * Get the material list
      *
-     * @param context Current importer context (imp.hashCode)
-     * @return Number of meshes in the scene that belongs to the context
+     * @return Material list
      */
-    private native int _NativeGetNumMeshes(long context);
+    public final Material[] getMaterials() {
+        return m_vMaterials;
+    }
 
-    /**
-     * JNI bridge function - for internal use only
-     * Retrieve the number of animations in a scene
-     *
-     * @param context Current importer context (imp.hashCode)
-     * @return Number of animations in the scene that belongs to the context
+     /**
+     * Get the number of animations in the scene
+     * @return this value could be 0, most models have no animations
      */
-    private native int _NativeGetNumAnimations(long context);
+    public int getNumAnimations() {
+        return m_vAnimations.length;
+    }
 
     /**
-     * JNI bridge function - for internal use only
-     * Retrieve the number of textures in a scene
+     * Get the animation list
      *
-     * @param context Current importer context (imp.hashCode)
-     * @return Number of textures in the scene that belongs to the context
+     * @return Animation list
      */
-    private native int _NativeGetNumTextures(long context);
+    public final Animation[] getAnimations() {
+        return m_vAnimations;
+    }
 
     /**
-     * JNI bridge function - for internal use only
-     * Retrieve the number of materials in a scene
+     * Get the root node of the scenegraph
      *
-     * @param context Current importer context (imp.hashCode)
-     * @return Number of materials in the scene that belongs to the context
+     * @return Root node
      */
-    private native int _NativeGetNumMaterials(long context);
+    public final Node getRootNode() {
+        return m_rootNode;
+    }
 }

+ 1 - 1
port/jAssimp/src/assimp/ShadingMode.java

@@ -43,7 +43,7 @@ package assimp;
 
 /**
  * Defines all shading models supported by the library
- * <p/>
+ * 
  * NOTE: The list of shading modes has been taken from Blender3D.
  * See Blender3D documentation for more information. The API does
  * not distinguish between "specular" and "diffuse" shaders (thus the

+ 41 - 81
port/jAssimp/src/assimp/Texture.java

@@ -43,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 package assimp;
 
 import java.awt.*;
+import java.awt.image.BufferedImage;
 
 /**
  * Represents an embedded texture. Sometimes textures are not referenced
@@ -56,31 +57,14 @@ import java.awt.*;
  * @author Aramis (Alexander Gessler)
  * @version 1.0
  */
-public class Texture extends Mappable {
+public class Texture  {
 
     protected int width = 0;
     protected int height = 0;
+    protected int needAlpha = 0xffffffff;
 
     protected Object data = null;
 
-    /**
-     * Construction from a given parent object and array index
-     *
-     * @param parent Must be valid, null is not allowed
-     * @param index  Valied index in the parent's list
-     */
-    public Texture(Object parent, int index) throws NativeError {
-        super(parent, index);
-
-        long lTemp;
-        if (0x0 == (lTemp = this._NativeGetTextureInfo(((Scene) this.getParent()).
-                getImporter().getContext(), this.getArrayIndex()))) {
-            throw new NativeError("Unable to get the width and height of the texture");
-        }
-        this.width = (int) (lTemp);
-        this.height = (int) (lTemp >> 32);
-    }
-
 
     /**
      * Retrieve the height of the texture image
@@ -100,6 +84,30 @@ public class Texture extends Mappable {
         return width;
     }
 
+
+    /**
+     * Returns whether the texture uses its alpha channel
+     * @return <code>true</code> if at least one pixel
+     * has an alpha value below 0xFF.
+     */
+    public boolean hasAlphaChannel() {
+
+        // already computed?
+        if (0xffffffff == needAlpha && null != data) {
+
+            Color[] clr = getColorArray();
+            for (Color c : clr) {
+              if (c.getAlpha() < 255) {
+                  needAlpha = 1;
+                  return true;
+              }
+            }
+            needAlpha = 0;
+            return false;
+        }
+        return 0x1 == needAlpha;
+    }
+
     /**
      * Get the color at a given position of the texture
      *
@@ -110,15 +118,6 @@ public class Texture extends Mappable {
     public Color getPixel(int x, int y) {
 
         assert(x < width && y < height);
-
-        // map the color data in memory if required ...
-        if (null == data) {
-            try {
-                this.onMap();
-            } catch (NativeError nativeError) {
-                return Color.black;
-            }
-        }
         return ((Color[]) data)[y * width + x];
     }
 
@@ -128,68 +127,29 @@ public class Texture extends Mappable {
      * @return Array of <code>java.awt.Color</code>, size: width * height
      */
     public Color[] getColorArray() {
-
-        // map the color data in memory if required ...
-        if (null == data) {
-            try {
-                this.onMap();
-            } catch (NativeError nativeError) {
-                return null;
-            }
-        }
         return (Color[]) data;
     }
 
+
     /**
-     * Internal helper function to map the native texture data into
-     * a <code>java.awt.Color</code> array
+     * Convert the texture into a <code>java.awt.BufferedImage</code>
+     * @return <code>java.awt.BufferedImage</code> object containing
+     * a copy of the texture image. The texture is a ARGB texture if
+     * an alpha channel is required, otehrwise RGB is used as format.
      */
-    @Override
-    protected void onMap() throws NativeError {
-        final int iNumPixels = width * height;
+    public BufferedImage convertToImage() {
 
-        // first allocate the output array
-        data = new Color[iNumPixels];
+        BufferedImage buf = new BufferedImage(width,height, hasAlphaChannel()
+                ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
 
-        // now allocate a temporary output array
-        byte[] temp = new byte[(iNumPixels) << 2];
+        int[] aiColorBuffer = new int[width*height];
+        Color[] clr = getColorArray();
 
-        // and copy the native color data to it
-        if (0xffffffff == this._NativeMapColorData(((Scene) this.getParent()).getImporter().getContext(),
-                this.getArrayIndex(), temp)) {
-            throw new NativeError("Unable to map aiTexture into the Java-VM");
+        for (int i = 0; i <  width*height;++i) {
+            aiColorBuffer[i] =  clr[i].getRGB();
         }
 
-        DefaultLogger.get().debug("Texture.onMap successful");
-
-        // now convert the temporary representation to a Color array
-        // (data is given in BGRA order, we need RGBA)
-        for (int i = 0, iBase = 0; i < iNumPixels; ++i, iBase += 4) {
-            ((Color[]) data)[i] = new Color(temp[iBase + 2], temp[iBase + 1], temp[iBase], temp[iBase + 3]);
-        }
-        return;
+        buf.setRGB(0,0,width,height,aiColorBuffer,0,width*4);
+        return buf;
     }
-
-    /**
-     * JNI bridge call. For internal use only
-     * The method maps the contents of the native aiTexture object into memory
-     * the native memory area will be deleted afterwards.
-     *
-     * @param context Current importer context (imp.hashCode)
-     * @param index   Index of the texture in the scene
-     * @param temp    Output array. Assumed to be width * height * 4 in size
-     * @return 0xffffffff if an error occured
-     */
-    protected native int _NativeMapColorData(long context, long index, byte[] temp);
-
-    /**
-     * JNI bridge call. For internal use only
-     * The method retrieves information on the underlying texture
-     *
-     * @param context Current importer context (imp.hashCode)
-     * @param index   Index of the texture in the scene
-     * @return 0x0 if an error occured, otherwise the width in the lower 32 bits
-     *         and the height in the higher 32 bits
-     */
-    private native long _NativeGetTextureInfo(long context, long index);
 }

+ 282 - 58
port/jAssimp/src/assimp/test/DumpToFile.java

@@ -57,6 +57,78 @@ import java.io.IOException;
  */
 public class DumpToFile {
 
+
+    /**
+     * Count all nodes recursively
+     *
+     * @param node Current node
+     * @return Number of nodes
+     */
+    public static int CountNodes(Node node) {
+
+        int ret = 1;
+        if (0 != node.getNumChildren()) {
+            for (Node n : node.getChildren()) {
+
+                ret += CountNodes(n);
+            }
+        }
+        return ret;
+    }
+
+
+    /**
+     * Print all nodes recursively
+     *
+     * @param node   Current node
+     * @param stream Output stream
+     * @param suffix Suffix to all output
+     * @throws IOException yes ... sometimes ... :-)
+     */
+    public static void PrintNodes(Node node, FileWriter stream, String suffix) throws IOException {
+        String suffNew = suffix + "\t";
+        stream.write(suffix + node.getName() + "\n");
+
+        // print all meshes
+        if (0 != node.getNumMeshes()) {
+            stream.write(suffNew + "Meshes: ");
+
+            for (int i : node.getMeshes()) {
+
+                stream.write(i + " ");
+            }
+            stream.write("\n");
+        }
+
+        // print all children
+        if (0 != node.getNumChildren()) {
+            for (Node n : node.getChildren()) {
+
+                PrintNodes(n, stream, suffNew);
+            }
+        }
+    }
+
+
+    /**
+     * Saves an embedded texture image as TrueVision Targa file
+     *
+     * @param texture Texture to be exported
+     * @param path    Output path
+     * @throws IOException yes ... sometimes ... :-)
+     */
+    public static void SaveTextureToTGA(Texture texture, String path) throws IOException {
+
+    }
+
+
+    /**
+     * Entry point of the application
+     *
+     * @param arguments The first argument is the name of the
+     *                  mesh to be opened, the second is te name of the primary output file.
+     * @throws IOException
+     */
     public static void Main(String[] arguments) throws IOException {
 
         /* Use output.txt as default output file if none was specified
@@ -67,7 +139,20 @@ public class DumpToFile {
             arguments = new String[2];
             arguments[0] = s;
             arguments[1] = "output.txt";
-        } else if (2 != arguments.length) return;
+        } else if (2 != arguments.length) {
+            System.exit(-5);
+        }
+
+        int iLen;
+        if ((iLen = arguments[1].length()) < 4 ||
+                arguments[1].charAt(iLen - 1) != 't' ||
+                arguments[1].charAt(iLen - 2) != 'x' ||
+                arguments[1].charAt(iLen - 3) != 't' ||
+                arguments[1].charAt(iLen - 4) != '.') {
+            System.out.println("The output path must have .txt as file extension");
+            System.exit(-10);
+            return;
+        }
 
         FileWriter stream;
         try {
@@ -75,20 +160,21 @@ public class DumpToFile {
         } catch (IOException e) {
             e.printStackTrace();
             System.out.println("Unable to open output file");
-            throw e;
+            System.exit(-15);
+            return;
         }
 
         /* Try to create an instance of class assimp.Importer.
-         * The constructor throws an assimp.NativeError exception
+         * The constructor throws an assimp.NativeException exception
          * if the native jAssimp library is not available.It must
          * be placed in the jar/class directory of the application
          */
         Importer imp;
         try {
             imp = new Importer();
-        } catch (NativeError nativeError) {
-            nativeError.printStackTrace();
-            System.out.println("NativeError exception [#1]: " + nativeError.getMessage());
+        } catch (NativeException nativeException) {
+            nativeException.printStackTrace();
+            System.out.println("NativeException exception [#1]: " + nativeException.getMessage());
             return;
         }
 
@@ -101,8 +187,9 @@ public class DumpToFile {
         imp.addPostProcessStep(PostProcessStep.CalcTangentSpace);
         imp.addPostProcessStep(PostProcessStep.GenSmoothNormals);
         imp.addPostProcessStep(PostProcessStep.JoinIdenticalVertices);
+        imp.addPostProcessStep(PostProcessStep.FixInfacingNormals);
 
-        /* Load the asset into memory. Again, a NativeError exception
+        /* Load the asset into memory. Again, a NativeException exception
          * could be thrown if an unexpected errors occurs in the
          * native interface. If assimp is just unable to load the asset
          * null is the return value and no exception is thrown
@@ -110,9 +197,9 @@ public class DumpToFile {
         Scene scene;
         try {
             scene = imp.readFile(arguments[0]);
-        } catch (NativeError nativeError) {
-            nativeError.printStackTrace();
-            System.out.println("NativeError exception [#2] :" + nativeError.getMessage());
+        } catch (NativeException nativeException) {
+            nativeException.printStackTrace();
+            System.out.println("NativeException exception [#2] :" + nativeException.getMessage());
             return;
         }
         if (null == scene) {
@@ -122,61 +209,198 @@ public class DumpToFile {
 
         /* Now iterate through all meshes that have been loaded
          */
-        int iMesh = 0;
-        for (Mesh mesh : scene.getMeshes()) {
-
-            stream.write("Mesh " + iMesh + "\n");
-            stream.write("\tNum Vertices: " + mesh.getNumVertices() + "\n");
-            stream.write("\tNum Faces: " + mesh.getNumFaces() + "\n");
-            stream.write("\tNum Bones: " + mesh.getNumBones() + "\n\n");
-
-            /* Output all vertices. First get direct access to jAssimp's buffers
-             * UV coords and colors could also be there, but we don't output them
-             * at the moment!
-             */
-            float[] positions = mesh.getPositionArray();
-            float[] normals = mesh.getNormalArray();
-            float[] tangents = mesh.getTangentArray();
-            float[] bitangents = mesh.getBitangentArray();
-            for (int i = 0; i < mesh.getNumVertices(); ++i) {
-
-                // format: "Vertex pos(x|y|z) nor(x|y|z) tan(x|y|) bit(x|y|z)"
-                // great that this IDE is automatically able to replace + with append ... ;-)
-                stream.write(new StringBuilder().
-                        append("\tVertex: pos(").
-                        append(positions[i * 3]).append("|").
-                        append(positions[i * 3 + 1]).append("|").
-                        append(positions[i * 3 + 2]).append(")\t").
-                        append("nor(").
-                        append(normals[i * 3]).append("|").
-                        append(normals[i * 3 + 1]).append("|").
-                        append(normals[i * 3 + 2]).append(")\t").
-                        append("tan(").
-                        append(tangents[i * 3]).append("|").
-                        append(tangents[i * 3 + 1]).append("|").
-                        append(tangents[i * 3 + 2]).append(")\t").
-                        append("bit(").
-                        append(bitangents[i * 3]).append("|").
-                        append(bitangents[i * 3 + 1]).append("|").
-                        append(bitangents[i * 3 + 2]).append(")\n").toString());
+        if (0 != scene.getNumMeshes()) {
+            for (Mesh mesh : scene.getMeshes()) {
+
+                stream.write("Mesh\n");
+                stream.write("\tNum Vertices: " + mesh.getNumVertices() + "\n");
+                stream.write("\tNum Faces: " + mesh.getNumFaces() + "\n");
+                stream.write("\tNum Bones: " + mesh.getNumBones() + "\n\n");
 
+                /* Output all vertices. First get direct access to jAssimp's buffers
+                */
+                float[] positions = mesh.getPositionArray();
+                float[] normals = mesh.getNormalArray();
+                float[] tangents = mesh.getTangentArray();
+                float[] bitangents = mesh.getBitangentArray();
+
+                float[][] uvs = new float[ Mesh.MAX_NUMBER_OF_TEXTURECOORDS][];
+                for (int i = 0; i < Mesh.MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+                    if (mesh.hasUVCoords((i))) uvs[i] = mesh.getTexCoordArray(i);
+                    else break;
+                }
+
+                float[][] vcs = new float[ Mesh.MAX_NUMBER_OF_COLOR_SETS][];
+                for (int i = 0; i < Mesh.MAX_NUMBER_OF_COLOR_SETS; ++i) {
+                    if (mesh.hasVertexColors((i))) uvs[i] = mesh.getVertexColorArray(i);
+                    else break;
+                }
+
+                for (int i = 0; i < mesh.getNumVertices(); ++i) {
+
+                    // format: "Vertex pos(x|y|z) nor(x|y|z) tan(x|y|) bit(x|y|z)"
+                    // great that this IDE is automatically able to replace + with append ... ;-)
+                    if (mesh.hasPositions()) {
+                        stream.write(new StringBuilder().
+                                append("\tVertex: pos(").
+                                append(positions[i * 3]).append("|").
+                                append(positions[i * 3 + 1]).append("|").
+                                append(positions[i * 3 + 2]).append(")").toString());
+                    }
+                    if (mesh.hasNormals()) {
+                        stream.write(new StringBuilder().
+                                append("\tnor(").
+                                append(normals[i * 3]).append("|").
+                                append(normals[i * 3 + 1]).append("|").
+                                append(normals[i * 3 + 2]).append(")").toString());
+                    }
+                    if (mesh.hasTangentsAndBitangents()) {
+                        stream.write(new StringBuilder().
+                                append("\ttan(").
+                                append(tangents[i * 3]).append("|").
+                                append(tangents[i * 3 + 1]).append("|").
+                                append(tangents[i * 3 + 2]).append(")").toString());
+
+                        stream.write(new StringBuilder().
+                                append("\tbit(").
+                                append(bitangents[i * 3]).append("|").
+                                append(bitangents[i * 3 + 1]).append("|").
+                                append(bitangents[i * 3 + 2]).append(")").toString());
+                    }
+
+                    for (int a = 0; i < Mesh.MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
+                        if (!mesh.hasUVCoords((a))) break;
+
+                        stream.write(new StringBuilder().append("\tuv").append(a).append("(").
+                                append(uvs[a][i * 3]).append("|").
+                                append(uvs[a][i * 3 + 1]).append("|").
+                                append(uvs[a][i * 3 + 2]).append(")").toString());
+                    }
+
+                    for (int a = 0; i < Mesh.MAX_NUMBER_OF_COLOR_SETS; ++a) {
+                        if (!mesh.hasVertexColors((a))) break;
+
+                        stream.write(new StringBuilder().append("\tcol").append(a).append("(").
+                                append(vcs[a][i * 4]).append("|").
+                                append(vcs[a][i * 4 + 1]).append("|").
+                                append(vcs[a][i * 4 + 2]).append("|").
+                                append(vcs[a][i * 4 + 3]).append(")").toString());
+                    }
+                    stream.write("\n");
+                }
+                stream.write("\n");
+
+                /* Now write a list of all faces in this model
+                */
+                int[] faces = mesh.getFaceArray();
+                for (int i = 0; i < mesh.getNumFaces(); ++i) {
+                    stream.write(new StringBuilder().append("\tFace (").
+                            append(faces[i * 3]).append("|").
+                            append(faces[i * 3 + 1]).append("|").
+                            append(faces[i * 3 + 2]).append(")\n").toString());
+                }
+                stream.write("\n");
+
+                /*  Now write a list of all bones of this model
+                */
+                if (mesh.hasBones()) {
+                    Bone[] bones = mesh.getBonesArray();
+                    for (Bone bone : bones) {
+
+                        stream.write("\tBone " + bone.getName() + "\n");
+                        Bone.Weight[] weights = bone.getWeightsArray();
+                        for (Bone.Weight weight : weights) {
+                            stream.write("\t\tWeight (" + weight.index + "|" + weight.weight + ")\n");
+                        }
+
+                    }
+                }
+                stream.write("\n");
             }
-            stream.write("\n\n");
-
-            /* Now write a list of all faces in this model
-             */
-            int[] faces = mesh.getFaceArray();
-            for (int i = 0; i < mesh.getNumFaces(); ++i) {
-                stream.write(new StringBuilder().append("\tFace (").
-                        append(faces[i * 3]).append("|").
-                        append(faces[i * 3 + 1]).append("|").
-                        append(faces[i * 3 + 2]).append(")\n").toString());
+        }
+
+        /* Now iterate through all animations that have been loaded
+        */
+        if (0 != scene.getNumAnimations()) {
+            for (Animation anim : scene.getAnimations()) {
+
+                stream.write("Animation\n" +
+                        "\tName: " + anim.getName() + "\n" +
+                        "\tDuration: " + anim.getDuration() + "\n" +
+                        "\tTicks/s: " + anim.getTicksPerSecond() + "\n" +
+                        "\tNum BoneAnim channels: " + anim.getNumBoneAnimChannels() + "\n\n");
+
+                /*
+                 * Write all bone animation channels
+                 */
+                if (0 != anim.getNumBoneAnimChannels()) {
+                    for (BoneAnim boneAnim : anim.getBoneAnimChannels()) {
+
+                        stream.write("\tBoneAnim\n" +
+                                "\tName: " + boneAnim.getName() + "\n" +
+                                "\tNum QuatKeys: " + boneAnim.getNumQuatKeys() + "\n");
+
+                        /* Write all rotation keys
+                         */
+                        for (BoneAnim.KeyFrame<Quaternion> key : boneAnim.getQuatKeys()) {
+                            stream.write("\t\tQuatKey: \n" +
+                                    "\t\t\tTicks: " + key.time + "\n" +
+                                    "\t\t\tValue: (" + key.value.x + "|" + key.value.y + "|" +
+                                    key.value.z + "|" + key.value.w + ")\n");
+                        }
+                        stream.write("\tNum SclKeys: " + boneAnim.getNumScalingKeys() + "\n");
+
+                        /* Write all scaling keys
+                        */
+                        for (BoneAnim.KeyFrame<float[]> key : boneAnim.getScalingKeys()) {
+                            stream.write("\t\tSclKey: \n" +
+                                    "\t\t\tTicks: " + key.time + "\n" +
+                                    "\t\t\tValue: (" + key.value[0] + "|" + key.value[1] + "|" +
+                                    key.value[2] + ")\n");
+                        }
+                        stream.write("\tNum PosKeys: " + boneAnim.getNumPosKeys() + "\n");
+
+                        /* Write all position keys
+                        */
+                        for (BoneAnim.KeyFrame<float[]> key : boneAnim.getPosKeys()) {
+                            stream.write("\t\tPosKey: \n" +
+                                    "\t\t\tTicks: " + key.time + "\n" +
+                                    "\t\t\tValue: (" + key.value[0] + "|" + key.value[1] + "|" +
+                                    key.value[2] + ")\n");
+                        }
+                        stream.write("\n");
+                    }
+                }
             }
+        }
 
-            ++iMesh;
+        /* Now print all nodes -> recursively
+         *
+         */
+        stream.write("Nodegraph\n" +
+                "\tNodes: " + CountNodes(scene.getRootNode()) + "\n\n");
+        PrintNodes(scene.getRootNode(), stream, "\t");
+        stream.write("\n");
+
+        /* Now print all textures .. ehm ... export them to proper TGA files
+         */
+        if (0 != scene.getNumTextures()) {
+            int i = 0;
+            for (Texture texture : scene.getTextures()) {
+
+                String path = arguments[1].substring(0, arguments[1].length() - 4) + "_tex" + i++ + ".tga";
+                stream.write("Emb. Texture\n" +
+                    "\tExportPath: " + path + "\n\n");
+
+                SaveTextureToTGA(texture, path);
+            }
         }
 
+        /*  Now print all materials
+         */
+
 
+        // close the stream again
         stream.close();
     }
 }