pbrt/src/utils/mesh.rs

162 lines
4.5 KiB
Rust

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<Vec<usize>>,
pub p: Arc<Vec<Point3f>>,
pub n: Option<Arc<Vec<Normal3f>>>,
pub s: Option<Arc<Vec<Vector3f>>>,
pub uv: Option<Arc<Vec<Point2f>>>,
pub face_indices: Option<Arc<Vec<usize>>>,
pub reverse_orientation: bool,
pub transform_swaps_handedness: bool,
}
impl TriangleMesh {
#[allow(clippy::too_many_arguments)]
pub fn new(
render_from_object: &Transform<Float>,
reverse_orientation: bool,
indices: Vec<usize>,
mut p: Vec<Point3f>,
mut s: Vec<Vector3f>,
mut n: Vec<Normal3f>,
uv: Vec<Point2f>,
face_indices: Vec<usize>,
) -> 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<Vec<usize>>,
pub p: Arc<Vec<Point3f>>,
pub n: Option<Arc<Vec<Normal3f>>>,
pub uv: Option<Arc<Vec<Point2f>>>,
pub image_distribution: Option<PiecewiseConstant2D>,
}
impl BilinearPatchMesh {
pub fn new(
render_from_object: &Transform<Float>,
reverse_orientation: bool,
indices: Vec<usize>,
mut p: Vec<Point3f>,
mut n: Vec<Normal3f>,
uv: Vec<Point2f>,
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),
}
}
}