- 科研
- 自动驾驶
- 物理引擎
【免费下载链接】webots
Webots Robot Simulator
Box 是 Webots 中最常用的几何原语之一,一个以局部坐标系原点为中心、三边与坐标轴对齐的长方体节点。本文将基于 Webots 官方参考文档与仓库源码(src/webots/nodes/WbBox.cpp、resources/web/wwi/nodes/WbBox.js),系统讲解 Box 节点的语法结构、size 字段取值约束、六面纹理映射方向,以及它作为碰撞检测 boundingObject 时的底层物理实现与工程实践。读完本文,你将能够在.wbt世界文件中熟练创建、调整并复用 Box 节点,同时理解其渲染与物理行为的内部机制。
一、节点语法与核心概念
Box 节点在.wbt文件中的完整定义非常简洁,只有一个用户可访问字段size:
Box { SFVec3f size 2 2 2 # any positive vector }- 类型:
Box属于Geometry节点的子类,必须被放在Shape节点的geometry字段中才能被渲染(详见 Shape 节点)。 - 默认尺寸:默认情况下,Box 在 x、y、z 三个维度上各长 2 米,几何范围为从 -1 到 +1。
- 中心位置:Box 永远以所在局部坐标系的原点 (0,0,0) 为中心,且三边分别与局部坐标系的 x、y、z 轴对齐。
- size 字段:
SFVec3f类型的向量,依次指定 Box 沿 x、y、z 轴方向的边长(外延尺寸)。注释明确要求其为"任意正向量"(any positive vector),说明三个分量都必须为正数。
一个完整的 Box 使用示例(来自仓库中的 e-puck 教程世界 projects/languages/matlab/worlds/e-puck_matlab.wbt):
Shape { appearance PBRAppearance { baseColor 0.501961 0 0.501961 roughness 1 metalness 0 } geometry DEF GEOM1 Box { size 0.2 0.2 0.1 } }二、size 字段:取值约束与源码级校验
size的三个分量定义了 Box 沿三个轴的边长。虽然语法注释只写了"any positive vector",但 Webots 在运行时会对非正数值做自动校正,这一行为可以直接在源码中确认:
在 src/webots/nodes/WbBox.cpp 中,sanitizeFields()调用WbFieldChecker::resetVector3IfNonPositive对mSize做校验,一旦出现非正分量,就会将整个size重置为(1.0, 1.0, 1.0):
bool WbBox::sanitizeFields() { if (WbFieldChecker::resetVector3IfNonPositive(this, mSize, WbVector3(1.0, 1.0, 1.0))) return false; return true; }这意味着:
- 如果直接写
Box { size 0 1 1 }之类含零或负值的尺寸,Webots 会把size静默修正为1 1 1,并在控制台给出类似Invalid 'size' changed to 1 1 1. The value should be positive.的警告(这一警告文本在仓库的 docs/discord/technical-questions-2019.md 讨论记录中也有印证)。 - 当 Box 被用作
boundingObject时,尺寸校验会更加严格:isSuitableForInsertionInBoundingObject()(WbBox.cpp)要求所有分量严格大于 0,否则在加载世界时就会报错All 'size' components must be positive for a Box used in a 'boundingObject'.,并拒绝将该 Box 用于碰撞检测。
此外,源码还提供了若干编程接口用于修改尺寸:setSize(x, y, z)、setX/setY/setZ以及rescale(scale)(将当前尺寸逐分量乘以缩放因子),这些方法在 WbBox.hpp 中声明,常用于 Supervisor 脚本运行时调整几何。
三、纹理映射:六个面的贴图方向规则
Box 的纹理是逐面(per-face)单独应用的,这是它与圆柱、球等连续曲面原语的重要区别。官方文档对六个面的纹理映射方向给出了明确的坐标系约定:
- 前面(+x 面)与后面(-x 面):从 Box 内部向外观察,以 +z 轴朝上,纹理的显示方向与二维图片正常显示方向一致。
- 右面(-y 面)与左面(+y 面):同样从内部观察、+z 轴朝上,纹理方向与二维图片一致。
- 顶面(+z 面):从上方沿 z 轴向下看向原点,以 +y 轴为视图"向上"方向,纹理方向与二维图片一致。
- 底面(-z 面):从下方沿 z 轴向上看向原点,以 -y 轴为视图"向上"方向,纹理方向与二维图片一致。
注意:文档中"前面/后面/左面/右面"的命名与源码中findIntersectedFace()的判定一一对应——FRONT_FACE对应 +x(intersectionPoint.x() == maxBound.x()),BACK_FACE对应 -x,LEFT_FACE对应 +y,RIGHT_FACE对应 -y,TOP_FACE/BOTTOM_FACE对应 ±z(见 WbBox.cpp)。
TextureTransform节点会直接影响 Box 的纹理坐标。关于translation、rotation、scale、center四个字段的完整变换语义(先平移、再绕中心旋转、最后绕中心非均匀缩放,且在几何表面上的视觉效果与坐标变换方向相反),请参见 TextureTransform 节点文档。
源码级的纹理坐标计算
Box 的 UV 计算并不依赖 3D 引擎的自动展开,而是由 Webots 自己完成。computeTextureCoordinate()(WbBox.cpp)先通过findIntersectedFace()确定射线命中的是哪个面,再按该面的局部比例计算 (u, v):
- 例如顶面(TOP_FACE):
u = (point.x - min.x) / size.x,v = 1 - (point.y - min.y) / size.y; - 前面(FRONT_FACE):
u = (point.y - min.y) / size.y,v = 1 - (point.z - min.z) / size.z。
当采用非递归(non-recursive)纹理映射时,UV 还会被压缩到六面展开图的特定象限(每个面占据整个 UV 空间的 1/4 × 1/2 区域),对应关系在 WbBox.hpp 中通过nonRecursiveTextureSizeFactor()返回的因子(4, 2)表达。pickUVCoordinate()(WbBox.cpp)则负责把射线命中点换算成 [0,1] 范围内的纹理坐标,供Display、Camera识别等拾取类功能使用。
四、Box 作为 boundingObject:碰撞检测的物理实现
Box 最常见的工程用途是作为Solid节点的boundingObject,即碰撞检测的几何代理。在 Webots 中,boundingObject字段指定用于碰撞检测的几何原语集合;若为 NULL,则对象不参与碰撞检测(详见 Solid 节点文档)。需要注意的是,一旦Solid配置了physics字段(开启动力学仿真),则boundingObject必须一并指定。
ODE 物理引擎中的盒体
Webots 的动力学仿真基于 ODE(Open Dynamics Engine)。当 Box 被用作 boundingObject 时:
createOdeGeom()(WbBox.cpp)调用dCreateBox(space, sx, sy, sz)创建 ODE 的盒形碰撞几何(dBoxGeom)。创建前会再次检查size各分量是否为正,非正则输出警告并返回 NULL。applyToOdeData()(WbBox.cpp)在每次尺寸变化后调用dGeomBoxSetLengths同步碰撞体的边长,并连同父级Solid的绝对缩放(absoluteScale())一起计算最终的世界坐标尺寸——这意味着父节点上的 Transform 缩放同样会作用到碰撞盒,且负缩放会被取绝对值处理(scaledSize()返回(size * absoluteScale).abs())。
因此,一个 Box 碰撞体的实际碰撞尺寸 =size× 其所在 Solid 链上所有 Transform 缩放因子的乘积。
碰撞体的可视化与性能
在 3D 窗口中,通过Tools → Show All Bounding Objects(或视图菜单中的"显示所有碰撞体")可以查看所有 boundingObject:它们以白色线框显示,发生碰撞时线框变为玫瑰色,静止空闲时变为蓝色(见 用户界面文档)。Box 作为 boundingObject 时,其线框会额外叠加一个随lineScale变化的外扩偏移,实现在 updateLineScale()。
从碰撞检测性能角度,官方在 教程 5:复合 Solid 与物理属性 中给出的原语效率排序为:Sphere > Box > Capsule > Cylinder,即 Box 是所有凸原语中仅次于球体、碰撞检测开销最低的选择之一。因此对于车体、墙体、货箱等长方体类物体,用 Box 做碰撞体是兼具精度与效率的推荐做法。
一个完整的碰撞体配置示例
来自测试世界 tests/api/worlds/brake.wbt(一个带关节和位置传感器的机械臂):
Robot { children [ DEF BASE_BOX Shape { geometry Box { size 0.2 0.5 0.2 } } HingeJoint { ... endPoint Solid { translation 0 0.25 -0.3 children [ DEF BOX_SHAPE Shape { geometry Box { size 0.1 0.1 0.5 } } ] boundingObject USE BOX_SHAPE physics Physics { } } } ] }这里展示了 Box 在 Webots 中的两种典型用法:作为纯视觉的Shape几何,以及通过DEF/USE机制复用同一 Box 作为boundingObject(关于 DEF/USE 的命名作用域与限制,参见 DEF 和 USE 文档)。用同一个 Box 同时充当视觉几何与碰撞几何,可以保证外观与物理形状严格一致。
五、延伸行为:包围球、流体与摩擦力方向
从源码还可以看出 Box 在其他子系统中的行为细节:
- 包围球(Bounding Sphere):
recomputeBoundingSphere()(WbBox.cpp)以原点为中心、size向量长度的一半为半径构造包围球,用于视锥剔除与拾取加速。 - 流体浸没(Fluid):当 Box 位于
Fluid节点中并参与浸没仿真时,checkFluidBoundingObjectOrientation()(WbBox.cpp)会检查浸没平面法线与重力矢量的夹角,若夹角过大(≥ π/2)会发出警告,提示浸没行为可能不符合预期。 - 摩擦力方向(Friction Direction):
computeFrictionDirection()(WbBox.cpp)根据接触法线在局部坐标系中占主导的分量,返回首个摩擦方向向量,用于各向异性摩擦的 ContactProperties 配置。
六、Web 端与 X3D 导出的同步支持
Webots 的 Web 流(web streaming)与在线查看器使用独立的 JavaScript 实现 resources/web/wwi/nodes/WbBox.js,该实现与 C++ 版本保持行为一致:同样通过resetVector3IfNonPositive做尺寸校验(默认重置为1 1 1)、以单位盒网格_wr_static_mesh_unit_box_new配合 transform 缩放渲染,并复刻了findIntersectedFace/computeTextureCoordinate的六面 UV 计算逻辑。此外,C++ 端的fieldsToSynchronizeWithW3d()(WbBox.cpp)表明size是导出到 X3D(W3D)格式时需要同步的关键字段。
七、常见注意事项小结
- 尺寸必须为正:
size任意分量为 0 或负数都会被重置为1 1 1(普通几何)或导致 boundingObject 加载报错。 - 纹理逐面映射:想统一旋转某个面的贴图,应使用
TextureTransform作用于纹理坐标,而非旋转 Box 本身。 - 碰撞尺寸随父级缩放:Box 作为 boundingObject 时,父级 Transform 的缩放会乘入最终碰撞尺寸。
- 效率优先:能用 Box 近似表示的碰撞体,尽量不用 Mesh/IndexedFaceSet,以换取更快的碰撞检测。
参考文档
- Box 节点(本文原始文档)
- Shape 节点 与 Solid 节点
- TextureTransform 节点
- DEF 和 USE 机制
- 教程 5:复合 Solid 与物理属性
- 源码实现:src/webots/nodes/WbBox.cpp、src/webots/nodes/WbBox.hpp、resources/web/wwi/nodes/WbBox.js
- 示例世界:projects/languages/matlab/worlds/e-puck_matlab.wbt、tests/api/worlds/brake.wbt
- 科研
- 自动驾驶
- 物理引擎
【免费下载链接】webots
Webots Robot Simulator
相关推荐
Webots Group 节点完全指南:零变换分组容器与 boundingObject 组合实战
Webots Group 节点完全指南:零变换分组容器与 boundingObject 组合实战 Group 是 Webots 场景图中最基础的"容器型"节点,
科研自动驾驶物理引擎Godot CollisionShape3D 完全指南:3D 物理碰撞体的形状节点与实战用法
Godot CollisionShape3D 完全指南:3D 物理碰撞体的形状节点与实战用法 导读 CollisionShape3D 是 Godot Engin
文档教程游戏开发Material Maker 3D 纹理选择节点(Select Node)完全指南:基于颜色索引的多纹理合并与映射实战
Material Maker 3D 纹理选择节点(Select Node)完全指南:基于颜色索引的多纹理合并与映射实战 Select(选择)节点 是 Mater
桌面应用图形学3D渲染图像处理
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考