diff --git a/port/jAssimp/jni_bridge/BuildHeader.bat b/port/jAssimp/jni_bridge/BuildHeader.bat index 2536eeca3..dc63ce67e 100644 --- a/port/jAssimp/jni_bridge/BuildHeader.bat +++ b/port/jAssimp/jni_bridge/BuildHeader.bat @@ -1,8 +1,2 @@ -javah -classpath ".\..\..\port\jAssimp\classes" -d "." "assimp.Importer" -javah -classpath ".\..\..\port\jAssimp\classes" -d "." "assimp.Material" -javah -classpath ".\..\..\port\jAssimp\classes" -d "." "assimp.Node" -javah -classpath ".\..\..\port\jAssimp\classes" -d "." "assimp.Scene" -javah -classpath ".\..\..\port\jAssimp\classes" -d "." "assimp.Mesh" -javah -classpath ".\..\..\port\jAssimp\classes" -d "." "assimp.Texture" -javah -classpath ".\..\..\port\jAssimp\classes" -d "." "assimp.Animation" -javah -classpath ".\..\..\port\jAssimp\classes" -d "." "assimp.PostProcessStep" +javah -classpath ".\..\classes" -d "." "assimp.Importer" + diff --git a/port/jAssimp/jni_bridge/JNIAnimation.cpp b/port/jAssimp/jni_bridge/JNIAnimation.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/port/jAssimp/jni_bridge/JNIBone.cpp b/port/jAssimp/jni_bridge/JNIBone.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/port/jAssimp/jni_bridge/JNIBoneAnim.cpp b/port/jAssimp/jni_bridge/JNIBoneAnim.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/port/jAssimp/jni_bridge/JNICalls.cpp b/port/jAssimp/jni_bridge/JNICalls.cpp index 5504210c7..fc2945322 100644 --- a/port/jAssimp/jni_bridge/JNICalls.cpp +++ b/port/jAssimp/jni_bridge/JNICalls.cpp @@ -41,15 +41,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file Implementation of the JNI API for jAssimp */ -#if (defined ASSIMP_JNI_EXPORT) // include the header files generated by javah #include "assimp_Importer.h" -#include "assimp_Animation.h" -#include "assimp_Node.h" -#include "assimp_Texture.h" -#include "assimp_Mesh.h" -#include "assimp_Material.h" // include assimp #include "../../include/aiTypes.h" @@ -59,9 +53,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../../include/aiAssert.h" #include "../../include/aiPostProcess.h" #include "../../include/assimp.hpp" - #include "../../include/DefaultLogger.h" +// include all jAssimp internal header files #include "JNIEnvironment.h" #include "JNILogger.h" @@ -165,7 +159,8 @@ JNIEXPORT jlong JNICALL Java_assimp_Importer__1NativeInitContext // setup the JNI environment ... // simply setup the newest JNIEnv* - JNIEnvironment::Get()->AttachToCurrentThread(jvmenv); + if(!JNIEnvironment::Get()->AttachToCurrentThread(jvmenv)) + return 0xffffffffffffffffL; return context; } @@ -218,10 +213,11 @@ JNIEXPORT jint JNICALL Java_assimp_Importer__1NativeLoad } // get the importer instance from the context Assimp::Importer* pcImp = (Assimp::Importer*)jvmcontext; + aiScene* pcOut; // and load the file. The aiScene object itself remains accessible // via Importer.GetScene(). - if(NULL == pcImp->ReadFile(std::string(szPath),(unsigned int)jvmflags)) + if(!(pcOut = pcImp->ReadFile(std::string(szPath),(unsigned int)jvmflags))) { DefaultLogger::get()->error("[jnibridge] Unable to load asset"); @@ -229,492 +225,26 @@ JNIEXPORT jint JNICALL Java_assimp_Importer__1NativeLoad free((void*)szPath); return AI_JNI_ERROR_RETURN; } + // release the path again free((void*)szPath); + + // 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 \ No newline at end of file diff --git a/port/jAssimp/jni_bridge/JNIEnvironment.cpp b/port/jAssimp/jni_bridge/JNIEnvironment.cpp index 462f0b303..2f694a598 100644 --- a/port/jAssimp/jni_bridge/JNIEnvironment.cpp +++ b/port/jAssimp/jni_bridge/JNIEnvironment.cpp @@ -41,8 +41,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file Implementation of the JNI API for jAssimp */ -#if (defined ASSIMP_JNI_EXPORT) - #include "JNIEnvironment.h" #include "JNILogger.h" @@ -51,36 +49,11 @@ using namespace Assimp; namespace Assimp { namespace JNIBridge { - -/*static*/ jclass JNIEnvironment::Class_java_lang_String = 0; -/*static*/ jmethodID JNIEnvironment::MID_String_getBytes = 0; -/*static*/ jmethodID JNIEnvironment::MID_String_init = 0; - - // ------------------------------------------------------------------------------------------------ bool JNIEnvironment::AttachToCurrentThread (JNIEnv* pcEnv) { ai_assert(NULL != pcEnv); - // first initialize some members - if (0 == Class_java_lang_String) - { - if( 0 == (Class_java_lang_String = pcEnv->FindClass("java.lang.String"))) - return false; - } - if (0 == MID_String_getBytes) - { - if( 0 == (MID_String_getBytes = pcEnv->GetStaticMethodID( - Class_java_lang_String,"getBytes","()[byte"))) - return false; - } - if (0 == MID_String_init) - { - if( 0 == (MID_String_init = pcEnv->GetStaticMethodID( - Class_java_lang_String,"String","([byte)V"))) - return false; - } - // now initialize the thread-local storage if (NULL == this->ptr.get()) { @@ -97,6 +70,10 @@ bool JNIEnvironment::AttachToCurrentThread (JNIEnv* pcEnv) // attach the logger ((JNILogDispatcher*)DefaultLogger::get())->OnAttachToCurrentThread(this->ptr.get()); + + // get handles to all methods/fields/classes + this->Initialize(); + return true; } // ------------------------------------------------------------------------------------------------ @@ -127,6 +104,33 @@ JNIThreadData* JNIEnvironment::GetThread() return this->ptr.get(); } // ------------------------------------------------------------------------------------------------ +void JNIEnvironment::_java::_lang::_String::Initialize() +{ + JNIEnv* pcEnv = JJNIEnvironment::Get()->GetThread()->m_pcEnv; + + // first initialize some members + if( !(this->Class = pcEnv->FindClass("java.lang.String"))) + JNIEnvironment::Get()->ThrowException("Unable to get handle of class java.lang.String"); + + if( !(this->getBytes = pcEnv->GetMethodID(this->Class,"getBytes","()[byte"))) + JNIEnvironment::Get()->ThrowException("Unable to get handle of class java.lang.String"); + + if( !(this->constructor_ByteArray = pcEnv->GetStaticMethodID( + this->Class,"","([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 + diff --git a/port/jAssimp/jni_bridge/JNIEnvironment.h b/port/jAssimp/jni_bridge/JNIEnvironment.h index 9253e9687..faf626b4b 100644 --- a/port/jAssimp/jni_bridge/JNIEnvironment.h +++ b/port/jAssimp/jni_bridge/JNIEnvironment.h @@ -48,12 +48,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -#include "../../include/aiAssert.h" +#include "../../../include/aiAssert.h" +#include "../../../include/aiMesh.h" +#include "../../../include/aiScene.h" + namespace Assimp { namespace JNIBridge { +#define AIJ_GET_HANDLE(__handle__) \ + (JNIEnvironment::Get()-> __handle__) + +#define AIJ_GET_DEFAULT_CTOR_HANDLE (__handle__) \ + (JNIEnvironment::Get()-> __handle__ . DefaultCtor) + +#define AIJ_GET_CLASS_HANDLE (__handle__) \ + (JNIEnvironment::Get()-> __handle__ . Class) + // --------------------------------------------------------------------------- /** @class JNIThreadData * @brief Manages a list of JNI data structures that are @@ -132,16 +144,310 @@ public: //! Get the thread local data of the current thread JNIThreadData* GetThread(); + //! Throw an NativeEror exception with the specified error message + //! The error message is optional. + void ThrowNativeError(const char* msg = NULL); + public: - //! Handle to the java.lang.String class - static jclass Class_java_lang_String; - //! Handle to the java.lang.String.getBytes() class - static jmethodID MID_String_getBytes; - //! Handle to the java.lang.String.String(byte[]) c'tor - static jmethodID MID_String_init; + struct _java + { + inline void Initialize() + { + lang.Initialize(); + } + + struct _lang + { + inline void Initialize() + { + String.Initialize(); + } + + struct _String + { + void Initialize(); + + //! Handle to the java.lang.String class + static jclass Class; + + //! Handle to the java.lang.String.getBytes() class + static jmethodID getBytes; + + //! Handle to the java.lang.String.String(byte[]) c'tor + static jmethodID constructor_ByteArray; + + } String; + + + struct _Array + { + void Initialize(); + + jclass FloatArray_Class; + jclass IntArray_Class; + + } Array; + + } lang; + } java; + + + + //! Represents the JNI interface to the package assimp + struct _assimp + { + //! Initializes the package assimp for use with jAssimp + inline void Initialize() + { + // the NativeError class must be initialized first as it + // is used by all other class initializers + NativeException.Initialize(); + + // now initialize all other classes, the rder doesn't care. + Scene.Initialize(); + Importer.Initialize(); + Mesh.Initialize(); + Bone.Initialize(); + Animation.Initialize(); + BoneAnim.Initialize(); + Texture.Initialize(); + CompressedTexture.Initialize(); + Matrix3x3.Initialize(); + Matrix4x4.Initialize(); + Quaternion.Initialize(); + Node.Initialize(); + Material.Initialize(); + }; + + //! Represents the JNI interface to class assimp.NativeException + struct _NativeException + { + void Initialize(); + + jclass Class; + + } NativeException; + + + //! Represents the JNI interface to class assimp.Importer + struct _Importer + { + void Initialize(); + + jclass Class; + + jfieldID scene; + + } Importer; + + + //! Represents the JNI interface to class assimp.Scene + struct _Scene + { + void Initialize(); + + jclass Class; + + jmethodID DefaultCtor; + + jfieldID m_vMeshes; + jfieldID m_vTextures; + jfieldID m_vMaterials; + jfieldID m_vAnimations; + jfieldID m_rootNode; + jfieldID flags; + + } Scene; + + + //! Represents the JNI interface to class assimp.Mesh + struct _Mesh + { + void Initialize(); + void Fill(jobject obj,const aiMesh* pcSrc); + + jclass Class; + + jmethodID DefaultCtor; + + jfieldID m_vVertices; + jfieldID m_vTangents; + jfieldID m_vBitangents; + jfieldID m_vNormals; + jfieldID m_avUVs; + jfieldID m_vFaces; + jfieldID m_avColors; + jfieldID m_aiNumUVComponents; + jfieldID m_vBones; + jfieldID m_iMaterialIndex; + + } Mesh; + + //! Represents the JNI interface to class assimp.Bone + struct _Bone + { + void Initialize(); + + jclass Class; + + jmethodID DefaultCtor; + + jfieldID name; + jfieldID weights; + + } Bone; + + //! Represents the JNI interface to class assimp.Animation + struct _Animation + { + void Initialize(); + + jclass Class; + + jmethodID DefaultCtor; + + jfieldID name; + jfieldID mDuration; + jfieldID mTicksPerSecond; + jfieldID boneAnims; + + } Animation; + + //! Represents the JNI interface to class assimp.BoneAnim + struct _BoneAnim + { + void Initialize(); + + + //! Represents the JNI interface to class assimp.BoneAnim.KeyFrame + 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*. diff --git a/port/jAssimp/jni_bridge/JNIIOStream.cpp b/port/jAssimp/jni_bridge/JNIIOStream.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/port/jAssimp/jni_bridge/JNIIOSystem.cpp b/port/jAssimp/jni_bridge/JNIIOSystem.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/port/jAssimp/jni_bridge/JNIMaterial.cpp b/port/jAssimp/jni_bridge/JNIMaterial.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/port/jAssimp/jni_bridge/JNIMesh.cpp b/port/jAssimp/jni_bridge/JNIMesh.cpp new file mode 100644 index 000000000..5608f5f8c --- /dev/null +++ b/port/jAssimp/jni_bridge/JNIMesh.cpp @@ -0,0 +1,239 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file Implementation of the JNI API for jAssimp */ + +#include "JNIEnvironment.h" +#include "JNILogger.h" + +using namespace Assimp; + +namespace Assimp { +namespace JNIBridge { + +// ------------------------------------------------------------------------------------------------ +void JNIEnvironment::_assimp::_Mesh::Initialize() +{ + JNIEnv* pc = JJNIEnvironment::Get()->GetThread()->m_pcEnv; + + // load a handle to the class + if(!(this->Class = pc->FindClass("assimp.Mesh"))) + JNIEnvironment::Get()->ThrowNativeError("Unable to load class assimp.mesh"); + + // load all fields of the class + this->m_vVertices = pc->GetFieldID(Class,"m_vVertices","[F"); + this->m_vNormals = pc->GetFieldID(Class,"m_vNormals","[F"); + this->m_vTangents = pc->GetFieldID(Class,"m_vTangents","[F"); + this->m_vBitangents = pc->GetFieldID(Class,"m_vBitangents","[F"); + this->m_avColors = pc->GetFieldID(Class,"m_avColors","[[F"); + this->m_avUVs = pc->GetFieldID(Class,"m_avColors","[[F"); + this->m_vFaces = pc->GetFieldID(Class,"m_vFaces","[I"); + this->m_vBones = pc->GetFieldID(Class,"m_vBones","[Lassimp.Bone;"); + + this->m_aiNumUVComponents = pc->GetFieldID(Class,"m_aiNumUVComponents","[I"); + this->m_iMaterialIndex = pc->GetFieldID(Class,"m_iMaterialIndex","I"); + + // check whether all fields have been loaded properly + if (!this->m_vVertices || !this->m_vNormals || !this->m_vTangents || + !this->m_vBitangents || !this->m_avColors || !this->m_avUVs || + !this->m_vFaces || !this->m_vBones || !this->m_aiNumUVComponents || + !this->m_iMaterialIndex) + { + JNIEnvironment::Get()->ThrowNativeError("Unable to load all fields of class assimp.mesh"); + } +} +// ------------------------------------------------------------------------------------------------ +void JNIEnvironment::_assimp::_Mesh::Fill(jobject obj,const aiMesh* pcSrc) +{ + JNIEnv* pc = JJNIEnvironment::Get()->GetThread()->m_pcEnv; + + // set the material index + pc->SetIntField(obj,this->m_iMaterialIndex,pcSrc->mMaterialIndex); + + + // allocate the arrays and fill them + float* pf; + const unsigned int size = pcSrc->mNumVertices*12; + const unsigned int size2 = pcSrc->mNumVertices*3; + + // copy vertex positions + if (pcSrc->HasPositions()) + { + // allocate and copy data + jfloatArray jfl = pc->NewFloatArray(size2); + JNU_CopyDataToArray(jfl,pcSrc->mVertices,size); + + // set the corresponding field in the java object + pc->SetObjectField(obj,this->m_vVertices,jfl); + } + // copy vertex normals + if (pcSrc->HasNormals()) + { + // allocate and copy data + jfloatArray jfl = pc->NewFloatArray(size2); + JNU_CopyDataToArray(jfl,pcSrc->mNormals,size); + + // set the corresponding field in the java object + pc->SetObjectField(obj,this->m_vNormals,jfl); + } + // copy tangents and bitangents + if (pcSrc->HasTangentsAndBitangents()) + { + // allocate and copy data + jfloatArray jfl = pc->NewFloatArray(size2); + JNU_CopyDataToArray(jfl,pcSrc->mTangents,size); + + // set the corresponding field in the java object + pc->SetObjectField(obj,this->m_vTangents,jfl); + + jfl = pc->NewFloatArray(size2); + JNU_CopyDataToArray(jfl,pcSrc->mBitangents,size); + + // set the corresponding field in the java object + pc->SetObjectField(obj,this->m_vBitangents,jfl); + } + // copy texture coordinates + if (pcSrc->HasTextureCoords(0)) + { + jobjectArray jobjarr = pc->NewObjectArray(AI_MAX_NUMBER_OF_TEXTURECOORDS, + AIJ_GET_HANDLE(java.lang.Array.FloatArray_Class),0); + + unsigned int channel = 0; + while (pcSrc->HasTextureCoords(channel)) + { + jfloatArray jfl = pc->NewFloatArray(size2); + JNU_CopyDataToArray(jfl,pcSrc->mTextureCoords[channel],size); + + pc->SetObjectArrayElement(jobjarr,channel,jfl) + ++channel; + } + + // set the corresponding field in the java object + pc->SetObjectField(obj,this->m_avUVs,jobjarr); + + jobjarr = (jobjectArray) pc->NewIntArray(AI_MAX_NUMBER_OF_TEXTURECOORDS); + pc->SetIntArrayRegion((jintArray)jobjarr,0,channel,&pcSrc->mNumUVComponents); + pc->SetObjectField(obj,this->m_aiNumUVComponents,jobjarr); + } + // copy vertex colors + if (pcSrc->HasVertexColors(0)) + { + const unsigned int size = pcSrc->mNumVertices<<4; + const unsigned int size2 = pcSrc->mNumVertices<<2; + + jobjectArray jobjarr = pc->NewObjectArray(AI_MAX_NUMBER_OF_COLOR_SETS, + AIJ_GET_HANDLE(java.lang.Array.FloatArray_Class),0); + + unsigned int channel = 0; + while (pcSrc->HasVertexColors(channel)) + { + jfloatArray jfl = pc->NewFloatArray(size2); + JNU_CopyDataToArray(jfl,pcSrc->mColors[channel],size); + + pc->SetObjectArrayElement(jobjarr,channel,jfl); + ++channel; + } + + // set the corresponding field in the java object + pc->SetObjectField(obj,this->m_avColors,jobjarr); + } + + + // copy faces + if (0 < pcSrc->mNumFaces) // just for safety + { + const unsigned int size = pcSrc->mNumFaces*12; + const unsigned int size2 = pcSrc->mNumFaces*3; + + // allocate and copy data + jintArray jil = pc->NewIntArray(size2); + + int* pf; + jboolean iscopy = FALSE; + + // lock the array and get direct access to its buffer + if(!pf = pc->GetPrimitiveArrayCritical(jil,&iscopy)) + JNIEnvironment::Get()->ThrowNativeError("Unable to lock face array"); + + // copy the data to the array - face by face + const aiFace** const pcEnd = pcSrc->mFaces+pcSrc->mNumFaces; + for (const aiFace* pcCur = pcSrc->mFaces;pcCur != pcEnd;++pcCur) + { + ai_assert(3 == pcCur->mNumIndices); + *pf++ = pcCur->mIndices[0]; + *pf++ = pcCur->mIndices[1]; + *pf++ = pcCur->mIndices[2]; + } + + // release our reference to the array + pc->ReleasePrimitiveArrayCritical(jil,pf,0); + + // set the corresponding field in the java object + pc->SetObjectField(obj,this->m_vFaces,jil); + } + + // copy bones + if (0 < pcSrc->mNumBones) + { + // allocate the array + jobjectArray jarr = pc->NewObjectArray(pcSrc->mNumBones, + AIJ_GET_HANDLE(assimp.Bone.Class),0); + + // and fill all members + for (unsigned int i = 0; i < pcSrc->mNumBones;++i) + { + // allocate the array element + jobject jobj = pc->NewObject(AIJ_GET_CLASS_HANDLE(assimp.Bone), + AIJ_GET_DEFAULT_CTOR_HANDLE(assimp.Bone)); + + // fill it from the native data + JNIEnvironment::Get()->assimp.Bone.Fill(jobj,pcSrc->mBones[i]); + + // and set the corresponding array entry + pc->SetObjectArrayElement(jarr,i,jobj); + } + + // set the corresponding field in the java object + pc->SetObjectField(obj,this->m_vBones,jil); + } +} + +}} \ No newline at end of file diff --git a/port/jAssimp/src/assimp/Mappable.java b/port/jAssimp/jni_bridge/JNINativeError.cpp similarity index 53% rename from port/jAssimp/src/assimp/Mappable.java rename to port/jAssimp/jni_bridge/JNINativeError.cpp index ddfa73158..31e04a877 100644 --- a/port/jAssimp/src/assimp/Mappable.java +++ b/port/jAssimp/jni_bridge/JNINativeError.cpp @@ -7,8 +7,8 @@ Copyright (c) 2006-2008, ASSIMP Development Team All rights reserved. -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the following +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above @@ -25,80 +25,56 @@ conditions are met: derived from this software without specific prior written permission of the ASSIMP Development Team. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------- */ +/** @file Implementation of the JNI API for jAssimp */ -package assimp; +#include "JNIEnvironment.h" +#include "JNILogger.h" +using namespace Assimp; -/** - * Defines base behaviour for all sub objects of Mesh. - * - * @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."); +} \ No newline at end of file diff --git a/port/jAssimp/jni_bridge/JNINode.cpp b/port/jAssimp/jni_bridge/JNINode.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/port/jAssimp/jni_bridge/JNIScene.cpp b/port/jAssimp/jni_bridge/JNIScene.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/port/jAssimp/jni_bridge/JNITexture.cpp b/port/jAssimp/jni_bridge/JNITexture.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/port/jAssimp/jni_bridge/assimp_Animation.h b/port/jAssimp/jni_bridge/assimp_Animation.h deleted file mode 100644 index 332bb6398..000000000 --- a/port/jAssimp/jni_bridge/assimp_Animation.h +++ /dev/null @@ -1,13 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class assimp_Animation */ - -#ifndef _Included_assimp_Animation -#define _Included_assimp_Animation -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif -#endif diff --git a/port/jAssimp/jni_bridge/assimp_Importer.h b/port/jAssimp/jni_bridge/assimp_Importer.h index 5e7a3af50..9c78855ab 100644 --- a/port/jAssimp/jni_bridge/assimp_Importer.h +++ b/port/jAssimp/jni_bridge/assimp_Importer.h @@ -7,13 +7,15 @@ #ifdef __cplusplus extern "C" { #endif +#undef assimp_Importer_PROPERTY_WAS_NOT_EXISTING +#define assimp_Importer_PROPERTY_WAS_NOT_EXISTING -1L /* * Class: assimp_Importer * Method: _NativeInitContext - * Signature: ()I + * Signature: (I)I */ JNIEXPORT jint JNICALL Java_assimp_Importer__1NativeInitContext - (JNIEnv *, jobject); + (JNIEnv *, jobject, jint); /* * Class: assimp_Importer @@ -31,6 +33,14 @@ JNIEXPORT jint JNICALL Java_assimp_Importer__1NativeFreeContext JNIEXPORT jint JNICALL Java_assimp_Importer__1NativeLoad (JNIEnv *, jobject, jstring, jint, jlong); +/* + * Class: assimp_Importer + * Method: _NativeSetPropertyInt + * Signature: (Ljava/lang/String;IJ)I + */ +JNIEXPORT jint JNICALL Java_assimp_Importer__1NativeSetPropertyInt + (JNIEnv *, jobject, jstring, jint, jlong); + #ifdef __cplusplus } #endif diff --git a/port/jAssimp/jni_bridge/assimp_Importer_DefaultIOStream.h b/port/jAssimp/jni_bridge/assimp_Importer_DefaultIOStream.h new file mode 100644 index 000000000..4394acc20 --- /dev/null +++ b/port/jAssimp/jni_bridge/assimp_Importer_DefaultIOStream.h @@ -0,0 +1,13 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* 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 diff --git a/port/jAssimp/jni_bridge/assimp_Importer_DefaultIOSystem.h b/port/jAssimp/jni_bridge/assimp_Importer_DefaultIOSystem.h new file mode 100644 index 000000000..8197b8f06 --- /dev/null +++ b/port/jAssimp/jni_bridge/assimp_Importer_DefaultIOSystem.h @@ -0,0 +1,13 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* 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 diff --git a/port/jAssimp/jni_bridge/assimp_Importer_Property.h b/port/jAssimp/jni_bridge/assimp_Importer_Property.h new file mode 100644 index 000000000..435c4b4e1 --- /dev/null +++ b/port/jAssimp/jni_bridge/assimp_Importer_Property.h @@ -0,0 +1,13 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* 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 diff --git a/port/jAssimp/jni_bridge/assimp_Material.h b/port/jAssimp/jni_bridge/assimp_Material.h deleted file mode 100644 index 0aa75e6c5..000000000 --- a/port/jAssimp/jni_bridge/assimp_Material.h +++ /dev/null @@ -1,13 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class assimp_Material */ - -#ifndef _Included_assimp_Material -#define _Included_assimp_Material -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif -#endif diff --git a/port/jAssimp/jni_bridge/assimp_Mesh.h b/port/jAssimp/jni_bridge/assimp_Mesh.h deleted file mode 100644 index a376085cb..000000000 --- a/port/jAssimp/jni_bridge/assimp_Mesh.h +++ /dev/null @@ -1,133 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* 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 diff --git a/port/jAssimp/jni_bridge/assimp_Node.h b/port/jAssimp/jni_bridge/assimp_Node.h deleted file mode 100644 index 593d7037a..000000000 --- a/port/jAssimp/jni_bridge/assimp_Node.h +++ /dev/null @@ -1,13 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class assimp_Node */ - -#ifndef _Included_assimp_Node -#define _Included_assimp_Node -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif -#endif diff --git a/port/jAssimp/jni_bridge/assimp_PostProcessStep.h b/port/jAssimp/jni_bridge/assimp_PostProcessStep.h deleted file mode 100644 index 4f4f53d43..000000000 --- a/port/jAssimp/jni_bridge/assimp_PostProcessStep.h +++ /dev/null @@ -1,33 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* 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 diff --git a/port/jAssimp/jni_bridge/assimp_Scene.h b/port/jAssimp/jni_bridge/assimp_Scene.h deleted file mode 100644 index 5a6a5a713..000000000 --- a/port/jAssimp/jni_bridge/assimp_Scene.h +++ /dev/null @@ -1,45 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* 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 diff --git a/port/jAssimp/jni_bridge/assimp_Texture.h b/port/jAssimp/jni_bridge/assimp_Texture.h deleted file mode 100644 index dbbb714ce..000000000 --- a/port/jAssimp/jni_bridge/assimp_Texture.h +++ /dev/null @@ -1,29 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* 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 diff --git a/port/jAssimp/jni_bridge/res/jAssimp.rc b/port/jAssimp/jni_bridge/res/jAssimp.rc new file mode 100644 index 000000000..d3a1398f3 --- /dev/null +++ b/port/jAssimp/jni_bridge/res/jAssimp.rc @@ -0,0 +1,84 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Deutsch (Deutschland) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#if (defined ASSIMP_JNI_EXPORT) + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x7L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040704b0" + BEGIN + VALUE "Comments", "Licensed under a 3-clause BSD license" + VALUE "CompanyName", "ASSIMP Development Team" + VALUE "FileDescription", "ASSIMP-JNI bridge module" + VALUE "FileVersion", "1, 0, 0, 0" + VALUE "InternalName", "jassimp" + VALUE "LegalCopyright", "Copyright (C) 2008" + VALUE "OriginalFilename", "jAssimpNN.dll" + VALUE "ProductName", "ASSIMP-JNI bridge module" + VALUE "ProductVersion", "1, 0, 0, 0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x407, 1200 + END +END + +#endif // !!ASSIMP_JNI_EXPORT + +#endif // Deutsch (Deutschland) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/port/jAssimp/module_assimp.xml b/port/jAssimp/module_assimp.xml new file mode 100644 index 000000000..7a06ca3d9 --- /dev/null +++ b/port/jAssimp/module_assimp.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/port/jAssimp/src/assimp/Animation.java b/port/jAssimp/src/assimp/Animation.java index 487809079..b57182ebf 100644 --- a/port/jAssimp/src/assimp/Animation.java +++ b/port/jAssimp/src/assimp/Animation.java @@ -50,18 +50,85 @@ package assimp; * @author Aramis (Alexander Gessler) * @version 1.0 */ -public class Animation extends Mappable { +public class Animation { + /** - * 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 "" + */ + 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 null + */ + 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 getNumBoneAnimChannels + * @return This value is never null + */ + public final BoneAnim getBoneAnimChannel(int i) { + assert(null != boneAnims && i < boneAnims.length); + return boneAnims[i]; } } diff --git a/port/jAssimp/src/assimp/Bone.java b/port/jAssimp/src/assimp/Bone.java index 1a3babbc1..00c66c208 100644 --- a/port/jAssimp/src/assimp/Bone.java +++ b/port/jAssimp/src/assimp/Bone.java @@ -1,11 +1,133 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + + package assimp; + /** - * Created by IntelliJ IDEA. - * User: Alex - * Date: 08.06.2008 - * Time: 15:31:01 - * To change this template use File | Settings | File Templates. + * A bone belongs to a mesh stores a list of vertex weights. + * It represents a joint of the skeleton. The bone hierarchy + * is contained in the node graph. + * + * @author Aramis (Alexander Gessler) + * @version 1.0 */ public class Bone { + + + /** + * Represents a single vertex weight + */ + public class Weight { + + + public Weight() { + index = 0; + weight = 1.0f; + } + + /** + * Index of the vertex in the corresponding Mesh + */ + 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 Weight 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 getNumWeights()-1 + * @return Vertex weight + */ + public final Weight getWeight(int weight) { + assert(null != weights && weight < this.weights.length); + return this.weights[weight]; + } } diff --git a/port/jAssimp/src/assimp/BoneAnim.java b/port/jAssimp/src/assimp/BoneAnim.java new file mode 100644 index 000000000..54a3ea460 --- /dev/null +++ b/port/jAssimp/src/assimp/BoneAnim.java @@ -0,0 +1,149 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + + +package assimp; + + +/** + * A bone animation channel defines the animation keyframes for + * a single bone in the mesh hierarchy. + * + * @author Aramis (Alexander Gessler) + * @version 1.0 + */ +public class BoneAnim { + + /** + * Describes a keyframe + */ + public class KeyFrame { + + /** + * 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[] mQuatKeys; + + /** + * Position keyframes. Component ordering is x,y,z + */ + private KeyFrame[] mPosKeys; + + /** + * scaling keyframes. Component ordering is x,y,z + */ + private KeyFrame[] 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 null if there are no rotation keys + */ + public final KeyFrame[] getQuatKeys() { + return mQuatKeys; + } + + /** + * Get a reference to the list of all position keyframes + * @return Could be null if there are no position keys + */ + public final KeyFrame[] getPosKeys() { + return mPosKeys; + } + + /** + * Get a reference to the list of all scaling keyframes + * @return Could be null if there are no scaling keys + */ + public final KeyFrame[] getScalingKeys() { + return mScalingKeys; + } + +} diff --git a/port/jAssimp/src/assimp/CompressedTexture.java b/port/jAssimp/src/assimp/CompressedTexture.java index dea38c7e9..d29f2984d 100644 --- a/port/jAssimp/src/assimp/CompressedTexture.java +++ b/port/jAssimp/src/assimp/CompressedTexture.java @@ -42,7 +42,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package assimp; +import javax.imageio.ImageIO; +import javax.imageio.stream.ImageInputStream; import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.ByteArrayInputStream; /** * Represents an embedded compressed texture that is stored in a format @@ -59,23 +64,6 @@ public class CompressedTexture extends Texture { private String m_format = ""; - - /** - * Construction from a given parent object and array index - * - * @param parent Must be valid, null is not allowed - * @param index Valied index in the parent's list - */ - public CompressedTexture(Object parent, int index) throws NativeError { - super(parent, index); - - // need to get the format of the texture via the JNI - if ((m_format = this._NativeGetCTextureFormat(((Scene) this.getParent()). - getImporter().getContext(), this.getArrayIndex())).equals("")) { - throw new NativeError("Unable to get the format of the compressed texture"); - } - } - /** * Retrieves the format of the texture data. This is * the most common file extension of the format (without a @@ -84,7 +72,7 @@ public class CompressedTexture extends Texture { * @return Extension string or null if the format of the texture * data is not known to ASSIMP. */ - public String getFormat() { + public final String getFormat() { return m_format; } @@ -93,15 +81,7 @@ public class CompressedTexture extends Texture { * * @return Data poiner */ - public byte[] getData() { - if (null == data) { - try { - this.onMap(); - } catch (NativeError nativeError) { - DefaultLogger.get().error(nativeError.getMessage()); - return null; - } - } + public final byte[] getData() { return (byte[]) data; } @@ -110,7 +90,7 @@ public class CompressedTexture extends Texture { * * @return Data poiner */ - public int getLength() { + public final int getLength() { return width; } @@ -120,7 +100,7 @@ public class CompressedTexture extends Texture { * @return n/a */ @Override - public int getHeight() { + public final int getHeight() { return 0; } @@ -130,7 +110,7 @@ public class CompressedTexture extends Texture { * @return n/a */ @Override - public int getWidth() { + public final int getWidth() { return 0; } @@ -150,33 +130,55 @@ public class CompressedTexture extends Texture { * @return n/a */ @Override - public Color[] getColorArray() { + public final Color[] getColorArray() { return null; } + /** - * Internal helper function to map the native texture data into - * a byte array in the memory of the JVM + * @return The return value is true of the + * file format can't be recognized. + * @see Texture.hasAlphaChannel() */ - @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 java.awt.BufferedImage + * + * @return java.awt.BufferedImage object containing + * a copy of the texture image. The return value is null + * 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; + } } diff --git a/port/jAssimp/src/assimp/ConfigProperty.java b/port/jAssimp/src/assimp/ConfigProperty.java new file mode 100644 index 000000000..e8f2b0afc --- /dev/null +++ b/port/jAssimp/src/assimp/ConfigProperty.java @@ -0,0 +1,154 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + + +package assimp; + +/** + * Defines configuration properties. + * + * Static helper class, can't be instanced. It defines configuration + * property keys to be used with Importer.setPropertyInt + * + * @author Aramis (Alexander Gessler) + * @version 1.0 + */ +public class ConfigProperty { + + private ConfigProperty() { + } + + + + /** + * Default value for the CONFIG_PP_SLM_TRIANGLE_LIMIT + * configuration property. + */ + public static final int DEFAULT_SLM_MAX_TRIANGLES = 1000000; + + + /** + * Default value for the CONFIG_PP_SLM_VERTEX_LIMIT + * configuration property. + */ + public static final int DEFAULT_SLM_MAX_VERTICES = 1000000; + + + /** + * Default value for the CONFIG_PP_LBW_MAX_WEIGHTS + * configuration property. + */ + public static final int DEFAULT_LBW_MAX_WEIGHTS = 4; + + + + + + /** + * Set the maximum number of vertices in a mesh. + *

