Bullet-Native Crash with Ragdolls

Hey Guys,
I know that Ragdolls are still under development so this is just a notice for whoever wants to look into the physics:

  1. No matter what model I use (an own or Sinbad test-asset) **native-**bullet crashes the VM at the first physics tick with RagdollMode on (Access Violation in native code).
    Note: I currently only tested on Windows x64 (3.0 SDK) and Mac OS (master).
    On Windows there was only an acess violation reported and on mac os # C [libbulletjme.dylib+0x10194e] convexHullSupport(btVector3 const&, btVector3 const*, int, btVector3 const&)+0x31e

    C [libbulletjme.dylib+0x10194e] convexHullSupport(btVector3 const&, btVector3 const*, int, btVector3 const&)+0x31e
    C [libbulletjme.dylib+0x1015b4] btConvexShape::localGetSupportVertexWithoutMarginNonVirtual(btVector3 const&) const+0x1fc4
    C [libbulletjme.dylib+0x195d8c] btGjkPairDetector::getClosestPointsNonVirtual(btDiscreteCollisionDetectorInterface::ClosestPointInput const&, btDiscreteCollisionDetectorInterface::Result&, btIDebugDraw*)+0x107c
    C [libbulletjme.dylib+0x194d05] btGjkPairDetector::getClosestPoints(btDiscreteCollisionDetectorInterface::ClosestPointInput const&, btDiscreteCollisionDetectorInterface::Result&, btIDebugDraw*, bool)+0x35
    C [libbulletjme.dylib+0xa6fd3] btConvexConvexAlgorithm::processCollision(btCollisionObjectWrapper const*, btCollisionObjectWrapper const*, btDispatcherInfo const&, btManifoldResult*)+0x44b3
    C [libbulletjme.dylib+0x677fb] btCollisionDispatcher::defaultNearCallback(btBroadphasePair&, btCollisionDispatcher&, btDispatcherInfo const&)+0x21b
    C [libbulletjme.dylib+0x68f1c] btCollisionPairCallback::processOverlap(btBroadphasePair&)+0x3c
    C [libbulletjme.dylib+0x3e251] btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback*, btDispatcher*)+0x81
    C [libbulletjme.dylib+0x6863f] btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache*, btDispatcherInfo const&, btDispatcher*)+0x5f
    C [libbulletjme.dylib+0x6b281] btCollisionWorld::performDiscreteCollisionDetection()+0x101
    C [libbulletjme.dylib+0x2683c0] btDiscreteDynamicsWorld::internalSingleStepSimulation(float)+0x110
    C [libbulletjme.dylib+0x2681dd] btDiscreteDynamicsWorld::stepSimulation(float, int, float)+0x2ad
    C [libbulletjme.dylib+0x1bcb7] jmePhysicsSpace::stepSimulation(float, int, float)+0x37
    C [libbulletjme.dylib+0x127d] Java_com_jme3_bullet_PhysicsSpace_stepSimulation+0x7d
    j com.jme3.bullet.PhysicsSpace.stepSimulation(JFIF)V+0
    j com.jme3.bullet.PhysicsSpace.update(FI)V+11

With JBullet everything works as expected.

TestCase:

package mygame;

import com.jme3.app.Application;
import com.jme3.app.SimpleApplication;
import com.jme3.asset.AssetManager;
import com.jme3.asset.TextureKey;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.collision.shapes.MeshCollisionShape;
import com.jme3.bullet.control.KinematicRagdollControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;
import com.jme3.scene.shape.Sphere;
import com.jme3.scene.shape.Sphere.TextureMode;
import com.jme3.system.AppSettings;
import com.jme3.texture.Texture;

/**
 * test
 * @author normenhansen
 */
public class Main extends SimpleApplication {

    public static void main(String[] args) {
        Main app = new Main();
        AppSettings a = new AppSettings(true);
        a.setFrameRate(30);
        app.setSettings(a);
        app.start();
    }

