一、几何体的组合
THREE.Group()可用来创建一个组,每一组中可包含多个对象,可对这些对象进行整体的调整,也可以单独调整组中的某个对象。使用add方法即可向组中添加对象。
示例:
import '../../stylus/index.styl'
import * as THREE from 'three'
import * as dat from 'dat.gui'
import {initTrackballControls, initThree, initStats} from "../../util/util";
function init(){
let stats = initStats();
let {camera, scene, renderer} = initThree();
let spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(0, 30, 50);
spotLight.castShadow = true;
spotLight.shadow.mapSize.set(2048, 2048);
scene.add(spotLight);
let axes = new THREE.AxesHelper(20);
scene.add(axes);
let planeGeometry = new THREE.PlaneBufferGeometry(60, 40, 1,1);
let planeMaterial = new THREE.MeshLambertMaterial({
color: 0xffffff
});
let plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = -0.5*Math.PI;
plane.receiveShadow = true;
scene.add(plane);
let cubeGeometry = new THREE.BoxBufferGeometry(5,5,5,5,5,5);
let cubeMaterial = new THREE.MeshStandardMaterial({
color: 0x00ffff
});
let cube1 = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube1.position.set(-6, 5, 0);
let cube2 = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube2.position.set(6, 5, 5);
let group = new THREE.Group();
group.add(cube1, cube2);
scene.add(group);
let gui = new dat.GUI();
let cube1GUI = gui.addFolder('cube1');
let cube2GUI = gui.addFolder('cube2');
let groupGUI = gui.addFolder('group');
let cube1Controls = {
positionX: cube1.position.x,
positionY: cube1.position.y,
positionZ: cube1.position.z,
scale: 1
};
let cube2Controls = {
positionX: cube2.position.x,
positionY: cube2.position.y,
positionZ: cube2.position.z,
scale: 1
};
let groupControls = {
positionX: group.position.x,
positionY: group.position.y,
positionZ: group.position.z,
scale: 1
};
cube1GUI.add(cube1Controls, 'positionX', -10, -6);
cube1GUI.add(cube1Controls, 'positionY', 5, 10);
cube1GUI.add(cube1Controls, 'positionZ', 0, 10);
cube1GUI.add(cube1Controls, 'scale', 0, 3);
cube2GUI.add(cube2Controls, 'positionX', 6, 10);
cube2GUI.add(cube2Controls, 'positionY', 5, 10);
cube2GUI.add(cube2Controls, 'positionZ', 5, 10);
cube2GUI.add(cube2Controls, 'scale', 0, 3);
groupGUI.add(groupControls, 'positionX', -10, 10);
groupGUI.add(groupControls, 'positionY', 0, 10);
groupGUI.add(groupControls, 'positionZ', -10, 10);
groupGUI.add(groupControls, 'scale', 0, 3);
let trackballControls = initTrackballControls(camera, renderer);
function render(){
stats.update();
trackballControls.update();
cube1.position.set(cube1Controls.positionX, cube1Controls.positionY, cube1Controls.positionZ);
cube1.scale.set(cube1Controls.scale, cube1Controls.scale, cube1Controls.scale);
cube2.position.set(cube2Controls.positionX, cube2Controls.positionY, cube2Controls.positionZ);
cube2.scale.set(cube2Controls.scale, cube2Controls.scale, cube2Controls.scale);
group.position.set(groupControls.positionX, groupControls.positionY, groupControls.positionZ);
group.scale.set(groupControls.scale, groupControls.scale, groupControls.scale);
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
}
init();
上例创建了两个立方体,并加入了一个Group中,使用右侧控制器可对这两个立方体进行位置及缩放的变化;其中group选项下可对整体进行调整,cube1/cube2分别对应一个立方体。
二、几何体的合并
通过THREE.Geometry.merge()方法可实现几何体之间的合并,一旦合并无法单独控制被合并的几何体。当页面存在大量几何体,使用合并可提高页面性能。
如下,场景中显示500个立方体,观察fps好想还可以,通过右侧控制器将cubeNumber调至10000个点击redraw,你会发现fps迅速降低至低于30fps,如果勾选merge,你会发现fps就正常了。
import '../../stylus/index.styl'
import * as THREE from 'three';
import * as dat from 'dat.gui';
import {initTrackballControls, initStats, initThree} from "../../util/util";
function init () {
let stats = initStats();
let {scene, camera, renderer} = initThree();
camera.position.set(-100, 100, 80);
let cubeMaterial = new THREE.MeshNormalMaterial({
transparent: true,
opacity: 0.8
});
let addCube = () => {
let cubeGeometry = new THREE.BoxGeometry(4,4,4,4);
let cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.position.x = - 100 + Math.round(Math.random() * 200);
cube.position.y = Math.round(Math.random() * 10);
cube.position.z = - 100 + Math.round(Math.random() * 200);
return cube;
};
for (let i = 0; i < 500; i++) {
scene.add(addCube());
}
let gui = new dat.GUI();
let guiControls = {
cubeNumber: 500,
merge: false,
redraw: function () {
let removeArr = [];
scene.children.forEach(item => {
item instanceof THREE.Mesh && removeArr.push(item);
});
removeArr.forEach(item => scene.remove(item));
if ( this.merge ) {
let geometry = new THREE.Geometry();
for (let i = 0; i < this.cubeNumber; i++) {
let cubeMesh = addCube();
cubeMesh.updateMatrix();
geometry.merge(cubeMesh.geometry, cubeMesh.matrix);
}
scene.add(new THREE.Mesh(geometry, cubeMaterial));
} else {
for (let i = 0; i < this.cubeNumber; i++) {
scene.add(addCube());
}
}
addCube();
}
};
gui.add(guiControls, 'cubeNumber');
gui.add(guiControls, 'merge');
gui.add(guiControls, 'redraw');
let trackballControls = initTrackballControls(camera, renderer);
function render() {
stats.update();
trackballControls.update();
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
}
init();