pbrt/src/shapes/triangle.rs

115 lines
3.9 KiB
Rust

use crate::core::shape::{CreateShape, ALL_TRIANGLE_MESHES};
use crate::core::texture::FloatTexture;
use crate::shapes::mesh::TriangleMesh;
use crate::{Arena, FileLoc, ParameterDictionary};
use anyhow::{bail, Result};
use log::warn;
use shared::core::shape::Shape;
use shared::shapes::TriangleShape;
use shared::{Ptr, Transform};
use std::collections::HashMap;
use std::sync::Arc;
impl CreateShape for TriangleShape {
fn create(
render_from_object: Transform,
_object_from_render: Transform,
reverse_orientation: bool,
parameters: ParameterDictionary,
_float_texture: &HashMap<String, Arc<FloatTexture>>,
_loc: FileLoc,
arena: &Arena,
) -> Result<Vec<Ptr<Shape>>> {
let mut vertex_indices = parameters.get_int_array("indices")?;
let p = parameters.get_point3f_array("P")?;
let mut uvs = parameters.get_point2f_array("uv")?;
let mut s = parameters.get_vector3f_array("S")?;
let mut n = parameters.get_normal3f_array("N")?;
if vertex_indices.is_empty() {
if p.len() == 3 {
} else {
bail!("Vertex indices \"indices\" must be provided with triangle mesh.");
}
} else if vertex_indices.len() % 3 != 0 {
let excess = vertex_indices.len() % 3;
warn!(
"Number of vertex indices {} not a multiple of 3. Discarding {} excess.",
vertex_indices.len(),
excess
);
let new_len = vertex_indices.len() - excess;
vertex_indices.truncate(new_len);
}
if p.is_empty() {
bail!("Vertex positions \"P\" must be provided with triangle mesh.");
}
if !uvs.is_empty() && uvs.len() != p.len() {
warn!("Number of \"uv\"s for triangle mesh must match \"P\"s. Discarding uvs.");
uvs.clear();
}
if !s.is_empty() && s.len() != p.len() {
warn!("Number of \"S\"s for triangle mesh must match \"P\"s. Discarding \"S\"s.");
s.clear();
}
if !n.is_empty() && n.len() != p.len() {
warn!("Number of \"N\"s for triangle mesh must match \"P\"s. Discarding \"N\"s.");
n.clear();
}
for (_, &index) in vertex_indices.iter().enumerate() {
// Check for negative indices (if keeping i32) or out of bounds
if index < 0 || index as usize >= p.len() {
bail!(
"TriangleMesh has out-of-bounds vertex index {} ({} \"P\" values were given). Discarding this mesh.",
index,
p.len()
);
}
}
let mut face_indices = parameters.get_int_array("faceIndices")?;
let n_triangles = vertex_indices.len() / 3;
if !face_indices.is_empty() && face_indices.len() != n_triangles {
warn!(
"Number of face indices {} does not match number of triangles {}. Discarding face indices.",
face_indices.len(),
n_triangles
);
face_indices.clear();
}
let host = TriangleMesh::new(
&render_from_object,
reverse_orientation,
vertex_indices,
p,
n,
s,
uvs,
face_indices,
);
let host_arc = Arc::new(host);
let mut global_store = ALL_TRIANGLE_MESHES.lock();
// let mesh_index = global_store.len() as u32;
global_store.push(host_arc.clone());
drop(global_store);
let n_patches = host_arc.device.n_triangles;
let mesh_ptr = Ptr::from(&host_arc.device);
let mut shapes = Vec::with_capacity(n_patches as usize);
for i in 0..n_patches {
shapes.push(arena.alloc(Shape::Triangle(TriangleShape {
mesh: mesh_ptr,
tri_index: i as i32,
})));
}
Ok(shapes)
}
}