Character bounces in Scene created with explorer but is fine on terrain

I am doing some testing with the scene explorer so I created a Scene and edited a terrain for it, just with some mountains as @Normen explainned in jME SDK Usecase Demo 1 video. I added a RigidBodyControl to the scene.
The problem is, if I use this scene, the character keeps bouncing upside down. But if I use a created Terrain, all works fine.
Does anybody can give me some insight? I don’t know what I am doing wrong with the physics on my Scene.

Here is my code:
[java]
/*

  • To change this template, choose Tools | Templates
  • and open the template in the editor.
    */
    package mygame;

/*

  • Copyright © 2009-2012 jMonkeyEngine All rights reserved. <p/>
  • Redistribution and use 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. <p/> * 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. <p/> * Neither the name of
  • ‘jMonkeyEngine’ nor the names of its contributors may be used to endorse or
  • promote products derived from this software without specific prior written
  • permission. <p/> 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.
    */
    import com.jme3.animation.AnimChannel;
    import com.jme3.animation.AnimControl;
    import com.jme3.animation.AnimEventListener;
    import com.jme3.app.SimpleApplication;
    import com.jme3.bullet.BulletAppState;
    import com.jme3.bullet.PhysicsSpace;
    import com.jme3.bullet.control.BetterCharacterControl;
    import com.jme3.bullet.control.RigidBodyControl;
    import com.jme3.bullet.util.CollisionShapeFactory;
    import com.jme3.input.ChaseCamera;
    import com.jme3.input.KeyInput;
    import com.jme3.input.MouseInput;
    import com.jme3.input.controls.ActionListener;
    import com.jme3.input.controls.KeyTrigger;
    import com.jme3.input.controls.MouseButtonTrigger;
    import com.jme3.input.controls.TouchListener;
    import com.jme3.input.controls.TouchTrigger;
    import com.jme3.input.event.TouchEvent;
    import static com.jme3.input.event.TouchEvent.Type.FLING;
    import static com.jme3.input.event.TouchEvent.Type.LONGPRESSED;
    import static com.jme3.input.event.TouchEvent.Type.MOVE;
    import static com.jme3.input.event.TouchEvent.Type.TAP;
    import static com.jme3.input.event.TouchEvent.Type.UP;
    import com.jme3.light.AmbientLight;
    import com.jme3.light.DirectionalLight;
    import com.jme3.material.Material;
    import com.jme3.math.ColorRGBA;
    import com.jme3.math.FastMath;
    import com.jme3.math.Quaternion;
    import com.jme3.math.Vector3f;
    import com.jme3.renderer.RenderManager;
    import com.jme3.renderer.queue.RenderQueue;
    import com.jme3.scene.CameraNode;
    import com.jme3.scene.Geometry;
    import com.jme3.scene.Node;
    import com.jme3.scene.SceneGraphVisitor;
    import com.jme3.scene.SceneGraphVisitorAdapter;
    import com.jme3.scene.Spatial;
    import com.jme3.system.AppSettings;
    import com.jme3.terrain.geomipmap.TerrainQuad;
    import com.jme3.terrain.heightmap.AbstractHeightMap;
    import com.jme3.terrain.heightmap.ImageBasedHeightMap;
    import com.jme3.texture.Texture;
    import com.jme3.texture.Texture.WrapMode;
    import com.jme3.util.SkyFactory;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;

