Merge pull request #1489 from ihmcrobotics/feature/jassimp-classloader
Feature/jassimp IO systempull/1494/head^2
commit
5a15226a95
|
@ -1,7 +1,9 @@
|
||||||
#include "jassimp.h"
|
#include "jassimp.h"
|
||||||
|
|
||||||
#include <assimp/cimport.h>
|
#include <assimp/Importer.hpp>
|
||||||
#include <assimp/scene.h>
|
#include <assimp/scene.h>
|
||||||
|
#include <assimp/IOStream.hpp>
|
||||||
|
#include <assimp/IOSystem.hpp>
|
||||||
|
|
||||||
|
|
||||||
#ifdef JNI_LOG
|
#ifdef JNI_LOG
|
||||||
|
@ -12,9 +14,11 @@
|
||||||
#define lprintf(...) printf (__VA_ARGS__)
|
#define lprintf(...) printf (__VA_ARGS__)
|
||||||
#endif /* ANDROID */
|
#endif /* ANDROID */
|
||||||
#else
|
#else
|
||||||
#define lprintf
|
#define lprintf
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static std::string gLastErrorString;
|
||||||
|
|
||||||
// Automatically deletes a local ref when it goes out of scope
|
// Automatically deletes a local ref when it goes out of scope
|
||||||
class SmartLocalRef {
|
class SmartLocalRef {
|
||||||
private:
|
private:
|
||||||
|
@ -270,6 +274,81 @@ static bool callv(JNIEnv *env, jobject object, const char* typeName,
|
||||||
return true;
|
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,
|
static bool callStaticObject(JNIEnv *env, const char* typeName, const char* methodName,
|
||||||
const char* signature,/* const*/ jvalue* params, jobject& returnValue)
|
const char* signature,/* const*/ jvalue* params, jobject& returnValue)
|
||||||
|
@ -359,6 +438,158 @@ static bool copyBufferArray(JNIEnv *env, jobject jMesh, const char* jBufferName,
|
||||||
return true;
|
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)
|
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
|
JNIEXPORT jstring JNICALL Java_jassimp_Jassimp_getErrorString
|
||||||
(JNIEnv *env, jclass jClazz)
|
(JNIEnv *env, jclass jClazz)
|
||||||
{
|
{
|
||||||
const char *err = aiGetErrorString();
|
const char *err = gLastErrorString.c_str();
|
||||||
|
|
||||||
if (NULL == err)
|
if (NULL == err)
|
||||||
{
|
{
|
||||||
|
@ -1486,18 +1717,26 @@ JNIEXPORT jstring JNICALL Java_jassimp_Jassimp_getErrorString
|
||||||
|
|
||||||
|
|
||||||
JNIEXPORT jobject JNICALL Java_jassimp_Jassimp_aiImportFile
|
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;
|
jobject jScene = NULL;
|
||||||
|
|
||||||
/* convert params */
|
/* convert params */
|
||||||
const char* cFilename = env->GetStringUTFChars(jFilename, NULL);
|
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);
|
lprintf("opening file: %s\n", cFilename);
|
||||||
|
|
||||||
/* do import */
|
/* do import */
|
||||||
const aiScene *cScene = aiImportFile(cFilename, (unsigned int) postProcess);
|
const aiScene *cScene = imp.ReadFile(cFilename, (unsigned int) postProcess);
|
||||||
|
|
||||||
if (!cScene)
|
if (!cScene)
|
||||||
{
|
{
|
||||||
|
@ -1552,19 +1791,13 @@ error:
|
||||||
/* thats really a problem because we cannot throw in this case */
|
/* thats really a problem because we cannot throw in this case */
|
||||||
env->FatalError("could not throw java.io.IOException");
|
env->FatalError("could not throw java.io.IOException");
|
||||||
}
|
}
|
||||||
|
gLastErrorString = imp.GetErrorString();
|
||||||
env->ThrowNew(exception, aiGetErrorString());
|
env->ThrowNew(exception, gLastErrorString.c_str());
|
||||||
|
|
||||||
lprintf("problem detected\n");
|
lprintf("problem detected\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
/*
|
|
||||||
* NOTE: this releases all memory used in the native domain.
|
|
||||||
* Ensure all data has been passed to java before!
|
|
||||||
*/
|
|
||||||
aiReleaseImport(cScene);
|
|
||||||
|
|
||||||
|
|
||||||
/* free params */
|
/* free params */
|
||||||
env->ReleaseStringUTFChars(jFilename, cFilename);
|
env->ReleaseStringUTFChars(jFilename, cFilename);
|
||||||
|
|
|
@ -39,7 +39,7 @@ JNIEXPORT jstring JNICALL Java_jassimp_Jassimp_getErrorString
|
||||||
* Signature: (Ljava/lang/String;J)Ljassimp/AiScene;
|
* Signature: (Ljava/lang/String;J)Ljassimp/AiScene;
|
||||||
*/
|
*/
|
||||||
JNIEXPORT jobject JNICALL Java_jassimp_Jassimp_aiImportFile
|
JNIEXPORT jobject JNICALL Java_jassimp_Jassimp_aiImportFile
|
||||||
(JNIEnv *, jclass, jstring, jlong);
|
(JNIEnv *, jclass, jstring, jlong, jobject);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2017 Florida Institute for Human and Machine Cognition (IHMC)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package jassimp;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IOSystem based on the Java classloader.<p>
|
||||||
|
*
|
||||||
|
* This IOSystem allows loading models directly from the
|
||||||
|
* classpath. No extraction to the file system is
|
||||||
|
* necessary.
|
||||||
|
*
|
||||||
|
* @author Jesper Smith
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class AiClassLoaderIOSystem implements AiIOSystem<AiInputStreamIOStream>
|
||||||
|
{
|
||||||
|
private final Class<?> clazz;
|
||||||
|
private final ClassLoader classLoader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new AiClassLoaderIOSystem.<p>
|
||||||
|
*
|
||||||
|
* This constructor uses a ClassLoader to resolve
|
||||||
|
* resources.
|
||||||
|
*
|
||||||
|
* @param classLoader classLoader to resolve resources.
|
||||||
|
*/
|
||||||
|
public AiClassLoaderIOSystem(ClassLoader classLoader) {
|
||||||
|
this.clazz = null;
|
||||||
|
this.classLoader = classLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new AiClassLoaderIOSystem.<p>
|
||||||
|
*
|
||||||
|
* This constructor uses a Class to resolve
|
||||||
|
* resources.
|
||||||
|
*
|
||||||
|
* @param class<?> class to resolve resources.
|
||||||
|
*/
|
||||||
|
public AiClassLoaderIOSystem(Class<?> clazz) {
|
||||||
|
this.clazz = clazz;
|
||||||
|
this.classLoader = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AiInputStreamIOStream open(String filename, String ioMode) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
InputStream is;
|
||||||
|
|
||||||
|
if(clazz != null) {
|
||||||
|
is = clazz.getResourceAsStream(filename);
|
||||||
|
}
|
||||||
|
else if (classLoader != null) {
|
||||||
|
is = classLoader.getResourceAsStream(filename);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
System.err.println("[" + getClass().getSimpleName() +
|
||||||
|
"] No class or classLoader provided to resolve " + filename);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(is != null) {
|
||||||
|
return new AiInputStreamIOStream(is);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
System.err.println("[" + getClass().getSimpleName() +
|
||||||
|
"] Cannot find " + filename);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close(AiInputStreamIOStream file) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean exists(String path)
|
||||||
|
{
|
||||||
|
URL url = null;
|
||||||
|
if(clazz != null) {
|
||||||
|
url = clazz.getResource(path);
|
||||||
|
}
|
||||||
|
else if (classLoader != null) {
|
||||||
|
url = classLoader.getResource(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(url == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char getOsSeparator()
|
||||||
|
{
|
||||||
|
return '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2017 Florida Institute for Human and Machine Cognition (IHMC)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package jassimp;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to allow custom resource loaders for jassimp.<p>
|
||||||
|
*
|
||||||
|
* The design is based on passing the file wholly in memory,
|
||||||
|
* because Java inputstreams do not have to support seek. <p>
|
||||||
|
*
|
||||||
|
* Writing files from Java is unsupported.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @author Jesper Smith
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface AiIOStream
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read all data into buffer. <p>
|
||||||
|
*
|
||||||
|
* The whole stream should be read into the buffer.
|
||||||
|
* No support is provided for partial reads.
|
||||||
|
*
|
||||||
|
* @param buffer Target buffer for the model data
|
||||||
|
*
|
||||||
|
* @return true if successful, false if an error occurred.
|
||||||
|
*/
|
||||||
|
boolean read(ByteBuffer buffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The total size of this stream. <p>
|
||||||
|
*
|
||||||
|
* @return total size of this stream
|
||||||
|
*/
|
||||||
|
int getFileSize();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2017 Florida Institute for Human and Machine Cognition (IHMC)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package jassimp;
|
||||||
|
|
||||||
|
public interface AiIOSystem <T extends AiIOStream>
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Open a new file with a given path.
|
||||||
|
* When the access to the file is finished, call close() to release all associated resources
|
||||||
|
*
|
||||||
|
* @param path Path to the file
|
||||||
|
* @param ioMode file I/O mode. Required are: "wb", "w", "wt", "rb", "r", "rt".
|
||||||
|
*
|
||||||
|
* @return AiIOStream or null if an error occurred
|
||||||
|
*/
|
||||||
|
public T open(String path, String ioMode);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for the existence of a file at the given path.
|
||||||
|
*
|
||||||
|
* @param path path to the file
|
||||||
|
* @return true if there is a file with this path, else false.
|
||||||
|
*/
|
||||||
|
public boolean exists(String path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the system specific directory separator.<p>
|
||||||
|
*
|
||||||
|
* @return System specific directory separator
|
||||||
|
*/
|
||||||
|
public char getOsSeparator();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the given file and releases all resources associated with it.
|
||||||
|
*
|
||||||
|
* @param file The file instance previously created by Open().
|
||||||
|
*/
|
||||||
|
public void close(T file);
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2017 Florida Institute for Human and Machine Cognition (IHMC)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package jassimp;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of AiIOStream reading from a InputStream
|
||||||
|
*
|
||||||
|
* @author Jesper Smith
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class AiInputStreamIOStream implements AiIOStream
|
||||||
|
{
|
||||||
|
private final ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
|
||||||
|
public AiInputStreamIOStream(URI uri) throws IOException {
|
||||||
|
this(uri.toURL());
|
||||||
|
}
|
||||||
|
|
||||||
|
public AiInputStreamIOStream(URL url) throws IOException {
|
||||||
|
this(url.openStream());
|
||||||
|
}
|
||||||
|
|
||||||
|
public AiInputStreamIOStream(InputStream is) throws IOException {
|
||||||
|
int read;
|
||||||
|
byte[] data = new byte[1024];
|
||||||
|
while((read = is.read(data, 0, data.length)) != -1) {
|
||||||
|
os.write(data, 0, read);
|
||||||
|
}
|
||||||
|
os.flush();
|
||||||
|
|
||||||
|
is.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getFileSize() {
|
||||||
|
return os.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean read(ByteBuffer buffer) {
|
||||||
|
ByteBufferOutputStream bos = new ByteBufferOutputStream(buffer);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
os.writeTo(bos);
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal helper class to copy the contents of an OutputStream
|
||||||
|
* into a ByteBuffer. This avoids a copy.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static class ByteBufferOutputStream extends OutputStream {
|
||||||
|
|
||||||
|
private final ByteBuffer buffer;
|
||||||
|
|
||||||
|
public ByteBufferOutputStream(ByteBuffer buffer) {
|
||||||
|
this.buffer = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(int b) throws IOException
|
||||||
|
{
|
||||||
|
buffer.put((byte) b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(byte b[], int off, int len) throws IOException {
|
||||||
|
buffer.put(b, off, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -79,6 +79,20 @@ public final class Jassimp {
|
||||||
return importFile(filename, EnumSet.noneOf(AiPostProcessSteps.class));
|
return importFile(filename, EnumSet.noneOf(AiPostProcessSteps.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imports a file via assimp without post processing.
|
||||||
|
*
|
||||||
|
* @param filename the file to import
|
||||||
|
* @param ioSystem ioSystem to load files, or null for default
|
||||||
|
* @return the loaded scene
|
||||||
|
* @throws IOException if an error occurs
|
||||||
|
*/
|
||||||
|
public static AiScene importFile(String filename, AiIOSystem<?> ioSystem)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
return importFile(filename, EnumSet.noneOf(AiPostProcessSteps.class), ioSystem);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Imports a file via assimp.
|
* Imports a file via assimp.
|
||||||
|
@ -89,12 +103,28 @@ public final class Jassimp {
|
||||||
* @throws IOException if an error occurs
|
* @throws IOException if an error occurs
|
||||||
*/
|
*/
|
||||||
public static AiScene importFile(String filename,
|
public static AiScene importFile(String filename,
|
||||||
Set<AiPostProcessSteps> postProcessing) throws IOException {
|
Set<AiPostProcessSteps> postProcessing)
|
||||||
|
throws IOException {
|
||||||
|
return importFile(filename, postProcessing, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imports a file via assimp.
|
||||||
|
*
|
||||||
|
* @param filename the file to import
|
||||||
|
* @param postProcessing post processing flags
|
||||||
|
* @param ioSystem ioSystem to load files, or null for default
|
||||||
|
* @return the loaded scene, or null if an error occurred
|
||||||
|
* @throws IOException if an error occurs
|
||||||
|
*/
|
||||||
|
public static AiScene importFile(String filename,
|
||||||
|
Set<AiPostProcessSteps> postProcessing, AiIOSystem<?> ioSystem)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
loadLibrary();
|
loadLibrary();
|
||||||
|
|
||||||
return aiImportFile(filename, AiPostProcessSteps.toRawValue(
|
return aiImportFile(filename, AiPostProcessSteps.toRawValue(
|
||||||
postProcessing));
|
postProcessing), ioSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -310,7 +340,7 @@ public final class Jassimp {
|
||||||
* @throws IOException if an error occurs
|
* @throws IOException if an error occurs
|
||||||
*/
|
*/
|
||||||
private static native AiScene aiImportFile(String filename,
|
private static native AiScene aiImportFile(String filename,
|
||||||
long postProcessing) throws IOException;
|
long postProcessing, AiIOSystem<?> ioSystem) throws IOException;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue