☰
Webots Web 动画导出:将 3D 仿真录制为可交互的 HTML5 动画页面
2026/10/6 2:09:17 网站建设 项目流程
  • 科研
  • 自动驾驶
  • 物理引擎

【免费下载链接】webots

Webots Robot Simulator

项目地址:https://gitcode.com/gh_mirrors/web/webots
点击查看免费下载

导读

Web Animation 是 Webots 内建的一项导出功能:它可以把正在运行的 3D 仿真实时录制为一个"可交互的电影"——一个独立的HTML5页面,页面自带播放/暂停等播放控件,同时还允许观众在任意时刻自由旋转、缩放、平移视角。与单纯的 Web Scene 导出(静态 3D 场景快照)不同,Web 动画额外导出一个包含运动物体轨迹的JSON动画文件,完整重现仿真过程中物体的位移、旋转与外观变化。阅读完本文,你将掌握 Web 动画的录制与导出流程、webots-viewWeb 组件(WebotsView.js 包)的属性与方法 API、动画文件记录的字段范围与底层实现原理,并了解如何在自有网站中嵌入动画、如何规避浏览器本地文件安全限制。


什么是 Web 动画

Webots 可以将一段仿真录制为交互式 3DHTML页面,效果类似"带播放控制条的电影",但观看者可以在播放过程中随时改变视角(用鼠标或触摸屏导航,操作方式与 Webots 内 3D 窗口一致)。

其机制与 Web Scene 导出 基本一致:导出时先生成一个包含世界图形信息的W3D文件(Webots 自定义的、基于 XML 的 3D 图形格式),再生成HTML5页面和CSS样式文件。Web 动画与 Web Scene 的唯一区别在于:Web 动画额外导出一个JSON动画文件,其中记录了运动物体的位置序列,页面加载后由播放器按时间轴回放这些更新。

下图为 Webots 生成的一个动画页面示例(原文档中的示例动画页面由 Cyberbotics 官方托管):

说明:在项目仓库的 docs/guide/web-animation.md 中可查看本文对应的官方文档原文;关于导出过程中的静态场景(W3D)、CSS文件与浏览器兼容性细节,请同时参考 docs/guide/web-scene.md。


如何导出 Web 动画

导出过程全部在 Webots 图形界面中完成,无需编写任何代码:

  1. 打开一个正在(或准备)运行的仿真世界;
  2. 在主菜单中选择Share...;
  3. 在弹出的共享对话框中,选择是上传到 webots.cloud还是保存到本地;
  4. 点击Record and export animation按钮开始录制;
  5. 在仿真中执行你想要展示的动作;
  6. 录制完成后,点击Stop HTML5 animation按钮结束录制并保存动画;
  7. Webots 会询问是否用操作系统默认浏览器播放生成的文件。

导出产物

录制结束后,目标HTML文件所在目录会同时生成以下文件:

文件作用
*.html包含 Webots 播放器(web component)的 HTML5 页面
*.css页面样式,仅作为样式参考,可以修改或删除
*.w3d3D 场景图形文件
*.json动画序列文件(运动物体位置、颜色等更新的时间序列)
所需纹理图片场景引用的贴图资源

注意:由于默认浏览器对本地file协议的限制(详见下文"浏览器兼容性与安全限制"一节),播放选项可能无法正常工作,此时请改用本地 HTTP 服务器方式预览。

用 Supervisor 控制器控制录制

除了 GUI 按钮,一个 Supervisor 控制器同样可以启动或停止动画录制,这让批量生成动画、或让仿真在特定条件满足时自动开始录制成为可能。对应 API 声明位于 include/controller/c/webots/supervisor.h:

bool wb_supervisor_animation_start_recording(const char *filename); bool wb_supervisor_animation_stop_recording();

在 Webots 内部,WbSupervisorUtilities会将 Supervisor 发出的录制请求与WbAnimationRecorder的状态信号(animationStartStatusChanged/animationStopStatusChanged)关联起来(见 src/webots/nodes/utils/WbSupervisorUtilities.cpp)。


如何在网站中嵌入 Web 动画

嵌入方式与 Web Scene 完全一致,请参考 docs/guide/web-scene.md#how-to-embed-a-web-scene-in-your-website 中的说明:

  • 导出的HTML页面本身即为最简单的集成参照,外站可以直接引用;导出的CSS文件可以在集成过程中替换。
  • 若追求更省事的方案,可以用一个指向生成页面的<iframe>标签嵌入。

无论哪种方式,播放器所需的CSS、JavaScript等资源都可以长期复用 Cyberbotics 官网托管的资源。


编程接口:webots-viewWeb 组件

Web 动画页面由 WebotsView.js 包中的webots-viewWeb 组件负责播放。组件通过自定义属性接收配置,通过公开方法实现更复杂的交互。

组件属性(Attributes)

