For those in the tank, wasm or WebAssembly is a low-level programming language for a virtual stack machine once designed as a portable compilation target for high-level languages ββsuch as C, C ++, C #, Rust, Go. Simply put, you can write high performance, compact, and portable code using wasm. Our Armory uses wasm too. Thanks to him, the engine can run in the browser and on other platforms using Krom.
Traits in C and Rust
Wasm is also used in traits or scripts. To do this, we will write a cube rotation script in C.
Cube rotation code
#define WASM_EXPORT __attribute__((visibility("default")))
// Declare Armory API used in this module
// github.com/armory3d/armory/blob/master/Sources/armory/trait/internal/wasm_api.h
void notify_on_update(void* f);
int get_object(const char* name);
void set_transform(int object, float x, float y, float z,
float rx, float ry, float rz, float sx, float sy, float sz);
WASM_EXPORT
void update() {
static float rot = 0.0f;
rot += 0.01f;
set_transform(get_object("Cube"), 0, 0, 0, 0, 0, rot, 1, 1, 1); // Set cube rotation
}
// Include main function, Armory calls it when trait is instantiated
WASM_EXPORT
int main() {
notify_on_update(update); // Register callback
return 0;
}
Compile the source code in C will help us webassembly.studio . We will move the resulting wasm file to the blend_location / Bundled folder.
Next, let's create a cube in blender, go to properties - Object - Armory Traits, create a new wasm traits, select our wasm file in modules . Press F5 and watch the cube rotate. An example can be downloaded from here .
The same thing but only in Rust.
Rust code
extern {
fn notify_on_update(f: extern fn() -> ()) -> ();
fn get_object(name: *const i8) -> i32;
fn set_transform(object: i32, x: f32, y: f32, z: f32, rx: f32, ry: f32, rz: f32, sx: f32, sy: f32, sz: f32) -> ();
}
#[no_mangle]
pub extern "C" fn update() -> () {
unsafe {
let name = std::ffi::CString::new("Cube").unwrap();
let object = get_object(name.as_ptr());
static mut rot: f32 = 0.1;
rot += 0.01;
set_transform(object, 0.0, 0.0, 0.0, 0.0, 0.0, rot, 1.0, 1.0, 1.0);
}
}
#[no_mangle]
pub extern "C" fn main() -> i32 {
unsafe {
notify_on_update(update);
}
return 0;
}
We compile and transfer to Bundled .
Calling wasm from Haxe
Wasm can be called directly from properties written in haxe. Let's start with a simple C function.
#define WASM_EXPORT __attribute__((visibility("default")))
WASM_EXPORT
float test() {
return 0.01f;
}
We compile the source to webassembly.studio . Place the resulting file in blend_location / Bundled.
Calling test () from Haxe.
package arm;
import iron.data.*
class MyTrait extends iron.Trait {
public function new() {
super();
notifyOnInit(init);
}
function init() {
Data.getBlob("main.wasm", function(b:kha.Blob) { // Load wasm blob
var wasm = Wasm.instance(b); // Create wasm module
var rot = 0.0;
notifyOnUpdate(function() {
rot += wasm.exports.test(); // Call function from wasm module!
object.transform.setRotation(0, 0, rot);
});
});
}
}
Examples can be downloaded from here .