Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up
for free
Visualization of mechanical CAD drawings using WebAssembly and WebGL
CADDi
November 05, 2019
Technology
0
1.8k
Visualization of mechanical CAD drawings using WebAssembly and WebGL
CADDi
November 05, 2019
Tweet
Share
More Decks by CADDi
See All by CADDi
caddi_eng
3
63k
caddi_eng
3
15k
caddi_eng
1
12k
caddi_eng
3
18k
caddi_eng
0
1.3k
caddi_eng
0
470
caddi_eng
9
81k
caddi_eng
3
19k
caddi_eng
1
30k
Other Decks in Technology
See All in Technology
prog893
0
150
kota2and3kan
2
360
you
0
150
tatsy
2
440
charity
12
14k
tutsunom
1
170
hponka
0
1.6k
miura55
0
170
1ftseabass
PRO
0
120
miu_crescent
0
390
oracle4engineer
9
6.2k
line_developers
PRO
2
190
Featured
See All Featured
lauravandoore
440
28k
smashingmag
232
18k
moore
125
21k
mojombo
359
62k
marcelosomers
221
15k
jakevdp
776
200k
davidbonilla
70
3.6k
tanoku
259
24k
jasonvnalue
81
8.2k
zakiwarfel
88
3.4k
brad_frost
157
6.5k
erikaheidi
14
4.5k
Transcript
Visualization of mechanical CAD drawings using WebAssembly and WebGL Rust
Tokyo 2019 @TaigaMerlin
Introduction • Aki, CTO @ CADDi Inc (キャディ株式会社) • Former
embedded engineer • Following Rust since 0.9 • Eagerly awaiting 1.39 (ha)
Agenda 1. State of CAD software 2. WebAssembly 3. WebGL
4. Results 5. Learnings
State of CAD software
[C]omputer [A]ided [D]esign grabcad.com/library/engine-v-twin
[C]omputer [A]ided [D]esign www.eventshigh.com
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)
Objective: 2D drawings in the browser
None
Binary code format that runs in a host environment
Not just for the web! (See WASI)
Host environment What is WebAssembly? C++, Rust, etc .wasm .js
.html .css
What is WebAssembly? caniuse.com
What is WebAssembly? caniuse.com
Who’s using WebAssembly? ...and many more!
Show me the Rust code!
WebAssembly sample ----- RUST ----- #[no_mangle] pub extern fn add(a:
i32, b: i32) -> i32 { a+b }
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)
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)
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)
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)
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
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
WebAssembly: numeric instructions
WebAssembly: trigonometry?
WebAssembly: trigonometry?
I want my transcendental functions!
I want my transcendental functions!
WebAssembly interfacing with host environment
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
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>
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
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>
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>
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
Where are my transcendental functions?
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>
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>
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>
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!
Let’s print the result! JavaScript Math.cos() Rust do_trig() cos()
Let’s print the result! JavaScript Math.cos() console.log() Rust do_trig() cos()
Let’s print the result! JavaScript Math.cos() console.log() Rust do_trig() cos()
console_log()
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>
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>
Yay transcendental functions!
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
example.wasm WebAssembly Format (abridged) Import section Export section console_log() #0
do_trig() #3
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
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
.wasm file WebAssembly DATA CODE LINEAR MEMORY PROCESSOR program memory
program instructions
WebAssembly has a Harvard-like architecture DATA PROCESSOR CODE I/O
None
3D Applications Raytracing experiments.withgoogle.com newnaw.com What can WebGL do?
What is WebGL? • JavaScript API for 2D and 3D
rendering in the browser caniuse.com
What is WebGL2? • WebGL ⇒ WebGL2 ⇒ WebGPU(?) caniuse.com
What is WebGL2? • WebGL ⇒ WebGL2 ⇒ WebGPU(?) caniuse.com
The difficulty with graphics APIs
Software architecture Native Application Native CAD library (x86) Graphics stack
(OpenGL)
Software architecture Native Application Native CAD library (x86) Graphics stack
(OpenGL) Web Application Native CAD library (wasm) Graphics stack (WebGL) vs
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)
Results
Results
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
Access all JavaScript APIs from WebAssembly
• wasm-bindgen • web-sys: DOM, WebGL, WebAudio, etc • js-sys:
ECMAScript Rust and JavaScript coexist peacefully
The future is bright!
Thank you! @TaigaMerlin