@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
6 lines (5 loc) • 11.4 kB
JavaScript
/*
All material copyright ESRI, All Rights Reserved, unless otherwise specified.
See https://js.arcgis.com/4.32/esri/copyright.txt for details.
*/
import e from"../../../../../core/Logger.js";import{getOrCreateMapValue as t}from"../../../../../core/MapUtils.js";import i from"../../../../../core/PooledArray.js";import{isTypedArray as o}from"../../../../../core/typedArrayUtil.js";import{s as n}from"../../../../../chunks/vec32.js";import{clone as r}from"../../../../../core/libs/gl-matrix-2/factories/vec3f64.js";import{create as s}from"../../../../../geometry/support/aaBoundingBox.js";import{compactIndices as a}from"../../../../../geometry/support/Indices.js";import{c as l}from"../../../../../chunks/vec3.js";import{c}from"../../../../../chunks/vec33.js";import{ViewingMode as m}from"../../../../ViewingMode.js";import{ColorMixModeEnum as p,encodeSymbolColor as f}from"../../../layers/support/symbolColorUtils.js";import{computeOffsetObb as h}from"../../../support/orientedBoundingBox.js";import{glLayout as g}from"../../../support/buffer/glUtil.js";import{newLayout as d}from"../../../support/buffer/InterleavedLayout.js";import u from"./ComponentData.js";import{ComponentObject as b}from"./ComponentObject.js";import{IntersectionGeometry as y}from"./IntersectionGeometry.js";import{Renderable as v}from"./Renderable.js";import{RenderGeometry as _}from"./RenderGeometry.js";import{RenderSubmitSystem as C}from"./RenderSubmitSystem.js";import{createVertexBufferLayout as M}from"./SourceGeometry.js";import{UniformComponentParameters as j}from"./UniformComponentParameters.js";import{ComponentParametersVarying as w,ComponentParametersUniform as O,ComponentParameterSummary as x,ComponentMaterial as D}from"./Material/ComponentMaterial.js";import{vertexAttributeLocations as A}from"./Material/ComponentTechnique.js";import{encodeElevationOffset as R}from"./Material/shader/ComponentData.glsl.js";import{olidEnabled as S}from"../../effects/geometry/olidUtils.js";import{getVisibility as E,updateVisibilityWithCount as I}from"../../lib/ComponentUtils.js";import{assert as H}from"../../lib/Util.js";import{VertexAttribute as V}from"../../lib/VertexAttribute.js";import{getVerticalOffsetI3S as U}from"../../lib/verticalOffsetUtils.js";import{BufferManager as B}from"../../lib/TextureBackedBuffer/BufferManager.js";import{BufferObject as P}from"../../../../webgl/BufferObject.js";import{Usage as N,PrimitiveType as T}from"../../../../webgl/enums.js";import{VertexArrayObject as k}from"../../../../webgl/VertexArrayObject.js";const L=()=>e.getLogger("esri.views.3d.webgl-engine.collections.Component.ComponentObjectCollection");class G{constructor(e,t){this._renderManager=e,this._viewingMode=t,this._elevationRangeCacheVerticalOffset=NaN,this._elevationRangeCacheMin=NaN,this._elevationRangeCacheMax=NaN,this._activeHighlightOptions=new Map,this._visible=new i,this._hidden=new i,this._renderSubmit=new C(this),this._renderManager.register(this._renderSubmit),this._componentBufferManager=new B(e.rctx,2+(S()?1:0))}destroy(){H(0===this._hidden.length&&0===this._visible.length,"ObjectCollection should be empty upon disposal"),this._componentBufferManager.destroy(),this._visible.forAll((e=>e.destroy())),this._hidden.forAll((e=>e.destroy())),this._visible.clear(),this._hidden.clear()}createObject(e){const t=e.geometry,i=new u(this._componentBufferManager,a(t.componentOffsets)),o=this._createRenderable(e,i),n=new y(this._viewingMode,t.positionData,i),r=new b(e.transform,e.toMapSpace,e.obb.clone(),i,o,n);return(r.visible?this._visible:this._hidden).push(r),r}destroyObject(e){const t=e;(t.visible?this._visible:this._hidden).removeUnordered(t),t.destroy(),this._notifyDirty()}setObjectVisibility(e,t){const i=e;t!==i.visible&&(t?(this._hidden.removeUnordered(i),this._visible.push(i)):(this._visible.removeUnordered(i),this._hidden.push(i)),i.visible=t,this._notifyDirty())}preSubmit(e){const t=e.camera.eye;this.visibleObjects.forAll((e=>e.renderable.meta.cameraDepthSquared=n(t,e.obb.center)))}getMaterial(e){return e.renderable.material}updateMaterial(e,t){const i=e.renderable.material;t(i),i.dirty&&this._notifyDirty()}setAllComponentVisibilities(e,t){const i=e;i.componentData.visibility.reset(t),i.componentData.markVisibilityDirty(),this._notifyDirty()}forEachVisibleComponent(e,t){return e.componentData.visibility.forEachComponent(t)}getComponentCount(e){const t=e,i=t.componentData.visibility.componentCount;return{visible:i,invisible:t.componentData.count-i}}setComponentData(e,t){const i=e,{renderable:o,componentData:n}=i,r=o.material,s=n.materialDataBuffer,a=n.materialDataIndices,l=new j,c=s.textureBuffer,m=new Uint8Array(4),g=new Uint32Array(m.buffer);let d=0,u=0,b=0,y=n.verticalOffsets,v=1/0,_=-1/0,C=!1,M=!1,D=0;for(let h=0;h<n.count;h++){t(h,l),d+=+(l.externalColor[3]<1),u+=+(l.externalColorMixMode===p.Replace&&1===l.externalColor[3]),b+=+l.castShadows,f(l.externalColor,l.externalColorMixMode,m),m[2]=254&m[2]|+l.castShadows,c.setData(a[h],0,m[0],m[1],m[2],m[3]),C||=h>0&&D!==g[0],D=g[0],M||=0!==l.elevationOffset,M&&null==y&&(y=new Array(h).fill(0)),null!=y&&(y[h]=l.elevationOffset),v=Math.min(v,l.elevationOffset),_=Math.max(_,l.elevationOffset),R(l.elevationOffset,m),c.setData(a[h],1,m[0],m[1],m[2],m[3]);const e=l.objectAndLayerIdColor;null!=e&&c.setData(a[h],2,e[0],e[1],e[2],e[3]),l.pickable!==E(n.pickability,h)&&(n.pickability=I(n.pickability,n.count,h,l.pickable))}n.verticalOffsets=M?y:null,i.offsetObb=M?h(i.obb,v,_,this._viewingMode,i.offsetObb??i.obb.clone()):null,C||M||S()?(r.componentParameters=new w,r.componentParameters.castShadows=W(b,n.count),r.componentParameters.transparent=W(d,n.count),r.componentParameters.opaqueOverride=W(u,n.count),r.componentParameters.texture=c,c.updateTexture()):(r.componentParameters=new O,r.componentParameters.castShadows=l.castShadows?x.All:x.None,r.componentParameters.externalColor=l.externalColor,r.componentParameters.externalColorMixMode=l.externalColorMixMode),this._elevationRangeCacheVerticalOffset=NaN,this._notifyDirty()}getComponentAabb(e,t,i,o=!1){e.intersectionGeometry.getComponentAabb(t,i);const n=e,r=n.componentData.verticalOffsets;if(o||null==r)return i;const s=r[t];if(this._viewingMode===m.Local||0===s)return i[2]+=s,i[5]+=s,i;const a=U(s);return a.localOrigin=n.transform.position,a.applyToAabb(i)}getComponentObb(e){return e.obb}getObjectTransform(e){return e.transform}getComponentPositions(e,t,i){return e.intersectionGeometry.getComponentPositions(t,i)}expandRangeWithComponentObjectElevationRange(e,t,i,o){Number.isNaN(this._elevationRangeCacheVerticalOffset)||this._elevationRangeCacheVerticalOffset!==t||o.expandElevationRangeValues(this._elevationRangeCacheMin,this._elevationRangeCacheMax);const n=e,r=n.componentData,s=r.count,a=r.verticalOffsets,l=n.intersectionGeometry,c=this._viewingMode===m.Local,p=l.getComponentAabbs(),f=z;let h=1/0,g=-1/0;for(let m=0;m<s;m++){const e=6*m,r=a?.[m]??0;let s=1/0,l=-1/0;if(c)s=p[e+2]+r+t,l=p[e+5]+r+t;else{if(f[0]=p[e],f[1]=p[e+1],f[2]=p[e+2],f[3]=p[e+3],f[4]=p[e+4],f[5]=p[e+5],0!==r){const e=U(r);e.localOrigin=n.transform.position,e.applyToAabb(f)}const s=Math.max(Math.abs(f[3]),Math.abs(f[0])),a=Math.max(Math.abs(f[4]),Math.abs(f[1])),l=t+f[5]+i;o.expandElevationRangeValues(t+f[2],Math.sqrt(s*s+a*a+l*l)-i)}o.expandElevationRangeValues(s,l),h=Math.min(h,s),g=Math.max(g,l)}this._elevationRangeCacheVerticalOffset=t,this._elevationRangeCacheMin=h,this._elevationRangeCacheMax=g}intersect(e,t,i,o,n,r,s){const a=e,{transform:l}=a,{position:c}=l;return null!=n&&(n.localOrigin=c),a.intersectionGeometry.intersect(t,i,o,n,a.componentData.verticalOffsets,l,r,s)}addEdges(e,t,i,o,n){const r=e,{indices:s,positions:a}=r.intersectionGeometry,l=r.componentData.offsets;return t.addComponentObject(r,a,s,l,i,o,n)}async extractEdgeInformation(e,t,i){const o=e,n=o.componentData.visibility;if(n.allInvisible()){const{extractComponentsEdgeLocationsLayout:e}=await import("../../lib/edgeRendering/edgeProcessing.js");return{buffer:e.createBuffer(0),origin:[0,0,0]}}const{indices:s,positions:a}=o.intersectionGeometry,m=o.componentData.offsets,{EdgeInputBufferLayout:p}=await import("../../lib/edgeRendering/bufferLayouts.js"),f=p.createBuffer(a.length/3);c(f.position.typedBuffer,a,f.position.typedBufferStride,3),l(f.position,f.position,o.transform.rotationScale),this._setComponentIndices(f.componentIndex,s,m);const h=f.count,g=this._computeVisibilityIndices(s,n,m,h);return{origin:r(o.transform.position),buffer:await t.extractComponentsEdgeLocations({indices:g,indicesLength:g.length,skipDeduplicate:!0,data:f,writerSettings:{reducedPrecision:!1,variants:0}},i)}}_setComponentIndices(e,t,i){let o=0;for(let n=0;n<i.length-1;n++){const r=i[n],s=i[n+1];for(let i=r;i<s;i++){const n=t?t[i]:i;e.set(n,o)}o++}}_computeVisibilityIndices(e,t,i,n){if(e&&t.allVisible())return e;let r=0;t.forEachComponentRange(((e,t)=>(r+=i[t]-i[e],!0)));const s=o(e)?2===e?.BYTES_PER_ELEMENT||n<=65536?new Uint16Array(r):new Uint32Array(r):new Array(r);let a=0;return t.forEachComponentRange(((t,o)=>{const n=i[t],r=i[o];for(let i=n;i<r;i++)s[a++]=e?e[i]:i;return!0})),s}addComponentHighlight(e,i,o){const n=e.componentData,r=t(n.componentHighlights,o,(()=>new Uint32Array(n.count+1)));{const e=this._activeHighlightOptions.get(o)??0;this._activeHighlightOptions.set(o,e+1)}0===r[i]++&&(n.markHighlightsDirty(),this._notifyDirty()),r[n.count]++}removeComponentHighlight(e,t,i){const{componentData:o}=e,n=o.componentHighlights.get(i);if(void 0===n)return void L().warn("Removing non-existing highlight.");const r=n[t];if(0===r)return void L().warn("Removing non-existing highlight.");this._removeActiveHighlight(i);const s=n[o.count];if(r>1)return n[t]=r-1,void(n[o.count]=s-1);n[t]=0,1===s?o.componentHighlights.delete(i):n[o.count]=s-1,o.markHighlightsDirty(),this._notifyDirty()}_removeActiveHighlight(e,t=1){const i=this._activeHighlightOptions.get(e);if(void 0===i)L().warn("Removing non-existing highlight.");else{const o=i-t;o<0&&L().warn("Removing non-existing highlight."),o<=0?this._activeHighlightOptions.delete(e):this._activeHighlightOptions.set(e,o)}}clearHighlights(e){const{componentData:t}=e,{componentHighlights:i}=t;if(i.size>0){for(const e of i)this._removeActiveHighlight(e[0],e[1][t.count]);i.clear(),t.markHighlightsDirty(),this._notifyDirty()}}hasHighlightOptions(e){return this._activeHighlightOptions.has(e)}getObjectGPUMemoryUsage(e){return e.renderable.meta.gpuMemoryEstimate}get visibleObjects(){return this._visible}_createRenderable(e,t){const i=this._renderManager.rctx,o=e.geometry,n=o.vertices.layoutParameters,r=P.createVertex(i,N.STATIC_DRAW,o.vertices.data),s=o.indices?P.createIndex(i,N.STATIC_DRAW,o.indices):null,a=g(M(n)),l=new Uint16Array(o.vertices.count);for(let g=0;g<t.count;g++){const e=t.offsets[g],i=t.offsets[g+1],n=t.materialDataIndices[g];if(null!=o.indices)for(let t=e;t<i;t++){l[o.indices[t]]=n}else for(let t=e;t<i;t++)l[t]=n}const c=P.createVertex(i,N.STATIC_DRAW,l.buffer),m=new D(e.transform,e.toMapSpace),p=new k(i,A,new Map([["data",a],["componentIndices",q]]),new Map([["data",r],["componentIndices",c]]),s),f=new _(p,T.TRIANGLES,n,null!=s),h={cameraDepthSquared:.5,gpuMemoryEstimate:r.usedMemory+c.usedMemory+(null!=s?s.usedMemory:0)};return new v(m,f,h)}_notifyDirty(){this._renderManager.notifyDirty()}}const q=g(d().u16(V.COMPONENTINDEX));function W(e,t){return e===t?x.All:0===e?x.None:x.Some}const z=s();export{G as ComponentObjectCollection};