This commit is contained in:
Tsuki 2024-07-22 21:55:59 +08:00
parent 328a3127ae
commit 57bbbfe97f
22 changed files with 1495 additions and 542 deletions

24
Cargo.lock generated
View File

@ -1470,9 +1470,9 @@ dependencies = [
[[package]] [[package]]
name = "quick-xml" name = "quick-xml"
version = "0.31.0" version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" checksum = "6f24d770aeca0eacb81ac29dfbc55ebcc09312fdd1f8bbecdc7e4a84e000e3b4"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]
@ -1670,9 +1670,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]] [[package]]
name = "sctk-adwaita" name = "sctk-adwaita"
version = "0.8.1" version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82b2eaf3a5b264a521b988b2e73042e742df700c4f962cde845d1541adb46550" checksum = "70b31447ca297092c5a9916fc3b955203157b37c19ca8edde4f52e9843e602c7"
dependencies = [ dependencies = [
"ab_glyph", "ab_glyph",
"log", "log",
@ -2051,9 +2051,9 @@ checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
[[package]] [[package]]
name = "wayland-backend" name = "wayland-backend"
version = "0.3.4" version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34e9e6b6d4a2bb4e7e69433e0b35c7923b95d4dc8503a84d25ec917a4bbfdf07" checksum = "f90e11ce2ca99c97b940ee83edbae9da2d56a08f9ea8158550fd77fa31722993"
dependencies = [ dependencies = [
"cc", "cc",
"downcast-rs", "downcast-rs",
@ -2065,9 +2065,9 @@ dependencies = [
[[package]] [[package]]
name = "wayland-client" name = "wayland-client"
version = "0.31.3" version = "0.31.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e63801c85358a431f986cffa74ba9599ff571fc5774ac113ed3b490c19a1133" checksum = "7e321577a0a165911bdcfb39cf029302479d7527b517ee58ab0f6ad09edf0943"
dependencies = [ dependencies = [
"bitflags 2.5.0", "bitflags 2.5.0",
"rustix", "rustix",
@ -2137,9 +2137,9 @@ dependencies = [
[[package]] [[package]]
name = "wayland-scanner" name = "wayland-scanner"
version = "0.31.2" version = "0.31.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67da50b9f80159dec0ea4c11c13e24ef9e7574bd6ce24b01860a175010cea565" checksum = "d7b56f89937f1cf2ee1f1259cf2936a17a1f45d8f0aa1019fae6d470d304cfa6"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quick-xml", "quick-xml",
@ -2148,9 +2148,9 @@ dependencies = [
[[package]] [[package]]
name = "wayland-sys" name = "wayland-sys"
version = "0.31.2" version = "0.31.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "105b1842da6554f91526c14a2a2172897b7f745a805d62af4ce698706be79c12" checksum = "43676fe2daf68754ecf1d72026e4e6c15483198b5d24e888b74d3f22f887a148"
dependencies = [ dependencies = [
"dlib", "dlib",
"log", "log",

View File

@ -13,7 +13,7 @@ glutin = "0.31.3"
glutin-winit = "0.4.2" glutin-winit = "0.4.2"
copypasta = "0.10.1" copypasta = "0.10.1"
raw-window-handle = "0.5.2" raw-window-handle = "0.5.2"
winit = "0.29.15" winit = "0.29.3"
cgmath = "0.18.0" cgmath = "0.18.0"
nalgebra-glm = "0.18.0" nalgebra-glm = "0.18.0"
regex = "1.10.5" regex = "1.10.5"

View File

@ -21,4 +21,5 @@ void main()
if (v_color.a == 0) { discard; } if (v_color.a == 0) { discard; }
FragColor = stroke(v_distance, v_linewidth, v_antialias, v_color); FragColor = stroke(v_distance, v_linewidth, v_antialias, v_color);
// FragColor = v_color;
} }

View File

@ -33,47 +33,67 @@ void main ()
// This function is externally generated // This function is externally generated
// fetch_uniforms(); // fetch_uniforms();
float id = gl_VertexID;
v_linewidth = linewidth; v_linewidth = linewidth;
v_antialias = antialias; v_antialias = antialias;
v_color = color; v_color = color;
// transform prev/curr/next // transform prev/curr/next
vec4 prev_ = <transform(prev)>; // vec4 prev_ = <transform(prev)>;
vec4 curr_ = <transform(curr)>; // vec4 curr_ = <transform(curr)>;
vec4 next_ = <transform(next)>; // vec4 next_ = <transform(next)>;
// prev/curr/next in viewport coordinates // prev/curr/next in viewport coordinates
vec2 _prev = NDC_to_viewport(prev_, <viewport.viewport_global>.zw); // vec2 _prev = NDC_to_viewport(prev_, <viewport.viewport_global>.zw);
vec2 _curr = NDC_to_viewport(curr_, <viewport.viewport_global>.zw); // vec2 _curr = NDC_to_viewport(curr_, <viewport.viewport_global>.zw);
vec2 _next = NDC_to_viewport(next_, <viewport.viewport_global>.zw); // vec2 _next = NDC_to_viewport(next_, <viewport.viewport_global>.zw);
// Compute vertex final position (in viewport coordinates) // Compute vertex final position (in viewport coordinates)
float w = linewidth/2.0 + 1.5*antialias; float w = linewidth/2.0 + 1.5*antialias;
float z; float z;
vec2 P; vec2 P;
// if( curr == prev) {
// vec2 v = normalize(_next.xy - _curr.xy);
// vec2 normal = normalize(vec2(-v.y,v.x));
// P = _curr.xy + normal*w*id;
// } else if (curr == next) {
// vec2 v = normalize(_curr.xy - _prev.xy);
// vec2 normal = normalize(vec2(-v.y,v.x));
// P = _curr.xy + normal*w*id;
// } else {
// vec2 v0 = normalize(_curr.xy - _prev.xy);
// vec2 v1 = normalize(_next.xy - _curr.xy);
// vec2 normal = normalize(vec2(-v0.y,v0.x));
// vec2 tangent = normalize(v0+v1);
// vec2 miter = vec2(-tangent.y, tangent.x);
// float l = abs(w / dot(miter,normal));
// P = _curr.xy + miter*l*sign(id);
// }
if( curr == prev) { if( curr == prev) {
vec2 v = normalize(_next.xy - _curr.xy); vec2 v = normalize(next.xy - curr.xy);
vec2 normal = normalize(vec2(-v.y,v.x)); vec2 normal = normalize(vec2(-v.y,v.x));
P = _curr.xy + normal*w*id; P = curr.xy + normal*w*id;
} else if (curr == next) { } else if (curr == next) {
vec2 v = normalize(_curr.xy - _prev.xy); vec2 v = normalize(curr.xy - prev.xy);
vec2 normal = normalize(vec2(-v.y,v.x)); vec2 normal = normalize(vec2(-v.y,v.x));
P = _curr.xy + normal*w*id; P = curr.xy + normal*w*id;
} else { } else {
vec2 v0 = normalize(_curr.xy - _prev.xy); vec2 v0 = normalize(curr.xy - prev.xy);
vec2 v1 = normalize(_next.xy - _curr.xy); vec2 v1 = normalize(next.xy - curr.xy);
vec2 normal = normalize(vec2(-v0.y,v0.x)); vec2 normal = normalize(vec2(-v0.y,v0.x));
vec2 tangent = normalize(v0+v1); vec2 tangent = normalize(v0+v1);
vec2 miter = vec2(-tangent.y, tangent.x); vec2 miter = vec2(-tangent.y, tangent.x);
float l = abs(w / dot(miter,normal)); float l = abs(w / dot(miter,normal));
P = _curr.xy + miter*l*sign(id); P = curr.xy + miter*l*sign(id);
} }
if( abs(id) > 1.5 ) v_color.a = 0.0; if( abs(id) > 1.5 ) v_color.a = 0.0;
v_distance = w*id; v_distance = w*id;
gl_Position = viewport_to_NDC(P, <viewport.viewport_global>.zw, curr_.z / curr_.w); // gl_Position = viewport_to_NDC(P, <viewport.viewport_global>.zw, curr_.z / curr_.w);
// gl_Position = curr.xy + miter * l * sign(id);
<viewport.transform()>; gl_Position = vec4(P , 0.0, 1.0);
// <viewport.transform()>;
} }

View File

@ -1,12 +1,7 @@
layout(location = 0) in vec3 vertex;
uniform mat4 projection; uniform mat4 projection;
uniform mat4 view; uniform mat4 view;
const vec2 verts[3] = vec2[3](
vec2(0.5f, 1.0f),
vec2(0.0f, 0.0f),
vec2(1.0f, 0.0f)
);
out vec2 vert; out vec2 vert;
out vec4 color; out vec4 color;
@ -23,7 +18,7 @@ vec4 srgb_to_linear(vec4 srgb_color) {
} }
void main() { void main() {
vert = verts[gl_VertexID]; vert = vec2(vertex.xy);
color = srgb_to_linear(vec4(vert, 0.5, 1.0)); color = srgb_to_linear(vec4(vert, 0.5, 1.0));
gl_Position = vec4(vert - 0.5, 0.0, 1.0); gl_Position = vec4(vert, 0.0, 1.0);
} }

View File

@ -3,6 +3,10 @@
layout(points) in; layout(points) in;
layout(triangle_strip, max_vertices = 4) out; layout(triangle_strip, max_vertices = 4) out;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
// conf: Range, Elevation, Resolution, 0.0 // conf: Range, Elevation, Resolution, 0.0
uniform vec4 conf; uniform vec4 conf;
in float in_value[]; in float in_value[];

View File

@ -1,4 +1,6 @@
// Layout // Layout
layout(location = 0) in vec3 position; layout(location = 0) in vec3 position;
out float in_value; out float in_value;

View File

@ -1,25 +1,23 @@
use std::num::NonZeroU32;
use cgmath::Euler; use cgmath::Euler;
use glow::NativeProgram; use glow::NativeProgram;
use nalgebra_glm::{ use nalgebra_glm::{look_at, Mat4x4, Vec3};
Vec3, Mat4x4, look_at use std::num::NonZeroU32;
};
#[derive(Clone)]
pub(crate) struct Camera { pub(crate) struct Camera {
pos: Vec3, pos: Vec3,
upward: Vec3, upward: Vec3,
front: Vec3 front: 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, front: Vec3) -> Self {
Self { Self {
pos: world_loc, pos: world_loc,
upward, upward,
front front,
} }
} }
@ -51,5 +49,4 @@ impl Camera {
let l = self.pos + self.front; let l = self.pos + self.front;
look_at(&self.pos, &l, &self.upward) look_at(&self.pos, &l, &self.upward)
} }
} }

View File

@ -1,68 +0,0 @@
use glow::HasContext;
use crate::{
components::{CodeType, Program, Shader},
graphics::transforms::{
polar::Polar, position::Position, trackball::Trackball, viewport::Viewport, Transform,
},
};
// pub struct PPI {
// transform: Trackball,
// program: Program,
// }
// impl PPI {
// pub fn new(version: &'static str) -> Self {
// let trackball = Trackball::new().unwrap();
// let projection = Polar::new().unwrap();
// let position = Position::new().unwrap();
// // let transform = trackball.chain(projection.chain(position));
// let vertex = Shader::new(
// glow::VERTEX_SHADER,
// CodeType::<&'static str>::Path("agg-fast-path.vert".into()),
// )
// .unwrap();
// let fragment = Shader::new(
// glow::FRAGMENT_SHADER,
// CodeType::<&'static str>::Path("agg-fast-path.frag".into()),
// )
// .unwrap();
// let mut program = Program::new(vertex, fragment, None, version);
// let viewport = Viewport::new().unwrap();
// // program.set_transform(&transform);
// program.set_viewport(&viewport);
// Self { transform, program }
// }
// pub fn compile(&mut self, gl: &glow::Context) {
// self.program.compile(gl);
// }
// pub fn program(&self) -> &Program {
// &self.program
// }
// pub fn native_program(&self) -> Option<<glow::Context as HasContext>::Program> {
// self.program.native_program
// }
// }
mod test {
use super::*;
#[test]
fn test_ppi() {
// let ppi = PPI::new("450");
// println!("{}", ppi.program.vertex());
}
}

View File

@ -8,16 +8,18 @@ use crate::errors::*;
use crate::graphics::transforms::viewport::Viewport; use crate::graphics::transforms::viewport::Viewport;
use crate::graphics::transforms::Transform; use crate::graphics::transforms::Transform;
use crate::graphics::ty::Ty; use crate::graphics::ty::Ty;
use crate::graphics::Graphics; use crate::graphics::{AttaWithBuffer, Config, Graphics};
use super::Colletion; use super::Colletion;
pub struct AggFastPath { pub struct AggFastPath {
program: Program, program: Program,
buffer: Vec<Point>, buffer: Vec<Point>,
indice: Vec<[u32; 3]>,
vao: Option<NativeVertexArray>, vao: Option<NativeVertexArray>,
vbo: Option<NativeBuffer>, vbo: Option<NativeBuffer>,
ebo: Option<NativeBuffer>,
} }
impl AggFastPath { impl AggFastPath {
@ -63,6 +65,8 @@ impl AggFastPath {
Ok(Self { Ok(Self {
program, program,
buffer: Vec::with_capacity(128), buffer: Vec::with_capacity(128),
indice: Vec::with_capacity(128 * 2),
ebo: None,
vao: None, vao: None,
vbo: None, vbo: None,
}) })
@ -104,6 +108,12 @@ impl AggFastPath {
pub fn program_ref(&self) -> &Program { pub fn program_ref(&self) -> &Program {
&self.program &self.program
} }
fn init(&mut self, gl: &glow::Context) {
self.set_anatialias(gl, 0.005);
self.set_linecolor(gl, [1.0, 1.0, 1.0, 1.0]);
self.set_linewidth(gl, 0.02);
}
} }
impl Colletion for AggFastPath { impl Colletion for AggFastPath {
@ -111,6 +121,7 @@ impl Colletion for AggFastPath {
fn append(&mut self, item: Self::Item) { fn append(&mut self, item: Self::Item) {
self.buffer.extend(item.points); self.buffer.extend(item.points);
self.indice.extend(item.ebo);
} }
} }
@ -118,10 +129,15 @@ impl Graphics for AggFastPath {
fn compile(&mut self, gl: &glow::Context) -> Result<()> { fn compile(&mut self, gl: &glow::Context) -> Result<()> {
use bytemuck::cast_slice; use bytemuck::cast_slice;
self.program.compile(gl)?; self.program.compile(gl)?;
unsafe { unsafe {
let vao = gl.create_vertex_array().unwrap(); let vao = gl.create_vertex_array().unwrap();
gl.bind_vertex_array(Some(vao)); gl.bind_vertex_array(Some(vao));
for p in self.buffer.iter() {
println!("{}", p);
}
println!("{:?}", self.indice);
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));
@ -143,8 +159,18 @@ impl Graphics for AggFastPath {
gl.enable_vertex_attrib_array(3); gl.enable_vertex_attrib_array(3);
gl.vertex_attrib_pointer_f32(3, 1, glow::FLOAT, false, 40, 36); gl.vertex_attrib_pointer_f32(3, 1, glow::FLOAT, false, 40, 36);
let ebo = gl.create_buffer().unwrap();
gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(ebo));
gl.buffer_data_u8_slice(
glow::ELEMENT_ARRAY_BUFFER,
cast_slice(&self.indice),
glow::STATIC_DRAW,
);
self.vao = Some(vao); self.vao = Some(vao);
self.vbo = Some(vbo); self.vbo = Some(vbo);
self.ebo = Some(ebo);
gl.bind_vertex_array(None); gl.bind_vertex_array(None);
} }
@ -152,13 +178,16 @@ impl Graphics for AggFastPath {
Ok(()) Ok(())
} }
fn draw(&self, gl: &glow::Context) -> Result<()> { fn draw(&self, gl: &glow::Context, count: i32) -> Result<()> {
unsafe { unsafe {
gl.clear(glow::COLOR_BUFFER_BIT); gl.clear(glow::COLOR_BUFFER_BIT);
gl.use_program(Some(self.program.native_program.unwrap()));
gl.bind_vertex_array(Some(self.vao.unwrap())); gl.bind_vertex_array(Some(self.vao.unwrap()));
gl.draw_arrays(glow::TRIANGLE_STRIP, 0, self.buffer.len() as i32); gl.draw_elements(
glow::TRIANGLES,
(self.indice.len() * 3) as i32,
glow::UNSIGNED_INT,
0,
);
gl.bind_vertex_array(None); gl.bind_vertex_array(None);
} }
@ -169,14 +198,53 @@ impl Graphics for AggFastPath {
self.program.destroy(gl); self.program.destroy(gl);
unsafe { unsafe {
self.ebo.map(|ebo| gl.delete_buffer(ebo));
self.vao.map(|vao| gl.delete_vertex_array(vao)); self.vao.map(|vao| gl.delete_vertex_array(vao));
self.vbo.map(|vbo| gl.delete_buffer(vbo)); self.vbo.map(|vbo| gl.delete_buffer(vbo));
} }
Ok(()) Ok(())
} }
fn program_ref(&self) -> &Program {
&self.program
}
fn program_mut(&mut self) -> &mut Program {
&mut self.program
}
fn set_config(&mut self, gl: &glow::Context, config: Option<&Config>) -> Result<()> {
Ok(())
}
fn mount(&mut self, gl: &glow::Context) -> Result<()> {
unsafe {
gl.use_program(self.program.native_program);
self.init(gl);
}
Ok(())
}
fn unmount(&mut self, gl: &glow::Context) -> Result<()> {
unsafe {
gl.use_program(None);
}
Ok(())
}
} }
impl AttaWithBuffer for AggFastPath {
type Data = ();
fn bake(&self, data: &Self::Data) -> Result<(Vec<f32>, Option<Vec<u32>>, i32)> {
Ok((vec![], None, 0))
}
fn init(&self, gl: &glow::Context) -> (NativeVertexArray, NativeBuffer, Option<NativeBuffer>) {
(self.vao.unwrap(), self.vbo.unwrap(), self.ebo)
}
}
#[repr(C)] #[repr(C)]
#[derive(Debug, Clone, Copy, Zeroable, Pod)] #[derive(Debug, Clone, Copy, Zeroable, Pod)]
pub struct Point { pub struct Point {
@ -186,11 +254,23 @@ pub struct Point {
id: f32, id: f32,
} }
impl std::fmt::Display for Point {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Point {{ prev: {:?}, curr: {:?}, next: {:?}, id: {} }}",
self.prev, self.curr, self.next, self.id
)
}
}
impl Ty for Point {} impl Ty for Point {}
#[derive(Debug)] #[derive(Debug)]
pub struct Path { pub struct Path {
points: Vec<Point>, points: Vec<Point>,
ebo: Vec<[u32; 3]>,
is_closed: bool, is_closed: bool,
is_empty: bool, is_empty: bool,
} }
@ -199,6 +279,8 @@ impl Default for Path {
fn default() -> Self { fn default() -> Self {
Self { Self {
points: Vec::with_capacity(500), points: Vec::with_capacity(500),
ebo: Vec::with_capacity(500),
is_closed: false, is_closed: false,
is_empty: true, is_empty: true,
} }
@ -225,6 +307,8 @@ impl PathBuilder {
Path { Path {
points: Vec::with_capacity(500), points: Vec::with_capacity(500),
is_closed: self.is_closed, is_closed: self.is_closed,
ebo: Vec::with_capacity(500),
is_empty: true, is_empty: true,
} }
} }
@ -234,6 +318,7 @@ impl Path {
pub fn new(is_closed: bool) -> Self { pub fn new(is_closed: bool) -> Self {
Self { Self {
points: Vec::with_capacity(500), points: Vec::with_capacity(500),
ebo: Vec::with_capacity(500),
is_closed, is_closed,
is_empty: true, is_empty: true,
} }
@ -304,6 +389,11 @@ impl Path {
self.points[len - 1].next = curr; self.points[len - 1].next = curr;
self.points[len - 2].next = curr; self.points[len - 2].next = curr;
} }
for s in 0..(self.points.len() / 2) - 1 {
let s = s as u32;
self.ebo.push([s * 2, s * 2 + 1, (s + 1) * 2 + 1]);
self.ebo.push([s * 2, (s + 1) * 2 + 1, (s + 1) * 2]);
}
} }
pub fn len(&self) -> usize { pub fn len(&self) -> usize {

View File

@ -1,20 +1,21 @@
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use bytemuck::{Pod, Zeroable}; use bytemuck::{cast_slice, Pod, Zeroable};
use glow::{HasContext, NativeBuffer, NativeVertexArray}; 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::Transform;
use crate::graphics::ty::Ty; use crate::graphics::ty::Ty;
use crate::graphics::Graphics; use crate::graphics::Graphics;
use super::{AttaWithBuffer, Config};
pub struct Hello { pub struct Hello {
program: Program, program: Program,
buffer: Vec<Point>, buffer: Vec<Point>,
vao: Option<NativeVertexArray>, vao: Option<NativeVertexArray>,
vbo: Option<NativeBuffer>,
} }
impl Hello { impl Hello {
@ -38,6 +39,7 @@ impl Hello {
program, program,
buffer: Vec::with_capacity(128), buffer: Vec::with_capacity(128),
vao: None, vao: None,
vbo: None,
}) })
} }
@ -58,19 +60,46 @@ impl Graphics for Hello {
.create_vertex_array() .create_vertex_array()
.expect("Cannot create vertex array"); .expect("Cannot create vertex array");
let buffer: Vec<[f32; 3]> = vec![
[-0.5, -0.5, 0.0],
[-0.5, 0.5, 0.0],
[0.5, 0.5, 0.0],
[0.5, -0.5, 0.0],
];
gl.bind_vertex_array(Some(vertex_array));
let vbo = gl.create_buffer().unwrap();
gl.bind_buffer(glow::ARRAY_BUFFER, Some(vbo));
gl.buffer_data_u8_slice(glow::ARRAY_BUFFER, cast_slice(&buffer), glow::STATIC_DRAW);
gl.enable_vertex_attrib_array(0);
gl.vertex_attrib_pointer_f32(0, 3, glow::FLOAT, false, 12, 0);
let ebo = gl.create_buffer().unwrap();
// let e: [[u32; 3]; 2] = [[0, 1, 3], [0, 2, 3]];
let e: [[u32; 3]; 2] = [[0, 1, 2], [2, 3, 0]];
gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(ebo));
gl.buffer_data_u8_slice(
glow::ELEMENT_ARRAY_BUFFER,
cast_slice(&e),
glow::STATIC_DRAW,
);
self.vao = Some(vertex_array); self.vao = Some(vertex_array);
self.vbo = Some(vbo);
} }
Ok(()) Ok(())
} }
fn draw(&self, gl: &glow::Context) -> Result<()> { fn draw(&self, gl: &glow::Context, count: i32) -> Result<()> {
unsafe { unsafe {
gl.clear_color(0.05, 0.05, 0.1, 1.0); gl.clear_color(0.05, 0.05, 0.1, 1.0);
gl.clear(glow::COLOR_BUFFER_BIT); gl.clear(glow::COLOR_BUFFER_BIT);
gl.use_program(Some(self.program.native_program.unwrap()));
gl.bind_vertex_array(self.vao); gl.bind_vertex_array(self.vao);
gl.draw_arrays(glow::TRIANGLES, 0, 3);
gl.draw_elements(glow::TRIANGLES, 6, glow::UNSIGNED_INT, 0);
} }
Ok(()) Ok(())
@ -80,11 +109,51 @@ impl Graphics for Hello {
self.program.destroy(gl); self.program.destroy(gl);
unsafe { unsafe {
self.vbo.map(|vbo| gl.delete_buffer(vbo));
self.vao.map(|vao| gl.delete_vertex_array(vao)); self.vao.map(|vao| gl.delete_vertex_array(vao));
} }
Ok(()) Ok(())
} }
fn program_ref(&self) -> &Program {
&self.program
}
fn program_mut(&mut self) -> &mut Program {
&mut self.program
}
fn set_config(&mut self, gl: &glow::Context, config: Option<&Config>) -> Result<()> {
Ok(())
}
fn mount(&mut self, gl: &glow::Context) -> Result<()> {
unsafe {
gl.use_program(self.program.native_program);
}
Ok(())
}
fn unmount(&mut self, gl: &glow::Context) -> Result<()> {
unsafe {
gl.use_program(None);
}
Ok(())
}
}
impl AttaWithBuffer for Hello {
type Data = ();
fn bake(&self, data: &Self::Data) -> Result<(Vec<f32>, Option<Vec<u32>>, i32)> {
return Ok((vec![], None, 0));
}
fn init(&self, gl: &glow::Context) -> (NativeVertexArray, NativeBuffer, Option<NativeBuffer>) {
panic!("Not implemented");
}
} }
#[repr(C)] #[repr(C)]

