|
@@ -1,7 +1,9 @@
|
|
|
#include "jassimp.h"
|
|
|
|
|
|
-#include <assimp/cimport.h>
|
|
|
+#include <assimp/Importer.hpp>
|
|
|
#include <assimp/scene.h>
|
|
|
+#include <assimp/IOStream.hpp>
|
|
|
+#include <assimp/IOSystem.hpp>
|
|
|
|
|
|
|
|
|
#ifdef JNI_LOG
|
|
@@ -12,9 +14,11 @@
|
|
|
#define lprintf(...) printf (__VA_ARGS__)
|
|
|
#endif /* ANDROID */
|
|
|
#else
|
|
|
-#define lprintf
|
|
|
+#define lprintf
|
|
|
#endif
|
|
|
|
|
|
+static std::string gLastErrorString;
|
|
|
+
|
|
|
// Automatically deletes a local ref when it goes out of scope
|
|
|
class SmartLocalRef {
|
|
|
private:
|
|
@@ -270,6 +274,81 @@ static bool callv(JNIEnv *env, jobject object, const char* typeName,
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+static jobject callo(JNIEnv *env, jobject object, const char* typeName, const char* methodName,
|
|
|
+ const char* signature,/* const*/ jvalue* params)
|
|
|
+{
|
|
|
+ jclass clazz = env->FindClass(typeName);
|
|
|
+ SmartLocalRef clazzRef(env, clazz);
|
|
|
+
|
|
|
+ if (NULL == clazz)
|
|
|
+ {
|
|
|
+ lprintf("could not find class %s\n", typeName);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ jmethodID mid = env->GetMethodID(clazz, methodName, signature);
|
|
|
+
|
|
|
+ if (NULL == mid)
|
|
|
+ {
|
|
|
+ lprintf("could not find method %s with signature %s in type %s\n", methodName, signature, typeName);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ jobject jReturnValue = env->CallObjectMethodA(object, mid, params);
|
|
|
+
|
|
|
+ return jReturnValue;
|
|
|
+}
|
|
|
+
|
|
|
+static int calli(JNIEnv *env, jobject object, const char* typeName, const char* methodName,
|
|
|
+ const char* signature)
|
|
|
+{
|
|
|
+ jclass clazz = env->FindClass(typeName);
|
|
|
+ SmartLocalRef clazzRef(env, clazz);
|
|
|
+
|
|
|
+ if (NULL == clazz)
|
|
|
+ {
|
|
|
+ lprintf("could not find class %s\n", typeName);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ jmethodID mid = env->GetMethodID(clazz, methodName, signature);
|
|
|
+
|
|
|
+ if (NULL == mid)
|
|
|
+ {
|
|
|
+ lprintf("could not find method %s with signature %s in type %s\n", methodName, signature, typeName);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ jint jReturnValue = env->CallIntMethod(object, mid);
|
|
|
+
|
|
|
+ return (int) jReturnValue;
|
|
|
+}
|
|
|
+
|
|
|
+static int callc(JNIEnv *env, jobject object, const char* typeName, const char* methodName,
|
|
|
+ const char* signature)
|
|
|
+{
|
|
|
+ jclass clazz = env->FindClass(typeName);
|
|
|
+ SmartLocalRef clazzRef(env, clazz);
|
|
|
+
|
|
|
+ if (NULL == clazz)
|
|
|
+ {
|
|
|
+ lprintf("could not find class %s\n", typeName);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ jmethodID mid = env->GetMethodID(clazz, methodName, signature);
|
|
|
+
|
|
|
+ if (NULL == mid)
|
|
|
+ {
|
|
|
+ lprintf("could not find method %s with signature %s in type %s\n", methodName, signature, typeName);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ jint jReturnValue = env->CallCharMethod(object, mid);
|
|
|
+
|
|
|
+ return (int) jReturnValue;
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
static bool callStaticObject(JNIEnv *env, const char* typeName, const char* methodName,
|
|
|
const char* signature,/* const*/ jvalue* params, jobject& returnValue)
|
|
@@ -359,6 +438,158 @@ static bool copyBufferArray(JNIEnv *env, jobject jMesh, const char* jBufferName,
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+class JavaIOStream : public Assimp::IOStream
|
|
|
+{
|
|
|
+private:
|
|
|
+ size_t pos;
|
|
|
+ size_t size;
|
|
|
+ char* buffer;
|
|
|
+ jobject jIOStream;
|
|
|
+
|
|
|
+
|
|
|
+public:
|
|
|
+ JavaIOStream(size_t size, char* buffer, jobject jIOStream) :
|
|
|
+ pos(0),
|
|
|
+ size(size),
|
|
|
+ buffer(buffer),
|
|
|
+ jIOStream(jIOStream)
|
|
|
+ {};
|
|
|
+
|
|
|
+
|
|
|
+ ~JavaIOStream(void)
|
|
|
+ {
|
|
|
+ free(buffer);
|
|
|
+ };
|
|
|
+
|
|
|
+ size_t Read(void* pvBuffer, size_t pSize, size_t pCount)
|
|
|
+ {
|
|
|
+ const size_t cnt = std::min(pCount,(size - pos)/pSize);
|
|
|
+ const size_t ofs = pSize*cnt;
|
|
|
+
|
|
|
+ memcpy(pvBuffer, buffer + pos, ofs);
|
|
|
+ pos += ofs;
|
|
|
+
|
|
|
+ return cnt;
|
|
|
+ };
|
|
|
+ size_t Write(const void* pvBuffer, size_t pSize, size_t pCount)
|
|
|
+ {
|
|
|
+ return 0;
|
|
|
+ };
|
|
|
+
|
|
|
+ aiReturn Seek(size_t pOffset, aiOrigin pOrigin)
|
|
|
+ {
|
|
|
+ if (aiOrigin_SET == pOrigin) {
|
|
|
+ if (pOffset >= size) {
|
|
|
+ return AI_FAILURE;
|
|
|
+ }
|
|
|
+ pos = pOffset;
|
|
|
+ }
|
|
|
+ else if (aiOrigin_END == pOrigin) {
|
|
|
+ if (pOffset >= size) {
|
|
|
+ return AI_FAILURE;
|
|
|
+ }
|
|
|
+ pos = size-pOffset;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if (pOffset + pos >= size) {
|
|
|
+ return AI_FAILURE;
|
|
|
+ }
|
|
|
+ pos += pOffset;
|
|
|
+ }
|
|
|
+ return AI_SUCCESS;
|
|
|
+ };
|
|
|
+
|
|
|
+ size_t Tell(void) const
|
|
|
+ {
|
|
|
+ return pos;
|
|
|
+ };
|
|
|
+
|
|
|
+ size_t FileSize() const
|
|
|
+ {
|
|
|
+ return size;
|
|
|
+ };
|
|
|
+
|
|
|
+ void Flush() {};
|
|
|
+
|
|
|
+
|
|
|
+ jobject javaObject()
|
|
|
+ {
|
|
|
+ return jIOStream;
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+class JavaIOSystem : public Assimp::IOSystem {
|
|
|
+ private:
|
|
|
+ JNIEnv* mJniEnv;
|
|
|
+ jobject& mJavaIOSystem;
|
|
|
+
|
|
|
+ public:
|
|
|
+ JavaIOSystem(JNIEnv* env, jobject& javaIOSystem) :
|
|
|
+ mJniEnv(env),
|
|
|
+ mJavaIOSystem(javaIOSystem)
|
|
|
+ {};
|
|
|
+
|
|
|
+ bool Exists( const char* pFile) const
|
|
|
+ {
|
|
|
+ jvalue params[1];
|
|
|
+ params[0].l = mJniEnv->NewStringUTF(pFile);
|
|
|
+ return call(mJniEnv, mJavaIOSystem, "jassimp/AiIOSystem", "exists", "(Ljava/lang/String;)Z", params);
|
|
|
+
|
|
|
+ };
|
|
|
+ char getOsSeparator() const
|
|
|
+ {
|
|
|
+ return (char) callc(mJniEnv, mJavaIOSystem, "jassimp/AiIOSystem", "getOsSeparator", "()C");
|
|
|
+ };
|
|
|
+
|
|
|
+ Assimp::IOStream* Open(const char* pFile,const char* pMode = "rb")
|
|
|
+ {
|
|
|
+ jvalue params[2];
|
|
|
+ params[0].l = mJniEnv->NewStringUTF(pFile);
|
|
|
+ params[1].l = mJniEnv->NewStringUTF(pMode);
|
|
|
+
|
|
|
+
|
|
|
+ jobject jStream = callo(mJniEnv, mJavaIOSystem, "jassimp/AiIOSystem", "open", "(Ljava/lang/String;Ljava/lang/String;)Ljassimp/AiIOStream;", params);
|
|
|
+ if(NULL == jStream)
|
|
|
+ {
|
|
|
+ lprintf("NULL object from AiIOSystem.open\n");
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ size_t size = calli(mJniEnv, jStream, "jassimp/AiIOStream", "getFileSize", "()I");
|
|
|
+ lprintf("Model file size is %d\n", size);
|
|
|
+
|
|
|
+ char* buffer = (char*)malloc(size);
|
|
|
+ jobject javaBuffer = mJniEnv->NewDirectByteBuffer(buffer, size);
|
|
|
+
|
|
|
+ jvalue readParams[1];
|
|
|
+ readParams[0].l = javaBuffer;
|
|
|
+ if(call(mJniEnv, jStream, "jassimp/AiIOStream", "read", "(Ljava/nio/ByteBuffer;)Z", readParams))
|
|
|
+ {
|
|
|
+ return new JavaIOStream(size, buffer, jStream);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ lprintf("Read failure on AiIOStream.read");
|
|
|
+ free(buffer);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ };
|
|
|
+ void Close( Assimp::IOStream* pFile)
|
|
|
+ {
|
|
|
+
|
|
|
+ jvalue params[1];
|
|
|
+ params[0].l = ((JavaIOStream*) pFile)->javaObject();
|
|
|
+ callv(mJniEnv, mJavaIOSystem, "jassimp/AiIOSystem", "close", "(Ljassimp/AiIOStream;)V", params);
|
|
|
+ delete pFile;
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+};
|
|
|
|
|
|
|
|
|
static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
|
|
@@ -1474,7 +1705,7 @@ JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getlongsize
|
|
|
JNIEXPORT jstring JNICALL Java_jassimp_Jassimp_getErrorString
|
|
|
(JNIEnv *env, jclass jClazz)
|
|
|
{
|
|
|
- const char *err = aiGetErrorString();
|
|
|
+ const char *err = gLastErrorString.c_str();
|
|
|
|
|
|
if (NULL == err)
|
|
|
{
|
|
@@ -1486,18 +1717,26 @@ JNIEXPORT jstring JNICALL Java_jassimp_Jassimp_getErrorString
|
|
|
|
|
|
|
|
|
JNIEXPORT jobject JNICALL Java_jassimp_Jassimp_aiImportFile
|
|
|
- (JNIEnv *env, jclass jClazz, jstring jFilename, jlong postProcess)
|
|
|
+ (JNIEnv *env, jclass jClazz, jstring jFilename, jlong postProcess, jobject ioSystem)
|
|
|
{
|
|
|
jobject jScene = NULL;
|
|
|
|
|
|
/* convert params */
|
|
|
const char* cFilename = env->GetStringUTFChars(jFilename, NULL);
|
|
|
+
|
|
|
+ Assimp::Importer imp;
|
|
|
|
|
|
-
|
|
|
+
|
|
|
+ if(ioSystem != NULL)
|
|
|
+ {
|
|
|
+ imp.SetIOHandler(new JavaIOSystem(env, ioSystem));
|
|
|
+ lprintf("Created aiFileIO\n");
|
|
|
+ }
|
|
|
+
|
|
|
lprintf("opening file: %s\n", cFilename);
|
|
|
|
|
|
/* do import */
|
|
|
- const aiScene *cScene = aiImportFile(cFilename, (unsigned int) postProcess);
|
|
|
+ const aiScene *cScene = imp.ReadFile(cFilename, (unsigned int) postProcess);
|
|
|
|
|
|
if (!cScene)
|
|
|
{
|
|
@@ -1552,19 +1791,13 @@ error:
|
|
|
/* thats really a problem because we cannot throw in this case */
|
|
|
env->FatalError("could not throw java.io.IOException");
|
|
|
}
|
|
|
-
|
|
|
- env->ThrowNew(exception, aiGetErrorString());
|
|
|
+ gLastErrorString = imp.GetErrorString();
|
|
|
+ env->ThrowNew(exception, gLastErrorString.c_str());
|
|
|
|
|
|
lprintf("problem detected\n");
|
|
|
}
|
|
|
|
|
|
end:
|
|
|
- /*
|
|
|
- * NOTE: this releases all memory used in the native domain.
|
|
|
- * Ensure all data has been passed to java before!
|
|
|
- */
|
|
|
- aiReleaseImport(cScene);
|
|
|
-
|
|
|
|
|
|
/* free params */
|
|
|
env->ReleaseStringUTFChars(jFilename, cFilename);
|