three
Version:
JavaScript 3D library
153 lines (90 loc) • 3.03 kB
JavaScript
THREE.WebGLClipping = function() {
var scope = this,
globalState = null,
numGlobalPlanes = 0,
localClippingEnabled = false,
renderingShadows = false,
plane = new THREE.Plane(),
viewNormalMatrix = new THREE.Matrix3(),
uniform = { value: null, needsUpdate: false };
this.uniform = uniform;
this.numPlanes = 0;
this.init = function( planes, enableLocalClipping, camera ) {
var enabled =
planes.length !== 0 ||
enableLocalClipping ||
// enable state of previous frame - the clipping code has to
// run another frame in order to reset the state:
numGlobalPlanes !== 0 ||
localClippingEnabled;
localClippingEnabled = enableLocalClipping;
globalState = projectPlanes( planes, camera, 0 );
numGlobalPlanes = planes.length;
return enabled;
};
this.beginShadows = function() {
renderingShadows = true;
projectPlanes( null );
};
this.endShadows = function() {
renderingShadows = false;
resetGlobalState();
};
this.setState = function( planes, clipShadows, camera, cache, fromCache ) {
if ( ! localClippingEnabled ||
planes === null || planes.length === 0 ||
renderingShadows && ! clipShadows ) {
// there's no local clipping
if ( renderingShadows ) {
// there's no global clipping
projectPlanes( null );
} else {
resetGlobalState();
}
} else {
var nGlobal = renderingShadows ? 0 : numGlobalPlanes,
lGlobal = nGlobal * 4,
dstArray = cache.clippingState || null;
uniform.value = dstArray; // ensure unique state
dstArray = projectPlanes( planes, camera, lGlobal, fromCache );
for ( var i = 0; i !== lGlobal; ++ i ) {
dstArray[ i ] = globalState[ i ];
}
cache.clippingState = dstArray;
this.numPlanes += nGlobal;
}
};
function resetGlobalState() {
if ( uniform.value !== globalState ) {
uniform.value = globalState;
uniform.needsUpdate = numGlobalPlanes > 0;
}
scope.numPlanes = numGlobalPlanes;
}
function projectPlanes( planes, camera, dstOffset, skipTransform ) {
var nPlanes = planes !== null ? planes.length : 0,
dstArray = null;
if ( nPlanes !== 0 ) {
dstArray = uniform.value;
if ( skipTransform !== true || dstArray === null ) {
var flatSize = dstOffset + nPlanes * 4,
viewMatrix = camera.matrixWorldInverse;
viewNormalMatrix.getNormalMatrix( viewMatrix );
if ( dstArray === null || dstArray.length < flatSize ) {
dstArray = new Float32Array( flatSize );
}
for ( var i = 0, i4 = dstOffset;
i !== nPlanes; ++ i, i4 += 4 ) {
plane.copy( planes[ i ] ).
applyMatrix4( viewMatrix, viewNormalMatrix );
plane.normal.toArray( dstArray, i4 );
dstArray[ i4 + 3 ] = plane.constant;
}
}
uniform.value = dstArray;
uniform.needsUpdate = true;
}
scope.numPlanes = nPlanes;
return dstArray;
}
};