内置几何体
此笔记记录于DISCOVER three.js,大多数为其中的摘要,少数为笔者自己的理解
目录
效果
Material.flatShading
属性
js
const material = new MeshStandardMaterial({
color: 'red',
flatShading: true,
});
左边: flatShading 禁用。右边: flatShading 启用。
Train.js
js
import { Group, MathUtils } from 'three';
import { createMeshes } from './meshes.js';
const wheelSpeed = MathUtils.degToRad(24);
class Train extends Group {
constructor() {
super();
this.meshes = createMeshes();
this.add(
this.meshes.nose,
this.meshes.cabin,
this.meshes.chimney,
this.meshes.smallWheelRear,
this.meshes.smallWheelCenter,
this.meshes.smallWheelFront,
this.meshes.bigWheel,
);
}
tick(delta) {
this.meshes.bigWheel.rotation.y += wheelSpeed * delta;
this.meshes.smallWheelRear.rotation.y += wheelSpeed * delta;
this.meshes.smallWheelCenter.rotation.y += wheelSpeed * delta;
this.meshes.smallWheelFront.rotation.y += wheelSpeed * delta;
}
}
export { Train };
Train
类继承自Group
- 注意
super()
的使用。这意味着Train
类现在具有Group
的所有常规功能。
geometries.js
js
import { BoxBufferGeometry, CylinderBufferGeometry } from 'three';
function createGeometries() {
const cabin = new BoxBufferGeometry(2, 2.25, 1.5);
const nose = new CylinderBufferGeometry(0.75, 0.75, 3, 12);
// we can reuse a single cylinder geometry for all 4 wheels
const wheel = new CylinderBufferGeometry(0.4, 0.4, 1.75, 16);
// different values for the top and bottom radius creates a cone shape
const chimney = new CylinderBufferGeometry(0.3, 0.1, 0.5);
return {
cabin,
nose,
wheel,
chimney,
};
}
export { createGeometries };
materials.js
js
import { MeshStandardMaterial } from 'three';
function createMaterials() {
const body = new MeshStandardMaterial({
color: 'firebrick',
flatShading: true,
});
const detail = new MeshStandardMaterial({
color: 'darkslategray',
flatShading: true,
});
return { body, detail };
}
export { createMaterials };
meshes.js
js
import { Mesh } from 'three';
import { createGeometries } from './geometries.js';
import { createMaterials } from './materials.js';
function createMeshes() {
const geometries = createGeometries();
const materials = createMaterials();
const cabin = new Mesh(geometries.cabin, materials.body);
cabin.position.set(1.5, 1.4, 0);
const chimney = new Mesh(geometries.chimney, materials.detail);
chimney.position.set(-2, 1.9, 0);
const nose = new Mesh(geometries.nose, materials.body);
nose.position.set(-1, 1, 0);
nose.rotation.z = Math.PI / 2;
const smallWheelRear = new Mesh(geometries.wheel, materials.detail);
smallWheelRear.position.y = 0.5;
smallWheelRear.rotation.x = Math.PI / 2;
const smallWheelCenter = smallWheelRear.clone();
smallWheelCenter.position.x = -1;
const smallWheelFront = smallWheelRear.clone();
smallWheelFront.position.x = -2;
const bigWheel = smallWheelRear.clone();
bigWheel.position.set(1.5, 0.9, 0);
bigWheel.scale.set(2, 1.25, 2);
return {
nose,
cabin,
chimney,
smallWheelRear,
smallWheelCenter,
smallWheelFront,
bigWheel,
};
}
export { createMeshes };
World.js 中使用
js
import { createCamera } from './components/camera.js';
import {
createAxesHelper,
createGridHelper,
} from './components/helpers.js';
import { createLights } from './components/lights.js';
import { createScene } from './components/scene.js';
import { Train } from './components/Train/Train.js';
import { createControls } from './systems/controls.js';
import { createRenderer } from './systems/renderer.js';
import { Resizer } from './systems/Resizer.js';
import { Loop } from './systems/Loop.js';
let camera;
let renderer;
let scene;
let loop;
class World {
constructor(container) {
camera = createCamera();
renderer = createRenderer();
scene = createScene();
loop = new Loop(camera, scene, renderer);
container.append(renderer.domElement);
const controls = createControls(camera, renderer.domElement);
const { ambientLight, mainLight } = createLights();
const train = new Train();
loop.updatables.push(controls, train);
scene.add(ambientLight, mainLight, train);
const resizer = new Resizer(container, camera, renderer);
scene.add(createAxesHelper(), createGridHelper());
}
render() {
renderer.render(scene, camera);
}
start() {
loop.start();
}
stop() {
loop.stop();
}
}
export { World };