View File

@ -3,20 +3,31 @@ pub mod colormap;
mod colormesh; mod colormesh;
pub mod hello; pub mod hello;
pub mod ppi; pub mod ppi;
pub mod threed;
pub mod tools; pub mod tools;
pub mod transforms; pub mod transforms;
pub mod ty; pub mod ty;
use crate::{components::Program, errors::*}; use crate::{components::Program, errors::*};
pub use colormesh::ColorMesh; use glow::{NativeBuffer, NativeVertexArray};
use imgui::TextureId; use ppi::PPIConfig;
pub trait Graphics { pub trait Graphics: AttaWithBuffer {
fn draw(&self, gl: &glow::Context) -> Result<()>; fn draw(&self, gl: &glow::Context, count: i32) -> Result<()>;
fn compile(&mut self, gl: &glow::Context) -> Result<()>; fn compile(&mut self, gl: &glow::Context) -> Result<()>;
fn destroy(&mut self, gl: &glow::Context) -> Result<()>; fn destroy(&mut self, gl: &glow::Context) -> Result<()>;
fn program_ref(&self) -> &Program;
fn program_mut(&mut self) -> &mut Program;
fn mount(&mut self, gl: &glow::Context) -> Result<()>;
fn unmount(&mut self, gl: &glow::Context) -> Result<()>;
fn set_config(&mut self, gl: &glow::Context, config: Option<&Config>) -> Result<()>;
} }
pub trait AttaWithProgram { pub trait AttaWithProgram {
@ -25,12 +36,36 @@ pub trait AttaWithProgram {
pub trait AttaWithBuffer { pub trait AttaWithBuffer {
type Data; type Data;
fn attach_with_buffer(&mut self, gl: &glow::Context, data: &Self::Data) -> Result<()>;
fn bake(&self, data: &Self::Data) -> Result<(Vec<f32>, Option<Vec<u32>>, i32)>;
fn init(&self, gl: &glow::Context) -> (NativeVertexArray, NativeBuffer, Option<NativeBuffer>);
} }
macro_rules! config_for_everyitem {
($({$conf:ty => $name:tt},)+) => {
$(
impl From<$conf> for Config {
fn from(value: $conf) -> Self {
Self::$name(value)
}
}
)+
pub trait AttaWithWindow { };
}
fn attach_with_window(&mut self, gl: &glow::Context) -> Result<TextureId>;
#[derive(Clone)]
pub enum Config {
PPI(PPIConfig),
}
config_for_everyitem!({PPIConfig => PPI},);
pub trait AttachWithMouse {
fn attach_with_mouse(&mut self, state: MouseState);
}
#[derive(Debug, Clone)]
pub enum MouseState {
Drag { from: [f32; 2], delta: [f32; 2] },
} }

View File

@ -1,30 +1,18 @@
use std::cell::RefCell; use glow::{HasContext, NativeBuffer, NativeVertexArray};
use std::rc::Rc;
use bytemuck::cast_slice; use crate::components::{CodeType, Program, Shader};
use glow::{HasContext, NativeBuffer, NativeFramebuffer, NativeTexture, NativeVertexArray};
use ndarray::{s, IndexLonger};
use crate::components::{CodeType, Program, Shader, Snippet};
use crate::data_loader::{CoordType, Data, DataType}; use crate::data_loader::{CoordType, Data, DataType};
use crate::errors::*; use crate::errors::*;
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::Transform; use super::{transforms, AttaWithBuffer, Config, Graphics};
use super::{ty, AttaWithBuffer, AttaWithWindow, Graphics};
pub struct PPI { pub struct PPI {
program: Program, program: Program,
layer: isize, layer: isize,
vao: Option<NativeVertexArray>,
vbo: Option<NativeBuffer>,
cmap: Option<Box<dyn ColorMap>>, cmap: Option<Box<dyn ColorMap>>,
framebuffer: Option<NativeFramebuffer>,
frametexture: Option<NativeTexture>,
buffer: Vec<[f32; 3]>,
} }
impl PPI { impl PPI {
@ -44,24 +32,18 @@ impl PPI {
CodeType::<String>::Path("ppi.frag".into()), CodeType::<String>::Path("ppi.frag".into()),
)?; )?;
let program = Program::new(vertex, fragment, Some(geom), "330 core"); let transform = ThreeD::new(1.0, 2.0, 1000.0, 45.0)?;
let mut program = Program::new(vertex, fragment, Some(geom), "330 core");
program.set_transform(&transform);
Ok(Self { Ok(Self {
program, program,
layer: 0, layer: 0,
vao: None,
vbo: None,
buffer: Vec::with_capacity(180 * 50),
framebuffer: None,
frametexture: None,
cmap: None, cmap: None,
}) })
} }
pub fn set_transform<T: Transform>(&mut self, transform: &T) {
self.program.set_transform(transform);
}
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);
} }
@ -75,23 +57,14 @@ impl PPI {
&mut self.program &mut self.program
} }
fn set_conf(&self, gl: &glow::Context, dpir: f32, dpie: f32) { fn set_conf(&self, gl: &glow::Context, rdpi: f32, adpi: f32) {
let location = self.program.get_uniform_location(gl, "conf"); let location = self.program.get_uniform_location(gl, "conf");
unsafe { unsafe {
gl.uniform_4_f32(location.as_ref(), dpir, dpie, 0f32, 0f32); gl.uniform_4_f32(location.as_ref(), rdpi, adpi, 0f32, 0f32);
} }
} }
pub fn add_ppi_layer(&mut self, layer: isize) { fn bake_data(&self, data: &Data) -> Result<(Vec<f32>, i32)> {
self.layer = self.layer + layer;
self.layer.clamp(0, 23);
}
pub fn program_ref(&self) -> &Program {
&self.program
}
fn bake_data(&self, data: &Data) -> Result<Vec<[f32; 3]>> {
let first_block = data.blocks.get(0).unwrap(); let first_block = data.blocks.get(0).unwrap();
let first_block_data = first_block.data.view(); let first_block_data = first_block.data.view();
if let CoordType::Polar { if let CoordType::Polar {
@ -113,16 +86,17 @@ impl PPI {
let dt = first_block_data let dt = first_block_data
.get([self.layer as usize, azi_idx, r_idx]) .get([self.layer as usize, azi_idx, r_idx])
.unwrap(); .unwrap();
vertices.push([r, *azi, *dt]); vertices.extend([r, *azi, *dt]);
} }
} }
return Ok(vertices); let len = vertices.len() as i32 / 3;
return Ok((vertices, len));
} else { } else {
return Err(Error::InvalidDataType); return Err(Error::InvalidDataType);
} }
} }
fn data_info(&self, data: &Data) -> Result<(f32, f32, DataType)> { 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,
@ -140,6 +114,23 @@ impl PPI {
return Err(Error::InvalidDataType); return Err(Error::InvalidDataType);
} }
} }
fn init(&mut self, gl: &glow::Context, config: &PPIConfig) {
self.cmap
.as_mut()
.unwrap()
.attach_with_program(gl, &self.program)
.unwrap();
let origin = self.program.get_uniform_location(gl, "polar_origin");
let rdpi = config.rdpi;
let adpi = config.adpi;
self.set_conf(gl, rdpi, adpi);
unsafe {
gl.uniform_1_f32(origin.as_ref(), 90.0f32.to_radians());
}
}
} }
fn min_step(data: &Vec<f32>) -> f32 { fn min_step(data: &Vec<f32>) -> f32 {
@ -173,84 +164,57 @@ fn max_step(data: &Vec<f32>) -> f32 {
impl Graphics for PPI { impl Graphics for PPI {
fn compile(&mut self, gl: &glow::Context) -> Result<()> { fn compile(&mut self, gl: &glow::Context) -> Result<()> {
self.program.compile(gl)?; self.program.compile(gl)?;
self.cmap
.as_mut()
.unwrap()
.attach_with_program(gl, &self.program)?;
unsafe {
let vao = gl.create_vertex_array().unwrap();
gl.bind_vertex_array(Some(vao));
let vbo = gl.create_buffer().unwrap();
gl.bind_buffer(glow::ARRAY_BUFFER, Some(vbo));
gl.enable_vertex_attrib_array(0);
gl.vertex_attrib_pointer_f32(0, 3, glow::FLOAT, false, 12, 0);
self.vao = Some(vao);
self.vbo = Some(vbo);
gl.bind_vertex_array(None);
}
// let location = self.program.get_uniform_location(gl, "conf");
let origin = self.program.get_uniform_location(gl, "polar_origin");
unsafe {
// gl.uniform_4_f32(location.as_ref(), dpir, dpie, 0.0, 0.0);
gl.uniform_1_f32(origin.as_ref(), 90.0f32.to_radians());
}
Ok(()) Ok(())
} }
fn destroy(&mut self, gl: &glow::Context) -> Result<()> { fn destroy(&mut self, gl: &glow::Context) -> Result<()> {
self.program.destroy(gl); self.program.destroy(gl);
unsafe {
self.vao.map(|vao| gl.delete_vertex_array(vao));
self.vbo.map(|vbo| gl.delete_buffer(vbo));
self.framebuffer.map(|fb| gl.delete_framebuffer(fb));
self.frametexture.map(|ft| gl.delete_texture(ft));
self.cmap.as_mut().unwrap().destroy(gl);
}
Ok(()) Ok(())
} }
fn draw(&self, gl: &glow::Context) -> Result<()> { fn draw(&self, gl: &glow::Context, count: i32) -> Result<()> {
unsafe { unsafe {
gl.clear(glow::COLOR_BUFFER_BIT); gl.clear(glow::COLOR_BUFFER_BIT);
gl.use_program(Some(self.program.native_program.unwrap()));
self.cmap self.cmap
.as_ref() .as_ref()
.unwrap() .unwrap()
.bind_texture(gl, &self.program)?; .bind_texture(gl, &self.program)?;
if self.framebuffer.is_some() { gl.draw_arrays(glow::POINTS, 0, count);
gl.bind_framebuffer(glow::FRAMEBUFFER, self.framebuffer); }
Ok(())
} }
gl.depth_mask(false); fn program_ref(&self) -> &Program {
gl.bind_vertex_array(Some(self.vao.unwrap())); &self.program
gl.draw_arrays(glow::POINTS, 0, self.buffer.len() as i32);
gl.depth_mask(true);
if self.framebuffer.is_some() {
gl.framebuffer_texture_2d(
glow::FRAMEBUFFER,
glow::COLOR_ATTACHMENT0,
glow::TEXTURE_2D,
self.frametexture,
0,
);
assert_eq!(
gl.check_framebuffer_status(glow::FRAMEBUFFER),
glow::FRAMEBUFFER_COMPLETE
);
gl.bind_texture(glow::TEXTURE_2D, None);
gl.bind_framebuffer(glow::FRAMEBUFFER, None);
} }
gl.bind_vertex_array(None); fn program_mut(&mut self) -> &mut Program {
&mut self.program
}
fn set_config(&mut self, gl: &glow::Context, config: Option<&Config>) -> Result<()> {
if let Some(config) = config {
if let Config::PPI(config) = config {
self.init(gl, config);
} else {
panic!("Errr config type");
}
}
Ok(())
}
fn mount(&mut self, gl: &glow::Context) -> Result<()> {
unsafe {
gl.use_program(self.program.native_program);
}
Ok(())
}
fn unmount(&mut self, gl: &glow::Context) -> Result<()> {
unsafe {
gl.use_program(None); gl.use_program(None);
} }
Ok(()) Ok(())
@ -260,68 +224,33 @@ impl Graphics for PPI {
impl AttaWithBuffer for PPI { impl AttaWithBuffer for PPI {
type Data = Data; type Data = Data;
fn attach_with_buffer(&mut self, gl: &glow::Context, data: &Self::Data) -> Result<()> { fn bake(&self, data: &Self::Data) -> Result<(Vec<f32>, Option<Vec<u32>>, i32)> {
let (rdpi, adpi, data_type) = self.data_info(data)?; // let (rdpi, adpi, data_type) = self.data_info(data)?;
let baked_buffer = self.bake_data(data)?; let baked_buffer = self.bake_data(data)?;
self.buffer = baked_buffer; Ok((baked_buffer.0, None, baked_buffer.1))
unsafe {
gl.use_program(self.program.native_program);
self.set_conf(gl, rdpi, adpi);
gl.bind_vertex_array(self.vao);
gl.buffer_data_u8_slice(
glow::ARRAY_BUFFER,
cast_slice(&self.buffer),
glow::STATIC_DRAW,
);
} }
Ok(()) fn init(&self, gl: &glow::Context) -> (NativeVertexArray, NativeBuffer, Option<NativeBuffer>) {
unsafe {
let vao = gl.create_vertex_array().unwrap();
gl.bind_vertex_array(Some(vao));
let vbo = gl.create_buffer().unwrap();
gl.bind_buffer(glow::ARRAY_BUFFER, Some(vbo));
gl.enable_vertex_attrib_array(0);
gl.vertex_attrib_pointer_f32(0, 3, glow::FLOAT, false, 12, 0);
gl.bind_vertex_array(None);
(vao, vbo, None)
}
} }
} }
impl AttaWithWindow for PPI { #[derive(Default, Clone)]
fn attach_with_window(&mut self, gl: &glow::Context) -> Result<imgui::TextureId> { pub struct PPIConfig {
unsafe { pub layer: usize,
if self.framebuffer.is_none() { pub rdpi: f32,
let framebuffer = gl.create_framebuffer().unwrap(); pub adpi: f32,
gl.bind_framebuffer(glow::FRAMEBUFFER, Some(framebuffer)); pub trackball: ThreeD,
let texture = gl.create_texture().unwrap();
gl.bind_texture(glow::TEXTURE_2D, Some(texture));
gl.tex_image_2d(
glow::TEXTURE_2D,
0,
glow::RGB8 as i32,
800,
600,
0,
glow::RGB,
glow::UNSIGNED_BYTE,
None,
);
gl.tex_parameter_i32(
glow::TEXTURE_2D,
glow::TEXTURE_MIN_FILTER,
glow::LINEAR as i32,
);
gl.tex_parameter_i32(
glow::TEXTURE_2D,
glow::TEXTURE_MAG_FILTER,
glow::LINEAR as i32,
);
gl.bind_framebuffer(glow::FRAMEBUFFER, None);
gl.bind_texture(glow::TEXTURE_2D, None);
self.frametexture = Some(texture);
Ok(imgui::TextureId::from(texture.0.get() as usize))
} else {
Ok(imgui::TextureId::from(
self.frametexture.unwrap().0.get() as usize
))
}
}
}
} }
mod test { mod test {

82
src/graphics/threed.rs Normal file
View File

@ -0,0 +1,82 @@
use std::rc::Rc;
use super::transforms::Transform;
use super::transforms::{position::Position, trackball::Trackball, ChainedTransform};
use super::{AttaWithProgram, AttachWithMouse};
use crate::camera::Camera;
use crate::errors::*;
use glow::HasContext;
use nalgebra_glm::Vec3;
#[derive(Clone)]
pub struct ThreeD {
transform: Rc<ChainedTransform>,
projection: nalgebra_glm::Mat4,
trackball: Trackball,
camera: Camera,
}
impl ThreeD {
pub fn new(aspect: f32, z_far: f32, z_near: f32, fov: f32) -> Result<Self> {
let trackball = Trackball::new()?;
let transform = ChainedTransform::from(&trackball).chain(&Position::new()?);
let camera = Camera::new(
Vec3::new(0.0, 0.0, 0.0),
Vec3::new(0.0, 0.0, -1.0),
Vec3::new(0.0, 1.0, 0.0),
);
let projection = nalgebra_glm::perspective(aspect, fov, z_near, z_far);
Ok(Self {
transform: Rc::new(transform),
trackball,
camera,
projection,
})
}
}
impl Default for ThreeD {
fn default() -> Self {
Self::new(1.0, 2.0, 1000.0, 45.0).unwrap()
}
}
impl AttaWithProgram for ThreeD {
fn attach_with_program(
&self,
gl: &glow::Context,
program: &crate::components::Program,
) -> Result<()> {
unsafe {
let view = program.get_uniform_location(gl, "trackball_view");
let projection = program.get_uniform_location(gl, "trackball_projection");
self.trackball.attach_with_program(gl, program)?;
gl.uniform_matrix_4_f32_slice(
view.as_ref(),
false,
self.camera.get_view_matrix().as_slice(),
);
gl.uniform_matrix_4_f32_slice(projection.as_ref(), false, self.projection.as_slice());
}
Ok(())
}
}
impl Transform for ThreeD {
fn snippet(&self) -> &crate::components::Snippet {
self.transform.snippet()
}
}
impl AttachWithMouse for ThreeD {
fn attach_with_mouse(&mut self, state: super::MouseState) {
if let super::MouseState::Drag { from, delta } = state {
self.trackball
.on_mouse_drag(from[0], from[1], delta[0], delta[1]);
}
}
}

View File

@ -12,19 +12,19 @@ pub struct ChainedTransform {
} }
impl ChainedTransform { impl ChainedTransform {
pub fn from<T: Transform + '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)], chain: vec![Box::new(transform.clone())],
} }
} }
pub fn chain(mut self, other: impl Transform + 'static) -> 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)); self.chain.push(Box::new(other.clone()));
self self
} }
} }

View File

@ -4,6 +4,7 @@ use crate::{
errors::*, errors::*,
graphics::AttaWithProgram, graphics::AttaWithProgram,
}; };
#[derive(Debug, Clone)]
pub struct Position { pub struct Position {
snippet: Snippet, snippet: Snippet,
} }

View File

@ -7,6 +7,7 @@ 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};
#[derive(Debug, Clone)]
pub struct TrackballModel { pub struct TrackballModel {
rotation: UnitQuaternion<f32>, rotation: UnitQuaternion<f32>,
count: usize, count: usize,
@ -36,7 +37,7 @@ impl TrackballModel {
trackball trackball
} }
pub fn drag_to(&mut self, x: f32, y: f32, dx: f32, dy: f32) { 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;
@ -47,23 +48,23 @@ impl TrackballModel {
self.model = self.rotation.to_homogeneous(); self.model = self.rotation.to_homogeneous();
} }
pub fn model(&self) -> &Matrix4<f32> { fn model(&self) -> &Matrix4<f32> {
&self.model &self.model
} }
pub fn theta(&self) -> f32 { fn theta(&self) -> f32 {
self.theta self.theta
} }
pub fn set_theta(&mut self, theta: f32) { 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);
} }
pub fn phi(&self) -> f32 { fn phi(&self) -> f32 {
self.phi self.phi
} }
pub fn set_phi(&mut self, phi: f32) { 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);
} }
@ -128,17 +129,10 @@ impl TrackballModel {
} }
} }
#[derive(Debug, Clone)]
pub struct Trackball { pub struct Trackball {
snippet: Snippet, snippet: Snippet,
znear: f32,
zfar: f32,
zoom: f32,
aspect: f32,
model: TrackballModel, model: TrackballModel,
projection: nalgebra_glm::Mat4x4,
view: nalgebra::Matrix4<f32>,
} }
impl Trackball { impl Trackball {
@ -152,82 +146,18 @@ impl Trackball {
let model = TrackballModel::new(45.0, 45.0); let model = TrackballModel::new(45.0, 45.0);
let aspect = 1.0;
let fovy = 45.0;
let near = 2.0;
let far = 1000.0;
let projection = nalgebra_glm::perspective(aspect, fovy, near, far);
let mut view: Matrix4<f32> = Matrix4::identity();
let distance: f32 = 8.0;
let translation = Translation3::new(0.0, 0.0, -distance.abs());
view = translation.to_homogeneous() * view;
Ok(Self { Ok(Self {
snippet: snippets, snippet: snippets,
znear: near,
zfar: far,
zoom: fovy,
aspect,
model, model,
projection,
view,
}) })
} }
pub fn on_mouse_drag( pub fn on_mouse_drag(&mut self, x: f32, y: f32, dx: f32, dy: f32) {
&mut self,
gl: &glow::Context,
program: &mut Program,
x: f32,
y: f32,
dx: f32,
dy: f32,
) {
self.model.drag_to(x, y, dx, dy); self.model.drag_to(x, y, dx, dy);
unsafe {
let model = self.snippet.find_symbol("trackball_model").unwrap();
let l = program.get_uniform_location(gl, &model);
gl.uniform_matrix_4_f32_slice(l.as_ref(), false, self.model.model().as_slice());
}
} }
pub fn on_mouse_scroll( pub fn model(&self) -> &Matrix4<f32> {
&mut self, self.model.model()
gl: &glow::Context,
program: &mut Program,
x: f32,
y: f32,
dz: f32,
) {
self.zoom += dz;
self.projection = nalgebra_glm::perspective(self.aspect, self.zoom, self.znear, self.zfar);
unsafe {
let model = self.snippet.find_symbol("trackball_projection").unwrap();
let l = program.get_uniform_location(gl, &model);
gl.uniform_matrix_4_f32_slice(l.as_ref(), false, self.model.model().as_slice());
}
}
fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> Result<()> {
unsafe {
let model = self.snippet.find_symbol("trackball_model").unwrap();
let l = program.get_uniform_location(gl, &model);
gl.uniform_matrix_4_f32_slice(l.as_ref(), false, self.model.model().as_slice());
let projection = self.snippet.find_symbol("trackball_projection").unwrap();
let l = program.get_uniform_location(gl, &projection);
gl.uniform_matrix_4_f32_slice(l.as_ref(), false, self.projection.as_slice());
let view = self.snippet.find_symbol("trackball_view").unwrap();
let l = program.get_uniform_location(gl, &view);
gl.uniform_matrix_4_f32_slice(l.as_ref(), false, self.view.as_slice());
}
Ok(())
} }
} }
@ -239,7 +169,13 @@ impl Transform for Trackball {
impl AttaWithProgram for Trackball { 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<()> {
self.attach_with_program(gl, program) unsafe {
let model = self.snippet.find_symbol("trackball_model").unwrap();
let l = program.get_uniform_location(gl, &model);
gl.uniform_matrix_4_f32_slice(l.as_ref(), false, self.model.model().as_slice());
}
Ok(())
} }
} }

