Spaces:
Running
Running
| import { Matrix3 } from '../../math/Matrix3.js'; | |
| import { Plane } from '../../math/Plane.js'; | |
| function WebGLClipping(properties) { | |
| const scope = this; | |
| let globalState = null, | |
| numGlobalPlanes = 0, | |
| localClippingEnabled = false, | |
| renderingShadows = false; | |
| const 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) { | |
| const 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 (material, camera, useCache) { | |
| const planes = material.clippingPlanes, | |
| clipIntersection = material.clipIntersection, | |
| clipShadows = material.clipShadows; | |
| const materialProperties = properties.get(material); | |
| 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 { | |
| const nGlobal = renderingShadows ? 0 : numGlobalPlanes, | |
| lGlobal = nGlobal * 4; | |
| let dstArray = materialProperties.clippingState || null; | |
| uniform.value = dstArray; // ensure unique state | |
| dstArray = projectPlanes(planes, camera, lGlobal, useCache); | |
| for (let i = 0; i !== lGlobal; ++i) { | |
| dstArray[i] = globalState[i]; | |
| } | |
| materialProperties.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) { | |
| const nPlanes = planes !== null ? planes.length : 0; | |
| let dstArray = null; | |
| if (nPlanes !== 0) { | |
| dstArray = uniform.value; | |
| if (skipTransform !== true || dstArray === null) { | |
| const flatSize = dstOffset + nPlanes * 4, | |
| viewMatrix = camera.matrixWorldInverse; | |
| viewNormalMatrix.getNormalMatrix(viewMatrix); | |
| if (dstArray === null || dstArray.length < flatSize) { | |
| dstArray = new Float32Array(flatSize); | |
| } | |
| for (let 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; | |
| scope.numIntersection = 0; | |
| return dstArray; | |
| } | |
| } | |
| export { WebGLClipping }; | |