携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第9天,点击查看活动详情 >>
前言
这一篇依旧是针对场景去学习,加深对于场景图树状结构以及组的理解,这篇的话,是做一个坦克车车,众所周知,一个车,包含车身,前2后2四个轮子,还有发动机,车窗车门等等。在threeJs里,当然也需要按照这个构成来绘制坦克小车车。坦克将有 6 个轮子和一个炮塔。坦克会沿着一条路径行驶。会有一个球体在周围移动,坦克会瞄准球体。听起来很简单对吧?接下来一步步实现一下
场景初始化
创建一个背景色为AAA的场景
const canvas = document.querySelector('#c');
const renderer = new THREE.WebGLRenderer({canvas: canvas});
renderer.setClearColor(0xAAAAAA);
renderer.shadowMap.enabled = true;
const scene = new THREE.Scene();
添加主相机
fov是视角大小,应该还没忘记吧?相机的位置是(24,12,30)的位置,multiplyScalar方法会把坐标统一缩放到对应倍数
function makeCamera(fov = 40) {
const aspect = 2; // the canvas default
const zNear = 0.1;
const zFar = 1000;
return new THREE.PerspectiveCamera(fov, aspect, zNear, zFar);
}
const camera = makeCamera();
camera.position.set(8, 4, 10).multiplyScalar(3);
camera.lookAt(0, 0, 0);
添加灯光
灯光是为了能看出来3D的效果,略去代码
绘制地面
地面是为了更好的展示坦克
const groundGeometry = new THREE.PlaneGeometry(50, 50);
const groundMaterial = new THREE.MeshPhongMaterial({color: 0xCC8866});
const groundMesh = new THREE.Mesh(groundGeometry, groundMaterial);
groundMesh.rotation.x = Math.PI * -.5;
groundMesh.receiveShadow = true;
scene.add(groundMesh);
绘制坦克
回顾一下我们想要实现的功能,首先,坦克车应该是由多部分组成的整体,所以tank对象本身应该是一个Object3D对象,然后再把其他部分有机结合起来
const tank = new THREE.Object3D();
scene.add(tank);
接下来就是车身,轮子等部分,添加到tank上,添加的代码省略,请自行查看代码片段,注释详尽,很好找的。这里的关键点是轮子的位置,轮子的位置是相对于车身的,因为轮子会添加到车身的mesh上,首先,高度上 也就是Y轴坐标,这里相机的位置是俯视偏右,所以Y坐标就是车身2分之一即可,z轴坐标,前后轮分别是车长负三分之一和三分之一,中间轮子是0点,X轴是左右,分别是宽度除以2加上或者减去轮子宽度的二分之一,坐标是有方向的,所以还需要根据方向调整正负号,最终会形成一组轮子坐标,这里X轴规律是 为负都为负,为正都为正。
[
[-carWidth / 2 - wheelThickness / 2, -carHeight / 2, carLength / 3],
[ carWidth / 2 + wheelThickness / 2, -carHeight / 2, carLength / 3],
[-carWidth / 2 - wheelThickness / 2, -carHeight / 2, 0],
[ carWidth / 2 + wheelThickness / 2, -carHeight / 2, 0],
[-carWidth / 2 - wheelThickness / 2, -carHeight / 2, -carLength / 3],
[ carWidth / 2 + wheelThickness / 2, -carHeight / 2, -carLength / 3],
]
这样一个小车就拼了起来
老规矩,代码以代码片段的方式引入