Rotating a Ghost Control

I’ve been having problems figuring out the ghost control on an app I’m doing on the Android platform. I created a test app to simplify it down to a floor, a ghost control, and a falling box.



When I have the ghost control without any rotation, the falling box is detected at the proper location as far as I can tell, but when I rotate the node that the ghost control is attached to, the falling box is detected at what appears to be the wrong location. Specifically, when I rotate the node the ghost control is attached to by 45 degrees around the z axis, the falling box is detected a little higher than when the ghost control is not rotated at all. The falling box is offset a little in the x direction, so it should have been detected a little lower than without the rotation, I think.



I enabled debug shapes and they appear correct on the screen (ie. ghost control debug shape appears rotated correctly). But when the falling box is detected by the ghost control, there is a gap between the debug shape for the falling box and the debug shape for the ghost control.



Could someone please look at the code below and let me know if I am doing the rotation wrong or if there is a problem inside jme3? I would really appreciate it. I’ve tried node.rotate, node.setLocalRotation, and control.setPhysicsRotation, but nothing seems to work the way I thought it would.



Thanks!



[java]

package com.interstatewebgroup.jmonkeytutorials;



import java.util.List;



import android.util.Log;



import com.jme3.app.Application;

import com.jme3.app.SimpleApplication;

import com.jme3.bullet.BulletAppState;

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.math.FastMath;

import com.jme3.math.Quaternion;

import com.jme3.math.Vector3f;

import com.jme3.scene.Node;





public class GhostTest1Game extends SimpleApplication {

private BulletAppState bulletAppState;

private GhostControl ghostControl;

private Node node;

private Node physicsBox;

private RigidBodyControl nodeControl;

private RigidBodyControl physicsBoxControl;



public static void main(String[] args) {

Application app = new GhostTest1Game();

app.start();

}



@Override

public void simpleInitApp() {

bulletAppState = new BulletAppState();

stateManager.attach(bulletAppState);

bulletAppState.getPhysicsSpace().enableDebug(assetManager);



// the floor, does not move (mass=0)

node = new Node(“Floor”);

nodeControl = new RigidBodyControl(

new BoxCollisionShape(new Vector3f(100, 1, 100)), 0);

node.addControl(nodeControl);

node.setName(“floor”);

nodeControl.setPhysicsLocation(new Vector3f(0f, -6, 0f));

rootNode.attachChild(node);

bulletAppState.getPhysicsSpace().add(node);



// falling box, (mass=1)

physicsBox = new Node(“PhysicsBox”);

physicsBoxControl = new RigidBodyControl(

new BoxCollisionShape(new Vector3f(1, 1, 1)), 1);

physicsBox.addControl(physicsBoxControl);

physicsBox.setName(“physicsbox”);

physicsBoxControl.setPhysicsLocation(new Vector3f(1.75f, 10, 0));

rootNode.attachChild(physicsBox);

bulletAppState.getPhysicsSpace().add(physicsBox);



// rotation for Ghost Control Node

Quaternion rotQuat = new Quaternion();

rotQuat.fromAngleAxis(45*FastMath.DEG_TO_RAD, new Vector3f(0,0,1));

Vector3f halfExtents = new Vector3f(1, 1, 1);



// ghost control box

ghostControl = new GhostControl(new BoxCollisionShape(halfExtents));

Node ghostNode=new Node(“Ghost Object”);

ghostNode.addControl(ghostControl);

rootNode.attachChild(ghostNode);

bulletAppState.getPhysicsSpace().add(ghostControl);



ghostNode.rotate(rotQuat);



}



@Override

public void simpleUpdate(float tpf) {

fpsText.setText(

"Overlapping objects: " +

ghostControl.getOverlappingObjects().toString());



List<PhysicsCollisionObject> objs = ghostControl.getOverlappingObjects();



if (objs.contains(nodeControl)) {

Log.d(“simpleUpdate”, “node” + nodeControl.getPhysicsLocation().toString());

nodeControl.setKinematic(true);

}

if (objs.contains(physicsBoxControl)) {

Log.d(“simpleUpdate”, “physicsBox” +

physicsBoxControl.getPhysicsLocation().toString());

physicsBoxControl.setKinematic(true);

}

}

}

[/java]

Do not use setLocalTranslation setLocalRotation or setLocalScale for physics objects, use setPhysicsLocalRotation and the same for translation and scale.

Did you ever figure out what the deal with this is? Might it have something to do with the ghostNode working on the physicsTick and not the update()?

LOL -.- , that thread is very old.

morrowsend said:
Did you ever figure out what the deal with this is? Might it have something to do with the ghostNode working on the physicsTick and not the update()?


Probably no, because he didn't move/rotate/scale the physics model in update loop. At least is this what the code shows.

In addition to not using the .rotate on the node, I also did some reading on the bullet forum and thought I saw that ghost objects were always axis aligned instead of object aligned. I’m not sure if that is true or not, but it seemed to match what I was seeing. I removed the requirement to rotate the ghost control and everything seemed to work out. Some day I’ll get back to that to see if ghost controls can be rotated.