You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
166 lines
3.1 KiB
166 lines
3.1 KiB
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;
|