| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 | ( function () {	class CSMHelper extends THREE.Group {		constructor( csm ) {			super();			this.csm = csm;			this.displayFrustum = true;			this.displayPlanes = true;			this.displayShadowBounds = true;			const indices = new Uint16Array( [ 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 ] );			const positions = new Float32Array( 24 );			const frustumGeometry = new THREE.BufferGeometry();			frustumGeometry.setIndex( new THREE.BufferAttribute( indices, 1 ) );			frustumGeometry.setAttribute( 'position', new THREE.BufferAttribute( positions, 3, false ) );			const frustumLines = new THREE.LineSegments( frustumGeometry, new THREE.LineBasicMaterial() );			this.add( frustumLines );			this.frustumLines = frustumLines;			this.cascadeLines = [];			this.cascadePlanes = [];			this.shadowLines = [];		}		updateVisibility() {			const displayFrustum = this.displayFrustum;			const displayPlanes = this.displayPlanes;			const displayShadowBounds = this.displayShadowBounds;			const frustumLines = this.frustumLines;			const cascadeLines = this.cascadeLines;			const cascadePlanes = this.cascadePlanes;			const shadowLines = this.shadowLines;			for ( let i = 0, l = cascadeLines.length; i < l; i ++ ) {				const cascadeLine = cascadeLines[ i ];				const cascadePlane = cascadePlanes[ i ];				const shadowLineGroup = shadowLines[ i ];				cascadeLine.visible = displayFrustum;				cascadePlane.visible = displayFrustum && displayPlanes;				shadowLineGroup.visible = displayShadowBounds;			}			frustumLines.visible = displayFrustum;		}		update() {			const csm = this.csm;			const camera = csm.camera;			const cascades = csm.cascades;			const mainFrustum = csm.mainFrustum;			const frustums = csm.frustums;			const lights = csm.lights;			const frustumLines = this.frustumLines;			const frustumLinePositions = frustumLines.geometry.getAttribute( 'position' );			const cascadeLines = this.cascadeLines;			const cascadePlanes = this.cascadePlanes;			const shadowLines = this.shadowLines;			this.position.copy( camera.position );			this.quaternion.copy( camera.quaternion );			this.scale.copy( camera.scale );			this.updateMatrixWorld( true );			while ( cascadeLines.length > cascades ) {				this.remove( cascadeLines.pop() );				this.remove( cascadePlanes.pop() );				this.remove( shadowLines.pop() );			}			while ( cascadeLines.length < cascades ) {				const cascadeLine = new THREE.Box3Helper( new THREE.Box3(), 0xffffff );				const planeMat = new THREE.MeshBasicMaterial( {					transparent: true,					opacity: 0.1,					depthWrite: false,					side: THREE.DoubleSide				} );				const cascadePlane = new THREE.Mesh( new THREE.PlaneGeometry(), planeMat );				const shadowLineGroup = new THREE.Group();				const shadowLine = new THREE.Box3Helper( new THREE.Box3(), 0xffff00 );				shadowLineGroup.add( shadowLine );				this.add( cascadeLine );				this.add( cascadePlane );				this.add( shadowLineGroup );				cascadeLines.push( cascadeLine );				cascadePlanes.push( cascadePlane );				shadowLines.push( shadowLineGroup );			}			for ( let i = 0; i < cascades; i ++ ) {				const frustum = frustums[ i ];				const light = lights[ i ];				const shadowCam = light.shadow.camera;				const farVerts = frustum.vertices.far;				const cascadeLine = cascadeLines[ i ];				const cascadePlane = cascadePlanes[ i ];				const shadowLineGroup = shadowLines[ i ];				const shadowLine = shadowLineGroup.children[ 0 ];				cascadeLine.box.min.copy( farVerts[ 2 ] );				cascadeLine.box.max.copy( farVerts[ 0 ] );				cascadeLine.box.max.z += 1e-4;				cascadePlane.position.addVectors( farVerts[ 0 ], farVerts[ 2 ] );				cascadePlane.position.multiplyScalar( 0.5 );				cascadePlane.scale.subVectors( farVerts[ 0 ], farVerts[ 2 ] );				cascadePlane.scale.z = 1e-4;				this.remove( shadowLineGroup );				shadowLineGroup.position.copy( shadowCam.position );				shadowLineGroup.quaternion.copy( shadowCam.quaternion );				shadowLineGroup.scale.copy( shadowCam.scale );				shadowLineGroup.updateMatrixWorld( true );				this.attach( shadowLineGroup );				shadowLine.box.min.set( shadowCam.bottom, shadowCam.left, - shadowCam.far );				shadowLine.box.max.set( shadowCam.top, shadowCam.right, - shadowCam.near );			}			const nearVerts = mainFrustum.vertices.near;			const farVerts = mainFrustum.vertices.far;			frustumLinePositions.setXYZ( 0, farVerts[ 0 ].x, farVerts[ 0 ].y, farVerts[ 0 ].z );			frustumLinePositions.setXYZ( 1, farVerts[ 3 ].x, farVerts[ 3 ].y, farVerts[ 3 ].z );			frustumLinePositions.setXYZ( 2, farVerts[ 2 ].x, farVerts[ 2 ].y, farVerts[ 2 ].z );			frustumLinePositions.setXYZ( 3, farVerts[ 1 ].x, farVerts[ 1 ].y, farVerts[ 1 ].z );			frustumLinePositions.setXYZ( 4, nearVerts[ 0 ].x, nearVerts[ 0 ].y, nearVerts[ 0 ].z );			frustumLinePositions.setXYZ( 5, nearVerts[ 3 ].x, nearVerts[ 3 ].y, nearVerts[ 3 ].z );			frustumLinePositions.setXYZ( 6, nearVerts[ 2 ].x, nearVerts[ 2 ].y, nearVerts[ 2 ].z );			frustumLinePositions.setXYZ( 7, nearVerts[ 1 ].x, nearVerts[ 1 ].y, nearVerts[ 1 ].z );			frustumLinePositions.needsUpdate = true;		}	}	THREE.CSMHelper = CSMHelper;} )();
 |