+ * This is used by the "SplitLargeMeshes" PostProcess-Step to determine + * whether a mesh must be splitted or not. + * \note The default value is DEFAULT_SLM_MAX_TRIANGLES + */ + public static final String CONFIG_PP_SLM_TRIANGLE_LIMIT + = "pp.slm.triangle_limit"; + + + /** + * Set the maximum number of triangles in a mesh. + *

+ * This is used by the "SplitLargeMeshes" PostProcess-Step to determine + * whether a mesh must be splitted or not. + * \note The default value is DEFAULT_SLM_MAX_VERTICES + */ + public static final String CONFIG_PP_SLM_VERTEX_LIMIT + = "pp.slm.vertex_limit"; + + + /** + * Set the maximum number of bones affecting a single vertex + *

+ * This is used by the aiProcess_LimitBoneWeights PostProcess-Step. + * \note The default value is DEFAULT_LBW_MAX_WEIGHTS + */ + public static final String CONFIG_PP_LBW_MAX_WEIGHTS + = "pp.lbw.weights_limit"; + + + /** + * Set the vertex animation keyframe to be imported + *

+ * 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 + * CONFIG_IMPORT_XXX_KEYFRAME 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 + *

+ * 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"; +} diff --git a/port/jAssimp/src/assimp/IOSystem.java b/port/jAssimp/src/assimp/IOSystem.java index b9ac9fa97..d602d2561 100644 --- a/port/jAssimp/src/assimp/IOSystem.java +++ b/port/jAssimp/src/assimp/IOSystem.java @@ -42,7 +42,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package assimp; -import java.io.InputStream; import java.io.FileNotFoundException; diff --git a/port/jAssimp/src/assimp/Importer.java b/port/jAssimp/src/assimp/Importer.java index e519dbd2b..09386d224 100644 --- a/port/jAssimp/src/assimp/Importer.java +++ b/port/jAssimp/src/assimp/Importer.java @@ -45,9 +45,7 @@ package assimp; import java.util.Vector; import java.io.FileNotFoundException; import java.io.FileReader; -import java.io.IOException; import java.io.File; -import java.lang.ref.Reference; /** * Main class of jAssimp. The class is a simple wrapper for the native @@ -64,6 +62,15 @@ import java.lang.ref.Reference; */ public class Importer { + + /** + * Represents a property (key-value) + */ + private class Property { + String key; + Type value; + } + /** * Default implementation of IOStream. *
@@ -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> properties; + + + /** + * Specifies whether the native jAssimp library is currently + * in a loaded state. + */ + private static boolean bLibInitialized = false; + + + private static final String JASSIMP_RUNTIME_NAME_X64 = "jAssimp64"; + private static final String JASSIMP_RUNTIME_NAME_X86 = "jAssimp32"; + + public static final int PROPERTY_WAS_NOT_EXISTING = 0xffffffff; + /** * Public constructor. Initialises the JNI bridge to the native * ASSIMP library. A native Assimp::Importer object is constructed and @@ -159,47 +185,50 @@ public class Importer { * is initialized. * * @param iVersion Version of the JNI interface to be used. - * @throws NativeError Thrown if the jassimp library could not be loaded + * @throws NativeException Thrown if the jassimp library could not be loaded * or if the entry point to the module wasn't found. if this exception * is not thrown, you can assume that jAssimp is fully available. */ - public Importer(int iVersion) throws NativeError { + public Importer(int iVersion) throws NativeException { // allocate a default I/O system ioSystem = new DefaultIOSystem(); - /** try to load the jassimp library. First try to load the - * x64 version, in case of failure the x86 version - */ - try { - System.loadLibrary("jassimp64"); - } - catch (UnsatisfiedLinkError exc) { + if (!bLibInitialized) { + + /** try to load the jassimp library. First try to load the + * x64 version, in case of failure the x86 version + */ try { - System.loadLibrary("jassimp32"); + System.loadLibrary(JASSIMP_RUNTIME_NAME_X64); } - catch (UnsatisfiedLinkError exc2) { - throw new NativeError("Unable to load the jassimp library"); + catch (UnsatisfiedLinkError exc) { + try { + System.loadLibrary(JASSIMP_RUNTIME_NAME_X86); + } + catch (UnsatisfiedLinkError exc2) { + throw new NativeException("Unable to load the jAssimp library"); + } } + bLibInitialized = true; } // now create the native Importer class and setup our internal // data structures outside the VM. try { if (0xffffffffffffffffl == (this.m_iNativeHandle = _NativeInitContext(iVersion))) { - throw new NativeError( + throw new NativeException( "Unable to initialize the native library context." + "The initialization routine has failed"); } } catch (UnsatisfiedLinkError exc) { - throw new NativeError( + throw new NativeException( "Unable to initialize the native library context." + "The initialization routine has not been found"); } - return; } - public Importer() throws NativeError { + public Importer() throws NativeException { this(0); } @@ -208,21 +237,23 @@ public class Importer { * assets. If no custom implementation was provided via setIoSystem() * a default implementation will be used. Use isDefaultIoSystem() * to check this. + * * @return Always a valid IOSystem object, never null. */ - public IOSystem getIoSystem() { + public final IOSystem getIoSystem() { return ioSystem; } - + /** * Checks whether a default IO system is currently being used to load * assets. Using the default IO system has many performance benefits, * but it is possible to provide a custom IO system (setIoSystem()). * This allows applications to add support for archives like ZIP. + * * @return true if a default IOSystem 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 java.lang.Object.finalize() * 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 ConfigProperty class + * + * @param prop Name of the config property + * @param val New value for the config property + * @return Old value of the property or PROPERTY_WAS_NOT_EXISTING + * if the property has not yet been set. + */ + public final int setPropertyInt(final String prop, int val) { + + for (Property 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 propNew = new Property(); + 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 + * setPropertyInt. All supported config properties are + * defined as constants in the ConfigProperty 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 i : this.properties) { + if (i.key.equals(prop)) { + return i.value; + } + } + return error_return; + } + + /** + * Gets an integer config property that has been set using + * setPropertyInt. All supported config properties are + * defined as constants in the ConfigProperty class + * + * @param prop Name of the config property + * @return Current of the property or PROPERTY_WAS_NOT_EXISTING + * 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); } diff --git a/port/jAssimp/src/assimp/Material.java b/port/jAssimp/src/assimp/Material.java index b9a6f1f93..4e15fdf47 100644 --- a/port/jAssimp/src/assimp/Material.java +++ b/port/jAssimp/src/assimp/Material.java @@ -47,16 +47,179 @@ package assimp; /** * Class to wrap materials. Materials are represented in ASSIMP as a list of * key/value pairs, the key being a String 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 Object + * @param key MATKEY_XXX key constant + * @return null if the property wasn't there or hasn't + * the desired output type. The returned Object 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 String + */ 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 float[]. + * 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 float[]. + * 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 float[]. + * 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 float[]. + * 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 MATKEY_TEXOP_DIFFUSE */ public static String MATKEY_TEXOP_SPECULAR(int N) { return "$tex.op.specular[" + N + "]"; } /** - * @see MATKEY_TEXOP_DIFFUSE() + * @see MATKEY_TEXOP_DIFFUSE */ public static String MATKEY_TEXOP_AMBIENT(int N) { return "$tex.op.ambient[" + N + "]"; } /** - * @see MATKEY_TEXOP_DIFFUSE() + * @see MATKEY_TEXOP_DIFFUSE */ public static String MATKEY_TEXOP_EMISSIVE(int N) { return "$tex.op.emissive[" + N + "]"; } /** - * @see MATKEY_TEXOP_DIFFUSE() + * @see MATKEY_TEXOP_DIFFUSE */ public static String MATKEY_TEXOP_NORMALS(int N) { return "$tex.op.normals[" + N + "]"; } /** - * @see MATKEY_TEXOP_DIFFUSE() + * @see MATKEY_TEXOP_DIFFUSE */ public static String MATKEY_TEXOP_HEIGHT(int N) { return "$tex.op.height[" + N + "]"; } /** - * @see MATKEY_TEXOP_DIFFUSE() + * @see MATKEY_TEXOP_DIFFUSE */ public static String MATKEY_TEXOP_SHININESS(int N) { return "$tex.op.shininess[" + N + "]"; } /** - * @see MATKEY_TEXOP_DIFFUSE() + * @see MATKEY_TEXOP_DIFFUSE */ 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 { - - } } diff --git a/port/jAssimp/src/assimp/Matrix3x3.java b/port/jAssimp/src/assimp/Matrix3x3.java new file mode 100644 index 000000000..98ecd7284 --- /dev/null +++ b/port/jAssimp/src/assimp/Matrix3x3.java @@ -0,0 +1,149 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +package assimp; + +/** + * Represents a 3x3 row major matrix + * + * @author Aramis (Alexander Gessler) + * @version 1.0 + */ +public class Matrix3x3 { + + + /** + * Default constructor. Initializes the matrix with its identity + */ + public Matrix3x3() { + coeff[0] = coeff[4] = coeff[8] = 1.0f; + } + + /** + * Copy constructor + * @param other Matrix to be copied + */ + public Matrix3x3 ( Matrix3x3 other) { + System.arraycopy(other.coeff, 0, this.coeff, 0, 9); + } + + /** + * Construction from nine given coefficents + * @param a1 + * @param a2 + * @param a3 + * @param b1 + * @param b2 + * @param b3 + * @param c1 + * @param c2 + * @param c3 + */ + public Matrix3x3 (float a1, float a2, float a3, + float b1, float b2, float b3, + float c1, float c2, float c3) { + + coeff[0] = a1; + coeff[1] = a2; + coeff[2] = a3; + coeff[3] = b1; + coeff[4] = b2; + coeff[5] = b3; + coeff[6] = c1; + coeff[7] = c2; + coeff[8] = c3; + } + + + /** + * Copy constructor (construction from a 4x4 matrix) + * @param other Matrix to be copied + */ + public Matrix3x3 ( Matrix4x4 other) { + coeff[0] = other.coeff[0]; + coeff[1] = other.coeff[1]; + coeff[2] = other.coeff[2]; + coeff[3] = other.coeff[4]; + coeff[4] = other.coeff[5]; + coeff[5] = other.coeff[6]; + coeff[6] = other.coeff[8]; + coeff[7] = other.coeff[9]; + coeff[8] = other.coeff[10]; + } + + + /** + * The coefficients of the matrix + */ + public float[] coeff = new float[9]; + + + /** + * Returns a field in the matrix + * @param row Row index + * @param column Column index + * @return The corresponding field value + */ + public final float get(int row, int column) { + assert(row <= 2 && column <= 2); + return coeff[row*3+column]; + } + + + /** + * Multiplies *this* matrix with another matrix + * @param m Matrix to multiply with + * @return Output matrix + */ + public final Matrix3x3 Mul(Matrix3x3 m) { + + return new Matrix3x3( + m.coeff[0] * coeff[0] + m.coeff[3] * coeff[1] + m.coeff[6] * coeff[2], + m.coeff[1] * coeff[0] + m.coeff[4] * coeff[1] + m.coeff[7] * coeff[2], + m.coeff[2] * coeff[0] + m.coeff[5] * coeff[1] + m.coeff[8] * coeff[2], + m.coeff[0] * coeff[3] + m.coeff[3] * coeff[4] + m.coeff[6] * coeff[5], + m.coeff[1] * coeff[3] + m.coeff[4] * coeff[4] + m.coeff[7] * coeff[5], + m.coeff[2] * coeff[3] + m.coeff[5] * coeff[4] + m.coeff[8] * coeff[5], + m.coeff[0] * coeff[6] + m.coeff[3] * coeff[7] + m.coeff[6] * coeff[8], + m.coeff[1] * coeff[6] + m.coeff[4] * coeff[7] + m.coeff[7] * coeff[8], + m.coeff[2] * coeff[6] + m.coeff[5] * coeff[7] + m.coeff[8] * coeff[8]); + } +} diff --git a/port/jAssimp/src/assimp/Matrix4x4.java b/port/jAssimp/src/assimp/Matrix4x4.java new file mode 100644 index 000000000..da32f7abb --- /dev/null +++ b/port/jAssimp/src/assimp/Matrix4x4.java @@ -0,0 +1,179 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +package assimp; + +/** + * Represents a 4x4 row major matrix + * + * @author Aramis (Alexander Gessler) + * @version 1.0 + */ +public class Matrix4x4 { + + + /** + * Default constructor. Initializes the matrix with its identity + */ + public Matrix4x4() { + coeff[0] = coeff[5] = coeff[10] = coeff[15] = 1.0f; + } + + /** + * Copy constructor + * @param other Matrix to be copied + */ + public Matrix4x4 ( Matrix4x4 other) { + System.arraycopy(other.coeff, 0, this.coeff, 0, 16); + } + + + /** + * Construction from 16 given coefficents + * @param a1 + * @param a2 + * @param a3 + * @param a4 + * @param b1 + * @param b2 + * @param b3 + * @param b4 + * @param c1 + * @param c2 + * @param c3 + * @param c4 + * @param d1 + * @param d2 + * @param d3 + * @param d4 + */ + public Matrix4x4 (float a1, float a2, float a3, float a4, + float b1, float b2, float b3, float b4, + float c1, float c2, float c3, float c4, + float d1, float d2, float d3, float d4) { + + coeff[0] = a1; + coeff[1] = a2; + coeff[2] = a3; + coeff[3] = a4; + coeff[4] = b1; + coeff[5] = b2; + coeff[6] = b3; + coeff[7] = b4; + coeff[8] = c1; + coeff[9] = c2; + coeff[10] = c3; + coeff[11] = c4; + coeff[12] = d1; + coeff[13] = d2; + coeff[14] = d3; + coeff[15] = d4; + } + + + /** + * Copy constructor (construction from a 4x4 matrix) + * @param other Matrix to be copied + */ + public Matrix4x4 ( Matrix3x3 other) { + coeff[0] = other.coeff[0]; + coeff[1] = other.coeff[1]; + coeff[2] = other.coeff[2]; + coeff[4] = other.coeff[3]; + coeff[5] = other.coeff[4]; + coeff[6] = other.coeff[5]; + coeff[8] = other.coeff[6]; + coeff[9] = other.coeff[7]; + coeff[10] = other.coeff[8]; + coeff[15] = 1.0f; + } + + + /** + * The coefficients of the matrix + */ + public float[] coeff = new float[16]; + + + /** + * Returns a field in the matrix + * @param row Row index + * @param column Column index + * @return The corresponding field value + */ + public final float get(int row, int column) { + assert(row <= 3 && column <= 3); + return coeff[row*4+column]; + } + + + /** + * Computes the transpose of the matrix. *this* matrix + * will be modified! + */ + public final Matrix4x4 transpose() { + + float fTemp = coeff[1*4 +0]; + coeff[1*4 +0] = coeff[0*4 +1]; + coeff[0*4 +1] = fTemp; + + fTemp = coeff[2*4 +0]; + coeff[2*4 +0] = coeff[0*4 +2]; + coeff[0*4 +2] = fTemp; + + fTemp = coeff[2*4 +1]; + coeff[2*4 +1] = coeff[1*4 +2]; + coeff[1*4 +2] = fTemp; + + fTemp = coeff[3*4 +0]; + coeff[3*4 +0] = coeff[0*4 +3]; + coeff[0*4 +3] = fTemp; + + fTemp = coeff[3*4 +1]; + coeff[3*4 +1] = coeff[1*4 +3]; + coeff[1*4 +3] = fTemp; + + fTemp = coeff[3*4 +2]; + coeff[3*4 +2] = coeff[2*4 +3]; + coeff[2*4 +3] = fTemp; + return this; + } +} diff --git a/port/jAssimp/src/assimp/Mesh.java b/port/jAssimp/src/assimp/Mesh.java index 18be10065..60397b30f 100644 --- a/port/jAssimp/src/assimp/Mesh.java +++ b/port/jAssimp/src/assimp/Mesh.java @@ -60,48 +60,23 @@ import java.awt.*; * @author Aramis (Alexander Gessler) * @version 1.0 */ -public class Mesh extends Mappable { +public class Mesh { /** * Defines the maximum number of UV(W) channels that are available * for a mesh. If a loader finds more channels in a file, some * will be skipped */ - private static final int MAX_NUMBER_OF_TEXTURECOORDS = 0x4; + public static final int MAX_NUMBER_OF_TEXTURECOORDS = 0x4; /** * Defines the maximum number of vertex color channels that are * available for a mesh. If a loader finds more channels in a file, * some will be skipped */ - private static final int MAX_NUMBER_OF_COLOR_SETS = 0x4; + public static final int MAX_NUMBER_OF_COLOR_SETS = 0x4; - /** - * Specifies which vertex components are existing in - * the native implementation. If a member is null here, - * although it is existing, it hasn't yet been mapped - * into memory - */ - private int m_iPresentFlags = 0; - - private static final int PF_POSITION = 0x1; - private static final int PF_NORMAL = 0x2; - private static final int PF_TANGENTBITANGENT = 0x4; - private static final int PF_BONES = 0x8; - private static final int PF_VERTEXCOLOR = 0x1000; - private static final int PF_UVCOORD = 0x10000; - - private static int PF_VERTEXCOLORn(int n) { - assert(n <= MAX_NUMBER_OF_COLOR_SETS); - return PF_VERTEXCOLOR << n; - } - - private static int PF_UVCOORDn(int n) { - assert(n <= MAX_NUMBER_OF_TEXTURECOORDS); - return PF_UVCOORD << n; - } - /** * Contains the vertices loaded from the model */ @@ -150,53 +125,28 @@ public class Mesh extends Mappable { */ private int[] m_vFaces = null; - /** - * Number of vertices in the mesh - */ - private int m_iNumVertices; /** - * Number of faces in the mesh + * Bones which are influencing the mesh */ - private int m_iNumFaces; - - /** - * Number of bones in the mesh - */ - private int m_iNumBones; + private Bone[] m_vBones = null; /** * Material index of the mesh */ - private int m_iMaterialIndex; + 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 - * getVertex() will assert this. + * getPosition() 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 { * getNumUVComponents returns for channel * 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 * getNumUVComponents * (channel). 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 java.awt.Color */ - 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 getNumFaces() * @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]; + } } diff --git a/port/jAssimp/src/assimp/NativeError.java b/port/jAssimp/src/assimp/NativeException.java similarity index 92% rename from port/jAssimp/src/assimp/NativeError.java rename to port/jAssimp/src/assimp/NativeException.java index 4775c2b82..db81c4d3e 100644 --- a/port/jAssimp/src/assimp/NativeError.java +++ b/port/jAssimp/src/assimp/NativeException.java @@ -45,13 +45,13 @@ package assimp; * Exception class used by jAssimp. It is thrown whenever an unknown error * occurs in the JNI bridge between the native Assimp library and the Java VM. */ -public class NativeError extends Exception { +public class NativeException extends Exception { - public NativeError() { + public NativeException() { super("Unknown error"); } - public NativeError(String sz) { + public NativeException(String sz) { super(sz); } } diff --git a/port/jAssimp/src/assimp/Node.java b/port/jAssimp/src/assimp/Node.java index bfbb5e44b..10079e933 100644 --- a/port/jAssimp/src/assimp/Node.java +++ b/port/jAssimp/src/assimp/Node.java @@ -70,7 +70,7 @@ public class Node { * Local transformation matrix of the node * Stored in row-major order. */ - private float[] nodeTransform = null; + private Matrix4x4 nodeTransform = null; /** @@ -85,15 +85,9 @@ public class Node { * List of all child nodes * May be empty */ - private Vector children = null; - private int numChildren = 0; // temporary - - /** - * Parent scene - */ - private Scene parentScene = null; - + private Node[] children = null; + /** * Parent node or null if we're the root node of the scene */ @@ -101,31 +95,29 @@ public class Node { /** * Constructs a new node and initializes it - * @param parentScene Parent scene object * @param parentNode Parent node or null for root nodes - * @param index Unique index of the node */ - public Node(Scene parentScene, Node parentNode, int index) { + public Node(Node parentNode) { - this.parentScene = parentScene; this.parent = parentNode; - - // Initialize JNI class members, including numChildren - this._NativeInitMembers(parentScene.getImporter().getContext(),index); - - // get all children of the node - for (int i = 0; i < numChildren;++i) { - this.children.add(new Node(parentScene, this, ++index)); - } } + /** + * Returns the number of meshes of this node + * @return Number of meshes + */ + public final int getNumMeshes() { + return meshIndices.length; + } + /** * Get a list of all meshes of this node * - * @return Array containing indices into the Scene's mesh list + * @return Array containing indices into the Scene's mesh list. + * If there are no meshes, the array is null */ - 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 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 null + * 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; } } diff --git a/port/jAssimp/src/assimp/PostProcessStep.java b/port/jAssimp/src/assimp/PostProcessStep.java index a8e1bffa1..e14cbead4 100644 --- a/port/jAssimp/src/assimp/PostProcessStep.java +++ b/port/jAssimp/src/assimp/PostProcessStep.java @@ -187,78 +187,27 @@ public class PostProcessStep { new PostProcessStep("ValidateDataStructure"); - /** - * Set the vertex split limit for the "SplitLargeMeshes" process - * If a mesh exceeds this limit it will be splitted - * - * @param limit New vertex split limit. Pass 0xffffffff to disable - * a vertex split limit. However, splitting by triangles is still active - * then. - * @return Old vertex split limit - */ - public static synchronized int setVertexSplitLimit(int limit) { - if (s_iVertexSplitLimit != limit) { - // send to the JNI bridge ... - s_iVertexSplitLimit = limit; - _NativeSetVertexSplitLimit(limit); - } - return limit; - } + /** This step tries to determine which meshes have normal vectors + * that are facing inwards. The algorithm is simple but effective: + * the bounding box of all vertices + their normals is compared against + * the volume of the bounding box of all vertices without their normals. + * This works well for most objects, problems might occur with planar + * surfaces. However the step tries to filter such cases out. + * The step inverts all infacing normals. Generally it is recommended + * to enable this step. + */ + public static final PostProcessStep FixInfacingNormals = + new PostProcessStep("FixInfacingNormals"); - /** - * Set the triangle split limit for the "SplitLargeMeshes" process - * If a mesh exceeds this limit it will be splitted - * - * @param limit new triangle split limit. Pass 0xffffffff to disable - * a triangle split limit. However, splitting by vertices is still active - * then. - * @return Old triangle split limit - */ - public static synchronized int setTriangleSplitLimit(int limit) { - if (s_iTriangleSplitLimit != limit) { - // send to the JNI bridge ... - s_iTriangleSplitLimit = limit; - _NativeSetTriangleSplitLimit(limit); - } - return limit; - } - /** - * Set the bone weight limit for the "LimitBoneWeights" process - * If a mesh exceeds this limit it will be splitted - * - * @param limit new bone weight limit. Pass 0xffffffff to disable it. - * @return Old bone weight limit - */ - public static synchronized int setSetBoneWeightLimit(int limit) { - if (s_iBoneWeightLimit != limit) { - // send to the JNI bridge ... - s_iBoneWeightLimit = limit; - _NativeSetBoneWeightLimit(limit); - } - return limit; - } - - /** - * JNI bridge call. For internal use only - * - * @param limit New vertex split limit - */ - private native static void _NativeSetVertexSplitLimit(int limit); - - /** - * JNI bridge call. For internal use only - * - * @param limit New triangle split limit - */ - private native static void _NativeSetTriangleSplitLimit(int limit); - - /** - * JNI bridge call. For internal use only - * - * @param limit New bone weight limit - */ - private native static void _NativeSetBoneWeightLimit(int limit); + /** 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: + * http://www.cs.princeton.edu/gfx/pubs/Sander_2007_%3ETR/tipsy.pdf + */ + public static final PostProcessStep ImproveVertexLocality = + new PostProcessStep("ImproveVertexLocality"); private final String myName; // for debug only diff --git a/port/jAssimp/src/assimp/Quaternion.java b/port/jAssimp/src/assimp/Quaternion.java new file mode 100644 index 000000000..288cf95af --- /dev/null +++ b/port/jAssimp/src/assimp/Quaternion.java @@ -0,0 +1,147 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +package assimp; + + +/** + * Represents a rotation quaternion + * + * @author Aramis (Alexander Gessler) + * @version 1.0 + */ +public class Quaternion { + + public float x, y, z, w; + + + /** + * Construction from euler angles + * + * @param fPitch Rotation around the x axis + * @param fYaw Rotation around the y axis + * @param fRoll Rotation around the z axis + */ + public Quaternion(float fPitch, float fYaw, float fRoll) { + float fSinPitch = (float) Math.sin(fPitch * 0.5F); + float fCosPitch = (float) Math.cos(fPitch * 0.5F); + float fSinYaw = (float) Math.sin(fYaw * 0.5F); + float fCosYaw = (float) Math.cos(fYaw * 0.5F); + float fSinRoll = (float) Math.sin(fRoll * 0.5F); + float fCosRoll = (float) Math.cos(fRoll * 0.5F); + float fCosPitchCosYaw = (fCosPitch * fCosYaw); + float fSinPitchSinYaw = (fSinPitch * fSinYaw); + x = fSinRoll * fCosPitchCosYaw - fCosRoll * fSinPitchSinYaw; + y = fCosRoll * fSinPitch * fCosYaw + fSinRoll * fCosPitch * fSinYaw; + z = fCosRoll * fCosPitch * fSinYaw - fSinRoll * fSinPitch * fCosYaw; + w = fCosRoll * fCosPitchCosYaw + fSinRoll * fSinPitchSinYaw; + } + + /** + * Construction from an existing rotation matrix + * + * @param pRotMatrix Matrix to be converted to a quaternion + */ + public Quaternion(Matrix3x3 pRotMatrix) { + + float t = 1 + pRotMatrix.coeff[0] + pRotMatrix.coeff[4] + pRotMatrix.coeff[8]; + + // large enough + if (t > 0.00001f) { + float s = (float) Math.sqrt(t) * 2.0f; + x = (pRotMatrix.coeff[8] - pRotMatrix.coeff[7]) / s; + y = (pRotMatrix.coeff[6] - pRotMatrix.coeff[2]) / s; + z = (pRotMatrix.coeff[1] - pRotMatrix.coeff[3]) / s; + w = 0.25f * s; + } // else we have to check several cases + else if (pRotMatrix.coeff[0] > pRotMatrix.coeff[4] && + pRotMatrix.coeff[0] > pRotMatrix.coeff[8]) { + // Column 0: + float s = (float) Math.sqrt(1.0f + pRotMatrix.coeff[0] - + pRotMatrix.coeff[4] - pRotMatrix.coeff[8]) * 2.0f; + x = -0.25f * s; + y = (pRotMatrix.coeff[1] + pRotMatrix.coeff[3]) / s; + z = (pRotMatrix.coeff[6] + pRotMatrix.coeff[2]) / s; + w = (pRotMatrix.coeff[7] - pRotMatrix.coeff[5]) / s; + } + else if (pRotMatrix.coeff[4] > pRotMatrix.coeff[8]) { + // Column 1: + float s = (float) Math.sqrt(1.0f + pRotMatrix.coeff[4] - + pRotMatrix.coeff[0] - pRotMatrix.coeff[8]) * 2.0f; + x = (pRotMatrix.coeff[1] + pRotMatrix.coeff[3]) / s; + y = -0.25f * s; + z = (pRotMatrix.coeff[5] + pRotMatrix.coeff[7]) / s; + w = (pRotMatrix.coeff[2] - pRotMatrix.coeff[6]) / s; + } + else { + // Column 2: + float s = (float) Math.sqrt(1.0f + pRotMatrix.coeff[8] - + pRotMatrix.coeff[0] - pRotMatrix.coeff[4]) * 2.0f; + x = (pRotMatrix.coeff[6] + pRotMatrix.coeff[2]) / s; + y = (pRotMatrix.coeff[5] + pRotMatrix.coeff[7]) / s; + z = -0.25f * s; + w = (pRotMatrix.coeff[3] - pRotMatrix.coeff[1]) / s; + } + } + + + /** + * Convert the quaternion to a rotation matrix + * + * @return 3x3 rotation matrix + */ + public Matrix3x3 getMatrix() { + + Matrix3x3 resMatrix = new Matrix3x3(); + resMatrix.coeff[0] = 1.0f - 2.0f * (y * y + z * z); + resMatrix.coeff[1] = 2.0f * (x * y + z * w); + resMatrix.coeff[2] = 2.0f * (x * z - y * w); + resMatrix.coeff[3] = 2.0f * (x * y - z * w); + resMatrix.coeff[4] = 1.0f - 2.0f * (x * x + z * z); + resMatrix.coeff[5] = 2.0f * (y * z + x * w); + resMatrix.coeff[6] = 2.0f * (x * z + y * w); + resMatrix.coeff[7] = 2.0f * (y * z - x * w); + resMatrix.coeff[8] = 1.0f - 2.0f * (x * x + y * y); + + return resMatrix; + } + +} diff --git a/port/jAssimp/src/assimp/Scene.java b/port/jAssimp/src/assimp/Scene.java index 9199a7af3..3bbd3928c 100644 --- a/port/jAssimp/src/assimp/Scene.java +++ b/port/jAssimp/src/assimp/Scene.java @@ -42,8 +42,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package assimp; -import java.util.Vector; - /** * Represents the asset data that has been loaded. A scene consists of * multiple meshes, animations, materials and embedded textures. @@ -57,13 +55,13 @@ import java.util.Vector; */ public class Scene { - // NOTE: use Vector's to be able to use the constructor for initialisation - private Vector m_vMeshes; - private Vector m_vTextures; - private Vector m_vMaterials; - private Vector 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 getMeshes() { + public final Mesh[] getMeshes() { return m_vMeshes; } + /** + * Get the number of meshes in the scene + * @return this value can be 0 if the ANIMATION_SKELETON_ONLY + * 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 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 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 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); } diff --git a/port/jAssimp/src/assimp/ShadingMode.java b/port/jAssimp/src/assimp/ShadingMode.java index cde2e282e..9bc2dd6c3 100644 --- a/port/jAssimp/src/assimp/ShadingMode.java +++ b/port/jAssimp/src/assimp/ShadingMode.java @@ -43,7 +43,7 @@ package assimp; /** * Defines all shading models supported by the library - *

+ * * 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 diff --git a/port/jAssimp/src/assimp/Texture.java b/port/jAssimp/src/assimp/Texture.java index e3c1b41d8..2f225638b 100644 --- a/port/jAssimp/src/assimp/Texture.java +++ b/port/jAssimp/src/assimp/Texture.java @@ -43,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package assimp; import java.awt.*; +import java.awt.image.BufferedImage; /** * Represents an embedded texture. Sometimes textures are not referenced @@ -56,31 +57,14 @@ import java.awt.*; * @author Aramis (Alexander Gessler) * @version 1.0 */ -public class Texture extends Mappable { +public class Texture { protected int width = 0; protected int height = 0; + protected int needAlpha = 0xffffffff; protected Object data = null; - /** - * Construction from a given parent object and array index - * - * @param parent Must be valid, null is not allowed - * @param index Valied index in the parent's list - */ - public Texture(Object parent, int index) throws NativeError { - super(parent, index); - - long lTemp; - if (0x0 == (lTemp = this._NativeGetTextureInfo(((Scene) this.getParent()). - getImporter().getContext(), this.getArrayIndex()))) { - throw new NativeError("Unable to get the width and height of the texture"); - } - this.width = (int) (lTemp); - this.height = (int) (lTemp >> 32); - } - /** * Retrieve the height of the texture image @@ -100,6 +84,30 @@ public class Texture extends Mappable { return width; } + + /** + * Returns whether the texture uses its alpha channel + * @return true 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 java.awt.Color, 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 java.awt.Color array + * Convert the texture into a java.awt.BufferedImage + * @return java.awt.BufferedImage object containing + * a copy of the texture image. The texture is a ARGB texture if + * an alpha channel is required, otehrwise RGB is used as format. */ - @Override - protected void onMap() throws NativeError { - final int iNumPixels = width * height; + public BufferedImage convertToImage() { - // first allocate the output array - data = new Color[iNumPixels]; + BufferedImage buf = new BufferedImage(width,height, hasAlphaChannel() + ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB); - // now allocate a temporary output array - byte[] temp = new byte[(iNumPixels) << 2]; + int[] aiColorBuffer = new int[width*height]; + Color[] clr = getColorArray(); - // and copy the native color data to it - if (0xffffffff == this._NativeMapColorData(((Scene) this.getParent()).getImporter().getContext(), - this.getArrayIndex(), temp)) { - throw new NativeError("Unable to map aiTexture into the Java-VM"); + for (int i = 0; i < width*height;++i) { + aiColorBuffer[i] = clr[i].getRGB(); } - DefaultLogger.get().debug("Texture.onMap successful"); - - // now convert the temporary representation to a Color array - // (data is given in BGRA order, we need RGBA) - for (int i = 0, iBase = 0; i < iNumPixels; ++i, iBase += 4) { - ((Color[]) data)[i] = new Color(temp[iBase + 2], temp[iBase + 1], temp[iBase], temp[iBase + 3]); - } - return; + buf.setRGB(0,0,width,height,aiColorBuffer,0,width*4); + return buf; } - - /** - * JNI bridge call. For internal use only - * The method maps the contents of the native aiTexture object into memory - * the native memory area will be deleted afterwards. - * - * @param context Current importer context (imp.hashCode) - * @param index Index of the texture in the scene - * @param temp Output array. Assumed to be width * height * 4 in size - * @return 0xffffffff if an error occured - */ - protected native int _NativeMapColorData(long context, long index, byte[] temp); - - /** - * JNI bridge call. For internal use only - * The method retrieves information on the underlying texture - * - * @param context Current importer context (imp.hashCode) - * @param index Index of the texture in the scene - * @return 0x0 if an error occured, otherwise the width in the lower 32 bits - * and the height in the higher 32 bits - */ - private native long _NativeGetTextureInfo(long context, long index); } diff --git a/port/jAssimp/src/assimp/test/DumpToFile.java b/port/jAssimp/src/assimp/test/DumpToFile.java index 2d48fc395..e6f6f46a0 100644 --- a/port/jAssimp/src/assimp/test/DumpToFile.java +++ b/port/jAssimp/src/assimp/test/DumpToFile.java @@ -57,6 +57,78 @@ import java.io.IOException; */ public class DumpToFile { + + /** + * Count all nodes recursively + * + * @param node Current node + * @return Number of nodes + */ + public static int CountNodes(Node node) { + + int ret = 1; + if (0 != node.getNumChildren()) { + for (Node n : node.getChildren()) { + + ret += CountNodes(n); + } + } + return ret; + } + + + /** + * Print all nodes recursively + * + * @param node Current node + * @param stream Output stream + * @param suffix Suffix to all output + * @throws IOException yes ... sometimes ... :-) + */ + public static void PrintNodes(Node node, FileWriter stream, String suffix) throws IOException { + String suffNew = suffix + "\t"; + stream.write(suffix + node.getName() + "\n"); + + // print all meshes + if (0 != node.getNumMeshes()) { + stream.write(suffNew + "Meshes: "); + + for (int i : node.getMeshes()) { + + stream.write(i + " "); + } + stream.write("\n"); + } + + // print all children + if (0 != node.getNumChildren()) { + for (Node n : node.getChildren()) { + + PrintNodes(n, stream, suffNew); + } + } + } + + + /** + * Saves an embedded texture image as TrueVision Targa file + * + * @param texture Texture to be exported + * @param path Output path + * @throws IOException yes ... sometimes ... :-) + */ + public static void SaveTextureToTGA(Texture texture, String path) throws IOException { + + } + + + /** + * Entry point of the application + * + * @param arguments The first argument is the name of the + * mesh to be opened, the second is te name of the primary output file. + * @throws IOException + */ public static void Main(String[] arguments) throws IOException { /* Use output.txt as default output file if none was specified @@ -67,7 +139,20 @@ public class DumpToFile { arguments = new String[2]; arguments[0] = s; arguments[1] = "output.txt"; - } else if (2 != arguments.length) return; + } else if (2 != arguments.length) { + System.exit(-5); + } + + int iLen; + if ((iLen = arguments[1].length()) < 4 || + arguments[1].charAt(iLen - 1) != 't' || + arguments[1].charAt(iLen - 2) != 'x' || + arguments[1].charAt(iLen - 3) != 't' || + arguments[1].charAt(iLen - 4) != '.') { + System.out.println("The output path must have .txt as file extension"); + System.exit(-10); + return; + } FileWriter stream; try { @@ -75,20 +160,21 @@ public class DumpToFile { } catch (IOException e) { e.printStackTrace(); System.out.println("Unable to open output file"); - throw e; + System.exit(-15); + return; } /* Try to create an instance of class assimp.Importer. - * The constructor throws an assimp.NativeError exception + * The constructor throws an assimp.NativeException exception * if the native jAssimp library is not available.It must * be placed in the jar/class directory of the application */ Importer imp; try { imp = new Importer(); - } catch (NativeError nativeError) { - nativeError.printStackTrace(); - System.out.println("NativeError exception [#1]: " + nativeError.getMessage()); + } catch (NativeException nativeException) { + nativeException.printStackTrace(); + System.out.println("NativeException exception [#1]: " + nativeException.getMessage()); return; } @@ -101,8 +187,9 @@ public class DumpToFile { imp.addPostProcessStep(PostProcessStep.CalcTangentSpace); imp.addPostProcessStep(PostProcessStep.GenSmoothNormals); imp.addPostProcessStep(PostProcessStep.JoinIdenticalVertices); + imp.addPostProcessStep(PostProcessStep.FixInfacingNormals); - /* Load the asset into memory. Again, a NativeError exception + /* Load the asset into memory. Again, a NativeException exception * could be thrown if an unexpected errors occurs in the * native interface. If assimp is just unable to load the asset * null is the return value and no exception is thrown @@ -110,9 +197,9 @@ public class DumpToFile { Scene scene; try { scene = imp.readFile(arguments[0]); - } catch (NativeError nativeError) { - nativeError.printStackTrace(); - System.out.println("NativeError exception [#2] :" + nativeError.getMessage()); + } catch (NativeException nativeException) { + nativeException.printStackTrace(); + System.out.println("NativeException exception [#2] :" + nativeException.getMessage()); return; } if (null == scene) { @@ -122,61 +209,198 @@ public class DumpToFile { /* Now iterate through all meshes that have been loaded */ - int iMesh = 0; - for (Mesh mesh : scene.getMeshes()) { + if (0 != scene.getNumMeshes()) { + for (Mesh mesh : scene.getMeshes()) { - stream.write("Mesh " + iMesh + "\n"); - stream.write("\tNum Vertices: " + mesh.getNumVertices() + "\n"); - stream.write("\tNum Faces: " + mesh.getNumFaces() + "\n"); - stream.write("\tNum Bones: " + mesh.getNumBones() + "\n\n"); + 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(); - for (int i = 0; i < mesh.getNumVertices(); ++i) { + /* Output all vertices. First get direct access to jAssimp's buffers + */ + float[] positions = mesh.getPositionArray(); + float[] normals = mesh.getNormalArray(); + float[] tangents = mesh.getTangentArray(); + float[] bitangents = mesh.getBitangentArray(); - // format: "Vertex pos(x|y|z) nor(x|y|z) tan(x|y|) bit(x|y|z)" - // great that this IDE is automatically able to replace + with append ... ;-) - stream.write(new StringBuilder(). - append("\tVertex: pos("). - append(positions[i * 3]).append("|"). - append(positions[i * 3 + 1]).append("|"). - append(positions[i * 3 + 2]).append(")\t"). - append("nor("). - append(normals[i * 3]).append("|"). - append(normals[i * 3 + 1]).append("|"). - append(normals[i * 3 + 2]).append(")\t"). - append("tan("). - append(tangents[i * 3]).append("|"). - append(tangents[i * 3 + 1]).append("|"). - append(tangents[i * 3 + 2]).append(")\t"). - append("bit("). - append(bitangents[i * 3]).append("|"). - append(bitangents[i * 3 + 1]).append("|"). - append(bitangents[i * 3 + 2]).append(")\n").toString()); + float[][] uvs = new float[ Mesh.MAX_NUMBER_OF_TEXTURECOORDS][]; + for (int i = 0; i < Mesh.MAX_NUMBER_OF_TEXTURECOORDS; ++i) { + if (mesh.hasUVCoords((i))) uvs[i] = mesh.getTexCoordArray(i); + else break; + } + float[][] vcs = new float[ Mesh.MAX_NUMBER_OF_COLOR_SETS][]; + for (int i = 0; i < Mesh.MAX_NUMBER_OF_COLOR_SETS; ++i) { + if (mesh.hasVertexColors((i))) uvs[i] = mesh.getVertexColorArray(i); + else break; + } + + for (int i = 0; i < mesh.getNumVertices(); ++i) { + + // format: "Vertex pos(x|y|z) nor(x|y|z) tan(x|y|) bit(x|y|z)" + // great that this IDE is automatically able to replace + with append ... ;-) + if (mesh.hasPositions()) { + stream.write(new StringBuilder(). + append("\tVertex: pos("). + append(positions[i * 3]).append("|"). + append(positions[i * 3 + 1]).append("|"). + append(positions[i * 3 + 2]).append(")").toString()); + } + if (mesh.hasNormals()) { + stream.write(new StringBuilder(). + append("\tnor("). + append(normals[i * 3]).append("|"). + append(normals[i * 3 + 1]).append("|"). + append(normals[i * 3 + 2]).append(")").toString()); + } + if (mesh.hasTangentsAndBitangents()) { + stream.write(new StringBuilder(). + append("\ttan("). + append(tangents[i * 3]).append("|"). + append(tangents[i * 3 + 1]).append("|"). + append(tangents[i * 3 + 2]).append(")").toString()); + + stream.write(new StringBuilder(). + append("\tbit("). + append(bitangents[i * 3]).append("|"). + append(bitangents[i * 3 + 1]).append("|"). + append(bitangents[i * 3 + 2]).append(")").toString()); + } + + for (int a = 0; i < Mesh.MAX_NUMBER_OF_TEXTURECOORDS; ++a) { + if (!mesh.hasUVCoords((a))) break; + + stream.write(new StringBuilder().append("\tuv").append(a).append("("). + append(uvs[a][i * 3]).append("|"). + append(uvs[a][i * 3 + 1]).append("|"). + append(uvs[a][i * 3 + 2]).append(")").toString()); + } + + for (int a = 0; i < Mesh.MAX_NUMBER_OF_COLOR_SETS; ++a) { + if (!mesh.hasVertexColors((a))) break; + + stream.write(new StringBuilder().append("\tcol").append(a).append("("). + append(vcs[a][i * 4]).append("|"). + append(vcs[a][i * 4 + 1]).append("|"). + append(vcs[a][i * 4 + 2]).append("|"). + append(vcs[a][i * 4 + 3]).append(")").toString()); + } + stream.write("\n"); + } + stream.write("\n"); + + /* Now write a list of all faces in this model + */ + int[] faces = mesh.getFaceArray(); + for (int i = 0; i < mesh.getNumFaces(); ++i) { + stream.write(new StringBuilder().append("\tFace ("). + append(faces[i * 3]).append("|"). + append(faces[i * 3 + 1]).append("|"). + append(faces[i * 3 + 2]).append(")\n").toString()); + } + stream.write("\n"); + + /* Now write a list of all bones of this model + */ + if (mesh.hasBones()) { + Bone[] bones = mesh.getBonesArray(); + for (Bone bone : bones) { + + stream.write("\tBone " + bone.getName() + "\n"); + Bone.Weight[] weights = bone.getWeightsArray(); + for (Bone.Weight weight : weights) { + stream.write("\t\tWeight (" + weight.index + "|" + weight.weight + ")\n"); + } + + } + } + stream.write("\n"); } - stream.write("\n\n"); - - /* Now write a list of all faces in this model - */ - int[] faces = mesh.getFaceArray(); - for (int i = 0; i < mesh.getNumFaces(); ++i) { - stream.write(new StringBuilder().append("\tFace ("). - append(faces[i * 3]).append("|"). - append(faces[i * 3 + 1]).append("|"). - append(faces[i * 3 + 2]).append(")\n").toString()); - } - - ++iMesh; } + /* 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 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 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 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(); } }