UNPKG

@arcgis/core

Version:

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

3 lines (2 loc) 8.19 kB
/* COPYRIGHT Esri - https://js.arcgis.com/5.0.19/LICENSE.txt */ import e from"../../../../core/PooledArray.js";import{multiply as t}from"../../../../core/libs/gl-matrix-2/math/mat4.js";import{create as r}from"../../../../core/libs/gl-matrix-2/factories/mat4f64.js";import{transformMat4 as n}from"../../../../core/libs/gl-matrix-2/math/vec3.js";import{lerp as i}from"../../../../core/libs/gl-matrix-2/math/vec4.js";import{create as a}from"../../../../core/libs/gl-matrix-2/factories/vec4f64.js";import{intersectsSphere as s}from"../../../../geometry/support/frustum.js";import{Sphere as o}from"../../../../geometry/support/sphere.js";import{maxScale as f}from"../../support/mathUtils.js";import{DepthRange as h}from"./DepthRange.js";import{assert as c}from"./Util.js";const u=1e4,l=100,d=500,m=500,_=.1;function g(e,t,r,n){let i=0;if(!t.some(e=>!!e.material&&(i+=e.numGeometries,i>=u)))return F.compute(e,t,n);const a=new h;return r.forEach(t=>a.union(p(e,t))),a}function p(e,t){if(!t.visible)return;const r=new h,n=t.getSpatialQueryAccelerator();return n?b(r,e,n):w(r,e,t.objects),r}function b(e,t,r){const{eye:n,viewForward:i,frustum:a}=t,s=e=>e.visible,o=r.objectCount;if(o<d)E.set(t.near,Math.min(e.near,t.far)),r.forEachInDepthRange(n,i,1,E,(r,n)=>{M(e,t,r),E.far=e.near,n.setRange(E)},a,s),E.set(Math.max(e.far,t.near),t.far),r.forEachInDepthRange(n,i,-1,E,(r,n)=>{M(e,t,r),E.near=e.far,n.setRange(E)},a,s);else{const n=Math.max(Math.min(o,m),Math.ceil(o*_)),f=r.findClosest(i,1,a,s,n),h=r.findClosest(i,-1,a,s,n);f&&h&&(x(e,t,f.boundingVolumeWorldSpace.bounds),x(e,t,h.boundingVolumeWorldSpace.bounds))}}function w(e,t,r){S.clear(),r.forEach(e=>{e.visible&&0!==e.geometries.length&&S.add(e,t)}),S.empty||(S.sort(),E.set(t.near,Math.min(e.near,t.far)),S.forEachInDepthRange(E,1,(r,n)=>{n<e.near&&M(e,t,r)}),E.set(Math.max(e.far,t.near),t.far),S.forEachInDepthRange(E,-1,(t,r,n)=>{e.far=Math.max(e.far,n)}))}function M(e,r,n){if(!n.visible)return;if(!s(r.frustum,n.boundingVolumeWorldSpace.bounds))return;const i=n.transformation,a=D;n.geometries.forEach(n=>{t(a,i,n.transformation);const s=f(a);j(e,r,n.boundingInfo,a,s)})}function j(e,t,r,i,a){if(null==r)return;n(A.center,r.center,i);const{eye:o,viewForward:f}=t,h=f[0]*(A.center[0]-o[0])+f[1]*(A.center[1]-o[1])+f[2]*(A.center[2]-o[2]);if(A.radius=r.radius*a,!(h-A.radius>e.near&&h+A.radius<e.far)&&s(t.frustum,A))if(r.radius>l&&r.getChildren())for(const n of r.getChildren())j(e,t,n,i,a);else W.unionDepthRangeWithAABB(e,t.viewProjectionMatrix,i,r.bbMin,r.bbMax)}function x(e,t,r){const n=t.eye,i=t.viewForward,a=(r.center[0]-n[0])*i[0]+(r.center[1]-n[1])*i[1]+(r.center[2]-n[2])*i[2];e.near=Math.min(e.near,a-r.radius),e.far=Math.max(e.far,a+r.radius)}class R{constructor(){this._items=new e({allocator:e=>e||{object:null,distance:0,near:0,far:0},deallocator:e=>(e.object=null,e.distance=0,e.near=0,e.far=0,e)})}get length(){return this._items.length}get empty(){return 0===this._items.length}clear(){this._items.clear()}add(e,t){const r=t.eye,n=t.viewForward,i=e.boundingVolumeWorldSpace.bounds,a=(i.center[0]-r[0])*n[0]+(i.center[1]-r[1])*n[1]+(i.center[2]-r[2])*n[2];if(!Number.isFinite(a))return;const s=this._items.pushNew();s.object=e,s.distance=a,s.near=a-i.radius,s.far=a+i.radius}sort(){this._items.sort((e,t)=>e.distance-t.distance)}forEachInDepthRange(e,t,r){if(1===t)for(let n=0;n<this._items.length;++n){const t=this._items.data[n];t.far<e.near||t.near>e.far||r(t.object,t.near,t.far)}else for(let n=this._items.length-1;n>=0;--n){const t=this._items.data[n];t.far<e.near||t.near>e.far||r(t.object,t.near,t.far)}}}class v{constructor(){this._geometries=new Array,this._near=[],this._far=[],this._nearCandidates=[],this._farCandidates=[],this._looseRange=new h(0,0)}compute(e,t,r){this._reset();const{viewMatrix:n}=e;t.forEach(e=>{e.forEachGeometry(e=>{if(!e.visible||0===r&&!e.castShadow)return;const t=e.boundingSphere,i=n[2]*t.center[0]+n[6]*t.center[1]+n[10]*t.center[2]+n[14],a=i-t.radius,s=i+t.radius;this._geometries.push(e),this._near.push(-s),this._far.push(-a)})});const i=new h;if(0===this._geometries.length)return i;for(let f=0;f<this._geometries.length;++f)this._near[f]>i.far&&(i.far=this._near[f]),this._near[f]>2&&this._far[f]<i.near&&(i.near=this._far[f]);const a=this._looseRange;a.near=Math.max(.5*i.near,2),a.far=2*i.far;let s=0,o=0;for(let f=0;f<this._geometries.length;++f)this._near[f]<i.near&&(this._near[f]>=a.near?i.near=this._near[f]:this._nearCandidates[s++]=f),this._far[f]>i.far&&(this._far[f]<=a.far?i.far=this._far[f]:this._farCandidates[o++]=f);if(0===this._nearCandidates.length&&0===this._farCandidates.length)return i;this._nearCandidates.sort((e,t)=>this._near[e]<this._near[t]?-1:this._near[e]>this._near[t]?1:0),this._farCandidates.sort((e,t)=>this._far[e]<this._far[t]?1:this._far[e]>this._far[t]?-1:0);for(let f=0;f<this._nearCandidates.length;++f){const t=this._nearCandidates[f];if(this._near[t]<i.near){const r=this._geometries[t],{boundingInfo:n,shaderTransformation:a}=r;this._includeNearBoundingInfoRec(e,n,a,i)}}for(let f=0;f<this._farCandidates.length;++f){const t=this._farCandidates[f];if(this._far[t]>i.far){const r=this._geometries[t],{boundingInfo:n,shaderTransformation:a}=r;this._includeFarBoundingInfoRec(e,n,a,i)}}return this._reset(),i}_reset(){this._geometries.length=0,this._near.length=0,this._far.length=0,this._nearCandidates.length=0,this._farCandidates.length=0}_isOutsideSidePlanes(e,t){const{center:r,radius:n}=e;return t[0][0]*r[0]+t[0][1]*r[1]+t[0][2]*r[2]+t[0][3]>n||t[1][0]*r[0]+t[1][1]*r[1]+t[1][2]*r[2]+t[1][3]>n||t[2][0]*r[0]+t[2][1]*r[1]+t[2][2]*r[2]+t[2][3]>n||t[3][0]*r[0]+t[3][1]*r[1]+t[3][2]*r[2]+t[3][3]>n}_includeNearBoundingInfoRec(e,t,r,i){if(null==t)return;const a=t.center;n(A.center,a,r),A.radius=t.radius*f(r);const{frustum:s}=e;if(this._isOutsideSidePlanes(A,s))return;const o=A.center[0],h=A.center[1],c=A.center[2],u=A.radius,{viewMatrix:d}=e,m=d[2]*o+d[6]*h+d[10]*c+d[14],_=m+u;if(!(-(m-u)<2||-_>=i.near))if(-_>this._looseRange.near)i.near=-_;else{if(u>l){const n=t.getChildren();if(void 0!==n){for(const t of n)this._includeNearBoundingInfoRec(e,t,r,i);return}}W.unionDepthRangeWithAABB(i,e.viewProjectionMatrix,r,t.bbMin,t.bbMax)}}_includeFarBoundingInfoRec(e,t,r,i){if(null==t)return;const a=t.center;n(A.center,a,r),A.radius=t.radius*f(r);const{frustum:s}=e;if(this._isOutsideSidePlanes(A,s))return;const[o,h,c]=A.center,{viewMatrix:u,viewProjectionMatrix:d}=e,m=u[2]*o+u[6]*h+u[10]*c+u[14]-A.radius;if(!(-m<=i.far))if(-m<this._looseRange.far)i.far=-m;else{if(A.radius>l){const n=t.getChildren();if(void 0!==n){for(const t of n)this._includeFarBoundingInfoRec(e,t,r,i);return}}W.unionDepthRangeWithAABB(i,d,r,t.bbMin,t.bbMax)}}}class C{constructor(){this._modelViewProj=r(),this._clipPosition=[a(),a(),a(),a(),a(),a(),a(),a()]}unionDepthRangeWithAABB(e,r,n,i,a){const s=this._modelViewProj;t(s,r,n);let o=!1;for(let t=0;t<8;++t){const e=this._clipPosition[t],r=0===t||3===t||4===t||7===t?i[0]:a[0],n=0===t||1===t||4===t||5===t?i[1]:a[1],o=t<4?i[2]:a[2];e[0]=s[0]*r+s[4]*n+s[8]*o+s[12],e[1]=s[1]*r+s[5]*n+s[9]*o+s[13],e[2]=s[2]*r+s[6]*n+s[10]*o+s[14],e[3]=s[3]*r+s[7]*n+s[11]*o+s[15]}for(let t=0;t<12;++t){const r=B(this._clipPosition[y[t][0]],this._clipPosition[y[t][1]],this._clipPosition[y[t][2]]);let n=!0;for(let e=0;e<r.length;++e){if(r[e][3]>=2){n=!1;break}}if(!n){o=!0;for(let t=0;t<r.length;++t){const n=r[t][3];Number.isFinite(n)&&(e.near=Math.min(n,e.near),e.far=Math.max(n,e.far))}}}return o}}function B(e,t,r){let n=[e,t,r];for(let i=0;i<4;++i){const e=n;n=[];for(let t=0;t<e.length;++t){const r=e[t],a=e[(t+1)%e.length];I(a,i)?(I(r,i)||n.push(P(r,a,i)),n.push(a)):I(r,i)&&n.push(P(r,a,i))}}return n}function I(e,t){return 0===t?e[0]>=-e[3]:1===t?e[1]>=-e[3]:2===t?e[0]<=e[3]:3===t?e[1]<=e[3]:void c(!1)}function P(e,t,r){let n=0;return 0===r?n=(-e[3]-e[0])/(t[0]-e[0]+t[3]-e[3]):1===r?n=(-e[3]-e[1])/(t[1]-e[1]+t[3]-e[3]):2===r?n=(e[3]-e[0])/(t[0]-e[0]-t[3]+e[3]):3===r&&(n=(e[3]-e[1])/(t[1]-e[1]-t[3]+e[3])),i(a(),e,t,n)}const y=[[0,1,3],[2,3,1],[1,5,2],[6,2,5],[5,4,6],[7,6,4],[4,0,7],[3,7,0],[3,2,7],[6,7,2],[4,5,0],[1,0,5]],A=new o,D=r(),E=new h,S=new R,F=new v,W=new C;export{g as depthRangeFromScene};