Share the frame render logic across all display backends (color term, Y4M video)
This commit is contained in:
@@ -10,6 +10,7 @@ edition = "2018"
|
|||||||
ansi_term = "0.12"
|
ansi_term = "0.12"
|
||||||
decorum = "0.3"
|
decorum = "0.3"
|
||||||
enum_dispatch = "0.3"
|
enum_dispatch = "0.3"
|
||||||
|
image = "0.23"
|
||||||
ndarray = "0.13"
|
ndarray = "0.13"
|
||||||
piecewise-linear = "0.1"
|
piecewise-linear = "0.1"
|
||||||
y4m = "0.7"
|
y4m = "0.7"
|
||||||
|
@@ -1,16 +1,42 @@
|
|||||||
use ansi_term::Color::RGB;
|
use ansi_term::Color::RGB;
|
||||||
use crate::{consts, Material as _, SimState};
|
use crate::{consts, Material as _, SimState};
|
||||||
|
use image::{RgbImage, Rgb};
|
||||||
|
use std::convert::TryInto as _;
|
||||||
use std::fmt::Write as _;
|
use std::fmt::Write as _;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use y4m::{Colorspace, encode, Encoder, Frame, Ratio};
|
use y4m;
|
||||||
|
|
||||||
|
fn simstate_to_image(state: &SimState) -> RgbImage {
|
||||||
|
let w = state.width().try_into().unwrap();
|
||||||
|
let h = state.height().try_into().unwrap();
|
||||||
|
let mut image = RgbImage::new(w, h);
|
||||||
|
for y in 0..h {
|
||||||
|
for x in 0..w {
|
||||||
|
let cell = state.get(x as usize, y as usize);
|
||||||
|
//let r = norm_color(cell.bz() * consts::C);
|
||||||
|
//let r = 0;
|
||||||
|
let r = norm_color(cell.mat().mz()*1.0e-2);
|
||||||
|
let b = (55.0*cell.mat().conductivity()).min(255.0) as u8;
|
||||||
|
//let b = 0;
|
||||||
|
//let b = norm_color(cell.ey());
|
||||||
|
//let g = 0;
|
||||||
|
//let g = norm_color(cell.ex());
|
||||||
|
//let g = norm_color(curl(cell.ex(), cell.ey()));
|
||||||
|
let g = norm_color((cell.bz() * 1.0e4).into());
|
||||||
|
image.put_pixel(x, y, Rgb([r, g, b]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
image
|
||||||
|
}
|
||||||
|
|
||||||
pub struct NumericTermRenderer;
|
|
||||||
|
|
||||||
pub trait Renderer {
|
pub trait Renderer {
|
||||||
fn render(&mut self, state: &SimState);
|
fn render(&mut self, state: &SimState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct NumericTermRenderer;
|
||||||
|
|
||||||
impl Renderer for NumericTermRenderer {
|
impl Renderer for NumericTermRenderer {
|
||||||
fn render(&mut self, state: &SimState) {
|
fn render(&mut self, state: &SimState) {
|
||||||
for y in 0..state.height() {
|
for y in 0..state.height() {
|
||||||
@@ -50,33 +76,24 @@ fn curl(x: f64, y: f64) -> f64 {
|
|||||||
|
|
||||||
impl Renderer for ColorTermRenderer {
|
impl Renderer for ColorTermRenderer {
|
||||||
fn render(&mut self, state: &SimState) {
|
fn render(&mut self, state: &SimState) {
|
||||||
let mut buf = String::new();
|
|
||||||
let square = "█";
|
let square = "█";
|
||||||
for y in 0..state.height() {
|
let im = simstate_to_image(state);
|
||||||
for x in 0..state.width() {
|
let buf: String = im
|
||||||
let cell = state.get(x, y);
|
.enumerate_rows()
|
||||||
//let r = norm_color(cell.bz() * consts::C);
|
.map(|(_y, row)| {
|
||||||
//let r = 0;
|
format!("{}\n", row.map(|(_x, _y, p)| {
|
||||||
let r = norm_color(cell.mat().mz()*1.0e-2);
|
format!("{}", RGB(p.0[0], p.0[1], p.0[2]).paint(square))
|
||||||
let b = (55.0*cell.mat().conductivity()).min(255.0) as u8;
|
}).collect::<String>())
|
||||||
//let b = 0;
|
})
|
||||||
//let b = norm_color(cell.ey());
|
.collect();
|
||||||
//let g = 0;
|
|
||||||
//let g = norm_color(cell.ex());
|
println!("{}time: {:.3e} (fr {})", buf, state.time(), state.step_no());
|
||||||
//let g = norm_color(curl(cell.ex(), cell.ey()));
|
|
||||||
let g = norm_color((cell.bz() * 1.0e4).into());
|
|
||||||
//let g = norm_color(cell.ey().into());
|
|
||||||
write!(&mut buf, "{}", RGB(r, g, b).paint(square));
|
|
||||||
}
|
|
||||||
write!(&mut buf, "\n");
|
|
||||||
}
|
|
||||||
println!("{}\ntime: {:.3e} (fr {})", buf, state.time(), state.step_no());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Y4MRenderer {
|
pub struct Y4MRenderer {
|
||||||
out_path: PathBuf,
|
out_path: PathBuf,
|
||||||
encoder: Option<Encoder<File>>,
|
encoder: Option<y4m::Encoder<File>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Y4MRenderer {
|
impl Y4MRenderer {
|
||||||
@@ -90,10 +107,11 @@ impl Y4MRenderer {
|
|||||||
|
|
||||||
impl Renderer for Y4MRenderer {
|
impl Renderer for Y4MRenderer {
|
||||||
fn render(&mut self, state: &SimState) {
|
fn render(&mut self, state: &SimState) {
|
||||||
|
let im = simstate_to_image(state);
|
||||||
if self.encoder.is_none() {
|
if self.encoder.is_none() {
|
||||||
let writer = File::create(&self.out_path).unwrap();
|
let writer = File::create(&self.out_path).unwrap();
|
||||||
self.encoder = Some(encode(state.width(), state.height(), Ratio::new(30, 1))
|
self.encoder = Some(y4m::encode(im.width() as usize, im.height() as usize, y4m::Ratio::new(30, 1))
|
||||||
.with_colorspace(Colorspace::C444)
|
.with_colorspace(y4m::Colorspace::C444)
|
||||||
.write_header(writer)
|
.write_header(writer)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
);
|
);
|
||||||
@@ -102,27 +120,13 @@ impl Renderer for Y4MRenderer {
|
|||||||
let mut pix_y = Vec::new();
|
let mut pix_y = Vec::new();
|
||||||
let mut pix_u = Vec::new();
|
let mut pix_u = Vec::new();
|
||||||
let mut pix_v = Vec::new();
|
let mut pix_v = Vec::new();
|
||||||
for y in 0..state.height() {
|
for &Rgb([r, g, b]) in im.pixels() {
|
||||||
for x in 0..state.width() {
|
|
||||||
let cell = state.get(x, y);
|
|
||||||
//let r = norm_color(cell.bz() * consts::C);
|
|
||||||
//let r = 0;
|
|
||||||
let r = norm_color(cell.mat().mz()*1.0e-2);
|
|
||||||
let b = (55.0*cell.mat().conductivity()).min(255.0) as u8;
|
|
||||||
//let b = 0;
|
|
||||||
//let b = norm_color(cell.ey());
|
|
||||||
//let g = 0;
|
|
||||||
//let g = norm_color(cell.ex());
|
|
||||||
//let g = norm_color(curl(cell.ex(), cell.ey()));
|
|
||||||
let g = norm_color((cell.bz() * 1.0e4).into());
|
|
||||||
//let g = norm_color(cell.ey().into());
|
|
||||||
pix_y.push(r);
|
pix_y.push(r);
|
||||||
pix_u.push(g);
|
pix_u.push(g);
|
||||||
pix_v.push(b);
|
pix_v.push(b);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let frame = Frame::new([&*pix_y, &*pix_u, &*pix_v], None);
|
let frame = y4m::Frame::new([&*pix_y, &*pix_u, &*pix_v], None);
|
||||||
let enc = self.encoder.as_mut().unwrap();
|
let enc = self.encoder.as_mut().unwrap();
|
||||||
enc.write_frame(&frame).unwrap()
|
enc.write_frame(&frame).unwrap()
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user