166 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			166 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import { Matrix3, Plane, Vector4 } from 'three';
 | |
| 
 | |
| const _plane = new Plane();
 | |
| const _viewNormalMatrix = new Matrix3();
 | |
| 
 | |
| let _clippingContextVersion = 0;
 | |
| 
 | |
| class ClippingContext {
 | |
| 
 | |
| 	constructor() {
 | |
| 
 | |
| 		this.version = ++ _clippingContextVersion;
 | |
| 
 | |
| 		this.globalClippingCount = 0;
 | |
| 
 | |
| 		this.localClippingCount = 0;
 | |
| 		this.localClippingEnabled = false;
 | |
| 		this.localClipIntersection = false;
 | |
| 
 | |
| 		this.planes = [];
 | |
| 
 | |
| 		this.parentVersion = 0;
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	projectPlanes( source, offset ) {
 | |
| 
 | |
| 		const l = source.length;
 | |
| 		const planes = this.planes;
 | |
| 
 | |
| 		for ( let i = 0; i < l; i ++ ) {
 | |
| 
 | |
| 			_plane.copy( source[ i ] ).applyMatrix4( this.viewMatrix, _viewNormalMatrix );
 | |
| 
 | |
| 			const v = planes[ offset + i ];
 | |
| 			const normal = _plane.normal;
 | |
| 
 | |
| 			v.x = - normal.x;
 | |
| 			v.y = - normal.y;
 | |
| 			v.z = - normal.z;
 | |
| 			v.w = _plane.constant;
 | |
| 
 | |
| 		}
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	updateGlobal( renderer, camera ) {
 | |
| 
 | |
| 		const rendererClippingPlanes = renderer.clippingPlanes;
 | |
| 		this.viewMatrix = camera.matrixWorldInverse;
 | |
| 
 | |
| 		_viewNormalMatrix.getNormalMatrix( this.viewMatrix );
 | |
| 
 | |
| 		let update = false;
 | |
| 
 | |
| 		if ( Array.isArray( rendererClippingPlanes ) && rendererClippingPlanes.length !== 0 ) {
 | |
| 
 | |
| 			const l = rendererClippingPlanes.length;
 | |
| 
 | |
| 			if ( l !== this.globalClippingCount ) {
 | |
| 
 | |
| 				const planes = [];
 | |
| 
 | |
| 				for ( let i = 0; i < l; i ++ ) {
 | |
| 
 | |
| 					planes.push( new Vector4() );
 | |
| 
 | |
| 				}
 | |
| 
 | |
| 				this.globalClippingCount = l;
 | |
| 				this.planes = planes;
 | |
| 
 | |
| 				update = true;
 | |
| 
 | |
| 			}
 | |
| 
 | |
| 			this.projectPlanes( rendererClippingPlanes, 0 );
 | |
| 
 | |
| 		} else if ( this.globalClippingCount !== 0 ) {
 | |
| 
 | |
| 			this.globalClippingCount = 0;
 | |
| 			this.planes = [];
 | |
| 			update = true;
 | |
| 
 | |
| 		}
 | |
| 
 | |
| 		if ( renderer.localClippingEnabled !== this.localClippingEnabled ) {
 | |
| 
 | |
| 			this.localClippingEnabled = renderer.localClippingEnabled;
 | |
| 			update = true;
 | |
| 
 | |
| 		}
 | |
| 
 | |
| 		if ( update ) this.version = _clippingContextVersion ++;
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	update( parent, material ) {
 | |
| 
 | |
| 		let update = false;
 | |
| 
 | |
| 		if ( this !== parent && parent.version !== this.parentVersion ) {
 | |
| 
 | |
| 			this.globalClippingCount = material.isShadowNodeMaterial ? 0 : parent.globalClippingCount;
 | |
| 			this.localClippingEnabled = parent.localClippingEnabled;
 | |
| 			this.planes = Array.from( parent.planes );
 | |
| 			this.parentVersion = parent.version;
 | |
| 			this.viewMatrix = parent.viewMatrix;
 | |
| 
 | |
| 
 | |
| 			update = true;
 | |
| 
 | |
| 		}
 | |
| 
 | |
| 		if ( this.localClippingEnabled ) {
 | |
| 
 | |
| 			const localClippingPlanes = material.clippingPlanes;
 | |
| 
 | |
| 			if ( ( Array.isArray( localClippingPlanes ) && localClippingPlanes.length !== 0 ) ) {
 | |
| 
 | |
| 				const l = localClippingPlanes.length;
 | |
| 				const planes = this.planes;
 | |
| 				const offset = this.globalClippingCount;
 | |
| 
 | |
| 				if ( update || l !== this.localClippingCount ) {
 | |
| 
 | |
| 					planes.length = offset + l;
 | |
| 
 | |
| 					for ( let i = 0; i < l; i ++ ) {
 | |
| 
 | |
| 						planes[ offset + i ] = new Vector4();
 | |
| 
 | |
| 					}
 | |
| 
 | |
| 					this.localClippingCount = l;
 | |
| 					update = true;
 | |
| 
 | |
| 				}
 | |
| 
 | |
| 				this.projectPlanes( localClippingPlanes, offset );
 | |
| 
 | |
| 
 | |
| 			} else if ( this.localClippingCount !== 0 ) {
 | |
| 
 | |
| 				this.localClippingCount = 0;
 | |
| 				update = true;
 | |
| 
 | |
| 			}
 | |
| 
 | |
| 			if ( this.localClipIntersection !== material.clipIntersection ) {
 | |
| 
 | |
| 				this.localClipIntersection = material.clipIntersection;
 | |
| 				update = true;
 | |
| 
 | |
| 			}
 | |
| 
 | |
| 		}
 | |
| 
 | |
| 		if ( update ) this.version = _clippingContextVersion ++;
 | |
| 
 | |
| 	}
 | |
| 
 | |
| }
 | |
| 
 | |
| export default ClippingContext;
 |