Я пытаюсь реализовать алгоритм BVH в моем трассировщике лучей Rust, но у меня проблемы с временем жизни и владением. У меня есть черта Hittable
, которую реализует множество разных вещей - Sphere
, Triangle
, Mesh
, и c. Итак, у меня есть Vec<Box<dyn Hittable>>
, который я хочу превратить в дерево этой структуры:
pub struct BvhNode {
bounding_box: BoundingBox,
left: Box<dyn Hittable>,
right: Box<dyn Hittable>,
}
Итак, у меня есть рекурсивный алгоритм, который почти работает, если бы не пожизненные вопросы. Моя функция выглядит так:
pub fn new(objects: Vec<Box<dyn Hittable>>, start: usize, end: usize, t0: f64, t1: f64) -> Self {
let r = util::rand();
let comp = if r < 1. / 3. {
util::box_x_compare
} else if r < 2. / 3. {
util::box_y_compare
} else {
util::box_z_compare
}; // which axis to compare along (random for now)
let num_obj = end - start;
let mut left: Box<dyn Hittable>;
let mut right: Box<dyn Hittable>;
if num_obj == 1 {
left = objects[start];
right = objects[start];
} else if num_obj == 2 {
if comp(&&objects[start], &&objects[start + 1]) != Ordering::Greater {
left = objects[start];
right = objects[start + 1];
} else {
left = objects[start + 1];
right = objects[start];
}
} else {
let mut slice: Vec<&Box<dyn Hittable>> = Vec::new();
for i in start..end { // make a copy to sort
slice.push(&objects[i]);
}
slice.sort_by(comp);
let mid = start + num_obj / 2;
let l = BvhNode::new(objects, start, mid, t0, t1);
let r = BvhNode::new(objects, mid, end, t0, t1);
left = Box::new(l.clone());
right = Box::new(r.clone());
}
let left_box = left.get_bounding_box(t0, t1);
let right_box = right.get_bounding_box(t0, t1);
if left_box.is_none() || right_box.is_none() {
println!("Error: No bounding box in Bvh Node");
panic!();
}
Self { left, right, bounding_box: BoundingBox::new(Point3::origin(), Point3::origin()) }
}
Во-первых, я столкнулся с некоторыми проблемами при попытке «выйти из ve c», чего я не могу сделать, поэтому я попытался реализовать Clone
на все типы, реализующие Hittable
. Это работает почти для всех из них, но моя Triangle
struct
pub struct Triangle <'b> {
mat: &'b Box<dyn Material>,
bounding_box: Option<BoundingBox>,
p: Vec<Point3<f64>>,
n: Vec<Vector3<f64>>,
uv: Vec<Vector2<f64>>,
}
содержит ссылку на материал связанного с ней меня sh, который не нравится клону. Я мог бы сделать клон самого Материала, но он потенциально может быть очень большим, и я не хочу иметь тысячи его копий для каждого треугольника в me sh.
Я чувствую, что должен быть лучший способ спроектировать мою систему, например, избавиться от ссылок в Triangle
, чтобы ее можно было легко скопировать. Как только эта структура будет создана, мне больше не понадобится Vec
, поэтому возможность move
объектов извлекать из нее внутри копирования их также будет работать, но я не вижу способа сделать это. .
Если поможет, полный файл находится на GitHub здесь