#![allow(dead_code)]
use std::f32::consts::FRAC_PI_8;
#[allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DepthResolveMethod {
Min,
Max,
Average,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct DepthResolveConfig {
pub method: DepthResolveMethod,
pub sample_count: u32,
pub reversed_z: bool,
pub ref_angle_rad: f32,
}
impl Default for DepthResolveConfig {
fn default() -> Self {
DepthResolveConfig {
method: DepthResolveMethod::Min,
sample_count: 4,
reversed_z: false,
ref_angle_rad: FRAC_PI_8,
}
}
}
pub fn default_depth_resolve_config() -> DepthResolveConfig {
DepthResolveConfig::default()
}
pub fn new_depth_resolve(sample_count: u32, method: DepthResolveMethod) -> DepthResolveConfig {
DepthResolveConfig {
sample_count,
method,
..DepthResolveConfig::default()
}
}
pub fn dr_set_method(cfg: &mut DepthResolveConfig, method: DepthResolveMethod) {
cfg.method = method;
}
pub fn dr_set_reversed_z(cfg: &mut DepthResolveConfig, v: bool) {
cfg.reversed_z = v;
}
pub fn dr_method_name(cfg: &DepthResolveConfig) -> &'static str {
match cfg.method {
DepthResolveMethod::Min => "min",
DepthResolveMethod::Max => "max",
DepthResolveMethod::Average => "average",
}
}
pub fn dr_resolve(cfg: &DepthResolveConfig, samples: &[f32]) -> f32 {
if samples.is_empty() {
return if cfg.reversed_z { 0.0 } else { 1.0 };
}
match cfg.method {
DepthResolveMethod::Min => samples.iter().cloned().fold(f32::MAX, f32::min),
DepthResolveMethod::Max => samples.iter().cloned().fold(f32::MIN, f32::max),
DepthResolveMethod::Average => samples.iter().sum::<f32>() / samples.len() as f32,
}
}
pub fn dr_linearize(cfg: &DepthResolveConfig, depth: f32, near: f32, far: f32) -> f32 {
let d = depth.clamp(0.0, 1.0);
let d = if cfg.reversed_z { 1.0 - d } else { d };
near * far / (far - d * (far - near))
}
pub fn dr_memory_saved(cfg: &DepthResolveConfig, pixel_count: u64) -> u64 {
let bytes_per_sample = 4u64; pixel_count * bytes_per_sample * (cfg.sample_count as u64 - 1)
}
pub fn dr_to_json(cfg: &DepthResolveConfig) -> String {
format!(
r#"{{"method":"{}","samples":{},"reversed_z":{}}}"#,
dr_method_name(cfg),
cfg.sample_count,
cfg.reversed_z
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_method_is_min() {
assert_eq!(
default_depth_resolve_config().method,
DepthResolveMethod::Min
);
}
#[test]
fn resolve_min() {
let cfg = new_depth_resolve(4, DepthResolveMethod::Min);
let v = dr_resolve(&cfg, &[0.9, 0.5, 0.7]);
assert!((v - 0.5).abs() < 1e-5);
}
#[test]
fn resolve_max() {
let cfg = new_depth_resolve(4, DepthResolveMethod::Max);
let v = dr_resolve(&cfg, &[0.9, 0.5, 0.7]);
assert!((v - 0.9).abs() < 1e-5);
}
#[test]
fn resolve_average() {
let cfg = new_depth_resolve(4, DepthResolveMethod::Average);
let v = dr_resolve(&cfg, &[0.0, 1.0]);
assert!((v - 0.5).abs() < 1e-5);
}
#[test]
fn empty_samples_returns_far() {
let cfg = default_depth_resolve_config();
assert!((dr_resolve(&cfg, &[]) - 1.0).abs() < 1e-5);
}
#[test]
fn linearize_in_range() {
let cfg = default_depth_resolve_config();
let v = dr_linearize(&cfg, 0.5, 0.1, 100.0);
assert!(v > 0.0 && v < 100.0);
}
#[test]
fn method_name_correct() {
let cfg = new_depth_resolve(4, DepthResolveMethod::Average);
assert_eq!(dr_method_name(&cfg), "average");
}
#[test]
fn memory_saved_nonzero() {
let cfg = new_depth_resolve(4, DepthResolveMethod::Min);
assert!(dr_memory_saved(&cfg, 1920 * 1080) > 0);
}
#[test]
fn json_has_method() {
assert!(dr_to_json(&default_depth_resolve_config()).contains("method"));
}
}