models_cv/
filter.rs

1extern crate nalgebra as na;
2
3use na::{Vector2, Matrix3xX};
4use std::collections::HashMap;
5use crate::triangle::Triangle;
6use crate::rasterizer;
7
8
9pub enum FilterType {
10    Depth,
11    Rasterizer
12}
13
14pub fn filter_visible_screen_points_by_depth(screen_points_with_index: &Vec<(usize,Vector2<f32>)>, points_cam: &Matrix3xX<f32>,) -> Vec<(usize,Vector2<usize>)> {
15    let mut closest_point_map = HashMap::<(usize,usize), usize>::with_capacity(screen_points_with_index.len());
16    for (i,&(global_id,screen_p)) in screen_points_with_index.iter().filter(|(_,p)| p.x > 0.0 && p.y >= 0.0).enumerate() {
17        let key = (screen_p.x.floor() as usize,screen_p.y.floor() as usize);
18        match closest_point_map.contains_key(&key) {
19            true => {
20                let current_point_index = closest_point_map.get(&key).unwrap();
21                let current_point_depth = points_cam[*current_point_index];
22                let depth = points_cam[(2,global_id)];
23                // GLTF models are displayed along the negative Z-Axis
24                if depth > current_point_depth  {
25                    closest_point_map.insert(key, i);
26                }
27            },
28            false => {closest_point_map.insert(key, i);()}
29        }
30    }
31    closest_point_map.into_values().map(|i| screen_points_with_index[i]).map(|(i,v)| (i, Vector2::new(v.x.floor() as usize, v.y.floor() as usize))).collect()
32}
33
34pub fn filter_visible_screen_points_by_rasterizer(screen_cam_triangles: &Vec<(Triangle<2>,Triangle<3>)>, screen_width: f32, screen_height: f32) -> Vec<(usize,Vector2<usize>)> {
35    assert!(screen_height.fract() <= f32::EPSILON);
36    assert!(screen_width.fract() <= f32::EPSILON);
37    let mut depth_buffer = HashMap::<(usize,usize),(f32,Option<(usize,Vector2<usize>)>)>::with_capacity((screen_height*screen_width) as usize);
38    for (tri_2d,tri_3d) in screen_cam_triangles.iter() {
39        let barycentric_coordiantes_with_pixel = rasterizer::calc_all_pixels_within_triangle(tri_2d);
40        let barycentric_coordiantes = barycentric_coordiantes_with_pixel.iter().map(|(w0,w1,w2,_)| (*w0,*w1,*w2)).collect::<Vec<_>>();
41        let pixel_depths = rasterizer::calc_inv_z_for_all_pixels(&barycentric_coordiantes,tri_3d);
42        let mut triangle_association_map = HashMap::<(usize,usize),usize>::with_capacity(3);
43        triangle_association_map.insert((tri_2d.get_v0().x.floor() as usize,tri_2d.get_v0().y.floor() as usize), tri_2d.get_id0().expect("Expected id for v0!"));
44        triangle_association_map.insert((tri_2d.get_v1().x.floor() as usize,tri_2d.get_v1().y.floor() as usize), tri_2d.get_id1().expect("Expected id for v1!"));
45        triangle_association_map.insert((tri_2d.get_v2().x.floor() as usize,tri_2d.get_v2().y.floor() as usize), tri_2d.get_id2().expect("Expected id for v2!"));
46        for i in 0..pixel_depths.len() {
47            let depth = pixel_depths[i];
48            assert!(depth < 0.0);
49            let pixel = barycentric_coordiantes_with_pixel[i].3;
50            let key = (pixel.x.floor() as usize,pixel.y.floor() as usize);
51            let pixel_u = Vector2::new(key.0,key.1);
52            let pixel_is_vertex = triangle_association_map.contains_key(&key);
53            match (depth_buffer.contains_key(&key), pixel_is_vertex) {
54                (false,false) => {
55                    depth_buffer.insert(key.clone(), (depth,None));
56                    ()
57                },
58                (false,true) => {
59                    depth_buffer.insert(key.clone(), (depth,Some((*triangle_association_map.get(&key).unwrap(),pixel_u))));
60                    ()
61                },
62                (true,false) => {
63                    let &(current_depth,_v) = depth_buffer.get(&key).unwrap();
64                    assert!(current_depth < 0.0);
65                    // GLTF is defined along -Z
66                    if depth > current_depth {
67                        depth_buffer.insert(key.clone(), (depth,None));
68                    }
69                },
70                (true,true) => {
71                    let &(current_depth,_v) = depth_buffer.get(&key).unwrap();
72                    assert!(current_depth < 0.0);
73                    // GLTF is defined along -Z
74                    if depth > current_depth {
75                        depth_buffer.insert(key.clone(), (depth,Some((*triangle_association_map.get(&key).unwrap(),pixel_u))));
76                    }
77                }
78            }
79        }      
80    }
81    depth_buffer.values().into_iter().filter(|(_, some_v)| some_v.is_some()).map(|(_,some_v)|some_v.unwrap()).collect()
82}