UNPKG

@arcgis/core

Version:

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

3 lines (2 loc) • 12.7 kB
/* COPYRIGHT Esri - https://js.arcgis.com/5.0.19/LICENSE.txt */ import{__decorate as e}from"tslib";import{isSome as t}from"../../../../../core/arrayUtils.js";import r from"../../../../../core/Error.js";import{someMap as n,getOrCreateMapValue as s}from"../../../../../core/MapUtils.js";import{destroyMaybe as a}from"../../../../../core/maybe.js";import{isAborted as i,throwIfAborted as o}from"../../../../../core/promiseUtils.js";import{property as l,subclass as c}from"../../../../../core/accessorSupport/decorators.js";import{create as h}from"../../../../../core/libs/gl-matrix-2/factories/mat4f64.js";import{subtract as d,dot as u,transformMat4 as m}from"../../../../../core/libs/gl-matrix-2/math/vec3.js";import{create as f}from"../../../../../core/libs/gl-matrix-2/factories/vec3f64.js";import{create as _,freeze as p}from"../../../../../core/libs/gl-matrix-2/factories/vec4f64.js";import{debugFlags as g}from"../../../support/debugFlags.js";import{glLayout as y}from"../../../support/buffer/glUtil.js";import v from"../../../webgl/RenderCamera.js";import{AsyncRenderPlugin as b}from"../../effects/RenderPlugin.js";import{DepthRange as I}from"../DepthRange.js";import{assert as C}from"../Util.js";import{InstanceData as D}from"./InstanceData.js";import{InstanceOctree as R}from"./InstanceOctree.js";import{LevelSelector as E}from"./LevelSelector.js";import{LodLevel as x}from"./LodLevel.js";import{getRenderInstanceDataLayout as S,RenderInstanceData as w}from"./RenderInstanceData.js";import{colorMixModes as L}from"../../materials/internal/MaterialUtil.js";import{encodeDoubleVec3 as j}from"../../materials/renderers/utils.js";import{DefaultMaterialDrawParameters as U}from"../../shaders/DefaultMaterialTechnique.js";import{defaultHighlightName as T}from"../../../../support/HighlightDefaults.js";import{TaskPriority as O,noBudget as A}from"../../../../support/Scheduler.js";import{bindVertexBufferLayout as M}from"../../../../webgl/Util.js";import{fromLayout as q}from"../../../../webgl/VertexAttributeLocations.js";const B=e=>{const t=e.baseBoundingSphere.radius,r=e.levels.map(e=>e.minScreenSpaceRadius);return new E(t,r)};let F=class extends b{constructor(e,t){super(e),this.type=3,this.isGround=!1,this._levels=[],this._defaultRenderInstanceData=new Array,this._highlightRenderInstanceDatas=new Map,this._instanceIndex=0,this._cycleStartIndex=0,this._slicePlane=!1,this._camera=new v,this._updateCyclesWithStaticCamera=-1,this._needFullCycle=!1,this.produces=new Map([[2,e=>this._produces(e)],[4,e=>!!this._hasTransparentLevels()&&this._produces(e)]]),this._instanceData=new D({shaderTransformation:e.shaderTransformation},e.symbol.materialParameters),this.addHandles(t.registerTask(O.LOD_RENDERER,this))}initialize(){this._instanceBufferLayout=S(this.symbol.materialParameters),this._glInstanceBufferLayout=y(this._instanceBufferLayout,1),this.addHandles([this._instanceData.events.on("instances-changed",()=>this._requestUpdateCycle()),this._instanceData.events.on("instance-transform-changed",({index:e})=>{this._requestUpdateCycle(),this.metadata.notifyGraphicGeometryChanged(e)}),this._instanceData.events.on("instance-visibility-changed",({index:e})=>{this._requestUpdateCycle(!0),this.metadata.notifyGraphicVisibilityChanged(e)}),this._instanceData.events.on("instance-highlight-changed",()=>this._requestUpdateCycle(!0))])}get _allRenderInstanceData(){return[this._defaultRenderInstanceData,...this._highlightRenderInstanceDatas.values()]}get _allRenderInstanceDataExceptHighlightShadow(){const e=[this._defaultRenderInstanceData];for(const t of this._highlightRenderInstanceDatas)t[0]!==T&&e.push(t[1]);return e}hasHighlight(e){return this._highlightRenderInstanceDatas.has(e)}get _enableLevelSelection(){return this.symbol.levels.length>1}get levels(){return this._levels}get baseBoundingBox(){return this._levels[this._levels.length-1].boundingBox}get baseBoundingSphere(){return this._levels[this._levels.length-1].boundingSphere}get baseMaterial(){return this._levels[this._levels.length-1].components[0].material}get slicePlaneEnabled(){return this._slicePlane}set slicePlaneEnabled(e){this._slicePlane=e}get layerViewUid(){return this.metadata.layerViewUid}get instanceData(){return this._instanceData}get hasEmitters(){return this._levels.some(e=>e.components.some(e=>e.material.hasEmissions))}get usedMemory(){return this._allRenderInstanceData.reduce((e,t)=>t.reduce((e,t)=>e+t.usedMemory,e),this._levels.reduce((e,t)=>e+t.components.reduce((e,t)=>e+t.usedMemory,0),0))}get renderStats(){const e=this._instanceData.size,t=[];return this._levels.forEach((e,r)=>{const n=this._allRenderInstanceData[0][r].size+this._allRenderInstanceData[1][r].size,s=e.triangleCount;t.push({renderedInstances:n,renderedTriangles:n*s,trianglesPerInstance:s})}),{totalInstances:e,renderedInstances:t.reduce((e,t)=>e+t.renderedInstances,0),renderedTriangles:t.reduce((e,t)=>e+t.renderedTriangles,0),levels:t}}_createRenderInstanceDataArray(){const{rctx:e}=this._context.renderContext;return this.symbol.levels.map(t=>new w(e,this._instanceBufferLayout))}async initializeRenderContext(e,r){this._context=e,this._defaultRenderInstanceData=this._createRenderInstanceDataArray();const n=await Promise.allSettled(this.symbol.levels.map(t=>x.create(e,t,r))),s=n.map(e=>"fulfilled"===e.status?e.value:null).filter(t);if(i(r)||s.length!==n.length){s.forEach(e=>e.destroy()),o(r);for(const e of n)if("rejected"===e.status)throw e.reason}this._levels=s,this._levelSelector=B(this)}uninitializeRenderContext(){this._invalidateOctree(),this._levels.forEach(e=>e.destroy()),this._defaultRenderInstanceData.forEach(e=>e.destroy()),this._highlightRenderInstanceDatas.forEach(e=>e.forEach(e=>e.destroy()))}_hasTransparentLevels(){return this._levels.some(e=>e.components.some(e=>{const t=e.material.produces.get(4);return t?.(0)}))}hasHighlights(){return n(this._highlightRenderInstanceDatas,e=>e.some(e=>e.size>0))}_produces(e){return(8!==e||this.hasHighlights())&&(4!==e||this.hasHighlight(T))}prepareRender(e){if(!g.LOD_INSTANCE_RENDERER_DISABLE_UPDATES){if(this._enableLevelSelection){const t=e.bind.contentCamera.equals(this._camera);this._camera.copyFrom(e.bind.contentCamera),t||this._requestUpdateCycle()}this._needFullCycle&&(this.runTask(A),this._needFullCycle=!1)}}acquireTechniques(e){if(!this.baseMaterial.visible||!this.baseMaterial.isVisibleForOutput(e.output))return null;const t=this._getInstanceDatas(e);if(!t)return null;const r=new Array,n=this.levels;return t.forEach(t=>n.forEach(({components:n},s)=>n.forEach(n=>r.push(this._beginComponent(e,t[s],n))))),r}render(e,t){const r=this._getInstanceDatas(e);if(!r||null==t)return;let n=0;const s=this.levels;r.forEach(r=>s.forEach(({components:s},a)=>s.forEach(s=>this._renderComponent(e,t[n++],r[a],s,a)))),e.rctx.unbindBuffer(34962),e.rctx.bindVAO(null)}_getInstanceDatas(e){const{output:t,bind:r}=e,n=8===t,s=4===t,a=5!==t;if(!n&&!s)return a?this._allRenderInstanceData:this._allRenderInstanceDataExceptHighlightShadow;const{_highlightRenderInstanceDatas:i}=this;if(a){if(n){const e=r.highlight?.name;if(!e)return null;const t=i.get(e);return t?[t]:null}const e=i.get(T);return s?e?[e]:null:Array.from(i.values())}return null}intersect(e,t,r,n){if(!this.baseMaterial.visible||null==this._octree)return;const s=f();d(s,n,r);const a=s=>{this._instanceData.getCombinedModelTransform(s,N),e.transform.set(N),m(G,r,e.transform.inverse),m(W,n,e.transform.inverse);const a=this._instanceData.getState(s),i=this._instanceData.getLodLevel(s),o=this._levels.length;4&a&&(C(!!(18&a),"invalid instance state"),C(i>=0&&i<o,"invaid lod level"),this._levels[i].intersect(e,t,G,W,s,this.metadata,o))};this.baseMaterial.parameters.verticalOffset?this._octree.forEach(a):this._octree.forEachAlongRay(r,s,a)}notifyShaderTransformationChanged(){this._invalidateOctree(),this._requestUpdateCycle()}get _octree(){if(null==this._octreeCached){const e=this._instanceData,t=e.view?.state;if(!t)return null;this._octreeCached=new R(e,this.baseBoundingSphere);for(let r=0;r<e.capacity;++r)18&t.get(r)&&this._octreeCached.addInstance(r)}return this._octreeCached}_invalidateOctree(){this._octreeCached=a(this._octreeCached)}queryDepthRange(e){if(null==this._octree)return new I;const t=e.viewForward,r=this._octree.findClosest(t,1,e.frustum),n=this._octree.findClosest(t,-1,e.frustum);if(null==r||null==n)return new I;const s=e.eye,a=this._instanceData.view;a.boundingSphere.getVec(r,z),d(z,z,s);const i=u(z,t)-z[3];a.boundingSphere.getVec(n,z),d(z,z,s);const o=u(z,t)+z[3];return new I(i,o)}_requestUpdateCycle(e=!1){this._updateCyclesWithStaticCamera=-1,this._cycleStartIndex=this._instanceIndex,e&&(this._needFullCycle=!0,this._context.requestRender())}_startUpdateCycle(){this._updateCyclesWithStaticCamera++,this._allRenderInstanceData.forEach(e=>e.forEach(e=>e.startUpdateCycle()))}get readyToRun(){return this._instanceData.size>0&&this._updateCyclesWithStaticCamera<1}runTask(e){const{_enableLevelSelection:t,_camera:n,_levelSelector:a}=this;this._allRenderInstanceData.forEach(e=>e.forEach(e=>e.beginUpdate()));const i=this._instanceData,o=i.view;let l=i.size;const c=i.capacity;let h=this._instanceIndex;const d=Math.ceil(c/500),{_highlightRenderInstanceDatas:u}=this;for(let m=0;m<l&&!e.done;++m){h===this._cycleStartIndex&&this._startUpdateCycle();const m=o.state.get(h);let f=0;if(!(1&m)){h=h+1===c?0:h+1,l++;continue}const _=o.lodLevel.get(h);if(2&m&&this._defaultRenderInstanceData[_].freeTail(),16&m){const e=i.geHighlightOptionsPrev(h);if(e){const t=u.get(e);if(!t)throw new r("internal:lod-renderer","Internal error in lodRenderer");t[_].freeTail(),t.every(e=>e.isEmpty)&&(t.forEach(e=>e.destroy()),u.delete(e))}}if(32&m)i.freeInstance(h);else if(4&m){let e=0;if(t&&(o.modelOrigin.getVec(h,P),e=a.selectLevel(P,i.getCombinedMedianScaleFactor(h),n)),f=-83&m,e>=0)if(8&m){const t=i.getHighlightName(h);if(t){const n=()=>{const e=this._createRenderInstanceDataArray();return e.forEach(e=>e.beginUpdate()),e},a=s(u,t,n);if(e>=a.length)throw new r("internal:lod-renderer",`LodRenderer internal error - missing lodLevel ${e}`);H(a[e],o,h)}f|=16}else H(this._defaultRenderInstanceData[e],o,h),f|=2;o.state.set(h,f),o.lodLevel.set(h,e)}else f=-83&m,o.state.set(h,f);const p=!!(18&m),g=!!(18&f);null!=this._octreeCached&&(!p&&g?this._octreeCached.addInstance(h):p&&!g?this._octreeCached.removeInstance(h):p&&g&&64&m&&(this._octreeCached.removeInstance(h),this._octreeCached.addInstance(h))),h=h+1===c?0:h+1,h%d===0&&e.madeProgress(),p!==g&&this.metadata.notifyGraphicVisibilityChanged(h),g&&64&m&&this.metadata.notifyGraphicGeometryChanged(h)}this._instanceIndex=h,this._allRenderInstanceData.forEach(e=>e.forEach(e=>e.endUpdate())),this._context.requestRender()}_beginComponent(e,t,r){if(0===t.size)return null;const n=r.glMaterials.load(e.rctx,e.bind.slot,e.output);return n?.beginSlot(e.bind)}_renderComponent(e,t,r,n,s){if(!t)return;const{bind:a,rctx:i}=e;i.runAppleAmdDriverHelper();const o=i.bindTechnique(t,a,n.material.parameters,Y),l=this._glInstanceBufferLayout;o.assertCompatibleVertexAttributeLocations(n.vao,q(l)),i.bindVAO(n.vao),g.LOD_INSTANCE_RENDERER_COLORIZE_BY_LEVEL&&0===e.output&&(o.setUniform4fv("externalColor",k[Math.min(s,k.length-1)]),o.setUniform1i("symbolColorMixMode",L.replace));const c=r.capacity,h=r.headIndex,d=r.tailIndex,u=r.firstIndex,m=(e,s)=>{M(i,o.locations,r.buffer,e),i.drawArraysInstanced(t.primitiveType,0,n.numVertices,s-e)};n.material.transparent&&null!=u?h>d?(C(u>=d&&u<=h,"invalid firstIndex"),m(u,h),m(d,u)):h<d&&(u<=h?(C(u>=0&&u<=h,"invalid firstIndex"),m(u,h),m(d,c),m(0,u)):(C(u>=d&&u<=c,"invalid firstIndex"),m(u,c),m(0,h),m(d,u))):h>d?m(d,h):h<d&&(m(0,h),m(d,c))}};function H(e,t,r){const n=e.allocateHead();V(t,r,e.view,n)}function V(e,t,r,n){j(e.modelOrigin,t,r.modelOriginHi,r.modelOriginLo,n),r.model.copyFrom(n,e.model,t),r.modelNormal.copyFrom(n,e.modelNormal,t),e.color&&r.color&&r.color.copyFrom(n,e.color,t),e.olidColor&&r.olidColor&&r.olidColor.copyFrom(n,e.olidColor,t),e.featureAttribute&&r.featureAttribute&&r.featureAttribute.copyFrom(n,e.featureAttribute,t)}e([l({constructOnly:!0})],F.prototype,"symbol",void 0),e([l({constructOnly:!0})],F.prototype,"metadata",void 0),e([l({constructOnly:!0})],F.prototype,"shaderTransformation",void 0),e([l()],F.prototype,"_instanceData",void 0),e([l()],F.prototype,"_cycleStartIndex",void 0),e([l({readOnly:!0})],F.prototype,"_enableLevelSelection",null),e([l()],F.prototype,"_updateCyclesWithStaticCamera",void 0),e([l({readOnly:!0})],F.prototype,"readyToRun",null),F=e([c("esri.views.3d.webgl-engine.lib.lodRendering.LodRenderer")],F);const P=f(),z=_(),N=h(),G=f(),W=f(),k=[p(1,0,1,1),p(0,0,1,1),p(0,1,0,1),p(1,1,0,1),p(1,0,0,1)],Y=new U;export{F as LodRenderer};