# #场景 #节点 #结构 #动画 #根节点 #引擎

场景图

适用于游戏和动画的快速场景图

1 个不稳定版本

0.1.0 2023年2月9日

#1384 in 游戏开发

MIT/Apache

48KB
893

场景图

docs.rs Crates.io Crates.io

本库提供了一个类似于Unity或Unreal引擎中使用的场景图结构。它速度快,性能好,易于操作。

快速入门

要安装,请将以下内容添加到您的Cargo.toml中

scene-graph = "0.1.0"

或运行

cargo add scene-graph

以下是一个基本的SceneGraph示例

use scene_graph::SceneGraph;

fn main() {
    let mut sg: SceneGraph<&'static str> = SceneGraph::new("root");

    sg.attach_at_root("first child");
    // note that insertion order is honored.
    let second_child_handle = sg.attach_at_root("second child");

    // collect the nodes
    let nodes = Vec::from_iter(sg.iter().map(|(_parent, node)| *node));

    // note that the "root" is not seen in an `iter` operation.
    assert_eq!(nodes, ["first child", "second child"]);

    sg.attach(second_child_handle, "first grand-child").unwrap();
    sg.attach(second_child_handle, "second grand-child").unwrap();

    sg.attach_at_root("weird third way younger child");

    let nodes = Vec::from_iter(sg.iter().map(|(_parent, node)| *node));

    // note the iteration order -- because we `iter` depth first, we'll get the youngest child last.
    assert_eq!(
        nodes,
        [
            "first child",
            "second child",
            "first grand-child",
            "second grand-child",
            "weird third way younger child"
        ]
    );
}

SceneGraph的iter函数在深度优先遍历中返回父节点值和当前节点值的一个元组。SceneGraph主要设计用于Transform树,其iter是遍历这些Transform以将局部变换的场景图转换为世界空间变换的最佳方式。

分离节点

可以通过调用detach来分离场景图中的节点,这将返回一个新的SceneGraph<T>,其根是提供的节点。可以通过SceneGraph::attach_graphSceneGraph<T>附加到另一个SceneGraph<T>上。如果不需要此功能,用户可以使用remove简单地删除节点并完全丢弃它。

在不删除节点的情况下分离节点的子节点也很简单 —— iter_detach将返回一个迭代器,该迭代器将分离节点的每个后代。

petgraph的比较

SceneGraph类似于petgraph::stable_graph::StableGraph,但有一些区别。

在M1 Mac上,SceneGraph在遍历节点方面比petgraph略快,但创建节点的延迟略高。

benches 场景图 petgraph
添加和删除节点 52ns 8.56ns
遍历50k个节点 217µs 299.49µs
遍历64个节点 311ns 456.49ns

然而,这并不是scene-graph真正发光的地方 —— scene-graph的编写目标是快速迭代,与petgraph不同,petgraph是一个通用图形工具。例如,在petgraph中没有与iter函数简单等价的函数。

// in `scene-graph`
for (parent, child) in sg.iter() {
    todo!();
}

// in `petgraph`
petgraph::visit::depth_first_search(&petgraph_sg, Some(root_idx), |event| match event {
    petgraph::visit::DfsEvent::Discover(_, _) => todo!(),
    petgraph::visit::DfsEvent::TreeEdge(_, _) => todo!(),
    petgraph::visit::DfsEvent::BackEdge(_, _) => todo!(),
    petgraph::visit::DfsEvent::CrossForwardEdge(_, _) => todo!(),
    petgraph::visit::DfsEvent::Finish(_, _) => todo!(),
});

然而,petgraph 提供了许多 scene-graph 完全缺乏的算法。例如,在 petgraph 中查找图中两个节点之间的距离很简单,而在 scene-graph 中完全由用户控制。

依赖项

此包依赖于 thiserror 以提供便利,并依赖 thunderdome 的支持 Arena 分配器。实验证明 thunderdome 是选项中最容易使用且速度最快的。

MSRV

此包目前还没有 MSRV。如果它得到良好的采用,将决定一个 MSRV 政策。

许可证

双许可 MIT 或 APACHE 2.0。

依赖项

~0.4–0.8MB
~19K SLoC