RayTest problems with bullet 2.82, proposed solution, need help building

Hey guys,

I noticed problems with raytesting & native bullet 2.82. It is because native bullet uses “gjk” raytesting by default, which apparently is a bit buggy. I notice it primarily when trying to raytest against large boxes. Anyway, the author of this change does offer a way to use the old raytesting method by settings some m_flags on the RayTestCallback object, see here:

https://code.google.com/p/bullet/source/detail?r=2686

It didn’t appear jMonkeyEngine3 provided access to m_flags to set the raytest method, so I added it to the bullet native’s PhysicsSpace.cpp file, like so:

[code] JNIEXPORT void JNICALL Java_com_jme3_bullet_PhysicsSpace_rayTest_1native
(JNIEnv * env, jobject object, jobject from, jobject to, jlong spaceId, jobject resultlist, jint flags) {

    jmePhysicsSpace* space = reinterpret_cast<jmePhysicsSpace*> (spaceId);
    if (space == NULL) {
        jclass newExc = env->FindClass("java/lang/NullPointerException");
        env->ThrowNew(newExc, "The physics space does not exist.");
        return;
    }

    struct AllRayResultCallback : public btCollisionWorld::RayResultCallback {

        AllRayResultCallback(const btVector3& rayFromWorld, const btVector3 & rayToWorld) : m_rayFromWorld(rayFromWorld), m_rayToWorld(rayToWorld) {
        }
        jobject resultlist;
        JNIEnv* env;
        btVector3 m_rayFromWorld; //used to calculate hitPointWorld from hitFraction
        btVector3 m_rayToWorld;

        btVector3 m_hitNormalWorld;
        btVector3 m_hitPointWorld;

        virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace) {
            if (normalInWorldSpace) {
                m_hitNormalWorld = rayResult.m_hitNormalLocal;
            } else {
                m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis() * rayResult.m_hitNormalLocal;
            }
            m_hitPointWorld.setInterpolate3(m_rayFromWorld, m_rayToWorld, rayResult.m_hitFraction);

            jmeBulletUtil::addResult(env, resultlist, m_hitNormalWorld, m_hitPointWorld, rayResult.m_hitFraction, rayResult.m_collisionObject);

            return 1.f;
        }
    };

    btVector3 native_to = btVector3();
    jmeBulletUtil::convert(env, to, &native_to);

    btVector3 native_from = btVector3();
    jmeBulletUtil::convert(env, from, &native_from);

    AllRayResultCallback resultCallback(native_from, native_to);
    resultCallback.env = env;
    resultCallback.resultlist = resultlist;
    resultCallback.m_flags = flags;
    space->getDynamicsWorld()->rayTest(native_from, native_to, resultCallback);
    return;
}[/code]

Modified header:

[code]/*

  • Class: com_jme3_bullet_PhysicsSpace
  • Method: rayTest_native
  • Signature: (Lcom/jme3/math/Vector3f;Lcom/jme3/math/Vector3f;JLjava/util/List;I)V
    */
    JNIEXPORT void JNICALL Java_com_jme3_bullet_PhysicsSpace_rayTest_1native
    (JNIEnv *, jobject, jobject, jobject, jlong, jobject, jint);[/code]

Made these changes to PhysicsSpace.java for bullet native:

[code] /**
* Sets m_flags for raytest, see https://code.google.com/p/bullet/source/browse/trunk/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h
* for possible options. Defaults to using the faster, approximate raytest.
*/
public void SetRayTestFlags(int flags) {
rayTestFlags = flags;
}

/**
 * Gets m_flags for raytest, see https://code.google.com/p/bullet/source/browse/trunk/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h
 * for possible options.
 * @return rayTestFlags
 */
public int GetRayTestFlags() {
    return rayTestFlags;
}

/**
 * Performs a ray collision test and returns the results as a list of
 * PhysicsRayTestResults
 */
public List<PhysicsRayTestResult> rayTest(Vector3f from, Vector3f to, List<PhysicsRayTestResult> results) {
    results.clear();
    rayTest_native(from, to, physicsSpaceId, results, rayTestFlags);
    return results;
}

public native void rayTest_native(Vector3f from, Vector3f to, long physicsSpaceId, List<PhysicsRayTestResult> results, int flags);[/code]

rayTestFlags just being a private int = 4 (defaulting to using the simple raytest that worked better for me)

Anyway, this does work on my Linux 64 machine, because I can successfully build those native bullet binaries. However, I’m having trouble getting the mingw32 / Windows builds to work… I can also build the Mac version with these improvements. I may need help from someone to build the Windows 32-bit version, then we can get this problem solved…

Thank you,

  • Phr00t

Tagging @Momoko_Fan in this thread, since I think he was the one who built & submitted 2.82…

After much blood, sweat and tears, I got native bullet to build for Windows 32/64-bit and Linux 32/64-bit. It includes the fixes above, so now programmers can pick whether they want to use the “new” gjk raytest method (which doesn’t work for me on large objects), or the simple/faster one (that we’ve used in 2.81 and older). There are some other flags we have access to now for raytesting, so enjoy! I’ll work on getting the Mac builds most likely by Tuesday.

1 Like

Please check back with a core developer before you commit such (or any) changes, especially when they make the build process more complicated. The library is supposed to be built on a mingw linux system, its nice you “somehow” managed to build it but it has to be built on that system, too. Furthermore capital methods are against the java conventions. This change will not be kept as it is.

I only modified a few simple lines in the cpp/h files, and that did not complicate the build process. It was a matter of getting it to build on my local machine that was complicated. It was built on a MinGW linux system and the process should not have changed at all for your system.

I’m not sure what you mean by “capital methods are against the java conventions” and if you must make changes, all that I ask is the “m_flags” are still made available at the Java level, so programmers like myself can modify them.

Yes, all I ask of you is that you check back before you commit changes.

OK, understandable. What changes, if any, would you like to see in the current commits that retain the same functionality?

I didn’t make my mind up on how exactly configuration for the PhysicsSpace will happen in the future, I try to avoid coarse disparity between the native and java versions as much as possible so there will probably be an external class encapsulating such things to be passed to the physics space. So you can just switch the configuration for the PhysicsSpace instead of rewriting your application to fit a new API as with your added methods here. So if you want to keep this as it is I suggest keeping it local to your build, thanks for the information though.

P.S. In java methods generally start with a lower case letter, if you intend to contribute to open source projects I suggest sticking to that pattern.