diff --git a/jme3-bullet-native/src/native/cpp/com_jme3_bullet_PhysicsSpace.cpp b/jme3-bullet-native/src/native/cpp/com_jme3_bullet_PhysicsSpace.cpp index b51630c55..32bc249dd 100644 --- a/jme3-bullet-native/src/native/cpp/com_jme3_bullet_PhysicsSpace.cpp +++ b/jme3-bullet-native/src/native/cpp/com_jme3_bullet_PhysicsSpace.cpp @@ -468,6 +468,68 @@ extern "C" { return; } + + + JNIEXPORT void JNICALL Java_com_jme3_bullet_PhysicsSpace_sweepTest_1native + (JNIEnv * env, jobject object, jlong shapeId, jobject from, jobject to, jlong spaceId, jobject resultlist, jfloat allowedCcdPenetration) { + + jmePhysicsSpace* space = reinterpret_cast (spaceId); + if (space == NULL) { + jclass newExc = env->FindClass("java/lang/NullPointerException"); + env->ThrowNew(newExc, "The physics space does not exist."); + return; + } + + btCollisionShape* shape = reinterpret_cast (shapeId); + if (shape == NULL) { + jclass newExc = env->FindClass("java/lang/NullPointerException"); + env->ThrowNew(newExc, "The shape does not exist."); + return; + } + + struct AllConvexResultCallback : public btCollisionWorld::ConvexResultCallback { + + AllConvexResultCallback(const btTransform& convexFromWorld, const btTransform & convexToWorld) : m_convexFromWorld(convexFromWorld), m_convexToWorld(convexToWorld) { + } + jobject resultlist; + JNIEnv* env; + btTransform m_convexFromWorld; //used to calculate hitPointWorld from hitFraction + btTransform m_convexToWorld; + + btVector3 m_hitNormalWorld; + btVector3 m_hitPointWorld; + + virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult, bool normalInWorldSpace) { + if (normalInWorldSpace) { + m_hitNormalWorld = convexResult.m_hitNormalLocal; + } + else { + m_hitNormalWorld = convexResult.m_hitCollisionObject->getWorldTransform().getBasis() * convexResult.m_hitNormalLocal; + } + m_hitPointWorld.setInterpolate3(m_convexFromWorld.getBasis() * m_convexFromWorld.getOrigin(), m_convexToWorld.getBasis() * m_convexToWorld.getOrigin(), convexResult.m_hitFraction); + + jmeBulletUtil::addSweepResult(env, resultlist, &m_hitNormalWorld, &m_hitPointWorld, convexResult.m_hitFraction, convexResult.m_hitCollisionObject); + + return 1.f; + } + }; + + btTransform native_to = btTransform(); + jmeBulletUtil::convert(env, to, &native_to); + + btTransform native_from = btTransform(); + jmeBulletUtil::convert(env, from, &native_from); + + btScalar native_allowed_ccd_penetration = btScalar(allowedCcdPenetration); + + + AllConvexResultCallback resultCallback(native_from, native_to); + resultCallback.env = env; + resultCallback.resultlist = resultlist; + space->getDynamicsWorld()->convexSweepTest((btConvexShape *) shape, native_from, native_to, resultCallback, native_allowed_ccd_penetration); + return; + } + #ifdef __cplusplus } #endif diff --git a/jme3-bullet-native/src/native/cpp/com_jme3_bullet_PhysicsSpace.h b/jme3-bullet-native/src/native/cpp/com_jme3_bullet_PhysicsSpace.h index e040f8da8..b499ff04c 100644 --- a/jme3-bullet-native/src/native/cpp/com_jme3_bullet_PhysicsSpace.h +++ b/jme3-bullet-native/src/native/cpp/com_jme3_bullet_PhysicsSpace.h @@ -165,6 +165,15 @@ JNIEXPORT void JNICALL Java_com_jme3_bullet_PhysicsSpace_initNativePhysics JNIEXPORT void JNICALL Java_com_jme3_bullet_PhysicsSpace_finalizeNative (JNIEnv *, jobject, jlong); + +/* +* Class: com_jme3_bullet_PhysicsSpace +* Method : sweepTest_native +* Signature: (J;L;Lcom/jme3/math/Transform;Lcom/jme3/math/Transform;L;JLjava/util/List;F)V +*/ +JNIEXPORT void JNICALL Java_com_jme3_bullet_PhysicsSpace_sweepTest_1native +(JNIEnv *, jobject, jlong, jobject, jobject, jlong, jobject, jfloat); + #ifdef __cplusplus } #endif diff --git a/jme3-bullet-native/src/native/cpp/jmeBulletUtil.cpp b/jme3-bullet-native/src/native/cpp/jmeBulletUtil.cpp index fa88ad473..04b56a545 100644 --- a/jme3-bullet-native/src/native/cpp/jmeBulletUtil.cpp +++ b/jme3-bullet-native/src/native/cpp/jmeBulletUtil.cpp @@ -59,6 +59,38 @@ void jmeBulletUtil::convert(JNIEnv* env, jobject in, btVector3* out) { out->setZ(z); } +void jmeBulletUtil::convert(JNIEnv* env, jobject in, btQuaternion* out) { + if (in == NULL || out == NULL) { + jmeClasses::throwNPE(env); + } + float x = env->GetFloatField(in, jmeClasses::Quaternion_x); + if (env->ExceptionCheck()) { + env->Throw(env->ExceptionOccurred()); + return; + } + float y = env->GetFloatField(in, jmeClasses::Quaternion_y); //env->CallFloatMethod(in, jmeClasses::Vector3f_getY); + if (env->ExceptionCheck()) { + env->Throw(env->ExceptionOccurred()); + return; + } + float z = env->GetFloatField(in, jmeClasses::Quaternion_z); //env->CallFloatMethod(in, jmeClasses::Vector3f_getZ); + if (env->ExceptionCheck()) { + env->Throw(env->ExceptionOccurred()); + return; + } + + float w = env->GetFloatField(in, jmeClasses::Quaternion_w); //env->CallFloatMethod(in, jmeClasses::Vector3f_getZ); + if (env->ExceptionCheck()) { + env->Throw(env->ExceptionOccurred()); + return; + } + out->setX(x); + out->setY(y); + out->setZ(z); + out->setW(w); +} + + void jmeBulletUtil::convert(JNIEnv* env, const btVector3* in, jobject out) { if (in == NULL || out == NULL) { jmeClasses::throwNPE(env); @@ -325,3 +357,61 @@ void jmeBulletUtil::addResult(JNIEnv* env, jobject resultlist, btVector3* hitnor return; } } + + +void jmeBulletUtil::addSweepResult(JNIEnv* env, jobject resultlist, btVector3* hitnormal, btVector3* m_hitPointWorld, btScalar m_hitFraction, const btCollisionObject* hitobject) { + + jobject singleresult = env->AllocObject(jmeClasses::PhysicsSweep_Class); + jobject hitnormalvec = env->AllocObject(jmeClasses::Vector3f); + + convert(env, hitnormal, hitnormalvec); + jmeUserPointer *up1 = (jmeUserPointer*)hitobject->getUserPointer(); + + env->SetObjectField(singleresult, jmeClasses::PhysicsSweep_normalInWorldSpace, hitnormalvec); + env->SetFloatField(singleresult, jmeClasses::PhysicsSweep_hitfraction, m_hitFraction); + + env->SetObjectField(singleresult, jmeClasses::PhysicsSweep_collisionObject, up1->javaCollisionObject); + env->CallVoidMethod(resultlist, jmeClasses::PhysicsSweep_addmethod, singleresult); + if (env->ExceptionCheck()) { + env->Throw(env->ExceptionOccurred()); + return; + } +} + +void jmeBulletUtil::convert(JNIEnv* env, jobject in, btTransform* out) { + if (in == NULL || out == NULL) { + jmeClasses::throwNPE(env); + } + + jobject translation_vec = env->CallObjectMethod(in, jmeClasses::Transform_translation); + if (env->ExceptionCheck()) { + env->Throw(env->ExceptionOccurred()); + return; + } + + jobject rot_quat = env->CallObjectMethod(in, jmeClasses::Transform_rotation); + if (env->ExceptionCheck()) { + env->Throw(env->ExceptionOccurred()); + return; + } + + /* + //Scale currently not supported by bullet + //@TBD: Create an assertion somewhere to avoid scale values + jobject scale_vec = env->GetObjectField(in, jmeClasses::Transform_scale); + if (env->ExceptionCheck()) { + env->Throw(env->ExceptionOccurred()); + return; + } + */ + btVector3 native_translation_vec = btVector3(); + //btVector3 native_scale_vec = btVector3(); + btQuaternion native_rot_quat = btQuaternion(); + + convert(env, translation_vec, &native_translation_vec); + //convert(env, scale_vec, native_scale_vec); + convert(env, rot_quat, &native_rot_quat); + + out->setRotation(native_rot_quat); + out->setOrigin(native_translation_vec); +} diff --git a/jme3-bullet-native/src/native/cpp/jmeBulletUtil.h b/jme3-bullet-native/src/native/cpp/jmeBulletUtil.h index 96509ab9e..fa09d09cc 100644 --- a/jme3-bullet-native/src/native/cpp/jmeBulletUtil.h +++ b/jme3-bullet-native/src/native/cpp/jmeBulletUtil.h @@ -42,10 +42,13 @@ public: static void convert(JNIEnv* env, jobject in, btVector3* out); static void convert(JNIEnv* env, const btVector3* in, jobject out); static void convert(JNIEnv* env, jobject in, btMatrix3x3* out); + static void convert(JNIEnv* env, jobject in, btQuaternion* out); static void convert(JNIEnv* env, const btMatrix3x3* in, jobject out); static void convertQuat(JNIEnv* env, jobject in, btMatrix3x3* out); static void convertQuat(JNIEnv* env, const btMatrix3x3* in, jobject out); + static void convert(JNIEnv* env, jobject in, btTransform* out); static void addResult(JNIEnv* env, jobject resultlist, btVector3* hitnormal, btVector3* m_hitPointWorld,const btScalar m_hitFraction,const btCollisionObject* hitobject); + static void addSweepResult(JNIEnv* env, jobject resultlist, btVector3* hitnormal, btVector3* m_hitPointWorld, const btScalar m_hitFraction, const btCollisionObject* hitobject); private: jmeBulletUtil(){}; ~jmeBulletUtil(){}; diff --git a/jme3-bullet-native/src/native/cpp/jmeClasses.cpp b/jme3-bullet-native/src/native/cpp/jmeClasses.cpp index e0b5515b4..6b7caa0e9 100644 --- a/jme3-bullet-native/src/native/cpp/jmeClasses.cpp +++ b/jme3-bullet-native/src/native/cpp/jmeClasses.cpp @@ -91,6 +91,21 @@ jfieldID jmeClasses::PhysicsRay_collisionObject; jclass jmeClasses::PhysicsRay_listresult; jmethodID jmeClasses::PhysicsRay_addmethod; +jclass jmeClasses::PhysicsSweep_Class; +jmethodID jmeClasses::PhysicsSweep_newSingleResult; + +jfieldID jmeClasses::PhysicsSweep_normalInWorldSpace; +jfieldID jmeClasses::PhysicsSweep_hitfraction; +jfieldID jmeClasses::PhysicsSweep_collisionObject; + +jclass jmeClasses::PhysicsSweep_listresult; +jmethodID jmeClasses::PhysicsSweep_addmethod; + + +jclass jmeClasses::Transform; +jmethodID jmeClasses::Transform_rotation; +jmethodID jmeClasses::Transform_translation; + //private fields //JNIEnv* jmeClasses::env; JavaVM* jmeClasses::vm; @@ -240,6 +255,70 @@ void jmeClasses::initJavaClasses(JNIEnv* env) { env->Throw(env->ExceptionOccurred()); return; } + + PhysicsSweep_Class = (jclass)env->NewGlobalRef(env->FindClass("com/jme3/bullet/collision/PhysicsSweepTestResult")); + if (env->ExceptionCheck()) { + env->Throw(env->ExceptionOccurred()); + return; +} + + PhysicsSweep_newSingleResult = env->GetMethodID(PhysicsSweep_Class, "", "()V"); + if (env->ExceptionCheck()) { + env->Throw(env->ExceptionOccurred()); + return; + } + + PhysicsSweep_normalInWorldSpace = env->GetFieldID(PhysicsSweep_Class, "hitNormalLocal", "Lcom/jme3/math/Vector3f;"); + if (env->ExceptionCheck()) { + env->Throw(env->ExceptionOccurred()); + return; + } + + + PhysicsSweep_hitfraction = env->GetFieldID(PhysicsSweep_Class, "hitFraction", "F"); + if (env->ExceptionCheck()) { + env->Throw(env->ExceptionOccurred()); + return; + } + + + PhysicsSweep_collisionObject = env->GetFieldID(PhysicsSweep_Class, "collisionObject", "Lcom/jme3/bullet/collision/PhysicsCollisionObject;"); + if (env->ExceptionCheck()) { + env->Throw(env->ExceptionOccurred()); + return; + } + + PhysicsSweep_listresult = env->FindClass("java/util/List"); + PhysicsSweep_listresult = (jclass)env->NewGlobalRef(PhysicsSweep_listresult); + if (env->ExceptionCheck()) { + env->Throw(env->ExceptionOccurred()); + return; + } + + PhysicsSweep_addmethod = env->GetMethodID(PhysicsSweep_listresult, "add", "(Ljava/lang/Object;)Z"); + if (env->ExceptionCheck()) { + env->Throw(env->ExceptionOccurred()); + return; + } + + Transform = (jclass)env->NewGlobalRef(env->FindClass("com/jme3/math/Transform")); + if (env->ExceptionCheck()) { + env->Throw(env->ExceptionOccurred()); + return; + } + + Transform_rotation = env->GetMethodID(Transform, "getRotation", "()Lcom/jme3/math/Quaternion;"); + if (env->ExceptionCheck()) { + env->Throw(env->ExceptionOccurred()); + return; + } + + Transform_translation = env->GetMethodID(Transform, "getTranslation", "()Lcom/jme3/math/Vector3f;"); + if (env->ExceptionCheck()) { + env->Throw(env->ExceptionOccurred()); + return; + } + } void jmeClasses::throwNPE(JNIEnv* env) { diff --git a/jme3-bullet-native/src/native/cpp/jmeClasses.h b/jme3-bullet-native/src/native/cpp/jmeClasses.h index 24684dae9..bb1b0e99a 100644 --- a/jme3-bullet-native/src/native/cpp/jmeClasses.h +++ b/jme3-bullet-native/src/native/cpp/jmeClasses.h @@ -89,6 +89,18 @@ public: static jclass PhysicsRay_listresult; static jmethodID PhysicsRay_addmethod; + static jclass PhysicsSweep_Class; + static jmethodID PhysicsSweep_newSingleResult; + static jfieldID PhysicsSweep_normalInWorldSpace; + static jfieldID PhysicsSweep_hitfraction; + static jfieldID PhysicsSweep_collisionObject; + static jclass PhysicsSweep_listresult; + static jmethodID PhysicsSweep_addmethod; + + static jclass Transform; + static jmethodID Transform_rotation; + static jmethodID Transform_translation; + static jclass DebugMeshCallback; static jmethodID DebugMeshCallback_addVector; diff --git a/jme3-bullet/src/main/java/com/jme3/bullet/PhysicsSpace.java b/jme3-bullet/src/main/java/com/jme3/bullet/PhysicsSpace.java index 0f011f8d7..380dc3e16 100644 --- a/jme3-bullet/src/main/java/com/jme3/bullet/PhysicsSpace.java +++ b/jme3-bullet/src/main/java/com/jme3/bullet/PhysicsSpace.java @@ -820,6 +820,10 @@ public class PhysicsSpace { // return lrr.hitFraction; // } // } +// +// + + /** * Performs a sweep collision test and returns the results as a list of * PhysicsSweepTestResults
You have to use different Transforms for @@ -828,48 +832,47 @@ public class PhysicsSpace { * center. */ public List sweepTest(CollisionShape shape, Transform start, Transform end) { - List results = new LinkedList(); -// if (!(shape.getCShape() instanceof ConvexShape)) { -// logger.log(Level.WARNING, "Trying to sweep test with incompatible mesh shape!"); -// return results; -// } -// dynamicsWorld.convexSweepTest((ConvexShape) shape.getCShape(), Converter.convert(start, sweepTrans1), Converter.convert(end, sweepTrans2), new InternalSweepListener(results)); - return results; + List results = new LinkedList(); + sweepTest(shape, start, end , results); + return (List) results; + } + public List sweepTest(CollisionShape shape, Transform start, Transform end, List results) { + return sweepTest(shape, start, end, results, 0.0f); } + public native void sweepTest_native(long shape, Transform from, Transform to, long physicsSpaceId, List results, float allowedCcdPenetration); /** * Performs a sweep collision test and returns the results as a list of * PhysicsSweepTestResults
You have to use different Transforms for - * start and end (at least distance > 0.4f). SweepTest will not see a + * start and end (at least distance > allowedCcdPenetration). SweepTest will not see a * collision if it starts INSIDE an object and is moving AWAY from its * center. */ - public List sweepTest(CollisionShape shape, Transform start, Transform end, List results) { + public List sweepTest(CollisionShape shape, Transform start, Transform end, List results, float allowedCcdPenetration ) { results.clear(); -// if (!(shape.getCShape() instanceof ConvexShape)) { -// logger.log(Level.WARNING, "Trying to sweep test with incompatible mesh shape!"); -// return results; -// } -// dynamicsWorld.convexSweepTest((ConvexShape) shape.getCShape(), Converter.convert(start, sweepTrans1), Converter.convert(end, sweepTrans2), new InternalSweepListener(results)); + sweepTest_native(shape.getObjectId(), start, end, physicsSpaceId, results, allowedCcdPenetration); return results; } -// private class InternalSweepListener extends CollisionWorld.ConvexResultCallback { -// -// private List results; -// -// public InternalSweepListener(List results) { -// this.results = results; -// } -// -// @Override -// public float addSingleResult(LocalConvexResult lcr, boolean bln) { -// PhysicsCollisionObject obj = (PhysicsCollisionObject) lcr.hitCollisionObject.getUserPointer(); -// results.add(new PhysicsSweepTestResult(obj, Converter.convert(lcr.hitNormalLocal), lcr.hitFraction, bln)); -// return lcr.hitFraction; -// } -// } +/* private class InternalSweepListener extends CollisionWorld.ConvexResultCallback { + + private List results; + + public InternalSweepListener(List results) { + this.results = results; + } + + @Override + public float addSingleResult(LocalConvexResult lcr, boolean bln) { + PhysicsCollisionObject obj = (PhysicsCollisionObject) lcr.hitCollisionObject.getUserPointer(); + results.add(new PhysicsSweepTestResult(obj, Converter.convert(lcr.hitNormalLocal), lcr.hitFraction, bln)); + return lcr.hitFraction; + } + } + + */ + /** * destroys the current PhysicsSpace so that a new one can be created */