sync
This commit is contained in:
parent
2fcff3c6d9
commit
db89b19eb4
443
Cargo.lock
generated
443
Cargo.lock
generated
@ -18,6 +18,12 @@ version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046"
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.11"
|
||||
@ -40,6 +46,21 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aligned-vec"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21d3b756e34402640015c5fec93cfdb93a4d22740996674392aa7ab8b996e8b4"
|
||||
dependencies = [
|
||||
"equator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "allocator-api2"
|
||||
version = "0.2.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
|
||||
|
||||
[[package]]
|
||||
name = "android-activity"
|
||||
version = "0.5.2"
|
||||
@ -67,6 +88,21 @@ version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04"
|
||||
|
||||
[[package]]
|
||||
name = "android-tzdata"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.14"
|
||||
@ -116,6 +152,12 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
|
||||
|
||||
[[package]]
|
||||
name = "approx"
|
||||
version = "0.4.0"
|
||||
@ -224,9 +266,15 @@ checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.6.0"
|
||||
@ -313,6 +361,20 @@ version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d1d389c4b5c60ebf7955904cd19f5a225f53f42e03d4459a2d57463ed62c6a8"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"wasm-bindgen",
|
||||
"windows-targets 0.52.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clipboard-win"
|
||||
version = "3.1.1"
|
||||
@ -402,6 +464,15 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.20"
|
||||
@ -435,6 +506,22 @@ version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2"
|
||||
|
||||
[[package]]
|
||||
name = "earcutr"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79127ed59a85d7687c409e9978547cffb7dc79675355ed22da6b66fd5f6ead01"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||
|
||||
[[package]]
|
||||
name = "env_filter"
|
||||
version = "0.1.0"
|
||||
@ -458,6 +545,26 @@ dependencies = [
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equator"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c35da53b5a021d2484a7cc49b2ac7f2d840f8236a286f84202369bd338d761ea"
|
||||
dependencies = [
|
||||
"equator-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equator-macro"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3bf679796c0322556351f287a51b49e48f7c4986e727b5dd78c972d30e2e16cc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
@ -474,6 +581,22 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "float_next_after"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8bf7cc16383c4b8d58b9905a8509f02926ce3058053c056376248d958c9df1e8"
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
version = "0.5.0"
|
||||
@ -492,7 +615,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -501,6 +624,44 @@ version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b"
|
||||
|
||||
[[package]]
|
||||
name = "geo"
|
||||
version = "0.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f811f663912a69249fa620dcd2a005db7254529da2d8a0b23942e81f47084501"
|
||||
dependencies = [
|
||||
"earcutr",
|
||||
"float_next_after",
|
||||
"geo-types",
|
||||
"geographiclib-rs",
|
||||
"log",
|
||||
"num-traits",
|
||||
"robust",
|
||||
"rstar",
|
||||
"spade",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "geo-types"
|
||||
version = "0.7.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ff16065e5720f376fbced200a5ae0f47ace85fd70b7e54269790281353b6d61"
|
||||
dependencies = [
|
||||
"approx 0.5.1",
|
||||
"num-traits",
|
||||
"rstar",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "geographiclib-rs"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6e5ed84f8089c70234b0a8e0aedb6dc733671612ddc0d37c6066052f9781960"
|
||||
dependencies = [
|
||||
"libm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gethostname"
|
||||
version = "0.4.3"
|
||||
@ -610,11 +771,34 @@ dependencies = [
|
||||
"gl_generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hash32"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"allocator-api2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heapless"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
|
||||
dependencies = [
|
||||
"hash32",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
@ -628,6 +812,29 @@ version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icrate"
|
||||
version = "0.0.4"
|
||||
@ -720,6 +927,21 @@ version = "1.70.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
||||
|
||||
[[package]]
|
||||
name = "jni"
|
||||
version = "0.21.1"
|
||||
@ -788,6 +1010,12 @@ dependencies = [
|
||||
"windows-targets 0.52.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.0.2"
|
||||
@ -870,6 +1098,15 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mint"
|
||||
version = "0.5.9"
|
||||
@ -887,7 +1124,23 @@ dependencies = [
|
||||
"num-complex",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
"simba",
|
||||
"simba 0.8.1",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nalgebra"
|
||||
version = "0.33.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c4b5f057b303842cf3262c27e465f4c303572e7f6b0648f60e16248ac3397f4"
|
||||
dependencies = [
|
||||
"approx 0.5.1",
|
||||
"matrixmultiply",
|
||||
"nalgebra-macros",
|
||||
"num-complex",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
"simba 0.9.0",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
@ -898,9 +1151,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e68879ff227a94627e63bbd518b4f82b8f0cc56bb01a498251507de6d1c412d6"
|
||||
dependencies = [
|
||||
"approx 0.5.1",
|
||||
"nalgebra",
|
||||
"nalgebra 0.32.5",
|
||||
"num-traits",
|
||||
"simba",
|
||||
"simba 0.8.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nalgebra-macros"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ndarray"
|
||||
version = "0.15.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adb12d4e967ec485a5f71c6311fe28158e9d6f4bc4a447b474184d0f91a8fa32"
|
||||
dependencies = [
|
||||
"matrixmultiply",
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"rawpointer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -944,6 +1221,38 @@ dependencies = [
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom-derive"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ff943d68b88d0b87a6e0d58615e8fa07f9fd5a1319fa0a72efc1f62275c79a7"
|
||||
dependencies = [
|
||||
"nom",
|
||||
"nom-derive-impl",
|
||||
"rustversion",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom-derive-impl"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd0b9a93a84b0d3ec3e70e02d332dc33ac6dfac9cde63e17fcb77172dededa62"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
|
||||
dependencies = [
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.6"
|
||||
@ -968,6 +1277,7 @@ version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
@ -979,6 +1289,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"libm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -999,7 +1310,7 @@ dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1179,10 +1490,16 @@ dependencies = [
|
||||
name = "radar-g"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"aligned-vec",
|
||||
"anyhow",
|
||||
"bytemuck",
|
||||
"byteorder",
|
||||
"cgmath",
|
||||
"chrono",
|
||||
"copypasta",
|
||||
"env_logger",
|
||||
"flate2",
|
||||
"geo",
|
||||
"glow",
|
||||
"glutin",
|
||||
"glutin-winit",
|
||||
@ -1191,11 +1508,16 @@ dependencies = [
|
||||
"imgui-winit-support",
|
||||
"include_dir",
|
||||
"log",
|
||||
"nalgebra 0.33.0",
|
||||
"nalgebra-glm",
|
||||
"ndarray",
|
||||
"nom",
|
||||
"nom-derive",
|
||||
"once_cell",
|
||||
"raw-window-handle 0.5.2",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"winit",
|
||||
]
|
||||
@ -1274,6 +1596,23 @@ version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
|
||||
|
||||
[[package]]
|
||||
name = "robust"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cbf4a6aa5f6d6888f39e980649f3ad6b666acdce1d78e95b8a2cb076e687ae30"
|
||||
|
||||
[[package]]
|
||||
name = "rstar"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "133315eb94c7b1e8d0cb097e5a710d850263372fd028fff18969de708afc7008"
|
||||
dependencies = [
|
||||
"heapless",
|
||||
"num-traits",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.34"
|
||||
@ -1287,6 +1626,18 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
||||
|
||||
[[package]]
|
||||
name = "safe_arch"
|
||||
version = "0.7.1"
|
||||
@ -1332,22 +1683,33 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.203"
|
||||
version = "1.0.204"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
|
||||
checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.203"
|
||||
version = "1.0.204"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
|
||||
checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.120"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1363,6 +1725,19 @@ dependencies = [
|
||||
"wide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simba"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b3a386a501cd104797982c15ae17aafe8b9261315b5d07e3ec803f2ea26be0fa"
|
||||
dependencies = [
|
||||
"approx 0.5.1",
|
||||
"num-complex",
|
||||
"num-traits",
|
||||
"paste",
|
||||
"wide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.9"
|
||||
@ -1432,12 +1807,41 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spade"
|
||||
version = "2.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f4ec45f91925e2c9ab3b6a857ee9ed36916990df76a1c475d783a328e247cc8"
|
||||
dependencies = [
|
||||
"hashbrown",
|
||||
"num-traits",
|
||||
"robust",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||
|
||||
[[package]]
|
||||
name = "strict-num"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.66"
|
||||
@ -1466,7 +1870,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1600,7 +2004,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.66",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@ -1634,7 +2038,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.66",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@ -1815,6 +2219,15 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.45.0"
|
||||
@ -2168,5 +2581,5 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.66",
|
||||
]
|
||||
|
||||
11
Cargo.toml
11
Cargo.toml
@ -24,3 +24,14 @@ thiserror = "1.0.61"
|
||||
log = "0.4.22"
|
||||
env_logger = "0.11.3"
|
||||
bytemuck = { version = "1.16.1", features = ["derive"] }
|
||||
nalgebra = "0.33.0"
|
||||
nom-derive = "0.10.1"
|
||||
serde = { version = "1.0.204", features = ["derive"] }
|
||||
byteorder = "1.5.0"
|
||||
chrono = "0.4.38"
|
||||
flate2 = "1.0.30"
|
||||
anyhow = "1.0.86"
|
||||
serde_json = "1.0.120"
|
||||
geo = "0.28.0"
|
||||
ndarray = "0.15.6"
|
||||
aligned-vec = "0.6.0"
|
||||
|
||||
@ -11,6 +11,8 @@ in float v_distance;
|
||||
in float v_linewidth;
|
||||
in float v_antialias;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
// Main
|
||||
// ------------------------------------
|
||||
void main()
|
||||
@ -18,5 +20,5 @@ void main()
|
||||
<viewport.clipping()>;
|
||||
|
||||
if (v_color.a == 0) { discard; }
|
||||
gl_FragColor = stroke(v_distance, v_linewidth, v_antialias, v_color);
|
||||
FragColor = stroke(v_distance, v_linewidth, v_antialias, v_color);
|
||||
}
|
||||
@ -31,7 +31,9 @@ out vec4 v_color;
|
||||
void main ()
|
||||
{
|
||||
// This function is externally generated
|
||||
fetch_uniforms();
|
||||
// fetch_uniforms();
|
||||
|
||||
float id = gl_VertexID;
|
||||
v_linewidth = linewidth;
|
||||
v_antialias = antialias;
|
||||
v_color = color;
|
||||
|
||||
19
shaders/colormap.glsl
Normal file
19
shaders/colormap.glsl
Normal file
@ -0,0 +1,19 @@
|
||||
uniform sampler1D colormap;
|
||||
uniform vec4 conf;
|
||||
|
||||
vec4 linear_colormap(float value)
|
||||
{
|
||||
float vmin = conf.x;
|
||||
float vmax = conf.y;
|
||||
float count = conf.z - 1.0;
|
||||
|
||||
float invalid = conf.w;
|
||||
|
||||
if (value == invalid) {
|
||||
return vec4(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
float v = clamp((value - vmin), vmin, vmax) / (vmax - vmin);
|
||||
vec4 result = texture(colormap, v);
|
||||
return result;
|
||||
}
|
||||
19
shaders/hello.frag
Normal file
19
shaders/hello.frag
Normal file
@ -0,0 +1,19 @@
|
||||
in vec2 vert;
|
||||
in vec4 color;
|
||||
|
||||
out vec4 frag_color;
|
||||
|
||||
vec4 linear_to_srgb(vec4 linear_color) {
|
||||
vec3 linear = linear_color.rgb;
|
||||
vec3 selector = ceil(linear - 0.0031308);
|
||||
vec3 less_than_branch = linear * 12.92;
|
||||
vec3 greater_than_branch = pow(linear, vec3(1.0/2.4)) * 1.055 - 0.055;
|
||||
return vec4(
|
||||
mix(less_than_branch, greater_than_branch, selector),
|
||||
linear_color.a
|
||||
);
|
||||
}
|
||||
|
||||
void main() {
|
||||
frag_color = linear_to_srgb(color);
|
||||
}
|
||||
29
shaders/hello.vert
Normal file
29
shaders/hello.vert
Normal file
@ -0,0 +1,29 @@
|
||||
uniform mat4 projection;
|
||||
uniform mat4 view;
|
||||
|
||||
const vec2 verts[3] = vec2[3](
|
||||
vec2(0.5f, 1.0f),
|
||||
vec2(0.0f, 0.0f),
|
||||
vec2(1.0f, 0.0f)
|
||||
);
|
||||
|
||||
out vec2 vert;
|
||||
out vec4 color;
|
||||
|
||||
vec4 srgb_to_linear(vec4 srgb_color) {
|
||||
// Calcuation as documented by OpenGL
|
||||
vec3 srgb = srgb_color.rgb;
|
||||
vec3 selector = ceil(srgb - 0.04045);
|
||||
vec3 less_than_branch = srgb / 12.92;
|
||||
vec3 greater_than_branch = pow((srgb + 0.055) / 1.055, vec3(2.4));
|
||||
return vec4(
|
||||
mix(less_than_branch, greater_than_branch, selector),
|
||||
srgb_color.a
|
||||
);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vert = verts[gl_VertexID];
|
||||
color = srgb_to_linear(vec4(vert, 0.5, 1.0));
|
||||
gl_Position = vec4(vert - 0.5, 0.0, 1.0);
|
||||
}
|
||||
32
shaders/ppi.frag
Normal file
32
shaders/ppi.frag
Normal file
@ -0,0 +1,32 @@
|
||||
#include "transform/polar.glsl"
|
||||
|
||||
in float x;
|
||||
in float y;
|
||||
|
||||
in float value;
|
||||
flat in vec4 vrange;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
void main() {
|
||||
|
||||
vec4 inversed = inverse(x, y);
|
||||
|
||||
|
||||
if (inversed.x < vrange.x || inversed.x > vrange.z) {
|
||||
discard;
|
||||
}
|
||||
|
||||
vec4 result = <colormap(value)>;
|
||||
|
||||
if (result.w == 0.0) {
|
||||
discard;
|
||||
}
|
||||
|
||||
// result = texture(colormap_2, 1.0);
|
||||
|
||||
// vec4 result = vec4(value /10.0, value / 10.0, 1.0, value / 10.0);
|
||||
|
||||
|
||||
FragColor = result;
|
||||
}
|
||||
61
shaders/ppi.geom
Normal file
61
shaders/ppi.geom
Normal file
@ -0,0 +1,61 @@
|
||||
#include "transform/polar.glsl"
|
||||
|
||||
layout(points) in;
|
||||
layout(triangle_strip, max_vertices = 4) out;
|
||||
|
||||
// conf: Range, Elevation, Resolution, 0.0
|
||||
uniform vec4 conf;
|
||||
in float in_value[];
|
||||
|
||||
out float x;
|
||||
out float y;
|
||||
out float value;
|
||||
|
||||
flat out vec4 vrange;
|
||||
|
||||
|
||||
void main() {
|
||||
vec4 reso = vec4(conf.x/2.0, conf.y/2.0 * radian, 0.0, 0.0);
|
||||
vec4 loc;
|
||||
float c = cos(reso.y);
|
||||
|
||||
vec4 po = gl_in[0].gl_Position;
|
||||
po.y = po.y * radian;
|
||||
|
||||
vrange = vec4(po.x - reso.x, po.y - reso.y, po.x + reso.x, po.y + reso.y);
|
||||
value = in_value[0];
|
||||
|
||||
gl_Position = po - reso;
|
||||
loc = forward(gl_Position);
|
||||
x = loc.x;
|
||||
y = loc.y;
|
||||
gl_Position = <transform(loc)>;
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = po + vec4(reso.x, -reso.y, 0.0, 0.0);
|
||||
gl_Position.x = gl_Position.x / c;
|
||||
loc = forward(gl_Position);
|
||||
x = loc.x;
|
||||
y = loc.y;
|
||||
gl_Position = <transform(loc)>;
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = po + vec4(-reso.x, reso.y, 0.0, 0.0);
|
||||
loc = forward(gl_Position);
|
||||
x = loc.x;
|
||||
y = loc.y;
|
||||
gl_Position = <transform(loc)>;
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = po + reso;
|
||||
gl_Position.x = gl_Position.x / c;
|
||||
loc = forward(gl_Position);
|
||||
x = loc.x;
|
||||
y = loc.y;
|
||||
gl_Position = <transform(loc)>;
|
||||
EmitVertex();
|
||||
|
||||
EndPrimitive();
|
||||
|
||||
}
|
||||
|
||||
8
shaders/ppi.vert
Normal file
8
shaders/ppi.vert
Normal file
@ -0,0 +1,8 @@
|
||||
// Layout
|
||||
layout(location = 0) in vec3 position;
|
||||
out float in_value;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(position.x, position.y, 0.0, 1.0);
|
||||
in_value = position.z;
|
||||
}
|
||||
@ -1,7 +1,8 @@
|
||||
use glow::HasContext;
|
||||
use glow::{HasContext, NativeUniformLocation};
|
||||
|
||||
use super::shader::Shader;
|
||||
use super::snippets::{CodeType, Snippet};
|
||||
use crate::components::CodeComponent;
|
||||
use crate::graphics::transforms::{viewport::Viewport, Transform};
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -43,6 +44,7 @@ impl Program {
|
||||
pub fn set_hook(&mut self, hook: &str, code: &Snippet) {
|
||||
self.vertex.set_hook(hook, code);
|
||||
self.fragment.set_hook(hook, code);
|
||||
self.geometry.as_mut().map(|g| g.set_hook(hook, code));
|
||||
}
|
||||
|
||||
pub fn set_transform<T: Transform>(&mut self, value: &T) {
|
||||
@ -55,25 +57,48 @@ impl Program {
|
||||
|
||||
pub fn compile(&mut self, gl: &glow::Context) -> crate::errors::Result<()> {
|
||||
use crate::errors::Error;
|
||||
unsafe {
|
||||
// let vertex_array = gl
|
||||
// .create_vertex_array()
|
||||
// .expect("Cannot create vertex array");
|
||||
|
||||
self.vertex.define("_GLUMPY__VERTEX_SHADER__");
|
||||
self.fragment.define("_GLUMPY__FRAGMENT_SHADER__");
|
||||
|
||||
unsafe {
|
||||
let program = gl.create_program().map_err(|e| Error::InvalidProgram(e))?;
|
||||
|
||||
let vertex_shader =
|
||||
self.create_shader(gl, &self.vertex.to_string(),self.version, glow::VERTEX_SHADER);
|
||||
let fragment_shader =
|
||||
self.create_shader(gl, &self.fragment.to_string(),self.version, glow::FRAGMENT_SHADER);
|
||||
let vertex_shader = self.vertex.compile(&self.version, gl);
|
||||
let fragment_shader = self.fragment.compile(&self.version, gl);
|
||||
|
||||
gl.attach_shader(program, vertex_shader);
|
||||
gl.attach_shader(program, fragment_shader);
|
||||
|
||||
// Geom Shader
|
||||
let geom_shader = if let Some(geometry) = self.geometry.as_mut() {
|
||||
geometry.define("_GLUMPY__GEOMETRY_SHADER__");
|
||||
let geometry_shader = geometry.compile(&self.version, gl);
|
||||
|
||||
gl.attach_shader(program, geometry_shader);
|
||||
|
||||
Some(geometry_shader)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
gl.link_program(program);
|
||||
|
||||
if !gl.get_program_link_status(program) {
|
||||
return Err(Error::InvalidProgram(gl.get_program_info_log(program)));
|
||||
}
|
||||
|
||||
gl.detach_shader(program, vertex_shader);
|
||||
gl.detach_shader(program, fragment_shader);
|
||||
if let Some(_) = self.geometry.as_ref() {
|
||||
gl.detach_shader(program, geom_shader.unwrap());
|
||||
gl.delete_shader(geom_shader.unwrap());
|
||||
}
|
||||
|
||||
gl.delete_shader(vertex_shader);
|
||||
gl.delete_shader(fragment_shader);
|
||||
|
||||
gl.use_program(Some(program));
|
||||
|
||||
self.native_program = Some(program);
|
||||
}
|
||||
@ -81,42 +106,24 @@ impl Program {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_shader(
|
||||
&self,
|
||||
gl: &glow::Context,
|
||||
code: &str,
|
||||
version: &'static str,
|
||||
shader_type: u32,
|
||||
) -> <glow::Context as HasContext>::Shader {
|
||||
let shader = unsafe {
|
||||
let shader = gl
|
||||
.create_shader(glow::VERTEX_SHADER)
|
||||
.expect("Cannot create shader");
|
||||
gl.shader_source(
|
||||
shader,
|
||||
&format!("{}\n{}", &format!("#version {}", self.version), code),
|
||||
);
|
||||
gl.compile_shader(shader);
|
||||
if !gl.get_shader_compile_status(shader) {
|
||||
panic!("{}", gl.get_shader_info_log(shader))
|
||||
}
|
||||
shader
|
||||
};
|
||||
shader
|
||||
}
|
||||
|
||||
pub fn destroy(&self, gl: &glow::Context) {
|
||||
unsafe {
|
||||
self.native_program.map(|p| gl.delete_program(p));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render(&self, gl: &glow::Context) {
|
||||
unsafe {
|
||||
gl.clear_color(0.05, 0.05, 0.1, 1.0);
|
||||
gl.clear(glow::COLOR_BUFFER_BIT);
|
||||
gl.use_program(self.native_program);
|
||||
}
|
||||
pub fn get_uniform_location(
|
||||
&self,
|
||||
gl: &glow::Context,
|
||||
name: &str,
|
||||
) -> Option<NativeUniformLocation> {
|
||||
self.native_program
|
||||
.as_ref()
|
||||
.map(|p| unsafe {
|
||||
let location = gl.get_uniform_location(*p, name);
|
||||
location
|
||||
})
|
||||
.flatten()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6,14 +6,14 @@ use super::{
|
||||
};
|
||||
use crate::{
|
||||
errors::{Error, Result},
|
||||
utils::{find_file, CodeBlock},
|
||||
utils::{find_file, Code, CodeBlock},
|
||||
};
|
||||
use glow::HasContext;
|
||||
use log::{info, warn};
|
||||
pub use utils::fetchcode;
|
||||
pub type ShaderType = u32;
|
||||
#[derive(Debug)]
|
||||
pub struct Shader {
|
||||
code: String,
|
||||
target: u32,
|
||||
parsed: CodeBlock,
|
||||
pub hooks: Vec<String>,
|
||||
@ -27,7 +27,7 @@ impl std::fmt::Display for Shader {
|
||||
|
||||
impl Shader {
|
||||
pub fn new<S: Borrow<str>>(target: ShaderType, code: CodeType<S>) -> Result<Self> {
|
||||
let mut code = match code {
|
||||
let code = match code {
|
||||
CodeType::Code(code) => code.borrow().to_string(),
|
||||
CodeType::Path(path) => {
|
||||
let code = find_file(path).expect("Failed to find file");
|
||||
@ -35,21 +35,6 @@ impl Shader {
|
||||
}
|
||||
};
|
||||
|
||||
match target {
|
||||
|
||||
glow::VERTEX_SHADER => {
|
||||
code.insert_str(0, "#define _GLUMPY__VERTEX_SHADER__\n");
|
||||
}
|
||||
|
||||
glow::FRAGMENT_SHADER => {
|
||||
code.insert_str(0, "#define _GLUMPY__FRAGMENT_SHADER__\n");
|
||||
}
|
||||
|
||||
_ => {
|
||||
warn!("Unknown shader type: {}", target);
|
||||
}
|
||||
}
|
||||
|
||||
let code = merge_includes(code).map_err(|e| Error::InvalidSnippet(e.to_string()))?;
|
||||
let parsed = CodeBlock::new(&code)?;
|
||||
|
||||
@ -58,17 +43,43 @@ impl Shader {
|
||||
|
||||
Ok(Self {
|
||||
target,
|
||||
code,
|
||||
parsed,
|
||||
hooks,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn compile(&self) {}
|
||||
pub fn compile(
|
||||
&self,
|
||||
version: &str,
|
||||
gl: &glow::Context,
|
||||
) -> <glow::Context as HasContext>::Shader {
|
||||
let shader = unsafe {
|
||||
let shader = gl.create_shader(self.target).expect("Cannot create shader");
|
||||
gl.shader_source(
|
||||
shader,
|
||||
&format!("{}\n{}", &format!("#version {}", version), self.to_string()),
|
||||
);
|
||||
gl.compile_shader(shader);
|
||||
if !gl.get_shader_compile_status(shader) {
|
||||
panic!("{}", gl.get_shader_info_log(shader))
|
||||
}
|
||||
shader
|
||||
};
|
||||
shader
|
||||
}
|
||||
|
||||
pub fn define(&mut self, s: &str) {
|
||||
self.parsed
|
||||
.insert(Code::new(&format!("#define {}\n", s)), 0);
|
||||
}
|
||||
|
||||
pub fn set_hook(&mut self, hook: &str, code: &Snippet) {
|
||||
self.parsed.set_hook(hook, code);
|
||||
}
|
||||
|
||||
pub fn target(&self) -> u32 {
|
||||
self.target
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeComponent for Shader {
|
||||
|
||||
14
src/data_loader/error.rs
Normal file
14
src/data_loader/error.rs
Normal file
@ -0,0 +1,14 @@
|
||||
use thiserror::Error;
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ETWSError {
|
||||
#[error("IO Error")]
|
||||
IOError {
|
||||
#[from]
|
||||
source: std::io::Error,
|
||||
},
|
||||
#[error("Format Error")]
|
||||
FormatError {
|
||||
#[from]
|
||||
source: anyhow::Error,
|
||||
},
|
||||
}
|
||||
260
src/data_loader/mod.rs
Normal file
260
src/data_loader/mod.rs
Normal file
@ -0,0 +1,260 @@
|
||||
use crate::errors::*;
|
||||
use crate::utils::geo_tools::calculate_coverage;
|
||||
use ndarray::ArrayD;
|
||||
pub mod error;
|
||||
mod parser;
|
||||
|
||||
use chrono::Utc;
|
||||
|
||||
macro_rules! block_prepare {
|
||||
($data: ident, $_ty: ty, $shape:ident, $(($branch: tt),)+) => {
|
||||
match $data {
|
||||
$(
|
||||
$branch(data) => ArrayD::from_shape_vec($shape.as_slice(), data.into_iter().map(|b| b as $_ty).collect::<Vec<$_ty>>()).unwrap(),
|
||||
)+
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! block_data_type_prepare {
|
||||
($data: ident, $($branch: tt => $data_type: tt,)+) => {
|
||||
match $data {
|
||||
$(
|
||||
$branch => $data_type,
|
||||
)+
|
||||
_ => DataType::Unknown
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Data {
|
||||
pub filetime: chrono::DateTime<Utc>,
|
||||
pub radar_info: RadarInfo,
|
||||
pub blocks: Vec<Block>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum DataType {
|
||||
ET,
|
||||
VIL,
|
||||
EB,
|
||||
DBZ,
|
||||
VEl,
|
||||
ZDR,
|
||||
PHIDP,
|
||||
KDP,
|
||||
CC,
|
||||
HCA,
|
||||
QPE,
|
||||
QPF,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Block {
|
||||
pub data: ArrayD<f32>,
|
||||
pub data_type: DataType,
|
||||
pub coord_type: CoordType,
|
||||
pub min_value: f32,
|
||||
pub max_value: f32,
|
||||
pub unvalid_value: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum CoordType {
|
||||
Polar {
|
||||
azimuth_range: [f64; 2],
|
||||
r_range: [f64; 2],
|
||||
elevation_range: [f64; 2],
|
||||
azimuth: Vec<f32>,
|
||||
r: Vec<f32>,
|
||||
elevation: Vec<f32>,
|
||||
},
|
||||
Cartesian {
|
||||
lat_range: [f64; 2],
|
||||
lon_range: [f64; 2],
|
||||
hgt_range: [f64; 2],
|
||||
lat: Vec<f32>,
|
||||
lon: Vec<f32>,
|
||||
hgt: Vec<f32>,
|
||||
},
|
||||
|
||||
Other,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RadarInfo {
|
||||
pub lat_range: [f32; 2],
|
||||
pub lon_range: [f32; 2],
|
||||
pub center: [f32; 3],
|
||||
}
|
||||
|
||||
impl Data {
|
||||
pub fn from_path(path: impl AsRef<std::path::Path>) -> Result<Self> {
|
||||
let record = parser::Record::parse_from_path(path)?;
|
||||
|
||||
let mut radar_loc: [Option<f64>; 3] = [None, None, None];
|
||||
|
||||
let blocks = record
|
||||
.blocks
|
||||
.into_iter()
|
||||
.map(|b| {
|
||||
let vec_data = b.data;
|
||||
use parser::ValueResult::*;
|
||||
|
||||
let info = b.info;
|
||||
|
||||
radar_loc = [info.radar_alt, info.radar_lat, info.radar_lon];
|
||||
let shape = info
|
||||
.dimension_size
|
||||
.into_iter()
|
||||
.map(|s| s as usize)
|
||||
.collect::<Vec<usize>>();
|
||||
|
||||
let new_data = block_prepare!(
|
||||
vec_data,
|
||||
f32,
|
||||
shape,
|
||||
(I64),
|
||||
(F64),
|
||||
(I32),
|
||||
(F32),
|
||||
(I16),
|
||||
(U64),
|
||||
(U32),
|
||||
(I8),
|
||||
(U8),
|
||||
);
|
||||
|
||||
let dim_len = info.dimension_values.len();
|
||||
let dim_last = info.dimension_values.get(dim_len - 1).unwrap();
|
||||
let dim_minus_one = info.dimension_values.get(dim_len - 2).unwrap();
|
||||
let (dim_minus_two_range, dim_minus_two) = if dim_len == 3 {
|
||||
let hgt = info.dimension_values.get(dim_len - 3).unwrap();
|
||||
(
|
||||
[hgt[0], hgt[hgt.len() - 1]],
|
||||
hgt.iter().map(|v| *v as f32).collect(),
|
||||
)
|
||||
} else {
|
||||
([0.0, 0.0], vec![])
|
||||
};
|
||||
|
||||
let dim_last_range = [dim_last[0], dim_last[dim_last.len() - 1]];
|
||||
let dim_minus_one_range =
|
||||
[dim_minus_one[0], dim_minus_one[dim_minus_one.len() - 1]];
|
||||
|
||||
let coord_type = if info.dimension_des.contains(&format!("lat")) {
|
||||
CoordType::Cartesian {
|
||||
lat_range: dim_minus_one_range,
|
||||
lon_range: dim_last_range,
|
||||
hgt_range: dim_minus_two_range,
|
||||
lat: dim_minus_one.iter().map(|v| *v as f32).collect(),
|
||||
lon: dim_last.iter().map(|v| *v as f32).collect(),
|
||||
hgt: dim_minus_two,
|
||||
}
|
||||
} else if info.dimension_des.contains(&format!("ele"))
|
||||
|| info.dimension_des.contains(&format!("el"))
|
||||
|| info.dimension_des.contains(&format!("elevation"))
|
||||
{
|
||||
CoordType::Polar {
|
||||
azimuth_range: dim_minus_one_range,
|
||||
r_range: dim_last_range,
|
||||
elevation_range: dim_minus_two_range,
|
||||
azimuth: dim_minus_one.iter().map(|v| *v as f32).collect(),
|
||||
r: dim_last.iter().map(|v| *v as f32).collect(),
|
||||
elevation: dim_minus_two,
|
||||
}
|
||||
} else {
|
||||
CoordType::Other
|
||||
};
|
||||
|
||||
use DataType::*;
|
||||
let valuetype = info.value_type.as_str();
|
||||
|
||||
let data_type = block_data_type_prepare!(valuetype,
|
||||
"ET" => ET,
|
||||
"VIL" => VIL,
|
||||
"EB" => EB,
|
||||
"DBZ" =>DBZ,
|
||||
"CR" => DBZ,
|
||||
"R" => DBZ,
|
||||
"V" => VEl,
|
||||
"ZDR" => ZDR,
|
||||
"PHIDP" => PHIDP,
|
||||
"KDP" => KDP,
|
||||
"CC" => CC,
|
||||
"HCA" => HCA,
|
||||
"QPE" => QPE,
|
||||
"QPF" => QPF,
|
||||
"FR" => DBZ,
|
||||
);
|
||||
|
||||
Block {
|
||||
data: new_data,
|
||||
data_type,
|
||||
coord_type,
|
||||
min_value: 0.0,
|
||||
max_value: 204.0,
|
||||
unvalid_value: info.fill_value as f32,
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let radar_info = match blocks.first().unwrap().coord_type {
|
||||
CoordType::Cartesian {
|
||||
lat_range,
|
||||
lon_range,
|
||||
..
|
||||
} => RadarInfo {
|
||||
lat_range: [lat_range[0] as f32, lat_range[1] as f32],
|
||||
lon_range: [lon_range[0] as f32, lon_range[1] as f32],
|
||||
center: [
|
||||
lat_range[0] as f32 + (lat_range[1] - lat_range[0]) as f32 / 2.0,
|
||||
lon_range[0] as f32 + (lon_range[1] - lon_range[0]) as f32 / 2.0,
|
||||
0.0,
|
||||
],
|
||||
},
|
||||
CoordType::Polar { r_range, .. } => {
|
||||
let (min_lat, max_lat, min_lon, max_lon) =
|
||||
calculate_coverage(radar_loc[1].unwrap(), radar_loc[2].unwrap(), r_range[1]);
|
||||
|
||||
RadarInfo {
|
||||
lat_range: [min_lat as f32, max_lat as f32],
|
||||
lon_range: [min_lon as f32, max_lon as f32],
|
||||
center: [
|
||||
radar_loc[1].unwrap() as f32,
|
||||
radar_loc[2].unwrap() as f32,
|
||||
radar_loc[0].unwrap() as f32,
|
||||
],
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
panic!("Unknown coord type");
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
filetime: record.filetime,
|
||||
blocks,
|
||||
radar_info,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_data_slice(&self, index: usize) -> Option<&[f32]> {
|
||||
self.blocks.get(index).map(|b| b.data.as_slice().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
mod test {
|
||||
use super::Data;
|
||||
|
||||
#[test]
|
||||
fn test_load() {
|
||||
// let path = "/Volumes/data6/RadarArray/ShaoXing/radarData/OutputProducts/RadarProducts/FuseDataX/20030506/ZJSXAA_20030506200000_FR.dat.gz";
|
||||
let path = "/Users/tsuki/Desktop/ZJSXAA_20230627163400_VIL.dat.gz";
|
||||
|
||||
let data = Data::from_path(path).unwrap();
|
||||
println!("{:?}", data);
|
||||
}
|
||||
}
|
||||
388
src/data_loader/parser.rs
Normal file
388
src/data_loader/parser.rs
Normal file
@ -0,0 +1,388 @@
|
||||
use super::error::ETWSError;
|
||||
use aligned_vec::AVec;
|
||||
use byteorder::{BigEndian, ByteOrder, LittleEndian};
|
||||
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||
use flate2::read::GzDecoder;
|
||||
use nom::{
|
||||
bytes::complete::{tag, take},
|
||||
multi::count,
|
||||
IResult,
|
||||
};
|
||||
use nom_derive::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::path::Path;
|
||||
|
||||
pub enum ValueResult {
|
||||
I64(Vec<i64>),
|
||||
F64(Vec<f64>),
|
||||
I32(Vec<i32>),
|
||||
F32(Vec<f32>),
|
||||
I16(Vec<i16>),
|
||||
U64(Vec<u64>),
|
||||
U32(Vec<u32>),
|
||||
I8(Vec<i8>),
|
||||
U8(Vec<u8>),
|
||||
}
|
||||
|
||||
enum ValueTypes {
|
||||
I64,
|
||||
F64,
|
||||
I32,
|
||||
F32,
|
||||
U64,
|
||||
U32,
|
||||
I16,
|
||||
I8,
|
||||
U8,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum Order {
|
||||
BigEndian,
|
||||
LittleEndian,
|
||||
}
|
||||
|
||||
pub struct Record {
|
||||
pub filetime: DateTime<Utc>,
|
||||
pub blocks: Vec<ParsedBlock>, // Fill in generic types appropriately
|
||||
}
|
||||
|
||||
macro_rules! match_in_macro {
|
||||
($block:ident,$len:ident,$input:ident,$offset:ident,$scale:ident,$fill_value:ident,$(($branch:path, $t:ty, $bigger:ty,$raw_result:path, $bigger_result:path)),+) => {
|
||||
{
|
||||
use std::mem;
|
||||
let need_trans = $offset != 0.0 || $scale != 1.0;
|
||||
let trans_to_bigger = $offset.trunc() != $offset || $scale != 1.0;
|
||||
match $block {
|
||||
$(
|
||||
$branch => {
|
||||
let ratio = mem::size_of::<$t>() / mem::size_of::<u8>();
|
||||
let (input, result) = take($len * ratio)($input)?;
|
||||
|
||||
let result = unsafe {
|
||||
|
||||
let mut ptr = result.as_ptr() as *const u8;
|
||||
let aligned = ptr.align_offset(mem::align_of::<$t>());
|
||||
|
||||
if aligned != 0 {
|
||||
let p = AVec::<u8>::from_slice(mem::align_of::<$t>(), result);
|
||||
ptr = p.into_raw_parts().0;
|
||||
}
|
||||
|
||||
let ptr = ptr.cast::<$t>();
|
||||
|
||||
let slice = std::slice::from_raw_parts(ptr, $len);
|
||||
let slice = slice.to_vec();
|
||||
|
||||
if trans_to_bigger {
|
||||
let offset = $offset as $bigger;
|
||||
let scale = $scale as $bigger;
|
||||
$bigger_result(
|
||||
slice
|
||||
.into_iter()
|
||||
.map(|p| if (p as f64 - $fill_value).abs() < f64::EPSILON {p as $bigger} else {(p as $bigger - offset) / scale} )
|
||||
.collect::<Vec<$bigger>>(),
|
||||
)
|
||||
} else {
|
||||
$raw_result(if need_trans {
|
||||
let offset = $offset as $t;
|
||||
slice.into_iter().map(|p| if (p as f64 - $fill_value).abs() < f64::EPSILON {p} else {p - offset}).collect::<Vec<$t>>()
|
||||
} else {
|
||||
slice
|
||||
})
|
||||
}
|
||||
};
|
||||
Ok((input, result))
|
||||
},
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
impl Record {
|
||||
pub fn parse_from_path(path: impl AsRef<Path>) -> Result<Self, ETWSError> {
|
||||
let path = path.as_ref();
|
||||
if !(path.ends_with(".dat") || !path.ends_with(".dat.gz")) {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidInput,
|
||||
"Invalid file extension",
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
if !path.exists() {
|
||||
return Err(std::io::Error::new(std::io::ErrorKind::NotFound, "File not found").into());
|
||||
}
|
||||
|
||||
let mut file = File::open(path)?;
|
||||
let binary_data = if path.extension().unwrap() == "gz" {
|
||||
let mut result: Vec<u8> = Vec::new();
|
||||
let mut decoder = GzDecoder::new(file);
|
||||
decoder.read_to_end(&mut result)?;
|
||||
result
|
||||
} else {
|
||||
let mut result = Vec::new();
|
||||
file.read_to_end(&mut result)?;
|
||||
result
|
||||
};
|
||||
|
||||
let (_, parsed) =
|
||||
Self::_parse(binary_data.as_slice()).map_err(|_| anyhow::Error::msg("Parse error"))?;
|
||||
|
||||
Ok(parsed)
|
||||
}
|
||||
|
||||
fn _parse(binary_data: &[u8]) -> IResult<&[u8], Record> {
|
||||
let start_tag = b"UNI_DATA";
|
||||
let (input, _) = tag(start_tag)(binary_data)?;
|
||||
let (input, order) = Self::_parse_split_fn(input, 8, 8, Self::_parse_order)?;
|
||||
let (input, hlen) = take(4usize)(input)?;
|
||||
|
||||
let hlen = match order {
|
||||
Order::BigEndian => BigEndian::read_u32(hlen),
|
||||
_ => LittleEndian::read_u32(hlen),
|
||||
};
|
||||
let (input, record_info) = Self::_parse_split_fn(input, 0, 8, |input| {
|
||||
let (input, p) = take(hlen)(input)?;
|
||||
let p: RecordInfo = serde_json::from_slice(p).unwrap();
|
||||
Ok((input, p))
|
||||
})?;
|
||||
|
||||
let (input, blocks) =
|
||||
count(Self::_parse_block_fn(order), record_info.block_num as usize)(input)?;
|
||||
|
||||
let data_time =
|
||||
NaiveDateTime::parse_from_str(&record_info.file_time, r"%Y%m%d%H%M%S").unwrap();
|
||||
let filetime = data_time.and_utc();
|
||||
|
||||
Ok((input, Record { filetime, blocks }))
|
||||
}
|
||||
|
||||
fn _parse_order(input: &[u8]) -> IResult<&[u8], Order> {
|
||||
let (input, order) = take(4usize)(input)?;
|
||||
let result = if order == b"LEND" {
|
||||
Order::LittleEndian
|
||||
} else {
|
||||
Order::BigEndian
|
||||
};
|
||||
let (input, _) = take(4usize)(input)?;
|
||||
Ok((input, result))
|
||||
}
|
||||
|
||||
fn _parse_split(input: &[u8], s: usize, fore: usize, after: usize) -> IResult<&[u8], &[u8]> {
|
||||
let (input, _) = take(fore)(input)?;
|
||||
let (input, result) = take(s)(input)?;
|
||||
let (input, _) = take(after)(input)?;
|
||||
Ok((input, result))
|
||||
}
|
||||
|
||||
fn _parse_split_fn<E, F: Fn(&[u8]) -> IResult<&[u8], E>>(
|
||||
input: &[u8],
|
||||
fore: usize,
|
||||
after: usize,
|
||||
f: F,
|
||||
) -> IResult<&[u8], E> {
|
||||
let (input, _) = take(fore)(input)?;
|
||||
let (input, result) = (f)(input)?;
|
||||
let (input, _) = take(after)(input)?;
|
||||
Ok((input, result))
|
||||
}
|
||||
|
||||
fn _parse_block_fn(order: Order) -> impl FnMut(&[u8]) -> IResult<&[u8], ParsedBlock> {
|
||||
move |input| Self::_parse_split_fn(input, 0, 0, |input| Self::_parse_block(input, order))
|
||||
}
|
||||
|
||||
fn _parse_block(input: &[u8], order: Order) -> IResult<&[u8], ParsedBlock> {
|
||||
let (input, _) = take(8usize)(input)?;
|
||||
let (input, hlen1) = Self::_parse_u32(input, order)?;
|
||||
let (input, block_info) = Self::_parse_split_fn(input, 0, 8, |input| {
|
||||
let (input, p) = take(hlen1)(input)?;
|
||||
|
||||
let p: BlockJsonInfo = serde_json::from_slice(p).unwrap();
|
||||
Ok((input, p))
|
||||
})?;
|
||||
|
||||
let (input, _) = take(8usize)(input)?; // skip 8 bytes
|
||||
let (input, hlen2) = Self::_parse_u32(input, order)?;
|
||||
let dimension_size = block_info.dimension_size.clone();
|
||||
let size = dimension_size.iter().fold(1, |acc, x| acc * x) as usize;
|
||||
let value_type = block_info.value_type.clone();
|
||||
let value_type = Self::_parse_type(&value_type);
|
||||
|
||||
let (input, data) = Self::_parse_matrix(
|
||||
input,
|
||||
value_type,
|
||||
order,
|
||||
size,
|
||||
block_info.value_offset,
|
||||
block_info.value_scale,
|
||||
block_info.fill_value,
|
||||
)?;
|
||||
|
||||
Ok((
|
||||
input,
|
||||
ParsedBlock {
|
||||
info: block_info,
|
||||
data,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
fn _parse_i32(input: &[u8], order: Order) -> IResult<&[u8], i32> {
|
||||
let (input, hlen) = take(4usize)(input)?;
|
||||
let hlen = match order {
|
||||
Order::BigEndian => BigEndian::read_i32(hlen),
|
||||
_ => LittleEndian::read_i32(hlen),
|
||||
};
|
||||
|
||||
Ok((input, hlen))
|
||||
}
|
||||
|
||||
fn _parse_u32(input: &[u8], order: Order) -> IResult<&[u8], u32> {
|
||||
let (input, hlen) = take(4usize)(input)?;
|
||||
let hlen = match order {
|
||||
Order::BigEndian => BigEndian::read_u32(hlen),
|
||||
_ => LittleEndian::read_u32(hlen),
|
||||
};
|
||||
|
||||
Ok((input, hlen))
|
||||
}
|
||||
|
||||
fn _parse_i64(input: &[u8], order: Order) -> IResult<&[u8], i64> {
|
||||
let (input, hlen) = take(8usize)(input)?;
|
||||
let hlen = match order {
|
||||
Order::BigEndian => BigEndian::read_i64(hlen),
|
||||
_ => LittleEndian::read_i64(hlen),
|
||||
};
|
||||
|
||||
Ok((input, hlen))
|
||||
}
|
||||
|
||||
fn _parse_u64(input: &[u8], order: Order) -> IResult<&[u8], u64> {
|
||||
let (input, hlen) = take(8usize)(input)?;
|
||||
let hlen = match order {
|
||||
Order::BigEndian => BigEndian::read_u64(hlen),
|
||||
_ => LittleEndian::read_u64(hlen),
|
||||
};
|
||||
|
||||
Ok((input, hlen))
|
||||
}
|
||||
|
||||
fn _parse_type<'a>(type_str: &'a str) -> ValueTypes {
|
||||
match type_str {
|
||||
"b" => ValueTypes::I8,
|
||||
"B" => ValueTypes::U8,
|
||||
"i" => ValueTypes::I32,
|
||||
"I" => ValueTypes::U32,
|
||||
"f" => ValueTypes::F32,
|
||||
"d" => ValueTypes::F64,
|
||||
"h" => ValueTypes::I16,
|
||||
_ => panic!("Invalid type"),
|
||||
}
|
||||
}
|
||||
|
||||
fn _parse_matrix(
|
||||
input: &[u8],
|
||||
type_: ValueTypes,
|
||||
order: Order,
|
||||
len: usize,
|
||||
offset: f32,
|
||||
scale: f32,
|
||||
fill_value: f64,
|
||||
) -> IResult<&[u8], ValueResult> {
|
||||
match_in_macro!(
|
||||
type_,
|
||||
len,
|
||||
input,
|
||||
offset,
|
||||
scale,
|
||||
fill_value,
|
||||
(
|
||||
ValueTypes::I64,
|
||||
i64,
|
||||
f64,
|
||||
ValueResult::I64,
|
||||
ValueResult::F64
|
||||
),
|
||||
(
|
||||
ValueTypes::F64,
|
||||
f64,
|
||||
f64,
|
||||
ValueResult::F64,
|
||||
ValueResult::F64
|
||||
),
|
||||
(
|
||||
ValueTypes::U64,
|
||||
u64,
|
||||
f64,
|
||||
ValueResult::U64,
|
||||
ValueResult::F64
|
||||
),
|
||||
(
|
||||
ValueTypes::I32,
|
||||
i32,
|
||||
f32,
|
||||
ValueResult::I32,
|
||||
ValueResult::F32
|
||||
),
|
||||
(
|
||||
ValueTypes::F32,
|
||||
f32,
|
||||
f32,
|
||||
ValueResult::F32,
|
||||
ValueResult::F32
|
||||
),
|
||||
(
|
||||
ValueTypes::U32,
|
||||
u32,
|
||||
f32,
|
||||
ValueResult::U32,
|
||||
ValueResult::F32
|
||||
),
|
||||
(
|
||||
ValueTypes::I16,
|
||||
i16,
|
||||
f32,
|
||||
ValueResult::I16,
|
||||
ValueResult::F32
|
||||
),
|
||||
(ValueTypes::I8, i8, f32, ValueResult::I8, ValueResult::F32),
|
||||
(ValueTypes::U8, u8, f32, ValueResult::U8, ValueResult::F32)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct RecordInfo {
|
||||
file_time: String,
|
||||
block_num: i32,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct BlockJsonInfo {
|
||||
pub value_name: String,
|
||||
pub value_des: String,
|
||||
pub value_type: String,
|
||||
pub dimension_size: Vec<u64>,
|
||||
pub dimension: usize,
|
||||
pub dimension_des: Vec<String>,
|
||||
pub dimension_start: Vec<f64>,
|
||||
pub dimension_end: Vec<f64>,
|
||||
pub dimension_values: Vec<Vec<f64>>,
|
||||
pub fill_value: f64,
|
||||
pub value_scale: f32,
|
||||
pub value_offset: f32,
|
||||
pub radar_alt: Option<f64>,
|
||||
pub radar_lat: Option<f64>,
|
||||
pub radar_lon: Option<f64>,
|
||||
pub radar_name: Option<String>,
|
||||
}
|
||||
|
||||
pub struct ParsedBlock {
|
||||
pub info: BlockJsonInfo,
|
||||
pub data: ValueResult,
|
||||
}
|
||||
@ -12,4 +12,13 @@ pub enum Error {
|
||||
|
||||
#[error("Invalid Program {0}")]
|
||||
InvalidProgram(String),
|
||||
|
||||
#[error("Invalid Data")]
|
||||
InvalidData {
|
||||
#[from]
|
||||
source: crate::data_loader::error::ETWSError,
|
||||
},
|
||||
|
||||
#[error("Invalid CoordType")]
|
||||
InvalidDataType,
|
||||
}
|
||||
|
||||
@ -7,62 +7,62 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
pub struct PPI {
|
||||
transform: Trackball,
|
||||
program: Program,
|
||||
}
|
||||
// pub struct PPI {
|
||||
// transform: Trackball,
|
||||
// program: Program,
|
||||
// }
|
||||
|
||||
impl PPI {
|
||||
pub fn new(version: &'static str) -> Self {
|
||||
let trackball = Trackball::new().unwrap();
|
||||
let projection = Polar::new().unwrap();
|
||||
let position = Position::new().unwrap();
|
||||
// impl PPI {
|
||||
// pub fn new(version: &'static str) -> Self {
|
||||
// let trackball = Trackball::new().unwrap();
|
||||
// let projection = Polar::new().unwrap();
|
||||
// let position = Position::new().unwrap();
|
||||
|
||||
let transform = trackball.chain(projection.chain(position));
|
||||
// // let transform = trackball.chain(projection.chain(position));
|
||||
|
||||
let vertex = Shader::new(
|
||||
glow::VERTEX_SHADER,
|
||||
CodeType::<&'static str>::Path("agg-fast-path.vert".into()),
|
||||
)
|
||||
.unwrap();
|
||||
// let vertex = Shader::new(
|
||||
// glow::VERTEX_SHADER,
|
||||
// CodeType::<&'static str>::Path("agg-fast-path.vert".into()),
|
||||
// )
|
||||
// .unwrap();
|
||||
|
||||
let fragment = Shader::new(
|
||||
glow::FRAGMENT_SHADER,
|
||||
CodeType::<&'static str>::Path("agg-fast-path.frag".into()),
|
||||
)
|
||||
.unwrap();
|
||||
// let fragment = Shader::new(
|
||||
// glow::FRAGMENT_SHADER,
|
||||
// CodeType::<&'static str>::Path("agg-fast-path.frag".into()),
|
||||
// )
|
||||
// .unwrap();
|
||||
|
||||
let mut program = Program::new(vertex, fragment, None, version);
|
||||
// let mut program = Program::new(vertex, fragment, None, version);
|
||||
|
||||
let viewport = Viewport::new().unwrap();
|
||||
// let viewport = Viewport::new().unwrap();
|
||||
|
||||
program.set_transform(&transform);
|
||||
// // program.set_transform(&transform);
|
||||
|
||||
program.set_viewport(&viewport);
|
||||
// program.set_viewport(&viewport);
|
||||
|
||||
Self { transform, program }
|
||||
}
|
||||
// Self { transform, program }
|
||||
// }
|
||||
|
||||
pub fn compile(&mut self, gl: &glow::Context) {
|
||||
self.program.compile(gl);
|
||||
}
|
||||
// pub fn compile(&mut self, gl: &glow::Context) {
|
||||
// self.program.compile(gl);
|
||||
// }
|
||||
|
||||
pub fn program(&self) -> &Program {
|
||||
&self.program
|
||||
}
|
||||
// pub fn program(&self) -> &Program {
|
||||
// &self.program
|
||||
// }
|
||||
|
||||
pub fn native_program(&self) -> Option<<glow::Context as HasContext>::Program> {
|
||||
self.program.native_program
|
||||
}
|
||||
}
|
||||
// pub fn native_program(&self) -> Option<<glow::Context as HasContext>::Program> {
|
||||
// self.program.native_program
|
||||
// }
|
||||
// }
|
||||
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_ppi() {
|
||||
let ppi = PPI::new("450");
|
||||
// let ppi = PPI::new("450");
|
||||
|
||||
println!("{}", ppi.program.vertex());
|
||||
// println!("{}", ppi.program.vertex());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use glow::{HasContext, NativeBuffer, NativeVertexArray};
|
||||
|
||||
use crate::components::{fetchcode, CodeComponent, CodeType, Program, Shader, Snippet};
|
||||
use crate::errors::*;
|
||||
@ -14,10 +15,13 @@ use super::Colletion;
|
||||
pub struct AggFastPath {
|
||||
program: Program,
|
||||
buffer: Vec<Point>,
|
||||
|
||||
vao: Option<NativeVertexArray>,
|
||||
vbo: Option<NativeBuffer>,
|
||||
}
|
||||
|
||||
impl AggFastPath {
|
||||
pub fn new<T: Transform>(transform: &T, viewport: &Viewport) -> Result<Self> {
|
||||
pub fn new() -> Result<Self> {
|
||||
let vertex = Shader::new(
|
||||
glow::VERTEX_SHADER,
|
||||
CodeType::<String>::Path("agg-fast-path.vert".into()),
|
||||
@ -28,10 +32,14 @@ impl AggFastPath {
|
||||
CodeType::<String>::Path("agg-fast-path.frag".into()),
|
||||
)?;
|
||||
|
||||
let input_snippet = Snippet::new("input",CodeType::Code("
|
||||
let input_snippet = Snippet::new(
|
||||
"input",
|
||||
CodeType::Code(
|
||||
"
|
||||
layout(location = 0) in vec3 prev;
|
||||
layout(location = 1) in vec3 curr;
|
||||
layout(location = 2) in vec3 next;
|
||||
layout(location = 3) in float id;
|
||||
|
||||
uniform float linewidth;
|
||||
|
||||
@ -39,24 +47,63 @@ impl AggFastPath {
|
||||
|
||||
uniform vec4 color;
|
||||
|
||||
") ,false, None)?;
|
||||
",
|
||||
),
|
||||
false,
|
||||
None,
|
||||
)?;
|
||||
|
||||
let vertex = vertex.add_snippet_before(input_snippet);
|
||||
|
||||
let mut program = Program::new(vertex, fragment, None, "330 core");
|
||||
let program = Program::new(vertex, fragment, None, "330 core");
|
||||
|
||||
program.set_transform(transform);
|
||||
program.set_viewport(viewport);
|
||||
|
||||
println!("{}", program.vertex());
|
||||
|
||||
println!("{}", program.fragment());
|
||||
// program.set_transform(transform);
|
||||
// program.set_viewport(viewport);
|
||||
|
||||
Ok(Self {
|
||||
program,
|
||||
buffer: Vec::with_capacity(128),
|
||||
vao: None,
|
||||
vbo: None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_transform<T: Transform>(&mut self, transform: &T) {
|
||||
self.program.set_transform(transform);
|
||||
}
|
||||
|
||||
pub fn set_viewport(&mut self, viewport: &Viewport) {
|
||||
self.program.set_viewport(viewport);
|
||||
}
|
||||
|
||||
pub fn set_linecolor(&mut self, gl: &glow::Context, color: [f32; 4]) {
|
||||
let loc = self.program.get_uniform_location(gl, "color");
|
||||
unsafe {
|
||||
gl.uniform_4_f32(loc.as_ref(), color[0], color[1], color[2], color[3]);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_linewidth(&mut self, gl: &glow::Context, linewidth: f32) {
|
||||
let loc = self.program.get_uniform_location(gl, "linewidth");
|
||||
unsafe {
|
||||
gl.uniform_1_f32(loc.as_ref(), linewidth);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_anatialias(&mut self, gl: &glow::Context, antialias: f32) {
|
||||
let loc = self.program.get_uniform_location(gl, "antialias");
|
||||
unsafe {
|
||||
gl.uniform_1_f32(loc.as_ref(), antialias);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn program(&mut self) -> &mut Program {
|
||||
&mut self.program
|
||||
}
|
||||
|
||||
pub fn program_ref(&self) -> &Program {
|
||||
&self.program
|
||||
}
|
||||
}
|
||||
|
||||
impl Colletion for AggFastPath {
|
||||
@ -68,16 +115,63 @@ impl Colletion for AggFastPath {
|
||||
}
|
||||
|
||||
impl Graphics for AggFastPath {
|
||||
|
||||
fn compile(&mut self, gl: &glow::Context) -> Result<()> {
|
||||
self.program.compile(gl)
|
||||
use bytemuck::cast_slice;
|
||||
self.program.compile(gl)?;
|
||||
unsafe {
|
||||
let vao = gl.create_vertex_array().unwrap();
|
||||
|
||||
gl.bind_vertex_array(Some(vao));
|
||||
|
||||
let vbo = gl.create_buffer().unwrap();
|
||||
gl.bind_buffer(glow::ARRAY_BUFFER, Some(vbo));
|
||||
gl.buffer_data_u8_slice(
|
||||
glow::ARRAY_BUFFER,
|
||||
cast_slice(&self.buffer),
|
||||
glow::STATIC_DRAW,
|
||||
);
|
||||
|
||||
gl.enable_vertex_attrib_array(0);
|
||||
gl.vertex_attrib_pointer_f32(0, 3, glow::FLOAT, false, 40, 0);
|
||||
|
||||
gl.enable_vertex_attrib_array(1);
|
||||
gl.vertex_attrib_pointer_f32(1, 3, glow::FLOAT, false, 40, 12);
|
||||
|
||||
gl.enable_vertex_attrib_array(2);
|
||||
gl.vertex_attrib_pointer_f32(2, 3, glow::FLOAT, false, 40, 24);
|
||||
|
||||
gl.enable_vertex_attrib_array(3);
|
||||
gl.vertex_attrib_pointer_f32(3, 1, glow::FLOAT, false, 40, 36);
|
||||
|
||||
self.vao = Some(vao);
|
||||
self.vbo = Some(vbo);
|
||||
|
||||
gl.bind_vertex_array(None);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn draw(&self, gl: &glow::Context) -> Result<()> {
|
||||
unsafe {
|
||||
gl.clear(glow::COLOR_BUFFER_BIT);
|
||||
gl.use_program(Some(self.program.native_program.unwrap()));
|
||||
gl.bind_vertex_array(Some(self.vao.unwrap()));
|
||||
gl.draw_arrays(glow::TRIANGLE_STRIP, 0, self.buffer.len() as i32);
|
||||
|
||||
fn draw(&self) -> Result<()> {
|
||||
gl.bind_vertex_array(None);
|
||||
}
|
||||
|
||||
use bytemuck::cast_slice;
|
||||
let b:&[u8] = cast_slice(&self.buffer);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn destroy(&mut self, gl: &glow::Context) -> Result<()> {
|
||||
self.program.destroy(gl);
|
||||
|
||||
unsafe {
|
||||
self.vao.map(|vao| gl.delete_vertex_array(vao));
|
||||
self.vbo.map(|vbo| gl.delete_buffer(vbo));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -89,6 +183,7 @@ pub struct Point {
|
||||
prev: [f32; 3],
|
||||
curr: [f32; 3],
|
||||
next: [f32; 3],
|
||||
id: f32,
|
||||
}
|
||||
|
||||
impl Ty for Point {}
|
||||
@ -101,49 +196,38 @@ pub struct Path {
|
||||
}
|
||||
|
||||
impl Default for Path {
|
||||
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
points: Vec::with_capacity(500),
|
||||
is_closed: false,
|
||||
is_empty: true
|
||||
is_empty: true,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub struct PathBuilder {
|
||||
is_closed: bool,
|
||||
}
|
||||
|
||||
impl Default for PathBuilder{
|
||||
|
||||
impl Default for PathBuilder {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
is_closed: false
|
||||
}
|
||||
Self { is_closed: false }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl PathBuilder {
|
||||
|
||||
pub fn is_closed(&mut self , is_closed: bool) -> &mut Self {
|
||||
pub fn is_closed(&mut self, is_closed: bool) -> &mut Self {
|
||||
self.is_closed = is_closed;
|
||||
self
|
||||
}
|
||||
|
||||
|
||||
pub fn build(&self) -> Path {
|
||||
|
||||
Path {
|
||||
points: Vec::with_capacity(500),
|
||||
is_closed: self.is_closed,
|
||||
is_empty: true,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl Path {
|
||||
@ -159,19 +243,20 @@ impl Path {
|
||||
PathBuilder::default()
|
||||
}
|
||||
|
||||
|
||||
pub fn push(&mut self, point: [f32; 3]) {
|
||||
if self.is_empty {
|
||||
self.points.push(Point {
|
||||
prev: point,
|
||||
curr: point,
|
||||
next: point,
|
||||
id: 1.0,
|
||||
});
|
||||
|
||||
self.points.push(Point {
|
||||
prev: point,
|
||||
curr: point,
|
||||
next: point,
|
||||
id: -1.0,
|
||||
});
|
||||
|
||||
self.is_empty = false;
|
||||
@ -180,12 +265,21 @@ impl Path {
|
||||
let prev = self.points[len - 1].curr;
|
||||
let curr = point;
|
||||
let next = point;
|
||||
self.points.push(Point { prev, curr, next });
|
||||
self.points[len - 1].next = curr;
|
||||
self.points.push(Point {
|
||||
prev,
|
||||
curr,
|
||||
next,
|
||||
id: 1.0,
|
||||
});
|
||||
self.points.push(Point {
|
||||
prev,
|
||||
curr,
|
||||
next,
|
||||
id: -1.0,
|
||||
});
|
||||
|
||||
if len == 2 {
|
||||
self.points[0].next = curr;
|
||||
}
|
||||
self.points[len - 1].next = curr;
|
||||
self.points[len - 2].next = curr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -195,20 +289,28 @@ impl Path {
|
||||
let curr = self.points.first().unwrap().curr;
|
||||
let prev = self.points[len - 1].curr;
|
||||
let next = self.points[1].next;
|
||||
self.points.push(Point { prev, curr, next });
|
||||
self.points.push(Point {
|
||||
prev,
|
||||
curr,
|
||||
next,
|
||||
id: 1.0,
|
||||
});
|
||||
self.points.push(Point {
|
||||
prev,
|
||||
curr,
|
||||
next,
|
||||
id: -1.0,
|
||||
});
|
||||
self.points[len - 1].next = curr;
|
||||
self.points[len - 2].next = curr;
|
||||
}
|
||||
|
||||
self.points.push(self.points.last().unwrap().clone());
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.points.len() - 2
|
||||
self.points.len()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
impl Deref for Path {
|
||||
type Target = [u8];
|
||||
|
||||
@ -225,7 +327,6 @@ impl DerefMut for Path {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mod test {
|
||||
|
||||
use crate::graphics::transforms::{polar::Polar, position::Position, trackball::Trackball};
|
||||
@ -234,7 +335,6 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_path() {
|
||||
|
||||
let mut path = Path::builder().is_closed(false).build();
|
||||
|
||||
path.push([9.0, 9.0, 9.0]);
|
||||
@ -248,16 +348,14 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_agg() {
|
||||
// let viewport = Trackball::new().unwrap();
|
||||
// let trans = Polar::new().unwrap();
|
||||
// let position = Position::new().unwrap();
|
||||
|
||||
let viewport = Trackball::new().unwrap();
|
||||
let trans = Polar::new().unwrap();
|
||||
let position = Position::new().unwrap();
|
||||
// let transform = viewport.chain(trans.chain(position));
|
||||
|
||||
let transform = viewport.chain(trans.chain(position));
|
||||
|
||||
let viewport = &Viewport::new().unwrap();
|
||||
|
||||
let agg_path = AggFastPath::new(&transform, &viewport).unwrap();
|
||||
// let viewport = &Viewport::new().unwrap();
|
||||
|
||||
// let agg_path = AggFastPath::new(&transform, &viewport).unwrap();
|
||||
}
|
||||
}
|
||||
129
src/graphics/colormap/linear.rs
Normal file
129
src/graphics/colormap/linear.rs
Normal file
@ -0,0 +1,129 @@
|
||||
use glow::HasContext;
|
||||
|
||||
use crate::components::{CodeType, Program, Snippet};
|
||||
use crate::errors::*;
|
||||
|
||||
use super::ColorMap;
|
||||
|
||||
pub struct LinearColormap {
|
||||
snippet: Snippet,
|
||||
colors: Vec<[u8; 4]>,
|
||||
|
||||
color_changed: bool,
|
||||
texture: Option<glow::NativeTexture>,
|
||||
|
||||
pub min: f32,
|
||||
pub max: f32,
|
||||
}
|
||||
|
||||
impl LinearColormap {
|
||||
pub fn new() -> Result<Self> {
|
||||
let snippet = Snippet::new(
|
||||
"linear",
|
||||
CodeType::<&'static str>::Path("colormap.glsl".into()),
|
||||
true,
|
||||
None,
|
||||
)?;
|
||||
|
||||
Ok(Self {
|
||||
snippet,
|
||||
colors: vec![],
|
||||
texture: None,
|
||||
color_changed: true,
|
||||
min: 0.0,
|
||||
max: 1.0,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_colors(&mut self, colors: Vec<[u8; 4]>) {
|
||||
self.colors = colors;
|
||||
self.color_changed = true;
|
||||
}
|
||||
|
||||
pub fn set_range(&mut self, min: f32, max: f32) {
|
||||
self.min = min;
|
||||
self.max = max;
|
||||
}
|
||||
}
|
||||
|
||||
impl ColorMap for LinearColormap {
|
||||
fn attach_with_program(
|
||||
&mut self,
|
||||
gl: &glow::Context,
|
||||
program: &crate::components::Program,
|
||||
) -> crate::errors::Result<()> {
|
||||
use bytemuck::cast_slice;
|
||||
unsafe {
|
||||
if self.color_changed {
|
||||
let texture = gl.create_texture().unwrap();
|
||||
gl.bind_texture(glow::TEXTURE_1D, Some(texture));
|
||||
gl.tex_image_1d(
|
||||
glow::TEXTURE_1D,
|
||||
0,
|
||||
glow::RGBA as i32,
|
||||
self.colors.len() as i32,
|
||||
0,
|
||||
glow::RGBA,
|
||||
glow::UNSIGNED_BYTE,
|
||||
Some(cast_slice(&self.colors)),
|
||||
);
|
||||
|
||||
gl.tex_parameter_i32(
|
||||
glow::TEXTURE_1D,
|
||||
glow::TEXTURE_MIN_FILTER,
|
||||
glow::NEAREST as i32,
|
||||
);
|
||||
gl.tex_parameter_i32(
|
||||
glow::TEXTURE_1D,
|
||||
glow::TEXTURE_MAG_FILTER,
|
||||
glow::NEAREST as i32,
|
||||
);
|
||||
|
||||
let name = self.snippet.find_symbol("conf").unwrap();
|
||||
let location = program.get_uniform_location(gl, &name);
|
||||
|
||||
// gl.uniform_2_f32(location.as_ref(), 0);
|
||||
gl.uniform_4_f32(
|
||||
location.as_ref(),
|
||||
self.min,
|
||||
self.max,
|
||||
self.colors.len() as f32,
|
||||
125.0,
|
||||
);
|
||||
|
||||
self.texture = Some(texture);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn bind_texture(&self, gl: &glow::Context, program: &Program) -> crate::errors::Result<()> {
|
||||
unsafe {
|
||||
gl.active_texture(glow::TEXTURE0);
|
||||
gl.bind_texture(glow::TEXTURE_1D, self.texture);
|
||||
let name = self.snippet.find_symbol("colormap").unwrap();
|
||||
let location = program.get_uniform_location(gl, &name);
|
||||
gl.uniform_1_i32(location.as_ref(), 0);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn snippet_ref(&self) -> &crate::components::Snippet {
|
||||
&self.snippet
|
||||
}
|
||||
}
|
||||
|
||||
mod test {
|
||||
#[test]
|
||||
|
||||
fn test() {
|
||||
use super::LinearColormap;
|
||||
|
||||
let mut colormap = LinearColormap::new().unwrap();
|
||||
|
||||
// colormap.set_colors(vec![[0.0, 0.0, 0.0, 1.0], [1.0, 1.0, 1.0, 1.0]]);
|
||||
colormap.set_range(0.0, 1.0);
|
||||
}
|
||||
}
|
||||
15
src/graphics/colormap/mod.rs
Normal file
15
src/graphics/colormap/mod.rs
Normal file
@ -0,0 +1,15 @@
|
||||
use crate::components::Program;
|
||||
|
||||
pub mod linear;
|
||||
|
||||
pub trait ColorMap {
|
||||
fn attach_with_program(
|
||||
&mut self,
|
||||
gl: &glow::Context,
|
||||
program: &crate::components::Program,
|
||||
) -> crate::errors::Result<()>;
|
||||
|
||||
fn bind_texture(&self, gl: &glow::Context, program: &Program) -> crate::errors::Result<()>;
|
||||
|
||||
fn snippet_ref(&self) -> &crate::components::Snippet;
|
||||
}
|
||||
241
src/graphics/hello.rs
Normal file
241
src/graphics/hello.rs
Normal file
@ -0,0 +1,241 @@
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use glow::{HasContext, NativeBuffer, NativeVertexArray};
|
||||
|
||||
use crate::components::{fetchcode, CodeComponent, CodeType, Program, Shader, Snippet};
|
||||
use crate::errors::*;
|
||||
use crate::graphics::transforms::viewport::Viewport;
|
||||
use crate::graphics::transforms::Transform;
|
||||
use crate::graphics::ty::Ty;
|
||||
use crate::graphics::Graphics;
|
||||
|
||||
pub struct Hello {
|
||||
program: Program,
|
||||
buffer: Vec<Point>,
|
||||
|
||||
vao: Option<NativeVertexArray>,
|
||||
}
|
||||
|
||||
impl Hello {
|
||||
pub fn new() -> Result<Self> {
|
||||
let vertex = Shader::new(
|
||||
glow::VERTEX_SHADER,
|
||||
CodeType::<String>::Path("hello.vert".into()),
|
||||
)?;
|
||||
|
||||
let fragment = Shader::new(
|
||||
glow::FRAGMENT_SHADER,
|
||||
CodeType::<String>::Path("hello.frag".into()),
|
||||
)?;
|
||||
|
||||
let program = Program::new(vertex, fragment, None, "330 core");
|
||||
|
||||
println!("Vertex:\n{}", program.vertex());
|
||||
println!("Fragment:\n{}", program.fragment());
|
||||
|
||||
Ok(Self {
|
||||
program,
|
||||
buffer: Vec::with_capacity(128),
|
||||
vao: None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn program(&mut self) -> &mut Program {
|
||||
&mut self.program
|
||||
}
|
||||
|
||||
pub fn program_ref(&self) -> &Program {
|
||||
&self.program
|
||||
}
|
||||
}
|
||||
|
||||
impl Graphics for Hello {
|
||||
fn compile(&mut self, gl: &glow::Context) -> Result<()> {
|
||||
self.program.compile(gl)?;
|
||||
unsafe {
|
||||
let vertex_array = gl
|
||||
.create_vertex_array()
|
||||
.expect("Cannot create vertex array");
|
||||
|
||||
self.vao = Some(vertex_array);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn draw(&self, gl: &glow::Context) -> Result<()> {
|
||||
unsafe {
|
||||
gl.clear_color(0.05, 0.05, 0.1, 1.0);
|
||||
gl.clear(glow::COLOR_BUFFER_BIT);
|
||||
gl.use_program(Some(self.program.native_program.unwrap()));
|
||||
gl.bind_vertex_array(self.vao);
|
||||
gl.draw_arrays(glow::TRIANGLES, 0, 3);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn destroy(&mut self, gl: &glow::Context) -> Result<()> {
|
||||
self.program.destroy(gl);
|
||||
|
||||
unsafe {
|
||||
self.vao.map(|vao| gl.delete_vertex_array(vao));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy, Zeroable, Pod)]
|
||||
pub struct Point {
|
||||
prev: [f32; 3],
|
||||
curr: [f32; 3],
|
||||
next: [f32; 3],
|
||||
}
|
||||
|
||||
impl Ty for Point {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Path {
|
||||
points: Vec<Point>,
|
||||
is_closed: bool,
|
||||
is_empty: bool,
|
||||
}
|
||||
|
||||
impl Default for Path {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
points: Vec::with_capacity(500),
|
||||
is_closed: false,
|
||||
is_empty: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PathBuilder {
|
||||
is_closed: bool,
|
||||
}
|
||||
|
||||
impl Default for PathBuilder {
|
||||
fn default() -> Self {
|
||||
Self { is_closed: false }
|
||||
}
|
||||
}
|
||||
|
||||
impl PathBuilder {
|
||||
pub fn is_closed(&mut self, is_closed: bool) -> &mut Self {
|
||||
self.is_closed = is_closed;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(&self) -> Path {
|
||||
Path {
|
||||
points: Vec::with_capacity(500),
|
||||
is_closed: self.is_closed,
|
||||
is_empty: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Path {
|
||||
pub fn new(is_closed: bool) -> Self {
|
||||
Self {
|
||||
points: Vec::with_capacity(500),
|
||||
is_closed,
|
||||
is_empty: true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn builder() -> PathBuilder {
|
||||
PathBuilder::default()
|
||||
}
|
||||
|
||||
pub fn push(&mut self, point: [f32; 3]) {
|
||||
if self.is_empty {
|
||||
self.points.push(Point {
|
||||
prev: point,
|
||||
curr: point,
|
||||
next: point,
|
||||
});
|
||||
|
||||
self.is_empty = false;
|
||||
} else {
|
||||
let len = self.points.len();
|
||||
let prev = self.points[len - 1].curr;
|
||||
let curr = point;
|
||||
let next = point;
|
||||
self.points.push(Point { prev, curr, next });
|
||||
self.points[len - 1].next = curr;
|
||||
|
||||
if len == 2 {
|
||||
self.points[0].next = curr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn finish(&mut self) {
|
||||
if self.is_closed {
|
||||
let len = self.points.len();
|
||||
let curr = self.points.first().unwrap().curr;
|
||||
let prev = self.points[len - 1].curr;
|
||||
let next = self.points[1].next;
|
||||
self.points.push(Point { prev, curr, next });
|
||||
self.points[len - 1].next = curr;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.points.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Path {
|
||||
type Target = [u8];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
use bytemuck::cast_slice;
|
||||
cast_slice(&self.points)
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Path {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
use bytemuck::cast_slice_mut;
|
||||
cast_slice_mut(&mut self.points)
|
||||
}
|
||||
}
|
||||
|
||||
mod test {
|
||||
|
||||
use crate::graphics::transforms::{polar::Polar, position::Position, trackball::Trackball};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_path() {
|
||||
let mut path = Path::builder().is_closed(false).build();
|
||||
|
||||
path.push([9.0, 9.0, 9.0]);
|
||||
|
||||
path.push([9.0, 19.0, 9.0]);
|
||||
|
||||
path.finish();
|
||||
|
||||
println!("{:?}, len: {}", path, path.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_agg() {
|
||||
// let viewport = Trackball::new().unwrap();
|
||||
// let trans = Polar::new().unwrap();
|
||||
// let position = Position::new().unwrap();
|
||||
|
||||
// let transform = viewport.chain(trans.chain(position));
|
||||
|
||||
// let viewport = &Viewport::new().unwrap();
|
||||
|
||||
// let agg_path = AggFastPath::new(&transform, &viewport).unwrap();
|
||||
}
|
||||
}
|
||||
@ -1,14 +1,28 @@
|
||||
pub mod collections;
|
||||
pub mod colormap;
|
||||
mod colormesh;
|
||||
pub mod hello;
|
||||
pub mod ppi;
|
||||
pub mod tools;
|
||||
pub mod transforms;
|
||||
pub mod ty;
|
||||
use crate::errors::*;
|
||||
use crate::{components::Program, errors::*};
|
||||
|
||||
pub use colormesh::ColorMesh;
|
||||
|
||||
pub trait Graphics {
|
||||
fn draw(&self) -> Result<()>;
|
||||
fn draw(&self, gl: &glow::Context) -> Result<()>;
|
||||
|
||||
fn compile(&mut self, gl: &glow::Context) -> Result<()>;
|
||||
|
||||
fn destroy(&mut self, gl: &glow::Context) -> Result<()>;
|
||||
}
|
||||
|
||||
pub trait AttaWithProgram {
|
||||
fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> Result<()>;
|
||||
}
|
||||
|
||||
pub trait AttaWithBuffer {
|
||||
type Data;
|
||||
fn attach_with_buffer(&mut self, gl: &glow::Context, data: &Self::Data) -> Result<()>;
|
||||
}
|
||||
|
||||
251
src/graphics/ppi.rs
Normal file
251
src/graphics/ppi.rs
Normal file
@ -0,0 +1,251 @@
|
||||
use bytemuck::cast_slice;
|
||||
use glow::{HasContext, NativeBuffer, NativeVertexArray};
|
||||
use ndarray::{s, IndexLonger};
|
||||
|
||||
use crate::components::{CodeType, Program, Shader, Snippet};
|
||||
use crate::data_loader::{CoordType, Data, DataType};
|
||||
use crate::errors::*;
|
||||
|
||||
use super::colormap::ColorMap;
|
||||
use super::transforms::viewport::Viewport;
|
||||
use super::transforms::Transform;
|
||||
use super::{ty, AttaWithBuffer, Graphics};
|
||||
|
||||
pub struct PPI<'a> {
|
||||
program: Program,
|
||||
layer: isize,
|
||||
vao: Option<NativeVertexArray>,
|
||||
vbo: Option<NativeBuffer>,
|
||||
|
||||
cmap: &'a mut dyn ColorMap,
|
||||
|
||||
buffer: Vec<[f32; 3]>,
|
||||
}
|
||||
|
||||
impl<'a> PPI<'a> {
|
||||
pub fn new(cmap: &'a mut dyn ColorMap) -> Result<Self> {
|
||||
let vertex = Shader::new(
|
||||
glow::VERTEX_SHADER,
|
||||
CodeType::<String>::Path("ppi.vert".into()),
|
||||
)?;
|
||||
|
||||
let geom = Shader::new(
|
||||
glow::GEOMETRY_SHADER,
|
||||
CodeType::<String>::Path("ppi.geom".into()),
|
||||
)?;
|
||||
|
||||
let fragment = Shader::new(
|
||||
glow::FRAGMENT_SHADER,
|
||||
CodeType::<String>::Path("ppi.frag".into()),
|
||||
)?;
|
||||
|
||||
let mut program = Program::new(vertex, fragment, Some(geom), "330 core");
|
||||
|
||||
program.set_hook("colormap", cmap.snippet_ref());
|
||||
|
||||
Ok(Self {
|
||||
program,
|
||||
layer: 0,
|
||||
vao: None,
|
||||
vbo: None,
|
||||
buffer: Vec::with_capacity(180 * 50),
|
||||
cmap,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_transform<T: Transform>(&mut self, transform: &T) {
|
||||
self.program.set_transform(transform);
|
||||
}
|
||||
|
||||
pub fn set_viewport(&mut self, viewport: &Viewport) {
|
||||
self.program.set_viewport(viewport);
|
||||
}
|
||||
|
||||
pub fn set_colormap(&mut self, colormap: &'a mut dyn ColorMap) {
|
||||
self.cmap = colormap;
|
||||
// self.program.set_hook("colormap", colormap.snippet_ref());
|
||||
}
|
||||
|
||||
pub fn program(&mut self) -> &mut Program {
|
||||
&mut self.program
|
||||
}
|
||||
|
||||
fn set_conf(&self, gl: &glow::Context, dpir: f32, dpie: f32) {
|
||||
let location = self.program.get_uniform_location(gl, "conf");
|
||||
unsafe {
|
||||
gl.uniform_4_f32(location.as_ref(), dpir, dpie, 0f32, 0f32);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_ppi_layer(&mut self, layer: isize) {
|
||||
self.layer = self.layer + layer;
|
||||
self.layer.clamp(0, 23);
|
||||
}
|
||||
|
||||
pub fn program_ref(&self) -> &Program {
|
||||
&self.program
|
||||
}
|
||||
|
||||
fn bake_data(&self, data: &Data) -> Result<Vec<[f32; 3]>> {
|
||||
let first_block = data.blocks.get(0).unwrap();
|
||||
let first_block_data = first_block.data.view();
|
||||
if let CoordType::Polar {
|
||||
r_range,
|
||||
azimuth,
|
||||
r,
|
||||
..
|
||||
} = &first_block.coord_type
|
||||
{
|
||||
let azimuth_len = azimuth.len();
|
||||
let r_len = r.len();
|
||||
|
||||
let mut vertices = Vec::with_capacity(azimuth_len * r_len);
|
||||
|
||||
for azi_idx in 0..azimuth_len {
|
||||
for r_idx in 0..r_len {
|
||||
let azi = azimuth.get(azi_idx).unwrap();
|
||||
let r = r.get(r_idx).unwrap() / r_range[1] as f32;
|
||||
let dt = first_block_data
|
||||
.get([self.layer as usize, azi_idx, r_idx])
|
||||
.unwrap();
|
||||
vertices.push([r, *azi, *dt]);
|
||||
}
|
||||
}
|
||||
return Ok(vertices);
|
||||
} else {
|
||||
return Err(Error::InvalidDataType);
|
||||
}
|
||||
}
|
||||
|
||||
fn data_info(&self, data: &Data) -> Result<(f32, f32, DataType)> {
|
||||
let first_block = data.blocks.get(0).unwrap();
|
||||
if let CoordType::Polar {
|
||||
azimuth,
|
||||
r,
|
||||
r_range,
|
||||
..
|
||||
} = &first_block.coord_type
|
||||
{
|
||||
let mut sorted_azimuth = azimuth.clone();
|
||||
sorted_azimuth.sort_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Greater));
|
||||
let azi_step = max_step(&sorted_azimuth);
|
||||
let r_step = min_step(r) / (r_range[1]) as f32;
|
||||
return Ok((r_step, azi_step, first_block.data_type));
|
||||
} else {
|
||||
return Err(Error::InvalidDataType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn min_step(data: &Vec<f32>) -> f32 {
|
||||
// 计算相邻元素之间的间距
|
||||
let mut min_gap = f32::MAX;
|
||||
for window in data.windows(2) {
|
||||
if let [a, b] = window {
|
||||
let gap = b - a;
|
||||
if gap < min_gap {
|
||||
min_gap = gap;
|
||||
}
|
||||
}
|
||||
}
|
||||
return min_gap;
|
||||
}
|
||||
|
||||
fn max_step(data: &Vec<f32>) -> f32 {
|
||||
// 计算相邻元素之间的间距
|
||||
let mut max_gap = f32::MIN;
|
||||
for window in data.windows(2) {
|
||||
if let [a, b] = window {
|
||||
let gap = b - a;
|
||||
if gap > max_gap {
|
||||
max_gap = gap;
|
||||
}
|
||||
}
|
||||
}
|
||||
return max_gap;
|
||||
}
|
||||
|
||||
impl<'a> Graphics for PPI<'a> {
|
||||
fn compile(&mut self, gl: &glow::Context) -> Result<()> {
|
||||
self.program.compile(gl)?;
|
||||
self.cmap.attach_with_program(gl, &self.program)?;
|
||||
unsafe {
|
||||
let vao = gl.create_vertex_array().unwrap();
|
||||
gl.bind_vertex_array(Some(vao));
|
||||
let vbo = gl.create_buffer().unwrap();
|
||||
gl.bind_buffer(glow::ARRAY_BUFFER, Some(vbo));
|
||||
gl.enable_vertex_attrib_array(0);
|
||||
gl.vertex_attrib_pointer_f32(0, 3, glow::FLOAT, false, 12, 0);
|
||||
|
||||
self.vao = Some(vao);
|
||||
self.vbo = Some(vbo);
|
||||
gl.bind_vertex_array(None);
|
||||
}
|
||||
|
||||
// let location = self.program.get_uniform_location(gl, "conf");
|
||||
let origin = self.program.get_uniform_location(gl, "polar_origin");
|
||||
|
||||
unsafe {
|
||||
// gl.uniform_4_f32(location.as_ref(), dpir, dpie, 0.0, 0.0);
|
||||
gl.uniform_1_f32(origin.as_ref(), 90.0f32.to_radians());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn destroy(&mut self, gl: &glow::Context) -> Result<()> {
|
||||
self.program.destroy(gl);
|
||||
|
||||
unsafe {
|
||||
self.vao.map(|vao| gl.delete_vertex_array(vao));
|
||||
self.vbo.map(|vbo| gl.delete_buffer(vbo));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn draw(&self, gl: &glow::Context) -> Result<()> {
|
||||
unsafe {
|
||||
gl.clear(glow::COLOR_BUFFER_BIT);
|
||||
gl.use_program(Some(self.program.native_program.unwrap()));
|
||||
self.cmap.bind_texture(gl, &self.program)?;
|
||||
gl.depth_mask(false);
|
||||
gl.bind_vertex_array(Some(self.vao.unwrap()));
|
||||
gl.draw_arrays(glow::POINTS, 0, self.buffer.len() as i32);
|
||||
gl.depth_mask(true);
|
||||
gl.bind_vertex_array(None);
|
||||
gl.use_program(None);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AttaWithBuffer for PPI<'a> {
|
||||
type Data = Data;
|
||||
|
||||
fn attach_with_buffer(&mut self, gl: &glow::Context, data: &Self::Data) -> Result<()> {
|
||||
let (rdpi, adpi, data_type) = self.data_info(data)?;
|
||||
let baked_buffer = self.bake_data(data)?;
|
||||
self.buffer = baked_buffer;
|
||||
unsafe {
|
||||
gl.use_program(self.program.native_program);
|
||||
self.set_conf(gl, rdpi, adpi);
|
||||
gl.bind_vertex_array(self.vao);
|
||||
gl.buffer_data_u8_slice(
|
||||
glow::ARRAY_BUFFER,
|
||||
cast_slice(&self.buffer),
|
||||
glow::STATIC_DRAW,
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
mod test {
|
||||
#[test]
|
||||
fn test_ppi() {
|
||||
use super::*;
|
||||
// let ppi = PPI::new().unwrap();
|
||||
}
|
||||
}
|
||||
@ -2,12 +2,50 @@ pub mod polar;
|
||||
pub mod position;
|
||||
pub mod trackball;
|
||||
pub mod viewport;
|
||||
use crate::components::Snippet;
|
||||
use crate::components::{Program, Snippet};
|
||||
|
||||
pub trait Transform {
|
||||
use super::AttaWithProgram;
|
||||
|
||||
pub struct ChainedTransform {
|
||||
snippet: Snippet,
|
||||
chain: Vec<Box<dyn Transform>>,
|
||||
}
|
||||
|
||||
impl ChainedTransform {
|
||||
pub fn from<T: Transform + 'static>(transform: T) -> Self {
|
||||
let snippet = transform.snippet().clone();
|
||||
// let snippet = transform.snippet().to_owned();
|
||||
Self {
|
||||
snippet,
|
||||
chain: vec![Box::new(transform)],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn chain(mut self, other: impl Transform + 'static) -> Self {
|
||||
let new_snippet = self.snippet.clone().chain(other.snippet().to_owned());
|
||||
self.snippet = new_snippet;
|
||||
self.chain.push(Box::new(other));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Transform for ChainedTransform {
|
||||
fn snippet(&self) -> &Snippet {
|
||||
&self.snippet
|
||||
}
|
||||
}
|
||||
|
||||
impl AttaWithProgram for ChainedTransform {
|
||||
fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> super::Result<()> {
|
||||
for transform in &self.chain {
|
||||
transform.attach_with_program(gl, program)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
pub trait Transform: AttaWithProgram {
|
||||
fn snippet(&self) -> &Snippet;
|
||||
|
||||
fn chain(self, other: impl Transform) -> Self;
|
||||
}
|
||||
|
||||
mod test {
|
||||
@ -16,11 +54,11 @@ mod test {
|
||||
#[test]
|
||||
fn test_transform() {
|
||||
let polar = polar::Polar::new().unwrap();
|
||||
let trackball = trackball::Trackball::new().unwrap();
|
||||
let polar_trackball = polar.chain(trackball);
|
||||
// let trackball = trackball::Trackball::new().unwrap();
|
||||
|
||||
println!("{}", polar_trackball.snippet().prepare_code());
|
||||
// let chained = ChainedTransform::from(polar).chain(trackball);
|
||||
|
||||
// println!("{}", polar_trackball.snippet().call(vec![]));
|
||||
// println!("{}", chained.snippet().prepare_code());
|
||||
// println!("{}", chained.snippet().call(&vec![]).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
use crate::{
|
||||
components::{CodeType, Snippet},
|
||||
components::{CodeType, Program, Snippet},
|
||||
errors::*,
|
||||
graphics::AttaWithProgram,
|
||||
};
|
||||
|
||||
use super::Transform;
|
||||
@ -30,11 +31,11 @@ impl Transform for Polar {
|
||||
fn snippet(&self) -> &Snippet {
|
||||
&self.snippet
|
||||
}
|
||||
}
|
||||
|
||||
fn chain(mut self, other: impl Transform) -> Self {
|
||||
let new_snippet = self.snippet.chain(other.snippet().to_owned());
|
||||
self.snippet = new_snippet;
|
||||
self
|
||||
impl AttaWithProgram for Polar {
|
||||
fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
use super::Transform;
|
||||
use crate::{
|
||||
components::{CodeType, Snippet},
|
||||
components::{CodeType, Program, Snippet},
|
||||
errors::*,
|
||||
graphics::AttaWithProgram,
|
||||
};
|
||||
pub struct Position {
|
||||
snippet: Snippet,
|
||||
@ -24,11 +25,11 @@ impl Transform for Position {
|
||||
fn snippet(&self) -> &Snippet {
|
||||
&self.snippet
|
||||
}
|
||||
}
|
||||
|
||||
fn chain(mut self, other: impl Transform) -> Self {
|
||||
let new_snippet = self.snippet.chain(other.snippet().to_owned());
|
||||
self.snippet = new_snippet;
|
||||
self
|
||||
impl AttaWithProgram for Position {
|
||||
fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,10 +1,144 @@
|
||||
use crate::components::{CodeType, Snippet};
|
||||
use crate::components::{CodeType, Program, Snippet};
|
||||
use crate::errors::Result;
|
||||
use crate::graphics::AttaWithProgram;
|
||||
|
||||
use super::Transform;
|
||||
|
||||
use glow::HasContext;
|
||||
use nalgebra::{Matrix4, Quaternion, Translation3, Unit, UnitQuaternion, Vector3};
|
||||
|
||||
pub struct TrackballModel {
|
||||
rotation: UnitQuaternion<f32>,
|
||||
count: usize,
|
||||
model: Matrix4<f32>,
|
||||
renorm_count: usize,
|
||||
trackball_size: f32,
|
||||
x: f32,
|
||||
y: f32,
|
||||
theta: f32,
|
||||
phi: f32,
|
||||
}
|
||||
|
||||
impl TrackballModel {
|
||||
pub fn new(theta: f32, phi: f32) -> Self {
|
||||
let mut trackball = Self {
|
||||
rotation: UnitQuaternion::identity(),
|
||||
count: 0,
|
||||
model: Matrix4::identity(),
|
||||
renorm_count: 97,
|
||||
trackball_size: 0.8,
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
theta,
|
||||
phi,
|
||||
};
|
||||
trackball.set_orientation(theta, phi);
|
||||
trackball
|
||||
}
|
||||
|
||||
pub fn drag_to(&mut self, x: f32, y: f32, dx: f32, dy: f32) {
|
||||
let q = self.rotate(x, y, dx, dy);
|
||||
self.rotation *= q;
|
||||
self.count += 1;
|
||||
if self.count > self.renorm_count {
|
||||
self.rotation = UnitQuaternion::new_normalize(*self.rotation.clone());
|
||||
self.count = 0;
|
||||
}
|
||||
self.model = self.rotation.to_homogeneous();
|
||||
}
|
||||
|
||||
pub fn model(&self) -> &Matrix4<f32> {
|
||||
&self.model
|
||||
}
|
||||
|
||||
pub fn theta(&self) -> f32 {
|
||||
self.theta
|
||||
}
|
||||
|
||||
pub fn set_theta(&mut self, theta: f32) {
|
||||
self.set_orientation(theta % 360.0, self.phi % 360.0);
|
||||
}
|
||||
|
||||
pub fn phi(&self) -> f32 {
|
||||
self.phi
|
||||
}
|
||||
|
||||
pub fn set_phi(&mut self, phi: f32) {
|
||||
self.set_orientation(self.theta % 360.0, phi % 360.0);
|
||||
}
|
||||
|
||||
fn get_orientation(&self) -> (f32, f32) {
|
||||
let q = self.rotation.quaternion();
|
||||
let ax = (2.0 * (q.w * q.i + q.j * q.k) / (1.0 - 2.0 * (q.i * q.i + q.j * q.j))).atan()
|
||||
* 180.0
|
||||
/ std::f32::consts::PI;
|
||||
let az = (2.0 * (q.w * q.k + q.i * q.j) / (1.0 - 2.0 * (q.j * q.j + q.k * q.k))).atan()
|
||||
* 180.0
|
||||
/ std::f32::consts::PI;
|
||||
(-az, ax)
|
||||
}
|
||||
|
||||
fn set_orientation(&mut self, theta: f32, phi: f32) {
|
||||
self.theta = theta;
|
||||
self.phi = phi;
|
||||
|
||||
let angle = self.theta * (std::f32::consts::PI / 180.0);
|
||||
let sine = (0.5 * angle).sin();
|
||||
let xrot =
|
||||
UnitQuaternion::from_quaternion(Quaternion::new((0.5 * angle).cos(), sine, 0.0, 0.0));
|
||||
|
||||
let angle = self.phi * (std::f32::consts::PI / 180.0);
|
||||
let sine = (0.5 * angle).sin();
|
||||
let zrot =
|
||||
UnitQuaternion::from_quaternion(Quaternion::new((0.5 * angle).cos(), 0.0, 0.0, sine));
|
||||
|
||||
self.rotation = xrot * zrot;
|
||||
self.model = self.rotation.to_homogeneous();
|
||||
}
|
||||
|
||||
fn project(&self, r: f32, x: f32, y: f32) -> f32 {
|
||||
let d = (x * x + y * y).sqrt();
|
||||
if d < r * 0.70710678118654752440 {
|
||||
(r * r - d * d).sqrt()
|
||||
} else {
|
||||
let t = r / 1.41421356237309504880;
|
||||
t * t / d
|
||||
}
|
||||
}
|
||||
|
||||
fn rotate(&self, x: f32, y: f32, dx: f32, dy: f32) -> UnitQuaternion<f32> {
|
||||
if dx == 0.0 && dy == 0.0 {
|
||||
return UnitQuaternion::identity();
|
||||
}
|
||||
|
||||
let last = Vector3::new(x, y, self.project(self.trackball_size, x, y));
|
||||
let new = Vector3::new(
|
||||
x + dx,
|
||||
y + dy,
|
||||
self.project(self.trackball_size, x + dx, y + dy),
|
||||
);
|
||||
|
||||
let a = new.cross(&last);
|
||||
let d = last - new;
|
||||
let t = d.norm() / (2.0 * self.trackball_size);
|
||||
let t = t.clamp(-1.0, 1.0);
|
||||
|
||||
let phi = 2.0 * t.asin();
|
||||
UnitQuaternion::from_axis_angle(&Unit::new_normalize(a), phi)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Trackball {
|
||||
snippet: Snippet,
|
||||
|
||||
znear: f32,
|
||||
zfar: f32,
|
||||
zoom: f32,
|
||||
aspect: f32,
|
||||
model: TrackballModel,
|
||||
|
||||
projection: nalgebra_glm::Mat4x4,
|
||||
view: nalgebra::Matrix4<f32>,
|
||||
}
|
||||
|
||||
impl Trackball {
|
||||
@ -16,7 +150,84 @@ impl Trackball {
|
||||
None,
|
||||
)?;
|
||||
|
||||
Ok(Self { snippet: snippets })
|
||||
let model = TrackballModel::new(45.0, 45.0);
|
||||
|
||||
let aspect = 1.0;
|
||||
let fovy = 45.0;
|
||||
let near = 2.0;
|
||||
let far = 1000.0;
|
||||
|
||||
let projection = nalgebra_glm::perspective(aspect, fovy, near, far);
|
||||
|
||||
let mut view: Matrix4<f32> = Matrix4::identity();
|
||||
|
||||
let distance: f32 = 8.0;
|
||||
|
||||
let translation = Translation3::new(0.0, 0.0, -distance.abs());
|
||||
view = translation.to_homogeneous() * view;
|
||||
|
||||
Ok(Self {
|
||||
snippet: snippets,
|
||||
znear: near,
|
||||
zfar: far,
|
||||
zoom: fovy,
|
||||
aspect,
|
||||
model,
|
||||
projection,
|
||||
view,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn on_mouse_drag(
|
||||
&mut self,
|
||||
gl: &glow::Context,
|
||||
program: &mut Program,
|
||||
x: f32,
|
||||
y: f32,
|
||||
dx: f32,
|
||||
dy: f32,
|
||||
) {
|
||||
self.model.drag_to(x, y, dx, dy);
|
||||
unsafe {
|
||||
let model = self.snippet.find_symbol("trackball_model").unwrap();
|
||||
let l = program.get_uniform_location(gl, &model);
|
||||
gl.uniform_matrix_4_f32_slice(l.as_ref(), false, self.model.model().as_slice());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_mouse_scroll(
|
||||
&mut self,
|
||||
gl: &glow::Context,
|
||||
program: &mut Program,
|
||||
x: f32,
|
||||
y: f32,
|
||||
dz: f32,
|
||||
) {
|
||||
self.zoom += dz;
|
||||
self.projection = nalgebra_glm::perspective(self.aspect, self.zoom, self.znear, self.zfar);
|
||||
unsafe {
|
||||
let model = self.snippet.find_symbol("trackball_projection").unwrap();
|
||||
let l = program.get_uniform_location(gl, &model);
|
||||
gl.uniform_matrix_4_f32_slice(l.as_ref(), false, self.model.model().as_slice());
|
||||
}
|
||||
}
|
||||
|
||||
fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> Result<()> {
|
||||
unsafe {
|
||||
let model = self.snippet.find_symbol("trackball_model").unwrap();
|
||||
let l = program.get_uniform_location(gl, &model);
|
||||
gl.uniform_matrix_4_f32_slice(l.as_ref(), false, self.model.model().as_slice());
|
||||
|
||||
let projection = self.snippet.find_symbol("trackball_projection").unwrap();
|
||||
let l = program.get_uniform_location(gl, &projection);
|
||||
gl.uniform_matrix_4_f32_slice(l.as_ref(), false, self.projection.as_slice());
|
||||
|
||||
let view = self.snippet.find_symbol("trackball_view").unwrap();
|
||||
let l = program.get_uniform_location(gl, &view);
|
||||
gl.uniform_matrix_4_f32_slice(l.as_ref(), false, self.view.as_slice());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,11 +235,11 @@ impl Transform for Trackball {
|
||||
fn snippet(&self) -> &Snippet {
|
||||
&self.snippet
|
||||
}
|
||||
}
|
||||
|
||||
fn chain(mut self, other: impl Transform) -> Self {
|
||||
let new_snippet = self.snippet.chain(other.snippet().to_owned());
|
||||
self.snippet = new_snippet;
|
||||
self
|
||||
impl AttaWithProgram for Trackball {
|
||||
fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> Result<()> {
|
||||
self.attach_with_program(gl, program)
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,8 +248,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_trackball() {
|
||||
let trackball = Trackball::new().unwrap();
|
||||
|
||||
println!("{}", trackball.snippet);
|
||||
// let trackball = Trackball::new().unwrap();
|
||||
// println!("{}", trackball.snippet);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,15 @@
|
||||
use glow::HasContext;
|
||||
|
||||
use crate::{
|
||||
components::{self, CodeType, Snippet},
|
||||
components::{self, CodeType, Program, Snippet},
|
||||
errors::*,
|
||||
graphics::AttaWithProgram,
|
||||
};
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Viewport {
|
||||
snippet: Snippet,
|
||||
viewport_global: [f32; 4],
|
||||
viewport_local: Option<[f32; 4]>,
|
||||
}
|
||||
|
||||
impl Viewport {
|
||||
@ -15,10 +21,71 @@ impl Viewport {
|
||||
None,
|
||||
)?;
|
||||
|
||||
Ok(Self { snippet: snippets })
|
||||
Ok(Self {
|
||||
snippet: snippets,
|
||||
viewport_global: [0.0, 0.0, 0.0, 0.0],
|
||||
viewport_local: None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn snippet(&self) -> &Snippet {
|
||||
&self.snippet
|
||||
}
|
||||
|
||||
pub fn set_global(&mut self, x: f32, y: f32, width: f32, height: f32) {
|
||||
self.viewport_global = [x, y, width, height];
|
||||
}
|
||||
|
||||
pub fn create_local(&self, x: f32, y: f32, width: f32, height: f32) -> Self {
|
||||
let mut l = self.clone();
|
||||
l.viewport_local = Some([x, y, width, height]);
|
||||
l
|
||||
}
|
||||
|
||||
fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> Result<()> {
|
||||
unsafe {
|
||||
let global = self.snippet.find_symbol("viewport_global").unwrap();
|
||||
let l = program.get_uniform_location(gl, &global);
|
||||
gl.uniform_4_f32(
|
||||
l.as_ref(),
|
||||
self.viewport_global[0],
|
||||
self.viewport_global[1],
|
||||
self.viewport_global[2],
|
||||
self.viewport_global[3],
|
||||
);
|
||||
|
||||
let local = self.snippet.find_symbol("viewport_local").unwrap();
|
||||
|
||||
if let Some([x, y, z, w]) = self.viewport_local {
|
||||
let l = program.get_uniform_location(gl, &local);
|
||||
let l = l.as_ref();
|
||||
gl.uniform_4_f32(l, x, y, z, w);
|
||||
} else {
|
||||
let l = program.get_uniform_location(gl, &local);
|
||||
let l = l.as_ref();
|
||||
gl.uniform_4_f32(
|
||||
l,
|
||||
self.viewport_global[0],
|
||||
self.viewport_global[1],
|
||||
self.viewport_global[2],
|
||||
self.viewport_global[3],
|
||||
);
|
||||
}
|
||||
|
||||
let viewport = self.snippet.find_symbol("viewport_transform").unwrap();
|
||||
let l = program.get_uniform_location(gl, &viewport);
|
||||
gl.uniform_1_f32(l.as_ref(), 0.0);
|
||||
|
||||
let viewport = self.snippet.find_symbol("viewport_clipping").unwrap();
|
||||
let l = program.get_uniform_location(gl, &viewport);
|
||||
gl.uniform_1_f32(l.as_ref(), 0.0);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl AttaWithProgram for Viewport {
|
||||
fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> Result<()> {
|
||||
self.attach_with_program(gl, program)
|
||||
}
|
||||
}
|
||||
|
||||
32
src/main.rs
32
src/main.rs
@ -1,7 +1,10 @@
|
||||
use data_loader::Data;
|
||||
use graphics::AttaWithBuffer;
|
||||
use imgui::Condition;
|
||||
|
||||
mod camera;
|
||||
mod components;
|
||||
mod data_loader;
|
||||
mod errors;
|
||||
mod graphics;
|
||||
mod support;
|
||||
@ -12,8 +15,10 @@ mod final_pg;
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
let choices = ["test test this is 1", "test test this is 2"];
|
||||
let path = "/Users/tsuki/Desktop/ZJSXAA_20230113070200_R.dat.gz";
|
||||
let data = Data::from_path(path).unwrap();
|
||||
let mut value = 0;
|
||||
support::supporter::init(move |_, ui| {
|
||||
support::supporter::init(move |_, ui, program, window, gl| {
|
||||
ui.window("Hello world")
|
||||
.size([300.0, 110.0], Condition::FirstUseEver)
|
||||
.build(|| {
|
||||
@ -31,25 +36,18 @@ fn main() {
|
||||
"Mouse Position: ({:.1},{:.1})",
|
||||
mouse_pos[0], mouse_pos[1]
|
||||
));
|
||||
});
|
||||
|
||||
ui.window("Hello world")
|
||||
.size([300.0, 110.0], Condition::FirstUseEver)
|
||||
.build(|| {
|
||||
ui.text_wrapped("Hello world!");
|
||||
ui.text_wrapped("こんにちは世界!");
|
||||
if ui.button(choices[value]) {
|
||||
value += 1;
|
||||
value %= 2;
|
||||
if ui.button("Add Layer") {
|
||||
program.add_ppi_layer(1);
|
||||
program.attach_with_buffer(gl, &data).unwrap();
|
||||
window.request_redraw();
|
||||
}
|
||||
|
||||
ui.button("This...is...imgui-rs!");
|
||||
ui.separator();
|
||||
let mouse_pos = ui.io().mouse_pos;
|
||||
ui.text(format!(
|
||||
"Mouse Position: ({:.1},{:.1})",
|
||||
mouse_pos[0], mouse_pos[1]
|
||||
));
|
||||
if ui.button("Remove Layer") {
|
||||
program.add_ppi_layer(-1);
|
||||
program.attach_with_buffer(gl, &data).unwrap();
|
||||
window.request_redraw();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
use crate::camera::Camera;
|
||||
use crate::graphics::Graphics;
|
||||
use crate::graphics::colormap::linear::LinearColormap;
|
||||
use crate::graphics::ppi::PPI;
|
||||
use crate::graphics::transforms::{position, ChainedTransform};
|
||||
use crate::graphics::{hello, AttaWithBuffer, AttaWithProgram, Graphics};
|
||||
use crate::{
|
||||
graphics::{
|
||||
collections::agg_fast_path::AggFastPath,
|
||||
@ -34,28 +37,16 @@ use std::time::Instant;
|
||||
|
||||
pub fn init<FUi>(mut run_ui: FUi)
|
||||
where
|
||||
FUi: FnMut(&mut bool, &mut Ui) + 'static,
|
||||
FUi: FnMut(&mut bool, &mut Ui, &mut PPI, &Window, &glow::Context) + 'static,
|
||||
{
|
||||
let (event_loop, window, surface, context) = create_window();
|
||||
let (mut winit_platform, mut imgui_context) = imgui_init(&window);
|
||||
|
||||
{
|
||||
let dpi_mode = if let Ok(factor) = std::env::var("IMGUI_EXAMPLE_FORCE_DPI_FACTOR") {
|
||||
// Allow forcing of HiDPI factor for debugging purposes
|
||||
match factor.parse::<f64>() {
|
||||
Ok(f) => HiDpiMode::Locked(f),
|
||||
Err(e) => panic!("Invalid scaling factor: {}", e),
|
||||
}
|
||||
} else {
|
||||
HiDpiMode::Default
|
||||
};
|
||||
|
||||
winit_platform.attach_window(imgui_context.io_mut(), &window, dpi_mode);
|
||||
}
|
||||
|
||||
let gl = unsafe {
|
||||
let gl = glow_context(&context);
|
||||
gl.enable(glow::DEPTH_TEST);
|
||||
gl.enable(glow::BLEND);
|
||||
gl.blend_func(glow::SRC_ALPHA, glow::ONE_MINUS_SRC_ALPHA);
|
||||
gl
|
||||
};
|
||||
|
||||
@ -64,30 +55,37 @@ where
|
||||
.expect("failed to create renderer");
|
||||
|
||||
let mut last_frame = Instant::now();
|
||||
let tri_renderer = Triangler::new(ig_renderer.gl_context(), "#version 330");
|
||||
let transform = Position::new().unwrap();
|
||||
|
||||
let viewport = Trackball::new().unwrap();
|
||||
let trans = Polar::new().unwrap();
|
||||
let position = Position::new().unwrap();
|
||||
let mut viewport = Viewport::new().unwrap();
|
||||
let mut cmap = LinearColormap::new().unwrap();
|
||||
|
||||
let transform = viewport.chain(trans.chain(position));
|
||||
cmap.set_colors(vec![
|
||||
[170, 170, 170, 255],
|
||||
[0, 34, 255, 255],
|
||||
[1, 160, 246, 255],
|
||||
[0, 236, 236, 255],
|
||||
[0, 216, 0, 255],
|
||||
[1, 144, 0, 255],
|
||||
[255, 255, 0, 255],
|
||||
[231, 192, 0, 255],
|
||||
[255, 144, 0, 255],
|
||||
[255, 0, 0, 255],
|
||||
[214, 0, 0, 255],
|
||||
[192, 0, 0, 255],
|
||||
[255, 0, 240, 255],
|
||||
[150, 0, 180, 255],
|
||||
]);
|
||||
cmap.set_range(0.0, 70.0);
|
||||
|
||||
let viewport = Viewport::new().unwrap();
|
||||
let mut ppi = PPI::new(&mut cmap).unwrap();
|
||||
ppi.set_transform(&transform);
|
||||
ppi.set_viewport(&viewport);
|
||||
ppi.compile(ig_renderer.gl_context()).unwrap();
|
||||
|
||||
let mut agg_path = AggFastPath::new(&transform, &viewport).unwrap();
|
||||
|
||||
agg_path.compile(ig_renderer.gl_context()).unwrap();
|
||||
|
||||
let program = tri_renderer.program();
|
||||
let mut camera = Camera::new(
|
||||
Vec3::new(0.5, 0.5, 1.0), // Camera position (world location
|
||||
Vec3::new(0.0, 1.0, 0.0), // Upward vector
|
||||
Vec3::new(0.0, 0.0, -1.0), // Look at vector
|
||||
);
|
||||
|
||||
let mut last_position: Option<PhysicalPosition<f64>> = None;
|
||||
let mut yaw = -90.0;
|
||||
let mut pitch = 0.0;
|
||||
transform
|
||||
.attach_with_program(ig_renderer.gl_context(), ppi.program_ref())
|
||||
.unwrap();
|
||||
|
||||
event_loop
|
||||
.run(move |event, window_target| {
|
||||
@ -115,40 +113,26 @@ where
|
||||
|
||||
unsafe {
|
||||
let gl = ig_renderer.gl_context();
|
||||
|
||||
gl.clear(glow::COLOR_BUFFER_BIT | glow::DEPTH_BUFFER_BIT);
|
||||
|
||||
let loc = gl.get_uniform_location(program, "projection");
|
||||
let size = window.inner_size();
|
||||
let projection =
|
||||
perspective(size.width as f32 / size.height as f32, 45.0, 0.1, 100.0);
|
||||
gl.uniform_matrix_4_f32_slice(loc.as_ref(), false, projection.as_slice());
|
||||
|
||||
let loc = gl.get_uniform_location(program, "view");
|
||||
let view = camera.get_view_matrix();
|
||||
gl.uniform_matrix_4_f32_slice(loc.as_ref(), false, view.as_slice());
|
||||
gl.clear(glow::DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
tri_renderer.render(ig_renderer.gl_context());
|
||||
|
||||
ppi.draw(ig_renderer.gl_context()).unwrap();
|
||||
let ui = imgui_context.frame();
|
||||
|
||||
if ui.is_mouse_pos_valid(ui.io().mouse_pos) {
|
||||
let mouse_pos = ui.io().mouse_pos;
|
||||
if ui.is_mouse_dragging(imgui::MouseButton::Right) {
|
||||
mouse_callback(
|
||||
&mut last_position,
|
||||
PhysicalPosition::new(mouse_pos[0] as f64, mouse_pos[1] as f64),
|
||||
0.05,
|
||||
&mut pitch,
|
||||
&mut yaw,
|
||||
&mut camera,
|
||||
);
|
||||
// mouse_callback(
|
||||
// &mut last_position,
|
||||
// PhysicalPosition::new(mouse_pos[0] as f64, mouse_pos[1] as f64),
|
||||
// 0.05,
|
||||
// &mut pitch,
|
||||
// &mut yaw,
|
||||
// &mut camera,
|
||||
// );
|
||||
}
|
||||
}
|
||||
|
||||
let mut run = true;
|
||||
run_ui(&mut run, ui);
|
||||
run_ui(&mut run, ui, &mut ppi, &window, ig_renderer.gl_context());
|
||||
|
||||
if !run {
|
||||
window_target.exit();
|
||||
@ -182,12 +166,23 @@ where
|
||||
NonZeroU32::new(new_size.width).unwrap(),
|
||||
NonZeroU32::new(new_size.height).unwrap(),
|
||||
);
|
||||
|
||||
viewport.set_global(
|
||||
0f32,
|
||||
0f32,
|
||||
new_size.width as f32,
|
||||
new_size.height as f32,
|
||||
);
|
||||
|
||||
viewport
|
||||
.attach_with_program(ig_renderer.gl_context(), ppi.program_ref())
|
||||
.unwrap();
|
||||
}
|
||||
winit_platform.handle_event(imgui_context.io_mut(), &window, &event);
|
||||
}
|
||||
winit::event::Event::LoopExiting => {
|
||||
let gl = ig_renderer.gl_context();
|
||||
tri_renderer.destroy(gl);
|
||||
ppi.destroy(gl).unwrap();
|
||||
}
|
||||
event => {
|
||||
winit_platform.handle_event(imgui_context.io_mut(), &window, &event);
|
||||
@ -302,11 +297,20 @@ fn imgui_init(window: &Window) -> (WinitPlatform, imgui::Context) {
|
||||
imgui_context.set_ini_filename(None);
|
||||
|
||||
let mut winit_platform = WinitPlatform::init(&mut imgui_context);
|
||||
winit_platform.attach_window(
|
||||
imgui_context.io_mut(),
|
||||
window,
|
||||
imgui_winit_support::HiDpiMode::Rounded,
|
||||
);
|
||||
|
||||
{
|
||||
let dpi_mode = if let Ok(factor) = std::env::var("IMGUI_EXAMPLE_FORCE_DPI_FACTOR") {
|
||||
// Allow forcing of HiDPI factor for debugging purposes
|
||||
match factor.parse::<f64>() {
|
||||
Ok(f) => HiDpiMode::Locked(f),
|
||||
Err(e) => panic!("Invalid scaling factor: {}", e),
|
||||
}
|
||||
} else {
|
||||
HiDpiMode::Default
|
||||
};
|
||||
|
||||
winit_platform.attach_window(imgui_context.io_mut(), &window, dpi_mode);
|
||||
}
|
||||
|
||||
imgui_context
|
||||
.fonts()
|
||||
|
||||
17
src/utils/geo_tools.rs
Normal file
17
src/utils/geo_tools.rs
Normal file
@ -0,0 +1,17 @@
|
||||
use geo::{algorithm::haversine_destination::HaversineDestination, Point};
|
||||
pub fn calculate_coverage(lat_deg: f64, lon_deg: f64, radius_km: f64) -> (f64, f64, f64, f64) {
|
||||
let center = Point::new(lon_deg, lat_deg);
|
||||
|
||||
// 计算四个方向(北、南、东、西)的点
|
||||
let north = center.haversine_destination(0.0, radius_km);
|
||||
let south = center.haversine_destination(180.0, radius_km);
|
||||
let east = center.haversine_destination(90.0, radius_km);
|
||||
let west = center.haversine_destination(270.0, radius_km);
|
||||
|
||||
let min_lat = south.y();
|
||||
let max_lat = north.y();
|
||||
let min_lon = west.x();
|
||||
let max_lon = east.x();
|
||||
|
||||
(min_lat, max_lat, min_lon, max_lon)
|
||||
}
|
||||
@ -2,6 +2,7 @@ mod parser;
|
||||
use include_dir::{include_dir, Dir};
|
||||
pub use parser::*;
|
||||
use std::{num::NonZeroU32, path::Path};
|
||||
pub mod geo_tools;
|
||||
|
||||
use glow::HasContext;
|
||||
use glutin::{
|
||||
|
||||
@ -14,12 +14,12 @@ use nom::{
|
||||
branch::alt,
|
||||
bytes::complete::{tag, take_till, take_until, take_while, take_while1},
|
||||
character::complete::{
|
||||
alpha1, char, digit1, multispace0, multispace1, none_of, space0, space1,
|
||||
alpha1, char, digit0, digit1, multispace0, multispace1, none_of, space0, space1,
|
||||
},
|
||||
combinator::{cut, map, map_res, opt, recognize, verify},
|
||||
multi::{fold_many0, many0, many0_count, many1, separated_list0, separated_list1},
|
||||
sequence::{delimited, pair, preceded, separated_pair, terminated, tuple},
|
||||
IResult, InputIter,
|
||||
Finish, IResult, InputIter,
|
||||
};
|
||||
|
||||
use crate::{components::Snippet, errors::*};
|
||||
@ -143,8 +143,10 @@ pub enum Modifier {
|
||||
Static,
|
||||
Extern,
|
||||
Uniform,
|
||||
In(Option<usize>),
|
||||
Layout(Option<Vec<Expression>>),
|
||||
In,
|
||||
Out,
|
||||
Flat,
|
||||
}
|
||||
|
||||
impl Display for Modifier {
|
||||
@ -154,9 +156,18 @@ impl Display for Modifier {
|
||||
Modifier::Static => write!(f, "static"),
|
||||
Modifier::Extern => write!(f, "extern"),
|
||||
Modifier::Uniform => write!(f, "uniform"),
|
||||
Modifier::In(Some(v)) => write!(f, "layout(location = {}) in", v),
|
||||
Modifier::In(None) => write!(f, "in"),
|
||||
Modifier::In => write!(f, "in"),
|
||||
Modifier::Layout(Some(v)) => write!(
|
||||
f,
|
||||
"layout({})",
|
||||
v.iter()
|
||||
.map(|v| v.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(",")
|
||||
),
|
||||
Modifier::Layout(None) => write!(f, "layout"),
|
||||
Modifier::Out => write!(f, "out"),
|
||||
Modifier::Flat => write!(f, "flat"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -176,24 +187,22 @@ fn modifier(input: &str) -> IResult<&str, Modifier> {
|
||||
Ok::<Modifier, nom::error::Error<&str>>(Modifier::Uniform)
|
||||
}),
|
||||
map_res(
|
||||
pair(
|
||||
opt(tuple((
|
||||
tag("layout"),
|
||||
multispace0::<&str, nom::error::Error<&str>>,
|
||||
delimited(
|
||||
char('('),
|
||||
tuple((tag("location"), multispace0, char('='), space0, digit1)),
|
||||
char(')'),
|
||||
),
|
||||
space0,
|
||||
))),
|
||||
tag("in"),
|
||||
),
|
||||
|(a, _)| {
|
||||
let c = a.map(|(_, _, (_, _, _, _, v), _)| v.parse::<usize>().unwrap());
|
||||
Ok::<Modifier, nom::error::Error<&str>>(Modifier::In(c))
|
||||
},
|
||||
tuple((
|
||||
tag("layout"),
|
||||
opt(delimited(
|
||||
char('('),
|
||||
separated_list0(char(','), ws(alt((parse_assignment, parse_variable)))),
|
||||
char(')'),
|
||||
)),
|
||||
)),
|
||||
|(_, v)| Ok::<Modifier, nom::error::Error<&str>>(Modifier::Layout(v)),
|
||||
),
|
||||
map_res(tag("flat"), |_| {
|
||||
Ok::<Modifier, nom::error::Error<&str>>(Modifier::Flat)
|
||||
}),
|
||||
map_res(tag("in"), |_| {
|
||||
Ok::<Modifier, nom::error::Error<&str>>(Modifier::In)
|
||||
}),
|
||||
map_res(tag("out"), |_| {
|
||||
Ok::<Modifier, nom::error::Error<&str>>(Modifier::Out)
|
||||
}),
|
||||
@ -217,7 +226,8 @@ impl Display for ShareVariable {
|
||||
self.modif
|
||||
.iter()
|
||||
.map(|v| format!("{}", v))
|
||||
.collect::<String>(),
|
||||
.collect::<Vec<_>>()
|
||||
.join(" "),
|
||||
self.typ,
|
||||
self.name,
|
||||
self.value
|
||||
@ -228,17 +238,19 @@ impl Display for ShareVariable {
|
||||
}
|
||||
}
|
||||
|
||||
fn array_parse(input: &str) -> IResult<&str, Option<usize>> {
|
||||
let (input, v) = delimited(pair(char('['), space0), digit0, ws(char(']')))(input)?;
|
||||
Ok((input, v.parse().ok()))
|
||||
}
|
||||
|
||||
fn _share_variable(input: &str) -> IResult<&str, ShareVariable> {
|
||||
let (input, modifier) = many0(modifier)(input)?;
|
||||
let (input, _) = multispace1(input)?;
|
||||
let (input, modifier) = many0(terminated(modifier, multispace1))(input)?;
|
||||
// let (input, _) = multispace1(input)?;
|
||||
let (input, typ) = type_name(input)?;
|
||||
let (input, _) = multispace1(input)?;
|
||||
let (input, name) = identifier(input)?;
|
||||
let (input, name) = recognize(pair(identifier, opt(array_parse)))(input)?;
|
||||
|
||||
let (input, value) = opt(preceded(
|
||||
ws(char('=')),
|
||||
ws(take_till(|c| c == ';' || c == '\n')),
|
||||
))(input)?;
|
||||
let (input, value) = opt(preceded(ws(char('=')), ws(take_till(|c| c == ';'))))(input)?;
|
||||
Ok((
|
||||
input,
|
||||
ShareVariable {
|
||||
@ -250,6 +262,11 @@ fn _share_variable(input: &str) -> IResult<&str, ShareVariable> {
|
||||
))
|
||||
}
|
||||
|
||||
fn geom_layout(input: &str) -> IResult<&str, Vec<Modifier>> {
|
||||
let (input, modifier) = separated_list1(space1, modifier)(input)?;
|
||||
Ok((input, modifier))
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Eq, Hash)]
|
||||
pub enum PreprocessorDirective {
|
||||
IfDef { condition: String },
|
||||
@ -441,7 +458,7 @@ fn hook(input: &str) -> IResult<&str, Hook> {
|
||||
separated_list1(char('.'), identifier),
|
||||
opt(delimited(
|
||||
char('('),
|
||||
separated_list0(ws(char(',')), ws(identifier)),
|
||||
separated_list0(char(','), ws(expression)),
|
||||
char(')'),
|
||||
)),
|
||||
),
|
||||
@ -481,6 +498,40 @@ pub enum Code {
|
||||
PreprocessorDirective(Rc<RefCell<PreprocessorDirective>>, Box<Vec<Code>>),
|
||||
Macro(Rc<RefCell<PreprocessorDirective>>),
|
||||
ShareVariable(Rc<RefCell<ShareVariable>>),
|
||||
GeomLayout(Rc<RefCell<Vec<Modifier>>>),
|
||||
}
|
||||
|
||||
impl Code {
|
||||
pub fn parse(input: &str) -> IResult<&str, Self> {
|
||||
ws(alt((
|
||||
map(
|
||||
tuple((
|
||||
alt((parse_ifdef, parse_ifndef)),
|
||||
many0(Self::parse),
|
||||
cut(parse_endif),
|
||||
)),
|
||||
|(pre, inner, _)| {
|
||||
Code::PreprocessorDirective(Rc::new(RefCell::new(pre)), Box::new(inner))
|
||||
},
|
||||
),
|
||||
map(parse_macro, |v| Code::Macro(Rc::new(RefCell::new(v)))),
|
||||
map(include, |v| Code::Include(Rc::new(RefCell::new(v)))),
|
||||
map(function, |v| Code::Function(Rc::new(RefCell::new(v)))),
|
||||
map(terminated(parse_struct, pair(space0, char(';'))), |s| {
|
||||
Code::Struct(Rc::new(RefCell::new(s)))
|
||||
}),
|
||||
map(terminated(_share_variable, char(';')), |v| {
|
||||
Code::ShareVariable(Rc::new(RefCell::new(v)))
|
||||
}),
|
||||
map(terminated(geom_layout, char(';')), |v| {
|
||||
Code::GeomLayout(Rc::new(RefCell::new(v)))
|
||||
}),
|
||||
)))(input)
|
||||
}
|
||||
|
||||
pub fn new(input: &str) -> Self {
|
||||
Self::parse(input).finish().unwrap().1
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -664,7 +715,7 @@ impl Display for Statement {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Expression {
|
||||
Binary {
|
||||
left: Box<Expression>,
|
||||
@ -694,6 +745,10 @@ pub enum Expression {
|
||||
base: Box<Expression>,
|
||||
member: String,
|
||||
},
|
||||
ArrayAccess {
|
||||
base: Box<Expression>,
|
||||
member: Box<Expression>,
|
||||
},
|
||||
|
||||
Hook(Hook),
|
||||
}
|
||||
@ -740,6 +795,9 @@ impl Display for Expression {
|
||||
Expression::Hook(hook) => write!(f, "{}", hook),
|
||||
Expression::StructMemberAccess { base, member } => write!(f, "{}.{}", base, member),
|
||||
Expression::StructPointerAccess { base, member } => write!(f, "{}->{}", base, member),
|
||||
Expression::ArrayAccess { base, member } => {
|
||||
write!(f, "{}[{}]", base, member)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -879,13 +937,31 @@ fn parse_arith(input: &str) -> IResult<&str, Expression> {
|
||||
)(input)
|
||||
}
|
||||
|
||||
fn parse_array_access(input: &str) -> IResult<&str, Expression> {
|
||||
let inn = delimited(
|
||||
char('['),
|
||||
alt((map(parse_integer, Expression::Literal), parse_variable)),
|
||||
char(']'),
|
||||
);
|
||||
let (input, rs) = pair(parse_variable, inn)(input)?;
|
||||
|
||||
Ok((
|
||||
input,
|
||||
Expression::ArrayAccess {
|
||||
base: Box::new(rs.0),
|
||||
member: Box::new(rs.1),
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
fn parse_factor(input: &str) -> IResult<&str, Expression> {
|
||||
delimited(
|
||||
multispace0,
|
||||
alt((
|
||||
delimited(char('('), expression, char(')')),
|
||||
parse_struct_pointer_access,
|
||||
parse_struct_member_access,
|
||||
parse_struct_pointer_access,
|
||||
parse_array_access,
|
||||
parse_unary,
|
||||
parse_function_call,
|
||||
parse_assignment,
|
||||
@ -957,7 +1033,10 @@ fn parse_struct_member_access(input: &str) -> IResult<&str, Expression> {
|
||||
map(
|
||||
separated_pair(
|
||||
alt((
|
||||
// parse_struct_member_access,
|
||||
// parse_struct_pointer_access,
|
||||
map(hook, Expression::Hook),
|
||||
parse_array_access,
|
||||
map(identifier, |v| Expression::Variable(v.to_string())),
|
||||
)),
|
||||
char('.'),
|
||||
@ -1142,6 +1221,20 @@ impl Display for Code {
|
||||
}
|
||||
Code::Macro(v) => write!(f, "{}", *v.borrow()),
|
||||
Code::ShareVariable(v) => write!(f, "{};", *v.borrow()),
|
||||
Code::GeomLayout(v) => {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
v.borrow()
|
||||
.iter()
|
||||
.map(|v| v.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(" ")
|
||||
)?;
|
||||
writeln!(f, ";")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1210,27 +1303,7 @@ impl CodeBlock {
|
||||
}
|
||||
|
||||
fn _parse(input: &str) -> IResult<&str, Vec<Code>> {
|
||||
many1(ws(alt((
|
||||
map(
|
||||
tuple((
|
||||
alt((parse_ifdef, parse_ifndef)),
|
||||
Self::_parse,
|
||||
cut(parse_endif),
|
||||
)),
|
||||
|(pre, inner, _)| {
|
||||
Code::PreprocessorDirective(Rc::new(RefCell::new(pre)), Box::new(inner))
|
||||
},
|
||||
),
|
||||
map(parse_macro, |v| Code::Macro(Rc::new(RefCell::new(v)))),
|
||||
map(include, |v| Code::Include(Rc::new(RefCell::new(v)))),
|
||||
map(function, |v| Code::Function(Rc::new(RefCell::new(v)))),
|
||||
map(terminated(parse_struct, pair(space0, char(';'))), |s| {
|
||||
Code::Struct(Rc::new(RefCell::new(s)))
|
||||
}),
|
||||
map(terminated(_share_variable, char(';')), |v| {
|
||||
Code::ShareVariable(Rc::new(RefCell::new(v)))
|
||||
}),
|
||||
))))(input)
|
||||
many1(Code::parse)(input)
|
||||
}
|
||||
|
||||
pub fn public_variables(&self) -> Vec<&RFC<ShareVariable>> {
|
||||
@ -1291,7 +1364,10 @@ impl CodeBlock {
|
||||
}
|
||||
}
|
||||
|
||||
Expression::FunctionCall { parameters, .. } => {
|
||||
Expression::FunctionCall { parameters, name } => {
|
||||
if let Some(new) = map.get(name) {
|
||||
*name = new.clone();
|
||||
}
|
||||
for para in parameters.iter_mut() {
|
||||
_expression_mangling(para, map);
|
||||
}
|
||||
@ -1302,12 +1378,24 @@ impl CodeBlock {
|
||||
_expression_mangling(right, map);
|
||||
}
|
||||
|
||||
Expression::Binary { left, right, .. } => {
|
||||
_expression_mangling(left, map);
|
||||
_expression_mangling(right, map);
|
||||
}
|
||||
|
||||
Expression::Unary { right, .. } => {
|
||||
_expression_mangling(right, map);
|
||||
}
|
||||
|
||||
Expression::StructMemberAccess { base, .. } => {
|
||||
_expression_mangling(base, map);
|
||||
}
|
||||
|
||||
Expression::StructPointerAccess { base, .. } => {
|
||||
Expression::StructPointerAccess { base, .. } => _expression_mangling(base, map),
|
||||
|
||||
Expression::ArrayAccess { base, member } => {
|
||||
_expression_mangling(base, map);
|
||||
_expression_mangling(member, map);
|
||||
}
|
||||
|
||||
_ => {}
|
||||
@ -1331,6 +1419,15 @@ impl CodeBlock {
|
||||
_mangling_block(block, map);
|
||||
}
|
||||
|
||||
Statement::Else { block } => {
|
||||
if let Statement::If { condition, block } = block.as_mut() {
|
||||
_expression_mangling(condition, map);
|
||||
_mangling_block(block, map);
|
||||
} else {
|
||||
_mangling_block(block, map);
|
||||
}
|
||||
}
|
||||
|
||||
Statement::While { condition, block } => {
|
||||
_expression_mangling(condition, map);
|
||||
_mangling_block(block, map);
|
||||
@ -1420,6 +1517,10 @@ impl CodeBlock {
|
||||
pub fn find_variable(&self, name: &str) -> Option<&RFC<ShareVariable>> {
|
||||
self.snippet.find_variable(name)
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, code: Code, index: usize) {
|
||||
self.codes.insert(index, code);
|
||||
}
|
||||
}
|
||||
|
||||
impl SnippetCode {
|
||||
@ -1706,10 +1807,16 @@ impl SnippetCode {
|
||||
Self::_check_hook_exp(old, code, v, valid);
|
||||
}
|
||||
}
|
||||
|
||||
Statement::Expression(v) => {
|
||||
Self::_check_hook_exp(old, code, v, valid);
|
||||
}
|
||||
|
||||
Statement::Return(v) => {
|
||||
v.as_mut()
|
||||
.map(|v| Self::_check_hook_exp(old, code, v, valid));
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@ -1731,57 +1838,59 @@ impl SnippetCode {
|
||||
#[test]
|
||||
fn test() {
|
||||
let input = r#"
|
||||
// -----------------------------------------------------------------------------
|
||||
// Copyright (c) 2009-2016 Nicolas P. Rougier. All rights reserved.
|
||||
// Distributed under the (new) BSD License.
|
||||
// -----------------------------------------------------------------------------
|
||||
uniform vec4 viewport_local;
|
||||
uniform vec4 viewport_global;
|
||||
uniform int viewport_transform;
|
||||
uniform int viewport_clipping;
|
||||
#include "transform/polar.glsl"
|
||||
|
||||
#ifdef _GLUMPY__VERTEX_SHADER__
|
||||
void transform()
|
||||
{
|
||||
if (viewport_transform == 0) return;
|
||||
layout(points) in;
|
||||
layout(triangle_strip, max_vertices = 4) out;
|
||||
|
||||
vec4 position = gl_Position;
|
||||
// conf: Elevation, Range, Resolution, 0.0
|
||||
uniform vec4 conf;
|
||||
|
||||
float w = viewport_local.z / viewport_global.z;
|
||||
float h = viewport_local.w / viewport_global.w;
|
||||
float x = 2.0*(viewport_local.x / viewport_global.z) - 1.0 + w;
|
||||
float y = 2.0*(viewport_local.y / viewport_global.w) - 1.0 + h;
|
||||
out float eth;
|
||||
out float rng;
|
||||
|
||||
gl_Position = vec4((x + w*position.x/position.w)*position.w,
|
||||
(y + h*position.y/position.w)*position.w,
|
||||
position.z, position.w);
|
||||
}
|
||||
#endif
|
||||
out vec4 vrange;
|
||||
|
||||
#ifdef _GLUMPY__FRAGMENT_SHADER__
|
||||
void clipping()
|
||||
{
|
||||
if (viewport_clipping == 0) return;
|
||||
|
||||
vec2 position = gl_FragCoord.xy;
|
||||
if( position.x < (viewport_local.x)) discard;
|
||||
else if( position.x > (viewport_local.x+viewport_local.z)) discard;
|
||||
else if( position.y < (viewport_local.y)) discard;
|
||||
else if( position.y > (viewport_local.y+viewport_local.w)) discard;
|
||||
void main() {
|
||||
|
||||
/*
|
||||
if( length(position.x - viewport_local.x) < 1.0 )
|
||||
gl_FragColor = vec4(0,0,0,1);
|
||||
else if( length(position.x - viewport_local.x - viewport_local.z) < 1.0 )
|
||||
gl_FragColor = vec4(0,0,0,1);
|
||||
else if( length(position.y - viewport_local.y) < 1.0 )
|
||||
gl_FragColor = vec4(0,0,0,1);
|
||||
else if( length(position.y - viewport_local.y - viewport_local.w) < 1.0 )
|
||||
gl_FragColor = vec4(0,0,0,1);
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
// Resolution
|
||||
vec4 reso = vec4(conf.x/2.0, conf.y/2.0, 0.0, 0.0);
|
||||
float c = cos(reso.x);
|
||||
|
||||
vec4 po = gl_in[0].gl_Position;
|
||||
|
||||
vrange = vec4(po.x - reso.x, po.y - reso.y, po.x + reso.x, po.y + reso.y);
|
||||
|
||||
gl_Position = po - reso;
|
||||
eth = gl_Position.x;
|
||||
rng = gl_Position.y;
|
||||
gl_Position = <transform(forward(gl_Position))>;
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = po + vec4(-reso.x, reso.y, 0.0, 0.0);
|
||||
gl_Position.y = gl_Position.y / c;
|
||||
eth = gl_Position.x;
|
||||
rng = gl_Position.y;
|
||||
gl_Position = <transform(forward(gl_Position))>;
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = po + reso;
|
||||
gl_Position.y = gl_Position.y / c;
|
||||
eth = gl_Position.x;
|
||||
rng = gl_Position.y;
|
||||
gl_Position = <transform(forward(gl_Position))>;
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = po + vec4(reso.x, -reso.y, 0.0, 0.0);
|
||||
eth = gl_Position.x;
|
||||
rng = gl_Position.y;
|
||||
gl_Position = <transform(forward(gl_Position))>;
|
||||
EmitVertex();
|
||||
|
||||
EndPrimitive();
|
||||
|
||||
}
|
||||
|
||||
"#;
|
||||
|
||||
@ -1792,64 +1901,72 @@ void clipping()
|
||||
|
||||
#[test]
|
||||
fn test_expression() {
|
||||
let input = "
|
||||
let input = r#"
|
||||
void main() {
|
||||
|
||||
void main ()
|
||||
{
|
||||
fetch_uniforms();
|
||||
v_linewidth = linewidth;
|
||||
v_antialias = antialias;
|
||||
v_color = color;
|
||||
vec4 reso = vec4(conf.x/2.0, conf.y/2.0, 0.0, 0.0);
|
||||
float c = cos(reso.x);
|
||||
|
||||
vec4 prev_ = transform_6(forward_5(position_7(forward_2(prev.x), forward_3(prev.y), forward_4(prev.z))));
|
||||
vec4 curr_ = transform_6(forward_5(position_7(forward_2(curr.x), forward_3(curr.y), forward_4(curr.z))));
|
||||
vec4 next_ = transform_6(forward_5(position_7(forward_2(next.x), forward_3(next.y), forward_4(next.z))));
|
||||
vec4 po = gl_in[0].gl_Position;
|
||||
|
||||
vec2 _prev = NDC_to_viewport(prev_, <viewport.viewport_global>.zw);
|
||||
vec2 _curr = NDC_to_viewport(curr_, <viewport.viewport_global>.zw);
|
||||
vec2 _next = NDC_to_viewport(next_, <viewport.viewport_global>.zw);
|
||||
vrange = vec4(po.x - reso.x, po.y - reso.y, po.x + reso.x, po.y + reso.y);
|
||||
|
||||
float w = linewidth/2.0 + 1.5*antialias;
|
||||
float z;
|
||||
vec2 P;
|
||||
if( curr == prev) {
|
||||
vec2 v = normalize(_next.xy - _curr.xy);
|
||||
vec2 normal = normalize(vec2(-v.y,v.x));
|
||||
P = _curr.xy + normal*w*id;
|
||||
} else if (curr == next) {
|
||||
vec2 v = normalize(_curr.xy - _prev.xy);
|
||||
vec2 normal = normalize(vec2(-v.y,v.x));
|
||||
P = _curr.xy + normal*w*id;
|
||||
} else {
|
||||
vec2 v0 = normalize(_curr.xy - _prev.xy);
|
||||
vec2 v1 = normalize(_next.xy - _curr.xy);
|
||||
vec2 normal = normalize(vec2(-v0.y,v0.x));
|
||||
vec2 tangent = normalize(v0+v1);
|
||||
vec2 miter = vec2(-tangent.y, tangent.x);
|
||||
float l = abs(w / dot(miter,normal));
|
||||
P = _curr.xy + miter*l*sign(id);
|
||||
}
|
||||
gl_Position = po - reso;
|
||||
eth = gl_Position.x;
|
||||
rng = gl_Position.y;
|
||||
gl_Position = <transform(forward(gl_Position))>;
|
||||
EmitVertex();
|
||||
|
||||
if( abs(id) > 1.5 ) v_color.a = 0.0;
|
||||
gl_Position = po + vec4(-reso.x, reso.y, 0.0, 0.0);
|
||||
gl_Position.y = gl_Position.y / c;
|
||||
eth = gl_Position.x;
|
||||
rng = gl_Position.y;
|
||||
gl_Position = <transform(forward(gl_Position))>;
|
||||
EmitVertex();
|
||||
|
||||
v_distance = w*id;
|
||||
gl_Position = viewport_to_NDC(P, <viewport.viewport_global>.zw, curr_.z / curr_.w);
|
||||
gl_Position = po + reso;
|
||||
gl_Position.y = gl_Position.y / c;
|
||||
eth = gl_Position.x;
|
||||
rng = gl_Position.y;
|
||||
gl_Position = <transform(forward(gl_Position))>;
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = po + vec4(reso.x, -reso.y, 0.0, 0.0);
|
||||
eth = gl_Position.x;
|
||||
rng = gl_Position.y;
|
||||
gl_Position = <transform(forward(gl_Position))>;
|
||||
EmitVertex();
|
||||
|
||||
EndPrimitive();
|
||||
|
||||
<viewport.transform>;
|
||||
}
|
||||
|
||||
";
|
||||
"#;
|
||||
let result = ws(function)(input).unwrap();
|
||||
println!("{:?}", result.1);
|
||||
println!("{}", result.1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_expression_2() {
|
||||
let input = r#"
|
||||
<transform(prev)>
|
||||
<transform(forward(gl_Position))>
|
||||
"#;
|
||||
|
||||
let result = ws(expression)(input).unwrap();
|
||||
let result = ws(hook)(input).unwrap();
|
||||
|
||||
println!("{}", result.1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_shared_variable() {
|
||||
let input = r#"
|
||||
in float in_value[];
|
||||
layout(points) in;
|
||||
|
||||
|
||||
"#;
|
||||
|
||||
let result = ws(_share_variable)(input).unwrap();
|
||||
|
||||
println!("{}", result.1);
|
||||
}
|
||||
@ -1857,12 +1974,15 @@ fn test_expression_2() {
|
||||
#[test]
|
||||
fn test_function() {
|
||||
let input = r#"
|
||||
vec4 forward(float rho, float theta, float z, float w)
|
||||
{
|
||||
return vec4(rho * cos(theta + polar_origin),
|
||||
rho * sin(theta + polar_origin),
|
||||
z, w);
|
||||
float norm_rad(float rad) {
|
||||
float result = mod(angle, M_2_PI);
|
||||
if(result < 0.0) {
|
||||
result = M_2_PI + result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
"#;
|
||||
|
||||
let result = ws(function)(input).unwrap();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user