Added current WIP version of jAssimp

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@83 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
pull/1/head
aramis_acg 2008-08-07 22:55:02 +00:00
parent 42ef23e745
commit e358f6b938
47 changed files with 2784 additions and 1695 deletions

View File

@ -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"

View File

@ -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);
// 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;
}
// 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_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];
// 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++;
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

View File

@ -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

View File

@ -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:
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_java_lang_String;
static jclass Class;
//! Handle to the java.lang.String.getBytes() class
static jmethodID MID_String_getBytes;
static jmethodID getBytes;
//! Handle to the java.lang.String.String(byte[]) c'tor
static jmethodID MID_String_init;
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*.

View File

@ -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);
}
}
}}

View File

@ -39,66 +39,42 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Implementation of the JNI API for jAssimp */
package assimp;
#include "JNIEnvironment.h"
#include "JNILogger.h"
using namespace Assimp;
/**
* Defines base behaviour for all sub objects of <code>Mesh</code>.
*
* @author Aramis (Alexander Gessler)
* @version 1.0
*/
public abstract class Mappable {
namespace Assimp {
namespace JNIBridge {
/**
* Index of the mapped object in the parent Mesh
*/
private int m_iArrayIndex = 0;
// ------------------------------------------------------------------------------------------------
JNIEnvironment::_assimp::_NativeException::Initialize()
{
// get a handle to the JNI context for this thread
JNIEnv* pc = JJNIEnvironment::Get()->GetThread()->m_pcEnv;
/**
* 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;
// 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.");
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -50,18 +50,85 @@ package assimp;
* @author Aramis (Alexander Gessler)
* @version 1.0
*/
public class Animation extends Mappable {
public class Animation {
/**
* Construction from a given object and array index
*
* @param parent Must be valid, null is not allowed
* @param index Valied index in the parent's list
* The name of the animation.
*/
public Animation(Object parent, int index) {
super(parent, index);
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;
/**
* Returns the name of the animation channel
*
* @return If the modelling package this data was exported from does support
* only a single animation channel, this name is usually <code>""</code>
*/
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];
}
}

View File

@ -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];
}
}

View File

@ -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;
}
}

View File

@ -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 {
public boolean hasAlphaChannel() {
// first allocate the output array
data = 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;
// now allocate a temporary output array
byte[] temp = new byte[this.width];
// todo: add more
// 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");
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;
}
}

View File

@ -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";
}

View File

@ -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;

View File

@ -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();
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("jassimp64");
System.loadLibrary(JASSIMP_RUNTIME_NAME_X64);
}
catch (UnsatisfiedLinkError exc) {
try {
System.loadLibrary("jassimp32");
System.loadLibrary(JASSIMP_RUNTIME_NAME_X86);
}
catch (UnsatisfiedLinkError exc2) {
throw new NativeError("Unable to load the jassimp library");
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,9 +237,10 @@ 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;
}
@ -220,9 +250,10 @@ public class Importer {
* 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);
}

View File

@ -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 {
}
}

View File

@ -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]);
}
}

View File

@ -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;
}
}

View File

