ThreeJs学习笔记【day9】场景【2】

127 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 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],
  ]

这样一个小车就拼了起来

image.png

老规矩,代码以代码片段的方式引入