Collision shape in center instead of bottom of model with BetterCharacterControl

I loaded the Sinbad and Ninja models from the test assets, and created a blue box, it might be a bit difficult to see but the capsule shape of the BetterCharacterControl is where it should be on the ninja model, but on the Sinbad model and the blue box the shape seems to start from the center rather than the bottom.

I assume I could edit the Sinbad model in blender and give it some sort of offset but I can’t do that with meshes I’ve created in code, is there some way to make sure the collision shape starts at the bottom of all the models I attach BetterCharacterControls to?

Edit: Heres the code I use to create the box:

Box b = new Box(0.12f, 0.88f, 0.23f); // create a box of roughly average human dimensions.
            Geometry geom = new Geometry("Box", b);  // create a cube geometry from the box shape            
            Material mat = new Material(app.getAssetManager(),
            "Common/MatDefs/Misc/Unshaded.j3md");  // create a simple material
            mat.setColor("Color", ColorRGBA.Blue);   // set color of material to blue
            geom.setMaterial(mat);                   // set the cube geometry 's material
            return geom;

And here’s the code I use to create the BetterCharacterControls:

BetterCharacterControl character = new BetterCharacterControl(0.23f, 1.75f, 0.1f);            
            Node node = app.getStateManager().getState(_SpatialHandlingState.class).getCharacterNode(e);          
            
            character.setWalkDirection(new Vector3f(0f, 0f, 0f));
            node.addControl(character);            
            bulletAppState.getPhysicsSpace().add(character);

The can be replicated my changing the BetterCharacterControl test to load the Sinbad model (and scaling to about 0.25, otherwise the model is huge) or a box instead of the Monkey. Is there an easy way to fix this in code?

geom.setLocalTranslation(0, 0.88f, 0);

The best way I’ve found to fix this is to offset the models a certain amount from the parent node that the character control is actually attached to.

Spatial entityModel = createModel(e);            
 characterNode.attachChild(entityModel);
            
 BoundingBox bounds = (BoundingBox)entityModel.getWorldBound();
 float offset = bounds.getYExtent();
 entityModel.setLocalTranslation(0.0f, offset, 0.0f);

Edit: Too late, although my solution works for arbitrarily sized models, so theres that.

@pinecone said: The best way I've found to fix this is to offset the models a certain amount from the parent node that the character control is actually attached to.
Spatial entityModel = createModel(e);            
 characterNode.attachChild(entityModel);
            
 BoundingBox bounds = (BoundingBox)entityModel.getWorldBound();
 float offset = bounds.getYExtent();
 entityModel.setLocalTranslation(0.0f, offset, 0.0f);

Edit: Too late, although my solution works for arbitrarily sized models, so theres that.

Yours has some problems, too… using WorldBound means that it will pick up any translation, rotation, etc. that the parent might have (or it’s parent and so on).

Also, using just yExtent presumes that center is 0,0,0. For example, if the model was already with feet at 0,0,0 then your offset would move it’s feet up to where it’s waist was. offset = yExtent - center.y

My solution was only a hint because I get the feeling the OP is very new to scene graphs to have not considered just offseting the child and so has some discovery to go through. And because the original post was bumped after only 3 hours.

OP, it’s worth getting to know about using the model bounds for scale and position normalization. The time invested will be well spent.

It’s just you and me in this thread, check the usernames :P.

You’re right, I am a bit new to this, although the code I have loading the models is initialization code just pulling placeholder nodes from the scenegraph so from what I can tell I only really need to worry about the center position problem.

As far as I can tell though the BoundingBox .getCenter() method gets the actual center of the box, rather than the (0, 0, 0) position in the model that I need. I can’t find any methods in the javadocs that do that, is there anything?

Edit: turns out that’s actually exactly what it does and I just had a sneaky bug, I think my problems are all solved now.

The usual approach is, to simple make the players stand on their feet in a modeling programm,
then for the shape you have a known size of the player (qg 1.8 meter) Eg halflife 2 its 72 world units for a standing player (they dont use meteres)
With that you know where the actual center is, and can easily position the player somewhere due to the fact that the feet are at 0

How did you solve your problem? I’m having your originally named problem and I need a workaround.

8 years later, that user may not still be reading this forum. If the suggestions already made in this thread don’t help then you should post your code.

2 Likes

This is the snippet for the BetterCharacterControl.

advancedPlayer = new BetterCharacterControl(6f, 12, 30);
bulletAppState.getPhysicsSpace().add(advancedPlayer);
Spatial advancedSpatial = assetManager.loadModel("Models/Oto/Oto.mesh.xml");
BoundingBox boundingBox = (BoundingBox) advancedSpatial.getWorldBound();
//        advancedSpatial.setLocalTranslation(0, boundingBox.getYExtent() + 12, 0);
advancedSpatial.setLocalTranslation(new Vector3f(0, 10, -20));
advancedSpatial.addControl(advancedPlayer);
//        advancedPlayer.getRigidBody().setPhysicsLocation(new Vector3f(0, 20, -60));
//        advancedSpatial.setLocalTranslation(new Vector3f(0, 20, -60));
bulletAppState.setDebugEnabled(true);

rootNode.attachChild(advancedSpatial);

I have pasted my commented code all together so that it is clear of what I had tried. In my scene I have 2 object, this one the, BetterCharacterControl and the other one is a CharacterControl. The CharacterControl is working fine and I was trying to discover the features of the BetterCharacterControl.

Make a new Post
But I think there several solutions to this:
1: Make a new parent node and adjust the height inside it and add BCC to the parent node
2: Adjust the model inside a blender and rise where its bottom at 0 point
3: Make a complex Bounding shape to the model to adjust it position

1 Like

Thank you @carpenter. Your suggestion worked. I don’t see the need to make a new thread since my problem is solved. Here is my code snip:

Node advancedNode = new Node("Oto-Player");
advancedPlayer = new BetterCharacterControl(1.5f, 5.5f, 1);
bulletAppState.getPhysicsSpace().add(advancedPlayer);
advancedSpatial = assetManager.loadModel("Models/Oto/Oto.mesh.xml");
advancedSpatial.setLocalTranslation(new Vector3f(0, 5, 0));
advancedNode.addControl(advancedPlayer);
advancedNode.setLocalScale(0.5f);
advancedNode.attachChild(advancedSpatial);
advancedPlayer.getRigidBody().setPhysicsLocation(new Vector3f(-10, 10, -80));
bulletAppState.setDebugEnabled(true);

rootNode.attachChild(advancedNode);
1 Like

Glad, it helped

1 Like