diff --git a/Cargo.lock b/Cargo.lock index a6deabf..343010e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -904,6 +904,27 @@ dependencies = [ "web-sys", ] +[[package]] +name = "glsl" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "577ac945ce66a4b7004c6e2807f517f94ef027dda89df578abe1fbb979d22f49" +dependencies = [ + "nom", +] + +[[package]] +name = "glsl-quasiquote" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "165f0276eb5b572678e2658b357d669aa08eca35032ca20381c24d58b46cca62" +dependencies = [ + "glsl", + "proc-macro-faithful-display", + "proc-macro2", + "quote", +] + [[package]] name = "glutin" version = "0.31.3" @@ -1860,6 +1881,12 @@ dependencies = [ "toml_edit 0.21.1", ] +[[package]] +name = "proc-macro-faithful-display" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5bdf93a22e0e7b3d52e42837f111845a69957294d23671efeeb8d1baef4773a" + [[package]] name = "proc-macro2" version = "1.0.85" @@ -1938,6 +1965,8 @@ dependencies = [ "freetype-rs", "geo", "glow", + "glsl", + "glsl-quasiquote", "glutin", "glutin-winit", "image", @@ -1960,6 +1989,7 @@ dependencies = [ "serde_json", "thiserror", "tinyfiledialogs", + "toml", "tracker", "winit", ] @@ -2290,9 +2320,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" dependencies = [ "serde", ] @@ -2549,21 +2579,21 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.15" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac2caab0bf757388c6c0ae23b3293fdb463fee59434529014f85e3263b995c28" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.16", + "toml_edit 0.22.20", ] [[package]] name = "toml_datetime" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] @@ -2581,15 +2611,15 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.16" +version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "278f3d518e152219c994ce877758516bca5e118eaed6996192a774fb9fbf0788" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.15", + "winnow 0.6.18", ] [[package]] @@ -3213,9 +3243,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.15" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "557404e450152cd6795bb558bca69e43c585055f4606e3bcae5894fc6dac9ba0" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 89906a5..4ee2c99 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ dirs = "5.0.1" env_logger = "0.11.3" flate2 = "1.0.30" # font-kit = {version = "0.14.1"} -freetype-rs = "0.37.0" +freetype-rs = {version="0.37.0",features = ["bundled"]} geo = "0.28.0" glow = "0.13.1" glutin = "0.31.3" @@ -43,9 +43,13 @@ thiserror = "1.0.61" winit = "0.29.3" tinyfiledialogs = "3.0" tracker = "0.2.2" +glsl = "7.0.0" +glsl-quasiquote = "7.0.0" +toml = "0.8.19" [features] default = ["sdf_font"] normal_font = [] sdf_font = [] +inparser = [] diff --git a/radar.toml b/radar.toml new file mode 100644 index 0000000..c498f8f --- /dev/null +++ b/radar.toml @@ -0,0 +1,30 @@ +[[cmap]] +type="DBZ" +levels = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75] +colors = ["#aaaaaa", "#0022ff", "#01a0f6", "#00ecec", "#00d800", "#019000", "#ffff00", "#e7c000", "#ff9000", "#ff0000", "#d60000", + "#c00000", "#ff00f0", "#9600b4", "#ad90f0"] + +[[cmap]] +type="VEL" +levels = [-90,-45, -35, -27, -20, -15, -10, -5, -1, 0, 1, 5, 10, 15, 20, 27, 1000] +colors = ["#9fffff", "#00e0ff", "#0080ff", "#320096", "#00fb90", "#00bb90", "#008f00", "#cdc09f","#000000", "#f88700", "#ffcf00", "#ffff00", "#ae0000", "#d07000", "#dd0000", "#ff0000"] + +[[cmap]] +type="SW" +colors=["#E0E0E0", "#7CE0E0", "#00E0E0", "#00B0B0", "#00FEFE", "#00C400", "#008000", "#FEFE00", "#FED200", "#FE7C00", "#FEB0B0", "#FE5858", "#FE0000", "#FEFEFE"] +levels=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] + +[[cmap]] +type="CC" +colors=["#003CFF", "#00EFEF", "#00BABF", "#00837D", "#008938", "#00B729", "#00DA0D", "#00FF00", "#FFFF3B", "#FFF000", "#FFC600", "#FFA500", "#FF7200", "#FF1F00", "#C10000", "#D400AA"] +levels=[0, 0.1, 0.3, 0.5, 0.6, 0.7, 0.8, 0.85, 0.9, 0.92, 0.94, 0.95, 0.96, 0.97, 0.98, 0.99] + +[[cmap]] +type="KDP" +colors=["#00FFFF", "#00EFEF", "#00A8AC", "#B4B4B4", "#B4B4B4", "#00C027", "#00E80A", "#24FF24", "#FFFF1E", "#FFE600", "#FFBC00", "#FF9800", "#FF5E00", "#F20F00", "#BB003A", "#DD009C", "#FF00FF"] +levels=[-0.8, -0.4, -0.2, -0.1, 0.1, 0.15, 0.22, 0.33, 0.5, 0.75, 1.1, 1.7, 2.4, 3.1, 7, 20] + +[[cmap]] +type="ZDR" +colors=["#464646", "#505050", "#5A5A5A", "#646464", "#6E6E6E", "#787878", "#828282", "#8C8C8C", "#969696", "#AFAFAF", "#C8C8C8", "#DCF0DC", "#00C027", "#00E80A", "#24FF24", "#FFFF1E", "#FFF20F", "#FFE600", "#FFBC00", "#FF9800", "#FF5E00", "#FFFF00", "#F20F00", "#BB003A", "#DD009C", "#FF00FF"] +levels=[-5, -4.5, -4, -3.5, -3, -2.5, -2, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 6, 6.5, 7] \ No newline at end of file diff --git a/src/camera.rs b/src/camera.rs index 07f09bb..dd768a2 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -7,17 +7,17 @@ use std::num::NonZeroU32; pub(crate) struct Camera { pos: Vec3, upward: Vec3, - front: Vec3, + center: Vec3, } pub type CameraPositon = Vec3; impl Camera { - pub(crate) fn new(world_loc: CameraPositon, upward: Vec3, front: Vec3) -> Self { + pub(crate) fn new(world_loc: CameraPositon, upward: Vec3, center: Vec3) -> Self { Self { pos: world_loc, upward, - front, + center, } } @@ -29,14 +29,6 @@ impl Camera { self.pos = pos; } - pub fn get_front(&self) -> Vec3 { - self.front - } - - pub fn set_front(&mut self, front: Vec3) { - self.front = front; - } - pub fn get_upward(&self) -> Vec3 { self.upward } @@ -46,8 +38,8 @@ impl Camera { } pub fn get_view_matrix(&self) -> Mat4x4 { - let l = self.pos + self.front; - look_at(&l, &self.pos, &self.upward) + let l = self.center; + look_at(&self.pos, &l, &self.upward) } } @@ -56,7 +48,7 @@ impl Default for Camera { Self { pos: Vec3::new(0.0, 0.0, 0.0), upward: Vec3::new(0.0, 1.0, 0.0), - front: Vec3::new(0.0, 0.0, -1.0), + center: Vec3::new(0.0, 0.0, -1.0), } } } diff --git a/src/components/program.rs b/src/components/program.rs index e844b23..9940034 100644 --- a/src/components/program.rs +++ b/src/components/program.rs @@ -3,7 +3,7 @@ use glow::{HasContext, NativeUniformLocation}; use super::shader::Shader; use super::snippets::{CodeType, Snippet}; use crate::components::CodeComponent; -use crate::graphics::transforms::{viewport::Viewport, Transform}; +use crate::graphics::transforms::viewport::Viewport; #[derive(Debug)] pub struct Program { @@ -45,16 +45,19 @@ impl Program { self.geometry.as_ref() } + #[cfg(feature = "inparser")] pub fn set_hook(&mut self, hook: &str, code: &Snippet) { self.vertex.set_hook(hook, code); self.fragment.set_hook(hook, code); self.geometry.as_mut().map(|g| g.set_hook(hook, code)); } + #[cfg(feature = "inparser")] pub fn set_transform(&mut self, value: &T) { self.set_hook("transform", value.snippet()); } + #[cfg(feature = "inparser")] pub fn set_viewport(&mut self, viewport: &Viewport) { self.set_hook("viewport", viewport.snippet()); } @@ -62,8 +65,11 @@ impl Program { pub fn compile(&mut self, gl: &glow::Context) -> crate::errors::Result<()> { use crate::errors::Error; - self.vertex.define("_GLUMPY__VERTEX_SHADER__"); - self.fragment.define("_GLUMPY__FRAGMENT_SHADER__"); + #[cfg(feature = "inparser")] + { + self.vertex.define("_GLUMPY__VERTEX_SHADER__"); + self.fragment.define("_GLUMPY__FRAGMENT_SHADER__"); + } unsafe { let program = gl.create_program().map_err(|e| Error::InvalidProgram(e))?; @@ -76,6 +82,7 @@ impl Program { // Geom Shader let geom_shader = if let Some(geometry) = self.geometry.as_mut() { + #[cfg(feature = "inparser")] geometry.define("_GLUMPY__GEOMETRY_SHADER__"); let geometry_shader = geometry.compile(&self.version, gl); @@ -138,13 +145,13 @@ mod test { fn test_program() { let vertex = Shader::new( glow::VERTEX_SHADER, - CodeType::<&'static str>::Path("agg-fast-path.vert".into()), + CodeType::from_path("agg-fast-path.vert"), ) .unwrap(); let fragment = Shader::new( glow::FRAGMENT_SHADER, - CodeType::<&'static str>::Path("agg-fast-path.frag".into()), + CodeType::from_path("agg-fast-path.frag"), ) .unwrap(); diff --git a/src/components/shader.rs b/src/components/shader.rs index 5606656..7939322 100644 --- a/src/components/shader.rs +++ b/src/components/shader.rs @@ -15,7 +15,10 @@ pub type ShaderType = u32; #[derive(Debug)] pub struct Shader { target: u32, + #[cfg(feature = "inparser")] parsed: CodeBlock, + parsed: String, + #[cfg(feature = "inparser")] pub hooks: Vec, } @@ -26,25 +29,34 @@ impl std::fmt::Display for Shader { } impl Shader { - pub fn new>(target: ShaderType, code: CodeType) -> Result { + pub fn new(target: ShaderType, code: CodeType) -> Result { let code = match code { - CodeType::Code(code) => code.borrow().to_string(), + CodeType::Code(code) => code, CodeType::Path(path) => { - let code = find_file(path).expect(&format!("Failed to find file {}", path)); + let code = find_file(&path).expect(&format!( + "Failed to find file {}", + &path.as_os_str().to_str().unwrap() + )); code } }; - let code = merge_includes(code).map_err(|e| Error::InvalidSnippet(e.to_string()))?; - let parsed = CodeBlock::new(&code)?; - - let hooks = parsed.all_hooks().iter().map(|h| h.name.clone()).collect(); - info!("Shader:{} Hooks: {:?}", target, hooks); + #[cfg(feature = "inparser")] + { + let code = merge_includes(code).map_err(|e| Error::InvalidSnippet(e.to_string()))?; + let parsed = CodeBlock::new(&code)?; + let hooks = parsed.all_hooks().iter().map(|h| h.name.clone()).collect(); + info!("Shader:{} Hooks: {:?}", target, hooks); + return Ok(Self { + target, + parsed, + hooks, + }); + } Ok(Self { target, - parsed, - hooks, + parsed: code, }) } @@ -68,11 +80,13 @@ impl Shader { shader } + #[cfg(feature = "inparser")] pub fn define(&mut self, s: &str) { self.parsed .insert(Code::new(&format!("#define {}\n", s)), 0); } + #[cfg(feature = "inparser")] pub fn set_hook(&mut self, hook: &str, code: &Snippet) { self.parsed.set_hook(hook, code); } @@ -217,13 +231,8 @@ mod utils { body.push_str("}\n\n"); let input = header + &body; - let result = Snippet::new( - "fetch_uniform", - CodeType::::Code(input), - false, - None, - ) - .unwrap(); + let result = + Snippet::new("fetch_uniform", CodeType::from_code(input), false, None).unwrap(); result } @@ -237,7 +246,7 @@ mod test { fn test_shader() { let shader = Shader::new( glow::VERTEX_SHADER, - CodeType::<&'static str>::Path("agg-fast-path.vert".into()), + CodeType::from_path("agg-fast-path.vert"), ) .unwrap(); diff --git a/src/components/snippets/mod.rs b/src/components/snippets/mod.rs index 71c7357..ca10cf0 100644 --- a/src/components/snippets/mod.rs +++ b/src/components/snippets/mod.rs @@ -3,7 +3,7 @@ use std::{ cell::{Ref, RefCell}, collections::{HashMap, HashSet}, ops::Add, - path::Path, + path::{Path, PathBuf}, rc::Rc, sync::atomic::{AtomicUsize, Ordering}, }; @@ -11,6 +11,7 @@ pub use util::Variable; use crate::{ errors::{Error, Result}, + shaders::{CodePiece, EmptyPiece}, utils::{find_file, Code, CodeBlock, Function, Hook, ShareVariable, SnippetCode}, }; mod util; @@ -27,9 +28,33 @@ pub enum InputType { Other(Variable), } -pub enum CodeType = &'static str, P: AsRef = &'static str> { - Code(S), - Path(P), +// pub enum CodeType< +// CP: CodePiece = EmptyPiece, +// S: std::borrow::Borrow = &'static str, +// P: AsRef = &'static str, +// > { +// Code(S), +// Path(P), +// CodePiece(CP), +// } + +pub enum CodeType { + Code(String), + Path(PathBuf), +} + +impl CodeType { + pub fn from_path>(path: P) -> Self { + Self::Path(path.as_ref().to_path_buf()) + } + + pub fn from_code>(code: S) -> Self { + Self::Code(code.borrow().to_string()) + } + + pub fn from_piece(piece: CP) -> Self { + Self::Code(piece.to_string()) + } } #[derive(Debug, Clone)] @@ -44,14 +69,14 @@ pub struct Snippet { } impl Snippet { - pub fn new, P: AsRef>( + pub fn new( name: &'static str, - code: CodeType, + code: CodeType, mangling: bool, main: Option, ) -> Result { let code = match code { - CodeType::Code(code) => code.borrow().to_string(), + CodeType::Code(code) => code, CodeType::Path(path) => { let code = find_file(path).expect("Failed to find file"); code @@ -173,13 +198,7 @@ impl Add for Snippet { let code = rhs.parsed.to_string(); raw_code.push_str(&code); - Snippet::new( - self.name, - CodeType::::Code(raw_code), - false, - None, - ) - .unwrap() + Snippet::new(self.name, CodeType::from_code(raw_code), false, None).unwrap() } } @@ -207,11 +226,9 @@ mod tests { } "#; - let snippet = - Snippet::new("polar", CodeType::<&'static str>::Code(code), true, None).unwrap(); + let snippet = Snippet::new("polar", CodeType::from_code(code), true, None).unwrap(); - let snippet2 = - Snippet::new("polar2", CodeType::<&'static str>::Code(code), true, None).unwrap(); + let snippet2 = Snippet::new("polar2", CodeType::from_code(code), true, None).unwrap(); let snippet3 = snippet.clone() + snippet2.clone(); diff --git a/src/data_loader/mod.rs b/src/data_loader/mod.rs index 40a69db..5ca3407 100644 --- a/src/data_loader/mod.rs +++ b/src/data_loader/mod.rs @@ -170,7 +170,7 @@ impl Data { }; use DataType::*; - let valuetype = info.value_type.as_str(); + let valuetype = info.value_name.as_str(); let data_type = block_data_type_prepare!(valuetype, "ET" => ET, diff --git a/src/errors.rs b/src/errors.rs index 4a1cefc..53edfc0 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -27,4 +27,7 @@ pub enum Error { #[error("Invalid Font {0}")] FontError(String), + + #[error("Invalid Setting {0}")] + SettingError(String), } diff --git a/src/graphics/collections/agg_fast_path.rs b/src/graphics/collections/agg_fast_path.rs index 2bc4259..11e2f39 100644 --- a/src/graphics/collections/agg_fast_path.rs +++ b/src/graphics/collections/agg_fast_path.rs @@ -6,7 +6,6 @@ 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::{AttaWithBuffer, Config, Graphics}; @@ -26,17 +25,17 @@ impl AggFastPath { pub fn new() -> Result { let vertex = Shader::new( glow::VERTEX_SHADER, - CodeType::::Path("agg-fast-path.vert".into()), + CodeType::from_path("agg-fast-path.vert"), )?; let fragment = Shader::new( glow::FRAGMENT_SHADER, - CodeType::::Path("agg-fast-path.frag".into()), + CodeType::from_path("agg-fast-path.frag"), )?; let input_snippet = Snippet::new( "input", - CodeType::<&'static str>::Code( + CodeType::from_code( " layout(location = 0) in vec3 prev; layout(location = 1) in vec3 curr; @@ -72,10 +71,12 @@ impl AggFastPath { }) } + #[cfg(feature = "inparser")] pub fn set_transform(&mut self, transform: &T) { self.program.set_transform(transform); } + #[cfg(feature = "inparser")] pub fn set_viewport(&mut self, viewport: &Viewport) { self.program.set_viewport(viewport); } @@ -182,7 +183,6 @@ impl Graphics for AggFastPath { fn draw(&self, gl: &glow::Context, count: i32) -> Result<()> { unsafe { - gl.clear(glow::COLOR_BUFFER_BIT); gl.bind_vertex_array(Some(self.vao.unwrap())); gl.draw_elements( glow::TRIANGLES, @@ -425,8 +425,6 @@ impl DerefMut for Path { mod test { - use crate::graphics::transforms::{polar::Polar, position::Position, trackball::Trackball}; - use super::*; #[test] diff --git a/src/graphics/colormap/linear.rs b/src/graphics/colormap/linear.rs index abd0621..da65977 100644 --- a/src/graphics/colormap/linear.rs +++ b/src/graphics/colormap/linear.rs @@ -1,40 +1,37 @@ -use glow::HasContext; - +use super::ColorMap; use crate::components::{CodeType, Program, Snippet}; use crate::errors::*; - -use super::ColorMap; +use crate::shaders::colormap::ColorMap as CmapPiece; +use glow::HasContext; pub struct LinearColormap { - snippet: Snippet, colors: Vec<[u8; 4]>, color_changed: bool, texture: Option, + pub unvalid: f32, pub min: f32, pub max: f32, } impl LinearColormap { pub fn new() -> Result { - 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, + unvalid: 0.0, }) } + pub fn set_unvalid_value(&mut self, value: f32) { + self.unvalid = value; + self.color_changed = true; + } + pub fn set_colors(&mut self, colors: Vec<[u8; 4]>) { self.colors = colors; self.color_changed = true; @@ -79,18 +76,14 @@ impl ColorMap for LinearColormap { 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); + let location = program.get_uniform_location(gl, "colormap_conf"); gl.uniform_4_f32( location.as_ref(), self.min, self.max, self.colors.len() as f32, - 125.0, + self.unvalid, ); - self.texture = Some(texture); } } @@ -110,17 +103,12 @@ impl ColorMap for LinearColormap { 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); + let location = program.get_uniform_location(gl, "colormap"); gl.uniform_1_i32(location.as_ref(), 0); } Ok(()) } - - fn snippet_ref(&self) -> &crate::components::Snippet { - &self.snippet - } } mod test { diff --git a/src/graphics/colormap/mod.rs b/src/graphics/colormap/mod.rs index 5363e29..7b288ea 100644 --- a/src/graphics/colormap/mod.rs +++ b/src/graphics/colormap/mod.rs @@ -11,7 +11,5 @@ pub trait ColorMap { fn bind_texture(&self, gl: &glow::Context, program: &Program) -> crate::errors::Result<()>; - fn snippet_ref(&self) -> &crate::components::Snippet; - fn destroy(&mut self, gl: &glow::Context); } diff --git a/src/graphics/font/mod.rs b/src/graphics/font/mod.rs index c99a827..787ccbd 100644 --- a/src/graphics/font/mod.rs +++ b/src/graphics/font/mod.rs @@ -13,7 +13,7 @@ use crate::{ utils::resources::RcGlTexture, }; -use super::{threed::ThreeD, transforms::viewport::Viewport, AttaWithBuffer, Config, Graphics}; +use super::{transforms::viewport::Viewport, AttaWithBuffer, Config, Graphics}; pub struct Text<'a> { gl: &'a glow::Context, font_manager: RefCell, @@ -153,13 +153,13 @@ impl<'a> Text<'a> { pub fn new(gl: &'a glow::Context, font_manager: FontManager) -> Result { let vertex = Shader::new( glow::VERTEX_SHADER, - crate::components::CodeType::<&str>::Path("font.vert"), + crate::components::CodeType::from_path("font.vert"), )?; - let fragment = Shader::new(glow::FRAGMENT_SHADER, CodeType::<&str>::Path("font.frag"))?; + let fragment = Shader::new(glow::FRAGMENT_SHADER, CodeType::from_path("font.frag"))?; - let transform = ThreeD::new(1.0, 0.1, 100.0, 45.0)?; let mut program = Program::new(vertex, fragment, None, "330 core"); + #[cfg(feature = "inparser")] program.set_transform(&transform); Ok(Self { @@ -171,6 +171,7 @@ impl<'a> Text<'a> { }) } + #[cfg(feature = "inparser")] pub fn set_viewport(&mut self, viewport: &Viewport) { self.program.set_viewport(viewport); } diff --git a/src/graphics/hello.rs b/src/graphics/hello.rs index 0d99f46..40d941b 100644 --- a/src/graphics/hello.rs +++ b/src/graphics/hello.rs @@ -20,15 +20,8 @@ pub struct Hello { impl Hello { pub fn new() -> Result { - let vertex = Shader::new( - glow::VERTEX_SHADER, - CodeType::::Path("hello.vert".into()), - )?; - - let fragment = Shader::new( - glow::FRAGMENT_SHADER, - CodeType::::Path("hello.frag".into()), - )?; + let vertex = Shader::new(glow::VERTEX_SHADER, CodeType::from_path("hello.vert"))?; + let fragment = Shader::new(glow::FRAGMENT_SHADER, CodeType::from_path("hello.frag"))?; let program = Program::new(vertex, fragment, None, "330 core"); @@ -284,8 +277,6 @@ impl DerefMut for Path { mod test { - use crate::graphics::transforms::{polar::Polar, position::Position, trackball::Trackball}; - use super::*; #[test] diff --git a/src/graphics/mod.rs b/src/graphics/mod.rs index 7e6db79..848141d 100644 --- a/src/graphics/mod.rs +++ b/src/graphics/mod.rs @@ -9,7 +9,13 @@ pub mod tools; pub mod transforms; pub mod ty; -use crate::{components::Program, errors::*, graphics::font::FontConfig}; +use crate::{ + camera::Camera, + components::Program, + errors::*, + graphics::font::FontConfig, + ui::{operation::Projection, typ::CameraOP}, +}; use glow::{HasContext, NativeBuffer, NativeVertexArray}; use ppi::PPIConfig; @@ -113,11 +119,22 @@ pub enum Config { config_for_everyitem!({PPIConfig => PPI},{FontConfig => Font}, ); pub trait AttachWithMouse { - fn attach_with_mouse(&mut self, state: &MouseState); + type State: CameraOP; + fn attach_with_mouse( + &mut self, + state: &Self::State, + camera: &mut Camera, + projection: &mut Projection, + ) -> bool; + + fn reset(&mut self); + + fn init_camera(&self) -> Camera; } #[derive(Debug, Clone)] pub enum MouseState { Drag { from: [f32; 2], delta: [f32; 2] }, + Wheel(f32), None, } diff --git a/src/graphics/ppi.rs b/src/graphics/ppi.rs index fb36b27..f757348 100644 --- a/src/graphics/ppi.rs +++ b/src/graphics/ppi.rs @@ -1,92 +1,64 @@ use super::colormap::ColorMap; -use super::threed::ThreeD; use super::transforms::viewport::Viewport; use super::{transforms, AttaWithBuffer, AttaWithProgram, AttachWithMouse, Config, Graphics}; use crate::components::{CodeType, Program, Shader}; use crate::data_loader::{CoordType, Data, DataType}; use crate::errors::*; use crate::graphics::colormap::linear::LinearColormap; -use crate::graphics::transforms::Transform; use glow::{HasContext, NativeBuffer, NativeVertexArray}; pub struct PPI { program: Program, - cmap: Option>, + cmap: LinearColormap, } impl PPI { pub fn new() -> Result { - let vertex = Shader::new( - glow::VERTEX_SHADER, - CodeType::::Path("ppi.vert".into()), - )?; - - let geom = Shader::new( - glow::GEOMETRY_SHADER, - CodeType::::Path("ppi.geom".into()), - )?; - + use crate::shaders::ppi::*; + let vertex = Shader::new(glow::VERTEX_SHADER, CodeType::from_piece(PPIVertex::new()))?; + let geom = Shader::new(glow::GEOMETRY_SHADER, CodeType::from_piece(PPIGeom::new()))?; let fragment = Shader::new( glow::FRAGMENT_SHADER, - CodeType::::Path("ppi.frag".into()), + CodeType::from_piece(PPIFragment::new()), )?; - let mut cmap = LinearColormap::new()?; - 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 transform = ThreeD::new(1.0, 0.1, 100.0, 45.0)?; - let mut program = Program::new(vertex, fragment, Some(geom), "330 core"); - program.set_transform(&transform); - program.set_hook("colormap", cmap.snippet_ref()); - Ok(Self { - program, - cmap: Some(Box::new(cmap)), - }) - } - - pub fn set_viewport(&mut self, viewport: &Viewport) { - self.program.set_viewport(viewport); + Ok(Self { program, cmap }) } pub fn program(&mut self) -> &mut Program { &mut self.program } - fn set_conf(&self, gl: &glow::Context, rdpi: f32, adpi: f32) { + fn set_conf(&mut self, gl: &glow::Context, config: &PPIConfig) { + let rdpi = config.rdpi; + let adpi = config.adpi; let location = self.program.get_uniform_location(gl, "conf"); + self.cmap + .set_range(config.color_range[0], config.color_range[1]); + self.cmap.set_colors(config.colors.clone()); + self.cmap.set_unvalid_value(config.unvalid_value); + self.cmap.attach_with_program(gl, &self.program); + unsafe { - gl.uniform_4_f32(location.as_ref(), rdpi, adpi, 0f32, 0f32); + gl.uniform_4_f32( + location.as_ref(), + rdpi, + adpi, + 0f32, + if config.three_d { 1.0 } else { 0.0 }, + ); } } - // fn bake_data(&self, data: &Data, layer: usize) -> Result<(Vec, i32)> { - - // } - - pub fn data_info(&self, data: &Data) -> Result<(f32, f32, DataType)> { + pub fn data_info(&self, data: &Data) -> Result<(f32, f32, DataType, usize, f32)> { let first_block = data.blocks.get(0).unwrap(); if let CoordType::Polar { azimuth, r, r_range, + elevation, .. } = &first_block.coord_type { @@ -94,24 +66,25 @@ impl PPI { 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)); + + let unvalid = first_block.unvalid_value; + + return Ok(( + r_step, + azi_step, + first_block.data_type, + elevation.len(), + unvalid, + )); } else { return Err(Error::InvalidDataType); } } fn init(&mut self, gl: &glow::Context, config: &PPIConfig) { - self.cmap - .as_mut() - .unwrap() - .attach_with_program(gl, &self.program) - .unwrap(); - + self.set_conf(gl, config); + self.cmap.attach_with_program(gl, &self.program).unwrap(); let origin = self.program.get_uniform_location(gl, "polar_origin"); - - let rdpi = config.rdpi; - let adpi = config.adpi; - self.set_conf(gl, rdpi, adpi); unsafe { gl.uniform_1_f32(origin.as_ref(), 90.0f32.to_radians()); } @@ -162,12 +135,7 @@ impl Graphics for PPI { fn draw(&self, gl: &glow::Context, count: i32) -> Result<()> { unsafe { - gl.clear(glow::COLOR_BUFFER_BIT); - self.cmap - .as_ref() - .unwrap() - .bind_texture(gl, &self.program)?; - + self.cmap.bind_texture(gl, &self.program)?; gl.draw_arrays(glow::POINTS, 0, count); } Ok(()) @@ -215,6 +183,7 @@ impl AttaWithBuffer for PPI { if let CoordType::Polar { r_range, azimuth, + elevation, r, .. } = &first_block.coord_type @@ -223,13 +192,15 @@ impl AttaWithBuffer for PPI { let r_len = r.len(); let mut vertices = Vec::with_capacity(azimuth_len * r_len); + let ele = elevation.get(layer).unwrap(); 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 r = *r.get(r_idx).unwrap(); let dt = first_block_data.get([layer, azi_idx, r_idx]).unwrap(); - vertices.extend([r, *azi, *dt]); + vertices.extend([r, *azi, *ele, *dt]); } } let len = vertices.len() as i32 / 3; @@ -246,7 +217,7 @@ impl AttaWithBuffer for PPI { 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); + gl.vertex_attrib_pointer_f32(0, 4, glow::FLOAT, false, 16, 0); gl.bind_vertex_array(None); (vao, vbo, None) @@ -256,9 +227,13 @@ impl AttaWithBuffer for PPI { #[derive(Default, Clone, Debug)] pub struct PPIConfig { + pub unvalid_value: f32, pub layer: usize, + pub colors: Vec<[u8; 4]>, + pub color_range: [f32; 2], pub rdpi: f32, pub adpi: f32, + pub three_d: bool, } mod test { diff --git a/src/graphics/threed.rs b/src/graphics/threed.rs index aca5b13..4308786 100644 --- a/src/graphics/threed.rs +++ b/src/graphics/threed.rs @@ -1,138 +1,75 @@ use std::rc::Rc; +use tracker::track; -use super::transforms::Transform; -use super::transforms::{position::Position, trackball::Trackball, ChainedTransform}; +use super::transforms::{position::Position, trackball::TrackballModel}; use super::{AttaWithProgram, AttachWithMouse}; -use crate::camera::Camera; +use crate::camera::{self, Camera}; use crate::errors::*; +use crate::ui::operation::Projection; use glow::HasContext; -use nalgebra_glm::Vec3; +use nalgebra_glm::{Mat4, Vec3}; #[derive(Clone)] -pub struct ThreeD { - transform: Rc, - projection: nalgebra_glm::Mat4, - trackball: Trackball, - camera: Camera, +pub struct Trackball { + trackball: TrackballModel, } -impl ThreeD { +impl Trackball { pub fn new(aspect: f32, z_near: f32, z_far: f32, fov: f32) -> Result { - let trackball = Trackball::new()?; - let transform = ChainedTransform::from(&trackball).chain(&Position::new()?); + let trackball = TrackballModel::new(0.0, 90.0); - let camera = Camera::new( - Vec3::new(0.0, -1.0, 0.0), - Vec3::new(0.0, 1.0, 0.0), - Vec3::new(0.0, 1.0, 0.0), - ); - - let projection = nalgebra_glm::perspective(aspect, fov.to_radians(), z_near, z_far); - - Ok(Self { - transform: Rc::new(transform), - trackball, - camera, - projection, - }) - } - - pub fn set_aspect(&mut self, aspect: f32) { - self.projection = nalgebra_glm::perspective(aspect, 45.0f32.to_radians(), 0.1, 100.0); - } - - pub fn set_fov(&mut self, fov: f32) { - self.projection = nalgebra_glm::perspective(1.0, fov.to_radians(), 0.1, 100.0); - } - - pub fn set_z_near(&mut self, z_near: f32) { - self.projection = nalgebra_glm::perspective(1.0, 45.0f32.to_radians(), z_near, 100.0); - } - - pub fn set_z_far(&mut self, z_far: f32) { - self.projection = nalgebra_glm::perspective(1.0, 45.0f32.to_radians(), 0.1, z_far); + Ok(Self { trackball }) } } -impl Default for ThreeD { +impl Default for Trackball { fn default() -> Self { Self::new(16.0 / 9.0, 0.1, 1000.0, 45.0).unwrap() } } -impl AttaWithProgram for ThreeD { +impl AttaWithProgram for Trackball { fn attach_with_program( &self, gl: &glow::Context, program: &crate::components::Program, ) -> Result<()> { - unsafe { - let view = program.get_uniform_location(gl, "trackball_view"); - let projection = program.get_uniform_location(gl, "trackball_projection"); - let model = program.get_uniform_location(gl, "trackball_model"); - - let view_mat = nalgebra_glm::translation(&nalgebra_glm::vec3(0.0, 0.0, -3.0)); - - gl.uniform_matrix_4_f32_slice( - view.as_ref(), - false, - // nalgebra::Matrix4::identity().as_slice(), - view_mat.as_slice(), - // self.camera.get_view_matrix().as_slice(), - ); - - // println!("projection: {:?}", self.projection); - - // let scale_factor = nalgebra_glm::vec3(1.5, 1.5, 1.0); - // let res = nalgebra_glm::scaling(&scale_factor); - let ident: nalgebra_glm::Mat4 = nalgebra_glm::identity(); - gl.uniform_matrix_4_f32_slice( - model.as_ref(), - false, - ident.as_slice(), - // nalgebra::Matrix4::identity().as_slice(), - ); - - gl.uniform_matrix_4_f32_slice( - view.as_ref(), - false, - ident.as_slice(), - // nalgebra::Matrix4::identity().as_slice(), - ); - - gl.uniform_matrix_4_f32_slice( - projection.as_ref(), - false, - ident.as_slice(), - // nalgebra::Matrix4::identity().as_slice(), - ); - - // let rotate = - // nalgebra_glm::rotation(45.0f32.to_radians(), &nalgebra_glm::vec3(1.0, 0.0, 0.0)); - - // gl.uniform_matrix_4_f32_slice( - // model.as_ref(), - // false, - // rotate.as_slice(), // nalgebra::Matrix4::identity().as_slice(), - // ); - - // gl.uniform_matrix_4_f32_slice(projection.as_ref(), false, self.projection.as_slice()); - } + self.trackball.attach_with_program(gl, program); Ok(()) } } -impl Transform for ThreeD { - fn snippet(&self) -> &crate::components::Snippet { - self.transform.snippet() - } -} - -impl AttachWithMouse for ThreeD { - fn attach_with_mouse(&mut self, state: &super::MouseState) { - if let super::MouseState::Drag { from, delta } = state { - self.trackball - .on_mouse_drag(from[0], from[1], delta[0], delta[1]); +impl AttachWithMouse for Trackball { + type State = super::MouseState; + fn attach_with_mouse( + &mut self, + state: &Self::State, + camera: &mut Camera, + projection: &mut Projection, + ) -> bool { + match state { + &super::MouseState::Wheel(delta) => { + projection.set_fov((projection.fov() - delta).clamp(15.0, 120.0)); + true + } + super::MouseState::Drag { from, delta } => { + self.trackball.drag_to(from[0], from[1], delta[0], delta[1]); + true + } + _ => false, } } + + fn reset(&mut self) { + self.trackball.set_phi(90.0); + self.trackball.set_theta(0.0); + } + + fn init_camera(&self) -> Camera { + Camera::new( + Vec3::new(0.0, 30.0, 10.0), + Vec3::new(0.0, 1.0, 0.0), + Vec3::new(0.0, 0.0, 0.0), + ) + } } diff --git a/src/graphics/transforms/mod.rs b/src/graphics/transforms/mod.rs index f17c483..3f61e1d 100644 --- a/src/graphics/transforms/mod.rs +++ b/src/graphics/transforms/mod.rs @@ -6,59 +6,56 @@ use crate::components::{Program, Snippet}; use super::AttaWithProgram; -pub struct ChainedTransform { - snippet: Snippet, - chain: Vec>, -} +// pub struct ChainedTransform { +// snippet: Snippet, +// chain: Vec>, +// } -impl ChainedTransform { - pub fn from(transform: &T) -> Self { - let snippet = transform.snippet().clone(); - // let snippet = transform.snippet().to_owned(); - Self { - snippet, - chain: vec![Box::new(transform.clone())], - } - } +// impl ChainedTransform { +// pub fn from(transform: &T) -> Self { +// let snippet = transform.snippet().clone(); +// // let snippet = transform.snippet().to_owned(); +// Self { +// snippet, +// chain: vec![Box::new(transform.clone())], +// } +// } - pub fn chain(mut self, other: &P) -> Self { - let new_snippet = self.snippet.clone().chain(other.snippet().to_owned()); - self.snippet = new_snippet; - self.chain.push(Box::new(other.clone())); - self - } -} +// pub fn chain(mut self, other: &P) -> Self { +// let new_snippet = self.snippet.clone().chain(other.snippet().to_owned()); +// self.snippet = new_snippet; +// self.chain.push(Box::new(other.clone())); +// self +// } +// } -impl Transform for ChainedTransform { - fn snippet(&self) -> &Snippet { - &self.snippet - } -} +// 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)?; - } +// 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; -} +// Ok(()) +// } +// } -mod test { - use super::*; +// mod test { +// use super::*; - #[test] - fn test_transform() { - let polar = polar::Polar::new().unwrap(); - // let trackball = trackball::Trackball::new().unwrap(); +// #[test] +// fn test_transform() { +// let polar = polar::Polar::new().unwrap(); +// // let trackball = trackball::Trackball::new().unwrap(); - // let chained = ChainedTransform::from(polar).chain(trackball); +// // let chained = ChainedTransform::from(polar).chain(trackball); - // println!("{}", chained.snippet().prepare_code()); - // println!("{}", chained.snippet().call(&vec![]).unwrap()); - } -} +// // println!("{}", chained.snippet().prepare_code()); +// // println!("{}", chained.snippet().call(&vec![]).unwrap()); +// } +// } diff --git a/src/graphics/transforms/polar.rs b/src/graphics/transforms/polar.rs index 1a8cd43..cdaef93 100644 --- a/src/graphics/transforms/polar.rs +++ b/src/graphics/transforms/polar.rs @@ -4,8 +4,6 @@ use crate::{ graphics::AttaWithProgram, }; -use super::Transform; - pub struct Polar { snippet: Snippet, origin: f32, @@ -15,7 +13,7 @@ impl Polar { pub fn new() -> Result { let snippets = Snippet::new( "polar", - CodeType::<&'static str>::Path("transform/polar.glsl".into()), + CodeType::from_path("transform/polar.glsl"), true, Some("forward".to_string()), )?; @@ -27,12 +25,6 @@ impl Polar { } } -impl Transform for Polar { - fn snippet(&self) -> &Snippet { - &self.snippet - } -} - impl AttaWithProgram for Polar { fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> Result<()> { Ok(()) diff --git a/src/graphics/transforms/position.rs b/src/graphics/transforms/position.rs index 0d2b6e1..bd4bf97 100644 --- a/src/graphics/transforms/position.rs +++ b/src/graphics/transforms/position.rs @@ -1,4 +1,3 @@ -use super::Transform; use crate::{ components::{CodeType, Program, Snippet}, errors::*, @@ -13,7 +12,7 @@ impl Position { pub fn new() -> Result { let snippets = Snippet::new( "position", - CodeType::<&'static str>::Path("transform/position.glsl".into()), + CodeType::from_path("transform/position.glsl"), false, None, )?; @@ -22,12 +21,6 @@ impl Position { } } -impl Transform for Position { - fn snippet(&self) -> &Snippet { - &self.snippet - } -} - impl AttaWithProgram for Position { fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> Result<()> { Ok(()) diff --git a/src/graphics/transforms/trackball.rs b/src/graphics/transforms/trackball.rs index 7352427..5480d93 100644 --- a/src/graphics/transforms/trackball.rs +++ b/src/graphics/transforms/trackball.rs @@ -2,8 +2,6 @@ use crate::components::{CodeType, Program, Snippet}; use crate::errors::Result; use crate::graphics::AttaWithProgram; -use super::Transform; - use glow::HasContext; use nalgebra::{Matrix4, Quaternion, Translation3, Unit, UnitQuaternion, Vector3}; @@ -27,7 +25,7 @@ impl TrackballModel { count: 0, model: Matrix4::identity(), renorm_count: 97, - trackball_size: 0.8, + trackball_size: 100.0, x: 0.0, y: 0.0, theta, @@ -37,7 +35,7 @@ impl TrackballModel { trackball } - fn drag_to(&mut self, x: f32, y: f32, dx: f32, dy: f32) { + 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; @@ -56,7 +54,7 @@ impl TrackballModel { self.theta } - fn set_theta(&mut self, theta: f32) { + pub fn set_theta(&mut self, theta: f32) { self.set_orientation(theta % 360.0, self.phi % 360.0); } @@ -64,7 +62,7 @@ impl TrackballModel { self.phi } - fn set_phi(&mut self, phi: f32) { + pub fn set_phi(&mut self, phi: f32) { self.set_orientation(self.theta % 360.0, phi % 360.0); } @@ -83,12 +81,12 @@ impl TrackballModel { self.theta = theta; self.phi = phi; - let angle = self.theta * (std::f32::consts::PI / 180.0); + let angle = self.theta.to_radians(); 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 angle = self.phi.to_radians(); let sine = (0.5 * angle).sin(); let zrot = UnitQuaternion::from_quaternion(Quaternion::new((0.5 * angle).cos(), 0.0, 0.0, sine)); @@ -129,49 +127,27 @@ impl TrackballModel { } } -#[derive(Debug, Clone)] -pub struct Trackball { - snippet: Snippet, - model: TrackballModel, -} +// impl Trackball { +// pub fn new() -> Result { +// let model = TrackballModel::new(0.0, 0.0); -impl Trackball { - pub fn new() -> Result { - let snippets = Snippet::new( - "trackball", - CodeType::<&'static str>::Path("transform/trackball.glsl".into()), - false, - None, - )?; +// Ok(Self { model }) +// } - let model = TrackballModel::new(45.0, 45.0); +// pub fn on_mouse_drag(&mut self, x: f32, y: f32, dx: f32, dy: f32) { +// self.model.drag_to(x, y, dx, dy); +// } - Ok(Self { - snippet: snippets, - model, - }) - } +// pub fn model(&self) -> &Matrix4 { +// self.model.model() +// } +// } - pub fn on_mouse_drag(&mut self, x: f32, y: f32, dx: f32, dy: f32) { - self.model.drag_to(x, y, dx, dy); - } - - pub fn model(&self) -> &Matrix4 { - self.model.model() - } -} - -impl Transform for Trackball { - fn snippet(&self) -> &Snippet { - &self.snippet - } -} - -impl AttaWithProgram for Trackball { +impl AttaWithProgram for TrackballModel { fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> Result<()> { unsafe { let l = program.get_uniform_location(gl, "trackball_model"); - gl.uniform_matrix_4_f32_slice(l.as_ref(), false, self.model.model().as_slice()); + gl.uniform_matrix_4_f32_slice(l.as_ref(), false, self.model().as_slice()); } Ok(()) @@ -183,6 +159,12 @@ mod test { #[test] fn test_trackball() { + let mut trackball = TrackballModel::new(45.0, 45.0); + println!("{:?}", trackball.model()); + + trackball.drag_to(0.0, 10.0, 15.0, 30.0); + println!("{:?}", trackball.model()); + // let trackball = Trackball::new().unwrap(); // println!("{}", trackball.snippet); } diff --git a/src/graphics/transforms/viewport.rs b/src/graphics/transforms/viewport.rs index 751ded3..586f8d7 100644 --- a/src/graphics/transforms/viewport.rs +++ b/src/graphics/transforms/viewport.rs @@ -16,7 +16,7 @@ impl Viewport { pub fn new() -> Result { let snippets = Snippet::new( "viewport", - CodeType::<&'static str>::Path("transform/viewport.glsl".into()), + CodeType::from_path("transform/viewport.glsl"), true, None, )?; diff --git a/src/main.rs b/src/main.rs index 7e5b703..3fc940b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +#![feature(proc_macro_hygiene)] #![allow(unused)] mod camera; mod components; @@ -6,6 +7,8 @@ mod errors; mod font_manager; mod graphics; mod pg; +mod setting; +mod shaders; mod support; mod ui; mod utils; @@ -13,6 +16,9 @@ mod utils; use pg::App; use support::supporter::run; +use once_cell::sync::Lazy; +static SETTING: Lazy = Lazy::new(|| setting::Setting::new()); + fn main() { env_logger::init(); run(move |gl| App::new(gl).unwrap()); diff --git a/src/pg/app.rs b/src/pg/app.rs index 5570074..df1dfd7 100644 --- a/src/pg/app.rs +++ b/src/pg/app.rs @@ -5,7 +5,7 @@ use crate::{ data_loader::Data, errors::*, graphics::{ - colormap::linear::LinearColormap, ppi::PPI, threed::ThreeD, AttaWithBuffer, + colormap::linear::LinearColormap, ppi::PPI, threed::Trackball, AttaWithBuffer, AttaWithProgram, Graphics, }, ui::{State, GUI}, @@ -20,7 +20,7 @@ use crate::{ use glow::HasContext; use imgui::Ui; -use super::app_type::{self, AppType}; +use super::layout_type::{self, Layout}; use super::{ModulePackage, Programs}; use crate::{font_manager::FontManager, graphics::font::Text}; @@ -28,30 +28,24 @@ pub struct App<'gl> { gl: &'gl GL, context: Context<'gl>, gui: GUI, - app_type: AppType<'gl>, + layout: Layout<'gl>, } impl<'gl> App<'gl> { pub fn new(gl: &'gl GL) -> Result { let programs = Programs::new(gl).unwrap(); let mut default_state = State::default(); - let mut gui = GUI::new(State::default()); - let app_type = gui.apptype(gl); - + let layout = gui.layout(gl); let context = Context::new(gl, Cache::new(), programs); Ok(Self { gui, gl, context, - app_type, + layout, }) } - pub fn init<'a>(&'a mut self) -> AppType { - self.gui.apptype(&self.gl) - } - pub fn prepare(&mut self) { if let Err(e) = self.context.programs.prepare() { error!("prepare failed: {:?}", e); @@ -67,13 +61,13 @@ impl<'gl> App<'gl> { } pub fn render<'a>(&'a mut self) { - if let Err(e) = self.app_type.draw_program(&mut self.context) { + if let Err(e) = self.layout.launch_render_task(&mut self.context) { error!("draw_program failed: {:?}", e); } } pub fn render_ui<'a>(&'a mut self, ui: &Ui, window: &winit::window::Window, run: &mut bool) { - *run = self.gui.render(ui, &mut self.context, &mut self.app_type); + *run = self.gui.render(ui, &mut self.context, &mut self.layout); } pub fn destroy(&mut self) { diff --git a/src/pg/app_type.rs b/src/pg/layout_type.rs similarity index 52% rename from src/pg/app_type.rs rename to src/pg/layout_type.rs index 1e92a85..7d97138 100644 --- a/src/pg/app_type.rs +++ b/src/pg/layout_type.rs @@ -1,28 +1,70 @@ -use crate::errors::*; use crate::graphics::ty; use crate::pg::{Context, ModulePackage}; -use crate::ui::typ::{LayoutAppType, MainLoadTyp}; +use crate::ui::typ::{LayoutAttach, MainLoadAttach}; use crate::utils::resources::{ManagedResource, RcGlRcFramebuffer, RcGlRcRenderbuffer, GL}; +use crate::{errors::*, main}; use glow::HasContext; const RBO_WIDTH: i32 = 1920; const RBO_HEIGHT: i32 = 1080; +// App Layout Type +macro_rules! impl_layout { + ($({$name:ident => $attach:ty}),+ $(,)?) => { + pub enum Layout<'gl> { + $( + $name($attach), + )+ + } + + impl<'gl> Layout<'gl> { + pub fn launch_render_task(&mut self, mut context: &mut Context<'gl>) -> Result<()> + { + let programs = &mut context.programs; + let gl = programs.gl; + + match self { + $( + Self::$name(typ) => { + typ.render_task(gl, programs)?; + } + )+ + } + Ok(()) + } + + pub fn append_package(&mut self, package: ModulePackage<'gl>) { + match self { + $( + Self::$name(typ) => { + typ.append(package); + } + )+ + } + } + + } + }; +} + pub struct ViewPort { renderer_size: [f32; 2], main_fbo: RcGlRcFramebuffer, _main_rbo: RcGlRcRenderbuffer, + _main_depth_rbo: RcGlRcRenderbuffer, } impl ViewPort { pub fn new(gl: &GL) -> Self { let main_fbo: RcGlRcFramebuffer = gl.create_resource_rc(); let main_rbo: RcGlRcRenderbuffer = gl.create_resource_rc(); + let main_depth_rbo: RcGlRcRenderbuffer = gl.create_resource_rc(); main_fbo.bind(glow::FRAMEBUFFER); - main_rbo.bind(glow::RENDERBUFFER); unsafe { + // Color Attachment + main_rbo.bind(glow::RENDERBUFFER); gl.renderbuffer_storage(glow::RENDERBUFFER, glow::RGBA8, RBO_WIDTH, RBO_HEIGHT); gl.framebuffer_renderbuffer( glow::FRAMEBUFFER, @@ -30,12 +72,33 @@ impl ViewPort { glow::RENDERBUFFER, Some(main_rbo.native()), ); + main_rbo.unbind(glow::RENDERBUFFER); + + // Depth Attachment + main_depth_rbo.bind(glow::RENDERBUFFER); + gl.renderbuffer_storage( + glow::RENDERBUFFER, + glow::DEPTH_COMPONENT24, + RBO_WIDTH, + RBO_HEIGHT, + ); + + gl.framebuffer_renderbuffer( + glow::FRAMEBUFFER, + glow::DEPTH_ATTACHMENT, + glow::RENDERBUFFER, + Some(main_depth_rbo.native()), + ); + main_depth_rbo.unbind(glow::RENDERBUFFER); + // gl.clear_color(1.0, 0.0, 0.0, 1.0); // gl.clear(glow::COLOR_BUFFER_BIT); // 检查帧缓冲是否完整 if gl.check_framebuffer_status(glow::FRAMEBUFFER) != glow::FRAMEBUFFER_COMPLETE { panic!("Framebuffer is not complete!"); } + + gl.enable(glow::DEPTH_TEST); } main_fbo.unbind(glow::FRAMEBUFFER); @@ -43,6 +106,7 @@ impl ViewPort { renderer_size: [0.0, 0.0], main_fbo, _main_rbo: main_rbo, + _main_depth_rbo: main_depth_rbo, } } @@ -76,70 +140,6 @@ impl ViewPort { } } -macro_rules! app_type_into { - ($({$t: ty => $b:tt},)+) => { - $( - impl<'gl> From<$t> for AppType<'gl> { - fn from(t: $t) -> Self { - Self::$b(t) - } - } - - impl<'a,'gl> From<&'a AppType<'gl>> for &'a $t { - fn from(t: &'a AppType<'gl>) -> Self { - if let AppType::$b(t) = t { - t - } else { - panic!("AppType is not {}", stringify!($b)); - } - } - } - - impl<'a,'gl> From<&'a mut AppType<'gl>> for &'a mut $t { - fn from(t: &'a mut AppType<'gl>) -> Self { - if let AppType::$b(t) = t { - t - } else { - panic!("AppType is not {}", stringify!($b)); - } - } - } - - )+ - }; -} - -pub enum AppType<'gl> { - MainLoad(MainLoadTyp<'gl>), - Other, -} - -app_type_into!({ - MainLoadTyp<'gl> => MainLoad -},); - -impl<'gl> AppType<'gl> { - pub fn draw_program<'b>(&mut self, mut context: &mut Context<'gl>) -> Result<()> - where - 'gl: 'b, - { - let programs = &mut context.programs; - let gl = programs.gl; - match self { - Self::MainLoad(typ) => { - programs.draw(typ)?; - } - Self::Other => {} - } - Ok(()) - } - - pub fn deal_with_cursor(&mut self, package: ModulePackage<'gl>) { - match self { - Self::MainLoad(typ) => { - typ.deal_with_cursor(package); - } - Self::Other => {} - } - } -} +impl_layout!( + {MainLoad => MainLoadAttach<'gl>}, +); diff --git a/src/pg/mod.rs b/src/pg/mod.rs index 2efb065..1c82522 100644 --- a/src/pg/mod.rs +++ b/src/pg/mod.rs @@ -1,17 +1,23 @@ mod app; -pub mod app_type; +use glow::HasContext; +pub mod layout_type; mod modules; use crate::font_manager::FontManager; use crate::graphics::font::Text; use crate::graphics::ppi::PPI; -use crate::graphics::threed::ThreeD; -use crate::ui::typ::LayoutAppType; +use crate::graphics::threed::Trackball; +use crate::graphics::{AttaWithProgram, AttachWithMouse}; +use crate::ui::operation::Operation; +use crate::ui::typ::LayoutAttach; use crate::utils::cache::CachedData; use crate::utils::resources::GL; use crate::{errors::*, graphics::Graphics}; pub use app::{App, Context}; pub use modules::{Module, ModuleCursor, ModuleData, PPIModule, PPIPackage}; +use std::sync::atomic::AtomicUsize; + +static MODULE_PACKAGE_ID: AtomicUsize = AtomicUsize::new(0); pub(super) struct Programs<'gl> { gl: &'gl GL, @@ -69,26 +75,18 @@ impl<'gl> Programs<'gl> { pub fn draw_modules( &mut self, modules: &mut ModulePackage<'gl>, - init_info: &ThreeD, + operation: &Operation, ) -> Result<()> { - // if !modules.need_update { - // return Ok(()); - // } match &mut modules.modules { _ModulePackage::PPI(ppi) => { self.ppi().start(); - self.ppi().init(init_info); - self.ppi().render(ppi)?; + self.ppi().render(ppi, operation)?; self.ppi().end(); } } modules.need_update = false; Ok(()) } - - pub fn draw>(&mut self, ty: &mut M) -> Result<()> { - ty.draw_program(self.gl, self) - } } pub enum Data<'a> { @@ -119,8 +117,6 @@ macro_rules! impl_module_package { _ModulePackage::$b(t) } } - - )+ }; } @@ -130,7 +126,8 @@ impl_module_data!({ }); pub struct ModulePackage<'gl> { - need_update: bool, + id: usize, + pub need_update: bool, modules: _ModulePackage<'gl>, } @@ -148,19 +145,27 @@ where { fn from(t: T) -> Self { Self { + id: MODULE_PACKAGE_ID.fetch_add(1, std::sync::atomic::Ordering::SeqCst), modules: t.into(), need_update: true, } } } -impl ModulePackage<'_> { - pub fn ui_build(&mut self, ui: &imgui::Ui) -> Result<()> { - match &mut self.modules { - _ModulePackage::PPI(ppi) => { - ppi.ui_build(ui); - } - } - Ok(()) +impl PartialEq for ModulePackage<'_> { + fn eq(&self, other: &Self) -> bool { + self.id == other.id + } +} + +impl ModulePackage<'_> { + pub fn ui_build(&mut self, ui: &imgui::Ui) -> Result { + Ok(match &mut self.modules { + _ModulePackage::PPI(ppi) => ppi.ui_build(ui), + }) + } + + pub fn dirty(&mut self) { + self.need_update = true; } } diff --git a/src/pg/modules/mod.rs b/src/pg/modules/mod.rs index f7c741e..fb22777 100644 --- a/src/pg/modules/mod.rs +++ b/src/pg/modules/mod.rs @@ -1,6 +1,13 @@ -use crate::utils::{ - cache::CachedData, - resources::{ManagedResource, RcGlBuffer, RcGlVertexArray}, +use crate::{ + graphics::AttachWithMouse, + ui::{ + operation::{self, Operation}, + typ::CameraOP, + }, + utils::{ + cache::CachedData, + resources::{ManagedResource, RcGlBuffer, RcGlVertexArray}, + }, }; use glow::{HasContext, NativeBuffer, NativeVertexArray}; mod ppi; @@ -63,14 +70,18 @@ impl<'a> Attach<'a> { pub trait Module: Sized { type Cursor: ModuleCursor; type Data; - type InitInfo; + type Operation: AttachWithMouse; - fn render(&mut self, cursor: &mut Self::Cursor) -> Result<()>; + fn render( + &mut self, + cursor: &mut Self::Cursor, + operation: &Operation, + ) -> Result<()>; fn resize(&self, size: [f32; 2]); fn destroy(&self); fn start(&mut self); - fn init(&mut self, info: &Self::InitInfo) -> Result<()>; + // fn init(&mut self, info: &Operation) -> Result<()>; fn end(&mut self); fn load_data<'dt>(&self, data: &CachedData) -> Result; } @@ -88,5 +99,5 @@ pub trait ModuleCursor { where F: FnOnce(&mut Self::Config); - fn ui_build(&mut self, ui: &imgui::Ui); + fn ui_build(&mut self, ui: &imgui::Ui) -> bool; } diff --git a/src/pg/modules/ppi.rs b/src/pg/modules/ppi.rs index 0161091..4b06891 100644 --- a/src/pg/modules/ppi.rs +++ b/src/pg/modules/ppi.rs @@ -1,6 +1,9 @@ use std::rc::Rc; use tracker::track; +use crate::graphics::{font::Text, *}; +use crate::ui::operation::{self, Operation}; +use crate::SETTING; use crate::{ data_loader::Data, errors::*, @@ -10,9 +13,7 @@ use crate::{ }; use imgui::VerticalSlider; use ppi::{PPIConfig, PPI}; -use threed::ThreeD; - -use crate::graphics::{font::Text, *}; +use threed::Trackball; use super::{Attach, Module, ModuleCursor}; pub struct PPIModule<'b, 'a: 'b> { @@ -35,9 +36,13 @@ impl<'b, 'a: 'b> PPIModule<'b, 'a> { let (vbo, ebo, len) = self.ppi_program.bake( data, &PPIConfig { + unvalid_value: config.unvalid_value, + color_range: config.color_range, + colors: config.colors.clone(), layer: config.layer, rdpi: config.rdpi, adpi: config.adpi, + three_d: config.is_three_d, }, )?; attach.bind_data(&vbo, ebo.as_ref(), len); @@ -48,7 +53,7 @@ impl<'b, 'a: 'b> PPIModule<'b, 'a> { impl<'b, 'a: 'b> Module for PPIModule<'b, 'a> { type Cursor = PPIPackage<'a>; type Data = Data; - type InitInfo = ThreeD; + type Operation = Trackball; fn start(&mut self) { self.ppi_program.mount(&self.gl).unwrap(); @@ -58,16 +63,26 @@ impl<'b, 'a: 'b> Module for PPIModule<'b, 'a> { self.ppi_program.unmount(&self.gl).unwrap(); } - fn render<'dt>(&mut self, cursor: &mut Self::Cursor) -> Result<()> { + fn render<'dt>( + &mut self, + cursor: &mut Self::Cursor, + operation: &Operation, + ) -> Result<()> { + operation.attach_with_program(&self.gl, self.ppi_program.program()); let attach = &mut cursor.ppi_attach; let data = &cursor.ppi_data.borrow(); let config = &mut cursor.ppi_config; + self.ppi_program.set_config( &self.gl, &PPIConfig { + unvalid_value: config.unvalid_value, + color_range: config.color_range, + colors: config.colors.clone(), layer: config.layer, rdpi: config.rdpi, adpi: config.adpi, + three_d: config.is_three_d, }, )?; @@ -92,11 +107,25 @@ impl<'b, 'a: 'b> Module for PPIModule<'b, 'a> { } let (vao, vbo, ebo) = self.ppi_program.init(&self.gl); let mut attach = Attach::new(&self.gl, vao, vbo, ebo, None); - let (r, a, t) = self.ppi_program.data_info(&_data)?; + let (r, a, t, max_layer, unvalid) = self.ppi_program.data_info(&_data)?; + + let cmap = SETTING.find(&t); + + if cmap.is_none() { + return Err(Error::InvalidDataType); + } + + let cmap = cmap.unwrap(); + let config = PPIModuleConfig { + color_range: cmap.value_range(), + colors: cmap.color()?, layer: 0, rdpi: r, adpi: a, + max_layer, + unvalid_value: unvalid, + is_three_d: true, tracker: 0, }; @@ -104,16 +133,19 @@ impl<'b, 'a: 'b> Module for PPIModule<'b, 'a> { Ok(PPIPackage::new(config, attach, data)) } - - fn init(&mut self, info: &Self::InitInfo) -> Result<()> { - info.attach_with_program(&self.gl, &self.ppi_program.program()); - Ok(()) - } } #[track] +#[derive(PartialEq)] pub struct PPIModuleConfig { pub layer: usize, + pub colors: Vec<[u8; 4]>, + pub color_range: [f32; 2], + pub is_three_d: bool, + #[do_not_track] + pub unvalid_value: f32, + #[do_not_track] + pub max_layer: usize, #[do_not_track] pub rdpi: f32, #[do_not_track] @@ -148,12 +180,17 @@ impl<'gl> ModuleCursor for PPIPackage<'gl> { f(&mut self.ppi_config); } - fn ui_build(&mut self, ui: &imgui::Ui) { + fn ui_build(&mut self, ui: &imgui::Ui) -> bool { let mut layer = self.ppi_config.layer; + let mut is_three_d = self.ppi_config.is_three_d; + ui.text("PPI Data Config"); - ui.slider("Layer", 0, 10, &mut layer); + ui.slider("Layer", 0, self.ppi_config.max_layer - 1, &mut layer); + ui.checkbox("three d?", &mut is_three_d); ui.separator(); self.ppi_config.set_layer(layer); + self.ppi_config.set_is_three_d(is_three_d); + self.ppi_config.changed_any() } } diff --git a/src/setting.rs b/src/setting.rs new file mode 100644 index 0000000..55d4ed3 --- /dev/null +++ b/src/setting.rs @@ -0,0 +1,101 @@ +use crate::errors::*; +use serde::{Deserialize, Serialize}; +use std::fs::{read, read_to_string}; + +use crate::{data_loader::DataType, utils::color_tools::hex_to_rgba_u8}; + +macro_rules! find_cmap { + ($c:ident,$find_on:ident,$({$b:tt => $name:literal}),*) => { + + { + let mut cmap = None; + match $c { + $( + $b => { + let find_v = $find_on.iter().find(|cb| cb.type_name == $name).map(|cb| cb); + cmap = find_v; + } + )* + _ => {} + } + cmap + } + + + }; +} + +#[derive(Deserialize, Serialize)] +pub struct Setting { + pub cmap: Vec, +} + +impl Setting { + pub fn find(&self, name: &DataType) -> Option<&CB> { + let cmap = &self.cmap; + use DataType::*; + find_cmap!( + name, cmap, + {DBZ => "DBZ"}, + {VEl => "VEL"}, + {VIL => "VIL"} + ) + } +} + +impl Setting { + pub fn new() -> Self { + let file = read_to_string("./radar.toml").unwrap(); + let setting: Setting = toml::from_str(&file).unwrap(); + setting + } +} + +#[derive(Deserialize, Serialize)] +pub struct CB { + #[serde(rename = "type")] + pub type_name: String, + pub colors: Vec, + pub levels: Vec, +} + +impl CB { + pub fn value_range(&self) -> [f32; 2] { + let mut range = [0.0, 0.0]; + let levels = &self.levels; + range[0] = levels[0]; + range[1] = levels[levels.len() - 1]; + range + } + + pub fn color(&self) -> Result> { + if self.colors.len() != self.levels.len() - 1 { + return Err(Error::SettingError("Color and level mismatch".to_string())); + } + + let mut result = self + .colors + .iter() + .map(|v| hex_to_rgba_u8(v)) + .collect::, String>>() + .map_err(|v| Error::SettingError(v.to_string()))?; + + let mut span = Vec::with_capacity(self.levels.len() - 1); + + for idx in 0..self.levels.len() - 1 { + let start = self.levels[idx]; + let end = self.levels[idx + 1]; + let range = end - start; + span.push(range); + } + + let range = self.value_range(); + let all_range = range[1] - range[0]; + + for (level, r) in span.iter().zip(result.iter_mut()) { + r[3] = ((*level / all_range) * 255.0) as u8; + } + + Ok(result) + } +} diff --git a/src/shaders/colormap.rs b/src/shaders/colormap.rs new file mode 100644 index 0000000..77c24cc --- /dev/null +++ b/src/shaders/colormap.rs @@ -0,0 +1,50 @@ +use super::CodePiece; +use crate::impl_code_piece; +use glsl::syntax::ShaderStage; +use glsl::syntax::TranslationUnit; +use glsl::transpiler::glsl::show_translation_unit; +use glsl_quasiquote::glsl; + +pub struct ColorMap(pub ShaderStage); + +impl ColorMap { + pub fn new() -> Self { + let raw = glsl! { + uniform sampler1D colormap; + uniform vec4 colormap_conf; + + float find_idx(float ratio) { + float i = 0; + float count = colormap_conf.z - 1.0; + float sum = 0.0; + + while (ratio > sum) { + sum += texture(colormap, float(i++) / count).w; + } + return i / count; + } + + vec4 linear_colormap(float value) + { + float vmin = colormap_conf.x; + float vmax = colormap_conf.y; + float count = colormap_conf.z - 1.0; + + float invalid = colormap_conf.w; + + if (value == invalid) { + return vec4(0.0, 0.0, 0.0, 0.0); + } + + float v = clamp((value - vmin), vmin, vmax) / (vmax - vmin); + float idx = find_idx(v); + vec4 result = texture(colormap, idx); + return result; + } + }; + + Self(raw) + } +} + +impl_code_piece!(ColorMap, 0); diff --git a/src/shaders/math.rs b/src/shaders/math.rs new file mode 100644 index 0000000..49dbd9f --- /dev/null +++ b/src/shaders/math.rs @@ -0,0 +1,73 @@ +use glsl::syntax::ShaderStage; +use glsl_quasiquote::glsl; + +use super::CodePiece; +use glsl::syntax::TranslationUnit; +use glsl::transpiler::glsl::show_translation_unit; + +use crate::impl_code_piece; + +pub struct Constants { + pub raw: ShaderStage, +} + +impl Constants { + pub fn new() -> Constants { + let raw = glsl! { + + #ifndef _GLUMPY__CONSTANTS__ + #define _GLUMPY__CONSTANTS__ + + // The base of natural logarithms (e) + const float M_E = 2.71828182845904523536028747135266250; + + // The logarithm to base 2 of M_E (log2(e)) + const float M_LOG2E = 1.44269504088896340735992468100189214; + + // The logarithm to base 10 of M_E (log10(e)) + const float M_LOG10E = 0.434294481903251827651128918916605082; + + // The natural logarithm of 2 (loge(2)) + const float M_LN2 = 0.693147180559945309417232121458176568; + + // The natural logarithm of 10 (loge(10)) + const float M_LN10 = 2.30258509299404568401799145468436421; + + // Pi, the ratio of a circle's circumference to its diameter. + const float M_PI = 3.14159265358979323846264338327950288; + + // Pi divided by two (pi/2) + const float M_PI_2 = 1.57079632679489661923132169163975144; + + // Pi divided by four (pi/4) + const float M_PI_4 = 0.785398163397448309615660845819875721; + + // The reciprocal of pi (1/pi) + const float M_1_PI = 0.318309886183790671537767526745028724; + + // Two times the reciprocal of pi (2/pi) + const float M_2_PI = 0.636619772367581343075535053490057448; + + // Two times the reciprocal of the square root of pi (2/sqrt(pi)) + const float M_2_SQRTPI = 1.12837916709551257389615890312154517; + + // The square root of two (sqrt(2)) + const float M_SQRT2 = 1.41421356237309504880168872420969808; + + // The reciprocal of the square root of two (1/sqrt(2)) + const float M_SQRT1_2 = 0.707106781186547524400844362104849039; + + // 1 degree in radians + const float degree = 180.0/M_PI; + + // 1 radian in degrees + const float radian = M_PI/180.0; + + #endif + }; + + Constants { raw } + } +} + +impl_code_piece!(Constants, raw); diff --git a/src/shaders/mod.rs b/src/shaders/mod.rs new file mode 100644 index 0000000..33ed41f --- /dev/null +++ b/src/shaders/mod.rs @@ -0,0 +1,97 @@ +pub mod colormap; +pub mod math; +pub mod polar; +pub mod ppi; +pub mod trackball; +use glsl::{ + syntax::{ShaderStage, TranslationUnit}, + transpiler::glsl::{show_struct, show_translation_unit}, +}; +use glsl_quasiquote::glsl; + +use crate::components::Shader; + +struct PPI { + vertex: ShaderStage, +} + +impl PPI { + fn new() -> Self { + let vertex: ShaderStage = glsl! { + layout(location = 0) in vec3 position; + out float in_value; + + void main() { + gl_Position = vec4(position.x, position.y, 0.5, 1.0); + in_value = position.z; + } + }; + + Self { vertex } + } +} + +impl std::fmt::Display for PPI { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + show_translation_unit(f, &self.vertex); + Ok(()) + } +} + +#[derive(std::fmt::Debug)] +pub struct EmptyPiece(pub TranslationUnit); + +pub trait CodePiece: std::fmt::Display { + fn raw(&self) -> &TranslationUnit; + + fn include(i: T, raw: TranslationUnit) -> TranslationUnit { + let mut s = i.raw().clone(); + s.extend(raw); + s + } +} + +impl CodePiece for EmptyPiece { + fn raw(&self) -> &TranslationUnit { + &self.0 + } +} + +impl std::fmt::Display for EmptyPiece { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + Ok(()) + } +} + +#[macro_export] +macro_rules! impl_code_piece { + ($t:ty, $c:tt) => { + impl CodePiece for $t { + fn raw(&self) -> &TranslationUnit { + &self.$c + } + } + + impl std::fmt::Display for $t { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + show_translation_unit(f, &self.$c); + Ok(()) + } + } + }; +} + +mod test { + + use glsl::transpiler::glsl::show_translation_unit; + + use super::math::Constants; + use super::polar::PolarTransform; + use super::PPI; + + #[test] + fn test() { + let polar = PolarTransform::new(); + println!("{}", polar); + } +} diff --git a/src/shaders/polar.rs b/src/shaders/polar.rs new file mode 100644 index 0000000..34e178c --- /dev/null +++ b/src/shaders/polar.rs @@ -0,0 +1,58 @@ +use super::CodePiece; +use crate::impl_code_piece; +use glsl::syntax::ShaderStage; +use glsl::syntax::TranslationUnit; +use glsl::transpiler::glsl::show_translation_unit; + +use super::math::Constants; +use glsl_quasiquote::glsl; + +pub struct PolarTransform { + pub raw: ShaderStage, +} + +impl PolarTransform { + pub fn new() -> PolarTransform { + let raw = glsl! { + + uniform float polar_origin; + + vec4 forward(float rho, float theta, float z, float w) + { + return vec4(rho * cos(theta + polar_origin), + rho * sin(theta + polar_origin), + rho * sin(z), w); + } + + vec4 forward(float x, float y) {return forward(x, y, 0.0, 1.0);} + vec4 forward(float x, float y, float z) {return forward(x, y, z, 1.0);} + vec4 forward(vec2 P) { return forward(P.x, P.y); } + vec4 forward(vec3 P) { return forward(P.x, P.y, P.z, 1.0); } + vec4 forward(vec4 P) { return forward(P.x, P.y, P.z, P.w); } + + vec4 inverse(float x, float y, float z, float w) + { + float rho = length(vec2(x,y)); + float theta = atan(y,x); + if( theta < 0.0 ) + theta = 2.0*M_PI+theta; + return vec4(rho, theta-polar_origin, z, w); + } + + + vec4 inverse(float x, float y) {return inverse(x,y,0.0,1.0); } + vec4 inverse(float x, float y, float z) {return inverse(x,y,z,1.0); } + vec4 inverse(vec2 P) { return inverse(P.x, P.y, 0.0, 1.0); } + vec4 inverse(vec3 P) { return inverse(P.x, P.y, P.z, 1.0); } + vec4 inverse(vec4 P) { return inverse(P.x, P.y, P.z, P.w); } + }; + + let mut constant = Constants::new().raw; + + constant.extend(raw); + + PolarTransform { raw: constant } + } +} + +impl_code_piece!(PolarTransform, raw); diff --git a/src/shaders/ppi.rs b/src/shaders/ppi.rs new file mode 100644 index 0000000..fb4d600 --- /dev/null +++ b/src/shaders/ppi.rs @@ -0,0 +1,147 @@ +use super::trackball::Trackball; +use super::CodePiece; +use crate::impl_code_piece; +use glsl::syntax::ShaderStage; +use glsl::syntax::TranslationUnit; +use glsl::transpiler::glsl::show_translation_unit; +use glsl_quasiquote::glsl; + +pub struct PPIVertex(pub ShaderStage); +pub struct PPIGeom(pub ShaderStage); +pub struct PPIFragment(pub ShaderStage); + +impl PPIVertex { + pub fn new() -> Self { + let raw = glsl! { + layout(location = 0) in vec4 position; + out float in_value; + + void main() { + gl_Position = vec4(position.x * 10.0, position.y, position.z, 1.0); + in_value = position.w; + } + }; + + Self(raw) + } +} + +impl PPIGeom { + pub fn new() -> Self { + let mut trackball = Trackball::new().0; + let polar = super::polar::PolarTransform::new().raw; + let raw = glsl! { + layout(points) in; + layout(triangle_strip, max_vertices = 4) out; + + // conf: Range, Elevation, Resolution, mode + uniform vec4 conf; + in float in_value[]; + + out float x; + out float y; + out float value; + + flat out vec4 vrange; + + + void main() { + float rdpi = conf.x * 10.0; + float mode = conf.w; + vec4 reso = vec4(rdpi/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 *= radian; + po.z *= radian * mode; + + 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(); + + } + + }; + + trackball.extend(polar); + trackball.extend(raw); + + Self(trackball) + } +} + +impl PPIFragment { + pub fn new() -> Self { + use super::polar::PolarTransform; + let mut include = PolarTransform::new().raw; + let mut colormap = super::colormap::ColorMap::new().0; + let raw = 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 = linear_colormap(value); + + if (result.w == 0.0) { + discard; + } + + FragColor = result; + } + }; + + include.extend(colormap); + include.extend(raw); + + Self(include) + } +} + +impl_code_piece!(PPIVertex, 0); +impl_code_piece!(PPIGeom, 0); +impl_code_piece!(PPIFragment, 0); diff --git a/src/shaders/trackball.rs b/src/shaders/trackball.rs new file mode 100644 index 0000000..57a9bfd --- /dev/null +++ b/src/shaders/trackball.rs @@ -0,0 +1,30 @@ +use super::CodePiece; +use glsl::syntax::ShaderStage; +use glsl::syntax::TranslationUnit; +use glsl::transpiler::glsl::show_translation_unit; + +use crate::impl_code_piece; + +pub struct Trackball(pub ShaderStage); + +impl Trackball { + pub fn new() -> Self { + let raw = glsl_quasiquote::glsl! { + uniform mat4 trackball_view; + uniform mat4 trackball_model; + uniform mat4 trackball_projection; + + vec4 transform(vec4 position) + { + return trackball_projection + * trackball_view + * trackball_model + * position; + } + }; + + Self(raw) + } +} + +impl_code_piece!(Trackball, 0); diff --git a/src/support/supporter.rs b/src/support/supporter.rs index 2f0a845..5bb56ae 100644 --- a/src/support/supporter.rs +++ b/src/support/supporter.rs @@ -1,4 +1,4 @@ -use crate::{pg::App, utils::resources::GL}; +use crate::{graphics::font, pg::App, utils::resources::GL}; use glow::HasContext; use glutin::{ @@ -7,6 +7,7 @@ use glutin::{ display::{GetGlDisplay, GlDisplay}, surface::{GlSurface, Surface, SurfaceAttributesBuilder, WindowSurface}, }; +use imgui::FontConfig; use imgui_winit_support::{ winit::{ dpi::LogicalSize, @@ -202,9 +203,14 @@ fn imgui_init(window: &Window) -> (WinitPlatform, imgui::Context) { winit_platform.attach_window(imgui_context.io_mut(), &window, dpi_mode); } + let mut font_conf = FontConfig::default(); + font_conf.size_pixels = 16.0; + imgui_context .fonts() - .add_font(&[imgui::FontSource::DefaultFontData { config: None }]); + .add_font(&[imgui::FontSource::DefaultFontData { + config: Some(font_conf), + }]); println!("imgui global scale: {}", winit_platform.hidpi_factor()); diff --git a/src/ui/io.rs b/src/ui/io.rs index 5afc84a..3c62b7e 100644 --- a/src/ui/io.rs +++ b/src/ui/io.rs @@ -23,14 +23,21 @@ impl IO { let io = ui.io(); let delta = if ui.is_mouse_dragging(imgui::MouseButton::Left) { - Some(ui.mouse_drag_delta_with_button(imgui::MouseButton::Left)) + let delta = ui.mouse_drag_delta_with_threshold(imgui::MouseButton::Left, 5.0); + ui.reset_mouse_drag_delta(imgui::MouseButton::Left); + Some(delta) } else { None }; + let windows_position = ui.window_pos(); + IO { mouse: MouseIO { - position: io.mouse_pos, + position: [ + io.mouse_pos[0] - windows_position[0], + io.mouse_pos[1] - windows_position[1], + ], drag_delta: delta, is_dragging: ui.is_mouse_dragging(imgui::MouseButton::Left), left_button_pressed: io.mouse_down[0], diff --git a/src/ui/mod.rs b/src/ui/mod.rs index a912485..abd1d74 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -4,7 +4,7 @@ use log::*; use crate::data_loader::Data; use crate::errors::*; -use crate::pg::app_type::AppType; +use crate::pg::layout_type::Layout; use crate::pg::{ModulePackage, Programs}; use crate::utils::cache::Cache; use crate::utils::resources::{RcGlRcFramebuffer, RcGlRcRenderbuffer, RcGlRcResource, GL}; @@ -18,10 +18,11 @@ mod state; pub mod typ; pub use layout::*; pub use state::State; +pub mod operation; pub struct GUI { state: State, - layout: layout::Layout, + layout_manager: layout::Layout, renderer_size: [f32; 2], } @@ -29,12 +30,12 @@ impl GUI { pub fn new(state: State) -> Self { GUI { state, - layout: layout::Layout::new(), + layout_manager: layout::Layout::new(), renderer_size: [0.0, 0.0], } } - pub fn apptype<'a, 'gl>(&'a mut self, gl: &'gl GL) -> AppType<'gl> { + pub fn layout<'a, 'gl>(&'a mut self, gl: &'gl GL) -> Layout<'gl> { self.state.app_type.init_apptype(gl) } @@ -42,22 +43,22 @@ impl GUI { &mut self, ui: &Ui, context: &'b mut crate::pg::Context<'gl>, - app_type: &'b mut AppType<'gl>, + layout_atta: &'b mut Layout<'gl>, ) -> bool { // Menu bar - self.menu_bar(ui, context, app_type); + self.menu_bar(ui, context, layout_atta); let menu_bar_height = ui.frame_height(); let display_size = ui.io().display_size; // Layout Size Reset - self.layout.set_origin([0.0, menu_bar_height]); - self.layout + self.layout_manager.set_origin([0.0, menu_bar_height]); + self.layout_manager .set_size([display_size[0], display_size[1] - menu_bar_height]); // Render self.state .app_type - .render(ui, context, &mut self.layout, app_type); + .render(ui, context, &mut self.layout_manager, layout_atta); true } @@ -66,7 +67,7 @@ impl GUI { &self, ui: &Ui, context: &'b mut crate::pg::Context<'gl>, - app_type: &mut AppType<'gl>, + layout_atta: &mut Layout<'gl>, ) { if let Some(top_menu) = ui.begin_main_menu_bar() { if let Some(menu) = ui.begin_menu("File") { @@ -75,7 +76,7 @@ impl GUI { Some(file) => match context.load_data(file.clone()) { Ok(data) => { info!("Data loaded: {:?}", file); - app_type.deal_with_cursor(data); + layout_atta.append_package(data); } Err(e) => { error!("Failed to get or insert data: {:?}", e); diff --git a/src/ui/operation.rs b/src/ui/operation.rs new file mode 100644 index 0000000..60d219b --- /dev/null +++ b/src/ui/operation.rs @@ -0,0 +1,124 @@ +use super::typ::CameraOP; +use crate::{ + camera::Camera, + components::Program, + graphics::{AttaWithProgram, AttachWithMouse}, +}; + +pub struct Operation { + camera: Camera, + projection: Projection, + operation: T, + need_update: bool, +} + +impl Operation { + pub fn new(operation: T, aspect: f32, fov: f32, z_near: f32, z_far: f32) -> Self { + let projection = Projection::new(aspect, fov, z_near, z_far); + Self { + projection, + camera: operation.init_camera(), + operation, + need_update: true, + } + } + + pub fn deal_io(&mut self, io: &super::io::IO) { + self.need_update = self.operation.attach_with_mouse( + &T::State::from_context(io), + &mut self.camera, + &mut self.projection, + ); + } + + pub fn set_camera(&mut self, f: impl Fn(&mut Camera)) { + f(&mut self.camera); + self.need_update = true; + } + + pub fn set_projection(&mut self, f: impl Fn(&mut Projection)) { + f(&mut self.projection); + self.need_update = true; + } + + pub fn attach_with_program(&self, gl: &glow::Context, program: &mut Program) { + use glow::HasContext; + unsafe { + let projection = program.get_uniform_location(gl, "trackball_projection"); + gl.uniform_matrix_4_f32_slice(projection.as_ref(), false, self.projection.as_slice()); + let view = program.get_uniform_location(gl, "trackball_view"); + gl.uniform_matrix_4_f32_slice( + view.as_ref(), + false, + self.camera.get_view_matrix().as_slice(), + ); + } + self.operation.attach_with_program(gl, program); + } + + pub fn attach_with_mouse(&mut self, camera_op: &T::State) -> bool { + self.operation + .attach_with_mouse(camera_op, &mut self.camera, &mut self.projection) + } + + pub fn is_need_update(&self) -> bool { + self.need_update + } + + pub fn reset(&mut self) { + self.operation.reset(); + self.need_update = true; + } +} + +pub struct Projection { + fov: f32, + z_near: f32, + z_far: f32, + aspect: f32, + projection: nalgebra_glm::Mat4, +} + +impl Projection { + fn new(aspect: f32, fov: f32, z_near: f32, z_far: f32) -> Self { + let projection = nalgebra_glm::perspective(aspect, fov.to_radians(), z_near, z_far); + Self { + aspect, + fov, + z_far, + z_near, + projection, + } + } + fn new_perspective(&self) -> nalgebra_glm::Mat4 { + nalgebra_glm::perspective(self.aspect, self.fov.to_radians(), self.z_near, self.z_far) + } + + pub fn set_aspect(&mut self, aspect: f32) { + self.aspect = aspect; + self.projection = self.new_perspective(); + } + + pub fn set_fov(&mut self, fov: f32) { + self.fov = fov; + self.projection = self.new_perspective(); + } + + pub fn set_z_near(&mut self, z_near: f32) { + self.z_near = z_near; + self.projection = self.new_perspective(); + } + + pub fn set_z_far(&mut self, z_far: f32) { + self.z_far = z_far; + self.projection = self.new_perspective(); + } + + pub fn fov(&self) -> f32 { + self.fov + } + + fn as_slice(&self) -> &[f32] { + self.projection.as_slice() + } +} diff --git a/src/ui/state.rs b/src/ui/state.rs index 82473c0..eb3e199 100644 --- a/src/ui/state.rs +++ b/src/ui/state.rs @@ -41,14 +41,14 @@ impl UiType { ui: &imgui::Ui, context: &mut crate::pg::Context<'gl>, layout: &mut crate::ui::layout::Layout, - app_typ: &mut crate::pg::app_type::AppType<'gl>, + app_typ: &mut crate::pg::layout_type::Layout<'gl>, ) { let gl = context.gl; let app_typ = app_typ.into(); uit!(self, {Mainload => render(ui,context,layout,app_typ)},); } - pub fn init_apptype<'gl>(&mut self, gl: &'gl GL) -> crate::pg::app_type::AppType<'gl> { + pub fn init_apptype<'gl>(&mut self, gl: &'gl GL) -> crate::pg::layout_type::Layout<'gl> { uit!(self, {Mainload => init(gl)},).into() } } diff --git a/src/ui/typ/main_load.rs b/src/ui/typ/main_load.rs index a703d1d..daac37e 100644 --- a/src/ui/typ/main_load.rs +++ b/src/ui/typ/main_load.rs @@ -1,26 +1,32 @@ -use super::{CameraOP, Layout, LayoutAppType, LayoutMod, Size}; -use crate::graphics::threed::ThreeD; +use std::thread::panicking; + +use super::{CameraOP, Layout, LayoutAttach, LayoutMod, Size}; +use crate::camera::Camera; +use crate::graphics::threed::Trackball; use crate::graphics::{AttaWithProgram, AttachWithMouse, MouseState}; use crate::pg::ModulePackage; -use crate::pg::{_ModulePackage, app_type::ViewPort}; +use crate::pg::{_ModulePackage, layout_type::ViewPort}; use crate::ui::io::IO; +use crate::ui::operation::Operation; use crate::utils::resources::GL; use glow::HasContext; use imgui::{Condition, Ui, WindowFlags}; +use nalgebra_glm::Vec3; pub struct MainLoad {} impl LayoutMod for MainLoad { - type AppType<'gl> = MainLoadTyp<'gl>; + type Attach<'gl> = MainLoadAttach<'gl>; fn render<'b, 'gl>( &mut self, ui: &imgui::Ui, context: &mut crate::pg::Context<'gl>, layout: &mut Layout, - apptyp: &mut Self::AppType<'gl>, + apptyp: &mut Self::Attach<'gl>, ) where 'gl: 'b, { + let mut changed = true; let mut grid = layout.grid(2, 1, [0.0, 0.0]); grid.set_col_size(&[size!(20.0%), size!(fill)]); grid.set_row_size(&[size!(fill)]); @@ -35,8 +41,27 @@ impl LayoutMod for MainLoad { grid.with(0, 0, [1, 1]) .start_window(ui, "MainLoad") .build(|| { + for package in 0..apptyp.packages.len() { + if ui.button(format!("Delete Package {}", package)) { + apptyp.packages.remove(package); + } + } + + ui.separator(); + for package in apptyp.packages.iter_mut() { - package.ui_build(ui); + if package.ui_build(ui).unwrap() { + package.dirty(); + } + } + + ui.separator(); + + if ui.button("ON TOP") { + apptyp + .operation + .set_camera(|c| c.set_position(Vec3::new(0.0, 0.0, 20.0))); + apptyp.operation.reset(); } }); @@ -58,48 +83,68 @@ impl LayoutMod for MainLoad { // ui.set_cursor_screen_pos([pos[0] + size[0], pos[1] + size[1]]); let draws = ui.get_window_draw_list(); - let fbo = apptyp.main_viewport.fbo(); - let fbo = fbo.native(); - draws - .add_callback({ - move || unsafe { - let x = pos[0] * scale[0]; - let y = (dsp_size[1] - pos[1]) * scale[1]; + draws.channels_split(2, |channels| { + channels.set_current(0); + let fbo = apptyp.main_viewport.fbo(); + let fbo = fbo.native(); - // gl.enable(glow::SCISSOR_TEST); - // gl.scissor(0, 0, size[0] as i32, size[1] as i32); - gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(fbo)); - gl.blit_framebuffer( - 0, - 0, - (content_size[0]) as i32, - (content_size[1]) as i32, - x as i32, - y as i32, - (x + content_size[0] * scale[0]) as i32, - (y - content_size[1] * scale[1]) as i32, - glow::COLOR_BUFFER_BIT, - glow::NEAREST, - ); - gl.bind_framebuffer(glow::READ_FRAMEBUFFER, None); - } - }) - .build(); + draws + .add_callback({ + move || unsafe { + let x = pos[0] * scale[0]; + let y = (dsp_size[1] - pos[1]) * scale[1]; + + // gl.enable(glow::SCISSOR_TEST); + // gl.scissor(0, 0, size[0] as i32, size[1] as i32); + gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(fbo)); + gl.blit_framebuffer( + 0, + 0, + (content_size[0]) as i32, + (content_size[1]) as i32, + x as i32, + y as i32, + (x + content_size[0] * scale[0]) as i32, + (y - content_size[1] * scale[1]) as i32, + glow::COLOR_BUFFER_BIT, + glow::NEAREST, + ); + gl.bind_framebuffer(glow::READ_FRAMEBUFFER, None); + } + }) + .build(); + + channels.set_current(1); + draws + .add_circle( + [pos[0] + 200.0, pos[1] + 200.0], + 50.0, + [1.0, 0.0, 0.0, 1.0], + ) + .filled(true) + .build(); + + draws.add_text( + [pos[0] + 300.0, pos[1] + 300.0], + [1.0, 1.0, 1.0, 1.0], + "Hello World", + ); + }); if ui.is_window_hovered() { let cio = IO::new(ui); - apptyp.deal_with_camera(&cio); + apptyp.operation.deal_io(&cio); } }); }); } - fn init<'gl>(&mut self, gl: &'gl GL) -> Self::AppType<'gl> { - let typ = MainLoadTyp { + fn init<'gl>(&mut self, gl: &'gl GL) -> Self::Attach<'gl> { + let typ = MainLoadAttach { main_viewport: ViewPort::new(gl), packages: Vec::new(), - camera_op: ThreeD::default(), + operation: Operation::new(Trackball::default(), 16.0 / 9.0, 45.0, 0.1, 1000.0), }; typ } @@ -109,13 +154,11 @@ impl MainLoad { pub fn new() -> Self { MainLoad {} } - - fn render_window(&mut self, ui: &Ui, context: &mut crate::pg::Context) {} } -pub struct MainLoadTyp<'gl> { +pub struct MainLoadAttach<'gl> { + operation: Operation, main_viewport: ViewPort, - camera_op: ThreeD, packages: Vec>, } @@ -127,32 +170,42 @@ impl CameraOP for MouseState { delta: context.mouse.drag_delta.unwrap(), } } else { - Self::None + if context.mouse.wheel_delta != 0.0 { + Self::Wheel(context.mouse.wheel_delta) + } else { + Self::None + } } } } -impl<'gl> LayoutAppType<'gl> for MainLoadTyp<'gl> { - type CameraOP = MouseState; - fn deal_with_cursor(&mut self, package: ModulePackage<'gl>) { +impl<'gl> LayoutAttach<'gl> for MainLoadAttach<'gl> { + fn append(&mut self, package: ModulePackage<'gl>) { self.packages.push(package); } - fn draw_program( + fn render_task( &mut self, gl: &glow::Context, programs: &mut crate::pg::Programs<'gl>, ) -> crate::errors::Result<()> { self.main_viewport.bind(gl); - for package in self.packages.iter_mut() { - programs.draw_modules(package, &self.camera_op)?; + if self.packages.iter().any(|v| v.need_update) || self.operation.is_need_update() { + unsafe { + gl.clear(glow::COLOR_BUFFER_BIT | glow::DEPTH_BUFFER_BIT); + } + + for package in self.packages.iter_mut() { + programs.draw_modules(package, &self.operation)?; + } + } + + if self.packages.is_empty() { + unsafe { + gl.clear(glow::COLOR_BUFFER_BIT); + } } self.main_viewport.unbind(); Ok(()) } - - fn _deal_with_camera(&mut self, camera_op: Self::CameraOP) { - // println!("Camera Op: {:?}", camera_op); - self.camera_op.attach_with_mouse(&camera_op); - } } diff --git a/src/ui/typ/mod.rs b/src/ui/typ/mod.rs index 8ddebc5..eb41e2c 100644 --- a/src/ui/typ/mod.rs +++ b/src/ui/typ/mod.rs @@ -3,35 +3,61 @@ use std::fmt::Debug; use super::io::IO; use super::layout::{Layout, Size}; mod main_load; -use crate::pg::app_type::AppType; +use crate::pg::layout_type::Layout as _Layout; use crate::pg::{self, ModuleCursor, ModulePackage, Programs}; use crate::utils::resources::GL; pub use main_load::*; +macro_rules! app_type_into { + ($({$t: ty => $b:tt},)+) => { + $( + impl<'gl> From<$t> for _Layout<'gl> { + fn from(t: $t) -> Self { + Self::$b(t) + } + } + + impl<'a,'gl> From<&'a _Layout<'gl>> for &'a $t { + fn from(t: &'a _Layout<'gl>) -> Self { + if let _Layout::$b(t) = t { + t + } else { + panic!("_Layout is not {}", stringify!($b)); + } + } + } + + impl<'a,'gl> From<&'a mut _Layout<'gl>> for &'a mut $t { + fn from(t: &'a mut _Layout<'gl>) -> Self { + if let _Layout::$b(t) = t { + t + } else { + panic!("_Layout is not {}", stringify!($b)); + } + } + } + + )+ + }; +} + pub trait LayoutMod { - type AppType<'gl>: Into> + LayoutAppType<'gl>; + type Attach<'gl>: Into<_Layout<'gl>> + LayoutAttach<'gl>; fn render<'dt, 'b, 'gl>( &mut self, ui: &imgui::Ui, context: &mut crate::pg::Context<'gl>, layout: &mut Layout, - apptyp: &mut Self::AppType<'gl>, + apptyp: &mut Self::Attach<'gl>, ) where 'gl: 'b; - fn init<'dt, 'gl>(&mut self, gl: &'gl GL) -> Self::AppType<'gl>; + fn init<'dt, 'gl>(&mut self, gl: &'gl GL) -> Self::Attach<'gl>; } -pub trait LayoutAppType<'gl> { - type CameraOP: CameraOP + Debug; - fn deal_with_cursor(&mut self, package: ModulePackage<'gl>); +pub trait LayoutAttach<'gl> { + fn append(&mut self, package: ModulePackage<'gl>); - fn deal_with_camera(&mut self, camera_op: &IO) { - self._deal_with_camera(CameraOP::from_context(camera_op)); - } - - fn _deal_with_camera(&mut self, camera_op: Self::CameraOP); - - fn draw_program( + fn render_task( &mut self, gl: &glow::Context, programs: &mut Programs<'gl>, @@ -47,3 +73,7 @@ impl CameraOP for () { () } } + +app_type_into!({ + MainLoadAttach<'gl> => MainLoad +},); diff --git a/src/utils/color_tools.rs b/src/utils/color_tools.rs new file mode 100644 index 0000000..afc5bb4 --- /dev/null +++ b/src/utils/color_tools.rs @@ -0,0 +1,18 @@ +pub fn hex_to_rgba_u8(hex: &str) -> Result<[u8; 4], String> { + let hex = hex.trim_start_matches('#'); + + if hex.len() != 6 && hex.len() != 8 { + return Err("Hex color should be in #RRGGBB or #RRGGBBAA format".to_string()); + } + + let r = u8::from_str_radix(&hex[0..2], 16).map_err(|e| e.to_string())?; + let g = u8::from_str_radix(&hex[2..4], 16).map_err(|e| e.to_string())?; + let b = u8::from_str_radix(&hex[4..6], 16).map_err(|e| e.to_string())?; + let a = if hex.len() == 8 { + u8::from_str_radix(&hex[6..8], 16).map_err(|e| e.to_string())? + } else { + 255 // 默认不透明 + }; + + Ok([r, g, b, a]) +} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 5dfe3f1..2bd2b19 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,3 +1,4 @@ +pub mod color_tools; mod parser; pub mod resources; use include_dir::{include_dir, Dir};