Yet I clearly set the collision shape to horizontal(0).
Don’t pay attention to the pink wireframe. Although it displays in the correct orientation, the ingame collision is not the same as the wireframe. In other words, we don’t need to trouble shoot the wireframe, just the actual collision.
I just ran a simple test with a Kinematic RigidBodyControl from a PlaneCollisionShape, and a CharacterControl with a CapsuleCollisionShape setting the physics location to 10 units above zero, and setting physics debug to true (no meshes)
setting the axis to 1 provided a “vertical” debug capsule wireframe which fell onto the plane until it touched and stopped, standing straight up.
setting the axis to 0 provided a “horizontal” debug capsule wireframe pointing left and right which also fell onto the plane until it touched, and did not roll.
setting the axis to 2 provided a “horziontal” debug capsule wireframe pointing toward the camera which also fell onto the plane until it touched, and did not roll.
This seems to be expected behaviour, but I did not implement any custom input controls. (although I did have to initialize the gravity manually to keep the CharacterControl from flying awkwardly into the negative x direction.)
Are you setting/updating the CharacterControl’s (or the terrain rigid body control’s) physics location manually somewhere each frame?
Edit:
after creating and adding the BulletAppState and setting debug to true, this is the relevant code i used to setup my test:
public void setupCapsuleCollisonShapeTest() {
// 0 = x axis, 1 = y axis, 2 = z axis
CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(1.5f, 6f, 0);
CharacterControl capsule = new CharacterControl(capsuleShape, 0.05f);
bulletAppState.getPhysicsSpace().add(capsule );
capsule.setGravity(new Vector3f(0f, -9.81f, 0f)); // reset gravity to -y
capsule .setPhysicsLocation(new Vector3f(0f, 10f, 0f));
Plane plane = new Plane(Vector3f.UNIT_Y, 0f);
PlaneCollisionShape planeShape = new PlaneCollisionShape(plane);
RigidBodyControl terrain = new RigidBodyControl(planeShape, 0);
bulletAppState.getPhysicsSpace().add(terrain);
}
I literally just copy and pasted the ‘hello collision’ example. So I strongly suggest for people to use it. It only takes a minute to get the test going.
I tried that first, but unfortunately I couldnt see the capsule debug wireframe. I guess it is closer to the camera than the near clipping plane would allow to be visible.
Also, that tutorial may need updating.
You have to pull back the camera by adding a vector offset in order to view your own capsule wireframe. Like this:
private Vector3f cameraOffset = new Vector3f(0,0,5);
cam.setLocation(cameraOffset.add(player.getPhysicsLocation().getX(),
player.getPhysicsLocation().getY(),
player.getPhysicsLocation().getZ()));
I’m trying to stick to the tutorial because people come up with too many questions and doubt too many things if you don’t specify a clear source such as a tutorial.
@ decoyhiding Also your height of 6 is too small to see the difference. There is a reason why I put 18 on mine. You won’t notice the capsule clipping through the floor because the debug wireframe overlays over everything. My test was crafted to make the bug obvious. It took sometime. It is hard to make it obvious.
No @pspeed. Don’t look at the wireframe. It is displayed correctly as per the values. Yes the wireframe is vertical when I set it to 1 in the picture. BUT the collision remain horizontal.
Your picture is not at all clear. In one it looks like the door is halfway through the ground and in the other it looks like the door is fully underground.
In the first picture you are looking at the bottom of the door because you are short. In the second picture you are looking at the top of the door because you are tall. The camera rotation has not changed a bit. And the character is touching the door. That’s not my model. That’s the town.zip example if you wall forward when you load the level.
ok, after trying adjustments on the tutorial I must admit, I do see the behaviour @Pixelapp is describing.
if i set the axis to 0 for horizontal (x), the capsule debug wireframe does hover above the expected point of contact, and setting axis to 1 for vertical (y) seems to make the wireframe sink into the terrain. it is best noticed when offsetting the camera and “walking” along the angled building rooftops
after my isolated test with a plane, i suspect this is related to the implementation of input controls in the tutorial, or maybe an error with the collision shape of the scene in town.zip.
But regarding your “bug”, as stated, it’s not true… because literally everyone who ever uses a character control and tons of examples that don’t seem to have no issues at all with CapsuleCollisionShape. It’s probably used by literally everyone who has ever used bullet.
Maybe there is something wrong with the tutorial… but even for me who barely used bullet, capsule has always worked the way I want it.
I wonder if it’s specific to character control. I guess internally it’s casting rays or somesuch to do part of it’s job and maybe it doesn’t work well with non-vertical capsules.
My guess is that a regular rigid body would fall/lay as expected.
I added input controls to the CharacterControl in my simple test and changed plane to box. The behavior is still as expected, it even stays on top of the box until the very last part moves off the edge, whereas in the tutorial, the horizontal capsule will fall off the building roof as soon as the vertical capsule would have moved off.
I really think something in the tutorial code is causing this unexpected effect.
i checked the libraries and the helloCollision tutorial built from the JmeTests project is using:
@Pixelapp here is my “quick and dirty” test case showing expected behavior in an environment isolated from the HelloCollision tutorial, if you want to verify.
movement keys: i, j, k, l to not conflict with flyCam controls
Edit: disclaimer - no best practices here.
import com.jme3.app.SimpleApplication;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.shapes.BoxCollisionShape;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
public class CapsuleCollisionShapeTest extends SimpleApplication implements ActionListener {
public BulletAppState bulletAppState;
private boolean left, right, up, down;
private CharacterControl capsule;
private Vector3f walkDirection;
public static void main(String[] args) {
CapsuleCollisionShapeTest app = new CapsuleCollisionShapeTest();
app.start();
}
@Override
public void simpleInitApp() {
this.flyCam.setMoveSpeed(20f);
bulletAppState = new BulletAppState();
stateManager.attach(bulletAppState);
bulletAppState.setDebugEnabled(true);
setupCapsuleCollisonShapeTest();
walkDirection = new Vector3f();
setUpKeys();
}
public void setupCapsuleCollisonShapeTest() {
CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(1.5f, 6f, 0);
capsule = new CharacterControl(capsuleShape, 0.05f);
bulletAppState.getPhysicsSpace().add(capsule );
capsule.setGravity(new Vector3f(0f, -9.81f, 0f));
capsule .setPhysicsLocation(new Vector3f(0f, 10f, 0f));
BoxCollisionShape boxShape = new BoxCollisionShape(new Vector3f(6f, 1f, 6f));
RigidBodyControl terrain = new RigidBodyControl(boxShape, 0);
bulletAppState.getPhysicsSpace().add(terrain);
}
private void setUpKeys() {
inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_J));
inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_L));
inputManager.addMapping("Up", new KeyTrigger(KeyInput.KEY_I));
inputManager.addMapping("Down", new KeyTrigger(KeyInput.KEY_K));
inputManager.addMapping("Jump", new KeyTrigger(KeyInput.KEY_SPACE));
inputManager.addListener(this, "Left");
inputManager.addListener(this, "Right");
inputManager.addListener(this, "Up");
inputManager.addListener(this, "Down");
inputManager.addListener(this, "Jump");
}
public void onAction(String binding, boolean value, float tpf) {
if (binding.equals("Left")) {
if (value) { left = true; } else { left = false; }
} else if (binding.equals("Right")) {
if (value) { right = true; } else { right = false; }
} else if (binding.equals("Up")) {
if (value) { up = true; } else { up = false; }
} else if (binding.equals("Down")) {
if (value) { down = true; } else { down = false; }
} else if (binding.equals("Jump")) {
capsule.jump(new Vector3f(0f, 10f, 0f));
}
}
@Override
public void simpleUpdate(float tpf) {
walkDirection.set(0, 0, 0);
if (left) {
walkDirection.subtractLocal(Vector3f.UNIT_X);
}
if (right) {
walkDirection.addLocal(Vector3f.UNIT_X);
}
if (up) {
walkDirection.subtractLocal(Vector3f.UNIT_Z);
}
if (down) {
walkDirection.addLocal(Vector3f.UNIT_Z);
}
capsule.setWalkDirection(walkDirection);
}
@Override
public void simpleRender(RenderManager rm) {
//TODO: add render code
}
}
Although, I’m still not sure why I have to re-initialize the gravity on the CharacterControl to keep it from falling in the x axis.