소스 검색

Updated jAssimp API. 40% are complete now, some JNI wrappers are ready

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@34 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
aramis_acg 17 년 전
부모
커밋
aab9376628

+ 8 - 0
code/Importer.cpp

@@ -200,6 +200,14 @@ const aiScene* Importer::ReadFile( const std::string& pFile, unsigned int pFlags
 	// validate the flags
 	ai_assert(ValidateFlags(pFlags));
 
+	// check whether this Importer instance has already loaded
+	// a scene. In this case we need to delete the old one
+	if (this->mScene)
+	{
+		delete mScene;
+		this->mScene = NULL;
+	}
+
 	// first check if the file is accessable at all
 	if( !mIOHandler->Exists( pFile))
 	{

+ 1 - 0
code/jAssimp/BuildHeader.bat

@@ -4,3 +4,4 @@ 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"

+ 234 - 2
code/jAssimp/JNICalls.cpp

@@ -43,7 +43,239 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #if (defined ASSIMP_JNI_EXPORT)
 
-// include the JNI API
-#include <jni.h>
+// 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"
+#include "../../include/aiMesh.h"
+#include "../../include/aiAnim.h"
+#include "../../include/aiScene.h"
+#include "../../include/aiAssert.h"
+#include "../../include/aiPostProcess.h"
+#include "../../include/assimp.hpp"
+
+#include "../DefaultLogger.h"
+
+using namespace Assimp;
+
+#include <list>
+
+namespace Assimp {
+namespace JNIBridge {
+
+// used as error return code
+#define AI_JNI_ERROR_RETURN 0xffffffff
+
+// typedef for a jassimp context, used to uniquely identify
+// the Importer object which belongs to a java Importer
+
+typedef uint64_t JASSIMP_CONTEXT;
+
+#if (defined _DEBUG)
+
+	typedef std::list< JASSIMP_CONTEXT > ImporterContextList;
+	static ImporterContextList g_listActiveContexts;
+
+// ------------------------------------------------------------------------------------------------
+/* Used in debug builds to validate a context
+*/
+bool jValidateContext (JASSIMP_CONTEXT context)
+{
+	for (ImporterContextList::const_iterator
+		i =  g_listActiveContexts.begin();
+		i != g_listActiveContexts.end();++i)
+	{
+		if (context == *i)return true;
+	}
+	DefaultLogger::get()->error("[jnibridge] Invalid context");
+	return false;
+}
+// ------------------------------------------------------------------------------------------------
+/* Used in debug builds to validate a given scene
+*/
+bool jValidateScene (const aiScene* scene)
+{
+	if (!scene)
+	{
+		DefaultLogger::get()->error("[jnibridge] No asset loaded at the moment");
+		return false;
+	}
+	return true;
+}
+
+#endif // ! ASSIMP_DEBUG
+// ------------------------------------------------------------------------------------------------
+/* Used in debug builds to validate a given scene
+*/
+Assimp::Importer* jGetValidImporterScenePair (JASSIMP_CONTEXT jvmcontext)
+{
+#if (defined _DEBUG)
+	if (!jValidateContext((JASSIMP_CONTEXT)jvmcontext))return NULL;
+#endif // ! ASSIMP_DEBUG
+
+	// get the importer instance from the context
+	Assimp::Importer* pcImp = (Assimp::Importer*)jvmcontext;
+
+#if (defined _DEBUG)
+	if (!jValidateScene(pcImp->GetScene()))return NULL;
+#endif // ! ASSIMP_DEBUG
+	return pcImp;
+}
+// ------------------------------------------------------------------------------------------------
+/*
+ * Class:     assimp_Importer
+ * Method:    _NativeInitContext
+ * Signature: ()I
+ */
+JNIEXPORT jlong JNICALL Java_assimp_Importer__1NativeInitContext
+  (JNIEnv * jvmenv, jobject jvmthis)
+{
+	ai_assert(NULL != jvmenv && NULL != jvmthis);
+
+	// 2^64-1 indicates error
+	JASSIMP_CONTEXT context = 0xffffffffffffffffL;
+
+	// create a new Importer instance
+	Assimp::Importer* pcImp = new Assimp::Importer();
+	context = (JASSIMP_CONTEXT)(uintptr_t)pcImp;
+
+#if (defined _DEBUG)
+	g_listActiveContexts.push_back(context);
+#endif // ! ASSIMP_DEBUG
+	return context;
+}
+// ------------------------------------------------------------------------------------------------
+/*
+ * Class:     assimp_Importer
+ * Method:    _NativeFreeContext
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_assimp_Importer__1NativeFreeContext
+  (JNIEnv * jvmenv, jobject jvmthis, jlong jvmcontext)
+{
+	ai_assert(NULL != jvmenv && NULL != jvmthis);
+
+#if (defined _DEBUG)
+	if (!jValidateContext((JASSIMP_CONTEXT)jvmcontext))return AI_JNI_ERROR_RETURN;
+#endif // ! ASSIMP_DEBUG
+
+	// delete the Importer instance
+	Assimp::Importer* pcImp = (Assimp::Importer*)jvmcontext;
+	delete pcImp;
+
+#if (defined _DEBUG)
+	g_listActiveContexts.remove(jvmcontext);
+#endif // ! ASSIMP_DEBUG
+	return 0;
+}
+// ------------------------------------------------------------------------------------------------
+/*
+ * Class:     assimp_Importer
+ * Method:    _NativeLoad
+ * Signature: (Ljava/lang/String;II)I
+ */
+JNIEXPORT jint JNICALL Java_assimp_Importer__1NativeLoad
+  (JNIEnv *jvmenv, jobject jvmthis, jstring jvmpath, jint jvmflags, jlong jvmcontext)
+{
+	ai_assert(NULL != jvmenv && NULL != jvmthis);
+	jint iRet = 0;
+
+#if (defined _DEBUG)
+	if (!jValidateContext((JASSIMP_CONTEXT)jvmcontext))return AI_JNI_ERROR_RETURN;
+#endif // ! ASSIMP_DEBUG
+
+	// get the path from the jstring
+	const char* szPath = jvmenv->GetStringUTFChars(jvmpath,NULL);
+	if (!szPath)
+	{
+		DefaultLogger::get()->error("[jnibridge] Unable to get path string from the java vm");
+		return AI_JNI_ERROR_RETURN;
+	}
+	// get the importer instance from the context
+	Assimp::Importer* pcImp = (Assimp::Importer*)jvmcontext;
+
+	// and load the file. The aiScene object itself remains accessible
+	// via Importer.GetScene().
+	if(NULL == pcImp->ReadFile(std::string(szPath),(unsigned int)jvmflags))
+	{
+		DefaultLogger::get()->error("[jnibridge] Unable to load asset");
+
+		// release the path again
+		jvmenv->ReleaseStringUTFChars(jvmpath,szPath);
+		return AI_JNI_ERROR_RETURN;
+	}
+	// release the path again
+	jvmenv->ReleaseStringUTFChars(jvmpath,szPath);
+	return iRet;
+}
+// ------------------------------------------------------------------------------------------------
+/*
+ * Class:     assimp_Scene
+ * Method:    _NativeGetNumMeshes
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_assimp_Scene__1NativeGetNumMeshes
+  (JNIEnv *jvmenv, jobject jvmthis, jlong jvmcontext)
+{
+	ai_assert(NULL != jvmenv && NULL != jvmthis);
+	// 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)
+{
+	
+	ai_assert(NULL != jvmenv && NULL != jvmthis);
+	// 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)
+{
+	ai_assert(NULL != jvmenv && NULL != jvmthis);
+	// 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)
+{
+	ai_assert(NULL != jvmenv && NULL != jvmthis);
+	// we need a valid scene for this
+	Assimp::Importer* pcImp = jGetValidImporterScenePair(jvmcontext);
+	if (!pcImp)return AI_JNI_ERROR_RETURN;
+	return (jint)pcImp->GetScene()->mNumMaterials;
+}
+
+}; //! namespace JNIBridge
+}; //! namespace Assimp
 #endif // !ASSIMP_JNI_EXPORT

+ 13 - 0
code/jAssimp/assimp_Animation.h

@@ -0,0 +1,13 @@
+/* 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

+ 4 - 4
code/jAssimp/assimp_Importer.h

@@ -18,18 +18,18 @@ JNIEXPORT jint JNICALL Java_assimp_Importer__1NativeInitContext
 /*
  * Class:     assimp_Importer
  * Method:    _NativeFreeContext
- * Signature: (I)I
+ * Signature: (J)I
  */
 JNIEXPORT jint JNICALL Java_assimp_Importer__1NativeFreeContext
-  (JNIEnv *, jobject, jint);
+  (JNIEnv *, jobject, jlong);
 
 /*
  * Class:     assimp_Importer
  * Method:    _NativeLoad
- * Signature: (Ljava/lang/String;II)I
+ * Signature: (Ljava/lang/String;IJ)I
  */
 JNIEXPORT jint JNICALL Java_assimp_Importer__1NativeLoad
-  (JNIEnv *, jobject, jstring, jint, jint);
+  (JNIEnv *, jobject, jstring, jint, jlong);
 
 #ifdef __cplusplus
 }

+ 8 - 8
code/jAssimp/assimp_Scene.h

@@ -10,34 +10,34 @@ extern "C" {
 /*
  * Class:     assimp_Scene
  * Method:    _NativeGetNumMeshes
- * Signature: (I)I
+ * Signature: (J)I
  */
 JNIEXPORT jint JNICALL Java_assimp_Scene__1NativeGetNumMeshes
-  (JNIEnv *, jobject, jint);
+  (JNIEnv *, jobject, jlong);
 
 /*
  * Class:     assimp_Scene
  * Method:    _NativeGetNumAnimations
- * Signature: (I)I
+ * Signature: (J)I
  */
 JNIEXPORT jint JNICALL Java_assimp_Scene__1NativeGetNumAnimations
-  (JNIEnv *, jobject, jint);
+  (JNIEnv *, jobject, jlong);
 
 /*
  * Class:     assimp_Scene
  * Method:    _NativeGetNumTextures
- * Signature: (I)I
+ * Signature: (J)I
  */
 JNIEXPORT jint JNICALL Java_assimp_Scene__1NativeGetNumTextures
-  (JNIEnv *, jobject, jint);
+  (JNIEnv *, jobject, jlong);
 
 /*
  * Class:     assimp_Scene
  * Method:    _NativeGetNumMaterials
- * Signature: (I)I
+ * Signature: (J)I
  */
 JNIEXPORT jint JNICALL Java_assimp_Scene__1NativeGetNumMaterials
-  (JNIEnv *, jobject, jint);
+  (JNIEnv *, jobject, jlong);
 
 #ifdef __cplusplus
 }

+ 1 - 1
include/aiMaterial.h

@@ -522,7 +522,7 @@ aiReturn aiGetMaterialString(const C_STRUCT aiMaterial* pMat,
 #define AI_TEXTYPE_DIFFUSE		0x7
 
 // ---------------------------------------------------------------------------
-/** Helper function to get a diffuse texture from a material
+/** Helper function to get a texture from a material
  *
  *  This function is provided just for convinience. 
  *  @param pMat Pointer to the input material. May not be NULL

+ 9 - 0
include/assimp.hpp

@@ -161,6 +161,15 @@ public:
 	*/
 	void GetExtensionList(std::string& szOut);
 
+
+	// -------------------------------------------------------------------
+	/** Returns the scene loaded by the last successful call to ReadFile()
+	*
+	* @return Current scene or NULL if there is currently no scene loaded
+	*/
+	inline const aiScene* GetScene()
+		{return this->mScene;}
+
 private:
 	/** Empty copy constructor. */
 	Importer(const Importer &other);

+ 44 - 17
port/jAssimp/src/assimp/Importer.java

@@ -70,7 +70,7 @@ public class Importer {
      * Assimp::Importer object. For 64 bit platforms it is something else ..
      * at least it is guaranted to be unique ;-)
      */
-    private int m_iNativeHandle = 0xffffffff;
+    private long m_iNativeHandle = 0xffffffffffffffffl;
 
     /**
      * Loaded scene. It can't be used after the Importer class instance
@@ -88,9 +88,10 @@ public class Importer {
      * ASSIMP library. A native Assimp::Importer object is constructed and
      * initialized. The flag list is set to zero, a default I/O handler
      * is constructed.
+     *
      * @throws NativeError 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.
+     *                     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() throws NativeError {
         /** try to load the jassimp library. First try to load the
@@ -110,16 +111,16 @@ public class Importer {
         // now create the native Importer class and setup our internal
         // data structures outside the VM.
         try {
-            if (0xffffffff == (this.m_iNativeHandle = _NativeInitContext())) {
+            if (0xffffffffffffffffl == (this.m_iNativeHandle = _NativeInitContext())) {
                 throw new NativeError(
                         "Unable to initialize the native library context." +
-                        "The initialization routine has failed");
+                                "The initialization routine has failed");
             }
         }
         catch (UnsatisfiedLinkError exc) {
             throw new NativeError(
                     "Unable to initialize the native library context." +
-                    "The initialization routine has not been found");
+                            "The initialization routine has not been found");
         }
         return;
     }
@@ -183,17 +184,20 @@ public class Importer {
      * a default implementation is used. This implementation uses fopen()/
      * fread()/fwrite()/fclose()/ftell()/fseek() and provides no support
      * for archives like ZIP or PAK.
+     *
      * @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
+     * occurs in the JNI bridge module.
      */
-    public Scene readFile(String path) {
+    public Scene readFile(String path) throws NativeError {
         this.scene = new Scene(this);
         this.path = path;
 
         // we need to build a path that is valid for the current OS
         char sep = System.getProperty("file.separator").charAt(0);
-        if(sep != '\\') this.path = this.path.replace('\\',sep);
-        if(sep != '/') this.path = this.path.replace('/',sep);
+        if (sep != '\\') this.path = this.path.replace('\\', sep);
+        if (sep != '/') this.path = this.path.replace('/', sep);
 
         // need to build a list of postprocess step as bitflag combination
         // Of course, this could have been implemented directly. However,
@@ -212,11 +216,20 @@ public class Importer {
         }
 
         // now load the mesh
-        if(0xffffffff == this._NativeLoad(this.path,flags,this.m_iNativeHandle) ||
-                ! this.scene.construct()) {
+        if (0xffffffff == this._NativeLoad(this.path, flags, this.m_iNativeHandle)) {
             this.scene = null;
             this.path = null;
-            return null;
+            throw new NativeError("Failed to load the mesh");
+        }
+        // and setup our Scene object
+        try {
+          this.scene.construct();
+        }
+        catch (NativeError exc) {
+
+            this.scene = null;
+            this.path = null;
+            throw exc;
         }
         return this.scene;
     }
@@ -260,17 +273,29 @@ public class Importer {
 
     /**
      * Implementation of <code>java.lang.Object.hashCode()</code>
-     *
+     * <p/>
      * The native handle obtained from the JNI bridge is used as hash code.
-     * It is assumed to be unique, in fact it is normall the address of
+     * It is assumed to be unique, in fact it is normally the address of
      * the native Assimp::Importer object.
+     *
      * @return An unique value representing the object
      */
     @Override
     public int hashCode() {
+        return (int) (m_iNativeHandle >> 32) ^ (int) (m_iNativeHandle);
+    }
+
+
+    /**
+     * Retrieves the native context of the class. This is normally the
+     * address of the native Importer object.
+     * @return Native context
+     */
+    public long getContext() {
         return m_iNativeHandle;
     }
 
+
     /**
      * JNI bridge call. For internal use only
      * The method initializes the ASSIMP-JNI bridge for use. No native
@@ -288,16 +313,18 @@ public class Importer {
      * JNI bridge call. For internal use only
      * The method destroys the ASSIMP-JNI bridge. No native function call
      * to assimp will be successful after this method has been called.
+     *
      * @return 0xffffffff if an error occured
      */
-    private native int _NativeFreeContext(int iContext);
+    private native int _NativeFreeContext(long iContext);
 
     /**
      * JNI bridge call. For internal use only
      * The method loads the model into memory, but does not map it into the VM
-     * @param path Path (valid separators for the OS) to the model to be loaded
+     *
+     * @param path  Path (valid separators for the OS) to the model to be loaded
      * @param flags List of postprocess steps to be executed
      * @return 0xffffffff if an error occured
      */
-    private native int _NativeLoad(String path,int flags, int iContext);
+    private native int _NativeLoad(String path, int flags, long iContext);
 }

+ 464 - 1
port/jAssimp/src/assimp/Mesh.java

@@ -74,18 +74,481 @@ public class Mesh extends IMappable {
      */
     private 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_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
+     */
+    private float[] m_vVertices = null;
+
+    /**
+     * Contains the normal vectors loaded from the model or
+     * computed by postprocess steps. Needn't be existing
+     */
+    private float[] m_vNormals = null;
+
+    /**
+     * Contains the tangent vectors computed by Assimp
+     * Needn't be existing
+     */
+    private float[] m_vTangents = null;
+
+    /**
+     * Contains the bitangent vectors computed by Assimp
+     * Needn't be existing
+     */
+    private float[] m_vBitangents = null;
+
+    /**
+     * Contains the texture coordinate sets that have been loaded
+     * Needn't be existing
+     */
+    private float[][] m_avUVs = new float[MAX_NUMBER_OF_TEXTURECOORDS][];
+
+    /**
+     * Specifies how many texture coordinate components are valid
+     * in an UV channel. Normally this will be 2, but 3d texture
+     * coordinates for cubic or volumetric mapping are also supported.
+     */
+    private int[] m_aiNumUVComponents = new int[MAX_NUMBER_OF_TEXTURECOORDS];
+
+    /**
+     * Contains the vertex color sets that have been loaded
+     * Needn't be existing
+     */
+    private float[][] m_avColors = new float[MAX_NUMBER_OF_COLOR_SETS][];
+
+    /**
+     * Number of vertices in the mesh
+     */
+    private int m_iNumVertices;
+
+
     /**
      * 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) {
+    public Mesh(Object parent, int index) throws NativeError {
         super(parent, index);
+
+        assert (parent instanceof Scene);
+
+        Scene sc = (Scene) parent;
+        if (0xffffffff == (this.m_iPresentFlags = this._NativeGetPresenceFlags(
+                sc.getImporter().getContext()))) {
+            throw new NativeError("Unable to obtain a list of vertex presence flags");
+        }
+        if (0xffffffff == (this.m_iNumVertices = this._NativeGetNumVertices(
+                sc.getImporter().getContext()))) {
+            throw new NativeError("Unable to obtain the number of vertices in the mesh");
+        }
+        if (0xffffffff == this._NativeGetNumUVComponents(
+                sc.getImporter().getContext(), this.m_aiNumUVComponents)) {
+            throw new NativeError("Unable to obtain the number of UV components");
+        }
+    }
+
+    /**
+     * Check whether there are vertex positions in the model
+     * <code>getVertex()</code> will assert this.
+     *
+     * @return true if vertex positions are available.
+     */
+    public boolean hasPositions() {
+        return 0 != (this.m_iPresentFlags & PF_POSITION);
+    }
+
+    /**
+     * Check whether there are normal vectors in the model
+     * <code>getNormal()</code> will assert this.
+     *
+     * @return true if vertex normals are available.
+     */
+    public boolean hasNormals() {
+        return 0 != (this.m_iPresentFlags & PF_NORMAL);
+    }
+
+    /**
+     * Check whether there are tangents/bitangents in the model
+     * <code>getTangent()</code> and <code>GetBitangent()</code> will assert this.
+     *
+     * @return true if vertex tangents and bitangents are available.
+     */
+    public boolean hasTangentsAndBitangents() {
+        return 0 != (this.m_iPresentFlags & PF_TANGENTBITANGENT);
+    }
+
+    /**
+     * Check whether a given UV set is existing the model
+     * <code>getUV()</code> will assert this.
+     *
+     * @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));
+    }
+
+    /**
+     * Check whether a given vertex color set is existing the model
+     * <code>getColor()</code> will assert this.
+     *
+     * @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));
+    }
+
+
+    /**
+     * Get the number of vertices in the model
+     *
+     * @return Number of vertices in the asset. This could be 0 in some
+     *         extreme cases although loaders should filter such cases out
+     */
+    public int getNumVertices() {
+        return m_iNumVertices;
+    }
+
+    /**
+     * Get a vertex position in the mesh
+     *
+     * @param iIndex Zero-based index of the vertex
+     * @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();
+
+        iIndex *= 3;
+        afOut[0] = this.m_vVertices[iIndex];
+        afOut[1] = this.m_vVertices[iIndex + 1];
+        afOut[2] = this.m_vVertices[iIndex + 2];
+    }
+
+    /**
+     * Get a vertex position in the mesh
+     *
+     * @param iIndex   Zero-based index of the vertex
+     * @param afOut    Output array, size must at least be 3
+     * @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();
+
+        iIndex *= 3;
+        afOut[iOutBase] = this.m_vVertices[iIndex];
+        afOut[iOutBase + 1] = this.m_vVertices[iIndex + 1];
+        afOut[iOutBase + 2] = this.m_vVertices[iIndex + 2];
+    }
+
+    /**
+     * Provides direct access to the vertex position array of the mesh
+     * This is the recommended way of accessing the data.
+     *
+     * @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();
+        return this.m_vVertices;
+    }
+
+    /**
+     * Get a vertex normal in the mesh
+     *
+     * @param iIndex Zero-based index of the vertex
+     * @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();
+
+        iIndex *= 3;
+        afOut[0] = this.m_vNormals[iIndex];
+        afOut[1] = this.m_vNormals[iIndex + 1];
+        afOut[2] = this.m_vNormals[iIndex + 2];
+    }
+
+    /**
+     * Get a vertex normal in the mesh
+     *
+     * @param iIndex   Zero-based index of the vertex
+     * @param afOut    Output array, size must at least be 3
+     * @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();
+
+        iIndex *= 3;
+        afOut[iOutBase] = this.m_vNormals[iIndex];
+        afOut[iOutBase + 1] = this.m_vNormals[iIndex + 1];
+        afOut[iOutBase + 2] = this.m_vNormals[iIndex + 2];
+    }
+
+    /**
+     * Provides direct access to the vertex normal array of the mesh
+     * This is the recommended way of accessing the data.
+     *
+     * @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();
+        return this.m_vNormals;
+    }
+
+    /**
+     * Get a vertex tangent in the mesh
+     *
+     * @param iIndex Zero-based index of the vertex
+     * @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();
+
+        iIndex *= 3;
+        afOut[0] = this.m_vTangents[iIndex];
+        afOut[1] = this.m_vTangents[iIndex + 1];
+        afOut[2] = this.m_vTangents[iIndex + 2];
+    }
+
+    /**
+     * Get a vertex tangent in the mesh
+     *
+     * @param iIndex   Zero-based index of the vertex
+     * @param afOut    Output array, size must at least be 3
+     * @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();
+
+        iIndex *= 3;
+        afOut[iOutBase] = this.m_vTangents[iIndex];
+        afOut[iOutBase + 1] = this.m_vTangents[iIndex + 1];
+        afOut[iOutBase + 2] = this.m_vTangents[iIndex + 2];
+    }
+
+    /**
+     * Provides direct access to the vertex tangent array of the mesh
+     * This is the recommended way of accessing the data.
+     *
+     * @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();
+        return this.m_vTangents;
+    }
+
+    /**
+     * Get a vertex bitangent in the mesh
+     *
+     * @param iIndex Zero-based index of the vertex
+     * @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();
+
+        iIndex *= 3;
+        afOut[0] = this.m_vBitangents[iIndex];
+        afOut[1] = this.m_vBitangents[iIndex + 1];
+        afOut[2] = this.m_vBitangents[iIndex + 2];
+    }
+
+    /**
+     * Get a vertex bitangent in the mesh
+     *
+     * @param iIndex   Zero-based index of the vertex
+     * @param afOut    Output array, size must at least be 3
+     * @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();
+
+        iIndex *= 3;
+        afOut[iOutBase] = this.m_vBitangents[iIndex];
+        afOut[iOutBase + 1] = this.m_vBitangents[iIndex + 1];
+        afOut[iOutBase + 2] = this.m_vBitangents[iIndex + 2];
+    }
+
+    /**
+     * Provides direct access to the vertex bitangent array of the mesh
+     * This is the recommended way of accessing the data.
+     *
+     * @return Array of floats, size is numverts * 3. Component ordering
+     *         is xyz.
+     */
+    public float[] getBitangentArray() {
+        assert(this.hasTangentsAndBitangents());
+        if (null == this.m_vBitangents) this.mapBitangents();
+        return this.m_vBitangents;
+    }
+
+    /**
+     * Get a vertex texture coordinate in the mesh
+     *
+     * @param channel Texture coordinate channel
+     * @param iIndex  Zero-based index of the vertex
+     * @param afOut   Output array, size must at least be equal to the value
+     * <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);
+
+        iIndex *= this.m_aiNumUVComponents[channel];
+        for (int i = 0; i < this.m_aiNumUVComponents[channel];++i) {
+            afOut[i] = this.m_avUVs[channel][iIndex+i];
+        }
+    }
+
+    /**
+     * Get a vertex texture coordinate in the mesh
+     *
+     * @param channel Texture coordinate channel
+     * @param iIndex  Zero-based index of the vertex
+     * @param afOut   Output array, size must at least be equal to the value
+     * <code>getNumUVComponents</code> returns for <code>channel</code>
+     * 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);
+
+        iIndex *= this.m_aiNumUVComponents[channel];
+        for (int i = 0; i < this.m_aiNumUVComponents[channel];++i) {
+            afOut[i+iOutBase] = this.m_avUVs[channel][iIndex+i];
+        }
+    }
+
+    /**
+     * Provides direct access to a texture coordinate channel of the mesh
+     * This is the recommended way of accessing the data.
+     *
+     * @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);
+        return this.m_avUVs[channel];
     }
 
 
     protected void OnMap() throws NativeError {
 
+        // map all vertex component arrays into our memory
+
     }
+
+
+    /**
+     * JNI bridge function - for internal use only
+     * Retrieve a bit combination which indicates which vertex
+     * components are existing in the model.
+     *
+     * @param context Current importer context (imp.hashCode)
+     * @return Combination of the PF_XXX constants
+     */
+    private native int _NativeGetPresenceFlags(long context);
+
+    /**
+     * JNI bridge function - for internal use only
+     * Retrieve the number of vertices in the mesh
+     *
+     * @param context Current importer context (imp.hashCode)
+     * @return Number of vertices in the mesh
+     */
+    private native int _NativeGetNumVertices(long context);
+
+    /**
+     * JNI bridge function - for internal use only
+     * Retrieve the number of uvw components for a channel
+     *
+     * @param context Current importer context (imp.hashCode)
+     * @param out Output array. Size must be MAX_NUMBER_OF_TEXTURECOORDS.
+     * @return 0xffffffff if an error occured
+     */
+     private native int _NativeGetNumUVComponents(long context, int[] out);
 }

+ 53 - 49
port/jAssimp/src/assimp/Scene.java

@@ -124,88 +124,92 @@ public class Scene {
     /**
      * Used to initialize the class instance. Called by Importer. Will maybe
      * be replaced with a RAII solution ...
+     *
      * @return true if we're successful
      */
-    protected boolean construct() {
+    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) return false;
+        if (0xffffffff == iTemp) throw new NativeError("Unable to obtain number of meshes in the scene");
         this.m_vMeshes.setSize(iTemp);
 
-        // Mesh, Animation, Texture, Material and Node constructors
-        // throw exceptions if they fail
-        try {
+        for (i = 0; i < iTemp; ++i) {
+            this.m_vMeshes.set(i, new Mesh(this, i));
+        }
 
-            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);
 
-            // load all animations
-            iTemp = this._NativeGetNumAnimations(imp.hashCode());
-            if (0xffffffff == iTemp) return false;
-            this.m_vAnimations.setSize(iTemp);
+        for (i = 0; i < iTemp; ++i) {
+            this.m_vAnimations.set(i, new Animation(this, i));
+        }
 
-            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);
 
-            // load all textures
-            iTemp = this._NativeGetNumTextures(imp.hashCode());
-            if (0xffffffff == iTemp) return false;
-            this.m_vTextures.setSize(iTemp);
+        for (i = 0; i < iTemp; ++i) {
+            this.m_vTextures.set(i, new Texture(this, i));
+        }
 
-            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);
 
-            // load all materials
-            iTemp = this._NativeGetNumMaterials(imp.hashCode());
-            if (0xffffffff == iTemp) return false;
-            this.m_vMaterials.setSize(iTemp);
+        for (i = 0; i < iTemp; ++i) {
+            this.m_vMaterials.set(i, new Material(this, i));
+        }
 
-            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);
 
-            // now load all nodes
-            //this.m_rootNode = new Node(this, 0xffffffff);
 
-        }
-        catch (Exception ex) {
-            // LOG
-            return false;
-        }
-        return true;
+        return;
     }
 
-    /** JNI bridge function - for internal use only
+    /**
+     * JNI bridge function - for internal use only
      * Retrieve the number of meshes in a scene
+     *
      * @param context Current importer context (imp.hashCode)
-     * @return  Number of meshes in the scene that belongs to the context
+     * @return Number of meshes in the scene that belongs to the context
      */
-    private native int _NativeGetNumMeshes(int context);
+    private native int _NativeGetNumMeshes(long context);
 
-    /** JNI bridge function - for internal use only
+    /**
+     * 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
+     * @return Number of animations in the scene that belongs to the context
      */
-    private native int _NativeGetNumAnimations(int context);
+    private native int _NativeGetNumAnimations(long context);
 
-    /** JNI bridge function - for internal use only
+    /**
+     * JNI bridge function - for internal use only
      * Retrieve the number of textures in a scene
+     *
      * @param context Current importer context (imp.hashCode)
-     * @return  Number of textures in the scene that belongs to the context
+     * @return Number of textures in the scene that belongs to the context
      */
-    private native int _NativeGetNumTextures(int context);
+    private native int _NativeGetNumTextures(long context);
 
-    /** JNI bridge function - for internal use only
+    /**
+     * JNI bridge function - for internal use only
      * Retrieve the number of materials in a scene
+     *
      * @param context Current importer context (imp.hashCode)
-     * @return  Number of materials in the scene that belongs to the context
+     * @return Number of materials in the scene that belongs to the context
      */
-    private native int _NativeGetNumMaterials(int context);
+    private native int _NativeGetNumMaterials(long context);
 }

+ 4 - 4
workspaces/jidea5.1/jAssimp.ipr

@@ -49,18 +49,18 @@
     <option name="MAXIMUM_HEAP_SIZE" value="128" />
   </component>
   <component name="JavadocGenerationManager">
-    <option name="OUTPUT_DIRECTORY" />
-    <option name="OPTION_SCOPE" value="protected" />
+    <option name="OUTPUT_DIRECTORY" value="J:/Programmieren/ASSIMP/assimp2/doc/javadoc" />
+    <option name="OPTION_SCOPE" value="package" />
     <option name="OPTION_HIERARCHY" value="true" />
     <option name="OPTION_NAVIGATOR" value="true" />
     <option name="OPTION_INDEX" value="true" />
     <option name="OPTION_SEPARATE_INDEX" value="true" />
     <option name="OPTION_DOCUMENT_TAG_USE" value="false" />
     <option name="OPTION_DOCUMENT_TAG_AUTHOR" value="false" />
-    <option name="OPTION_DOCUMENT_TAG_VERSION" value="false" />
+    <option name="OPTION_DOCUMENT_TAG_VERSION" value="true" />
     <option name="OPTION_DOCUMENT_TAG_DEPRECATED" value="true" />
     <option name="OPTION_DEPRECATED_LIST" value="true" />
-    <option name="OTHER_OPTIONS" value="" />
+    <option name="OTHER_OPTIONS" />
     <option name="HEAP_SIZE" />
     <option name="OPEN_IN_BROWSER" value="true" />
   </component>

+ 2 - 2
workspaces/vc8/assimp.vcproj

@@ -307,7 +307,7 @@
 				InlineFunctionExpansion="2"
 				EnableIntrinsicFunctions="true"
 				FavorSizeOrSpeed="1"
-				AdditionalIncludeDirectories="&quot;C:\Program Files\Java\jdk1.6.0_01\include&quot;;&quot;C:\Program Files\Java\jdk1.6.0_01\include\win32&quot;"
+				AdditionalIncludeDirectories="&quot;$(JAVA_HOME)\include&quot;;&quot;$(JAVA_HOME)\include\win32&quot;"
 				PreprocessorDefinitions="NDEBUG;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32;ASSIMP_JNI_EXPORT"
 				StringPooling="true"
 				BufferSecurityCheck="false"
@@ -377,7 +377,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="&quot;C:\Program Files\Java\jdk1.6.0_01\include&quot;;&quot;C:\Program Files\Java\jdk1.6.0_01\include\win32&quot;"
+				AdditionalIncludeDirectories="&quot;$(JAVA_HOME)\include&quot;;&quot;$(JAVA_HOME)\include\win32&quot;"
 				PreprocessorDefinitions="DEBUG;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32;ASSIMP_JNI_EXPORT"
 				BasicRuntimeChecks="3"
 				SmallerTypeCheck="true"