Three.js 实时机器人动画:时间戳插值与缓冲

机器人 Pose、Joint、路径数据由后端按时间戳持续返回。前端不是收到一条就直接更新模型——那样画面只会一顿一顿地跳——而是:

  • 为每个机器人维护一份独立的 RobotBuffer;
  • 用统一的 originTime 把后端的绝对时间戳换算成相对动画时间;
  • 缓存的数量和时间跨度达到阈值后,再建立前端的 playTime 开始播放;
  • 渲染时按当前播放时间,在时间戳 Buffer 里找到前后两个采样点,算出插值比例;
  • 位置用 Lerp、姿态用 Quaternion SLERP、关节值用线性插值;
  • 最后把算出的 position、quaternion、jointValues 写回 URDFRobot 和 URDFJoint。

这样做把后端数据频率和 Three.js 渲染频率解耦,同时抵抗一定的网络抖动,让机器人运动连续、平滑。

这篇按这个链路走一遍,核心代码都贴出来。

阅读更多

Three.js 如何显示坐标系、碰撞体和质心

前面几篇讲交互。这一篇回到模型本身 —— URDF 里除了 <visual> 描述的外观,还有三样渲染用不到、调模型时离不开的东西:关节坐标系、碰撞体、<inertial>。

它们默认都不显示,需要时再打开。

阅读更多

Three.js 如何实现悬停高亮与提示框

上一篇讲拖动关节时屏幕上那条辅助线。这一篇讲鼠标还没按下时的两件事:亮起来的那个零件,和跟着指针走的那个小框。

命中检测在拖动关节那篇里讲过 —— pointermove 发一条射线,从命中的 Mesh 往上找出 link 和 joint。这一篇从命中之后开始。

难点不在显示,在信息怎么从三维场景里出去:命中的结果在控制器手里,提示框却是画布外面一个普通的 DOM 节点。

阅读更多

Three.js 如何生成关节的运动轨迹

上一篇讲鼠标怎么拖着关节动。这一篇讲拖动时屏幕上那条辅助线 —— 它告诉用户”这个关节还能往两边走多远”。

这条线是拖拽开始时才出现的,一松手就消失。

阅读更多

Three.js 如何用鼠标拖动关节

上一篇讲了怎么给关节一个角度。但那套方法是给程序用的 —— 滑条、动画数据、算法,都能算出一个确定的数。这篇文章讲的是把这个数交给鼠标:按住机器人的某一截拖一下,关节跟着转。

难点在坐标系。鼠标是二维的,关节是三维的,中间要换三次。

阅读更多

Three.js 如何旋转和推拉关节

机器人模型加载进来之后,下一步是让它动。这篇不讲 URDF 怎么解析,只讲一件事:手上有一个关节角度、或者一段推拉距离,怎么在 Three.js 里让对应那截模型动起来。

阅读更多

Three.js 如何解析 URDF 机器人模型

机器人可视化的第一步,是把一个 URDF 文件变成 Three.js 场景里能渲染、能动的东西。

这件事听起来像是「加载一个模型」,但 URDF 根本不是模型文件。它里面没有顶点、没有法线、没有材质贴图,只有一个 XML 骨架,描述机器人由哪些刚体组成、这些刚体怎么连起来。真正的几何体(STL、DAE)是另外的文件。

所以 Three.js 要做的,是把这套「关系描述」翻译成一棵 Object3D 树。这篇分两部分:先讲 URDF 到底描述了什么,再逐段拆 URDFLoader 的源码,看它每一步在干什么。

阅读更多

threejs使用pbr物理材质

MeshStandardMaterial 是 three.js 里默认走 PBR 的材质。它的着色基于 metallic-roughness 工作流——也就是 glTF 用的那一套——光照响应是物理化的,跟 MeshPhongMaterial 那种靠高光指数凑出来的效果不是一个路子。

它一共两个核心旋钮:

参数 范围 含义
metalness 0–1 0 是电介质(塑料、木头、漆面、玻璃),1 是纯金属。中间值基本只在烘焙贴图里出现
roughness 0–1 0 是镜面,高光收成一个点;1 完全漫反射,没有高光

两个参数,配上一张 color、一张法线贴图,已经能覆盖场景里绝大部分东西:塑料外壳、木头桌面、没上漆的金属、混凝土、地面。日常够用了。

但它们有一条共同的边界——描述的全都是”同一个表面”。roughness 说的是这个表面有多粗糙,metalness 说的是这个表面是不是金属,color 说的是这个表面是什么颜色。三个答案指向的是同一层。

一辆车不是这么回事:

  • 车漆是两层。底下是带颜色的色漆,上面覆一层无色透明的清漆。清漆有自己的粗糙度,跟底色那层完全是两回事——底色可以很哑,清漆同时很亮。
  • 玻璃不是一个”表面”,是一个”体积”。光要穿过去,还要在穿过的那段路程里被染色。
  • 轮毂是纯金属,没有漫反射,看到的全是反射来的环境。这条 standard 能表达,但它会牵出环境贴图的问题。

前两条 MeshStandardMaterial 表达不了:它没法说”这个表面之上还盖着另一层,那层有自己的粗糙度”,也没法说”光会穿过这个表面,并在里面走一段”。

MeshPhysicalMaterial 就是来补这两块的。

阅读更多

threejs后处理实现轮廓线功能

鼠标移到光伏基站里的配电箱上,箱体亮起一圈黄边;移到旁边的汇流箱上,边就跟着换到汇流箱。这一圈边就是轮廓线,three.js 里对应的东西是后处理里的 OutlinePass。

先把一个容易混的地方分开:这圈边是”画”出来的,”鼠标在哪个箱体上”是”算”出来的。 判断鼠标指着谁用的是 Raycaster 射线拾取,把那个物体描一圈用的是 OutlinePass。两件事经常一起出现,但互不认识——OutlinePass 全程不关心鼠标,它只知道”这批物体要描边”。

这篇只讲描边那一半。

阅读更多

Three.js InstancedMesh 实例化渲染

场景里要放一万个一样的物体,最直接的写法是循环 new 一万个 Mesh,一个个 add 进场景。几十个没问题,上万之后帧率会掉下来一大截。

原因不在几何体:一万个立方体加起来也才 12 万个三角形,对 GPU 来说这点量很小。问题出在 DrawCall。

阅读更多