I Compared Jmonkeyengine 3.6 with Godot 4.2

You have a powerful machine than I have. Thanks by the way for motivating me. your test is also very nice and it is very helpful to me.

1 Like

almost 1000 Cubes with 50 to 60 FPS. Dropped to 13 FPS at 1060 boxes. Thanks for this test. Thanks for providing Windows Executeables.

1 Like

Can you provide Windows executables ? if possible !

1 Like

As a final experiment, I switched the textures back on, to see how much difference it would make. To my surprise, on my machine thereā€™s hardly any; but this is probably because the texture processing is being offloaded onto the GPU. However, I ran both tests again using watch -d -n 0.5 nvidia-smi to monitor GPU load and the difference between the two runs was small: with textures was 18% Ā± 2%; without was 17% Ā± 2%.

1 Like

I have absolutely no idea how to make a Windows executable, nor could I test one if I did!

Could somebody give me some pointers?

1 Like

Out of interest, Iā€™ve rerun my (untextured) test with vsync off. Initial framerate was over 3,000, but it dropped steadily. However, it didnā€™t fall below 60 until after 2,500 blocks, so actually very slightly better performance than with vsync on.

1 Like

yes, in Godot you have Jolt physics plugin. Its a lot of difference.

Its much different than Bullet ones. and muuch faster. (not made for simulation tho, just for game industry)

Bullet one comparison i would not see so much difference.

2 Likes

I also donā€™t know. by the way. thanks for your time.

Thank you v. much guys. One of you provided Windows & Linux Executables. I tested it and I got almost 3X more cubes at 60 FPS.
This is not a small community. Iā€™m amazed how fast you guys have helped in in just one week. less than one week I would say. Thank you JME community.

2 Likes

Yes sure, I make use of packr lib. You can see instructions here:

4 Likes

Thanks, working on it!

2 Likes

when done. upload files. I will test.

Test 2 link: https://youtu.be/Am35T_sk3vM

Thanks for posting the Test 2 video. It looks like graphics does not have much effect on the performance of your test.

Iā€™d like to understand why Jolt Physics is faster. Has anyone determined the reasons? Does it use better algorithms, and if so, which ones? Does it provide the same simulation quality?

I asked whether the source code for each test was available, which library was used, and what time step was used. Iā€™m still curious. In the absence of source code, I wonder what settings your app uses that might affect performance.

One concern I have is that Bullet with defaults settings will perform up to 4 simulation steps per frame. And it does so consistently under heavy load, trying to achieve real-time simulation with good accuracy. I suspect a lot of devs are unaware of this feature, and I assume other physics engines donā€™t do this. So when people compare Bullet with other physics engines under heavy load, Bullet is simulating 4x as many steps!

Since your test doesnā€™t care about real-time simulation or accuracy, you can configure your app (during initialization) to simulate only one step per frame:

physicsSpace.setMaxSubSteps(1);

Iā€™d be curious to know how that change affects the behavior of your test, if at all.

This presentation, by the designer of Jolt, gives a good explanation.

Note particularly that he isolates the phases which need to be done in a single thread, which implies (although Iā€™m not sure he says explicitly) that heā€™s multi-threading as much as he can ā€“ which makes a lot of sense on modern multi-core processors.

2 Likes

(yes, he does talk about multi-threading ā€“ from about 12:30 in).

This test looked implausible to me

I too, created my own test, but written in Java. Like the OPā€™s test, it creates a fountain of endless boxes. My version terminates automatically when FPS falls below 30. The final box count seems to be reproducible within about +/- 3%.

I ran some tests on my 2021-vintage gaming laptop. With a little tuning, I achieved 2790-2831 boxes at 30 FPS:

  • Linux Mint 21.3 edge (6.5.0-35 kernel)
  • OpenJDK 64-Bit Server VM Temurin-17.0.10+7
  • assertions disabled
  • JMonkeyEngine v3.6.1-stable
  • LWJGL v3.3.2
  • 640x480 window, VSync on
  • Minie v8.1.0 physics library
  • setMaxSubSteps(1)
  • BroadphaseType.AXIS_SWEEP_3

I report the measured range of boxes at 30 FPS (2790 to 2831) over 3 separate runs. 2800 boxes seems to me like a plausible baseline for physics performance (though of course I wish it were higher).

Using setMaxSubSteps(4) (the default setting) limits the number of boxes to 1714-1800, about a 37% reduction.

Using BroadphaseType.DBVT limits the number of boxes to 2568-2634, about a 7% reduction.

Using jme3-jbullet in place of Minie limits the number of boxes to 1397-1425, about a 45% reduction. (Tested with DBVT because AXIS_SWEEP_3 is broken in JBullet.)

Here is the source code:

package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.collision.shapes.BoxCollisionShape;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.font.BitmapText;
import com.jme3.material.Material;
import com.jme3.material.Materials;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
import java.util.logging.Level;
import java.util.logging.Logger;
import jme3utilities.Heart;

/**
 * The "fountain of boxes" stress test to estimate how many active dynamic rigid
 * bodies can be simulated while rendering 30 frames per second.
 *
 * @author Stephen Gold sgold@sonic.net
 */
public class Main extends SimpleApplication {

    private static BitmapText statusDisplay;
    private static Box smallBox;
    private static BoxCollisionShape smallBoxShape;
    private static float secondsSinceFpsUpdate = 0f;
    private static int framesSinceFpsUpdate = 0;
    private static int numBoxes = 1;
    private static Material solidGray;
    private static PhysicsSpace physicsSpace;

