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;
 |