This commit is contained in:
core 2023-11-10 13:35:33 -05:00
parent f709d1fb88
commit d7c399d0d7
Signed by: core
GPG Key ID: FDBF740DADDCEECF
5 changed files with 368 additions and 142 deletions

View File

@ -1,30 +1,30 @@
use crate::mode::Mode;
use nexrad2::message31::MOMENT_DATA_FOLDED;
pub fn correlation_coefficient(val: f32) -> &'static str {
pub fn correlation_coefficient(val: f32) -> [f32; 3] {
let gradient = [
(0.275, "black"),
(0.35, "darkgrey"),
(0.4, "gray"),
(0.5, "silver"),
(0.6, "midnightblue"),
(0.7, "darkblue"),
(0.8, "blue"),
(0.91, "green"),
(0.92, "yellowgreen"),
(0.93, "olivedrab"),
(0.94, "yellow"),
(0.95, "gold"),
(0.96, "orange"),
(0.97, "orangered"),
(0.98, "red"),
(0.99, "firebrick"),
(1.0, "maroon"),
(1.01, "darkmagenta"),
(1.02, "purple"),
(1.03, "mediumvioletred"),
(1.045, "pink"),
(1.05, "lavenderblush"),
(0.275, [0.0, 0.0, 0.0]),
(0.35, [169.0, 169.0, 169.0]),
(0.4, [128.0, 128.0, 128.0]),
(0.5, [192.0, 192.0, 192.0]),
(0.6, [25.0, 25.0, 112.0]),
(0.7, [0.0, 0.0, 139.0]),
(0.8, [0.0, 0.0, 255.0]),
(0.91, [0.0, 128.0, 0.0]),
(0.92, [154.0, 205.0, 50.0]),
(0.93, [107.0, 142.0, 35.0]),
(0.94, [255.0, 255.0, 0.0]),
(0.95, [255.0, 215.0, 0.0]),
(0.96, [255.0, 165.0, 0.0]),
(0.97, [255.0, 69.0, 0.0]),
(0.98, [255.0, 0.0, 0.0]),
(0.99, [178.0, 34.0, 34.0]),
(1.0, [128.0, 0.0, 0.0]),
(1.01, [139.0, 0.0, 139.0]),
(1.02, [128.0, 0.0, 128.0]),
(1.03, [199.0, 21.0, 133.0]),
(1.045, [255.0, 192.0, 203.0]),
(1.05, [255.0, 240.0, 245.0]),
];
for (threshold, color) in gradient {
@ -33,35 +33,35 @@ pub fn correlation_coefficient(val: f32) -> &'static str {
}
}
"white"
[255.0, 255.0, 255.0]
}
pub fn spectrum_width(val: f32) -> &'static str {
pub fn spectrum_width(val: f32) -> [f32; 3] {
let gradient = [
(1.0, "black"),
(2.0, "#222222"),
(3.0, "#333333"),
(4.0, "#444444"),
(5.0, "#555555"),
(6.0, "#666666"),
(7.0, "#777777"),
(8.0, "#888888"),
(9.0, "#999999"),
(10.0, "burlywood"),
(11.0, "sandybrown"),
(12.0, "gold"),
(13.0, "orange"),
(15.0, "orangered"),
(17.0, "red"),
(19.0, "firebrick"),
(23.0, "darkred"),
(25.0, "hotpink"),
(27.0, "fuchsia"),
(30.0, "lavender"),
(32.0, "white"),
(35.0, "yellow"),
(60.0, "lime"),
(1000.0, "purple"),
(1.0, [0.0, 0.0, 0.0]),
(2.0, [0x22 as f32, 0x22 as f32, 0x22 as f32]),
(3.0, [0x33 as f32, 0x33 as f32, 0x33 as f32]),
(4.0, [0x44 as f32, 0x44 as f32, 0x44 as f32]),
(5.0, [0x55 as f32, 0x55 as f32, 0x55 as f32]),
(6.0, [0x66 as f32, 0x66 as f32, 0x66 as f32]),
(7.0, [0x77 as f32, 0x77 as f32, 0x77 as f32]),
(8.0, [0x88 as f32, 0x88 as f32, 0x88 as f32]),
(9.0, [0x99 as f32, 0x99 as f32, 0x99 as f32]),
(10.0, [222.0, 184.0, 135.0]),
(11.0, [244.0, 164.0, 96.0]),
(12.0, [255.0, 215.0, 0.0]),
(13.0, [255.0, 165.0, 0.0]),
(15.0, [255.0, 69.0, 0.0]),
(17.0, [255.0, 0.0, 0.0]),
(19.0, [178.0, 34.0, 34.0]),
(23.0, [139.0, 0.0, 0.0]),
(25.0, [255.0, 105.0, 180.0]),
(27.0, [255.0, 0.0, 255.0]),
(30.0, [230.0, 230.0, 250.0]),
(32.0, [255.0, 255.0, 255.0]),
(35.0, [255.0, 255.0, 0.0]),
(60.0, [0.0, 255.0, 0.0]),
(1000.0, [128.0, 0.0, 128.0]),
];
for (threshold, color) in gradient {
@ -70,33 +70,33 @@ pub fn spectrum_width(val: f32) -> &'static str {
}
}
"white"
[255.0, 255.0, 255.0]
}
pub fn differential_reflectivity(val: f32) -> &'static str {
pub fn differential_reflectivity(val: f32) -> [f32; 3] {
let gradient = [
(-3.0, "black"),
(-1.0, "#333333"),
(-0.5, "#666666"),
(0.1, "#999999"),
(0.0, "#cccccc"),
(0.1, "white"),
(0.25, "navy"),
(0.5, "blue"),
(0.75, "deepskyblue"),
(1.0, "cyan"),
(1.25, "mediumaquamarine"),
(1.5, "lime"),
(1.75, "yellowgreen"),
(2.0, "yellow"),
(2.5, "gold"),
(3.0, "orange"),
(4.0, "orangered"),
(5.0, "red"),
(6.0, "maroon"),
(7.0, "hotpink"),
(10.0, "pink"),
(999.0, "white"),
(-3.0, [0.0, 0.0, 0.0]),
(-1.0, [0x33 as f32, 0x33 as f32, 0x33 as f32]),
(-0.5, [0x66 as f32, 0x66 as f32, 0x66 as f32]),
(0.1, [0x99 as f32, 0x99 as f32, 0x99 as f32]),
(0.0, [0xcc as f32, 0xcc as f32, 0xcc as f32]),
(0.1, [255.0, 255.0, 255.0]),
(0.25, [0.0, 0.0, 128.0]),
(0.5, [0.0, 0.0, 255.0]),
(0.75, [0.0, 191.0, 255.0]),
(1.0, [0.0, 255.0, 255.0]),
(1.25, [102.0, 205.0, 170.0]),
(1.5, [0.0, 255.0, 0.0]),
(1.75, [154.0, 205.0, 50.0]),
(2.0, [255.0, 255.0, 0.0]),
(2.5, [255.0, 215.0, 0.0]),
(3.0, [255.0, 165.0, 0.0]),
(4.0, [255.0, 69.0, 0.0]),
(5.0, [255.0, 0.0, 0.0]),
(6.0, [128.0, 0.0, 0.0]),
(7.0, [255.0, 105.0, 180.0]),
(10.0, [255.0, 192.0, 203.0]),
(999.0, [255.0, 255.0, 255.0]),
];
for (threshold, color) in gradient {
@ -105,82 +105,82 @@ pub fn differential_reflectivity(val: f32) -> &'static str {
}
}
"white"
[255.0, 255.0, 255.0]
}
pub fn dbz_noaa(dbz: f32) -> &'static str {
pub fn dbz_noaa(dbz: f32) -> [f32; 3] {
if dbz < 5.0 || dbz == MOMENT_DATA_FOLDED {
"#000000"
[0x00 as f32, 0x00 as f32, 0x00 as f32]
} else if dbz >= 5.0 && dbz < 10.0 {
"#40e8e3"
[0x40 as f32, 0xe8 as f32, 0xe3 as f32]
} else if dbz >= 10.0 && dbz < 15.0 {
"#26a4fa"
[0x26 as f32, 0xa4 as f32, 0xfa as f32]
} else if dbz >= 15.0 && dbz < 20.0 {
"#0030ed"
[0x00 as f32, 0x30 as f32, 0xed as f32]
} else if dbz >= 20.0 && dbz < 25.0 {
"#49fb3e"
[0x49 as f32, 0xfb as f32, 0x3e as f32]
} else if dbz >= 25.0 && dbz < 30.0 {
"#36c22e"
[0x36 as f32, 0xc2 as f32, 0x2e as f32]
} else if dbz >= 30.0 && dbz < 35.0 {
"#278c1e"
[0x27 as f32, 0x8c as f32, 0x1e as f32]
} else if dbz >= 35.0 && dbz < 40.0 {
"#fef543"
[0xfe as f32, 0xf5 as f32, 0x43 as f32]
} else if dbz >= 40.0 && dbz < 45.0 {
"#ebb433"
[0xeb as f32, 0xb4 as f32, 0x33 as f32]
} else if dbz >= 45.0 && dbz < 50.0 {
"#f6952e"
[0xf6 as f32, 0x95 as f32, 0x2e as f32]
} else if dbz >= 50.0 && dbz < 55.0 {
"#f80a26"
[0xf8 as f32, 0x0a as f32, 0x26 as f32]
} else if dbz >= 55.0 && dbz < 60.0 {
"#cb0516"
[0xcb as f32, 0x05 as f32, 0x16 as f32]
} else if dbz >= 60.0 && dbz < 65.0 {
"#a90813"
[0xa9 as f32, 0x08 as f32, 0x13 as f32]
} else if dbz >= 65.0 && dbz < 70.0 {
"#ee34fa"
[0xee as f32, 0x34 as f32, 0xfa as f32]
} else if dbz >= 79.0 && dbz < 75.0 {
"#9161c4"
[0x91 as f32, 0x61 as f32, 0xc4 as f32]
} else {
"#ffffff"
[255.0, 255.0, 255.0]
}
}
pub fn velocity(vel: f32) -> &'static str {
pub fn velocity(vel: f32) -> [f32; 3] {
if vel == MOMENT_DATA_FOLDED {
return "#691ac1";
return [0x69 as f32, 0x1a as f32, 0xc1 as f32];
}
let colors = [
"#F91473", // 140
"#AA1079", // 130
"#6E0E80", // 120
"#2E0E84", // 110
"#151F93", // 100
"#236FB3", // 90
"#41DADB", // 80
"#66E1E2", // 70
"#9EE8EA", // 60
"#57FA63", // 50
"#31E32B", // 40
[0xf9, 0x14, 0x73],
[0xaa, 0x10, 0x79],
[0x6e, 0x0e, 0x80],
[0x2e, 0x0e, 0x84],
[0x15, 0x1f, 0x93],
[0x23, 0x6f, 0xb3],
[0x41, 0xda, 0xdb],
[0x66, 0xe1, 0xe2],
[0x9e, 0xe8, 0xea],
[0x58, 0xfa, 0x63],
[0x31, 0xe3, 0x2b],
// "#21BE0A", // 35
"#24AA1F", // 30
"#197613", // 20
"#456742", // -10
"#634F50", // 0
"#6e2e39", // 10
"#7F030C", // 20
"#B60716", // 30
[0x24, 0xaa, 0x1f],
[0x19, 0x76, 0x13],
[0x45, 0x67, 0x42],
[0x63, 0x4f, 0x50],
[0x6e, 0x2e, 0x39],
[0x7f, 0x03, 0x0c],
[0xb6, 0x07, 0x16],
// "#C5000D", // 35
"#F32245", // 40
"#F6508A", // 50
"#FB8BBF", // 60
"#FDDE93", // 70
"#FCB470", // 80
"#FA814B", // 90
"#DD603C", // 100
"#B7452D", // 110
"#932C20", // 120
"#711614", // 130
"#520106", // 140
[0xf3, 0x22, 0x45],
[0xf6, 0x50, 0x8a],
[0xfb, 0x8b, 0xbf],
[0xfd, 0xde, 0x93],
[0xfc, 0xb4, 0x70],
[0xfa, 0x81, 0x4b],
[0xdd, 0x60, 0x3c],
[0xb7, 0x45, 0x2d],
[0x93, 0x2c, 0x20],
[0x71, 0x16, 0x14],
[0x52, 0x01, 0x06],
];
let i = scale_int(
@ -191,15 +191,15 @@ pub fn velocity(vel: f32) -> &'static str {
0,
);
colors[i as usize]
[colors[i as usize][0] as f32, colors[i as usize][1] as f32, colors[i as usize][2] as f32]
}
pub fn scale_int(val: i32, o_max: i32, o_min: i32, n_max: i32, n_min: i32) -> i32 {
(((val - o_min) * n_max - n_min) / o_max - o_min) + n_min
}
pub fn color_scheme(product: Mode, value: f32) -> &'static str {
match product {
pub fn color_scheme(product: Mode, value: f32) -> [f32; 3] {
let rgb = match product {
Mode::Reflectivity => dbz_noaa(value),
Mode::Velocity => velocity(value),
Mode::SpectrumWidth => spectrum_width(value),
@ -207,8 +207,14 @@ pub fn color_scheme(product: Mode, value: f32) -> &'static str {
Mode::DifferentialPhase => correlation_coefficient(value),
Mode::CorrelationCoefficient => correlation_coefficient(value),
Mode::ClutterFilterPowerRemoved => dbz_noaa(value),
Mode::RadarInoperative => "#ff0000",
}
Mode::RadarInoperative => [255.0, 255.0, 255.0],
};
[rgb_to_srgb_float_individual_unscaled(rgb[0]), rgb_to_srgb_float_individual_unscaled(rgb[1]), rgb_to_srgb_float_individual_unscaled(rgb[2])]
}
pub fn rgb_to_srgb_float_individual_unscaled(rgb_color: f32) -> f32 {
((rgb_color / 255.0 + 0.055) / 1.055).powf(2.4)
}
pub fn rgb_to_srgb(c: u32, a: f32) -> [f32; 4] {

View File

@ -1,4 +1,4 @@
pub mod vertex;
pub mod vertex_index;
pub mod colors;
pub mod time;
pub mod scope;

View File

@ -1,3 +1,4 @@
use std::f64::consts::PI;
use crate::mode::Mode;
use nexrad2::Nexrad2Chunk;
@ -23,10 +24,11 @@ use wgpu_glyph::{GlyphBrush, GlyphBrushBuilder, HorizontalAlign, Layout, Section
use winit::dpi::PhysicalSize;
use winit::event::WindowEvent;
use winit::window::Window;
use nexrad2::message31::MOMENT_DATA_BELOW_THRESHOLD;
use crate::mode::Mode::{RadarInoperative, Reflectivity};
use crate::rendering::colors::rgb_to_srgb;
use crate::rendering::colors::{color_scheme, rgb_to_srgb};
use crate::rendering::time::zulu;
use crate::rendering::vertex::{VERTICES};
use crate::rendering::vertex_index::{INDICES, Vertex, VERTICES};
use crate::utils::parse_date;
use crate::vcp::vcp_string;
@ -53,6 +55,7 @@ pub struct WgpuState {
pub size: PhysicalSize<u32>,
pub window: Window,
pub vertex_buffer: wgpu::Buffer,
pub index_buffer: wgpu::Buffer,
pub pipeline: RenderPipeline,
pub staging_belt: StagingBelt,
pub glyph_brush: GlyphBrush<()>
@ -118,6 +121,14 @@ impl ScopeState {
}
);
let index_buffer = device.create_buffer_init(
&wgpu::util::BufferInitDescriptor {
label: Some("Index Buffer"),
contents: bytemuck::cast_slice(INDICES),
usage: wgpu::BufferUsages::INDEX,
}
);
let shader = device.create_shader_module(ShaderModuleDescriptor {
label: Some("Shader"),
source: ShaderSource::Wgsl(include_str!("../shader.wgsl").into()),
@ -135,7 +146,7 @@ impl ScopeState {
vertex: VertexState {
module: &shader,
entry_point: "vs_main",
buffers: &[],
buffers: &[Vertex::descriptor()],
},
primitive: PrimitiveState {
topology: PrimitiveTopology::TriangleList,
@ -178,7 +189,8 @@ impl ScopeState {
vertex_buffer,
pipeline: render_pipeline,
staging_belt,
glyph_brush
glyph_brush,
index_buffer
};
info!("initializing the scope");
@ -250,6 +262,186 @@ impl ScopeState {
let physical_height =
(self.wgpu.surface_config.height as f64 * self.wgpu.window.scale_factor()) as f32;
let mut verticies = vec![];
let mut indicies = vec![];
// ACTUAL DATA RENDERING
if let Some(ar2) = &self.ar2 {
let px_per_km = 1.0 / 50.0;
let xc = 0.0;
let yc = 0.0;
let radials = ar2.elevations.get(&self.selected_elevation).unwrap();
let first_gate_px = (radials[0]
.available_data
.get("REF")
.expect("reflectivity is missing!")
.gdm
.data_moment_range) as f32
/ 1000.0
* px_per_km;
let gate_interval_km = (radials[0]
.available_data
.get("REF")
.expect("reflectivity is missing!")
.gdm
.data_moment_range_sample_interval) as f32
/ 1000.0;
let gate_width_px = gate_interval_km * px_per_km;
for radial in radials {
/* weird rounding stolen from go-nexrad */
let mut azimuth_angle = (radial.header.azimuth_angle as f64) - 90.0;
if azimuth_angle < 0.0 {
azimuth_angle = 360.0 + azimuth_angle;
}
let mut azimuth = azimuth_angle.floor();
let azimuth_spacing = match radial.header.azimuth_resolution_spacing {
1 => 0.5,
_ => 1.0,
};
if (azimuth_angle + azimuth_spacing).floor() > azimuth {
azimuth += azimuth_spacing;
}
/* conclude the weird rounding stolen from go-nexrad */
// Angles specified clockwise in radians
let start_angle = azimuth * (PI / 180.0);
let end_angle = azimuth_spacing * (PI / 180.0);
let mut distance_x = first_gate_px;
let mut distance_y = first_gate_px;
// line width
// line cap
let gates = radial
.available_data
.get(self.scope_mode.rname())
.expect("selected unavailable product")
.scaled_data();
let num_gates = gates.len();
for (num, value) in gates.iter().enumerate() {
if *value != MOMENT_DATA_BELOW_THRESHOLD {
let x0 = 1.0 / (start_angle.cos() * distance_x as f64);
let y0 = 1.0 / (start_angle.sin() * distance_y as f64);
let x1 = 1.0 / (distance_x as f64);
let y1 = 1.0 / (distance_y as f64);
// C--D
// | |
// A--B
/*
(x0, y1) -- (x1, y1)
| |
(x0, y0) -- (x1, y0)
*/
let vertex_a = Vertex { position: [x0 as f32, y0 as f32, 0.0], color: color_scheme(self.scope_mode, *value) };
let vertex_b = Vertex { position: [x1 as f32, y0 as f32, 0.0], color: color_scheme(self.scope_mode, *value) };
let vertex_c = Vertex { position: [x0 as f32, y1 as f32, 0.0], color: color_scheme(self.scope_mode, *value) };
let vertex_d = Vertex { position: [x1 as f32, y1 as f32, 0.0], color: color_scheme(self.scope_mode, *value) };
let vindex_a = verticies.len();
verticies.push(vertex_a);
let vindex_b = verticies.len();
verticies.push(vertex_b);
let vindex_c = verticies.len();
verticies.push(vertex_c);
let vindex_d = verticies.len();
verticies.push(vertex_d);
// ABC <-> BCD
indicies.extend_from_slice(&[vindex_a, vindex_b, vindex_c]);
indicies.extend_from_slice(&[vindex_b, vindex_c, vindex_d]);
/*
ctx.move_to(
xc as f64 + start_angle.cos() * distance_x as f64,
yc as f64 + start_angle.sin() * distance_y as f64,
);
ctx.begin_path();
if num == 0 {
ctx.ellipse(
xc as f64,
yc as f64,
distance_x as f64,
distance_y as f64,
0.0,
start_angle - 0.001,
end_angle + 0.001,
)?;
} else if num == num_gates - 1 {
ctx.ellipse(
xc as f64,
yc as f64,
distance_x as f64,
distance_y as f64,
0.0,
start_angle,
end_angle,
)?;
} else {
ctx.ellipse(
xc as f64,
yc as f64,
distance_x as f64,
distance_y as f64,
0.0,
start_angle,
end_angle + 0.001,
)?;
}
ctx.set_stroke_style(&JsValue::from_str(&format!(
"{}px {}",
gate_width_px + 1.0,
color_scheme(state.scope_mode, *value)
)));
ctx.stroke();
*/
}
distance_x += gate_width_px;
distance_y += gate_width_px;
azimuth += azimuth_spacing;
}
}
}
info!("Radar data tesselated - {} verticies {} indicies", verticies.len(), indicies.len());
info!("{:?}", verticies.get(0).map(|u| u.position).unwrap_or([0.0, 0.0, 0.0]));
self.wgpu.vertex_buffer.destroy();
let new_vertex_buffer = self.wgpu.device.create_buffer_init(
&wgpu::util::BufferInitDescriptor {
label: Some("Vertex Buffer"),
contents: bytemuck::cast_slice(verticies.as_slice()),
usage: wgpu::BufferUsages::VERTEX,
}
);
self.wgpu.vertex_buffer = new_vertex_buffer;
self.wgpu.index_buffer.destroy();
let new_index_buffer = self.wgpu.device.create_buffer_init(
&wgpu::util::BufferInitDescriptor {
label: Some("Index Buffer"),
contents: bytemuck::cast_slice(indicies.as_slice()),
usage: wgpu::BufferUsages::INDEX,
}
);
self.wgpu.index_buffer = new_index_buffer;
// LOCK BLOCK
{
@ -274,7 +466,9 @@ impl ScopeState {
});
render_pass.set_pipeline(&self.wgpu.pipeline);
render_pass.draw(0..3, 0..1);
render_pass.set_vertex_buffer(0, self.wgpu.vertex_buffer.slice(..));
render_pass.set_index_buffer(self.wgpu.index_buffer.slice(..), wgpu::IndexFormat::Uint16); // 1.
render_pass.draw_indexed(0..(indicies.len() as u32), 0, 0..1);
}

View File

@ -32,9 +32,26 @@ impl Vertex {
}
}
/*
C--D
| |
A--B
ABC <-> BCD
*/
pub const VERTICES: &[Vertex] = &[
Vertex { position: [0.0, 0.5, 0.0], color: [1.0, 0.0, 0.0] },
Vertex { position: [-0.5, -0.5, 0.0], color: [0.0, 1.0, 0.0] },
Vertex { position: [0.5, -0.5, 0.0], color: [0.0, 0.0, 1.0] },
Vertex { position: [-1.0, -1.0, 0.0], color: [1.0, 0.0, 0.0] }, // A
Vertex { position: [1.0, -1.0, 0.0], color: [0.0, 1.0, 0.0] }, // B
Vertex { position: [-1.0, 1.0, 0.0], color: [0.0, 0.0, 1.0] }, // C
Vertex { position: [1.0, 1.0, 0.0], color: [1.0, 1.0, 1.0] }, // D
];
pub const INDICES: &[u16] = &[
0, 1, 2,
3, 2, 1
];

View File

@ -1,16 +1,22 @@
// Vertex shader
struct VertexInput {
@location(0) position: vec3<f32>,
@location(1) color: vec3<f32>,
};
struct VertexOutput {
@builtin(position) clip_position: vec4<f32>,
@location(0) color: vec3<f32>,
};
@vertex
fn vs_main(
@builtin(vertex_index) in_vertex_index: u32,
model: VertexInput,
) -> VertexOutput {
var out: VertexOutput;
let x = f32(1 - i32(in_vertex_index)) * 0.5;
let y = f32(i32(in_vertex_index & 1u) * 2 - 1) * 0.5;
out.clip_position = vec4<f32>(x, y, 0.0, 1.0);
out.color = model.color;
out.clip_position = vec4<f32>(model.position, 1.0);
return out;
}
@ -18,5 +24,8 @@ fn vs_main(
@fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
return vec4<f32>(0.0, 0.0, 0.0, 1.0);
return vec4<f32>(in.color, 1.0);
}