ppi module

This commit is contained in:
Tsuki 2024-08-16 16:30:06 +08:00
parent 91f67b395f
commit 9aab1b5304
44 changed files with 1427 additions and 617 deletions

54
Cargo.lock generated
View File

@ -904,6 +904,27 @@ dependencies = [
"web-sys", "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]] [[package]]
name = "glutin" name = "glutin"
version = "0.31.3" version = "0.31.3"
@ -1860,6 +1881,12 @@ dependencies = [
"toml_edit 0.21.1", "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]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.85" version = "1.0.85"
@ -1938,6 +1965,8 @@ dependencies = [
"freetype-rs", "freetype-rs",
"geo", "geo",
"glow", "glow",
"glsl",
"glsl-quasiquote",
"glutin", "glutin",
"glutin-winit", "glutin-winit",
"image", "image",
@ -1960,6 +1989,7 @@ dependencies = [
"serde_json", "serde_json",
"thiserror", "thiserror",
"tinyfiledialogs", "tinyfiledialogs",
"toml",
"tracker", "tracker",
"winit", "winit",
] ]
@ -2290,9 +2320,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_spanned" name = "serde_spanned"
version = "0.6.6" version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d"
dependencies = [ dependencies = [
"serde", "serde",
] ]
@ -2549,21 +2579,21 @@ dependencies = [
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.8.15" version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac2caab0bf757388c6c0ae23b3293fdb463fee59434529014f85e3263b995c28" checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
dependencies = [ dependencies = [
"serde", "serde",
"serde_spanned", "serde_spanned",
"toml_datetime", "toml_datetime",
"toml_edit 0.22.16", "toml_edit 0.22.20",
] ]
[[package]] [[package]]
name = "toml_datetime" name = "toml_datetime"
version = "0.6.6" version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
dependencies = [ dependencies = [
"serde", "serde",
] ]
@ -2581,15 +2611,15 @@ dependencies = [
[[package]] [[package]]
name = "toml_edit" name = "toml_edit"
version = "0.22.16" version = "0.22.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "278f3d518e152219c994ce877758516bca5e118eaed6996192a774fb9fbf0788" checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d"
dependencies = [ dependencies = [
"indexmap", "indexmap",
"serde", "serde",
"serde_spanned", "serde_spanned",
"toml_datetime", "toml_datetime",
"winnow 0.6.15", "winnow 0.6.18",
] ]
[[package]] [[package]]
@ -3213,9 +3243,9 @@ dependencies = [
[[package]] [[package]]
name = "winnow" name = "winnow"
version = "0.6.15" version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "557404e450152cd6795bb558bca69e43c585055f4606e3bcae5894fc6dac9ba0" checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]

View File

@ -16,7 +16,7 @@ dirs = "5.0.1"
env_logger = "0.11.3" env_logger = "0.11.3"
flate2 = "1.0.30" flate2 = "1.0.30"
# font-kit = {version = "0.14.1"} # font-kit = {version = "0.14.1"}
freetype-rs = "0.37.0" freetype-rs = {version="0.37.0",features = ["bundled"]}
geo = "0.28.0" geo = "0.28.0"
glow = "0.13.1" glow = "0.13.1"
glutin = "0.31.3" glutin = "0.31.3"
@ -43,9 +43,13 @@ thiserror = "1.0.61"
winit = "0.29.3" winit = "0.29.3"
tinyfiledialogs = "3.0" tinyfiledialogs = "3.0"
tracker = "0.2.2" tracker = "0.2.2"
glsl = "7.0.0"
glsl-quasiquote = "7.0.0"
toml = "0.8.19"
[features] [features]
default = ["sdf_font"] default = ["sdf_font"]
normal_font = [] normal_font = []
sdf_font = [] sdf_font = []
inparser = []

30
radar.toml Normal file
View File

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

View File

@ -7,17 +7,17 @@ use std::num::NonZeroU32;
pub(crate) struct Camera { pub(crate) struct Camera {
pos: Vec3, pos: Vec3,
upward: Vec3, upward: Vec3,
front: Vec3, center: Vec3,
} }
pub type CameraPositon = Vec3; pub type CameraPositon = Vec3;
impl Camera { 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 { Self {
pos: world_loc, pos: world_loc,
upward, upward,
front, center,
} }
} }
@ -29,14 +29,6 @@ impl Camera {
self.pos = pos; 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 { pub fn get_upward(&self) -> Vec3 {
self.upward self.upward
} }
@ -46,8 +38,8 @@ impl Camera {
} }
pub fn get_view_matrix(&self) -> Mat4x4 { pub fn get_view_matrix(&self) -> Mat4x4 {
let l = self.pos + self.front; let l = self.center;
look_at(&l, &self.pos, &self.upward) look_at(&self.pos, &l, &self.upward)
} }
} }
@ -56,7 +48,7 @@ impl Default for Camera {
Self { Self {
pos: Vec3::new(0.0, 0.0, 0.0), pos: Vec3::new(0.0, 0.0, 0.0),
upward: Vec3::new(0.0, 1.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),
} }
} }
} }

View File