    public static void main(String[] args) {
        Main app = new Main();
        app.start();
    }

    @Override
    public void simpleInitApp() {
        if (Heart.areAssertionsEnabled()) {
            System.out.println("Warning: assertions are enabled.");
        }

        // Disable logging of rigid-body creation:
        Logger prbLogger
                = Logger.getLogger("com.jme3.bullet.objects.PhysicsRigidBody");
        prbLogger.setLevel(Level.SEVERE);

        // Pre-position the main camera and disable FlyByCamera:
        cam.setLocation(new Vector3f(0f, 110f, 210f));
        cam.setRotation(new Quaternion(0f, 0.9777315f, -0.20985f, 0.00143f));
        flyCam.setEnabled(false);

        // Attach a simple status display to the GUI node:
        statusDisplay = new BitmapText(loadGuiFont());
        statusDisplay.setLocalTranslation(0f, settings.getHeight(), 0f);
        guiNode.attachChild(statusDisplay);

        // Create a high-gravity PhysicsSpace:
        BulletAppState bulletAppState = new BulletAppState();
        bulletAppState.setBroadphaseType(
                PhysicsSpace.BroadphaseType.AXIS_SWEEP_3); // default = DBVT
        bulletAppState.setWorldMax(new Vector3f(100f, 50f, 100f));
        bulletAppState.setWorldMin(new Vector3f(-100f, -200f, -100f));
        stateManager.attach(bulletAppState);
        physicsSpace = bulletAppState.getPhysicsSpace();
        physicsSpace.setGravity(new Vector3f(0f, -99f, 0f));
        physicsSpace.setMaxSubSteps(1); // IMPORTANT! default = 4
        System.out.printf("maxSubSteps = %d, numSolvers = %d%n",
                physicsSpace.maxSubSteps(), physicsSpace.countSolvers());

        // Add a big blue box to serve as a platform:
        float size = 99f; // half extent in world units
        Box bigBox = new Box(size, size, size);
        BoxCollisionShape bigBoxShape
                = new BoxCollisionShape(new Vector3f(size, size, size));
        Material solidBlue = new Material(assetManager, Materials.UNSHADED);
        solidBlue.setColor("Color", ColorRGBA.Blue);

        RigidBodyControl staticRbc = new RigidBodyControl(bigBoxShape, 0f);
        staticRbc.setPhysicsSpace(physicsSpace);

        Geometry bbGeom = new Geometry("BigBox", bigBox);
        rootNode.attachChild(bbGeom);
        bbGeom.move(0f, -size, 0f);
        bbGeom.addControl(staticRbc);
        bbGeom.setMaterial(solidBlue);

        smallBox = new Box(1f, 1f, 1f);
        smallBoxShape = new BoxCollisionShape(new Vector3f(1f, 1f, 1f));

        solidGray = new Material(assetManager, Materials.UNSHADED);
        solidGray.setColor("Color", ColorRGBA.DarkGray);
    }

    @Override
    public void simpleUpdate(float tpf) {
        // Drop a small, gray, dynamic box from (0, 40, 0):
        RigidBodyControl dynamicRbc = new RigidBodyControl(smallBoxShape, 1f);
        dynamicRbc.setPhysicsSpace(physicsSpace);

        Geometry sbGeom = new Geometry("", smallBox);
        rootNode.attachChild(sbGeom);
        sbGeom.move(0f, 40f, 0f);
        sbGeom.addControl(dynamicRbc);
        sbGeom.setMaterial(solidGray);
        ++numBoxes;

        // Update the status:
        String statusText = "numBoxes = " + numBoxes;
        statusDisplay.setText(statusText);

        // Update the FPS statistics:
        secondsSinceFpsUpdate += tpf;
        ++framesSinceFpsUpdate;
        if (secondsSinceFpsUpdate >= 1f) {
            // Calculate frames per second over a 1-second interval:
            float fps = framesSinceFpsUpdate / secondsSinceFpsUpdate;
            if (fps < 30f) {
                // Terminate the application if FPS drops below 30:
                System.out.println(statusText);
                stop();
            }
            secondsSinceFpsUpdate = 0f;
            framesSinceFpsUpdate = 0;
        }
    }
}
11 Likes

It was an interesting test, so I did a test in my editor as well.

1 Like

Yes, the main reason is better collision-check tree managment as i know. It have recursive QuadTree as i remember and special optimizations for it.

Also it disable physics for CS faster in better way

And Also it can ā€œglueā€ CS together of elements to optimize even further

It was designed for Horizon Zero Dawn game, and later published openly by author i assume.

Its not physics for simulation, but made just for game purpose. (so its not simulation accurate)

You can read it here also:

4 Likes

Thanks

Continuing on from this discussion, thereā€™s Java bindings project wrapping Jolt

Iā€™m wondering whether it would be interesting and good learning to try to build bridge code to allow jMonkeyEngine projects to be switched relatively easily to use Jolt. Obviously this depends a lot on how similar the Jolt API is to the Bullet API, which I havenā€™t yet investigated.

There donā€™t seem to be many comparisons of the two out there on the Web yet, which seems to me a little surprising.

What I get from these discussions generally is:

Jolt uses multi-processor architectures much better than Bullet

In the Thrive discussion, Joltā€™s documentation seems to be considered good, whereas Bulletā€™s is considered harder to use.

Given that, these days, most of the machines people play games on are multi-core machines, Joltā€™s better ability to exploit multiple cores definitely seems a win.

1 Like