UNPKG

@arcgis/core

Version:

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

6 lines (5 loc) • 8.29 kB
/* All material copyright ESRI, All Rights Reserved, unless otherwise specified. See https://js.arcgis.com/4.33/esri/copyright.txt for details. */ import e from"../../../../core/Error.js";import{assertIsSome as t}from"../../../../core/maybe.js";import{MinPriority as r}from"../../../../core/MemCache.js";import{throwIfAborted as o}from"../../../../core/promiseUtils.js";import{generateUUID as n}from"../../../../core/uuid.js";import{normalFromMat4 as s}from"../../../../core/libs/gl-matrix-2/math/mat3.js";import{create as a}from"../../../../core/libs/gl-matrix-2/factories/mat3f64.js";import{q as i}from"../../../../chunks/vec32.js";import{ONES as l}from"../../../../core/libs/gl-matrix-2/factories/vec3f64.js";import{projectBoundingSphere as d}from"../../../../geometry/projection/projectBoundingSphere.js";import{isRelativeVertexSpace as c}from"../../../../geometry/support/meshVertexSpaceUtils.js";import{h as u}from"../../../../chunks/sphere.js";import{CachedMeshData as m}from"./CachedMeshData.js";import{convertMeshMaterialToPBRMaterial as h}from"./I3SClientMaterialUtil.js";class f{constructor(e,t,r,o){this._uid=e,this._worker=o,this._id2Meta=new Map,this._oid2Meta=new Map,this._indexSR=t.indexSR,this._vertexSR=t.vertexSR,this._renderSR=t.renderSR,this._memCache=r.newCache(`sl-client-mesh-data-${this._uid}`)}get uid(){return this._uid}get worker(){return this._worker}get indexSR(){return this._indexSR}get renderSR(){return this._renderSR}createMeshNodeInfo(e,t){const r=`mesh${t}`,o=e.extent,n=o.spatialReference,s=this._indexSR,a=y(o,e.origin);d(a,n,a,s);return{type:"mesh",id:r,version:w(e),oid:t,mbs:a,componentNodeIds:[],unloadedMesh:e,nodeIndex:null,loadMeshPromise:null}}addMeshNode(t,r){if(null!=this.getMeshNodeIndex(r.oid))throw new e("scenelayer",`I3SClientNodeLoader: client side mesh for feature oid=${r.oid} already exists`);r.nodeIndex=t,this._id2Meta.set(r.id,r),this._oid2Meta.set(r.oid,r)}getMeshNodeIndex(e){const t=this._oid2Meta.get(e);return null==t||"mesh"!==t.type?null:t.nodeIndex}getMeshNodeInfo(e){const t=this._oid2Meta.values();for(const r of t)if("mesh"===r.type&&r.id===e)return r;return null}removeNode(e){const t=this._id2Meta.get(e);null!=t&&(this._id2Meta.delete(e),"mesh"===t.type&&this._oid2Meta.delete(t.oid))}async loadNodeJSON(t){const r=this._id2Meta.get(t);if(null==r)throw new e("scenelayer",`I3SClientNodeLoader::loadNodeJSON unable to find node ${t}`);switch(r.type){case"mesh":return this._loadMeshNodeJSON(r);case"mesh-component":return p(r);default:throw new e("scenelayer",`I3SClientNodeLoader::loadNodeJSON unable to handle node ${t}`)}}async _loadMeshNodeJSON(e){const t=e.id,r=(await this._getMeshData(e)).loadedMesh;if(null==r.components||0===r.components.length)return{id:t,version:null,mbs:e.mbs,obb:null,sharedResource:null,geometryData:null,attributeData:null,featureData:null,children:null};const o=[],n=r.components;for(let s=0;s<n.length;++s){const r=`${t}-component${s}`,n={type:"mesh-component",id:r,mbs:e.mbs,componentIndex:s,meshNodeInfo:e,textureData:new Map};this._id2Meta.set(n.id,n),e.componentNodeIds.push(r),o.push({id:n.id,href:null,mbs:n.mbs,obb:null})}return{id:t,version:null,mbs:e.mbs,obb:null,sharedResource:null,geometryData:null,attributeData:null,featureData:null,children:o}}updateNodeIndex(e,t,r){const o=this._id2Meta.get(e);o&&"mesh"===o.type&&(o.nodeIndex=r)}async loadNodeData(r,n){const s=this._id2Meta.get(r);if(null==s||"mesh-component"!==s.type)throw new e("scenelayer",`Failed to load client node data for node ${r} (unexpected node info)`);const a=s.meshNodeInfo,i=await this._getMeshData(a),l=i.loadedMesh,d=a.oid;if(null==l.components)throw new e("scenelayer",`Failed to load client node data for node ${r} (unexpected null reference)`);const c=l.components[s.componentIndex],{material:u,requiredTextures:m,textureData:f}=await h(c.material);if(null!=f)for(const e of f)null!=e&&s.textureData.set(e.id,e);const p={params:{material:u},type:"ArrayBufferView"},{vertexSpace:y,origin:M,transform:w}=l,S=[M.x,M.y,M.z??0];i.projectionPromise||(t(this._worker,"SceneLayerWorker is needed to project mesh"),i.projectionPromise=this._worker.project({positions:l.vertexAttributes.position,localMatrix:w?.localMatrix,vertexSpace:y.toJSON(),origin:S,inSpatialReference:l.spatialReference.toJSON(),outSpatialReference:this._vertexSR.toJSON()},n));const{projected:b,original:_,projectedOrigin:N}=await i.projectionPromise;l.vertexAttributes.position=_;const{transformed:v,original:D}=await x(c,i,this._worker,n);l.vertexAttributes.normal=D,o(n);const{geometryBuffer:R,geometryDescriptor:j}=g(b,c.faces,v,l.vertexAttributes.uv,l.vertexAttributes.color,d);return{geometryData:{featureDataPosition:N,featureIds:[],geometries:[p]},attributeDataInfo:{attributeData:{},loadedAttributes:[]},geometryBuffer:R,geometryDescriptor:j,requiredTextures:m,textureData:f,normalReferenceFrame:this._vertexSR.isGeographic?"east-north-up":"vertex-reference-frame"}}async loadAttributes(e,t,r){const o=e.numFeatures,n={};for(const{field:{name:s}}of t)n[s]=new Array(o);return n}async loadTextures(e,t,r){const o=e.id,n=this._id2Meta.get(o);if(null==n||"mesh-component"!==n.type)throw new Error(`Failed to load textures for node ${e.id} (unexpected node info)`);const s=[];for(const a of t)s.push(n.textureData.get(a.id)||null);return s}async _getMeshData(e){const t=e.version,o=this._memCache.get(t);if(null==o){if(null!=e.loadMeshPromise)return e.loadMeshPromise;const o=async(o,n)=>{const s=e.unloadedMesh.clone();try{await s.load()}catch(i){n(i)}const a=new m(s);this._memCache.put(t,a,r),e.loadMeshPromise=null,o(a)};return e.loadMeshPromise=new Promise(((e,t)=>o(e,t))),e.loadMeshPromise}return o}}async function p(e){return{id:e.id,version:e.meshNodeInfo.version,mbs:e.mbs,obb:null,sharedResource:null,geometryData:null,attributeData:null,featureData:null,children:null,isEmpty:!1}}function y(e,t){const{spatialReference:r}=e,o=[1,-1],n=[.5*e.width,.5*e.height,e.hasZ?.5*(e.zmax-e.zmin):0],s=r.isGeographic?r.metersPerUnit:1,a=e.center;let i=0;if(e.hasZ)for(let l=0;l<2;++l)for(let e=0;e<2;++e)for(let r=0;r<2;++r){const d=(a.x+o[l]*n[0]-t.x)*s,c=(a.y+o[e]*n[1]-t.y)*s,u=a.z+o[r]*n[2]-t.z;i=Math.max(d*d+c*c+u*u,i)}else for(let l=0;l<2;++l)for(let e=0;e<2;++e){const r=(a.x+o[l]*n[0]-t.x)*s,d=(a.y+o[e]*n[1]-t.y)*s;i=Math.max(r*r+d*d,i)}return u([t.x,t.y,t.z],Math.sqrt(i))}async function x(e,r,o,n){const{transform:d,vertexAttributes:c}=r.loadedMesh,u="source"===e.shading?c.normal:null;if(!(null!=u&&null!=d&&(0!==d.rotationAngle||!i(d.scale,l))))return{transformed:u,original:c.normal};if(!r.normalsTransformPromise){t(o,"SceneLayerWorker is needed to transform mesh normals");const e=a();s(e,d.localMatrix),r.normalsTransformPromise=o.transformNormals({normalMatrix:e,normals:u},n)}return r.normalsTransformPromise}function g(e,t,r,o,n,s){const a=1,i=(t?.length??0)/3,l=3*i;let d=0,c=0,u=!1,m=0,h=!1,f=0,p=!1,y=0,x=0,g=0;d+=S,d+=S,c=d,d+=3*l*b,null!=r&&(u=!0,m=d,d+=3*l*b),null!=o&&(h=!0,f=d,d+=2*l*b),null!=n&&(p=!0,y=d,d+=4*l*_),x=d,d+=a*N,g=d,d+=2*a*S;const w=new ArrayBuffer(d),v=new Uint8Array(w);M(v,0,l),M(v,S,a);const D=new Float32Array(w,c),R=null!=r?new Float32Array(w,m):null,j=null!=o?new Float32Array(w,f):null,I=null!=n?new Uint8Array(w,y):null;for(let M=0;M<i;++M){const s=3*M;for(let a=0;a<3;++a){const i=t[s+a],l=3*i,d=9*M+3*a;if(D[d]=e[l],D[d+1]=e[l+1],D[d+2]=e[l+2],R&&(R[d]=r[l],R[d+1]=r[l+1],R[d+2]=r[l+2]),j){const e=2*i,t=6*M+2*a;j[t]=o[e],j[t+1]=o[e+1]}if(I){const e=4*i,t=12*M+4*a;I[t]=n[e],I[t+1]=n[e+1],I[t+2]=n[e+2],I[t+3]=n[e+3]}}}M(v,x,s),M(v,x+S,s/2**32),M(v,g,0),M(v,g+S,i-1);return{geometryBuffer:w,geometryDescriptor:{isDraco:!1,isLegacy:!0,color:p,normal:u,uv0:h,uvRegion:!1,featureIndex:!0}}}function M(e,t,r){e[t]=255&r,e[t+1]=255&r>>8,e[t+2]=255&r>>16,e[t+3]=255&r>>24}function w(e){const t=e.metadata.displaySource?.source;if(null==t||!Array.isArray(t)||!t.length||t[0]instanceof File)return n();const r=t;let o="";for(const n of r)o+=n.makeHash();return o+JSON.stringify(e.transform?.toJSON()??"")+(c(e.vertexSpace)?JSON.stringify(e.vertexSpace.origin):"")+JSON.stringify(e.spatialReference)}const S=4,b=4,_=1,N=8;export{f as I3SClientNodeLoader,y as createSphereFromExtent,b as sizeOfFloat32,S as sizeOfInt32,N as sizeOfUInt64,_ as sizeOfUInt8,x as transformNormals};