前言
基于前面的学习,我们继续深入
3-坐标辅助器与轨道控制器
可能大家大家进入官方文档很卡,大家可以把源码下载下来,然后在vscode终端直接npm run dev就能本地部署,打开之后点击docs即可进去。怎么部署呢?大家可以看b站这个视频: www.bilibili.com/video/BV1Gg…
1-坐标辅助器(axesHelper)
为了能更好的观察,我们可以引入一个坐标辅助器,代码如下:
//添加世界坐标辅助器
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
然后我们就能在页面上看见x,y轴。为什么看不见z轴?因为它在我们正对面,换句话来说,问我们的视角就是z轴。那我们怎么才能看到z轴呢?可以设置:
camera.lookAt(3, 0, 0)
偏移之后我们就能看见z轴啦!
2-轨道控制器(controls)
为什么要加入这个?首先呢我们为了方便开发,会取消第一节所讲的自动旋转。然后我们加入轨道控制器,再加入相应的内容(后面会讲到),就能更好的开发我们的页面了
首先我们引入控制器:
//导入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
//创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);//renderer.domElement监听的是canvas事件,若想换别的也行如document.body,记住body要设置宽高!
//带阻尼,带有一定的惯性,优化手感哈哈
controls.enableDamping = true;
//设置阻尼系数
controls.dampingFactor = 0.05;
//也可以设置旋转速度
controls.autoRotate=0.05;
//在渲染函数里面更新
//渲染循环
function animate() {
controls.update(); // 只更新控制器内部状态
requestAnimationFrame(animate);
// cube.rotation.x += 0.01;除去自动旋转
// cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
//相关配置可以去看官方文档
4-物体位移与父子元素
1. 物体位移基础
1.1 position属性
所有继承自Object3D
的对象(如Mesh、Group)都包含position
属性:
cube.position.set(x, y, z)
- 使用右手坐标系:X轴右,Y轴上,Z轴朝向屏幕外
- 默认坐标为(0,0,0)
1.2 坐标系类型
- 局部坐标系 (Local Space):相对于父容器的坐标
- 世界坐标系 (World Space):场景中的绝对坐标
2. 父子元素关系
2.1 创建父子关系
parent.add(child)
- 子对象继承父对象的变换(位移/旋转/缩放)
- 父子关系形成场景图(Scene Graph)结构
2.2 位移继承特性
操作对象 | 局部坐标变化 | 世界坐标变化 |
---|---|---|
父物体 | 保持不变 | 改变 |
子物体 | 相对父物体 | 自动更新 |
3. 位移叠加原理
3.1 变换矩阵计算
物体最终位置由矩阵乘法决定:
World Matrix = Parent World Matrix × Local Matrix
3.2 示例场景
/* 创建父子物体 */
const parent = new THREE.Mesh(geometry, material)//材质的话可以颜色跟儿子不一样,容易区分
const child = new THREE.Mesh(geometry, material)
parent.add(child)
/* 设置位移 */
parent.position.set(2, 0, 0) // 父物体右移2单位
child.position.set(0, 1, 0) // 子物体在父坐标系中上移1单位
最终世界坐标计算:
子物体世界坐标 = 父物体位置 + 子物体局部位置
= (2,0,0) + (0,1,0)
= (2,1,0)
4. 注意事项
-
性能优化
- 避免每帧更新矩阵,需要时手动调用
updateMatrixWorld()
- 避免每帧更新矩阵,需要时手动调用
-
坐标系混淆
- 使用
getWorldPosition()
获取世界坐标:
const worldPosition = new THREE.Vector3() child.getWorldPosition(worldPosition)
- 使用
-
复合变换 当存在旋转/缩放时,位移计算会受矩阵乘法顺序影响
5. 完整代码示例
// 场景初始化
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000)
const renderer = new THREE.WebGLRenderer()
// 创建物体
const geometry = new THREE.BoxGeometry()
const material = new THREE.MeshBasicMaterial({color: 0x00ff00})
//const parentmaterial = new THREE.MeshBasicMaterial({color: 0x ff00ff00})
// 创建父子物体
const parent = new THREE.Mesh(geometry, material)
const child = new THREE.Mesh(geometry, material)
parent.add(child)
// 设置初始位置
parent.position.set(2, 0, 0) // 父物体X轴+2
child.position.set(0, 1, 0) // 子物体在父坐标系中Y+1
// 将父物体加入场景
scene.add(parent)
// 验证世界坐标
const worldPos = new THREE.Vector3()
child.getWorldPosition(worldPos)
console.log('World Position:', worldPos) // 输出 (2,1,0)
// 相机位置
camera.position.z = 5
搜索vector3可以进入查看
总结
- 父子关系通过
add()
方法建立,形成层级变换链 - 局部坐标通过矩阵乘法转换为世界坐标
- 使用
getWorldPosition()
获取准确世界空间位置 - 注意变换顺序对最终结果的影响