use crate::core::geometry::{Normal3f, Point2f, Point3f, Vector3f}; use crate::utils::sampling::PiecewiseConstant2D; use crate::{gvec_from_slice, gvec_with_capacity, Float, GVec, Ptr, Transform}; #[repr(C)] #[derive(Debug, Clone)] pub struct TriangleMesh { pub p: GVec, pub n: GVec, pub s: GVec, pub uv: GVec, pub vertex_indices: GVec, pub face_indices: GVec, pub n_triangles: u32, pub n_vertices: u32, pub reverse_orientation: bool, pub transform_swaps_handedness: bool, } #[repr(C)] #[derive(Debug, Clone)] pub struct BilinearPatchMesh { pub p: GVec, pub n: GVec, pub uv: GVec, pub vertex_indices: GVec, pub n_patches: u32, pub n_vertices: u32, pub reverse_orientation: bool, pub transform_swaps_handedness: bool, pub image_distribution: Ptr, } impl TriangleMesh { pub fn new( render_from_object: &Transform, reverse_orientation: bool, vertex_indices: &[i32], p: &[Point3f], n: &[Normal3f], s: &[Vector3f], uv: &[Point2f], face_indices: &[i32], ) -> Self { let n_triangles = (vertex_indices.len() / 3) as u32; let n_vertices = p.len() as u32; let mut p_gvec = gvec_with_capacity(p.len()); for pt in p { p_gvec.push(render_from_object.apply_to_point(*pt)); } let mut n_gvec = gvec_with_capacity(n.len()); if !n.is_empty() { assert_eq!(n_vertices as usize, n.len(), "Normal count mismatch"); for nn in n { let mut transformed = render_from_object.apply_to_normal(*nn); if reverse_orientation { transformed = -transformed; } n_gvec.push(transformed); } } let mut s_gvec = gvec_with_capacity(s.len()); if !s.is_empty() { assert_eq!(n_vertices as usize, s.len(), "Tangent count mismatch"); for ss in s { s_gvec.push(render_from_object.apply_to_vector(*ss)); } } assert!( uv.is_empty() || uv.len() == n_vertices as usize, "UV count mismatch" ); assert!( face_indices.is_empty() || face_indices.len() == n_triangles as usize, "Face index count mismatch" ); Self { vertex_indices: gvec_from_slice(vertex_indices), p: p_gvec, n: n_gvec, s: s_gvec, uv: gvec_from_slice(uv), face_indices: gvec_from_slice(face_indices), n_triangles, n_vertices, reverse_orientation, transform_swaps_handedness: render_from_object.swaps_handedness(), } } pub fn positions(&self) -> &[Point3f] { &self.p } pub fn indices(&self) -> &[i32] { &self.vertex_indices } pub fn normals(&self) -> &[Normal3f] { &self.n } pub fn uvs(&self) -> &[Point2f] { &self.uv } } impl BilinearPatchMesh { pub fn new( render_from_object: &Transform, reverse_orientation: bool, vertex_indices: &[i32], p: &[Point3f], n: &[Normal3f], uv: &[Point2f], image_distribution: Option<&PiecewiseConstant2D>, ) -> Self { let n_patches = (vertex_indices.len() / 4) as u32; let n_vertices = p.len() as u32; let mut p_gvec = gvec_with_capacity(p.len()); for pt in p { p_gvec.push(render_from_object.apply_to_point(*pt)); } let mut n_gvec = gvec_with_capacity(n.len()); if !n.is_empty() { assert_eq!(n_vertices as usize, n.len()); for nn in n { let mut transformed = render_from_object.apply_to_normal(*nn); if reverse_orientation { transformed = -transformed; } n_gvec.push(transformed); } } assert!(uv.is_empty() || uv.len() == n_vertices as usize); Self { vertex_indices: gvec_from_slice(vertex_indices), p: p_gvec, n: n_gvec, uv: gvec_from_slice(uv), image_distribution: Ptr::from(image_distribution), n_patches, n_vertices, reverse_orientation, transform_swaps_handedness: render_from_object.swaps_handedness(), } } }