Spaces:
Running
Running
/** | |
* @author tschw | |
*/ | |
import { Matrix3 } from '../../math/Matrix3.js'; | |
import { Plane } from '../../math/Plane.js'; | |
function WebGLClipping() { | |
var scope = this, | |
globalState = null, | |
numGlobalPlanes = 0, | |
localClippingEnabled = false, | |
renderingShadows = false, | |
plane = new Plane(), | |
viewNormalMatrix = new Matrix3(), | |
uniform = { value: null, needsUpdate: false }; | |
this.uniform = uniform; | |
this.numPlanes = 0; | |
this.numIntersection = 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, clipIntersection, 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.numIntersection = clipIntersection ? this.numPlanes : 0; | |
this.numPlanes += nGlobal; | |
} | |
}; | |
function resetGlobalState() { | |
if ( uniform.value !== globalState ) { | |
uniform.value = globalState; | |
uniform.needsUpdate = numGlobalPlanes > 0; | |
} | |
scope.numPlanes = numGlobalPlanes; | |
scope.numIntersection = 0; | |
} | |
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; | |
} | |
} | |
export { WebGLClipping }; | |