属性说明
data-thumbnail缩略图.jpg文件名;不设置时加载期间显示默认缩略图
data-scene包含 3D 场景的.w3d文件名
data-animation包含动画序列的.json文件名
data-autoplay布尔值,是否自动播放动画,默认为true
data-isMobileDevice布尔值,指定应用是否运行在移动设备上
showCustomWindow布尔值,是否在工具栏显示自定义窗口按钮;默认隐藏,且必须在加载动画之前设置

关键行为:webots-view的属性只在页面加载时求值一次。如果data-scene与data-animation均已设置,组件会自动尝试加载动画。

典型用法示例(将动画文件与页面放在同一目录时):

<webots-view ><script> const view = document.querySelector('webots-view'); view.loadAnimation('scene.w3d', 'animation.json', true, false, 'scene.jpg', false); </script>

自定义信息窗口

你可以将一个空窗口个性化为动画的辅助信息面板(如显示图表、动画说明等)。要启用它,必须在加载动画之前将webots-view元素的showCustomWindow属性设为true,之后工具栏右侧会出现一个打开该窗口的图标。

可用以下函数个性化窗口内容:

函数说明
setCustomWindowTitle(title)设置窗口标题,title为新标题
setCustomWindowTooltip(tooltip)设置窗口按钮的提示文字,tooltip为新的提示
setCustomWindowContent(content)设置窗口内容(替换已有内容),content为新内容

注意:这些函数必须在onReady()被调用之后调用,以确保窗口已经创建完成。


动画文件格式与底层实现

JSON 文件结构

动画JSON文件不是对每一帧做完整快照,而是只记录发生变化的部分。从 src/webots/engine/WbAnimationRecorder.cpp 的computeUpdateData()可以看出,每一帧的结构为:

{ "time": 12.34, "updates": [ { "id": 42, "translation": "0.1 0.2 0.3", "rotation": "0 1 0 1.5708" } ] }

文件头部还包含两个关键元数据(见 WbAnimationRecorder.cpp):

  • basicTimeStep:由WorldInfo.basicTimeStep与WorldInfo.fps共同推导,公式为basicTimeStep * ceil((1000.0 / fps) / basicTimeStep),是播放时每个动画帧对应的仿真时间间隔;
  • labelsIds:动画中涉及的 Supervisor 文本标签(label)id 列表,用;分隔。

录制停止时,WbAnimationRecorder::stopRecording()会把初始状态帧(时间time: 0)写在所有更新帧之前;初始状态只包含那些在动画期间实际发生过变化的节点(通过WbAnimationCommand::isChangedFromStart()判断)。如果整个仿真期间没有任何节点发生变化,Webots 会给出明确提示:无动画内容可导出,此时应改用 Web Scene 导出。

录制器的核心流程

Web 动画录制在 Webots 内部由单例WbAnimationRecorder(src/webots/engine/WbAnimationRecorder.hpp)实现,其工作流程为:

  1. start():先把世界导出为 HTML/W3D 场景(world->exportAsHtml(fileName, true)),再把目标文件名由.html替换为.json并开始录制(WbAnimationRecorder.cpp);
  2. populateCommands():遍历世界中所有子节点,对每个实现了fieldsToSynchronizeWithW3d()的节点创建一个WbAnimationCommand,监听其相关字段的valueChanged等信号;USE节点被跳过——DEF/USE 机制由前端webots.min.js处理(WbAnimationRecorder.cpp);
  3. update():在每个物理步结束(physicsStepEnded信号)时检查是否满足当前时间 - 上次更新时间 >= 1000.0 / fps,满足则把这一时刻的脏字段(dirty fields)序列化写入JSON文件(WbAnimationRecorder.cpp)——这就是下文"刷新率"一节中WorldInfo.fps起作用的代码依据;
  4. stop():断开信号、写入头部与初始帧、收尾关闭文件,并询问用户是否在浏览器中打开(WbAnimationRecorder.cpp)。

另外,WbAnimationCommand在序列化translation与rotation时做了数值舍入(ROUND(x, 0.0001)写入文件、ROUND(x, 0.001)做变化检测),既能压缩数据量,又避免每帧都因浮点噪声写出无意义更新(WbAnimationRecorder.cpp)。

节点删除与标签(Labels)

  • 当某个节点在录制过程中被删除,updateCommandsAfterNodeDeletion()会移除对应的录制命令,避免写入失效节点数据(WbAnimationRecorder.cpp);
  • Supervisor 在仿真中添加的文本标签(wb_supervisor_set_label)也会被同步记录为动画的labels数组,可随动画一起回放。

动画记录字段的范围(Limitations)

动画文件只记录以下字段的变化:

节点字段说明
LED.colorLED 颜色变化
Material.diffuseColor漫反射颜色变化
Material.emissiveColor自发光颜色变化
TextureTransform.translation纹理坐标平移(仅针对 Track 节点,用于表现传送带等履带纹理运动)
Pose.rotation姿态旋转
Pose.translation姿态平移
Light.color光源颜色变化
Light.on光源开关变化