View File

@ -1,83 +1,16 @@
use std::cell::RefCell; mod ui;
use std::rc::Rc; use pg::App;
use data_loader::Data;
use graphics::colormap::linear::LinearColormap;
use graphics::ppi::PPI;
use graphics::transforms::position::Position;
use graphics::transforms::viewport::Viewport;
use graphics::{AttaWithBuffer, Graphics, AttaWithWindow};
use imgui::Condition;
mod camera; mod camera;
mod components; mod components;
mod data_loader; mod data_loader;
mod errors; mod errors;
mod graphics; mod graphics;
mod pg;
mod support; mod support;
mod utils; mod utils;
use imgui::*; use support::supporter::run;
mod final_pg;
fn main() { fn main() {
env_logger::init(); env_logger::init();
run(move |gl| App::new(gl).unwrap());
let transform = Position::new().unwrap();
let mut viewport = Viewport::new().unwrap();
viewport.set_global(0.0, 0.0, 600.0, 800.0);
let mut cmap = LinearColormap::new().unwrap();
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 mut ppi = PPI::new().unwrap();
ppi.set_transform(&transform);
ppi.set_viewport(&viewport);
ppi.set_colormap(Box::new(cmap));
let ppi = Rc::new(RefCell::new(ppi));
let registers = vec![ppi.clone()];
let registers = registers.into_iter().map(|r| {
r as Rc<RefCell<dyn Graphics>>
}).collect();
support::supporter::init(move |run, ui, window, gl| {
let mut ppi = ppi.borrow_mut();
let texture = ppi.attach_with_window(gl).unwrap();
ui.window("test").build(||{
if ui.button("load") {
let data = Data::from_path(r#"C:\Users\qwin7\Downloads\ZJSXAA_20230113070200_R.dat.gz"#).unwrap();
ppi.attach_with_buffer(gl, &data).unwrap();
}
});
ui.window("Test").size([200.0,400.0], imgui::Condition::FirstUseEver).build(|| {
imgui::Image::new(texture, [200.0, 400.0]).build(ui);
});
},
registers,
);
} }

740
src/pg.rs Normal file
View File

@ -0,0 +1,740 @@
use crate::data_loader::Data;
use crate::graphics::colormap::linear::LinearColormap;
use crate::graphics::ppi::PPIConfig;
use crate::graphics::transforms::position::Position;
use crate::graphics::transforms::viewport::Viewport;
use crate::graphics::transforms::ChainedTransform;
use crate::graphics::{ppi::PPI, Graphics};
use crate::graphics::{AttaWithBuffer, AttaWithProgram, Config, MouseState};
use crate::{errors::*, ui::base};
use glow::{HasContext, NativeBuffer, NativeFramebuffer, NativeTexture, NativeVertexArray};
use imgui::{ImStr, ImString, Textures, Ui};
use log::info;
use serde::de;
use std::collections::HashSet;
use std::{cell::RefCell, collections::HashMap, rc::Rc};
use winit::window;
pub type Graphic<Data> = Rc<RefCell<dyn Graphics<Data = Data>>>;
type RcGraphic<T> = Rc<RefCell<T>>;
pub struct App<'a> {
pub ui_state: State,
gl: &'a glow::Context,
viewport: Viewport,
windows: HashMap<ImString, WindowData>,
programs: [Graphic<Data>; 1],
pub ppi_module: RcGraphic<PPI>,
program_with_window: HashMap<usize, Vec<ImString>>,
// Auto clean up
all_vaos: HashMap<NativeVertexArray, usize>,
all_other_buffers: HashMap<NativeBuffer, usize>,
all_framebuffers: HashMap<NativeFramebuffer, usize>,
all_frametextures: HashMap<NativeTexture, usize>,
}
impl<'a> App<'a> {
pub fn new(gl: &'a glow::Context) -> Result<Self> {
let viewport = Viewport::new()?;
let mut cmap = LinearColormap::new().unwrap();
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 cmap = Box::new(cmap);
let mut ppi = PPI::new()?;
ppi.set_viewport(&viewport);
ppi.set_colormap(cmap);
let ppi = Rc::new(RefCell::new(ppi));
let programs = [ppi.clone() as Graphic<Data>];
Ok(Self {
ui_state: State {},
viewport,
programs,
windows: HashMap::new(),
ppi_module: ppi,
gl,
program_with_window: HashMap::new(),
all_vaos: HashMap::with_capacity(30),
all_other_buffers: HashMap::with_capacity(30),
all_framebuffers: HashMap::with_capacity(30),
all_frametextures: HashMap::with_capacity(30),
})
}
pub fn render(&mut self) {
let mut need_clean = false;
for (id, program) in self.programs.iter().enumerate() {
let mut p = program.borrow_mut();
if self.program_with_window.len() == 0 {
return;
}
p.mount(&self.gl).unwrap();
self.program_with_window.get(&id).map(|windows| {
for window in windows.iter() {
let window_info = self.windows.get_mut(window).unwrap();
if !window_info.need_redraw {
continue;
}
let conf = if window_info.re_init {
window_info.config.as_ref()
} else {
None
};
{
p.set_config(self.gl, conf).unwrap();
window_info.re_init = false;
}
unsafe {
self.gl
.bind_framebuffer(glow::FRAMEBUFFER, window_info.framebuffer);
let attach = window_info.attach.as_ref();
if attach.is_some() {
self.gl.bind_vertex_array(Some(attach.unwrap().vao));
}
if attach.is_some() {
let window_size = window_info.size;
self.gl
.viewport(0, 0, window_size[0] as i32, window_size[1] as i32);
p.draw(&self.gl, attach.as_ref().unwrap().len).unwrap();
}
if attach.is_some() {
self.gl.bind_vertex_array(None);
}
self.gl.bind_framebuffer(glow::FRAMEBUFFER, None);
window_info.need_redraw = false;
need_clean = true;
}
}
});
p.unmount(&self.gl).unwrap();
}
if need_clean {
self.clean();
}
}
pub fn render_ui(&mut self, ui: &Ui, window: &winit::window::Window, run: &mut bool) {
base(ui, window, run, self);
}
pub fn create_framebuffer(
&mut self,
id: &str,
size: (i32, i32),
) -> Result<(NativeFramebuffer, NativeTexture)> {
let id = &ImString::new(id);
let gl = self.gl;
let tex = unsafe {
let already = self.windows.contains_key(id)
&& self.windows.get(id).unwrap().framebuffer.is_some();
if already {
return Ok((
self.windows[id].framebuffer.unwrap(),
self.windows[id].frametexture.unwrap(),
));
}
let framebuffer = gl.create_framebuffer().unwrap();
gl.bind_framebuffer(glow::FRAMEBUFFER, Some(framebuffer));
let texture = gl.create_texture().unwrap();
gl.bind_texture(glow::TEXTURE_2D, Some(texture));
gl.tex_image_2d(
glow::TEXTURE_2D,
0,
glow::RGB8 as i32,
size.0,
size.1,
0,
glow::RGB,
glow::UNSIGNED_BYTE,
None,
);
gl.tex_parameter_i32(
glow::TEXTURE_2D,
glow::TEXTURE_MIN_FILTER,
glow::LINEAR as i32,
);
gl.tex_parameter_i32(
glow::TEXTURE_2D,
glow::TEXTURE_MAG_FILTER,
glow::LINEAR as i32,
);
gl.framebuffer_texture_2d(
glow::FRAMEBUFFER,
glow::COLOR_ATTACHMENT0,
glow::TEXTURE_2D,
Some(texture),
0,
);
assert_eq!(
gl.check_framebuffer_status(glow::FRAMEBUFFER),
glow::FRAMEBUFFER_COMPLETE
);
gl.bind_framebuffer(glow::FRAMEBUFFER, None);
gl.bind_texture(glow::TEXTURE_2D, None);
self.all_framebuffers_add(&framebuffer);
self.all_frametextures_add(&texture);
(framebuffer, texture)
};
Ok(tex)
}
pub fn prepare(&mut self) {
for program in self.programs.iter() {
let mut p = program.borrow_mut();
p.compile(&self.gl).unwrap();
}
}
pub fn destroy(&mut self) {
for p in self.programs.iter() {
let mut p = p.borrow_mut();
p.unmount(&self.gl).unwrap();
p.destroy(&self.gl).unwrap();
}
info!("Cleaning up all resources");
unsafe {
for vao in self.all_vaos.keys() {
self.gl.delete_vertex_array(*vao);
}
for vbo in self.all_other_buffers.keys() {
self.gl.delete_buffer(*vbo);
}
for framebuffer in self.all_framebuffers.keys() {
self.gl.delete_framebuffer(*framebuffer);
}
for texture in self.all_frametextures.keys() {
self.gl.delete_texture(*texture);
}
}
}
pub fn create_ppi_render(&mut self, id: &str, config: Option<PPIConfig>) {
let id = &ImString::new(id);
let (vao, vbo, ebo) = self.ppi_module.borrow().init(&self.gl);
self.windows.get_mut(id).map(|w| {
w.attach = Some(Attach {
vao,
vbo,
ebo,
len: 0,
});
w.need_redraw = true;
w.program = 0;
w.config = Some(config.unwrap_or_default().into());
});
let v = self.program_with_window.entry(0).or_insert(vec![]);
v.push(id.clone());
self.all_vaos_add(&vao);
self.all_other_buffers_add(&vbo);
ebo.map(|ebo| self.all_other_buffers_add(&ebo));
}
pub fn bind_data(&mut self, id: &str, data: &Data) -> Result<()> {
let id = &ImString::new(id);
use bytemuck::cast_slice;
let window = self.windows.get_mut(id).unwrap();
let program = window.program;
let program = self.programs[program].borrow();
let data = program.bake(data)?;
assert!(window.attach.is_some());
let attach = window.attach.as_mut().unwrap();
attach.len = data.2;
unsafe {
self.gl.bind_buffer(glow::VERTEX_ARRAY, Some(attach.vbo));
self.gl.buffer_data_u8_slice(
glow::ARRAY_BUFFER,
cast_slice(data.0.as_slice()),
glow::STATIC_DRAW,
);
if let Some(ebo) = attach.ebo {
self.gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, attach.ebo);
self.gl.buffer_data_u8_slice(
glow::ELEMENT_ARRAY_BUFFER,
cast_slice(&data.1.as_ref().unwrap()),
glow::STATIC_DRAW,
);
self.gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, None);
}
self.gl.bind_buffer(glow::VERTEX_ARRAY, None);
}
Ok(())
}
fn all_framebuffers_add(&mut self, framebuffer: &NativeFramebuffer) {
self.all_framebuffers
.entry(*framebuffer)
.and_modify(|v| *v += 1)
.or_insert(1);
info!(
"Framebuffer: {:?} + 1, Framebuffer {:?}: {}",
framebuffer, framebuffer, self.all_framebuffers[framebuffer]
);
}
fn all_framebuffers_minus(&mut self, framebuffer: &NativeFramebuffer) {
self.all_framebuffers
.entry(*framebuffer)
.and_modify(|v| *v -= 1);
info!(
"Framebuffer: {:?} - 1, Framebuffer {:?}: {}",
framebuffer, framebuffer, self.all_framebuffers[framebuffer]
);
}
fn all_frametextures_add(&mut self, texture: &NativeTexture) {
self.all_frametextures
.entry(*texture)
.and_modify(|v| *v += 1)
.or_insert(1);
info!(
"Texture: {:?} + 1, Frametexture {:?}: {}",
texture, texture, self.all_frametextures[texture]
);
}
fn all_frametextures_minus(&mut self, texture: &NativeTexture) {
self.all_frametextures
.entry(*texture)
.and_modify(|v| *v -= 1);
info!(
"Texture: {:?} - 1, Frametexture {:?}: {}",
texture, texture, self.all_frametextures[texture]
);
}
fn all_vaos_add(&mut self, vao: &NativeVertexArray) {
self.all_vaos
.entry(*vao)
.and_modify(|v| *v += 1)
.or_insert(1);
info!("Vao: {:?} + 1, Vao {:?}: {}", vao, vao, self.all_vaos[vao]);
}
fn all_vaos_minus(&mut self, vao: &NativeVertexArray) {
self.all_vaos.entry(*vao).and_modify(|v| *v -= 1);
info!("Vao: {:?} - 1, Vao {:?}: {}", vao, vao, self.all_vaos[vao]);
}
fn all_other_buffers_add(&mut self, buffer: &NativeBuffer) {
self.all_other_buffers
.entry(*buffer)
.and_modify(|v| *v += 1)
.or_insert(1);
info!(
"Buffer: {:?} + 1, Buffer {:?}: {}",
buffer, buffer, self.all_other_buffers[buffer]
);
}
fn all_other_buffers_minus(&mut self, buffer: &NativeBuffer) {
self.all_other_buffers
.entry(*buffer)
.and_modify(|v| *v -= 1);
info!(
"Buffer: {:?} - 1, Buffer {:?}: {}",
buffer, buffer, self.all_other_buffers[buffer]
);
}
pub fn show_window(&mut self, ui: &Ui) {
let mut need_resize = vec![];
for (id, window) in self.windows.iter_mut() {
ui.window(&window.title)
.size(window.size, imgui::Condition::FirstUseEver)
.opened(&mut window.open)
.flags(imgui::WindowFlags::NO_SCROLLBAR)
.build(|| {
if ui.is_mouse_clicked(imgui::MouseButton::Left) {
let io = ui.io();
let pos = io.mouse_pos;
window.last_mouse_position = pos;
}
if ui.is_mouse_dragging(imgui::MouseButton::Left) {
let delta = ui.mouse_drag_delta();
window.last_mouse_delta = delta;
window.accmulate_mouse_delta = [
window.accmulate_mouse_delta[0] + delta[0],
window.accmulate_mouse_delta[1] + delta[1],
];
window.motion = Some(MouseState::Drag {
from: window.last_mouse_position,
delta: delta,
});
}
if ui.is_mouse_released(imgui::MouseButton::Left) {
if window.size != ui.window_size() {
window.size = ui.window_size();
println!("resized: {:?}", window.size);
need_resize.push((window.title.clone(), ui.window_size()));
}
}
if let Some(texture) = window.frametexture {
let cursor = ui.cursor_pos();
imgui::Image::new(
imgui::TextureId::new(texture.0.get() as usize),
ui.window_size(),
)
.build(ui);
ui.set_cursor_pos(cursor);
if ui.invisible_button(&window.title, ui.window_size()) {
let io = ui.io();
let pos = io.mouse_pos;
let window_pos = ui.window_pos();
let related_pos = [pos[0] - window_pos[0], pos[1] - window_pos[1]];
}
}
});
}
for (id, size) in need_resize.iter() {
self.reset_window_size(id, *size);
}
}
// pub fn copy_window_resource(
// &mut self,
// src: &str,
// dst: &str,
// stick: bool,
// ) -> Option<NativeTexture> {
// let src = &ImString::new(src);
// let window_info = self.windows.get(src).unwrap();
// let new_texture = if stick {
// let new_framebuffer_tex = self.create_framebuffer(dst, (300, 300)).unwrap();
// unsafe {
// self.gl
// .bind_framebuffer(glow::READ_FRAMEBUFFER, window_info.framebuffer);
// self.gl
// .bind_framebuffer(glow::DRAW_FRAMEBUFFER, Some(self.framebuffers[dst].0));
// self.gl.blit_framebuffer(
// 0,
// 0,
// 300,
// 300,
// 0,
// 0,
// 300,
// 300,
// glow::COLOR_BUFFER_BIT,
// glow::NEAREST,
// );
// self.gl.bind_framebuffer(glow::READ_FRAMEBUFFER, None);
// self.gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, None);
// }
// self.framebuffers
// .get_mut(dst)
// .map(|(_, redraw, program, atta)| {
// *atta = new_framebuffer.as_ref().map(|v| v.3.clone()).flatten();
// *redraw = true;
// *program = new_framebuffer.as_ref().map(|v| v.2).unwrap();
// });
// Some(new_framebuffer_tex)
// } else {
// let texture = self.frametextures.get(src).map(|texture| *texture);
// if let Some(ref framebuffer) = new_framebuffer {
// if let Some(ref texture) = texture {
// self.all_framebuffers_add(&framebuffer.0);
// self.all_frametextures_add(&texture);
// self.framebuffers
// .insert(ImString::new(dst), framebuffer.clone());
// self.frametextures
// .insert(ImString::new(dst), texture.clone());
// }
// }
// texture
// };
// new_framebuffer.map(|framebuffer| {
// new_texture.map(|_| {
// self.all_vaos_add(&framebuffer.3.as_ref().unwrap().vao);
// self.all_other_buffers_add(&framebuffer.3.as_ref().unwrap().vbo);
// framebuffer.3.as_ref().unwrap().ebo.map(|ebo| {
// self.all_other_buffers_add(&ebo);
// });
// self.program_with_window.get_mut(&framebuffer.2).map(|v| {
// v.push(ImString::new(dst));
// });
// });
// });
// new_texture
// }
pub fn create_render_window(&mut self, title: &str, size: [f32; 2]) -> Result<()> {
// Insert the window data into the windows hashmap
let id = ImString::new(title);
let mut data = WindowData::new(id.clone(), size);
let (fb, tex) =
self.create_framebuffer(title, (size[0].floor() as i32, size[1].floor() as i32))?;
data.framebuffer = Some(fb);
data.frametexture = Some(tex);
self.windows.insert(id, data);
Ok(())
}
pub fn set_config(&mut self, id: &str) -> Option<&mut Config> {
let id = &ImString::new(id);
self.windows
.get_mut(id)
.map(|v| {
v.re_init = true;
v.config.as_mut()
})
.flatten()
}
fn reset_window_size(&mut self, id: &ImString, size: [f32; 2]) {
let window_info = self.windows.get_mut(id).unwrap();
window_info.need_redraw = true;
let tex = unsafe {
self.gl
.bind_framebuffer(glow::FRAMEBUFFER, window_info.framebuffer);
let texture = self.gl.create_texture().unwrap();
self.gl.bind_texture(glow::TEXTURE_2D, Some(texture));
self.gl.tex_image_2d(
glow::TEXTURE_2D,
0,
glow::RGB8 as i32,
size[0].floor() as i32,
size[1].floor() as i32,
0,
glow::RGB,
glow::UNSIGNED_BYTE,
None,
);
self.gl.tex_parameter_i32(
glow::TEXTURE_2D,
glow::TEXTURE_MIN_FILTER,
glow::LINEAR as i32,
);
self.gl.tex_parameter_i32(
glow::TEXTURE_2D,
glow::TEXTURE_MAG_FILTER,
glow::LINEAR as i32,
);
self.gl.framebuffer_texture_2d(
glow::FRAMEBUFFER,
glow::COLOR_ATTACHMENT0,
glow::TEXTURE_2D,
Some(texture),
0,
);
assert_eq!(
self.gl.check_framebuffer_status(glow::FRAMEBUFFER),
glow::FRAMEBUFFER_COMPLETE
);
self.gl.bind_framebuffer(glow::FRAMEBUFFER, None);
self.gl.bind_texture(glow::TEXTURE_2D, None);
texture
};
let raw_tex = window_info.frametexture.as_ref().unwrap().to_owned();
self.all_frametextures_minus(&raw_tex);
self.all_frametextures_add(&tex);
}
pub fn destroy_window(&mut self) {
let ids: Vec<_> = self
.windows
.iter()
.filter(|v| v.1.open == false)
.map(|v| v.0.clone())
.collect();
for id in ids.iter() {
let window = self.windows.remove(id).unwrap();
window.framebuffer.map(|framebuffer| {
self.all_framebuffers_minus(&framebuffer);
});
window.frametexture.map(|texture| {
self.all_frametextures_minus(&texture);
});
if let Some(atta) = window.attach {
self.all_vaos_minus(&atta.vao);
self.all_other_buffers_minus(&atta.vbo);
atta.ebo.map(|ebo| {
self.all_other_buffers_minus(&ebo);
});
}
}
}
fn clean(&mut self) {
info!("Cleaning up unused resources");
unsafe {
self.all_framebuffers
.iter()
.filter(|v| *v.1 == 0)
.for_each(|(bf, _)| {
info!("Deleting framebuffer: {:?}", bf);
self.gl.delete_framebuffer(*bf);
});
self.all_frametextures
.iter()
.filter(|v| *v.1 == 0)
.for_each(|(bf, _)| {
info!("Deleting texture: {:?}", bf);
self.gl.delete_texture(*bf);
});
self.all_vaos
.iter()
.filter(|v| *v.1 == 0)
.for_each(|(bf, _)| {
info!("Deleting vao: {:?}", bf);
self.gl.delete_vertex_array(*bf);
});
self.all_other_buffers
.iter()
.filter(|v| *v.1 == 0)
.for_each(|(bf, _)| {
info!("Deleting buffer: {:?}", bf);
self.gl.delete_buffer(*bf);
});
}
self.all_framebuffers.retain(|_, v| *v > 0);
self.all_frametextures.retain(|_, v| *v > 0);
self.all_vaos.retain(|_, v| *v > 0);
self.all_other_buffers.retain(|_, v| *v > 0);
}
}
#[derive(Debug, Clone)]
pub struct Attach {
pub vao: NativeVertexArray,
pub vbo: NativeBuffer,
pub ebo: Option<NativeBuffer>,
pub len: i32,
}
pub struct State {}
pub struct WindowData {
pub title: ImString,
pub open: bool,
pub copy_from: Option<ImString>,
pub size: [f32; 2],
framebuffer: Option<NativeFramebuffer>,
frametexture: Option<NativeTexture>,
need_redraw: bool,
program: usize,
attach: Option<Attach>,
re_init: bool,
last_mouse_position: [f32; 2],
last_mouse_delta: [f32; 2],
accmulate_mouse_delta: [f32; 2],
mouse_position: [f32; 2],
motion: Option<MouseState>,
config: Option<Config>,
}
impl WindowData {
pub fn new(title: ImString, size: [f32; 2]) -> Self {
Self {
title,
open: true,
copy_from: None,
size,
last_mouse_position: [0.0, 0.0],
last_mouse_delta: [0.0, 0.0],
accmulate_mouse_delta: [0.0, 0.0],
mouse_position: [0.0, 0.0],
motion: None,
framebuffer: None,
frametexture: None,
need_redraw: false,
program: 0,
attach: None,
re_init: false,
config: None,
}
}
fn set_current_mouse_delta(&mut self, delta: [f32; 2]) {
self.last_mouse_delta = delta;
self.accmulate_mouse_delta = [
self.accmulate_mouse_delta[0] + delta[0],
self.accmulate_mouse_delta[1] + delta[1],
];
}
fn set_mouse_postion(&mut self, pos: [f32; 2]) {
self.mouse_position = pos;
}
}

