| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 | import {	Group,	Mesh,	LineSegments,	BufferGeometry,	LineBasicMaterial,	Box3Helper,	Box3,	PlaneGeometry,	MeshBasicMaterial,	BufferAttribute,	DoubleSide} from '../../../build/three.module.js';class CSMHelper extends 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 BufferGeometry();		frustumGeometry.setIndex( new BufferAttribute( indices, 1 ) );		frustumGeometry.setAttribute( 'position', new BufferAttribute( positions, 3, false ) );		const frustumLines = new LineSegments( frustumGeometry, new 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 Box3Helper( new Box3(), 0xffffff );			const planeMat = new MeshBasicMaterial( { transparent: true, opacity: 0.1, depthWrite: false, side: DoubleSide } );			const cascadePlane = new Mesh( new PlaneGeometry(), planeMat );			const shadowLineGroup = new Group();			const shadowLine = new Box3Helper( new 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;	}}export { CSMHelper };
 |