其余字段均不会被记录;节点的插入与删除也不会被记录。其他限制请参考 docs/guide/web-scene.md#limitations(如Skin节点不支持、Pen设备不支持、同一页面只能存在一个webots-view元素等)。

从源码角度看,"记录哪些字段"由各节点实现的fieldsToSynchronizeWithW3d()方法决定,录制器只同步这些字段。例如:

  • src/webots/nodes/WbPose.cpp:Pose同步translation、rotation;
  • src/webots/nodes/WbLight.cpp:Light同步color、on、intensity、ambientIntensity、castShadows;
  • src/webots/nodes/WbMaterial.cpp:Material同步ambientIntensity、shininess、specularColor、transparency、emissiveColor等;
  • src/webots/nodes/WbTextureTransform.cpp:TextureTransform同步center、rotation、scale、translation。

一个值得注意的实现细节:LED.color本身并没有独立的序列化逻辑——在 src/webots/nodes/WbLed.cpp 中,LED 节点会递归查找其子结构中的Material、PBRAppearance与Light节点,并把颜色写入这些节点(setMaterialsAndLightsColor())。因此 LED 颜色动画在JSON文件中实际表现为Material.diffuseColor/Material.emissiveColor/Light.color等字段的更新,这也解释了为什么LED.color出现在可记录字段列表中。


场景刷新率(Scene Refresh Rate)

动画的渲染节奏由浏览器标准的window.requestAnimationFrame()驱动,其回调次数通常为每秒 60 次,多数浏览器中会与显示器刷新率保持一致(参见 MDN 关于requestAnimationFrame的文档)。

但刷新率还受WorldInfo.basicTimeStep影响:因为动画更新只在仿真步进(physics step)时才会发出。实际刷新率可用下图公式估算:

即实际帧率受以下三者共同制约:

  1. 浏览器requestAnimationFrame提供的显示刷新率(通常约 60 Hz);
  2. 仿真步长WorldInfo.basicTimeStep(更新只在每个仿真步发送);
  3. WorldInfo.fps(录制器按1000 / fps毫秒间隔采样,见上文WbAnimationRecorder::update()源码)。

实际刷新率约为min(1 / basicTimeStep, 显示刷新率)附近,并受WorldInfo.fps的采样上限约束。

注意:不建议在录制动画过程中修改WorldInfo.FPS或WorldInfo.basicTimeStep字段,否则会导致动画时间轴与采样节奏错乱。


浏览器兼容性与安全限制

Web 动画播放器内部基于WRENJS库(Webots 渲染引擎 WREN 编译为 WebAssembly 的版本,底层依赖WebGL 2)。相关限制与应对方法与 Web Scene 一致,详见 docs/guide/web-scene.md#remarks-on-the-used-technologies-and-their-limitations,核心要点如下:

  • WebGL 2 支持:新版 Firefox、Chrome、Edge 均已支持;Safari 尚未支持,遇到渲染异常请先确认浏览器设置中 WebGL 2 已启用。
  • 本地文件(file协议)限制:Chrome、Firefox 68+ 等浏览器默认禁止通过file协议打开本地W3D与纹理文件,而播放器需要读取这些文件。解决方式有两种:
    • 在导出文件所在目录启动本地 HTTP 服务器,然后通过服务器访问HTML文件:
      # Python 3 python3 -m http.server # Python 2 python -m SimpleHTTPServer # Node.js(需先全局安装 http-server) sudo npm install -g http-server http-server
    • 临时关闭浏览器安全标志:
      • Chrome:以--allow-file-access-from-files或--disable-web-security --user-data-dir=.chrome启动;
      • Firefox:在地址栏输入about:config,搜索privacy.file_unique_origin或security.fileuri.strict_origin_policy,双击将其从true改为false。

总结

Web Animation 把 Webots 仿真与 Web 发布无缝衔接:通过 GUI 一键录制或 Supervisor API 程序化控制,即可产出一套HTML + W3D + JSON + CSS的交互式动画页面,再由webots-viewWeb 组件在任意支持 WebGL 2 的浏览器中回放。录制过程以"只记录变化字段 + 时间序列"的方式生成紧凑的 JSON 动画,字段范围受各节点fieldsToSynchronizeWithW3d()约束,播放节奏则由WorldInfo.basicTimeStep、WorldInfo.fps与浏览器刷新率共同决定。掌握了本文的导出流程、组件 API 与底层机制,你便可以在自己的网站中快速发布可交互、可自由观察视角的机器人仿真动画。

  • 科研
  • 自动驾驶
  • 物理引擎

【免费下载链接】webots

Webots Robot Simulator

项目地址:https://gitcode.com/gh_mirrors/web/webots
点击查看免费下载

相关推荐

上一篇:百度网盘密码智能获取工具完全操作指南
下一篇:Neovim LSP配置终极指南:快速搭建300+语言开发环境的完整方案

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询