Making vehicle larger causes suspension issues

I created a car (with the help of the jMonkeyEngine documentation) and used the fancy car they had. However, I noticed the car was very small, and I wanted it to be larger. So I scaled the car and the wheels by a factor of four. However, when I did that, the wheels started going through the ground and the car. I figured it might be a suspension problem but after trying different suspension values, nothing worked. What is the problem here?

Code (the part of the code responsible for making the car):

        public void addToSpace(Node rootNode, BulletAppState state){
           node = (Node) assetManager.loadModel(carFile);
           Geometry chassis = findGeometry(node, "Car");
           chassis.setLocalScale(4f);
        
           box = (BoundingBox) chassis.getModelBound();        
           CollisionShape hull = CollisionShapeFactory.createDynamicMeshShape(chassis);
           car = new VehicleControl(hull, mass);
           node.addControl(car);
        
           car.setSuspensionCompression(comp * 2.0f * FastMath.sqrt(stiffness));
           car.setSuspensionDamping(damp * 2.0f * FastMath.sqrt(stiffness));
           car.setSuspensionStiffness(stiffness);
           car.setMaxSuspensionForce(20000f);
        
           createWheel(node, "WheelFrontLeft");
           createWheel(node, "WheelFrontRight");
           createWheel(node, "WheelBackLeft");
           createWheel(node, "WheelBackRight");
        
           car.getWheel(2).setFrictionSlip(4);
           car.getWheel(3).setFrictionSlip(4);
        
           rootNode.attachChild(node);
           state.getPhysicsSpace().add(car);
    }
    
    private void createWheel(Node carNode, String wheel){
        Geometry w = findGeometry(carNode, wheel);
        w.center();
        w.setLocalScale(4f);
        box = (BoundingBox) w.getModelBound();
        float radius = box.getYExtent();
        float backWheel = (radius * 1.7f) - 1f;
        float frontWheel = (radius * 1.9f) - 1f;
        
        Vector3f wheelDir = new Vector3f(0, -1, 0);
        Vector3f wheelAx = new Vector3f(-1, 0, 0);
        
        if(wheel.equals("WheelFrontRight") || wheel.equals("WheelFrontLeft"))
            car.addWheel(w.getParent(), box.getCenter().add(0, -frontWheel, 0),
                    wheelDir, wheelAx, 0.2f, radius, true);
        else if(wheel.equals("WheelBackRight") || wheel.equals("WheelBackLeft"))
            car.addWheel(w.getParent(), box.getCenter().add(0, -backWheel, 0),
                    wheelDir, wheelAx, 0.2f, radius, false);            
    }

Which physics library are you using (Minie, jme3-bullet, or jme3-jbullet)?

What vehicle parameters were you using before you scaled up the model?

I am using jme3-bullet, I simple used setLocalScale on the geometry that creates the car, as well as on the wheels before they were added to the car. However, when I did that, the wheels went into the ground and through the car.

1 Like

Are you using the same ā€œFerrariā€ model thatā€™s used in TestFancyCar, or a different model?

Try to do the setLocalScale() on the whole car Node instead,

This node hereā€¦

Im using the same Ferrari model from TestFancyCar.

1 Like

I tried that, but the wheels did not update their position accordingly, just their size.

I attempted to re-create your app from the fragment provided. I turned on debug visualization using

bulletAppState.setDebugEnabled(true);

Doing so revealed that the wheels were positioned wrong. Get the wheel positions right before you start tuning the suspension.

Hereā€™s a suggestion for wheel positioning:

    final private static float modelScale = 4f;

    public void addToSpace(Node rootNode, BulletAppState state) {
        node = (Node) assetManager.loadModel(carFile);
        Geometry chassis = findGeometry(node, "Car");
        chassis.scale(modelScale);

        CollisionShape hull = CollisionShapeFactory.createDynamicMeshShape(chassis);
        car = new VehicleControl(hull, mass);
        node.addControl(car);

        car.setSuspensionCompression(comp * 2.0f * FastMath.sqrt(stiffness));
        car.setSuspensionDamping(damp * 2.0f * FastMath.sqrt(stiffness));
        car.setSuspensionStiffness(stiffness);
        car.setMaxSuspensionForce(20000f);

        createWheel(node, "WheelFrontLeft");
        createWheel(node, "WheelFrontRight");
        createWheel(node, "WheelBackLeft");
        createWheel(node, "WheelBackRight");

        car.getWheel(2).setFrictionSlip(4);
        car.getWheel(3).setFrictionSlip(4);

        rootNode.attachChild(node);
        state.getPhysicsSpace().add(car);
    }

    private void createWheel(Node carNode, String wheel) {
        Geometry w = findGeometry(carNode, wheel);
        w.center();
        Node wheelNode = w.getParent();
        wheelNode.scale(modelScale);
        float radius = 0.4727f * modelScale;
        Vector3f wheelDir = new Vector3f(0, -1, 0);
        Vector3f wheelAx = new Vector3f(-1, 0, 0);

        switch (wheel) {
            case "WheelFrontLeft":
                car.addWheel(wheelNode,
                        new Vector3f(-1.12f, 0.5754f, -1.69f).multLocal(modelScale),
                        wheelDir, wheelAx, 0.2f, radius, true);
                break;
            case "WheelFrontRight":
                car.addWheel(wheelNode,
                        new Vector3f(+1.12f, 0.5754f, -1.69f).multLocal(modelScale),
                        wheelDir, wheelAx, 0.2f, radius, true);
                break;
            case "WheelBackLeft":
                car.addWheel(wheelNode,
                        new Vector3f(-1.12f, 0.67f, +2.1f).multLocal(modelScale),
                        wheelDir, wheelAx, 0.2f, radius, false);
                break;
            case "WheelBackRight":
                car.addWheel(wheelNode,
                        new Vector3f(+1.12f, 0.67f, +2.1f).multLocal(modelScale),
                        wheelDir, wheelAx, 0.2f, radius, false);
                break;
            default:
                throw new IllegalArgumentException("wheel = " + wheel);
        }
    }

2 Likes