当你打开 Three.js 写 3D 场景时,第一个要搞懂的问题就是:
一个物体到底摆在哪里?
别小看这个问题。你觉得一个立方体在世界坐标 (3,0,0),结果它移动后出现在奇怪的位置,十次里有九次是因为------
👉 你忘了它有个"爸爸"。
今天我们就用一个超通俗的方式,把 Three.js 的坐标讲清楚。看完这篇文章,你会明白:
- 世界坐标(World Coordinates)和本地坐标(Local Coordinates)到底怎么回事?
- 世界坐标,基准点为固定原点(0,0,0),描述物体在整个场景中的绝对位置
- 局部/本地坐标,基准点为物体自身的几何中心(中心点),描述子物体相对于父物体的位置
- 子对象相对于父对象的坐标是怎么计算的?
- 为什么把 cube 放进 parentCube 后,位置就"变了"?
- 实战代码是如何运行的?
准备好了吗?开始!
🧱 1. 世界坐标:整个世界的"绝对地址"
在 Three.js 中,有一个你永远逃不掉的概念:
世界坐标(World Coordinates)就是所有物体的绝对位置。
比如:
js
cube.position.set(3, 0, 0);
scene.add(cube);
意思很简单:
cube 在世界的 x=3 的位置。
就像你告诉朋友:"我在北京"。
无论你爸在哪,你都在北京。
👨👦 2. 本地坐标:相对于"父元素"的位置
但如果你写了:
js
const parentCube = new THREE.Mesh(geometry, parentMaterial);
parentCube.add(cube);
事情就不一样了。
cube 就有了一个"爸爸" parentCube。
此时你再写:
js
cube.position.set(3, 0, 0);
scene.add(parentCube);
这句话就变成:
cube 在 parentCube 的局部空间中,相对于父物体,往 x 正方向移动 3。
也就是说:
- parentCube 就像一个坐标参照系。
- cube 相当于在这个内部空间里移动。
这就好比你说:
"我离我爸三米远。"
但你爸在北京,你也就实际上还是在北京附近。
⚙️ 3. 回到你的示例:它到底发生了什么?
你写的代码如下:
js
const cube = new THREE.Mesh(geometry, material);
const parentCube = new THREE.Mesh(geometry, parentMaterial);
parentCube.add(cube);
parentCube.position.set(-3, 0, 0);
// cube.position.x = 1;
// cube 的坐标是相对于 parentCube 的,所以在页面上可以看到 cube 相对于 parentCube(父元素)向右移动到了原点坐标处
cube.position.set(3, 0, 0);
让我们逐步理解发生了什么。
🟦 第一步:parentCube 放在世界坐标 (-3,0,0)
这意味着:
"爸爸站在世界左边 3 单位的位置。"
🟦 第二步:cube 相对"爸爸"往右移动 3 个单位
cube.position.set(3,0,0) 的意思是:
cube 在父对象内部向右移动 3。
也就是说:
👉 cube 的世界坐标 = 父对象世界坐标 + 自己的本地坐标
计算一下:
- 父对象在世界: (-3, 0, 0)
- cube 在本地: (+3, 0, 0)
所以 cube 在世界中的真实位置:
js
世界位置 = (-3) + 3 = 0
------刚好回到了世界原点!🎯
这就是你看到:
cube "看起来回到了原点"。
🎯 4. 一个超形象的比喻:三.js 坐标 = 现实世界的"你"和"你爸"
- 世界坐标:你住在北京就是北京,这是全世界都懂的绝对坐标。
- 本地坐标:你说"我离我爸三米远",那你得先知道你爸在哪。
- 父对象移动时,子对象跟着被整体移动:因为你爸挪窝了,你当然也跟着挪了。
这就是 parent.add(child) 的意义:
你把 child 的命运交给了 parent。
🧪 5. 实战代码:一眼看懂坐标关系
完整例子如下:
js
// 父立方体
const parentCube = new THREE.Mesh(geometry, parentMaterial);
scene.add(parentCube);
parentCube.position.set(-3, 0, 0);
// 子立方体
const cube = new THREE.Mesh(geometry, material);
parentCube.add(cube);
// cube 不是在世界坐标移动,而是在父坐标系中移动
cube.position.set(3, 0, 0);

运行后你会看到:
- parentCube 在世界左边 (-3,0,0)
- cube 在 parentCube 内部向右移动 3( cube 的参考点变成了 parentCube)
- 所以 cube 的世界位置被"抵消掉",回到原点