Question about GhostControl and GetOverlappingObjects

I have a question about when an object is part of the overlappingobjects collection on a GhostControl. I have a box shape GhostControl to detect when an object falls through a hole. It looks like the object becomes part of the getoverlappingobjects for the GhostControl only when the entire object is inside the GhostControl. If I define a floor that makes the object only sink part way into the hole, then the GhostControl does not report the object via getoverlappingobjects.



Does an object have to be completely encompassed inside the GhostControl in order for the getoverlappingobjects to register the collision?



Is there a better way to sense the collision between a GhostControl and an Object? All I’m really interested in is whether the object makes contact with the GhostControl.



If it matters, I’m developing on Android.

Actually the ghost control should have the floor in its overlapping objects, the character also uses the ghost control for that.

I went back and looked at it again. You’re right that the floor is in the overlappingobjects, but when the ball drops through the hole and hits the floor, it does not register. The number of overlapping objects stays at 1. If I move the floor down 1 more unit, then the ball registers and the number of overlapping objects is 2.



Maybe the shere I’m using for the ball is not done right? Can you see anything obvious?



[java]

package com.interstatewebgroup.jmonkeytutorials;



import java.util.ArrayList;

import java.util.List;



import android.util.Log;



import com.jme3.app.SimpleApplication;

import com.jme3.asset.TextureKey;

import com.jme3.bullet.BulletAppState;

import com.jme3.bullet.PhysicsSpace;

import com.jme3.bullet.PhysicsTickListener;

import com.jme3.bullet.collision.PhysicsCollisionEvent;

import com.jme3.bullet.collision.PhysicsCollisionListener;

import com.jme3.bullet.collision.PhysicsCollisionObject;

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

import com.jme3.bullet.control.GhostControl;

import com.jme3.bullet.control.RigidBodyControl;

import com.jme3.font.BitmapText;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Vector3f;

import com.jme3.scene.Geometry;

import com.jme3.scene.shape.Box;

import com.jme3.scene.shape.Sphere;

import com.jme3.scene.shape.Sphere.TextureMode;

import com.jme3.texture.Texture;

import com.jme3.texture.Texture.WrapMode;

