createMeshShape doesn't work for me

Hi everyone, first post. Let me first start by saying thanks to the entire jMonkey Engine and jMonkeyPlatform team! It’s awesome to see such a comprehensive open-source 3d graphics and physics engine for the Java platform, not to mention with its own IDE and active community.



Alright, here’s my noob problem. I was following the Hello Collision tutorial, and got it working just fine. I wanted to add a model I made in Blender 2.49.2 that I exported as an Ogre XML mesh. It loads fine (though, solid white with no texture) but falls through the floor. The engine then crashes with a null pointer exception and stack trace. Now, I’ve discovered that using a CapsuleCollisionShape keeps my model from falling through the floor. But when I try to use createMeshShape to get the true collision shape, it doesn’t.

You can see below where I commented out that line and used a CapsuleCollisionShape instead.



[java]

package mygame;



import com.bulletphysics.collision.shapes.CollisionShape;

import com.jme3.app.SimpleBulletApplication;

import com.jme3.asset.plugins.ZipLocator;

import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;

import com.jme3.bullet.collision.shapes.CompoundCollisionShape;

import com.jme3.bullet.nodes.PhysicsCharacterNode;

import com.jme3.bullet.nodes.PhysicsNode;

import com.jme3.bullet.util.CollisionShapeFactory;

import com.jme3.input.KeyInput;

import com.jme3.input.controls.ActionListener;

import com.jme3.input.controls.KeyTrigger;

import com.jme3.light.DirectionalLight;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Vector3f;

import com.jme3.renderer.queue.RenderQueue.ShadowMode;

import com.jme3.scene.Node;

import com.jme3.scene.Spatial;



