Visualization of mechanical CAD drawings using WebAssembly and WebGL

E55fbffb4afd0a84d36c945ed68d8c19?s=47 CADDi
November 05, 2019

Visualization of mechanical CAD drawings using WebAssembly and WebGL

E55fbffb4afd0a84d36c945ed68d8c19?s=128

CADDi

November 05, 2019
Tweet

Transcript

  1. Visualization of mechanical CAD drawings using WebAssembly and WebGL Rust

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

    embedded engineer • Following Rust since 0.9 • Eagerly awaiting 1.39 (ha)
  3. Agenda 1. State of CAD software 2. WebAssembly 3. WebGL

    4. Results 5. Learnings
  4. State of CAD software

  5. [C]omputer [A]ided [D]esign grabcad.com/library/engine-v-twin

  6. [C]omputer [A]ided [D]esign www.eventshigh.com

  7. 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)
  8. Objective: 2D drawings in the browser

  9. None
  10. Binary code format that runs in a host environment

  11. Not just for the web! (See WASI)

  12. Host environment What is WebAssembly? C++, Rust, etc .wasm .js

    .html .css
  13. What is WebAssembly? caniuse.com

  14. What is WebAssembly? caniuse.com

  15. Who’s using WebAssembly? ...and many more!

  16. Show me the Rust code!

  17. WebAssembly sample ----- RUST ----- #[no_mangle] pub extern fn add(a:

    i32, b: i32) -> i32 { a+b }
  18. 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)
  19. 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)
  20. 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)
  21. 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)
  22. 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
  23. 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
  24. WebAssembly: numeric instructions

  25. WebAssembly: trigonometry?

  26. WebAssembly: trigonometry?

  27. I want my transcendental functions!

  28. I want my transcendental functions!

  29. WebAssembly interfacing with host environment

  30. 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
  31. 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>
  32. 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
  33. 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>
  34. 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>
  35. 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
  36. Where are my transcendental functions?

  37. 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>
  38. 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>
  39. 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>
  40. 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!
  41. Let’s print the result! JavaScript Math.cos() Rust do_trig() cos()

  42. Let’s print the result! JavaScript Math.cos() console.log() Rust do_trig() cos()

  43. Let’s print the result! JavaScript Math.cos() console.log() Rust do_trig() cos()

    console_log()
  44. 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>
  45. 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>
  46. Yay transcendental functions!

  47. 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
  48. example.wasm WebAssembly Format (abridged) Import section Export section console_log() #0

    do_trig() #3
  49. 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
  50. 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
  51. .wasm file WebAssembly DATA CODE LINEAR MEMORY PROCESSOR program memory

    program instructions
  52. WebAssembly has a Harvard-like architecture DATA PROCESSOR CODE I/O

  53. None
  54. 3D Applications Raytracing experiments.withgoogle.com newnaw.com What can WebGL do?

  55. What is WebGL? • JavaScript API for 2D and 3D

    rendering in the browser caniuse.com
  56. What is WebGL2? • WebGL ⇒ WebGL2 ⇒ WebGPU(?) caniuse.com

  57. What is WebGL2? • WebGL ⇒ WebGL2 ⇒ WebGPU(?) caniuse.com

  58. The difficulty with graphics APIs

  59. Software architecture Native Application Native CAD library (x86) Graphics stack

    (OpenGL)
  60. Software architecture Native Application Native CAD library (x86) Graphics stack

    (OpenGL) Web Application Native CAD library (wasm) Graphics stack (WebGL) vs
  61. 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)
  62. Results

  63. Results

  64. 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
  65. Access all JavaScript APIs from WebAssembly

  66. • wasm-bindgen • web-sys: DOM, WebGL, WebAudio, etc • js-sys:

    ECMAScript Rust and JavaScript coexist peacefully
  67. The future is bright!

  68. Thank you! @TaigaMerlin