UNPKG

three-stdlib

Version:

stand-alone library of threejs examples

116 lines (115 loc) 5.21 kB
import { Group, BufferGeometry, BufferAttribute, LineSegments, LineBasicMaterial, Box3Helper, Box3, MeshBasicMaterial, DoubleSide, Mesh, PlaneGeometry } from "three"; class CSMHelper extends Group { constructor(csm) { super(); this.csm = csm; this.displayFrustum = true; this.displayPlanes = true; this.displayShadowBounds = true; const indices = new Uint16Array([0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7]); const positions = new Float32Array(24); const frustumGeometry = new BufferGeometry(); frustumGeometry.setIndex(new BufferAttribute(indices, 1)); frustumGeometry.setAttribute("position", new BufferAttribute(positions, 3, false)); const frustumLines = new LineSegments(frustumGeometry, new LineBasicMaterial()); this.add(frustumLines); this.frustumLines = frustumLines; this.cascadeLines = []; this.cascadePlanes = []; this.shadowLines = []; } updateVisibility() { const displayFrustum = this.displayFrustum; const displayPlanes = this.displayPlanes; const displayShadowBounds = this.displayShadowBounds; const frustumLines = this.frustumLines; const cascadeLines = this.cascadeLines; const cascadePlanes = this.cascadePlanes; const shadowLines = this.shadowLines; for (let i = 0, l = cascadeLines.length; i < l; i++) { const cascadeLine = cascadeLines[i]; const cascadePlane = cascadePlanes[i]; const shadowLineGroup = shadowLines[i]; cascadeLine.visible = displayFrustum; cascadePlane.visible = displayFrustum && displayPlanes; shadowLineGroup.visible = displayShadowBounds; } frustumLines.visible = displayFrustum; } update() { const csm = this.csm; const camera = csm.camera; const cascades = csm.cascades; const mainFrustum = csm.mainFrustum; const frustums = csm.frustums; const lights = csm.lights; const frustumLines = this.frustumLines; const frustumLinePositions = frustumLines.geometry.getAttribute("position"); const cascadeLines = this.cascadeLines; const cascadePlanes = this.cascadePlanes; const shadowLines = this.shadowLines; this.position.copy(camera.position); this.quaternion.copy(camera.quaternion); this.scale.copy(camera.scale); this.updateMatrixWorld(true); while (cascadeLines.length > cascades) { this.remove(cascadeLines.pop()); this.remove(cascadePlanes.pop()); this.remove(shadowLines.pop()); } while (cascadeLines.length < cascades) { const cascadeLine = new Box3Helper(new Box3(), 16777215); const planeMat = new MeshBasicMaterial({ transparent: true, opacity: 0.1, depthWrite: false, side: DoubleSide }); const cascadePlane = new Mesh(new PlaneGeometry(), planeMat); const shadowLineGroup = new Group(); const shadowLine = new Box3Helper(new Box3(), 16776960); shadowLineGroup.add(shadowLine); this.add(cascadeLine); this.add(cascadePlane); this.add(shadowLineGroup); cascadeLines.push(cascadeLine); cascadePlanes.push(cascadePlane); shadowLines.push(shadowLineGroup); } for (let i = 0; i < cascades; i++) { const frustum = frustums[i]; const light = lights[i]; const shadowCam = light.shadow.camera; const farVerts2 = frustum.vertices.far; const cascadeLine = cascadeLines[i]; const cascadePlane = cascadePlanes[i]; const shadowLineGroup = shadowLines[i]; const shadowLine = shadowLineGroup.children[0]; cascadeLine.box.min.copy(farVerts2[2]); cascadeLine.box.max.copy(farVerts2[0]); cascadeLine.box.max.z += 1e-4; cascadePlane.position.addVectors(farVerts2[0], farVerts2[2]); cascadePlane.position.multiplyScalar(0.5); cascadePlane.scale.subVectors(farVerts2[0], farVerts2[2]); cascadePlane.scale.z = 1e-4; this.remove(shadowLineGroup); shadowLineGroup.position.copy(shadowCam.position); shadowLineGroup.quaternion.copy(shadowCam.quaternion); shadowLineGroup.scale.copy(shadowCam.scale); shadowLineGroup.updateMatrixWorld(true); this.attach(shadowLineGroup); shadowLine.box.min.set(shadowCam.bottom, shadowCam.left, -shadowCam.far); shadowLine.box.max.set(shadowCam.top, shadowCam.right, -shadowCam.near); } const nearVerts = mainFrustum.vertices.near; const farVerts = mainFrustum.vertices.far; frustumLinePositions.setXYZ(0, farVerts[0].x, farVerts[0].y, farVerts[0].z); frustumLinePositions.setXYZ(1, farVerts[3].x, farVerts[3].y, farVerts[3].z); frustumLinePositions.setXYZ(2, farVerts[2].x, farVerts[2].y, farVerts[2].z); frustumLinePositions.setXYZ(3, farVerts[1].x, farVerts[1].y, farVerts[1].z); frustumLinePositions.setXYZ(4, nearVerts[0].x, nearVerts[0].y, nearVerts[0].z); frustumLinePositions.setXYZ(5, nearVerts[3].x, nearVerts[3].y, nearVerts[3].z); frustumLinePositions.setXYZ(6, nearVerts[2].x, nearVerts[2].y, nearVerts[2].z); frustumLinePositions.setXYZ(7, nearVerts[1].x, nearVerts[1].y, nearVerts[1].z); frustumLinePositions.needsUpdate = true; } } export { CSMHelper }; //# sourceMappingURL=CSMHelper.js.map