/**

  • Example 12 - how to give objects physical properties so they bounce and fall.
  • @author base code by double1984, updated by zathras

    /

    public class GhostTest1Game extends SimpleApplication

    implements PhysicsCollisionListener, PhysicsTickListener {



    /
    * Prepare the Physics Application State (jBullet) /

    private BulletAppState bulletAppState;



    Geometry geoBall;

    ArrayList<Ball> balls = new ArrayList<Ball>();

    GhostControl ghostScoreBox;



    BitmapText nodeScore;

    private int curScore = 0;



    private class Ball {

    boolean scored = false;

    RigidBodyControl body;

    }



    @Override

    public void simpleInitApp() {

    /
    * Set up Physics Game /

    bulletAppState = new BulletAppState();

    stateManager.attach(bulletAppState);

    bulletAppState.getPhysicsSpace().addCollisionListener(this);

    bulletAppState.getPhysicsSpace().addTickListener(this);



    /
    * Configure cam to look at scene /

    cam.setLocation(new Vector3f(7f, 20f, -20f));

    cam.lookAt(new Vector3f(7f, 2f, 5f), new Vector3f(0, 1, 0));

    cam.setFrustumFar(100);



    // create a blue box

    Box boxBox1 = new Box(Vector3f.ZERO, 2f,1f,7f);

    Geometry geoBox1 = new Geometry("Box1", boxBox1);

    Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

    mat1.setColor("Color", ColorRGBA.Blue);

    geoBox1.setMaterial(mat1);



    /
    * attach the box to the graphics display /

    rootNode.attachChild(geoBox1);

    /
    * Make physical with a mass > 0.0f. /

    RigidBodyControl phyBox1 = new RigidBodyControl(0f);

    /
    * Add box to physics space. /

    geoBox1.addControl(phyBox1);

    bulletAppState.getPhysicsSpace().add(phyBox1);

    /
    * set the location /

    phyBox1.setPhysicsLocation(new Vector3f(2,1,7));



    // create a red box

    Box boxBox2 = new Box(Vector3f.ZERO, 3f,1f,4f);

    Geometry geoBox2 = new Geometry("Box2", boxBox2);

    Material mat2 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

    mat2.setColor("Color", ColorRGBA.Red);

    geoBox2.setMaterial(mat2);



    /
    * attach the box to the graphics display /

    rootNode.attachChild(geoBox2);

    /
    * Make physical with a mass > 0.0f. /

    RigidBodyControl phyBox2 = new RigidBodyControl(0f);

    /
    * Add box to physics space. /

    geoBox2.addControl(phyBox2);

    bulletAppState.getPhysicsSpace().add(phyBox2);

    /
    * set the location /

    phyBox2.setPhysicsLocation(new Vector3f(7, 1, 4));



    // create a DarkGray box

    Box boxBox3 = new Box(Vector3f.ZERO, 2f,1f,7f);

    Geometry geoBox3 = new Geometry("Box3", boxBox3);

    Material mat3 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

    mat3.setColor("Color", ColorRGBA.DarkGray);

    geoBox3.setMaterial(mat3);



    /
    * attach the box to the graphics display /

    rootNode.attachChild(geoBox3);

    /
    * Make physical with a mass > 0.0f. /

    RigidBodyControl phyBox3 = new RigidBodyControl(0f);

    /
    * Add box to physics space. /

    geoBox3.addControl(phyBox3);

    bulletAppState.getPhysicsSpace().add(phyBox3);

    /
    * set the location /

    phyBox3.setPhysicsLocation(new Vector3f(12, 1, 7));



    // create a Orange box

    Box boxBox4 = new Box(Vector3f.ZERO, 7f,1f,3f);

    Geometry geoBox4 = new Geometry("Box4", boxBox4);

    Material mat4 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

    mat4.setColor("Color", ColorRGBA.Orange);

    geoBox4.setMaterial(mat4);



    /
    * attach the box to the graphics display /

    rootNode.attachChild(geoBox4);

    /
    * Make physical with a mass > 0.0f. /

    RigidBodyControl phyBox4 = new RigidBodyControl(0f);

    /
    * Add box to physics space. /

    geoBox4.addControl(phyBox4);

    bulletAppState.getPhysicsSpace().add(phyBox4);

    /
    * set the location /

    phyBox4.setPhysicsLocation(new Vector3f(7, 1, 17));



    // create a floor

    TextureKey keyFloor = new TextureKey("Textures/Terrain/Pond/Pond.png");

    keyFloor.setGenerateMips(true);

    Texture texFloor = assetManager.loadTexture(keyFloor);

    texFloor.setWrap(WrapMode.Repeat);

    Material matFloor = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

    matFloor.setTexture("ColorMap", texFloor);



    Box boxFloor = new Box(Vector3f.ZERO, 20f,1f,20f);

    Geometry geoFloor = new Geometry("Floor", boxFloor);

    geoFloor.setMaterial(matFloor);



    /
    * attach the box to the graphics display /

    rootNode.attachChild(geoFloor);

    /
    * Make physical with a mass > 0.0f. /

    RigidBodyControl phyFloor = new RigidBodyControl(0f);

    /
    * Add box to physics space. /

    geoFloor.addControl(phyFloor);

    bulletAppState.getPhysicsSpace().add(phyFloor);

    /
    * set the location /

    phyFloor.setPhysicsLocation(new Vector3f(10, -1, 10));



    // create a scoring box

    Vector3f extentsScoreBox = new Vector3f(3,3,3);

    BoxCollisionShape shapeScoreBox = new BoxCollisionShape(extentsScoreBox);

    ghostScoreBox = new GhostControl(shapeScoreBox);



    /
    * Add box to physics space. /

    bulletAppState.getPhysicsSpace().add(ghostScoreBox);

    /
    * set the location /

    ghostScoreBox.setPhysicsLocation(new Vector3f(7, -1, 11));



    /
    * Initialize the score text display /

    guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");

    nodeScore = new BitmapText(guiFont, true);

    nodeScore.setSize(guiFont.getCharSet().getRenderedSize() * 4);

    nodeScore.setText("Score: " + Integer.toString(curScore));



    /
    * Origin of guiNode objects
  • 0,0 is the bottom left corner of the screen
  • BitmapText origin is the top left corner of the box



    /

    nodeScore.setLocalTranslation(

    settings.getWidth() - nodeScore.getLineWidth(),

    nodeScore.getHeight(),

    0);

    nodeScore.setColor(ColorRGBA.Pink);

    guiNode.attachChild(nodeScore);



    }



    /
    This method creates one individual physical cannon ball.
  • By defaul, the ball is accelerated and flies
  • from the camera position in the camera direction.*/

    public void dropBall() {

    /** Initialize the cannon ball geometry /

    Sphere sphere = new Sphere(32, 32, 1.5f, true, false);

    sphere.setTextureMode(TextureMode.Projected);



    Material stone_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

    TextureKey key2 = new TextureKey("Textures/Terrain/Rock/Rock.PNG");

    key2.setGenerateMips(true);

    Texture tex2 = assetManager.loadTexture(key2);

    stone_mat.setTexture("ColorMap", tex2);



    /
    * Create a cannon ball geometry and attach to scene graph. /

    geoBall = new Geometry("Ball", sphere);

    geoBall.setMaterial(stone_mat);

    rootNode.attachChild(geoBall);

    /
    * Make the ball physical with a mass > 0.0f /

    RigidBodyControl phyBall = new RigidBodyControl(1f);



    Ball tmpBall = new Ball();

    tmpBall.scored = false;

    tmpBall.body = phyBall;

    balls.add(tmpBall);



    /
    * Add physical ball to physics space. /

    geoBall.addControl(phyBall);

    bulletAppState.getPhysicsSpace().add(phyBall);

    /
    * Position the cannon ball /

    phyBall.setPhysicsLocation(new Vector3f(7, 7, 11));

    /
    * Accelerate the physical ball to shoot it. /

    // phyBall.setLinearVelocity(cam.getDirection().mult(15));



    }



    /
    * Score Display */

    protected void initScoreDisplay() {

    }



    @Override

    public void simpleUpdate(float tpf) {



    if (balls.size() < 1) {

    dropBall();

    }



    nodeScore.setLocalTranslation(

    settings.getWidth() - nodeScore.getLineWidth(),

    nodeScore.getHeight(),

    0);



    }



    @Override

    public void collision(PhysicsCollisionEvent event) {



    }



    @Override

    public void physicsTick(PhysicsSpace arg0, float arg1) {

    // TODO Auto-generated method stub



    List<PhysicsCollisionObject> objOverlappingObjects = ghostScoreBox.getOverlappingObjects();

    int numOverlappingObjects = objOverlappingObjects.size();

    if (numOverlappingObjects > 0) {

    Log.d("physicsTick", "Number of Overlapping Objects with Ghost Box: " + numOverlappingObjects);

    for (int i=0; i<balls.size(); i++) {

    Ball tmpBall = balls.get(i);

    if (objOverlappingObjects.contains(tmpBall.body)) {

    Log.d("physicsTick", "objOverlap Detected");

    if (!tmpBall.scored) {

    curScore += 10;

    tmpBall.scored = true;

    nodeScore.setText("Score: " + curScore);

    }

    }

    }

    }





    }



    @Override

    public void prePhysicsTick(PhysicsSpace arg0, float arg1) {

    // TODO Auto-generated method stub



    }



    }

    [/java]