You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何遍历C++中深度未知的嵌套Assembly结构下的所有Model?

嵌套渲染架构的Model遍历方案

下面提供几种直接可用的实现方式,都不需要复制Model数据,适配你当前的架构:

1. 基于回调的递归遍历(推荐)

这种方式不需要额外存储Model,直接在遍历过程中处理数据,适合构建加速结构、光栅化这类实时处理场景。

首先给Assembly类添加一个接受回调的遍历方法:

class Assembly {
    // 原有成员:std::vector<std::shared_ptr<Model>> models;
    //          std::vector<std::shared_ptr<Assembly>> assemblies;
public:
    void traverseModels(const std::function<void(std::shared_ptr<Model>&)>& callback) {
        // 先处理当前Assembly下的Model
        for (auto& model : models) {
            callback(model);
        }
        // 递归处理子Assembly
        for (auto& sub_assembly : assemblies) {
            sub_assembly->traverseModels(callback);
        }
    }
};

然后在Universe中封装统一的遍历入口:

class Universe {
    // 原有成员:std::vector<std::shared_ptr<Model>> models;
    //          std::vector<std::shared_ptr<Assembly>> assemblies;
public:
    void traverseAllModels(const std::function<void(std::shared_ptr<Model>&)>& callback) {
        // 处理直接属于Universe的Model
        for (auto& model : models) {
            callback(model);
        }
        // 遍历所有Assembly及其嵌套结构
        for (auto& assembly : assemblies) {
            assembly->traverseModels(callback);
        }
    }
};

使用时只需要传入处理逻辑即可,比如构建光线追踪加速结构:

Universe my_universe;
BVHBuilder bvh_builder;

// 遍历所有Model并添加到BVH
my_universe.traverseAllModels([&](std::shared_ptr<Model>& model) {
    bvh_builder.add_model_geometry(model->get_geometry());
});

2. 收集Model引用的批量遍历

如果需要多次复用全量Model列表,可以收集所有Model的引用(而非复制),避免重复递归遍历:

在Assembly中添加收集方法:

class Assembly {
public:
    void collectModels(std::vector<std::reference_wrapper<std::shared_ptr<Model>>>& out_models) {
        for (auto& model : models) {
            out_models.emplace_back(model);
        }
        for (auto& sub_assembly : assemblies) {
            sub_assembly->collectModels(out_models);
        }
    }
};

在Universe中实现全量Model引用的获取:

class Universe {
public:
    std::vector<std::reference_wrapper<std::shared_ptr<Model>>> getAllModels() {
        std::vector<std::reference_wrapper<std::shared_ptr<Model>>> all_models;
        // 添加直接属于Universe的Model
        for (auto& model : models) {
            all_models.emplace_back(model);
        }
        // 添加所有Assembly中的Model
        for (auto& assembly : assemblies) {
            assembly->collectModels(all_models);
        }
        return all_models;
    }
};

使用时可以直接遍历引用列表:

auto all_models = my_universe.getAllModels();
for (auto& model_ref : all_models) {
    auto& model = model_ref.get();
    // 执行光栅化或其他处理逻辑
    rasterizer.submit_model(model);
}

这里存储的是shared_ptr<Model>的引用,不会复制Model数据,仅维护引用关系。

3. 架构重构(简化层级)

如果后续需要频繁扩展场景节点逻辑,可以将Universe和Assembly抽象为统一的SceneNode类,减少层级区分的复杂度:

// 通用场景节点,包含Model和子节点
class SceneNode {
public:
    std::vector<std::shared_ptr<Model>> models;
    std::vector<std::shared_ptr<SceneNode>> children;

    void traverseModels(const std::function<void(std::shared_ptr<Model>&)>& callback) {
        for (auto& model : models) callback(model);
        for (auto& child : children) child->traverseModels(callback);
    }
};

// Universe作为根节点,扩展自身的管理功能
class Universe : public SceneNode {
    // 新增专属成员:比如相机、渲染设置、全局光源等
    std::shared_ptr<Camera> main_camera;
    RenderSettings render_settings;
};

这种重构后,所有遍历逻辑完全统一,不需要区分Universe和Assembly的处理流程,代码更简洁易维护。


内容的提问来源于stack exchange,提问作者Chris Gnam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 05:10:32