    @Override
    public void simpleInitApp()
    {
        viewPort.setBackgroundColor(ColorRGBA.Green);
        BulletAppState b = new BulletAppState();
        stateManager.attach(b);
        
        createPhysicsTestWorld(rootNode, assetManager, b.getPhysicsSpace());
        createBallShooter(this, rootNode, b.getPhysicsSpace());
        flyCam.setMoveSpeed(flyCam.getMoveSpeed() * 5f);
        
        Node model = (Node) assetManager.loadModel("Models/Sinbad/Sinbad.mesh.xml");
        //Bug 2: Node model = (Node)assetManager.loadModel("Models/Mr_Chan_onemesh.j3o"); // The model doesn't have the correct Ambient Color but I didnt change it.
        model.lookAt(new Vector3f(0,0,1), Vector3f.UNIT_Y);
        model.setLocalTranslation(4, 0, -7f);

        KinematicRagdollControl ragdoll = new KinematicRagdollControl(0.5f);
        model.addControl(ragdoll);
        //Bug two: model.getChild("python_mr_chan-suit01lres").addControl(ragdoll);
        ragdoll.setRagdollMode();

        b.getPhysicsSpace().add(ragdoll);

        rootNode.attachChild(model);

        DirectionalLight d = new DirectionalLight(); // needed because of faulty ambient color
        d.setColor(ColorRGBA.White);
        d.setDirection(new Vector3f(0f, -1f, -1f));
        rootNode.addLight(d);
    }        
    // Directly copied from GitHub
   public static void createPhysicsTestWorld(Node rootNode, AssetManager assetManager, PhysicsSpace space) {
        AmbientLight light = new AmbientLight();
        light.setColor(ColorRGBA.White);
        rootNode.addLight(light);

        Material material = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        material.setTexture("ColorMap", assetManager.loadTexture("Interface/Logo/Monkey.jpg"));

        Box floorBox = new Box(140, 0.25f, 140);
        Geometry floorGeometry = new Geometry("Floor", floorBox);
        floorGeometry.setMaterial(material);
        floorGeometry.setLocalTranslation(0, -5, 0);
//        Plane plane = new Plane();
//        plane.setOriginNormal(new Vector3f(0, 0.25f, 0), Vector3f.UNIT_Y);
//        floorGeometry.addControl(new RigidBodyControl(new PlaneCollisionShape(plane), 0));
        floorGeometry.addControl(new RigidBodyControl(0));
        rootNode.attachChild(floorGeometry);
        space.add(floorGeometry);

        //movable boxes
        for (int i = 0; i < 12; i++) {
            Box box = new Box(0.25f, 0.25f, 0.25f);
            Geometry boxGeometry = new Geometry("Box", box);
            boxGeometry.setMaterial(material);
            boxGeometry.setLocalTranslation(i, 5, -3);
            //RigidBodyControl automatically uses box collision shapes when attached to single geometry with box mesh
            boxGeometry.addControl(new RigidBodyControl(2));
            rootNode.attachChild(boxGeometry);
            space.add(boxGeometry);
        }

        //immovable sphere with mesh collision shape
        Sphere sphere = new Sphere(8, 8, 1);
        Geometry sphereGeometry = new Geometry("Sphere", sphere);
        sphereGeometry.setMaterial(material);
        sphereGeometry.setLocalTranslation(4, -4, 2);
        sphereGeometry.addControl(new RigidBodyControl(new MeshCollisionShape(sphere), 0));
        rootNode.attachChild(sphereGeometry);
        space.add(sphereGeometry);

    }
   
   /**
     * creates the necessary inputlistener and action to shoot balls from teh camera
     * @param app
     * @param rootNode
     * @param space
     */
    public static void createBallShooter(final Application app, final Node rootNode, final PhysicsSpace space) {
        ActionListener actionListener = new ActionListener() {

            public void onAction(String name, boolean keyPressed, float tpf) {
                Sphere bullet = new Sphere(32, 32, 0.4f, true, false);
                bullet.setTextureMode(TextureMode.Projected);
                Material mat2 = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
                TextureKey key2 = new TextureKey("Textures/Terrain/Rock/Rock.PNG");
                key2.setGenerateMips(true);
                Texture tex2 = app.getAssetManager().loadTexture(key2);
                mat2.setTexture("ColorMap", tex2);
                if (name.equals("shoot") && !keyPressed) {
                    Geometry bulletg = new Geometry("bullet", bullet);
                    bulletg.setMaterial(mat2);
                    bulletg.setShadowMode(ShadowMode.CastAndReceive);
                    bulletg.setLocalTranslation(app.getCamera().getLocation());
                    RigidBodyControl bulletControl = new RigidBodyControl(10);
                    bulletg.addControl(bulletControl);
                    bulletControl.setLinearVelocity(app.getCamera().getDirection().mult(50));
                    bulletg.addControl(bulletControl);
                    rootNode.attachChild(bulletg);
                    space.add(bulletControl);
                }
            }
        };
        app.getInputManager().addMapping("shoot", new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
        app.getInputManager().addListener(actionListener, "shoot");
    }
}

The World-Setup Methods are simply borrowed from the Physics Tests.

  1. I have a model (see commented code in test case) which is also crashing native bullet and looking like a mixture of gollum and voldemort with jbullet (I don’t know if this is a “skinning?” issue or actually my faulty model (it has an unnamed bone I can’t delete in the .j3o))
    Anyway here’s the model: https://drive.google.com/file/d/0B_3OrAun35rYY1ZRaUVmZTZRSEU/view?usp=sharing (44 MiB, I know, I suck :D)

It works with the test that comes with jme. Maybe your model has zero vertex parts that are in the name library of the ragdoll control? Its not like the ragdoll control works out of the box with just any model.

I found my fault :confused: I didn’t look into setupSinbad() that’s why the jme model didn’t work:
I need to define which bones should be used as ragdoll.
Crazy though, that there is a crash without any defined bone

Yeah, a native crash should never occur. This is definitely a jME3 bug.

Hopefully it can be reproduced with a sample model.

I added a bug report here: