Why can't I connect CharacterControl to a node and connect that node to another node?

Hi!

I’m going to try bullet physics. By this, I will build a simple car game. This is my simple car in Blender.

Markering_014

I start to first initialize the bullet physics.

         // Bullet 
        BulletAppState bulletAppState = new BulletAppState();
        bulletAppState.setDebugEnabled(true);
        stateManager.attach(bulletAppState);

Then I import the car model and connect it to the nodes.

Spatial Car = assetManager.loadModel("Models/Car.j3o");
Node carNode = new Node();
rootNode.attachChild(carNode);
carNode.attachChild(Car);

Then I compute the collision shape volume for my car.

        BoundingBox boundingBox = (BoundingBox) carNode.getWorldBound();
        float width = boundingBox.getXExtent();
        float length = boundingBox.getYExtent();
        CapsuleCollisionShape capsuleCollisionShape = new CapsuleCollisionShape(length, width, 2);

Then I create the control for the car and attach it to the carNode.

CharacterControl carControl = new CharacterControl(capsuleCollisionShape, 1f); // 1f > 0 mass
carNode.addControl(carControl);

Then I use bullet appstate to say that the physics should take account to the control for the car.

bulletAppState.getPhysicsSpace().add(carControl);

Also I need a floor for the car to stand on too.

         // Load scene and control
        Spatial scene = assetManager.loadModel("Scenes/carScene.j3o");
        rootNode.attachChild(scene);
        Spatial floor = rootNode.getChild("floor");
        bulletAppState.getPhysicsSpace().add(floor.getControl(RigidBodyControl.class));

So the result was that the car is flying on the collision shape round thing.
Markering_017

Then I was because the center of the car was placed under the car in Blender(first picture). Then I was thinking “Why not have a transparent rectangular box over the car and then set the collision shape over that box and then connect the car to that box?”.

So I created a invisible box and imported to JME and set the material Materials/Geom/SimpleGeom.j3m I also lower the box a little bit so the center would be in the middle of the box.

Markering_018

Then I import it that box and set the nodes.

Spatial Block = assetManager.loadModel("Models/Block.j3o"); // Transperency block
Node blockNode = new Node();

Lifting the block up and attach it.
blockNode.setLocalTranslation(0, 2.60319f, 0);
blockNode.attachChild(Block);

Create the collision shape and physics for that box.

BoundingBox boundingBox = (BoundingBox) blockNode.getWorldBound();
        float width = boundingBox.getXExtent();
        float length = boundingBox.getYExtent();
        CapsuleCollisionShape capsuleCollisionShape = new CapsuleCollisionShape(length, width, 2);
        CharacterControl carControl = new CharacterControl(capsuleCollisionShape, 1f); // 1f > 0 mass
        blockNode.addControl(carControl);
        bulletAppState.getPhysicsSpace().add(carControl);

Then connect blockNode to carNode.
carNode.attachChild(blockNode);

And the result is no car available inside this collision shape but the good thing is that the collision shape is not cutting in the floor.

Markering_020

How can I attach the car inside this box? I have some kinda solve this problem by moving the car center in JME a little bit lower.

Markering_021

Instead of this height.

Markering_022

This gave me the result, but I don’t really like to do this. I pretty sure that I is a better way to move the collision shape and not the car.

Markering_023

I remove the grid.

Markering_024

Looks good. Not sure if this is the correct way to do this.

First: Do you really want to use a CharacterControl?

  1. If yes, use BetterCharacterControl, but then you have the “Shooter Walking” Style, which might not be like driving, actually the car could turn while standing.
  2. If no, look into https://wiki.jmonkeyengine.org/jme3/advanced/vehicles.html

Note: You would not need to generate any collision shape, BetterCharacterControl has it’s own Constructor where you pass the height and width, but the RigidBodyControl itself will generate a different, non-capsule shape.

Also in case you didn’t you may want to use these tutorials https://wiki.jmonkeyengine.org/jme3.html#tutorials-for-beginners (they show BetterCharacterControl, e.g., but you already seem to have some basic knowledge)

Well! If BetterCharacterControl is better that CharacterControl, then I will use BetterCharacterControl.

Well, it meant to be better, some people have complaints about it and use the older charactercontrol, but I use BCC without major issues so far, it certainly is newer.

Note: For physicsSpace.add: You don’t need the control, it could also be a Spatial of any kind.
And also note that BCC also won’t give you driving physics

What do you mean with driving physics? I assume that I need to build an action listener to move the car in the update() method?

CharacterControls are meant for Humans as they walk, that means you can jump, rotate on place, have an acceleration and braking power of infinity, don’t slip.
You want a VehicleControl, as described in my point 2 link probably.

But yeah, you need an ActionListener to give input (in BCC it’s setWalkDirection). update() method is wrong, because an action listener get’s called when an action happened, which is “unrelated” to update

Can I still use my car instead of “boxes” as the example you gave me?

Isn’t it better to use the Scene Composer instead?

I mean. Instead to writing a collision box, set the box’s dimensions, initial position, place a control for the box and set its physical properties such as mass, gravity, damping and stiffness etc.

Isn’t it better to use the Scene Composer?

Markering_026

Markering_027

Markering_028

1 Like

If you feel that way inclined then yes :slight_smile: I am the type of guy that chooses a terminal over a GUI. Others prefer it the other way around.

1 Like

Can it be that the Scene Composer is less powerfull than writing pure java code? The should do the same job, right?

The reason why I prefer the Scene Composer is that I only need to click on the model to create the collision box, and it will not only give a box, it really fits the complete model.

Right now I have this code in simpleInitApp()

/ FlyCam
flyCam.setMoveSpeed(20);

    // Initizalize bulletAppState
    bulletAppState = new BulletAppState();
    bulletAppState.setDebugEnabled(false); // Show grid
    stateManager.attach(bulletAppState);
    
    // Load models
    Spatial carModel = assetManager.loadModel("Models/Car.j3o");

    rootNode.attachChild(carModel);
    Spatial car = rootNode.getChild("car");
    bulletAppState.getPhysicsSpace().add(car.getControl(RigidBodyControl.class));
    
    // Add floor
    Spatial scene = assetManager.loadModel("Scenes/newScene.j3o");
    rootNode.attachChild(scene);
    Spatial floor = rootNode.getChild("floor");
    bulletAppState.getPhysicsSpace().add(floor.getControl(RigidBodyControl.class));

I don’t understand why the car only sinks a little bit and not fall to the floor and bounce.

If I lower the damping, the car will go through the floor. Why isin’t the floor holding the car back?

In Code you can do everything what you can do in the SDK however you can’t do everything in the SDK which you can do in code, so yeah, you may hit limitations, but for that case not really.

That’s because it uses a HullCollisionShape or something, could be done in code, but doesn’t matter.

Try Physics Debug, probably the actual wheel suspension end point is just on the floor.

I guess this is when the damper is “overpowered”, which means it can’t hold the vehicles mass and breaks out, much like a broken damper in your car.

All the SDK does is write the code for you, really. It’s just a graphical way of carrying out certain tasks.

Ok. Thank you. Maybe I should focus to get comfortable to use pure code instead.

This example works really great.
https://wiki.jmonkeyengine.org/jme3/advanced/vehicles.html

But if I want to exchange

BoxCollisionShape box = new BoxCollisionShape(new Vector3f(1.2f, 0.5f, 2.4f));

So it would fit a complete model. What kind of method should I use then?

I tried to look for HullCollision Shape, but I don’t know how to use that.
https://javadoc.jmonkeyengine.org/com/jme3/bullet/collision/shapes/HullCollisionShape.html

Edit: Solve it by using

