学习交流欢迎加群:789723098,博主会将一些demo整理共享
有时候我们在开发一些项目的时候,需要不断的往场景中添加和移除模型,所以会经常调用到scene,这是一件很烦的事,特别是当项目很大的时候,你会发现再很多地方乱用scene.add和scene.romove会很容易出错,那有没有什么好方法避免N多次的scene调用的,当然是有的啦,three.js设计的时候应该也考虑到这个问题了吧,所以就有了THREE.Group这个东西。
为了解决上述问题,我们可以在一开始实例化一个THREE.Group,然后讲不带任何子对象的group挂载到scene下面,像:
scene = new THREE.Scene()
group1 = new THREE.Group()
group2 = new THREE.Group()
scene.add(group1, group2)
从这里开始,你可以根据场景需求,在程序运行的任何阶段,将模型添加到group里面,场景就会自动将模型显示出来,删除的时候亦只需要移除group中的子对象即可:
group1.remove(...)
group2.remove(...)
......
这样一来就可以不用频繁调用scene去添加和移除模型。当需要移除某个group时,直接通过scene移除即可:
scene.remove(group1);
scene.remove(group2);
下边时笔者实现的一个demo, 代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<script type="module">
import * as THREE from './../build/three.module.js';
import Stats from './../examples/jsm/libs/stats.module.js';
import dat from './../examples/jsm/libs/dat.gui.module.js';
let container, stats, gui;
let renderer, scene, group, camera, ambientLight, directionLight;
const w = window.innerWidth, h = window.innerHeight;
let meshList = [ 'None', 'box', 'sphere', 'plane' ];
let config = {
addMesh: 'None',
removeMesh: 'None',
removeGroup: () => scene.remove( group ),
addGroup: () => scene.add( group )
};
init();
render();
function init() {
container = document.createElement( 'div' );
document.body.append( container );
scene = new THREE.Scene();
scene.background = new THREE.Color( 0x000000 );
// scene.fog = new THREE.Fog( 0xffffff, 0x444444 );
group = new THREE.Group();
scene.add( group );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( w, h );
renderer.shadowMap.enabled = false;
container.appendChild( renderer.domElement );
camera = new THREE.PerspectiveCamera( 45, w / h, 1, 1000 );
camera.position.set( - 40, 60, 120 );
camera.lookAt( new THREE.Vector3() );
ambientLight = new THREE.AmbientLight( 0x141414 );
scene.add( ambientLight );
directionLight = new THREE.DirectionalLight( 0xffffff );
directionLight.position.set( 0, 200, 100 );
directionLight.castShadow = true;
directionLight.shadow.camera.top = 180;
directionLight.shadow.camera.bottom = - 100;
directionLight.shadow.camera.left = - 120;
directionLight.shadow.camera.right = 120;
scene.add( directionLight );
const box = createMesh( 'box' );
box.name = 'box';
console.log( box );
group.add( box );
initGui();
initStats();
}
function createMesh( name ) {
let mesh;
switch ( name ) {
case 'box':
mesh = new THREE.Mesh(
new THREE.BoxBufferGeometry( 30, 30, 30 ),
new THREE.MeshLambertMaterial( {
color: 0x00cc99,
side: THREE.DoubleSide
} )
);
mesh.position.set( 0, 0, 0 );
break;
case 'sphere':
mesh = new THREE.Mesh(
new THREE.SphereBufferGeometry( 20, 40, 40 ),
new THREE.MeshLambertMaterial( {
color: 0x663300,
side: THREE.DoubleSide
} )
);
mesh.position.set( - 50, 0, 0 );
break;
case 'plane':
mesh = new THREE.Mesh(
new THREE.PlaneBufferGeometry( 30, 30 ),
new THREE.MeshLambertMaterial( {
color: 0x3399ff,
side: THREE.DoubleSide
} )
);
mesh.position.set( 50, 0, 0 );
// mesh.rotation.x = - Math.PI / 2;
break;
}
return mesh;
}
function initGui() {
gui = new dat.GUI();
gui.add( config, 'addMesh', meshList ).onChange( ( e ) => {
switch ( e ) {
case 'box':
const box = createMesh( 'box' );
box.name = 'box';
group.add( box );
break;
case 'sphere':
const sphere = createMesh( 'sphere' );
sphere.name = 'sphere';
group.add( sphere );
break;
case 'plane':
const plane = createMesh( 'plane' );
plane.name = 'plane';
group.add( plane );
break;
}
} );
gui.add( config, 'removeMesh', meshList ).onChange( ( e ) => {
switch ( e ) {
case 'sphere':
removeMeshFromGroup( 'sphere' );
break;
case 'box':
removeMeshFromGroup( 'box' );
break;
case 'plane':
removeMeshFromGroup( 'plane' );
break;
}
} );
gui.add( config, 'removeGroup' );
gui.add( config, 'addGroup' );
}
function initStats() {
stats = new Stats();
container.appendChild( stats.domElement );
}
function removeMeshFromGroup( name ) {
group.children.forEach( ( child ) => {
if ( child.name === name ) {
group.remove( child );
}
} );
}
function render() {
renderer.render( scene, camera );
stats.update();
requestAnimationFrame( render );
}
</script>
</body>
</html>
demo效果: