Merge branch 'master' into feature/jassimp-classloader-license

pull/1497/head
Kim Kulling 2017-10-18 09:58:37 +02:00 committed by GitHub
commit b0c435a66e
5 changed files with 336 additions and 9 deletions

2
.gitignore vendored
View File

@ -81,3 +81,5 @@ lib64/assimp-vc120-mtd.ilk
lib64/assimp-vc120-mtd.exp
lib64/assimp-vc120-mt.exp
xcuserdata
cmake-build-debug

View File

@ -214,7 +214,7 @@ static bool getStaticField(JNIEnv *env, const char* className, const char* field
return false;
}
jfieldID fieldId = env->GetFieldID(clazz, fieldName, signature);
jfieldID fieldId = env->GetStaticFieldID(clazz, fieldName, signature);
if (NULL == fieldId)
{
@ -1005,8 +1005,164 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene)
return true;
}
static bool loadMetadata(JNIEnv *env, const aiNode* cNode, jobject& jNode)
{
aiMetadata *cMetadata = cNode->mMetaData;
static bool loadSceneNode(JNIEnv *env, const aiNode *cNode, jobject parent, jobject* loadedNode = NULL)
for(unsigned i = 0; i<cMetadata->mNumProperties; i++) {
aiString& metaDataKey = cMetadata->mKeys[i];
void* cData = cMetadata->mValues[i].mData;
aiMetadataType cMetadataType = cMetadata->mValues[i].mType;
jobject jAiMetadataEntry = NULL;
SmartLocalRef refMetadataEntry(env, jAiMetadataEntry);
if(!createInstance(env, "jassimp/AiMetadataEntry", jAiMetadataEntry)) {
return false;
}
jobject jAiMetadataTypeEnumValue = NULL;
SmartLocalRef refMetadataTypeEnumValue(env, jAiMetadataTypeEnumValue);
jobject jMetadataData = NULL;
SmartLocalRef refMetadataData(env, jMetadataData);
bool getMetadataTypeSuccess = false;
bool getMetadataDataSuccess = false;
jvalue boxingMethodArgument[1];
jboolean exceptionThrown;
switch (cMetadataType) {
case AI_BOOL: {
getMetadataTypeSuccess = getStaticField(env, "jassimp/AiMetadataEntry$AiMetadataType", "AI_BOOL", "Ljassimp/AiMetadataEntry$AiMetadataType;", jAiMetadataTypeEnumValue);
boxingMethodArgument[0].z = (jboolean) *static_cast<bool*>(cData);
getMetadataDataSuccess = callStaticObject(env, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", boxingMethodArgument, jMetadataData);
break;
}
case AI_INT32: {
getMetadataTypeSuccess = getStaticField(env, "jassimp/AiMetadataEntry$AiMetadataType", "AI_INT32", "Ljassimp/AiMetadataEntry$AiMetadataType;", jAiMetadataTypeEnumValue);
boxingMethodArgument[0].i = (jint) *static_cast<int32_t*>(cData);
getMetadataDataSuccess = callStaticObject(env, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", boxingMethodArgument, jMetadataData);
break;
}
case AI_UINT64: {
getMetadataTypeSuccess = getStaticField(env, "jassimp/AiMetadataEntry$AiMetadataType", "AI_UINT64", "Ljassimp/AiMetadataEntry$AiMetadataType;", jAiMetadataTypeEnumValue);
boxingMethodArgument[0].j = (jlong) *static_cast<uint64_t*>(cData);
getMetadataDataSuccess = callStaticObject(env, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", boxingMethodArgument, jMetadataData);
break;
}
case AI_FLOAT: {
getMetadataTypeSuccess = getStaticField(env, "jassimp/AiMetadataEntry$AiMetadataType", "AI_FLOAT", "Ljassimp/AiMetadataEntry$AiMetadataType;", jAiMetadataTypeEnumValue);
boxingMethodArgument[0].f = (jfloat) *static_cast<float*>(cData);
getMetadataDataSuccess = callStaticObject(env, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", boxingMethodArgument, jMetadataData);
break;
}
case AI_DOUBLE: {
getMetadataTypeSuccess = getStaticField(env, "jassimp/AiMetadataEntry$AiMetadataType", "AI_DOUBLE", "Ljassimp/AiMetadataEntry$AiMetadataType;", jAiMetadataTypeEnumValue);
boxingMethodArgument[0].d = (jdouble) *static_cast<double*>(cData);
getMetadataDataSuccess = callStaticObject(env, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", boxingMethodArgument, jMetadataData);
break;
}
case AI_AISTRING: {
getMetadataTypeSuccess = getStaticField(env, "jassimp/AiMetadataEntry$AiMetadataType", "AI_AISTRING", "Ljassimp/AiMetadataEntry$AiMetadataType;", jAiMetadataTypeEnumValue);
jMetadataData = env->NewStringUTF(static_cast<aiString*>(cData)->C_Str());
getMetadataDataSuccess = (jMetadataData != NULL);
break;
}
case AI_AIVECTOR3D: {
getMetadataTypeSuccess = getStaticField(env, "jassimp/AiMetadataEntry$AiMetadataType", "AI_AIVECTOR3D",
"Ljassimp/AiMetadataEntry$AiMetadataType;",
jAiMetadataTypeEnumValue);
jvalue wrapVec3Args[3];
aiVector3D *vector3D = static_cast<aiVector3D *>(cData);
wrapVec3Args[0].f = vector3D->x;
wrapVec3Args[1].f = vector3D->y;
wrapVec3Args[2].f = vector3D->z;
getMetadataDataSuccess = callStaticObject(env, "jassimp/Jassimp", "wrapVec3", "(FFF)Ljava/lang/Object;",
wrapVec3Args, jMetadataData);
break;
}
default: {
getMetadataTypeSuccess = false;
getMetadataDataSuccess = false;
break;
}
}
exceptionThrown = env->ExceptionCheck();
if(!getMetadataTypeSuccess || !getMetadataDataSuccess) {
if(exceptionThrown)
{
env->ExceptionDescribe();
}
return false;
}
if(!setObjectField(env, jAiMetadataEntry, "mType", "Ljassimp/AiMetadataEntry$AiMetadataType;", jAiMetadataTypeEnumValue)) {
exceptionThrown = env->ExceptionCheck();
if(exceptionThrown)
{
env->ExceptionDescribe();
}
return false;
}
if(!setObjectField(env, jAiMetadataEntry, "mData", "Ljava/lang/Object;", jMetadataData)) {
exceptionThrown = env->ExceptionCheck();
if(exceptionThrown)
{
env->ExceptionDescribe();
}
return false;
}
jobject jNodeMetadata = NULL;
SmartLocalRef refMetadata(env, jNodeMetadata);
if(!getField(env, jNode, "m_metaData", "Ljava/util/Map;", jNodeMetadata)) {
exceptionThrown = env->ExceptionCheck();
if(exceptionThrown)
{
env->ExceptionDescribe();
}
return false;
}
jclass hashMapClass = env->FindClass("java/util/HashMap");
jmethodID jHashMapPutMethod = env->GetMethodID(hashMapClass, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
jstring jKey = env->NewStringUTF(metaDataKey.C_Str());
SmartLocalRef keyRef(env, jKey);
// Only check exception instead of result here because maps will return
// null on success if they did not overwrite an existing mapping for the given key.
env->CallObjectMethod(jNodeMetadata, jHashMapPutMethod, jKey, jAiMetadataEntry);
exceptionThrown = env->ExceptionCheck();
if(exceptionThrown) {
env->ExceptionDescribe();
return false;
}
}
return true;
}
static bool loadSceneNode(JNIEnv *env, const aiNode *cNode, jobject parent, jobject* loadedNode = NULL)
{
lprintf(" converting node %s ...\n", cNode->mName.C_Str());
@ -1019,7 +1175,7 @@ static bool loadSceneNode(JNIEnv *env, const aiNode *cNode, jobject parent, jobj
wrapMatParams[0].l = jMatrixArr;
jobject jMatrix;
SmartLocalRef refMatrix(env, jMatrix);
if (!callStaticObject(env, "jassimp/Jassimp", "wrapMatrix", "([F)Ljava/lang/Object;", wrapMatParams, jMatrix))
{
return false;
@ -1068,12 +1224,19 @@ static bool loadSceneNode(JNIEnv *env, const aiNode *cNode, jobject parent, jobj
}
}
if (NULL != loadedNode)
{
*loadedNode = jNode;
} else {
env->DeleteLocalRef(jNode);
}
if (NULL != loadedNode)
{
if(cNode->mMetaData) {
if(!loadMetadata(env, cNode, jNode))
{
return false;
}
}
*loadedNode = jNode;
} else {
env->DeleteLocalRef(jNode);
}
return true;
}

View File

@ -0,0 +1,118 @@
package jassimp;
/*
---------------------------------------------------------------------------
Open Asset Import Library - Java Binding (jassimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp 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 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.
---------------------------------------------------------------------------
*/
public class AiMetadataEntry
{
public enum AiMetadataType
{
AI_BOOL, AI_INT32, AI_UINT64, AI_FLOAT, AI_DOUBLE, AI_AISTRING, AI_AIVECTOR3D
}
private AiMetadataType mType;
private Object mData;
public AiMetadataType getMetaDataType()
{
return mType;
}
public Object getData()
{
return mData;
}
public static boolean getAiBoolAsBoolean(AiMetadataEntry metadataEntry)
{
checkTypeBeforeCasting(metadataEntry, AiMetadataType.AI_BOOL);
return (boolean) metadataEntry.mData;
}
public static int getAiInt32AsInteger(AiMetadataEntry metadataEntry)
{
checkTypeBeforeCasting(metadataEntry, AiMetadataType.AI_INT32);
return (int) metadataEntry.mData;
}
public static long getAiUint64AsLong(AiMetadataEntry metadataEntry)
{
checkTypeBeforeCasting(metadataEntry, AiMetadataType.AI_UINT64);
return (long) metadataEntry.mData;
}
public static float getAiFloatAsFloat(AiMetadataEntry metadataEntry)
{
checkTypeBeforeCasting(metadataEntry, AiMetadataType.AI_FLOAT);
return (float) metadataEntry.mData;
}
public static double getAiDoubleAsDouble(AiMetadataEntry metadataEntry)
{
checkTypeBeforeCasting(metadataEntry, AiMetadataType.AI_DOUBLE);
return (double) metadataEntry.mData;
}
public static String getAiStringAsString(AiMetadataEntry metadataEntry)
{
checkTypeBeforeCasting(metadataEntry, AiMetadataType.AI_AISTRING);
return (String) metadataEntry.mData;
}
public static AiVector getAiAiVector3DAsAiVector(AiMetadataEntry metadataEntry)
{
checkTypeBeforeCasting(metadataEntry, AiMetadataType.AI_AIVECTOR3D);
return (AiVector) metadataEntry.mData;
}
private static void checkTypeBeforeCasting(AiMetadataEntry entry, AiMetadataType expectedType)
{
if(entry.mType != expectedType)
{
throw new RuntimeException("Cannot cast entry of type " + entry.mType.name() + " to " + expectedType.name());
}
}
}

View File

@ -41,7 +41,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package jassimp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
@ -185,6 +187,18 @@ public final class AiNode {
public int[] getMeshes() {
return m_meshReferences;
}
/**
* Returns the metadata entries for this node.<p>
*
* Consult the original Doxygen for importer_notes to
* see which formats have metadata and what to expect.
*
* @return A map of metadata names to entries.
*/
public Map<String, AiMetadataEntry> getMetadata() {
return m_metaData;
}
/**
@ -219,6 +233,11 @@ public final class AiNode {
* List of children.
*/
private final List<AiNode> m_children = new ArrayList<AiNode>();
/**
* List of metadata entries.
*/
private final Map<String, AiMetadataEntry> m_metaData = new HashMap<String, AiMetadataEntry>();
/**

View File

@ -280,3 +280,28 @@ TEST_F( utObjImportExport, issue1453_segfault ) {
const aiScene *scene = myimporter.ReadFileFromMemory( ObjModel.c_str(), ObjModel.size(), aiProcess_ValidateDataStructure );
EXPECT_EQ( nullptr, scene );
}
TEST_F(utObjImportExport, relative_indices_Test) {
static const std::string ObjModel =
"v -0.500000 0.000000 0.400000\n"
"v -0.500000 0.000000 -0.800000\n"
"v -0.500000 1.000000 -0.800000\n"
"v -0.500000 1.000000 0.400000\n"
"f -4 -3 -2 -1\nB";
Assimp::Importer myimporter;
const aiScene *scene = myimporter.ReadFileFromMemory(ObjModel.c_str(), ObjModel.size(), aiProcess_ValidateDataStructure);
EXPECT_NE(nullptr, scene);
EXPECT_EQ(scene->mNumMeshes, 1);
const aiMesh *mesh = scene->mMeshes[0];
EXPECT_EQ(mesh->mNumVertices, 4);
EXPECT_EQ(mesh->mNumFaces, 1);
const aiFace face = mesh->mFaces[0];
EXPECT_EQ(face.mNumIndices, 4);
for (unsigned int i = 0; i < face.mNumIndices; ++i)
{
EXPECT_EQ(face.mIndices[i], i);
}
}