pbrt/shared/src/shapes/mesh.rs

155 lines
4.5 KiB
Rust

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<Point3f>,
pub n: GVec<Normal3f>,
pub s: GVec<Vector3f>,
pub uv: GVec<Point2f>,
pub vertex_indices: GVec<i32>,
pub face_indices: GVec<i32>,
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<Point3f>,
pub n: GVec<Normal3f>,
pub uv: GVec<Point2f>,
pub vertex_indices: GVec<i32>,
pub n_patches: u32,
pub n_vertices: u32,
pub reverse_orientation: bool,
pub transform_swaps_handedness: bool,
pub image_distribution: Ptr<PiecewiseConstant2D>,
}
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(),
}
}
}