【问题标题】:How can I turn a Vec of trait objects into a tree structure?如何将特征对象的 Vec 转换为树结构?
【发布时间】:2020-07-10 21:13:50
【问题描述】:

我正在尝试在我的 Rust 光线追踪器中实现 BVH 算法,但我在生命周期和所有权方面遇到了问题。我有一个特征Hittable,可以用一堆不同的东西实现——SphereTriangleMesh 等等。所以我有一个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()) }
    }

首先,我在尝试“移出 vec”时遇到了一些问题,这是我做不到的,因此我尝试在所有实现 Hittable 的类型上实现 Clone。它适用于几乎所有人,但我的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>>,
}

包含对其关联网格的材质的引用,这是克隆不喜欢的。我可以复制材质本身,但它可能非常大,我不希望网格中的每个三角形都有数千个副本。

我觉得必须有更好的方法来设计我的系统,比如去掉 Triangle 中的引用,以便可以轻松复制它。创建此结构后,我将不再需要Vec,因此能够将对象从move 中取出并复制它们也可以,但我也没有办法做到这一点.

如果有帮助,完整文件在 GitHub here

【问题讨论】:

    标签: rust lifetime ownership


    【解决方案1】:

    我能够通过将 objects Vec 更改为 &amp;mut Vec&lt;Box&lt;dyn Hittable&gt;&gt; 然后使用 objects.remove() 而不是对其进行索引来解决此问题。我不得不稍微改变算法来处理新的方法,但它应该可以工作。

    【讨论】:

      猜你喜欢
      • 2020-02-29
      • 2013-02-26
      • 1970-01-01
      • 1970-01-01
      • 2021-08-07
      • 2019-10-23
      • 2019-04-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多