use litequad::{prelude::{next_frame, clear_background, WHITE, vec3, LIGHTGRAY, BLACK, is_key_pressed, KeyCode, draw_text, vec2, screen_width, screen_height, Vec3, Color, is_key_down}, camera::{set_camera, Camera3D, set_default_camera, Camera}, models::{draw_line_3d, draw_sphere}};
use crate::{max_display, Plot3D, max_matrix, Marker};
pub async fn run(plot: Plot3D) {
let xs = plot.xs;
let ys = plot.ys;
let zs = plot.zs;
let mut max_x = max_matrix(&xs);
max_x = max_display(max_x, false);
let steps_x = 6.;
let step_x = max_x / steps_x;
let mut max_y = max_matrix(&ys);
max_y = max_display(max_y, false);
let steps_y = 6.;
let step_y = max_y / steps_y;
let mut max_z = max_matrix(&zs);
max_z = max_display(max_z, false);
let steps_z = 6.;
let step_z = max_z / steps_z;
let yaw: f32 = 1.18;
let front = vec3(
yaw.cos(),
0.,
yaw.sin(),
)
.normalize();
let world_up = vec3(0.0, 0.0, 1.0);
let right = front.cross(world_up).normalize();
let mut position = vec3(-14., 10., 13.);
loop {
clear_background(WHITE);
if is_key_pressed(KeyCode::Escape) {
break;
}
if is_key_down(KeyCode::A) {
position -= front;
}
if is_key_down(KeyCode::D) {
position += front;
}
if is_key_down(KeyCode::W) {
position -= right;
}
if is_key_down(KeyCode::S) {
position += right;
}
let camera = Camera3D {
position,
up: vec3(0., 1., 0.),
target: vec3(0., 0., 0.),
..Default::default()
};
set_camera(&camera);
let mut draw_later = Vec::<(f64, Vec3)>::new();
let spacing_z = 1.6;
let spacing_x = 1.;
let slices_bot = 6;
let slices_left = 6;
let slices_back = 6;
draw_bottom_grid(slices_bot, slices_left, spacing_x, spacing_z);
draw_left_grid(slices_left, spacing_x, spacing_z);
draw_back_grid(slices_back, spacing_x, spacing_z);
let half_slices = (slices_bot as i32) / 2;
draw_line_3d(
vec3(half_slices as f32 * spacing_x, 0., half_slices as f32 * spacing_z),
vec3(half_slices as f32 * spacing_x, slices_back as f32 * spacing_x, half_slices as f32 * spacing_z),
BLACK
);
draw_line_3d(
vec3(-half_slices as f32 * spacing_x, 0., -half_slices as f32 * spacing_z),
vec3(-half_slices as f32 * spacing_x, 0., half_slices as f32 * spacing_z),
BLACK
);
draw_line_3d(
vec3(half_slices as f32 * spacing_x, 0., -half_slices as f32 * spacing_z),
vec3(half_slices as f32 * spacing_x, 0., half_slices as f32 * spacing_z),
BLACK
);
draw_line_3d(
vec3(half_slices as f32 * spacing_x, 0., half_slices as f32 * spacing_z),
vec3(-half_slices as f32 * spacing_x, 0., half_slices as f32 * spacing_z),
BLACK
);
draw_line_3d(
vec3(half_slices as f32 * spacing_x, 0., -half_slices as f32 * spacing_z),
vec3(-half_slices as f32 * spacing_x, 0., -half_slices as f32 * spacing_z),
BLACK
);
for (idx, i) in (-half_slices+1..half_slices).into_iter().enumerate() {
draw_line_3d(
vec3((-half_slices as f32 + 0.2) * spacing_x, 0., i as f32 * spacing_z),
vec3((-half_slices as f32 - 0.2) * spacing_x, 0., i as f32 * spacing_z),
BLACK
);
draw_later.push(((idx+1) as f64 * step_x, vec3((-half_slices as f32 + 0.4) * spacing_x - 2.1, 0., i as f32 * spacing_z)));
}
for (idx, i) in (-half_slices+1..half_slices).into_iter().enumerate() {
draw_line_3d(
vec3(i as f32 * spacing_x, 0., (half_slices as f32 - 0.1) * spacing_z),
vec3(i as f32 * spacing_x, 0., (half_slices as f32 + 0.1) * spacing_z),
BLACK
);
draw_later.push(((idx+1) as f64 * step_z, vec3(i as f32 * spacing_x - 0.1, 0., (half_slices as f32 - 0.1) * spacing_z + 0.9)));
}
for i in 1..=slices_bot {
draw_line_3d(
vec3(half_slices as f32 * spacing_x, i as f32 * spacing_x, (half_slices as f32 - 0.1) * spacing_z),
vec3(half_slices as f32 * spacing_x, i as f32 * spacing_x, (half_slices as f32 + 0.1) * spacing_z),
BLACK
);
draw_later.push((i as f64 * step_y, vec3(half_slices as f32 * spacing_x, i as f32 * spacing_x -0.1, (half_slices as f32 - 0.1) * spacing_z + 0.6)));
}
let slices = 1;
for (idx, xs) in xs.iter().enumerate() {
let mut coords = Vec::new();
let mut shadow: Vec<(f32, f32, f32)> = Vec::new();
let ys = &ys[idx];
let zs = &zs[idx];
let line_desc = &plot.line_desc[idx];
for i in 0..xs.len() {
let z = ((xs[i] / step_x) * slices as f64) as f32 ;
let y = ((ys[i] / step_y) * slices as f64) as f32;
let x = ((zs[i] / step_z) * slices as f64) as f32;
let transform = vec3((x - half_slices as f32) * spacing_x, y * spacing_x, (z - half_slices as f32) * spacing_z);
let (x, y, z) = transform.into();
match line_desc.marker {
Marker::Circle(_) => {
draw_sphere(transform, 0.1, None, line_desc.color);
draw_sphere((x, 0., z).into(), 0.065, None, Color::new(0., 0., 0., 0.2))
},
Marker::None => {},
}
shadow.push((x, 0., z));
coords.push((x, y, z));
if coords.len() >= 2 {
match line_desc.line_type {
crate::LineType::Solid => {
draw_line_3d(
coords[0].into(),
coords[1].into(),
line_desc.color
);
draw_line_3d(
shadow[0].into(),
shadow[1].into(),
Color::new(0., 0., 0., 0.2)
);
},
crate::LineType::None => {},
}
coords.remove(0);
shadow.remove(0);
}
}
}
let mat = camera.matrix();
set_default_camera();
for draw in draw_later {
let transform = mat.project_point3(vec3(draw.1.x, draw.1.y, draw.1.z));
let a = vec2(
(transform.x / 2. + 0.5) * screen_width(),
(0.5 - transform.y / 2.) * screen_height(),
);
let text = format!("{:.3}", draw.0);
draw_text(&text, a.x, a.y, 15., BLACK);
}
next_frame().await;
std::thread::sleep(std::time::Duration::from_millis(16));
}
}
pub fn draw_bottom_grid(slices_z: u32, slices_x: u32, spacing_x: f32, spacing_z: f32) {
let half_slices_x = (slices_x as i32) / 2;
let half_slices_z = (slices_z as i32) / 2;
for i in -half_slices_x..=half_slices_x {
draw_line_3d(
vec3(i as f32 * spacing_x, 0., -half_slices_z as f32 * spacing_z),
vec3(i as f32 * spacing_x, 0., half_slices_z as f32 * spacing_z),
LIGHTGRAY,
);
}
for i in -half_slices_z..=half_slices_z {
draw_line_3d(
vec3(-half_slices_x as f32 * spacing_x, 0., i as f32 * spacing_z),
vec3(half_slices_x as f32 * spacing_x, 0., i as f32 * spacing_z),
LIGHTGRAY,
);
}
}
pub fn draw_left_grid(slices: u32, spacing_x: f32, spacing_z: f32) {
let half_slices = (slices as i32) / 2;
for i in -half_slices..=half_slices {
draw_line_3d(
vec3(i as f32 * spacing_x, 0., -half_slices as f32 * spacing_z),
vec3(i as f32 * spacing_x, slices as f32 * spacing_x, -half_slices as f32 * spacing_z),
LIGHTGRAY,
);
draw_line_3d(
vec3(-half_slices as f32 * spacing_x, (i+half_slices) as f32 * spacing_x, -half_slices as f32 * spacing_z),
vec3(half_slices as f32 * spacing_x, (i+half_slices) as f32 * spacing_x, -half_slices as f32 * spacing_z),
LIGHTGRAY,
);
}
}
pub fn draw_back_grid(slices: u32, spacing_x: f32, spacing_z: f32) {
let half_slices = (slices as i32) / 2;
for i in -half_slices..=half_slices {
draw_line_3d(
vec3(half_slices as f32 * spacing_x, (i+half_slices) as f32 * spacing_x, -half_slices as f32 * spacing_z),
vec3(half_slices as f32 * spacing_x, (i+half_slices) as f32 * spacing_x, half_slices as f32* spacing_z),
LIGHTGRAY
);
draw_line_3d(
vec3(half_slices as f32 * spacing_x, 0., i as f32 * spacing_z),
vec3(half_slices as f32 * spacing_x, slices as f32 * spacing_x, i as f32 * spacing_z),
LIGHTGRAY
);
}
}