Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Visualization of mechanical CAD drawings using WebAssembly and WebGL - Rust Tokyo 2019

Visualization of mechanical CAD drawings using WebAssembly and WebGL - Rust Tokyo 2019

[email protected]

November 05, 2019
Tweet

Other Decks in Technology

Transcript

  1. Introduction • Aki, CTO @ CADDi Inc (キャディ株式会社) • Former

    embedded engineer • Following Rust since 0.9 • Eagerly awaiting 1.39 (ha)
  2. CAD in manufacturing 3D geometric kernels • Open CASCADE (C++,

    OSS) • Parasolid (C, proprietary) • ACIS (C++, proprietary) 2D drawing used in procurement • rust dxf (Rust, OSS) • libdxfrw (C++, OSS)
  3. WebAssembly sample ----- RUST ----- #[no_mangle] pub extern fn add(a:

    i32, b: i32) -> i32 { a+b } ----- WASM/WAT ----- (func $add (type 1) (param i32 i32) (result i32) local.get 0 local.get 1 i32.add)
  4. WebAssembly is typed ----- RUST ----- #[no_mangle] pub extern fn

    add(a: i32, b: i32) -> i32 { a+b } ----- WASM/WAT ----- (func $add (type 1) (param i32 i32) (result i32) local.get 0 local.get 1 i32.add)
  5. WebAssembly resembles a stack machine ----- RUST ----- #[no_mangle] pub

    extern fn add(a: i32, b: i32) -> i32 { a+b } ----- WASM/WAT ----- (func $add (type 1) (param i32 i32) (result i32) local.get 0 ← push arg 0 onto the stack local.get 1 i32.add)
  6. WebAssembly resembles a stack machine ----- RUST ----- #[no_mangle] pub

    extern fn add(a: i32, b: i32) -> i32 { a+b } ----- WASM/WAT ----- (func $add (type 1) (param i32 i32) (result i32) local.get 0 ← push arg 0 onto the stack local.get 1 ← push arg 1 onto the stack i32.add)
  7. WebAssembly resembles a stack machine ----- RUST ----- #[no_mangle] pub

    extern fn add(a: i32, b: i32) -> i32 { a+b } ----- WASM/WAT ----- (func $add (type 1) (param i32 i32) (result i32) local.get 0 ← push arg 0 onto the stack local.get 1 ← push arg 1 onto the stack i32.add) ← execute math operation
  8. WebAssembly resembles a stack machine ----- RUST ----- #[no_mangle] pub

    extern fn add(a: i32, b: i32) -> i32 { a+b } ----- WASM/WAT ----- (func $add (type 1) (param i32 i32) (result i32) local.get 0 ← push arg 0 onto the stack local.get 1 ← push arg 1 onto the stack i32.add) ← execute math operation
  9. Rust (.wasm) ⇔ JavaScript (.js) ----- Rust ----- pub fn

    rust_function () { unsafe { js_function (); } } ----- JavaScript ----- wasm.instance.exports.rust_function (); Calling Rust from JavaScript Calling JavaScript from Rust
  10. Call a Rust function from JavaScript ----- Rust ----- #[no_mangle]

    pub extern fn add(a: i32, b: i32) -> i32 { a + b } ----- SHELL ----- $ rustc -O --target=wasm32-unknown-unknown example.rs -o example.wasm ----- HTML ----- <script> WebAssembly .instantiateStreaming ( fetch('example.wasm' ), {}) .then(wasm => { var add_func = wasm.instance.exports.add; }); </script>
  11. Call a Rust function from JavaScript ----- Rust ----- #[no_mangle]

    pub extern fn add(a: i32, b: i32) -> i32 { a + b } ----- SHELL ----- $ rustc -O --target=wasm32-unknown-unknown example.rs -o example.wasm ----- HTML ----- <script> WebAssembly .instantiateStreaming ( fetch('example.wasm' ), {}) .then(wasm => { var add_func = wasm.instance.exports.add; }); </script> - WebAssembly has no main() - It behaves like a JS module/library
  12. Call a Rust function from JavaScript ----- Rust ----- #[no_mangle]

    pub extern fn add(a: i32, b: i32) -> i32 { a + b } ----- SHELL ----- $ rustc -O --target=wasm32-unknown-unknown example.rs -o example.wasm ----- HTML ----- <script> WebAssembly .instantiateStreaming ( fetch('example.wasm' ), {}) .then(wasm => { var add_func = wasm.instance.exports.add; var result = add_func(10, 20); console.log(result); }); </script>
  13. Call a Rust function from JavaScript ----- Rust ----- #[no_mangle]

    pub extern fn add(a: i32, b: i32) -> i32 { a + b } ----- SHELL ----- $ rustc -O --target=wasm32-unknown-unknown example.rs -o example.wasm ----- HTML ----- <script> WebAssembly .instantiateStreaming ( fetch('example.wasm' ), {}) .then(wasm => { var add_func = wasm.instance.exports.add; var result = add_func(10, 20); console.log(result); }); </script>
  14. Call a Rust function from JavaScript • Can be used

    to implement compute heavy code in Rust • Access those functions from JavaScript • eg: Image resizing algorithm for an image editing online tool
  15. Call a JavaScript function from Rust ----- Rust ----- #[link(wasm_import_module

    = "imports")] extern { fn cos(theta: f64) -> f64; } #[no_mangle] pub extern fn do_trig() { unsafe { cos(0.0); } } ----- HTML ----- <script> WebAssembly .instantiateStreaming ( fetch('example.wasm' ), { imports: { cos: (x) => Math.cos(x) } }) .then(wasm => { wasm.instance.exports.do_trig(); }); </script>
  16. Call a JavaScript function from Rust ----- Rust ----- #[link(wasm_import_module

    = "imports")] extern { fn cos(theta: f64) -> f64; } #[no_mangle] pub extern fn do_trig() { unsafe { cos(0.0); } } ----- HTML ----- <script> WebAssembly .instantiateStreaming ( fetch('example.wasm' ), { imports: { cos: (x) => Math.cos(x) } }) .then(wasm => { wasm.instance.exports.do_trig(); }); </script>
  17. Call a JavaScript function from Rust ----- Rust ----- #[link(wasm_import_module

    = "imports")] extern { fn cos(theta: f64) -> f64; } #[no_mangle] pub extern fn do_trig() { unsafe { cos(0.0); } } ----- HTML ----- <script> WebAssembly .instantiateStreaming ( fetch('example.wasm' ), { imports: { cos: (x) => Math.cos(x) } }) .then(wasm => { wasm.instance.exports.do_trig(); }); </script>
  18. Call a JavaScript function from Rust ----- Rust ----- #[link(wasm_import_module

    = "imports")] extern { fn cos(theta: f64) -> f64; } #[no_mangle] pub extern fn do_trig() { unsafe { cos(0.0); } } ----- HTML ----- <script> WebAssembly .instantiateStreaming ( fetch('example.wasm' ), { imports: { cos: (x) => Math.cos(x) } }) .then(wasm => { wasm.instance.exports.do_trig(); }); </script> - We probably want a debug print… - But WebAssembly has no I/O!
  19. Call a JavaScript function from Rust ----- RUST ----- #[link(wasm_import_module

    = "imports")] extern { fn console_log (x: f64); fn cos(theta: f64) -> f64; } #[no_mangle] pub extern fn do_trig() { unsafe { console_log (cos(0.0)); console_log (cos(3.14/4.0)); } } ----- HTML ----- <script> WebAssembly .instantiateStreaming ( fetch('example.wasm' ), { imports: { console_log : (x) => console.log(x), cos: (x) => Math.cos(x) } }) .then(wasm => { wasm.instance.exports.do_trig(); }); </script>
  20. Call a JavaScript function from Rust ----- RUST ----- #[link(wasm_import_module

    = "imports")] extern { fn console_log (x: f64); fn cos(theta: f64) -> f64; } #[no_mangle] pub extern fn do_trig() { unsafe { console_log (cos(0.0)); console_log (cos(3.14/4.0)); } } ----- HTML ----- <script> WebAssembly .instantiateStreaming ( fetch('example.wasm' ), { imports: { console_log : (x) => console.log(x), cos: (x) => Math.cos(x) } }) .then(wasm => { wasm.instance.exports.do_trig(); }); </script>
  21. Call a JavaScript function from Rust ----- RUST ----- #[link(wasm_import_module

    = "imports")] extern { fn console_log (x: f64); } #[no_mangle] pub extern fn do_trig() { ... } Imported function Exported function
  22. example.wasm WebAssembly Format (abridged) Import section Export section console_log() Code

    section local.get 0 local.get 1 i32.add #2 #0 do_trig() #3 Data section 0x67 0x65 0x74 0x20 0x74 0x68 0x69 0x73 0x3f 0x20 0x44 0x4d 0x20 0x6d 0x65 #0
  23. example.wasm WebAssembly Format (abridged) Import section Export section console_log() Code

    section local.get 0 local.get 1 i32.add #2 #0 do_trig() #3 Data section Memory section: declares linear memory regions 0x67 0x65 0x74 0x20 0x74 0x68 0x69 0x73 0x3f 0x20 0x44 0x4d 0x20 0x6d 0x65 #0
  24. What is WebGL? • JavaScript API for 2D and 3D

    rendering in the browser caniuse.com
  25. Software architecture Native Application Native CAD library (x86) Graphics stack

    (OpenGL) Web Application Native CAD library (wasm) Graphics stack (WebGL) vs
  26. Software architecture Native Application Native CAD library (x86) Graphics stack

    (OpenGL) Web Application Native CAD library (wasm) Graphics stack (WebGL) vs - kiss3d (graphics engine supporting WebGL) - rust-dxf (native DXF file parser)
  27. Current challenges • Text rendering for CJK languages (Font support,

    garbled text, etc) • Running native code expecting native syscalls and interfaces (Emscripten) • Rust graphics ecosystem is still young
  28. • wasm-bindgen • web-sys: DOM, WebGL, WebAudio, etc • js-sys:

    ECMAScript Rust and JavaScript coexist peacefully