UNPKG

@arcgis/core

Version:

ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API

6 lines (5 loc) 5.07 kB
/* All material copyright ESRI, All Rights Reserved, unless otherwise specified. See https://js.arcgis.com/4.32/esri/copyright.txt for details. */ import has from"../../../../core/has.js";import{clamp as t}from"../../../../core/mathUtils.js";import{releaseMaybe as e}from"../../../../core/maybe.js";import{fromRotation as i}from"../../../../core/libs/gl-matrix-2/math/mat4.js";import{create as s}from"../../../../core/libs/gl-matrix-2/factories/mat4f64.js";import{a as r,g as h,v as a,t as o}from"../../../../chunks/vec32.js";import{create as c}from"../../../../core/libs/gl-matrix-2/factories/vec3f64.js";import{ColorFormat as n,DepthFormat as l}from"../../webgl/formats.js";import{applyTextureResizeFloorModulo as u,applyTextureResizeModulo as f}from"./textureUtils.js";import{ViewshedFaceCamera as m}from"./ViewshedFaceCamera.js";import{FramebufferBit as d}from"../../../webgl/enums.js";class p{constructor(){this.textureSizeQuality=1,this.textureSizeModHighQuality=1.3,this.textureSizeModLowQuality=.9,this.textureSizeMultiple=128,this.toleranceSides=5,this.toleranceBottomTop=10}textureSizeModifier(t){const e=t?this.textureSizeModHighQuality:this.textureSizeModLowQuality;return this.textureSizeQuality*e}textureResizeModulo(t){return Math.ceil(t/this.textureSizeMultiple)*this.textureSizeMultiple}}const _=["front","left","right","back","top","bottom"];function g(t){return!["top","bottom"].includes(t)}class x{constructor(t){this._fbos=t,this._minTextureSize=16,this._faces={},this._width=0,this._height=0,this.settings=new p,this._maxTextureSize=Math.min(has("esri-mobile")?4096:16384,t.rctx.parameters.maxTextureSize)}get depthTexture(){return this._handle?.getTexture()}get ready(){return null!=this.depthTexture&&0!==this._width&&0!==this._height}get nearFar(){const t=this.faces;return 0===t.length?null:t[0].nearFar}get numActiveFaces(){const t=this._faces;let e=0;return Object.keys(t).forEach((i=>{t[i]&&(e+=1)})),e}get faces(){const t=this._faces,e=[];for(const i of _){const s=t[i];s&&e.push(s)}return e}get atlasRegions(){return this.faces.map((t=>[t.x/this._width,(t.x+t.width)/this._width,t.y/this._height,(t.y+t.height)/this._height]))}get viewshedProjectionMatrices(){return this.faces.map((t=>t.projectionMatrix))}get viewshedViewMatrices(){return this.faces.map((t=>t.viewMatrix))}_setupFaceCamera(e,n,l,u){const{effectiveObserverRenderSpace:f,tiltedUpVector:d,targetRenderSpace:p,farDistanceRenderSpace:_,horizontalFieldOfView:x,verticalFieldOfView:w}=n,b=c();r(b,p,f);const M=c(),S=c(),z=(t,e)=>{const r=c(),a=s();return i(a,t,e),o(r,b,a),h(r,f,r),r};let T,F=d;const v=Math.min(90,x),B=Math.min(90,Math.max(0,(x-90)/2));let j=-45,y=45,O=-45,R=45;if(g(e)){const e=e=>t(e,-45,45);O=e(-w/2)-this.settings.toleranceBottomTop,R=e(+w/2)+this.settings.toleranceBottomTop}switch(e){case"front":T=p,j=-v/2,y=v/2;break;case"left":T=z(Math.PI/2,d),j=45-B;break;case"right":T=z(-Math.PI/2,d),y=-45+B;break;case"top":T=h(M,f,d),F=a(S,b);break;case"bottom":T=r(M,f,d),F=b;break;case"back":T=z(Math.PI,d)}const k=new m({center:T,eye:f,up:F,far:_});k.sectionAnglesDeg=[j-this.settings.toleranceSides,y+this.settings.toleranceSides,O,R],k.fovY=Math.PI/2;const E=k.setViewport(l,u);return this._faces[e]=k,E}isActive(t){return this._computeActiveFaces(t).size>0}_computeActiveFaces(t){const e=new Set,{horizontalFieldOfView:i,verticalFieldOfView:s}=t,r=-s/2,h=s/2;return 0===i||0===s||(r<=45&&h>=-45&&e.add("front"),i>90&&(e.add("left"),e.add("right")),i>270&&e.add("back"),h>45-this.settings.toleranceBottomTop&&e.add("top"),r<-45+this.settings.toleranceBottomTop&&e.add("bottom")),e}_computeBaseTextureSize(e,i,s,r){const h=i/e.pixelRatio,a=this.settings.textureSizeModifier(s),o=Math.max(e.fullWidth,e.fullHeight),c=f(Math.floor(o*h*a)),n=Math.floor(this._maxTextureSize/r),l=t(c,this._minTextureSize,n);return u(l)}_ensureFBO(t){const e=this._width,i=this._height;this._handle?.fbo?.width===e&&this._handle?.fbo?.height===i||(this._handle?.release(),this._handle=this._fbos.acquire(e,i,"viewshed shadow map",n.RGBA4));const s=t?l.DEPTH_STENCIL_TEXTURE:l.DEPTH16_BUFFER;this._handle.acquireDepth(s)}clearFBO(t){const e=this._fbos.rctx;this._ensureFBO(t),e.bindFramebuffer(this._handle?.fbo),e.setClearColor(1,1,1,1),e.clear(d.COLOR|d.DEPTH)}dispose(){this._handle=e(this._handle)}start(t,e,i,s,r=!1){this._faces={};const h=this._computeActiveFaces(e),a=h.size;if(0===a)return!1;const o=this._computeBaseTextureSize(t,s,i,a);let c=0,n=0,l=0;return _.filter((t=>h.has(t))).forEach((t=>{const i=w(t,a);i>n&&(l=Math.max(l,c),c=0),n=i;const s=i*o;c+=this._setupFaceCamera(t,e,[c,s],o)})),l=Math.max(l,c),this._width=this.settings.textureResizeModulo(l),this._height=b(a)*o,this.clearFBO(r),!0}finish(){this._handle?.detachDepth()}get test(){return{faces:this._faces,faceTypes:_,width:this._width,height:this._height,getFBO:()=>this._fbos.acquire(this._width,this._height,"viewshed shadow map",n.RGBA4)}}}function w(t,e){if(e<4)return 0;const i="front"===t||"left"===t;return 4===e?i?0:1:i||"right"===t?0:1}function b(t){return t<4?1:2}export{x as ViewshedShadowMap};