Three.js动态增删场景模型

 学习交流欢迎加群: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效果:

猜你喜欢

转载自blog.csdn.net/qq_37338983/article/details/102943362