UNPKG

three

Version:

JavaScript 3D library

170 lines (94 loc) 3.38 kB
import { Matrix3 } from '../../math/Matrix3.js'; import { Plane } from '../../math/Plane.js'; import { Vector4 } from '../../math/Vector4.js'; const _plane = /*@__PURE__*/ new Plane(); class ClippingContext { constructor( parentContext = null ) { this.version = 0; this.clipIntersection = null; this.cacheKey = ''; if ( parentContext === null ) { this.intersectionPlanes = []; this.unionPlanes = []; this.viewNormalMatrix = new Matrix3(); this.clippingGroupContexts = new WeakMap(); this.shadowPass = false; } else { this.viewNormalMatrix = parentContext.viewNormalMatrix; this.clippingGroupContexts = parentContext.clippingGroupContexts; this.shadowPass = parentContext.shadowPass; this.viewMatrix = parentContext.viewMatrix; } this.parentVersion = null; } projectPlanes( source, destination, offset ) { const l = source.length; for ( let i = 0; i < l; i ++ ) { _plane.copy( source[ i ] ).applyMatrix4( this.viewMatrix, this.viewNormalMatrix ); const v = destination[ offset + i ]; const normal = _plane.normal; v.x = - normal.x; v.y = - normal.y; v.z = - normal.z; v.w = _plane.constant; } } updateGlobal( scene, camera ) { this.shadowPass = ( scene.overrideMaterial !== null && scene.overrideMaterial.isShadowNodeMaterial ); this.viewMatrix = camera.matrixWorldInverse; this.viewNormalMatrix.getNormalMatrix( this.viewMatrix ); } update( parentContext, clippingGroup ) { let update = false; if ( parentContext.version !== this.parentVersion ) { this.intersectionPlanes = Array.from( parentContext.intersectionPlanes ); this.unionPlanes = Array.from( parentContext.unionPlanes ); this.parentVersion = parentContext.version; } if ( this.clipIntersection !== clippingGroup.clipIntersection ) { this.clipIntersection = clippingGroup.clipIntersection; if ( this.clipIntersection ) { this.unionPlanes.length = parentContext.unionPlanes.length; } else { this.intersectionPlanes.length = parentContext.intersectionPlanes.length; } } const srcClippingPlanes = clippingGroup.clippingPlanes; const l = srcClippingPlanes.length; let dstClippingPlanes; let offset; if ( this.clipIntersection ) { dstClippingPlanes = this.intersectionPlanes; offset = parentContext.intersectionPlanes.length; } else { dstClippingPlanes = this.unionPlanes; offset = parentContext.unionPlanes.length; } if ( dstClippingPlanes.length !== offset + l ) { dstClippingPlanes.length = offset + l; for ( let i = 0; i < l; i ++ ) { dstClippingPlanes[ offset + i ] = new Vector4(); } update = true; } this.projectPlanes( srcClippingPlanes, dstClippingPlanes, offset ); if ( update ) { this.version ++; this.cacheKey = `${ this.intersectionPlanes.length }:${ this.unionPlanes.length }`; } } getGroupContext( clippingGroup ) { if ( this.shadowPass && ! clippingGroup.clipShadows ) return this; let context = this.clippingGroupContexts.get( clippingGroup ); if ( context === undefined ) { context = new ClippingContext( this ); this.clippingGroupContexts.set( clippingGroup, context ); } context.update( this, clippingGroup ); return context; } get unionClippingCount() { return this.unionPlanes.length; } } export default ClippingContext;