215
src/support/_s.rs Normal file
View File

@ -0,0 +1,215 @@
use std::num::NonZeroU32;
use glow::HasContext;
use glutin::{
config::ConfigTemplateBuilder,
context::{ContextApi, ContextAttributesBuilder, NotCurrentGlContext, PossiblyCurrentContext},
display::{GetGlDisplay, GlDisplay},
surface::{GlSurface, Surface, SurfaceAttributesBuilder, SwapInterval, WindowSurface},
};
use imgui_winit_support::WinitPlatform;
use raw_window_handle::HasRawWindowHandle;
use winit::{
dpi::LogicalSize,
event_loop::EventLoop,
window::{Window, WindowBuilder},
};
pub fn create_window(
title: &str,
context_api: Option<ContextApi>,
) -> (
EventLoop<()>,
Window,
Surface<WindowSurface>,
PossiblyCurrentContext,
) {
let event_loop = EventLoop::new().unwrap();
let window_builder = WindowBuilder::new()
.with_title(title)
.with_inner_size(LogicalSize::new(1024, 768));
let (window, cfg) = glutin_winit::DisplayBuilder::new()
.with_window_builder(Some(window_builder))
.build(&event_loop, ConfigTemplateBuilder::new(), |mut configs| {
configs.next().unwrap()
})
.expect("Failed to create OpenGL window");
let window = window.unwrap();
let mut context_attribs = ContextAttributesBuilder::new();
if let Some(context_api) = context_api {
context_attribs = context_attribs.with_context_api(context_api);
}
let context_attribs = context_attribs.build(Some(window.raw_window_handle()));
let context = unsafe {
cfg.display()
.create_context(&cfg, &context_attribs)
.expect("Failed to create OpenGL context")
};
let surface_attribs = SurfaceAttributesBuilder::<WindowSurface>::new()
.with_srgb(Some(true))
.build(
window.raw_window_handle(),
NonZeroU32::new(1024).unwrap(),
NonZeroU32::new(768).unwrap(),
);
let surface = unsafe {
cfg.display()
.create_window_surface(&cfg, &surface_attribs)
.expect("Failed to create OpenGL surface")
};
let context = context
.make_current(&surface)
.expect("Failed to make OpenGL context current");
surface
.set_swap_interval(&context, SwapInterval::Wait(NonZeroU32::new(1).unwrap()))
.expect("Failed to set swap interval");
(event_loop, window, surface, context)
}
pub fn glow_context(context: &PossiblyCurrentContext) -> glow::Context {
unsafe {
glow::Context::from_loader_function_cstr(|s| context.display().get_proc_address(s).cast())
}
}
pub fn imgui_init(window: &Window) -> (WinitPlatform, imgui::Context) {
let mut imgui_context = imgui::Context::create();
imgui_context.set_ini_filename(None);
let mut winit_platform = WinitPlatform::init(&mut imgui_context);
winit_platform.attach_window(
imgui_context.io_mut(),
window,
imgui_winit_support::HiDpiMode::Rounded,
);
imgui_context
.fonts()
.add_font(&[imgui::FontSource::DefaultFontData { config: None }]);
imgui_context.io_mut().font_global_scale = (1.0 / winit_platform.hidpi_factor()) as f32;
(winit_platform, imgui_context)
}
pub struct Triangler {
pub program: <glow::Context as HasContext>::Program,
pub vertex_array: <glow::Context as HasContext>::VertexArray,
}
impl Triangler {
pub fn new(gl: &glow::Context, shader_header: &str) -> Self {
const VERTEX_SHADER_SOURCE: &str = r#"
const vec2 verts[3] = vec2[3](
vec2(0.5f, 1.0f),
vec2(0.0f, 0.0f),
vec2(1.0f, 0.0f)
);
out vec2 vert;
out vec4 color;
vec4 srgb_to_linear(vec4 srgb_color) {
// Calcuation as documented by OpenGL
vec3 srgb = srgb_color.rgb;
vec3 selector = ceil(srgb - 0.04045);
vec3 less_than_branch = srgb / 12.92;
vec3 greater_than_branch = pow((srgb + 0.055) / 1.055, vec3(2.4));
return vec4(
mix(less_than_branch, greater_than_branch, selector),
srgb_color.a
);
}
void main() {
vert = verts[gl_VertexID];
color = srgb_to_linear(vec4(vert, 0.5, 1.0));
gl_Position = vec4(vert - 0.5, 0.0, 1.0);
}
"#;
const FRAGMENT_SHADER_SOURCE: &str = r#"
in vec2 vert;
in vec4 color;
out vec4 frag_color;
vec4 linear_to_srgb(vec4 linear_color) {
vec3 linear = linear_color.rgb;
vec3 selector = ceil(linear - 0.0031308);
vec3 less_than_branch = linear * 12.92;
vec3 greater_than_branch = pow(linear, vec3(1.0/2.4)) * 1.055 - 0.055;
return vec4(
mix(less_than_branch, greater_than_branch, selector),
linear_color.a
);
}
void main() {
frag_color = linear_to_srgb(color);
}
"#;
let mut shaders = [
(glow::VERTEX_SHADER, VERTEX_SHADER_SOURCE, None),
(glow::FRAGMENT_SHADER, FRAGMENT_SHADER_SOURCE, None),
];
unsafe {
let vertex_array = gl
.create_vertex_array()
.expect("Cannot create vertex array");
let program = gl.create_program().expect("Cannot create program");
for (kind, source, handle) in &mut shaders {
let shader = gl.create_shader(*kind).expect("Cannot create shader");
gl.shader_source(shader, &format!("{}\n{}", shader_header, *source));
gl.compile_shader(shader);
if !gl.get_shader_compile_status(shader) {
panic!("{}", gl.get_shader_info_log(shader));
}
gl.attach_shader(program, shader);
*handle = Some(shader);
}
gl.link_program(program);
if !gl.get_program_link_status(program) {
panic!("{}", gl.get_program_info_log(program));
}
for &(_, _, shader) in &shaders {
gl.detach_shader(program, shader.unwrap());
gl.delete_shader(shader.unwrap());
}
Self {
program,
vertex_array,
}
}
}
pub fn render(&self, gl: &glow::Context) {
unsafe {
gl.clear_color(0.05, 0.05, 0.1, 1.0);
gl.clear(glow::COLOR_BUFFER_BIT);
gl.use_program(Some(self.program));
gl.bind_vertex_array(Some(self.vertex_array));
gl.draw_arrays(glow::TRIANGLES, 0, 3);
}
}
pub fn destroy(&self, gl: &glow::Context) {
unsafe {
gl.delete_program(self.program);
gl.delete_vertex_array(self.vertex_array);
}
}
}