@ -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;
private int m_iMaterialIndex = 0;
/**
* 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);
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");
}
/**
* Provides access to the array of all bones influencing this
* mesh.
*
* @return Bone array
*/
public final Bone[] getBonesArray() {
assert (null != this.m_vBones);
return this.m_vBones;
}
/**
* JNI bridge function - for internal use only
* Retrieve a bit combination which indicates which vertex
* components are existing in the model.
* Get a bone influencing the mesh
*
* @param context Current importer context (imp.hashCode)
* @return Combination of the PF_XXX constants
* @param i Index of the bone
* @return Bone
*/
private native int _NativeGetPresenceFlags(long context, long index);
/**
* 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
*
* @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, 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];
}
}

View File

@ -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);
}
}

View File

@ -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,13 +85,7 @@ 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;
/**
@ -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() {
public final Matrix4x4 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;
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;
}
}

View File

@ -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
/** 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 synchronized int setVertexSplitLimit(int limit) {
if (s_iVertexSplitLimit != limit) {
// send to the JNI bridge ...
s_iVertexSplitLimit = limit;
_NativeSetVertexSplitLimit(limit);
}
return limit;
}
public static final PostProcessStep FixInfacingNormals =
new PostProcessStep("FixInfacingNormals");
/**
* 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
/** 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 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);
public static final PostProcessStep ImproveVertexLocality =
new PostProcessStep("ImproveVertexLocality");
private final String myName; // for debug only

View File

@ -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;
}
}

View File

@ -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,39 +74,103 @@ 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 number of meshes in the scene
* @return this value can be 0 if the <code>ANIMATION_SKELETON_ONLY</code>
* flag is set.
*/
public final int getNumMeshes() {
return m_vMeshes.length;
}
/**
* Get a mesh from the scene
* @param i Index of the mesh
* @return scene.mesh[i]
*/
public final Mesh getMesh(int i) {
assert(i < m_vMeshes.length);
return m_vMeshes[i];
}
/**
* Get the texture list
*
* @return Texture list
*/
public final Vector<Texture> getTextures() {
public final Texture[] getTextures() {
return m_vTextures;
}
/**
* Get the number of textures in the scene
* @return this value is often 0 since most texture's arent' embedded
*/
public int getNumTextures() {
return m_vTextures.length;
}
/**
* Get an embedded texture from the scene
* @param i Index of the mesh
* @return scene.texture[i]
*/
public final Texture getTexture(int i) {
assert(i < m_vTextures.length);
return m_vTextures[i];
}
/**
* Get the material list
*
* @return Material list
*/
public final Vector<Material> getMaterials() {
public final Material[] getMaterials() {
return m_vMaterials;
}
/**
* Get the number of animations in the scene
* @return this value could be 0, most models have no animations
*/
public int getNumAnimations() {
return m_vAnimations.length;
}
/**
* Get the animation list
*
* @return Animation list
*/
public final Vector<Animation> getAnimations() {
public final Animation[] getAnimations() {
return m_vAnimations;
}
@ -120,94 +182,4 @@ public class Scene {
public final Node getRootNode() {
return m_rootNode;
}
/**
* Used to initialize the class instance. Called by Importer. Will maybe
* be replaced with a RAII solution ...
*/
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;
}
/**
* 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
*/
private native int _NativeGetNumMeshes(long context);
/**
* 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
*/
private native int _NativeGetNumAnimations(long context);
/**
* 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
*/
private native int _NativeGetNumTextures(long context);
/**
* 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
*/
private native int _NativeGetNumMaterials(long context);
}

View File

@ -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

View File

@ -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
*/
@Override
protected void onMap() throws NativeError {
final int iNumPixels = width * height;
// first allocate the output array
data = new Color[iNumPixels];
// now allocate a temporary output array
byte[] temp = new byte[(iNumPixels) << 2];
// 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");
}
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;
}
/**
* 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
* 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.
*/
protected native int _NativeMapColorData(long context, long index, byte[] temp);
public BufferedImage convertToImage() {
/**
* 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);
BufferedImage buf = new BufferedImage(width,height, hasAlphaChannel()
? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
int[] aiColorBuffer = new int[width*height];
Color[] clr = getColorArray();
for (int i = 0; i < width*height;++i) {
aiColorBuffer[i] = clr[i].getRGB();
}
buf.setRGB(0,0,width,height,aiColorBuffer,0,width*4);
return buf;
}
}

View File

@ -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,46 +209,86 @@ public class DumpToFile {
/* Now iterate through all meshes that have been loaded
*/
int iMesh = 0;
if (0 != scene.getNumMeshes()) {
for (Mesh mesh : scene.getMeshes()) {
stream.write("Mesh " + iMesh + "\n");
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
* 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();
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(")\t").
append("nor(").
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(")\t").
append("tan(").
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(")\t").
append("bit(").
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(")\n").toString());
append(bitangents[i * 3 + 2]).append(")").toString());
}
stream.write("\n\n");
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
*/
@ -172,11 +299,108 @@ public class DumpToFile {
append(faces[i * 3 + 1]).append("|").
append(faces[i * 3 + 2]).append(")\n").toString());
}
stream.write("\n");
++iMesh;
/* 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");
}
}
/* 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");
}
}
}
}
/* 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();
}
}