/**

  • Example 9 - How to make walls and floors solid.
  • This version uses Physics and a custom Action Listener.
  • @author normen, with edits by Zathras

    /

    public class Main

    extends SimpleBulletApplication

    implements ActionListener {



    private Spatial sceneModel;

    private PhysicsNode landscape;

    private PhysicsCharacterNode player;

    private Vector3f walkDirection = new Vector3f();

    private boolean left = false, right = false, up = false, down = false;



    public static void main(String[] args) {

    Main app = new Main();

    app.start();

    }



    public void simpleInitApp() {

    // We re-use the flyby camera for rotation, while positioning is handled by physics

    viewPort.setBackgroundColor(new ColorRGBA(0.7f,0.8f,1f,1f));

    flyCam.setMoveSpeed(100);

    setupKeys();



    // We add a light so we see the scene

    DirectionalLight dl = new DirectionalLight();

    dl.setColor(ColorRGBA.White.clone().multLocal(2)); // bright white light

    dl.setDirection(new Vector3f(2.8f, -2.8f, -2.8f).normalize());

    rootNode.addLight(dl);



    // We load the scene from the zip file and adjust its size.

    assetManager.registerLocator(“town.zip”, ZipLocator.class.getName());

    sceneModel = assetManager.loadModel(“main.scene”);

    sceneModel.setLocalScale(2f);



    // We set up collision detection for the scene by creating a

    // compound collision shape and a physics node.

    CompoundCollisionShape sceneShape = CollisionShapeFactory.createMeshCompoundShape((Node) sceneModel);

    landscape = new PhysicsNode(sceneModel, sceneShape, 0);



    //Set up my thing

    Spatial myThingModel = assetManager.loadModel(“Models/Sphere.mesh.xml”);

    PhysicsNode myThingPhysicsNode = new PhysicsNode(myThingModel,

    CollisionShapeFactory.createMeshShape((Node)myThingModel),

    //new CapsuleCollisionShape(1.5f, 6f, 1),

    (float) 0.5);

    myThingPhysicsNode.setLocalTranslation(new Vector3f(2, 15, 0));

    rootNode.attachChild(myThingPhysicsNode);

    getPhysicsSpace().add(myThingPhysicsNode);



    // We set up collision detection for the player by creating

    // a capsule collision shape and a physics character node.

    // The physics character node offers extra settings for

    // size, stepheight, jumping, falling, and gravity.

    // We also put the player in its starting position.

    player = new PhysicsCharacterNode(new CapsuleCollisionShape(1.5f, 6f, 1), .05f);

    player.setJumpSpeed(20);

    player.setFallSpeed(30);

    player.setGravity(30);

    player.setLocalTranslation(new Vector3f(0, 10, 0));



    // We attach the scene and the player to the rootnode and the physics space,

    // to make them appear in the game world.

    rootNode.attachChild(landscape);

    rootNode.attachChild(player);

    getPhysicsSpace().add(landscape);

    getPhysicsSpace().add(player);

    }



    /
    * We over-write some navigational key mappings here, so we can
  • add physics-controlled walking and jumping: /

    private void setupKeys() {

    inputManager.addMapping(“Lefts”, new KeyTrigger(KeyInput.KEY_A));

    inputManager.addMapping(“Rights”, new KeyTrigger(KeyInput.KEY_D));

    inputManager.addMapping(“Ups”, new KeyTrigger(KeyInput.KEY_W));

    inputManager.addMapping(“Downs”, new KeyTrigger(KeyInput.KEY_S));

    inputManager.addMapping(“Jumps”, new KeyTrigger(KeyInput.KEY_SPACE));

    inputManager.addListener(this, “Lefts”);

    inputManager.addListener(this, “Rights”);

    inputManager.addListener(this, “Ups”);

    inputManager.addListener(this, “Downs”);

    inputManager.addListener(this, “Jumps”);

    }



    /
    * These are our custom actions triggered by key presses.
  • We do not walk yet, we just keep track of the direction the user pressed. */

    public void onAction(String binding, boolean value, float tpf) {

    if (binding.equals(“Lefts”)) {

    if (value) { left = true; } else { left = false; }

    } else if (binding.equals(“Rights”)) {

    if (value) { right = true; } else { right = false; }

    } else if (binding.equals(“Ups”)) {

    if (value) { up = true; } else { up = false; }

    } else if (binding.equals(“Downs”)) {

    if (value) { down = true; } else { down = false; }

    } else if (binding.equals(“Jumps”)) {

    player.jump();

    }

    }



    /**
  • This is the main event loop–walking happens here.
  • We check in which direction the player is walking by interpreting
  • the camera direction forward (camDir) and to the side (camLeft).
  • The setWalkDirection() command is what lets a physics-controlled player walk.
  • We also make sure here that the camera moves with player.

    */

    @Override

    public void simpleUpdate(float tpf) {

    Vector3f camDir = cam.getDirection().clone().multLocal(0.6f);

    Vector3f camLeft = cam.getLeft().clone().multLocal(0.4f);

    walkDirection.set(0, 0, 0);

    if (left) { walkDirection.addLocal(camLeft); }

    if (right) { walkDirection.addLocal(camLeft.negate()); }

    if (up) { walkDirection.addLocal(camDir); }

    if (down) { walkDirection.addLocal(camDir.negate()); }

    player.setWalkDirection(walkDirection);

    cam.setLocation(player.getLocalTranslation());

    }

    }

    [/java]



    Thanks in advance for any help.

Add myThingPhysicsNode.attachDebugShape(assetManager); in line 70, this should give you a debug shape for the generated collision shape so you can debug better…



Cheers,

Normen

thanks for the quick reply and the tip, I didn’t know about debug shape. Here’s what i got, one with capsule shape and one with createMeshShape. Strangely enough the mesh shape looks fine!

Ahhhh ok. So the mesh shapes don’t collide with each other. Which also explains why I’m able to stand on my model when i spawn on top of it :). I’m sorry I didn’t catch that in the javadoc. I used createBoxShape for my model and it works sufficiently. Thanks for your help!



Btw I have a project in mind, once I get the basics hammered out and make some progress I’ll post it in the projects section. Reading the other posts there have helped me immensely in understanding the engine. Big thanks to everyone that contributes.

Oh, your mesh shape is supposed to move. That does not work, re-read the javadoc of the collisionshape generator. You could use a GImpact shape which is a dynamic mesh shape, but I strongly disencourage you from doing so as it requires too much CPU power. You could combine basic shapes in a compound collision shape to match the original shape as closely as needed.



Cheers,

Normen