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.
almost 1000 Cubes with 50 to 60 FPS. Dropped to 13 FPS at 1060 boxes. Thanks for this test. Thanks for providing Windows Executeables.
Can you provide Windows executables ? if possible !
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%.
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?
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.
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.
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.
Yes sure, I make use of packr lib. You can see instructions here:
Thanks, working on it!
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.
(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;
}
}
}
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:
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.
- A comparison paper by the author of Jolt, which may not be unbiased but is informative;
- Thereās this Twitter post, which implies Jolt canāt (yet) do some of the things Bullet can;
- A discussion on the Thrive development forum;
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.