UNPKG

@three.ez/batched-mesh-extensions

Version:
3 lines (2 loc) 11.2 kB
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const A=require("bvh.js"),u=require("three"),ht=require("three/addons/utils/SortUtils.js");class G{constructor(t,e,o=0,n=!0){this.nodesMap=new Map,this._origin=new Float32Array(3),this._dir=new Float32Array(3),this._cameraPos=new Float32Array(3),this._boxArray=new Float32Array(6),this.target=t,this.accurateCulling=n,this._margin=o,this.bvh=new A.BVH(new A.HybridBuilder,e===2e3?A.WebGLCoordinateSystem:A.WebGPUCoordinateSystem)}create(){const t=this.target.instanceCount,e=this.target._instanceInfo.length,o=this.target._instanceInfo,n=new Array(t),r=new Uint32Array(t);let i=0;this.clear();for(let c=0;c<e;c++)o[c].active&&(n[i]=this.getBox(c,new Float32Array(6)),r[i]=c,i++);this.bvh.createFromArray(r,n,c=>{this.nodesMap.set(c.object,c)},this._margin)}insert(t){const e=this.bvh.insert(t,this.getBox(t,new Float32Array(6)),this._margin);this.nodesMap.set(t,e)}insertRange(t){const e=t.length,o=new Array(e);for(let n=0;n<e;n++)o[n]=this.getBox(t[n],new Float32Array(6));this.bvh.insertRange(t,o,this._margin,n=>{this.nodesMap.set(n.object,n)})}move(t){const e=this.nodesMap.get(t);e&&(this.getBox(t,e.box),this.bvh.move(e,this._margin))}delete(t){const e=this.nodesMap.get(t);e&&(this.bvh.delete(e),this.nodesMap.delete(t))}clear(){this.bvh.clear(),this.nodesMap.clear()}frustumCulling(t,e){this._margin>0&&this.accurateCulling?this.bvh.frustumCulling(t.elements,(o,n,r)=>{n.isIntersectedMargin(o.box,r,this._margin)&&e(o)}):this.bvh.frustumCulling(t.elements,e)}raycast(t,e){const o=t.ray,n=this._origin,r=this._dir;A.vec3ToArray(o.origin,n),A.vec3ToArray(o.direction,r),this.bvh.rayIntersections(r,n,e,t.near,t.far)}intersectBox(t,e){const o=this._boxArray;return A.box3ToArray(t,o),this.bvh.intersectsBox(o,e)}getBox(t,e){const o=this.target,n=o._instanceInfo[t].geometryIndex;return o.getBoundingBoxAt(n,z).applyMatrix4(o.getMatrixAt(t,lt)),A.box3ToArray(z,e),e}}const z=new u.Box3,lt=new u.Matrix4;class U{constructor(){this.array=[],this.pool=[]}push(t,e,o,n){const r=this.pool,i=this.array,c=i.length;c>=r.length&&r.push({start:null,count:null,z:null,zSort:null,index:null});const a=r[c];a.index=t,a.start=o,a.count=n,a.z=e,i.push(a)}reset(){this.array.length=0}}function Y(s,t={}){this.bvh=new G(this,s,t.margin,t.accurateCulling),this.bvh.create()}function dt(s){const t={get:e=>e.zSort,aux:new Array(s.maxInstanceCount),reversed:null};return function(o){t.reversed=s.material.transparent,s.maxInstanceCount>t.aux.length&&(t.aux.length=s.maxInstanceCount);let n=1/0,r=-1/0;for(const{z:a}of o)a>r&&(r=a),a<n&&(n=a);const i=r-n,c=(2**32-1)/i;for(const a of o)a.zSort=(a.z-n)*c;ht.radixSort(o,t)}}function k(s,t){return s.z-t.z}function N(s,t){return t.z-s.z}const V=new u.Frustum,M=new U,R=new u.Matrix4,T=new u.Matrix4,O=new u.Vector3,E=new u.Vector3,j=new u.Vector3,mt=new u.Vector3,D=new u.Sphere;function Z(s,t,e,o,n,r){this.frustumCulling(e)}function X(s,t=s){if(!this._visibilityChanged&&!this.perObjectFrustumCulled&&!this.sortObjects)return;this._indirectTexture.needsUpdate=!0,this._visibilityChanged=!1;const e=this.sortObjects,o=this.perObjectFrustumCulled;if(!o&&!e){this.updateIndexArray();return}if(T.copy(this.matrixWorld).invert(),E.setFromMatrixPosition(s.matrixWorld).applyMatrix4(T),j.setFromMatrixPosition(t.matrixWorld).applyMatrix4(T),O.set(0,0,-1).transformDirection(s.matrixWorld).transformDirection(T),o?(R.multiplyMatrices(s.projectionMatrix,s.matrixWorldInverse).multiply(this.matrixWorld),this.bvh?this.BVHCulling(s,t):this.linearCulling(s,t)):this.updateRenderList(),e){const n=this.geometry.getIndex(),r=n===null?1:n.array.BYTES_PER_ELEMENT,i=this._multiDrawStarts,c=this._multiDrawCounts,a=this._indirectTexture.image.data,g=this.customSort;g===null?M.array.sort(this.material.transparent?N:k):g(M.array);const l=M.array,d=l.length;for(let h=0;h<d;h++){const m=l[h];i[h]=m.start*r,c[h]=m.count,a[h]=m.index}M.reset()}}function $(){if(!this._visibilityChanged)return;const s=this.geometry.getIndex(),t=s===null?1:s.array.BYTES_PER_ELEMENT,e=this._instanceInfo,o=this._geometryInfo,n=this._multiDrawStarts,r=this._multiDrawCounts,i=this._indirectTexture.image.data;let c=0;for(let a=0,g=e.length;a<g;a++){const l=e[a];if(l.visible&&l.active){const d=l.geometryIndex,h=o[d];n[c]=h.start*t,r[c]=h.count,i[c]=a,c++}}this._multiDrawCount=c}function J(){const s=this._instanceInfo,t=this._geometryInfo;for(let e=0,o=s.length;e<o;e++){const n=s[e];if(n.visible&&n.active){const r=n.geometryIndex,i=t[r],c=this.getPositionAt(e).sub(E).dot(O);M.push(e,c,i.start,i.count)}}this._multiDrawCount=M.array.length}function K(s,t){const e=this.geometry.getIndex(),o=e===null?1:e.array.BYTES_PER_ELEMENT,n=this._instanceInfo,r=this._geometryInfo,i=this.sortObjects,c=this._multiDrawStarts,a=this._multiDrawCounts,g=this._indirectTexture.image.data,l=this.onFrustumEnter;let d=0;this.bvh.frustumCulling(R,h=>{const m=h.object,f=n[m];if(!f.visible)return;const B=f.geometryIndex,y=r[B],x=y.LOD;let p,_;if(x){const S=this.getPositionAt(m).distanceToSquared(j),w=this.getLODIndex(x,S);if(l&&!l(m,s,t,w))return;p=x[w].start,_=x[w].count}else{if(l&&!l(m,s))return;p=y.start,_=y.count}if(i){const S=this.getPositionAt(m).sub(E).dot(O);M.push(m,S,p,_)}else c[d]=p*o,a[d]=_,g[d]=m,d++}),this._multiDrawCount=i?M.array.length:d}function Q(s,t){const e=this.geometry.getIndex(),o=e===null?1:e.array.BYTES_PER_ELEMENT,n=this._instanceInfo,r=this._geometryInfo,i=this.sortObjects,c=this._multiDrawStarts,a=this._multiDrawCounts,g=this._indirectTexture.image.data,l=this.onFrustumEnter;let d=0;V.setFromProjectionMatrix(R);for(let h=0,m=n.length;h<m;h++){const f=n[h];if(!f.visible||!f.active)continue;const B=f.geometryIndex,y=r[B],x=y.LOD;let p,_;const S=y.boundingSphere,w=S.radius,C=S.center;if(C.x===0&&C.y===0&&C.z===0){const b=this.getPositionAndMaxScaleOnAxisAt(h,D.center);D.radius=w*b}else this.applyMatrixAtToSphere(h,D,C,w);if(V.intersectsSphere(D)){if(x){const b=D.center.distanceToSquared(j),v=this.getLODIndex(x,b);if(l&&!l(h,s,t,v))continue;p=x[v].start,_=x[v].count}else{if(l&&!l(h,s))continue;p=y.start,_=y.count}if(i){const b=mt.subVectors(D.center,E).dot(O);M.push(h,b,p,_)}else c[d]=p*o,a[d]=_,g[d]=h,d++}}this._multiDrawCount=i?M.array.length:d}const gt=new u.Vector3;function tt(s,t=gt){const e=s*16,o=this._matricesTexture.image.data;return t.x=o[e+12],t.y=o[e+13],t.z=o[e+14],t}function et(s,t){const e=s*16,o=this._matricesTexture.image.data,n=o[e+0],r=o[e+1],i=o[e+2],c=n*n+r*r+i*i,a=o[e+4],g=o[e+5],l=o[e+6],d=a*a+g*g+l*l,h=o[e+8],m=o[e+9],f=o[e+10],B=h*h+m*m+f*f;return t.x=o[e+12],t.y=o[e+13],t.z=o[e+14],Math.sqrt(Math.max(c,d,B))}function nt(s,t,e,o){const n=s*16,r=this._matricesTexture.image.data,i=r[n+0],c=r[n+1],a=r[n+2],g=r[n+3],l=r[n+4],d=r[n+5],h=r[n+6],m=r[n+7],f=r[n+8],B=r[n+9],y=r[n+10],x=r[n+11],p=r[n+12],_=r[n+13],S=r[n+14],w=r[n+15],C=t.center,L=e.x,b=e.y,v=e.z,P=1/(g*L+m*b+x*v+w);C.x=(i*L+l*b+f*v+p)*P,C.y=(c*L+d*b+B*v+_)*P,C.z=(a*L+h*b+y*v+S)*P;const ct=i*i+c*c+a*a,at=l*l+d*d+h*h,ut=f*f+B*B+y*y;t.radius=o*Math.sqrt(Math.max(ct,at,ut))}function ot(s,t,e,o=0){const n=this._geometryInfo[s],r=t.isBufferGeometry?t.index.array:t;e=e**2,n.LOD??(n.LOD=[{start:n.start,count:n.count,distance:0,hysteresis:0}]);const i=n.LOD,c=i[i.length-1],a=c.start+c.count,g=r.length;if(a-n.start+g>n.reservedIndexCount)throw new Error("BatchedMesh LOD: Reserved space request exceeds the maximum buffer size.");i.push({start:a,count:g,distance:e,hysteresis:o});const l=this.geometry.getIndex(),d=l.array,h=n.vertexStart;for(let m=0;m<g;m++)d[a+m]=r[m]+h;l.needsUpdate=!0}function st(s,t){for(let e=s.length-1;e>0;e--){const o=s[e],n=o.distance-o.distance*o.hysteresis;if(t>=n)return e}return 0}const F=[],I=new u.Mesh,ft=new u.Ray,q=new u.Vector3,W=new u.Vector3,H=new u.Matrix4;function rt(s,t){var i,c;if(!this.material||this.instanceCount===0)return;I.geometry=this.geometry,I.material=this.material,(i=I.geometry).boundingBox??(i.boundingBox=new u.Box3),(c=I.geometry).boundingSphere??(c.boundingSphere=new u.Sphere);const e=s.ray,o=s.near,n=s.far;H.copy(this.matrixWorld).invert(),W.setFromMatrixScale(this.matrixWorld),q.copy(s.ray.direction).multiply(W);const r=q.length();if(s.ray=ft.copy(s.ray).applyMatrix4(H),s.near/=r,s.far/=r,this.bvh)this.bvh.raycast(s,a=>this.checkInstanceIntersection(s,a,t));else if(this.boundingSphere===null&&this.computeBoundingSphere(),s.ray.intersectsSphere(this.boundingSphere))for(let a=0,g=this._instanceInfo.length;a<g;a++)this.checkInstanceIntersection(s,a,t);s.ray=e,s.near=o,s.far=n}function it(s,t,e){const o=this._instanceInfo[t];if(!o.active||!o.visible)return;const n=o.geometryIndex,r=this._geometryInfo[n];this.getMatrixAt(t,I.matrixWorld),I.geometry.boundsTree=this.boundsTrees?this.boundsTrees[n]:void 0,I.geometry.boundsTree||(this.getBoundingBoxAt(n,I.geometry.boundingBox),this.getBoundingSphereAt(n,I.geometry.boundingSphere),I.geometry.setDrawRange(r.start,r.count)),I.raycast(s,F);for(const i of F)i.batchId=t,i.object=this,e.push(i);F.length=0}function yt(){u.BatchedMesh.prototype.computeBVH=Y,u.BatchedMesh.prototype.onBeforeRender=Z,u.BatchedMesh.prototype.frustumCulling=X,u.BatchedMesh.prototype.updateIndexArray=$,u.BatchedMesh.prototype.updateRenderList=J,u.BatchedMesh.prototype.BVHCulling=K,u.BatchedMesh.prototype.linearCulling=Q,u.BatchedMesh.prototype.getPositionAt=tt,u.BatchedMesh.prototype.getPositionAndMaxScaleOnAxisAt=et,u.BatchedMesh.prototype.applyMatrixAtToSphere=nt,u.BatchedMesh.prototype.addGeometryLOD=ot,u.BatchedMesh.prototype.getLODIndex=st,u.BatchedMesh.prototype.raycast=rt,u.BatchedMesh.prototype.checkInstanceIntersection=it}function xt(){yt()}function pt(s){const t=s.material,e=t.onBeforeCompile.bind(t);t.onBeforeCompile=(o,n)=>{if(s.uniformsTexture){o.uniforms.uniformsTexture={value:s.uniformsTexture};const{vertex:r,fragment:i}=s.uniformsTexture.getUniformsGLSL("uniformsTexture","batchIndex","float");o.vertexShader=o.vertexShader.replace("void main() {",r),o.fragmentShader=o.fragmentShader.replace("void main() {",i),o.vertexShader=o.vertexShader.replace("void main() {","void main() { float batchIndex = getIndirectIndex( gl_DrawID );")}e(o,n)}}function _t(s){let t=0,e=0;for(const o of s)t+=o.attributes.position.count,e+=o.index.count;return{vertexCount:t,indexCount:e}}function It(s){const t=[];let e=0,o=0;for(const n of s){let r=0;for(const i of n){const c=i.index.count;o+=c,r+=c,e+=i.attributes.position.count}t.push(r)}return{vertexCount:e,indexCount:o,LODIndexCount:t}}exports.BVHCulling=K;exports.BatchedMeshBVH=G;exports.MultiDrawRenderList=U;exports.addGeometryLOD=ot;exports.applyMatrixAtToSphere=nt;exports.checkInstanceIntersection=it;exports.computeBVH=Y;exports.createRadixSort=dt;exports.extendBatchedMeshPrototype=xt;exports.frustumCulling=X;exports.getBatchedMeshCount=_t;exports.getBatchedMeshLODCount=It;exports.getLODIndex=st;exports.getPositionAndMaxScaleOnAxisAt=et;exports.getPositionAt=tt;exports.linearCulling=Q;exports.onBeforeRender=Z;exports.patchBatchedMeshMaterial=pt;exports.raycast=rt;exports.sortOpaque=k;exports.sortTransparent=N;exports.updateIndexArray=$;exports.updateRenderList=J; //# sourceMappingURL=webgpu.cjs.map