armory
armory copied to clipboard
[html5 (JS)] WASM Ammo.js + WebWorker
Hi all, there is a way to speed up Armory3D when exporting to html5.
The speed up will come from the physic module.
The physic module ammo.js can be used as a JS-compiled WASM module and sync physics info using a webWorker.
The module then run in its own thread and the 3D objects properties are then updated using the webWorker.
Meaning that for each frame there is no need to wait anymore for the physics to be calculated. (no slow FPS due to Physics)
in theory :
!
Examples :
with only Javascript Ammo.js
with WASM Ammo.js + WebWorker
-
To run the ammo.js module as a WASM module you need first to compile ammo.js to WASM. More info about compiling it yourself here : https://github.com/kripken/ammo.js/#building
Here is the compiled file : ammo.wasm.wasm
-
You first need to launch a webWorker using javascript that will load our module, something like :
var physicsWorker = null;
var nextPhysicsWorker = new Worker('worker.wasm.js');
if (physicsWorker) physicsWorker.terminate();
physicsWorker = nextPhysicsWorker;
nextPhysicsWorker = null;
if (!physicsWorker) physicsWorker = new Worker('worker.wasm.js');
-
Here is what a WebWorker will look like : worker.wasm.js We probably need to rewrite the "Bullet-interfacing code" for Armory.
-
Armory is loading the normal JS ammo.js inside the kha.js script by calling this function here : https://github.com/armory3d/armory/blob/58e4744aa10b197c34c5e929578fce4c76427003/Sources/armory/system/Starter.hx#L77
and it seems that Krom at line 80 is already using the WASM version of ammo.js - so we just need to rewrite this function for the html5 export.
- Finally : we need to sync 3D objects using the worker. We need to access and update all 3D objects with their transforms generated by the worker and get them update in the 3D canvas. The function will look like this :
physicsWorker.onmessage = function(event) {
var data = event.data;
if (data.objects.length != TotalNumberOfObjectsWithPhysics) return;
for (var i = 0; i < TotalNumberOfObjectsWithPhysics; i++) {
var physicsObject = data.objects[i];
renderObject.position[0] = physicsObject[0];
renderObject.position[1] = physicsObject[1];
renderObject.position[2] = physicsObject[2];
quaternion.x = physicsObject[3];
quaternion.y = physicsObject[4];
quaternion.z = physicsObject[5];
quaternion.w = physicsObject[6];
renderObject.rotation = quaternion.toEuler();
}
};
physicsWorker.postMessage(TotalNumberOfObjectsWithPhysics);
Also here is a 3D scene with cube and added physics that can be used as a benchmark. https://github.com/onelsonic/armory_tests/raw/master/mesh_generate.7z
Hey @onelsonic
This looks cool and so I did some digging. Although I am not adept with JS coding, I found this on Haxe Code Cookbook. I am willing to add this functionality but I might need to study some more about it.
I cleaned up my post above and updated the ammo.wasm.wasm with the same compiled file used by Krom. The inline web workers in Haxe looks promising.
I see that Kha has an HTML5 backend with workers which might work for this : https://github.com/Kode/Kha/tree/master/Backends/HTML5-Worker/kha
I've added add/remove cubes option to the mesh_generate
example for benchmarking.
https://disktree.net/app/armory_examples_browser/#examples-mesh_generate
Source in pending pr: https://github.com/armory3d/armory_examples/pull/28/files#diff-9451dba57586c2efa810d775e2c692f5ce2bd887fb2cdc1596f16643fb4fe2c8
Any idea what the % overhead is for moving all the transforms data back to be rendered? Does it scale linearly?