基于 Rerun C++ SDK 构建三维模拟时钟:Boxes3D、Points3D 与 Arrows3D 时间轴动画实战

发布时间:2026/9/16 21:28:48
基于 Rerun C++ SDK 构建三维模拟时钟:Boxes3D、Points3D 与 Arrows3D 时间轴动画实战 基于 Rerun C SDK 构建三维模拟时钟Boxes3D、Points3D 与 Arrows3D 时间轴动画实战【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun导读本指南以仓库中的 examples/cpp/clock 示例为核心讲解如何使用 Rerun 的 C SDKrerun_cpp仅用Boxes3D、Points3D、Arrows3D三种 3D 原语构建一个带时分秒指针、在sim_time时间轴上持续动画的模拟时钟。读完本文你将掌握 Rerun C 示例的 CMake 构建流程、RecordingStream数据流的基本用法、时间轴Timeline驱动动画的机制以及如何用最小代码实现少量图元、大量事件的高频可视化场景。一、示例概览一个由三种 3D 原语组成的时钟examples/cpp/clock是一个极简但完整的 Rerun C 示例。它没有导入任何外部模型或纹理而是纯程序化地生成一个表盘与三根指针表盘frame由Boxes3D半尺寸盒体构成指针端点_pt后缀实体由Points3D构成指针本身hand后缀实体由Arrows3D带起点、方向向量、半径的箭头构成。三根指针分别是秒针seconds、分针minutes和时针hours它们围绕world坐标系的原点旋转。整个动画在sim_time这一时间轴上推进每帧同时写入 6 个实体每个指针各 2 个端点和箭头共循环 10,000 步。与 Python 版 examples/python/clock/clock.py同样记录world/seconds_pt、world/seconds_hand等实体和 Rust 版 examples/rust/clock/src/main.rscargo run -p clock -- --help可运行相比C 版在实现逻辑上完全一致本文以 C 版源码 main.cpp 为准展开讲解。二、构建与运行三种方式任选2.1 从仓库根目录构建推荐原文档给出的构建方式要求先克隆仓库并具备 Rust 工具链因为rerun_cpp需要编译其 Rust 核心然后在仓库根目录执行cmake . cmake --build . --target example_clock ./examples/cpp/clock/example_clock第一条命令cmake .会读取仓库根目录的CMakeLists.txt其中通过add_subdirectory(clock)将 examples/cpp/clock/CMakeLists.txt 纳入构建根级 examples/cpp/CMakeLists.txt 中还有add_dependencies(examples example_clock)即example_clock也是examples聚合目标的一部分。第二条命令cmake --build . --target example_clock只编译时钟这一个目标避免全量编译整个仓库。第三条命令直接运行生成的可执行文件。程序启动时会调用rec.spawn()自动拉起一个 Rerun Viewer 窗口并建立 gRPC 连接因此无需手动开启查看器。2.2 作为独立 CMake 项目构建如果脱离仓库单独使用该示例CMakeLists.txt提供了备选路径当未定义RERUN_REPOSITORY变量时它会通过FetchContent从预编译的rerun_cpp_sdk.zipURL 由RERUN_CPP_URL变量指定默认指向最新 release 的rerun_cpp_sdk.zip下载并链接rerun_sdkset(RERUN_CPP_URL https://github.com/rerun-io/rerun/releases/latest/download/rerun_cpp_sdk.zip CACHE STRING URL to the rerun_cpp zip.) include(FetchContent) FetchContent_Declare(rerun_sdk URL ${RERUN_CPP_URL}) FetchContent_MakeAvailable(rerun_sdk)两种分支最终都通过target_link_libraries(example_clock PRIVATE rerun_sdk)链接 SDK。在仓库内构建时rerun_strict_warning_settings(example_clock)还会为该目标启用严格的编译警告设置保证示例代码质量符合仓库规范。说明CMakeLists.txt中的RERUN_CPP_URL默认指向外部下载地址文章不再展开外部链接在仓库内构建时不会触发该分支。三、核心实现拆解从数据流到图元完整源码见 examples/cpp/clock/main.cpp逻辑分三段常量与工具函数、静态场景初始化、时间轴循环写入。3.1 常量定义表盘与指针的几何参数const float LENGTH_S 20.0f; // 秒针长度 const float LENGTH_M 10.0f; // 分针长度 const float LENGTH_H 4.0f; // 时针长度 const float WIDTH_S 0.25f; // 秒针半径绘制时取一半 const float WIDTH_M 0.4f; // 分针半径 const float WIDTH_H 0.6f; // 时针半径秒针最长20 个单位且最细宽度 0.25分针次之时针最短最粗符合真实钟表的视觉比例表盘用秒针长度作为半尺寸即表盘半径恰好等于秒针长度指针旋转到任意角度都不会超出表盘边界循环总步数num_steps 10000即生成 10,000 帧时间序列数据。3.2log_hand单根指针的写入逻辑void log_hand( const rerun::RecordingStream rec, const char* name, seconds step, float angle, float length, float width, uint8_t blue ) { const auto tip rerun::Vec3D{length * sinf(angle * TAU), length * cosf(angle * TAU), 0.0f}; const auto c static_castuint8_t(angle * 255.0f); const auto color rerun::Color{static_castuint8_t(255 - c), c, blue, std::maxuint8_t(128, blue)}; rec.set_time_duration(sim_time, step); rec.log( std::string(world/) name _pt, rerun::Points3D(rerun::Position3D(tip)).with_colors(color) ); rec.log( std::string(world/) name hand, rerun::Arrows3D::from_vectors(rerun::Vector3D(tip)) .with_origins({{0.0f, 0.0f, 0.0f}}) .with_colors(color) .with_radii({width * 0.5f}) ); }该函数体现了三个关键设计1. 角度 → 端点的三角函数映射指针端点坐标由tip (length·sin(angle·TAU), length·cos(angle·TAU), 0)计算。TAU 2π被定义为常量angle取值为 0~1 的归一化角度乘上TAU后即得完整圆周的弧度。这样只需传入指针在一圈中的比例位置即可得到三维空间中的端点坐标。z分量恒为 0说明整个时钟平面位于z0平面内。2. 角度驱动的渐变色c angle * 255颜色为(255-c, c, blue, max(128, blue))。随着指针旋转红绿通道沿色环平滑过渡从红到绿再到红形成彩虹渐变效果blue参数用于区分三根指针的基色——秒针为 0红绿渐变、分针为 128、时针为 255同时透明度始终不低于 128保证在深色背景下清晰可见。这与 Python 版中color_s (255 - scaled*255, scaled*255, 0, 128)的计算完全一致。3. 实体路径命名与图元选择每根指针在world下写入两个实体world/seconds_ptPoints3D只含端点位置Position3D(tip)并附颜色world/seconds_handArrows3Dfrom_vectors从端点向量直接构造箭头原点固定在(0,0,0)半径取width * 0.5因为Arrows3D的半径是直径语义。值得注意的是Rust 版 main.rs 中同样使用.with_radii([width * 0.5])三个语言版本的参数语义保持一致。3.3 时间轴动画的核心机制rec.set_time_duration(sim_time, step);set_time_duration为后续的所有log调用设置一个双时间点timeline——名为sim_time类型为持续时间Duration数值为step秒。这一行必须出现在该时间步的log之前即先设时间再写数据。循环中每次迭代都会推进sim_time于是 Rerun Viewer 底部的时间轴会出现可拖动的进度条用户可以像播放视频一样回放/快进整个时钟动画。由于step类型为std::chrono::seconds时间单位是秒Rust 版对应rec.set_duration_secs(sim_time, step as f64)Python 版对应rr.set_time(sim_time, durationt_secs)三者语义等价。3.4 静态场景log_static与ViewCoordinates在进入动画循环前代码写入两个一次性静态实体rec.log_static(world, rerun::ViewCoordinates::RIGHT_HAND_Y_UP); rec.log_static(world/frame, rerun::Boxes3D::from_half_sizes({{LENGTH_S, LENGTH_S, 1.0f}}));ViewCoordinates::RIGHT_HAND_Y_UP声明world坐标系为右手系、Y 轴向上即 Y 是世界上方向这保证 3D 视角下时钟垂直于地面摆放视觉观感正确其他 C 示例如 examples/cpp/dna/main.cpp 也使用同类坐标声明。Boxes3D::from_half_sizes({{LENGTH_S, LENGTH_S, 1.0f}})以原点为中心、半尺寸为(20, 20, 1)生成一个很薄的方形表盘。log_static与log的区别在于静态数据不属于任何时间点在整个录制期间恒定存在不会在时间轴上产生变化因此只需记录一次。Python 版对应rr.log(..., staticTrue)Rust 版对应rec.log_static(...)是各语言 SDK 的统一约定。四、指针的运动学取模运算驱动的三种转速在main的循环中三根指针以不同的模数计算归一化角度for (int step 0; step num_steps; step) { log_hand(rec, seconds, seconds(step), (step % 60) / 60.0f, LENGTH_S, WIDTH_S, 0); log_hand(rec, minutes, seconds(step), (step % 3600) / 3600.0f, LENGTH_M, WIDTH_M, 128); log_hand(rec, hours, seconds(step), (step % 43200) / 43200.0f, LENGTH_H, WIDTH_H, 255); }指针模数周期归一化角度说明秒针60(step % 60) / 60每 60 秒转一圈走一圈需 60 步分针3,600(step % 3600) / 3600每 3,600 秒转一圈转速为秒针的 1/60时针43,200(step % 43200) / 43200每 43,200 秒12 小时转一圈转速为分针的 1/12三者的周期之比为 60 : 3600 : 43200 1 : 60 : 720恰好对应真实时钟秒、分、时的传动比。angle始终落在[0, 1)区间内保证指针每转完一圈就平滑复位不会产生跳变。从性能角度看每步迭代只写入 6 个小图元3 个Points3D 3 个Arrows3DRust 版源码注释中明确将此类场景定位为many small events大量小事件的基准测试这意味着该示例也适合用于测试 Rerun 在高频、小数据量日志场景下的吞吐表现。五、运行结果与 Rerun Viewer 中的交互运行./examples/cpp/clock/example_clock后rec.spawn().exit_on_failure()自动启动 Rerun Viewer 进程并通过 gRPC 接收数据若启动失败程序直接退出exit_on_failure避免无头环境下挂死。Viewer 中呈现一个位于z0平面、Y 轴向上的表盘秒/分/时针由红绿渐变色箭头从原点指向各自端点端点处有同色的小圆点。底部时间轴显示sim_time单位为秒可拖动进度条逐帧观察指针运动也可使用播放按钮连续回放 10,000 帧动画。由于所有实体均挂在world/层级下可在左侧实体树中单独隐藏/显示某根指针或表盘。六、拓展同一思路在 Python 与 Rust 中的实现该示例在仓库中三语言齐备可作为学习 Rerun 多语言 API 一致性的对照素材Pythonexamples/python/clock/clock.py —— 通过rr.script_setup(args, rerun_example_clock)初始化--steps命令行参数控制步数默认 10,000用rr.set_time(sim_time, durationt_secs)设置时间点Rustexamples/rust/clock/src/main.rs —— 通过cargo run -p clock -- --help运行支持--steps参数默认 10000用rec.set_duration_secs(sim_time, step as f64)设置时间点。三份实现共享同一套实体路径world/frame、world/seconds_pt等、同一组几何常量与取模周期只是 API 形态不同——这为同一数据集在三种语言间互换提供了直观样例。若读者想进一步了解 Rerun 的时间轴与数据模型机制可参考仓库根目录的 ARCHITECTURE.md 与 docs/content/concepts 目录下的概念文档。七、小结examples/cpp/clock用约 60 行代码完整演示了 Rerun C SDK 的核心用法RecordingStream创建与spawn拉起 Viewer、log_static写入静态场景、set_time_duration驱动时间轴、Points3D/Arrows3D/Boxes3D三种图元组合、以及基于归一化角度与取模运算的指针运动学。它既是新手入门 Rerun 的Hello World也是评估 SDK 高频小事件写入性能的轻量基准值得在动手编写自己的可视化应用前先行跑通。【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考