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"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046"
|
checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ahash"
|
name = "ahash"
|
||||||
version = "0.8.11"
|
version = "0.8.11"
|
||||||
@ -40,6 +46,21 @@ dependencies = [
|
|||||||
"memchr",
|
"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]]
|
[[package]]
|
||||||
name = "android-activity"
|
name = "android-activity"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
@ -67,6 +88,21 @@ version = "0.2.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04"
|
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]]
|
[[package]]
|
||||||
name = "anstream"
|
name = "anstream"
|
||||||
version = "0.6.14"
|
version = "0.6.14"
|
||||||
@ -116,6 +152,12 @@ dependencies = [
|
|||||||
"windows-sys 0.52.0",
|
"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]]
|
[[package]]
|
||||||
name = "approx"
|
name = "approx"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
@ -224,9 +266,15 @@ checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"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]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
@ -313,6 +361,20 @@ version = "1.0.11"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9d1d389c4b5c60ebf7955904cd19f5a225f53f42e03d4459a2d57463ed62c6a8"
|
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]]
|
[[package]]
|
||||||
name = "clipboard-win"
|
name = "clipboard-win"
|
||||||
version = "3.1.1"
|
version = "3.1.1"
|
||||||
@ -402,6 +464,15 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crc32fast"
|
||||||
|
version = "1.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-utils"
|
name = "crossbeam-utils"
|
||||||
version = "0.8.20"
|
version = "0.8.20"
|
||||||
@ -435,6 +506,22 @@ version = "1.2.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2"
|
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]]
|
[[package]]
|
||||||
name = "env_filter"
|
name = "env_filter"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -458,6 +545,26 @@ dependencies = [
|
|||||||
"log",
|
"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]]
|
[[package]]
|
||||||
name = "equivalent"
|
name = "equivalent"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
@ -474,6 +581,22 @@ dependencies = [
|
|||||||
"windows-sys 0.52.0",
|
"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]]
|
[[package]]
|
||||||
name = "foreign-types"
|
name = "foreign-types"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
@ -492,7 +615,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -501,6 +624,44 @@ version = "0.3.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b"
|
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]]
|
[[package]]
|
||||||
name = "gethostname"
|
name = "gethostname"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
@ -610,11 +771,34 @@ dependencies = [
|
|||||||
"gl_generator",
|
"gl_generator",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hash32"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.14.5"
|
version = "0.14.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
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]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
@ -628,6 +812,29 @@ version = "2.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
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]]
|
[[package]]
|
||||||
name = "icrate"
|
name = "icrate"
|
||||||
version = "0.0.4"
|
version = "0.0.4"
|
||||||
@ -720,6 +927,21 @@ version = "1.70.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
|
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]]
|
[[package]]
|
||||||
name = "jni"
|
name = "jni"
|
||||||
version = "0.21.1"
|
version = "0.21.1"
|
||||||
@ -788,6 +1010,12 @@ dependencies = [
|
|||||||
"windows-targets 0.52.5",
|
"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]]
|
[[package]]
|
||||||
name = "libredox"
|
name = "libredox"
|
||||||
version = "0.0.2"
|
version = "0.0.2"
|
||||||
@ -870,6 +1098,15 @@ version = "0.2.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
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]]
|
[[package]]
|
||||||
name = "mint"
|
name = "mint"
|
||||||
version = "0.5.9"
|
version = "0.5.9"
|
||||||
@ -887,7 +1124,23 @@ dependencies = [
|
|||||||
"num-complex",
|
"num-complex",
|
||||||
"num-rational",
|
"num-rational",
|
||||||
"num-traits",
|
"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",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -898,9 +1151,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "e68879ff227a94627e63bbd518b4f82b8f0cc56bb01a498251507de6d1c412d6"
|
checksum = "e68879ff227a94627e63bbd518b4f82b8f0cc56bb01a498251507de6d1c412d6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"approx 0.5.1",
|
"approx 0.5.1",
|
||||||
"nalgebra",
|
"nalgebra 0.32.5",
|
||||||
"num-traits",
|
"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]]
|
[[package]]
|
||||||
@ -944,6 +1221,38 @@ dependencies = [
|
|||||||
"minimal-lexical",
|
"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]]
|
[[package]]
|
||||||
name = "num-complex"
|
name = "num-complex"
|
||||||
version = "0.4.6"
|
version = "0.4.6"
|
||||||
@ -968,6 +1277,7 @@ version = "0.4.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
|
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"num-bigint",
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
@ -979,6 +1289,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
|
"libm",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -999,7 +1310,7 @@ dependencies = [
|
|||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1179,10 +1490,16 @@ dependencies = [
|
|||||||
name = "radar-g"
|
name = "radar-g"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"aligned-vec",
|
||||||
|
"anyhow",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
|
"byteorder",
|
||||||
"cgmath",
|
"cgmath",
|
||||||
|
"chrono",
|
||||||
"copypasta",
|
"copypasta",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
|
"flate2",
|
||||||
|
"geo",
|
||||||
"glow",
|
"glow",
|
||||||
"glutin",
|
"glutin",
|
||||||
"glutin-winit",
|
"glutin-winit",
|
||||||
@ -1191,11 +1508,16 @@ dependencies = [
|
|||||||
"imgui-winit-support",
|
"imgui-winit-support",
|
||||||
"include_dir",
|
"include_dir",
|
||||||
"log",
|
"log",
|
||||||
|
"nalgebra 0.33.0",
|
||||||
"nalgebra-glm",
|
"nalgebra-glm",
|
||||||
|
"ndarray",
|
||||||
"nom",
|
"nom",
|
||||||
|
"nom-derive",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"raw-window-handle 0.5.2",
|
"raw-window-handle 0.5.2",
|
||||||
"regex",
|
"regex",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"winit",
|
"winit",
|
||||||
]
|
]
|
||||||
@ -1274,6 +1596,23 @@ version = "0.8.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
|
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]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.38.34"
|
version = "0.38.34"
|
||||||
@ -1287,6 +1626,18 @@ dependencies = [
|
|||||||
"windows-sys 0.52.0",
|
"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]]
|
[[package]]
|
||||||
name = "safe_arch"
|
name = "safe_arch"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
@ -1332,22 +1683,33 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.203"
|
version = "1.0.204"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
|
checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.203"
|
version = "1.0.204"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
|
checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"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]]
|
[[package]]
|
||||||
@ -1363,6 +1725,19 @@ dependencies = [
|
|||||||
"wide",
|
"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]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
version = "0.4.9"
|
version = "0.4.9"
|
||||||
@ -1432,12 +1807,41 @@ dependencies = [
|
|||||||
"serde",
|
"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]]
|
[[package]]
|
||||||
name = "strict-num"
|
name = "strict-num"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
|
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]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.66"
|
version = "2.0.66"
|
||||||
@ -1466,7 +1870,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1600,7 +2004,7 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.66",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1634,7 +2038,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.66",
|
||||||
"wasm-bindgen-backend",
|
"wasm-bindgen-backend",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
@ -1815,6 +2219,15 @@ version = "0.4.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
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]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.45.0"
|
version = "0.45.0"
|
||||||
@ -2168,5 +2581,5 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.66",
|
||||||
]
|
]
|
||||||
|
|||||||
11
Cargo.toml
11
Cargo.toml
@ -24,3 +24,14 @@ thiserror = "1.0.61"
|
|||||||
log = "0.4.22"
|
log = "0.4.22"
|
||||||
env_logger = "0.11.3"
|
env_logger = "0.11.3"
|
||||||
bytemuck = { version = "1.16.1", features = ["derive"] }
|
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_linewidth;
|
||||||
in float v_antialias;
|
in float v_antialias;
|
||||||
|
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
// Main
|
// Main
|
||||||
// ------------------------------------
|
// ------------------------------------
|
||||||
void main()
|
void main()
|
||||||
@ -18,5 +20,5 @@ void main()
|
|||||||
<viewport.clipping()>;
|
<viewport.clipping()>;
|
||||||
|
|
||||||
if (v_color.a == 0) { discard; }
|
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 ()
|
void main ()
|
||||||
{
|
{
|
||||||
// This function is externally generated
|
// This function is externally generated
|
||||||
fetch_uniforms();
|
// fetch_uniforms();
|
||||||
|
|
||||||
|
float id = gl_VertexID;
|
||||||
v_linewidth = linewidth;
|
v_linewidth = linewidth;
|
||||||
v_antialias = antialias;
|
v_antialias = antialias;
|
||||||
v_color = color;
|
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::shader::Shader;
|
||||||
use super::snippets::{CodeType, Snippet};
|
use super::snippets::{CodeType, Snippet};
|
||||||
|
use crate::components::CodeComponent;
|
||||||
use crate::graphics::transforms::{viewport::Viewport, Transform};
|
use crate::graphics::transforms::{viewport::Viewport, Transform};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -43,6 +44,7 @@ impl Program {
|
|||||||
pub fn set_hook(&mut self, hook: &str, code: &Snippet) {
|
pub fn set_hook(&mut self, hook: &str, code: &Snippet) {
|
||||||
self.vertex.set_hook(hook, code);
|
self.vertex.set_hook(hook, code);
|
||||||
self.fragment.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) {
|
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<()> {
|
pub fn compile(&mut self, gl: &glow::Context) -> crate::errors::Result<()> {
|
||||||
use crate::errors::Error;
|
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 program = gl.create_program().map_err(|e| Error::InvalidProgram(e))?;
|
||||||
|
|
||||||
let vertex_shader =
|
let vertex_shader = self.vertex.compile(&self.version, gl);
|
||||||
self.create_shader(gl, &self.vertex.to_string(),self.version, glow::VERTEX_SHADER);
|
let fragment_shader = self.fragment.compile(&self.version, gl);
|
||||||
let fragment_shader =
|
|
||||||
self.create_shader(gl, &self.fragment.to_string(),self.version, glow::FRAGMENT_SHADER);
|
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);
|
gl.link_program(program);
|
||||||
|
|
||||||
if !gl.get_program_link_status(program) {
|
if !gl.get_program_link_status(program) {
|
||||||
return Err(Error::InvalidProgram(gl.get_program_info_log(program)));
|
return Err(Error::InvalidProgram(gl.get_program_info_log(program)));
|
||||||
}
|
}
|
||||||
|
|
||||||
gl.detach_shader(program, vertex_shader);
|
gl.detach_shader(program, vertex_shader);
|
||||||
gl.detach_shader(program, fragment_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);
|
self.native_program = Some(program);
|
||||||
}
|
}
|
||||||
@ -81,42 +106,24 @@ impl Program {
|
|||||||
Ok(())
|
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) {
|
pub fn destroy(&self, gl: &glow::Context) {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.native_program.map(|p| gl.delete_program(p));
|
self.native_program.map(|p| gl.delete_program(p));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(&self, gl: &glow::Context) {
|
pub fn get_uniform_location(
|
||||||
unsafe {
|
&self,
|
||||||
gl.clear_color(0.05, 0.05, 0.1, 1.0);
|
gl: &glow::Context,
|
||||||
gl.clear(glow::COLOR_BUFFER_BIT);
|
name: &str,
|
||||||
gl.use_program(self.native_program);
|
) -> 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::{
|
use crate::{
|
||||||
errors::{Error, Result},
|
errors::{Error, Result},
|
||||||
utils::{find_file, CodeBlock},
|
utils::{find_file, Code, CodeBlock},
|
||||||
};
|
};
|
||||||
|
use glow::HasContext;
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
pub use utils::fetchcode;
|
pub use utils::fetchcode;
|
||||||
pub type ShaderType = u32;
|
pub type ShaderType = u32;
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Shader {
|
pub struct Shader {
|
||||||
code: String,
|
|
||||||
target: u32,
|
target: u32,
|
||||||
parsed: CodeBlock,
|
parsed: CodeBlock,
|
||||||
pub hooks: Vec<String>,
|
pub hooks: Vec<String>,
|
||||||
@ -27,7 +27,7 @@ impl std::fmt::Display for Shader {
|
|||||||
|
|
||||||
impl Shader {
|
impl Shader {
|
||||||
pub fn new<S: Borrow<str>>(target: ShaderType, code: CodeType<S>) -> Result<Self> {
|
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::Code(code) => code.borrow().to_string(),
|
||||||
CodeType::Path(path) => {
|
CodeType::Path(path) => {
|
||||||
let code = find_file(path).expect("Failed to find file");
|
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 code = merge_includes(code).map_err(|e| Error::InvalidSnippet(e.to_string()))?;
|
||||||
let parsed = CodeBlock::new(&code)?;
|
let parsed = CodeBlock::new(&code)?;
|
||||||
|
|
||||||
@ -58,17 +43,43 @@ impl Shader {
|
|||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
target,
|
target,
|
||||||
code,
|
|
||||||
parsed,
|
parsed,
|
||||||
hooks,
|
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) {
|
pub fn set_hook(&mut self, hook: &str, code: &Snippet) {
|
||||||
self.parsed.set_hook(hook, code);
|
self.parsed.set_hook(hook, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn target(&self) -> u32 {
|
||||||
|
self.target
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CodeComponent for Shader {
|
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}")]
|
#[error("Invalid Program {0}")]
|
||||||
InvalidProgram(String),
|
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 {
|
// pub struct PPI {
|
||||||
transform: Trackball,
|
// transform: Trackball,
|
||||||
program: Program,
|
// program: Program,
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl PPI {
|
// impl PPI {
|
||||||
pub fn new(version: &'static str) -> Self {
|
// pub fn new(version: &'static str) -> Self {
|
||||||
let trackball = Trackball::new().unwrap();
|
// let trackball = Trackball::new().unwrap();
|
||||||
let projection = Polar::new().unwrap();
|
// let projection = Polar::new().unwrap();
|
||||||
let position = Position::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(
|
// let vertex = Shader::new(
|
||||||
glow::VERTEX_SHADER,
|
// glow::VERTEX_SHADER,
|
||||||
CodeType::<&'static str>::Path("agg-fast-path.vert".into()),
|
// CodeType::<&'static str>::Path("agg-fast-path.vert".into()),
|
||||||
)
|
// )
|
||||||
.unwrap();
|
// .unwrap();
|
||||||
|
|
||||||
let fragment = Shader::new(
|
// let fragment = Shader::new(
|
||||||
glow::FRAGMENT_SHADER,
|
// glow::FRAGMENT_SHADER,
|
||||||
CodeType::<&'static str>::Path("agg-fast-path.frag".into()),
|
// CodeType::<&'static str>::Path("agg-fast-path.frag".into()),
|
||||||
)
|
// )
|
||||||
.unwrap();
|
// .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) {
|
// pub fn compile(&mut self, gl: &glow::Context) {
|
||||||
self.program.compile(gl);
|
// self.program.compile(gl);
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn program(&self) -> &Program {
|
// pub fn program(&self) -> &Program {
|
||||||
&self.program
|
// &self.program
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn native_program(&self) -> Option<<glow::Context as HasContext>::Program> {
|
// pub fn native_program(&self) -> Option<<glow::Context as HasContext>::Program> {
|
||||||
self.program.native_program
|
// self.program.native_program
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ppi() {
|
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 std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
use bytemuck::{Pod, Zeroable};
|
use bytemuck::{Pod, Zeroable};
|
||||||
|
use glow::{HasContext, NativeBuffer, NativeVertexArray};
|
||||||
|
|
||||||
use crate::components::{fetchcode, CodeComponent, CodeType, Program, Shader, Snippet};
|
use crate::components::{fetchcode, CodeComponent, CodeType, Program, Shader, Snippet};
|
||||||
use crate::errors::*;
|
use crate::errors::*;
|
||||||
@ -14,10 +15,13 @@ use super::Colletion;
|
|||||||
pub struct AggFastPath {
|
pub struct AggFastPath {
|
||||||
program: Program,
|
program: Program,
|
||||||
buffer: Vec<Point>,
|
buffer: Vec<Point>,
|
||||||
|
|
||||||
|
vao: Option<NativeVertexArray>,
|
||||||
|
vbo: Option<NativeBuffer>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AggFastPath {
|
impl AggFastPath {
|
||||||
pub fn new<T: Transform>(transform: &T, viewport: &Viewport) -> Result<Self> {
|
pub fn new() -> Result<Self> {
|
||||||
let vertex = Shader::new(
|
let vertex = Shader::new(
|
||||||
glow::VERTEX_SHADER,
|
glow::VERTEX_SHADER,
|
||||||
CodeType::<String>::Path("agg-fast-path.vert".into()),
|
CodeType::<String>::Path("agg-fast-path.vert".into()),
|
||||||
@ -28,10 +32,14 @@ impl AggFastPath {
|
|||||||
CodeType::<String>::Path("agg-fast-path.frag".into()),
|
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 = 0) in vec3 prev;
|
||||||
layout(location = 1) in vec3 curr;
|
layout(location = 1) in vec3 curr;
|
||||||
layout(location = 2) in vec3 next;
|
layout(location = 2) in vec3 next;
|
||||||
|
layout(location = 3) in float id;
|
||||||
|
|
||||||
uniform float linewidth;
|
uniform float linewidth;
|
||||||
|
|
||||||
@ -39,24 +47,63 @@ impl AggFastPath {
|
|||||||
|
|
||||||
uniform vec4 color;
|
uniform vec4 color;
|
||||||
|
|
||||||
") ,false, None)?;
|
",
|
||||||
|
),
|
||||||
|
false,
|
||||||
|
None,
|
||||||
|
)?;
|
||||||
|
|
||||||
let vertex = vertex.add_snippet_before(input_snippet);
|
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_transform(transform);
|
||||||
program.set_viewport(viewport);
|
// program.set_viewport(viewport);
|
||||||
|
|
||||||
println!("{}", program.vertex());
|
|
||||||
|
|
||||||
println!("{}", program.fragment());
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
program,
|
program,
|
||||||
buffer: Vec::with_capacity(128),
|
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 {
|
impl Colletion for AggFastPath {
|
||||||
@ -68,16 +115,63 @@ impl Colletion for AggFastPath {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Graphics for AggFastPath {
|
impl Graphics for AggFastPath {
|
||||||
|
|
||||||
fn compile(&mut self, gl: &glow::Context) -> Result<()> {
|
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) -> Result<()> {
|
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);
|
||||||
|
|
||||||
use bytemuck::cast_slice;
|
gl.bind_vertex_array(None);
|
||||||
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -89,6 +183,7 @@ pub struct Point {
|
|||||||
prev: [f32; 3],
|
prev: [f32; 3],
|
||||||
curr: [f32; 3],
|
curr: [f32; 3],
|
||||||
next: [f32; 3],
|
next: [f32; 3],
|
||||||
|
id: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ty for Point {}
|
impl Ty for Point {}
|
||||||
@ -101,49 +196,38 @@ pub struct Path {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Path {
|
impl Default for Path {
|
||||||
|
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
points: Vec::with_capacity(500),
|
points: Vec::with_capacity(500),
|
||||||
is_closed: false,
|
is_closed: false,
|
||||||
is_empty: true
|
is_empty: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PathBuilder {
|
pub struct PathBuilder {
|
||||||
is_closed: bool,
|
is_closed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PathBuilder{
|
impl Default for PathBuilder {
|
||||||
|
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self { is_closed: false }
|
||||||
is_closed: false
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PathBuilder {
|
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.is_closed = is_closed;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn build(&self) -> Path {
|
pub fn build(&self) -> Path {
|
||||||
|
|
||||||
Path {
|
Path {
|
||||||
points: Vec::with_capacity(500),
|
points: Vec::with_capacity(500),
|
||||||
is_closed: self.is_closed,
|
is_closed: self.is_closed,
|
||||||
is_empty: true,
|
is_empty: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Path {
|
impl Path {
|
||||||
@ -159,19 +243,20 @@ impl Path {
|
|||||||
PathBuilder::default()
|
PathBuilder::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn push(&mut self, point: [f32; 3]) {
|
pub fn push(&mut self, point: [f32; 3]) {
|
||||||
if self.is_empty {
|
if self.is_empty {
|
||||||
self.points.push(Point {
|
self.points.push(Point {
|
||||||
prev: point,
|
prev: point,
|
||||||
curr: point,
|
curr: point,
|
||||||
next: point,
|
next: point,
|
||||||
|
id: 1.0,
|
||||||
});
|
});
|
||||||
|
|
||||||
self.points.push(Point {
|
self.points.push(Point {
|
||||||
prev: point,
|
prev: point,
|
||||||
curr: point,
|
curr: point,
|
||||||
next: point,
|
next: point,
|
||||||
|
id: -1.0,
|
||||||
});
|
});
|
||||||
|
|
||||||
self.is_empty = false;
|
self.is_empty = false;
|
||||||
@ -180,12 +265,21 @@ impl Path {
|
|||||||
let prev = self.points[len - 1].curr;
|
let prev = self.points[len - 1].curr;
|
||||||
let curr = point;
|
let curr = point;
|
||||||
let next = point;
|
let next = point;
|
||||||
self.points.push(Point { prev, curr, next });
|
self.points.push(Point {
|
||||||
self.points[len - 1].next = curr;
|
prev,
|
||||||
|
curr,
|
||||||
|
next,
|
||||||
|
id: 1.0,
|
||||||
|
});
|
||||||
|
self.points.push(Point {
|
||||||
|
prev,
|
||||||
|
curr,
|
||||||
|
next,
|
||||||
|
id: -1.0,
|
||||||
|
});
|
||||||
|
|
||||||
if len == 2 {
|
self.points[len - 1].next = curr;
|
||||||
self.points[0].next = curr;
|
self.points[len - 2].next = curr;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,20 +289,28 @@ impl Path {
|
|||||||
let curr = self.points.first().unwrap().curr;
|
let curr = self.points.first().unwrap().curr;
|
||||||
let prev = self.points[len - 1].curr;
|
let prev = self.points[len - 1].curr;
|
||||||
let next = self.points[1].next;
|
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 - 1].next = curr;
|
||||||
|
self.points[len - 2].next = curr;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.points.push(self.points.last().unwrap().clone());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.points.len() - 2
|
self.points.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Deref for Path {
|
impl Deref for Path {
|
||||||
type Target = [u8];
|
type Target = [u8];
|
||||||
|
|
||||||
@ -225,7 +327,6 @@ impl DerefMut for Path {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mod test {
|
mod test {
|
||||||
|
|
||||||
use crate::graphics::transforms::{polar::Polar, position::Position, trackball::Trackball};
|
use crate::graphics::transforms::{polar::Polar, position::Position, trackball::Trackball};
|
||||||
@ -234,7 +335,6 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_path() {
|
fn test_path() {
|
||||||
|
|
||||||
let mut path = Path::builder().is_closed(false).build();
|
let mut path = Path::builder().is_closed(false).build();
|
||||||
|
|
||||||
path.push([9.0, 9.0, 9.0]);
|
path.push([9.0, 9.0, 9.0]);
|
||||||
@ -248,16 +348,14 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_agg() {
|
fn test_agg() {
|
||||||
|
// let viewport = Trackball::new().unwrap();
|
||||||
|
// let trans = Polar::new().unwrap();
|
||||||
|
// let position = Position::new().unwrap();
|
||||||
|
|
||||||
let viewport = Trackball::new().unwrap();
|
// let transform = viewport.chain(trans.chain(position));
|
||||||
let trans = Polar::new().unwrap();
|
|
||||||
let position = Position::new().unwrap();
|
|
||||||
|
|
||||||
let transform = viewport.chain(trans.chain(position));
|
// let viewport = &Viewport::new().unwrap();
|
||||||
|
|
||||||
let viewport = &Viewport::new().unwrap();
|
|
||||||
|
|
||||||
let agg_path = AggFastPath::new(&transform, &viewport).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 collections;
|
||||||
|
pub mod colormap;
|
||||||
mod colormesh;
|
mod colormesh;
|
||||||
|
pub mod hello;
|
||||||
|
pub mod ppi;
|
||||||
pub mod tools;
|
pub mod tools;
|
||||||
pub mod transforms;
|
pub mod transforms;
|
||||||
pub mod ty;
|
pub mod ty;
|
||||||
use crate::errors::*;
|
use crate::{components::Program, errors::*};
|
||||||
|
|
||||||
pub use colormesh::ColorMesh;
|
pub use colormesh::ColorMesh;
|
||||||
|
|
||||||
pub trait Graphics {
|
pub trait Graphics {
|
||||||
fn draw(&self) -> Result<()>;
|
fn draw(&self, gl: &glow::Context) -> Result<()>;
|
||||||
|
|
||||||
fn compile(&mut 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 position;
|
||||||
pub mod trackball;
|
pub mod trackball;
|
||||||
pub mod viewport;
|
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 snippet(&self) -> &Snippet;
|
||||||
|
|
||||||
fn chain(self, other: impl Transform) -> Self;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mod test {
|
mod test {
|
||||||
@ -16,11 +54,11 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_transform() {
|
fn test_transform() {
|
||||||
let polar = polar::Polar::new().unwrap();
|
let polar = polar::Polar::new().unwrap();
|
||||||
let trackball = trackball::Trackball::new().unwrap();
|
// let trackball = trackball::Trackball::new().unwrap();
|
||||||
let polar_trackball = polar.chain(trackball);
|
|
||||||
|
|
||||||
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::{
|
use crate::{
|
||||||
components::{CodeType, Snippet},
|
components::{CodeType, Program, Snippet},
|
||||||
errors::*,
|
errors::*,
|
||||||
|
graphics::AttaWithProgram,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::Transform;
|
use super::Transform;
|
||||||
@ -30,11 +31,11 @@ impl Transform for Polar {
|
|||||||
fn snippet(&self) -> &Snippet {
|
fn snippet(&self) -> &Snippet {
|
||||||
&self.snippet
|
&self.snippet
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn chain(mut self, other: impl Transform) -> Self {
|
impl AttaWithProgram for Polar {
|
||||||
let new_snippet = self.snippet.chain(other.snippet().to_owned());
|
fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> Result<()> {
|
||||||
self.snippet = new_snippet;
|
Ok(())
|
||||||
self
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
use super::Transform;
|
use super::Transform;
|
||||||
use crate::{
|
use crate::{
|
||||||
components::{CodeType, Snippet},
|
components::{CodeType, Program, Snippet},
|
||||||
errors::*,
|
errors::*,
|
||||||
|
graphics::AttaWithProgram,
|
||||||
};
|
};
|
||||||
pub struct Position {
|
pub struct Position {
|
||||||
snippet: Snippet,
|
snippet: Snippet,
|
||||||
@ -24,11 +25,11 @@ impl Transform for Position {
|
|||||||
fn snippet(&self) -> &Snippet {
|
fn snippet(&self) -> &Snippet {
|
||||||
&self.snippet
|
&self.snippet
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn chain(mut self, other: impl Transform) -> Self {
|
impl AttaWithProgram for Position {
|
||||||
let new_snippet = self.snippet.chain(other.snippet().to_owned());
|
fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> Result<()> {
|
||||||
self.snippet = new_snippet;
|
Ok(())
|
||||||
self
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,144 @@
|
|||||||
use crate::components::{CodeType, Snippet};
|
use crate::components::{CodeType, Program, Snippet};
|
||||||
use crate::errors::Result;
|
use crate::errors::Result;
|
||||||
|
use crate::graphics::AttaWithProgram;
|
||||||
|
|
||||||
use super::Transform;
|
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 {
|
pub struct Trackball {
|
||||||
snippet: Snippet,
|
snippet: Snippet,
|
||||||
|
|
||||||
|
znear: f32,
|
||||||
|
zfar: f32,
|
||||||
|
zoom: f32,
|
||||||
|
aspect: f32,
|
||||||
|
model: TrackballModel,
|
||||||
|
|
||||||
|
projection: nalgebra_glm::Mat4x4,
|
||||||
|
view: nalgebra::Matrix4<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Trackball {
|
impl Trackball {
|
||||||
@ -16,7 +150,84 @@ impl Trackball {
|
|||||||
None,
|
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 {
|
fn snippet(&self) -> &Snippet {
|
||||||
&self.snippet
|
&self.snippet
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn chain(mut self, other: impl Transform) -> Self {
|
impl AttaWithProgram for Trackball {
|
||||||
let new_snippet = self.snippet.chain(other.snippet().to_owned());
|
fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> Result<()> {
|
||||||
self.snippet = new_snippet;
|
self.attach_with_program(gl, program)
|
||||||
self
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,8 +248,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_trackball() {
|
fn test_trackball() {
|
||||||
let trackball = Trackball::new().unwrap();
|
// let trackball = Trackball::new().unwrap();
|
||||||
|
// println!("{}", trackball.snippet);
|
||||||
println!("{}", trackball.snippet);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,15 @@
|
|||||||
|
use glow::HasContext;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
components::{self, CodeType, Snippet},
|
components::{self, CodeType, Program, Snippet},
|
||||||
errors::*,
|
errors::*,
|
||||||
|
graphics::AttaWithProgram,
|
||||||
};
|
};
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub struct Viewport {
|
pub struct Viewport {
|
||||||
snippet: Snippet,
|
snippet: Snippet,
|
||||||
|
viewport_global: [f32; 4],
|
||||||
|
viewport_local: Option<[f32; 4]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Viewport {
|
impl Viewport {
|
||||||
@ -15,10 +21,71 @@ impl Viewport {
|
|||||||
None,
|
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 {
|
pub fn snippet(&self) -> &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;
|
use imgui::Condition;
|
||||||
|
|
||||||
mod camera;
|
mod camera;
|
||||||
mod components;
|
mod components;
|
||||||
|
mod data_loader;
|
||||||
mod errors;
|
mod errors;
|
||||||
mod graphics;
|
mod graphics;
|
||||||
mod support;
|
mod support;
|
||||||
@ -12,8 +15,10 @@ mod final_pg;
|
|||||||
fn main() {
|
fn main() {
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
let choices = ["test test this is 1", "test test this is 2"];
|
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;
|
let mut value = 0;
|
||||||
support::supporter::init(move |_, ui| {
|
support::supporter::init(move |_, ui, program, window, gl| {
|
||||||
ui.window("Hello world")
|
ui.window("Hello world")
|
||||||
.size([300.0, 110.0], Condition::FirstUseEver)
|
.size([300.0, 110.0], Condition::FirstUseEver)
|
||||||
.build(|| {
|
.build(|| {
|
||||||
@ -31,25 +36,18 @@ fn main() {
|
|||||||
"Mouse Position: ({:.1},{:.1})",
|
"Mouse Position: ({:.1},{:.1})",
|
||||||
mouse_pos[0], mouse_pos[1]
|
mouse_pos[0], mouse_pos[1]
|
||||||
));
|
));
|
||||||
});
|
|
||||||
|
|
||||||
ui.window("Hello world")
|
if ui.button("Add Layer") {
|
||||||
.size([300.0, 110.0], Condition::FirstUseEver)
|
program.add_ppi_layer(1);
|
||||||
.build(|| {
|
program.attach_with_buffer(gl, &data).unwrap();
|
||||||
ui.text_wrapped("Hello world!");
|
window.request_redraw();
|
||||||
ui.text_wrapped("こんにちは世界!");
|
|
||||||
if ui.button(choices[value]) {
|
|
||||||
value += 1;
|
|
||||||
value %= 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.button("This...is...imgui-rs!");
|
if ui.button("Remove Layer") {
|
||||||
ui.separator();
|
program.add_ppi_layer(-1);
|
||||||
let mouse_pos = ui.io().mouse_pos;
|
program.attach_with_buffer(gl, &data).unwrap();
|
||||||
ui.text(format!(
|
window.request_redraw();
|
||||||
"Mouse Position: ({:.1},{:.1})",
|
}
|
||||||
mouse_pos[0], mouse_pos[1]
|
|
||||||
));
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
use crate::camera::Camera;
|
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::{
|
use crate::{
|
||||||
graphics::{
|
graphics::{
|
||||||
collections::agg_fast_path::AggFastPath,
|
collections::agg_fast_path::AggFastPath,
|
||||||
@ -34,28 +37,16 @@ use std::time::Instant;
|
|||||||
|
|
||||||
pub fn init<FUi>(mut run_ui: FUi)
|
pub fn init<FUi>(mut run_ui: FUi)
|
||||||
where
|
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 (event_loop, window, surface, context) = create_window();
|
||||||
let (mut winit_platform, mut imgui_context) = imgui_init(&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 = unsafe {
|
||||||
let gl = glow_context(&context);
|
let gl = glow_context(&context);
|
||||||
gl.enable(glow::DEPTH_TEST);
|
gl.enable(glow::DEPTH_TEST);
|
||||||
|
gl.enable(glow::BLEND);
|
||||||
|
gl.blend_func(glow::SRC_ALPHA, glow::ONE_MINUS_SRC_ALPHA);
|
||||||
gl
|
gl
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -64,30 +55,37 @@ where
|
|||||||
.expect("failed to create renderer");
|
.expect("failed to create renderer");
|
||||||
|
|
||||||
let mut last_frame = Instant::now();
|
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 mut viewport = Viewport::new().unwrap();
|
||||||
let trans = Polar::new().unwrap();
|
let mut cmap = LinearColormap::new().unwrap();
|
||||||
let position = Position::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();
|
transform
|
||||||
|
.attach_with_program(ig_renderer.gl_context(), ppi.program_ref())
|
||||||
agg_path.compile(ig_renderer.gl_context()).unwrap();
|
.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;
|
|
||||||
|
|
||||||
event_loop
|
event_loop
|
||||||
.run(move |event, window_target| {
|
.run(move |event, window_target| {
|
||||||
@ -115,40 +113,26 @@ where
|
|||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let gl = ig_renderer.gl_context();
|
let gl = ig_renderer.gl_context();
|
||||||
|
gl.clear(glow::DEPTH_BUFFER_BIT);
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
|
ppi.draw(ig_renderer.gl_context()).unwrap();
|
||||||
tri_renderer.render(ig_renderer.gl_context());
|
|
||||||
|
|
||||||
let ui = imgui_context.frame();
|
let ui = imgui_context.frame();
|
||||||
|
|
||||||
if ui.is_mouse_pos_valid(ui.io().mouse_pos) {
|
if ui.is_mouse_pos_valid(ui.io().mouse_pos) {
|
||||||
let mouse_pos = ui.io().mouse_pos;
|
let mouse_pos = ui.io().mouse_pos;
|
||||||
if ui.is_mouse_dragging(imgui::MouseButton::Right) {
|
if ui.is_mouse_dragging(imgui::MouseButton::Right) {
|
||||||
mouse_callback(
|
// mouse_callback(
|
||||||
&mut last_position,
|
// &mut last_position,
|
||||||
PhysicalPosition::new(mouse_pos[0] as f64, mouse_pos[1] as f64),
|
// PhysicalPosition::new(mouse_pos[0] as f64, mouse_pos[1] as f64),
|
||||||
0.05,
|
// 0.05,
|
||||||
&mut pitch,
|
// &mut pitch,
|
||||||
&mut yaw,
|
// &mut yaw,
|
||||||
&mut camera,
|
// &mut camera,
|
||||||
);
|
// );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut run = true;
|
let mut run = true;
|
||||||
run_ui(&mut run, ui);
|
run_ui(&mut run, ui, &mut ppi, &window, ig_renderer.gl_context());
|
||||||
|
|
||||||
if !run {
|
if !run {
|
||||||
window_target.exit();
|
window_target.exit();
|
||||||
@ -182,12 +166,23 @@ where
|
|||||||
NonZeroU32::new(new_size.width).unwrap(),
|
NonZeroU32::new(new_size.width).unwrap(),
|
||||||
NonZeroU32::new(new_size.height).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_platform.handle_event(imgui_context.io_mut(), &window, &event);
|
||||||
}
|
}
|
||||||
winit::event::Event::LoopExiting => {
|
winit::event::Event::LoopExiting => {
|
||||||
let gl = ig_renderer.gl_context();
|
let gl = ig_renderer.gl_context();
|
||||||
tri_renderer.destroy(gl);
|
ppi.destroy(gl).unwrap();
|
||||||
}
|
}
|
||||||
event => {
|
event => {
|
||||||
winit_platform.handle_event(imgui_context.io_mut(), &window, &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);
|
imgui_context.set_ini_filename(None);
|
||||||
|
|
||||||
let mut winit_platform = WinitPlatform::init(&mut imgui_context);
|
let mut winit_platform = WinitPlatform::init(&mut imgui_context);
|
||||||
winit_platform.attach_window(
|
|
||||||
imgui_context.io_mut(),
|
{
|
||||||
window,
|
let dpi_mode = if let Ok(factor) = std::env::var("IMGUI_EXAMPLE_FORCE_DPI_FACTOR") {
|
||||||
imgui_winit_support::HiDpiMode::Rounded,
|
// 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
|
imgui_context
|
||||||
.fonts()
|
.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};
|
use include_dir::{include_dir, Dir};
|
||||||
pub use parser::*;
|
pub use parser::*;
|
||||||
use std::{num::NonZeroU32, path::Path};
|
use std::{num::NonZeroU32, path::Path};
|
||||||
|
pub mod geo_tools;
|
||||||
|
|
||||||
use glow::HasContext;
|
use glow::HasContext;
|
||||||
use glutin::{
|
use glutin::{
|
||||||
|
|||||||
@ -14,12 +14,12 @@ use nom::{
|
|||||||
branch::alt,
|
branch::alt,
|
||||||
bytes::complete::{tag, take_till, take_until, take_while, take_while1},
|
bytes::complete::{tag, take_till, take_until, take_while, take_while1},
|
||||||
character::complete::{
|
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},
|
combinator::{cut, map, map_res, opt, recognize, verify},
|
||||||
multi::{fold_many0, many0, many0_count, many1, separated_list0, separated_list1},
|
multi::{fold_many0, many0, many0_count, many1, separated_list0, separated_list1},
|
||||||
sequence::{delimited, pair, preceded, separated_pair, terminated, tuple},
|
sequence::{delimited, pair, preceded, separated_pair, terminated, tuple},
|
||||||
IResult, InputIter,
|
Finish, IResult, InputIter,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{components::Snippet, errors::*};
|
use crate::{components::Snippet, errors::*};
|
||||||
@ -143,8 +143,10 @@ pub enum Modifier {
|
|||||||
Static,
|
Static,
|
||||||
Extern,
|
Extern,
|
||||||
Uniform,
|
Uniform,
|
||||||
In(Option<usize>),
|
Layout(Option<Vec<Expression>>),
|
||||||
|
In,
|
||||||
Out,
|
Out,
|
||||||
|
Flat,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Modifier {
|
impl Display for Modifier {
|
||||||
@ -154,9 +156,18 @@ impl Display for Modifier {
|
|||||||
Modifier::Static => write!(f, "static"),
|
Modifier::Static => write!(f, "static"),
|
||||||
Modifier::Extern => write!(f, "extern"),
|
Modifier::Extern => write!(f, "extern"),
|
||||||
Modifier::Uniform => write!(f, "uniform"),
|
Modifier::Uniform => write!(f, "uniform"),
|
||||||
Modifier::In(Some(v)) => write!(f, "layout(location = {}) in", v),
|
Modifier::In => write!(f, "in"),
|
||||||
Modifier::In(None) => 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::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)
|
Ok::<Modifier, nom::error::Error<&str>>(Modifier::Uniform)
|
||||||
}),
|
}),
|
||||||
map_res(
|
map_res(
|
||||||
pair(
|
tuple((
|
||||||
opt(tuple((
|
|
||||||
tag("layout"),
|
tag("layout"),
|
||||||
multispace0::<&str, nom::error::Error<&str>>,
|
opt(delimited(
|
||||||
delimited(
|
|
||||||
char('('),
|
char('('),
|
||||||
tuple((tag("location"), multispace0, char('='), space0, digit1)),
|
separated_list0(char(','), ws(alt((parse_assignment, parse_variable)))),
|
||||||
char(')'),
|
char(')'),
|
||||||
|
)),
|
||||||
|
)),
|
||||||
|
|(_, v)| Ok::<Modifier, nom::error::Error<&str>>(Modifier::Layout(v)),
|
||||||
),
|
),
|
||||||
space0,
|
map_res(tag("flat"), |_| {
|
||||||
))),
|
Ok::<Modifier, nom::error::Error<&str>>(Modifier::Flat)
|
||||||
tag("in"),
|
}),
|
||||||
),
|
map_res(tag("in"), |_| {
|
||||||
|(a, _)| {
|
Ok::<Modifier, nom::error::Error<&str>>(Modifier::In)
|
||||||
let c = a.map(|(_, _, (_, _, _, _, v), _)| v.parse::<usize>().unwrap());
|
}),
|
||||||
Ok::<Modifier, nom::error::Error<&str>>(Modifier::In(c))
|
|
||||||
},
|
|
||||||
),
|
|
||||||
map_res(tag("out"), |_| {
|
map_res(tag("out"), |_| {
|
||||||
Ok::<Modifier, nom::error::Error<&str>>(Modifier::Out)
|
Ok::<Modifier, nom::error::Error<&str>>(Modifier::Out)
|
||||||
}),
|
}),
|
||||||
@ -217,7 +226,8 @@ impl Display for ShareVariable {
|
|||||||
self.modif
|
self.modif
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v| format!("{}", v))
|
.map(|v| format!("{}", v))
|
||||||
.collect::<String>(),
|
.collect::<Vec<_>>()
|
||||||
|
.join(" "),
|
||||||
self.typ,
|
self.typ,
|
||||||
self.name,
|
self.name,
|
||||||
self.value
|
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> {
|
fn _share_variable(input: &str) -> IResult<&str, ShareVariable> {
|
||||||
let (input, modifier) = many0(modifier)(input)?;
|
let (input, modifier) = many0(terminated(modifier, multispace1))(input)?;
|
||||||
let (input, _) = multispace1(input)?;
|
// let (input, _) = multispace1(input)?;
|
||||||
let (input, typ) = type_name(input)?;
|
let (input, typ) = type_name(input)?;
|
||||||
let (input, _) = multispace1(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(
|
let (input, value) = opt(preceded(ws(char('=')), ws(take_till(|c| c == ';'))))(input)?;
|
||||||
ws(char('=')),
|
|
||||||
ws(take_till(|c| c == ';' || c == '\n')),
|
|
||||||
))(input)?;
|
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
ShareVariable {
|
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)]
|
#[derive(Debug, PartialEq, Clone, Eq, Hash)]
|
||||||
pub enum PreprocessorDirective {
|
pub enum PreprocessorDirective {
|
||||||
IfDef { condition: String },
|
IfDef { condition: String },
|
||||||
@ -441,7 +458,7 @@ fn hook(input: &str) -> IResult<&str, Hook> {
|
|||||||
separated_list1(char('.'), identifier),
|
separated_list1(char('.'), identifier),
|
||||||
opt(delimited(
|
opt(delimited(
|
||||||
char('('),
|
char('('),
|
||||||
separated_list0(ws(char(',')), ws(identifier)),
|
separated_list0(char(','), ws(expression)),
|
||||||
char(')'),
|
char(')'),
|
||||||
)),
|
)),
|
||||||
),
|
),
|
||||||
@ -481,6 +498,40 @@ pub enum Code {
|
|||||||
PreprocessorDirective(Rc<RefCell<PreprocessorDirective>>, Box<Vec<Code>>),
|
PreprocessorDirective(Rc<RefCell<PreprocessorDirective>>, Box<Vec<Code>>),
|
||||||
Macro(Rc<RefCell<PreprocessorDirective>>),
|
Macro(Rc<RefCell<PreprocessorDirective>>),
|
||||||
ShareVariable(Rc<RefCell<ShareVariable>>),
|
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)]
|
#[derive(Debug, Clone)]
|
||||||
@ -664,7 +715,7 @@ impl Display for Statement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Expression {
|
pub enum Expression {
|
||||||
Binary {
|
Binary {
|
||||||
left: Box<Expression>,
|
left: Box<Expression>,
|
||||||
@ -694,6 +745,10 @@ pub enum Expression {
|
|||||||
base: Box<Expression>,
|
base: Box<Expression>,
|
||||||
member: String,
|
member: String,
|
||||||
},
|
},
|
||||||
|
ArrayAccess {
|
||||||
|
base: Box<Expression>,
|
||||||
|
member: Box<Expression>,
|
||||||
|
},
|
||||||
|
|
||||||
Hook(Hook),
|
Hook(Hook),
|
||||||
}
|
}
|
||||||
@ -740,6 +795,9 @@ impl Display for Expression {
|
|||||||
Expression::Hook(hook) => write!(f, "{}", hook),
|
Expression::Hook(hook) => write!(f, "{}", hook),
|
||||||
Expression::StructMemberAccess { base, member } => write!(f, "{}.{}", base, member),
|
Expression::StructMemberAccess { base, member } => write!(f, "{}.{}", base, member),
|
||||||
Expression::StructPointerAccess { 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)
|
)(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> {
|
fn parse_factor(input: &str) -> IResult<&str, Expression> {
|
||||||
delimited(
|
delimited(
|
||||||
multispace0,
|
multispace0,
|
||||||
alt((
|
alt((
|
||||||
delimited(char('('), expression, char(')')),
|
delimited(char('('), expression, char(')')),
|
||||||
parse_struct_pointer_access,
|
|
||||||
parse_struct_member_access,
|
parse_struct_member_access,
|
||||||
|
parse_struct_pointer_access,
|
||||||
|
parse_array_access,
|
||||||
parse_unary,
|
parse_unary,
|
||||||
parse_function_call,
|
parse_function_call,
|
||||||
parse_assignment,
|
parse_assignment,
|
||||||
@ -957,7 +1033,10 @@ fn parse_struct_member_access(input: &str) -> IResult<&str, Expression> {
|
|||||||
map(
|
map(
|
||||||
separated_pair(
|
separated_pair(
|
||||||
alt((
|
alt((
|
||||||
|
// parse_struct_member_access,
|
||||||
|
// parse_struct_pointer_access,
|
||||||
map(hook, Expression::Hook),
|
map(hook, Expression::Hook),
|
||||||
|
parse_array_access,
|
||||||
map(identifier, |v| Expression::Variable(v.to_string())),
|
map(identifier, |v| Expression::Variable(v.to_string())),
|
||||||
)),
|
)),
|
||||||
char('.'),
|
char('.'),
|
||||||
@ -1142,6 +1221,20 @@ impl Display for Code {
|
|||||||
}
|
}
|
||||||
Code::Macro(v) => write!(f, "{}", *v.borrow()),
|
Code::Macro(v) => write!(f, "{}", *v.borrow()),
|
||||||
Code::ShareVariable(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>> {
|
fn _parse(input: &str) -> IResult<&str, Vec<Code>> {
|
||||||
many1(ws(alt((
|
many1(Code::parse)(input)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn public_variables(&self) -> Vec<&RFC<ShareVariable>> {
|
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() {
|
for para in parameters.iter_mut() {
|
||||||
_expression_mangling(para, map);
|
_expression_mangling(para, map);
|
||||||
}
|
}
|
||||||
@ -1302,12 +1378,24 @@ impl CodeBlock {
|
|||||||
_expression_mangling(right, map);
|
_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::StructMemberAccess { base, .. } => {
|
||||||
_expression_mangling(base, map);
|
_expression_mangling(base, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
Expression::StructPointerAccess { base, .. } => {
|
Expression::StructPointerAccess { base, .. } => _expression_mangling(base, map),
|
||||||
|
|
||||||
|
Expression::ArrayAccess { base, member } => {
|
||||||
_expression_mangling(base, map);
|
_expression_mangling(base, map);
|
||||||
|
_expression_mangling(member, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {}
|
_ => {}
|
||||||
@ -1331,6 +1419,15 @@ impl CodeBlock {
|
|||||||
_mangling_block(block, map);
|
_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 } => {
|
Statement::While { condition, block } => {
|
||||||
_expression_mangling(condition, map);
|
_expression_mangling(condition, map);
|
||||||
_mangling_block(block, map);
|
_mangling_block(block, map);
|
||||||
@ -1420,6 +1517,10 @@ impl CodeBlock {
|
|||||||
pub fn find_variable(&self, name: &str) -> Option<&RFC<ShareVariable>> {
|
pub fn find_variable(&self, name: &str) -> Option<&RFC<ShareVariable>> {
|
||||||
self.snippet.find_variable(name)
|
self.snippet.find_variable(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn insert(&mut self, code: Code, index: usize) {
|
||||||
|
self.codes.insert(index, code);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SnippetCode {
|
impl SnippetCode {
|
||||||
@ -1706,10 +1807,16 @@ impl SnippetCode {
|
|||||||
Self::_check_hook_exp(old, code, v, valid);
|
Self::_check_hook_exp(old, code, v, valid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Statement::Expression(v) => {
|
Statement::Expression(v) => {
|
||||||
Self::_check_hook_exp(old, code, v, valid);
|
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]
|
#[test]
|
||||||
fn test() {
|
fn test() {
|
||||||
let input = r#"
|
let input = r#"
|
||||||
// -----------------------------------------------------------------------------
|
#include "transform/polar.glsl"
|
||||||
// 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;
|
|
||||||
|
|
||||||
#ifdef _GLUMPY__VERTEX_SHADER__
|
layout(points) in;
|
||||||
void transform()
|
layout(triangle_strip, max_vertices = 4) out;
|
||||||
{
|
|
||||||
if (viewport_transform == 0) return;
|
|
||||||
|
|
||||||
vec4 position = gl_Position;
|
// conf: Elevation, Range, Resolution, 0.0
|
||||||
|
uniform vec4 conf;
|
||||||
|
|
||||||
float w = viewport_local.z / viewport_global.z;
|
out float eth;
|
||||||
float h = viewport_local.w / viewport_global.w;
|
out float rng;
|
||||||
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;
|
|
||||||
|
|
||||||
gl_Position = vec4((x + w*position.x/position.w)*position.w,
|
out vec4 vrange;
|
||||||
(y + h*position.y/position.w)*position.w,
|
|
||||||
position.z, position.w);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _GLUMPY__FRAGMENT_SHADER__
|
|
||||||
void clipping()
|
|
||||||
{
|
|
||||||
if (viewport_clipping == 0) return;
|
|
||||||
|
|
||||||
vec2 position = gl_FragCoord.xy;
|
void main() {
|
||||||
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;
|
|
||||||
|
|
||||||
/*
|
// Resolution
|
||||||
if( length(position.x - viewport_local.x) < 1.0 )
|
vec4 reso = vec4(conf.x/2.0, conf.y/2.0, 0.0, 0.0);
|
||||||
gl_FragColor = vec4(0,0,0,1);
|
float c = cos(reso.x);
|
||||||
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
|
|
||||||
|
|
||||||
|
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]
|
#[test]
|
||||||
fn test_expression() {
|
fn test_expression() {
|
||||||
let input = "
|
let input = r#"
|
||||||
|
void main() {
|
||||||
|
|
||||||
void main ()
|
vec4 reso = vec4(conf.x/2.0, conf.y/2.0, 0.0, 0.0);
|
||||||
{
|
float c = cos(reso.x);
|
||||||
fetch_uniforms();
|
|
||||||
v_linewidth = linewidth;
|
|
||||||
v_antialias = antialias;
|
|
||||||
v_color = color;
|
|
||||||
|
|
||||||
vec4 prev_ = transform_6(forward_5(position_7(forward_2(prev.x), forward_3(prev.y), forward_4(prev.z))));
|
vec4 po = gl_in[0].gl_Position;
|
||||||
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))));
|
|
||||||
|
|
||||||
vec2 _prev = NDC_to_viewport(prev_, <viewport.viewport_global>.zw);
|
vrange = vec4(po.x - reso.x, po.y - reso.y, po.x + reso.x, po.y + reso.y);
|
||||||
vec2 _curr = NDC_to_viewport(curr_, <viewport.viewport_global>.zw);
|
|
||||||
vec2 _next = NDC_to_viewport(next_, <viewport.viewport_global>.zw);
|
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();
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( abs(id) > 1.5 ) v_color.a = 0.0;
|
"#;
|
||||||
|
|
||||||
v_distance = w*id;
|
|
||||||
gl_Position = viewport_to_NDC(P, <viewport.viewport_global>.zw, curr_.z / curr_.w);
|
|
||||||
|
|
||||||
<viewport.transform>;
|
|
||||||
}
|
|
||||||
|
|
||||||
";
|
|
||||||
let result = ws(function)(input).unwrap();
|
let result = ws(function)(input).unwrap();
|
||||||
println!("{:?}", result.1);
|
println!("{}", result.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_expression_2() {
|
fn test_expression_2() {
|
||||||
let input = r#"
|
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);
|
println!("{}", result.1);
|
||||||
}
|
}
|
||||||
@ -1857,12 +1974,15 @@ fn test_expression_2() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_function() {
|
fn test_function() {
|
||||||
let input = r#"
|
let input = r#"
|
||||||
vec4 forward(float rho, float theta, float z, float w)
|
float norm_rad(float rad) {
|
||||||
{
|
float result = mod(angle, M_2_PI);
|
||||||
return vec4(rho * cos(theta + polar_origin),
|
if(result < 0.0) {
|
||||||
rho * sin(theta + polar_origin),
|
result = M_2_PI + result;
|
||||||
z, w);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let result = ws(function)(input).unwrap();
|
let result = ws(function)(input).unwrap();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user