use crate::core::pbrt::Float; use crate::geometry::{Normal3f, Point2f, Point3f, Vector3f}; use crate::utils::sampling::PiecewiseConstant2D; use crate::utils::transform::Transform; use std::sync::Arc; #[derive(Debug, Clone)] pub struct TriangleMesh { pub n_triangles: usize, pub n_vertices: usize, pub vertex_indices: Arc>, pub p: Arc>, pub n: Option>>, pub s: Option>>, pub uv: Option>>, pub face_indices: Option>>, pub reverse_orientation: bool, pub transform_swaps_handedness: bool, } impl TriangleMesh { #[allow(clippy::too_many_arguments)] pub fn new( render_from_object: &Transform, reverse_orientation: bool, indices: Vec, mut p: Vec, mut s: Vec, mut n: Vec, uv: Vec, face_indices: Vec, ) -> Self { let n_triangles = indices.len() / 3; let n_vertices = p.len(); for pt in p.iter_mut() { *pt = render_from_object.apply_to_point(*pt); } let transform_swaps_handedness = render_from_object.swaps_handedness(); let uv = if !uv.is_empty() { assert_eq!(n_vertices, uv.len()); Some(uv) } else { None }; let n = if !n.is_empty() { assert_eq!(n_vertices, n.len()); for nn in n.iter_mut() { *nn = render_from_object.apply_to_normal(*nn); if reverse_orientation { *nn = -*nn; } } Some(n) } else { None }; let s = if !s.is_empty() { assert_eq!(n_vertices, s.len()); for ss in s.iter_mut() { *ss = render_from_object.apply_to_vector(*ss); } Some(s) } else { None }; let face_indices = if !face_indices.is_empty() { assert_eq!(n_triangles, face_indices.len()); Some(face_indices) } else { None }; assert!(p.len() <= i32::MAX as usize); assert!(indices.len() <= i32::MAX as usize); Self { n_triangles, n_vertices, vertex_indices: Arc::new(indices), p: Arc::new(p), n: n.map(Arc::new), s: s.map(Arc::new), uv: uv.map(Arc::new), face_indices: face_indices.map(Arc::new), reverse_orientation, transform_swaps_handedness, } } } #[derive(Debug, Clone)] pub struct BilinearPatchMesh { pub reverse_orientation: bool, pub transform_swaps_handedness: bool, pub n_patches: usize, pub n_vertices: usize, pub vertex_indices: Arc>, pub p: Arc>, pub n: Option>>, pub uv: Option>>, pub image_distribution: Option, } impl BilinearPatchMesh { pub fn new( render_from_object: &Transform, reverse_orientation: bool, indices: Vec, mut p: Vec, mut n: Vec, uv: Vec, image_distribution: PiecewiseConstant2D, ) -> Self { let n_patches = indices.len() / 3; let n_vertices = p.len(); for pt in p.iter_mut() { *pt = render_from_object.apply_to_point(*pt); } let transform_swaps_handedness = render_from_object.swaps_handedness(); let uv = if !uv.is_empty() { assert_eq!(n_vertices, uv.len()); Some(uv) } else { None }; let n = if !n.is_empty() { assert_eq!(n_vertices, n.len()); for nn in n.iter_mut() { *nn = render_from_object.apply_to_normal(*nn); if reverse_orientation { *nn = -*nn; } } Some(n) } else { None }; assert!(p.len() <= i32::MAX as usize); assert!(indices.len() <= i32::MAX as usize); Self { n_patches, n_vertices, vertex_indices: Arc::new(indices), p: Arc::new(p), n: n.map(Arc::new), uv: uv.map(Arc::new), reverse_orientation, transform_swaps_handedness, image_distribution: Some(image_distribution), } } }