This commit is contained in:
Tsuki 2024-07-18 20:52:15 +08:00
parent 2fcff3c6d9
commit db89b19eb4
33 changed files with 2919 additions and 429 deletions

443
Cargo.lock generated
View File

@ -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",
] ]

View File

@ -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"

View File

@ -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);
} }

View File

@ -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
View 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
View 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
View 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
View 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
View 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
View 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;
}

View File

@ -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()
} }
} }

View File

@ -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
View 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
View 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
View 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,
}

View File

@ -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,
} }

View File

@ -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());
} }
} }

View File

@ -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,17 +115,64 @@ 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, gl: &glow::Context) -> Result<()> {
unsafe {
gl.clear(glow::COLOR_BUFFER_BIT);
gl.use_program(Some(self.program.native_program.unwrap()));
gl.bind_vertex_array(Some(self.vao.unwrap()));
gl.draw_arrays(glow::TRIANGLE_STRIP, 0, self.buffer.len() as i32);
fn draw(&self) -> Result<()> { gl.bind_vertex_array(None);
}
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));
}
use bytemuck::cast_slice;
let b:&[u8] = cast_slice(&self.buffer);
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();
} }
} }

View 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);
}
}

View 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
View 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();
}
}

View File

@ -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
View 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();
}
}

View File

@ -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());
} }
} }

View File

@ -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
} }
} }

View File

@ -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
} }
} }

View File

@ -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);
} }
} }

View File

@ -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)
}
} }

View File

@ -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]
));
}); });
}); });
} }

View File

@ -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
View 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)
}

View File

@ -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::{

View File

@ -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"), opt(delimited(
multispace0::<&str, nom::error::Error<&str>>, char('('),
delimited( separated_list0(char(','), ws(alt((parse_assignment, parse_variable)))),
char('('), char(')'),
tuple((tag("location"), multispace0, char('='), space0, digit1)), )),
char(')'), )),
), |(_, v)| Ok::<Modifier, nom::error::Error<&str>>(Modifier::Layout(v)),
space0,
))),
tag("in"),
),
|(a, _)| {
let c = a.map(|(_, _, (_, _, _, _, v), _)| v.parse::<usize>().unwrap());
Ok::<Modifier, nom::error::Error<&str>>(Modifier::In(c))
},
), ),
map_res(tag("flat"), |_| {
Ok::<Modifier, nom::error::Error<&str>>(Modifier::Flat)
}),
map_res(tag("in"), |_| {
Ok::<Modifier, nom::error::Error<&str>>(Modifier::In)
}),
map_res(tag("out"), |_| { 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);
float w = linewidth/2.0 + 1.5*antialias; gl_Position = po - reso;
float z; eth = gl_Position.x;
vec2 P; rng = gl_Position.y;
if( curr == prev) { gl_Position = <transform(forward(gl_Position))>;
vec2 v = normalize(_next.xy - _curr.xy); EmitVertex();
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; gl_Position = po + vec4(-reso.x, reso.y, 0.0, 0.0);
gl_Position.y = gl_Position.y / c;
eth = gl_Position.x;
rng = gl_Position.y;
gl_Position = <transform(forward(gl_Position))>;
EmitVertex();
v_distance = w*id; gl_Position = po + reso;
gl_Position = viewport_to_NDC(P, <viewport.viewport_global>.zw, curr_.z / curr_.w); gl_Position.y = gl_Position.y / c;
eth = gl_Position.x;
rng = gl_Position.y;
gl_Position = <transform(forward(gl_Position))>;
EmitVertex();
gl_Position = po + vec4(reso.x, -reso.y, 0.0, 0.0);
eth = gl_Position.x;
rng = gl_Position.y;
gl_Position = <transform(forward(gl_Position))>;
EmitVertex();
EndPrimitive();
<viewport.transform>;
} }
"; "#;
let result = ws(function)(input).unwrap(); 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();