@ -3,7 +3,7 @@ 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::components::CodeComponent;
use crate::graphics::transforms::{viewport::Viewport, Transform}; use crate::graphics::transforms::viewport::Viewport;
#[derive(Debug)] #[derive(Debug)]
pub struct Program { pub struct Program {
@ -45,16 +45,19 @@ impl Program {
self.geometry.as_ref() self.geometry.as_ref()
} }
#[cfg(feature = "inparser")]
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)); self.geometry.as_mut().map(|g| g.set_hook(hook, code));
} }
#[cfg(feature = "inparser")]
pub fn set_transform<T: Transform>(&mut self, value: &T) { pub fn set_transform<T: Transform>(&mut self, value: &T) {
self.set_hook("transform", value.snippet()); self.set_hook("transform", value.snippet());
} }
#[cfg(feature = "inparser")]
pub fn set_viewport(&mut self, viewport: &Viewport) { pub fn set_viewport(&mut self, viewport: &Viewport) {
self.set_hook("viewport", viewport.snippet()); self.set_hook("viewport", viewport.snippet());
} }
@ -62,8 +65,11 @@ 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;
#[cfg(feature = "inparser")]
{
self.vertex.define("_GLUMPY__VERTEX_SHADER__"); self.vertex.define("_GLUMPY__VERTEX_SHADER__");
self.fragment.define("_GLUMPY__FRAGMENT_SHADER__"); self.fragment.define("_GLUMPY__FRAGMENT_SHADER__");
}
unsafe { unsafe {
let program = gl.create_program().map_err(|e| Error::InvalidProgram(e))?; let program = gl.create_program().map_err(|e| Error::InvalidProgram(e))?;
@ -76,6 +82,7 @@ impl Program {
// Geom Shader // Geom Shader
let geom_shader = if let Some(geometry) = self.geometry.as_mut() { let geom_shader = if let Some(geometry) = self.geometry.as_mut() {
#[cfg(feature = "inparser")]
geometry.define("_GLUMPY__GEOMETRY_SHADER__"); geometry.define("_GLUMPY__GEOMETRY_SHADER__");
let geometry_shader = geometry.compile(&self.version, gl); let geometry_shader = geometry.compile(&self.version, gl);
@ -138,13 +145,13 @@ mod test {
fn test_program() { fn test_program() {
let vertex = Shader::new( let vertex = Shader::new(
glow::VERTEX_SHADER, glow::VERTEX_SHADER,
CodeType::<&'static str>::Path("agg-fast-path.vert".into()), CodeType::from_path("agg-fast-path.vert"),
) )
.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::from_path("agg-fast-path.frag"),
) )
.unwrap(); .unwrap();

View File

@ -15,7 +15,10 @@ pub type ShaderType = u32;
#[derive(Debug)] #[derive(Debug)]
pub struct Shader { pub struct Shader {
target: u32, target: u32,
#[cfg(feature = "inparser")]
parsed: CodeBlock, parsed: CodeBlock,
parsed: String,
#[cfg(feature = "inparser")]
pub hooks: Vec<String>, pub hooks: Vec<String>,
} }
@ -26,25 +29,34 @@ 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(target: ShaderType, code: CodeType) -> Result<Self> {
let code = match code { let code = match code {
CodeType::Code(code) => code.borrow().to_string(), CodeType::Code(code) => code,
CodeType::Path(path) => { 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 code
} }
}; };
#[cfg(feature = "inparser")]
{
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)?;
let hooks = parsed.all_hooks().iter().map(|h| h.name.clone()).collect(); let hooks = parsed.all_hooks().iter().map(|h| h.name.clone()).collect();
info!("Shader:{} Hooks: {:?}", target, hooks); info!("Shader:{} Hooks: {:?}", target, hooks);
return Ok(Self {
Ok(Self {
target, target,
parsed, parsed,
hooks, hooks,
});
}
Ok(Self {
target,
parsed: code,
}) })
} }
@ -68,11 +80,13 @@ impl Shader {
shader shader
} }
#[cfg(feature = "inparser")]
pub fn define(&mut self, s: &str) { pub fn define(&mut self, s: &str) {
self.parsed self.parsed
.insert(Code::new(&format!("#define {}\n", s)), 0); .insert(Code::new(&format!("#define {}\n", s)), 0);
} }
#[cfg(feature = "inparser")]
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);
} }
@ -217,13 +231,8 @@ mod utils {
body.push_str("}\n\n"); body.push_str("}\n\n");
let input = header + &body; let input = header + &body;
let result = Snippet::new( let result =
"fetch_uniform", Snippet::new("fetch_uniform", CodeType::from_code(input), false, None).unwrap();
CodeType::<String>::Code(input),
false,
None,
)
.unwrap();
result result
} }
@ -237,7 +246,7 @@ mod test {
fn test_shader() { fn test_shader() {
let shader = Shader::new( let shader = Shader::new(
glow::VERTEX_SHADER, glow::VERTEX_SHADER,
CodeType::<&'static str>::Path("agg-fast-path.vert".into()), CodeType::from_path("agg-fast-path.vert"),
) )
.unwrap(); .unwrap();

View File

@ -3,7 +3,7 @@ use std::{
cell::{Ref, RefCell}, cell::{Ref, RefCell},
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
ops::Add, ops::Add,
path::Path, path::{Path, PathBuf},
rc::Rc, rc::Rc,
sync::atomic::{AtomicUsize, Ordering}, sync::atomic::{AtomicUsize, Ordering},
}; };
@ -11,6 +11,7 @@ pub use util::Variable;
use crate::{ use crate::{
errors::{Error, Result}, errors::{Error, Result},
shaders::{CodePiece, EmptyPiece},
utils::{find_file, Code, CodeBlock, Function, Hook, ShareVariable, SnippetCode}, utils::{find_file, Code, CodeBlock, Function, Hook, ShareVariable, SnippetCode},
}; };
mod util; mod util;
@ -27,9 +28,33 @@ pub enum InputType {
Other(Variable), Other(Variable),
} }
pub enum CodeType<S: std::borrow::Borrow<str> = &'static str, P: AsRef<Path> = &'static str> { // pub enum CodeType<
Code(S), // CP: CodePiece = EmptyPiece,
Path(P), // S: std::borrow::Borrow<str> = &'static str,
// P: AsRef<Path> = &'static str,
// > {
// Code(S),
// Path(P),
// CodePiece(CP),
// }
pub enum CodeType {
Code(String),
Path(PathBuf),
}
impl CodeType {
pub fn from_path<P: AsRef<Path>>(path: P) -> Self {
Self::Path(path.as_ref().to_path_buf())
}
pub fn from_code<S: std::borrow::Borrow<str>>(code: S) -> Self {
Self::Code(code.borrow().to_string())
}
pub fn from_piece<CP: CodePiece>(piece: CP) -> Self {
Self::Code(piece.to_string())
}
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -44,14 +69,14 @@ pub struct Snippet {
} }
impl Snippet { impl Snippet {
pub fn new<S: std::borrow::Borrow<str>, P: AsRef<Path>>( pub fn new(
name: &'static str, name: &'static str,
code: CodeType<S, P>, code: CodeType,
mangling: bool, mangling: bool,
main: Option<String>, main: Option<String>,
) -> Result<Self> { ) -> Result<Self> {
let code = match code { let code = match code {
CodeType::Code(code) => code.borrow().to_string(), CodeType::Code(code) => code,
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");
code code
@ -173,13 +198,7 @@ impl Add for Snippet {
let code = rhs.parsed.to_string(); let code = rhs.parsed.to_string();
raw_code.push_str(&code); raw_code.push_str(&code);
Snippet::new( Snippet::new(self.name, CodeType::from_code(raw_code), false, None).unwrap()
self.name,
CodeType::<std::string::String>::Code(raw_code),
false,
None,
)
.unwrap()
} }
} }
@ -207,11 +226,9 @@ mod tests {
} }
"#; "#;
let snippet = let snippet = Snippet::new("polar", CodeType::from_code(code), true, None).unwrap();
Snippet::new("polar", CodeType::<&'static str>::Code(code), true, None).unwrap();
let snippet2 = let snippet2 = Snippet::new("polar2", CodeType::from_code(code), true, None).unwrap();
Snippet::new("polar2", CodeType::<&'static str>::Code(code), true, None).unwrap();
let snippet3 = snippet.clone() + snippet2.clone(); let snippet3 = snippet.clone() + snippet2.clone();

View File

@ -170,7 +170,7 @@ impl Data {
}; };
use DataType::*; use DataType::*;
let valuetype = info.value_type.as_str(); let valuetype = info.value_name.as_str();
let data_type = block_data_type_prepare!(valuetype, let data_type = block_data_type_prepare!(valuetype,
"ET" => ET, "ET" => ET,

View File

@ -27,4 +27,7 @@ pub enum Error {
#[error("Invalid Font {0}")] #[error("Invalid Font {0}")]
FontError(String), FontError(String),
#[error("Invalid Setting {0}")]
SettingError(String),
} }

View File

@ -6,7 +6,6 @@ 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::*;
use crate::graphics::transforms::viewport::Viewport; use crate::graphics::transforms::viewport::Viewport;
use crate::graphics::transforms::Transform;
use crate::graphics::ty::Ty; use crate::graphics::ty::Ty;
use crate::graphics::{AttaWithBuffer, Config, Graphics}; use crate::graphics::{AttaWithBuffer, Config, Graphics};
@ -26,17 +25,17 @@ impl AggFastPath {
pub fn new() -> 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::from_path("agg-fast-path.vert"),
)?; )?;
let fragment = Shader::new( let fragment = Shader::new(
glow::FRAGMENT_SHADER, glow::FRAGMENT_SHADER,
CodeType::<String>::Path("agg-fast-path.frag".into()), CodeType::from_path("agg-fast-path.frag"),
)?; )?;
let input_snippet = Snippet::new( let input_snippet = Snippet::new(
"input", "input",
CodeType::<&'static str>::Code( CodeType::from_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;
@ -72,10 +71,12 @@ impl AggFastPath {
}) })
} }
#[cfg(feature = "inparser")]
pub fn set_transform<T: Transform>(&mut self, transform: &T) { pub fn set_transform<T: Transform>(&mut self, transform: &T) {
self.program.set_transform(transform); self.program.set_transform(transform);
} }
#[cfg(feature = "inparser")]
pub fn set_viewport(&mut self, viewport: &Viewport) { pub fn set_viewport(&mut self, viewport: &Viewport) {
self.program.set_viewport(viewport); self.program.set_viewport(viewport);
} }
@ -182,7 +183,6 @@ impl Graphics for AggFastPath {
fn draw(&self, gl: &glow::Context, count: i32) -> Result<()> { fn draw(&self, gl: &glow::Context, count: i32) -> Result<()> {
unsafe { unsafe {
gl.clear(glow::COLOR_BUFFER_BIT);
gl.bind_vertex_array(Some(self.vao.unwrap())); gl.bind_vertex_array(Some(self.vao.unwrap()));
gl.draw_elements( gl.draw_elements(
glow::TRIANGLES, glow::TRIANGLES,
@ -425,8 +425,6 @@ impl DerefMut for Path {
mod test { mod test {
use crate::graphics::transforms::{polar::Polar, position::Position, trackball::Trackball};
use super::*; use super::*;
#[test] #[test]

View File

@ -1,40 +1,37 @@
use glow::HasContext; use super::ColorMap;
use crate::components::{CodeType, Program, Snippet}; use crate::components::{CodeType, Program, Snippet};
use crate::errors::*; use crate::errors::*;
use crate::shaders::colormap::ColorMap as CmapPiece;
use super::ColorMap; use glow::HasContext;
pub struct LinearColormap { pub struct LinearColormap {
snippet: Snippet,
colors: Vec<[u8; 4]>, colors: Vec<[u8; 4]>,
color_changed: bool, color_changed: bool,
texture: Option<glow::NativeTexture>, texture: Option<glow::NativeTexture>,
pub unvalid: f32,
pub min: f32, pub min: f32,
pub max: f32, pub max: f32,
} }
impl LinearColormap { impl LinearColormap {
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
let snippet = Snippet::new(
"linear",
CodeType::<&'static str>::Path("colormap.glsl".into()),
true,
None,
)?;
Ok(Self { Ok(Self {
snippet,
colors: vec![], colors: vec![],
texture: None, texture: None,
color_changed: true, color_changed: true,
min: 0.0, min: 0.0,
max: 1.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]>) { pub fn set_colors(&mut self, colors: Vec<[u8; 4]>) {
self.colors = colors; self.colors = colors;
self.color_changed = true; self.color_changed = true;
@ -79,18 +76,14 @@ impl ColorMap for LinearColormap {
glow::NEAREST as i32, glow::NEAREST as i32,
); );
let name = self.snippet.find_symbol("conf").unwrap(); let location = program.get_uniform_location(gl, "colormap_conf");
let location = program.get_uniform_location(gl, &name);
// gl.uniform_2_f32(location.as_ref(), 0);
gl.uniform_4_f32( gl.uniform_4_f32(
location.as_ref(), location.as_ref(),
self.min, self.min,
self.max, self.max,
self.colors.len() as f32, self.colors.len() as f32,
125.0, self.unvalid,
); );
self.texture = Some(texture); self.texture = Some(texture);
} }
} }
@ -110,17 +103,12 @@ impl ColorMap for LinearColormap {
unsafe { unsafe {
gl.active_texture(glow::TEXTURE0); gl.active_texture(glow::TEXTURE0);
gl.bind_texture(glow::TEXTURE_1D, self.texture); gl.bind_texture(glow::TEXTURE_1D, self.texture);
let name = self.snippet.find_symbol("colormap").unwrap(); let location = program.get_uniform_location(gl, "colormap");
let location = program.get_uniform_location(gl, &name);
gl.uniform_1_i32(location.as_ref(), 0); gl.uniform_1_i32(location.as_ref(), 0);
} }
Ok(()) Ok(())
} }
fn snippet_ref(&self) -> &crate::components::Snippet {
&self.snippet
}
} }
mod test { mod test {

View File

@ -11,7 +11,5 @@ pub trait ColorMap {
fn bind_texture(&self, gl: &glow::Context, program: &Program) -> crate::errors::Result<()>; 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); fn destroy(&mut self, gl: &glow::Context);
} }

View File

@ -13,7 +13,7 @@ use crate::{
utils::resources::RcGlTexture, 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> { pub struct Text<'a> {
gl: &'a glow::Context, gl: &'a glow::Context,
font_manager: RefCell<FontManager>, font_manager: RefCell<FontManager>,
@ -153,13 +153,13 @@ impl<'a> Text<'a> {
pub fn new(gl: &'a glow::Context, font_manager: FontManager) -> Result<Self> { pub fn new(gl: &'a glow::Context, font_manager: FontManager) -> Result<Self> {
let vertex = Shader::new( let vertex = Shader::new(
glow::VERTEX_SHADER, 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"); let mut program = Program::new(vertex, fragment, None, "330 core");
#[cfg(feature = "inparser")]
program.set_transform(&transform); program.set_transform(&transform);
Ok(Self { Ok(Self {
@ -171,6 +171,7 @@ impl<'a> Text<'a> {
}) })
} }
#[cfg(feature = "inparser")]
pub fn set_viewport(&mut self, viewport: &Viewport) { pub fn set_viewport(&mut self, viewport: &Viewport) {
self.program.set_viewport(viewport); self.program.set_viewport(viewport);
} }

View File

@ -20,15 +20,8 @@ pub struct Hello {
impl Hello { impl Hello {
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
let vertex = Shader::new( let vertex = Shader::new(glow::VERTEX_SHADER, CodeType::from_path("hello.vert"))?;
glow::VERTEX_SHADER, let fragment = Shader::new(glow::FRAGMENT_SHADER, CodeType::from_path("hello.frag"))?;
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"); let program = Program::new(vertex, fragment, None, "330 core");
@ -284,8 +277,6 @@ impl DerefMut for Path {
mod test { mod test {
use crate::graphics::transforms::{polar::Polar, position::Position, trackball::Trackball};
use super::*; use super::*;
#[test] #[test]

View File

@ -9,7 +9,13 @@ pub mod tools;
pub mod transforms; pub mod transforms;
pub mod ty; 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 glow::{HasContext, NativeBuffer, NativeVertexArray};
use ppi::PPIConfig; use ppi::PPIConfig;
@ -113,11 +119,22 @@ pub enum Config {
config_for_everyitem!({PPIConfig => PPI},{FontConfig => Font}, ); config_for_everyitem!({PPIConfig => PPI},{FontConfig => Font}, );
pub trait AttachWithMouse { 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)] #[derive(Debug, Clone)]
pub enum MouseState { pub enum MouseState {
Drag { from: [f32; 2], delta: [f32; 2] }, Drag { from: [f32; 2], delta: [f32; 2] },
Wheel(f32),
None, None,
} }

View File

@ -1,92 +1,64 @@
use super::colormap::ColorMap; use super::colormap::ColorMap;
use super::threed::ThreeD;
use super::transforms::viewport::Viewport; use super::transforms::viewport::Viewport;
use super::{transforms, AttaWithBuffer, AttaWithProgram, AttachWithMouse, Config, Graphics}; use super::{transforms, AttaWithBuffer, AttaWithProgram, AttachWithMouse, Config, Graphics};
use crate::components::{CodeType, Program, Shader}; use crate::components::{CodeType, Program, Shader};
use crate::data_loader::{CoordType, Data, DataType}; use crate::data_loader::{CoordType, Data, DataType};
use crate::errors::*; use crate::errors::*;
use crate::graphics::colormap::linear::LinearColormap; use crate::graphics::colormap::linear::LinearColormap;
use crate::graphics::transforms::Transform;
use glow::{HasContext, NativeBuffer, NativeVertexArray}; use glow::{HasContext, NativeBuffer, NativeVertexArray};
pub struct PPI { pub struct PPI {
program: Program, program: Program,
cmap: Option<Box<dyn ColorMap>>, cmap: LinearColormap,
} }
impl PPI { impl PPI {
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
let vertex = Shader::new( use crate::shaders::ppi::*;
glow::VERTEX_SHADER, let vertex = Shader::new(glow::VERTEX_SHADER, CodeType::from_piece(PPIVertex::new()))?;
CodeType::<String>::Path("ppi.vert".into()), let geom = Shader::new(glow::GEOMETRY_SHADER, CodeType::from_piece(PPIGeom::new()))?;
)?;
let geom = Shader::new(
glow::GEOMETRY_SHADER,
CodeType::<String>::Path("ppi.geom".into()),
)?;
let fragment = Shader::new( let fragment = Shader::new(
glow::FRAGMENT_SHADER, glow::FRAGMENT_SHADER,
CodeType::<String>::Path("ppi.frag".into()), CodeType::from_piece(PPIFragment::new()),
)?; )?;
let mut cmap = LinearColormap::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"); let mut program = Program::new(vertex, fragment, Some(geom), "330 core");
program.set_transform(&transform);
program.set_hook("colormap", cmap.snippet_ref());
Ok(Self { Ok(Self { program, cmap })
program,
cmap: Some(Box::new(cmap)),
})
}
pub fn set_viewport(&mut self, viewport: &Viewport) {
self.program.set_viewport(viewport);
} }
pub fn program(&mut self) -> &mut Program { pub fn program(&mut self) -> &mut Program {
&mut self.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"); 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 { 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<f32>, i32)> { pub fn data_info(&self, data: &Data) -> Result<(f32, f32, DataType, usize, f32)> {
// }
pub fn data_info(&self, data: &Data) -> Result<(f32, f32, DataType)> {
let first_block = data.blocks.get(0).unwrap(); let first_block = data.blocks.get(0).unwrap();
if let CoordType::Polar { if let CoordType::Polar {
azimuth, azimuth,
r, r,
r_range, r_range,
elevation,
.. ..
} = &first_block.coord_type } = &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)); sorted_azimuth.sort_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Greater));
let azi_step = max_step(&sorted_azimuth); let azi_step = max_step(&sorted_azimuth);
let r_step = min_step(r) / (r_range[1]) as f32; 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 { } else {
return Err(Error::InvalidDataType); return Err(Error::InvalidDataType);
} }
} }
fn init(&mut self, gl: &glow::Context, config: &PPIConfig) { fn init(&mut self, gl: &glow::Context, config: &PPIConfig) {
self.cmap self.set_conf(gl, config);
.as_mut() self.cmap.attach_with_program(gl, &self.program).unwrap();
.unwrap()
.attach_with_program(gl, &self.program)
.unwrap();
let origin = self.program.get_uniform_location(gl, "polar_origin"); 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 { unsafe {
gl.uniform_1_f32(origin.as_ref(), 90.0f32.to_radians()); 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<()> { fn draw(&self, gl: &glow::Context, count: i32) -> Result<()> {
unsafe { unsafe {
gl.clear(glow::COLOR_BUFFER_BIT); self.cmap.bind_texture(gl, &self.program)?;
self.cmap
.as_ref()
.unwrap()
.bind_texture(gl, &self.program)?;
gl.draw_arrays(glow::POINTS, 0, count); gl.draw_arrays(glow::POINTS, 0, count);
} }
Ok(()) Ok(())
@ -215,6 +183,7 @@ impl AttaWithBuffer for PPI {
if let CoordType::Polar { if let CoordType::Polar {
r_range, r_range,
azimuth, azimuth,
elevation,
r, r,
.. ..
} = &first_block.coord_type } = &first_block.coord_type
@ -223,13 +192,15 @@ impl AttaWithBuffer for PPI {
let r_len = r.len(); let r_len = r.len();
let mut vertices = Vec::with_capacity(azimuth_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 azi_idx in 0..azimuth_len {
for r_idx in 0..r_len { for r_idx in 0..r_len {
let azi = azimuth.get(azi_idx).unwrap(); 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() / r_range[1] as f32;
// let r = *r.get(r_idx).unwrap();
let dt = first_block_data.get([layer, azi_idx, 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; let len = vertices.len() as i32 / 3;
@ -246,7 +217,7 @@ impl AttaWithBuffer for PPI {
let vbo = gl.create_buffer().unwrap(); let vbo = gl.create_buffer().unwrap();
gl.bind_buffer(glow::ARRAY_BUFFER, Some(vbo)); gl.bind_buffer(glow::ARRAY_BUFFER, Some(vbo));
gl.enable_vertex_attrib_array(0); 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); gl.bind_vertex_array(None);
(vao, vbo, None) (vao, vbo, None)
@ -256,9 +227,13 @@ impl AttaWithBuffer for PPI {
#[derive(Default, Clone, Debug)] #[derive(Default, Clone, Debug)]
pub struct PPIConfig { pub struct PPIConfig {
pub unvalid_value: f32,
pub layer: usize, pub layer: usize,
pub colors: Vec<[u8; 4]>,
pub color_range: [f32; 2],
pub rdpi: f32, pub rdpi: f32,
pub adpi: f32, pub adpi: f32,
pub three_d: bool,
} }
mod test { mod test {

View File

@ -1,138 +1,75 @@
use std::rc::Rc; use std::rc::Rc;
use tracker::track;
use super::transforms::Transform; use super::transforms::{position::Position, trackball::TrackballModel};
use super::transforms::{position::Position, trackball::Trackball, ChainedTransform};
use super::{AttaWithProgram, AttachWithMouse}; use super::{AttaWithProgram, AttachWithMouse};
use crate::camera::Camera; use crate::camera::{self, Camera};
use crate::errors::*; use crate::errors::*;
use crate::ui::operation::Projection;
use glow::HasContext; use glow::HasContext;
use nalgebra_glm::Vec3; use nalgebra_glm::{Mat4, Vec3};
#[derive(Clone)] #[derive(Clone)]
pub struct ThreeD { pub struct Trackball {
transform: Rc<ChainedTransform>, trackball: TrackballModel,
projection: nalgebra_glm::Mat4,
trackball: Trackball,
camera: Camera,
} }
impl ThreeD { impl Trackball {
pub fn new(aspect: f32, z_near: f32, z_far: f32, fov: f32) -> Result<Self> { pub fn new(aspect: f32, z_near: f32, z_far: f32, fov: f32) -> Result<Self> {
let trackball = Trackball::new()?; let trackball = TrackballModel::new(0.0, 90.0);
let transform = ChainedTransform::from(&trackball).chain(&Position::new()?);
let camera = Camera::new( Ok(Self { trackball })
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);
} }
} }
impl Default for ThreeD { impl Default for Trackball {
fn default() -> Self { fn default() -> Self {
Self::new(16.0 / 9.0, 0.1, 1000.0, 45.0).unwrap() 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( fn attach_with_program(
&self, &self,
gl: &glow::Context, gl: &glow::Context,
program: &crate::components::Program, program: &crate::components::Program,
) -> Result<()> { ) -> Result<()> {
unsafe { self.trackball.attach_with_program(gl, program);
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());
}
Ok(()) Ok(())
} }
} }
impl Transform for ThreeD { impl AttachWithMouse for Trackball {
fn snippet(&self) -> &crate::components::Snippet { type State = super::MouseState;
self.transform.snippet() 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,
}
} }
}
impl AttachWithMouse for ThreeD { fn reset(&mut self) {
fn attach_with_mouse(&mut self, state: &super::MouseState) { self.trackball.set_phi(90.0);
if let super::MouseState::Drag { from, delta } = state { self.trackball.set_theta(0.0);
self.trackball
.on_mouse_drag(from[0], from[1], delta[0], delta[1]);
} }
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),
)
} }
} }

View File

@ -6,59 +6,56 @@ use crate::components::{Program, Snippet};
use super::AttaWithProgram; use super::AttaWithProgram;
pub struct ChainedTransform { // pub struct ChainedTransform {
snippet: Snippet, // snippet: Snippet,
chain: Vec<Box<dyn Transform>>, // chain: Vec<Box<dyn Transform>>,
} // }
impl ChainedTransform { // impl ChainedTransform {
pub fn from<T: Transform + Clone + 'static>(transform: &T) -> Self { // pub fn from<T: Transform + Clone + 'static>(transform: &T) -> Self {
let snippet = transform.snippet().clone(); // let snippet = transform.snippet().clone();
// let snippet = transform.snippet().to_owned(); // // let snippet = transform.snippet().to_owned();
Self { // Self {
snippet, // snippet,
chain: vec![Box::new(transform.clone())], // chain: vec![Box::new(transform.clone())],
} // }
} // }
pub fn chain<P: Transform + 'static + Clone>(mut self, other: &P) -> Self { // pub fn chain<P: Transform + 'static + Clone>(mut self, other: &P) -> Self {
let new_snippet = self.snippet.clone().chain(other.snippet().to_owned()); // let new_snippet = self.snippet.clone().chain(other.snippet().to_owned());
self.snippet = new_snippet; // self.snippet = new_snippet;
self.chain.push(Box::new(other.clone())); // self.chain.push(Box::new(other.clone()));
self // self
} // }
} // }
impl Transform for ChainedTransform { // impl Transform for ChainedTransform {
fn snippet(&self) -> &Snippet { // fn snippet(&self) -> &Snippet {
&self.snippet // &self.snippet
} // }
} // }
impl AttaWithProgram for ChainedTransform { // impl AttaWithProgram for ChainedTransform {
fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> super::Result<()> { // fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> super::Result<()> {
for transform in &self.chain { // for transform in &self.chain {
transform.attach_with_program(gl, program)?; // transform.attach_with_program(gl, program)?;
} // }
Ok(()) // Ok(())
} // }
} // }
pub trait Transform: AttaWithProgram {
fn snippet(&self) -> &Snippet;
}
mod test { // mod test {
use super::*; // use super::*;
#[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 chained = ChainedTransform::from(polar).chain(trackball); // // let chained = ChainedTransform::from(polar).chain(trackball);
// println!("{}", chained.snippet().prepare_code()); // // println!("{}", chained.snippet().prepare_code());
// println!("{}", chained.snippet().call(&vec![]).unwrap()); // // println!("{}", chained.snippet().call(&vec![]).unwrap());
} // }
} // }

View File

@ -4,8 +4,6 @@ use crate::{
graphics::AttaWithProgram, graphics::AttaWithProgram,
}; };
use super::Transform;
pub struct Polar { pub struct Polar {
snippet: Snippet, snippet: Snippet,
origin: f32, origin: f32,
@ -15,7 +13,7 @@ impl Polar {
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
let snippets = Snippet::new( let snippets = Snippet::new(
"polar", "polar",
CodeType::<&'static str>::Path("transform/polar.glsl".into()), CodeType::from_path("transform/polar.glsl"),
true, true,
Some("forward".to_string()), Some("forward".to_string()),
)?; )?;
@ -27,12 +25,6 @@ impl Polar {
} }
} }
impl Transform for Polar {
fn snippet(&self) -> &Snippet {
&self.snippet
}
}
impl AttaWithProgram for Polar { impl AttaWithProgram for Polar {
fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> Result<()> { fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> Result<()> {
Ok(()) Ok(())

View File

@ -1,4 +1,3 @@
use super::Transform;
use crate::{ use crate::{
components::{CodeType, Program, Snippet}, components::{CodeType, Program, Snippet},
errors::*, errors::*,
@ -13,7 +12,7 @@ impl Position {
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
let snippets = Snippet::new( let snippets = Snippet::new(
"position", "position",
CodeType::<&'static str>::Path("transform/position.glsl".into()), CodeType::from_path("transform/position.glsl"),
false, false,
None, None,
)?; )?;
@ -22,12 +21,6 @@ impl Position {
} }
} }
impl Transform for Position {
fn snippet(&self) -> &Snippet {
&self.snippet
}
}
impl AttaWithProgram for Position { impl AttaWithProgram for Position {
fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> Result<()> { fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> Result<()> {
Ok(()) Ok(())

View File

@ -2,8 +2,6 @@ use crate::components::{CodeType, Program, Snippet};
use crate::errors::Result; use crate::errors::Result;
use crate::graphics::AttaWithProgram; use crate::graphics::AttaWithProgram;
use super::Transform;
use glow::HasContext; use glow::HasContext;
use nalgebra::{Matrix4, Quaternion, Translation3, Unit, UnitQuaternion, Vector3}; use nalgebra::{Matrix4, Quaternion, Translation3, Unit, UnitQuaternion, Vector3};
@ -27,7 +25,7 @@ impl TrackballModel {
count: 0, count: 0,
model: Matrix4::identity(), model: Matrix4::identity(),
renorm_count: 97, renorm_count: 97,
trackball_size: 0.8, trackball_size: 100.0,
x: 0.0, x: 0.0,
y: 0.0, y: 0.0,
theta, theta,
@ -37,7 +35,7 @@ impl TrackballModel {
trackball 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); let q = self.rotate(x, y, dx, dy);
self.rotation *= q; self.rotation *= q;
self.count += 1; self.count += 1;
@ -56,7 +54,7 @@ impl TrackballModel {
self.theta 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); self.set_orientation(theta % 360.0, self.phi % 360.0);
} }
@ -64,7 +62,7 @@ impl TrackballModel {
self.phi 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); self.set_orientation(self.theta % 360.0, phi % 360.0);
} }
@ -83,12 +81,12 @@ impl TrackballModel {
self.theta = theta; self.theta = theta;
self.phi = phi; 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 sine = (0.5 * angle).sin();
let xrot = let xrot =
UnitQuaternion::from_quaternion(Quaternion::new((0.5 * angle).cos(), sine, 0.0, 0.0)); 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 sine = (0.5 * angle).sin();
let zrot = let zrot =
UnitQuaternion::from_quaternion(Quaternion::new((0.5 * angle).cos(), 0.0, 0.0, sine)); UnitQuaternion::from_quaternion(Quaternion::new((0.5 * angle).cos(), 0.0, 0.0, sine));
@ -129,49 +127,27 @@ impl TrackballModel {
} }
} }
#[derive(Debug, Clone)] // impl Trackball {
pub struct Trackball { // pub fn new() -> Result<Self> {
snippet: Snippet, // let model = TrackballModel::new(0.0, 0.0);
model: TrackballModel,
}
impl Trackball { // Ok(Self { model })
pub fn new() -> Result<Self> { // }
let snippets = Snippet::new(
"trackball",
CodeType::<&'static str>::Path("transform/trackball.glsl".into()),
false,
None,
)?;
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 { // pub fn model(&self) -> &Matrix4<f32> {
snippet: snippets, // self.model.model()
model, // }
}) // }
}
pub fn on_mouse_drag(&mut self, x: f32, y: f32, dx: f32, dy: f32) { impl AttaWithProgram for TrackballModel {
self.model.drag_to(x, y, dx, dy);
}
pub fn model(&self) -> &Matrix4<f32> {
self.model.model()
}
}
impl Transform for Trackball {
fn snippet(&self) -> &Snippet {
&self.snippet
}
}
impl AttaWithProgram for Trackball {
fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> Result<()> { fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> Result<()> {
unsafe { unsafe {
let l = program.get_uniform_location(gl, "trackball_model"); 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(()) Ok(())
@ -183,6 +159,12 @@ mod test {
#[test] #[test]
fn test_trackball() { 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(); // let trackball = Trackball::new().unwrap();
// println!("{}", trackball.snippet); // println!("{}", trackball.snippet);
} }

View File

@ -16,7 +16,7 @@ impl Viewport {
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
let snippets = Snippet::new( let snippets = Snippet::new(
"viewport", "viewport",
CodeType::<&'static str>::Path("transform/viewport.glsl".into()), CodeType::from_path("transform/viewport.glsl"),
true, true,
None, None,
)?; )?;

View File

@ -1,3 +1,4 @@
#![feature(proc_macro_hygiene)]
#![allow(unused)] #![allow(unused)]
mod camera; mod camera;
mod components; mod components;
@ -6,6 +7,8 @@ mod errors;
mod font_manager; mod font_manager;
mod graphics; mod graphics;
mod pg; mod pg;
mod setting;
mod shaders;
mod support; mod support;
mod ui; mod ui;
mod utils; mod utils;
@ -13,6 +16,9 @@ mod utils;
use pg::App; use pg::App;
use support::supporter::run; use support::supporter::run;
use once_cell::sync::Lazy;
static SETTING: Lazy<setting::Setting> = Lazy::new(|| setting::Setting::new());
fn main() { fn main() {
env_logger::init(); env_logger::init();
run(move |gl| App::new(gl).unwrap()); run(move |gl| App::new(gl).unwrap());

View File

@ -5,7 +5,7 @@ use crate::{
data_loader::Data, data_loader::Data,
errors::*, errors::*,
graphics::{ graphics::{
colormap::linear::LinearColormap, ppi::PPI, threed::ThreeD, AttaWithBuffer, colormap::linear::LinearColormap, ppi::PPI, threed::Trackball, AttaWithBuffer,
AttaWithProgram, Graphics, AttaWithProgram, Graphics,
}, },
ui::{State, GUI}, ui::{State, GUI},
@ -20,7 +20,7 @@ use crate::{
use glow::HasContext; use glow::HasContext;
use imgui::Ui; use imgui::Ui;
use super::app_type::{self, AppType}; use super::layout_type::{self, Layout};
use super::{ModulePackage, Programs}; use super::{ModulePackage, Programs};
use crate::{font_manager::FontManager, graphics::font::Text}; use crate::{font_manager::FontManager, graphics::font::Text};
@ -28,30 +28,24 @@ pub struct App<'gl> {
gl: &'gl GL, gl: &'gl GL,
context: Context<'gl>, context: Context<'gl>,
gui: GUI, gui: GUI,
app_type: AppType<'gl>, layout: Layout<'gl>,
} }
impl<'gl> App<'gl> { impl<'gl> App<'gl> {
pub fn new(gl: &'gl GL) -> Result<Self> { pub fn new(gl: &'gl GL) -> Result<Self> {
let programs = Programs::new(gl).unwrap(); let programs = Programs::new(gl).unwrap();
let mut default_state = State::default(); let mut default_state = State::default();
let mut gui = GUI::new(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); let context = Context::new(gl, Cache::new(), programs);
Ok(Self { Ok(Self {
gui, gui,
gl, gl,
context, context,
app_type, layout,
}) })
} }
pub fn init<'a>(&'a mut self) -> AppType {
self.gui.apptype(&self.gl)
}
pub fn prepare(&mut self) { pub fn prepare(&mut self) {
if let Err(e) = self.context.programs.prepare() { if let Err(e) = self.context.programs.prepare() {
error!("prepare failed: {:?}", e); error!("prepare failed: {:?}", e);
@ -67,13 +61,13 @@ impl<'gl> App<'gl> {
} }
pub fn render<'a>(&'a mut self) { 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); error!("draw_program failed: {:?}", e);
} }
} }
pub fn render_ui<'a>(&'a mut self, ui: &Ui, window: &winit::window::Window, run: &mut bool) { 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) { pub fn destroy(&mut self) {

View File

@ -1,28 +1,70 @@
use crate::errors::*;
use crate::graphics::ty; use crate::graphics::ty;
use crate::pg::{Context, ModulePackage}; 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::utils::resources::{ManagedResource, RcGlRcFramebuffer, RcGlRcRenderbuffer, GL};
use crate::{errors::*, main};
use glow::HasContext; use glow::HasContext;
const RBO_WIDTH: i32 = 1920; const RBO_WIDTH: i32 = 1920;
const RBO_HEIGHT: i32 = 1080; 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 { pub struct ViewPort {
renderer_size: [f32; 2], renderer_size: [f32; 2],
main_fbo: RcGlRcFramebuffer, main_fbo: RcGlRcFramebuffer,
_main_rbo: RcGlRcRenderbuffer, _main_rbo: RcGlRcRenderbuffer,
_main_depth_rbo: RcGlRcRenderbuffer,
} }
impl ViewPort { impl ViewPort {
pub fn new(gl: &GL) -> Self { pub fn new(gl: &GL) -> Self {
let main_fbo: RcGlRcFramebuffer = gl.create_resource_rc(); let main_fbo: RcGlRcFramebuffer = gl.create_resource_rc();
let main_rbo: RcGlRcRenderbuffer = 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_fbo.bind(glow::FRAMEBUFFER);
main_rbo.bind(glow::RENDERBUFFER);
unsafe { unsafe {
// Color Attachment
main_rbo.bind(glow::RENDERBUFFER);
gl.renderbuffer_storage(glow::RENDERBUFFER, glow::RGBA8, RBO_WIDTH, RBO_HEIGHT); gl.renderbuffer_storage(glow::RENDERBUFFER, glow::RGBA8, RBO_WIDTH, RBO_HEIGHT);
gl.framebuffer_renderbuffer( gl.framebuffer_renderbuffer(
glow::FRAMEBUFFER, glow::FRAMEBUFFER,
@ -30,12 +72,33 @@ impl ViewPort {
glow::RENDERBUFFER, glow::RENDERBUFFER,
Some(main_rbo.native()), 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_color(1.0, 0.0, 0.0, 1.0);
// gl.clear(glow::COLOR_BUFFER_BIT); // gl.clear(glow::COLOR_BUFFER_BIT);
// 检查帧缓冲是否完整 // 检查帧缓冲是否完整
if gl.check_framebuffer_status(glow::FRAMEBUFFER) != glow::FRAMEBUFFER_COMPLETE { if gl.check_framebuffer_status(glow::FRAMEBUFFER) != glow::FRAMEBUFFER_COMPLETE {
panic!("Framebuffer is not complete!"); panic!("Framebuffer is not complete!");
} }
gl.enable(glow::DEPTH_TEST);
} }
main_fbo.unbind(glow::FRAMEBUFFER); main_fbo.unbind(glow::FRAMEBUFFER);
@ -43,6 +106,7 @@ impl ViewPort {
renderer_size: [0.0, 0.0], renderer_size: [0.0, 0.0],
main_fbo, main_fbo,
_main_rbo: main_rbo, _main_rbo: main_rbo,
_main_depth_rbo: main_depth_rbo,
} }
} }
@ -76,70 +140,6 @@ impl ViewPort {
} }
} }
macro_rules! app_type_into { impl_layout!(
($({$t: ty => $b:tt},)+) => { {MainLoad => MainLoadAttach<'gl>},
$( );
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 => {}
}
}
}

View File

@ -1,17 +1,23 @@
mod app; mod app;
pub mod app_type; use glow::HasContext;
pub mod layout_type;
mod modules; mod modules;
use crate::font_manager::FontManager; use crate::font_manager::FontManager;
use crate::graphics::font::Text; use crate::graphics::font::Text;
use crate::graphics::ppi::PPI; use crate::graphics::ppi::PPI;
use crate::graphics::threed::ThreeD; use crate::graphics::threed::Trackball;
use crate::ui::typ::LayoutAppType; use crate::graphics::{AttaWithProgram, AttachWithMouse};
use crate::ui::operation::Operation;
use crate::ui::typ::LayoutAttach;
use crate::utils::cache::CachedData; use crate::utils::cache::CachedData;
use crate::utils::resources::GL; use crate::utils::resources::GL;
use crate::{errors::*, graphics::Graphics}; use crate::{errors::*, graphics::Graphics};
pub use app::{App, Context}; pub use app::{App, Context};
pub use modules::{Module, ModuleCursor, ModuleData, PPIModule, PPIPackage}; 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> { pub(super) struct Programs<'gl> {
gl: &'gl GL, gl: &'gl GL,
@ -69,26 +75,18 @@ impl<'gl> Programs<'gl> {
pub fn draw_modules( pub fn draw_modules(
&mut self, &mut self,
modules: &mut ModulePackage<'gl>, modules: &mut ModulePackage<'gl>,
init_info: &ThreeD, operation: &Operation<Trackball>,
) -> Result<()> { ) -> Result<()> {
// if !modules.need_update {
// return Ok(());
// }
match &mut modules.modules { match &mut modules.modules {
_ModulePackage::PPI(ppi) => { _ModulePackage::PPI(ppi) => {
self.ppi().start(); self.ppi().start();
self.ppi().init(init_info); self.ppi().render(ppi, operation)?;
self.ppi().render(ppi)?;
self.ppi().end(); self.ppi().end();
} }
} }
modules.need_update = false; modules.need_update = false;
Ok(()) Ok(())
} }
pub fn draw<M: LayoutAppType<'gl>>(&mut self, ty: &mut M) -> Result<()> {
ty.draw_program(self.gl, self)
}
} }
pub enum Data<'a> { pub enum Data<'a> {
@ -119,8 +117,6 @@ macro_rules! impl_module_package {
_ModulePackage::$b(t) _ModulePackage::$b(t)
} }
} }
)+ )+
}; };
} }
@ -130,7 +126,8 @@ impl_module_data!({
}); });
pub struct ModulePackage<'gl> { pub struct ModulePackage<'gl> {
need_update: bool, id: usize,
pub need_update: bool,
modules: _ModulePackage<'gl>, modules: _ModulePackage<'gl>,
} }
@ -148,19 +145,27 @@ where
{ {
fn from(t: T) -> Self { fn from(t: T) -> Self {
Self { Self {
id: MODULE_PACKAGE_ID.fetch_add(1, std::sync::atomic::Ordering::SeqCst),
modules: t.into(), modules: t.into(),
need_update: true, need_update: true,
} }
} }
} }
impl ModulePackage<'_> { impl PartialEq for ModulePackage<'_> {
pub fn ui_build(&mut self, ui: &imgui::Ui) -> Result<()> { fn eq(&self, other: &Self) -> bool {
match &mut self.modules { self.id == other.id
_ModulePackage::PPI(ppi) => { }
ppi.ui_build(ui); }
}
} impl ModulePackage<'_> {
Ok(()) pub fn ui_build(&mut self, ui: &imgui::Ui) -> Result<bool> {
Ok(match &mut self.modules {
_ModulePackage::PPI(ppi) => ppi.ui_build(ui),
})
}
pub fn dirty(&mut self) {
self.need_update = true;
} }
} }

View File

@ -1,6 +1,13 @@
use crate::utils::{ use crate::{
graphics::AttachWithMouse,
ui::{
operation::{self, Operation},
typ::CameraOP,
},
utils::{
cache::CachedData, cache::CachedData,
resources::{ManagedResource, RcGlBuffer, RcGlVertexArray}, resources::{ManagedResource, RcGlBuffer, RcGlVertexArray},
},
}; };
use glow::{HasContext, NativeBuffer, NativeVertexArray}; use glow::{HasContext, NativeBuffer, NativeVertexArray};
mod ppi; mod ppi;
@ -63,14 +70,18 @@ impl<'a> Attach<'a> {
pub trait Module: Sized { pub trait Module: Sized {
type Cursor: ModuleCursor; type Cursor: ModuleCursor;
type Data; 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<Self::Operation>,
) -> Result<()>;
fn resize(&self, size: [f32; 2]); fn resize(&self, size: [f32; 2]);
fn destroy(&self); fn destroy(&self);
fn start(&mut self); fn start(&mut self);
fn init(&mut self, info: &Self::InitInfo) -> Result<()>; // fn init(&mut self, info: &Operation<Self::Operation>) -> Result<()>;
fn end(&mut self); fn end(&mut self);
fn load_data<'dt>(&self, data: &CachedData<Self::Data>) -> Result<Self::Cursor>; fn load_data<'dt>(&self, data: &CachedData<Self::Data>) -> Result<Self::Cursor>;
} }
@ -88,5 +99,5 @@ pub trait ModuleCursor {
where where
F: FnOnce(&mut Self::Config); F: FnOnce(&mut Self::Config);
fn ui_build(&mut self, ui: &imgui::Ui); fn ui_build(&mut self, ui: &imgui::Ui) -> bool;
} }

View File

@ -1,6 +1,9 @@
use std::rc::Rc; use std::rc::Rc;
use tracker::track; use tracker::track;
use crate::graphics::{font::Text, *};
use crate::ui::operation::{self, Operation};
use crate::SETTING;
use crate::{ use crate::{
data_loader::Data, data_loader::Data,
errors::*, errors::*,
@ -10,9 +13,7 @@ use crate::{
}; };
use imgui::VerticalSlider; use imgui::VerticalSlider;
use ppi::{PPIConfig, PPI}; use ppi::{PPIConfig, PPI};
use threed::ThreeD; use threed::Trackball;
use crate::graphics::{font::Text, *};
use super::{Attach, Module, ModuleCursor}; use super::{Attach, Module, ModuleCursor};
pub struct PPIModule<'b, 'a: 'b> { 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( let (vbo, ebo, len) = self.ppi_program.bake(
data, data,
&PPIConfig { &PPIConfig {
unvalid_value: config.unvalid_value,
color_range: config.color_range,
colors: config.colors.clone(),
layer: config.layer, layer: config.layer,
rdpi: config.rdpi, rdpi: config.rdpi,
adpi: config.adpi, adpi: config.adpi,
three_d: config.is_three_d,
}, },
)?; )?;
attach.bind_data(&vbo, ebo.as_ref(), len); 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> { impl<'b, 'a: 'b> Module for PPIModule<'b, 'a> {
type Cursor = PPIPackage<'a>; type Cursor = PPIPackage<'a>;
type Data = Data; type Data = Data;
type InitInfo = ThreeD; type Operation = Trackball;
fn start(&mut self) { fn start(&mut self) {
self.ppi_program.mount(&self.gl).unwrap(); 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(); 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<Self::Operation>,
) -> Result<()> {
operation.attach_with_program(&self.gl, self.ppi_program.program());
let attach = &mut cursor.ppi_attach; let attach = &mut cursor.ppi_attach;
let data = &cursor.ppi_data.borrow(); let data = &cursor.ppi_data.borrow();
let config = &mut cursor.ppi_config; let config = &mut cursor.ppi_config;
self.ppi_program.set_config( self.ppi_program.set_config(
&self.gl, &self.gl,
&PPIConfig { &PPIConfig {
unvalid_value: config.unvalid_value,
color_range: config.color_range,
colors: config.colors.clone(),
layer: config.layer, layer: config.layer,
rdpi: config.rdpi, rdpi: config.rdpi,
adpi: config.adpi, 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 (vao, vbo, ebo) = self.ppi_program.init(&self.gl);
let mut attach = Attach::new(&self.gl, vao, vbo, ebo, None); 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 { let config = PPIModuleConfig {
color_range: cmap.value_range(),
colors: cmap.color()?,
layer: 0, layer: 0,
rdpi: r, rdpi: r,
adpi: a, adpi: a,
max_layer,
unvalid_value: unvalid,
is_three_d: true,
tracker: 0, tracker: 0,
}; };
@ -104,16 +133,19 @@ impl<'b, 'a: 'b> Module for PPIModule<'b, 'a> {
Ok(PPIPackage::new(config, attach, data)) 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] #[track]
#[derive(PartialEq)]
pub struct PPIModuleConfig { pub struct PPIModuleConfig {
pub layer: usize, 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] #[do_not_track]
pub rdpi: f32, pub rdpi: f32,
#[do_not_track] #[do_not_track]
@ -148,12 +180,17 @@ impl<'gl> ModuleCursor for PPIPackage<'gl> {
f(&mut self.ppi_config); 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 layer = self.ppi_config.layer;
let mut is_three_d = self.ppi_config.is_three_d;
ui.text("PPI Data Config"); 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(); ui.separator();
self.ppi_config.set_layer(layer); self.ppi_config.set_layer(layer);
self.ppi_config.set_is_three_d(is_three_d);
self.ppi_config.changed_any()
} }
} }

101
src/setting.rs Normal file
View File

@ -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<CB>,
}
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<String>,
pub levels: Vec<f32>,
}
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<Vec<[u8; 4]>> {
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::<std::result::Result<Vec<_>, 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)
}
}

50
src/shaders/colormap.rs Normal file
View File

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

73
src/shaders/math.rs Normal file
View File

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

97
src/shaders/mod.rs Normal file
View File

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

58
src/shaders/polar.rs Normal file
View File

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

147
src/shaders/ppi.rs Normal file
View File

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

30
src/shaders/trackball.rs Normal file
View File

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

View File

@ -1,4 +1,4 @@
use crate::{pg::App, utils::resources::GL}; use crate::{graphics::font, pg::App, utils::resources::GL};
use glow::HasContext; use glow::HasContext;
use glutin::{ use glutin::{
@ -7,6 +7,7 @@ use glutin::{
display::{GetGlDisplay, GlDisplay}, display::{GetGlDisplay, GlDisplay},
surface::{GlSurface, Surface, SurfaceAttributesBuilder, WindowSurface}, surface::{GlSurface, Surface, SurfaceAttributesBuilder, WindowSurface},
}; };
use imgui::FontConfig;
use imgui_winit_support::{ use imgui_winit_support::{
winit::{ winit::{
dpi::LogicalSize, 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); 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 imgui_context
.fonts() .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()); println!("imgui global scale: {}", winit_platform.hidpi_factor());

View File

@ -23,14 +23,21 @@ impl IO {
let io = ui.io(); let io = ui.io();
let delta = if ui.is_mouse_dragging(imgui::MouseButton::Left) { 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 { } else {
None None
}; };
let windows_position = ui.window_pos();
IO { IO {
mouse: MouseIO { mouse: MouseIO {
position: io.mouse_pos, position: [
io.mouse_pos[0] - windows_position[0],
io.mouse_pos[1] - windows_position[1],
],
drag_delta: delta, drag_delta: delta,
is_dragging: ui.is_mouse_dragging(imgui::MouseButton::Left), is_dragging: ui.is_mouse_dragging(imgui::MouseButton::Left),
left_button_pressed: io.mouse_down[0], left_button_pressed: io.mouse_down[0],

View File

@ -4,7 +4,7 @@ use log::*;
use crate::data_loader::Data; use crate::data_loader::Data;
use crate::errors::*; use crate::errors::*;
use crate::pg::app_type::AppType; use crate::pg::layout_type::Layout;
use crate::pg::{ModulePackage, Programs}; use crate::pg::{ModulePackage, Programs};
use crate::utils::cache::Cache; use crate::utils::cache::Cache;
use crate::utils::resources::{RcGlRcFramebuffer, RcGlRcRenderbuffer, RcGlRcResource, GL}; use crate::utils::resources::{RcGlRcFramebuffer, RcGlRcRenderbuffer, RcGlRcResource, GL};
@ -18,10 +18,11 @@ mod state;
pub mod typ; pub mod typ;
pub use layout::*; pub use layout::*;
pub use state::State; pub use state::State;
pub mod operation;
pub struct GUI { pub struct GUI {
state: State, state: State,
layout: layout::Layout, layout_manager: layout::Layout,
renderer_size: [f32; 2], renderer_size: [f32; 2],
} }
@ -29,12 +30,12 @@ impl GUI {
pub fn new(state: State) -> Self { pub fn new(state: State) -> Self {
GUI { GUI {
state, state,
layout: layout::Layout::new(), layout_manager: layout::Layout::new(),
renderer_size: [0.0, 0.0], 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) self.state.app_type.init_apptype(gl)
} }
@ -42,22 +43,22 @@ impl GUI {
&mut self, &mut self,
ui: &Ui, ui: &Ui,
context: &'b mut crate::pg::Context<'gl>, context: &'b mut crate::pg::Context<'gl>,
app_type: &'b mut AppType<'gl>, layout_atta: &'b mut Layout<'gl>,
) -> bool { ) -> bool {
// Menu bar // Menu bar
self.menu_bar(ui, context, app_type); self.menu_bar(ui, context, layout_atta);
let menu_bar_height = ui.frame_height(); let menu_bar_height = ui.frame_height();
let display_size = ui.io().display_size; let display_size = ui.io().display_size;
// Layout Size Reset // Layout Size Reset
self.layout.set_origin([0.0, menu_bar_height]); self.layout_manager.set_origin([0.0, menu_bar_height]);
self.layout self.layout_manager
.set_size([display_size[0], display_size[1] - menu_bar_height]); .set_size([display_size[0], display_size[1] - menu_bar_height]);
// Render // Render
self.state self.state
.app_type .app_type
.render(ui, context, &mut self.layout, app_type); .render(ui, context, &mut self.layout_manager, layout_atta);
true true
} }
@ -66,7 +67,7 @@ impl GUI {
&self, &self,
ui: &Ui, ui: &Ui,
context: &'b mut crate::pg::Context<'gl>, 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(top_menu) = ui.begin_main_menu_bar() {
if let Some(menu) = ui.begin_menu("File") { if let Some(menu) = ui.begin_menu("File") {
@ -75,7 +76,7 @@ impl GUI {
Some(file) => match context.load_data(file.clone()) { Some(file) => match context.load_data(file.clone()) {
Ok(data) => { Ok(data) => {
info!("Data loaded: {:?}", file); info!("Data loaded: {:?}", file);
app_type.deal_with_cursor(data); layout_atta.append_package(data);
} }
Err(e) => { Err(e) => {
error!("Failed to get or insert data: {:?}", e); error!("Failed to get or insert data: {:?}", e);

124
src/ui/operation.rs Normal file
View File

@ -0,0 +1,124 @@
use super::typ::CameraOP;
use crate::{
camera::Camera,
components::Program,
graphics::{AttaWithProgram, AttachWithMouse},
};
pub struct Operation<T: AttachWithMouse> {
camera: Camera,
projection: Projection,
operation: T,
need_update: bool,
}
impl<T: AttachWithMouse + AttaWithProgram> Operation<T> {
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()
}
}

View File

@ -41,14 +41,14 @@ impl UiType {
ui: &imgui::Ui, ui: &imgui::Ui,
context: &mut crate::pg::Context<'gl>, context: &mut crate::pg::Context<'gl>,
layout: &mut crate::ui::layout::Layout, 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 gl = context.gl;
let app_typ = app_typ.into(); let app_typ = app_typ.into();
uit!(self, {Mainload => render(ui,context,layout,app_typ)},); 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() uit!(self, {Mainload => init(gl)},).into()
} }
} }

View File

@ -1,26 +1,32 @@
use super::{CameraOP, Layout, LayoutAppType, LayoutMod, Size}; use std::thread::panicking;
use crate::graphics::threed::ThreeD;
use super::{CameraOP, Layout, LayoutAttach, LayoutMod, Size};
use crate::camera::Camera;
use crate::graphics::threed::Trackball;
use crate::graphics::{AttaWithProgram, AttachWithMouse, MouseState}; use crate::graphics::{AttaWithProgram, AttachWithMouse, MouseState};
use crate::pg::ModulePackage; 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::io::IO;
use crate::ui::operation::Operation;
use crate::utils::resources::GL; use crate::utils::resources::GL;
use glow::HasContext; use glow::HasContext;
use imgui::{Condition, Ui, WindowFlags}; use imgui::{Condition, Ui, WindowFlags};
use nalgebra_glm::Vec3;
pub struct MainLoad {} pub struct MainLoad {}
impl LayoutMod for MainLoad { impl LayoutMod for MainLoad {
type AppType<'gl> = MainLoadTyp<'gl>; type Attach<'gl> = MainLoadAttach<'gl>;
fn render<'b, 'gl>( fn render<'b, 'gl>(
&mut self, &mut self,
ui: &imgui::Ui, ui: &imgui::Ui,
context: &mut crate::pg::Context<'gl>, context: &mut crate::pg::Context<'gl>,
layout: &mut Layout, layout: &mut Layout,
apptyp: &mut Self::AppType<'gl>, apptyp: &mut Self::Attach<'gl>,
) where ) where
'gl: 'b, 'gl: 'b,
{ {
let mut changed = true;
let mut grid = layout.grid(2, 1, [0.0, 0.0]); let mut grid = layout.grid(2, 1, [0.0, 0.0]);
grid.set_col_size(&[size!(20.0%), size!(fill)]); grid.set_col_size(&[size!(20.0%), size!(fill)]);
grid.set_row_size(&[size!(fill)]); grid.set_row_size(&[size!(fill)]);
@ -35,8 +41,27 @@ impl LayoutMod for MainLoad {
grid.with(0, 0, [1, 1]) grid.with(0, 0, [1, 1])
.start_window(ui, "MainLoad") .start_window(ui, "MainLoad")
.build(|| { .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() { 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,6 +83,9 @@ impl LayoutMod for MainLoad {
// ui.set_cursor_screen_pos([pos[0] + size[0], pos[1] + size[1]]); // ui.set_cursor_screen_pos([pos[0] + size[0], pos[1] + size[1]]);
let draws = ui.get_window_draw_list(); let draws = ui.get_window_draw_list();
draws.channels_split(2, |channels| {
channels.set_current(0);
let fbo = apptyp.main_viewport.fbo(); let fbo = apptyp.main_viewport.fbo();
let fbo = fbo.native(); let fbo = fbo.native();
@ -87,19 +115,36 @@ impl LayoutMod for MainLoad {
}) })
.build(); .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() { if ui.is_window_hovered() {
let cio = IO::new(ui); 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> { fn init<'gl>(&mut self, gl: &'gl GL) -> Self::Attach<'gl> {
let typ = MainLoadTyp { let typ = MainLoadAttach {
main_viewport: ViewPort::new(gl), main_viewport: ViewPort::new(gl),
packages: Vec::new(), packages: Vec::new(),
camera_op: ThreeD::default(), operation: Operation::new(Trackball::default(), 16.0 / 9.0, 45.0, 0.1, 1000.0),
}; };
typ typ
} }
@ -109,13 +154,11 @@ impl MainLoad {
pub fn new() -> Self { pub fn new() -> Self {
MainLoad {} MainLoad {}
} }
fn render_window(&mut self, ui: &Ui, context: &mut crate::pg::Context) {}
} }
pub struct MainLoadTyp<'gl> { pub struct MainLoadAttach<'gl> {
operation: Operation<Trackball>,
main_viewport: ViewPort, main_viewport: ViewPort,
camera_op: ThreeD,
packages: Vec<ModulePackage<'gl>>, packages: Vec<ModulePackage<'gl>>,
} }
@ -126,33 +169,43 @@ impl CameraOP for MouseState {
from: context.mouse.position, from: context.mouse.position,
delta: context.mouse.drag_delta.unwrap(), delta: context.mouse.drag_delta.unwrap(),
} }
} else {
if context.mouse.wheel_delta != 0.0 {
Self::Wheel(context.mouse.wheel_delta)
} else { } else {
Self::None Self::None
} }
} }
}
} }
impl<'gl> LayoutAppType<'gl> for MainLoadTyp<'gl> { impl<'gl> LayoutAttach<'gl> for MainLoadAttach<'gl> {
type CameraOP = MouseState; fn append(&mut self, package: ModulePackage<'gl>) {
fn deal_with_cursor(&mut self, package: ModulePackage<'gl>) {
self.packages.push(package); self.packages.push(package);
} }
fn draw_program( fn render_task(
&mut self, &mut self,
gl: &glow::Context, gl: &glow::Context,
programs: &mut crate::pg::Programs<'gl>, programs: &mut crate::pg::Programs<'gl>,
) -> crate::errors::Result<()> { ) -> crate::errors::Result<()> {
self.main_viewport.bind(gl); self.main_viewport.bind(gl);
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() { for package in self.packages.iter_mut() {
programs.draw_modules(package, &self.camera_op)?; programs.draw_modules(package, &self.operation)?;
}
}
if self.packages.is_empty() {
unsafe {
gl.clear(glow::COLOR_BUFFER_BIT);
}
} }
self.main_viewport.unbind(); self.main_viewport.unbind();
Ok(()) Ok(())
} }
fn _deal_with_camera(&mut self, camera_op: Self::CameraOP) {
// println!("Camera Op: {:?}", camera_op);
self.camera_op.attach_with_mouse(&camera_op);
}
} }

View File

@ -3,35 +3,61 @@ use std::fmt::Debug;
use super::io::IO; use super::io::IO;
use super::layout::{Layout, Size}; use super::layout::{Layout, Size};
mod main_load; 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::pg::{self, ModuleCursor, ModulePackage, Programs};
use crate::utils::resources::GL; use crate::utils::resources::GL;
pub use main_load::*; 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 { pub trait LayoutMod {
type AppType<'gl>: Into<AppType<'gl>> + LayoutAppType<'gl>; type Attach<'gl>: Into<_Layout<'gl>> + LayoutAttach<'gl>;
fn render<'dt, 'b, 'gl>( fn render<'dt, 'b, 'gl>(
&mut self, &mut self,
ui: &imgui::Ui, ui: &imgui::Ui,
context: &mut crate::pg::Context<'gl>, context: &mut crate::pg::Context<'gl>,
layout: &mut Layout, layout: &mut Layout,
apptyp: &mut Self::AppType<'gl>, apptyp: &mut Self::Attach<'gl>,
) where ) where
'gl: 'b; '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> { pub trait LayoutAttach<'gl> {
type CameraOP: CameraOP + Debug; fn append(&mut self, package: ModulePackage<'gl>);
fn deal_with_cursor(&mut self, package: ModulePackage<'gl>);
fn deal_with_camera(&mut self, camera_op: &IO) { fn render_task(
self._deal_with_camera(CameraOP::from_context(camera_op));
}
fn _deal_with_camera(&mut self, camera_op: Self::CameraOP);
fn draw_program(
&mut self, &mut self,
gl: &glow::Context, gl: &glow::Context,
programs: &mut Programs<'gl>, programs: &mut Programs<'gl>,
@ -47,3 +73,7 @@ impl CameraOP for () {
() ()
} }
} }
app_type_into!({
MainLoadAttach<'gl> => MainLoad
},);

18
src/utils/color_tools.rs Normal file
View File

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

View File

@ -1,3 +1,4 @@
pub mod color_tools;
mod parser; mod parser;
pub mod resources; pub mod resources;
use include_dir::{include_dir, Dir}; use include_dir::{include_dir, Dir};