1use num_traits::AsPrimitive;
2use rayon::iter::IntoParallelIterator;
3use rayon::iter::ParallelIterator;
4
5pub fn pix2tri<Index>(
6 tri2vtx: &[Index],
7 vtx2xyz: &[f32],
8 bvhnodes: &[Index],
9 aabbs: &[f32],
10 img_shape: &(usize, usize), transform_ndc2world: &[f32; 16],
12) -> Vec<Index>
13where
14 Index: num_traits::PrimInt + AsPrimitive<usize> + Sync + Send,
15 usize: AsPrimitive<Index>,
16{
17 let tri_for_pix = |i_pix: usize| {
18 let i_h = i_pix / img_shape.0;
19 let i_w = i_pix - i_h * img_shape.0;
20 let (ray_org, ray_dir) =
22 crate::cam3::ray3_homogeneous((i_w, i_h), img_shape, transform_ndc2world);
23 let mut hits: Vec<(f32, usize)> = vec![];
24 del_msh_core::bvh3::search_intersection_ray::<Index>(
25 &mut hits,
26 &ray_org,
27 &ray_dir,
28 &del_msh_core::bvh3::TriMeshWithBvh {
29 tri2vtx,
30 vtx2xyz,
31 bvhnodes,
32 aabbs,
33 },
34 0,
35 );
36 hits.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());
37 let Some(&(_depth, i_tri)) = hits.first() else {
38 return Index::max_value();
39 };
40 i_tri.as_()
41 };
42 let img: Vec<Index> = (0..img_shape.0 * img_shape.1)
43 .into_par_iter()
44 .map(tri_for_pix)
45 .collect();
46 img
47}
48
49pub fn render_depth_bvh(
50 image_size: (usize, usize),
51 img_data: &mut [f32],
52 transform_ndc2world: &[f32; 16],
53 tri2vtx: &[usize],
54 vtx2xyz: &[f32],
55 bvhnodes: &[usize],
56 aabbs: &[f32],
57) {
58 let transform_world2ndc: [f32; 16] =
59 nalgebra::Matrix4::<f32>::from_column_slice(transform_ndc2world)
60 .try_inverse()
61 .unwrap()
62 .as_slice()
63 .try_into()
64 .unwrap();
65 let (width, height) = image_size;
66 for ih in 0..height {
67 for iw in 0..width {
68 let (ray_org, ray_dir) =
69 crate::cam3::ray3_homogeneous((iw, ih), &image_size, transform_ndc2world);
70 let mut hits: Vec<(f32, usize)> = vec![];
71 del_msh_core::bvh3::search_intersection_ray(
72 &mut hits,
73 &ray_org,
74 &ray_dir,
75 &del_msh_core::bvh3::TriMeshWithBvh {
76 tri2vtx,
77 vtx2xyz,
78 bvhnodes,
79 aabbs,
80 },
81 0,
82 );
83 hits.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());
84 let Some(&(depth, _i_tri)) = hits.first() else {
85 continue;
86 };
87 let pos = del_geo_core::vec3::axpy(depth, &ray_dir, &ray_org);
88 let ndc =
89 del_geo_core::mat4_col_major::transform_homogeneous(&transform_world2ndc, &pos)
90 .unwrap();
91 let depth_ndc = (ndc[2] + 1f32) * 0.5f32;
92 img_data[ih * width + iw] = depth_ndc;
93 }
94 }
95}
96
97pub fn render_normalmap_from_pix2tri(
98 image_size: (usize, usize),
99 cam_modelviewd: &[f32; 16],
100 tri2vtx: &[usize],
101 vtx2xyz: &[f32],
102 pix2tri: &[usize],
103) -> Vec<f32> {
104 let (width, height) = image_size;
105 let mut img = vec![0f32; height * width * 3];
106 for ih in 0..height {
107 for iw in 0..width {
108 let i_tri = pix2tri[ih * width + iw];
109 if i_tri == usize::MAX {
110 continue;
111 }
112 let tri = del_msh_core::trimesh3::to_tri3(i_tri, tri2vtx, vtx2xyz);
113 let nrm = tri.normal();
114 let nrm = del_geo_core::mat4_col_major::transform_vector(cam_modelviewd, &nrm);
115 let unrm = del_geo_core::vec3::normalized(&nrm);
116 img[(ih * width + iw) * 3] = unrm[0] * 0.5 + 0.5;
117 img[(ih * width + iw) * 3 + 1] = unrm[1] * 0.5 + 0.5;
118 img[(ih * width + iw) * 3 + 2] = unrm[2] * 0.5 + 0.5;
119 }
120 }
121 img
122}
123
124pub fn render_texture_from_pix2tri(
125 img_shape: (usize, usize),
126 transform_ndc2world: &[f32; 16],
127 tri2vtx: &[usize],
128 vtx2xyz: &[f32],
129 vtx2uv: &[f32],
130 pix2tri: &[usize],
131 tex_shape: (usize, usize),
132 tex_data: &[f32],
133 interpolation: &crate::texture::Interpolation,
134) -> Vec<f32> {
135 let (width, height) = img_shape;
136 let mut img = vec![0f32; height * width * 3];
137 for ih in 0..height {
138 for iw in 0..width {
139 let (ray_org, ray_dir) =
140 crate::cam3::ray3_homogeneous((iw, ih), &img_shape, transform_ndc2world);
141 let i_tri = pix2tri[ih * width + iw];
142 if i_tri == usize::MAX {
143 continue;
144 }
145 let tri = del_msh_core::trimesh3::to_tri3(i_tri, tri2vtx, vtx2xyz);
146 let a = tri.intersection_against_ray(&ray_org, &ray_dir).unwrap();
147 let q = del_geo_core::vec3::axpy(a, &ray_dir, &ray_org);
148 let bc = del_geo_core::tri3::barycentric_coords(tri.p0, tri.p1, tri.p2, &q);
149 let uv0 = arrayref::array_ref!(vtx2uv, tri2vtx[i_tri * 3 + 0] * 2, 2);
150 let uv1 = arrayref::array_ref!(vtx2uv, tri2vtx[i_tri * 3 + 1] * 2, 2);
151 let uv2 = arrayref::array_ref!(vtx2uv, tri2vtx[i_tri * 3 + 2] * 2, 2);
152 let uv = [
153 uv0[0] * bc[0] + uv1[0] * bc[1] + uv2[0] * bc[2],
154 uv0[1] * bc[0] + uv1[1] * bc[1] + uv2[1] * bc[2],
155 ];
156 let pix = [
165 uv[0] * tex_shape.0 as f32,
166 (1. - uv[1]) * tex_shape.1 as f32,
167 ];
168 let res = match interpolation {
169 crate::texture::Interpolation::Nearest => {
170 crate::texture::nearest::<3>(&pix, &tex_shape, tex_data)
171 }
172 crate::texture::Interpolation::Bilinear => {
173 crate::texture::bilinear::<3>(&pix, &tex_shape, tex_data)
174 }
175 };
176 img[(ih * width + iw) * 3] = res[0];
177 img[(ih * width + iw) * 3 + 1] = res[1];
178 img[(ih * width + iw) * 3 + 2] = res[2];
179 }
180 }
181 img
182}