/**

  • A walking physical character followed by a 3rd person camera. (No animation.)

  • @author normenhansen, zathras
    */
    public class Main extends SimpleApplication
    implements ActionListener, AnimEventListener, TouchListener {

    private BulletAppState bulletAppState;
    private BetterCharacterControl physicsCharacter;
    private Node characterNode;
    private Node model;
    private CameraNode camNode;
    boolean rotate = false;
    private Vector3f walkDirection = new Vector3f(0, 0, 0);
    private Vector3f viewDirection = new Vector3f(0, 0, 1);
    boolean leftStrafe = false, rightStrafe = false, forward = false, backward = false,
    leftRotate = false, rightRotate = false;
    private boolean left = false, right = false, up = false, down = false;
    private Vector3f normalGravity = new Vector3f(0.0f,-9.8f,0.0f);
    private ChaseCamera chaseCamera;
    private boolean lockView = false;
    private boolean jumpwalk = true;
    private List<AnimChannel> animChannels;
    private List<AnimControl> animControls;
    //terrain
    //loaded terrain
    private Spatial terrainSpatial;
    //created terrain
    private TerrainQuad terrainQuad;
    //terrain common
    private Node terrain;
    private RigidBodyControl terrainPhysicsNode;
    boolean loadedTerrain = false;
    //Materials
    Material matRock;
    Material matBullet;

    public static void main(String[] args) {
    Main app = new Main();
    AppSettings settings = new AppSettings(true);
    settings.setRenderer(AppSettings.LWJGL_OPENGL2);
    settings.setAudioRenderer(AppSettings.LWJGL_OPENAL);
    app.setSettings(settings);
    app.start();
    }

    @Override
    public void simpleInitApp() {
    //setup keyboard mapping
    setupKeys();

     // activate physics
     bulletAppState = new BulletAppState();
     stateManager.attach(bulletAppState);
     bulletAppState.setDebugEnabled(true);
    
     // init a physics test scene
     loadedTerrain = false;
     if (loadedTerrain) {
         loadTerrain();
     } else {
         createTerrain();
     }
     createCharacter();
    
     flyCam.setEnabled(false);
     chaseCamera = new ChaseCamera(cam, model, inputManager);
     chaseCamera.setSmoothMotion(false);
     chaseCamera.setToggleRotationTrigger(new MouseButtonTrigger(MouseInput.BUTTON_MIDDLE));
    
     createLight();
     //stateManager.attach(new VideoRecorderAppState());
     
     inputManager.addMapping("Touch", new TouchTrigger(0));
     inputManager.addListener(this, new String[]{"Touch"});
    

    }

    private void createTerrain() {
    // load sky
    Spatial sky = SkyFactory.createSky(assetManager, “Textures/ColorRamp/cloudy.png”, true);
    rootNode.attachChild(sky);
    //rootNode.attachChild(SkyFactory.createSky(assetManager, “Textures/Sky/Bright/BrightSky.dds”, false));
    matRock = new Material(assetManager, “Common/MatDefs/Terrain/TerrainLighting.j3md”);
    matRock.setBoolean(“useTriPlanarMapping”, false);
    matRock.setBoolean(“WardIso”, true);
    matRock.setTexture(“AlphaMap”, assetManager.loadTexture(“Textures/Terrain/splat/alphamap.png”));
    Texture heightMapImage = assetManager.loadTexture(“Textures/Terrain/splat/mountains512.png”);
    Texture grass = assetManager.loadTexture(“Textures/Terrain/splat/grass.jpg”);
    grass.setWrap(WrapMode.Repeat);
    matRock.setTexture(“DiffuseMap”, grass);
    matRock.setFloat(“DiffuseMap_0_scale”, 64);
    Texture dirt = assetManager.loadTexture(“Textures/Terrain/splat/dirt.jpg”);
    dirt.setWrap(WrapMode.Repeat);
    matRock.setTexture(“DiffuseMap_1”, dirt);
    matRock.setFloat(“DiffuseMap_1_scale”, 16);
    Texture rock = assetManager.loadTexture(“Textures/Terrain/splat/road.jpg”);
    rock.setWrap(WrapMode.Repeat);
    matRock.setTexture(“DiffuseMap_2”, rock);
    matRock.setFloat(“DiffuseMap_2_scale”, 128);
    Texture normalMap0 = assetManager.loadTexture(“Textures/Terrain/splat/grass_normal.jpg”);
    normalMap0.setWrap(WrapMode.Repeat);
    Texture normalMap1 = assetManager.loadTexture(“Textures/Terrain/splat/dirt_normal.png”);
    normalMap1.setWrap(WrapMode.Repeat);
    Texture normalMap2 = assetManager.loadTexture(“Textures/Terrain/splat/road_normal.png”);
    normalMap2.setWrap(WrapMode.Repeat);
    matRock.setTexture(“NormalMap”, normalMap0);
    matRock.setTexture(“NormalMap_1”, normalMap2);
    matRock.setTexture(“NormalMap_2”, normalMap2);

     AbstractHeightMap heightmap = null;
     try {
         heightmap = new ImageBasedHeightMap(heightMapImage.getImage(), 0.25f);
         heightmap.load();
    
     } catch (Exception e) {
     }
    
     terrainQuad = new TerrainQuad("terrain", 65, 513, heightmap.getHeightMap());
     terrainQuad.setMaterial(matRock);
     terrainQuad.setLocalScale(new Vector3f(2, 2, 2));
     terrainQuad.setLocalTranslation(-100, -40, 150);
     terrain = new Node();
     terrain.attachChild(terrainQuad);
    
     terrainPhysicsNode = new RigidBodyControl(CollisionShapeFactory.createMeshShape(terrain), 0);
     terrain.addControl(terrainPhysicsNode);
     getPhysicsSpace().add(terrain);
     rootNode.attachChild(terrain);
    

    }

    public void loadTerrain() {
    terrainSpatial = assetManager.loadModel(“Scenes/gilbScene.j3o”);
    terrainSpatial.depthFirstTraversal(new SceneGraphVisitor() {

         @Override
         public void visit(Spatial spatial) {
             RigidBodyControl rigidBodyControl = spatial.getControl(RigidBodyControl.class);
             if(rigidBodyControl != null) {
                 terrainPhysicsNode = rigidBodyControl;
             }
         }
     });
     terrain = new Node();
     terrain.attachChild(terrainSpatial);
     terrain.addControl(terrainPhysicsNode);
     getPhysicsSpace().add(terrainPhysicsNode);
     rootNode.attachChild(terrain);
    

    }

    public void createCharacter() {
    // Create a node for the character model
    characterNode = new Node(“character node”);
    if (!loadedTerrain) {
    characterNode.setLocalTranslation(new Vector3f(56.0f, 1.0f, 169.0f));
    } else {
    characterNode.setLocalTranslation(new Vector3f(0.0f, 1.0f, 0.0f));
    }

     // Add a character control to the node so we can add other things and
     // control the model rotation
     physicsCharacter = new BetterCharacterControl(0.5f, 2.5f, 80f);
     characterNode.addControl(physicsCharacter);
     // Load model, attach to character node
     model = (Node) assetManager.loadModel("Models/Jaime/Jaime.j3o");
     model.setShadowMode(RenderQueue.ShadowMode.CastAndReceive);
    
     model.setLocalScale(2.0f);
     characterNode.attachChild(model);
     setAnimControls(model);
     setAnimation("Idle", 0.3f);
     // Add character node to the rootNode
     getPhysicsSpace().add(physicsCharacter);
     getPhysicsSpace().addAll(characterNode);
     physicsCharacter.setGravity(normalGravity);
     rootNode.attachChild(characterNode);
    

    }

    @Override
    public void simpleUpdate(float tpf) {
    checkGravity();
    // Get current forward and left vectors of model by using its rotation
    // to rotate the unit vectors
    Vector3f modelForwardDir = characterNode.getWorldRotation().mult(Vector3f.UNIT_Z);
    Vector3f modelLeftDir = characterNode.getWorldRotation().mult(Vector3f.UNIT_X);

     // WalkDirection is global!
     // You *can* make your character fly with this.
     walkDirection.set(0, 0, 0);
     if (leftStrafe || left || down) {
         walkDirection.addLocal(modelLeftDir.mult(1.0f));
     } else if (rightStrafe || right) {
         walkDirection.addLocal(modelLeftDir.negate().multLocal(1.0f));
     }
     if (forward || up) {
         walkDirection.addLocal(modelForwardDir.mult(1.0f));
     } else if (backward) {
         walkDirection.addLocal(modelForwardDir.negate().multLocal(1.0f));
     }
     physicsCharacter.setWalkDirection(walkDirection);
    
     if (walkDirection.z != 0f || walkDirection.x != 0f || walkDirection.y != 0f) {
         setAnimation("Walk", 1.0f);
     } else {
         setAnimation("Idle", 0.3f);
     }
     // ViewDirection is local to characters physics system!
     // The final world rotation depends on the gravity and on the state of
     // setApplyPhysicsLocal()
     if (leftRotate) {
         Quaternion rotateL = new Quaternion().fromAngleAxis(FastMath.PI * tpf, Vector3f.UNIT_Y);
         rotateL.multLocal(viewDirection);
     } else if (rightRotate) {
         Quaternion rotateR = new Quaternion().fromAngleAxis(-FastMath.PI * tpf, Vector3f.UNIT_Y);
         rotateR.multLocal(viewDirection);
     }
     physicsCharacter.setViewDirection(viewDirection);
     int x = (int) model.getWorldTranslation().x;
     int y = (int) model.getWorldTranslation().y;
     int z = (int) model.getWorldTranslation().z;
     String position = "(" + x + ", " + y + ", " + z + ")";
     fpsText.setSize(12.0f);
     fpsText.setText("Position = ".concat(position));
    

    }

    private PhysicsSpace getPhysicsSpace() {
    return bulletAppState.getPhysicsSpace();
    }

    @Override
    public void onAction(String binding, boolean value, float tpf) {
    switch (binding) {
    case “Strafe Left”:
    if (value) {
    leftStrafe = true;
    } else {
    leftStrafe = false;
    }
    break;
    case “Strafe Right”:
    if (value) {
    rightStrafe = true;
    } else {
    rightStrafe = false;
    }
    break;
    case “Rotate Left”:
    if (value) {
    leftRotate = true;
    } else {
    leftRotate = false;
    }
    break;
    case “Rotate Right”:
    if (value) {
    rightRotate = true;
    } else {
    rightRotate = false;
    }
    break;
    case “walk Forward”:
    if (value) {
    forward = true;
    } else {
    forward = false;
    }
    break;
    case “walk Backward”:
    if (value) {
    backward = true;
    } else {
    backward = false;
    }
    break;
    case “Jump”:
    physicsCharacter.jump();
    break;
    case “Duck”:
    if (value) {
    physicsCharacter.setDucked(true);
    } else {
    physicsCharacter.setDucked(false);
    }
    break;
    case “Lock View”:
    if (value && lockView) {
    lockView = false;
    } else if (value && !lockView) {
    lockView = true;
    }
    //flyCam.setEnabled(!lockView);
    //camNode.setEnabled(lockView);
    break;
    case “jumpWalk”:
    if (!value) {
    jumpwalk = !jumpwalk;
    }
    break;
    }
    }

    private void setupKeys() {
    inputManager.addMapping(“Strafe Left”,
    new KeyTrigger(KeyInput.KEY_U),
    new KeyTrigger(KeyInput.KEY_Z));
    inputManager.addMapping(“Strafe Right”,
    new KeyTrigger(KeyInput.KEY_O),
    new KeyTrigger(KeyInput.KEY_X));

     inputManager.addMapping("Rotate Left",
             new KeyTrigger(KeyInput.KEY_J),
             new KeyTrigger(KeyInput.KEY_LEFT),
             new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
     inputManager.addMapping("Rotate Right",
             new KeyTrigger(KeyInput.KEY_L),
             new KeyTrigger(KeyInput.KEY_RIGHT),
             new MouseButtonTrigger(MouseInput.BUTTON_RIGHT));
     inputManager.addMapping("walk Forward",
             new KeyTrigger(KeyInput.KEY_I),
             new KeyTrigger(KeyInput.KEY_UP),
             new MouseButtonTrigger(MouseInput.BUTTON_MIDDLE));
     inputManager.addMapping("walk Backward",
             new KeyTrigger(KeyInput.KEY_K),
             new KeyTrigger(KeyInput.KEY_DOWN));
     inputManager.addMapping("Jump",
             new KeyTrigger(KeyInput.KEY_F),
             new KeyTrigger(KeyInput.KEY_SPACE));
     inputManager.addMapping("Duck",
             new KeyTrigger(KeyInput.KEY_G),
             new KeyTrigger(KeyInput.KEY_LSHIFT),
             new KeyTrigger(KeyInput.KEY_RSHIFT));
     inputManager.addMapping("jumpWalk", new KeyTrigger(KeyInput.KEY_J));
     inputManager.addMapping("Lock View",
             new KeyTrigger(KeyInput.KEY_RETURN));
     inputManager.addListener(this, "Strafe Left", "Strafe Right");
     inputManager.addListener(this, "Rotate Left", "Rotate Right");
     inputManager.addListener(this, "walk Forward", "walk Backward");
     inputManager.addListener(this, "Jump", "Duck", "Lock View");
     inputManager.addListener(this, "jumpWalk");
    

    }

    @Override
    public void simpleRender(RenderManager rm) {
    }

    private void createLight() {
    //if (!loadedTerrain) {
    Vector3f direction = new Vector3f(-0.1f, -0.7f, -1).normalizeLocal();
    DirectionalLight directionalLight = new DirectionalLight();
    directionalLight.setDirection(direction);
    directionalLight.setColor(new ColorRGBA(1f, 1f, 1f, 1.0f));
    rootNode.addLight(directionalLight);
    AmbientLight ambientLight = new AmbientLight();
    rootNode.addLight(ambientLight);
    //}
    }

    @Override
    public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) {
    }

    @Override
    public void onAnimChange(AnimControl control, AnimChannel channel, String animName) {
    }

    private void setAnimControls(Spatial spatial) {
    if (spatial == null) {
    if (animControls != null) {
    for (Iterator<AnimControl> it = animControls.iterator(); it.hasNext():wink: {
    AnimControl animControl = it.next();
    animControl.clearChannels();
    }
    }
    animControls = null;
    animChannels = null;
    return;
    }

     SceneGraphVisitorAdapter visitor = new SceneGraphVisitorAdapter() {
         @Override
         public void visit(Geometry geom) {
             super.visit(geom);
             checkForAnimControl(geom);
         }
    
         @Override
         public void visit(Node geom) {
             super.visit(geom);
             checkForAnimControl(geom);
         }
    
         private void checkForAnimControl(Spatial geom) {
             AnimControl animControl = geom.getControl(AnimControl.class);
             if (animControl == null) {
                 return;
             }
             if (animControls == null) {
                 animControls = new ArrayList&lt;&gt;();
             }
             if (animChannels == null) {
                 animChannels = new ArrayList&lt;&gt;();
             }
             animControls.add(animControl);
             animChannels.add(animControl.createChannel());
         }
     };
     spatial.depthFirstTraversal(visitor);
    

    }

    public void setAnimation(String animation, float speed) {
    for (AnimChannel animChannel : animChannels) {
    try {
    if (animChannel.getAnimationName().equals(animation)) {
    return;
    }
    } catch (Exception e) {
    }
    animChannel.setAnim(animation);
    animChannel.setSpeed(speed);
    }
    }

    private void checkGravity() {
    Vector3f dist = terrain.getWorldTranslation().subtract(characterNode.getWorldTranslation());
    if (dist.length() < 24) {
    physicsCharacter.setGravity(dist.normalizeLocal().multLocal(9.81f));
    } else {
    physicsCharacter.setGravity(normalGravity);
    }
    }

    @Override
    public void onTouch(String name, TouchEvent evt, float tpf) {
    float x;
    float y;
    float pressure;
    switch (evt.getType()) {
    case MOVE:
    x = evt.getX();
    y = evt.getY();

             pressure = evt.getPressure();
             up = false;
             left = false;
             right = false;
             if(x&gt;400) right = true;
             else left = true;
             break;
    
         case TAP:
             x = evt.getX();
             y = evt.getY();
             up = false;
             left = false;
             right = false;
             if(x&gt;400) right = true;
             else left = true;
             break;
    
         case LONGPRESSED:
             // move forward
             up = true;
             break;
    
         case UP:
             up = false;
             break;
    
         case FLING:
             break;
    
         default:
             break;
     }
     evt.setConsumed();
    

    }

}
[/java]