Merge pull request #133 from jdm/pf3-magicleap

Add Magic Leap demo
This commit is contained in:
Patrick Walton 2019-04-17 15:01:18 -07:00 committed by GitHub
commit fbc2a56b30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
58 changed files with 46640 additions and 0 deletions

12
.travis.yml Normal file
View File

@ -0,0 +1,12 @@
language: rust
addons:
apt:
packages:
- libegl1-mesa-dev
- libgtk-3-dev
- libsdl2-dev
script:
- cd demo/native
- cargo build
- cd ../magicleap
- cargo build

490
Cargo.lock generated
View File

@ -21,6 +21,24 @@ dependencies = [
"memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "andrew"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"line_drawing 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rusttype 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "android_glue"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ansi_term"
version = "0.11.0"
@ -29,6 +47,14 @@ dependencies = [
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "approx"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "area-lut"
version = "0.2.0"
@ -102,6 +128,11 @@ name = "bitflags"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "block"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "byteorder"
version = "1.3.1"
@ -122,6 +153,15 @@ name = "cfg-if"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cgl"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gleam 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "clap"
version = "2.32.0"
@ -144,6 +184,20 @@ dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cocoa"
version = "0.18.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"objc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "color_quant"
version = "1.0.1"
@ -161,6 +215,31 @@ dependencies = [
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "core-foundation"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "core-foundation-sys"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "core-graphics"
version = "0.17.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crc32fast"
version = "1.1.2"
@ -225,6 +304,19 @@ dependencies = [
"sdl2-sys 0.32.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "dlib"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "downcast-rs"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "egl"
version = "0.2.7"
@ -291,6 +383,19 @@ dependencies = [
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "fs_extra"
version = "1.1.0"
@ -342,6 +447,56 @@ dependencies = [
"xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "gl_generator"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"khronos_api 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "gl_generator"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"khronos_api 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "gleam"
version = "0.6.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gl_generator 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "glutin"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"android_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"cgl 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"cocoa 0.18.4 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
"gl_generator 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"objc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"shared_library 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-client 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"winit 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
"x11-dl 2.18.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "hashbrown"
version = "0.1.8"
@ -472,6 +627,11 @@ name = "khronos_api"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "khronos_api"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lazy_static"
version = "1.3.0"
@ -497,6 +657,32 @@ dependencies = [
"crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libloading"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "line_drawing"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lock_api"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "log"
version = "0.3.9"
@ -528,6 +714,14 @@ name = "lzw"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "malloc_buf"
version = "0.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "memchr"
version = "0.1.11"
@ -541,6 +735,15 @@ name = "memchr"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memmap"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "memoffset"
version = "0.2.1"
@ -554,6 +757,18 @@ dependencies = [
"gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "nix"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "nodrop"
version = "0.1.13"
@ -627,6 +842,59 @@ dependencies = [
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "objc"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ordered-float"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "osmesa-sys"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"shared_library 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "owning_ref"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parking_lot"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parking_lot_core"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pathfinder_android_demo"
version = "0.1.0"
@ -694,6 +962,27 @@ dependencies = [
"rustache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pathfinder_magicleap_demo"
version = "0.1.0"
dependencies = [
"egl 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"glutin 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"pathfinder_demo 0.1.0",
"pathfinder_geometry 0.3.0",
"pathfinder_gl 0.1.0",
"pathfinder_gpu 0.1.0",
"pathfinder_renderer 0.1.0",
"pathfinder_simd 0.3.0",
"pathfinder_svg 0.1.0",
"pathfinder_ui 0.1.0",
"rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
"usvg 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pathfinder_renderer"
version = "0.1.0"
@ -742,6 +1031,11 @@ dependencies = [
"serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "percent-encoding"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "phf"
version = "0.7.24"
@ -758,6 +1052,11 @@ dependencies = [
"siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pkg-config"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "png"
version = "0.12.0"
@ -1047,6 +1346,17 @@ dependencies = [
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rusttype"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"approx 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"stb_truetype 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ryu"
version = "0.2.7"
@ -1139,6 +1449,15 @@ dependencies = [
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "shared_library"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "simplecss"
version = "0.1.0"
@ -1159,6 +1478,35 @@ name = "smallvec"
version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "smithay-client-toolkit"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"andrew 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"dlib 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-client 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-commons 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-protocols 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "stable_deref_trait"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "stb_truetype"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "strsim"
version = "0.7.0"
@ -1325,6 +1673,60 @@ dependencies = [
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wayland-client"
version = "0.21.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"downcast-rs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-commons 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-scanner 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-sys 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wayland-commons"
version = "0.21.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-sys 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wayland-protocols"
version = "0.21.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-client 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-commons 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-scanner 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-sys 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wayland-scanner"
version = "0.21.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
"xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wayland-sys"
version = "0.21.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"dlib 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.2.8"
@ -1371,6 +1773,43 @@ dependencies = [
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winit"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"android_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"cocoa 0.18.4 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"objc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"smithay-client-toolkit 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"wayland-client 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"x11-dl 2.18.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "x11-dl"
version = "2.18.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "xdg"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "xml-rs"
version = "0.7.0"
@ -1379,6 +1818,11 @@ dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "xml-rs"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "xmlparser"
version = "0.8.1"
@ -1388,7 +1832,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c"
"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66"
"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5"
"checksum andrew 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9b7f09f89872c2b6b29e319377b1fbe91c6f5947df19a25596e121cf19a7b35e"
"checksum android_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum approx 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3"
"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71"
"checksum ascii 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a5fc969a8ce2c9c0c4b0429bb8431544f6658283c8326ba5ff8c762b75369335"
"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
@ -1397,19 +1844,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6"
"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643"
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
"checksum block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
"checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e"
"checksum cesu8 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
"checksum cgl 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "55e7ec0b74fe5897894cbc207092c577e87c52f8a59e8ca8d97ef37551f60a49"
"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
"checksum cocoa 0.18.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cf79daa4e11e5def06e55306aa3601b87de6b5149671529318da048f67cdd77b"
"checksum color_quant 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0dbbb57365263e881e805dc77d94697c9118fd94d8da011240555aa7b23445bd"
"checksum combine 3.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d2623b3542b48f4427e15ddd4995186decb594ebbd70271463886584b4a114b9"
"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d"
"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b"
"checksum core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)" = "56790968ab1c8a1202a102e6de05fc6e1ec87da99e4e93e9a7d13efbfc1e95a9"
"checksum crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e91d5240c6975ef33aeb5f148f35275c25eda8e8a5f95abe421978b05b8bf192"
"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
"checksum deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6abb26e16e8d419b5c78662aa9f82857c2386a073da266840e474d5055ec86"
"checksum dlib 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "77e51249a9d823a4cb79e3eca6dcd756153e8ed0157b6c04775d04bf1b13b76a"
"checksum downcast-rs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b92dfd5c2f75260cbf750572f95d387e7ca0ba5e3fbe9e1a33f23025be020f"
"checksum egl 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a373bc9844200b1ff15bd1b245931d1c20d09d06e4ec09f361171f29a4b0752d"
"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
"checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38"
@ -1418,12 +1873,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcb84c18ea5037a1c5a23039b4ff29403abce2e0d6b1daa11cf0bde2b30be15"
"checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33"
"checksum float-cmp 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "134a8fa843d80a51a5b77d36d42bc2def9edcb0262c914861d08129fd1926600"
"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
"checksum fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674"
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
"checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
"checksum gif 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4bca55ac1f213920ce3527ccd62386f1f15fa3f1714aeee1cf93f2c416903f"
"checksum gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1c73b90c285f02059b34a6c66bc645ba5faa18c0e3ab332e0725654fc71db441"
"checksum gl_generator 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0ffaf173cf76c73a73e080366bf556b4776ece104b06961766ff11449f38604"
"checksum gl_generator 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "39a23d5e872a275135d66895d954269cf5e8661d234eb1c2480f4ce0d586acbd"
"checksum gl_generator 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "75d69f914b49d9ff32fdf394cbd798f8c716d74fd19f9cc29da3e99797b2a78d"
"checksum gleam 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "39bb69499005e11b7b7cc0af38404a1bc0f53d954bffa8adcdb6e8d5b14f75d5"
"checksum glutin 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "535c6eda58adbb227604b2db10a022ffd6339d7ea3e970f338e7d98aeb24fcc3"
"checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da"
"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114"
"checksum image 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebdff791af04e30089bde8ad2a632b86af433b40c04db8d70ad4b21487db7a6a"
@ -1438,18 +1899,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum khronos 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c0711aaa80e6ba6eb1fa8978f1f46bfcb38ceb2f3f33f3736efbff39dac89f50"
"checksum khronos_api 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "037ab472c33f67b5fbd3e9163a2645319e5356fcd355efa6d4eb7fff4bbcb554"
"checksum khronos_api 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
"checksum libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122"
"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047"
"checksum libflate 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "54d1ddf9c52870243c5689d7638d888331c1116aa5b398f3ba1acfa7d8758ca1"
"checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2"
"checksum line_drawing 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5cc7ad3d82c845bdb5dde34ffdcc7a5fb4d2996e1e1ee0f19c33bc80e15196b9"
"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c"
"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
"checksum lyon_geom 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2b60eaa9061c87affcd671e88289ce6971324269ec6548b677e02624ef3ef63c"
"checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084"
"checksum malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39"
"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
"checksum nfd 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8e752e3c216bc8a491c5b59fa46da10f1379ae450b19ac688e07f4bb55042e98"
"checksum nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46f0f3210768d796e8fa79ec70ee6af172dacbe7147f5e69be5240a47778302b"
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
"checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e"
"checksum num-derive 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d9fe8fcafd1b86a37ce8a1cfa15ae504817e0c8c2e7ad42767371461ac1d316d"
@ -1459,8 +1927,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e96f040177bb3da242b5b1ecf3f54b5d5af3efbbfb18608977a5d2767b22f10"
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba"
"checksum objc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "31d20fd2b37e07cf5125be68357b588672e8cefe9a96f8c17a9d46053b3e590d"
"checksum ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "18869315e81473c951eb56ad5558bbc56978562d3ecfb87abb7a1e944cea4518"
"checksum osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88cfece6e95d2e717e0872a7f53a8684712ad13822a7979bc760b9c77ec0013b"
"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13"
"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337"
"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9"
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
"checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18"
"checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0"
"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
"checksum png 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f54b9600d584d3b8a739e1662a595fab051329eff43f20e7d8cc22872962145b"
"checksum png 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9adebf7fb91ccf5eac9da1a8e00e83cb8ae882c3e8d8e4ad59da73cb8c82a2c9"
"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915"
@ -1494,6 +1970,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619"
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
"checksum rusttype 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ce3926a2057b315b3e8bca6d1cec1e97f19436a8f9127621cd538cda9c96a38b"
"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
"checksum safe-transmute 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9604873ffe1980bc1f179103704a65c8aca141c248d9e52b7af95ff10578166e"
"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9"
@ -1507,10 +1984,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "9f301d728f2b94c9a7691c90f07b0b4e8a4517181d9461be94c04bddeb4bd850"
"checksum serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "beed18e6f5175aef3ba670e57c60ef3b1b74d250d962a26604bff4c80e970dd4"
"checksum serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "27dce848e7467aa0e2fcaf0a413641499c0b745452aaca1194d24dedde9e13c9"
"checksum shared_library 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5a9e7e0f2bfae24d8a5b5a66c5b257a83c7412304311512a0c054cd5e619da11"
"checksum simplecss 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "135685097a85a64067df36e28a243e94a94f76d829087ce0be34eeb014260c0e"
"checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac"
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be"
"checksum smithay-client-toolkit 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aa4899558362a65589b53313935099835acf999740915e134dff20cca7c6a28b"
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
"checksum stb_truetype 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "69b7df505db8e81d54ff8be4693421e5b543e08214bd8d99eb761fcb4d5668ba"
"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
"checksum svgdom 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a9b53b3ed152fc6b871f7232a8772c640567fd25d056941450637ecba32924d"
"checksum svgtypes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c43c25e6de7264024b5e351eb0c342039eb5acf51f2e9d0099bbd324b661453b"
@ -1532,6 +2013,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1"
"checksum wayland-client 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e77d1e6887f07ea2e5d79a3d7d03a875e62d3746334a909b5035d779d849a523"
"checksum wayland-commons 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)" = "dff69a5399ca212efa4966f3ee2a3773f19960d0fa329b9aca046a8508a0e09f"
"checksum wayland-protocols 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)" = "c9ccddf6a4407d982898e0f0a1172217843f3d40fe4272f828060b56a2d40d81"
"checksum wayland-scanner 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)" = "63bc5efa7dcdb8f04d2e5d1571c0d0577fc47076d133d68e056bdb299f1b60e2"
"checksum wayland-sys 0.21.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e76af81a601b84d400744f85f083381daa77ac01f6c8711e57e662dc3a35d69d"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
@ -1539,5 +2025,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba"
"checksum winit 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c57c15bd4c0ef18dff33e263e452abe32d00e2e05771cacaa410a14cc1c0776"
"checksum x11-dl 2.18.3 (registry+https://github.com/rust-lang/crates.io-index)" = "940586acb859ea05c53971ac231685799a7ec1dee66ac0bccc0e6ad96e06b4e3"
"checksum xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57"
"checksum xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c1cb601d29fe2c2ac60a2b2e5e293994d87a1f6fa9687a31a15270f909be9c2"
"checksum xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5"
"checksum xmlparser 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d78a7f29bb57edf63321d545d84f99360df71df36929a090bc067e1bcb65e34d"

View File

@ -2,6 +2,7 @@
members = [
"demo/android/rust",
"demo/common",
"demo/magicleap",
"demo/native",
"geometry",
"gl",

View File

@ -0,0 +1,3 @@
[target.aarch64-linux-android]
linker = "./fake-ld.sh"
ar = "aarch64-linux-android-ar"

1
demo/magicleap/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.out/

44
demo/magicleap/Cargo.toml Normal file
View File

@ -0,0 +1,44 @@
[package]
name = "pathfinder_magicleap_demo"
version = "0.1.0"
edition = "2018"
authors = ["Alan Jeffrey <ajeffrey@mozilla.com>"]
[dependencies]
gl = "0.6"
rayon = "1.0"
usvg = "0.4"
egl = "0.2"
log = "0.4"
smallvec = "0.6"
glutin = { version = "0.19", optional = true }
[lib]
crate-type = ["cdylib"]
[features]
mocked = ["glutin"]
[dependencies.pathfinder_demo]
path = "../common"
[dependencies.pathfinder_geometry]
path = "../../geometry"
[dependencies.pathfinder_gl]
path = "../../gl"
[dependencies.pathfinder_gpu]
path = "../../gpu"
[dependencies.pathfinder_renderer]
path = "../../renderer"
[dependencies.pathfinder_simd]
path = "../../simd"
[dependencies.pathfinder_svg]
path = "../../svg"
[dependencies.pathfinder_ui]
path = "../../ui"

15
demo/magicleap/Makefile Normal file
View File

@ -0,0 +1,15 @@
.PHONY: debug release install
debug:
cargo build --target aarch64-linux-android
$(MAGICLEAP_SDK)/mabu -t debug_device PathfinderDemo.package -s $(MLCERT)
release:
cargo build --release --target aarch64-linux-android
$(MAGICLEAP_SDK)/mabu -t release_device PathfinderDemo.package -s $(MLCERT)
install: .out/PathfinderDemo/PathfinderDemo.mpk
$(MAGICLEAP_SDK)/tools/mldb/mldb install -u .out/PathfinderDemo/PathfinderDemo.mpk
run:
${MAGICLEAP_SDK}/tools/mldb/mldb launch -w com.mozilla.pathfinder.demo

View File

@ -0,0 +1,19 @@
KIND = program
SRCS = src/main.cpp
LIBPATHS.debug = \
../../target/aarch64-linux-android/debug
LIBPATHS.release = \
../../target/aarch64-linux-android/release
USES = ml_sdk OpenGL stdc++
STLIBS = \
pathfinder_immersive_demo
SHLIBS = \
ml_privileges
DATAS = \
../../resources/** : resources/

View File

@ -0,0 +1,8 @@
USES = "lre/scenes"
REFS = PathfinderImmersiveDemo PathfinderLandscapeDemo
OPTIONS=package/debuggable/on
DATAS = \
../../target/aarch64-linux-android/release/*.so : bin/

View File

@ -0,0 +1,17 @@
KIND = program
SRCS = src/main.cpp
LIBPATHS.debug = \
../../target/aarch64-linux-android/debug
LIBPATHS.release = \
../../target/aarch64-linux-android/release
USES = ml_sdk OpenGL stdc++
SHLIBS = \
pathfinder_magicleap_demo \
ml_privileges
DATAS = \
../../resources/** : resources/

View File

@ -0,0 +1,19 @@
KIND = program
SRCS = src/landscape.cpp
LIBPATHS.debug = \
../../target/aarch64-linux-android/debug
LIBPATHS.release = \
../../target/aarch64-linux-android/release
INCS = \
src/ \
lre/code/inc/gen/
USES = \
lumin_runtime \
lre/code/srcs
SHLIBS = \
pathfinder_magicleap_demo

25
demo/magicleap/README.md Normal file
View File

@ -0,0 +1,25 @@
# Magic Leap demo
First, install v0.20.0 or later of the Magic Leap SDK. By default this is installed in `MagicLeap/mlsdk/<version>`, for example:
```
export MAGICLEAP_SDK=~/MagicLeap/mlsdk/v0.20.0
```
You will also need a signing certificate.
```
export MLCERT=~/MagicLeap/cert/mycert.cert
```
Now build the pathfinder demo library and `.mpk` archive:
```
cd demo/pathfinder
make release
```
The `.mpk` can be installed:
```
make install
```
and run:
```
make run
```

18
demo/magicleap/fake-ld.sh Executable file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env bash
# This shell script strips out the -landroid that is passed by default by rustc to
# the linker on aarch64-linux-android, and adds some entries to the ld search path.
set -o errexit
set -o nounset
set -o pipefail
TARGET=${TARGET:-"aarch64-linux-android"}
LD=${LD:-"${MAGICLEAP_SDK}/tools/toolchains/bin/${TARGET}-ld"}
LDFLAGS=${LDFLAGS:-"--sysroot=${MAGICLEAP_SDK}/lumin -L${MAGICLEAP_SDK}/lumin/usr/lib -L${MAGICLEAP_SDK}/tools/toolchains/lib/gcc/${TARGET}/4.9.x ${MAGICLEAP_SDK}/lumin/usr/lib/crtbegin_so.o"}
# Remove the -landroid flag, grr
ARGS=("$@")
ARGS=${ARGS[@]/-landroid}
${LD} ${LDFLAGS} ${ARGS}

12
demo/magicleap/lre/.gitignore vendored Normal file
View File

@ -0,0 +1,12 @@
.DS_Store
*.log
*.json.dirty
*.json.lock
*.pyc
*.sln
*.vcxproj*
pipeline/cache/intermediate/
.out/
.vscode/
.vs/

View File

@ -0,0 +1,13 @@
KIND = program
INCS = \
code/inc/ \
code/inc/gen/
SRCS = \
code/src/main.cpp \
code/src/PathfinderDemo.cpp
USES = \
lumin_runtime \
code/srcs

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="ASCII"?>
<mlproject:mlproject xmlns:mlproject="http://www.magicleap.com/uidesigner/mlproject" generated="true" srcGenVersion="1">
<designFile path="scenes/PathfinderDemo.design"/>
<pipelineDirectory path="pipeline"/>
<preferences key="srcgen.directories.incgen" value="inc/gen"/>
<preferences key="srcgen.directories.src" value="src"/>
<preferences key="srcgen.directories.srcgen" value="src/gen"/>
<preferences key="srcgen.directories.basedir" value="code"/>
<preferences key="srcgen.directories.inc" value="inc"/>
</mlproject:mlproject>

View File

@ -0,0 +1,3 @@
USES = "scenes" "pipeline/cache/AssetManifest"
REFS = PathfinderDemo

View File

@ -0,0 +1,99 @@
// %BANNER_BEGIN%
// ---------------------------------------------------------------------
// %COPYRIGHT_BEGIN%
//
// Copyright (c) 2018 Magic Leap, Inc. All Rights Reserved.
// Use of this file is governed by the Creator Agreement, located
// here: https://id.magicleap.com/creator-terms
//
// %COPYRIGHT_END%
// ---------------------------------------------------------------------
// %BANNER_END%
// %SRC_VERSION%: 1
#include <lumin/LandscapeApp.h>
#include <lumin/Prism.h>
#include <lumin/event/ServerEvent.h>
#include <SceneDescriptor.h>
#include <PrismSceneManager.h>
/**
* PathfinderDemo Landscape Application
*/
class PathfinderDemo : public lumin::LandscapeApp {
public:
/**
* Constructs the Landscape Application.
*/
PathfinderDemo();
/**
* Destroys the Landscape Application.
*/
virtual ~PathfinderDemo();
/**
* Disallows the copy constructor.
*/
PathfinderDemo(const PathfinderDemo&) = delete;
/**
* Disallows the move constructor.
*/
PathfinderDemo(PathfinderDemo&&) = delete;
/**
* Disallows the copy assignment operator.
*/
PathfinderDemo& operator=(const PathfinderDemo&) = delete;
/**
* Disallows the move assignment operator.
*/
PathfinderDemo& operator=(PathfinderDemo&&) = delete;
protected:
/**
* Initializes the Landscape Application.
* @return - 0 on success, error code on failure.
*/
int init() override;
/**
* Deinitializes the Landscape Application.
* @return - 0 on success, error code on failure.
*/
int deInit() override;
/**
* Returns the initial size of the Prism
* Used in createPrism().
*/
const glm::vec3 getInitialPrismSize() const;
/**
* Creates the prism, updates the private variable prism_ with the created prism.
*/
void createInitialPrism();
/**
* Initializes and creates the scene of all scenes marked as initially instanced
*/
void spawnInitialScenes();
/**
* Run application login
*/
virtual bool updateLoop(float fDelta) override;
/**
* Handle events from the server
*/
virtual bool eventListener(lumin::ServerEvent* event) override;
private:
lumin::Prism* prism_ = nullptr; // represents the bounded space where the App renders.
PrismSceneManager* prismSceneManager_ = nullptr;
};

View File

@ -0,0 +1,45 @@
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
//
// THE CONTENTS OF THIS FILE IS GENERATED BY CODE AND
// ANY MODIFICATIONS WILL BE OVERWRITTEN
//
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
// %BANNER_BEGIN%
// ---------------------------------------------------------------------
// %COPYRIGHT_BEGIN%
//
// Copyright (c) 2018 Magic Leap, Inc. All Rights Reserved.
// Use of this file is governed by the Creator Agreement, located
// here: https://id.magicleap.com/creator-terms
//
// %COPYRIGHT_END%
// ---------------------------------------------------------------------
// %BANNER_END%
// %SRC_VERSION%: 1
#pragma once
#include <SpawnedSceneBase.h>
#include <SpawnedSceneHandlers.h>
namespace scenes {
namespace PathfinderDemo {
namespace externalNodes {
}
struct SpawnedScene : public SpawnedSceneBase {
SpawnedScene(const SceneDescriptor& sceneDescriptor, lumin::Node* root);
~SpawnedScene();
};
SpawnedSceneBase* createSpawnedScene(const SceneDescriptor& sceneDescriptor, lumin::Node* root);
SpawnedSceneHandlers* createSpawnedSceneHandlers(SpawnedSceneBase& spawnedScene);
extern const SceneDescriptor descriptor;
}
}

View File

@ -0,0 +1,74 @@
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
//
// THE CONTENTS OF THIS FILE IS GENERATED BY CODE AND
// ANY MODIFICATIONS WILL BE OVERWRITTEN
//
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
// %BANNER_BEGIN%
// ---------------------------------------------------------------------
// %COPYRIGHT_BEGIN%
//
// Copyright (c) 2018 Magic Leap, Inc. All Rights Reserved.
// Use of this file is governed by the Creator Agreement, located
// here: https://id.magicleap.com/creator-terms
//
// %COPYRIGHT_END%
// ---------------------------------------------------------------------
// %BANNER_END%
// %SRC_VERSION%: 1
#pragma once
#include <lumin/Prism.h>
#include <lumin/node/Node.h>
#include <SceneDescriptor.h>
#include <SpawnedSceneBase.h>
#include <SpawnedSceneUserData.h>
#include <scenes.h>
class PrismSceneManager {
public:
typedef std::function<SpawnedSceneUserData*(SpawnedSceneBase&)> (*CreateSpawnedSceneUserData);
static void setUserDataCreator(const SceneDescriptor & sceneDescriptor, CreateSpawnedSceneUserData createSpawnedSceneUserData);
public:
PrismSceneManager(lumin::Prism* prism);
enum class SceneState {
Unloaded,
ResourceModelLoaded,
ResourceAndObjectModelLoaded,
};
void setSceneState(const SceneDescriptor & sceneDescriptor, SceneState sceneState);
SceneState getSceneState(const SceneDescriptor & sceneDescriptor, SceneState sceneState) const;
SpawnedSceneBase* spawnScene(const SceneDescriptor & sceneDescriptor);
lumin::Node* spawn(const SceneDescriptor & sceneDescriptor);
private:
typedef SpawnedSceneBase* (*CreateSpawnedScene)(const SceneDescriptor& sceneDescriptor, lumin::Node* root);
static const CreateSpawnedScene createSpawnedScene[scenes::numberOfExternalScenes];
typedef SpawnedSceneHandlers* (*CreateSpawnedSceneHandlers)(SpawnedSceneBase& spawnedScene);
static const CreateSpawnedSceneHandlers createSpawnedSceneHandlers[scenes::numberOfExternalScenes];
static CreateSpawnedSceneUserData createSpawnedSceneUserData[scenes::numberOfExternalScenes];
private:
lumin::Node* createNodeTree(const SceneDescriptor & sceneDescriptor);
private:
lumin::Prism* prism_;
SceneState sceneStates_[scenes::numberOfExternalScenes];
std::string objectModelNames_[scenes::numberOfExternalScenes];
};

View File

@ -0,0 +1,58 @@
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
//
// THE CONTENTS OF THIS FILE IS GENERATED BY CODE AND
// ANY MODIFICATIONS WILL BE OVERWRITTEN
//
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
// %BANNER_BEGIN%
// ---------------------------------------------------------------------
// %COPYRIGHT_BEGIN%
//
// Copyright (c) 2018 Magic Leap, Inc. All Rights Reserved.
// Use of this file is governed by the Creator Agreement, located
// here: https://id.magicleap.com/creator-terms
//
// %COPYRIGHT_END%
// ---------------------------------------------------------------------
// %BANNER_END%
// %SRC_VERSION%: 1
#pragma once
#include <string>
#include <map>
// data class
class SceneDescriptor {
public:
typedef std::map<std::string /* externalNodeName */, const std::string& /* externalNodeId */> ExternalNodeReferences;
SceneDescriptor(int index, const char* externalName, const char* id, const char* sceneGraphFilePath, const char* resourceModelFilePath, const ExternalNodeReferences& externalNodeReferences, bool initiallySpawned);
const std::string& getExternalName() const;
const std::string& getId() const;
const std::string& getSceneGraphPath() const;
const std::string& getResourceModelPath() const;
const ExternalNodeReferences & getExternalNodeReferences() const;
bool getInitiallySpawned() const;
private:
friend class PrismSceneManager;
int getIndex() const;
private:
int index_;
std::string externalName_;
std::string id_;
std::string sceneGraphPath_;
std::string resourceModelPath_;
const ExternalNodeReferences& externalNodeReferences_;
bool initiallySpawned_;
};
bool operator<(const SceneDescriptor& a, const SceneDescriptor& b);

View File

@ -0,0 +1,43 @@
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
//
// THE CONTENTS OF THIS FILE IS GENERATED BY CODE AND
// ANY MODIFICATIONS WILL BE OVERWRITTEN
//
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
// %BANNER_BEGIN%
// ---------------------------------------------------------------------
// %COPYRIGHT_BEGIN%
//
// Copyright (c) 2018 Magic Leap, Inc. All Rights Reserved.
// Use of this file is governed by the Creator Agreement, located
// here: https://id.magicleap.com/creator-terms
//
// %COPYRIGHT_END%
// ---------------------------------------------------------------------
// %BANNER_END%
// %SRC_VERSION%: 1
#pragma once
#include <lumin/node/Node.h>
class SceneDescriptor;
class SpawnedSceneHandlers;
struct SpawnedSceneUserData;
struct SpawnedSceneBase {
SpawnedSceneBase(const SceneDescriptor &sd, lumin::Node* rt);
virtual ~SpawnedSceneBase();
SpawnedSceneBase() = delete;
SpawnedSceneBase(const SpawnedSceneBase&) = delete;
SpawnedSceneBase(const SpawnedSceneBase&&) = delete;
const SceneDescriptor& sceneDescriptor;
lumin::Node* root = nullptr;
SpawnedSceneHandlers* handlers = nullptr;
SpawnedSceneUserData* userData = nullptr;
};

View File

@ -0,0 +1,31 @@
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
//
// THE CONTENTS OF THIS FILE IS GENERATED BY CODE AND
// ANY MODIFICATIONS WILL BE OVERWRITTEN
//
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
// %BANNER_BEGIN%
// ---------------------------------------------------------------------
// %COPYRIGHT_BEGIN%
//
// Copyright (c) 2018 Magic Leap, Inc. All Rights Reserved.
// Use of this file is governed by the Creator Agreement, located
// here: https://id.magicleap.com/creator-terms
//
// %COPYRIGHT_END%
// ---------------------------------------------------------------------
// %BANNER_END%
// %SRC_VERSION%: 1
#pragma once
struct SpawnedSceneBase;
class SpawnedSceneHandlers {
public:
SpawnedSceneHandlers(SpawnedSceneBase& ssb);
virtual ~SpawnedSceneHandlers();
};

View File

@ -0,0 +1,27 @@
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
//
// THE CONTENTS OF THIS FILE IS GENERATED BY CODE AND
// ANY MODIFICATIONS WILL BE OVERWRITTEN
//
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
// %BANNER_BEGIN%
// ---------------------------------------------------------------------
// %COPYRIGHT_BEGIN%
//
// Copyright (c) 2018 Magic Leap, Inc. All Rights Reserved.
// Use of this file is governed by the Creator Agreement, located
// here: https://id.magicleap.com/creator-terms
//
// %COPYRIGHT_END%
// ---------------------------------------------------------------------
// %BANNER_END%
// %SRC_VERSION%: 1
#pragma once
struct SpawnedSceneUserData {
virtual ~SpawnedSceneUserData();
};

View File

@ -0,0 +1,33 @@
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
//
// THE CONTENTS OF THIS FILE IS GENERATED BY CODE AND
// ANY MODIFICATIONS WILL BE OVERWRITTEN
//
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
// %BANNER_BEGIN%
// ---------------------------------------------------------------------
// %COPYRIGHT_BEGIN%
//
// Copyright (c) 2018 Magic Leap, Inc. All Rights Reserved.
// Use of this file is governed by the Creator Agreement, located
// here: https://id.magicleap.com/creator-terms
//
// %COPYRIGHT_END%
// ---------------------------------------------------------------------
// %BANNER_END%
// %SRC_VERSION%: 1
#pragma once
#include <SceneDescriptor.h>
#include <map>
namespace scenes {
const int numberOfExternalScenes = 1;
typedef std::map<std::string /* externalName */, const SceneDescriptor& /* sceneDescription */> SceneDescriptorReferences;
extern const SceneDescriptorReferences externalScenes;
}

View File

@ -0,0 +1,102 @@
// %BANNER_BEGIN%
// ---------------------------------------------------------------------
// %COPYRIGHT_BEGIN%
//
// Copyright (c) 2018 Magic Leap, Inc. All Rights Reserved.
// Use of this file is governed by the Creator Agreement, located
// here: https://id.magicleap.com/creator-terms
//
// %COPYRIGHT_END%
// ---------------------------------------------------------------------
// %BANNER_END%
// %SRC_VERSION%: 1
#include <PathfinderDemo.h>
#include <lumin/node/RootNode.h>
#include <lumin/ui/Cursor.h>
#include <ml_logging.h>
#include <scenes.h>
#include <PrismSceneManager.h>
PathfinderDemo::PathfinderDemo() {
ML_LOG(Debug, "PathfinderDemo Constructor.");
// Place your constructor implementation here.
}
PathfinderDemo::~PathfinderDemo() {
ML_LOG(Debug, "PathfinderDemo Destructor.");
// Place your destructor implementation here.
}
const glm::vec3 PathfinderDemo::getInitialPrismSize() const {
return glm::vec3(2.0f, 2.0f, 2.0f);
}
void PathfinderDemo::createInitialPrism() {
prism_ = requestNewPrism(getInitialPrismSize());
if (!prism_) {
ML_LOG(Error, "PathfinderDemo Error creating default prism.");
abort();
}
prismSceneManager_ = new PrismSceneManager(prism_);
}
int PathfinderDemo::init() {
ML_LOG(Debug, "PathfinderDemo Initializing.");
createInitialPrism();
lumin::ui::Cursor::SetScale(prism_, 0.03f);
spawnInitialScenes();
// Place your initialization here.
return 0;
}
int PathfinderDemo::deInit() {
ML_LOG(Debug, "PathfinderDemo Deinitializing.");
// Place your deinitialization here.
return 0;
}
void PathfinderDemo::spawnInitialScenes() {
// Iterate over all the exported scenes
for (auto& exportedSceneEntry : scenes::externalScenes ) {
// If this scene was marked to be instanced at app initialization, do it
const SceneDescriptor &sd = exportedSceneEntry.second;
if (sd.getInitiallySpawned()) {
lumin::Node* const spawnedRoot = prismSceneManager_->spawn(sd);
if (spawnedRoot) {
if (!prism_->getRootNode()->addChild(spawnedRoot)) {
ML_LOG(Error, "PathfinderDemo Failed to add spawnedRoot to the prism root node");
abort();
}
}
}
}
}
bool PathfinderDemo::updateLoop(float fDelta) {
// Place your update here.
// Return true for your app to continue running, false to terminate the app.
return true;
}
bool PathfinderDemo::eventListener(lumin::ServerEvent* event) {
// Place your event handling here.
// Return true if the event is consumed.
return false;
}

View File

@ -0,0 +1,63 @@
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
//
// THE CONTENTS OF THIS FILE IS GENERATED BY CODE AND
// ANY MODIFICATIONS WILL BE OVERWRITTEN
//
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
// %BANNER_BEGIN%
// ---------------------------------------------------------------------
// %COPYRIGHT_BEGIN%
//
// Copyright (c) 2018 Magic Leap, Inc. All Rights Reserved.
// Use of this file is governed by the Creator Agreement, located
// here: https://id.magicleap.com/creator-terms
//
// %COPYRIGHT_END%
// ---------------------------------------------------------------------
// %BANNER_END%
// %SRC_VERSION%: 1
#include <SceneDescriptor.h>
#include <SpawnedSceneBase.h>
#include <PathfinderDemo/PathfinderDemo.h>
namespace scenes {
namespace PathfinderDemo {
SpawnedScene::SpawnedScene(const SceneDescriptor& sceneDescriptor, lumin::Node* root)
: SpawnedSceneBase(sceneDescriptor, root) {
}
SpawnedScene::~SpawnedScene() {
}
SpawnedSceneBase* createSpawnedScene(const SceneDescriptor& sceneDescriptor, lumin::Node* root) {
using namespace externalNodes;
SpawnedScene* spawnedScene = new SpawnedScene(sceneDescriptor, root);
return spawnedScene;
}
class Handlers : public SpawnedSceneHandlers
{
public:
Handlers(SpawnedScene& ss);
private:
};
Handlers::Handlers(SpawnedScene& ss)
: SpawnedSceneHandlers(ss)
{
}
SpawnedSceneHandlers* createSpawnedSceneHandlers(SpawnedSceneBase& ssb) {
return new Handlers(static_cast<SpawnedScene&>(ssb));
}
}
}

View File

@ -0,0 +1,124 @@
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
//
// THE CONTENTS OF THIS FILE IS GENERATED BY CODE AND
// ANY MODIFICATIONS WILL BE OVERWRITTEN
//
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
// %BANNER_BEGIN%
// ---------------------------------------------------------------------
// %COPYRIGHT_BEGIN%
//
// Copyright (c) 2018 Magic Leap, Inc. All Rights Reserved.
// Use of this file is governed by the Creator Agreement, located
// here: https://id.magicleap.com/creator-terms
//
// %COPYRIGHT_END%
// ---------------------------------------------------------------------
// %BANNER_END%
// %SRC_VERSION%: 1
#include <PrismSceneManager.h>
#include <ml_logging.h>
PrismSceneManager::CreateSpawnedSceneUserData PrismSceneManager::createSpawnedSceneUserData[scenes::numberOfExternalScenes];
PrismSceneManager::PrismSceneManager(lumin::Prism* prism)
: prism_(prism) {
if (!prism_) {
ML_LOG(Error, "PrismSceneManager nullptr prism");
abort();
}
for (int i = 0; i < sizeof(sceneStates_)/sizeof(sceneStates_[0]); ++i) {
sceneStates_[i] = SceneState::Unloaded;
}
}
void PrismSceneManager::setSceneState(const SceneDescriptor & sceneDescriptor, SceneState newState) {
const int sceneIndex = sceneDescriptor.getIndex();
SceneState& sceneState = sceneStates_[sceneIndex];
std::string& objectModelName = objectModelNames_[sceneIndex];
if (sceneState == SceneState::Unloaded && (newState == SceneState::ResourceModelLoaded || newState == SceneState::ResourceAndObjectModelLoaded)) {
if (!prism_->loadResourceModel(sceneDescriptor.getResourceModelPath())) {
ML_LOG(Error, "PrismSceneManager failed to load resource model");
abort();
}
sceneState = SceneState::ResourceModelLoaded;
}
if (sceneState == SceneState::ResourceModelLoaded && newState == SceneState::ResourceAndObjectModelLoaded) {
std::string& objectModelName = objectModelNames_[sceneIndex];
if (!prism_->loadObjectModel(sceneDescriptor.getSceneGraphPath(), objectModelName)) {
ML_LOG(Error, "PrismSceneManager failed to load object model");
abort();
}
sceneState = SceneState::ResourceAndObjectModelLoaded;
}
if (sceneState == SceneState::ResourceAndObjectModelLoaded && (newState == SceneState::ResourceModelLoaded || newState == SceneState::Unloaded)) {
if (!prism_->unloadObjectModel(objectModelName)) {
ML_LOG(Error, "PrismSceneManager failed to unload object model");
abort();
}
sceneState = SceneState::ResourceModelLoaded;
objectModelName.clear();
}
// Currently there is no effective way to unload the resource model
}
SpawnedSceneBase* PrismSceneManager::spawnScene(const SceneDescriptor & sceneDescriptor) {
lumin::Node* root = createNodeTree(sceneDescriptor);
if (!root) {
return nullptr;
}
const int index = sceneDescriptor.getIndex();
CreateSpawnedScene css = createSpawnedScene[index];
SpawnedSceneBase* const spawnedScene = (*css)(sceneDescriptor, root);
CreateSpawnedSceneHandlers ch = createSpawnedSceneHandlers[index];
SpawnedSceneHandlers* const handlers = (*ch)(*spawnedScene);
spawnedScene->handlers = handlers;
CreateSpawnedSceneUserData cssud = createSpawnedSceneUserData[sceneDescriptor.getIndex()];
if (cssud) {
spawnedScene->userData = (*cssud)(*spawnedScene);
}
return spawnedScene;
}
lumin::Node* PrismSceneManager::spawn(const SceneDescriptor & sceneDescriptor) {
SpawnedSceneBase* spawnedSceneBase = spawnScene(sceneDescriptor);
if (!spawnedSceneBase) {
return nullptr;
}
lumin::Node* root = spawnedSceneBase->root;
return root;
}
lumin::Node* PrismSceneManager::createNodeTree(const SceneDescriptor & sceneDescriptor) {
setSceneState(sceneDescriptor, SceneState::ResourceAndObjectModelLoaded);
const int sceneIndex = sceneDescriptor.getIndex();
std::string& objectModelName = objectModelNames_[sceneIndex];
lumin::Node* root = prism_->createAll(objectModelName);
if (!root) {
ML_LOG(Error, "PrismSceneManager failed to create the scene. Is the scene empty?");
return nullptr;
}
return root;
}
void PrismSceneManager::setUserDataCreator(const SceneDescriptor & sceneDescriptor, CreateSpawnedSceneUserData cssud) {
createSpawnedSceneUserData[sceneDescriptor.getIndex()] = cssud ;
}

View File

@ -0,0 +1,66 @@
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
//
// THE CONTENTS OF THIS FILE IS GENERATED BY CODE AND
// ANY MODIFICATIONS WILL BE OVERWRITTEN
//
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
// %BANNER_BEGIN%
// ---------------------------------------------------------------------
// %COPYRIGHT_BEGIN%
//
// Copyright (c) 2018 Magic Leap, Inc. All Rights Reserved.
// Use of this file is governed by the Creator Agreement, located
// here: https://id.magicleap.com/creator-terms
//
// %COPYRIGHT_END%
// ---------------------------------------------------------------------
// %BANNER_END%
// %SRC_VERSION%: 1
#include <SceneDescriptor.h>
SceneDescriptor::SceneDescriptor(int index, const char * externalName, const char * id, const char * sceneGraphPath, const char * resourceModelPath, const ExternalNodeReferences& externalNodeReferences, bool initiallySpawned)
:
index_(index),
externalName_(externalName),
id_(id),
sceneGraphPath_(sceneGraphPath),
resourceModelPath_(resourceModelPath),
externalNodeReferences_(externalNodeReferences),
initiallySpawned_(initiallySpawned) {
}
int SceneDescriptor::getIndex() const {
return index_;
}
const std::string & SceneDescriptor::getExternalName() const {
return externalName_;
}
const std::string & SceneDescriptor::getId() const {
return id_;
}
const std::string & SceneDescriptor::getSceneGraphPath() const {
return sceneGraphPath_;
}
const std::string & SceneDescriptor::getResourceModelPath() const {
return resourceModelPath_;
}
const SceneDescriptor::ExternalNodeReferences & SceneDescriptor::getExternalNodeReferences() const {
return externalNodeReferences_;
}
bool SceneDescriptor::getInitiallySpawned() const {
return initiallySpawned_;
}
bool operator<(const SceneDescriptor& a, const SceneDescriptor& b) {
return a.getExternalName() < b.getExternalName();
}

View File

@ -0,0 +1,35 @@
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
//
// THE CONTENTS OF THIS FILE IS GENERATED BY CODE AND
// ANY MODIFICATIONS WILL BE OVERWRITTEN
//
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
// %BANNER_BEGIN%
// ---------------------------------------------------------------------
// %COPYRIGHT_BEGIN%
//
// Copyright (c) 2018 Magic Leap, Inc. All Rights Reserved.
// Use of this file is governed by the Creator Agreement, located
// here: https://id.magicleap.com/creator-terms
//
// %COPYRIGHT_END%
// ---------------------------------------------------------------------
// %BANNER_END%
// %SRC_VERSION%: 1
#include <SpawnedSceneBase.h>
#include <SpawnedSceneHandlers.h>
#include <SpawnedSceneUserData.h>
SpawnedSceneBase::SpawnedSceneBase(const SceneDescriptor &sd, lumin::Node* rt)
: sceneDescriptor(sd),
root(rt) {
}
SpawnedSceneBase::~SpawnedSceneBase() {
delete handlers;
delete userData;
}

View File

@ -0,0 +1,29 @@
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
//
// THE CONTENTS OF THIS FILE IS GENERATED BY CODE AND
// ANY MODIFICATIONS WILL BE OVERWRITTEN
//
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
// %BANNER_BEGIN%
// ---------------------------------------------------------------------
// %COPYRIGHT_BEGIN%
//
// Copyright (c) 2018 Magic Leap, Inc. All Rights Reserved.
// Use of this file is governed by the Creator Agreement, located
// here: https://id.magicleap.com/creator-terms
//
// %COPYRIGHT_END%
// ---------------------------------------------------------------------
// %BANNER_END%
// %SRC_VERSION%: 1
#include <SpawnedSceneHandlers.h>
SpawnedSceneHandlers::SpawnedSceneHandlers(SpawnedSceneBase& ssb) {
}
SpawnedSceneHandlers::~SpawnedSceneHandlers() {
}

View File

@ -0,0 +1,26 @@
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
//
// THE CONTENTS OF THIS FILE IS GENERATED BY CODE AND
// ANY MODIFICATIONS WILL BE OVERWRITTEN
//
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
// %BANNER_BEGIN%
// ---------------------------------------------------------------------
// %COPYRIGHT_BEGIN%
//
// Copyright (c) 2018 Magic Leap, Inc. All Rights Reserved.
// Use of this file is governed by the Creator Agreement, located
// here: https://id.magicleap.com/creator-terms
//
// %COPYRIGHT_END%
// ---------------------------------------------------------------------
// %BANNER_END%
// %SRC_VERSION%: 1
#include <SpawnedSceneUserData.h>
SpawnedSceneUserData::~SpawnedSceneUserData() {
}

View File

@ -0,0 +1,64 @@
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
//
// THE CONTENTS OF THIS FILE IS GENERATED BY CODE AND
// ANY MODIFICATIONS WILL BE OVERWRITTEN
//
// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING --
// %BANNER_BEGIN%
// ---------------------------------------------------------------------
// %COPYRIGHT_BEGIN%
//
// Copyright (c) 2018 Magic Leap, Inc. All Rights Reserved.
// Use of this file is governed by the Creator Agreement, located
// here: https://id.magicleap.com/creator-terms
//
// %COPYRIGHT_END%
// ---------------------------------------------------------------------
// %BANNER_END%
// %SRC_VERSION%: 1
#include <PrismSceneManager.h>
#include <scenes.h>
#include <PathfinderDemo/PathfinderDemo.h>
namespace scenes {
namespace PathfinderDemo {
namespace externalNodes {
}
const SceneDescriptor::ExternalNodeReferences externalNodesMap = {
};
const SceneDescriptor descriptor(
0,
"PathfinderDemo",
"root",
"/assets/scenes/PathfinderDemo.scene.xml",
"/assets/scenes/PathfinderDemo.scene.res.xml",
externalNodesMap,
true);
}
const SceneDescriptorReferences externalScenes = {
{PathfinderDemo::descriptor.getExternalName(), PathfinderDemo::descriptor}
};
struct VerifyNumberOfExternalScenes {
VerifyNumberOfExternalScenes() { assert(externalScenes.size() == numberOfExternalScenes); }
};
VerifyNumberOfExternalScenes verifyNumberOfExternalScenes;
}
const PrismSceneManager::CreateSpawnedScene PrismSceneManager::createSpawnedScene[scenes::numberOfExternalScenes] = {
::scenes::PathfinderDemo::createSpawnedScene
};
const PrismSceneManager::CreateSpawnedSceneHandlers PrismSceneManager::createSpawnedSceneHandlers[scenes::numberOfExternalScenes] = {
static_cast<CreateSpawnedSceneHandlers>(::scenes::PathfinderDemo::createSpawnedSceneHandlers)
};

View File

@ -0,0 +1,25 @@
// %BANNER_BEGIN%
// ---------------------------------------------------------------------
// %COPYRIGHT_BEGIN%
//
// Copyright (c) 2018 Magic Leap, Inc. All Rights Reserved.
// Use of this file is governed by the Creator Agreement, located
// here: https://id.magicleap.com/creator-terms
//
// %COPYRIGHT_END%
// ---------------------------------------------------------------------
// %BANNER_END%
// %SRC_VERSION%: 1
#include <PathfinderDemo.h>
#include <ml_logging.h>
int main(int argc, char **argv)
{
ML_LOG(Debug, "PathfinderDemo Starting.");
PathfinderDemo myApp;
return myApp.run();
}

View File

@ -0,0 +1,8 @@
SRCS = \
src/gen/scenes.cpp \
src/gen/PathfinderDemo/PathfinderDemo.cpp \
src/gen/PrismSceneManager.cpp \
src/gen/SceneDescriptor.cpp \
src/gen/SpawnedSceneBase.cpp \
src/gen/SpawnedSceneHandlers.cpp \
src/gen/SpawnedSceneUserData.cpp \

View File

@ -0,0 +1,19 @@
<manifest
xmlns:ml="magicleap"
ml:package="com.company.pathfinderdemo"
ml:version_code="1"
ml:version_name="1.0">
<application
ml:visible_name="PathfinderDemo"
ml:sdk_version="1.0">
<component
ml:name=".pathfinderdemo.universe"
ml:visible_name="PathfinderDemo"
ml:binary_name="bin/PathfinderDemo"
ml:type="Universe">
<icon
ml:model_folder="assets/icon/model"
ml:portal_folder="assets/icon/portal" />
</component>
</application>
</manifest>

View File

View File

@ -0,0 +1,47 @@
{
"intermediate-storage": {
"path": "cache",
"kind": "in-tree"
},
"project-schema-version": 4,
"types": {
"assets": [
"lap/types/asset/audio",
"lap/types/asset/material",
"lap/types/asset/model",
"lap/types/asset/outline-font",
"lap/types/asset/texture"
],
"files": [
"lap/types/file/bmp",
"lap/types/file/dds",
"lap/types/file/fbx",
"lap/types/file/files",
"lap/types/file/gltf",
"lap/types/file/jpg",
"lap/types/file/kmat",
"lap/types/file/ogg",
"lap/types/file/otf",
"lap/types/file/png",
"lap/types/file/tga",
"lap/types/file/tiff",
"lap/types/file/wav"
]
},
"checkpoint-hash": "c518bac956221c272b076912359b67d645f00f14a76f2f9cc3dee2f71cbe4aa1f702f8fd2d19a0b3b59af6ab227b83fedcbef788077d6757a9b5e691bd0f4398",
"templates": [
"lap/template/converted_texture_from_bmp",
"lap/template/converted_texture_from_tga",
"lap/template/converted_texture_from_tiff",
"lap/template/passthru_audio_from_ogg",
"lap/template/passthru_audio_from_wav",
"lap/template/passthru_material_from_kmat",
"lap/template/passthru_model_from_fbx",
"lap/template/passthru_model_from_gltf",
"lap/template/passthru_outline_font_from_otf",
"lap/template/passthru_texture_from_dds",
"lap/template/passthru_texture_from_jpg",
"lap/template/passthru_texture_from_png"
],
"nodes": {}
}

View File

@ -0,0 +1,3 @@
DATAS = \
scenes/PathfinderDemo.scene.res.xml : assets/scenes/PathfinderDemo.scene.res.xml \
scenes/PathfinderDemo.scene.xml : assets/scenes/PathfinderDemo.scene.xml

View File

@ -0,0 +1,177 @@
<?xml version="1.0" encoding="ASCII"?>
<design:rootNode xmlns:design="http://www.magicleap.com/uidesigner/rcp/document/design" name="root" nodeTypeId="lumin.root" modelId="lumin" version="1.11.1">
<property id="name" value="root"/>
<property id="sceneName" value="PathfinderDemo"/>
<node name="quad1" nodeTypeId="lumin.quad">
<property id="name" value="quad1"/>
<property id="position">
<property id="x" value="0.15"/>
<property id="y" value="-0.15"/>
<property id="z" value="-0.15"/>
</property>
<property id="rotation">
<property id="y" value="180.0"/>
</property>
<property id="scale"/>
<property id="size">
<property id="x" value="0.3"/>
<property id="y" value="0.3"/>
</property>
<property id="texCoords">
<property id="x">
<property id="y" value="1.0"/>
</property>
<property id="y">
<property id="x" value="1.0"/>
<property id="y" value="1.0"/>
</property>
<property id="z">
<property id="x" value="1.0"/>
</property>
<property id="w"/>
</property>
</node>
<node name="quad2" nodeTypeId="lumin.quad">
<property id="name" value="quad2"/>
<property id="position">
<property id="x" value="-0.15"/>
<property id="y" value="-0.15"/>
<property id="z" value="0.15"/>
</property>
<property id="rotation"/>
<property id="scale"/>
<property id="size">
<property id="x" value="0.3"/>
<property id="y" value="0.3"/>
</property>
<property id="texCoords">
<property id="x">
<property id="y" value="1.0"/>
</property>
<property id="y">
<property id="x" value="1.0"/>
<property id="y" value="1.0"/>
</property>
<property id="z">
<property id="x" value="1.0"/>
</property>
<property id="w"/>
</property>
</node>
<node name="quad3" nodeTypeId="lumin.quad">
<property id="name" value="quad3"/>
<property id="position">
<property id="x" value="0.15"/>
<property id="y" value="-0.15"/>
<property id="z" value="0.15"/>
</property>
<property id="rotation">
<property id="y" value="90.0"/>
</property>
<property id="scale"/>
<property id="size">
<property id="x" value="0.3"/>
<property id="y" value="0.3"/>
</property>
<property id="texCoords">
<property id="x">
<property id="y" value="1.0"/>
</property>
<property id="y">
<property id="x" value="1.0"/>
<property id="y" value="1.0"/>
</property>
<property id="z">
<property id="x" value="1.0"/>
</property>
<property id="w"/>
</property>
</node>
<node name="quad4" nodeTypeId="lumin.quad">
<property id="name" value="quad4"/>
<property id="position">
<property id="x" value="-0.15"/>
<property id="y" value="-0.15"/>
<property id="z" value="-0.15"/>
</property>
<property id="rotation">
<property id="y" value="-90.0"/>
</property>
<property id="scale"/>
<property id="size">
<property id="x" value="0.3"/>
<property id="y" value="0.3"/>
</property>
<property id="texCoords">
<property id="x">
<property id="y" value="1.0"/>
</property>
<property id="y">
<property id="x" value="1.0"/>
<property id="y" value="1.0"/>
</property>
<property id="z">
<property id="x" value="1.0"/>
</property>
<property id="w"/>
</property>
</node>
<node name="quad5" nodeTypeId="lumin.quad">
<property id="name" value="quad5"/>
<property id="position">
<property id="x" value="-0.15"/>
<property id="y" value="-0.15"/>
<property id="z" value="-0.15"/>
</property>
<property id="rotation">
<property id="x" value="90.0"/>
</property>
<property id="scale"/>
<property id="size">
<property id="x" value="0.3"/>
<property id="y" value="0.3"/>
</property>
<property id="texCoords">
<property id="x">
<property id="y" value="1.0"/>
</property>
<property id="y">
<property id="x" value="1.0"/>
<property id="y" value="1.0"/>
</property>
<property id="z">
<property id="x" value="1.0"/>
</property>
<property id="w"/>
</property>
</node>
<node name="quad6" nodeTypeId="lumin.quad">
<property id="name" value="quad6"/>
<property id="position">
<property id="x" value="-0.15"/>
<property id="y" value="0.15"/>
<property id="z" value="0.15"/>
</property>
<property id="rotation">
<property id="x" value="270.0"/>
</property>
<property id="scale"/>
<property id="size">
<property id="x" value="0.3"/>
<property id="y" value="0.3"/>
</property>
<property id="texCoords">
<property id="x">
<property id="y" value="1.0"/>
</property>
<property id="y">
<property id="x" value="1.0"/>
<property id="y" value="1.0"/>
</property>
<property id="z">
<property id="x" value="1.0"/>
</property>
<property id="w"/>
</property>
</node>
</design:rootNode>

View File

@ -0,0 +1 @@
<ResourceModel version="1"></ResourceModel>

View File

@ -0,0 +1,9 @@
<ObjectModel name="PathfinderDemo" version="1">
<TransformNode/>
<QuadNode castShadow="false" name="quad1" pos="0.15,-0.15,-0.15" receiveShadow="false" rot="-0,1,-0,-4.371139e-08" shader="MAX" size="0.300000, 0.300000"/>
<QuadNode castShadow="false" name="quad2" pos="-0.15,-0.15,0.15" receiveShadow="false" shader="MAX" size="0.300000, 0.300000"/>
<QuadNode castShadow="false" name="quad3" pos="0.15,-0.15,0.15" receiveShadow="false" rot="0,0.7071068,0,0.7071068" shader="MAX" size="0.300000, 0.300000"/>
<QuadNode castShadow="false" name="quad4" pos="-0.15,-0.15,-0.15" receiveShadow="false" rot="0,-0.7071068,0,0.7071068" shader="MAX" size="0.300000, 0.300000"/>
<QuadNode castShadow="false" name="quad5" pos="-0.15,-0.15,-0.15" receiveShadow="false" rot="0.7071068,0,0,0.7071068" shader="MAX" size="0.300000, 0.300000"/>
<QuadNode castShadow="false" name="quad6" pos="-0.15,0.15,0.15" receiveShadow="false" rot="0.7071068,0,-0,-0.7071068" shader="MAX" size="0.300000, 0.300000"/>
</ObjectModel>

View File

@ -0,0 +1,34 @@
<manifest
xmlns:ml="magicleap"
ml:package="com.mozilla.pathfinder.demo"
ml:version_code="1"
ml:version_name="1.0">
<application
ml:visible_name="Pathfinder Demo"
ml:sdk_version="0.20.0"
ml:min_api_level="4">
<uses-privilege ml:name="WorldReconstruction"/>
<uses-privilege ml:name="LowLatencyLightwear"/>
<uses-privilege ml:name="ControllerPose"/>
<component
ml:name=".universe"
ml:visible_name="PF Landscape Demo"
ml:binary_name="bin/PathfinderLandscapeDemo"
ml:type="Universe">
<icon
ml:model_folder="assets/icon/model"
ml:portal_folder="assets/icon/portal" />
</component>
<component
ml:name=".fullscreen"
ml:visible_name="PF Immersive Demo"
ml:binary_name="bin/PathfinderImmersiveDemo"
ml:type="Fullscreen">
<mime-type ml:name="image/svg"/>
<file-extension ml:name=".svg"/>
<icon
ml:model_folder="assets/icon/model"
ml:portal_folder="assets/icon/portal" />
</component>
</application>
</manifest>

293
demo/magicleap/src/c_api.rs Normal file
View File

@ -0,0 +1,293 @@
// pathfinder/demo/magicleap/src/c_api.rs
//
// Copyright © 2019 The Pathfinder Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Bindings to the C MagicLeap API
#![allow(dead_code)]
use gl::types::GLuint;
use std::error::Error;
use std::ffi::CStr;
use std::fmt;
#[cfg(not(feature = "mocked"))]
use std::os::raw::c_char;
use std::os::raw::c_void;
// Types from the MagicLeap C API
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct MLHandle(u64);
impl MLHandle {
pub fn as_gl_uint(self) -> GLuint {
self.0 as GLuint
}
}
impl<T> From<*mut T> for MLHandle {
fn from(ptr: *mut T) -> MLHandle {
MLHandle(ptr as u64)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct MLResult(u32);
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct MLGraphicsOptions {
pub graphics_flags: u32,
pub color_format: MLSurfaceFormat,
pub depth_format: MLSurfaceFormat,
}
impl Default for MLGraphicsOptions {
fn default() -> MLGraphicsOptions {
MLGraphicsOptions {
graphics_flags: 0,
color_format: MLSurfaceFormat::RGBA8UNormSRGB,
depth_format: MLSurfaceFormat::D32Float,
}
}
}
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct MLGraphicsRenderTargetsInfo {
pub min_clip: f32,
pub max_clip: f32,
pub num_virtual_cameras: u32,
pub buffers: [MLGraphicsRenderBufferInfo; ML_BUFFER_COUNT],
}
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct MLGraphicsRenderBufferInfo {
pub color: MLGraphicsRenderTarget,
pub depth: MLGraphicsRenderTarget,
}
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct MLGraphicsRenderTarget {
pub width: u32,
pub height: u32,
pub id: MLHandle,
pub format: MLSurfaceFormat,
}
#[derive(Clone, Copy, Debug)]
#[repr(u32)]
pub enum MLSurfaceFormat {
Unknown = 0,
RGBA8UNorm,
RGBA8UNormSRGB,
RGB10A2UNorm,
RGBA16Float,
D32Float,
D24NormS8,
D32FloatS8,
}
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct MLGraphicsVirtualCameraInfoArray {
pub num_virtual_cameras: u32,
pub color_id: MLHandle,
pub depth_id: MLHandle,
pub viewport: MLRectf,
pub virtual_cameras: [MLGraphicsVirtualCameraInfo; ML_VIRTUAL_CAMERA_COUNT],
}
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct MLGraphicsVirtualCameraInfo {
pub left_half_angle: f32,
pub right_half_angle: f32,
pub top_half_angle: f32,
pub bottom_half_angle: f32,
pub sync_object: MLHandle,
pub projection: MLMat4f,
pub transform: MLTransform,
pub virtual_camera_name: MLGraphicsVirtualCameraName,
}
#[derive(Clone, Copy, Debug)]
#[repr(i32)]
pub enum MLGraphicsVirtualCameraName {
Combined = -1,
Left = 0,
Right,
}
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct MLGraphicsFrameParams {
pub near_clip: f32,
pub far_clip: f32,
pub focus_distance: f32,
pub surface_scale: f32,
pub protected_surface: bool,
pub projection_type: MLGraphicsProjectionType,
}
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct MLSnapshotPtr(*mut c_void);
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct MLCoordinateFrameUID {
pub data: [u64; 2],
}
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct MLHeadTrackingStaticData {
pub coord_frame_head: MLCoordinateFrameUID,
}
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct MLGraphicsClipExtentsInfo {
pub virtual_camera_name: MLGraphicsVirtualCameraName,
pub projection: MLMat4f,
pub transform: MLTransform,
}
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct MLGraphicsClipExtentsInfoArray {
pub num_virtual_cameras: u32,
pub full_extents: MLGraphicsClipExtentsInfo,
pub virtual_camera_extents: [MLGraphicsClipExtentsInfo; ML_VIRTUAL_CAMERA_COUNT],
}
#[derive(Clone, Copy, Debug)]
#[repr(u32)]
pub enum MLGraphicsProjectionType {
SignedZ = 0,
ReversedInfiniteZ = 1,
UnsignedZ = 2,
}
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct MLTransform {
pub rotation: MLQuaternionf,
pub position: MLVec3f,
}
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct MLVec3f {
pub x: f32,
pub y: f32,
pub z: f32,
}
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct MLRectf {
pub x: f32,
pub y: f32,
pub w: f32,
pub h: f32,
}
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct MLQuaternionf {
pub x: f32,
pub y: f32,
pub z: f32,
pub w: f32,
}
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct MLMat4f {
pub matrix_colmajor: [f32; 16],
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum MLLogLevel {
Fatal = 0,
Error = 1,
Warning = 2,
Info = 3,
Debug = 4,
Verbose = 5,
}
// Constants from the MagicLeap C API
pub const ML_RESULT_OK: MLResult = MLResult(0);
pub const ML_RESULT_TIMEOUT: MLResult = MLResult(2);
pub const ML_RESULT_UNSPECIFIED_FAILURE: MLResult = MLResult(4);
pub const ML_HANDLE_INVALID: MLHandle = MLHandle(0xFFFFFFFFFFFFFFFF);
pub const ML_BUFFER_COUNT: usize = 3;
pub const ML_VIRTUAL_CAMERA_COUNT: usize = 2;
// ML error handling
impl fmt::Display for MLResult {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
let cmessage = unsafe { CStr::from_ptr(MLGetResultString(*self)) };
let message = cmessage.to_str().or(Err(fmt::Error))?;
formatter.write_str(message)
}
}
impl MLResult {
pub fn ok(self) -> Result<(), MLResult> {
if self == ML_RESULT_OK {
Ok(())
} else {
Err(self)
}
}
pub fn unwrap(self) {
self.ok().unwrap()
}
}
impl Error for MLResult {
}
// Functions from the MagicLeap C API
#[cfg(not(feature = "mocked"))]
extern "C" {
pub fn MLGraphicsCreateClientGL(options: *const MLGraphicsOptions, gl_context: MLHandle, graphics_client : &mut MLHandle) -> MLResult;
pub fn MLGraphicsDestroyClient(graphics_client: *mut MLHandle) -> MLResult;
pub fn MLHeadTrackingCreate(tracker: *mut MLHandle) -> MLResult;
pub fn MLHeadTrackingGetStaticData(head_tracker: MLHandle, data: *mut MLHeadTrackingStaticData) -> MLResult;
pub fn MLPerceptionGetSnapshot(snapshot: *mut MLSnapshotPtr) -> MLResult;
pub fn MLSnapshotGetTransform(snapshot: MLSnapshotPtr, id: *const MLCoordinateFrameUID, transform: *mut MLTransform) -> MLResult;
pub fn MLPerceptionReleaseSnapshot(snapshot: MLSnapshotPtr) -> MLResult;
pub fn MLLifecycleSetReadyIndication() -> MLResult;
pub fn MLGraphicsGetClipExtents(graphics_client: MLHandle, array: *mut MLGraphicsClipExtentsInfoArray) -> MLResult;
pub fn MLGraphicsGetRenderTargets(graphics_client: MLHandle, targets: *mut MLGraphicsRenderTargetsInfo) -> MLResult;
pub fn MLGraphicsInitFrameParams(params: *mut MLGraphicsFrameParams) -> MLResult;
pub fn MLGraphicsBeginFrame(graphics_client: MLHandle, params: *const MLGraphicsFrameParams, frame_handle: *mut MLHandle, virtual_camera_array: *mut MLGraphicsVirtualCameraInfoArray) -> MLResult;
pub fn MLGraphicsEndFrame(graphics_client: MLHandle, frame_handle: MLHandle) -> MLResult;
pub fn MLGraphicsSignalSyncObjectGL(graphics_client: MLHandle, sync_object: MLHandle) -> MLResult;
pub fn MLGetResultString(result_code: MLResult) -> *const c_char;
pub fn MLLoggingLogLevelIsEnabled(lvl: MLLogLevel) -> bool;
pub fn MLLoggingLog(lvl: MLLogLevel, tag: *const c_char, message: *const c_char);
}
#[cfg(feature = "mocked")]
pub use crate::mocked_c_api::*;

View File

@ -0,0 +1,46 @@
// pathfinder/demo/immersive/display.rs
//
// Copyright © 2019 The Pathfinder Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::error::Error;
use std::io;
use pathfinder_geometry::basic::point::Point2DI32;
use pathfinder_geometry::basic::rect::RectI32;
use pathfinder_geometry::basic::transform3d::Perspective;
use pathfinder_geometry::basic::transform3d::Transform3DF32;
use pathfinder_gl::GLVersion;
use pathfinder_gpu::resources::ResourceLoader;
pub trait Display: Sized {
type Error: DisplayError;
type Camera: DisplayCamera<Error = Self::Error>;
fn resource_loader(&self) -> &dyn ResourceLoader;
fn gl_version(&self) -> GLVersion;
fn make_current(&mut self) -> Result<(), Self::Error>;
fn running(&self) -> bool;
fn size(&self) -> Point2DI32;
fn begin_frame(&mut self) -> Result<&mut[Self::Camera], Self::Error>;
fn end_frame(&mut self) -> Result<(), Self::Error>;
}
pub trait DisplayCamera {
type Error: DisplayError;
fn bounds(&self) -> RectI32;
fn view(&self) -> Transform3DF32;
fn perspective(&self) -> Perspective;
fn make_current(&mut self) -> Result<(), Self::Error>;
}
pub trait DisplayError: Error + From<usvg::Error> + From<io::Error>{
}

View File

@ -0,0 +1,254 @@
// pathfinder/demo/immersive/glwindow.rs
//
// Copyright © 2019 The Pathfinder Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use gl;
use glutin::ContextBuilder;
use glutin::ContextError;
use glutin::CreationError;
use glutin::EventsLoop;
use glutin::Event;
use glutin::WindowEvent;
use glutin::GlContext;
use glutin::GlWindow;
use glutin::WindowBuilder;
use glutin::dpi::LogicalSize;
use crate::display::Display;
use crate::display::DisplayCamera;
use crate::display::DisplayError;
use pathfinder_geometry::basic::point::Point2DI32;
use pathfinder_geometry::basic::rect::RectI32;
use pathfinder_geometry::basic::transform3d::Transform3DF32;
use pathfinder_geometry::basic::transform3d::Perspective;
use pathfinder_gl::GLVersion;
use pathfinder_gpu::resources::FilesystemResourceLoader;
use pathfinder_gpu::resources::ResourceLoader;
use std::env;
use std::error::Error;
use std::fmt;
use std::f32::consts::FRAC_PI_4;
use std::io;
use std::rc::Rc;
use std::time::Instant;
use usvg;
pub struct GlWindowDisplay {
events_loop: EventsLoop,
gl_window: Rc<GlWindow>,
running: bool,
cameras: Vec<GlWindowCamera>,
resource_loader: FilesystemResourceLoader,
}
pub struct GlWindowCamera {
eye: Eye,
gl_window: Rc<GlWindow>,
start: Instant,
}
enum Eye {
Left,
Right,
}
#[derive(Debug)]
pub enum GlWindowError {
Creation(CreationError),
Context(ContextError),
SVG(usvg::Error),
IO(io::Error),
}
const DEFAULT_EYE_WIDTH: u32 = 1024;
const DEFAULT_EYE_HEIGHT: u32 = 768;
const CAMERA_DISTANCE: f32 = 3.0;
const NEAR_CLIP_PLANE: f32 = 0.01;
const FAR_CLIP_PLANE: f32 = 10.0;
impl Display for GlWindowDisplay {
type Error = GlWindowError;
type Camera = GlWindowCamera;
fn resource_loader(&self) -> &dyn ResourceLoader {
&self.resource_loader
}
fn gl_version(&self) -> GLVersion {
GLVersion::GL3
}
fn make_current(&mut self) -> Result<(), GlWindowError> {
let size = self.size();
unsafe {
self.gl_window.make_current()?;
gl::Viewport(0, 0, size.x(), size.y());
gl::Scissor(0, 0, size.x(), size.y());
gl::Enable(gl::SCISSOR_TEST);
}
self.handle_events();
Ok(())
}
fn begin_frame(&mut self) -> Result<&mut[GlWindowCamera], GlWindowError> {
self.handle_events();
Ok(&mut self.cameras[..])
}
fn end_frame(&mut self) -> Result<(), GlWindowError> {
self.handle_events();
self.gl_window.swap_buffers()?;
self.handle_events();
Ok(())
}
fn running(&self) -> bool {
self.running
}
fn size(&self) -> Point2DI32 {
window_size(&*self.gl_window)
}
}
impl DisplayCamera for GlWindowCamera {
type Error = GlWindowError;
fn make_current(&mut self) -> Result<(), GlWindowError> {
let bounds = self.bounds();
unsafe {
self.gl_window.make_current()?;
gl::Viewport(bounds.origin().x(), bounds.origin().y(), bounds.size().x(), bounds.size().y());
gl::Scissor(bounds.origin().x(), bounds.origin().y(), bounds.size().x(), bounds.size().y());
}
Ok(())
}
fn bounds(&self) -> RectI32 {
let window_size = window_size(&*self.gl_window);
let eye_size = Point2DI32::new(window_size.x()/2, window_size.y());
let origin = match self.eye {
Eye::Left => Point2DI32::new(0, 0),
Eye::Right => Point2DI32::new(eye_size.x(), 0),
};
RectI32::new(origin, eye_size)
}
fn perspective(&self) -> Perspective {
// TODO: add eye offsets
let bounds = self.bounds();
let aspect = bounds.size().x() as f32 / bounds.size().y() as f32;
let transform = Transform3DF32::from_perspective(FRAC_PI_4, aspect, NEAR_CLIP_PLANE, FAR_CLIP_PLANE);
Perspective::new(&transform, bounds.size())
}
fn view(&self) -> Transform3DF32 {
let duration = Instant::now() - self.start;
let rotation = duration.as_millis() as f32 / 1000.0;
Transform3DF32::from_rotation(rotation, 0.0, 0.0)
.pre_mul(&Transform3DF32::from_translation(0.0, 0.0, -CAMERA_DISTANCE))
}
}
impl GlWindowDisplay {
pub fn new() -> Result<GlWindowDisplay, GlWindowError> {
let resource_loader = FilesystemResourceLoader::locate();
let size = default_window_size();
let events_loop = glutin::EventsLoop::new();
let window = WindowBuilder::new()
.with_title("Pathfinder Immersive Demo")
.with_dimensions(size);
let context = ContextBuilder::new()
.with_vsync(true);
let gl_window = Rc::new(glutin::GlWindow::new(window, context, &events_loop)?);
let start = Instant::now();
let cameras = vec![
GlWindowCamera { gl_window: gl_window.clone(), start, eye: Eye::Left },
GlWindowCamera { gl_window: gl_window.clone(), start, eye: Eye::Right },
];
gl::load_with(|name| gl_window.get_proc_address(name) as *const _);
Ok(GlWindowDisplay {
resource_loader,
events_loop,
gl_window,
cameras,
running: true,
})
}
fn handle_events(&mut self) {
let running = &mut self.running;
self.events_loop.poll_events(|event| {
match event {
Event::WindowEvent { event: WindowEvent::CloseRequested, .. } |
Event::WindowEvent { event: WindowEvent::Destroyed, .. } => *running = false,
_ => (),
}
})
}
}
fn window_size(gl_window: &GlWindow) -> Point2DI32 {
let logical = gl_window
.get_inner_size()
.unwrap_or_else(|| default_window_size());
let hidpi = gl_window.get_hidpi_factor();
let physical = logical.to_physical(hidpi);
Point2DI32::new(physical.width as i32, physical.height as i32)
}
fn default_window_size() -> LogicalSize {
LogicalSize::new((DEFAULT_EYE_WIDTH * 2) as f64, DEFAULT_EYE_HEIGHT as f64)
}
impl fmt::Display for GlWindowError {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
GlWindowError::Creation(ref err) => err.fmt(formatter),
GlWindowError::Context(ref err) => err.fmt(formatter),
GlWindowError::SVG(ref err) => err.fmt(formatter),
GlWindowError::IO(ref err) => err.fmt(formatter),
}
}
}
impl Error for GlWindowError {
}
impl From<CreationError> for GlWindowError {
fn from(err: CreationError) -> GlWindowError {
GlWindowError::Creation(err)
}
}
impl From<ContextError> for GlWindowError {
fn from(err: ContextError) -> GlWindowError {
GlWindowError::Context(err)
}
}
impl From<usvg::Error> for GlWindowError {
fn from(err: usvg::Error) -> GlWindowError {
GlWindowError::SVG(err)
}
}
impl From<io::Error> for GlWindowError {
fn from(err: io::Error) -> GlWindowError {
GlWindowError::IO(err)
}
}
impl DisplayError for GlWindowError {
}

View File

@ -0,0 +1,129 @@
#![allow(unused_imports)]
#![allow(dead_code)]
use crate::display::Display;
use crate::display::DisplayCamera;
use log::debug;
use pathfinder_demo::Options;
use pathfinder_demo::BuildOptions;
use pathfinder_demo::SceneThreadProxy;
use pathfinder_demo::MainToSceneMsg;
use pathfinder_demo::SceneToMainMsg;
use pathfinder_demo::Camera;
use pathfinder_demo::CameraTransform3D;
use pathfinder_gl::GLDevice;
use pathfinder_renderer::gpu::renderer::Renderer;
use pathfinder_geometry::basic::point::Point2DI32;
use pathfinder_geometry::basic::point::Point2DF32;
use pathfinder_geometry::basic::point::Point3DF32;
use pathfinder_geometry::basic::rect::RectI32;
use pathfinder_geometry::basic::transform2d::Transform2DF32;
use pathfinder_geometry::basic::transform3d::Transform3DF32;
use pathfinder_geometry::basic::transform3d::Perspective;
use pathfinder_gpu::Device;
use pathfinder_simd::default::F32x4;
use pathfinder_svg::BuiltSVG;
use pathfinder_renderer::scene::Scene;
use pathfinder_renderer::builder::RenderTransform;
use std::error::Error;
use std::fmt;
use std::path::Path;
use std::path::PathBuf;
use std::time::Instant;
use usvg;
pub struct ImmersiveDemo<D> {
display: D,
renderer: Renderer<GLDevice>,
scene_thread_proxy: SceneThreadProxy,
svg_size: Point2DF32,
svg_to_world: Option<Transform3DF32>,
}
static DEFAULT_SVG_VIRTUAL_PATH: &'static str = "svg/Ghostscript_Tiger.svg";
// SVG dimensions in metres
const MAX_SVG_HEIGHT: f32 = 1.0;
const MAX_SVG_WIDTH: f32 = 1.0;
const DEFAULT_SVG_DISTANCE: f32 = 1.5;
impl<D: Display> ImmersiveDemo<D> {
pub fn new(mut display: D) -> Result<Self, D::Error> {
display.make_current()?;
let resources = display.resource_loader();
let options = Options::get();
let svg_data = resources.slurp(DEFAULT_SVG_VIRTUAL_PATH)?;
let tree = usvg::Tree::from_data(&svg_data[..], &usvg::Options::default())?;
let svg = BuiltSVG::from_tree(tree);
let svg_size = svg.scene.view_box.size();
let scene_thread_proxy = SceneThreadProxy::new(svg.scene, options);
let _ = scene_thread_proxy.sender.send(MainToSceneMsg::SetDrawableSize(display.size()));
let device = GLDevice::new(display.gl_version());
let viewport = RectI32::new(Point2DI32::new(0, 0), display.size());
let renderer = Renderer::new(device, resources, viewport, display.size());
Ok(ImmersiveDemo {
display,
renderer,
scene_thread_proxy,
svg_size,
svg_to_world: None,
})
}
pub fn running(&self) -> bool {
self.display.running()
}
pub fn render_scene(&mut self) -> Result<(), D::Error> {
self.display.make_current()?;
let cameras = self.display.begin_frame()?;
debug!("PF rendering a frame");
let start = Instant::now();
let svg_size = self.svg_size;
let svg_to_world = self.svg_to_world.get_or_insert_with(|| {
let view: Transform3DF32 = cameras[0].view();
let svg_to_world_scale = f32::max(MAX_SVG_WIDTH / svg_size.x(), MAX_SVG_HEIGHT / svg_size.y());
let svg_width = svg_size.x() * svg_to_world_scale;
let svg_height = svg_size.y() * svg_to_world_scale;
Transform3DF32::from_uniform_scale(svg_to_world_scale)
.pre_mul(&Transform3DF32::from_translation(-svg_width / 2.0, -svg_height / 2.0, -DEFAULT_SVG_DISTANCE))
.pre_mul(&Transform3DF32::from_scale(1.0, -1.0, 1.0))
.pre_mul(&view.inverse())
});
let render_transforms = cameras.iter()
.map(|camera| RenderTransform::Perspective(
camera.perspective()
.post_mul(&camera.view())
.post_mul(&svg_to_world)
)).collect();
let msg = MainToSceneMsg::Build(BuildOptions {
render_transforms: render_transforms,
stem_darkening_font_size: None,
});
let _ = self.scene_thread_proxy.sender.send(msg);
if let Ok(reply) = self.scene_thread_proxy.receiver.recv() {
for (camera, scene) in cameras.iter_mut().zip(reply.render_scenes) {
debug!("PF rendering eye after {}ms", (Instant::now() - start).as_millis());
camera.make_current()?;
let bounds = camera.bounds();
let background = F32x4::new(0.0, 0.0, 0.0, 1.0);
self.renderer.device.clear(Some(background), Some(1.0), Some(0));
self.renderer.enable_depth();
self.renderer.set_viewport(bounds);
self.renderer.render_scene(&scene.built_scene);
}
}
debug!("PF rendered frame after {}ms", (Instant::now() - start).as_millis());
self.display.end_frame()?;
Ok(())
}
}

View File

@ -0,0 +1,333 @@
// pathfinder/demo/magicleap/src/landscape.cpp
//
// Copyright © 2019 The Pathfinder Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
// A launcher for the ML1 pathfinder demo
#include <landscape.h>
#include <lumin/node/RootNode.h>
#include <lumin/node/QuadNode.h>
#include <lumin/resource/PlanarResource.h>
#include <lumin/ui/node/UiPanel.h>
#include <lumin/ui/Cursor.h>
#include <lumin/input/Raycast.h>
#include <lumin/event/ControlPose6DofInputEventData.h>
#include <lumin/event/GestureInputEventData.h>
#include <lumin/event/RayCastEventData.h>
#include <ml_dispatch.h>
#include <ml_logging.h>
#include <scenes.h>
#include <PrismSceneManager.h>
int main(int argc, char **argv)
{
ML_LOG(Debug, "PathfinderDemo Starting.");
PathfinderDemo myApp;
return myApp.run();
}
const char* QUAD_NAMES[NUM_QUADS] = {
"quad1",
"quad2",
"quad3",
"quad4",
"quad5",
"quad6",
};
const char* SVG_NAMES[NUM_QUADS] = {
"svg/Ghostscript_Tiger.svg",
"svg/nba-notext.svg",
"svg/julius-caesar-with-bg.svg",
"svg/magicleap-quickstart-p03.svg",
"svg/pathfinder_logo.svg",
"svg/pathfinder-magicleap-demo.svg",
};
PathfinderDemo::PathfinderDemo() {
ML_LOG(Debug, "PathfinderDemo Constructor.");
// Place your constructor implementation here.
}
PathfinderDemo::~PathfinderDemo() {
ML_LOG(Debug, "PathfinderDemo Destructor.");
// Place your destructor implementation here.
}
const glm::vec3 PathfinderDemo::getInitialPrismSize() const {
return glm::vec3(0.4f, 0.4f, 0.4f);
}
void PathfinderDemo::createInitialPrism() {
prism_ = requestNewPrism(getInitialPrismSize());
if (!prism_) {
ML_LOG(Error, "PathfinderDemo Error creating default prism.");
abort();
}
prismSceneManager_ = new PrismSceneManager(prism_);
}
int PathfinderDemo::init() {
ML_LOG(Debug, "PathfinderDemo Initializing.");
createInitialPrism();
lumin::ui::Cursor::SetEnabled(prism_, false);
spawnInitialScenes();
// Place your initialization here.
if (checkPrivilege(lumin::PrivilegeId::kControllerPose) != lumin::PrivilegeResult::kGranted) {
ML_LOG(Error, "Pathfinder Failed to get controller access");
abort();
return 1;
}
// Get the root node of the prism
lumin::RootNode* root_node = prism_->getRootNode();
if (!root_node) {
ML_LOG(Error, "Pathfinder Failed to get root node");
abort();
return 1;
}
for (int i=0; i<NUM_QUADS; i++) {
// Get the quad
lumin::QuadNode* quad_node = lumin::QuadNode::CastFrom(prism_->findNode(QUAD_NAMES[i], root_node));
if (!quad_node) {
ML_LOG(Error, "Pathfinder Failed to get quad node %d.", i);
abort();
return 1;
}
quad_nodes_[i] = quad_node->getNodeId();
// Create the EGL surface for it to draw to
lumin::ResourceIDType plane_id = prism_->createPlanarEGLResourceId();
if (!plane_id) {
ML_LOG(Error, "Pathfinder Failed to create EGL resource");
abort();
return 1;
}
quad_node->setRenderResource(plane_id);
renderNode(quad_node->getNodeId());
}
return 0;
}
void PathfinderDemo::renderNode(lumin::NodeIDType node_id) {
if (node_id == lumin::INVALID_NODE_ID) { return; }
lumin::QuadNode* quad_node = static_cast<lumin::QuadNode*>(prism_->getNode(node_id));
if (!quad_node) {
ML_LOG(Error, "Pathfinder Failed to get quad node");
return;
}
lumin::PlanarResource* plane = const_cast<lumin::PlanarResource*>(static_cast<const lumin::PlanarResource*>(quad_node->getRenderResource()));
if (!plane) {
ML_LOG(Error, "Pathfinder Failed to get plane");
return;
}
// Get the EGL context, surface and display.
uint32_t width = plane->getWidth();
uint32_t height = plane->getHeight();
EGLContext ctx = plane->getEGLContext();
EGLSurface surf = plane->getEGLSurface();
EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
// Initialize pathfinder
if (!pathfinder_) {
ML_LOG(Info, "Pathfinder initializing");
pathfinder_ = magicleap_pathfinder_init();
ML_LOG(Info, "Pathfinder initialized");
}
// Get the SVG filename
const char* svg_filename;
for (int i=0; i<NUM_QUADS; i++) {
if (quad_nodes_[i] == node_id) {
svg_filename = SVG_NAMES[i];
break;
}
}
if (!svg_filename) {
ML_LOG(Error, "Pathfinder Failed to get SVG filename");
return;
}
// Set the brightness
float brightness;
if (node_id == highlighted_node_) {
brightness = 0.6;
} else {
brightness = 0.4;
}
// Render the SVG
MagicLeapPathfinderRenderOptions options = {
dpy,
surf,
{ brightness, brightness, brightness, 1.0 },
{ 0, 0, width, height },
svg_filename,
};
eglMakeCurrent(dpy, surf, surf, ctx);
magicleap_pathfinder_render(pathfinder_, &options);
eglSwapBuffers(dpy, surf);
}
int PathfinderDemo::deInit() {
ML_LOG(Debug, "PathfinderDemo Deinitializing.");
// Place your deinitialization here.
magicleap_pathfinder_deinit(pathfinder_);
pathfinder_ = nullptr;
return 0;
}
void PathfinderDemo::spawnInitialScenes() {
// Iterate over all the exported scenes
for (auto& exportedSceneEntry : scenes::externalScenes ) {
// If this scene was marked to be instanced at app initialization, do it
const SceneDescriptor &sd = exportedSceneEntry.second;
if (sd.getInitiallySpawned()) {
lumin::Node* const spawnedRoot = prismSceneManager_->spawn(sd);
if (spawnedRoot) {
if (!prism_->getRootNode()->addChild(spawnedRoot)) {
ML_LOG(Error, "PathfinderDemo Failed to add spawnedRoot to the prism root node");
abort();
}
}
}
}
}
bool PathfinderDemo::updateLoop(float fDelta) {
// Place your update here.
if (focus_node_ != highlighted_node_) {
lumin::NodeIDType old_highlight = highlighted_node_;
highlighted_node_ = focus_node_;
renderNode(old_highlight);
renderNode(highlighted_node_);
}
// Return true for your app to continue running, false to terminate the app.
return true;
}
bool PathfinderDemo::eventListener(lumin::ServerEvent* event) {
// Place your event handling here.
lumin::ServerEventTypeValue typ = event->getServerEventTypeValue();
if (typ == lumin::ControlPose6DofInputEventData::GetServerEventTypeValue()) {
requestWorldRayCast(getHeadposeWorldPosition(), getHeadposeWorldForwardVector(), 0);
return false;
} else if (typ == lumin::RayCastEventData::GetServerEventTypeValue()) {
lumin::RayCastEventData* raycast_event = static_cast<lumin::RayCastEventData*>(event);
std::shared_ptr<lumin::RaycastResult> raycast_result = raycast_event->getHitData();
switch (raycast_result->getType()) {
case lumin::RaycastResultType::kQuadNode: {
std::shared_ptr<lumin::RaycastQuadNodeResult> quad_result = std::static_pointer_cast<lumin::RaycastQuadNodeResult>(raycast_result);
focus_node_ = quad_result->getNodeId();
return false;
}
default: {
focus_node_ = lumin::INVALID_NODE_ID;
return false;
}
}
} else if (typ == lumin::GestureInputEventData::GetServerEventTypeValue()) {
lumin::GestureInputEventData* gesture_event = static_cast<lumin::GestureInputEventData*>(event);
switch (gesture_event->getGesture()) {
case lumin::input::GestureType::TriggerClick: {
return onClick();
}
default: {
return false;
}
}
} else {
return false;
}
}
bool PathfinderDemo::onClick() {
lumin::RootNode* root_node = prism_->getRootNode();
for (int i=0; i<NUM_QUADS; i++) {
lumin::Node* node = prism_->findNode(QUAD_NAMES[i], root_node);
if (node->getNodeId() == focus_node_) {
dispatch(SVG_NAMES[i]);
return true;
}
}
return false;
}
void PathfinderDemo::dispatch(const char* svg_filename) {
ML_LOG(Info, "Dispatching %s", svg_filename);
MLDispatchPacket* dispatcher;
if (MLResult_Ok != MLDispatchAllocateEmptyPacket(&dispatcher)) {
ML_LOG(Error, "Failed to allocate dispatcher");
return;
}
if (MLResult_Ok != MLDispatchAllocateFileInfoList(dispatcher, 1)) {
ML_LOG(Error, "Failed to allocate file info list");
return;
}
MLFileInfo* file_info;
if (MLResult_Ok != MLDispatchGetFileInfoByIndex(dispatcher, 0, &file_info)) {
ML_LOG(Error, "Failed to get file info");
return;
}
if (MLResult_Ok != MLFileInfoSetFileName(file_info, svg_filename)) {
ML_LOG(Error, "Failed to set filename");
return;
}
if (MLResult_Ok != MLFileInfoSetMimeType(file_info, "image/svg")) {
ML_LOG(Error, "Failed to set mime type");
return;
}
if (MLResult_Ok != MLDispatchAddFileInfo(dispatcher, file_info)) {
ML_LOG(Error, "Failed to add file info");
return;
}
MLResult result = MLDispatchTryOpenApplication(dispatcher);
if (MLResult_Ok != result) {
ML_LOG(Error, "Failed to dispatch: %s", MLDispatchGetResultString(result));
return;
}
// https://forum.magicleap.com/hc/en-us/community/posts/360043198492-Calling-MLDispatchReleaseFileInfoList-causes-a-dynamic-link-error
// if (MLResult_Ok != MLDispatchReleaseFileInfoList(dispatcher, false)) {
// ML_LOG(Error, "Failed to deallocate file info list");
// return;
// }
if (MLResult_Ok != MLDispatchReleasePacket(&dispatcher, false, false)) {
ML_LOG(Error, "Failed to deallocate dispatcher");
return;
}
}
extern "C" void init_scene_thread(uint64_t id) {}

View File

@ -0,0 +1,137 @@
// pathfinder/demo/magicleap/src/landscape.h
//
// Copyright © 2019 The Pathfinder Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
// A launcher for the ML1 pathfinder demo
// Based on code generated by the Magic Leap Lumin Runtime Editor.
// Original copyright:
// Copyright (c) 2018 Magic Leap, Inc. All Rights Reserved.
// Use of this file is governed by the Creator Agreement, located
// here: https://id.magicleap.com/creator-terms
#include <EGL/egl.h>
#include <lumin/LandscapeApp.h>
#include <lumin/Prism.h>
#include <lumin/event/ServerEvent.h>
#include <SceneDescriptor.h>
#include <PrismSceneManager.h>
const uint32_t NUM_QUADS = 6;
/**
* PathfinderDemo Landscape Application
*/
class PathfinderDemo : public lumin::LandscapeApp {
public:
/**
* Constructs the Landscape Application.
*/
PathfinderDemo();
/**
* Destroys the Landscape Application.
*/
virtual ~PathfinderDemo();
/**
* Disallows the copy constructor.
*/
PathfinderDemo(const PathfinderDemo&) = delete;
/**
* Disallows the move constructor.
*/
PathfinderDemo(PathfinderDemo&&) = delete;
/**
* Disallows the copy assignment operator.
*/
PathfinderDemo& operator=(const PathfinderDemo&) = delete;
/**
* Disallows the move assignment operator.
*/
PathfinderDemo& operator=(PathfinderDemo&&) = delete;
protected:
/**
* Initializes the Landscape Application.
* @return - 0 on success, error code on failure.
*/
int init() override;
/**
* Deinitializes the Landscape Application.
* @return - 0 on success, error code on failure.
*/
int deInit() override;
/**
* Returns the initial size of the Prism
* Used in createPrism().
*/
const glm::vec3 getInitialPrismSize() const;
/**
* Creates the prism, updates the private variable prism_ with the created prism.
*/
void createInitialPrism();
/**
* Initializes and creates the scene of all scenes marked as initially instanced
*/
void spawnInitialScenes();
/**
* Respond to a click
*/
bool onClick();
/**
* Dispatch an SVG file to the immersive app
*/
void dispatch(const char* svg_filename);
/**
* Render a node in the scene
*/
void renderNode(lumin::NodeIDType node_id);
/**
* Run application login
*/
virtual bool updateLoop(float fDelta) override;
/**
* Handle events from the server
*/
virtual bool eventListener(lumin::ServerEvent* event) override;
private:
lumin::Prism* prism_ = nullptr; // represents the bounded space where the App renders.
PrismSceneManager* prismSceneManager_ = nullptr;
void* pathfinder_ = nullptr;
lumin::NodeIDType quad_nodes_[NUM_QUADS] = {lumin::INVALID_NODE_ID};
lumin::NodeIDType highlighted_node_ = lumin::INVALID_NODE_ID;
lumin::NodeIDType focus_node_ = lumin::INVALID_NODE_ID;
};
typedef struct MagicLeapPathfinderRenderOptions {
EGLDisplay display;
EGLSurface surface;
float bg_color[4];
uint32_t viewport[4];
const char* svg_filename;
} MagicLeapPathfinderRenderOptions;
extern "C" void* magicleap_pathfinder_init();
extern "C" void magicleap_pathfinder_render(void*, MagicLeapPathfinderRenderOptions*);
extern "C" void magicleap_pathfinder_deinit(void*);

254
demo/magicleap/src/lib.rs Normal file
View File

@ -0,0 +1,254 @@
// pathfinder/demo/magicleap/src/lib.rs
//
// Copyright © 2019 The Pathfinder Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! A demo app for Pathfinder on ML1.
use crate::magicleap::MagicLeapLogger;
use crate::magicleap::MagicLeapWindow;
use egl;
use egl::EGLContext;
use egl::EGLDisplay;
use egl::EGLSurface;
use gl::types::GLuint;
use log::info;
use pathfinder_demo::DemoApp;
use pathfinder_demo::Options;
use pathfinder_demo::UIVisibility;
use pathfinder_demo::BackgroundColor;
use pathfinder_demo::Mode;
use pathfinder_demo::window::Event;
use pathfinder_demo::window::SVGPath;
use pathfinder_geometry::basic::point::Point2DF32;
use pathfinder_geometry::basic::point::Point2DI32;
use pathfinder_geometry::basic::rect::RectI32;
use pathfinder_geometry::basic::transform2d::Transform2DF32;
use pathfinder_gl::GLDevice;
use pathfinder_gl::GLVersion;
use pathfinder_gpu::Device;
use pathfinder_gpu::resources::FilesystemResourceLoader;
use pathfinder_gpu::resources::ResourceLoader;
use pathfinder_renderer::builder::RenderOptions;
use pathfinder_renderer::builder::RenderTransform;
use pathfinder_renderer::builder::SceneBuilder;
use pathfinder_renderer::builder::SceneBuilderContext;
use pathfinder_renderer::gpu::renderer::Renderer;
use pathfinder_renderer::gpu_data::BuiltScene;
use pathfinder_simd::default::F32x4;
use pathfinder_svg::BuiltSVG;
use std::collections::HashMap;
use std::ffi::CStr;
use std::ffi::CString;
use std::os::raw::c_char;
use std::os::raw::c_void;
use std::sync::mpsc;
use usvg::Options as UsvgOptions;
use usvg::Tree;
mod c_api;
mod magicleap;
#[cfg(feature = "mocked")]
mod mocked_c_api;
struct ImmersiveApp {
sender: mpsc::Sender<Event>,
receiver: mpsc::Receiver<Event>,
demo: DemoApp<MagicLeapWindow>,
}
#[no_mangle]
pub extern "C" fn magicleap_pathfinder_demo_init(egl_display: EGLDisplay, egl_context: EGLContext) -> *mut c_void {
unsafe { c_api::MLLoggingLog(c_api::MLLogLevel::Info,
b"Pathfinder Demo\0".as_ptr() as *const _,
b"Initializing\0".as_ptr() as *const _) };
let tag = CString::new("Pathfinder Demo").unwrap();
let level = log::LevelFilter::Warn;
let logger = MagicLeapLogger::new(tag, level);
log::set_boxed_logger(Box::new(logger)).unwrap();
log::set_max_level(level);
info!("Initialized logging");
let window = MagicLeapWindow::new(egl_display, egl_context);
let window_size = window.size();
let mut options = Options::default();
options.ui = UIVisibility::None;
options.background_color = BackgroundColor::Transparent;
options.mode = Mode::VR;
options.jobs = Some(3);
let demo = DemoApp::new(window, window_size, options);
info!("Initialized app");
let (sender, receiver) = mpsc::channel();
Box::into_raw(Box::new(ImmersiveApp { sender, receiver, demo })) as *mut c_void
}
#[no_mangle]
pub unsafe extern "C" fn magicleap_pathfinder_demo_run(app: *mut c_void) {
let app = app as *mut ImmersiveApp;
if let Some(app) = app.as_mut() {
while app.demo.window.running() {
let mut events = Vec::new();
while let Some(event) = app.demo.window.try_get_event() {
events.push(event);
}
while let Ok(event) = app.receiver.try_recv() {
events.push(event);
}
let scene_count = app.demo.prepare_frame(events);
for scene_index in 0..scene_count {
app.demo.draw_scene(scene_index);
}
app.demo.finish_drawing_frame();
}
}
}
#[no_mangle]
pub unsafe extern "C" fn magicleap_pathfinder_demo_load(app: *mut c_void, svg_filename: *const c_char) {
let app = app as *mut ImmersiveApp;
if let Some(app) = app.as_mut() {
let svg_filename = CStr::from_ptr(svg_filename).to_string_lossy().into_owned();
info!("Loading {}.", svg_filename);
let _ = app.sender.send(Event::OpenSVG(SVGPath::Resource(svg_filename)));
}
}
struct MagicLeapPathfinder {
renderers: HashMap<(EGLSurface, EGLDisplay), Renderer<GLDevice>>,
svgs: HashMap<String, BuiltSVG>,
resources: FilesystemResourceLoader,
scene_builder_context: SceneBuilderContext,
}
#[repr(C)]
pub struct MagicLeapPathfinderRenderOptions {
display: EGLDisplay,
surface: EGLSurface,
bg_color: [f32; 4],
viewport: [u32; 4],
svg_filename: *const c_char,
}
#[no_mangle]
pub extern "C" fn magicleap_pathfinder_init() -> *mut c_void {
unsafe { c_api::MLLoggingLog(c_api::MLLogLevel::Info,
b"Pathfinder Demo\0".as_ptr() as *const _,
b"Initializing\0".as_ptr() as *const _) };
let tag = CString::new("Pathfinder Demo").unwrap();
let level = log::LevelFilter::Info;
let logger = MagicLeapLogger::new(tag, level);
log::set_boxed_logger(Box::new(logger)).unwrap();
log::set_max_level(level);
info!("Initialized logging");
gl::load_with(|s| egl::get_proc_address(s) as *const c_void);
info!("Initialized gl");
let pf = MagicLeapPathfinder {
renderers: HashMap::new(),
svgs: HashMap::new(),
resources: FilesystemResourceLoader::locate(),
scene_builder_context: SceneBuilderContext::new(),
};
info!("Initialized pf");
Box::into_raw(Box::new(pf)) as *mut c_void
}
#[no_mangle]
pub unsafe extern "C" fn magicleap_pathfinder_render(pf: *mut c_void, options: *const MagicLeapPathfinderRenderOptions) {
let pf = pf as *mut MagicLeapPathfinder;
if let (Some(pf), Some(options)) = (pf.as_mut(), options.as_ref()) {
let resources = &pf.resources;
let svg_filename = CStr::from_ptr(options.svg_filename).to_string_lossy().into_owned();
let svg = pf.svgs.entry(svg_filename).or_insert_with(|| {
let svg_filename = CStr::from_ptr(options.svg_filename).to_string_lossy();
let data = resources.slurp(&*svg_filename).unwrap();
let tree = Tree::from_data(&data, &UsvgOptions::default()).unwrap();
BuiltSVG::from_tree(tree)
});
let mut width = 0;
let mut height = 0;
egl::query_surface(options.display, options.surface, egl::EGL_WIDTH, &mut width);
egl::query_surface(options.display, options.surface, egl::EGL_HEIGHT, &mut height);
let size = Point2DI32::new(width, height);
let viewport_origin = Point2DI32::new(options.viewport[0] as i32, options.viewport[1] as i32);
let viewport_size = Point2DI32::new(options.viewport[2] as i32, options.viewport[3] as i32);
let viewport = RectI32::new(viewport_origin, viewport_size);
let bg_color = F32x4::new(options.bg_color[0], options.bg_color[1], options.bg_color[2], options.bg_color[3]);
let renderer = pf.renderers.entry((options.display, options.surface)).or_insert_with(|| {
let mut fbo = 0;
gl::GetIntegerv(gl::DRAW_FRAMEBUFFER_BINDING, &mut fbo);
let device = GLDevice::new(GLVersion::GLES3, fbo as GLuint);
Renderer::new(device, resources, viewport, size)
});
renderer.set_main_framebuffer_size(size);
renderer.set_viewport(viewport);
renderer.device.bind_default_framebuffer(viewport);
renderer.device.clear(Some(bg_color), Some(1.0), Some(0));
renderer.disable_depth();
svg.scene.view_box = viewport.to_f32();
let scale = i32::min(viewport_size.x(), viewport_size.y()) as f32 /
f32::max(svg.scene.bounds.size().x(), svg.scene.bounds.size().y());
let transform = Transform2DF32::from_translation(&svg.scene.bounds.size().scale(-0.5))
.post_mul(&Transform2DF32::from_scale(&Point2DF32::splat(scale)))
.post_mul(&Transform2DF32::from_translation(&viewport_size.to_f32().scale(0.5)));
let render_options = RenderOptions {
transform: RenderTransform::Transform2D(transform),
dilation: Point2DF32::default(),
barrel_distortion: None,
subpixel_aa_enabled: false,
};
let built_options = render_options.prepare(svg.scene.bounds);
let quad = built_options.quad();
let mut built_scene = BuiltScene::new(svg.scene.view_box, &quad, svg.scene.objects.len() as u32);
built_scene.shaders = svg.scene.build_shaders();
let (command_sender, command_receiver) = mpsc::channel();
let command_sender_clone = command_sender.clone();
SceneBuilder::new(&pf.scene_builder_context, &svg.scene, &built_options)
.build_sequentially(Box::new(move |command| { let _ = command_sender.send(Some(command)); }));
let _ = command_sender_clone.send(None);
renderer.begin_scene(&built_scene);
while let Ok(Some(command)) = command_receiver.recv() {
renderer.render_command(&command);
}
renderer.end_scene();
}
}
#[no_mangle]
pub unsafe extern "C" fn magicleap_pathfinder_deinit(pf: *mut c_void) {
Box::from_raw(pf as *mut MagicLeapPathfinder);
}

View File

@ -0,0 +1,406 @@
// pathfinder/demo/magicleap/src/magicleap.rs
//
// Copyright © 2019 The Pathfinder Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use crate::c_api::MLGraphicsBeginFrame;
use crate::c_api::MLGraphicsCreateClientGL;
use crate::c_api::MLGraphicsDestroyClient;
use crate::c_api::MLGraphicsEndFrame;
use crate::c_api::MLGraphicsGetRenderTargets;
use crate::c_api::MLGraphicsInitFrameParams;
use crate::c_api::MLGraphicsOptions;
use crate::c_api::MLGraphicsSignalSyncObjectGL;
use crate::c_api::MLGraphicsVirtualCameraInfoArray;
use crate::c_api::MLHandle;
use crate::c_api::MLHeadTrackingCreate;
use crate::c_api::MLLifecycleSetReadyIndication;
use crate::c_api::MLLogLevel;
use crate::c_api::MLLoggingLog;
use crate::c_api::MLMat4f;
use crate::c_api::MLQuaternionf;
use crate::c_api::MLRectf;
use crate::c_api::MLTransform;
use crate::c_api::MLVec3f;
use crate::c_api::ML_HANDLE_INVALID;
use crate::c_api::ML_RESULT_TIMEOUT;
use crate::c_api::ML_VIRTUAL_CAMERA_COUNT;
use egl;
use egl::EGL_NO_SURFACE;
use egl::EGLContext;
use egl::EGLDisplay;
use gl;
use gl::types::GLuint;
use log;
use log::debug;
use log::info;
use pathfinder_demo::window::CameraTransform;
use pathfinder_demo::window::Event;
use pathfinder_demo::window::View;
use pathfinder_demo::window::Window;
use pathfinder_demo::window::WindowSize;
use pathfinder_geometry::basic::point::Point2DI32;
use pathfinder_geometry::basic::point::Point2DF32;
use pathfinder_geometry::basic::rect::RectF32;
use pathfinder_geometry::basic::rect::RectI32;
use pathfinder_geometry::basic::transform3d::Perspective;
use pathfinder_geometry::basic::transform3d::Transform3DF32;
use pathfinder_geometry::distortion::BarrelDistortionCoefficients;
use pathfinder_geometry::util;
use pathfinder_gl::GLVersion;
use pathfinder_gpu::resources::FilesystemResourceLoader;
use pathfinder_gpu::resources::ResourceLoader;
use pathfinder_simd::default::F32x4;
use rayon::ThreadPoolBuilder;
use smallvec::SmallVec;
use std::ffi::CString;
use std::io::Write;
use std::mem;
use std::os::raw::c_void;
use std::path::PathBuf;
use std::thread;
use std::time::Duration;
pub struct MagicLeapWindow {
framebuffer_id: GLuint,
graphics_client: MLHandle,
size: Point2DI32,
virtual_camera_array: MLGraphicsVirtualCameraInfoArray,
initial_camera_transform: Option<Transform3DF32>,
frame_handle: MLHandle,
resource_loader: FilesystemResourceLoader,
pose_event: Option<Vec<CameraTransform>>,
running: bool,
in_frame: bool,
}
impl Window for MagicLeapWindow {
fn resource_loader(&self) -> &dyn ResourceLoader {
&self.resource_loader
}
fn gl_version(&self) -> GLVersion {
GLVersion::GL3
}
fn gl_default_framebuffer(&self) -> GLuint {
self.framebuffer_id
}
fn adjust_thread_pool_settings(&self, thread_pool_builder: ThreadPoolBuilder) -> ThreadPoolBuilder {
thread_pool_builder.start_handler(|id| unsafe { init_scene_thread(id) })
}
fn mouse_position(&self) -> Point2DI32 {
Point2DI32::new(0, 0)
}
fn create_user_event_id (&self) -> u32 {
0
}
fn push_user_event(_: u32, _: u32) {
}
fn present_open_svg_dialog(&mut self) {
}
fn run_save_dialog(&self, _: &str) -> Result<PathBuf, ()> {
Err(())
}
fn viewport(&self, _view: View) -> RectI32 {
RectI32::new(Point2DI32::default(), self.size)
}
fn barrel_distortion_coefficients(&self) -> BarrelDistortionCoefficients {
BarrelDistortionCoefficients { k0: 0.0, k1: 0.0 }
}
fn make_current(&mut self, view: View) {
self.begin_frame();
let eye = match view {
View::Stereo(eye) if (eye as usize) < ML_VIRTUAL_CAMERA_COUNT => eye as usize,
_ => { debug!("Asked for unexpected view: {:?}", view); 0 }
};
debug!("Making {} current.", eye);
let viewport = self.virtual_camera_array.viewport;
let color_id = self.virtual_camera_array.color_id.as_gl_uint();
let depth_id = self.virtual_camera_array.depth_id.as_gl_uint();
let virtual_camera = self.virtual_camera_array.virtual_cameras[eye];
let layer_id = virtual_camera.virtual_camera_name as i32;
unsafe {
gl::FramebufferTextureLayer(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, color_id, 0, layer_id);
gl::FramebufferTextureLayer(gl::FRAMEBUFFER, gl::DEPTH_ATTACHMENT, depth_id, 0, layer_id);
gl::Viewport(viewport.x as i32, viewport.y as i32, viewport.w as i32, viewport.h as i32);
}
debug!("Made {} current.", eye);
}
fn present(&mut self) {
self.end_frame();
self.begin_frame();
}
}
extern "C" {
fn init_scene_thread(id: usize);
}
fn get_proc_address(s: &str) -> *const c_void {
egl::get_proc_address(s) as *const c_void
}
impl MagicLeapWindow {
pub fn new(egl_display: EGLDisplay, egl_context: EGLContext) -> MagicLeapWindow {
debug!("Creating MagicLeapWindow");
let mut framebuffer_id = 0;
let graphics_options = MLGraphicsOptions::default();
let mut graphics_client = unsafe { mem::zeroed() };
let mut head_tracker = unsafe { mem::zeroed() };
let mut targets = unsafe { mem::zeroed() };
let virtual_camera_array = unsafe { mem::zeroed() };
let handle = MLHandle::from(egl_context);
unsafe {
egl::make_current(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, egl_context);
gl::load_with(get_proc_address);
gl::GenFramebuffers(1, &mut framebuffer_id);
MLGraphicsCreateClientGL(&graphics_options, handle, &mut graphics_client).unwrap();
MLLifecycleSetReadyIndication().unwrap();
MLHeadTrackingCreate(&mut head_tracker).unwrap();
MLGraphicsGetRenderTargets(graphics_client, &mut targets).unwrap();
}
let (max_width, max_height) = targets.buffers.iter().map(|buffer| buffer.color)
.chain(targets.buffers.iter().map(|buffer| buffer.depth))
.map(|target| (target.width as i32, target.height as i32))
.max()
.unwrap_or_default();
let resource_loader = FilesystemResourceLoader::locate();
debug!("Created MagicLeapWindow");
MagicLeapWindow {
framebuffer_id,
graphics_client,
size: Point2DI32::new(max_width, max_height),
frame_handle: ML_HANDLE_INVALID,
virtual_camera_array,
initial_camera_transform: None,
resource_loader,
pose_event: None,
running: true,
in_frame: false,
}
}
pub fn size(&self) -> WindowSize {
WindowSize {
logical_size: self.size,
backing_scale_factor: 1.0,
}
}
pub fn running(&self) -> bool {
self.running
}
pub fn try_get_event(&mut self) -> Option<Event> {
self.pose_event.take().map(Event::CameraTransforms)
}
fn begin_frame(&mut self) {
if !self.in_frame {
debug!("PF beginning frame");
let mut params = unsafe { mem::zeroed() };
unsafe {
gl::BindFramebuffer(gl::FRAMEBUFFER, self.framebuffer_id);
MLGraphicsInitFrameParams(&mut params).unwrap();
let mut result = MLGraphicsBeginFrame(self.graphics_client, &params, &mut self.frame_handle, &mut self.virtual_camera_array);
if result == ML_RESULT_TIMEOUT {
info!("PF frame timeout");
let mut sleep = Duration::from_millis(1);
let max_sleep = Duration::from_secs(5);
while result == ML_RESULT_TIMEOUT {
sleep = (sleep * 2).min(max_sleep);
info!("PF exponential backoff {}ms", sleep.as_millis());
thread::sleep(sleep);
result = MLGraphicsBeginFrame(self.graphics_client, &params, &mut self.frame_handle, &mut self.virtual_camera_array);
}
info!("PF frame finished timeout");
}
result.unwrap();
}
let virtual_camera_array = &self.virtual_camera_array;
let initial_camera = self.initial_camera_transform.get_or_insert_with(|| {
let initial_offset = Transform3DF32::from_translation(0.0, 0.0, 1.0);
let mut camera = virtual_camera_array.virtual_cameras[0].transform;
for i in 1..virtual_camera_array.num_virtual_cameras {
let next = virtual_camera_array.virtual_cameras[i as usize].transform;
camera = camera.lerp(next, 1.0 / (i as f32 + 1.0));
}
Transform3DF32::from(camera).post_mul(&initial_offset)
});
let camera_transforms = (0..virtual_camera_array.num_virtual_cameras)
.map(|i| {
let camera = &virtual_camera_array.virtual_cameras[i as usize];
let projection = Transform3DF32::from(camera.projection);
let size = RectI32::from(virtual_camera_array.viewport).size();
let perspective = Perspective::new(&projection, size);
let view = Transform3DF32::from(camera.transform).inverse().post_mul(initial_camera);
CameraTransform { perspective, view }
})
.collect();
self.in_frame = true;
self.pose_event = Some(camera_transforms);
debug!("PF begun frame");
}
}
fn end_frame(&mut self) {
if self.in_frame {
debug!("PF ending frame");
unsafe {
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
for i in 0..self.virtual_camera_array.num_virtual_cameras {
let virtual_camera = &self.virtual_camera_array.virtual_cameras[i as usize];
MLGraphicsSignalSyncObjectGL(self.graphics_client, virtual_camera.sync_object).unwrap();
}
MLGraphicsEndFrame(self.graphics_client, self.frame_handle).unwrap();
}
self.in_frame = false;
debug!("PF ended frame");
}
}
}
impl Drop for MagicLeapWindow {
fn drop(&mut self) {
self.end_frame();
unsafe {
gl::DeleteFramebuffers(1, &self.framebuffer_id);
MLGraphicsDestroyClient(&mut self.graphics_client);
}
}
}
// Logging
pub struct MagicLeapLogger {
tag: CString,
level_filter: log::LevelFilter,
}
impl log::Log for MagicLeapLogger {
fn enabled(&self, metadata: &log::Metadata) -> bool {
metadata.level() <= self.level_filter
}
fn log(&self, record: &log::Record) {
let lvl = match record.level() {
log::Level::Error => MLLogLevel::Error,
log::Level::Warn => MLLogLevel::Warning,
log::Level::Info => MLLogLevel::Info,
log::Level::Debug => MLLogLevel::Debug,
log::Level::Trace => MLLogLevel::Verbose,
};
let mut msg = SmallVec::<[u8; 128]>::new();
write!(msg, "{}\0", record.args()).unwrap();
unsafe {
MLLoggingLog(lvl, self.tag.as_ptr(), &msg[0] as *const _ as _);
}
}
fn flush(&self) {}
}
impl MagicLeapLogger {
pub fn new(tag: CString, level_filter: log::LevelFilter) -> Self {
MagicLeapLogger { tag, level_filter }
}
}
// Linear interpolation
impl MLVec3f {
fn lerp(&self, other: MLVec3f, t: f32) -> MLVec3f {
MLVec3f {
x: util::lerp(self.x, other.x, t),
y: util::lerp(self.y, other.y, t),
z: util::lerp(self.z, other.z, t),
}
}
}
impl MLQuaternionf {
fn lerp(&self, other: MLQuaternionf, t: f32) -> MLQuaternionf {
MLQuaternionf {
x: util::lerp(self.x, other.x, t),
y: util::lerp(self.y, other.y, t),
z: util::lerp(self.z, other.z, t),
w: util::lerp(self.w, other.w, t),
}
}
}
impl MLTransform {
fn lerp(&self, other: MLTransform, t: f32) -> MLTransform {
MLTransform {
rotation: self.rotation.lerp(other.rotation, t),
position: self.position.lerp(other.position, t),
}
}
}
// Impl pathfinder traits for c-api types
impl From<MLTransform> for Transform3DF32 {
fn from(mat: MLTransform) -> Self {
Transform3DF32::from(mat.rotation)
.pre_mul(&Transform3DF32::from(mat.position))
}
}
impl From<MLVec3f> for Transform3DF32 {
fn from(v: MLVec3f) -> Self {
Transform3DF32::from_translation(v.x, v.y, v.z)
}
}
impl From<MLRectf> for RectF32 {
fn from(r: MLRectf) -> Self {
RectF32::new(Point2DF32::new(r.x, r.y), Point2DF32::new(r.w, r.h))
}
}
impl From<MLRectf> for RectI32 {
fn from(r: MLRectf) -> Self {
RectF32::from(r).to_i32()
}
}
impl From<MLQuaternionf> for Transform3DF32 {
fn from(q: MLQuaternionf) -> Self {
Transform3DF32::from_rotation_quaternion(F32x4::new(q.x, q.y, q.z, q.w))
}
}
impl From<MLMat4f> for Transform3DF32 {
fn from(mat: MLMat4f) -> Self {
let a = mat.matrix_colmajor;
Transform3DF32::row_major(a[0], a[4], a[8], a[12],
a[1], a[5], a[9], a[13],
a[2], a[6], a[10], a[14],
a[3], a[7], a[11], a[15])
}
}

257
demo/magicleap/src/main.cpp Normal file
View File

@ -0,0 +1,257 @@
// pathfinder/demo/magicleap/src/main.cpp
//
// Copyright © 2019 The Pathfinder Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// The immersive mode pathfinder magicleap demo
#include <stdio.h>
#include <stdlib.h>
#include <chrono>
#include <cmath>
#include <unistd.h>
#include <sys/syscall.h>
#ifndef EGL_EGLEXT_PROTOTYPES
#define EGL_EGLEXT_PROTOTYPES
#endif
#include <EGL/egl.h>
#include <EGL/eglext.h>
#ifndef GL_GLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES
#endif
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
#include <ml_graphics.h>
#include <ml_head_tracking.h>
#include <ml_perception.h>
#include <ml_fileinfo.h>
#include <ml_lifecycle.h>
#include <ml_logging.h>
#include <ml_privileges.h>
// Entry points to the Rust code
extern "C" void* magicleap_pathfinder_demo_init(EGLDisplay egl_display, EGLContext egl_context);
extern "C" void magicleap_pathfinder_demo_load(void* app, const char* file_name);
extern "C" void magicleap_pathfinder_demo_run(void* app);
// Initialization of the scene thread
extern "C" void init_scene_thread(uint64_t id) {
// https://forum.magicleap.com/hc/en-us/community/posts/360043120832-How-many-CPUs-does-an-immersive-app-have-access-to-?page=1#community_comment_360005035691
// We pin scene thread 0 to the Denver core.
if (id < 3) {
uint32_t DenverCoreAffinityMask = 1 << (2 + id); // Denver core is CPU2, A57s are CPU3 and 4.
pid_t ThreadId = gettid();
syscall(__NR_sched_setaffinity, ThreadId, sizeof(DenverCoreAffinityMask), &DenverCoreAffinityMask);
}
}
// Constants
const char application_name[] = "com.mozilla.pathfinder.demo";
// Structures
struct graphics_context_t {
EGLDisplay egl_display;
EGLContext egl_context;
GLuint framebuffer_id;
GLuint vertex_shader_id;
GLuint fragment_shader_id;
GLuint program_id;
graphics_context_t();
~graphics_context_t();
void makeCurrent();
void swapBuffers();
void unmakeCurrent();
};
graphics_context_t::graphics_context_t() {
egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
EGLint major = 4;
EGLint minor = 0;
eglInitialize(egl_display, &major, &minor);
eglBindAPI(EGL_OPENGL_API);
EGLint config_attribs[] = {
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 0,
EGL_DEPTH_SIZE, 24,
EGL_STENCIL_SIZE, 8,
EGL_NONE
};
EGLConfig egl_config = nullptr;
EGLint config_size = 0;
eglChooseConfig(egl_display, config_attribs, &egl_config, 1, &config_size);
EGLint context_attribs[] = {
EGL_CONTEXT_MAJOR_VERSION_KHR, 3,
EGL_CONTEXT_MINOR_VERSION_KHR, 0,
EGL_NONE
};
egl_context = eglCreateContext(egl_display, egl_config, EGL_NO_CONTEXT, context_attribs);
}
void graphics_context_t::makeCurrent() {
eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, egl_context);
}
void graphics_context_t::unmakeCurrent() {
eglMakeCurrent(NULL, EGL_NO_SURFACE, EGL_NO_SURFACE, NULL);
}
void graphics_context_t::swapBuffers() {
// buffer swapping is implicit on device (MLGraphicsEndFrame)
}
graphics_context_t::~graphics_context_t() {
eglDestroyContext(egl_display, egl_context);
eglTerminate(egl_display);
}
// Callbacks
static void onStop(void* app)
{
ML_LOG(Info, "%s: On stop called.", application_name);
}
static void onPause(void* app)
{
ML_LOG(Info, "%s: On pause called.", application_name);
}
static void onResume(void* app)
{
ML_LOG(Info, "%s: On resume called.", application_name);
}
static void onNewInitArg(void* app)
{
ML_LOG(Info, "%s: On new init arg called.", application_name);
// Get the file argument if there is one
MLLifecycleInitArgList* arg_list = nullptr;
const MLLifecycleInitArg* arg = nullptr;
const MLFileInfo* file_info = nullptr;
const char* file_name = nullptr;
int64_t arg_list_len = 0;
int64_t file_list_len = 0;
if (MLResult_Ok != MLLifecycleGetInitArgList(&arg_list)) {
ML_LOG(Error, "%s: Failed to get init args.", application_name);
return;
}
if (MLResult_Ok != MLLifecycleGetInitArgListLength(arg_list, &arg_list_len)) {
ML_LOG(Error, "%s: Failed to get init arg length.", application_name);
return;
}
if (arg_list_len) {
if (MLResult_Ok != MLLifecycleGetInitArgByIndex(arg_list, 0, &arg)) {
ML_LOG(Error, "%s: Failed to get init arg.", application_name);
return;
}
if (MLResult_Ok != MLLifecycleGetFileInfoListLength(arg, &file_list_len)) {
ML_LOG(Error, "%s: Failed to get file list length.", application_name);
return;
}
}
if (file_list_len) {
if (MLResult_Ok != MLLifecycleGetFileInfoByIndex(arg, 0, &file_info)) {
ML_LOG(Error, "%s: Failed to get file info.", application_name);
return;
}
if (MLResult_Ok != MLFileInfoGetFileName(file_info, &file_name)) {
ML_LOG(Error, "%s: Failed to get file name.", application_name);
return;
}
}
// Tell pathfinder to load the file
magicleap_pathfinder_demo_load(app, file_name);
MLLifecycleFreeInitArgList(&arg_list);
}
extern "C" void logMessage(MLLogLevel lvl, char* msg) {
if (MLLoggingLogLevelIsEnabled(lvl)) {
MLLoggingLog(lvl, ML_DEFAULT_LOG_TAG, msg);
}
}
int main() {
// set up host-specific graphics surface
graphics_context_t graphics_context;
// Check privileges
if (MLResult_Ok != MLPrivilegesStartup()) {
ML_LOG(Error, "%s: Failed to initialize privileges.", application_name);
return -1;
}
if (MLPrivilegesRequestPrivilege(MLPrivilegeID_WorldReconstruction) != MLPrivilegesResult_Granted) {
ML_LOG(Error, "Privilege %d denied.", MLPrivilegeID_WorldReconstruction);
return -1;
}
if (MLPrivilegesRequestPrivilege(MLPrivilegeID_LowLatencyLightwear) != MLPrivilegesResult_Granted) {
ML_LOG(Error, "Privilege %d denied.", MLPrivilegeID_LowLatencyLightwear);
return -1;
}
// initialize perception system
MLPerceptionSettings perception_settings;
if (MLResult_Ok != MLPerceptionInitSettings(&perception_settings)) {
ML_LOG(Error, "%s: Failed to initialize perception.", application_name);
}
if (MLResult_Ok != MLPerceptionStartup(&perception_settings)) {
ML_LOG(Error, "%s: Failed to startup perception.", application_name);
return -1;
}
// Initialize pathfinder
void* app = magicleap_pathfinder_demo_init(graphics_context.egl_display, graphics_context.egl_context);
// let system know our app has started
MLLifecycleCallbacks lifecycle_callbacks = {};
lifecycle_callbacks.on_stop = onStop;
lifecycle_callbacks.on_pause = onPause;
lifecycle_callbacks.on_resume = onResume;
lifecycle_callbacks.on_new_initarg = onNewInitArg;
if (MLResult_Ok != MLLifecycleInit(&lifecycle_callbacks, app)) {
ML_LOG(Error, "%s: Failed to initialize lifecycle.", application_name);
return -1;
}
// Get the initial argument if there is one.
onNewInitArg(app);
// Run the demo!
ML_LOG(Info, "%s: Begin demo.", application_name);
magicleap_pathfinder_demo_run(app);
ML_LOG(Info, "%s: End demo.", application_name);
// Shut down
MLPerceptionShutdown();
return 0;
}

View File

@ -0,0 +1,98 @@
// pathfinder/demo/magicleap/src/mocked_c_api.rs
//
// Copyright © 2019 The Pathfinder Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! A mocked Rust implementation of the Magic Leap C API, to allow it to build without the ML SDK
#![allow(unused_variables)]
#![allow(dead_code)]
#![allow(non_snake_case)]
use crate::c_api::MLCoordinateFrameUID;
use crate::c_api::MLGraphicsClipExtentsInfoArray;
use crate::c_api::MLGraphicsFrameParams;
use crate::c_api::MLGraphicsOptions;
use crate::c_api::MLGraphicsRenderTargetsInfo;
use crate::c_api::MLGraphicsVirtualCameraInfoArray;
use crate::c_api::MLHandle;
use crate::c_api::MLHeadTrackingStaticData;
use crate::c_api::MLLogLevel;
use crate::c_api::MLResult;
use crate::c_api::MLSnapshotPtr;
use crate::c_api::MLTransform;
use std::os::raw::c_char;
pub unsafe fn MLGraphicsCreateClientGL(options: *const MLGraphicsOptions, gl_context: MLHandle, graphics_client : &mut MLHandle) -> MLResult {
unimplemented!()
}
pub unsafe fn MLGraphicsDestroyClient(graphics_client: *mut MLHandle) -> MLResult {
unimplemented!()
}
pub unsafe fn MLHeadTrackingCreate(tracker: *mut MLHandle) -> MLResult {
unimplemented!()
}
pub unsafe fn MLHeadTrackingGetStaticData(head_tracker: MLHandle, data: *mut MLHeadTrackingStaticData) -> MLResult {
unimplemented!()
}
pub unsafe fn MLPerceptionGetSnapshot(snapshot: *mut MLSnapshotPtr) -> MLResult {
unimplemented!()
}
pub unsafe fn MLSnapshotGetTransform(snapshot: MLSnapshotPtr, id: *const MLCoordinateFrameUID, transform: *mut MLTransform) -> MLResult {
unimplemented!()
}
pub unsafe fn MLPerceptionReleaseSnapshot(snapshot: MLSnapshotPtr) -> MLResult {
unimplemented!()
}
pub unsafe fn MLLifecycleSetReadyIndication() -> MLResult {
unimplemented!()
}
pub unsafe fn MLGraphicsGetClipExtents(graphics_client: MLHandle, array: *mut MLGraphicsClipExtentsInfoArray) -> MLResult {
unimplemented!()
}
pub unsafe fn MLGraphicsGetRenderTargets(graphics_client: MLHandle, targets: *mut MLGraphicsRenderTargetsInfo) -> MLResult {
unimplemented!()
}
pub unsafe fn MLGraphicsInitFrameParams(params: *mut MLGraphicsFrameParams) -> MLResult {
unimplemented!()
}
pub unsafe fn MLGraphicsBeginFrame(graphics_client: MLHandle, params: *const MLGraphicsFrameParams, frame_handle: *mut MLHandle, virtual_camera_array: *mut MLGraphicsVirtualCameraInfoArray) -> MLResult {
unimplemented!()
}
pub unsafe fn MLGraphicsEndFrame(graphics_client: MLHandle, frame_handle: MLHandle) -> MLResult {
unimplemented!()
}
pub unsafe fn MLGraphicsSignalSyncObjectGL(graphics_client: MLHandle, sync_object: MLHandle) -> MLResult {
unimplemented!()
}
pub unsafe fn MLGetResultString(result_code: MLResult) -> *const c_char {
unimplemented!()
}
pub unsafe fn MLLoggingLogLevelIsEnabled(lvl: MLLogLevel) -> bool {
unimplemented!()
}
pub unsafe fn MLLoggingLog(lvl: MLLogLevel, tag: *const c_char, message: *const c_char) {
unimplemented!()
}

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 269 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 134 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 59 KiB

25021
resources/svg/paper.svg Normal file

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 727 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 399 KiB