学习:
体积碰撞计算渲染
键盘/鼠标控制物体移动与视角切换
零散的东西
1.
const camera = new THREE.PerspectiveCamera( 70,
window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.rotation.order = 'YXZ';//指定了相机旋转的顺序,用于处理复杂的3D场景
和避免万向节锁(Gimbal Lock)
three.js
使用欧拉角(Euler Angles)来表示旋转,通过改变旋转顺序,可以影响旋转的结果。
欧拉角:
是一种表示物体在三维空间中旋转的方法
万向节锁:
2.物体阴影
THREE.DirectionalLight模拟了从天空和地面反射的光照,常用于模拟环境光源。在渲染户外场景时带来更加自然的照明效果。
设置相机投影,开启渲染器渲染阴影,指定物体渲染对象。其他优化阴影效果
详见:
2. 平行光阴影计算 | Three.js中文网 (webgl3d.cn)
3.鼠标指针锁定
document.body.requestPointerLock();
4.getForwardVector().multiplyScalar(speedDelta)
方向*大小
getForwardVector()
返回的是一个 THREE.Vector3
类型的向量对象,而 THREE.Vector3
类型的对象具有 multiplyScalar
方法。所以可以在调getForwardVector之后直接.multiplyScalar(speedDelta)
思路
实现按下w,a,s,d等键控制玩家移动:
const playerVelocity = new THREE.Vector3();
playerVelocity
通过修改playerVelocity的值来控制相机即玩家移动
1.键盘监听
用一个数组存储键盘按下状态keyStates[]
document.addEventListener('keydown', (event) => {
keyStates[event.code] = true;
});
document.addEventListener('keyup', (event) => {
keyStates[event.code] = false;
});
2.控制函数,在 animate()循环根据玩家按键来计算并更新playerVelocity值
function controls(deltaTime) {
const speedDelta = deltaTime * (playerOnFloor ? 5 : 8);
if (keyStates['KeyW']) {
playerVelocity.add(getForwardVector().multiplyScalar(speedDelta));
}
if (keyStates['KeyS']) {
playerVelocity.add(getForwardVector().multiplyScalar(- speedDelta));
}
if (playerOnFloor) {
if (keyStates['Space']) {
playerVelocity.y = 150;
}
}
.........
}
3.移动方向函数 getForwardVector()
和 getSideVector()实现前后左右移动
4.
updatePlayer中控制垂直轴移动及更新相机位置
5.处理玩家与场地的碰撞playerCollisions();
实现体积碰撞
通过使用 Capsule
碰撞器和八叉树(Octree
)来实现
八叉树:
用于空间分割的数据结构,通常用于三维计算机图形学和物理仿真中。高效的空间分割,减少计算量,适应性强。常应用于碰撞检测,光线追踪,场景管理。
胶囊体(Capsule)/玩家:
能有效表示角色的体积,又能简化碰撞检测计算。用于角色碰撞检测,简化计算
1.创建玩家的胶囊体碰撞器
2.将碰撞物体添加进八叉树内playerCollisions()
worldOctree.fromGraphNode(gltf.scene);
2.在动画循环中检测碰撞:playerCollisions()
3.updatePlayer(deltaTime)更新碰撞后移动的位置