CollisionShape carShape = CollisionShapeFactory.createMeshShape(carModel);

I still have some issues. I try to get comfortable with just use pure code when it comes to logic and only Scene Composer when it comes to light and design.

I import my car and my scene and set controls to them both, but still the car just fall through the scene(floor) all the time.

   // FlyCam
    flyCam.setMoveSpeed(20);
    
    // Initizalize bulletAppState
    BulletAppState bulletAppState = new BulletAppState();
    bulletAppState.setDebugEnabled(true); // Show grid
    stateManager.attach(bulletAppState);
    
    // Load Car and create mesh
    Spatial car = assetManager.loadModel("Models/Car.j3o");
    CollisionShape carShape = CollisionShapeFactory.createMeshShape(car);
    
    // Set up a control object for the car
    VehicleControl carControl = new VehicleControl(carShape, 400f); // 400 mass
    float stiffness = 60.0f;//200=f1 car
    float compValue = .3f; //(should be lower than damp)
    float dampValue = .4f;
    carControl.setSuspensionCompression(compValue * 2.0f * FastMath.sqrt(stiffness));
    carControl.setSuspensionDamping(dampValue * 2.0f * FastMath.sqrt(stiffness));
    carControl.setSuspensionStiffness(stiffness);
    carControl.setMaxSuspensionForce(10000.0f);

    // Add control to car
    rootNode.addControl(carControl);
    bulletAppState.getPhysicsSpace().add(carControl);
    
    // Load scene and create mesh
    Spatial scene = assetManager.loadModel("Scenes/newScene.j3o");
    CollisionShape sceneShape = CollisionShapeFactory.createMeshShape(scene);
    
    // Set up a control object for the scene
    RigidBodyControl sceneControl = new RigidBodyControl(sceneShape, 0f); // Need to have 0 in mass or else floor will fall down
    sceneControl.setCollisionGroup(0);
    sceneControl.setFriction(stiffness);
    
    // Add control to scene
    scene.addControl(sceneControl);
    bulletAppState.getPhysicsSpace().add(sceneControl);
    rootNode.attachChild(scene);

Then the car fall through the scene.

Markering_031

But if I exchange this code

    Spatial car = assetManager.loadModel("Models/Car.j3o");
    CollisionShape carShape = CollisionShapeFactory.createMeshShape(car);

With this code

    CompoundCollisionShape carShape = new CompoundCollisionShape();
    BoxCollisionShape box = new BoxCollisionShape(new Vector3f(1.2f, 0.5f, 2.4f));
    carShape.addChildShape(box, new Vector3f(0, 1, 0));

The box will stay.

Markering_032

The car is just a collection of different primitives I have made in Blender.

I’m my experience with vehicles the suspension settings are the hardest to get right. They have a short area in which they will work as expected, and behave irrationally when not. Setting them too high will also make them sink.

Such situations as this require a debug GUI where you are able to tinker with the settings, really…

I will say this, though; the TestFancyCar and TestVehicle are different in that fancycar is more involved. Start with TestVehicle, then graduate toward the fancycar.

At some stage you are going to need to create such debug states… it is inevitable.

I’m not at my pc right now but tomorrow if you’re still stuck I will get you started with a debug state and you can work from there, and maybe brush over my notes on vehicles and give you some tips.

Knowledge is power <3

Hi.

Yes. Still stuck. The reason why I want to use the CollisionShape instead of BoxCollisionShape class is that I it more fitting my model.

I will answer in 9 hours.

Mesh shapes cannot be used for dynamic objects. If you want an actual dynamic rigid body then you have to create a hierarchy of approximate simple shapes or convex hull shapes or whatever.

Ok. That gives a basic understanding why.

But when I use add collision shape then? It gives a very smooth layer of mesh.

Markering_034

Edit:

When I use this code of line, it working.

CollisionShape carShape = CollisionShapeFactory.createDynamicMeshShape(car);

Markering_036