use crate::params::{FilterParams, PmParams};
use cumulus3d_core::Result;
use std::sync::Arc;
#[derive(Clone, Debug)]
pub struct LevelImage {
pub width: usize,
pub height: usize,
pub gray: Arc<Vec<u8>>,
pub k: [f32; 4],
}
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[repr(C)]
pub struct PairGeometry {
pub r: [f32; 9],
pub t: [f32; 3],
pub center: [f32; 3],
}
#[derive(Clone, Debug)]
pub struct KernelView {
pub key: u64,
pub levels: Vec<LevelImage>,
pub sources: Vec<usize>,
pub pairs: Vec<PairGeometry>,
pub depth_min: f32,
pub depth_max: f32,
}
#[derive(Clone, Debug)]
pub struct KernelInput {
pub views: Vec<KernelView>,
pub num_levels: usize,
pub pm: PmParams,
pub filter: FilterParams,
pub seed: u64,
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct ViewState {
pub width: usize,
pub height: usize,
pub depth: Vec<f32>,
pub normal: Vec<[f32; 3]>,
pub cost: Vec<f32>,
pub prior: Vec<[f32; 4]>,
}
impl ViewState {
pub fn new(width: usize, height: usize) -> Self {
let n = width * height;
Self { width, height, depth: vec![0.0; n], normal: vec![[0.0; 3]; n], cost: vec![2.0; n], prior: Vec::new() }
}
}
#[derive(Clone, Debug)]
pub struct DepthSnapshot {
pub id: u64,
pub level: usize,
pub maps: Vec<Option<Arc<Vec<f32>>>>,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct RunParams {
pub level: usize,
pub geometric: bool,
pub random_init: bool,
pub iterations: u32,
pub run_id: u32,
pub use_prior: bool,
}
pub trait PatchMatchSession {
fn run(&mut self, views: &[usize], states: &mut [ViewState], params: &RunParams, snapshot: Option<&DepthSnapshot>) -> Result<()>;
fn evaluate(&mut self, level: usize, views: &[usize], states: &[ViewState], geometric: bool, snapshot: Option<&DepthSnapshot>) -> Result<Vec<Vec<f32>>>;
fn filter(&mut self, views: &[usize], states: &[ViewState], snapshot: &DepthSnapshot) -> Result<Vec<Vec<u8>>>;
fn upsample(&mut self, input: &KernelInput, level: usize, views: &[usize], low: &[ViewState], sigma_s: f32, sigma_c: f32) -> Result<Vec<ViewState>> {
Ok(views
.iter()
.zip(low)
.map(|(&v, s)| crate::upsample::joint_bilateral_upsample(s, &input.views[v].levels[level - 1], &input.views[v].levels[level], sigma_s, sigma_c))
.collect())
}
fn median_filter(&mut self, input: &KernelInput, level: usize, views: &[usize], states: &[ViewState]) -> Result<Vec<ViewState>> {
Ok(views.iter().zip(states).map(|(&v, s)| crate::upsample::median_plane_filter(s, &input.views[v].levels[level])).collect())
}
}
pub trait PatchMatchBackend: Send + Sync {
fn name(&self) -> String;
fn begin<'a>(&'a self, input: &'a KernelInput) -> Result<Box<dyn PatchMatchSession + 'a>>;
}
pub fn rng_state(seed: u64, view_key: u64, level: u32, run: u32, t: u32, half: u32, pixel: u64) -> u64 {
use crate::math::mix64;
let tag = ((level as u64) << 48) ^ ((run as u64) << 32) ^ ((t as u64) << 16) ^ half as u64;
mix64(seed ^ mix64(view_key ^ mix64(tag)) ^ pixel)
}
pub fn rng_next(state: &mut u64) -> f32 {
*state = state.wrapping_add(0x9e37_79b9_7f4a_7c15);
let z = crate::math::mix64(*state);
((z >> 40) as f32 + 1.0) * (1.0 / 16_777_216.0)
}