@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
6 lines (5 loc) • 5.03 kB
JavaScript
/*
All material copyright ESRI, All Rights Reserved, unless otherwise specified.
See https://js.arcgis.com/4.33/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,f as a,u as o,t as h}from"../../../../chunks/vec32.js";import{create as c}from"../../../../core/libs/gl-matrix-2/factories/vec3f64.js";import{DepthFormat as n}from"../core/FBOCacheFormats.js";import{applyTextureResizeModulo as l}from"./textureUtils.js";import{ViewshedFaceCamera as u}from"./ViewshedFaceCamera.js";import{DepthStencilAttachment as m,SizedDepthFormat as f,FramebufferBit as d}from"../../../webgl/enums.js";import{isSizedDepthStencilFormat as p}from"../../../webgl/textureUtils.js";class g{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 x(t){return!["top","bottom"].includes(t)}class w{constructor(t){this._fbos=t,this._faces={},this._width=0,this._height=0,this.settings=new g,this._maxTextureSize=Math.min(has("esri-mobile")?4096:16384,t.rctx.parameters.maxTextureSize)}get depthTexture(){return this._handle?.getTexture(m)}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,m){const{effectiveObserverRenderSpace:f,tiltedUpVector:d,targetRenderSpace:p,farDistanceRenderSpace:g,horizontalFieldOfView:_,verticalFieldOfView:w}=n,b=c();r(b,p,f);const M=c(),S=c(),F=(t,e)=>{const r=c(),o=s();return i(o,t,e),h(r,b,o),a(r,f,r),r};let z,T=d;const O=Math.min(90,_),v=Math.min(90,Math.max(0,(_-90)/2));let j=-45,B=45,y=-45,k=45;if(x(e)){const e=e=>t(e,-45,45);y=e(-w/2)-this.settings.toleranceBottomTop,k=e(+w/2)+this.settings.toleranceBottomTop}switch(e){case"front":z=p,j=-O/2,B=O/2;break;case"left":z=F(Math.PI/2,d),j=45-v;break;case"right":z=F(-Math.PI/2,d),B=-45+v;break;case"top":z=a(M,f,d),T=o(S,b);break;case"bottom":z=r(M,f,d),T=b;break;case"back":z=F(Math.PI,d)}const P=new u({center:z,eye:f,up:T,far:g});P.sectionAnglesDeg=[j-this.settings.toleranceSides,B+this.settings.toleranceSides,y,k],P.fovY=Math.PI/2;const C=P.setViewport(l,m);return this._faces[e]=P,C}isActive(t){return this._computeActiveFaces(t).size>0}_computeActiveFaces(t){const e=new Set,{horizontalFieldOfView:i,verticalFieldOfView:s}=t,r=-s/2,a=s/2;return 0===i||0===s||(r<=45&&a>=-45&&e.add("front"),i>90&&(e.add("left"),e.add("right")),i>270&&e.add("back"),a>45-this.settings.toleranceBottomTop&&e.add("top"),r<-45+this.settings.toleranceBottomTop&&e.add("bottom")),e}_computeBaseTextureSize({pixelRatio:t,fullWidth:e,fullHeight:i},s,r,a){const o=s/t,h=this.settings.textureSizeModifier(r);return l(Math.max(e,i)*o*h,this._maxTextureSize/a)}_ensureFBO(t){const e=this._width,i=this._height,s=this._handle?.fbo;s&&s.width===e&&s.height===i&&t===p(s.depthStencilTexture?.descriptor?.internalFormat??f.DEPTH_COMPONENT16)||(this._handle?.release(),this._handle=this._allocateFBO(t))}_allocateFBO(t){const{_width:e,_height:i}=this,s=t?n.DEPTH24_STENCIL8:n.DEPTH16,r=this._fbos.acquire(e,i,"viewshed shadow map",s);return r.getTexture(m)?.setShadowFiltering(!1),r}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._debugFBO||(this._handle=e(this._handle))}start(t,e,i,s,r=!1){this._faces={};const a=this._computeActiveFaces(e),o=a.size;if(0===o)return!1;const h=this._computeBaseTextureSize(t,s,i,o);let c=0,n=0,l=0;return _.filter((t=>a.has(t))).forEach((t=>{const i=b(t,o);i>n&&(l=Math.max(l,c),c=0),n=i;const s=i*h;c+=this._setupFaceCamera(t,e,[c,s],h)})),l=Math.max(l,c),this._width=this.settings.textureResizeModulo(l),this._height=M(o)*h,this.clearFBO(r),!0}finish(){}get test(){}}function b(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 M(t){return t<4?1:2}export{w as ViewshedShadowMap};