View File

@ -1,8 +1,4 @@
use crate::camera::Camera; use crate::pg::App;
use crate::graphics::colormap::linear::LinearColormap;
use crate::graphics::ppi::PPI;
use crate::graphics::transforms::{position, ChainedTransform};
use crate::graphics::{hello, AttaWithBuffer, AttaWithProgram, Graphics};
use crate::{ use crate::{
graphics::{ graphics::{
collections::agg_fast_path::AggFastPath, collections::agg_fast_path::AggFastPath,
@ -12,7 +8,6 @@ use crate::{
}, },
utils::Triangler, utils::Triangler,
}; };
use cgmath::InnerSpace;
use glow::HasContext; use glow::HasContext;
use glutin::{ use glutin::{
config::ConfigTemplateBuilder, config::ConfigTemplateBuilder,
@ -32,34 +27,34 @@ use imgui_winit_support::{
use nalgebra_glm::perspective; use nalgebra_glm::perspective;
use nalgebra_glm::Vec3; use nalgebra_glm::Vec3;
use raw_window_handle::HasRawWindowHandle; use raw_window_handle::HasRawWindowHandle;
use std::cell::RefCell;
use std::num::NonZeroU32; use std::num::NonZeroU32;
use std::rc::Rc;
use std::time::Instant; use std::time::Instant;
pub fn init<FUi>(mut run_ui: FUi, mut register: Vec<Rc<RefCell<dyn Graphics>>>) pub fn run<F>(mut app: F)
where where
FUi: FnMut(&mut bool, &mut Ui, &Window, &glow::Context) + 'static, F: for<'b> FnMut(&'b glow::Context) -> App<'b>,
{ {
// Create Window
let (event_loop, window, surface, context) = create_window(); let (event_loop, window, surface, context) = create_window();
let (mut winit_platform, mut imgui_context) = imgui_init(&window); let (mut winit_platform, mut imgui_context) = imgui_init(&window);
let gl = unsafe { // OpenGL context
let gl = glow_context(&context); let gl = glow_context(&context);
gl.enable(glow::DEPTH_TEST);
gl.enable(glow::BLEND);
gl.blend_func(glow::SRC_ALPHA, glow::ONE_MINUS_SRC_ALPHA);
gl
};
// OpenGL renderer from this crate // OpenGL renderer from this crate
let mut ig_renderer = imgui_glow_renderer::AutoRenderer::initialize(gl, &mut imgui_context) let mut ig_renderer = imgui_glow_renderer::AutoRenderer::initialize(gl, &mut imgui_context)
.expect("failed to create renderer"); .expect("failed to create renderer");
let gl_app = ig_renderer.gl_context().clone();
let gl_context = ig_renderer.gl_context().clone(); let gl_context = ig_renderer.gl_context().clone();
for r in register.iter_mut() { // let mut run = true;
r.borrow_mut().compile(&gl_context).unwrap(); let mut app = app(&gl_app);
}
let mut run = true;
// Prepare
app.prepare();
let mut last_frame = Instant::now(); let mut last_frame = Instant::now();
@ -86,32 +81,15 @@ where
} => { } => {
// Render your custom scene, note we need to borrow the OpenGL // Render your custom scene, note we need to borrow the OpenGL
// context from the `AutoRenderer`, which takes ownership of it. // context from the `AutoRenderer`, which takes ownership of it.
unsafe { unsafe {
gl_context.clear(glow::DEPTH_BUFFER_BIT); gl_context.clear(glow::COLOR_BUFFER_BIT | glow::DEPTH_BUFFER_BIT);
gl_context.clear(glow::COLOR_BUFFER_BIT);
} }
app.render();
let ui = imgui_context.frame(); let ui = imgui_context.frame();
app.render_ui(&ui, &window, &mut run);
if ui.is_mouse_pos_valid(ui.io().mouse_pos) { winit_platform.prepare_render(ui, &window);
let mouse_pos = ui.io().mouse_pos;
if ui.is_mouse_dragging(imgui::MouseButton::Right) {
}
}
for r in register.iter_mut() {
r.borrow_mut().draw(&gl_context).unwrap();
}
let mut run = true;
run_ui(&mut run, ui, &window, ig_renderer.gl_context());
if !run {
window_target.exit();
}
let draw_data = imgui_context.render(); let draw_data = imgui_context.render();
// Render imgui on top of it // Render imgui on top of it
@ -140,16 +118,11 @@ where
NonZeroU32::new(new_size.width).unwrap(), NonZeroU32::new(new_size.width).unwrap(),
NonZeroU32::new(new_size.height).unwrap(), NonZeroU32::new(new_size.height).unwrap(),
); );
} }
winit_platform.handle_event(imgui_context.io_mut(), &window, &event); winit_platform.handle_event(imgui_context.io_mut(), &window, &event);
} }
winit::event::Event::LoopExiting => { winit::event::Event::LoopExiting => {
app.destroy();
for r in register.iter_mut() {
r.borrow_mut().destroy(&gl_context).unwrap();
}
} }
event => { event => {
winit_platform.handle_event(imgui_context.io_mut(), &window, &event); winit_platform.handle_event(imgui_context.io_mut(), &window, &event);
@ -159,51 +132,6 @@ where
.unwrap() .unwrap()
} }
fn mouse_callback(
last_position: &mut Option<PhysicalPosition<f64>>,
current_position: PhysicalPosition<f64>,
sensitivity: f64,
pitch: &mut f64,
yaw: &mut f64,
camera: &mut Camera,
) {
use cgmath::{Deg, Euler, Quaternion};
let xpos = current_position.x;
let ypos = current_position.y;
if last_position.is_none() {
*last_position = Some(PhysicalPosition::new(xpos, ypos));
}
let _last_position = last_position.unwrap();
let mut xoffset = xpos - _last_position.x;
let mut yoffset = _last_position.y - ypos; // reversed since y-coordinates go from bottom to top
*last_position = Some(PhysicalPosition::new(xpos, ypos));
xoffset *= sensitivity;
yoffset *= sensitivity;
*yaw += xoffset;
*pitch += yoffset;
if *pitch > 89.0 {
*pitch = 89.0;
}
if *pitch < -89.0 {
*pitch = -89.0;
}
let euler_deg = Euler::new(Deg(*pitch), Deg(*yaw), Deg(0.0));
let c = Quaternion::from(euler_deg).normalize();
camera.set_front(Vec3::new(c.v.x as f32, c.v.y as f32, c.v.z as f32));
}
fn create_window() -> ( fn create_window() -> (
EventLoop<()>, EventLoop<()>,
Window, Window,

44
src/ui.rs Normal file
View File

@ -0,0 +1,44 @@
use crate::errors::*;
use crate::graphics::Config;
use crate::pg::App;
use crate::{data_loader::Data, pg::WindowData};
use glow::NativeTexture;
use imgui::{ImString, Ui};
pub fn base(ui: &Ui, window: &winit::window::Window, run: &mut bool, app: &mut App) {
ui.window("test")
.size([300.0, 200.0], imgui::Condition::FirstUseEver)
.build(|| {
if ui.button("PPI") {
let data =
load_data(r#"/Users/tsuki/Desktop/ZJSXAA_20230113070200_R.dat.gz"#).unwrap();
app.create_render_window("ppi", [300.0, 300.0]).unwrap();
app.create_ppi_render("ppi", None);
app.bind_data("ppi", &data).unwrap();
let (rdpi, adpi, _) = {
let ppi = app.ppi_module.borrow_mut();
ppi.data_info(&data).unwrap()
};
app.set_config("ppi").map(|config| {
if let Config::PPI(config) = config {
config.rdpi = rdpi;
config.adpi = adpi;
}
});
}
});
app.show_window(ui);
app.destroy_window();
}
fn create_display_window(title: &str, size: [f32; 2], copy_from: Option<ImString>) -> WindowData {
WindowData::new(ImString::new(title), size)
}
fn load_data(path: impl AsRef<std::path::Path>) -> Result<Data> {
let data = Data::from_path(path)?;
Ok(data)
}