use crate::{PixelPos, Point, RayHit, TilePos, Triangle, Uv};
use crate::cam::CameraPerspective;
use crate::frustrum::{
frustum_planes_tile,
frustum_planes_triangle_chunk_mask,
near_dim,
};
use crate::mask::CompressedMasks;
use crate::ray::{ray_dir, ray_triangle_chunk_hit_update};
use crate::triangle::{chunk_iter, triangle_chunk};
use crate::produce::Produce;
pub fn tile_mask<T: Produce<Triangle> + ?Sized>(
persp: &CameraPerspective,
dim: Uv,
tile_pos: Uv,
tile_size: Uv,
list: &T,
masks: &mut CompressedMasks,
) {
let fr = frustum_planes_tile(persp, dim, tile_pos, tile_size);
let mut i = 0;
let n = list.virtual_length();
loop {
if i >= n {break}
let (chunk, bits) = triangle_chunk(list, i);
masks.push(frustum_planes_triangle_chunk_mask(&fr, &chunk, bits));
i += 64;
}
}
pub fn tile_pos(dim: PixelPos, [i, j]: TilePos, tile_size: u32) -> Uv {
let x = (i as f32 * tile_size as f32) / dim[0] as f32 * 2.0 - 1.0;
let y = (j as f32 * tile_size as f32) / dim[1] as f32 * 2.0 - 1.0;
[x, y]
}
pub fn tile_size(dim: PixelPos, [i, j]: TilePos, tile_size: u32) -> Uv {
let tw = (dim[0] as f32 / tile_size as f32).ceil() * tile_size as f32;
let th = (dim[1] as f32 / tile_size as f32).ceil() * tile_size as f32;
let mix = i as f32 * tile_size as f32;
let miy = j as f32 * tile_size as f32;
let max = (i + 1) as f32 * tile_size as f32;
let may = (j + 1) as f32 * tile_size as f32;
[
(max.min(tw) - mix) / dim[0] as f32 * 2.0,
(may.min(th) - miy) / dim[1] as f32 * 2.0,
]
}
pub fn tile_grid(dim: PixelPos, tile_size: u32) -> [u32; 2] {
let tw = (dim[0] as f32 / tile_size as f32).ceil();
let th = (dim[1] as f32 / tile_size as f32).ceil();
[tw as u32, th as u32]
}
pub fn pre_masks(
dim: PixelPos,
n_tile_size: u32,
) -> Vec<CompressedMasks> {
let [w, h] = tile_grid(dim, n_tile_size);
let n = w * h;
vec![CompressedMasks::new(); n as usize]
}
pub fn masks<T: Produce<Triangle> + ?Sized + Sync>(
persp: &CameraPerspective,
dim: PixelPos,
n_tile_size: u32,
list: &T,
masks: &mut [CompressedMasks]
) {
use rayon::prelude::*;
let w = tile_grid(dim, n_tile_size)[0];
let ndim = near_dim(&persp);
masks.par_iter_mut().enumerate().for_each(|(k, masks)| {
masks.clear();
let i = k as u32 % w;
let j = k as u32 / w;
let tpos = tile_pos(dim, [i, j], n_tile_size);
let tsize = tile_size(dim, [i, j], n_tile_size);
tile_mask(persp, ndim, tpos, tsize, list, masks);
});
}
pub fn render_tile_depth<T: Produce<Triangle> + ?Sized>(
persp: &CameraPerspective,
dim: PixelPos,
pos: PixelPos,
n_tile_size: u32,
list: &T,
masks: &CompressedMasks,
tile: &mut [RayHit],
) {
let eye = [0.0; 3];
let iter = chunk_iter(list, masks);
for (off, (chunk, mask)) in iter {
for j in 0..n_tile_size {
for i in 0..n_tile_size {
let dir: Point = ray_dir(persp, eye, [pos[0] + i, pos[1] + j], dim);
ray_triangle_chunk_hit_update((eye, dir), &chunk, mask, off,
&mut tile[(j * n_tile_size + i) as usize]);
}
}
}
}