rayzee 7.21.0 → 7.22.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/rayzee.es.js CHANGED
@@ -586,6 +586,10 @@ var J = {
586
586
  skyTurbidity: .8,
587
587
  skyMieAnisotropy: .76,
588
588
  skyPreset: "clearMorning",
589
+ cameraProjection: "perspective",
590
+ panoramaLonRange: [-180, 180],
591
+ panoramaLatRange: [-90, 90],
592
+ panoramaLevelHorizon: !0,
589
593
  enableDOF: !1,
590
594
  fov: 55,
591
595
  focusDistance: .8,
@@ -1247,7 +1251,9 @@ var di = class {
1247
1251
  area: Fe(new Float32Array(256), "float"),
1248
1252
  point: Fe(new Float32Array(144), "float"),
1249
1253
  spot: Fe(new Float32Array(320), "float")
1250
- }, n("cameraWorldMatrix", new Ct(), "mat4"), n("cameraProjectionMatrixInverse", new Ct(), "mat4"), n("cameraViewMatrix", new Ct(), "mat4"), n("cameraProjectionMatrix", new Ct(), "mat4"), r("enableDOF", J.enableDOF), n("focusDistance", J.focusDistance, "float"), n("focalLength", J.focalLength, "float"), n("aperture", J.aperture, "float"), n("apertureScale", 1, "float"), n("anamorphicRatio", J.anamorphicRatio ?? 1, "float"), n("sceneScale", 1, "float"), this._uniforms.set("samplingTechnique", Fn), Fn.value = J.samplingTechnique, n("fireflyThreshold", J.fireflyThreshold, "float"), r("enableEmissiveTriangleSampling", J.enableEmissiveTriangleSampling), n("emissiveBoost", J.emissiveBoost, "float"), n("emissiveTriangleCount", 0, "int"), n("emissiveTotalPower", 0, "float"), n("lightBVHNodeCount", 0, "int"), n("emissiveVec4Offset", 0, "int"), n("reverseMapVec4Offset", 0, "int"), n("renderMode", J.renderMode, "int"), r("enableAlphaShadows", J.enableAlphaShadows), n("resolution", new sn(e, t), "vec2");
1254
+ }, n("cameraWorldMatrix", new Ct(), "mat4"), n("cameraProjectionMatrixInverse", new Ct(), "mat4"), n("cameraViewMatrix", new Ct(), "mat4"), n("cameraProjectionMatrix", new Ct(), "mat4");
1255
+ let i = ([e, t]) => new sn(e, t).multiplyScalar(xt.DEG2RAD);
1256
+ n("cameraProjection", +(J.cameraProjection === "equirectangular"), "int"), n("panoLonRange", i(J.panoramaLonRange), "vec2"), n("panoLatRange", i(J.panoramaLatRange), "vec2"), r("panoLevelHorizon", J.panoramaLevelHorizon), r("enableDOF", J.enableDOF), n("focusDistance", J.focusDistance, "float"), n("focalLength", J.focalLength, "float"), n("aperture", J.aperture, "float"), n("apertureScale", 1, "float"), n("anamorphicRatio", J.anamorphicRatio ?? 1, "float"), n("sceneScale", 1, "float"), this._uniforms.set("samplingTechnique", Fn), Fn.value = J.samplingTechnique, n("fireflyThreshold", J.fireflyThreshold, "float"), r("enableEmissiveTriangleSampling", J.enableEmissiveTriangleSampling), n("emissiveBoost", J.emissiveBoost, "float"), n("emissiveTriangleCount", 0, "int"), n("emissiveTotalPower", 0, "float"), n("lightBVHNodeCount", 0, "int"), n("emissiveVec4Offset", 0, "int"), n("reverseMapVec4Offset", 0, "int"), n("renderMode", J.renderMode, "int"), r("enableAlphaShadows", J.enableAlphaShadows), n("resolution", new sn(e, t), "vec2");
1251
1257
  }
1252
1258
  _nameAll() {
1253
1259
  for (let [e, t] of this._uniforms) t.name = fi[e] || e;
@@ -1892,7 +1898,7 @@ var Xi = class {
1892
1898
  0,
1893
1899
  0,
1894
1900
  1
1895
- ]), 1, 1, Bt, ft), this._envPlaceholder.needsUpdate = !0, this.environmentTexture = this._envPlaceholder, this.envTexSize = new sn(), this.envCDFTexture = null, this._initCDFTexture(), this.environmentRotationMatrix = new Ct(), this.cdfBuildTime = 0, this.envParams = {
1901
+ ]), 1, 1, Bt, ft, void 0, void 0, void 0, K, K), this._envPlaceholder.needsUpdate = !0, this.environmentTexture = this._envPlaceholder, this.envTexSize = new sn(), this.envCDFTexture = null, this._initCDFTexture(), this.environmentRotationMatrix = new Ct(), this.cdfBuildTime = 0, this.envParams = {
1896
1902
  mode: "hdri",
1897
1903
  gradientZenithColor: new tt(J.gradientZenithColor),
1898
1904
  gradientHorizonColor: new tt(J.gradientHorizonColor),
@@ -4693,7 +4699,6 @@ var Ws = /* @__PURE__ */ f(([e, t]) => {
4693
4699
  setMinImprovement(e) {
4694
4700
  this.minImprovement = Math.max(.001, e);
4695
4701
  }
4696
- setMaxTreelets() {}
4697
4702
  getStatistics() {
4698
4703
  return { ...this.stats };
4699
4704
  }
@@ -4902,7 +4907,7 @@ var rc = {
4902
4907
  reinsertionOptimizationTime: 0,
4903
4908
  reinsertionsApplied: 0,
4904
4909
  reinsertionIterations: 0
4905
- }, this.enableTreeletOptimization = !0, this.treeletSize = 5, this.treeletOptimizationPasses = 1, this.treeletMinImprovement = .02, this.maxTreeletDepth = 3, this.maxTreeletsPerScene = 20, this.treeletComplexityThreshold = 5e4, this.enableReinsertionOptimization = !0, this.reinsertionBatchSizeRatio = .02, this.reinsertionMaxIterations = 2, this.initializeBinArrays(), this._partResult = {
4910
+ }, this.enableTreeletOptimization = !1, this.treeletSize = 5, this.treeletOptimizationPasses = 1, this.treeletMinImprovement = .02, this.treeletComplexityThreshold = 5e4, this.enableReinsertionOptimization = !0, this.reinsertionBatchSizeRatio = .02, this.reinsertionMaxIterations = 2, this.initializeBinArrays(), this._partResult = {
4906
4911
  mid: 0,
4907
4912
  lMinX: 0,
4908
4913
  lMinY: 0,
@@ -4935,7 +4940,7 @@ var rc = {
4935
4940
  e.objectMedian !== void 0 && (this.enableObjectMedianFallback = e.objectMedian), e.spatialMedian !== void 0 && (this.enableSpatialMedianFallback = e.spatialMedian);
4936
4941
  }
4937
4942
  setTreeletConfig(e) {
4938
- e.enabled !== void 0 && (this.enableTreeletOptimization = e.enabled), e.size !== void 0 && (this.treeletSize = Math.max(3, Math.min(12, e.size))), e.passes !== void 0 && (this.treeletOptimizationPasses = Math.max(1, Math.min(3, e.passes))), e.minImprovement !== void 0 && (this.treeletMinImprovement = Math.max(.001, e.minImprovement));
4943
+ e.enabled !== void 0 && (this.enableTreeletOptimization = e.enabled), e.size !== void 0 && (this.treeletSize = Math.max(3, Math.min(12, e.size))), e.passes !== void 0 && (this.treeletOptimizationPasses = Math.max(1, Math.min(3, e.passes))), e.minImprovement !== void 0 && (this.treeletMinImprovement = Math.max(.001, e.minImprovement)), e.complexityThreshold !== void 0 && (this.treeletComplexityThreshold = e.complexityThreshold);
4939
4944
  }
4940
4945
  disableTreeletOptimization() {
4941
4946
  this.enableTreeletOptimization = !1;
@@ -5082,26 +5087,26 @@ var rc = {
5082
5087
  this.centroids = new Float32Array(a * 3), this.bMin = new Float32Array(a * 3), this.bMax = new Float32Array(a * 3), this.indices = new Uint32Array(a), this.mortonCodes = new Uint32Array(a), this.initializeTriangleArrays(), this.splitStats.initTime = performance.now() - o, this.sortTrianglesByMortonCode();
5083
5088
  let s = performance.now(), c = this.buildNodeRecursive(0, a, t, n);
5084
5089
  if (this.splitStats.sahBuildTime = performance.now() - s, this.enableTreeletOptimization && this.totalTriangles > 1e3) {
5085
- let e = this.totalTriangles > this.treeletComplexityThreshold, t = e ? 3 : this.treeletSize, r = e ? 10 : this.maxTreeletsPerScene, i = new Zs(this.traversalCost, this.intersectionCost);
5086
- i.setTreeletSize(t), i.setMinImprovement(this.treeletMinImprovement), i.setMaxTreelets(r);
5087
- let a = performance.now();
5090
+ let e = this.totalTriangles > this.treeletComplexityThreshold ? 3 : this.treeletSize, t = new Zs(this.traversalCost, this.intersectionCost);
5091
+ t.setTreeletSize(e), t.setMinImprovement(this.treeletMinImprovement);
5092
+ let r = performance.now();
5088
5093
  for (let e = 0; e < this.treeletOptimizationPasses; e++) {
5089
- let t = n ? (t) => {
5094
+ let i = n ? (t) => {
5090
5095
  n(`Treelet optimization pass ${e + 1}/${this.treeletOptimizationPasses}: ${t}`);
5091
5096
  } : null;
5092
5097
  try {
5093
- i.optimizeBVH(c, t);
5098
+ t.optimizeBVH(c, i);
5094
5099
  } catch (t) {
5095
5100
  ec.error(`treelet optimizer failed in pass ${e + 1}:`, t);
5096
5101
  break;
5097
5102
  }
5098
- let r = i.getStatistics(), o = performance.now() - a;
5099
- if (r.treeletsImproved === 0 && e > 0 || o > 15e3) break;
5103
+ let a = t.getStatistics(), o = performance.now() - r;
5104
+ if (a.treeletsImproved === 0 && e > 0 || o > 15e3) break;
5100
5105
  }
5101
- let o = performance.now() - a;
5102
- this.splitStats.treeletOptimizationTime = o;
5103
- let s = i.getStatistics();
5104
- this.splitStats.treeletsProcessed = s.treeletsProcessed, this.splitStats.treeletsImproved = s.treeletsImproved, this.splitStats.averageSAHImprovement = s.averageSAHImprovement;
5106
+ let i = performance.now() - r;
5107
+ this.splitStats.treeletOptimizationTime = i;
5108
+ let a = t.getStatistics();
5109
+ this.splitStats.treeletsProcessed = a.treeletsProcessed, this.splitStats.treeletsImproved = a.treeletsImproved, this.splitStats.averageSAHImprovement = a.averageSAHImprovement;
5105
5110
  }
5106
5111
  if (this.enableReinsertionOptimization && this.totalTriangles > 1e3) {
5107
5112
  let e = new $s(this.traversalCost, this.intersectionCost);
@@ -5537,7 +5542,7 @@ var rc = {
5537
5542
  }
5538
5543
  }
5539
5544
  }
5540
- }, pc = "var e=class{constructor(e,t){this.traversalCost=e,this.intersectionCost=t,this.maxTreeletLeaves=7,this.minImprovement=.02,this.topologyCache=new Map;for(let e=3;e<=this.maxTreeletLeaves;e++)this.topologyCache.set(e,this.generateTopologies(e));this.stats={treeletsProcessed:0,treeletsImproved:0,totalSAHImprovement:0,averageSAHImprovement:0,optimizationTime:0}}generateTopologies(e){if(e===1)return[0];if(e===2)return[[0,1]];let t=[];for(let n=1;n<e;n++){let r=this.generateTopologies(n),i=this.generateTopologies(e-n);for(let e of r)for(let r of i)t.push([e,this.offsetTopology(r,n)])}return t}offsetTopology(e,t){return typeof e==`number`?e+t:[this.offsetTopology(e[0],t),this.offsetTopology(e[1],t)]}optimizeBVH(e){let t=performance.now();this.stats={treeletsProcessed:0,treeletsImproved:0,totalSAHImprovement:0,averageSAHImprovement:0,optimizationTime:0};let n=this.identifyTreeletRoots(e);for(let e=0;e<n.length;e++){if(performance.now()-t>3e4){console.warn(`TreeletOptimizer: timeout after ${e}/${n.length} treelets`);break}this.optimizeTreelet(n[e])}return this.stats.optimizationTime=performance.now()-t,this.stats.averageSAHImprovement=this.stats.treeletsProcessed>0?this.stats.totalSAHImprovement/this.stats.treeletsProcessed:0,e}identifyTreeletRoots(e){let t=[],n=new Set,r=[{node:e,visited:!1}];for(;r.length>0;){let e=r[r.length-1];if(e.visited){r.pop();let i=e.node;if(i.triangleCount>0||n.has(i))continue;let a=this.countLeaves(i);a>=3&&a<=this.maxTreeletLeaves&&(t.push(i),this.markSubtree(i,n))}else{e.visited=!0;let t=e.node;if(t.triangleCount>0)continue;t.rightChild&&r.push({node:t.rightChild,visited:!1}),t.leftChild&&r.push({node:t.leftChild,visited:!1})}}return t}countLeaves(e){return e?e.triangleCount>0?1:this.countLeaves(e.leftChild)+this.countLeaves(e.rightChild):0}markSubtree(e,t){e&&(t.add(e),!(e.triangleCount>0)&&(this.markSubtree(e.leftChild,t),this.markSubtree(e.rightChild,t)))}optimizeTreelet(e){let t=[];this.extractLeaves(e,t);let n=t.length;if(n<3||n>this.maxTreeletLeaves)return;this.stats.treeletsProcessed++;let r=this.evaluateSubtreeSAH(e),i=this.topologyCache.get(n);if(!i||i.length===0)return;let a=r,o=null,s=null;if(n<=5){let e=this.generatePermutations(n);for(let n of i)for(let r of e){let e=this.evaluateTopology(n,t,r);e<a&&(a=e,o=n,s=r)}}else{let e=Array.from({length:n},(e,t)=>t);for(let n of i){let r=this.evaluateTopology(n,t,e);r<a&&(a=r,o=n,s=e);let i=this.greedySwapOptimize(n,t,e,r);i.cost<a&&(a=i.cost,o=n,s=i.perm)}}let c=(r-a)/r;o&&c>this.minImprovement&&(this.reconstructTreelet(e,o,t,s),this.stats.treeletsImproved++,this.stats.totalSAHImprovement+=c)}extractLeaves(e,t){if(e){if(e.triangleCount>0){t.push({minX:e.minX,minY:e.minY,minZ:e.minZ,maxX:e.maxX,maxY:e.maxY,maxZ:e.maxZ,triangleOffset:e.triangleOffset,triangleCount:e.triangleCount});return}this.extractLeaves(e.leftChild,t),this.extractLeaves(e.rightChild,t)}}evaluateSubtreeSAH(e){if(!e)return 0;if(e.triangleCount>0)return this.surfaceAreaFlat(e.minX,e.minY,e.minZ,e.maxX,e.maxY,e.maxZ)*e.triangleCount*this.intersectionCost;let t=this.evaluateSubtreeSAH(e.leftChild),n=this.evaluateSubtreeSAH(e.rightChild);return this.surfaceAreaFlat(e.minX,e.minY,e.minZ,e.maxX,e.maxY,e.maxZ)*this.traversalCost+t+n}evaluateTopology(e,t,n){return this.evalTopoRecursive(e,t,n).cost}evalTopoRecursive(e,t,n){if(typeof e==`number`){let r=t[n[e]];return{cost:this.surfaceAreaFlat(r.minX,r.minY,r.minZ,r.maxX,r.maxY,r.maxZ)*r.triangleCount*this.intersectionCost,minX:r.minX,minY:r.minY,minZ:r.minZ,maxX:r.maxX,maxY:r.maxY,maxZ:r.maxZ}}let r=this.evalTopoRecursive(e[0],t,n),i=this.evalTopoRecursive(e[1],t,n),a=Math.min(r.minX,i.minX),o=Math.min(r.minY,i.minY),s=Math.min(r.minZ,i.minZ),c=Math.max(r.maxX,i.maxX),l=Math.max(r.maxY,i.maxY),u=Math.max(r.maxZ,i.maxZ);return{cost:this.surfaceAreaFlat(a,o,s,c,l,u)*this.traversalCost+r.cost+i.cost,minX:a,minY:o,minZ:s,maxX:c,maxY:l,maxZ:u}}surfaceAreaFlat(e,t,n,r,i,a){let o=r-e,s=i-t,c=a-n;return 2*(o*s+s*c+c*o)}generatePermutations(e){let t=[],n=Array.from({length:e},(e,t)=>t),r=i=>{if(i===e){t.push([...n]);return}for(let t=i;t<e;t++)[n[i],n[t]]=[n[t],n[i]],r(i+1),[n[i],n[t]]=[n[t],n[i]]};return r(0),t}greedySwapOptimize(e,t,n,r){let i=[...n],a=r,o=!0;for(;o;){o=!1;for(let n=0;n<i.length-1;n++)for(let r=n+1;r<i.length;r++){[i[n],i[r]]=[i[r],i[n]];let s=this.evaluateTopology(e,t,i);s<a?(a=s,o=!0):[i[n],i[r]]=[i[r],i[n]]}}return{perm:i,cost:a}}reconstructTreelet(e,t,n,r){let i=this.buildSubtree(t,n,r);e.minX=i.minX,e.minY=i.minY,e.minZ=i.minZ,e.maxX=i.maxX,e.maxY=i.maxY,e.maxZ=i.maxZ,e.leftChild=i.leftChild,e.rightChild=i.rightChild,e.triangleOffset=i.triangleOffset,e.triangleCount=i.triangleCount}buildSubtree(e,n,r){if(typeof e==`number`){let i=n[r[e]],a=new t;return a.minX=i.minX,a.minY=i.minY,a.minZ=i.minZ,a.maxX=i.maxX,a.maxY=i.maxY,a.maxZ=i.maxZ,a.triangleOffset=i.triangleOffset,a.triangleCount=i.triangleCount,a}let i=this.buildSubtree(e[0],n,r),a=this.buildSubtree(e[1],n,r),o=new t;return o.leftChild=i,o.rightChild=a,o.minX=Math.min(i.minX,a.minX),o.minY=Math.min(i.minY,a.minY),o.minZ=Math.min(i.minZ,a.minZ),o.maxX=Math.max(i.maxX,a.maxX),o.maxY=Math.max(i.maxY,a.maxY),o.maxZ=Math.max(i.maxZ,a.maxZ),o}setTreeletSize(e){this.maxTreeletLeaves=Math.max(3,Math.min(7,e));for(let e=3;e<=this.maxTreeletLeaves;e++)this.topologyCache.has(e)||this.topologyCache.set(e,this.generateTopologies(e))}setMinImprovement(e){this.minImprovement=Math.max(.001,e)}setMaxTreelets(){}getStatistics(){return{...this.stats}}},t=class{constructor(){this.minX=0,this.minY=0,this.minZ=0,this.maxX=0,this.maxY=0,this.maxZ=0,this.leftChild=null,this.rightChild=null,this.triangleOffset=0,this.triangleCount=0}},n=class{constructor(e,t){this.traversalCost=e,this.intersectionCost=t,this.batchSizeRatio=.02,this.maxIterations=2,this.timeBudgetMs=15e3,this.stats={reinsertionsApplied:0,iterations:0,timeMs:0}}setBatchSizeRatio(e){this.batchSizeRatio=Math.max(.005,Math.min(.1,e))}setMaxIterations(e){this.maxIterations=Math.max(1,Math.min(5,e))}getStatistics(){return{...this.stats}}surfaceArea(e){let t=e.maxX-e.minX,n=e.maxY-e.minY,r=e.maxZ-e.minZ;return t*n+n*r+r*t}buildParentMap(e){let t=new Map;t.set(e,{parent:null,isLeft:!1});let n=[e];for(;n.length>0;){let e=n.pop();e.triangleCount>0||(e.leftChild&&(t.set(e.leftChild,{parent:e,isLeft:!0}),n.push(e.leftChild)),e.rightChild&&(t.set(e.rightChild,{parent:e,isLeft:!1}),n.push(e.rightChild)))}return t}findCandidates(e,t,n){let r=[],i=[e];for(;i.length>0;){let a=i.pop();if(a!==e&&n.get(a).parent!==e){let e=this.surfaceArea(a);r.length<t?(r.push({node:a,cost:e}),r.length===t&&this._heapify(r)):e>r[0].cost&&(r[0]={node:a,cost:e},this._siftDown(r,0))}a.triangleCount===0&&(a.leftChild&&i.push(a.leftChild),a.rightChild&&i.push(a.rightChild))}return r}_heapify(e){for(let t=(e.length>>1)-1;t>=0;t--)this._siftDown(e,t)}_siftDown(e,t){let n=e.length;for(;;){let r=t,i=2*t+1,a=2*t+2;if(i<n&&e[i].cost<e[r].cost&&(r=i),a<n&&e[a].cost<e[r].cost&&(r=a),r===t)break;let o=e[t];e[t]=e[r],e[r]=o,t=r}}findReinsertion(e,t,n){let r=n.get(e),i=r.parent;if(!i)return null;let a=r.isLeft?i.rightChild:i.leftChild,o=this.surfaceArea(e),s=this.surfaceArea(i),c=null,l=0,u=s,d=a.minX,f=a.minY,p=a.minZ,m=a.maxX,h=a.maxY,g=a.maxZ,_=a,v=i,y=[];do{for(y.length=0,y.push(u,_);y.length>0;){let t=y.pop(),n=y.pop();if(n-o<=l)continue;let r=Math.min(t.minX,e.minX),i=Math.min(t.minY,e.minY),a=Math.min(t.minZ,e.minZ),s=Math.max(t.maxX,e.maxX),u=Math.max(t.maxY,e.maxY),d=Math.max(t.maxZ,e.maxZ),f=s-r,p=u-i,m=d-a,h=n-(f*p+p*m+m*f);if(h>l&&(c=t,l=h),t.triangleCount===0&&t.leftChild&&t.rightChild){let e=h+this.surfaceArea(t);y.push(e,t.leftChild),y.push(e,t.rightChild)}}let t=n.get(v);if(!t||t.parent===null)break;if(v!==i){d=Math.min(d,_.minX),f=Math.min(f,_.minY),p=Math.min(p,_.minZ),m=Math.max(m,_.maxX),h=Math.max(h,_.maxY),g=Math.max(g,_.maxZ);let e=m-d,t=h-f,n=g-p,r=e*t+t*n+n*e;u+=this.surfaceArea(v)-r}let r=t.parent;_=t.isLeft?r.rightChild:r.leftChild,v=r}while(n.get(v).parent!==null);return c===a||c===i?null:c?{from:e,to:c,areaDiff:l}:null}getConflicts(e,t,n){let r=n.get(e);return[t,e,r.isLeft?r.parent.rightChild:r.parent.leftChild,n.get(t).parent,r.parent]}reinsertNode(e,t,n){let r=n.get(e),i=r.parent,a=r.isLeft?i.rightChild:i.leftChild,o=n.get(i),s=o.parent,c=n.get(t),l=c.parent;o.isLeft?s.leftChild=a:s.rightChild=a,i.leftChild=e,i.rightChild=t,i.triangleOffset=0,i.triangleCount=0,i.minX=Math.min(e.minX,t.minX),i.minY=Math.min(e.minY,t.minY),i.minZ=Math.min(e.minZ,t.minZ),i.maxX=Math.max(e.maxX,t.maxX),i.maxY=Math.max(e.maxY,t.maxY),i.maxZ=Math.max(e.maxZ,t.maxZ),c.isLeft?l.leftChild=i:l.rightChild=i,n.set(a,{parent:s,isLeft:o.isLeft}),n.set(i,{parent:l,isLeft:c.isLeft}),n.set(e,{parent:i,isLeft:!0}),n.set(t,{parent:i,isLeft:!1}),this.refitFrom(s,n),this.refitFrom(l,n)}refitFrom(e,t){let n=e;for(;n;){if(n.triangleCount===0&&n.leftChild&&n.rightChild){let e=n.leftChild,t=n.rightChild;n.minX=Math.min(e.minX,t.minX),n.minY=Math.min(e.minY,t.minY),n.minZ=Math.min(e.minZ,t.minZ),n.maxX=Math.max(e.maxX,t.maxX),n.maxY=Math.max(e.maxY,t.maxY),n.maxZ=Math.max(e.maxZ,t.maxZ)}let e=t.get(n);n=e?e.parent:null}}optimizeBVH(e,t){let n=performance.now();this.stats={reinsertionsApplied:0,iterations:0,timeMs:0};for(let r=0;r<this.maxIterations&&!(performance.now()-n>this.timeBudgetMs);r++){let i=this.buildParentMap(e),a=i.size,o=Math.max(1,Math.floor(a*this.batchSizeRatio));t&&t(`Reinsertion iter ${r+1}/${this.maxIterations}: selecting ${o} candidates`);let s=this.findCandidates(e,o,i),c=[];for(let t=0;t<s.length&&!(performance.now()-n>this.timeBudgetMs);t++){let n=this.findReinsertion(s[t].node,e,i);n&&n.areaDiff>0&&c.push(n)}c.sort((e,t)=>t.areaDiff-e.areaDiff);let l=new Set,u=0;for(let e of c){let t=this.getConflicts(e.from,e.to,i);if(!t.some(e=>l.has(e))){for(let e of t)l.add(e);this.reinsertNode(e.from,e.to,i),u++}}if(this.stats.reinsertionsApplied+=u,this.stats.iterations=r+1,t&&t(`Reinsertion iter ${r+1}: applied ${u} reinsertions`),u===0)break}return this.stats.timeMs=performance.now()-n,this.stats}};const r={silent:0,error:1,warn:2,info:3,debug:4},i=`info`,a=`rayzeeLogLevel`,o=`rayzeeLogNamespaces`,s=`color:#7c8494`,c=`color:inherit`;let l=null,u=null;function d(e){try{return globalThis.localStorage?.getItem(e)??null}catch{return null}}function f(e,t){try{t===null?globalThis.localStorage?.removeItem(e):globalThis.localStorage?.setItem(e,t)}catch{}}function p(){if(l!==null)return l;let e=globalThis.__RAYZEE_LOG_LEVEL__;return e!==void 0&&e in r?(l=r[e],l):(l=r[d(a)]??r[i],l)}function m(){if(u!==null)return u;let e=globalThis.__RAYZEE_LOG_NS__??d(o);return u=e?String(e).split(`,`).map(e=>e.trim()).filter(Boolean):[],u}function h(e,t){if(t<r.debug)return!0;let n=m();return n.length===0||n.some(t=>e===t||e.startsWith(`${t}:`))}function g(e,t,n){if(e>p()||!h(t,e))return;let i=e===r.error?console.error:e===r.warn?console.warn:console.log,a=`[${t}]`;typeof n[0]==`string`?i(`%c${a}%c ${n[0]}`,s,c,...n.slice(1)):i(`%c${a}`,s,...n)}const _={n:e=>Number(e).toLocaleString(`en-US`),ms:e=>e<10?`${Number(e).toFixed(1)} ms`:`${Math.round(e)} ms`,mb:e=>{let t=e/(1024*1024);return t<10?`${t.toFixed(1)} MB`:`${Math.round(t)} MB`},px:(e,t)=>`${e}×${t}`,count:(e,t,n=`${t}s`)=>`${_.n(e)} ${Number(e)===1?t:n}`,list:e=>e.filter(Boolean).join(` · `)},v={levels:r,setLevel(e){return e in r?(globalThis.__RAYZEE_LOG_LEVEL__=e,l=r[e],f(a,e===i?null:e),e):(console.warn(`[log] unknown level '${e}' — expected one of ${Object.keys(r).join(`, `)}`),this.getLevel())},getLevel(){let e=p();return Object.keys(r).find(t=>r[t]===e)},isEnabled(e){return(r[e]??r.debug)<=p()},only(...e){let t=e.flat().filter(Boolean);return u=t,globalThis.__RAYZEE_LOG_NS__=t.join(`,`),f(o,t.length?t.join(`,`):null),t.length&&this.setLevel(`debug`),t},refresh(){return l=null,u=null,this.getLevel()}};function y(e){return{namespace:e,error:(...t)=>g(r.error,e,t),warn:(...t)=>g(r.warn,e,t),info:(...t)=>g(r.info,e,t),debug:(...t)=>g(r.debug,e,t),isEnabled:e=>v.isEnabled(e),summary(t,n=[]){let i=n.filter(Boolean);if(i.length===0||!console.groupCollapsed){g(r.info,e,[t]),i.forEach(t=>g(r.debug,e,[t]));return}r.info>p()||((p()>=r.debug&&console.group?console.group:console.groupCollapsed)(`%c[${e}]%c ${t}`,s,c),i.forEach(e=>console.log(e)),console.groupEnd())}}}function b(e){e&&e in r&&(globalThis.__RAYZEE_LOG_LEVEL__=e,l=r[e])}const x=y(`bvh`),S={FLOATS_PER_TRIANGLE:32,POSITION_A_OFFSET:0,POSITION_B_OFFSET:4,POSITION_C_OFFSET:8,NORMAL_A_OFFSET:12,NORMAL_B_OFFSET:16,NORMAL_C_OFFSET:20,UV_AB_OFFSET:24,UV_C_MAT_OFFSET:28},C=S.FLOATS_PER_TRIANGLE;var w=class{constructor(){this.minX=0,this.minY=0,this.minZ=0,this.maxX=0,this.maxY=0,this.maxZ=0,this.leftChild=null,this.rightChild=null,this.triangleOffset=0,this.triangleCount=0}},T=class{constructor(){this.useWorker=!0,this.maxLeafSize=8,this.numBins=32,this.minBins=8,this.maxBins=64,this.totalNodes=0,this.processedTriangles=0,this.totalTriangles=0,this.lastProgressUpdate=0,this.progressUpdateInterval=100,this.traversalCost=1,this.intersectionCost=2.5,this.useMortonCodes=!0,this.mortonBits=10,this.mortonClusterThreshold=128,this.enableObjectMedianFallback=!0,this.enableSpatialMedianFallback=!0,this.splitStats={sahSplits:0,objectMedianSplits:0,spatialMedianSplits:0,failedSplits:0,avgBinsUsed:0,totalSplitAttempts:0,mortonSortTime:0,totalBuildTime:0,treeletOptimizationTime:0,treeletsProcessed:0,treeletsImproved:0,averageSAHImprovement:0,reinsertionOptimizationTime:0,reinsertionsApplied:0,reinsertionIterations:0},this.enableTreeletOptimization=!0,this.treeletSize=5,this.treeletOptimizationPasses=1,this.treeletMinImprovement=.02,this.maxTreeletDepth=3,this.maxTreeletsPerScene=20,this.treeletComplexityThreshold=5e4,this.enableReinsertionOptimization=!0,this.reinsertionBatchSizeRatio=.02,this.reinsertionMaxIterations=2,this.initializeBinArrays(),this._partResult={mid:0,lMinX:0,lMinY:0,lMinZ:0,lMaxX:0,lMaxY:0,lMaxZ:0,rMinX:0,rMinY:0,rMinZ:0,rMaxX:0,rMaxY:0,rMaxZ:0},this.centroids=null,this.bMin=null,this.bMax=null,this.indices=null,this.mortonCodes=null,this.triangles=null,this.reorderedTriangleData=null}initializeBinArrays(){let e=this.maxBins;this.binBoundsMin=new Float32Array(e*3),this.binBoundsMax=new Float32Array(e*3),this.binCounts=new Uint32Array(e),this.leftPrefixMin=new Float32Array(e*3),this.leftPrefixMax=new Float32Array(e*3),this.leftPrefixCount=new Uint32Array(e),this.rightPrefixMin=new Float32Array(e*3),this.rightPrefixMax=new Float32Array(e*3),this.rightPrefixCount=new Uint32Array(e)}getOptimalBinCount(e){return e<=16?this.minBins:e<=64?16:e<=256?32:e<=1024?48:this.maxBins}setAdaptiveBinConfig(e){e.minBins!==void 0&&(this.minBins=Math.max(4,e.minBins)),e.maxBins!==void 0&&(this.maxBins=Math.min(128,e.maxBins)),e.baseBins!==void 0&&(this.numBins=e.baseBins),e.maxBins!==void 0&&this.initializeBinArrays()}setMortonConfig(e){e.enabled!==void 0&&(this.useMortonCodes=e.enabled),e.bits!==void 0&&(this.mortonBits=Math.max(6,Math.min(10,e.bits))),e.threshold!==void 0&&(this.mortonClusterThreshold=Math.max(16,e.threshold))}setFallbackConfig(e){e.objectMedian!==void 0&&(this.enableObjectMedianFallback=e.objectMedian),e.spatialMedian!==void 0&&(this.enableSpatialMedianFallback=e.spatialMedian)}setTreeletConfig(e){e.enabled!==void 0&&(this.enableTreeletOptimization=e.enabled),e.size!==void 0&&(this.treeletSize=Math.max(3,Math.min(12,e.size))),e.passes!==void 0&&(this.treeletOptimizationPasses=Math.max(1,Math.min(3,e.passes))),e.minImprovement!==void 0&&(this.treeletMinImprovement=Math.max(.001,e.minImprovement))}disableTreeletOptimization(){this.enableTreeletOptimization=!1}setReinsertionConfig(e){e.enabled!==void 0&&(this.enableReinsertionOptimization=e.enabled),e.batchSizeRatio!==void 0&&(this.reinsertionBatchSizeRatio=Math.max(.005,Math.min(.1,e.batchSizeRatio))),e.maxIterations!==void 0&&(this.reinsertionMaxIterations=Math.max(1,Math.min(5,e.maxIterations)))}initializeTriangleArrays(){let e=this.totalTriangles,t=this.triangles,n=S.POSITION_A_OFFSET,r=S.POSITION_B_OFFSET,i=S.POSITION_C_OFFSET;for(let a=0;a<e;a++){let e=a*C,o=t[e+n],s=t[e+n+1],c=t[e+n+2],l=t[e+r],u=t[e+r+1],d=t[e+r+2],f=t[e+i],p=t[e+i+1],m=t[e+i+2],h=a*3;this.centroids[h]=(o+l+f)/3,this.centroids[h+1]=(s+u+p)/3,this.centroids[h+2]=(c+d+m)/3,this.bMin[h]=o<l?o<f?o:f:l<f?l:f,this.bMin[h+1]=s<u?s<p?s:p:u<p?u:p,this.bMin[h+2]=c<d?c<m?c:m:d<m?d:m,this.bMax[h]=o>l?o>f?o:f:l>f?l:f,this.bMax[h+1]=s>u?s>p?s:p:u>p?u:p,this.bMax[h+2]=c>d?c>m?c:m:d>m?d:m,this.indices[a]=a}}expandBits(e){return e=e*65537&4278190335,e=e*257&251719695,e=e*17&3272356035,e=e*5&1227133513,e}morton3D(e,t,n){return(this.expandBits(n)<<2)+(this.expandBits(t)<<1)+this.expandBits(e)}computeMortonCodeForIndex(e,t,n,r,i,a,o){let s=this.centroids,c=e*3,l=(1<<this.mortonBits)-1,u=i>0?(s[c]-t)/i:0,d=a>0?(s[c+1]-n)/a:0,f=o>0?(s[c+2]-r)/o:0,p=Math.max(0,Math.min(l,Math.floor(u*l))),m=Math.max(0,Math.min(l,Math.floor(d*l))),h=Math.max(0,Math.min(l,Math.floor(f*l)));return this.morton3D(p,m,h)}sortTrianglesByMortonCode(){let e=this.totalTriangles;if(!this.useMortonCodes||e<this.mortonClusterThreshold)return;let t=performance.now(),n=this.centroids,r=this.indices,i=1/0,a=1/0,o=1/0,s=-1/0,c=-1/0,l=-1/0;for(let t=0;t<e;t++){let e=r[t]*3,u=n[e],d=n[e+1],f=n[e+2];u<i&&(i=u),d<a&&(a=d),f<o&&(o=f),u>s&&(s=u),d>c&&(c=d),f>l&&(l=f)}let u=s-i,d=c-a,f=l-o,p=this.mortonCodes,m=(1<<this.mortonBits)-1,h=u>0?m/u:0,g=d>0?m/d:0,_=f>0?m/f:0;for(let t=0;t<e;t++){let e=r[t],s=e*3,c=(n[s]-i)*h,l=(n[s+1]-a)*g,u=(n[s+2]-o)*_;c=c<0?0:(c>m?m:c)|0,l=l<0?0:(l>m?m:l)|0,u=u<0?0:(u>m?m:u)|0,c=c*65537&4278190335,c=c*257&251719695,c=c*17&3272356035,c=c*5&1227133513,l=l*65537&4278190335,l=l*257&251719695,l=l*17&3272356035,l=l*5&1227133513,u=u*65537&4278190335,u=u*257&251719695,u=u*17&3272356035,u=u*5&1227133513,p[e]=(u<<2)+(l<<1)+c}let v=new Uint32Array(e),y=new Uint32Array(256);for(let t=0;t<32;t+=8){y.fill(0);for(let n=0;n<e;n++)y[p[r[n]]>>>t&255]++;let n=0;for(let e=0;e<256;e++){let t=y[e];y[e]=n,n+=t}for(let n=0;n<e;n++){let e=p[r[n]]>>>t&255;v[y[e]++]=r[n]}r.set(v)}this.splitStats.mortonSortTime+=performance.now()-t}build(e,t=30,n=null){if(this.totalTriangles=e.byteLength/(C*4),this.processedTriangles=0,this.lastProgressUpdate=performance.now(),!(this.useWorker&&null))return new Promise(r=>{r(this._buildSyncAndFlatten(e,t,n))})}_buildSyncAndFlatten(e,t,n){let r=this.buildSync(e,t,n);return{bvhData:this.flattenBVH(r),bvhRoot:!0,reorderedTriangles:this.reorderedTriangleData||null,originalToBvh:this.originalToBvhMap||null}}buildSync(t,r=30,i=null,a=null){let o=performance.now();this.totalNodes=0,this.processedTriangles=0,this.triangles=t,this.totalTriangles=t.byteLength/(C*4),this.lastProgressUpdate=performance.now(),this.splitStats={sahSplits:0,objectMedianSplits:0,spatialMedianSplits:0,failedSplits:0,avgBinsUsed:0,totalSplitAttempts:0,mortonSortTime:0,totalBuildTime:0,treeletOptimizationTime:0,treeletsProcessed:0,treeletsImproved:0,averageSAHImprovement:0,reinsertionOptimizationTime:0,reinsertionsApplied:0,reinsertionIterations:0,saOrderTime:0,initTime:0,sahBuildTime:0,reorderTime:0};let s=this.totalTriangles,c=performance.now();this.centroids=new Float32Array(s*3),this.bMin=new Float32Array(s*3),this.bMax=new Float32Array(s*3),this.indices=new Uint32Array(s),this.mortonCodes=new Uint32Array(s),this.initializeTriangleArrays(),this.splitStats.initTime=performance.now()-c,this.sortTrianglesByMortonCode();let l=performance.now(),u=this.buildNodeRecursive(0,s,r,i);if(this.splitStats.sahBuildTime=performance.now()-l,this.enableTreeletOptimization&&this.totalTriangles>1e3){let t=this.totalTriangles>this.treeletComplexityThreshold,n=t?3:this.treeletSize,r=t?10:this.maxTreeletsPerScene,a=new e(this.traversalCost,this.intersectionCost);a.setTreeletSize(n),a.setMinImprovement(this.treeletMinImprovement),a.setMaxTreelets(r);let o=performance.now();for(let e=0;e<this.treeletOptimizationPasses;e++){let t=i?t=>{i(`Treelet optimization pass ${e+1}/${this.treeletOptimizationPasses}: ${t}`)}:null;try{a.optimizeBVH(u,t)}catch(t){x.error(`treelet optimizer failed in pass ${e+1}:`,t);break}let n=a.getStatistics(),r=performance.now()-o;if(n.treeletsImproved===0&&e>0||r>15e3)break}let s=performance.now()-o;this.splitStats.treeletOptimizationTime=s;let c=a.getStatistics();this.splitStats.treeletsProcessed=c.treeletsProcessed,this.splitStats.treeletsImproved=c.treeletsImproved,this.splitStats.averageSAHImprovement=c.averageSAHImprovement}if(this.enableReinsertionOptimization&&this.totalTriangles>1e3){let e=new n(this.traversalCost,this.intersectionCost);e.setBatchSizeRatio(this.reinsertionBatchSizeRatio),e.setMaxIterations(this.reinsertionMaxIterations);let t=i?e=>{i(e)}:null;try{e.optimizeBVH(u,t)}catch(e){x.error(`reinsertion optimizer failed:`,e)}let r=e.getStatistics();this.splitStats.reinsertionOptimizationTime=r.timeMs,this.splitStats.reinsertionsApplied=r.reinsertionsApplied,this.splitStats.reinsertionIterations=r.iterations}let d=performance.now();this.applySAOrdering(u),this.splitStats.saOrderTime=performance.now()-d;let f=performance.now(),p=this.triangles,m=a||new Float32Array(s*C);for(let e=0;e<s;e++){let t=this.indices[e]*C,n=e*C;m.set(p.subarray(t,t+C),n)}this.reorderedTriangleData=m;let h=new Uint32Array(s);for(let e=0;e<s;e++)h[this.indices[e]]=e;this.originalToBvhMap=h,this.splitStats.reorderTime=performance.now()-f,this.splitStats.totalBuildTime=performance.now()-o;let g=this.splitStats.totalBuildTime,v=this.splitStats;return x.debug(`${_.n(s)} tris → ${_.n(this.totalNodes)} nodes in ${_.ms(g)} | SAH ${v.sahSplits} objMed ${v.objectMedianSplits} spatMed ${v.spatialMedianSplits} failed ${v.failedSplits}`+(v.treeletsProcessed?` | treelets ${v.treeletsImproved}/${v.treeletsProcessed} improved`:``)+(v.reinsertionsApplied?` | reinsertions ${v.reinsertionsApplied}`:``)),i&&i(100),this.centroids=null,this.bMin=null,this.bMax=null,this.mortonCodes=null,u}updateProgress(e,t){if(!t)return;this.processedTriangles+=e;let n=performance.now();n-this.lastProgressUpdate<this.progressUpdateInterval||(this.lastProgressUpdate=n,t(Math.min(Math.floor(this.processedTriangles/this.totalTriangles*100),99)))}buildNodeRecursiveToDepth(e,t,n,r,i,a,o,s,c,l,u){let d=new w;this.totalNodes++;let f=t-e;if(a===void 0?this.updateNodeBounds(d,e,t):(d.minX=a,d.minY=o,d.minZ=s,d.maxX=c,d.maxY=l,d.maxZ=u),f<=this.maxLeafSize||n<=0)return d.triangleOffset=e,d.triangleCount=f,this.updateProgress(f,i),d;if(r<=0&&f>this.maxLeafSize*16){let r=this.frontierTasks.length;return d.triangleOffset=e,d.triangleCount=f,d.isFrontier=!0,d.frontierTaskId=r,this.frontierTasks.push({taskId:r,start:e,end:t,depth:n,preMinX:d.minX,preMinY:d.minY,preMinZ:d.minZ,preMaxX:d.maxX,preMaxY:d.maxY,preMaxZ:d.maxZ}),d}let p=this.findBestSplitPositionSAH(e,t,d);if(!p.success){if(this.splitStats.failedSplits++,r>0||f<=this.maxLeafSize*16)return d.triangleOffset=e,d.triangleCount=f,this.updateProgress(f,i),d;let a=this.frontierTasks.length;return d.triangleOffset=e,d.triangleCount=f,d.isFrontier=!0,d.frontierTaskId=a,this.frontierTasks.push({taskId:a,start:e,end:t,depth:n,preMinX:d.minX,preMinY:d.minY,preMinZ:d.minZ,preMaxX:d.maxX,preMaxY:d.maxY,preMaxZ:d.maxZ}),d}p.method===`SAH`?this.splitStats.sahSplits++:p.method===`object_median`?this.splitStats.objectMedianSplits++:p.method===`spatial_median`&&this.splitStats.spatialMedianSplits++,this.partitionWithBounds(e,t,p.axis,p.pos);let m=this._partResult,h=m.mid,g=m.lMinX,_=m.lMinY,v=m.lMinZ,y=m.lMaxX,b=m.lMaxY,x=m.lMaxZ,S=m.rMinX,C=m.rMinY,T=m.rMinZ,E=m.rMaxX,D=m.rMaxY,O=m.rMaxZ;return h===e||h===t?(d.triangleOffset=e,d.triangleCount=f,this.updateProgress(f,i),d):(d.leftChild=this.buildNodeRecursiveToDepth(e,h,n-1,r-1,i,g,_,v,y,b,x),d.rightChild=this.buildNodeRecursiveToDepth(h,t,n-1,r-1,i,S,C,T,E,D,O),d)}buildNodeRecursive(e,t,n,r,i,a,o,s,c,l){let u=new w;this.totalNodes++;let d=t-e;if(i===void 0?this.updateNodeBounds(u,e,t):(u.minX=i,u.minY=a,u.minZ=o,u.maxX=s,u.maxY=c,u.maxZ=l),d<=this.maxLeafSize||n<=0)return u.triangleOffset=e,u.triangleCount=d,this.updateProgress(d,r),u;let f=this.findBestSplitPositionSAH(e,t,u);if(!f.success)return this.splitStats.failedSplits++,u.triangleOffset=e,u.triangleCount=d,this.updateProgress(d,r),u;f.method===`SAH`?this.splitStats.sahSplits++:f.method===`object_median`?this.splitStats.objectMedianSplits++:f.method===`spatial_median`&&this.splitStats.spatialMedianSplits++,this.partitionWithBounds(e,t,f.axis,f.pos);let p=this._partResult,m=p.mid,h=p.lMinX,g=p.lMinY,_=p.lMinZ,v=p.lMaxX,y=p.lMaxY,b=p.lMaxZ,x=p.rMinX,S=p.rMinY,C=p.rMinZ,T=p.rMaxX,E=p.rMaxY,D=p.rMaxZ;return m===e||m===t?(u.triangleOffset=e,u.triangleCount=d,this.updateProgress(d,r),u):(u.leftChild=this.buildNodeRecursive(e,m,n-1,r,h,g,_,v,y,b),u.rightChild=this.buildNodeRecursive(m,t,n-1,r,x,S,C,T,E,D),u)}partitionWithBounds(e,t,n,r){let i=this.indices,a=this.centroids,o=this.bMin,s=this.bMax,c=e,l=t-1,u=1/0,d=1/0,f=1/0,p=-1/0,m=-1/0,h=-1/0,g=1/0,_=1/0,v=1/0,y=-1/0,b=-1/0,x=-1/0;for(;c<=l;){let e=i[c],t=e*3;a[t+n]<=r?(o[t]<u&&(u=o[t]),o[t+1]<d&&(d=o[t+1]),o[t+2]<f&&(f=o[t+2]),s[t]>p&&(p=s[t]),s[t+1]>m&&(m=s[t+1]),s[t+2]>h&&(h=s[t+2]),c++):(o[t]<g&&(g=o[t]),o[t+1]<_&&(_=o[t+1]),o[t+2]<v&&(v=o[t+2]),s[t]>y&&(y=s[t]),s[t+1]>b&&(b=s[t+1]),s[t+2]>x&&(x=s[t+2]),i[c]=i[l],i[l]=e,l--)}let S=this._partResult;return S.mid=c,S.lMinX=u,S.lMinY=d,S.lMinZ=f,S.lMaxX=p,S.lMaxY=m,S.lMaxZ=h,S.rMinX=g,S.rMinY=_,S.rMinZ=v,S.rMaxX=y,S.rMaxY=b,S.rMaxZ=x,S}updateNodeBounds(e,t,n){let r=1/0,i=1/0,a=1/0,o=-1/0,s=-1/0,c=-1/0,l=this.indices,u=this.bMin,d=this.bMax;for(let e=t;e<n;e++){let t=l[e]*3;u[t]<r&&(r=u[t]),u[t+1]<i&&(i=u[t+1]),u[t+2]<a&&(a=u[t+2]),d[t]>o&&(o=d[t]),d[t+1]>s&&(s=d[t+1]),d[t+2]>c&&(c=d[t+2])}e.minX=r,e.minY=i,e.minZ=a,e.maxX=o,e.maxY=s,e.maxZ=c}findBestSplitPositionSAH(e,t,n){let r=1/0,i=-1,a=0,o=this.computeSurfaceAreaFlat(n.minX,n.minY,n.minZ,n.maxX,n.maxY,n.maxZ),s=t-e,c=this.intersectionCost*s,l=this.getOptimalBinCount(s);this.splitStats.totalSplitAttempts++,this.splitStats.avgBinsUsed=(this.splitStats.avgBinsUsed*(this.splitStats.totalSplitAttempts-1)+l)/this.splitStats.totalSplitAttempts;let u=this.indices,d=this.centroids,f=this.bMin,p=this.bMax,m=this.binBoundsMin,h=this.binBoundsMax,g=this.binCounts,_=this.leftPrefixMin,v=this.leftPrefixMax,y=this.leftPrefixCount,b=this.rightPrefixMin,x=this.rightPrefixMax,S=this.rightPrefixCount,C=1/0,w=-1/0,T=1/0,E=-1/0,D=1/0,O=-1/0;for(let n=e;n<t;n++){let e=u[n]*3,t=d[e],r=d[e+1],i=d[e+2];t<C&&(C=t),t>w&&(w=t),r<T&&(T=r),r>E&&(E=r),i<D&&(D=i),i>O&&(O=i)}let k=[C,T,D],A=[w,E,O];for(let n=0;n<3;n++){let s=k[n],C=A[n];if(C-s<1e-6)continue;for(let e=0;e<l;e++){g[e]=0;let t=e*3;m[t]=1/0,m[t+1]=1/0,m[t+2]=1/0,h[t]=-1/0,h[t+1]=-1/0,h[t+2]=-1/0}let w=l/(C-s);for(let r=e;r<t;r++){let e=u[r],t=d[e*3+n],i=Math.floor((t-s)*w);i>=l&&(i=l-1),g[i]++;let a=i*3,o=e*3;f[o]<m[a]&&(m[a]=f[o]),f[o+1]<m[a+1]&&(m[a+1]=f[o+1]),f[o+2]<m[a+2]&&(m[a+2]=f[o+2]),p[o]>h[a]&&(h[a]=p[o]),p[o+1]>h[a+1]&&(h[a+1]=p[o+1]),p[o+2]>h[a+2]&&(h[a+2]=p[o+2])}y[0]=g[0],_[0]=m[0],_[1]=m[1],_[2]=m[2],v[0]=h[0],v[1]=h[1],v[2]=h[2];for(let e=1;e<l;e++){let t=e*3,n=(e-1)*3;y[e]=y[e-1]+g[e];let r=_[n],i=m[t],a=_[n+1],o=m[t+1],s=_[n+2],c=m[t+2];_[t]=r<i?r:i,_[t+1]=a<o?a:o,_[t+2]=s<c?s:c;let l=v[n],u=h[t],d=v[n+1],f=h[t+1],p=v[n+2],b=h[t+2];v[t]=l>u?l:u,v[t+1]=d>f?d:f,v[t+2]=p>b?p:b}let T=l-1,E=T*3;S[T]=g[T],b[E]=m[E],b[E+1]=m[E+1],b[E+2]=m[E+2],x[E]=h[E],x[E+1]=h[E+1],x[E+2]=h[E+2];for(let e=T-1;e>=0;e--){let t=e*3,n=(e+1)*3;S[e]=S[e+1]+g[e];let r=b[n],i=m[t],a=b[n+1],o=m[t+1],s=b[n+2],c=m[t+2];b[t]=r<i?r:i,b[t+1]=a<o?a:o,b[t+2]=s<c?s:c;let l=x[n],u=h[t],d=x[n+1],f=h[t+1],p=x[n+2],_=h[t+2];x[t]=l>u?l:u,x[t+1]=d>f?d:f,x[t+2]=p>_?p:_}for(let e=1;e<l;e++){let t=(e-1)*3,u=e*3,d=y[e-1],f=S[e];if(d===0||f===0)continue;let p=v[t]-_[t],m=v[t+1]-_[t+1],h=v[t+2]-_[t+2],g=2*(p*m+m*h+h*p),w=x[u]-b[u],T=x[u+1]-b[u+1],E=x[u+2]-b[u+2],D=2*(w*T+T*E+E*w),O=this.traversalCost+g/o*d*this.intersectionCost+D/o*f*this.intersectionCost;O<r&&O<c&&(r=O,i=n,a=s+(C-s)*e/l)}}return i===-1?this.enableObjectMedianFallback?this.findObjectMedianSplit(e,t):this.enableSpatialMedianFallback?this.findSpatialMedianSplit(e,t):{success:!1,method:`fallbacks_disabled`}:{success:!0,axis:i,pos:a,method:`SAH`,binsUsed:l}}findObjectMedianSplit(e,t){let n=this.indices,r=this.centroids,i=-1,a=-1;for(let o=0;o<3;o++){let s=1/0,c=-1/0;for(let i=e;i<t;i++){let e=r[n[i]*3+o];e<s&&(s=e),e>c&&(c=e)}let l=c-s;l>a&&(a=l,i=o)}if(i===-1||a<1e-10)return this.enableSpatialMedianFallback?this.findSpatialMedianSplit(e,t):{success:!1,method:`object_median_failed`};let o=t-e,s=e+Math.floor(o/2);this.quickselect(e,t,s,i);let c=r[n[s]*3+i],l=!0;for(let e=s+1;e<t;e++)if(r[n[e]*3+i]>c){l=!1;break}if(l){let a=-1/0;for(let t=e;t<s;t++){let e=r[n[t]*3+i];e>a&&(a=e)}if(a<c)c=(a+c)*.5;else return this.enableSpatialMedianFallback?this.findSpatialMedianSplit(e,t):{success:!1,method:`object_median_degenerate`}}return{success:!0,axis:i,pos:c,method:`object_median`}}findSpatialMedianSplit(e,t){let n=this.indices,r=this.centroids,i=this.bMin,a=this.bMax,o=-1,s=-1,c=0,l=0;for(let r=0;r<3;r++){let u=1/0,d=-1/0;for(let o=e;o<t;o++){let e=n[o]*3+r;i[e]<u&&(u=i[e]),a[e]>d&&(d=a[e])}let f=d-u;f>s&&(s=f,o=r,c=u,l=d)}if(o===-1||s<1e-12)return{success:!1,method:`spatial_median_failed`};let u=(c+l)*.5,d=t-e,f=0;for(let i=e;i<t;i++)r[n[i]*3+o]<=u&&f++;if(f===0||f===d){let i=e+Math.floor(d/2);this.quickselect(e,t,i,o);let a=r[n[i]*3+o],s=!0;for(let i=e;i<t;i++)if(r[n[i]*3+o]!==a){s=!1;break}if(s)return{success:!1,method:`spatial_median_degenerate`};let c=-1/0;for(let t=e;t<i;t++){let e=r[n[t]*3+o];e>c&&(c=e)}if(c<a)u=(c+a)*.5;else{let e=1/0;for(let a=i+1;a<t;a++){let t=r[n[a]*3+o];t<e&&(e=t)}u=(a+e)*.5}}return{success:!0,axis:o,pos:u,method:`spatial_median`}}quickselect(e,t,n,r){let i=this.indices,a=this.centroids,o=e,s=t-1;for(;o<s;){let e=o+s>>>1,t=a[i[o]*3+r],c=a[i[e]*3+r],l=a[i[s]*3+r];if(t>c){let t=i[o];i[o]=i[e],i[e]=t}if(t>l){let e=i[o];i[o]=i[s],i[s]=e}if(c>l){let t=i[e];i[e]=i[s],i[s]=t}let u=a[i[e]*3+r],d=o,f=s;for(;d<=f;){for(;a[i[d]*3+r]<u;)d++;for(;a[i[f]*3+r]>u;)f--;if(d<=f){let e=i[d];i[d]=i[f],i[f]=e,d++,f--}}f<n&&(o=d),d>n&&(s=f)}}applySAOrdering(e){if(!e||!e.leftChild)return;let t=[e],n=[];for(;t.length>0;){let e=t.pop();!e.leftChild||!e.rightChild||(n.push(e),t.push(e.leftChild),t.push(e.rightChild))}for(let e=n.length-1;e>=0;e--){let t=n[e],r=t.leftChild,i=t.rightChild,a=r.maxX-r.minX,o=r.maxY-r.minY,s=r.maxZ-r.minZ,c=i.maxX-i.minX,l=i.maxY-i.minY,u=i.maxZ-i.minZ;c*l+l*u+u*c>a*o+o*s+s*a&&(t.leftChild=i,t.rightChild=r)}}flattenBVH(e){let t=[],n=[e];for(;n.length>0;){let e=n.pop();e._flatIndex=t.length,t.push(e),e.rightChild&&n.push(e.rightChild),e.leftChild&&n.push(e.leftChild)}let r=new Float32Array(t.length*16);for(let e=0;e<t.length;e++){let n=t[e],i=e*16;if(n.leftChild){let e=n.leftChild,t=n.rightChild;r[i]=e.minX,r[i+1]=e.minY,r[i+2]=e.minZ,r[i+3]=e._flatIndex,r[i+4]=e.maxX,r[i+5]=e.maxY,r[i+6]=e.maxZ,r[i+7]=t._flatIndex,r[i+8]=t.minX,r[i+9]=t.minY,r[i+10]=t.minZ,r[i+12]=t.maxX,r[i+13]=t.maxY,r[i+14]=t.maxZ}else r[i]=n.triangleOffset,r[i+1]=n.triangleCount,r[i+3]=-1}return r}flattenBVHWithFrontier(e){let t=[],n=[e];for(;n.length>0;){let e=n.pop();e._flatIndex=t.length,t.push(e),e.rightChild&&n.push(e.rightChild),e.leftChild&&n.push(e.leftChild)}let r=new Float32Array(t.length*16),i=[];for(let e=0;e<t.length;e++){let n=t[e],a=e*16;if(n.leftChild){let e=n.leftChild,t=n.rightChild;r[a]=e.minX,r[a+1]=e.minY,r[a+2]=e.minZ,r[a+3]=e._flatIndex,r[a+4]=e.maxX,r[a+5]=e.maxY,r[a+6]=e.maxZ,r[a+7]=t._flatIndex,r[a+8]=t.minX,r[a+9]=t.minY,r[a+10]=t.minZ,r[a+12]=t.maxX,r[a+13]=t.maxY,r[a+14]=t.maxZ}else if(n.isFrontier){let t=n.frontierTaskId;r[a]=n.triangleOffset,r[a+1]=n.triangleCount,r[a+2]=t,r[a+3]=-2,i.push({taskId:t,flatIndex:e})}else r[a]=n.triangleOffset,r[a+1]=n.triangleCount,r[a+3]=-1}return{flatData:r,frontierMap:i,nodeCount:t.length}}assembleParallelBVH(e,t,n,r){let i=[...r].sort((e,t)=>e.taskId-t.taskId),a=t;for(let e=0;e<i.length;e++)a+=i[e].nodeCount;let o=new Float32Array(a*16);o.set(e);let s=new Map;for(let e of n)s.set(e.taskId,e.flatIndex);let c=t;for(let e=0;e<i.length;e++){let t=i[e],n=t.flatData,r=t.nodeCount,a=c*16;o.set(n,a);for(let e=0;e<r;e++){let t=a+e*16;o[t+3]!==-1&&(o[t+3]+=c,o[t+7]+=c)}let l=s.get(t.taskId);if(l!==void 0){let e=l*16,t=a;for(let n=0;n<16;n++)o[e+n]=o[t+n]}c+=r}return o}computeSurfaceAreaFlat(e,t,n,r,i,a){let o=r-e,s=i-t,c=a-n;return 2*(o*s+s*c+c*o)}};const E=y(`bvh`);self.onmessage=function(e){let t=e.data,n=t.type;b(t.logLevel),n===`buildPhase1`?D(t):n===`assemble`?O(t):k(t)};function D(e){let{sharedTriangleData:t,sharedCentroids:n,sharedBMin:r,sharedBMax:i,sharedIndices:a,sharedMortonCodes:o,triangleCount:s,depth:c,parallelDepth:l,reportProgress:u,treeletOptimization:d}=e;try{let e=new T;d&&e.setTreeletConfig(d);let f=u?e=>{self.postMessage({type:`progress`,progress:e})}:null;e.triangles=new Float32Array(t),e.centroids=new Float32Array(n),e.bMin=new Float32Array(r),e.bMax=new Float32Array(i),e.indices=new Uint32Array(a),e.mortonCodes=new Uint32Array(o),e.totalTriangles=s,e.totalNodes=0,e.processedTriangles=0,e.lastProgressUpdate=performance.now(),e.splitStats={sahSplits:0,objectMedianSplits:0,spatialMedianSplits:0,failedSplits:0,avgBinsUsed:0,totalSplitAttempts:0,mortonSortTime:0,totalBuildTime:0,treeletOptimizationTime:0,treeletsProcessed:0,treeletsImproved:0,averageSAHImprovement:0,initTime:0,sahBuildTime:0,reorderTime:0};let p=performance.now(),m=performance.now();e.initializeTriangleArrays(),e.splitStats.initTime=performance.now()-m,e.sortTrianglesByMortonCode(),e.frontierTasks=[];let h=performance.now(),g=e.buildNodeRecursiveToDepth(0,s,c,l,f);e.splitStats.sahBuildTime=performance.now()-h,e.applySAOrdering(g);let v=performance.now(),{flatData:y,frontierMap:b,nodeCount:x}=e.flattenBVHWithFrontier(g),S=performance.now()-v,C=performance.now()-p;E.debug(`phase 1 ${_.ms(C)} (init ${_.ms(e.splitStats.initTime)} · morton ${_.ms(e.splitStats.mortonSortTime)} · SAH ${_.ms(e.splitStats.sahBuildTime)} · flatten ${_.ms(S)}) · ${e.frontierTasks.length} frontier tasks`),self.postMessage({type:`phase1Result`,topFlatData:y,topNodeCount:x,frontierTasks:e.frontierTasks,frontierMap:b,splitStats:e.splitStats},[y.buffer])}catch(e){E.error(`phase 1 failed:`,e),self.postMessage({type:`error`,error:e.message})}}function O(e){let{topFlatData:t,topNodeCount:n,frontierMap:r,subtreeResults:i,sharedTriangleData:a,sharedIndices:o,sharedReorderBuffer:s,triangleCount:c}=e;try{let e=performance.now(),l=new T().assembleParallelBVH(t,n,r,i),u=new Uint32Array(o),d=new Float32Array(a),f=new Float32Array(s);for(let e=0;e<c;e++){let t=u[e]*32,n=e*32;f.set(d.subarray(t,t+32),n)}let p=new Uint32Array(c);for(let e=0;e<c;e++)p[u[e]]=e;let m=performance.now()-e;E.debug(`phase 3 assemble + reorder ${_.ms(m)} (${_.mb(l.byteLength)} BVH)`),self.postMessage({type:`assembleResult`,bvhData:l,originalToBvh:p,triangleCount:c},[l.buffer,p.buffer])}catch(e){E.error(`assembly failed:`,e),self.postMessage({type:`error`,error:e.message})}}function k(e){let{triangleData:t,triangleByteOffset:n,triangleByteLength:r,depth:i,reportProgress:a,treeletOptimization:o,reinsertionOptimization:s,sharedReorderBuffer:c,maxLeafSize:l,numBins:u,maxBins:d,minBins:f}=e,p=new T;l!==void 0&&(p.maxLeafSize=l),u!==void 0&&(p.numBins=u),d!==void 0&&(p.maxBins=d),f!==void 0&&(p.minBins=f);try{o&&p.setTreeletConfig(o),s&&p.setReinsertionConfig(s);let e=a?e=>{self.postMessage({progress:e})}:null,l=n===void 0?new Float32Array(t):new Float32Array(t,n,r/4),u=c?new Float32Array(c):null,d=p.buildSync(l,i,e,u),f=performance.now(),m=p.flattenBVH(d),h=performance.now()-f;E.debug(`flatten ${_.ms(h)} (${_.mb(m.byteLength)})`);let g=p.originalToBvhMap||null;if(c){let e=[m.buffer];g&&e.push(g.buffer),self.postMessage({bvhData:m,originalToBvh:g,triangleCount:l.length/32,treeletStats:p.splitStats},e)}else{let e=p.reorderedTriangleData,t=e.byteLength/128,n=[m.buffer,e.buffer];g&&n.push(g.buffer),self.postMessage({bvhData:m,triangles:e,originalToBvh:g,triangleCount:t,treeletStats:p.splitStats},n)}}catch(e){E.error(`build failed:`,e),self.postMessage({error:e.message})}}", mc = typeof self < "u" && self.Blob && new Blob(["URL.revokeObjectURL(import.meta.url);", pc], { type: "text/javascript;charset=utf-8" });
5545
+ }, pc = "var e=class{constructor(e,t){this.traversalCost=e,this.intersectionCost=t,this.maxTreeletLeaves=7,this.minImprovement=.02,this.topologyCache=new Map;for(let e=3;e<=this.maxTreeletLeaves;e++)this.topologyCache.set(e,this.generateTopologies(e));this.stats={treeletsProcessed:0,treeletsImproved:0,totalSAHImprovement:0,averageSAHImprovement:0,optimizationTime:0}}generateTopologies(e){if(e===1)return[0];if(e===2)return[[0,1]];let t=[];for(let n=1;n<e;n++){let r=this.generateTopologies(n),i=this.generateTopologies(e-n);for(let e of r)for(let r of i)t.push([e,this.offsetTopology(r,n)])}return t}offsetTopology(e,t){return typeof e==`number`?e+t:[this.offsetTopology(e[0],t),this.offsetTopology(e[1],t)]}optimizeBVH(e){let t=performance.now();this.stats={treeletsProcessed:0,treeletsImproved:0,totalSAHImprovement:0,averageSAHImprovement:0,optimizationTime:0};let n=this.identifyTreeletRoots(e);for(let e=0;e<n.length;e++){if(performance.now()-t>3e4){console.warn(`TreeletOptimizer: timeout after ${e}/${n.length} treelets`);break}this.optimizeTreelet(n[e])}return this.stats.optimizationTime=performance.now()-t,this.stats.averageSAHImprovement=this.stats.treeletsProcessed>0?this.stats.totalSAHImprovement/this.stats.treeletsProcessed:0,e}identifyTreeletRoots(e){let t=[],n=new Set,r=[{node:e,visited:!1}];for(;r.length>0;){let e=r[r.length-1];if(e.visited){r.pop();let i=e.node;if(i.triangleCount>0||n.has(i))continue;let a=this.countLeaves(i);a>=3&&a<=this.maxTreeletLeaves&&(t.push(i),this.markSubtree(i,n))}else{e.visited=!0;let t=e.node;if(t.triangleCount>0)continue;t.rightChild&&r.push({node:t.rightChild,visited:!1}),t.leftChild&&r.push({node:t.leftChild,visited:!1})}}return t}countLeaves(e){return e?e.triangleCount>0?1:this.countLeaves(e.leftChild)+this.countLeaves(e.rightChild):0}markSubtree(e,t){e&&(t.add(e),!(e.triangleCount>0)&&(this.markSubtree(e.leftChild,t),this.markSubtree(e.rightChild,t)))}optimizeTreelet(e){let t=[];this.extractLeaves(e,t);let n=t.length;if(n<3||n>this.maxTreeletLeaves)return;this.stats.treeletsProcessed++;let r=this.evaluateSubtreeSAH(e),i=this.topologyCache.get(n);if(!i||i.length===0)return;let a=r,o=null,s=null;if(n<=5){let e=this.generatePermutations(n);for(let n of i)for(let r of e){let e=this.evaluateTopology(n,t,r);e<a&&(a=e,o=n,s=r)}}else{let e=Array.from({length:n},(e,t)=>t);for(let n of i){let r=this.evaluateTopology(n,t,e);r<a&&(a=r,o=n,s=e);let i=this.greedySwapOptimize(n,t,e,r);i.cost<a&&(a=i.cost,o=n,s=i.perm)}}let c=(r-a)/r;o&&c>this.minImprovement&&(this.reconstructTreelet(e,o,t,s),this.stats.treeletsImproved++,this.stats.totalSAHImprovement+=c)}extractLeaves(e,t){if(e){if(e.triangleCount>0){t.push({minX:e.minX,minY:e.minY,minZ:e.minZ,maxX:e.maxX,maxY:e.maxY,maxZ:e.maxZ,triangleOffset:e.triangleOffset,triangleCount:e.triangleCount});return}this.extractLeaves(e.leftChild,t),this.extractLeaves(e.rightChild,t)}}evaluateSubtreeSAH(e){if(!e)return 0;if(e.triangleCount>0)return this.surfaceAreaFlat(e.minX,e.minY,e.minZ,e.maxX,e.maxY,e.maxZ)*e.triangleCount*this.intersectionCost;let t=this.evaluateSubtreeSAH(e.leftChild),n=this.evaluateSubtreeSAH(e.rightChild);return this.surfaceAreaFlat(e.minX,e.minY,e.minZ,e.maxX,e.maxY,e.maxZ)*this.traversalCost+t+n}evaluateTopology(e,t,n){return this.evalTopoRecursive(e,t,n).cost}evalTopoRecursive(e,t,n){if(typeof e==`number`){let r=t[n[e]];return{cost:this.surfaceAreaFlat(r.minX,r.minY,r.minZ,r.maxX,r.maxY,r.maxZ)*r.triangleCount*this.intersectionCost,minX:r.minX,minY:r.minY,minZ:r.minZ,maxX:r.maxX,maxY:r.maxY,maxZ:r.maxZ}}let r=this.evalTopoRecursive(e[0],t,n),i=this.evalTopoRecursive(e[1],t,n),a=Math.min(r.minX,i.minX),o=Math.min(r.minY,i.minY),s=Math.min(r.minZ,i.minZ),c=Math.max(r.maxX,i.maxX),l=Math.max(r.maxY,i.maxY),u=Math.max(r.maxZ,i.maxZ);return{cost:this.surfaceAreaFlat(a,o,s,c,l,u)*this.traversalCost+r.cost+i.cost,minX:a,minY:o,minZ:s,maxX:c,maxY:l,maxZ:u}}surfaceAreaFlat(e,t,n,r,i,a){let o=r-e,s=i-t,c=a-n;return 2*(o*s+s*c+c*o)}generatePermutations(e){let t=[],n=Array.from({length:e},(e,t)=>t),r=i=>{if(i===e){t.push([...n]);return}for(let t=i;t<e;t++)[n[i],n[t]]=[n[t],n[i]],r(i+1),[n[i],n[t]]=[n[t],n[i]]};return r(0),t}greedySwapOptimize(e,t,n,r){let i=[...n],a=r,o=!0;for(;o;){o=!1;for(let n=0;n<i.length-1;n++)for(let r=n+1;r<i.length;r++){[i[n],i[r]]=[i[r],i[n]];let s=this.evaluateTopology(e,t,i);s<a?(a=s,o=!0):[i[n],i[r]]=[i[r],i[n]]}}return{perm:i,cost:a}}reconstructTreelet(e,t,n,r){let i=this.buildSubtree(t,n,r);e.minX=i.minX,e.minY=i.minY,e.minZ=i.minZ,e.maxX=i.maxX,e.maxY=i.maxY,e.maxZ=i.maxZ,e.leftChild=i.leftChild,e.rightChild=i.rightChild,e.triangleOffset=i.triangleOffset,e.triangleCount=i.triangleCount}buildSubtree(e,n,r){if(typeof e==`number`){let i=n[r[e]],a=new t;return a.minX=i.minX,a.minY=i.minY,a.minZ=i.minZ,a.maxX=i.maxX,a.maxY=i.maxY,a.maxZ=i.maxZ,a.triangleOffset=i.triangleOffset,a.triangleCount=i.triangleCount,a}let i=this.buildSubtree(e[0],n,r),a=this.buildSubtree(e[1],n,r),o=new t;return o.leftChild=i,o.rightChild=a,o.minX=Math.min(i.minX,a.minX),o.minY=Math.min(i.minY,a.minY),o.minZ=Math.min(i.minZ,a.minZ),o.maxX=Math.max(i.maxX,a.maxX),o.maxY=Math.max(i.maxY,a.maxY),o.maxZ=Math.max(i.maxZ,a.maxZ),o}setTreeletSize(e){this.maxTreeletLeaves=Math.max(3,Math.min(7,e));for(let e=3;e<=this.maxTreeletLeaves;e++)this.topologyCache.has(e)||this.topologyCache.set(e,this.generateTopologies(e))}setMinImprovement(e){this.minImprovement=Math.max(.001,e)}getStatistics(){return{...this.stats}}},t=class{constructor(){this.minX=0,this.minY=0,this.minZ=0,this.maxX=0,this.maxY=0,this.maxZ=0,this.leftChild=null,this.rightChild=null,this.triangleOffset=0,this.triangleCount=0}},n=class{constructor(e,t){this.traversalCost=e,this.intersectionCost=t,this.batchSizeRatio=.02,this.maxIterations=2,this.timeBudgetMs=15e3,this.stats={reinsertionsApplied:0,iterations:0,timeMs:0}}setBatchSizeRatio(e){this.batchSizeRatio=Math.max(.005,Math.min(.1,e))}setMaxIterations(e){this.maxIterations=Math.max(1,Math.min(5,e))}getStatistics(){return{...this.stats}}surfaceArea(e){let t=e.maxX-e.minX,n=e.maxY-e.minY,r=e.maxZ-e.minZ;return t*n+n*r+r*t}buildParentMap(e){let t=new Map;t.set(e,{parent:null,isLeft:!1});let n=[e];for(;n.length>0;){let e=n.pop();e.triangleCount>0||(e.leftChild&&(t.set(e.leftChild,{parent:e,isLeft:!0}),n.push(e.leftChild)),e.rightChild&&(t.set(e.rightChild,{parent:e,isLeft:!1}),n.push(e.rightChild)))}return t}findCandidates(e,t,n){let r=[],i=[e];for(;i.length>0;){let a=i.pop();if(a!==e&&n.get(a).parent!==e){let e=this.surfaceArea(a);r.length<t?(r.push({node:a,cost:e}),r.length===t&&this._heapify(r)):e>r[0].cost&&(r[0]={node:a,cost:e},this._siftDown(r,0))}a.triangleCount===0&&(a.leftChild&&i.push(a.leftChild),a.rightChild&&i.push(a.rightChild))}return r}_heapify(e){for(let t=(e.length>>1)-1;t>=0;t--)this._siftDown(e,t)}_siftDown(e,t){let n=e.length;for(;;){let r=t,i=2*t+1,a=2*t+2;if(i<n&&e[i].cost<e[r].cost&&(r=i),a<n&&e[a].cost<e[r].cost&&(r=a),r===t)break;let o=e[t];e[t]=e[r],e[r]=o,t=r}}findReinsertion(e,t,n){let r=n.get(e),i=r.parent;if(!i)return null;let a=r.isLeft?i.rightChild:i.leftChild,o=this.surfaceArea(e),s=this.surfaceArea(i),c=null,l=0,u=s,d=a.minX,f=a.minY,p=a.minZ,m=a.maxX,h=a.maxY,g=a.maxZ,_=a,v=i,y=[];do{for(y.length=0,y.push(u,_);y.length>0;){let t=y.pop(),n=y.pop();if(n-o<=l)continue;let r=Math.min(t.minX,e.minX),i=Math.min(t.minY,e.minY),a=Math.min(t.minZ,e.minZ),s=Math.max(t.maxX,e.maxX),u=Math.max(t.maxY,e.maxY),d=Math.max(t.maxZ,e.maxZ),f=s-r,p=u-i,m=d-a,h=n-(f*p+p*m+m*f);if(h>l&&(c=t,l=h),t.triangleCount===0&&t.leftChild&&t.rightChild){let e=h+this.surfaceArea(t);y.push(e,t.leftChild),y.push(e,t.rightChild)}}let t=n.get(v);if(!t||t.parent===null)break;if(v!==i){d=Math.min(d,_.minX),f=Math.min(f,_.minY),p=Math.min(p,_.minZ),m=Math.max(m,_.maxX),h=Math.max(h,_.maxY),g=Math.max(g,_.maxZ);let e=m-d,t=h-f,n=g-p,r=e*t+t*n+n*e;u+=this.surfaceArea(v)-r}let r=t.parent;_=t.isLeft?r.rightChild:r.leftChild,v=r}while(n.get(v).parent!==null);return c===a||c===i?null:c?{from:e,to:c,areaDiff:l}:null}getConflicts(e,t,n){let r=n.get(e);return[t,e,r.isLeft?r.parent.rightChild:r.parent.leftChild,n.get(t).parent,r.parent]}reinsertNode(e,t,n){let r=n.get(e),i=r.parent,a=r.isLeft?i.rightChild:i.leftChild,o=n.get(i),s=o.parent,c=n.get(t),l=c.parent;o.isLeft?s.leftChild=a:s.rightChild=a,i.leftChild=e,i.rightChild=t,i.triangleOffset=0,i.triangleCount=0,i.minX=Math.min(e.minX,t.minX),i.minY=Math.min(e.minY,t.minY),i.minZ=Math.min(e.minZ,t.minZ),i.maxX=Math.max(e.maxX,t.maxX),i.maxY=Math.max(e.maxY,t.maxY),i.maxZ=Math.max(e.maxZ,t.maxZ),c.isLeft?l.leftChild=i:l.rightChild=i,n.set(a,{parent:s,isLeft:o.isLeft}),n.set(i,{parent:l,isLeft:c.isLeft}),n.set(e,{parent:i,isLeft:!0}),n.set(t,{parent:i,isLeft:!1}),this.refitFrom(s,n),this.refitFrom(l,n)}refitFrom(e,t){let n=e;for(;n;){if(n.triangleCount===0&&n.leftChild&&n.rightChild){let e=n.leftChild,t=n.rightChild;n.minX=Math.min(e.minX,t.minX),n.minY=Math.min(e.minY,t.minY),n.minZ=Math.min(e.minZ,t.minZ),n.maxX=Math.max(e.maxX,t.maxX),n.maxY=Math.max(e.maxY,t.maxY),n.maxZ=Math.max(e.maxZ,t.maxZ)}let e=t.get(n);n=e?e.parent:null}}optimizeBVH(e,t){let n=performance.now();this.stats={reinsertionsApplied:0,iterations:0,timeMs:0};for(let r=0;r<this.maxIterations&&!(performance.now()-n>this.timeBudgetMs);r++){let i=this.buildParentMap(e),a=i.size,o=Math.max(1,Math.floor(a*this.batchSizeRatio));t&&t(`Reinsertion iter ${r+1}/${this.maxIterations}: selecting ${o} candidates`);let s=this.findCandidates(e,o,i),c=[];for(let t=0;t<s.length&&!(performance.now()-n>this.timeBudgetMs);t++){let n=this.findReinsertion(s[t].node,e,i);n&&n.areaDiff>0&&c.push(n)}c.sort((e,t)=>t.areaDiff-e.areaDiff);let l=new Set,u=0;for(let e of c){let t=this.getConflicts(e.from,e.to,i);if(!t.some(e=>l.has(e))){for(let e of t)l.add(e);this.reinsertNode(e.from,e.to,i),u++}}if(this.stats.reinsertionsApplied+=u,this.stats.iterations=r+1,t&&t(`Reinsertion iter ${r+1}: applied ${u} reinsertions`),u===0)break}return this.stats.timeMs=performance.now()-n,this.stats}};const r={silent:0,error:1,warn:2,info:3,debug:4},i=`info`,a=`rayzeeLogLevel`,o=`rayzeeLogNamespaces`,s=`color:#7c8494`,c=`color:inherit`;let l=null,u=null;function d(e){try{return globalThis.localStorage?.getItem(e)??null}catch{return null}}function f(e,t){try{t===null?globalThis.localStorage?.removeItem(e):globalThis.localStorage?.setItem(e,t)}catch{}}function p(){if(l!==null)return l;let e=globalThis.__RAYZEE_LOG_LEVEL__;return e!==void 0&&e in r?(l=r[e],l):(l=r[d(a)]??r[i],l)}function m(){if(u!==null)return u;let e=globalThis.__RAYZEE_LOG_NS__??d(o);return u=e?String(e).split(`,`).map(e=>e.trim()).filter(Boolean):[],u}function h(e,t){if(t<r.debug)return!0;let n=m();return n.length===0||n.some(t=>e===t||e.startsWith(`${t}:`))}function g(e,t,n){if(e>p()||!h(t,e))return;let i=e===r.error?console.error:e===r.warn?console.warn:console.log,a=`[${t}]`;typeof n[0]==`string`?i(`%c${a}%c ${n[0]}`,s,c,...n.slice(1)):i(`%c${a}`,s,...n)}const _={n:e=>Number(e).toLocaleString(`en-US`),ms:e=>e<10?`${Number(e).toFixed(1)} ms`:`${Math.round(e)} ms`,mb:e=>{let t=e/(1024*1024);return t<10?`${t.toFixed(1)} MB`:`${Math.round(t)} MB`},px:(e,t)=>`${e}×${t}`,count:(e,t,n=`${t}s`)=>`${_.n(e)} ${Number(e)===1?t:n}`,list:e=>e.filter(Boolean).join(` · `)},v={levels:r,setLevel(e){return e in r?(globalThis.__RAYZEE_LOG_LEVEL__=e,l=r[e],f(a,e===i?null:e),e):(console.warn(`[log] unknown level '${e}' — expected one of ${Object.keys(r).join(`, `)}`),this.getLevel())},getLevel(){let e=p();return Object.keys(r).find(t=>r[t]===e)},isEnabled(e){return(r[e]??r.debug)<=p()},only(...e){let t=e.flat().filter(Boolean);return u=t,globalThis.__RAYZEE_LOG_NS__=t.join(`,`),f(o,t.length?t.join(`,`):null),t.length&&this.setLevel(`debug`),t},refresh(){return l=null,u=null,this.getLevel()}};function y(e){return{namespace:e,error:(...t)=>g(r.error,e,t),warn:(...t)=>g(r.warn,e,t),info:(...t)=>g(r.info,e,t),debug:(...t)=>g(r.debug,e,t),isEnabled:e=>v.isEnabled(e),summary(t,n=[]){let i=n.filter(Boolean);if(i.length===0||!console.groupCollapsed){g(r.info,e,[t]),i.forEach(t=>g(r.debug,e,[t]));return}r.info>p()||((p()>=r.debug&&console.group?console.group:console.groupCollapsed)(`%c[${e}]%c ${t}`,s,c),i.forEach(e=>console.log(e)),console.groupEnd())}}}function b(e){e&&e in r&&(globalThis.__RAYZEE_LOG_LEVEL__=e,l=r[e])}const x=y(`bvh`),S={FLOATS_PER_TRIANGLE:32,POSITION_A_OFFSET:0,POSITION_B_OFFSET:4,POSITION_C_OFFSET:8,NORMAL_A_OFFSET:12,NORMAL_B_OFFSET:16,NORMAL_C_OFFSET:20,UV_AB_OFFSET:24,UV_C_MAT_OFFSET:28},C=S.FLOATS_PER_TRIANGLE;var w=class{constructor(){this.minX=0,this.minY=0,this.minZ=0,this.maxX=0,this.maxY=0,this.maxZ=0,this.leftChild=null,this.rightChild=null,this.triangleOffset=0,this.triangleCount=0}},T=class{constructor(){this.useWorker=!0,this.maxLeafSize=8,this.numBins=32,this.minBins=8,this.maxBins=64,this.totalNodes=0,this.processedTriangles=0,this.totalTriangles=0,this.lastProgressUpdate=0,this.progressUpdateInterval=100,this.traversalCost=1,this.intersectionCost=2.5,this.useMortonCodes=!0,this.mortonBits=10,this.mortonClusterThreshold=128,this.enableObjectMedianFallback=!0,this.enableSpatialMedianFallback=!0,this.splitStats={sahSplits:0,objectMedianSplits:0,spatialMedianSplits:0,failedSplits:0,avgBinsUsed:0,totalSplitAttempts:0,mortonSortTime:0,totalBuildTime:0,treeletOptimizationTime:0,treeletsProcessed:0,treeletsImproved:0,averageSAHImprovement:0,reinsertionOptimizationTime:0,reinsertionsApplied:0,reinsertionIterations:0},this.enableTreeletOptimization=!1,this.treeletSize=5,this.treeletOptimizationPasses=1,this.treeletMinImprovement=.02,this.treeletComplexityThreshold=5e4,this.enableReinsertionOptimization=!0,this.reinsertionBatchSizeRatio=.02,this.reinsertionMaxIterations=2,this.initializeBinArrays(),this._partResult={mid:0,lMinX:0,lMinY:0,lMinZ:0,lMaxX:0,lMaxY:0,lMaxZ:0,rMinX:0,rMinY:0,rMinZ:0,rMaxX:0,rMaxY:0,rMaxZ:0},this.centroids=null,this.bMin=null,this.bMax=null,this.indices=null,this.mortonCodes=null,this.triangles=null,this.reorderedTriangleData=null}initializeBinArrays(){let e=this.maxBins;this.binBoundsMin=new Float32Array(e*3),this.binBoundsMax=new Float32Array(e*3),this.binCounts=new Uint32Array(e),this.leftPrefixMin=new Float32Array(e*3),this.leftPrefixMax=new Float32Array(e*3),this.leftPrefixCount=new Uint32Array(e),this.rightPrefixMin=new Float32Array(e*3),this.rightPrefixMax=new Float32Array(e*3),this.rightPrefixCount=new Uint32Array(e)}getOptimalBinCount(e){return e<=16?this.minBins:e<=64?16:e<=256?32:e<=1024?48:this.maxBins}setAdaptiveBinConfig(e){e.minBins!==void 0&&(this.minBins=Math.max(4,e.minBins)),e.maxBins!==void 0&&(this.maxBins=Math.min(128,e.maxBins)),e.baseBins!==void 0&&(this.numBins=e.baseBins),e.maxBins!==void 0&&this.initializeBinArrays()}setMortonConfig(e){e.enabled!==void 0&&(this.useMortonCodes=e.enabled),e.bits!==void 0&&(this.mortonBits=Math.max(6,Math.min(10,e.bits))),e.threshold!==void 0&&(this.mortonClusterThreshold=Math.max(16,e.threshold))}setFallbackConfig(e){e.objectMedian!==void 0&&(this.enableObjectMedianFallback=e.objectMedian),e.spatialMedian!==void 0&&(this.enableSpatialMedianFallback=e.spatialMedian)}setTreeletConfig(e){e.enabled!==void 0&&(this.enableTreeletOptimization=e.enabled),e.size!==void 0&&(this.treeletSize=Math.max(3,Math.min(12,e.size))),e.passes!==void 0&&(this.treeletOptimizationPasses=Math.max(1,Math.min(3,e.passes))),e.minImprovement!==void 0&&(this.treeletMinImprovement=Math.max(.001,e.minImprovement)),e.complexityThreshold!==void 0&&(this.treeletComplexityThreshold=e.complexityThreshold)}disableTreeletOptimization(){this.enableTreeletOptimization=!1}setReinsertionConfig(e){e.enabled!==void 0&&(this.enableReinsertionOptimization=e.enabled),e.batchSizeRatio!==void 0&&(this.reinsertionBatchSizeRatio=Math.max(.005,Math.min(.1,e.batchSizeRatio))),e.maxIterations!==void 0&&(this.reinsertionMaxIterations=Math.max(1,Math.min(5,e.maxIterations)))}initializeTriangleArrays(){let e=this.totalTriangles,t=this.triangles,n=S.POSITION_A_OFFSET,r=S.POSITION_B_OFFSET,i=S.POSITION_C_OFFSET;for(let a=0;a<e;a++){let e=a*C,o=t[e+n],s=t[e+n+1],c=t[e+n+2],l=t[e+r],u=t[e+r+1],d=t[e+r+2],f=t[e+i],p=t[e+i+1],m=t[e+i+2],h=a*3;this.centroids[h]=(o+l+f)/3,this.centroids[h+1]=(s+u+p)/3,this.centroids[h+2]=(c+d+m)/3,this.bMin[h]=o<l?o<f?o:f:l<f?l:f,this.bMin[h+1]=s<u?s<p?s:p:u<p?u:p,this.bMin[h+2]=c<d?c<m?c:m:d<m?d:m,this.bMax[h]=o>l?o>f?o:f:l>f?l:f,this.bMax[h+1]=s>u?s>p?s:p:u>p?u:p,this.bMax[h+2]=c>d?c>m?c:m:d>m?d:m,this.indices[a]=a}}expandBits(e){return e=e*65537&4278190335,e=e*257&251719695,e=e*17&3272356035,e=e*5&1227133513,e}morton3D(e,t,n){return(this.expandBits(n)<<2)+(this.expandBits(t)<<1)+this.expandBits(e)}computeMortonCodeForIndex(e,t,n,r,i,a,o){let s=this.centroids,c=e*3,l=(1<<this.mortonBits)-1,u=i>0?(s[c]-t)/i:0,d=a>0?(s[c+1]-n)/a:0,f=o>0?(s[c+2]-r)/o:0,p=Math.max(0,Math.min(l,Math.floor(u*l))),m=Math.max(0,Math.min(l,Math.floor(d*l))),h=Math.max(0,Math.min(l,Math.floor(f*l)));return this.morton3D(p,m,h)}sortTrianglesByMortonCode(){let e=this.totalTriangles;if(!this.useMortonCodes||e<this.mortonClusterThreshold)return;let t=performance.now(),n=this.centroids,r=this.indices,i=1/0,a=1/0,o=1/0,s=-1/0,c=-1/0,l=-1/0;for(let t=0;t<e;t++){let e=r[t]*3,u=n[e],d=n[e+1],f=n[e+2];u<i&&(i=u),d<a&&(a=d),f<o&&(o=f),u>s&&(s=u),d>c&&(c=d),f>l&&(l=f)}let u=s-i,d=c-a,f=l-o,p=this.mortonCodes,m=(1<<this.mortonBits)-1,h=u>0?m/u:0,g=d>0?m/d:0,_=f>0?m/f:0;for(let t=0;t<e;t++){let e=r[t],s=e*3,c=(n[s]-i)*h,l=(n[s+1]-a)*g,u=(n[s+2]-o)*_;c=c<0?0:(c>m?m:c)|0,l=l<0?0:(l>m?m:l)|0,u=u<0?0:(u>m?m:u)|0,c=c*65537&4278190335,c=c*257&251719695,c=c*17&3272356035,c=c*5&1227133513,l=l*65537&4278190335,l=l*257&251719695,l=l*17&3272356035,l=l*5&1227133513,u=u*65537&4278190335,u=u*257&251719695,u=u*17&3272356035,u=u*5&1227133513,p[e]=(u<<2)+(l<<1)+c}let v=new Uint32Array(e),y=new Uint32Array(256);for(let t=0;t<32;t+=8){y.fill(0);for(let n=0;n<e;n++)y[p[r[n]]>>>t&255]++;let n=0;for(let e=0;e<256;e++){let t=y[e];y[e]=n,n+=t}for(let n=0;n<e;n++){let e=p[r[n]]>>>t&255;v[y[e]++]=r[n]}r.set(v)}this.splitStats.mortonSortTime+=performance.now()-t}build(e,t=30,n=null){if(this.totalTriangles=e.byteLength/(C*4),this.processedTriangles=0,this.lastProgressUpdate=performance.now(),!(this.useWorker&&null))return new Promise(r=>{r(this._buildSyncAndFlatten(e,t,n))})}_buildSyncAndFlatten(e,t,n){let r=this.buildSync(e,t,n);return{bvhData:this.flattenBVH(r),bvhRoot:!0,reorderedTriangles:this.reorderedTriangleData||null,originalToBvh:this.originalToBvhMap||null}}buildSync(t,r=30,i=null,a=null){let o=performance.now();this.totalNodes=0,this.processedTriangles=0,this.triangles=t,this.totalTriangles=t.byteLength/(C*4),this.lastProgressUpdate=performance.now(),this.splitStats={sahSplits:0,objectMedianSplits:0,spatialMedianSplits:0,failedSplits:0,avgBinsUsed:0,totalSplitAttempts:0,mortonSortTime:0,totalBuildTime:0,treeletOptimizationTime:0,treeletsProcessed:0,treeletsImproved:0,averageSAHImprovement:0,reinsertionOptimizationTime:0,reinsertionsApplied:0,reinsertionIterations:0,saOrderTime:0,initTime:0,sahBuildTime:0,reorderTime:0};let s=this.totalTriangles,c=performance.now();this.centroids=new Float32Array(s*3),this.bMin=new Float32Array(s*3),this.bMax=new Float32Array(s*3),this.indices=new Uint32Array(s),this.mortonCodes=new Uint32Array(s),this.initializeTriangleArrays(),this.splitStats.initTime=performance.now()-c,this.sortTrianglesByMortonCode();let l=performance.now(),u=this.buildNodeRecursive(0,s,r,i);if(this.splitStats.sahBuildTime=performance.now()-l,this.enableTreeletOptimization&&this.totalTriangles>1e3){let t=this.totalTriangles>this.treeletComplexityThreshold?3:this.treeletSize,n=new e(this.traversalCost,this.intersectionCost);n.setTreeletSize(t),n.setMinImprovement(this.treeletMinImprovement);let r=performance.now();for(let e=0;e<this.treeletOptimizationPasses;e++){let t=i?t=>{i(`Treelet optimization pass ${e+1}/${this.treeletOptimizationPasses}: ${t}`)}:null;try{n.optimizeBVH(u,t)}catch(t){x.error(`treelet optimizer failed in pass ${e+1}:`,t);break}let a=n.getStatistics(),o=performance.now()-r;if(a.treeletsImproved===0&&e>0||o>15e3)break}let a=performance.now()-r;this.splitStats.treeletOptimizationTime=a;let o=n.getStatistics();this.splitStats.treeletsProcessed=o.treeletsProcessed,this.splitStats.treeletsImproved=o.treeletsImproved,this.splitStats.averageSAHImprovement=o.averageSAHImprovement}if(this.enableReinsertionOptimization&&this.totalTriangles>1e3){let e=new n(this.traversalCost,this.intersectionCost);e.setBatchSizeRatio(this.reinsertionBatchSizeRatio),e.setMaxIterations(this.reinsertionMaxIterations);let t=i?e=>{i(e)}:null;try{e.optimizeBVH(u,t)}catch(e){x.error(`reinsertion optimizer failed:`,e)}let r=e.getStatistics();this.splitStats.reinsertionOptimizationTime=r.timeMs,this.splitStats.reinsertionsApplied=r.reinsertionsApplied,this.splitStats.reinsertionIterations=r.iterations}let d=performance.now();this.applySAOrdering(u),this.splitStats.saOrderTime=performance.now()-d;let f=performance.now(),p=this.triangles,m=a||new Float32Array(s*C);for(let e=0;e<s;e++){let t=this.indices[e]*C,n=e*C;m.set(p.subarray(t,t+C),n)}this.reorderedTriangleData=m;let h=new Uint32Array(s);for(let e=0;e<s;e++)h[this.indices[e]]=e;this.originalToBvhMap=h,this.splitStats.reorderTime=performance.now()-f,this.splitStats.totalBuildTime=performance.now()-o;let g=this.splitStats.totalBuildTime,v=this.splitStats;return x.debug(`${_.n(s)} tris → ${_.n(this.totalNodes)} nodes in ${_.ms(g)} | SAH ${v.sahSplits} objMed ${v.objectMedianSplits} spatMed ${v.spatialMedianSplits} failed ${v.failedSplits}`+(v.treeletsProcessed?` | treelets ${v.treeletsImproved}/${v.treeletsProcessed} improved`:``)+(v.reinsertionsApplied?` | reinsertions ${v.reinsertionsApplied}`:``)),i&&i(100),this.centroids=null,this.bMin=null,this.bMax=null,this.mortonCodes=null,u}updateProgress(e,t){if(!t)return;this.processedTriangles+=e;let n=performance.now();n-this.lastProgressUpdate<this.progressUpdateInterval||(this.lastProgressUpdate=n,t(Math.min(Math.floor(this.processedTriangles/this.totalTriangles*100),99)))}buildNodeRecursiveToDepth(e,t,n,r,i,a,o,s,c,l,u){let d=new w;this.totalNodes++;let f=t-e;if(a===void 0?this.updateNodeBounds(d,e,t):(d.minX=a,d.minY=o,d.minZ=s,d.maxX=c,d.maxY=l,d.maxZ=u),f<=this.maxLeafSize||n<=0)return d.triangleOffset=e,d.triangleCount=f,this.updateProgress(f,i),d;if(r<=0&&f>this.maxLeafSize*16){let r=this.frontierTasks.length;return d.triangleOffset=e,d.triangleCount=f,d.isFrontier=!0,d.frontierTaskId=r,this.frontierTasks.push({taskId:r,start:e,end:t,depth:n,preMinX:d.minX,preMinY:d.minY,preMinZ:d.minZ,preMaxX:d.maxX,preMaxY:d.maxY,preMaxZ:d.maxZ}),d}let p=this.findBestSplitPositionSAH(e,t,d);if(!p.success){if(this.splitStats.failedSplits++,r>0||f<=this.maxLeafSize*16)return d.triangleOffset=e,d.triangleCount=f,this.updateProgress(f,i),d;let a=this.frontierTasks.length;return d.triangleOffset=e,d.triangleCount=f,d.isFrontier=!0,d.frontierTaskId=a,this.frontierTasks.push({taskId:a,start:e,end:t,depth:n,preMinX:d.minX,preMinY:d.minY,preMinZ:d.minZ,preMaxX:d.maxX,preMaxY:d.maxY,preMaxZ:d.maxZ}),d}p.method===`SAH`?this.splitStats.sahSplits++:p.method===`object_median`?this.splitStats.objectMedianSplits++:p.method===`spatial_median`&&this.splitStats.spatialMedianSplits++,this.partitionWithBounds(e,t,p.axis,p.pos);let m=this._partResult,h=m.mid,g=m.lMinX,_=m.lMinY,v=m.lMinZ,y=m.lMaxX,b=m.lMaxY,x=m.lMaxZ,S=m.rMinX,C=m.rMinY,T=m.rMinZ,E=m.rMaxX,D=m.rMaxY,O=m.rMaxZ;return h===e||h===t?(d.triangleOffset=e,d.triangleCount=f,this.updateProgress(f,i),d):(d.leftChild=this.buildNodeRecursiveToDepth(e,h,n-1,r-1,i,g,_,v,y,b,x),d.rightChild=this.buildNodeRecursiveToDepth(h,t,n-1,r-1,i,S,C,T,E,D,O),d)}buildNodeRecursive(e,t,n,r,i,a,o,s,c,l){let u=new w;this.totalNodes++;let d=t-e;if(i===void 0?this.updateNodeBounds(u,e,t):(u.minX=i,u.minY=a,u.minZ=o,u.maxX=s,u.maxY=c,u.maxZ=l),d<=this.maxLeafSize||n<=0)return u.triangleOffset=e,u.triangleCount=d,this.updateProgress(d,r),u;let f=this.findBestSplitPositionSAH(e,t,u);if(!f.success)return this.splitStats.failedSplits++,u.triangleOffset=e,u.triangleCount=d,this.updateProgress(d,r),u;f.method===`SAH`?this.splitStats.sahSplits++:f.method===`object_median`?this.splitStats.objectMedianSplits++:f.method===`spatial_median`&&this.splitStats.spatialMedianSplits++,this.partitionWithBounds(e,t,f.axis,f.pos);let p=this._partResult,m=p.mid,h=p.lMinX,g=p.lMinY,_=p.lMinZ,v=p.lMaxX,y=p.lMaxY,b=p.lMaxZ,x=p.rMinX,S=p.rMinY,C=p.rMinZ,T=p.rMaxX,E=p.rMaxY,D=p.rMaxZ;return m===e||m===t?(u.triangleOffset=e,u.triangleCount=d,this.updateProgress(d,r),u):(u.leftChild=this.buildNodeRecursive(e,m,n-1,r,h,g,_,v,y,b),u.rightChild=this.buildNodeRecursive(m,t,n-1,r,x,S,C,T,E,D),u)}partitionWithBounds(e,t,n,r){let i=this.indices,a=this.centroids,o=this.bMin,s=this.bMax,c=e,l=t-1,u=1/0,d=1/0,f=1/0,p=-1/0,m=-1/0,h=-1/0,g=1/0,_=1/0,v=1/0,y=-1/0,b=-1/0,x=-1/0;for(;c<=l;){let e=i[c],t=e*3;a[t+n]<=r?(o[t]<u&&(u=o[t]),o[t+1]<d&&(d=o[t+1]),o[t+2]<f&&(f=o[t+2]),s[t]>p&&(p=s[t]),s[t+1]>m&&(m=s[t+1]),s[t+2]>h&&(h=s[t+2]),c++):(o[t]<g&&(g=o[t]),o[t+1]<_&&(_=o[t+1]),o[t+2]<v&&(v=o[t+2]),s[t]>y&&(y=s[t]),s[t+1]>b&&(b=s[t+1]),s[t+2]>x&&(x=s[t+2]),i[c]=i[l],i[l]=e,l--)}let S=this._partResult;return S.mid=c,S.lMinX=u,S.lMinY=d,S.lMinZ=f,S.lMaxX=p,S.lMaxY=m,S.lMaxZ=h,S.rMinX=g,S.rMinY=_,S.rMinZ=v,S.rMaxX=y,S.rMaxY=b,S.rMaxZ=x,S}updateNodeBounds(e,t,n){let r=1/0,i=1/0,a=1/0,o=-1/0,s=-1/0,c=-1/0,l=this.indices,u=this.bMin,d=this.bMax;for(let e=t;e<n;e++){let t=l[e]*3;u[t]<r&&(r=u[t]),u[t+1]<i&&(i=u[t+1]),u[t+2]<a&&(a=u[t+2]),d[t]>o&&(o=d[t]),d[t+1]>s&&(s=d[t+1]),d[t+2]>c&&(c=d[t+2])}e.minX=r,e.minY=i,e.minZ=a,e.maxX=o,e.maxY=s,e.maxZ=c}findBestSplitPositionSAH(e,t,n){let r=1/0,i=-1,a=0,o=this.computeSurfaceAreaFlat(n.minX,n.minY,n.minZ,n.maxX,n.maxY,n.maxZ),s=t-e,c=this.intersectionCost*s,l=this.getOptimalBinCount(s);this.splitStats.totalSplitAttempts++,this.splitStats.avgBinsUsed=(this.splitStats.avgBinsUsed*(this.splitStats.totalSplitAttempts-1)+l)/this.splitStats.totalSplitAttempts;let u=this.indices,d=this.centroids,f=this.bMin,p=this.bMax,m=this.binBoundsMin,h=this.binBoundsMax,g=this.binCounts,_=this.leftPrefixMin,v=this.leftPrefixMax,y=this.leftPrefixCount,b=this.rightPrefixMin,x=this.rightPrefixMax,S=this.rightPrefixCount,C=1/0,w=-1/0,T=1/0,E=-1/0,D=1/0,O=-1/0;for(let n=e;n<t;n++){let e=u[n]*3,t=d[e],r=d[e+1],i=d[e+2];t<C&&(C=t),t>w&&(w=t),r<T&&(T=r),r>E&&(E=r),i<D&&(D=i),i>O&&(O=i)}let k=[C,T,D],A=[w,E,O];for(let n=0;n<3;n++){let s=k[n],C=A[n];if(C-s<1e-6)continue;for(let e=0;e<l;e++){g[e]=0;let t=e*3;m[t]=1/0,m[t+1]=1/0,m[t+2]=1/0,h[t]=-1/0,h[t+1]=-1/0,h[t+2]=-1/0}let w=l/(C-s);for(let r=e;r<t;r++){let e=u[r],t=d[e*3+n],i=Math.floor((t-s)*w);i>=l&&(i=l-1),g[i]++;let a=i*3,o=e*3;f[o]<m[a]&&(m[a]=f[o]),f[o+1]<m[a+1]&&(m[a+1]=f[o+1]),f[o+2]<m[a+2]&&(m[a+2]=f[o+2]),p[o]>h[a]&&(h[a]=p[o]),p[o+1]>h[a+1]&&(h[a+1]=p[o+1]),p[o+2]>h[a+2]&&(h[a+2]=p[o+2])}y[0]=g[0],_[0]=m[0],_[1]=m[1],_[2]=m[2],v[0]=h[0],v[1]=h[1],v[2]=h[2];for(let e=1;e<l;e++){let t=e*3,n=(e-1)*3;y[e]=y[e-1]+g[e];let r=_[n],i=m[t],a=_[n+1],o=m[t+1],s=_[n+2],c=m[t+2];_[t]=r<i?r:i,_[t+1]=a<o?a:o,_[t+2]=s<c?s:c;let l=v[n],u=h[t],d=v[n+1],f=h[t+1],p=v[n+2],b=h[t+2];v[t]=l>u?l:u,v[t+1]=d>f?d:f,v[t+2]=p>b?p:b}let T=l-1,E=T*3;S[T]=g[T],b[E]=m[E],b[E+1]=m[E+1],b[E+2]=m[E+2],x[E]=h[E],x[E+1]=h[E+1],x[E+2]=h[E+2];for(let e=T-1;e>=0;e--){let t=e*3,n=(e+1)*3;S[e]=S[e+1]+g[e];let r=b[n],i=m[t],a=b[n+1],o=m[t+1],s=b[n+2],c=m[t+2];b[t]=r<i?r:i,b[t+1]=a<o?a:o,b[t+2]=s<c?s:c;let l=x[n],u=h[t],d=x[n+1],f=h[t+1],p=x[n+2],_=h[t+2];x[t]=l>u?l:u,x[t+1]=d>f?d:f,x[t+2]=p>_?p:_}for(let e=1;e<l;e++){let t=(e-1)*3,u=e*3,d=y[e-1],f=S[e];if(d===0||f===0)continue;let p=v[t]-_[t],m=v[t+1]-_[t+1],h=v[t+2]-_[t+2],g=2*(p*m+m*h+h*p),w=x[u]-b[u],T=x[u+1]-b[u+1],E=x[u+2]-b[u+2],D=2*(w*T+T*E+E*w),O=this.traversalCost+g/o*d*this.intersectionCost+D/o*f*this.intersectionCost;O<r&&O<c&&(r=O,i=n,a=s+(C-s)*e/l)}}return i===-1?this.enableObjectMedianFallback?this.findObjectMedianSplit(e,t):this.enableSpatialMedianFallback?this.findSpatialMedianSplit(e,t):{success:!1,method:`fallbacks_disabled`}:{success:!0,axis:i,pos:a,method:`SAH`,binsUsed:l}}findObjectMedianSplit(e,t){let n=this.indices,r=this.centroids,i=-1,a=-1;for(let o=0;o<3;o++){let s=1/0,c=-1/0;for(let i=e;i<t;i++){let e=r[n[i]*3+o];e<s&&(s=e),e>c&&(c=e)}let l=c-s;l>a&&(a=l,i=o)}if(i===-1||a<1e-10)return this.enableSpatialMedianFallback?this.findSpatialMedianSplit(e,t):{success:!1,method:`object_median_failed`};let o=t-e,s=e+Math.floor(o/2);this.quickselect(e,t,s,i);let c=r[n[s]*3+i],l=!0;for(let e=s+1;e<t;e++)if(r[n[e]*3+i]>c){l=!1;break}if(l){let a=-1/0;for(let t=e;t<s;t++){let e=r[n[t]*3+i];e>a&&(a=e)}if(a<c)c=(a+c)*.5;else return this.enableSpatialMedianFallback?this.findSpatialMedianSplit(e,t):{success:!1,method:`object_median_degenerate`}}return{success:!0,axis:i,pos:c,method:`object_median`}}findSpatialMedianSplit(e,t){let n=this.indices,r=this.centroids,i=this.bMin,a=this.bMax,o=-1,s=-1,c=0,l=0;for(let r=0;r<3;r++){let u=1/0,d=-1/0;for(let o=e;o<t;o++){let e=n[o]*3+r;i[e]<u&&(u=i[e]),a[e]>d&&(d=a[e])}let f=d-u;f>s&&(s=f,o=r,c=u,l=d)}if(o===-1||s<1e-12)return{success:!1,method:`spatial_median_failed`};let u=(c+l)*.5,d=t-e,f=0;for(let i=e;i<t;i++)r[n[i]*3+o]<=u&&f++;if(f===0||f===d){let i=e+Math.floor(d/2);this.quickselect(e,t,i,o);let a=r[n[i]*3+o],s=!0;for(let i=e;i<t;i++)if(r[n[i]*3+o]!==a){s=!1;break}if(s)return{success:!1,method:`spatial_median_degenerate`};let c=-1/0;for(let t=e;t<i;t++){let e=r[n[t]*3+o];e>c&&(c=e)}if(c<a)u=(c+a)*.5;else{let e=1/0;for(let a=i+1;a<t;a++){let t=r[n[a]*3+o];t<e&&(e=t)}u=(a+e)*.5}}return{success:!0,axis:o,pos:u,method:`spatial_median`}}quickselect(e,t,n,r){let i=this.indices,a=this.centroids,o=e,s=t-1;for(;o<s;){let e=o+s>>>1,t=a[i[o]*3+r],c=a[i[e]*3+r],l=a[i[s]*3+r];if(t>c){let t=i[o];i[o]=i[e],i[e]=t}if(t>l){let e=i[o];i[o]=i[s],i[s]=e}if(c>l){let t=i[e];i[e]=i[s],i[s]=t}let u=a[i[e]*3+r],d=o,f=s;for(;d<=f;){for(;a[i[d]*3+r]<u;)d++;for(;a[i[f]*3+r]>u;)f--;if(d<=f){let e=i[d];i[d]=i[f],i[f]=e,d++,f--}}f<n&&(o=d),d>n&&(s=f)}}applySAOrdering(e){if(!e||!e.leftChild)return;let t=[e],n=[];for(;t.length>0;){let e=t.pop();!e.leftChild||!e.rightChild||(n.push(e),t.push(e.leftChild),t.push(e.rightChild))}for(let e=n.length-1;e>=0;e--){let t=n[e],r=t.leftChild,i=t.rightChild,a=r.maxX-r.minX,o=r.maxY-r.minY,s=r.maxZ-r.minZ,c=i.maxX-i.minX,l=i.maxY-i.minY,u=i.maxZ-i.minZ;c*l+l*u+u*c>a*o+o*s+s*a&&(t.leftChild=i,t.rightChild=r)}}flattenBVH(e){let t=[],n=[e];for(;n.length>0;){let e=n.pop();e._flatIndex=t.length,t.push(e),e.rightChild&&n.push(e.rightChild),e.leftChild&&n.push(e.leftChild)}let r=new Float32Array(t.length*16);for(let e=0;e<t.length;e++){let n=t[e],i=e*16;if(n.leftChild){let e=n.leftChild,t=n.rightChild;r[i]=e.minX,r[i+1]=e.minY,r[i+2]=e.minZ,r[i+3]=e._flatIndex,r[i+4]=e.maxX,r[i+5]=e.maxY,r[i+6]=e.maxZ,r[i+7]=t._flatIndex,r[i+8]=t.minX,r[i+9]=t.minY,r[i+10]=t.minZ,r[i+12]=t.maxX,r[i+13]=t.maxY,r[i+14]=t.maxZ}else r[i]=n.triangleOffset,r[i+1]=n.triangleCount,r[i+3]=-1}return r}flattenBVHWithFrontier(e){let t=[],n=[e];for(;n.length>0;){let e=n.pop();e._flatIndex=t.length,t.push(e),e.rightChild&&n.push(e.rightChild),e.leftChild&&n.push(e.leftChild)}let r=new Float32Array(t.length*16),i=[];for(let e=0;e<t.length;e++){let n=t[e],a=e*16;if(n.leftChild){let e=n.leftChild,t=n.rightChild;r[a]=e.minX,r[a+1]=e.minY,r[a+2]=e.minZ,r[a+3]=e._flatIndex,r[a+4]=e.maxX,r[a+5]=e.maxY,r[a+6]=e.maxZ,r[a+7]=t._flatIndex,r[a+8]=t.minX,r[a+9]=t.minY,r[a+10]=t.minZ,r[a+12]=t.maxX,r[a+13]=t.maxY,r[a+14]=t.maxZ}else if(n.isFrontier){let t=n.frontierTaskId;r[a]=n.triangleOffset,r[a+1]=n.triangleCount,r[a+2]=t,r[a+3]=-2,i.push({taskId:t,flatIndex:e})}else r[a]=n.triangleOffset,r[a+1]=n.triangleCount,r[a+3]=-1}return{flatData:r,frontierMap:i,nodeCount:t.length}}assembleParallelBVH(e,t,n,r){let i=[...r].sort((e,t)=>e.taskId-t.taskId),a=t;for(let e=0;e<i.length;e++)a+=i[e].nodeCount;let o=new Float32Array(a*16);o.set(e);let s=new Map;for(let e of n)s.set(e.taskId,e.flatIndex);let c=t;for(let e=0;e<i.length;e++){let t=i[e],n=t.flatData,r=t.nodeCount,a=c*16;o.set(n,a);for(let e=0;e<r;e++){let t=a+e*16;o[t+3]!==-1&&(o[t+3]+=c,o[t+7]+=c)}let l=s.get(t.taskId);if(l!==void 0){let e=l*16,t=a;for(let n=0;n<16;n++)o[e+n]=o[t+n]}c+=r}return o}computeSurfaceAreaFlat(e,t,n,r,i,a){let o=r-e,s=i-t,c=a-n;return 2*(o*s+s*c+c*o)}};const E=y(`bvh`);self.onmessage=function(e){let t=e.data,n=t.type;b(t.logLevel),n===`buildPhase1`?D(t):n===`assemble`?O(t):k(t)};function D(e){let{sharedTriangleData:t,sharedCentroids:n,sharedBMin:r,sharedBMax:i,sharedIndices:a,sharedMortonCodes:o,triangleCount:s,depth:c,parallelDepth:l,reportProgress:u,treeletOptimization:d}=e;try{let e=new T;d&&e.setTreeletConfig(d);let f=u?e=>{self.postMessage({type:`progress`,progress:e})}:null;e.triangles=new Float32Array(t),e.centroids=new Float32Array(n),e.bMin=new Float32Array(r),e.bMax=new Float32Array(i),e.indices=new Uint32Array(a),e.mortonCodes=new Uint32Array(o),e.totalTriangles=s,e.totalNodes=0,e.processedTriangles=0,e.lastProgressUpdate=performance.now(),e.splitStats={sahSplits:0,objectMedianSplits:0,spatialMedianSplits:0,failedSplits:0,avgBinsUsed:0,totalSplitAttempts:0,mortonSortTime:0,totalBuildTime:0,treeletOptimizationTime:0,treeletsProcessed:0,treeletsImproved:0,averageSAHImprovement:0,initTime:0,sahBuildTime:0,reorderTime:0};let p=performance.now(),m=performance.now();e.initializeTriangleArrays(),e.splitStats.initTime=performance.now()-m,e.sortTrianglesByMortonCode(),e.frontierTasks=[];let h=performance.now(),g=e.buildNodeRecursiveToDepth(0,s,c,l,f);e.splitStats.sahBuildTime=performance.now()-h,e.applySAOrdering(g);let v=performance.now(),{flatData:y,frontierMap:b,nodeCount:x}=e.flattenBVHWithFrontier(g),S=performance.now()-v,C=performance.now()-p;E.debug(`phase 1 ${_.ms(C)} (init ${_.ms(e.splitStats.initTime)} · morton ${_.ms(e.splitStats.mortonSortTime)} · SAH ${_.ms(e.splitStats.sahBuildTime)} · flatten ${_.ms(S)}) · ${e.frontierTasks.length} frontier tasks`),self.postMessage({type:`phase1Result`,topFlatData:y,topNodeCount:x,frontierTasks:e.frontierTasks,frontierMap:b,splitStats:e.splitStats},[y.buffer])}catch(e){E.error(`phase 1 failed:`,e),self.postMessage({type:`error`,error:e.message})}}function O(e){let{topFlatData:t,topNodeCount:n,frontierMap:r,subtreeResults:i,sharedTriangleData:a,sharedIndices:o,sharedReorderBuffer:s,triangleCount:c}=e;try{let e=performance.now(),l=new T().assembleParallelBVH(t,n,r,i),u=new Uint32Array(o),d=new Float32Array(a),f=new Float32Array(s);for(let e=0;e<c;e++){let t=u[e]*32,n=e*32;f.set(d.subarray(t,t+32),n)}let p=new Uint32Array(c);for(let e=0;e<c;e++)p[u[e]]=e;let m=performance.now()-e;E.debug(`phase 3 assemble + reorder ${_.ms(m)} (${_.mb(l.byteLength)} BVH)`),self.postMessage({type:`assembleResult`,bvhData:l,originalToBvh:p,triangleCount:c},[l.buffer,p.buffer])}catch(e){E.error(`assembly failed:`,e),self.postMessage({type:`error`,error:e.message})}}function k(e){let{triangleData:t,triangleByteOffset:n,triangleByteLength:r,depth:i,reportProgress:a,treeletOptimization:o,reinsertionOptimization:s,sharedReorderBuffer:c,maxLeafSize:l,numBins:u,maxBins:d,minBins:f}=e,p=new T;l!==void 0&&(p.maxLeafSize=l),u!==void 0&&(p.numBins=u),d!==void 0&&(p.maxBins=d),f!==void 0&&(p.minBins=f);try{o&&p.setTreeletConfig(o),s&&p.setReinsertionConfig(s);let e=a?e=>{self.postMessage({progress:e})}:null,l=n===void 0?new Float32Array(t):new Float32Array(t,n,r/4),u=c?new Float32Array(c):null,d=p.buildSync(l,i,e,u),f=performance.now(),m=p.flattenBVH(d),h=performance.now()-f;E.debug(`flatten ${_.ms(h)} (${_.mb(m.byteLength)})`);let g=p.originalToBvhMap||null;if(c){let e=[m.buffer];g&&e.push(g.buffer),self.postMessage({bvhData:m,originalToBvh:g,triangleCount:l.length/32,treeletStats:p.splitStats},e)}else{let e=p.reorderedTriangleData,t=e.byteLength/128,n=[m.buffer,e.buffer];g&&n.push(g.buffer),self.postMessage({bvhData:m,triangles:e,originalToBvh:g,triangleCount:t,treeletStats:p.splitStats},n)}}catch(e){E.error(`build failed:`,e),self.postMessage({error:e.message})}}", mc = typeof self < "u" && self.Blob && new Blob(["URL.revokeObjectURL(import.meta.url);", pc], { type: "text/javascript;charset=utf-8" });
5541
5546
  function hc(e) {
5542
5547
  let t;
5543
5548
  try {
@@ -5558,7 +5563,7 @@ function hc(e) {
5558
5563
  }
5559
5564
  //#endregion
5560
5565
  //#region src/Processor/Workers/BVHSubtreeWorker.js?worker&inline
5561
- var gc = "var e=class{constructor(e,t){this.traversalCost=e,this.intersectionCost=t,this.maxTreeletLeaves=7,this.minImprovement=.02,this.topologyCache=new Map;for(let e=3;e<=this.maxTreeletLeaves;e++)this.topologyCache.set(e,this.generateTopologies(e));this.stats={treeletsProcessed:0,treeletsImproved:0,totalSAHImprovement:0,averageSAHImprovement:0,optimizationTime:0}}generateTopologies(e){if(e===1)return[0];if(e===2)return[[0,1]];let t=[];for(let n=1;n<e;n++){let r=this.generateTopologies(n),i=this.generateTopologies(e-n);for(let e of r)for(let r of i)t.push([e,this.offsetTopology(r,n)])}return t}offsetTopology(e,t){return typeof e==`number`?e+t:[this.offsetTopology(e[0],t),this.offsetTopology(e[1],t)]}optimizeBVH(e){let t=performance.now();this.stats={treeletsProcessed:0,treeletsImproved:0,totalSAHImprovement:0,averageSAHImprovement:0,optimizationTime:0};let n=this.identifyTreeletRoots(e);for(let e=0;e<n.length;e++){if(performance.now()-t>3e4){console.warn(`TreeletOptimizer: timeout after ${e}/${n.length} treelets`);break}this.optimizeTreelet(n[e])}return this.stats.optimizationTime=performance.now()-t,this.stats.averageSAHImprovement=this.stats.treeletsProcessed>0?this.stats.totalSAHImprovement/this.stats.treeletsProcessed:0,e}identifyTreeletRoots(e){let t=[],n=new Set,r=[{node:e,visited:!1}];for(;r.length>0;){let e=r[r.length-1];if(e.visited){r.pop();let i=e.node;if(i.triangleCount>0||n.has(i))continue;let a=this.countLeaves(i);a>=3&&a<=this.maxTreeletLeaves&&(t.push(i),this.markSubtree(i,n))}else{e.visited=!0;let t=e.node;if(t.triangleCount>0)continue;t.rightChild&&r.push({node:t.rightChild,visited:!1}),t.leftChild&&r.push({node:t.leftChild,visited:!1})}}return t}countLeaves(e){return e?e.triangleCount>0?1:this.countLeaves(e.leftChild)+this.countLeaves(e.rightChild):0}markSubtree(e,t){e&&(t.add(e),!(e.triangleCount>0)&&(this.markSubtree(e.leftChild,t),this.markSubtree(e.rightChild,t)))}optimizeTreelet(e){let t=[];this.extractLeaves(e,t);let n=t.length;if(n<3||n>this.maxTreeletLeaves)return;this.stats.treeletsProcessed++;let r=this.evaluateSubtreeSAH(e),i=this.topologyCache.get(n);if(!i||i.length===0)return;let a=r,o=null,s=null;if(n<=5){let e=this.generatePermutations(n);for(let n of i)for(let r of e){let e=this.evaluateTopology(n,t,r);e<a&&(a=e,o=n,s=r)}}else{let e=Array.from({length:n},(e,t)=>t);for(let n of i){let r=this.evaluateTopology(n,t,e);r<a&&(a=r,o=n,s=e);let i=this.greedySwapOptimize(n,t,e,r);i.cost<a&&(a=i.cost,o=n,s=i.perm)}}let c=(r-a)/r;o&&c>this.minImprovement&&(this.reconstructTreelet(e,o,t,s),this.stats.treeletsImproved++,this.stats.totalSAHImprovement+=c)}extractLeaves(e,t){if(e){if(e.triangleCount>0){t.push({minX:e.minX,minY:e.minY,minZ:e.minZ,maxX:e.maxX,maxY:e.maxY,maxZ:e.maxZ,triangleOffset:e.triangleOffset,triangleCount:e.triangleCount});return}this.extractLeaves(e.leftChild,t),this.extractLeaves(e.rightChild,t)}}evaluateSubtreeSAH(e){if(!e)return 0;if(e.triangleCount>0)return this.surfaceAreaFlat(e.minX,e.minY,e.minZ,e.maxX,e.maxY,e.maxZ)*e.triangleCount*this.intersectionCost;let t=this.evaluateSubtreeSAH(e.leftChild),n=this.evaluateSubtreeSAH(e.rightChild);return this.surfaceAreaFlat(e.minX,e.minY,e.minZ,e.maxX,e.maxY,e.maxZ)*this.traversalCost+t+n}evaluateTopology(e,t,n){return this.evalTopoRecursive(e,t,n).cost}evalTopoRecursive(e,t,n){if(typeof e==`number`){let r=t[n[e]];return{cost:this.surfaceAreaFlat(r.minX,r.minY,r.minZ,r.maxX,r.maxY,r.maxZ)*r.triangleCount*this.intersectionCost,minX:r.minX,minY:r.minY,minZ:r.minZ,maxX:r.maxX,maxY:r.maxY,maxZ:r.maxZ}}let r=this.evalTopoRecursive(e[0],t,n),i=this.evalTopoRecursive(e[1],t,n),a=Math.min(r.minX,i.minX),o=Math.min(r.minY,i.minY),s=Math.min(r.minZ,i.minZ),c=Math.max(r.maxX,i.maxX),l=Math.max(r.maxY,i.maxY),u=Math.max(r.maxZ,i.maxZ);return{cost:this.surfaceAreaFlat(a,o,s,c,l,u)*this.traversalCost+r.cost+i.cost,minX:a,minY:o,minZ:s,maxX:c,maxY:l,maxZ:u}}surfaceAreaFlat(e,t,n,r,i,a){let o=r-e,s=i-t,c=a-n;return 2*(o*s+s*c+c*o)}generatePermutations(e){let t=[],n=Array.from({length:e},(e,t)=>t),r=i=>{if(i===e){t.push([...n]);return}for(let t=i;t<e;t++)[n[i],n[t]]=[n[t],n[i]],r(i+1),[n[i],n[t]]=[n[t],n[i]]};return r(0),t}greedySwapOptimize(e,t,n,r){let i=[...n],a=r,o=!0;for(;o;){o=!1;for(let n=0;n<i.length-1;n++)for(let r=n+1;r<i.length;r++){[i[n],i[r]]=[i[r],i[n]];let s=this.evaluateTopology(e,t,i);s<a?(a=s,o=!0):[i[n],i[r]]=[i[r],i[n]]}}return{perm:i,cost:a}}reconstructTreelet(e,t,n,r){let i=this.buildSubtree(t,n,r);e.minX=i.minX,e.minY=i.minY,e.minZ=i.minZ,e.maxX=i.maxX,e.maxY=i.maxY,e.maxZ=i.maxZ,e.leftChild=i.leftChild,e.rightChild=i.rightChild,e.triangleOffset=i.triangleOffset,e.triangleCount=i.triangleCount}buildSubtree(e,n,r){if(typeof e==`number`){let i=n[r[e]],a=new t;return a.minX=i.minX,a.minY=i.minY,a.minZ=i.minZ,a.maxX=i.maxX,a.maxY=i.maxY,a.maxZ=i.maxZ,a.triangleOffset=i.triangleOffset,a.triangleCount=i.triangleCount,a}let i=this.buildSubtree(e[0],n,r),a=this.buildSubtree(e[1],n,r),o=new t;return o.leftChild=i,o.rightChild=a,o.minX=Math.min(i.minX,a.minX),o.minY=Math.min(i.minY,a.minY),o.minZ=Math.min(i.minZ,a.minZ),o.maxX=Math.max(i.maxX,a.maxX),o.maxY=Math.max(i.maxY,a.maxY),o.maxZ=Math.max(i.maxZ,a.maxZ),o}setTreeletSize(e){this.maxTreeletLeaves=Math.max(3,Math.min(7,e));for(let e=3;e<=this.maxTreeletLeaves;e++)this.topologyCache.has(e)||this.topologyCache.set(e,this.generateTopologies(e))}setMinImprovement(e){this.minImprovement=Math.max(.001,e)}setMaxTreelets(){}getStatistics(){return{...this.stats}}},t=class{constructor(){this.minX=0,this.minY=0,this.minZ=0,this.maxX=0,this.maxY=0,this.maxZ=0,this.leftChild=null,this.rightChild=null,this.triangleOffset=0,this.triangleCount=0}},n=class{constructor(e,t){this.traversalCost=e,this.intersectionCost=t,this.batchSizeRatio=.02,this.maxIterations=2,this.timeBudgetMs=15e3,this.stats={reinsertionsApplied:0,iterations:0,timeMs:0}}setBatchSizeRatio(e){this.batchSizeRatio=Math.max(.005,Math.min(.1,e))}setMaxIterations(e){this.maxIterations=Math.max(1,Math.min(5,e))}getStatistics(){return{...this.stats}}surfaceArea(e){let t=e.maxX-e.minX,n=e.maxY-e.minY,r=e.maxZ-e.minZ;return t*n+n*r+r*t}buildParentMap(e){let t=new Map;t.set(e,{parent:null,isLeft:!1});let n=[e];for(;n.length>0;){let e=n.pop();e.triangleCount>0||(e.leftChild&&(t.set(e.leftChild,{parent:e,isLeft:!0}),n.push(e.leftChild)),e.rightChild&&(t.set(e.rightChild,{parent:e,isLeft:!1}),n.push(e.rightChild)))}return t}findCandidates(e,t,n){let r=[],i=[e];for(;i.length>0;){let a=i.pop();if(a!==e&&n.get(a).parent!==e){let e=this.surfaceArea(a);r.length<t?(r.push({node:a,cost:e}),r.length===t&&this._heapify(r)):e>r[0].cost&&(r[0]={node:a,cost:e},this._siftDown(r,0))}a.triangleCount===0&&(a.leftChild&&i.push(a.leftChild),a.rightChild&&i.push(a.rightChild))}return r}_heapify(e){for(let t=(e.length>>1)-1;t>=0;t--)this._siftDown(e,t)}_siftDown(e,t){let n=e.length;for(;;){let r=t,i=2*t+1,a=2*t+2;if(i<n&&e[i].cost<e[r].cost&&(r=i),a<n&&e[a].cost<e[r].cost&&(r=a),r===t)break;let o=e[t];e[t]=e[r],e[r]=o,t=r}}findReinsertion(e,t,n){let r=n.get(e),i=r.parent;if(!i)return null;let a=r.isLeft?i.rightChild:i.leftChild,o=this.surfaceArea(e),s=this.surfaceArea(i),c=null,l=0,u=s,d=a.minX,f=a.minY,p=a.minZ,m=a.maxX,h=a.maxY,g=a.maxZ,_=a,v=i,y=[];do{for(y.length=0,y.push(u,_);y.length>0;){let t=y.pop(),n=y.pop();if(n-o<=l)continue;let r=Math.min(t.minX,e.minX),i=Math.min(t.minY,e.minY),a=Math.min(t.minZ,e.minZ),s=Math.max(t.maxX,e.maxX),u=Math.max(t.maxY,e.maxY),d=Math.max(t.maxZ,e.maxZ),f=s-r,p=u-i,m=d-a,h=n-(f*p+p*m+m*f);if(h>l&&(c=t,l=h),t.triangleCount===0&&t.leftChild&&t.rightChild){let e=h+this.surfaceArea(t);y.push(e,t.leftChild),y.push(e,t.rightChild)}}let t=n.get(v);if(!t||t.parent===null)break;if(v!==i){d=Math.min(d,_.minX),f=Math.min(f,_.minY),p=Math.min(p,_.minZ),m=Math.max(m,_.maxX),h=Math.max(h,_.maxY),g=Math.max(g,_.maxZ);let e=m-d,t=h-f,n=g-p,r=e*t+t*n+n*e;u+=this.surfaceArea(v)-r}let r=t.parent;_=t.isLeft?r.rightChild:r.leftChild,v=r}while(n.get(v).parent!==null);return c===a||c===i?null:c?{from:e,to:c,areaDiff:l}:null}getConflicts(e,t,n){let r=n.get(e);return[t,e,r.isLeft?r.parent.rightChild:r.parent.leftChild,n.get(t).parent,r.parent]}reinsertNode(e,t,n){let r=n.get(e),i=r.parent,a=r.isLeft?i.rightChild:i.leftChild,o=n.get(i),s=o.parent,c=n.get(t),l=c.parent;o.isLeft?s.leftChild=a:s.rightChild=a,i.leftChild=e,i.rightChild=t,i.triangleOffset=0,i.triangleCount=0,i.minX=Math.min(e.minX,t.minX),i.minY=Math.min(e.minY,t.minY),i.minZ=Math.min(e.minZ,t.minZ),i.maxX=Math.max(e.maxX,t.maxX),i.maxY=Math.max(e.maxY,t.maxY),i.maxZ=Math.max(e.maxZ,t.maxZ),c.isLeft?l.leftChild=i:l.rightChild=i,n.set(a,{parent:s,isLeft:o.isLeft}),n.set(i,{parent:l,isLeft:c.isLeft}),n.set(e,{parent:i,isLeft:!0}),n.set(t,{parent:i,isLeft:!1}),this.refitFrom(s,n),this.refitFrom(l,n)}refitFrom(e,t){let n=e;for(;n;){if(n.triangleCount===0&&n.leftChild&&n.rightChild){let e=n.leftChild,t=n.rightChild;n.minX=Math.min(e.minX,t.minX),n.minY=Math.min(e.minY,t.minY),n.minZ=Math.min(e.minZ,t.minZ),n.maxX=Math.max(e.maxX,t.maxX),n.maxY=Math.max(e.maxY,t.maxY),n.maxZ=Math.max(e.maxZ,t.maxZ)}let e=t.get(n);n=e?e.parent:null}}optimizeBVH(e,t){let n=performance.now();this.stats={reinsertionsApplied:0,iterations:0,timeMs:0};for(let r=0;r<this.maxIterations&&!(performance.now()-n>this.timeBudgetMs);r++){let i=this.buildParentMap(e),a=i.size,o=Math.max(1,Math.floor(a*this.batchSizeRatio));t&&t(`Reinsertion iter ${r+1}/${this.maxIterations}: selecting ${o} candidates`);let s=this.findCandidates(e,o,i),c=[];for(let t=0;t<s.length&&!(performance.now()-n>this.timeBudgetMs);t++){let n=this.findReinsertion(s[t].node,e,i);n&&n.areaDiff>0&&c.push(n)}c.sort((e,t)=>t.areaDiff-e.areaDiff);let l=new Set,u=0;for(let e of c){let t=this.getConflicts(e.from,e.to,i);if(!t.some(e=>l.has(e))){for(let e of t)l.add(e);this.reinsertNode(e.from,e.to,i),u++}}if(this.stats.reinsertionsApplied+=u,this.stats.iterations=r+1,t&&t(`Reinsertion iter ${r+1}: applied ${u} reinsertions`),u===0)break}return this.stats.timeMs=performance.now()-n,this.stats}};const r={silent:0,error:1,warn:2,info:3,debug:4},i=`info`,a=`rayzeeLogLevel`,o=`rayzeeLogNamespaces`,s=`color:#7c8494`,c=`color:inherit`;let l=null,u=null;function d(e){try{return globalThis.localStorage?.getItem(e)??null}catch{return null}}function f(e,t){try{t===null?globalThis.localStorage?.removeItem(e):globalThis.localStorage?.setItem(e,t)}catch{}}function p(){if(l!==null)return l;let e=globalThis.__RAYZEE_LOG_LEVEL__;return e!==void 0&&e in r?(l=r[e],l):(l=r[d(a)]??r[i],l)}function m(){if(u!==null)return u;let e=globalThis.__RAYZEE_LOG_NS__??d(o);return u=e?String(e).split(`,`).map(e=>e.trim()).filter(Boolean):[],u}function h(e,t){if(t<r.debug)return!0;let n=m();return n.length===0||n.some(t=>e===t||e.startsWith(`${t}:`))}function g(e,t,n){if(e>p()||!h(t,e))return;let i=e===r.error?console.error:e===r.warn?console.warn:console.log,a=`[${t}]`;typeof n[0]==`string`?i(`%c${a}%c ${n[0]}`,s,c,...n.slice(1)):i(`%c${a}`,s,...n)}const _={n:e=>Number(e).toLocaleString(`en-US`),ms:e=>e<10?`${Number(e).toFixed(1)} ms`:`${Math.round(e)} ms`,mb:e=>{let t=e/(1024*1024);return t<10?`${t.toFixed(1)} MB`:`${Math.round(t)} MB`},px:(e,t)=>`${e}×${t}`,count:(e,t,n=`${t}s`)=>`${_.n(e)} ${Number(e)===1?t:n}`,list:e=>e.filter(Boolean).join(` · `)},v={levels:r,setLevel(e){return e in r?(globalThis.__RAYZEE_LOG_LEVEL__=e,l=r[e],f(a,e===i?null:e),e):(console.warn(`[log] unknown level '${e}' — expected one of ${Object.keys(r).join(`, `)}`),this.getLevel())},getLevel(){let e=p();return Object.keys(r).find(t=>r[t]===e)},isEnabled(e){return(r[e]??r.debug)<=p()},only(...e){let t=e.flat().filter(Boolean);return u=t,globalThis.__RAYZEE_LOG_NS__=t.join(`,`),f(o,t.length?t.join(`,`):null),t.length&&this.setLevel(`debug`),t},refresh(){return l=null,u=null,this.getLevel()}};function y(e){return{namespace:e,error:(...t)=>g(r.error,e,t),warn:(...t)=>g(r.warn,e,t),info:(...t)=>g(r.info,e,t),debug:(...t)=>g(r.debug,e,t),isEnabled:e=>v.isEnabled(e),summary(t,n=[]){let i=n.filter(Boolean);if(i.length===0||!console.groupCollapsed){g(r.info,e,[t]),i.forEach(t=>g(r.debug,e,[t]));return}r.info>p()||((p()>=r.debug&&console.group?console.group:console.groupCollapsed)(`%c[${e}]%c ${t}`,s,c),i.forEach(e=>console.log(e)),console.groupEnd())}}}const b=y(`bvh`),x={FLOATS_PER_TRIANGLE:32,POSITION_A_OFFSET:0,POSITION_B_OFFSET:4,POSITION_C_OFFSET:8,NORMAL_A_OFFSET:12,NORMAL_B_OFFSET:16,NORMAL_C_OFFSET:20,UV_AB_OFFSET:24,UV_C_MAT_OFFSET:28},S=x.FLOATS_PER_TRIANGLE;var C=class{constructor(){this.minX=0,this.minY=0,this.minZ=0,this.maxX=0,this.maxY=0,this.maxZ=0,this.leftChild=null,this.rightChild=null,this.triangleOffset=0,this.triangleCount=0}},w=class{constructor(){this.useWorker=!0,this.maxLeafSize=8,this.numBins=32,this.minBins=8,this.maxBins=64,this.totalNodes=0,this.processedTriangles=0,this.totalTriangles=0,this.lastProgressUpdate=0,this.progressUpdateInterval=100,this.traversalCost=1,this.intersectionCost=2.5,this.useMortonCodes=!0,this.mortonBits=10,this.mortonClusterThreshold=128,this.enableObjectMedianFallback=!0,this.enableSpatialMedianFallback=!0,this.splitStats={sahSplits:0,objectMedianSplits:0,spatialMedianSplits:0,failedSplits:0,avgBinsUsed:0,totalSplitAttempts:0,mortonSortTime:0,totalBuildTime:0,treeletOptimizationTime:0,treeletsProcessed:0,treeletsImproved:0,averageSAHImprovement:0,reinsertionOptimizationTime:0,reinsertionsApplied:0,reinsertionIterations:0},this.enableTreeletOptimization=!0,this.treeletSize=5,this.treeletOptimizationPasses=1,this.treeletMinImprovement=.02,this.maxTreeletDepth=3,this.maxTreeletsPerScene=20,this.treeletComplexityThreshold=5e4,this.enableReinsertionOptimization=!0,this.reinsertionBatchSizeRatio=.02,this.reinsertionMaxIterations=2,this.initializeBinArrays(),this._partResult={mid:0,lMinX:0,lMinY:0,lMinZ:0,lMaxX:0,lMaxY:0,lMaxZ:0,rMinX:0,rMinY:0,rMinZ:0,rMaxX:0,rMaxY:0,rMaxZ:0},this.centroids=null,this.bMin=null,this.bMax=null,this.indices=null,this.mortonCodes=null,this.triangles=null,this.reorderedTriangleData=null}initializeBinArrays(){let e=this.maxBins;this.binBoundsMin=new Float32Array(e*3),this.binBoundsMax=new Float32Array(e*3),this.binCounts=new Uint32Array(e),this.leftPrefixMin=new Float32Array(e*3),this.leftPrefixMax=new Float32Array(e*3),this.leftPrefixCount=new Uint32Array(e),this.rightPrefixMin=new Float32Array(e*3),this.rightPrefixMax=new Float32Array(e*3),this.rightPrefixCount=new Uint32Array(e)}getOptimalBinCount(e){return e<=16?this.minBins:e<=64?16:e<=256?32:e<=1024?48:this.maxBins}setAdaptiveBinConfig(e){e.minBins!==void 0&&(this.minBins=Math.max(4,e.minBins)),e.maxBins!==void 0&&(this.maxBins=Math.min(128,e.maxBins)),e.baseBins!==void 0&&(this.numBins=e.baseBins),e.maxBins!==void 0&&this.initializeBinArrays()}setMortonConfig(e){e.enabled!==void 0&&(this.useMortonCodes=e.enabled),e.bits!==void 0&&(this.mortonBits=Math.max(6,Math.min(10,e.bits))),e.threshold!==void 0&&(this.mortonClusterThreshold=Math.max(16,e.threshold))}setFallbackConfig(e){e.objectMedian!==void 0&&(this.enableObjectMedianFallback=e.objectMedian),e.spatialMedian!==void 0&&(this.enableSpatialMedianFallback=e.spatialMedian)}setTreeletConfig(e){e.enabled!==void 0&&(this.enableTreeletOptimization=e.enabled),e.size!==void 0&&(this.treeletSize=Math.max(3,Math.min(12,e.size))),e.passes!==void 0&&(this.treeletOptimizationPasses=Math.max(1,Math.min(3,e.passes))),e.minImprovement!==void 0&&(this.treeletMinImprovement=Math.max(.001,e.minImprovement))}disableTreeletOptimization(){this.enableTreeletOptimization=!1}setReinsertionConfig(e){e.enabled!==void 0&&(this.enableReinsertionOptimization=e.enabled),e.batchSizeRatio!==void 0&&(this.reinsertionBatchSizeRatio=Math.max(.005,Math.min(.1,e.batchSizeRatio))),e.maxIterations!==void 0&&(this.reinsertionMaxIterations=Math.max(1,Math.min(5,e.maxIterations)))}initializeTriangleArrays(){let e=this.totalTriangles,t=this.triangles,n=x.POSITION_A_OFFSET,r=x.POSITION_B_OFFSET,i=x.POSITION_C_OFFSET;for(let a=0;a<e;a++){let e=a*S,o=t[e+n],s=t[e+n+1],c=t[e+n+2],l=t[e+r],u=t[e+r+1],d=t[e+r+2],f=t[e+i],p=t[e+i+1],m=t[e+i+2],h=a*3;this.centroids[h]=(o+l+f)/3,this.centroids[h+1]=(s+u+p)/3,this.centroids[h+2]=(c+d+m)/3,this.bMin[h]=o<l?o<f?o:f:l<f?l:f,this.bMin[h+1]=s<u?s<p?s:p:u<p?u:p,this.bMin[h+2]=c<d?c<m?c:m:d<m?d:m,this.bMax[h]=o>l?o>f?o:f:l>f?l:f,this.bMax[h+1]=s>u?s>p?s:p:u>p?u:p,this.bMax[h+2]=c>d?c>m?c:m:d>m?d:m,this.indices[a]=a}}expandBits(e){return e=e*65537&4278190335,e=e*257&251719695,e=e*17&3272356035,e=e*5&1227133513,e}morton3D(e,t,n){return(this.expandBits(n)<<2)+(this.expandBits(t)<<1)+this.expandBits(e)}computeMortonCodeForIndex(e,t,n,r,i,a,o){let s=this.centroids,c=e*3,l=(1<<this.mortonBits)-1,u=i>0?(s[c]-t)/i:0,d=a>0?(s[c+1]-n)/a:0,f=o>0?(s[c+2]-r)/o:0,p=Math.max(0,Math.min(l,Math.floor(u*l))),m=Math.max(0,Math.min(l,Math.floor(d*l))),h=Math.max(0,Math.min(l,Math.floor(f*l)));return this.morton3D(p,m,h)}sortTrianglesByMortonCode(){let e=this.totalTriangles;if(!this.useMortonCodes||e<this.mortonClusterThreshold)return;let t=performance.now(),n=this.centroids,r=this.indices,i=1/0,a=1/0,o=1/0,s=-1/0,c=-1/0,l=-1/0;for(let t=0;t<e;t++){let e=r[t]*3,u=n[e],d=n[e+1],f=n[e+2];u<i&&(i=u),d<a&&(a=d),f<o&&(o=f),u>s&&(s=u),d>c&&(c=d),f>l&&(l=f)}let u=s-i,d=c-a,f=l-o,p=this.mortonCodes,m=(1<<this.mortonBits)-1,h=u>0?m/u:0,g=d>0?m/d:0,_=f>0?m/f:0;for(let t=0;t<e;t++){let e=r[t],s=e*3,c=(n[s]-i)*h,l=(n[s+1]-a)*g,u=(n[s+2]-o)*_;c=c<0?0:(c>m?m:c)|0,l=l<0?0:(l>m?m:l)|0,u=u<0?0:(u>m?m:u)|0,c=c*65537&4278190335,c=c*257&251719695,c=c*17&3272356035,c=c*5&1227133513,l=l*65537&4278190335,l=l*257&251719695,l=l*17&3272356035,l=l*5&1227133513,u=u*65537&4278190335,u=u*257&251719695,u=u*17&3272356035,u=u*5&1227133513,p[e]=(u<<2)+(l<<1)+c}let v=new Uint32Array(e),y=new Uint32Array(256);for(let t=0;t<32;t+=8){y.fill(0);for(let n=0;n<e;n++)y[p[r[n]]>>>t&255]++;let n=0;for(let e=0;e<256;e++){let t=y[e];y[e]=n,n+=t}for(let n=0;n<e;n++){let e=p[r[n]]>>>t&255;v[y[e]++]=r[n]}r.set(v)}this.splitStats.mortonSortTime+=performance.now()-t}build(e,t=30,n=null){if(this.totalTriangles=e.byteLength/(S*4),this.processedTriangles=0,this.lastProgressUpdate=performance.now(),!(this.useWorker&&null))return new Promise(r=>{r(this._buildSyncAndFlatten(e,t,n))})}_buildSyncAndFlatten(e,t,n){let r=this.buildSync(e,t,n);return{bvhData:this.flattenBVH(r),bvhRoot:!0,reorderedTriangles:this.reorderedTriangleData||null,originalToBvh:this.originalToBvhMap||null}}buildSync(t,r=30,i=null,a=null){let o=performance.now();this.totalNodes=0,this.processedTriangles=0,this.triangles=t,this.totalTriangles=t.byteLength/(S*4),this.lastProgressUpdate=performance.now(),this.splitStats={sahSplits:0,objectMedianSplits:0,spatialMedianSplits:0,failedSplits:0,avgBinsUsed:0,totalSplitAttempts:0,mortonSortTime:0,totalBuildTime:0,treeletOptimizationTime:0,treeletsProcessed:0,treeletsImproved:0,averageSAHImprovement:0,reinsertionOptimizationTime:0,reinsertionsApplied:0,reinsertionIterations:0,saOrderTime:0,initTime:0,sahBuildTime:0,reorderTime:0};let s=this.totalTriangles,c=performance.now();this.centroids=new Float32Array(s*3),this.bMin=new Float32Array(s*3),this.bMax=new Float32Array(s*3),this.indices=new Uint32Array(s),this.mortonCodes=new Uint32Array(s),this.initializeTriangleArrays(),this.splitStats.initTime=performance.now()-c,this.sortTrianglesByMortonCode();let l=performance.now(),u=this.buildNodeRecursive(0,s,r,i);if(this.splitStats.sahBuildTime=performance.now()-l,this.enableTreeletOptimization&&this.totalTriangles>1e3){let t=this.totalTriangles>this.treeletComplexityThreshold,n=t?3:this.treeletSize,r=t?10:this.maxTreeletsPerScene,a=new e(this.traversalCost,this.intersectionCost);a.setTreeletSize(n),a.setMinImprovement(this.treeletMinImprovement),a.setMaxTreelets(r);let o=performance.now();for(let e=0;e<this.treeletOptimizationPasses;e++){let t=i?t=>{i(`Treelet optimization pass ${e+1}/${this.treeletOptimizationPasses}: ${t}`)}:null;try{a.optimizeBVH(u,t)}catch(t){b.error(`treelet optimizer failed in pass ${e+1}:`,t);break}let n=a.getStatistics(),r=performance.now()-o;if(n.treeletsImproved===0&&e>0||r>15e3)break}let s=performance.now()-o;this.splitStats.treeletOptimizationTime=s;let c=a.getStatistics();this.splitStats.treeletsProcessed=c.treeletsProcessed,this.splitStats.treeletsImproved=c.treeletsImproved,this.splitStats.averageSAHImprovement=c.averageSAHImprovement}if(this.enableReinsertionOptimization&&this.totalTriangles>1e3){let e=new n(this.traversalCost,this.intersectionCost);e.setBatchSizeRatio(this.reinsertionBatchSizeRatio),e.setMaxIterations(this.reinsertionMaxIterations);let t=i?e=>{i(e)}:null;try{e.optimizeBVH(u,t)}catch(e){b.error(`reinsertion optimizer failed:`,e)}let r=e.getStatistics();this.splitStats.reinsertionOptimizationTime=r.timeMs,this.splitStats.reinsertionsApplied=r.reinsertionsApplied,this.splitStats.reinsertionIterations=r.iterations}let d=performance.now();this.applySAOrdering(u),this.splitStats.saOrderTime=performance.now()-d;let f=performance.now(),p=this.triangles,m=a||new Float32Array(s*S);for(let e=0;e<s;e++){let t=this.indices[e]*S,n=e*S;m.set(p.subarray(t,t+S),n)}this.reorderedTriangleData=m;let h=new Uint32Array(s);for(let e=0;e<s;e++)h[this.indices[e]]=e;this.originalToBvhMap=h,this.splitStats.reorderTime=performance.now()-f,this.splitStats.totalBuildTime=performance.now()-o;let g=this.splitStats.totalBuildTime,v=this.splitStats;return b.debug(`${_.n(s)} tris → ${_.n(this.totalNodes)} nodes in ${_.ms(g)} | SAH ${v.sahSplits} objMed ${v.objectMedianSplits} spatMed ${v.spatialMedianSplits} failed ${v.failedSplits}`+(v.treeletsProcessed?` | treelets ${v.treeletsImproved}/${v.treeletsProcessed} improved`:``)+(v.reinsertionsApplied?` | reinsertions ${v.reinsertionsApplied}`:``)),i&&i(100),this.centroids=null,this.bMin=null,this.bMax=null,this.mortonCodes=null,u}updateProgress(e,t){if(!t)return;this.processedTriangles+=e;let n=performance.now();n-this.lastProgressUpdate<this.progressUpdateInterval||(this.lastProgressUpdate=n,t(Math.min(Math.floor(this.processedTriangles/this.totalTriangles*100),99)))}buildNodeRecursiveToDepth(e,t,n,r,i,a,o,s,c,l,u){let d=new C;this.totalNodes++;let f=t-e;if(a===void 0?this.updateNodeBounds(d,e,t):(d.minX=a,d.minY=o,d.minZ=s,d.maxX=c,d.maxY=l,d.maxZ=u),f<=this.maxLeafSize||n<=0)return d.triangleOffset=e,d.triangleCount=f,this.updateProgress(f,i),d;if(r<=0&&f>this.maxLeafSize*16){let r=this.frontierTasks.length;return d.triangleOffset=e,d.triangleCount=f,d.isFrontier=!0,d.frontierTaskId=r,this.frontierTasks.push({taskId:r,start:e,end:t,depth:n,preMinX:d.minX,preMinY:d.minY,preMinZ:d.minZ,preMaxX:d.maxX,preMaxY:d.maxY,preMaxZ:d.maxZ}),d}let p=this.findBestSplitPositionSAH(e,t,d);if(!p.success){if(this.splitStats.failedSplits++,r>0||f<=this.maxLeafSize*16)return d.triangleOffset=e,d.triangleCount=f,this.updateProgress(f,i),d;let a=this.frontierTasks.length;return d.triangleOffset=e,d.triangleCount=f,d.isFrontier=!0,d.frontierTaskId=a,this.frontierTasks.push({taskId:a,start:e,end:t,depth:n,preMinX:d.minX,preMinY:d.minY,preMinZ:d.minZ,preMaxX:d.maxX,preMaxY:d.maxY,preMaxZ:d.maxZ}),d}p.method===`SAH`?this.splitStats.sahSplits++:p.method===`object_median`?this.splitStats.objectMedianSplits++:p.method===`spatial_median`&&this.splitStats.spatialMedianSplits++,this.partitionWithBounds(e,t,p.axis,p.pos);let m=this._partResult,h=m.mid,g=m.lMinX,_=m.lMinY,v=m.lMinZ,y=m.lMaxX,b=m.lMaxY,x=m.lMaxZ,S=m.rMinX,w=m.rMinY,T=m.rMinZ,E=m.rMaxX,D=m.rMaxY,O=m.rMaxZ;return h===e||h===t?(d.triangleOffset=e,d.triangleCount=f,this.updateProgress(f,i),d):(d.leftChild=this.buildNodeRecursiveToDepth(e,h,n-1,r-1,i,g,_,v,y,b,x),d.rightChild=this.buildNodeRecursiveToDepth(h,t,n-1,r-1,i,S,w,T,E,D,O),d)}buildNodeRecursive(e,t,n,r,i,a,o,s,c,l){let u=new C;this.totalNodes++;let d=t-e;if(i===void 0?this.updateNodeBounds(u,e,t):(u.minX=i,u.minY=a,u.minZ=o,u.maxX=s,u.maxY=c,u.maxZ=l),d<=this.maxLeafSize||n<=0)return u.triangleOffset=e,u.triangleCount=d,this.updateProgress(d,r),u;let f=this.findBestSplitPositionSAH(e,t,u);if(!f.success)return this.splitStats.failedSplits++,u.triangleOffset=e,u.triangleCount=d,this.updateProgress(d,r),u;f.method===`SAH`?this.splitStats.sahSplits++:f.method===`object_median`?this.splitStats.objectMedianSplits++:f.method===`spatial_median`&&this.splitStats.spatialMedianSplits++,this.partitionWithBounds(e,t,f.axis,f.pos);let p=this._partResult,m=p.mid,h=p.lMinX,g=p.lMinY,_=p.lMinZ,v=p.lMaxX,y=p.lMaxY,b=p.lMaxZ,x=p.rMinX,S=p.rMinY,w=p.rMinZ,T=p.rMaxX,E=p.rMaxY,D=p.rMaxZ;return m===e||m===t?(u.triangleOffset=e,u.triangleCount=d,this.updateProgress(d,r),u):(u.leftChild=this.buildNodeRecursive(e,m,n-1,r,h,g,_,v,y,b),u.rightChild=this.buildNodeRecursive(m,t,n-1,r,x,S,w,T,E,D),u)}partitionWithBounds(e,t,n,r){let i=this.indices,a=this.centroids,o=this.bMin,s=this.bMax,c=e,l=t-1,u=1/0,d=1/0,f=1/0,p=-1/0,m=-1/0,h=-1/0,g=1/0,_=1/0,v=1/0,y=-1/0,b=-1/0,x=-1/0;for(;c<=l;){let e=i[c],t=e*3;a[t+n]<=r?(o[t]<u&&(u=o[t]),o[t+1]<d&&(d=o[t+1]),o[t+2]<f&&(f=o[t+2]),s[t]>p&&(p=s[t]),s[t+1]>m&&(m=s[t+1]),s[t+2]>h&&(h=s[t+2]),c++):(o[t]<g&&(g=o[t]),o[t+1]<_&&(_=o[t+1]),o[t+2]<v&&(v=o[t+2]),s[t]>y&&(y=s[t]),s[t+1]>b&&(b=s[t+1]),s[t+2]>x&&(x=s[t+2]),i[c]=i[l],i[l]=e,l--)}let S=this._partResult;return S.mid=c,S.lMinX=u,S.lMinY=d,S.lMinZ=f,S.lMaxX=p,S.lMaxY=m,S.lMaxZ=h,S.rMinX=g,S.rMinY=_,S.rMinZ=v,S.rMaxX=y,S.rMaxY=b,S.rMaxZ=x,S}updateNodeBounds(e,t,n){let r=1/0,i=1/0,a=1/0,o=-1/0,s=-1/0,c=-1/0,l=this.indices,u=this.bMin,d=this.bMax;for(let e=t;e<n;e++){let t=l[e]*3;u[t]<r&&(r=u[t]),u[t+1]<i&&(i=u[t+1]),u[t+2]<a&&(a=u[t+2]),d[t]>o&&(o=d[t]),d[t+1]>s&&(s=d[t+1]),d[t+2]>c&&(c=d[t+2])}e.minX=r,e.minY=i,e.minZ=a,e.maxX=o,e.maxY=s,e.maxZ=c}findBestSplitPositionSAH(e,t,n){let r=1/0,i=-1,a=0,o=this.computeSurfaceAreaFlat(n.minX,n.minY,n.minZ,n.maxX,n.maxY,n.maxZ),s=t-e,c=this.intersectionCost*s,l=this.getOptimalBinCount(s);this.splitStats.totalSplitAttempts++,this.splitStats.avgBinsUsed=(this.splitStats.avgBinsUsed*(this.splitStats.totalSplitAttempts-1)+l)/this.splitStats.totalSplitAttempts;let u=this.indices,d=this.centroids,f=this.bMin,p=this.bMax,m=this.binBoundsMin,h=this.binBoundsMax,g=this.binCounts,_=this.leftPrefixMin,v=this.leftPrefixMax,y=this.leftPrefixCount,b=this.rightPrefixMin,x=this.rightPrefixMax,S=this.rightPrefixCount,C=1/0,w=-1/0,T=1/0,E=-1/0,D=1/0,O=-1/0;for(let n=e;n<t;n++){let e=u[n]*3,t=d[e],r=d[e+1],i=d[e+2];t<C&&(C=t),t>w&&(w=t),r<T&&(T=r),r>E&&(E=r),i<D&&(D=i),i>O&&(O=i)}let k=[C,T,D],A=[w,E,O];for(let n=0;n<3;n++){let s=k[n],C=A[n];if(C-s<1e-6)continue;for(let e=0;e<l;e++){g[e]=0;let t=e*3;m[t]=1/0,m[t+1]=1/0,m[t+2]=1/0,h[t]=-1/0,h[t+1]=-1/0,h[t+2]=-1/0}let w=l/(C-s);for(let r=e;r<t;r++){let e=u[r],t=d[e*3+n],i=Math.floor((t-s)*w);i>=l&&(i=l-1),g[i]++;let a=i*3,o=e*3;f[o]<m[a]&&(m[a]=f[o]),f[o+1]<m[a+1]&&(m[a+1]=f[o+1]),f[o+2]<m[a+2]&&(m[a+2]=f[o+2]),p[o]>h[a]&&(h[a]=p[o]),p[o+1]>h[a+1]&&(h[a+1]=p[o+1]),p[o+2]>h[a+2]&&(h[a+2]=p[o+2])}y[0]=g[0],_[0]=m[0],_[1]=m[1],_[2]=m[2],v[0]=h[0],v[1]=h[1],v[2]=h[2];for(let e=1;e<l;e++){let t=e*3,n=(e-1)*3;y[e]=y[e-1]+g[e];let r=_[n],i=m[t],a=_[n+1],o=m[t+1],s=_[n+2],c=m[t+2];_[t]=r<i?r:i,_[t+1]=a<o?a:o,_[t+2]=s<c?s:c;let l=v[n],u=h[t],d=v[n+1],f=h[t+1],p=v[n+2],b=h[t+2];v[t]=l>u?l:u,v[t+1]=d>f?d:f,v[t+2]=p>b?p:b}let T=l-1,E=T*3;S[T]=g[T],b[E]=m[E],b[E+1]=m[E+1],b[E+2]=m[E+2],x[E]=h[E],x[E+1]=h[E+1],x[E+2]=h[E+2];for(let e=T-1;e>=0;e--){let t=e*3,n=(e+1)*3;S[e]=S[e+1]+g[e];let r=b[n],i=m[t],a=b[n+1],o=m[t+1],s=b[n+2],c=m[t+2];b[t]=r<i?r:i,b[t+1]=a<o?a:o,b[t+2]=s<c?s:c;let l=x[n],u=h[t],d=x[n+1],f=h[t+1],p=x[n+2],_=h[t+2];x[t]=l>u?l:u,x[t+1]=d>f?d:f,x[t+2]=p>_?p:_}for(let e=1;e<l;e++){let t=(e-1)*3,u=e*3,d=y[e-1],f=S[e];if(d===0||f===0)continue;let p=v[t]-_[t],m=v[t+1]-_[t+1],h=v[t+2]-_[t+2],g=2*(p*m+m*h+h*p),w=x[u]-b[u],T=x[u+1]-b[u+1],E=x[u+2]-b[u+2],D=2*(w*T+T*E+E*w),O=this.traversalCost+g/o*d*this.intersectionCost+D/o*f*this.intersectionCost;O<r&&O<c&&(r=O,i=n,a=s+(C-s)*e/l)}}return i===-1?this.enableObjectMedianFallback?this.findObjectMedianSplit(e,t):this.enableSpatialMedianFallback?this.findSpatialMedianSplit(e,t):{success:!1,method:`fallbacks_disabled`}:{success:!0,axis:i,pos:a,method:`SAH`,binsUsed:l}}findObjectMedianSplit(e,t){let n=this.indices,r=this.centroids,i=-1,a=-1;for(let o=0;o<3;o++){let s=1/0,c=-1/0;for(let i=e;i<t;i++){let e=r[n[i]*3+o];e<s&&(s=e),e>c&&(c=e)}let l=c-s;l>a&&(a=l,i=o)}if(i===-1||a<1e-10)return this.enableSpatialMedianFallback?this.findSpatialMedianSplit(e,t):{success:!1,method:`object_median_failed`};let o=t-e,s=e+Math.floor(o/2);this.quickselect(e,t,s,i);let c=r[n[s]*3+i],l=!0;for(let e=s+1;e<t;e++)if(r[n[e]*3+i]>c){l=!1;break}if(l){let a=-1/0;for(let t=e;t<s;t++){let e=r[n[t]*3+i];e>a&&(a=e)}if(a<c)c=(a+c)*.5;else return this.enableSpatialMedianFallback?this.findSpatialMedianSplit(e,t):{success:!1,method:`object_median_degenerate`}}return{success:!0,axis:i,pos:c,method:`object_median`}}findSpatialMedianSplit(e,t){let n=this.indices,r=this.centroids,i=this.bMin,a=this.bMax,o=-1,s=-1,c=0,l=0;for(let r=0;r<3;r++){let u=1/0,d=-1/0;for(let o=e;o<t;o++){let e=n[o]*3+r;i[e]<u&&(u=i[e]),a[e]>d&&(d=a[e])}let f=d-u;f>s&&(s=f,o=r,c=u,l=d)}if(o===-1||s<1e-12)return{success:!1,method:`spatial_median_failed`};let u=(c+l)*.5,d=t-e,f=0;for(let i=e;i<t;i++)r[n[i]*3+o]<=u&&f++;if(f===0||f===d){let i=e+Math.floor(d/2);this.quickselect(e,t,i,o);let a=r[n[i]*3+o],s=!0;for(let i=e;i<t;i++)if(r[n[i]*3+o]!==a){s=!1;break}if(s)return{success:!1,method:`spatial_median_degenerate`};let c=-1/0;for(let t=e;t<i;t++){let e=r[n[t]*3+o];e>c&&(c=e)}if(c<a)u=(c+a)*.5;else{let e=1/0;for(let a=i+1;a<t;a++){let t=r[n[a]*3+o];t<e&&(e=t)}u=(a+e)*.5}}return{success:!0,axis:o,pos:u,method:`spatial_median`}}quickselect(e,t,n,r){let i=this.indices,a=this.centroids,o=e,s=t-1;for(;o<s;){let e=o+s>>>1,t=a[i[o]*3+r],c=a[i[e]*3+r],l=a[i[s]*3+r];if(t>c){let t=i[o];i[o]=i[e],i[e]=t}if(t>l){let e=i[o];i[o]=i[s],i[s]=e}if(c>l){let t=i[e];i[e]=i[s],i[s]=t}let u=a[i[e]*3+r],d=o,f=s;for(;d<=f;){for(;a[i[d]*3+r]<u;)d++;for(;a[i[f]*3+r]>u;)f--;if(d<=f){let e=i[d];i[d]=i[f],i[f]=e,d++,f--}}f<n&&(o=d),d>n&&(s=f)}}applySAOrdering(e){if(!e||!e.leftChild)return;let t=[e],n=[];for(;t.length>0;){let e=t.pop();!e.leftChild||!e.rightChild||(n.push(e),t.push(e.leftChild),t.push(e.rightChild))}for(let e=n.length-1;e>=0;e--){let t=n[e],r=t.leftChild,i=t.rightChild,a=r.maxX-r.minX,o=r.maxY-r.minY,s=r.maxZ-r.minZ,c=i.maxX-i.minX,l=i.maxY-i.minY,u=i.maxZ-i.minZ;c*l+l*u+u*c>a*o+o*s+s*a&&(t.leftChild=i,t.rightChild=r)}}flattenBVH(e){let t=[],n=[e];for(;n.length>0;){let e=n.pop();e._flatIndex=t.length,t.push(e),e.rightChild&&n.push(e.rightChild),e.leftChild&&n.push(e.leftChild)}let r=new Float32Array(t.length*16);for(let e=0;e<t.length;e++){let n=t[e],i=e*16;if(n.leftChild){let e=n.leftChild,t=n.rightChild;r[i]=e.minX,r[i+1]=e.minY,r[i+2]=e.minZ,r[i+3]=e._flatIndex,r[i+4]=e.maxX,r[i+5]=e.maxY,r[i+6]=e.maxZ,r[i+7]=t._flatIndex,r[i+8]=t.minX,r[i+9]=t.minY,r[i+10]=t.minZ,r[i+12]=t.maxX,r[i+13]=t.maxY,r[i+14]=t.maxZ}else r[i]=n.triangleOffset,r[i+1]=n.triangleCount,r[i+3]=-1}return r}flattenBVHWithFrontier(e){let t=[],n=[e];for(;n.length>0;){let e=n.pop();e._flatIndex=t.length,t.push(e),e.rightChild&&n.push(e.rightChild),e.leftChild&&n.push(e.leftChild)}let r=new Float32Array(t.length*16),i=[];for(let e=0;e<t.length;e++){let n=t[e],a=e*16;if(n.leftChild){let e=n.leftChild,t=n.rightChild;r[a]=e.minX,r[a+1]=e.minY,r[a+2]=e.minZ,r[a+3]=e._flatIndex,r[a+4]=e.maxX,r[a+5]=e.maxY,r[a+6]=e.maxZ,r[a+7]=t._flatIndex,r[a+8]=t.minX,r[a+9]=t.minY,r[a+10]=t.minZ,r[a+12]=t.maxX,r[a+13]=t.maxY,r[a+14]=t.maxZ}else if(n.isFrontier){let t=n.frontierTaskId;r[a]=n.triangleOffset,r[a+1]=n.triangleCount,r[a+2]=t,r[a+3]=-2,i.push({taskId:t,flatIndex:e})}else r[a]=n.triangleOffset,r[a+1]=n.triangleCount,r[a+3]=-1}return{flatData:r,frontierMap:i,nodeCount:t.length}}assembleParallelBVH(e,t,n,r){let i=[...r].sort((e,t)=>e.taskId-t.taskId),a=t;for(let e=0;e<i.length;e++)a+=i[e].nodeCount;let o=new Float32Array(a*16);o.set(e);let s=new Map;for(let e of n)s.set(e.taskId,e.flatIndex);let c=t;for(let e=0;e<i.length;e++){let t=i[e],n=t.flatData,r=t.nodeCount,a=c*16;o.set(n,a);for(let e=0;e<r;e++){let t=a+e*16;o[t+3]!==-1&&(o[t+3]+=c,o[t+7]+=c)}let l=s.get(t.taskId);if(l!==void 0){let e=l*16,t=a;for(let n=0;n<16;n++)o[e+n]=o[t+n]}c+=r}return o}computeSurfaceAreaFlat(e,t,n,r,i,a){let o=r-e,s=i-t,c=a-n;return 2*(o*s+s*c+c*o)}};self.onmessage=function(t){let{tasks:r,sharedTriangleData:i,sharedCentroids:a,sharedBMin:o,sharedBMax:s,sharedIndices:c,triangleCount:l,maxLeafSize:u,numBins:d,maxBins:f,minBins:p,treeletConfig:m,reinsertionConfig:h,reportProgress:g}=t.data;for(let t=0;t<r.length;t++){let _=r[t];try{let t=new w;t.maxLeafSize=u,t.numBins=d,t.maxBins=f,t.minBins=p,t.triangles=new Float32Array(i),t.centroids=new Float32Array(a),t.bMin=new Float32Array(o),t.bMax=new Float32Array(s),t.indices=new Uint32Array(c),t.totalTriangles=l,t.totalNodes=0,t.processedTriangles=0,t.lastProgressUpdate=performance.now(),t.splitStats={sahSplits:0,objectMedianSplits:0,spatialMedianSplits:0,failedSplits:0,avgBinsUsed:0,totalSplitAttempts:0,mortonSortTime:0,totalBuildTime:0,treeletOptimizationTime:0,treeletsProcessed:0,treeletsImproved:0,averageSAHImprovement:0,initTime:0,sahBuildTime:0,reorderTime:0};let r=g?e=>{self.postMessage({type:`progress`,taskId:_.taskId,progress:e})}:null,v=performance.now(),y=t.buildNodeRecursive(_.start,_.end,_.depth,r,_.preMinX,_.preMinY,_.preMinZ,_.preMaxX,_.preMaxY,_.preMaxZ);if(m&&m.enabled&&_.end-_.start>1e3){let n=_.end-_.start>5e4,r=n?3:m.size||5,i=n?10:20,a=new e(t.traversalCost,t.intersectionCost);a.setTreeletSize(r),a.setMinImprovement(m.minImprovement||.02),a.setMaxTreelets(i);let o=m.passes||1;for(let e=0;e<o;e++)try{a.optimizeBVH(y,null)}catch(t){console.error(`[BVHSubtreeWorker] Treelet pass ${e+1} error:`,t);break}}if(h&&h.enabled&&_.end-_.start>1e3){let e=new n(t.traversalCost,t.intersectionCost);h.batchSizeRatio&&e.setBatchSizeRatio(h.batchSizeRatio),h.maxIterations&&e.setMaxIterations(h.maxIterations);try{e.optimizeBVH(y,null)}catch(e){console.error(`[BVHSubtreeWorker] Reinsertion error:`,e)}}t.applySAOrdering(y);let b=t.flattenBVH(y),x=b.length/16,S=performance.now()-v;console.log(`[BVHSubtreeWorker] Task ${_.taskId}: ${(_.end-_.start).toLocaleString()} triangles, ${x} nodes, ${Math.round(S)}ms`),self.postMessage({type:`subtreeResult`,taskId:_.taskId,flatData:b,nodeCount:x},[b.buffer])}catch(e){console.error(`[BVHSubtreeWorker] Task ${_.taskId} error:`,e),self.postMessage({type:`error`,taskId:_.taskId,error:e.message})}}};", _c = typeof self < "u" && self.Blob && new Blob(["URL.revokeObjectURL(import.meta.url);", gc], { type: "text/javascript;charset=utf-8" });
5566
+ var gc = "var e=class{constructor(e,t){this.traversalCost=e,this.intersectionCost=t,this.maxTreeletLeaves=7,this.minImprovement=.02,this.topologyCache=new Map;for(let e=3;e<=this.maxTreeletLeaves;e++)this.topologyCache.set(e,this.generateTopologies(e));this.stats={treeletsProcessed:0,treeletsImproved:0,totalSAHImprovement:0,averageSAHImprovement:0,optimizationTime:0}}generateTopologies(e){if(e===1)return[0];if(e===2)return[[0,1]];let t=[];for(let n=1;n<e;n++){let r=this.generateTopologies(n),i=this.generateTopologies(e-n);for(let e of r)for(let r of i)t.push([e,this.offsetTopology(r,n)])}return t}offsetTopology(e,t){return typeof e==`number`?e+t:[this.offsetTopology(e[0],t),this.offsetTopology(e[1],t)]}optimizeBVH(e){let t=performance.now();this.stats={treeletsProcessed:0,treeletsImproved:0,totalSAHImprovement:0,averageSAHImprovement:0,optimizationTime:0};let n=this.identifyTreeletRoots(e);for(let e=0;e<n.length;e++){if(performance.now()-t>3e4){console.warn(`TreeletOptimizer: timeout after ${e}/${n.length} treelets`);break}this.optimizeTreelet(n[e])}return this.stats.optimizationTime=performance.now()-t,this.stats.averageSAHImprovement=this.stats.treeletsProcessed>0?this.stats.totalSAHImprovement/this.stats.treeletsProcessed:0,e}identifyTreeletRoots(e){let t=[],n=new Set,r=[{node:e,visited:!1}];for(;r.length>0;){let e=r[r.length-1];if(e.visited){r.pop();let i=e.node;if(i.triangleCount>0||n.has(i))continue;let a=this.countLeaves(i);a>=3&&a<=this.maxTreeletLeaves&&(t.push(i),this.markSubtree(i,n))}else{e.visited=!0;let t=e.node;if(t.triangleCount>0)continue;t.rightChild&&r.push({node:t.rightChild,visited:!1}),t.leftChild&&r.push({node:t.leftChild,visited:!1})}}return t}countLeaves(e){return e?e.triangleCount>0?1:this.countLeaves(e.leftChild)+this.countLeaves(e.rightChild):0}markSubtree(e,t){e&&(t.add(e),!(e.triangleCount>0)&&(this.markSubtree(e.leftChild,t),this.markSubtree(e.rightChild,t)))}optimizeTreelet(e){let t=[];this.extractLeaves(e,t);let n=t.length;if(n<3||n>this.maxTreeletLeaves)return;this.stats.treeletsProcessed++;let r=this.evaluateSubtreeSAH(e),i=this.topologyCache.get(n);if(!i||i.length===0)return;let a=r,o=null,s=null;if(n<=5){let e=this.generatePermutations(n);for(let n of i)for(let r of e){let e=this.evaluateTopology(n,t,r);e<a&&(a=e,o=n,s=r)}}else{let e=Array.from({length:n},(e,t)=>t);for(let n of i){let r=this.evaluateTopology(n,t,e);r<a&&(a=r,o=n,s=e);let i=this.greedySwapOptimize(n,t,e,r);i.cost<a&&(a=i.cost,o=n,s=i.perm)}}let c=(r-a)/r;o&&c>this.minImprovement&&(this.reconstructTreelet(e,o,t,s),this.stats.treeletsImproved++,this.stats.totalSAHImprovement+=c)}extractLeaves(e,t){if(e){if(e.triangleCount>0){t.push({minX:e.minX,minY:e.minY,minZ:e.minZ,maxX:e.maxX,maxY:e.maxY,maxZ:e.maxZ,triangleOffset:e.triangleOffset,triangleCount:e.triangleCount});return}this.extractLeaves(e.leftChild,t),this.extractLeaves(e.rightChild,t)}}evaluateSubtreeSAH(e){if(!e)return 0;if(e.triangleCount>0)return this.surfaceAreaFlat(e.minX,e.minY,e.minZ,e.maxX,e.maxY,e.maxZ)*e.triangleCount*this.intersectionCost;let t=this.evaluateSubtreeSAH(e.leftChild),n=this.evaluateSubtreeSAH(e.rightChild);return this.surfaceAreaFlat(e.minX,e.minY,e.minZ,e.maxX,e.maxY,e.maxZ)*this.traversalCost+t+n}evaluateTopology(e,t,n){return this.evalTopoRecursive(e,t,n).cost}evalTopoRecursive(e,t,n){if(typeof e==`number`){let r=t[n[e]];return{cost:this.surfaceAreaFlat(r.minX,r.minY,r.minZ,r.maxX,r.maxY,r.maxZ)*r.triangleCount*this.intersectionCost,minX:r.minX,minY:r.minY,minZ:r.minZ,maxX:r.maxX,maxY:r.maxY,maxZ:r.maxZ}}let r=this.evalTopoRecursive(e[0],t,n),i=this.evalTopoRecursive(e[1],t,n),a=Math.min(r.minX,i.minX),o=Math.min(r.minY,i.minY),s=Math.min(r.minZ,i.minZ),c=Math.max(r.maxX,i.maxX),l=Math.max(r.maxY,i.maxY),u=Math.max(r.maxZ,i.maxZ);return{cost:this.surfaceAreaFlat(a,o,s,c,l,u)*this.traversalCost+r.cost+i.cost,minX:a,minY:o,minZ:s,maxX:c,maxY:l,maxZ:u}}surfaceAreaFlat(e,t,n,r,i,a){let o=r-e,s=i-t,c=a-n;return 2*(o*s+s*c+c*o)}generatePermutations(e){let t=[],n=Array.from({length:e},(e,t)=>t),r=i=>{if(i===e){t.push([...n]);return}for(let t=i;t<e;t++)[n[i],n[t]]=[n[t],n[i]],r(i+1),[n[i],n[t]]=[n[t],n[i]]};return r(0),t}greedySwapOptimize(e,t,n,r){let i=[...n],a=r,o=!0;for(;o;){o=!1;for(let n=0;n<i.length-1;n++)for(let r=n+1;r<i.length;r++){[i[n],i[r]]=[i[r],i[n]];let s=this.evaluateTopology(e,t,i);s<a?(a=s,o=!0):[i[n],i[r]]=[i[r],i[n]]}}return{perm:i,cost:a}}reconstructTreelet(e,t,n,r){let i=this.buildSubtree(t,n,r);e.minX=i.minX,e.minY=i.minY,e.minZ=i.minZ,e.maxX=i.maxX,e.maxY=i.maxY,e.maxZ=i.maxZ,e.leftChild=i.leftChild,e.rightChild=i.rightChild,e.triangleOffset=i.triangleOffset,e.triangleCount=i.triangleCount}buildSubtree(e,n,r){if(typeof e==`number`){let i=n[r[e]],a=new t;return a.minX=i.minX,a.minY=i.minY,a.minZ=i.minZ,a.maxX=i.maxX,a.maxY=i.maxY,a.maxZ=i.maxZ,a.triangleOffset=i.triangleOffset,a.triangleCount=i.triangleCount,a}let i=this.buildSubtree(e[0],n,r),a=this.buildSubtree(e[1],n,r),o=new t;return o.leftChild=i,o.rightChild=a,o.minX=Math.min(i.minX,a.minX),o.minY=Math.min(i.minY,a.minY),o.minZ=Math.min(i.minZ,a.minZ),o.maxX=Math.max(i.maxX,a.maxX),o.maxY=Math.max(i.maxY,a.maxY),o.maxZ=Math.max(i.maxZ,a.maxZ),o}setTreeletSize(e){this.maxTreeletLeaves=Math.max(3,Math.min(7,e));for(let e=3;e<=this.maxTreeletLeaves;e++)this.topologyCache.has(e)||this.topologyCache.set(e,this.generateTopologies(e))}setMinImprovement(e){this.minImprovement=Math.max(.001,e)}getStatistics(){return{...this.stats}}},t=class{constructor(){this.minX=0,this.minY=0,this.minZ=0,this.maxX=0,this.maxY=0,this.maxZ=0,this.leftChild=null,this.rightChild=null,this.triangleOffset=0,this.triangleCount=0}},n=class{constructor(e,t){this.traversalCost=e,this.intersectionCost=t,this.batchSizeRatio=.02,this.maxIterations=2,this.timeBudgetMs=15e3,this.stats={reinsertionsApplied:0,iterations:0,timeMs:0}}setBatchSizeRatio(e){this.batchSizeRatio=Math.max(.005,Math.min(.1,e))}setMaxIterations(e){this.maxIterations=Math.max(1,Math.min(5,e))}getStatistics(){return{...this.stats}}surfaceArea(e){let t=e.maxX-e.minX,n=e.maxY-e.minY,r=e.maxZ-e.minZ;return t*n+n*r+r*t}buildParentMap(e){let t=new Map;t.set(e,{parent:null,isLeft:!1});let n=[e];for(;n.length>0;){let e=n.pop();e.triangleCount>0||(e.leftChild&&(t.set(e.leftChild,{parent:e,isLeft:!0}),n.push(e.leftChild)),e.rightChild&&(t.set(e.rightChild,{parent:e,isLeft:!1}),n.push(e.rightChild)))}return t}findCandidates(e,t,n){let r=[],i=[e];for(;i.length>0;){let a=i.pop();if(a!==e&&n.get(a).parent!==e){let e=this.surfaceArea(a);r.length<t?(r.push({node:a,cost:e}),r.length===t&&this._heapify(r)):e>r[0].cost&&(r[0]={node:a,cost:e},this._siftDown(r,0))}a.triangleCount===0&&(a.leftChild&&i.push(a.leftChild),a.rightChild&&i.push(a.rightChild))}return r}_heapify(e){for(let t=(e.length>>1)-1;t>=0;t--)this._siftDown(e,t)}_siftDown(e,t){let n=e.length;for(;;){let r=t,i=2*t+1,a=2*t+2;if(i<n&&e[i].cost<e[r].cost&&(r=i),a<n&&e[a].cost<e[r].cost&&(r=a),r===t)break;let o=e[t];e[t]=e[r],e[r]=o,t=r}}findReinsertion(e,t,n){let r=n.get(e),i=r.parent;if(!i)return null;let a=r.isLeft?i.rightChild:i.leftChild,o=this.surfaceArea(e),s=this.surfaceArea(i),c=null,l=0,u=s,d=a.minX,f=a.minY,p=a.minZ,m=a.maxX,h=a.maxY,g=a.maxZ,_=a,v=i,y=[];do{for(y.length=0,y.push(u,_);y.length>0;){let t=y.pop(),n=y.pop();if(n-o<=l)continue;let r=Math.min(t.minX,e.minX),i=Math.min(t.minY,e.minY),a=Math.min(t.minZ,e.minZ),s=Math.max(t.maxX,e.maxX),u=Math.max(t.maxY,e.maxY),d=Math.max(t.maxZ,e.maxZ),f=s-r,p=u-i,m=d-a,h=n-(f*p+p*m+m*f);if(h>l&&(c=t,l=h),t.triangleCount===0&&t.leftChild&&t.rightChild){let e=h+this.surfaceArea(t);y.push(e,t.leftChild),y.push(e,t.rightChild)}}let t=n.get(v);if(!t||t.parent===null)break;if(v!==i){d=Math.min(d,_.minX),f=Math.min(f,_.minY),p=Math.min(p,_.minZ),m=Math.max(m,_.maxX),h=Math.max(h,_.maxY),g=Math.max(g,_.maxZ);let e=m-d,t=h-f,n=g-p,r=e*t+t*n+n*e;u+=this.surfaceArea(v)-r}let r=t.parent;_=t.isLeft?r.rightChild:r.leftChild,v=r}while(n.get(v).parent!==null);return c===a||c===i?null:c?{from:e,to:c,areaDiff:l}:null}getConflicts(e,t,n){let r=n.get(e);return[t,e,r.isLeft?r.parent.rightChild:r.parent.leftChild,n.get(t).parent,r.parent]}reinsertNode(e,t,n){let r=n.get(e),i=r.parent,a=r.isLeft?i.rightChild:i.leftChild,o=n.get(i),s=o.parent,c=n.get(t),l=c.parent;o.isLeft?s.leftChild=a:s.rightChild=a,i.leftChild=e,i.rightChild=t,i.triangleOffset=0,i.triangleCount=0,i.minX=Math.min(e.minX,t.minX),i.minY=Math.min(e.minY,t.minY),i.minZ=Math.min(e.minZ,t.minZ),i.maxX=Math.max(e.maxX,t.maxX),i.maxY=Math.max(e.maxY,t.maxY),i.maxZ=Math.max(e.maxZ,t.maxZ),c.isLeft?l.leftChild=i:l.rightChild=i,n.set(a,{parent:s,isLeft:o.isLeft}),n.set(i,{parent:l,isLeft:c.isLeft}),n.set(e,{parent:i,isLeft:!0}),n.set(t,{parent:i,isLeft:!1}),this.refitFrom(s,n),this.refitFrom(l,n)}refitFrom(e,t){let n=e;for(;n;){if(n.triangleCount===0&&n.leftChild&&n.rightChild){let e=n.leftChild,t=n.rightChild;n.minX=Math.min(e.minX,t.minX),n.minY=Math.min(e.minY,t.minY),n.minZ=Math.min(e.minZ,t.minZ),n.maxX=Math.max(e.maxX,t.maxX),n.maxY=Math.max(e.maxY,t.maxY),n.maxZ=Math.max(e.maxZ,t.maxZ)}let e=t.get(n);n=e?e.parent:null}}optimizeBVH(e,t){let n=performance.now();this.stats={reinsertionsApplied:0,iterations:0,timeMs:0};for(let r=0;r<this.maxIterations&&!(performance.now()-n>this.timeBudgetMs);r++){let i=this.buildParentMap(e),a=i.size,o=Math.max(1,Math.floor(a*this.batchSizeRatio));t&&t(`Reinsertion iter ${r+1}/${this.maxIterations}: selecting ${o} candidates`);let s=this.findCandidates(e,o,i),c=[];for(let t=0;t<s.length&&!(performance.now()-n>this.timeBudgetMs);t++){let n=this.findReinsertion(s[t].node,e,i);n&&n.areaDiff>0&&c.push(n)}c.sort((e,t)=>t.areaDiff-e.areaDiff);let l=new Set,u=0;for(let e of c){let t=this.getConflicts(e.from,e.to,i);if(!t.some(e=>l.has(e))){for(let e of t)l.add(e);this.reinsertNode(e.from,e.to,i),u++}}if(this.stats.reinsertionsApplied+=u,this.stats.iterations=r+1,t&&t(`Reinsertion iter ${r+1}: applied ${u} reinsertions`),u===0)break}return this.stats.timeMs=performance.now()-n,this.stats}};const r={silent:0,error:1,warn:2,info:3,debug:4},i=`info`,a=`rayzeeLogLevel`,o=`rayzeeLogNamespaces`,s=`color:#7c8494`,c=`color:inherit`;let l=null,u=null;function d(e){try{return globalThis.localStorage?.getItem(e)??null}catch{return null}}function f(e,t){try{t===null?globalThis.localStorage?.removeItem(e):globalThis.localStorage?.setItem(e,t)}catch{}}function p(){if(l!==null)return l;let e=globalThis.__RAYZEE_LOG_LEVEL__;return e!==void 0&&e in r?(l=r[e],l):(l=r[d(a)]??r[i],l)}function m(){if(u!==null)return u;let e=globalThis.__RAYZEE_LOG_NS__??d(o);return u=e?String(e).split(`,`).map(e=>e.trim()).filter(Boolean):[],u}function h(e,t){if(t<r.debug)return!0;let n=m();return n.length===0||n.some(t=>e===t||e.startsWith(`${t}:`))}function g(e,t,n){if(e>p()||!h(t,e))return;let i=e===r.error?console.error:e===r.warn?console.warn:console.log,a=`[${t}]`;typeof n[0]==`string`?i(`%c${a}%c ${n[0]}`,s,c,...n.slice(1)):i(`%c${a}`,s,...n)}const _={n:e=>Number(e).toLocaleString(`en-US`),ms:e=>e<10?`${Number(e).toFixed(1)} ms`:`${Math.round(e)} ms`,mb:e=>{let t=e/(1024*1024);return t<10?`${t.toFixed(1)} MB`:`${Math.round(t)} MB`},px:(e,t)=>`${e}×${t}`,count:(e,t,n=`${t}s`)=>`${_.n(e)} ${Number(e)===1?t:n}`,list:e=>e.filter(Boolean).join(` · `)},v={levels:r,setLevel(e){return e in r?(globalThis.__RAYZEE_LOG_LEVEL__=e,l=r[e],f(a,e===i?null:e),e):(console.warn(`[log] unknown level '${e}' — expected one of ${Object.keys(r).join(`, `)}`),this.getLevel())},getLevel(){let e=p();return Object.keys(r).find(t=>r[t]===e)},isEnabled(e){return(r[e]??r.debug)<=p()},only(...e){let t=e.flat().filter(Boolean);return u=t,globalThis.__RAYZEE_LOG_NS__=t.join(`,`),f(o,t.length?t.join(`,`):null),t.length&&this.setLevel(`debug`),t},refresh(){return l=null,u=null,this.getLevel()}};function y(e){return{namespace:e,error:(...t)=>g(r.error,e,t),warn:(...t)=>g(r.warn,e,t),info:(...t)=>g(r.info,e,t),debug:(...t)=>g(r.debug,e,t),isEnabled:e=>v.isEnabled(e),summary(t,n=[]){let i=n.filter(Boolean);if(i.length===0||!console.groupCollapsed){g(r.info,e,[t]),i.forEach(t=>g(r.debug,e,[t]));return}r.info>p()||((p()>=r.debug&&console.group?console.group:console.groupCollapsed)(`%c[${e}]%c ${t}`,s,c),i.forEach(e=>console.log(e)),console.groupEnd())}}}const b=y(`bvh`),x={FLOATS_PER_TRIANGLE:32,POSITION_A_OFFSET:0,POSITION_B_OFFSET:4,POSITION_C_OFFSET:8,NORMAL_A_OFFSET:12,NORMAL_B_OFFSET:16,NORMAL_C_OFFSET:20,UV_AB_OFFSET:24,UV_C_MAT_OFFSET:28},S=x.FLOATS_PER_TRIANGLE;var C=class{constructor(){this.minX=0,this.minY=0,this.minZ=0,this.maxX=0,this.maxY=0,this.maxZ=0,this.leftChild=null,this.rightChild=null,this.triangleOffset=0,this.triangleCount=0}},w=class{constructor(){this.useWorker=!0,this.maxLeafSize=8,this.numBins=32,this.minBins=8,this.maxBins=64,this.totalNodes=0,this.processedTriangles=0,this.totalTriangles=0,this.lastProgressUpdate=0,this.progressUpdateInterval=100,this.traversalCost=1,this.intersectionCost=2.5,this.useMortonCodes=!0,this.mortonBits=10,this.mortonClusterThreshold=128,this.enableObjectMedianFallback=!0,this.enableSpatialMedianFallback=!0,this.splitStats={sahSplits:0,objectMedianSplits:0,spatialMedianSplits:0,failedSplits:0,avgBinsUsed:0,totalSplitAttempts:0,mortonSortTime:0,totalBuildTime:0,treeletOptimizationTime:0,treeletsProcessed:0,treeletsImproved:0,averageSAHImprovement:0,reinsertionOptimizationTime:0,reinsertionsApplied:0,reinsertionIterations:0},this.enableTreeletOptimization=!1,this.treeletSize=5,this.treeletOptimizationPasses=1,this.treeletMinImprovement=.02,this.treeletComplexityThreshold=5e4,this.enableReinsertionOptimization=!0,this.reinsertionBatchSizeRatio=.02,this.reinsertionMaxIterations=2,this.initializeBinArrays(),this._partResult={mid:0,lMinX:0,lMinY:0,lMinZ:0,lMaxX:0,lMaxY:0,lMaxZ:0,rMinX:0,rMinY:0,rMinZ:0,rMaxX:0,rMaxY:0,rMaxZ:0},this.centroids=null,this.bMin=null,this.bMax=null,this.indices=null,this.mortonCodes=null,this.triangles=null,this.reorderedTriangleData=null}initializeBinArrays(){let e=this.maxBins;this.binBoundsMin=new Float32Array(e*3),this.binBoundsMax=new Float32Array(e*3),this.binCounts=new Uint32Array(e),this.leftPrefixMin=new Float32Array(e*3),this.leftPrefixMax=new Float32Array(e*3),this.leftPrefixCount=new Uint32Array(e),this.rightPrefixMin=new Float32Array(e*3),this.rightPrefixMax=new Float32Array(e*3),this.rightPrefixCount=new Uint32Array(e)}getOptimalBinCount(e){return e<=16?this.minBins:e<=64?16:e<=256?32:e<=1024?48:this.maxBins}setAdaptiveBinConfig(e){e.minBins!==void 0&&(this.minBins=Math.max(4,e.minBins)),e.maxBins!==void 0&&(this.maxBins=Math.min(128,e.maxBins)),e.baseBins!==void 0&&(this.numBins=e.baseBins),e.maxBins!==void 0&&this.initializeBinArrays()}setMortonConfig(e){e.enabled!==void 0&&(this.useMortonCodes=e.enabled),e.bits!==void 0&&(this.mortonBits=Math.max(6,Math.min(10,e.bits))),e.threshold!==void 0&&(this.mortonClusterThreshold=Math.max(16,e.threshold))}setFallbackConfig(e){e.objectMedian!==void 0&&(this.enableObjectMedianFallback=e.objectMedian),e.spatialMedian!==void 0&&(this.enableSpatialMedianFallback=e.spatialMedian)}setTreeletConfig(e){e.enabled!==void 0&&(this.enableTreeletOptimization=e.enabled),e.size!==void 0&&(this.treeletSize=Math.max(3,Math.min(12,e.size))),e.passes!==void 0&&(this.treeletOptimizationPasses=Math.max(1,Math.min(3,e.passes))),e.minImprovement!==void 0&&(this.treeletMinImprovement=Math.max(.001,e.minImprovement)),e.complexityThreshold!==void 0&&(this.treeletComplexityThreshold=e.complexityThreshold)}disableTreeletOptimization(){this.enableTreeletOptimization=!1}setReinsertionConfig(e){e.enabled!==void 0&&(this.enableReinsertionOptimization=e.enabled),e.batchSizeRatio!==void 0&&(this.reinsertionBatchSizeRatio=Math.max(.005,Math.min(.1,e.batchSizeRatio))),e.maxIterations!==void 0&&(this.reinsertionMaxIterations=Math.max(1,Math.min(5,e.maxIterations)))}initializeTriangleArrays(){let e=this.totalTriangles,t=this.triangles,n=x.POSITION_A_OFFSET,r=x.POSITION_B_OFFSET,i=x.POSITION_C_OFFSET;for(let a=0;a<e;a++){let e=a*S,o=t[e+n],s=t[e+n+1],c=t[e+n+2],l=t[e+r],u=t[e+r+1],d=t[e+r+2],f=t[e+i],p=t[e+i+1],m=t[e+i+2],h=a*3;this.centroids[h]=(o+l+f)/3,this.centroids[h+1]=(s+u+p)/3,this.centroids[h+2]=(c+d+m)/3,this.bMin[h]=o<l?o<f?o:f:l<f?l:f,this.bMin[h+1]=s<u?s<p?s:p:u<p?u:p,this.bMin[h+2]=c<d?c<m?c:m:d<m?d:m,this.bMax[h]=o>l?o>f?o:f:l>f?l:f,this.bMax[h+1]=s>u?s>p?s:p:u>p?u:p,this.bMax[h+2]=c>d?c>m?c:m:d>m?d:m,this.indices[a]=a}}expandBits(e){return e=e*65537&4278190335,e=e*257&251719695,e=e*17&3272356035,e=e*5&1227133513,e}morton3D(e,t,n){return(this.expandBits(n)<<2)+(this.expandBits(t)<<1)+this.expandBits(e)}computeMortonCodeForIndex(e,t,n,r,i,a,o){let s=this.centroids,c=e*3,l=(1<<this.mortonBits)-1,u=i>0?(s[c]-t)/i:0,d=a>0?(s[c+1]-n)/a:0,f=o>0?(s[c+2]-r)/o:0,p=Math.max(0,Math.min(l,Math.floor(u*l))),m=Math.max(0,Math.min(l,Math.floor(d*l))),h=Math.max(0,Math.min(l,Math.floor(f*l)));return this.morton3D(p,m,h)}sortTrianglesByMortonCode(){let e=this.totalTriangles;if(!this.useMortonCodes||e<this.mortonClusterThreshold)return;let t=performance.now(),n=this.centroids,r=this.indices,i=1/0,a=1/0,o=1/0,s=-1/0,c=-1/0,l=-1/0;for(let t=0;t<e;t++){let e=r[t]*3,u=n[e],d=n[e+1],f=n[e+2];u<i&&(i=u),d<a&&(a=d),f<o&&(o=f),u>s&&(s=u),d>c&&(c=d),f>l&&(l=f)}let u=s-i,d=c-a,f=l-o,p=this.mortonCodes,m=(1<<this.mortonBits)-1,h=u>0?m/u:0,g=d>0?m/d:0,_=f>0?m/f:0;for(let t=0;t<e;t++){let e=r[t],s=e*3,c=(n[s]-i)*h,l=(n[s+1]-a)*g,u=(n[s+2]-o)*_;c=c<0?0:(c>m?m:c)|0,l=l<0?0:(l>m?m:l)|0,u=u<0?0:(u>m?m:u)|0,c=c*65537&4278190335,c=c*257&251719695,c=c*17&3272356035,c=c*5&1227133513,l=l*65537&4278190335,l=l*257&251719695,l=l*17&3272356035,l=l*5&1227133513,u=u*65537&4278190335,u=u*257&251719695,u=u*17&3272356035,u=u*5&1227133513,p[e]=(u<<2)+(l<<1)+c}let v=new Uint32Array(e),y=new Uint32Array(256);for(let t=0;t<32;t+=8){y.fill(0);for(let n=0;n<e;n++)y[p[r[n]]>>>t&255]++;let n=0;for(let e=0;e<256;e++){let t=y[e];y[e]=n,n+=t}for(let n=0;n<e;n++){let e=p[r[n]]>>>t&255;v[y[e]++]=r[n]}r.set(v)}this.splitStats.mortonSortTime+=performance.now()-t}build(e,t=30,n=null){if(this.totalTriangles=e.byteLength/(S*4),this.processedTriangles=0,this.lastProgressUpdate=performance.now(),!(this.useWorker&&null))return new Promise(r=>{r(this._buildSyncAndFlatten(e,t,n))})}_buildSyncAndFlatten(e,t,n){let r=this.buildSync(e,t,n);return{bvhData:this.flattenBVH(r),bvhRoot:!0,reorderedTriangles:this.reorderedTriangleData||null,originalToBvh:this.originalToBvhMap||null}}buildSync(t,r=30,i=null,a=null){let o=performance.now();this.totalNodes=0,this.processedTriangles=0,this.triangles=t,this.totalTriangles=t.byteLength/(S*4),this.lastProgressUpdate=performance.now(),this.splitStats={sahSplits:0,objectMedianSplits:0,spatialMedianSplits:0,failedSplits:0,avgBinsUsed:0,totalSplitAttempts:0,mortonSortTime:0,totalBuildTime:0,treeletOptimizationTime:0,treeletsProcessed:0,treeletsImproved:0,averageSAHImprovement:0,reinsertionOptimizationTime:0,reinsertionsApplied:0,reinsertionIterations:0,saOrderTime:0,initTime:0,sahBuildTime:0,reorderTime:0};let s=this.totalTriangles,c=performance.now();this.centroids=new Float32Array(s*3),this.bMin=new Float32Array(s*3),this.bMax=new Float32Array(s*3),this.indices=new Uint32Array(s),this.mortonCodes=new Uint32Array(s),this.initializeTriangleArrays(),this.splitStats.initTime=performance.now()-c,this.sortTrianglesByMortonCode();let l=performance.now(),u=this.buildNodeRecursive(0,s,r,i);if(this.splitStats.sahBuildTime=performance.now()-l,this.enableTreeletOptimization&&this.totalTriangles>1e3){let t=this.totalTriangles>this.treeletComplexityThreshold?3:this.treeletSize,n=new e(this.traversalCost,this.intersectionCost);n.setTreeletSize(t),n.setMinImprovement(this.treeletMinImprovement);let r=performance.now();for(let e=0;e<this.treeletOptimizationPasses;e++){let t=i?t=>{i(`Treelet optimization pass ${e+1}/${this.treeletOptimizationPasses}: ${t}`)}:null;try{n.optimizeBVH(u,t)}catch(t){b.error(`treelet optimizer failed in pass ${e+1}:`,t);break}let a=n.getStatistics(),o=performance.now()-r;if(a.treeletsImproved===0&&e>0||o>15e3)break}let a=performance.now()-r;this.splitStats.treeletOptimizationTime=a;let o=n.getStatistics();this.splitStats.treeletsProcessed=o.treeletsProcessed,this.splitStats.treeletsImproved=o.treeletsImproved,this.splitStats.averageSAHImprovement=o.averageSAHImprovement}if(this.enableReinsertionOptimization&&this.totalTriangles>1e3){let e=new n(this.traversalCost,this.intersectionCost);e.setBatchSizeRatio(this.reinsertionBatchSizeRatio),e.setMaxIterations(this.reinsertionMaxIterations);let t=i?e=>{i(e)}:null;try{e.optimizeBVH(u,t)}catch(e){b.error(`reinsertion optimizer failed:`,e)}let r=e.getStatistics();this.splitStats.reinsertionOptimizationTime=r.timeMs,this.splitStats.reinsertionsApplied=r.reinsertionsApplied,this.splitStats.reinsertionIterations=r.iterations}let d=performance.now();this.applySAOrdering(u),this.splitStats.saOrderTime=performance.now()-d;let f=performance.now(),p=this.triangles,m=a||new Float32Array(s*S);for(let e=0;e<s;e++){let t=this.indices[e]*S,n=e*S;m.set(p.subarray(t,t+S),n)}this.reorderedTriangleData=m;let h=new Uint32Array(s);for(let e=0;e<s;e++)h[this.indices[e]]=e;this.originalToBvhMap=h,this.splitStats.reorderTime=performance.now()-f,this.splitStats.totalBuildTime=performance.now()-o;let g=this.splitStats.totalBuildTime,v=this.splitStats;return b.debug(`${_.n(s)} tris → ${_.n(this.totalNodes)} nodes in ${_.ms(g)} | SAH ${v.sahSplits} objMed ${v.objectMedianSplits} spatMed ${v.spatialMedianSplits} failed ${v.failedSplits}`+(v.treeletsProcessed?` | treelets ${v.treeletsImproved}/${v.treeletsProcessed} improved`:``)+(v.reinsertionsApplied?` | reinsertions ${v.reinsertionsApplied}`:``)),i&&i(100),this.centroids=null,this.bMin=null,this.bMax=null,this.mortonCodes=null,u}updateProgress(e,t){if(!t)return;this.processedTriangles+=e;let n=performance.now();n-this.lastProgressUpdate<this.progressUpdateInterval||(this.lastProgressUpdate=n,t(Math.min(Math.floor(this.processedTriangles/this.totalTriangles*100),99)))}buildNodeRecursiveToDepth(e,t,n,r,i,a,o,s,c,l,u){let d=new C;this.totalNodes++;let f=t-e;if(a===void 0?this.updateNodeBounds(d,e,t):(d.minX=a,d.minY=o,d.minZ=s,d.maxX=c,d.maxY=l,d.maxZ=u),f<=this.maxLeafSize||n<=0)return d.triangleOffset=e,d.triangleCount=f,this.updateProgress(f,i),d;if(r<=0&&f>this.maxLeafSize*16){let r=this.frontierTasks.length;return d.triangleOffset=e,d.triangleCount=f,d.isFrontier=!0,d.frontierTaskId=r,this.frontierTasks.push({taskId:r,start:e,end:t,depth:n,preMinX:d.minX,preMinY:d.minY,preMinZ:d.minZ,preMaxX:d.maxX,preMaxY:d.maxY,preMaxZ:d.maxZ}),d}let p=this.findBestSplitPositionSAH(e,t,d);if(!p.success){if(this.splitStats.failedSplits++,r>0||f<=this.maxLeafSize*16)return d.triangleOffset=e,d.triangleCount=f,this.updateProgress(f,i),d;let a=this.frontierTasks.length;return d.triangleOffset=e,d.triangleCount=f,d.isFrontier=!0,d.frontierTaskId=a,this.frontierTasks.push({taskId:a,start:e,end:t,depth:n,preMinX:d.minX,preMinY:d.minY,preMinZ:d.minZ,preMaxX:d.maxX,preMaxY:d.maxY,preMaxZ:d.maxZ}),d}p.method===`SAH`?this.splitStats.sahSplits++:p.method===`object_median`?this.splitStats.objectMedianSplits++:p.method===`spatial_median`&&this.splitStats.spatialMedianSplits++,this.partitionWithBounds(e,t,p.axis,p.pos);let m=this._partResult,h=m.mid,g=m.lMinX,_=m.lMinY,v=m.lMinZ,y=m.lMaxX,b=m.lMaxY,x=m.lMaxZ,S=m.rMinX,w=m.rMinY,T=m.rMinZ,E=m.rMaxX,D=m.rMaxY,O=m.rMaxZ;return h===e||h===t?(d.triangleOffset=e,d.triangleCount=f,this.updateProgress(f,i),d):(d.leftChild=this.buildNodeRecursiveToDepth(e,h,n-1,r-1,i,g,_,v,y,b,x),d.rightChild=this.buildNodeRecursiveToDepth(h,t,n-1,r-1,i,S,w,T,E,D,O),d)}buildNodeRecursive(e,t,n,r,i,a,o,s,c,l){let u=new C;this.totalNodes++;let d=t-e;if(i===void 0?this.updateNodeBounds(u,e,t):(u.minX=i,u.minY=a,u.minZ=o,u.maxX=s,u.maxY=c,u.maxZ=l),d<=this.maxLeafSize||n<=0)return u.triangleOffset=e,u.triangleCount=d,this.updateProgress(d,r),u;let f=this.findBestSplitPositionSAH(e,t,u);if(!f.success)return this.splitStats.failedSplits++,u.triangleOffset=e,u.triangleCount=d,this.updateProgress(d,r),u;f.method===`SAH`?this.splitStats.sahSplits++:f.method===`object_median`?this.splitStats.objectMedianSplits++:f.method===`spatial_median`&&this.splitStats.spatialMedianSplits++,this.partitionWithBounds(e,t,f.axis,f.pos);let p=this._partResult,m=p.mid,h=p.lMinX,g=p.lMinY,_=p.lMinZ,v=p.lMaxX,y=p.lMaxY,b=p.lMaxZ,x=p.rMinX,S=p.rMinY,w=p.rMinZ,T=p.rMaxX,E=p.rMaxY,D=p.rMaxZ;return m===e||m===t?(u.triangleOffset=e,u.triangleCount=d,this.updateProgress(d,r),u):(u.leftChild=this.buildNodeRecursive(e,m,n-1,r,h,g,_,v,y,b),u.rightChild=this.buildNodeRecursive(m,t,n-1,r,x,S,w,T,E,D),u)}partitionWithBounds(e,t,n,r){let i=this.indices,a=this.centroids,o=this.bMin,s=this.bMax,c=e,l=t-1,u=1/0,d=1/0,f=1/0,p=-1/0,m=-1/0,h=-1/0,g=1/0,_=1/0,v=1/0,y=-1/0,b=-1/0,x=-1/0;for(;c<=l;){let e=i[c],t=e*3;a[t+n]<=r?(o[t]<u&&(u=o[t]),o[t+1]<d&&(d=o[t+1]),o[t+2]<f&&(f=o[t+2]),s[t]>p&&(p=s[t]),s[t+1]>m&&(m=s[t+1]),s[t+2]>h&&(h=s[t+2]),c++):(o[t]<g&&(g=o[t]),o[t+1]<_&&(_=o[t+1]),o[t+2]<v&&(v=o[t+2]),s[t]>y&&(y=s[t]),s[t+1]>b&&(b=s[t+1]),s[t+2]>x&&(x=s[t+2]),i[c]=i[l],i[l]=e,l--)}let S=this._partResult;return S.mid=c,S.lMinX=u,S.lMinY=d,S.lMinZ=f,S.lMaxX=p,S.lMaxY=m,S.lMaxZ=h,S.rMinX=g,S.rMinY=_,S.rMinZ=v,S.rMaxX=y,S.rMaxY=b,S.rMaxZ=x,S}updateNodeBounds(e,t,n){let r=1/0,i=1/0,a=1/0,o=-1/0,s=-1/0,c=-1/0,l=this.indices,u=this.bMin,d=this.bMax;for(let e=t;e<n;e++){let t=l[e]*3;u[t]<r&&(r=u[t]),u[t+1]<i&&(i=u[t+1]),u[t+2]<a&&(a=u[t+2]),d[t]>o&&(o=d[t]),d[t+1]>s&&(s=d[t+1]),d[t+2]>c&&(c=d[t+2])}e.minX=r,e.minY=i,e.minZ=a,e.maxX=o,e.maxY=s,e.maxZ=c}findBestSplitPositionSAH(e,t,n){let r=1/0,i=-1,a=0,o=this.computeSurfaceAreaFlat(n.minX,n.minY,n.minZ,n.maxX,n.maxY,n.maxZ),s=t-e,c=this.intersectionCost*s,l=this.getOptimalBinCount(s);this.splitStats.totalSplitAttempts++,this.splitStats.avgBinsUsed=(this.splitStats.avgBinsUsed*(this.splitStats.totalSplitAttempts-1)+l)/this.splitStats.totalSplitAttempts;let u=this.indices,d=this.centroids,f=this.bMin,p=this.bMax,m=this.binBoundsMin,h=this.binBoundsMax,g=this.binCounts,_=this.leftPrefixMin,v=this.leftPrefixMax,y=this.leftPrefixCount,b=this.rightPrefixMin,x=this.rightPrefixMax,S=this.rightPrefixCount,C=1/0,w=-1/0,T=1/0,E=-1/0,D=1/0,O=-1/0;for(let n=e;n<t;n++){let e=u[n]*3,t=d[e],r=d[e+1],i=d[e+2];t<C&&(C=t),t>w&&(w=t),r<T&&(T=r),r>E&&(E=r),i<D&&(D=i),i>O&&(O=i)}let k=[C,T,D],A=[w,E,O];for(let n=0;n<3;n++){let s=k[n],C=A[n];if(C-s<1e-6)continue;for(let e=0;e<l;e++){g[e]=0;let t=e*3;m[t]=1/0,m[t+1]=1/0,m[t+2]=1/0,h[t]=-1/0,h[t+1]=-1/0,h[t+2]=-1/0}let w=l/(C-s);for(let r=e;r<t;r++){let e=u[r],t=d[e*3+n],i=Math.floor((t-s)*w);i>=l&&(i=l-1),g[i]++;let a=i*3,o=e*3;f[o]<m[a]&&(m[a]=f[o]),f[o+1]<m[a+1]&&(m[a+1]=f[o+1]),f[o+2]<m[a+2]&&(m[a+2]=f[o+2]),p[o]>h[a]&&(h[a]=p[o]),p[o+1]>h[a+1]&&(h[a+1]=p[o+1]),p[o+2]>h[a+2]&&(h[a+2]=p[o+2])}y[0]=g[0],_[0]=m[0],_[1]=m[1],_[2]=m[2],v[0]=h[0],v[1]=h[1],v[2]=h[2];for(let e=1;e<l;e++){let t=e*3,n=(e-1)*3;y[e]=y[e-1]+g[e];let r=_[n],i=m[t],a=_[n+1],o=m[t+1],s=_[n+2],c=m[t+2];_[t]=r<i?r:i,_[t+1]=a<o?a:o,_[t+2]=s<c?s:c;let l=v[n],u=h[t],d=v[n+1],f=h[t+1],p=v[n+2],b=h[t+2];v[t]=l>u?l:u,v[t+1]=d>f?d:f,v[t+2]=p>b?p:b}let T=l-1,E=T*3;S[T]=g[T],b[E]=m[E],b[E+1]=m[E+1],b[E+2]=m[E+2],x[E]=h[E],x[E+1]=h[E+1],x[E+2]=h[E+2];for(let e=T-1;e>=0;e--){let t=e*3,n=(e+1)*3;S[e]=S[e+1]+g[e];let r=b[n],i=m[t],a=b[n+1],o=m[t+1],s=b[n+2],c=m[t+2];b[t]=r<i?r:i,b[t+1]=a<o?a:o,b[t+2]=s<c?s:c;let l=x[n],u=h[t],d=x[n+1],f=h[t+1],p=x[n+2],_=h[t+2];x[t]=l>u?l:u,x[t+1]=d>f?d:f,x[t+2]=p>_?p:_}for(let e=1;e<l;e++){let t=(e-1)*3,u=e*3,d=y[e-1],f=S[e];if(d===0||f===0)continue;let p=v[t]-_[t],m=v[t+1]-_[t+1],h=v[t+2]-_[t+2],g=2*(p*m+m*h+h*p),w=x[u]-b[u],T=x[u+1]-b[u+1],E=x[u+2]-b[u+2],D=2*(w*T+T*E+E*w),O=this.traversalCost+g/o*d*this.intersectionCost+D/o*f*this.intersectionCost;O<r&&O<c&&(r=O,i=n,a=s+(C-s)*e/l)}}return i===-1?this.enableObjectMedianFallback?this.findObjectMedianSplit(e,t):this.enableSpatialMedianFallback?this.findSpatialMedianSplit(e,t):{success:!1,method:`fallbacks_disabled`}:{success:!0,axis:i,pos:a,method:`SAH`,binsUsed:l}}findObjectMedianSplit(e,t){let n=this.indices,r=this.centroids,i=-1,a=-1;for(let o=0;o<3;o++){let s=1/0,c=-1/0;for(let i=e;i<t;i++){let e=r[n[i]*3+o];e<s&&(s=e),e>c&&(c=e)}let l=c-s;l>a&&(a=l,i=o)}if(i===-1||a<1e-10)return this.enableSpatialMedianFallback?this.findSpatialMedianSplit(e,t):{success:!1,method:`object_median_failed`};let o=t-e,s=e+Math.floor(o/2);this.quickselect(e,t,s,i);let c=r[n[s]*3+i],l=!0;for(let e=s+1;e<t;e++)if(r[n[e]*3+i]>c){l=!1;break}if(l){let a=-1/0;for(let t=e;t<s;t++){let e=r[n[t]*3+i];e>a&&(a=e)}if(a<c)c=(a+c)*.5;else return this.enableSpatialMedianFallback?this.findSpatialMedianSplit(e,t):{success:!1,method:`object_median_degenerate`}}return{success:!0,axis:i,pos:c,method:`object_median`}}findSpatialMedianSplit(e,t){let n=this.indices,r=this.centroids,i=this.bMin,a=this.bMax,o=-1,s=-1,c=0,l=0;for(let r=0;r<3;r++){let u=1/0,d=-1/0;for(let o=e;o<t;o++){let e=n[o]*3+r;i[e]<u&&(u=i[e]),a[e]>d&&(d=a[e])}let f=d-u;f>s&&(s=f,o=r,c=u,l=d)}if(o===-1||s<1e-12)return{success:!1,method:`spatial_median_failed`};let u=(c+l)*.5,d=t-e,f=0;for(let i=e;i<t;i++)r[n[i]*3+o]<=u&&f++;if(f===0||f===d){let i=e+Math.floor(d/2);this.quickselect(e,t,i,o);let a=r[n[i]*3+o],s=!0;for(let i=e;i<t;i++)if(r[n[i]*3+o]!==a){s=!1;break}if(s)return{success:!1,method:`spatial_median_degenerate`};let c=-1/0;for(let t=e;t<i;t++){let e=r[n[t]*3+o];e>c&&(c=e)}if(c<a)u=(c+a)*.5;else{let e=1/0;for(let a=i+1;a<t;a++){let t=r[n[a]*3+o];t<e&&(e=t)}u=(a+e)*.5}}return{success:!0,axis:o,pos:u,method:`spatial_median`}}quickselect(e,t,n,r){let i=this.indices,a=this.centroids,o=e,s=t-1;for(;o<s;){let e=o+s>>>1,t=a[i[o]*3+r],c=a[i[e]*3+r],l=a[i[s]*3+r];if(t>c){let t=i[o];i[o]=i[e],i[e]=t}if(t>l){let e=i[o];i[o]=i[s],i[s]=e}if(c>l){let t=i[e];i[e]=i[s],i[s]=t}let u=a[i[e]*3+r],d=o,f=s;for(;d<=f;){for(;a[i[d]*3+r]<u;)d++;for(;a[i[f]*3+r]>u;)f--;if(d<=f){let e=i[d];i[d]=i[f],i[f]=e,d++,f--}}f<n&&(o=d),d>n&&(s=f)}}applySAOrdering(e){if(!e||!e.leftChild)return;let t=[e],n=[];for(;t.length>0;){let e=t.pop();!e.leftChild||!e.rightChild||(n.push(e),t.push(e.leftChild),t.push(e.rightChild))}for(let e=n.length-1;e>=0;e--){let t=n[e],r=t.leftChild,i=t.rightChild,a=r.maxX-r.minX,o=r.maxY-r.minY,s=r.maxZ-r.minZ,c=i.maxX-i.minX,l=i.maxY-i.minY,u=i.maxZ-i.minZ;c*l+l*u+u*c>a*o+o*s+s*a&&(t.leftChild=i,t.rightChild=r)}}flattenBVH(e){let t=[],n=[e];for(;n.length>0;){let e=n.pop();e._flatIndex=t.length,t.push(e),e.rightChild&&n.push(e.rightChild),e.leftChild&&n.push(e.leftChild)}let r=new Float32Array(t.length*16);for(let e=0;e<t.length;e++){let n=t[e],i=e*16;if(n.leftChild){let e=n.leftChild,t=n.rightChild;r[i]=e.minX,r[i+1]=e.minY,r[i+2]=e.minZ,r[i+3]=e._flatIndex,r[i+4]=e.maxX,r[i+5]=e.maxY,r[i+6]=e.maxZ,r[i+7]=t._flatIndex,r[i+8]=t.minX,r[i+9]=t.minY,r[i+10]=t.minZ,r[i+12]=t.maxX,r[i+13]=t.maxY,r[i+14]=t.maxZ}else r[i]=n.triangleOffset,r[i+1]=n.triangleCount,r[i+3]=-1}return r}flattenBVHWithFrontier(e){let t=[],n=[e];for(;n.length>0;){let e=n.pop();e._flatIndex=t.length,t.push(e),e.rightChild&&n.push(e.rightChild),e.leftChild&&n.push(e.leftChild)}let r=new Float32Array(t.length*16),i=[];for(let e=0;e<t.length;e++){let n=t[e],a=e*16;if(n.leftChild){let e=n.leftChild,t=n.rightChild;r[a]=e.minX,r[a+1]=e.minY,r[a+2]=e.minZ,r[a+3]=e._flatIndex,r[a+4]=e.maxX,r[a+5]=e.maxY,r[a+6]=e.maxZ,r[a+7]=t._flatIndex,r[a+8]=t.minX,r[a+9]=t.minY,r[a+10]=t.minZ,r[a+12]=t.maxX,r[a+13]=t.maxY,r[a+14]=t.maxZ}else if(n.isFrontier){let t=n.frontierTaskId;r[a]=n.triangleOffset,r[a+1]=n.triangleCount,r[a+2]=t,r[a+3]=-2,i.push({taskId:t,flatIndex:e})}else r[a]=n.triangleOffset,r[a+1]=n.triangleCount,r[a+3]=-1}return{flatData:r,frontierMap:i,nodeCount:t.length}}assembleParallelBVH(e,t,n,r){let i=[...r].sort((e,t)=>e.taskId-t.taskId),a=t;for(let e=0;e<i.length;e++)a+=i[e].nodeCount;let o=new Float32Array(a*16);o.set(e);let s=new Map;for(let e of n)s.set(e.taskId,e.flatIndex);let c=t;for(let e=0;e<i.length;e++){let t=i[e],n=t.flatData,r=t.nodeCount,a=c*16;o.set(n,a);for(let e=0;e<r;e++){let t=a+e*16;o[t+3]!==-1&&(o[t+3]+=c,o[t+7]+=c)}let l=s.get(t.taskId);if(l!==void 0){let e=l*16,t=a;for(let n=0;n<16;n++)o[e+n]=o[t+n]}c+=r}return o}computeSurfaceAreaFlat(e,t,n,r,i,a){let o=r-e,s=i-t,c=a-n;return 2*(o*s+s*c+c*o)}};self.onmessage=function(t){let{tasks:r,sharedTriangleData:i,sharedCentroids:a,sharedBMin:o,sharedBMax:s,sharedIndices:c,triangleCount:l,maxLeafSize:u,numBins:d,maxBins:f,minBins:p,treeletConfig:m,reinsertionConfig:h,reportProgress:g}=t.data;for(let t=0;t<r.length;t++){let _=r[t];try{let t=new w;t.maxLeafSize=u,t.numBins=d,t.maxBins=f,t.minBins=p,t.triangles=new Float32Array(i),t.centroids=new Float32Array(a),t.bMin=new Float32Array(o),t.bMax=new Float32Array(s),t.indices=new Uint32Array(c),t.totalTriangles=l,t.totalNodes=0,t.processedTriangles=0,t.lastProgressUpdate=performance.now(),t.splitStats={sahSplits:0,objectMedianSplits:0,spatialMedianSplits:0,failedSplits:0,avgBinsUsed:0,totalSplitAttempts:0,mortonSortTime:0,totalBuildTime:0,treeletOptimizationTime:0,treeletsProcessed:0,treeletsImproved:0,averageSAHImprovement:0,initTime:0,sahBuildTime:0,reorderTime:0};let r=g?e=>{self.postMessage({type:`progress`,taskId:_.taskId,progress:e})}:null,v=performance.now(),y=t.buildNodeRecursive(_.start,_.end,_.depth,r,_.preMinX,_.preMinY,_.preMinZ,_.preMaxX,_.preMaxY,_.preMaxZ);if(m&&m.enabled&&_.end-_.start>1e3){let n=_.end-_.start>5e4,r=n?3:m.size||5,i=n?10:20,a=new e(t.traversalCost,t.intersectionCost);a.setTreeletSize(r),a.setMinImprovement(m.minImprovement||.02),a.setMaxTreelets(i);let o=m.passes||1;for(let e=0;e<o;e++)try{a.optimizeBVH(y,null)}catch(t){console.error(`[BVHSubtreeWorker] Treelet pass ${e+1} error:`,t);break}}if(h&&h.enabled&&_.end-_.start>1e3){let e=new n(t.traversalCost,t.intersectionCost);h.batchSizeRatio&&e.setBatchSizeRatio(h.batchSizeRatio),h.maxIterations&&e.setMaxIterations(h.maxIterations);try{e.optimizeBVH(y,null)}catch(e){console.error(`[BVHSubtreeWorker] Reinsertion error:`,e)}}t.applySAOrdering(y);let b=t.flattenBVH(y),x=b.length/16,S=performance.now()-v;console.log(`[BVHSubtreeWorker] Task ${_.taskId}: ${(_.end-_.start).toLocaleString()} triangles, ${x} nodes, ${Math.round(S)}ms`),self.postMessage({type:`subtreeResult`,taskId:_.taskId,flatData:b,nodeCount:x},[b.buffer])}catch(e){console.error(`[BVHSubtreeWorker] Task ${_.taskId} error:`,e),self.postMessage({type:`error`,taskId:_.taskId,error:e.message})}}};", _c = typeof self < "u" && self.Blob && new Blob(["URL.revokeObjectURL(import.meta.url);", gc], { type: "text/javascript;charset=utf-8" });
5562
5567
  function vc(e) {
5563
5568
  let t;
5564
5569
  try {
@@ -7382,9 +7387,11 @@ var Zc = ai("scene"), Qc = class {
7382
7387
  maxTextureSize: Ir.DEFAULT_MAX_TEXTURE_SIZE,
7383
7388
  enableTextureCache: !0,
7384
7389
  maxConcurrentTextureTasks: Math.min(navigator.hardwareConcurrency || 4, 6),
7390
+ enableTreeletOptimization: !1,
7385
7391
  treeletSize: 7,
7386
7392
  treeletOptimizationPasses: 1,
7387
7393
  treeletMinImprovement: .01,
7394
+ treeletComplexityThreshold: 5e4,
7388
7395
  ...e
7389
7396
  }, this.triangleData = null, this.triangleCount = 0, this.materials = [], this.maps = [], this.normalMaps = [], this.bumpMaps = [], this.roughnessMaps = [], this.metalnessMaps = [], this.emissiveMaps = [], this.displacementMaps = [], this.anisotropyMaps = [], this.transmissionMaps = [], this.clearcoatMaps = [], this.clearcoatRoughnessMaps = [], this.sheenColorMaps = [], this.sheenRoughnessMaps = [], this.iridescenceMaps = [], this.iridescenceThicknessMaps = [], this.specularIntensityMaps = [], this.specularColorMaps = [], this.directionalLights = [], this.cameras = [], this.spheres = [], this.bvhRoot = null, this.bvhData = null, this.materialData = null, this.instanceTable = null, this.originalToBvhMap = null, this._refitWorker = null, this._refitSharedBuffers = null, this._rebuildGeneration = 0, this._pendingRebuilds = /* @__PURE__ */ new Map(), this.srgbBucketTextures = null, this.linearBucketTextures = null, this.emissiveTriangleData = null, this.emissiveTriangleCount = 0, this.lightBVHNodeData = null, this.lightBVHNodeCount = 0, this.emissiveBitTrailMap = null, this._initProcessors(), this.isProcessing = !1, this.processingStage = null, this.performanceMetrics = {
7390
7397
  textureCreationTime: 0,
@@ -7401,7 +7408,8 @@ var Zc = ai("scene"), Qc = class {
7401
7408
  enabled: this.config.enableTreeletOptimization,
7402
7409
  size: this.config.treeletSize,
7403
7410
  passes: this.config.treeletOptimizationPasses,
7404
- minImprovement: this.config.treeletMinImprovement
7411
+ minImprovement: this.config.treeletMinImprovement,
7412
+ complexityThreshold: this.config.treeletComplexityThreshold
7405
7413
  }), this.textureCreator = new Lc({ maxTextureSize: this.config.maxTextureSize }), this.emissiveTriangleBuilder = new Kc(), this.tlasBuilder = new kc();
7406
7414
  }
7407
7415
  _log(e, t) {
@@ -7489,7 +7497,8 @@ var Zc = ai("scene"), Qc = class {
7489
7497
  enabled: i !== !1,
7490
7498
  size: this.config.treeletSize,
7491
7499
  passes: this.config.treeletOptimizationPasses,
7492
- minImprovement: this.config.treeletMinImprovement
7500
+ minImprovement: this.config.treeletMinImprovement,
7501
+ complexityThreshold: this.config.treeletComplexityThreshold
7493
7502
  },
7494
7503
  reinsertionOptimization: {
7495
7504
  enabled: this.bvhBuilder.enableReinsertionOptimization,
@@ -7795,7 +7804,8 @@ var Zc = ai("scene"), Qc = class {
7795
7804
  enabled: this.config.enableTreeletOptimization,
7796
7805
  size: this.config.treeletSize,
7797
7806
  passes: this.config.treeletOptimizationPasses,
7798
- minImprovement: this.config.treeletMinImprovement
7807
+ minImprovement: this.config.treeletMinImprovement,
7808
+ complexityThreshold: this.config.treeletComplexityThreshold
7799
7809
  })), this._log("Configuration updated", this.config);
7800
7810
  }
7801
7811
  async refitBVH(e, t) {
@@ -7956,7 +7966,8 @@ var Zc = ai("scene"), Qc = class {
7956
7966
  enabled: s,
7957
7967
  size: this.config.treeletSize,
7958
7968
  passes: this.config.treeletOptimizationPasses,
7959
- minImprovement: this.config.treeletMinImprovement
7969
+ minImprovement: this.config.treeletMinImprovement,
7970
+ complexityThreshold: this.config.treeletComplexityThreshold
7960
7971
  },
7961
7972
  reinsertionOptimization: {
7962
7973
  enabled: this.bvhBuilder.enableReinsertionOptimization,
@@ -8745,7 +8756,7 @@ var vl = class {
8745
8756
  ACTIVE_RAY_COUNT: 0,
8746
8757
  ENTERING_COUNT: 1,
8747
8758
  CONVERGED_COUNT: 2,
8748
- FROZEN_COUNT: 3,
8759
+ RESERVED_3: 3,
8749
8760
  ACTIVE_PIXEL_COUNT: 4,
8750
8761
  COUNT: 5
8751
8762
  }, ru = {
@@ -8906,46 +8917,9 @@ var uu = class {
8906
8917
  let e = (e) => (e / 1048576).toFixed(1), t = Object.entries(this.byCategory).map(([t, n]) => `${t}=${e(n)}`);
8907
8918
  return `VRAM current=${e(this.current)}MB peak=${e(this.peak)}MB [${t.join(" ")}]`;
8908
8919
  }
8909
- }, du = ai("wavefront"), fu = {
8910
- generate: [
8911
- 16,
8912
- 16,
8913
- 1
8914
- ],
8915
- extend: [
8916
- 256,
8917
- 1,
8918
- 1
8919
- ],
8920
- shade: [
8921
- 256,
8922
- 1,
8923
- 1
8924
- ],
8925
- connect: [
8926
- 256,
8927
- 1,
8928
- 1
8929
- ],
8930
- accumulate: [
8931
- 256,
8932
- 1,
8933
- 1
8934
- ],
8935
- compact: [
8936
- 256,
8937
- 1,
8938
- 1
8939
- ],
8940
- finalWrite: [
8941
- 16,
8942
- 16,
8943
- 1
8944
- ]
8945
- }, pu = class {
8920
+ }, du = ai("wavefront"), fu = class {
8946
8921
  constructor(e) {
8947
- this.renderer = e, this.kernels = /* @__PURE__ */ new Map(), this.workgroupSizes = /* @__PURE__ */ new Map(), this.timing = /* @__PURE__ */ new Map(), this.profiling = !1, this.profile = /* @__PURE__ */ new Map(), this._firstDispatches = [], this._firstDispatchFlush = null;
8948
- for (let [e, t] of Object.entries(fu)) this.workgroupSizes.set(e, t);
8922
+ this.renderer = e, this.kernels = /* @__PURE__ */ new Map(), this.timing = /* @__PURE__ */ new Map(), this.profiling = !1, this.profile = /* @__PURE__ */ new Map(), this._firstDispatches = [], this._firstDispatchFlush = null;
8949
8923
  }
8950
8924
  _recordFirstDispatch(e, t) {
8951
8925
  this._firstDispatches.push({
@@ -8984,38 +8958,21 @@ var uu = class {
8984
8958
  }, this.profile.set(e, i)), i.calls++, i.totalMs += r - n;
8985
8959
  } else this.renderer.compute(t);
8986
8960
  }
8987
- setDispatchCount(e, t) {
8961
+ setDispatchForCount(e, t) {
8988
8962
  let n = this.kernels.get(e);
8989
- n && (n.dispatchSize = t);
8990
- }
8991
- calcScreenDispatch(e, t, n) {
8992
- let r = this.workgroupSizes.get(n) || [
8993
- 16,
8994
- 16,
8995
- 1
8996
- ];
8997
- return [
8998
- Math.ceil(e / r[0]),
8999
- Math.ceil(t / r[1]),
9000
- 1
9001
- ];
9002
- }
9003
- calcRayDispatch(e, t) {
9004
- let n = this.workgroupSizes.get(t) || [
9005
- 256,
9006
- 1,
9007
- 1
9008
- ];
9009
- return [
9010
- Math.ceil(e / n[0]),
8963
+ n && (n.dispatchSize = [
8964
+ Math.ceil(t / n.workgroupSize[0]),
9011
8965
  1,
9012
8966
  1
9013
- ];
8967
+ ]);
9014
8968
  }
9015
- getWorkgroupSize(e) {
9016
- return this.workgroupSizes.get(e) || [
9017
- 256,
9018
- 1,
8969
+ setDispatchForGrid(e, t, n) {
8970
+ let r = this.kernels.get(e);
8971
+ if (!r) return;
8972
+ let i = r.workgroupSize;
8973
+ r.dispatchSize = [
8974
+ Math.ceil(t / i[0]),
8975
+ Math.ceil(n / i[1]),
9019
8976
  1
9020
8977
  ];
9021
8978
  }
@@ -9051,7 +9008,66 @@ var uu = class {
9051
9008
  dispose() {
9052
9009
  clearTimeout(this._firstDispatchFlush), this._firstDispatchFlush = null, this._firstDispatches = [], this.kernels.clear(), this.timing.clear(), this.profile.clear();
9053
9010
  }
9054
- }, mu = 32, hu = 512, gu = 4, _u = 8, vu = 1e8, yu = () => y("int", mu).toVar(), bu = G("\n fn RayTriangleGeometry( rayOrigin: vec3f, rayDir: vec3f, pA: vec3f, pB: vec3f, pC: vec3f, closestHitDst: f32, woopParams: vec4f ) -> vec4f {\n\n // Returns vec4(t, u, v, hit) where hit > 0.5 means intersection.\n // woopParams: (Sx, Sy, Sz, bitcast<f32>(packed kx|ky<<2|kz<<4))\n var result = vec4f( 1e20f, 0.0f, 0.0f, 0.0f );\n\n let Sx = woopParams.x;\n let Sy = woopParams.y;\n let Sz = woopParams.z;\n // Packed as regular f32 (values 0–42), not bitcast — avoids subnormal FTZ on Apple GPUs.\n let packed = i32( woopParams.w );\n let kx = packed & 3;\n let ky = ( packed >> 2 ) & 3;\n let kz = ( packed >> 4 ) & 3;\n\n let A = pA - rayOrigin;\n let B = pB - rayOrigin;\n let C = pC - rayOrigin;\n\n let Akz = A[ kz ];\n let Bkz = B[ kz ];\n let Ckz = C[ kz ];\n\n let Ax = A[ kx ] - Sx * Akz;\n let Ay = A[ ky ] - Sy * Akz;\n let Bx = B[ kx ] - Sx * Bkz;\n let By = B[ ky ] - Sy * Bkz;\n let Cx = C[ kx ] - Sx * Ckz;\n let Cy = C[ ky ] - Sy * Ckz;\n\n // Edge function tests — all three must share sign (or be exactly zero) for hit.\n let U = Cx * By - Cy * Bx;\n let V = Ax * Cy - Ay * Cx;\n let W = Bx * Ay - By * Ax;\n\n let neg = U < 0.0f || V < 0.0f || W < 0.0f;\n let pos = U > 0.0f || V > 0.0f || W > 0.0f;\n if ( !( neg && pos ) ) {\n\n let det = U + V + W;\n if ( det != 0.0f ) {\n\n let T = U * ( Sz * Akz ) + V * ( Sz * Bkz ) + W * ( Sz * Ckz );\n\n // Sign-aware bounds check on t (multiply both sides by sign(det) once).\n let detSign = select( -1.0f, 1.0f, det > 0.0f );\n let tSigned = T * detSign;\n let detAbs = abs( det );\n\n if ( tSigned > 0.0f && tSigned < closestHitDst * detAbs ) {\n\n // Match Möller-Trumbore convention: u = weight of B, v = weight of C.\n // In Woop's edge functions, U → weight of A, V → weight of B, W → weight of C.\n let invDet = 1.0f / det;\n result = vec4f( T * invDet, V * invDet, W * invDet, 1.0f );\n\n }\n\n }\n\n }\n\n return result;\n\n }\n"), xu = G("\n fn computeWoopRayParams( rayDir: vec3f ) -> vec4f {\n\n let absDir = abs( rayDir );\n\n // kz = argmax(|dir|)\n var kz: i32 = 0;\n if ( absDir.y >= absDir.x ) { kz = 1; }\n if ( absDir.z >= absDir[ u32( kz ) ] ) { kz = 2; }\n\n var kx: i32 = ( kz + 1 ) % 3;\n var ky: i32 = ( kx + 1 ) % 3;\n\n // Preserve triangle winding when the dominant axis component is negative.\n if ( rayDir[ u32( kz ) ] < 0.0f ) {\n let tmp = kx;\n kx = ky;\n ky = tmp;\n }\n\n let dz = rayDir[ u32( kz ) ];\n let Sx = rayDir[ u32( kx ) ] / dz;\n let Sy = rayDir[ u32( ky ) ] / dz;\n let Sz = 1.0f / dz;\n\n let packed = kx | ( ky << 2 ) | ( kz << 4 );\n return vec4f( Sx, Sy, Sz, f32( packed ) );\n\n }\n"), Su = G("\n fn fastRayAABBDst( rayOrigin: vec3f, invDir: vec3f, boxMin: vec3f, boxMax: vec3f ) -> f32 {\n\n let t1 = ( boxMin - rayOrigin ) * invDir;\n let t2 = ( boxMax - rayOrigin ) * invDir;\n\n let tmin = min( t1, t2 );\n let tmax = max( t1, t2 );\n\n let tNear = max( max( tmin.x, tmin.y ), tmin.z );\n let tFar = min( min( tmax.x, tmax.y ), tmax.z ) * 1.00000024f; // Robust traversal: 2 ULP padding (Ize 2013)\n\n let isHit = tNear <= tFar && tFar > 0.0f;\n return select( 1e20f, max( tNear, 0.0f ), isHit );\n\n }\n"), Cu = (e) => f(([t, n, r, i]) => {
9011
+ }, pu = f(([e, t, n, r, i, a, o]) => {
9012
+ let s = U(0).toVar();
9013
+ return p(r.equal(N(1)), () => {
9014
+ let n = fe(i.x, i.y, e.x).toVar(), r = fe(a.y, a.x, e.y).toVar(), c = D(r).toVar(), l = U(0).toVar(), u = U(0).toVar(), d = U(0).toVar();
9015
+ p(o.equal(N(1)), () => {
9016
+ let e = U(t[2].x, 0, t[2].z).toVar();
9017
+ p(A(e, e).lessThan(j(1e-8)), () => {
9018
+ e.assign(U(t[1].x, 0, t[1].z));
9019
+ }), d.assign(I(e)), u.assign(U(0, 1, 0)), l.assign(O(u, d));
9020
+ }).Else(() => {
9021
+ l.assign(I(U(t[0]))), u.assign(I(U(t[1]))), d.assign(I(U(t[2])));
9022
+ }), s.assign(I(l.mul(Se(n).mul(c)).add(u.mul(Se(r))).sub(d.mul(D(n).mul(c)))));
9023
+ }).Else(() => {
9024
+ let r = U(e.x.mul(2).sub(1), j(1).sub(e.y.mul(2)), 1), i = n.mul(W(r, 1));
9025
+ s.assign(I(ue(t[0].xyz, t[1].xyz, t[2].xyz).mul(i.xyz.div(i.w))));
9026
+ }), s;
9027
+ }), mu = f(([e, t, n, r, i, a, o, s, c, l, u, d, f, m, h]) => {
9028
+ let g = U(n[3]).toVar(), _ = pu(e, n, r, i, a, o, s).toVar(), v = g.toVar(), y = _.toVar();
9029
+ return p(c.and(l.greaterThan(0)).and(u.lessThan(64)).and(d.greaterThan(.001)), () => {
9030
+ let e = l.div(u).mul(.001).mul(f).mul(m), r = qn(t), a = r.x.mul(h.max(.01)), o = r.y, s = U(0).toVar();
9031
+ p(i.equal(N(1)), () => {
9032
+ s.assign(ja({ N: _ }).mul(U(a, o, 0)));
9033
+ }).Else(() => {
9034
+ let e = I(U(n[0])), t = I(U(n[1]));
9035
+ s.assign(e.mul(a).add(t.mul(o)));
9036
+ }), v.assign(g.add(s.mul(e))), y.assign(I(g.add(_.mul(d)).sub(v)));
9037
+ }), ea({
9038
+ origin: v,
9039
+ direction: y
9040
+ });
9041
+ });
9042
+ function hu(e) {
9043
+ let { rayBufferRW: t, rngBufferRW: n, gBufferRW: r, resolution: i, frame: a, cameraWorldMatrix: o, cameraProjectionMatrixInverse: s, cameraProjection: c, panoLonRange: l, panoLatRange: u, panoLevelHorizon: d, enableDOF: m, focalLength: h, aperture: g, focusDistance: _, sceneScale: v, apertureScale: y, anamorphicRatio: b, renderWidth: x, chunkRowBase: C, chunkRows: w, transmissiveBounces: T, transparentBackground: E, auxGBufferEnabled: D, listDriven: O = !1, activeIndicesRO: k = null, counters: A = null } = e, ee = D.greaterThan(z(0)), te = (e, f, x) => {
9044
+ let S = H(j(e).add(.5), j(f).add(.5)), C = Un({ state: sr({
9045
+ pixelCoord: S,
9046
+ rayIndex: N(0),
9047
+ frame: a
9048
+ }).toVar() }).toVar(), w = or(S, N(1), N(1), C, i, a).toVar().sub(.5), D = H(S.x.add(w.x), S.y.sub(w.y)).div(i), O = ea.wrap(mu(D, C, o, s, c, l, u, d, m, h, g, _, v, y, b));
9049
+ Ml(t, x, O.origin, N(0), N(0)), Nl(t, x, O.direction, z(ru.ACTIVE)), Pl(t, x, W(1, 1, 1, 0).xyz, j(0)), Fl(t, x, W(U(0), L(E, j(1), j(0)))), p(ee, () => {
9050
+ El(r, x, U(0, 0, 1), j(1), U(0)), Yl(t, x, U(1));
9051
+ }), Ul(t, x, z(0), z(T), j(1), j(1), j(1)), n.element(x).assign(C);
9052
+ };
9053
+ return f(() => {
9054
+ if (O) {
9055
+ let e = M;
9056
+ p(e.lessThan(S(A.element(z(nu.ENTERING_COUNT)))), () => {
9057
+ let t = N(k.element(e)), n = t.add(C.mul(x));
9058
+ te(n.mod(x), n.div(x), z(t));
9059
+ });
9060
+ } else {
9061
+ let e = N(He.x).mul(16).add(N(se.x)), t = N(He.y).mul(16).add(N(se.y));
9062
+ p(e.lessThan(x).and(t.lessThan(w)), () => {
9063
+ te(e, t.add(C), z(t.mul(x).add(e)));
9064
+ });
9065
+ }
9066
+ });
9067
+ }
9068
+ //#endregion
9069
+ //#region src/TSL/BVHTraversal.js
9070
+ var gu = 32, _u = 512, vu = 4, yu = 8, bu = 1e8, xu = () => y("int", gu).toVar(), Su = G("\n fn RayTriangleGeometry( rayOrigin: vec3f, rayDir: vec3f, pA: vec3f, pB: vec3f, pC: vec3f, closestHitDst: f32, woopParams: vec4f ) -> vec4f {\n\n // Returns vec4(t, u, v, hit) where hit > 0.5 means intersection.\n // woopParams: (Sx, Sy, Sz, bitcast<f32>(packed kx|ky<<2|kz<<4))\n var result = vec4f( 1e20f, 0.0f, 0.0f, 0.0f );\n\n let Sx = woopParams.x;\n let Sy = woopParams.y;\n let Sz = woopParams.z;\n // Packed as regular f32 (values 0–42), not bitcast — avoids subnormal FTZ on Apple GPUs.\n let packed = i32( woopParams.w );\n let kx = packed & 3;\n let ky = ( packed >> 2 ) & 3;\n let kz = ( packed >> 4 ) & 3;\n\n let A = pA - rayOrigin;\n let B = pB - rayOrigin;\n let C = pC - rayOrigin;\n\n let Akz = A[ kz ];\n let Bkz = B[ kz ];\n let Ckz = C[ kz ];\n\n let Ax = A[ kx ] - Sx * Akz;\n let Ay = A[ ky ] - Sy * Akz;\n let Bx = B[ kx ] - Sx * Bkz;\n let By = B[ ky ] - Sy * Bkz;\n let Cx = C[ kx ] - Sx * Ckz;\n let Cy = C[ ky ] - Sy * Ckz;\n\n // Edge function tests — all three must share sign (or be exactly zero) for hit.\n let U = Cx * By - Cy * Bx;\n let V = Ax * Cy - Ay * Cx;\n let W = Bx * Ay - By * Ax;\n\n let neg = U < 0.0f || V < 0.0f || W < 0.0f;\n let pos = U > 0.0f || V > 0.0f || W > 0.0f;\n if ( !( neg && pos ) ) {\n\n let det = U + V + W;\n if ( det != 0.0f ) {\n\n let T = U * ( Sz * Akz ) + V * ( Sz * Bkz ) + W * ( Sz * Ckz );\n\n // Sign-aware bounds check on t (multiply both sides by sign(det) once).\n let detSign = select( -1.0f, 1.0f, det > 0.0f );\n let tSigned = T * detSign;\n let detAbs = abs( det );\n\n if ( tSigned > 0.0f && tSigned < closestHitDst * detAbs ) {\n\n // Match Möller-Trumbore convention: u = weight of B, v = weight of C.\n // In Woop's edge functions, U → weight of A, V → weight of B, W → weight of C.\n let invDet = 1.0f / det;\n result = vec4f( T * invDet, V * invDet, W * invDet, 1.0f );\n\n }\n\n }\n\n }\n\n return result;\n\n }\n"), Cu = G("\n fn computeWoopRayParams( rayDir: vec3f ) -> vec4f {\n\n let absDir = abs( rayDir );\n\n // kz = argmax(|dir|)\n var kz: i32 = 0;\n if ( absDir.y >= absDir.x ) { kz = 1; }\n if ( absDir.z >= absDir[ u32( kz ) ] ) { kz = 2; }\n\n var kx: i32 = ( kz + 1 ) % 3;\n var ky: i32 = ( kx + 1 ) % 3;\n\n // Preserve triangle winding when the dominant axis component is negative.\n if ( rayDir[ u32( kz ) ] < 0.0f ) {\n let tmp = kx;\n kx = ky;\n ky = tmp;\n }\n\n let dz = rayDir[ u32( kz ) ];\n let Sx = rayDir[ u32( kx ) ] / dz;\n let Sy = rayDir[ u32( ky ) ] / dz;\n let Sz = 1.0f / dz;\n\n let packed = kx | ( ky << 2 ) | ( kz << 4 );\n return vec4f( Sx, Sy, Sz, f32( packed ) );\n\n }\n"), wu = G("\n fn fastRayAABBDst( rayOrigin: vec3f, invDir: vec3f, boxMin: vec3f, boxMax: vec3f ) -> f32 {\n\n let t1 = ( boxMin - rayOrigin ) * invDir;\n let t2 = ( boxMax - rayOrigin ) * invDir;\n\n let tmin = min( t1, t2 );\n let tmax = max( t1, t2 );\n\n let tNear = max( max( tmin.x, tmin.y ), tmin.z );\n let tFar = min( min( tmax.x, tmax.y ), tmax.z ) * 1.00000024f; // Robust traversal: 2 ULP padding (Ize 2013)\n\n let isHit = tNear <= tFar && tFar > 0.0f;\n return select( 1e20f, max( tNear, 0.0f ), isHit );\n\n }\n"), Tu = (e) => f(([t, n, r, i]) => {
9055
9071
  let a = i ?? T(!1), o = aa({
9056
9072
  didHit: !1,
9057
9073
  dst: j(0x56bc75e2d63100000),
@@ -9062,12 +9078,12 @@ var uu = class {
9062
9078
  meshIndex: N(-1),
9063
9079
  boxTests: N(0),
9064
9080
  triTests: N(0)
9065
- }).toVar(), s = N(-1).toVar(), c = j(0).toVar(), l = j(0).toVar(), u = yu(), f = N(1).toVar();
9081
+ }).toVar(), s = N(-1).toVar(), c = j(0).toVar(), l = j(0).toVar(), u = xu(), f = N(1).toVar();
9066
9082
  u.element(N(0)).assign(N(0));
9067
- let h = fe(U(1), xe(t.direction), me(t.direction, U(0))), g = fe(U(1).div(t.direction), U(vu).mul(h), oe(_(t.direction), U(1e-8))).toVar(), v = t.origin, y = t.direction, b = xu({ rayDir: y }).toVar(), x = N(0).toVar();
9068
- return m(f.greaterThan(N(0)).and(x.lessThan(N(hu))), () => {
9083
+ let h = fe(U(1), xe(t.direction), me(t.direction, U(0))), g = fe(U(1).div(t.direction), U(bu).mul(h), oe(_(t.direction), U(1e-8))).toVar(), v = t.origin, y = t.direction, b = Cu({ rayDir: y }).toVar(), x = N(0).toVar();
9084
+ return m(f.greaterThan(N(0)).and(x.lessThan(N(_u))), () => {
9069
9085
  x.addAssign(1), f.subAssign(1);
9070
- let t = u.element(f).toVar(), i = $(n, t, N(0), N(gu));
9086
+ let t = u.element(f).toVar(), i = $(n, t, N(0), N(vu));
9071
9087
  e && o.boxTests.addAssign(1), p(i.w.lessThan(0), () => {
9072
9088
  p(i.w.greaterThan(j(-1.5)), () => {
9073
9089
  let t = N(i.x).toVar(), n = N(i.y).toVar();
@@ -9076,7 +9092,7 @@ var uu = class {
9076
9092
  end: n
9077
9093
  }, ({ i: n }) => {
9078
9094
  e && o.triTests.addAssign(1);
9079
- let i = t.add(n).toVar(), u = $(r, i, N(0), N(_u)).xyz, d = $(r, i, N(1), N(_u)).xyz, f = $(r, i, N(2), N(_u)).xyz, m = bu({
9095
+ let i = t.add(n).toVar(), u = $(r, i, N(0), N(yu)).xyz, d = $(r, i, N(1), N(yu)).xyz, f = $(r, i, N(2), N(yu)).xyz, m = Su({
9080
9096
  rayOrigin: v,
9081
9097
  rayDir: y,
9082
9098
  pA: u,
@@ -9086,7 +9102,7 @@ var uu = class {
9086
9102
  woopParams: b
9087
9103
  });
9088
9104
  p(m.w.greaterThan(.5), () => {
9089
- let e = m.x, t = m.y, n = m.z, u = $(r, i, N(3), N(_u)).xyz, d = $(r, i, N(4), N(_u)).xyz, f = $(r, i, N(5), N(_u)), h = f.xyz, g = N(f.w).toVar(), _ = j(1).sub(t).sub(n), v = y.dot(I(u.mul(_).add(d.mul(t)).add(h.mul(n))));
9105
+ let e = m.x, t = m.y, n = m.z, u = $(r, i, N(3), N(yu)).xyz, d = $(r, i, N(4), N(yu)).xyz, f = $(r, i, N(5), N(yu)), h = f.xyz, g = N(f.w).toVar(), _ = j(1).sub(t).sub(n), v = y.dot(I(u.mul(_).add(d.mul(t)).add(h.mul(n))));
9090
9106
  p(a.or(g.equal(N(2))).or(g.equal(N(0)).and(v.lessThan(-1e-4))).or(g.equal(N(1)).and(v.greaterThan(1e-4))), () => {
9091
9107
  o.didHit.assign(!0), o.dst.assign(e), s.assign(i), c.assign(t), l.assign(n);
9092
9108
  });
@@ -9095,17 +9111,17 @@ var uu = class {
9095
9111
  d();
9096
9112
  });
9097
9113
  }).Else(() => {
9098
- p(i.z.greaterThan(.5).and(f.lessThan(N(mu))), () => {
9114
+ p(i.z.greaterThan(.5).and(f.lessThan(N(gu))), () => {
9099
9115
  u.element(f).assign(N(i.x)), f.addAssign(1);
9100
9116
  });
9101
9117
  });
9102
9118
  }).Else(() => {
9103
- let e = $(n, t, N(1), N(gu)), r = $(n, t, N(2), N(gu)), a = $(n, t, N(3), N(gu)), s = N(i.w).toVar(), c = N(e.w).toVar(), l = Su({
9119
+ let e = $(n, t, N(1), N(vu)), r = $(n, t, N(2), N(vu)), a = $(n, t, N(3), N(vu)), s = N(i.w).toVar(), c = N(e.w).toVar(), l = wu({
9104
9120
  rayOrigin: v,
9105
9121
  invDir: g,
9106
9122
  boxMin: i.xyz,
9107
9123
  boxMax: e.xyz
9108
- }).toVar(), d = Su({
9124
+ }).toVar(), d = wu({
9109
9125
  rayOrigin: v,
9110
9126
  invDir: g,
9111
9127
  boxMin: r.xyz,
@@ -9113,21 +9129,21 @@ var uu = class {
9113
9129
  }).toVar();
9114
9130
  p(de(l, d).lessThan(o.dst), () => {
9115
9131
  let e = l.lessThan(d);
9116
- p(L(e, d, l).lessThan(o.dst).and(f.lessThan(N(mu))), () => {
9132
+ p(L(e, d, l).lessThan(o.dst).and(f.lessThan(N(gu))), () => {
9117
9133
  u.element(f).assign(L(e, c, s)), f.addAssign(1);
9118
- }), p(f.lessThan(N(mu)), () => {
9134
+ }), p(f.lessThan(N(gu)), () => {
9119
9135
  u.element(f).assign(L(e, s, c)), f.addAssign(1);
9120
9136
  });
9121
9137
  });
9122
9138
  });
9123
9139
  }), p(o.didHit, () => {
9124
9140
  o.hitPoint.assign(t.origin.add(t.direction.mul(o.dst)));
9125
- let e = j(1).sub(c).sub(l), n = $(r, s, N(3), N(_u)).xyz, i = $(r, s, N(4), N(_u)).xyz, a = $(r, s, N(5), N(_u)).xyz;
9141
+ let e = j(1).sub(c).sub(l), n = $(r, s, N(3), N(yu)).xyz, i = $(r, s, N(4), N(yu)).xyz, a = $(r, s, N(5), N(yu)).xyz;
9126
9142
  o.normal.assign(I(n.mul(e).add(i.mul(c)).add(a.mul(l))));
9127
- let u = $(r, s, N(6), N(_u)), d = $(r, s, N(7), N(_u));
9143
+ let u = $(r, s, N(6), N(yu)), d = $(r, s, N(7), N(yu));
9128
9144
  o.uv.assign(u.xy.mul(e).add(u.zw.mul(c)).add(d.xy.mul(l))), o.materialIndex.assign(N(d.z)), o.meshIndex.assign(N(d.w)), o.triangleIndex.assign(s);
9129
9145
  }), o;
9130
- }), wu = /* @__PURE__ */ Cu(!1), Tu = /* @__PURE__ */ Cu(!0), Eu = f(([e, t, n, r]) => {
9146
+ }), Eu = /* @__PURE__ */ Tu(!1), Du = /* @__PURE__ */ Tu(!0), Ou = f(([e, t, n, r]) => {
9131
9147
  let i = aa({
9132
9148
  didHit: !1,
9133
9149
  dst: r,
@@ -9138,12 +9154,12 @@ var uu = class {
9138
9154
  meshIndex: N(-1),
9139
9155
  boxTests: N(0),
9140
9156
  triTests: N(0)
9141
- }).toVar(), a = yu(), o = N(1).toVar();
9157
+ }).toVar(), a = xu(), o = N(1).toVar();
9142
9158
  a.element(N(0)).assign(N(0));
9143
- let s = fe(U(1), xe(e.direction), me(e.direction, U(0))), c = fe(U(1).div(e.direction), U(vu).mul(s), oe(_(e.direction), U(1e-8))).toVar(), l = xu({ rayDir: e.direction }).toVar(), u = N(0).toVar();
9144
- return m(o.greaterThan(N(0)).and(i.didHit.not()).and(u.lessThan(N(hu))), () => {
9159
+ let s = fe(U(1), xe(e.direction), me(e.direction, U(0))), c = fe(U(1).div(e.direction), U(bu).mul(s), oe(_(e.direction), U(1e-8))).toVar(), l = Cu({ rayDir: e.direction }).toVar(), u = N(0).toVar();
9160
+ return m(o.greaterThan(N(0)).and(i.didHit.not()).and(u.lessThan(N(_u))), () => {
9145
9161
  u.addAssign(1), o.subAssign(1);
9146
- let r = a.element(o).toVar(), s = $(t, r, N(0), N(gu));
9162
+ let r = a.element(o).toVar(), s = $(t, r, N(0), N(vu));
9147
9163
  p(s.w.lessThan(0), () => {
9148
9164
  p(s.w.greaterThan(j(-1.5)), () => {
9149
9165
  let t = N(s.x).toVar(), r = N(s.y).toVar();
@@ -9151,7 +9167,7 @@ var uu = class {
9151
9167
  start: N(0),
9152
9168
  end: r
9153
9169
  }, ({ i: r }) => {
9154
- let a = t.add(r).toVar(), o = $(n, a, N(0), N(_u)).xyz, s = $(n, a, N(1), N(_u)).xyz, c = $(n, a, N(2), N(_u)).xyz, u = bu({
9170
+ let a = t.add(r).toVar(), o = $(n, a, N(0), N(yu)).xyz, s = $(n, a, N(1), N(yu)).xyz, c = $(n, a, N(2), N(yu)).xyz, u = Su({
9155
9171
  rayOrigin: e.origin,
9156
9172
  rayDir: e.direction,
9157
9173
  pA: o,
@@ -9161,22 +9177,22 @@ var uu = class {
9161
9177
  woopParams: l
9162
9178
  });
9163
9179
  p(u.w.greaterThan(.5), () => {
9164
- let t = $(n, a, N(7), N(_u));
9180
+ let t = $(n, a, N(7), N(yu));
9165
9181
  i.didHit.assign(!0), i.dst.assign(u.x), i.materialIndex.assign(N(t.z)), i.meshIndex.assign(N(t.w)), i.hitPoint.assign(e.origin.add(e.direction.mul(u.x))), i.uv.assign(H(u.y, u.z)), i.triangleIndex.assign(a), d();
9166
9182
  });
9167
9183
  });
9168
9184
  }).Else(() => {
9169
- p(s.z.greaterThan(.5).and(o.lessThan(N(mu))), () => {
9185
+ p(s.z.greaterThan(.5).and(o.lessThan(N(gu))), () => {
9170
9186
  a.element(o).assign(N(s.x)), o.addAssign(1);
9171
9187
  });
9172
9188
  });
9173
9189
  }).Else(() => {
9174
- let n = $(t, r, N(1), N(gu)), l = $(t, r, N(2), N(gu)), u = $(t, r, N(3), N(gu)), d = N(s.w).toVar(), f = N(n.w).toVar(), m = Su({
9190
+ let n = $(t, r, N(1), N(vu)), l = $(t, r, N(2), N(vu)), u = $(t, r, N(3), N(vu)), d = N(s.w).toVar(), f = N(n.w).toVar(), m = wu({
9175
9191
  rayOrigin: e.origin,
9176
9192
  invDir: c,
9177
9193
  boxMin: s.xyz,
9178
9194
  boxMax: n.xyz
9179
- }).toVar(), h = Su({
9195
+ }).toVar(), h = wu({
9180
9196
  rayOrigin: e.origin,
9181
9197
  invDir: c,
9182
9198
  boxMin: l.xyz,
@@ -9184,66 +9200,33 @@ var uu = class {
9184
9200
  }).toVar();
9185
9201
  p(de(m, h).lessThan(i.dst), () => {
9186
9202
  let e = m.lessThan(h);
9187
- p(L(e, h, m).lessThan(i.dst).and(o.lessThan(N(mu))), () => {
9203
+ p(L(e, h, m).lessThan(i.dst).and(o.lessThan(N(gu))), () => {
9188
9204
  a.element(o).assign(L(e, f, d)), o.addAssign(1);
9189
- }), p(o.lessThan(N(mu)), () => {
9205
+ }), p(o.lessThan(N(gu)), () => {
9190
9206
  a.element(o).assign(L(e, d, f)), o.addAssign(1);
9191
9207
  });
9192
9208
  });
9193
9209
  });
9194
9210
  }), i;
9195
- }), Du = f(([e, t, n, r, i, a, o, s, c, l, u]) => {
9196
- let d = U(e.xy, 1), f = r.mul(W(d, 1)), m = I(ue(n[0].xyz, n[1].xyz, n[2].xyz).mul(f.xyz.div(f.w))).toVar(), h = U(n[3]).toVar(), g = h.toVar(), _ = m.toVar();
9197
- return p(i.and(a.greaterThan(0)).and(o.lessThan(64)).and(s.greaterThan(.001)), () => {
9198
- let e = a.div(o).mul(.001).mul(c).mul(l), r = qn(t), i = r.x.mul(u.max(.01)), d = r.y, f = I(U(n[0])), p = I(U(n[1])), v = f.mul(i).add(p.mul(d)).mul(e);
9199
- g.assign(h.add(v)), _.assign(I(h.add(m.mul(s)).sub(g)));
9200
- }), ea({
9201
- origin: g,
9202
- direction: _
9203
- });
9204
9211
  });
9205
- function Ou(e) {
9206
- let { rayBufferRW: t, rngBufferRW: n, gBufferRW: r, resolution: i, frame: a, cameraWorldMatrix: o, cameraProjectionMatrixInverse: s, enableDOF: c, focalLength: l, aperture: u, focusDistance: d, sceneScale: m, apertureScale: h, anamorphicRatio: g, renderWidth: _, chunkRowBase: v, chunkRows: y, transmissiveBounces: b, transparentBackground: x, auxGBufferEnabled: C, listDriven: w = !1, activeIndicesRO: T = null, counters: E = null } = e, D = C.greaterThan(z(0)), O = (e, f, _) => {
9207
- let v = H(j(e).add(.5), j(f).add(.5)), y = v.div(i).mul(2).sub(1).toVar();
9208
- y.y.assign(y.y.negate());
9209
- let S = Un({ state: sr({
9210
- pixelCoord: v,
9211
- rayIndex: N(0),
9212
- frame: a
9213
- }).toVar() }).toVar(), C = or(v, N(1), N(1), S, i, a).toVar(), w = H(2).div(i), T = C.sub(.5).mul(w), E = y.add(T), O = ea.wrap(Du(E, S, o, s, c, l, u, d, m, h, g));
9214
- Ml(t, _, O.origin, N(0), N(0)), Nl(t, _, O.direction, z(ru.ACTIVE)), Pl(t, _, W(1, 1, 1, 0).xyz, j(0)), Fl(t, _, W(U(0), L(x, j(1), j(0)))), p(D, () => {
9215
- El(r, _, U(0, 0, 1), j(1), U(0)), Yl(t, _, U(1));
9216
- }), Ul(t, _, z(0), z(b), j(1), j(1), j(1)), n.element(_).assign(S);
9217
- };
9218
- return f(() => {
9219
- if (w) {
9220
- let e = M;
9221
- p(e.lessThan(S(E.element(z(nu.ENTERING_COUNT)))), () => {
9222
- let t = N(T.element(e)), n = t.add(v.mul(_));
9223
- O(n.mod(_), n.div(_), z(t));
9224
- });
9225
- } else {
9226
- let e = N(He.x).mul(16).add(N(se.x)), t = N(He.y).mul(16).add(N(se.y));
9227
- p(e.lessThan(_).and(t.lessThan(y)), () => {
9228
- O(e, t.add(v), z(t.mul(_).add(e)));
9229
- });
9230
- }
9231
- });
9232
- }
9233
9212
  //#endregion
9234
9213
  //#region src/TSL/ExtendKernel.js
9235
9214
  function ku(e) {
9236
- let { bvhBuffer: t, triangleBuffer: n, materialBuffer: r, rayBufferRO: i, hitBufferRW: a, activeIndicesRO: o, counters: s, maxRayCount: c } = e;
9215
+ let { bvhBuffer: t, triangleBuffer: n, rayBufferRO: r, hitBufferRW: i, activeIndicesRO: a, counters: o, maxRayCount: s } = e;
9237
9216
  return f(() => {
9238
- let e = M, r = s ? S(s.element(z(nu.ENTERING_COUNT))) : c;
9239
- p(e.greaterThanEqual(r), () => {
9217
+ let e = M, c = o ? S(o.element(z(nu.ENTERING_COUNT))) : s;
9218
+ p(e.greaterThanEqual(c), () => {
9240
9219
  h();
9241
9220
  });
9242
- let l = o.element(e), u = ea({
9243
- origin: yl(i, l).toVar(),
9244
- direction: bl(i, l).toVar()
9245
- }), d = Hl(i, l).stackDepth.greaterThan(z(0)), f = aa.wrap(wu(u, t, n, d)).toVar();
9246
- Vl(a, l, f.dst, z(f.triangleIndex), f.uv.x, f.uv.y, f.normal, z(f.materialIndex), z(f.meshIndex));
9221
+ let l = a.element(e);
9222
+ p(xl(r, l).bitAnd(z(ru.ACTIVE)).equal(z(0)), () => {
9223
+ h();
9224
+ });
9225
+ let u = ea({
9226
+ origin: yl(r, l).toVar(),
9227
+ direction: bl(r, l).toVar()
9228
+ }), d = Hl(r, l).stackDepth.greaterThan(z(0)), f = aa.wrap(Eu(u, t, n, d)).toVar();
9229
+ Vl(i, l, f.dst, z(f.triangleIndex), f.uv.x, f.uv.y, f.normal, z(f.materialIndex), z(f.meshIndex));
9247
9230
  });
9248
9231
  }
9249
9232
  //#endregion
@@ -9528,7 +9511,7 @@ var Au = /* @__PURE__ */ G("\n fn equirectDirectionToUv( direction: vec3f, envir
9528
9511
  selectionTotalWeight: A
9529
9512
  });
9530
9513
  }), Ku = f(([e, t]) => F(bo(e, t), 1e-8)), qu = f(([e, t, n, r]) => Ku(r, la.wrap(Na(n, e, t, r)))), Ju = f(([e, t, n, r, i, a, o, s, c, l, u, d, h, g, _, v, y, b, x, S, C, w, T, E, D, O, k, ee, te, ne, re, ie, M]) => {
9531
- let P = U(0).toVar(), ae = U(0).toVar(), oe = e.add(t.mul(.001)).toVar(), se = f(([e, t, n]) => ys(e, t, n, Eu, w, T, E));
9514
+ let P = U(0).toVar(), ae = U(0).toVar(), oe = e.add(t.mul(.001)).toVar(), se = f(([e, t, n]) => ys(e, t, n, Ou, w, T, E));
9532
9515
  return p(n.emissiveIntensity.lessThanEqual(10), () => {
9533
9516
  let e = _.add(y).add(x).add(C).toVar(), f = e.greaterThan(N(0)).toVar(), w = j(0).toVar();
9534
9517
  p(f, () => {
@@ -10417,7 +10400,7 @@ function Bd(e) {
10417
10400
  });
10418
10401
  let Jt = ia.wrap(Ju(ut, dt, q, Lt, Ut, Gt, Wt, st, Ye, Qe, je, Ae, $e, ie, P, oe, se, le, ue, de, pe, t, n, r, g, _, v, i, te, ne, re, y, T(!1))).shadowed.toVar(), Yt = L(st.greaterThan(0), Ee, j(1));
10419
10402
  qe.assign(W(qe.xyz.add(Zu(Ke.mul(Jt).mul(Yt), j(st), ke, N(R))), qe.w)), Ve && p(Ie.equal(N(1)).and(Ne.greaterThan(N(0))), () => {
10420
- let e = f(([e, i, a]) => ys(e, i, a, Eu, t, n, r));
10403
+ let e = f(([e, i, a]) => ys(e, i, a, Ou, t, n, r));
10421
10404
  p(Le.greaterThan(N(0)), () => {
10422
10405
  let t = cd.wrap(Pd(ut, dt, Ye, Qe, je, Ae, $e, a, a, Pe, n));
10423
10406
  p(t.valid.and(t.pdf.greaterThan(0)), () => {
@@ -10485,50 +10468,46 @@ function Hd(e) {
10485
10468
  }
10486
10469
  var Ud = /* @__PURE__ */ G("\n fn nanInfToRed( c: vec3f ) -> vec3f {\n let isNan = c.x != c.x || c.y != c.y || c.z != c.z;\n let isInf = abs( c.x ) > 1e30f || abs( c.y ) > 1e30f || abs( c.z ) > 1e30f;\n if ( isNan || isInf ) { return vec3f( 1.0f, 0.0f, 0.0f ); }\n return vec3f( 0.0f );\n }\n");
10487
10470
  function Wd(e) {
10488
- let { rayBufferRO: t, gBufferRO: n, writeColorTex: r, writeNDTex: i, writeAlbedoTex: a, resolution: o, frame: s, enableAccumulation: c, hasPreviousAccumulated: l, accumulationAlpha: u, cameraIsMoving: d, transparentBackground: m, prevAccumTexture: h, prevAlbedoTexture: g, prevNormalDepthTexture: _, renderWidth: v, chunkRowBase: y, chunkRows: b, visMode: S, auxGBufferEnabled: C, cleanAuxNormalEnabled: w, counters: T, m2BufferRW: E, useAdaptiveSampling: D, noiseThreshold: O, adaptiveMinSamples: k, usePixelFreeze: A, pixelFreezeThreshold: ee, pixelFreezeStability: te, streakBufferRW: ne, frozenMaskRO: re } = e, ie = C.greaterThan(z(0)), M = w.greaterThan(z(0)), P = D.greaterThan(N(0)), oe = A.greaterThan(N(0));
10471
+ let { rayBufferRO: t, gBufferRO: n, writeColorTex: r, writeNDTex: i, writeAlbedoTex: a, resolution: o, frame: s, enableAccumulation: c, hasPreviousAccumulated: l, accumulationAlpha: u, cameraIsMoving: d, transparentBackground: m, prevAccumTexture: h, prevAlbedoTexture: g, prevNormalDepthTexture: _, renderWidth: v, chunkRowBase: y, chunkRows: b, visMode: S, auxGBufferEnabled: C, cleanAuxNormalEnabled: w, counters: T, m2BufferRW: E, useAdaptiveSampling: D, noiseThreshold: O, adaptiveMinSamples: k, usePixelFreeze: A, pixelFreezeThreshold: ee, streakBufferRW: te, frozenMaskRO: ne } = e, re = C.greaterThan(z(0)), ie = w.greaterThan(z(0)), M = D.greaterThan(N(0)), P = A.greaterThan(N(0));
10489
10472
  return f(() => {
10490
10473
  let e = N(He.x).mul(16).add(N(se.x)), f = N(He.y).mul(16).add(N(se.y));
10491
10474
  p(e.lessThan(v).and(f.lessThan(b)), () => {
10492
- let b = f.add(y), C = z(f.mul(v).add(e)), w = z(b.mul(v).add(e)), D = wl(t, C), A = D.xyz.toVar(), se = L(m, D.w, j(1)).toVar(), ce = oe.and(s.greaterThan(z(0))).and(re.element(w).equal(z(1))).toVar(), le = W(0).toVar(), ue = W(0).xyz.toVar();
10493
- p(ie, () => {
10475
+ let b = f.add(y), C = z(f.mul(v).add(e)), w = z(b.mul(v).add(e)), D = wl(t, C), A = D.xyz.toVar(), oe = L(m, D.w, j(1)).toVar(), se = P.and(s.greaterThan(z(0))).and(ne.element(w).equal(z(1))).toVar(), ce = W(0).toVar(), le = W(0).xyz.toVar();
10476
+ p(re, () => {
10494
10477
  let e = Dl(n, C);
10495
- le.assign(Ol(e)), ue.assign(W(kl(e), 0).xyz);
10478
+ ce.assign(Ol(e)), le.assign(W(kl(e), 0).xyz);
10496
10479
  });
10497
- let F = H(j(e).add(.5), j(b).add(.5)).div(o);
10480
+ let ue = H(j(e).add(.5), j(b).add(.5)).div(o);
10498
10481
  p(c.and(d.not()).and(s.greaterThan(z(0))).and(l).and(S.notEqual(N(11))), () => {
10499
- let e = je(h, F, 0).toVar();
10500
- A.assign(L(ce, e.xyz, fe(e.xyz, D.xyz, u))), p(ie, () => {
10501
- ue.assign(fe(je(g, F, 0).xyz, ue, u)), p(M, () => {
10502
- let e = je(_, F, 0).xyz.mul(2).sub(1), t = le.xyz.mul(2).sub(1).toVar(), n = fe(e, t, u).toVar(), r = ae(n), i = L(r.greaterThan(1e-4), n.div(r), t);
10503
- le.assign(W(i.mul(.5).add(.5), le.w));
10482
+ let e = je(h, ue, 0).toVar();
10483
+ A.assign(L(se, e.xyz, fe(e.xyz, D.xyz, u))), p(re, () => {
10484
+ le.assign(fe(je(g, ue, 0).xyz, le, u)), p(ie, () => {
10485
+ let e = je(_, ue, 0).xyz.mul(2).sub(1), t = ce.xyz.mul(2).sub(1).toVar(), n = fe(e, t, u).toVar(), r = ae(n), i = L(r.greaterThan(1e-4), n.div(r), t);
10486
+ ce.assign(W(i.mul(.5).add(.5), ce.w));
10504
10487
  });
10505
10488
  }), p(m, () => {
10506
- se.assign(L(ce, e.w, fe(e.w, D.w, u)));
10489
+ oe.assign(L(se, e.w, fe(e.w, D.w, u)));
10507
10490
  });
10508
- }), p(P, () => {
10491
+ }), p(M, () => {
10509
10492
  let e = Oa(D.xyz), t = fe(E.element(w).toVar(), e.mul(e), u).toVar();
10510
10493
  E.element(w).assign(t);
10511
10494
  let n = Oa(A).toVar(), r = t.sub(n.mul(n)).max(j(0)).div(j(s).add(1)).sqrt().toVar(), i = r.div(n.add(j(1e-4))), a = L(n.lessThan(j(1)), n.sqrt(), n), o = r.div(a.add(j(1e-4))).lessThan(O);
10512
10495
  p(s.greaterThanEqual(z(k)).and(o), () => {
10513
10496
  x(T.element(z(nu.CONVERGED_COUNT)), z(1));
10514
- }), p(oe, () => {
10497
+ }), p(P, () => {
10515
10498
  p(s.equal(z(0)), () => {
10516
- ne.element(w).assign(z(0));
10517
- }), p(ce, () => {
10518
- x(T.element(z(nu.FROZEN_COUNT)), z(1));
10519
- }), p(ce.not().and(s.greaterThan(z(0))), () => {
10520
- let e = L(s.greaterThanEqual(z(k)).and(i.lessThan(ee)), ne.element(w).add(z(1)), z(0)).toVar();
10521
- ne.element(w).assign(e), p(e.greaterThanEqual(z(te)), () => {
10522
- x(T.element(z(nu.FROZEN_COUNT)), z(1));
10523
- });
10499
+ te.element(w).assign(z(0));
10500
+ }), p(se.not().and(s.greaterThan(z(0))), () => {
10501
+ let e = L(s.greaterThanEqual(z(k)).and(i.lessThan(ee)), te.element(w).add(z(1)), z(0)).toVar();
10502
+ te.element(w).assign(e);
10524
10503
  });
10525
10504
  });
10526
10505
  }), p(S.equal(N(11)), () => {
10527
10506
  A.assign(Ud(A));
10528
10507
  });
10529
- let de = Re(z(e), z(b));
10530
- Ne(r, de, W(A, se)).toWriteOnly(), p(ie, () => {
10531
- Ne(i, de, le).toWriteOnly(), Ne(a, de, W(ue, 1)).toWriteOnly();
10508
+ let F = Re(z(e), z(b));
10509
+ Ne(r, F, W(A, oe)).toWriteOnly(), p(re, () => {
10510
+ Ne(i, F, ce).toWriteOnly(), Ne(a, F, W(le, 1)).toWriteOnly();
10532
10511
  });
10533
10512
  });
10534
10513
  });
@@ -10539,7 +10518,7 @@ var Gd = /* @__PURE__ */ G("\n fn visualizeDepth( depth: f32 ) -> vec3f {\n ret
10539
10518
  let _ = W(1, 0, 1, 1).toVar(), v = ea({
10540
10519
  origin: e,
10541
10520
  direction: t
10542
- }), y = aa.wrap(Tu(v, n, r).toVar());
10521
+ }), y = aa.wrap(Du(v, n, r).toVar());
10543
10522
  return p(l.equal(N(7)), () => {
10544
10523
  let e = j(y.triTests).div(u);
10545
10524
  _.assign(L(e.lessThan(1), W(U(e), 1), W(1, 0, 0, 1)));
@@ -10626,7 +10605,7 @@ var Gd = /* @__PURE__ */ G("\n fn visualizeDepth( depth: f32 ) -> vec3f {\n ret
10626
10605
  }).toVar(), h = ea({
10627
10606
  origin: y.hitPoint.add(u.mul(.001)),
10628
10607
  direction: m
10629
- }), v = aa.wrap(Tu(h, n, r).toVar()), b = U(0).toVar();
10608
+ }), v = aa.wrap(Du(h, n, r).toVar()), b = U(0).toVar();
10630
10609
  p(v.didHit.not(), () => {
10631
10610
  p(c, () => {
10632
10611
  b.assign(Pu({
@@ -10680,21 +10659,19 @@ var Gd = /* @__PURE__ */ G("\n fn visualizeDepth( depth: f32 ) -> vec3f {\n ret
10680
10659
  }), _;
10681
10660
  });
10682
10661
  function Yd(e) {
10683
- let { writeColorTex: t, writeNDTex: n, writeAlbedoTex: r, resolution: i, renderWidth: a, renderHeight: o, cameraWorldMatrix: s, cameraProjectionMatrixInverse: c, cameraProjectionMatrix: l, cameraViewMatrix: u, enableDOF: d, focalLength: m, aperture: h, focusDistance: g, sceneScale: _, apertureScale: v, anamorphicRatio: y, bvhBuffer: b, triangleBuffer: x, materialBuffer: S, envTexture: C, environmentMatrix: w, environmentIntensity: T, enableEnvironmentLight: E, visMode: D, debugVisScale: O, frame: k } = e;
10662
+ let { writeColorTex: t, writeNDTex: n, writeAlbedoTex: r, resolution: i, renderWidth: a, renderHeight: o, cameraWorldMatrix: s, cameraProjectionMatrixInverse: c, cameraProjectionMatrix: l, cameraViewMatrix: u, cameraProjection: d, panoLonRange: m, panoLatRange: h, panoLevelHorizon: g, enableDOF: _, focalLength: v, aperture: y, focusDistance: b, sceneScale: x, apertureScale: S, anamorphicRatio: C, bvhBuffer: w, triangleBuffer: T, materialBuffer: E, envTexture: D, environmentMatrix: O, environmentIntensity: k, enableEnvironmentLight: A, visMode: ee, debugVisScale: te, frame: ne } = e;
10684
10663
  return f(() => {
10685
10664
  let e = N(He.x).mul(16).add(N(se.x)), f = N(He.y).mul(16).add(N(se.y));
10686
10665
  p(e.lessThan(a).and(f.lessThan(o)), () => {
10687
- let a = H(j(e).add(.5), j(f).add(.5)), o = Un({ state: z(f.mul(N(i.x)).add(e)).add(z(1)) }).toVar(), A = a.div(i).mul(2).sub(1).toVar();
10688
- A.y.assign(A.y.negate());
10689
- let ee = ea.wrap(Du(A, o, s, c, d, m, h, g, _, v, y)), te = W(1, 0, 1, 1).toVar();
10690
- p(D.equal(N(9)), () => {
10691
- let e = or(a, N(0), N(1), o, i, k);
10692
- te.assign(W(e, 1, 1));
10666
+ let a = H(j(e).add(.5), j(f).add(.5)), o = Un({ state: z(f.mul(N(i.x)).add(e)).add(z(1)) }).toVar(), re = ea.wrap(mu(a.div(i), o, s, c, d, m, h, g, _, v, y, b, x, S, C)), ie = W(1, 0, 1, 1).toVar();
10667
+ p(ee.equal(N(9)), () => {
10668
+ let e = or(a, N(0), N(1), o, i, ne);
10669
+ ie.assign(W(e, 1, 1));
10693
10670
  }).Else(() => {
10694
- te.assign(Jd(ee.origin, ee.direction, b, x, S, C, w, T, E, D, O, a, i, l, u, k));
10671
+ ie.assign(Jd(re.origin, re.direction, w, T, E, D, O, k, A, ee, te, a, i, l, u, ne));
10695
10672
  });
10696
- let ne = Re(z(e), z(f));
10697
- Ne(t, ne, te).toWriteOnly(), Ne(n, ne, W(.5, .5, 1, 1)).toWriteOnly(), Ne(r, ne, W(te.xyz, 1)).toWriteOnly();
10673
+ let M = Re(z(e), z(f));
10674
+ Ne(t, M, ie).toWriteOnly(), Ne(n, M, W(.5, .5, 1, 1)).toWriteOnly(), Ne(r, M, W(ie.xyz, 1)).toWriteOnly();
10698
10675
  });
10699
10676
  });
10700
10677
  }
@@ -10740,16 +10717,33 @@ function Qd({ sortGlobalHistogram: e, bins: t = 256 }) {
10740
10717
  }
10741
10718
  function $d({ hitBufferRO: e, activeIndicesReadRO: t, sortedIndicesRW: n, sortGlobalHistogram: r, counters: i, bins: a = 256 }) {
10742
10719
  return f(() => {
10743
- let o = M, s = S(i.element(z(nu.ENTERING_COUNT)));
10744
- p(o.lessThan(s), () => {
10745
- let i = t.element(o), s = z(Bl(e, i)).clamp(z(0), z(a - 1)), c = x(r.element(s), z(1));
10746
- n.element(c).assign(i);
10720
+ let o = M, s = se.x, c = jn("uint", a);
10721
+ p(s.lessThan(z(a)), () => {
10722
+ C(c.element(s), z(0));
10723
+ }), Ve();
10724
+ let l = S(i.element(z(nu.ENTERING_COUNT))), u = o.lessThan(l), d = z(0).toVar(), f = z(0).toVar();
10725
+ p(u, () => {
10726
+ d.assign(t.element(o)), f.assign(z(Bl(e, d)).clamp(z(0), z(a - 1))), x(c.element(f), z(1));
10727
+ }), Ve(), p(s.lessThan(z(a)), () => {
10728
+ let e = c.element(s), t = S(e);
10729
+ p(t.greaterThan(z(0)), () => {
10730
+ C(e, x(r.element(s), t));
10731
+ });
10732
+ }), Ve(), p(u, () => {
10733
+ n.element(x(c.element(f), z(1))).assign(d);
10747
10734
  });
10748
10735
  });
10749
10736
  }
10750
10737
  //#endregion
10751
10738
  //#region src/Stages/PathTracer.js
10752
- var ef = ai("wavefront"), tf = class extends dl {
10739
+ var ef = ai("wavefront"), tf = 256, nf = [
10740
+ "extend",
10741
+ "shade",
10742
+ "globalHist",
10743
+ "globalScatter",
10744
+ "compact",
10745
+ "compactCopyback"
10746
+ ], rf = class extends dl {
10753
10747
  constructor(e, t, n, r = {}) {
10754
10748
  super(e, t, n, r), this.name = "PathTracer", this._packedBuffers = null, this._queueManager = null, this._kernelManager = null, this._gBufferAttr = null, this._m2Attr = null, this._streakAttr = null, this._frozenMaskAttr = null, this._dilateFrozenUniform = B(1, "int"), this._wavefrontReady = !1, this._auxGBufferEnabled = !1, this._auxGBufferUniform = B(0, "uint"), this._cleanAuxNormalEnabled = !1, this._cleanAuxNormalUniform = B(0, "uint"), this._useDynamicDispatch = !0, this._sortMaterials = !1, this._useSubgroupCompact = !1, this._lastBounceCounts = null, this._lastBounceCountsBudget = -1, this._readbackPending = !1, this._readbackEveryNFrames = 4, this._readbackFrameCounter = 0, this._readbackGeneration = 0, this._curveSizingValid = !1, this._bounceEarlyExitThreshold = 100, this._convergedFraction = 0, this._convergedReadbackPending = !1, this._lastActivePixelCount = 0, this._wfRenderWidth = B(1920, "int"), this._wfRenderHeight = B(1080, "int"), this._wfMaxRayCount = B(0, "uint"), this._wfCurrentBounce = B(0, "int"), this._wfChunkRowBase = B(0, "int"), this._wfChunkRows = B(0, "int"), this._wfIsFirstChunk = B(1, "uint"), this._pathBudget = 0, this._pathBudgetOverride = 0, this._chunkRows = 0, this._numChunks = 1, this.vramTracker = new uu(this.renderer), this._registerVRAMProviders(), ef.debug("initialized (wavefront)");
10755
10749
  }
@@ -10824,11 +10818,7 @@ var ef = ai("wavefront"), tf = class extends dl {
10824
10818
  let n = Math.min(l, c - t), r = this._setChunk(t, n, e), i = this.usePixelFreeze.value > 0, o = u && i && this._curveSizingValid && this._lastActivePixelCount > 0 ? this._lastActivePixelCount : r;
10825
10819
  if (i) {
10826
10820
  let e = Math.min(r, Math.ceil(o * 1.5) + 1024);
10827
- a.setDispatchCount("generateList", [
10828
- Math.ceil(e / 256),
10829
- 1,
10830
- 1
10831
- ]), a.dispatch("resetFrameCounters"), a.dispatch("buildActivePixels"), a.dispatch("seedEnter"), a.dispatch("generateList");
10821
+ a.setDispatchForCount("generateList", e), a.dispatch("resetFrameCounters"), a.dispatch("buildActivePixels"), a.dispatch("seedEnter"), a.dispatch("generateList");
10832
10822
  } else a.dispatch("generate"), a.dispatch("initActiveIndices");
10833
10823
  for (let e = 0; e <= s; e++) {
10834
10824
  this._wfCurrentBounce.value = e;
@@ -10839,20 +10829,11 @@ var ef = ai("wavefront"), tf = class extends dl {
10839
10829
  let n = e - 1, i;
10840
10830
  n < f && d[n] !== void 0 ? i = d[n] : f > 0 && (i = d[f - 1]), t = i > 0 ? i : r;
10841
10831
  } else e === 0 && i && (t = o);
10842
- let n = Math.min(r, Math.ceil(t * 1.5) + 1024), s = [
10843
- Math.ceil(n / 256),
10844
- 1,
10845
- 1
10846
- ];
10847
- a.setDispatchCount("extend", s), a.setDispatchCount("shade", s), a.setDispatchCount("globalHist", s), a.setDispatchCount("globalScatter", s), a.setDispatchCount("compact", s), a.setDispatchCount("compactCopyback", s);
10832
+ let n = Math.min(r, Math.ceil(t * 1.5) + 1024);
10833
+ for (let e of nf) a.setDispatchForCount(e, n);
10848
10834
  } else {
10849
10835
  a.dispatch("enterFull");
10850
- let e = [
10851
- Math.ceil(r / 256),
10852
- 1,
10853
- 1
10854
- ];
10855
- a.setDispatchCount("extend", e), a.setDispatchCount("shade", e), a.setDispatchCount("compact", e), a.setDispatchCount("globalHist", e), a.setDispatchCount("globalScatter", e);
10836
+ for (let e of nf) a.setDispatchForCount(e, r);
10856
10837
  }
10857
10838
  if (a.dispatch("extend"), this._sortMaterials && (a.dispatch("resetGlobalHist"), a.dispatch("globalHist"), a.dispatch("globalPrefix"), a.dispatch("globalScatter")), a.dispatch("shade"), a.dispatch("compact"), t ? a.dispatch("compactCopyback") : a.dispatch("snapshotBounceCount"), e < f && e < s && d[e] !== void 0 && d[e] <= this._bounceEarlyExitThreshold) break;
10858
10839
  }
@@ -10962,7 +10943,7 @@ var ef = ai("wavefront"), tf = class extends dl {
10962
10943
  let d = Te(this._streakAttr, "uint"), m = Te(this._streakAttr, "uint").toReadOnly();
10963
10944
  _l(this.renderer, this._frozenMaskAttr), this._frozenMaskAttr = new o(new Uint32Array(l), 1);
10964
10945
  let g = Te(this._frozenMaskAttr, "uint"), _ = Te(this._frozenMaskAttr, "uint").toReadOnly();
10965
- this._queueManager ? this._queueManager.resize(this._packedBuffers.capacity) : this._queueManager = new iu(this._packedBuffers.capacity, this.renderer), this._kernelManager ||= new pu(this.renderer);
10946
+ this._queueManager ? this._queueManager.resize(this._packedBuffers.capacity) : this._queueManager = new iu(this._packedBuffers.capacity, this.renderer), this._kernelManager ||= new fu(this.renderer);
10966
10947
  let v = this._packedBuffers, y = this._queueManager;
10967
10948
  this._wfRenderWidth.value = t, this._wfRenderHeight.value = n, this._wfMaxRayCount.value = Math.min(r, this._chunkRows * t);
10968
10949
  let b = this.shaderBuilder.prevColorTexNode, w = this.shaderBuilder.prevAlbedoTexNode, T = this.shaderBuilder.prevNormalDepthTexNode, E = this.storageTextures.getWriteTextures(), D = y.getCounters(), O = y.getBounceCounts(), k = this._wfCurrentBounce, A = f(() => {
@@ -10989,11 +10970,11 @@ var ef = ai("wavefront"), tf = class extends dl {
10989
10970
  });
10990
10971
  });
10991
10972
  this._kernelManager.register("initActiveIndices", te().compute([
10992
- Math.ceil(this._chunkRows * t / 256),
10973
+ Math.ceil(this._chunkRows * t / tf),
10993
10974
  1,
10994
10975
  1
10995
10976
  ], [
10996
- 256,
10977
+ tf,
10997
10978
  1,
10998
10979
  1
10999
10980
  ]));
@@ -11005,6 +10986,10 @@ var ef = ai("wavefront"), tf = class extends dl {
11005
10986
  frame: this.seedFrame,
11006
10987
  cameraWorldMatrix: this.cameraWorldMatrix,
11007
10988
  cameraProjectionMatrixInverse: this.cameraProjectionMatrixInverse,
10989
+ cameraProjection: this.cameraProjection,
10990
+ panoLonRange: this.panoLonRange,
10991
+ panoLatRange: this.panoLatRange,
10992
+ panoLevelHorizon: this.panoLevelHorizon,
11008
10993
  enableDOF: this.enableDOF,
11009
10994
  focalLength: this.focalLength,
11010
10995
  aperture: this.aperture,
@@ -11019,7 +11004,7 @@ var ef = ai("wavefront"), tf = class extends dl {
11019
11004
  transmissiveBounces: this.transmissiveBounces,
11020
11005
  transparentBackground: this.transparentBackground,
11021
11006
  auxGBufferEnabled: this._auxGBufferUniform
11022
- }, ne = Ou(j);
11007
+ }, ne = hu(j);
11023
11008
  this._kernelManager.register("generate", ne().compute([
11024
11009
  Math.ceil(t / 16),
11025
11010
  Math.ceil(this._chunkRows / 16),
@@ -11031,7 +11016,7 @@ var ef = ai("wavefront"), tf = class extends dl {
11031
11016
  ]));
11032
11017
  let re = this.pixelFreezeStability, ie = f(() => {
11033
11018
  C(D.element(z(nu.ACTIVE_RAY_COUNT)), z(0)), p(this._wfIsFirstChunk.greaterThan(z(0)), () => {
11034
- C(D.element(z(nu.CONVERGED_COUNT)), z(0)), C(D.element(z(nu.FROZEN_COUNT)), z(0));
11019
+ C(D.element(z(nu.CONVERGED_COUNT)), z(0));
11035
11020
  });
11036
11021
  });
11037
11022
  this._kernelManager.register("resetFrameCounters", ie().compute([
@@ -11075,11 +11060,11 @@ var ef = ai("wavefront"), tf = class extends dl {
11075
11060
  });
11076
11061
  });
11077
11062
  this._kernelManager.register("buildActivePixels", P().compute([
11078
- Math.ceil(this._chunkRows * t / 256),
11063
+ Math.ceil(this._chunkRows * t / tf),
11079
11064
  1,
11080
11065
  1
11081
11066
  ], [
11082
- 256,
11067
+ tf,
11083
11068
  1,
11084
11069
  1
11085
11070
  ]));
@@ -11096,18 +11081,18 @@ var ef = ai("wavefront"), tf = class extends dl {
11096
11081
  1,
11097
11082
  1
11098
11083
  ]));
11099
- let oe = Ou({
11084
+ let oe = hu({
11100
11085
  ...j,
11101
11086
  listDriven: !0,
11102
11087
  activeIndicesRO: y.activeIndicesRO.a,
11103
11088
  counters: D
11104
11089
  });
11105
11090
  this._kernelManager.register("generateList", oe().compute([
11106
- Math.ceil(i / 256),
11091
+ Math.ceil(i / tf),
11107
11092
  1,
11108
11093
  1
11109
11094
  ], [
11110
- 256,
11095
+ tf,
11111
11096
  1,
11112
11097
  1
11113
11098
  ]));
@@ -11123,7 +11108,6 @@ var ef = ai("wavefront"), tf = class extends dl {
11123
11108
  let he = ku({
11124
11109
  bvhBuffer: se,
11125
11110
  triangleBuffer: ce,
11126
- materialBuffer: le,
11127
11111
  rayBufferRO: v.rayBuffer.ro,
11128
11112
  hitBufferRW: v.hitBuffer.rw,
11129
11113
  activeIndicesRO: y.getActiveReadRO(),
@@ -11304,11 +11288,11 @@ var ef = ai("wavefront"), tf = class extends dl {
11304
11288
  }), L.element(e).assign(be.element(e));
11305
11289
  });
11306
11290
  this._kernelManager.register("compactCopyback", xe().compute([
11307
- Math.ceil(i / 256),
11291
+ Math.ceil(i / tf),
11308
11292
  1,
11309
11293
  1
11310
11294
  ], [
11311
- 256,
11295
+ tf,
11312
11296
  1,
11313
11297
  1
11314
11298
  ]));
@@ -11340,7 +11324,6 @@ var ef = ai("wavefront"), tf = class extends dl {
11340
11324
  adaptiveMinSamples: this.adaptiveMinSamples,
11341
11325
  usePixelFreeze: this.usePixelFreeze,
11342
11326
  pixelFreezeThreshold: this.pixelFreezeThreshold,
11343
- pixelFreezeStability: this.pixelFreezeStability,
11344
11327
  streakBufferRW: d,
11345
11328
  frozenMaskRO: _,
11346
11329
  chunkRowBase: this._wfChunkRowBase,
@@ -11366,6 +11349,10 @@ var ef = ai("wavefront"), tf = class extends dl {
11366
11349
  cameraProjectionMatrixInverse: this.cameraProjectionMatrixInverse,
11367
11350
  cameraProjectionMatrix: this.cameraProjectionMatrix,
11368
11351
  cameraViewMatrix: this.cameraViewMatrix,
11352
+ cameraProjection: this.cameraProjection,
11353
+ panoLonRange: this.panoLonRange,
11354
+ panoLatRange: this.panoLatRange,
11355
+ panoLevelHorizon: this.panoLevelHorizon,
11369
11356
  enableDOF: this.enableDOF,
11370
11357
  focalLength: this.focalLength,
11371
11358
  aperture: this.aperture,
@@ -11403,43 +11390,23 @@ var ef = ai("wavefront"), tf = class extends dl {
11403
11390
  }
11404
11391
  _setWfDispatch() {
11405
11392
  let e = this._wfRenderWidth.value, t = this._wfRenderHeight.value;
11406
- this._kernelManager.setDispatchCount("debug", [
11407
- Math.ceil(e / 16),
11408
- Math.ceil(t / 16),
11409
- 1
11410
- ]);
11393
+ this._kernelManager.setDispatchForGrid("debug", e, t);
11411
11394
  }
11412
11395
  _setChunk(e, t, n) {
11413
11396
  let r = this._wfRenderWidth.value, i = t * r;
11414
11397
  this._wfChunkRowBase.value = e, this._wfChunkRows.value = t, this._wfIsFirstChunk.value = +(n === 0), this._wfMaxRayCount.value = i;
11415
11398
  let a = this._kernelManager;
11416
- return a.setDispatchCount("generate", [
11417
- Math.ceil(r / 16),
11418
- Math.ceil(t / 16),
11419
- 1
11420
- ]), a.setDispatchCount("finalWrite", [
11421
- Math.ceil(r / 16),
11422
- Math.ceil(t / 16),
11423
- 1
11424
- ]), a.setDispatchCount("initActiveIndices", [
11425
- Math.ceil(i / 256),
11426
- 1,
11427
- 1
11428
- ]), a.setDispatchCount("buildActivePixels", [
11429
- Math.ceil(i / 256),
11430
- 1,
11431
- 1
11432
- ]), i;
11399
+ return a.setDispatchForGrid("generate", r, t), a.setDispatchForGrid("finalWrite", r, t), a.setDispatchForCount("initActiveIndices", i), a.setDispatchForCount("buildActivePixels", i), i;
11433
11400
  }
11434
11401
  dispose() {
11435
11402
  super.dispose(), this._packedBuffers?.dispose(), this._queueManager?.dispose(), this._kernelManager?.dispose(), this._gBufferAttr?.dispose?.(), this._m2Attr?.dispose?.(), this._streakAttr?.dispose?.(), this._frozenMaskAttr?.dispose?.(), this._packedBuffers = null, this._queueManager = null, this._kernelManager = null, this._gBufferAttr = null, this._m2Attr = null, this._streakAttr = null, this._frozenMaskAttr = null, this._wavefrontReady = !1;
11436
11403
  }
11437
- }, nf = class extends lr {
11404
+ }, af = class extends lr {
11438
11405
  constructor(e, t = {}) {
11439
11406
  super("NormalDepth", {
11440
11407
  ...t,
11441
11408
  executionMode: cr.ALWAYS
11442
- }), this.renderer = e, this.pathTracer = t.pathTracer, this._dirty = !0, this.cameraWorldMatrix = B(new Ct(), "mat4"), this.cameraProjectionMatrixInverse = B(new Ct(), "mat4"), this.resolutionWidth = B(t.width || 1), this.resolutionHeight = B(t.height || 1);
11409
+ }), this.renderer = e, this.pathTracer = t.pathTracer, this._dirty = !0, this.cameraWorldMatrix = B(new Ct(), "mat4"), this.cameraProjectionMatrixInverse = B(new Ct(), "mat4"), this.cameraProjection = B(0, "int"), this.panoLonRange = B(new sn(), "vec2"), this.panoLatRange = B(new sn(), "vec2"), this.panoLevelHorizon = B(1, "int"), this.resolutionWidth = B(t.width || 1), this.resolutionHeight = B(t.height || 1);
11443
11410
  let n = t.width || 1, r = t.height || 1;
11444
11411
  this._outputStorageTex = new s(Y, Y), this._outputStorageTex.type = ht, this._outputStorageTex.format = Bt, this._outputStorageTex.minFilter = Ot, this._outputStorageTex.magFilter = Ot, this._shadingStorageTex = new s(Y, Y), this._shadingStorageTex.type = ht, this._shadingStorageTex.format = Bt, this._shadingStorageTex.minFilter = Ot, this._shadingStorageTex.magFilter = Ot, this._shadingRT = new i(n, r, {
11445
11412
  type: ht,
@@ -11479,18 +11446,18 @@ var ef = ai("wavefront"), tf = class extends dl {
11479
11446
  this._computeNode = f(([r, i]) => {
11480
11447
  let l = N(He.x).mul(8).add(N(se.x)), u = N(He.y).mul(8).add(N(se.y));
11481
11448
  p(l.lessThan(N(a)).and(u.lessThan(N(o))), () => {
11482
- let d = U(j(l).add(.5).div(a).mul(2).sub(1), j(u).add(.5).div(o).mul(2).sub(1).negate(), 1), f = i.mul(W(d, 1)), m = I(ue(r[0].xyz, r[1].xyz, r[2].xyz).mul(f.xyz.div(f.w))), h = ea({
11449
+ let d = pu(H(j(l).add(.5).div(a), j(u).add(.5).div(o)), r, i, this.cameraProjection, this.panoLonRange, this.panoLatRange, this.panoLevelHorizon), f = ea({
11483
11450
  origin: U(r[3]),
11484
- direction: m
11485
- }), g = aa.wrap(wu(h, t, e)), _ = g.normal.mul(.5).add(.5), v = de(g.dst, j(65504)), y = g.didHit.select(W(_, v), W(0, 0, 0, j(65504)));
11486
- Ne(s, Re(z(l), z(u)), y).toWriteOnly();
11487
- let b = g.normal.toVar();
11488
- p(g.didHit, () => {
11489
- let e = ta.wrap(za(g.materialIndex, n)).toVar(), t = pa.wrap(as(g.uv, e)).toVar(), r = cs(g.normal, e, t).toVar();
11490
- b.assign(ls(r, e, t));
11451
+ direction: d
11452
+ }), m = aa.wrap(Eu(f, t, e)), h = m.normal.mul(.5).add(.5), g = de(m.dst, j(65504)), _ = m.didHit.select(W(h, g), W(0, 0, 0, j(65504)));
11453
+ Ne(s, Re(z(l), z(u)), _).toWriteOnly();
11454
+ let v = m.normal.toVar();
11455
+ p(m.didHit, () => {
11456
+ let e = ta.wrap(za(m.materialIndex, n)).toVar(), t = pa.wrap(as(m.uv, e)).toVar(), r = cs(m.normal, e, t).toVar();
11457
+ v.assign(ls(r, e, t));
11491
11458
  });
11492
- let x = g.didHit.select(W(b.mul(.5).add(.5), v), W(0, 0, 0, j(65504)));
11493
- Ne(c, Re(z(l), z(u)), x).toWriteOnly();
11459
+ let y = m.didHit.select(W(v.mul(.5).add(.5), g), W(0, 0, 0, j(65504)));
11460
+ Ne(c, Re(z(l), z(u)), y).toWriteOnly();
11494
11461
  });
11495
11462
  })(r, i).compute([
11496
11463
  this._dispatchX,
@@ -11506,7 +11473,7 @@ var ef = ai("wavefront"), tf = class extends dl {
11506
11473
  if (!this.enabled || !this._syncStorageBuffers()) return;
11507
11474
  this._computeBuilt || this._buildCompute();
11508
11475
  let t = this.pathTracer;
11509
- if (t && (this.cameraWorldMatrix.value.copy(t.uniforms.get("cameraWorldMatrix").value), this.cameraProjectionMatrixInverse.value.copy(t.uniforms.get("cameraProjectionMatrixInverse").value)), !this._dirty && this._hasHistory) {
11476
+ if (t && (this.cameraWorldMatrix.value.copy(t.uniforms.get("cameraWorldMatrix").value), this.cameraProjectionMatrixInverse.value.copy(t.uniforms.get("cameraProjectionMatrixInverse").value), this.cameraProjection.value = t.uniforms.get("cameraProjection").value, this.panoLonRange.value.copy(t.uniforms.get("panoLonRange").value), this.panoLatRange.value.copy(t.uniforms.get("panoLatRange").value), this.panoLevelHorizon.value = t.uniforms.get("panoLevelHorizon").value), !this._dirty && this._hasHistory) {
11510
11477
  let t = this._currentIdx === 0 ? this._rtA : this._rtB;
11511
11478
  e.setTexture("pathtracer:normalDepth", t.texture), e.setTexture("pathtracer:prevNormalDepth", t.texture), e.setTexture("pathtracer:shadingNormal", this._shadingRT.texture);
11512
11479
  return;
@@ -11544,7 +11511,7 @@ var ef = ai("wavefront"), tf = class extends dl {
11544
11511
  dispose() {
11545
11512
  this._computeNode?.dispose(), this._outputStorageTex?.dispose(), this._shadingStorageTex?.dispose(), this._shadingRT?.dispose(), this._rtA?.dispose(), this._rtB?.dispose();
11546
11513
  }
11547
- }, rf = class extends lr {
11514
+ }, of = class extends lr {
11548
11515
  constructor(e, t, n = {}) {
11549
11516
  super("MotionVector", {
11550
11517
  ...n,
@@ -11664,7 +11631,7 @@ var ef = ai("wavefront"), tf = class extends dl {
11664
11631
  dispose() {
11665
11632
  this._screenSpaceComputeNode?.dispose(), this._worldSpaceComputeNode?.dispose(), this._screenSpaceStorageTex?.dispose(), this._worldSpaceStorageTex?.dispose(), this.screenSpaceTarget?.dispose(), this.worldSpaceTarget?.dispose(), this._normalDepthTexNode?.dispose();
11666
11633
  }
11667
- }, af = (e) => L(e.equal(e), e, j(0)).clamp(0, 1e7), of = (e) => U(af(e.x), af(e.y), af(e.z)), sf = class extends lr {
11634
+ }, sf = (e) => L(e.equal(e), e, j(0)).clamp(0, 1e7), cf = (e) => U(sf(e.x), sf(e.y), sf(e.z)), lf = class extends lr {
11668
11635
  constructor(e, t = {}) {
11669
11636
  super("ASVGF", {
11670
11637
  ...t,
@@ -11705,7 +11672,7 @@ var ef = ai("wavefront"), tf = class extends dl {
11705
11672
  let e = this._colorTexNode, t = this._albedoTexNode, n = this._motionTexNode, r = this._readTemporalTexNode, i = this.gradientNoiseFloor, a = this.gradientSigmaScale, o = this._gradientStorageTex, s = this.resW, c = this.resH, l = Be("float", 144), u = Be("float", 144);
11706
11673
  this._gradientNode = f(() => {
11707
11674
  let d = se.x, f = se.y, m = f.mul(8).add(d), h = N(He.x).mul(8).sub(2).toVar(), g = N(He.y).mul(8).sub(2).toVar(), v = (i) => {
11708
- let a = i.mod(z(12)), o = i.div(z(12)), d = h.add(N(a)).clamp(N(0), N(s).sub(1)), f = g.add(N(o)).clamp(N(0), N(c).sub(1)), p = R(e, P(d, f)).xyz, m = R(t, P(d, f)).xyz, _ = Oa(of(p.div(F(m, U(Er))))).toVar();
11675
+ let a = i.mod(z(12)), o = i.div(z(12)), d = h.add(N(a)).clamp(N(0), N(s).sub(1)), f = g.add(N(o)).clamp(N(0), N(c).sub(1)), p = R(e, P(d, f)).xyz, m = R(t, P(d, f)).xyz, _ = Oa(cf(p.div(F(m, U(Er))))).toVar();
11709
11676
  l.element(i).assign(_);
11710
11677
  let v = R(n, P(d, f)), y = j(d).sub(v.x.mul(s)), b = j(f).sub(v.y.mul(c)), x = N(y.add(.5)).clamp(N(0), N(s).sub(1)), S = N(b.add(.5)).clamp(N(0), N(c).sub(1)), C = v.w.greaterThan(.5), w = R(r, P(x, S)).xyz, T = C.select(Oa(w), _);
11711
11678
  u.element(i).assign(T);
@@ -11752,7 +11719,7 @@ var ef = ai("wavefront"), tf = class extends dl {
11752
11719
  return f(() => {
11753
11720
  let f = N(He.x).mul(8).add(N(se.x)), y = N(He.y).mul(8).add(N(se.y));
11754
11721
  p(f.lessThan(N(g)).and(y.lessThan(N(v))), () => {
11755
- let b = P(f, y), x = R(t, b), S = x.xyz, C = x.w, w = R(n, b).xyz, T = F(w, U(Er)), E = of(S.div(T)), D = W(E, 1).toVar(), O = W(S, C).toVar();
11722
+ let b = P(f, y), x = R(t, b), S = x.xyz, C = x.w, w = R(n, b).xyz, T = F(w, U(Er)), E = cf(S.div(T)), D = W(E, 1).toVar(), O = W(S, C).toVar();
11756
11723
  p(m.greaterThan(.5).and(h.lessThan(.5)), () => {
11757
11724
  let e = R(r, b), t = e.w.greaterThan(.5), n = j(f).sub(e.x.mul(g)), c = j(y).sub(e.y.mul(v)), m = n.greaterThanEqual(0).and(n.lessThan(j(g))).and(c.greaterThanEqual(0)).and(c.lessThan(j(v)));
11758
11725
  p(t.and(m), () => {
@@ -11761,7 +11728,7 @@ var ef = ai("wavefront"), tf = class extends dl {
11761
11728
  return i.mul(l).mul(u);
11762
11729
  }, se = oe(w, te, re), ce = oe(k, te, ie), le = oe(w, ne, M), ue = oe(k, ne, ae), pe = se.add(ce).add(le).add(ue);
11763
11730
  p(pe.greaterThan(j(.01)), () => {
11764
- let e = R(o, P(w, te)), t = R(o, P(k, te)), n = R(o, P(w, ne)), r = R(o, P(k, ne)), i = j(1).div(pe), a = e.xyz.mul(se).add(t.xyz.mul(ce)).add(n.xyz.mul(le)).add(r.xyz.mul(ue)).mul(i), c = e.w.mul(se).add(t.w.mul(ce)).add(n.w.mul(le)).add(r.w.mul(ue)).mul(i), f = R(s, b).x.mul(d).clamp(0, 1), p = of(fe(a, E, fe(F(j(1).div(c.add(1)), u), j(1), f))), m = de(c.add(1), l);
11731
+ let e = R(o, P(w, te)), t = R(o, P(k, te)), n = R(o, P(w, ne)), r = R(o, P(k, ne)), i = j(1).div(pe), a = e.xyz.mul(se).add(t.xyz.mul(ce)).add(n.xyz.mul(le)).add(r.xyz.mul(ue)).mul(i), c = e.w.mul(se).add(t.w.mul(ce)).add(n.w.mul(le)).add(r.w.mul(ue)).mul(i), f = R(s, b).x.mul(d).clamp(0, 1), p = cf(fe(a, E, fe(F(j(1).div(c.add(1)), u), j(1), f))), m = de(c.add(1), l);
11765
11732
  D.assign(W(p, m)), O.assign(W(p.mul(T), C));
11766
11733
  });
11767
11734
  });
@@ -11879,7 +11846,7 @@ var ef = ai("wavefront"), tf = class extends dl {
11879
11846
  dispose() {
11880
11847
  this._gradientNode?.dispose(), this._temporalNodeA?.dispose(), this._temporalNodeB?.dispose(), this._temporalTexA?.dispose(), this._temporalTexB?.dispose(), this._outputModulatedTex?.dispose(), this._gradientStorageTex?.dispose(), this._demodulatedRT?.dispose(), this._outputRT?.dispose(), this._gradientRT?.dispose(), this._heatmapComputeNode?.dispose(), this._heatmapStorageTex?.dispose(), this.heatmapTarget?.dispose(), this._colorTexNode?.dispose(), this._albedoTexNode?.dispose(), this._motionTexNode?.dispose(), this._normalDepthTexNode?.dispose(), this._prevNormalDepthTexNode?.dispose(), this._readTemporalTexNode?.dispose(), this._gradientReadTexNode?.dispose(), this._heatmapRawColorTexNode?.dispose(), this._heatmapColorTexNode?.dispose(), this._heatmapTemporalTexNode?.dispose(), this._heatmapNDTexNode?.dispose(), this._heatmapMotionTexNode?.dispose(), this._heatmapGradientTexNode?.dispose();
11881
11848
  }
11882
- }, cf = (e) => L(e.equal(e), e, j(0)).clamp(0, 1e7), lf = /* @__PURE__ */ G("\n fn temporalAccumulate(\n lum: f32,\n prevMean: f32,\n prevMeanSq: f32,\n alpha: f32,\n spatialVariance: f32,\n varianceBoost: f32\n ) -> vec4f {\n\n let newMean = prevMean + ( lum - prevMean ) * alpha;\n let newMeanSq = prevMeanSq + ( lum * lum - prevMeanSq ) * alpha;\n let temporalVariance = max( newMeanSq - newMean * newMean, 0.0 );\n\n return vec4f(\n newMean,\n newMeanSq,\n temporalVariance * varianceBoost,\n spatialVariance * varianceBoost\n );\n\n }\n"), uf = class extends lr {
11849
+ }, uf = (e) => L(e.equal(e), e, j(0)).clamp(0, 1e7), df = /* @__PURE__ */ G("\n fn temporalAccumulate(\n lum: f32,\n prevMean: f32,\n prevMeanSq: f32,\n alpha: f32,\n spatialVariance: f32,\n varianceBoost: f32\n ) -> vec4f {\n\n let newMean = prevMean + ( lum - prevMean ) * alpha;\n let newMeanSq = prevMeanSq + ( lum * lum - prevMeanSq ) * alpha;\n let temporalVariance = max( newMeanSq - newMean * newMean, 0.0 );\n\n return vec4f(\n newMean,\n newMeanSq,\n temporalVariance * varianceBoost,\n spatialVariance * varianceBoost\n );\n\n }\n"), ff = class extends lr {
11883
11850
  constructor(e, t = {}) {
11884
11851
  super("VarianceEstimation", {
11885
11852
  ...t,
@@ -11905,9 +11872,9 @@ var ef = ai("wavefront"), tf = class extends dl {
11905
11872
  let n = this._colorTexNode, r = this.temporalAlpha, i = this.varianceBoost, a = this.resW, o = this.resH, s = Be("float", 100);
11906
11873
  return f(() => {
11907
11874
  let c = se.x, l = se.y, u = l.mul(8).add(c), d = N(He.x).mul(8).sub(1), f = N(He.y).mul(8).sub(1), m = u.mod(10), h = u.div(10), g = R(n, P(d.add(N(m)).clamp(N(0), N(a).sub(1)), f.add(N(h)).clamp(N(0), N(o).sub(1)))).xyz;
11908
- s.element(u).assign(cf(Oa(g))), p(u.lessThan(z(36)), () => {
11875
+ s.element(u).assign(uf(Oa(g))), p(u.lessThan(z(36)), () => {
11909
11876
  let e = u.add(z(64)), t = e.mod(10), r = e.div(10), i = R(n, P(d.add(N(t)).clamp(N(0), N(a).sub(1)), f.add(N(r)).clamp(N(0), N(o).sub(1)))).xyz;
11910
- s.element(e).assign(cf(Oa(i)));
11877
+ s.element(e).assign(uf(Oa(i)));
11911
11878
  }), Ve();
11912
11879
  let _ = N(He.x).mul(8).add(N(c)), v = N(He.y).mul(8).add(N(l));
11913
11880
  p(_.lessThan(N(a)).and(v.lessThan(N(o))), () => {
@@ -11918,7 +11885,7 @@ var ef = ai("wavefront"), tf = class extends dl {
11918
11885
  }
11919
11886
  n.divAssign(9), a.divAssign(9);
11920
11887
  let o = F(a.sub(n.mul(n)), j(0)), u = s.element(l.add(1).mul(10).add(c.add(1))), d = R(t, P(_, v));
11921
- Ne(e, Re(z(_), z(v)), lf(u, d.x, d.y, r, o, i)).toWriteOnly();
11888
+ Ne(e, Re(z(_), z(v)), df(u, d.x, d.y, r, o, i)).toWriteOnly();
11922
11889
  });
11923
11890
  })().compute([
11924
11891
  this._dispatchX,
@@ -11972,7 +11939,7 @@ var ef = ai("wavefront"), tf = class extends dl {
11972
11939
  dispose() {
11973
11940
  this._computeNodeA?.dispose(), this._computeNodeB?.dispose(), this._storageTexA?.dispose(), this._storageTexB?.dispose(), this._outputTarget?.dispose(), this._colorTexNode?.dispose(), this._readTexNodeA?.dispose(), this._readTexNodeB?.dispose();
11974
11941
  }
11975
- }, df = /* @__PURE__ */ G("\n fn bilateralWeight(\n centerLum: f32, sLum: f32,\n centerNormal: vec3f, sNormal: vec3f,\n centerDepth: f32, sDepth: f32,\n centerColor: vec3f, sColor: vec3f,\n kernelW: f32,\n sigmaL: f32, phiNorm: f32, phiDep: f32, phiCol: f32\n ) -> f32 {\n\n let lumW = exp( -abs( centerLum - sLum ) / sigmaL );\n // clamp dot to [0,1]: miss-ray normals decode to (-1,-1,-1) with\n // dot=3 → pow saturates to +inf → inf*0 = NaN. See project_tsl_pitfalls.\n // max(phiNorm, 1e-6): pow(0.0, 0.0) is undefined in WGSL and returned NaN on ~12%\n // of pixels when phiNormal was set to 0.\n let normW = pow( clamp( dot( centerNormal, sNormal ), 0.0, 1.0 ), max( phiNorm, 1e-6 ) );\n let depW = exp( -abs( centerDepth - sDepth ) / max( centerDepth * phiDep, 0.001 ) );\n let maxDiff = max( max( abs( centerColor.x - sColor.x ),\n abs( centerColor.y - sColor.y ) ),\n abs( centerColor.z - sColor.z ) );\n let avgLum = max( ( centerLum + sLum ) * 0.5, 0.0001 );\n let colW = exp( -( maxDiff / avgLum ) / max( phiCol, 0.0001 ) );\n return kernelW * lumW * normW * depW * colW;\n\n }\n"), ff = class extends lr {
11942
+ }, pf = /* @__PURE__ */ G("\n fn bilateralWeight(\n centerLum: f32, sLum: f32,\n centerNormal: vec3f, sNormal: vec3f,\n centerDepth: f32, sDepth: f32,\n centerColor: vec3f, sColor: vec3f,\n kernelW: f32,\n sigmaL: f32, phiNorm: f32, phiDep: f32, phiCol: f32\n ) -> f32 {\n\n let lumW = exp( -abs( centerLum - sLum ) / sigmaL );\n // clamp dot to [0,1]: miss-ray normals decode to (-1,-1,-1) with\n // dot=3 → pow saturates to +inf → inf*0 = NaN. See project_tsl_pitfalls.\n // max(phiNorm, 1e-6): pow(0.0, 0.0) is undefined in WGSL and returned NaN on ~12%\n // of pixels when phiNormal was set to 0.\n let normW = pow( clamp( dot( centerNormal, sNormal ), 0.0, 1.0 ), max( phiNorm, 1e-6 ) );\n let depW = exp( -abs( centerDepth - sDepth ) / max( centerDepth * phiDep, 0.001 ) );\n let maxDiff = max( max( abs( centerColor.x - sColor.x ),\n abs( centerColor.y - sColor.y ) ),\n abs( centerColor.z - sColor.z ) );\n let avgLum = max( ( centerLum + sLum ) * 0.5, 0.0001 );\n let colW = exp( -( maxDiff / avgLum ) / max( phiCol, 0.0001 ) );\n return kernelW * lumW * normW * depW * colW;\n\n }\n"), mf = class extends lr {
11976
11943
  constructor(e, t = {}) {
11977
11944
  super("BilateralFiltering", {
11978
11945
  ...t,
@@ -12027,7 +11994,7 @@ var ef = ai("wavefront"), tf = class extends dl {
12027
11994
  return fe(t.z, F(t.z, t.w), d);
12028
11995
  }, ee = k.select(A(p), x.w.mul(x.w)).toVar(), te = u.mul(we(F(ee, j(0)))).div(O).add(j(1e-4)), ne = U(0).toVar(), re = j(0).toVar(), ie = j(0).toVar();
12029
11996
  for (let e = 0; e < 5; e++) for (let i = 0; i < 5; i++) {
12030
- let a = i - 2, o = e - 2, u = y[e * 5 + i], d = f.add(m.mul(a)).clamp(N(0), N(_).sub(1)), p = b.add(m.mul(o)).clamp(N(0), N(v).sub(1)), h = R(t, P(d, p)), g = h.xyz, x = R(n, P(d, p)), C = R(r, P(d, p)).xyz.mul(2).sub(1), D = x.w, O = df(E, Oa(g), w, C, T, D, S, g, j(u), te, c, l, s), ee = k.select(A(P(d, p)), h.w.mul(h.w));
11997
+ let a = i - 2, o = e - 2, u = y[e * 5 + i], d = f.add(m.mul(a)).clamp(N(0), N(_).sub(1)), p = b.add(m.mul(o)).clamp(N(0), N(v).sub(1)), h = R(t, P(d, p)), g = h.xyz, x = R(n, P(d, p)), C = R(r, P(d, p)).xyz.mul(2).sub(1), D = x.w, O = pf(E, Oa(g), w, C, T, D, S, g, j(u), te, c, l, s), ee = k.select(A(P(d, p)), h.w.mul(h.w));
12031
11998
  ne.addAssign(g.mul(O)), re.addAssign(O), ie.addAssign(O.mul(O).mul(F(ee, j(0))));
12032
11999
  }
12033
12000
  let M = ne.div(F(re, j(1e-4))), ae = ie.div(F(re.mul(re), j(1e-8))), oe = h.equal(N(1)), se = oe.select(M.mul(D), M), ce = oe.select(R(o, p).w, we(F(ae, j(0))));
@@ -12086,7 +12053,7 @@ var ef = ai("wavefront"), tf = class extends dl {
12086
12053
  dispose() {
12087
12054
  this._computeNodeA?.dispose(), this._computeNodeB?.dispose(), this._storageTexA?.dispose(), this._storageTexB?.dispose(), this._outputTarget?.dispose(), this._readTexNode?.dispose(), this._normalDepthTexNode?.dispose(), this._shadingNormalTexNode?.dispose(), this._albedoTexNode?.dispose(), this._varianceTexNode?.dispose(), this._srcAlphaTexNode?.dispose();
12088
12055
  }
12089
- }, pf = 6e4, mf = (e) => L(e.equal(e), e, j(0)).clamp(0, 1e7), hf = (e) => U(mf(e.x), mf(e.y), mf(e.z)), gf = [
12056
+ }, hf = 6e4, gf = (e) => L(e.equal(e), e, j(0)).clamp(0, 1e7), _f = (e) => U(gf(e.x), gf(e.y), gf(e.z)), vf = [
12090
12057
  1 / 256,
12091
12058
  4 / 256,
12092
12059
  6 / 256,
@@ -12112,7 +12079,7 @@ var ef = ai("wavefront"), tf = class extends dl {
12112
12079
  6 / 256,
12113
12080
  4 / 256,
12114
12081
  1 / 256
12115
- ], _f = class extends lr {
12082
+ ], yf = class extends lr {
12116
12083
  constructor(e, t = {}) {
12117
12084
  super("EdgeAwareFiltering", {
12118
12085
  ...t,
@@ -12140,7 +12107,7 @@ var ef = ai("wavefront"), tf = class extends dl {
12140
12107
  return f(() => {
12141
12108
  let o = N(He.x).mul(16).add(N(se.x)), s = N(He.y).mul(16).add(N(se.y));
12142
12109
  p(o.lessThan(N(i)).and(s.lessThan(N(a))), () => {
12143
- let i = P(o, s), a = R(e, i).xyz, c = R(t, i).w.lessThan(j(pf)), l = R(n, i).xyz, u = L(c, F(l, U(Er)), U(1)), d = hf(a.div(u));
12110
+ let i = P(o, s), a = R(e, i).xyz, c = R(t, i).w.lessThan(j(hf)), l = R(n, i).xyz, u = L(c, F(l, U(Er)), U(1)), d = _f(a.div(u));
12144
12111
  Ne(r, Re(z(o), z(s)), W(d, 1)).toWriteOnly();
12145
12112
  });
12146
12113
  })().compute([
@@ -12158,12 +12125,12 @@ var ef = ai("wavefront"), tf = class extends dl {
12158
12125
  return f(() => {
12159
12126
  let f = N(He.x).mul(16).add(N(se.x)), v = N(He.y).mul(16).add(N(se.y));
12160
12127
  p(f.lessThan(N(g)).and(v.lessThan(N(_))), () => {
12161
- let p = P(f, v), y = R(t, p), b = y.xyz, x = Oa(b), S = R(r, p).w, C = R(i, p).xyz.mul(2).sub(1), w = S.lessThan(j(pf)), T = L(w, j(1), j(0)), E = R(a, p).xyz, D = L(w, F(E, U(Er)), U(1)), O = F(Oa(D), j(Er)), k = h.equal(N(1)), ee = (e) => {
12128
+ let p = P(f, v), y = R(t, p), b = y.xyz, x = Oa(b), S = R(r, p).w, C = R(i, p).xyz.mul(2).sub(1), w = S.lessThan(j(hf)), T = L(w, j(1), j(0)), E = R(a, p).xyz, D = L(w, F(E, U(Er)), U(1)), O = F(Oa(D), j(Er)), k = h.equal(N(1)), ee = (e) => {
12162
12129
  let t = R(o, e);
12163
12130
  return F(t.z, t.w);
12164
12131
  }, te = k.select(ee(p), y.w.mul(y.w)).toVar(), ne = c.mul(we(F(te, j(0)))).div(O).add(j(1e-4)), re = U(0).toVar(), ie = j(0).toVar(), M = j(0).toVar();
12165
12132
  for (let e = 0; e < 5; e++) for (let n = 0; n < 5; n++) {
12166
- let a = n - 2, o = e - 2, s = gf[e * 5 + n], c = P(f.add(d.mul(a)).clamp(N(0), N(g).sub(1)), v.add(d.mul(o)).clamp(N(0), N(_).sub(1))), p = R(t, c), m = p.xyz, h = Oa(m), y = R(r, c).w, b = R(i, c).xyz.mul(2).sub(1), w = L(y.lessThan(j(pf)), j(1), j(0)), E = x.sub(h).abs().div(ne).negate().exp(), D = _e(A(C, b).clamp(0, 1), l), O = S.sub(y).abs().div(F(S.mul(u), j(.001))).negate().exp(), te = T.mul(w), ae = T.oneMinus().mul(w.oneMinus()), oe = te.add(ae), se = fe(j(1), D.mul(O), te), ce = j(s).mul(E).mul(se).mul(oe), le = k.select(ee(c), p.w.mul(p.w));
12133
+ let a = n - 2, o = e - 2, s = vf[e * 5 + n], c = P(f.add(d.mul(a)).clamp(N(0), N(g).sub(1)), v.add(d.mul(o)).clamp(N(0), N(_).sub(1))), p = R(t, c), m = p.xyz, h = Oa(m), y = R(r, c).w, b = R(i, c).xyz.mul(2).sub(1), w = L(y.lessThan(j(hf)), j(1), j(0)), E = x.sub(h).abs().div(ne).negate().exp(), D = _e(A(C, b).clamp(0, 1), l), O = S.sub(y).abs().div(F(S.mul(u), j(.001))).negate().exp(), te = T.mul(w), ae = T.oneMinus().mul(w.oneMinus()), oe = te.add(ae), se = fe(j(1), D.mul(O), te), ce = j(s).mul(E).mul(se).mul(oe), le = k.select(ee(c), p.w.mul(p.w));
12167
12134
  re.addAssign(m.mul(ce)), ie.addAssign(ce), M.addAssign(ce.mul(ce).mul(F(le, j(0))));
12168
12135
  }
12169
12136
  let ae = re.div(F(ie, j(1e-4))), oe = M.div(F(ie.mul(ie), j(1e-8))), se = m.equal(N(1)), ce = R(n, p).xyz, le = fe(ce, ae.mul(D), s), ue = se.select(le, ae), de = se.select(R(n, p).w, we(F(oe, j(0))));
@@ -12225,7 +12192,7 @@ var ef = ai("wavefront"), tf = class extends dl {
12225
12192
  dispose() {
12226
12193
  this._computeDemod?.dispose(), this._computeAtrousA?.dispose(), this._computeAtrousB?.dispose(), this._demodTex?.dispose(), this._storageTexA?.dispose(), this._storageTexB?.dispose(), this.outputTarget?.dispose(), this._colorTexNode?.dispose(), this._ndTexNode?.dispose(), this._snTexNode?.dispose(), this._albedoTexNode?.dispose(), this._varTexNode?.dispose(), this._readTexNode?.dispose();
12227
12194
  }
12228
- }, vf = 256, yf = -8, bf = 6 - yf, xf = bf / vf, Sf = 1e4, Cf = /* @__PURE__ */ G("\n fn adaptExposure(\n geoMean: f32,\n prevExposure: f32,\n keyValue: f32,\n minExp: f32,\n maxExp: f32,\n speedBright: f32,\n speedDark: f32,\n dt: f32,\n isFirstFrame: f32\n ) -> vec4f {\n\n let targetExp = clamp( keyValue / max( geoMean, 0.001 ), minExp, maxExp );\n var newExposure = targetExp;\n\n // Temporal smoothing (skip on first frame)\n if ( isFirstFrame < 0.5 ) {\n\n // Asymmetric speed: brighter scenes adapt faster\n let speed = select( speedDark, speedBright, targetExp < prevExposure );\n let alpha = 1.0 - exp( -dt * speed );\n newExposure = mix( prevExposure, targetExp, alpha );\n\n }\n\n return vec4f( newExposure, geoMean, targetExp, 1.0 );\n\n }\n"), wf = class extends lr {
12195
+ }, bf = 256, xf = -8, Sf = 6 - xf, Cf = Sf / bf, wf = 1e4, Tf = /* @__PURE__ */ G("\n fn adaptExposure(\n geoMean: f32,\n prevExposure: f32,\n keyValue: f32,\n minExp: f32,\n maxExp: f32,\n speedBright: f32,\n speedDark: f32,\n dt: f32,\n isFirstFrame: f32\n ) -> vec4f {\n\n let targetExp = clamp( keyValue / max( geoMean, 0.001 ), minExp, maxExp );\n var newExposure = targetExp;\n\n // Temporal smoothing (skip on first frame)\n if ( isFirstFrame < 0.5 ) {\n\n // Asymmetric speed: brighter scenes adapt faster\n let speed = select( speedDark, speedBright, targetExp < prevExposure );\n let alpha = 1.0 - exp( -dt * speed );\n newExposure = mix( prevExposure, targetExp, alpha );\n\n }\n\n return vec4f( newExposure, geoMean, targetExp, 1.0 );\n\n }\n"), Ef = class extends lr {
12229
12196
  constructor(e, t = {}) {
12230
12197
  super("AutoExposure", {
12231
12198
  ...t,
@@ -12241,7 +12208,7 @@ var ef = ai("wavefront"), tf = class extends dl {
12241
12208
  depthBuffer: !1,
12242
12209
  stencilBuffer: !1
12243
12210
  };
12244
- this._downsampleTarget = new i(this.REDUCTION_SIZE, this.REDUCTION_SIZE, e), this._downsampleStorageTex = new s(this.REDUCTION_SIZE, this.REDUCTION_SIZE), this._downsampleStorageTex.type = ft, this._downsampleStorageTex.format = Bt, this._downsampleStorageTex.minFilter = Ot, this._downsampleStorageTex.magFilter = Ot, this._reductionStorageTex = new s(1, 1), this._reductionStorageTex.type = ft, this._reductionStorageTex.format = Bt, this._reductionStorageTex.minFilter = Ot, this._reductionStorageTex.magFilter = Ot, this._reductionReadTarget = new i(1, 1, e), this._adaptationResult = w(1, "vec4"), this._readbackBuffer = new n(16), this._readbackBuffer.name = "AutoExposureAdaptation", this._histogramBuffer = w(vf, "uint").toAtomic();
12211
+ this._downsampleTarget = new i(this.REDUCTION_SIZE, this.REDUCTION_SIZE, e), this._downsampleStorageTex = new s(this.REDUCTION_SIZE, this.REDUCTION_SIZE), this._downsampleStorageTex.type = ft, this._downsampleStorageTex.format = Bt, this._downsampleStorageTex.minFilter = Ot, this._downsampleStorageTex.magFilter = Ot, this._reductionStorageTex = new s(1, 1), this._reductionStorageTex.type = ft, this._reductionStorageTex.format = Bt, this._reductionStorageTex.minFilter = Ot, this._reductionStorageTex.magFilter = Ot, this._reductionReadTarget = new i(1, 1, e), this._adaptationResult = w(1, "vec4"), this._readbackBuffer = new n(16), this._readbackBuffer.name = "AutoExposureAdaptation", this._histogramBuffer = w(bf, "uint").toAtomic();
12245
12212
  }
12246
12213
  _buildCompute() {
12247
12214
  this._buildDownsampleCompute(), this._buildHistogramCompute(), this._buildHistogramAnalyzeCompute(), this._buildAdaptationCompute();
@@ -12275,7 +12242,7 @@ var ef = ai("wavefront"), tf = class extends dl {
12275
12242
  for (let i = 0; i < 16; i++) {
12276
12243
  let a = r.mul(16).add(i), o = a.mod(64), s = a.div(64), c = R(e, P(N(o), N(s))), l = c.x, u = c.y;
12277
12244
  p(u.greaterThan(0), () => {
12278
- let e = z(l.div(u).sub(j(yf)).div(j(bf)).mul(j(vf)).floor().clamp(0, j(vf - 1))), r = j(o).add(.5).div(j(64)), i = j(s).add(.5).div(j(64)), a = r.sub(.5), c = i.sub(.5), d = z(a.mul(a).add(c.mul(c)).mul(n).negate().exp().mul(j(Sf)));
12245
+ let e = z(l.div(u).sub(j(xf)).div(j(Sf)).mul(j(bf)).floor().clamp(0, j(bf - 1))), r = j(o).add(.5).div(j(64)), i = j(s).add(.5).div(j(64)), a = r.sub(.5), c = i.sub(.5), d = z(a.mul(a).add(c.mul(c)).mul(n).negate().exp().mul(j(wf)));
12279
12246
  x(t.element(e), d);
12280
12247
  });
12281
12248
  }
@@ -12293,14 +12260,14 @@ var ef = ai("wavefront"), tf = class extends dl {
12293
12260
  let e = this._histogramBuffer, t = this._reductionStorageTex, n = this.lowPercentileU, r = this.highPercentileU;
12294
12261
  this._histogramAnalyzeNode = f(() => {
12295
12262
  let i = j(0).toVar();
12296
- m(vf, ({ i: t }) => {
12263
+ m(bf, ({ i: t }) => {
12297
12264
  i.addAssign(j(S(e.element(t))));
12298
12265
  });
12299
12266
  let a = i.mul(n), o = i.mul(r), s = j(0).toVar(), c = j(0).toVar(), l = j(0).toVar(), u = j(0).toVar();
12300
- m(vf, ({ i: t }) => {
12267
+ m(bf, ({ i: t }) => {
12301
12268
  let n = j(S(e.element(t)));
12302
12269
  u.assign(s), s.addAssign(n), p(u.lessThan(o).and(s.greaterThan(a)), () => {
12303
- let e = j(yf).add(j(t).add(.5).mul(j(xf)));
12270
+ let e = j(xf).add(j(t).add(.5).mul(j(Cf)));
12304
12271
  c.addAssign(e.mul(n)), l.addAssign(n);
12305
12272
  });
12306
12273
  });
@@ -12315,7 +12282,7 @@ var ef = ai("wavefront"), tf = class extends dl {
12315
12282
  _buildAdaptationCompute() {
12316
12283
  let e = this._reductionReadTexNode, t = this._adaptationResult, n = this.keyValueU, r = this.minExposureU, i = this.maxExposureU, a = this.adaptSpeedBrightU, o = this.adaptSpeedDarkU, s = this.deltaTimeU, c = this.isFirstFrameU, l = this.previousExposureU;
12317
12284
  this._adaptationComputeNode = f(() => {
12318
- let u = R(e, P(N(0), N(0))).x, d = Cf(u, l, n, r, i, a, o, s, c);
12285
+ let u = R(e, P(N(0), N(0))).x, d = Tf(u, l, n, r, i, a, o, s, c);
12319
12286
  t.element(z(0)).assign(d);
12320
12287
  })().compute(1, [
12321
12288
  1,
@@ -12379,7 +12346,7 @@ var ef = ai("wavefront"), tf = class extends dl {
12379
12346
  dispose() {
12380
12347
  this._downsampleComputeNode?.dispose(), this._histogramComputeNode?.dispose(), this._histogramAnalyzeNode?.dispose(), this._adaptationComputeNode?.dispose(), this._downsampleTarget?.dispose(), this._downsampleStorageTex?.dispose(), this._reductionStorageTex?.dispose(), this._reductionReadTarget?.dispose(), this._readbackBuffer?.dispose(), this._inputTexNode?.dispose(), this._reductionReadTexNode?.dispose();
12381
12348
  }
12382
- }, Tf = class extends lr {
12349
+ }, Df = class extends lr {
12383
12350
  constructor(n, r = {}) {
12384
12351
  super("Compositor", {
12385
12352
  ...r,
@@ -12405,7 +12372,7 @@ var ef = ai("wavefront"), tf = class extends dl {
12405
12372
  dispose() {
12406
12373
  this._sourceTexNode?.dispose(), this.compositorMaterial?.dispose(), this.compositorQuad = null;
12407
12374
  }
12408
- }, Ef = class {
12375
+ }, Of = class {
12409
12376
  constructor() {
12410
12377
  this.textures = /* @__PURE__ */ new Map(), this.renderTargets = /* @__PURE__ */ new Map(), this.uniforms = /* @__PURE__ */ new Map(), this.state = {
12411
12378
  frame: 0,
@@ -12527,7 +12494,7 @@ var ef = ai("wavefront"), tf = class extends dl {
12527
12494
  dispose() {
12528
12495
  this.textures.clear(), this.renderTargets.clear(), this.uniforms.clear(), this._stateChangeCallbacks.clear(), this.state = {};
12529
12496
  }
12530
- }, Df = class extends ut {
12497
+ }, kf = class extends ut {
12531
12498
  constructor() {
12532
12499
  super(), this._onceCallbacks = /* @__PURE__ */ new Map();
12533
12500
  }
@@ -12565,38 +12532,38 @@ var ef = ai("wavefront"), tf = class extends dl {
12565
12532
  eventNames() {
12566
12533
  return this._listeners ? Object.keys(this._listeners) : [];
12567
12534
  }
12568
- }, Of = !1, kf = [], Af = /* @__PURE__ */ new WeakMap();
12569
- function jf(e) {
12570
- Of = !!e;
12535
+ }, Af = !1, jf = [], Mf = /* @__PURE__ */ new WeakMap();
12536
+ function Nf(e) {
12537
+ Af = !!e;
12571
12538
  }
12572
- function Mf() {
12573
- return kf.slice();
12539
+ function Pf() {
12540
+ return jf.slice();
12574
12541
  }
12575
- function Nf() {
12576
- kf.length = 0;
12542
+ function Ff() {
12543
+ jf.length = 0;
12577
12544
  }
12578
- function Pf(e) {
12545
+ function If(e) {
12579
12546
  let t = [];
12580
12547
  for (let n of Object.keys(e)) e[n]?.isTextureNode === !0 && t.push(n);
12581
12548
  return t;
12582
12549
  }
12583
- var Ff = (e) => !e || !e.image || !(e.image.width > 0);
12584
- function If(e, t, n) {
12585
- if (!Of) {
12550
+ var Lf = (e) => !e || !e.image || !(e.image.width > 0);
12551
+ function Rf(e, t, n) {
12552
+ if (!Af) {
12586
12553
  n();
12587
12554
  return;
12588
12555
  }
12589
- let r = Af.get(e);
12556
+ let r = Mf.get(e);
12590
12557
  if (r || (r = {
12591
12558
  phase: "pending",
12592
12559
  unboundAtCompile: []
12593
- }, Af.set(e, r)), r.phase !== "pending") {
12594
- n(), r.phase === "watch" && Lf(e, r);
12560
+ }, Mf.set(e, r)), r.phase !== "pending") {
12561
+ n(), r.phase === "watch" && zf(e, r);
12595
12562
  return;
12596
12563
  }
12597
12564
  let i = Object.prototype.hasOwnProperty.call(t, "compute"), a = t.compute;
12598
12565
  t.compute = function(...t) {
12599
- return r.phase === "pending" && (r.unboundAtCompile = Pf(e).filter((t) => Ff(e[t].value)), r.phase = r.unboundAtCompile.length < 2 ? "done" : "watch"), a.apply(this, t);
12566
+ return r.phase === "pending" && (r.unboundAtCompile = If(e).filter((t) => Lf(e[t].value)), r.phase = r.unboundAtCompile.length < 2 ? "done" : "watch"), a.apply(this, t);
12600
12567
  };
12601
12568
  try {
12602
12569
  n();
@@ -12604,14 +12571,14 @@ function If(e, t, n) {
12604
12571
  i ? t.compute = a : delete t.compute;
12605
12572
  }
12606
12573
  }
12607
- function Lf(e, t) {
12574
+ function zf(e, t) {
12608
12575
  let n = [];
12609
12576
  for (let r of t.unboundAtCompile) {
12610
12577
  let t = e[r]?.value;
12611
- if (Ff(t)) return;
12578
+ if (Lf(t)) return;
12612
12579
  t.isStorageTexture !== !0 && n.push(r);
12613
12580
  }
12614
- t.phase = "done", n.length !== 0 && kf.push({
12581
+ t.phase = "done", n.length !== 0 && jf.push({
12615
12582
  stage: e.name,
12616
12583
  nodes: n,
12617
12584
  unboundAtCompile: t.unboundAtCompile.slice(),
@@ -12620,9 +12587,9 @@ function Lf(e, t) {
12620
12587
  }
12621
12588
  //#endregion
12622
12589
  //#region src/Pipeline/RenderPipeline.js
12623
- var Rf = class {
12590
+ var Bf = class {
12624
12591
  constructor(e, t, n) {
12625
- this.renderer = e, this.width = t, this.height = n, this.stages = [], this.context = new Ef(), this.eventBus = new Df(), this.context.setState("width", t), this.context.setState("height", n), this.stats = {
12592
+ this.renderer = e, this.width = t, this.height = n, this.stages = [], this.context = new Of(), this.eventBus = new kf(), this.context.setState("width", t), this.context.setState("height", n), this.stats = {
12626
12593
  enabled: !1,
12627
12594
  logSkipped: !1,
12628
12595
  timings: /* @__PURE__ */ new Map(),
@@ -12656,7 +12623,7 @@ var Rf = class {
12656
12623
  }
12657
12624
  try {
12658
12625
  let n = this.stats.enabled ? performance.now() : 0;
12659
- if (If(t, this.renderer, () => t.render(this.context, e)), this.stats.enabled) {
12626
+ if (Rf(t, this.renderer, () => t.render(this.context, e)), this.stats.enabled) {
12660
12627
  let e = performance.now() - n;
12661
12628
  this.stats.timings.has(t.name) || this.stats.timings.set(t.name, []);
12662
12629
  let r = this.stats.timings.get(t.name);
@@ -12754,7 +12721,7 @@ var Rf = class {
12754
12721
  let e = this.getInfo();
12755
12722
  console.group("[Pipeline] Info"), console.log("Stages:", e.stages), console.log("Context Textures:", e.textures), console.log("Context Render Targets:", e.renderTargets), console.log("Context Uniforms:", e.uniforms), console.log("Event Types:", e.events), console.log("State:", e.contextState), console.groupEnd();
12756
12723
  }
12757
- }, zf = class {
12724
+ }, Vf = class {
12758
12725
  constructor() {
12759
12726
  this.timeElapsed = 0, this.lastResetTime = performance.now(), this.renderCompleteDispatched = !1;
12760
12727
  }
@@ -12776,7 +12743,7 @@ var Rf = class {
12776
12743
  resumeFromPause() {
12777
12744
  this.renderCompleteDispatched = !1, this.lastResetTime = performance.now() - this.timeElapsed * 1e3;
12778
12745
  }
12779
- }, Bf = class extends ut {
12746
+ }, Hf = class extends ut {
12780
12747
  constructor({ scene: e, camera: t, canvas: n, assetLoader: r, pathTracer: i, floorPlane: a }) {
12781
12748
  super(), this.scene = e, this.camera = t, this.canvas = n, this.assetLoader = r, this.pathTracer = i, this.floorPlane = a, this.raycaster = new Ut(), this.focusMode = !1, this.focusPointIndicator = null, this.afPointPlacementMode = !1, this.handleAFPointClick = this.handleAFPointClick.bind(this), this.selectedObject = null, this.selectMode = !1, this.clickTimeout = null, this.mouseDownPosition = null, this.dragThreshold = 5, this.handleFocusClick = this.handleFocusClick.bind(this), this.handleSelectClick = this.handleSelectClick.bind(this), this.handleSelectDoubleClick = this.handleSelectDoubleClick.bind(this), this.handleMouseDown = this.handleMouseDown.bind(this), this.handleMouseUp = this.handleMouseUp.bind(this), this.handleContextMenu = this.handleContextMenu.bind(this), this.handleContextPointerDown = this.handleContextPointerDown.bind(this), this.handleContextPointerUp = this.handleContextPointerUp.bind(this), this.contextPointerDownPosition = null, this.canvas.addEventListener("pointerdown", this.handleContextPointerDown), this.canvas.addEventListener("pointerup", this.handleContextPointerUp), this.canvas.addEventListener("contextmenu", this.handleContextMenu), this._overlayManager = null, this._transformManager = null, this._appDispatch = null, this._orbitControls = null, this._helperScene = null;
12782
12749
  }
@@ -13012,18 +12979,18 @@ var Rf = class {
13012
12979
  dispose() {
13013
12980
  this.canvas.removeEventListener("click", this.handleAFPointClick), this.canvas.removeEventListener("click", this.handleFocusClick), this.canvas.removeEventListener("mousedown", this.handleMouseDown), this.canvas.removeEventListener("mouseup", this.handleMouseUp), this.canvas.removeEventListener("click", this.handleSelectClick), this.canvas.removeEventListener("dblclick", this.handleSelectDoubleClick), this.canvas.removeEventListener("contextmenu", this.handleContextMenu), this.canvas.removeEventListener("pointerdown", this.handleContextPointerDown), this.canvas.removeEventListener("pointerup", this.handleContextPointerUp), this.clickTimeout &&= (clearTimeout(this.clickTimeout), null), this.mouseDownPosition = null, this.contextPointerDownPosition = null, this.focusPointIndicator &&= (this.scene.remove(this.focusPointIndicator), null), this.canvas.style.cursor = "auto", this.scene = null, this.camera = null, this.canvas = null, this.assetLoader = null, this.pathTracer = null, this.floorPlane = null, this.raycaster = null;
13014
12981
  }
13015
- }, Vf = {
12982
+ }, Uf = {
13016
12983
  STRING: "string",
13017
12984
  NUMBER: "number",
13018
12985
  WORD: "word",
13019
12986
  LBRACKET: "[",
13020
12987
  RBRACKET: "]"
13021
- }, Hf = (e) => e === " " || e === " " || e === "\n" || e === "\r" || e === "\f", Uf = (e) => e >= "0" && e <= "9", Wf = (e, t, n) => !!(Uf(e) || e === "." && Uf(t) || (e === "-" || e === "+") && (Uf(t) || t === "." && Uf(n)));
13022
- function Gf(e) {
12988
+ }, Wf = (e) => e === " " || e === " " || e === "\n" || e === "\r" || e === "\f", Gf = (e) => e >= "0" && e <= "9", Kf = (e, t, n) => !!(Gf(e) || e === "." && Gf(t) || (e === "-" || e === "+") && (Gf(t) || t === "." && Gf(n)));
12989
+ function qf(e) {
13023
12990
  let t = [], n = e.length, r = 0;
13024
12991
  for (; r < n;) {
13025
12992
  let i = e[r];
13026
- if (Hf(i)) {
12993
+ if (Wf(i)) {
13027
12994
  r++;
13028
12995
  continue;
13029
12996
  }
@@ -13032,11 +12999,11 @@ function Gf(e) {
13032
12999
  continue;
13033
13000
  }
13034
13001
  if (i === "[") {
13035
- t.push({ type: Vf.LBRACKET }), r++;
13002
+ t.push({ type: Uf.LBRACKET }), r++;
13036
13003
  continue;
13037
13004
  }
13038
13005
  if (i === "]") {
13039
- t.push({ type: Vf.RBRACKET }), r++;
13006
+ t.push({ type: Uf.RBRACKET }), r++;
13040
13007
  continue;
13041
13008
  }
13042
13009
  if (i === "\"") {
@@ -13045,12 +13012,12 @@ function Gf(e) {
13045
13012
  for (; r < n && e[r] !== "\"";) r++;
13046
13013
  if (r >= n) throw Error("PBRT tokenizer: unterminated string literal");
13047
13014
  t.push({
13048
- type: Vf.STRING,
13015
+ type: Uf.STRING,
13049
13016
  value: e.slice(i, r)
13050
13017
  }), r++;
13051
13018
  continue;
13052
13019
  }
13053
- if (Wf(i, e[r + 1], e[r + 2])) {
13020
+ if (Kf(i, e[r + 1], e[r + 2])) {
13054
13021
  let i = r;
13055
13022
  for (r++; r < n;) {
13056
13023
  let t = e[r];
@@ -13060,16 +13027,16 @@ function Gf(e) {
13060
13027
  let a = e.slice(i, r), o = Number(a);
13061
13028
  if (Number.isNaN(o)) throw Error(`PBRT tokenizer: invalid number "${a}"`);
13062
13029
  t.push({
13063
- type: Vf.NUMBER,
13030
+ type: Uf.NUMBER,
13064
13031
  value: o
13065
13032
  });
13066
13033
  continue;
13067
13034
  }
13068
13035
  {
13069
13036
  let i = r;
13070
- for (; r < n && !Hf(e[r]) && e[r] !== "\"" && e[r] !== "[" && e[r] !== "]" && e[r] !== "#";) r++;
13037
+ for (; r < n && !Wf(e[r]) && e[r] !== "\"" && e[r] !== "[" && e[r] !== "]" && e[r] !== "#";) r++;
13071
13038
  t.push({
13072
- type: Vf.WORD,
13039
+ type: Uf.WORD,
13073
13040
  value: e.slice(i, r)
13074
13041
  });
13075
13042
  }
@@ -13078,7 +13045,7 @@ function Gf(e) {
13078
13045
  }
13079
13046
  //#endregion
13080
13047
  //#region src/Processor/PBRT/PBRTMath.js
13081
- function Kf() {
13048
+ function Jf() {
13082
13049
  return [
13083
13050
  1,
13084
13051
  0,
@@ -13098,7 +13065,7 @@ function Kf() {
13098
13065
  1
13099
13066
  ];
13100
13067
  }
13101
- function qf(e, t) {
13068
+ function Yf(e, t) {
13102
13069
  let n = e[0], r = e[1], i = e[2], a = e[3], o = e[4], s = e[5], c = e[6], l = e[7], u = e[8], d = e[9], f = e[10], p = e[11], m = e[12], h = e[13], g = e[14], _ = e[15], v = t[0], y = t[1], b = t[2], x = t[3], S = t[4], C = t[5], w = t[6], T = t[7], E = t[8], D = t[9], O = t[10], k = t[11], A = t[12], ee = t[13], te = t[14], j = t[15];
13103
13070
  return [
13104
13071
  n * v + o * y + u * b + m * x,
@@ -13119,7 +13086,7 @@ function qf(e, t) {
13119
13086
  a * A + l * ee + p * te + _ * j
13120
13087
  ];
13121
13088
  }
13122
- function Jf(e, t, n) {
13089
+ function Xf(e, t, n) {
13123
13090
  return [
13124
13091
  1,
13125
13092
  0,
@@ -13139,7 +13106,7 @@ function Jf(e, t, n) {
13139
13106
  1
13140
13107
  ];
13141
13108
  }
13142
- function Yf(e, t, n) {
13109
+ function Zf(e, t, n) {
13143
13110
  return [
13144
13111
  e,
13145
13112
  0,
@@ -13159,7 +13126,7 @@ function Yf(e, t, n) {
13159
13126
  1
13160
13127
  ];
13161
13128
  }
13162
- function Xf(e, t, n, r) {
13129
+ function Qf(e, t, n, r) {
13163
13130
  let i = Math.hypot(t, n, r) || 1;
13164
13131
  t /= i, n /= i, r /= i;
13165
13132
  let a = e * Math.PI / 180, o = Math.cos(a), s = Math.sin(a), c = 1 - o, l = c * t * t + o, u = c * t * n - s * r, d = c * t * r + s * n, f = c * t * n + s * r, p = c * n * n + o, m = c * n * r - s * t;
@@ -13182,21 +13149,21 @@ function Xf(e, t, n, r) {
13182
13149
  1
13183
13150
  ];
13184
13151
  }
13185
- function Zf(e, t) {
13152
+ function $f(e, t) {
13186
13153
  return [
13187
13154
  e[0] - t[0],
13188
13155
  e[1] - t[1],
13189
13156
  e[2] - t[2]
13190
13157
  ];
13191
13158
  }
13192
- function Qf(e, t) {
13159
+ function ep(e, t) {
13193
13160
  return [
13194
13161
  e[1] * t[2] - e[2] * t[1],
13195
13162
  e[2] * t[0] - e[0] * t[2],
13196
13163
  e[0] * t[1] - e[1] * t[0]
13197
13164
  ];
13198
13165
  }
13199
- function $f(e) {
13166
+ function tp(e) {
13200
13167
  let t = Math.hypot(e[0], e[1], e[2]) || 1;
13201
13168
  return [
13202
13169
  e[0] / t,
@@ -13204,8 +13171,8 @@ function $f(e) {
13204
13171
  e[2] / t
13205
13172
  ];
13206
13173
  }
13207
- function ep(e, t, n) {
13208
- let r = $f(Zf(t, e)), i = $f(Qf($f(n), r)), a = Qf(r, i);
13174
+ function np(e, t, n) {
13175
+ let r = tp($f(t, e)), i = tp(ep(tp(n), r)), a = ep(r, i);
13209
13176
  return [
13210
13177
  i[0],
13211
13178
  i[1],
@@ -13225,9 +13192,9 @@ function ep(e, t, n) {
13225
13192
  1
13226
13193
  ];
13227
13194
  }
13228
- function tp(e) {
13195
+ function rp(e) {
13229
13196
  let t = e[0], n = e[1], r = e[2], i = e[3], a = e[4], o = e[5], s = e[6], c = e[7], l = e[8], u = e[9], d = e[10], f = e[11], p = e[12], m = e[13], h = e[14], g = e[15], _ = u * h * c - m * d * c + m * s * f - o * h * f - u * s * g + o * d * g, v = p * d * c - l * h * c - p * s * f + a * h * f + l * s * g - a * d * g, y = l * m * c - p * u * c + p * o * f - a * m * f - l * o * g + a * u * g, b = p * u * s - l * m * s - p * o * d + a * m * d + l * o * h - a * u * h, x = t * _ + n * v + r * y + i * b;
13230
- if (x === 0) return Kf();
13197
+ if (x === 0) return Jf();
13231
13198
  let S = 1 / x;
13232
13199
  return [
13233
13200
  _ * S,
@@ -13250,7 +13217,7 @@ function tp(e) {
13250
13217
  }
13251
13218
  //#endregion
13252
13219
  //#region src/Processor/PBRT/PBRTParser.js
13253
- var np = class {
13220
+ var ip = class {
13254
13221
  constructor(e = {}) {
13255
13222
  this.resolveInclude = e.resolveInclude || (() => {
13256
13223
  throw Error("PBRTParser: Include used but no resolveInclude provided");
@@ -13264,14 +13231,14 @@ var np = class {
13264
13231
  instances: [],
13265
13232
  objects: /* @__PURE__ */ new Map(),
13266
13233
  warnings: []
13267
- }, this.ctm = Kf(), this.state = {
13234
+ }, this.ctm = Jf(), this.state = {
13268
13235
  material: null,
13269
13236
  areaLight: null,
13270
13237
  reverseOrientation: !1
13271
13238
  }, this.attributeStack = [], this.transformStack = [], this.coordSystems = /* @__PURE__ */ new Map(), this.currentObject = null, this.objectBeginCTM = null, this.dirStack = [""], this.tokens = [], this.pos = 0, this._warnedUnknown = /* @__PURE__ */ new Set();
13272
13239
  }
13273
13240
  parse(e, t = "") {
13274
- return this.dirStack = [t], this._run(Gf(e)), this.ir;
13241
+ return this.dirStack = [t], this._run(qf(e)), this.ir;
13275
13242
  }
13276
13243
  _peek() {
13277
13244
  return this.tokens[this.pos];
@@ -13281,12 +13248,12 @@ var np = class {
13281
13248
  }
13282
13249
  _expectNumber(e) {
13283
13250
  let t = this._next();
13284
- if (!t || t.type !== Vf.NUMBER) throw Error(`PBRT parser: expected number for ${e}, got ${t ? t.value : "EOF"}`);
13251
+ if (!t || t.type !== Uf.NUMBER) throw Error(`PBRT parser: expected number for ${e}, got ${t ? t.value : "EOF"}`);
13285
13252
  return t.value;
13286
13253
  }
13287
13254
  _expectString(e) {
13288
13255
  let t = this._next();
13289
- if (!t || t.type !== Vf.STRING) throw Error(`PBRT parser: expected string for ${e}, got ${t ? t.value : "EOF"}`);
13256
+ if (!t || t.type !== Uf.STRING) throw Error(`PBRT parser: expected string for ${e}, got ${t ? t.value : "EOF"}`);
13290
13257
  return t.value;
13291
13258
  }
13292
13259
  _readNumbers(e) {
@@ -13295,17 +13262,17 @@ var np = class {
13295
13262
  return t;
13296
13263
  }
13297
13264
  _readBracketedOrBareNumbers(e) {
13298
- if (this._peek() && this._peek().type === Vf.LBRACKET) {
13265
+ if (this._peek() && this._peek().type === Uf.LBRACKET) {
13299
13266
  this._next();
13300
13267
  let e = [];
13301
- for (; this._peek() && this._peek().type !== Vf.RBRACKET;) e.push(this._expectNumber("transform element"));
13268
+ for (; this._peek() && this._peek().type !== Uf.RBRACKET;) e.push(this._expectNumber("transform element"));
13302
13269
  return this._next(), e;
13303
13270
  }
13304
13271
  return this._readNumbers(e);
13305
13272
  }
13306
13273
  _parseParams() {
13307
13274
  let e = {};
13308
- for (; this._peek() && this._peek().type === Vf.STRING;) {
13275
+ for (; this._peek() && this._peek().type === Uf.STRING;) {
13309
13276
  let t = this._next().value.trim().split(/\s+/), n = t[0], r = t[1] === void 0 ? t[0] : t[1];
13310
13277
  e[r] = {
13311
13278
  type: n,
@@ -13316,23 +13283,23 @@ var np = class {
13316
13283
  }
13317
13284
  _parseParamValue() {
13318
13285
  let e = [];
13319
- if (this._peek() && this._peek().type === Vf.LBRACKET) {
13320
- for (this._next(); this._peek() && this._peek().type !== Vf.RBRACKET;) e.push(this._coerceValueToken(this._next()));
13286
+ if (this._peek() && this._peek().type === Uf.LBRACKET) {
13287
+ for (this._next(); this._peek() && this._peek().type !== Uf.RBRACKET;) e.push(this._coerceValueToken(this._next()));
13321
13288
  this._next();
13322
13289
  } else e.push(this._coerceValueToken(this._next()));
13323
13290
  return e;
13324
13291
  }
13325
13292
  _coerceValueToken(e) {
13326
13293
  if (!e) throw Error("PBRT parser: unexpected EOF in parameter value");
13327
- if (e.type === Vf.NUMBER || e.type === Vf.STRING) return e.value;
13328
- if (e.type === Vf.WORD) return e.value === "true" ? !0 : e.value === "false" ? !1 : e.value;
13294
+ if (e.type === Uf.NUMBER || e.type === Uf.STRING) return e.value;
13295
+ if (e.type === Uf.WORD) return e.value === "true" ? !0 : e.value === "false" ? !1 : e.value;
13329
13296
  throw Error(`PBRT parser: unexpected token in parameter value: ${e.type}`);
13330
13297
  }
13331
13298
  _run(e) {
13332
13299
  let t = this.tokens, n = this.pos;
13333
13300
  for (this.tokens = e, this.pos = 0; this.pos < this.tokens.length;) {
13334
13301
  let e = this._next();
13335
- if (e.type !== Vf.WORD) throw Error(`PBRT parser: expected directive, got ${e.type} ${e.value ?? ""}`);
13302
+ if (e.type !== Uf.WORD) throw Error(`PBRT parser: expected directive, got ${e.type} ${e.value ?? ""}`);
13336
13303
  this._directive(e.value);
13337
13304
  }
13338
13305
  this.tokens = t, this.pos = n;
@@ -13340,25 +13307,25 @@ var np = class {
13340
13307
  _directive(e) {
13341
13308
  switch (e) {
13342
13309
  case "Identity":
13343
- this.ctm = Kf();
13310
+ this.ctm = Jf();
13344
13311
  break;
13345
13312
  case "Translate": {
13346
13313
  let [e, t, n] = this._readNumbers(3);
13347
- this.ctm = qf(this.ctm, Jf(e, t, n));
13314
+ this.ctm = Yf(this.ctm, Xf(e, t, n));
13348
13315
  break;
13349
13316
  }
13350
13317
  case "Scale": {
13351
13318
  let [e, t, n] = this._readNumbers(3);
13352
- this.ctm = qf(this.ctm, Yf(e, t, n));
13319
+ this.ctm = Yf(this.ctm, Zf(e, t, n));
13353
13320
  break;
13354
13321
  }
13355
13322
  case "Rotate": {
13356
13323
  let [e, t, n, r] = this._readNumbers(4);
13357
- this.ctm = qf(this.ctm, Xf(e, t, n, r));
13324
+ this.ctm = Yf(this.ctm, Qf(e, t, n, r));
13358
13325
  break;
13359
13326
  }
13360
13327
  case "LookAt": {
13361
- let e = this._readNumbers(9), t = ep([
13328
+ let e = this._readNumbers(9), t = np([
13362
13329
  e[0],
13363
13330
  e[1],
13364
13331
  e[2]
@@ -13371,7 +13338,7 @@ var np = class {
13371
13338
  e[7],
13372
13339
  e[8]
13373
13340
  ]);
13374
- this.ctm = qf(this.ctm, tp(t));
13341
+ this.ctm = Yf(this.ctm, rp(t));
13375
13342
  break;
13376
13343
  }
13377
13344
  case "Transform":
@@ -13379,7 +13346,7 @@ var np = class {
13379
13346
  break;
13380
13347
  case "ConcatTransform": {
13381
13348
  let e = this._readBracketedOrBareNumbers(16);
13382
- this.ctm = qf(this.ctm, e);
13349
+ this.ctm = Yf(this.ctm, e);
13383
13350
  break;
13384
13351
  }
13385
13352
  case "CoordinateSystem":
@@ -13395,7 +13362,7 @@ var np = class {
13395
13362
  this.ir.camera = {
13396
13363
  type: e,
13397
13364
  params: t,
13398
- cameraToWorld: tp(this.ctm)
13365
+ cameraToWorld: rp(this.ctm)
13399
13366
  };
13400
13367
  break;
13401
13368
  }
@@ -13419,7 +13386,7 @@ var np = class {
13419
13386
  this._skipTypeAndParams();
13420
13387
  break;
13421
13388
  case "WorldBegin":
13422
- this.ctm = Kf(), this.state = {
13389
+ this.ctm = Jf(), this.state = {
13423
13390
  material: null,
13424
13391
  areaLight: null,
13425
13392
  reverseOrientation: !1
@@ -13464,7 +13431,7 @@ var np = class {
13464
13431
  this._readNumbers(2);
13465
13432
  break;
13466
13433
  case "MediumInterface":
13467
- this._peek() && this._peek().type === Vf.STRING && this._next(), this._peek() && this._peek().type === Vf.STRING && this._next();
13434
+ this._peek() && this._peek().type === Uf.STRING && this._next(), this._peek() && this._peek().type === Uf.STRING && this._next();
13468
13435
  break;
13469
13436
  case "MakeNamedMedium":
13470
13437
  this._skipNamedAndParams();
@@ -13572,7 +13539,7 @@ var np = class {
13572
13539
  }
13573
13540
  }
13574
13541
  _emitShape(e) {
13575
- this.currentObject === null ? this.ir.shapes.push(e) : (e.relativeCTM = qf(tp(this.objectBeginCTM), e.ctm), this.ir.objects.get(this.currentObject).push(e));
13542
+ this.currentObject === null ? this.ir.shapes.push(e) : (e.relativeCTM = Yf(rp(this.objectBeginCTM), e.ctm), this.ir.objects.get(this.currentObject).push(e));
13576
13543
  }
13577
13544
  _include(e) {
13578
13545
  let t = this.resolveInclude(e, this.dirStack[this.dirStack.length - 1]);
@@ -13581,13 +13548,13 @@ var np = class {
13581
13548
  return;
13582
13549
  }
13583
13550
  let n = e.includes("/") ? e.slice(0, e.lastIndexOf("/")) : "";
13584
- this.dirStack.push(n), this._run(Gf(t)), this.dirStack.pop();
13551
+ this.dirStack.push(n), this._run(qf(t)), this.dirStack.pop();
13585
13552
  }
13586
13553
  _skipTypeAndParams() {
13587
- this._peek() && this._peek().type === Vf.STRING && this._next(), this._parseParams();
13554
+ this._peek() && this._peek().type === Uf.STRING && this._next(), this._parseParams();
13588
13555
  }
13589
13556
  _skipNamedAndParams() {
13590
- this._peek() && this._peek().type === Vf.STRING && this._next(), this._parseParams();
13557
+ this._peek() && this._peek().type === Uf.STRING && this._next(), this._parseParams();
13591
13558
  }
13592
13559
  _num(e, t) {
13593
13560
  return e && e.value.length ? e.value[0] : t;
@@ -13601,7 +13568,7 @@ var np = class {
13601
13568
  _warnUnknown(e) {
13602
13569
  this._warnedUnknown.has(e) || (this._warnedUnknown.add(e), this._warn(`Unsupported directive ignored: ${e}`));
13603
13570
  }
13604
- }, rp = {
13571
+ }, ap = {
13605
13572
  au: [
13606
13573
  1,
13607
13574
  .78,
@@ -13657,12 +13624,12 @@ var np = class {
13657
13624
  .9,
13658
13625
  .9
13659
13626
  ]
13660
- }, ip = [
13627
+ }, op = [
13661
13628
  .92,
13662
13629
  .92,
13663
13630
  .92
13664
13631
  ];
13665
- function ap(e) {
13632
+ function sp(e) {
13666
13633
  let t = Math.max(1e3, Math.min(4e4, e)) / 100, n, r, i;
13667
13634
  t <= 66 ? (n = 255, r = 99.47 * Math.log(t) - 161.12) : (n = 329.7 * (t - 60) ** -.1332, r = 288.12 * (t - 60) ** -.0755), i = t >= 66 ? 255 : t <= 19 ? 0 : 138.52 * Math.log(t - 10) - 305.04;
13668
13635
  let a = (e) => Math.max(0, Math.min(255, e)) / 255;
@@ -13672,15 +13639,15 @@ function ap(e) {
13672
13639
  a(i) ** 2.2
13673
13640
  ];
13674
13641
  }
13675
- function op(e, t, n) {
13642
+ function cp(e, t, n) {
13676
13643
  let r = e[t];
13677
13644
  return r && typeof r.value[0] == "number" ? r.value[0] : n;
13678
13645
  }
13679
- function sp(e, t, n) {
13646
+ function lp(e, t, n) {
13680
13647
  let r = e[t];
13681
13648
  return r && typeof r.value[0] == "string" ? r.value[0] : n;
13682
13649
  }
13683
- async function cp(e, t, n, r = null) {
13650
+ async function up(e, t, n, r = null) {
13684
13651
  let i = e[t];
13685
13652
  if (!i) return {
13686
13653
  rgb: r,
@@ -13719,14 +13686,14 @@ async function cp(e, t, n, r = null) {
13719
13686
  };
13720
13687
  }
13721
13688
  if (i.type === "blackbody") return {
13722
- rgb: ap(i.value[0]),
13689
+ rgb: sp(i.value[0]),
13723
13690
  texture: null
13724
13691
  };
13725
13692
  if (i.type === "spectrum") {
13726
13693
  if (typeof i.value[0] == "string") {
13727
- let e = lp(i.value[0]);
13728
- return e && rp[e] ? {
13729
- rgb: rp[e].slice(),
13694
+ let e = dp(i.value[0]);
13695
+ return e && ap[e] ? {
13696
+ rgb: ap[e].slice(),
13730
13697
  texture: null
13731
13698
  } : (n.warn(`named spectrum "${i.value[0]}" approximated to gray`), {
13732
13699
  rgb: [
@@ -13754,18 +13721,18 @@ async function cp(e, t, n, r = null) {
13754
13721
  texture: null
13755
13722
  };
13756
13723
  }
13757
- function lp(e) {
13724
+ function dp(e) {
13758
13725
  let t = e.toLowerCase().match(/metal-([a-z]+)/);
13759
13726
  if (t) return t[1];
13760
- for (let t of Object.keys(rp)) if (e.toLowerCase().includes(t)) return t;
13727
+ for (let t of Object.keys(ap)) if (e.toLowerCase().includes(t)) return t;
13761
13728
  return null;
13762
13729
  }
13763
- function up(e, t) {
13730
+ function fp(e, t) {
13764
13731
  if (e.roughness && typeof e.roughness.value[0] == "number") return e.roughness.value[0];
13765
- let n = op(e, "uroughness", null), r = op(e, "vroughness", null);
13732
+ let n = cp(e, "uroughness", null), r = cp(e, "vroughness", null);
13766
13733
  return n !== null && r !== null ? (n + r) / 2 : n === null ? t : n;
13767
13734
  }
13768
- async function dp(e, t) {
13735
+ async function pp(e, t) {
13769
13736
  let n = e?.type || "diffuse", r = e?.params || {}, i = new Et({
13770
13737
  side: ct,
13771
13738
  roughness: 1,
@@ -13777,7 +13744,7 @@ async function dp(e, t) {
13777
13744
  };
13778
13745
  switch (n) {
13779
13746
  case "diffuse":
13780
- o(await cp(r, "reflectance", t, [
13747
+ o(await up(r, "reflectance", t, [
13781
13748
  .5,
13782
13749
  .5,
13783
13750
  .5
@@ -13785,14 +13752,14 @@ async function dp(e, t) {
13785
13752
  break;
13786
13753
  case "conductor":
13787
13754
  case "metal": {
13788
- let e = await cp(r, "reflectance", t, null), n = r.eta, s = r.k, c = n && n.type === "spectrum" && typeof n.value[0] == "string";
13755
+ let e = await up(r, "reflectance", t, null), n = r.eta, s = r.k, c = n && n.type === "spectrum" && typeof n.value[0] == "string";
13789
13756
  if (e.rgb || e.texture) o(e);
13790
13757
  else if (n && s && !c) {
13791
- let e = (await cp(r, "eta", t, [
13758
+ let e = (await up(r, "eta", t, [
13792
13759
  .2,
13793
13760
  .92,
13794
13761
  1.1
13795
- ])).rgb, n = (await cp(r, "k", t, [
13762
+ ])).rgb, n = (await up(r, "k", t, [
13796
13763
  3.9,
13797
13764
  2.45,
13798
13765
  2.14
@@ -13802,28 +13769,28 @@ async function dp(e, t) {
13802
13769
  i(e[1], n[1]),
13803
13770
  i(e[2], n[2])
13804
13771
  ]);
13805
- } else a(n ? (await cp(r, "eta", t, ip)).rgb || ip : rp.cu);
13806
- i.metalness = 1, i.roughness = up(r, .1);
13772
+ } else a(n ? (await up(r, "eta", t, op)).rgb || op : ap.cu);
13773
+ i.metalness = 1, i.roughness = fp(r, .1);
13807
13774
  break;
13808
13775
  }
13809
13776
  case "dielectric":
13810
13777
  case "thindielectric":
13811
- i.transmission = 1, i.metalness = 0, i.color.setRGB(1, 1, 1), i.ior = op(r, "eta", 1.5), i.roughness = up(r, 0), i.thickness = n === "thindielectric" ? 0 : op(r, "thickness", 0);
13778
+ i.transmission = 1, i.metalness = 0, i.color.setRGB(1, 1, 1), i.ior = cp(r, "eta", 1.5), i.roughness = fp(r, 0), i.thickness = n === "thindielectric" ? 0 : cp(r, "thickness", 0);
13812
13779
  break;
13813
13780
  case "coateddiffuse":
13814
- o(await cp(r, "reflectance", t, [
13781
+ o(await up(r, "reflectance", t, [
13815
13782
  .5,
13816
13783
  .5,
13817
13784
  .5
13818
- ])), i.roughness = .6, i.metalness = 0, i.clearcoat = 1, i.clearcoatRoughness = up(r, 0);
13785
+ ])), i.roughness = .6, i.metalness = 0, i.clearcoat = 1, i.clearcoatRoughness = fp(r, 0);
13819
13786
  break;
13820
13787
  case "diffusetransmission": {
13821
- let e = await cp(r, "transmittance", t, [
13788
+ let e = await up(r, "transmittance", t, [
13822
13789
  .25,
13823
13790
  .25,
13824
13791
  .25
13825
13792
  ]);
13826
- o(await cp(r, "reflectance", t, [
13793
+ o(await up(r, "reflectance", t, [
13827
13794
  .25,
13828
13795
  .25,
13829
13796
  .25
@@ -13836,9 +13803,9 @@ async function dp(e, t) {
13836
13803
  i.transmission = 1, i.ior = 1, i.roughness = 0, i.color.setRGB(1, 1, 1);
13837
13804
  break;
13838
13805
  case "mix": {
13839
- let e = r.materials?.value || [], n = Math.max(0, Math.min(1, op(r, "amount", .5))), a = e[0] ? t.namedMaterials?.get(e[0]) : null, o = e[1] ? t.namedMaterials?.get(e[1]) : null;
13806
+ let e = r.materials?.value || [], n = Math.max(0, Math.min(1, cp(r, "amount", .5))), a = e[0] ? t.namedMaterials?.get(e[0]) : null, o = e[1] ? t.namedMaterials?.get(e[1]) : null;
13840
13807
  if (a && o) {
13841
- let [e, r] = await Promise.all([dp(a, t), dp(o, t)]), s = (e, t) => e * (1 - n) + t * n;
13808
+ let [e, r] = await Promise.all([pp(a, t), pp(o, t)]), s = (e, t) => e * (1 - n) + t * n;
13842
13809
  i.color.lerpColors(e.color, r.color, n), i.roughness = s(e.roughness, r.roughness), i.metalness = s(e.metalness, r.metalness), i.ior = s(e.ior ?? 1.5, r.ior ?? 1.5), i.transmission = s(e.transmission ?? 0, r.transmission ?? 0), i.thickness = s(e.thickness ?? 0, r.thickness ?? 0), i.clearcoat = s(e.clearcoat ?? 0, r.clearcoat ?? 0), i.clearcoatRoughness = s(e.clearcoatRoughness ?? 0, r.clearcoatRoughness ?? 0), i.emissive.lerpColors(e.emissive, r.emissive, n), i.emissiveIntensity = s(e.emissiveIntensity ?? 0, r.emissiveIntensity ?? 0), i.map = (n < .5 ? e.map : r.map) || null;
13843
13810
  break;
13844
13811
  }
@@ -13848,7 +13815,7 @@ async function dp(e, t) {
13848
13815
  case "subsurface":
13849
13816
  case "hair":
13850
13817
  case "measured":
13851
- t.warn(`material "${n}" not supported — using diffuse approximation`), a((await cp(r, "reflectance", t, [
13818
+ t.warn(`material "${n}" not supported — using diffuse approximation`), a((await up(r, "reflectance", t, [
13852
13819
  .5,
13853
13820
  .5,
13854
13821
  .5
@@ -13862,7 +13829,7 @@ async function dp(e, t) {
13862
13829
  }
13863
13830
  //#endregion
13864
13831
  //#region src/Processor/PBRT/PBRTSceneBuilder.js
13865
- var fp = [
13832
+ var mp = [
13866
13833
  1,
13867
13834
  0,
13868
13835
  0,
@@ -13879,7 +13846,7 @@ var fp = [
13879
13846
  0,
13880
13847
  0,
13881
13848
  1
13882
- ], pp = class {
13849
+ ], hp = class {
13883
13850
  constructor(e = {}) {
13884
13851
  this.resolvePLY = e.resolvePLY || (async () => null), this.resolveImage = e.resolveImage || (async () => null), this.resolveEnvironment = e.resolveEnvironment || e.resolveImage || (async () => null), this.convertHandedness = e.convertHandedness === !0, this.warnings = [], this.report = [], this._materialCache = /* @__PURE__ */ new Map(), this._textureCache = /* @__PURE__ */ new Map();
13885
13852
  }
@@ -13915,7 +13882,7 @@ var fp = [
13915
13882
  continue;
13916
13883
  }
13917
13884
  for (let e of i) {
13918
- let i = qf(r.ctm, e.relativeCTM || e.ctm), a = await this._buildShapeMesh(e, i, `instance_${n++}`);
13885
+ let i = Yf(r.ctm, e.relativeCTM || e.ctm), a = await this._buildShapeMesh(e, i, `instance_${n++}`);
13919
13886
  a && t.add(a);
13920
13887
  }
13921
13888
  }
@@ -13927,7 +13894,7 @@ var fp = [
13927
13894
  i.map && !a && (this.warn(`${n} (${e.type}, "${e.material?.type || "diffuse"}") has a texture map but no UVs — dropping map, using base color`), o = i.clone(), o.map = null);
13928
13895
  let s = new wt(r, o);
13929
13896
  s.name = n;
13930
- let c = this.convertHandedness ? qf(fp, t) : t;
13897
+ let c = this.convertHandedness ? Yf(mp, t) : t;
13931
13898
  new Ct().fromArray(c).decompose(s.position, s.quaternion, s.scale), s.updateMatrix(), r.computeBoundingBox();
13932
13899
  let l = r.boundingBox ? r.boundingBox.clone().applyMatrix4(s.matrix).getSize(new cn()) : new cn();
13933
13900
  return this.report.push({
@@ -13982,7 +13949,7 @@ var fp = [
13982
13949
  return i.setAttribute("position", new dt(Float32Array.from(t), 3)), i.setIndex(r), i.computeVertexNormals(), i;
13983
13950
  }
13984
13951
  async _plyMesh(e) {
13985
- let t = sp(e, "filename", null);
13952
+ let t = lp(e, "filename", null);
13986
13953
  if (!t) return this.warn("plymesh missing filename"), null;
13987
13954
  try {
13988
13955
  let e = await this.resolvePLY(t);
@@ -13992,10 +13959,10 @@ var fp = [
13992
13959
  }
13993
13960
  }
13994
13961
  _sphere(e) {
13995
- return new Zt(op(e, "radius", 1), 48, 32);
13962
+ return new Zt(cp(e, "radius", 1), 48, 32);
13996
13963
  }
13997
13964
  _disk(e) {
13998
- let t = op(e, "radius", 1), n = op(e, "innerradius", 0), r = op(e, "height", 0), i = [], a = [];
13965
+ let t = cp(e, "radius", 1), n = cp(e, "innerradius", 0), r = cp(e, "height", 0), i = [], a = [];
13999
13966
  for (let e = 0; e < 48; e++) {
14000
13967
  let o = e / 48 * Math.PI * 2, s = (e + 1) / 48 * Math.PI * 2, c = i.length / 3;
14001
13968
  i.push(Math.cos(o) * n, Math.sin(o) * n, r), i.push(Math.cos(o) * t, Math.sin(o) * t, r), i.push(Math.cos(s) * t, Math.sin(s) * t, r), i.push(Math.cos(s) * n, Math.sin(s) * n, r), a.push(c, c + 1, c + 2, c, c + 2, c + 3);
@@ -14010,15 +13977,15 @@ var fp = [
14010
13977
  resolveNamedTexture: (e) => this._resolveNamedTexture(e),
14011
13978
  namedMaterials: this.ir.namedMaterials,
14012
13979
  warn: (e) => this.warn(e)
14013
- }, r = await dp(e.material, n);
13980
+ }, r = await pp(e.material, n);
14014
13981
  return e.areaLight && await this._applyAreaLight(r, e.areaLight, n), t.set(e.areaLight, r), r;
14015
13982
  }
14016
13983
  async _applyAreaLight(e, t, n) {
14017
- let r = await cp(t.params, "L", n, [
13984
+ let r = await up(t.params, "L", n, [
14018
13985
  1,
14019
13986
  1,
14020
13987
  1
14021
- ]), i = op(t.params, "scale", 1), a = r.rgb || [
13988
+ ]), i = cp(t.params, "scale", 1), a = r.rgb || [
14022
13989
  1,
14023
13990
  1,
14024
13991
  1
@@ -14030,7 +13997,7 @@ var fp = [
14030
13997
  let t = this.ir.namedTextures.get(e), n = null;
14031
13998
  if (!t) this.warn(`named texture "${e}" not defined`);
14032
13999
  else if (t.class === "imagemap") {
14033
- let r = sp(t.params, "filename", null);
14000
+ let r = lp(t.params, "filename", null);
14034
14001
  if (r) try {
14035
14002
  let t = await this.resolveImage(r);
14036
14003
  t ? n = { texture: t } : this.warn(`image not found for texture "${e}": ${r}`);
@@ -14118,7 +14085,7 @@ var fp = [
14118
14085
  return c.name = "PBRT Camera", c.up.copy(a.normalize()), c.position.copy(r), c.lookAt(o), c.updateMatrixWorld(!0), c;
14119
14086
  }
14120
14087
  _verticalFov(e, t) {
14121
- let n = op(e, "fov", 90);
14088
+ let n = cp(e, "fov", 90);
14122
14089
  if (t >= 1) return n;
14123
14090
  let r = n * Math.PI / 180;
14124
14091
  return 2 * Math.atan(Math.tan(r / 2) / t) * 180 / Math.PI;
@@ -14126,7 +14093,7 @@ var fp = [
14126
14093
  async _buildEnvironment(e) {
14127
14094
  let t = e.find((e) => e.type === "infinite");
14128
14095
  if (!t) return null;
14129
- let n = op(t.params, "scale", 1), r = sp(t.params, "filename", null);
14096
+ let n = cp(t.params, "scale", 1), r = lp(t.params, "filename", null);
14130
14097
  if (r) try {
14131
14098
  let e = await this.resolveEnvironment(r);
14132
14099
  if (e) return e.mapping = lt, { texture: e };
@@ -14134,7 +14101,7 @@ var fp = [
14134
14101
  } catch (e) {
14135
14102
  this.warn(`failed to load infinite-light image ${r}: ${e.message}`);
14136
14103
  }
14137
- let i = ((await cp(t.params, "L", {
14104
+ let i = ((await up(t.params, "L", {
14138
14105
  resolveNamedTexture: async () => null,
14139
14106
  warn: (e) => this.warn(e)
14140
14107
  }, [
@@ -14153,20 +14120,20 @@ var fp = [
14153
14120
  _reportUnsupportedLights(e) {
14154
14121
  for (let t of e) t.type !== "infinite" && this.warn(`light "${t.type}" not supported (only infinite lights and emissive area lights are mapped)`);
14155
14122
  }
14156
- }, mp = new TextDecoder();
14157
- function hp(e) {
14123
+ }, gp = new TextDecoder();
14124
+ function _p(e) {
14158
14125
  let t = e.replace(/\\/g, "/").split("/"), n = [];
14159
14126
  for (let e of t) e === "" || e === "." || (e === ".." ? n.pop() : n.push(e));
14160
14127
  return n.join("/");
14161
14128
  }
14162
- function gp(e, t) {
14163
- return !e || t.startsWith("/") ? hp(t) : hp(`${e}/${t}`);
14129
+ function vp(e, t) {
14130
+ return !e || t.startsWith("/") ? _p(t) : _p(`${e}/${t}`);
14164
14131
  }
14165
- var _p = class {
14132
+ var yp = class {
14166
14133
  constructor(e) {
14167
14134
  this.byPath = /* @__PURE__ */ new Map(), this.byBase = /* @__PURE__ */ new Map();
14168
14135
  for (let t in e) {
14169
- let n = hp(t).toLowerCase(), r = {
14136
+ let n = _p(t).toLowerCase(), r = {
14170
14137
  norm: n,
14171
14138
  bytes: e[t]
14172
14139
  };
@@ -14176,13 +14143,13 @@ var _p = class {
14176
14143
  }
14177
14144
  }
14178
14145
  find(e) {
14179
- let t = hp(e).toLowerCase();
14146
+ let t = _p(e).toLowerCase();
14180
14147
  if (this.byPath.has(t)) return this.byPath.get(t).bytes;
14181
14148
  let n = this.byBase.get(t.split("/").pop());
14182
14149
  return n ? (n.find((e) => e.norm.endsWith("/" + t)) || n[0]).bytes : null;
14183
14150
  }
14184
14151
  };
14185
- function vp(e) {
14152
+ function bp(e) {
14186
14153
  let t = Object.keys(e).filter((e) => e.toLowerCase().endsWith(".pbrt"));
14187
14154
  if (t.length === 0) return null;
14188
14155
  let n = t.filter((e) => /(^|\/)(scene|main)\.pbrt$/i.test(e)), r = n.length ? n : t;
@@ -14191,17 +14158,17 @@ function vp(e) {
14191
14158
  return n === r ? e.length - t.length : n - r;
14192
14159
  }), r[0];
14193
14160
  }
14194
- async function yp(e) {
14195
- let { vfs: t, plyParser: n, imageFromBytes: r, envFromBytes: i, convertHandedness: a } = e, o = new _p(t), s = e.entryPath || vp(t);
14161
+ async function xp(e) {
14162
+ let { vfs: t, plyParser: n, imageFromBytes: r, envFromBytes: i, convertHandedness: a } = e, o = new yp(t), s = e.entryPath || bp(t);
14196
14163
  if (!s) throw Error("PBRT loader: no .pbrt file found in archive");
14197
14164
  let c = o.find(s);
14198
14165
  if (!c) throw Error(`PBRT loader: entry "${s}" not readable`);
14199
- let l = s.includes("/") ? s.slice(0, s.lastIndexOf("/")) : "", u = new np({ resolveInclude: (e, t) => {
14200
- let n = o.find(gp(t, e)) || o.find(e);
14201
- return n ? mp.decode(n) : null;
14202
- } }).parse(mp.decode(c), l), d = (e) => e.buffer.slice(e.byteOffset, e.byteOffset + e.byteLength);
14166
+ let l = s.includes("/") ? s.slice(0, s.lastIndexOf("/")) : "", u = new ip({ resolveInclude: (e, t) => {
14167
+ let n = o.find(vp(t, e)) || o.find(e);
14168
+ return n ? gp.decode(n) : null;
14169
+ } }).parse(gp.decode(c), l), d = (e) => e.buffer.slice(e.byteOffset, e.byteOffset + e.byteLength);
14203
14170
  return {
14204
- ...await new pp({
14171
+ ...await new hp({
14205
14172
  convertHandedness: a,
14206
14173
  resolvePLY: async (e) => {
14207
14174
  let t = o.find(e);
@@ -14221,7 +14188,7 @@ async function yp(e) {
14221
14188
  }
14222
14189
  //#endregion
14223
14190
  //#region src/Processor/AssetLoader.js
14224
- var bp = {
14191
+ var Sp = {
14225
14192
  glb: {
14226
14193
  type: "model",
14227
14194
  name: "GLB (GLTF Binary)"
@@ -14286,7 +14253,7 @@ var bp = {
14286
14253
  type: "archive",
14287
14254
  name: "ZIP Archive"
14288
14255
  }
14289
- }, xp = class e extends ut {
14256
+ }, Cp = class e extends ut {
14290
14257
  constructor(e, t, n) {
14291
14258
  super(), this.scene = e, this.camera = t, this.controls = n, this.targetModel = null, this._externalModel = null, this.floorPlane = null, this.sceneScale = 1, this.loaderCache = {}, this.uploadedFileInfo = null, this.animations = [], this.renderer = null, this._loadingManager = new vt(), this._loadCancelled = !1;
14292
14259
  }
@@ -14332,7 +14299,7 @@ var bp = {
14332
14299
  this.renderer = e;
14333
14300
  }
14334
14301
  getFileFormat(e) {
14335
- return bp[e.split(".").pop().toLowerCase()] || null;
14302
+ return Sp[e.split(".").pop().toLowerCase()] || null;
14336
14303
  }
14337
14304
  readFileAsArrayBuffer(e) {
14338
14305
  return new Promise((t, n) => {
@@ -14467,7 +14434,7 @@ var bp = {
14467
14434
  async loadArchiveFromFile(e, t) {
14468
14435
  try {
14469
14436
  let n = await this.readFileAsArrayBuffer(e), r = yn(new Uint8Array(n));
14470
- return vp(r) ? await this.loadPBRTFromZip(r, t) : await this.processObjMtlPairsInZip(r, t) || await this.findAndLoadModelFromZip(r, t);
14437
+ return bp(r) ? await this.loadPBRTFromZip(r, t) : await this.processObjMtlPairsInZip(r, t) || await this.findAndLoadModelFromZip(r, t);
14471
14438
  } catch (e) {
14472
14439
  throw console.error("Error loading ZIP archive:", e), e;
14473
14440
  }
@@ -14481,7 +14448,7 @@ var bp = {
14481
14448
  let { PLYLoader: e } = await import("three/examples/jsm/loaders/PLYLoader.js");
14482
14449
  this.loaderCache.ply = new e();
14483
14450
  }
14484
- let { group: n, environment: r, report: i, warnings: a, entryPath: o } = await yp({
14451
+ let { group: n, environment: r, report: i, warnings: a, entryPath: o } = await xp({
14485
14452
  vfs: e,
14486
14453
  plyParser: (e) => this.loaderCache.ply.parse(e),
14487
14454
  imageFromBytes: (e, t) => this._pbrtTextureFromBytes(e, t),
@@ -14580,7 +14547,7 @@ var bp = {
14580
14547
  }
14581
14548
  for (let t in e) {
14582
14549
  let n = t.split(".").pop().toLowerCase();
14583
- if (bp[n] && bp[n].type === "model") return console.log(`Loading model file from ZIP: ${t}`), await this.loadModelFromZipEntry(e[t], t, n, e);
14550
+ if (Sp[n] && Sp[n].type === "model") return console.log(`Loading model file from ZIP: ${t}`), await this.loadModelFromZipEntry(e[t], t, n, e);
14584
14551
  }
14585
14552
  throw Error("No supported model files found in the ZIP archive");
14586
14553
  }
@@ -15140,10 +15107,10 @@ var bp = {
15140
15107
  getSupportedFormats(e = null) {
15141
15108
  if (e) {
15142
15109
  let t = {};
15143
- for (let [n, r] of Object.entries(bp)) r.type === e && (t[n] = r);
15110
+ for (let [n, r] of Object.entries(Sp)) r.type === e && (t[n] = r);
15144
15111
  return t;
15145
15112
  }
15146
- return bp;
15113
+ return Sp;
15147
15114
  }
15148
15115
  dispose() {
15149
15116
  for (let e in this.loaderCache) {
@@ -15155,7 +15122,7 @@ var bp = {
15155
15122
  removeAllEventListeners() {
15156
15123
  this._listeners = void 0;
15157
15124
  }
15158
- }, Sp = {
15125
+ }, wp = {
15159
15126
  maxBounces: {
15160
15127
  uniform: "maxBounces",
15161
15128
  reset: !0
@@ -15224,6 +15191,10 @@ var bp = {
15224
15191
  uniform: "globalIlluminationIntensity",
15225
15192
  reset: !0
15226
15193
  },
15194
+ panoramaLevelHorizon: {
15195
+ uniform: "panoLevelHorizon",
15196
+ reset: !0
15197
+ },
15227
15198
  enableDOF: {
15228
15199
  uniform: "enableDOF",
15229
15200
  reset: !0
@@ -15304,6 +15275,18 @@ var bp = {
15304
15275
  uniform: "debugVisScale",
15305
15276
  reset: !0
15306
15277
  },
15278
+ cameraProjection: {
15279
+ handler: "handleCameraProjection",
15280
+ reset: !0
15281
+ },
15282
+ panoramaLonRange: {
15283
+ handler: "handlePanoramaLonRange",
15284
+ reset: !0
15285
+ },
15286
+ panoramaLatRange: {
15287
+ handler: "handlePanoramaLatRange",
15288
+ reset: !0
15289
+ },
15307
15290
  interactionModeEnabled: {
15308
15291
  handler: "handleInteractionModeEnabled",
15309
15292
  reset: !1
@@ -15326,18 +15309,27 @@ var bp = {
15326
15309
  },
15327
15310
  renderMode: { handler: "handleRenderMode" },
15328
15311
  environmentRotation: { handler: "handleEnvironmentRotation" }
15329
- }, Cp = {
15312
+ }, Tp = {
15330
15313
  bounces: "maxBounces",
15331
15314
  debugMode: "visMode"
15332
- }, wp = class extends ut {
15315
+ }, Ep = class extends ut {
15333
15316
  constructor(e = J) {
15334
15317
  super(), this._values = /* @__PURE__ */ new Map(), this._pathTracer = null, this._resetCallback = null, this._handlers = {}, this._delegates = {}, this._initDefaults(e);
15335
15318
  }
15336
- bind({ stages: e, renderer: t, resetCallback: n, reconcileCompletion: r }) {
15337
- this._pathTracer = e.pathTracer, this._resetCallback = n, this._delegates = {}, this._handlers = this._buildHandlers(e, t, r);
15319
+ bind(e) {
15320
+ this._pathTracer = e.stages.pathTracer, this._resetCallback = e.resetCallback, this._delegates = {}, this._handlers = this._buildHandlers(e);
15338
15321
  }
15339
- _buildHandlers(e, t, n) {
15322
+ _buildHandlers({ stages: e, renderer: t, reconcileCompletion: n, denoisingManager: r, cameraManager: i }) {
15323
+ let a = new sn(), o = (t, n) => {
15324
+ a.set(n?.[0] ?? 0, n?.[1] ?? 0).multiplyScalar(xt.DEG2RAD), e.pathTracer?.setUniform(t, a);
15325
+ };
15340
15326
  return {
15327
+ handleCameraProjection: (t) => {
15328
+ let n = t === "equirectangular";
15329
+ e.pathTracer?.setUniform("cameraProjection", +!!n), n && (r?.denoiserStrategy === "asvgf" && r.setDenoiserStrategy("edgeaware"), i?.setAutoFocusMode("manual"));
15330
+ },
15331
+ handlePanoramaLonRange: (e) => o("panoLonRange", e),
15332
+ handlePanoramaLatRange: (e) => o("panoLatRange", e),
15341
15333
  handleTransparentBackground: (t) => {
15342
15334
  e.pathTracer?.setUniform("transparentBackground", t), e.compositor?.setTransparentBackground(t);
15343
15335
  },
@@ -15375,7 +15367,7 @@ var bp = {
15375
15367
  let i = this._values.get(e);
15376
15368
  if (i === t) return;
15377
15369
  this._values.set(e, t);
15378
- let a = Sp[e];
15370
+ let a = wp[e];
15379
15371
  a && (this._applyRoute(a, t, i), (n === void 0 ? a.reset ?? !0 : n) && this._resetCallback?.(), r || this.dispatchEvent({
15380
15372
  type: dr.SETTING_CHANGED,
15381
15373
  key: e,
@@ -15389,7 +15381,7 @@ var bp = {
15389
15381
  let e = this._values.get(n);
15390
15382
  if (e === i) continue;
15391
15383
  this._values.set(n, i);
15392
- let a = Sp[n];
15384
+ let a = wp[n];
15393
15385
  a && (this._applyRoute(a, i, e), (a.reset ?? !0) && (r = !0), t || this.dispatchEvent({
15394
15386
  type: dr.SETTING_CHANGED,
15395
15387
  key: n,
@@ -15407,7 +15399,7 @@ var bp = {
15407
15399
  }
15408
15400
  applyAll() {
15409
15401
  for (let [e, t] of this._values) {
15410
- let n = Sp[e];
15402
+ let n = wp[e];
15411
15403
  n && this._applyRoute(n, t, void 0);
15412
15404
  }
15413
15405
  }
@@ -15415,10 +15407,10 @@ var bp = {
15415
15407
  e.uniform ? (this._pathTracer?.setUniform(e.uniform, t), e.after && this._pathTracer?.[e.after]?.()) : e.handler ? this._handlers[e.handler]?.(t, n) : e.delegate && this._delegates[e.delegate]?.updateParam?.(e.param, t);
15416
15408
  }
15417
15409
  _initDefaults(e) {
15418
- for (let t of Object.keys(Sp)) t in e && this._values.set(t, e[t]);
15419
- for (let [t, n] of Object.entries(Cp)) t in e && this._values.set(n, e[t]);
15410
+ for (let t of Object.keys(wp)) t in e && this._values.set(t, e[t]);
15411
+ for (let [t, n] of Object.entries(Tp)) t in e && this._values.set(n, e[t]);
15420
15412
  }
15421
- }, Tp = class extends ut {
15413
+ }, Dp = class extends ut {
15422
15414
  constructor(e) {
15423
15415
  super();
15424
15416
  let t = e.clientWidth, n = e.clientHeight;
@@ -15584,7 +15576,7 @@ var bp = {
15584
15576
  dispose() {
15585
15577
  this.controls?.dispose();
15586
15578
  }
15587
- }, Ep = class extends ut {
15579
+ }, Op = class extends ut {
15588
15580
  constructor(e, t, n, r = {}) {
15589
15581
  super(), this.scene = e, this.sceneHelpers = t, this.pathTracer = n, this._onReset = r.onReset || null;
15590
15582
  }
@@ -15744,14 +15736,14 @@ var bp = {
15744
15736
  ], n.distance = e.distance ?? 0, n.penumbra = e.penumbra ?? 0, n.decay = e.decay ?? 2) : e.type === "PointLight" && (n.distance = e.distance ?? 0, n.decay = e.decay ?? 2);
15745
15737
  return (e.type === "SpotLight" || e.type === "DirectionalLight") && e.userData?.gobo && (n.gobo = e.userData.gobo.name, n.goboIntensity = e.userData.gobo.intensity, n.goboInverted = !!e.userData.gobo.inverted, e.type === "DirectionalLight" && (n.goboScale = e.userData.gobo.scale ?? 5)), e.type === "SpotLight" && e.userData?.ies && (n.ies = e.userData.ies.name, n.iesIntensity = e.userData.ies.intensity ?? 1, n.fixtureLumens = e.userData.ies.fixtureLumens ?? null), n;
15746
15738
  }
15747
- }, Dp = class {
15739
+ }, kp = class {
15748
15740
  constructor(e, t = {}) {
15749
15741
  this.pathTracer = e, this._onReset = t.onReset || null, this.texture = null, this.entries = [], this._size = 256;
15750
15742
  }
15751
15743
  async loadLibrary(e, { size: t = 256 } = {}) {
15752
15744
  if (!Array.isArray(e) || e.length === 0) return [];
15753
15745
  this._size = t;
15754
- let n = await Promise.all(e.map((e) => Op(e.url))), r = t, i = t, a = n.length, o = new Uint8Array(r * i * a * 4), s = document.createElement("canvas");
15746
+ let n = await Promise.all(e.map((e) => Ap(e.url))), r = t, i = t, a = n.length, o = new Uint8Array(r * i * a * 4), s = document.createElement("canvas");
15755
15747
  s.width = r, s.height = i;
15756
15748
  let c = s.getContext("2d", { willReadFrequently: !0 });
15757
15749
  for (let e = 0; e < a; e++) {
@@ -15780,7 +15772,7 @@ var bp = {
15780
15772
  o.userData.gobo = {
15781
15773
  name: e.name,
15782
15774
  index: e.index,
15783
- intensity: kp(r),
15775
+ intensity: jp(r),
15784
15776
  inverted: !!i,
15785
15777
  scale: Math.max(1e-4, a)
15786
15778
  };
@@ -15822,28 +15814,28 @@ var bp = {
15822
15814
  return t && t.isSpotLight ? t : null;
15823
15815
  }
15824
15816
  };
15825
- function Op(e) {
15817
+ function Ap(e) {
15826
15818
  return new Promise((t, n) => {
15827
15819
  let r = new Image();
15828
15820
  r.crossOrigin = "anonymous", r.onload = () => t(r), r.onerror = () => n(/* @__PURE__ */ Error(`Failed to load gobo image: ${e}`)), r.src = e;
15829
15821
  });
15830
15822
  }
15831
- function kp(e) {
15823
+ function jp(e) {
15832
15824
  return Math.max(0, Math.min(1, e));
15833
15825
  }
15834
15826
  //#endregion
15835
15827
  //#region src/Processor/IESParser.js
15836
- function Ap(e, t = "ies") {
15828
+ function Mp(e, t = "ies") {
15837
15829
  let n = e.search(/TILT\s*=/i);
15838
15830
  if (n < 0) throw Error(`IES (${t}): missing TILT line`);
15839
15831
  let r = e.indexOf("\n", n);
15840
15832
  if (r < 0) throw Error(`IES (${t}): truncated TILT line`);
15841
15833
  let i = e.slice(n, r).match(/TILT\s*=\s*(\w+)/i), a = i ? i[1].toUpperCase() : "NONE", o = e.slice(r);
15842
15834
  if (a === "INCLUDE") {
15843
- let e = Pp(o), t = 2 + 2 * Number(e[1]);
15844
- o = Fp(o, t);
15835
+ let e = Ip(o), t = 2 + 2 * Number(e[1]);
15836
+ o = Lp(o, t);
15845
15837
  }
15846
- let s = Pp(o), c = 0, l = () => Number(s[c++]), u = l(), d = l(), f = l(), p = l(), m = l(), h = l();
15838
+ let s = Ip(o), c = 0, l = () => Number(s[c++]), u = l(), d = l(), f = l(), p = l(), m = l(), h = l();
15847
15839
  l(), l(), l(), l();
15848
15840
  let g = l();
15849
15841
  if (l(), l(), !Number.isFinite(p) || p <= 0) throw Error(`IES (${t}): invalid vertical angle count ${p}`);
@@ -15869,18 +15861,18 @@ function Ap(e, t = "ies") {
15869
15861
  name: t
15870
15862
  };
15871
15863
  }
15872
- function jp(e, t, n) {
15864
+ function Np(e, t, n) {
15873
15865
  let r = new Uint8Array(t * n), { verticalAngles: i, horizontalAngles: a, candela: o, maxCandela: s } = e;
15874
15866
  if (s <= 0) return r;
15875
15867
  let c = i[i.length - 1], l = a[a.length - 1], u = a[0], d = a.length === 1 || l === u;
15876
15868
  for (let e = 0; e < n; e++) {
15877
- let f = (e + .5) / n * c, p = Ip(i, f), m = Math.min(p + 1, i.length - 1), h = i[m] - i[p], g = h > 0 ? (f - i[p]) / h : 0;
15869
+ let f = (e + .5) / n * c, p = Rp(i, f), m = Math.min(p + 1, i.length - 1), h = i[m] - i[p], g = h > 0 ? (f - i[p]) / h : 0;
15878
15870
  for (let n = 0; n < t; n++) {
15879
15871
  let i;
15880
- if (d) i = Lp(o[p][0], o[m][0], g);
15872
+ if (d) i = zp(o[p][0], o[m][0], g);
15881
15873
  else {
15882
- let e = u + (n + .5) / t * (l - u), r = Ip(a, e), s = Math.min(r + 1, a.length - 1), c = a[s] - a[r], d = c > 0 ? (e - a[r]) / c : 0, f = o[p][r], h = o[p][s], _ = o[m][r], v = o[m][s];
15883
- i = Lp(Lp(f, h, d), Lp(_, v, d), g);
15874
+ let e = u + (n + .5) / t * (l - u), r = Rp(a, e), s = Math.min(r + 1, a.length - 1), c = a[s] - a[r], d = c > 0 ? (e - a[r]) / c : 0, f = o[p][r], h = o[p][s], _ = o[m][r], v = o[m][s];
15875
+ i = zp(zp(f, h, d), zp(_, v, d), g);
15884
15876
  }
15885
15877
  let c = Math.min(1, Math.max(0, i / s));
15886
15878
  r[e * t + n] = Math.round(c * 255);
@@ -15888,7 +15880,7 @@ function jp(e, t, n) {
15888
15880
  }
15889
15881
  return r;
15890
15882
  }
15891
- function Mp(e, t = .1) {
15883
+ function Pp(e, t = .1) {
15892
15884
  let { verticalAngles: n, horizontalAngles: r, candela: i, maxCandela: a } = e, o = Math.PI / 4;
15893
15885
  if (a <= 0 || !n?.length) return o;
15894
15886
  let s = a * t, c = r.length, l = n[n.length - 1], u = !1;
@@ -15903,7 +15895,7 @@ function Mp(e, t = .1) {
15903
15895
  let d = l * Math.PI / 180;
15904
15896
  return Math.min(Math.max(d, 5 * Math.PI / 180), 89 * Math.PI / 180);
15905
15897
  }
15906
- function Np(e, t, n = .7) {
15898
+ function Fp(e, t, n = .7) {
15907
15899
  let { verticalAngles: r, horizontalAngles: i, candela: a, maxCandela: o } = e;
15908
15900
  if (o <= 0 || !r?.length || t <= 0) return 0;
15909
15901
  let s = o * n, c = i.length, l = 0;
@@ -15916,15 +15908,15 @@ function Np(e, t, n = .7) {
15916
15908
  let u = t * 180 / Math.PI, d = u > 0 ? 1 - l / u : 0;
15917
15909
  return Math.min(Math.max(d, 0), 1);
15918
15910
  }
15919
- function Pp(e) {
15911
+ function Ip(e) {
15920
15912
  return e.split(/\s+/).filter((e) => e.length > 0);
15921
15913
  }
15922
- function Fp(e, t) {
15914
+ function Lp(e, t) {
15923
15915
  let n = /\S+/g, r = 0;
15924
15916
  for (; n.exec(e) !== null;) if (r++, r === t) return e.slice(n.lastIndex);
15925
15917
  return "";
15926
15918
  }
15927
- function Ip(e, t) {
15919
+ function Rp(e, t) {
15928
15920
  if (t <= e[0]) return 0;
15929
15921
  if (t >= e[e.length - 1]) return e.length - 1;
15930
15922
  let n = 0, r = e.length - 1;
@@ -15934,12 +15926,12 @@ function Ip(e, t) {
15934
15926
  }
15935
15927
  return n;
15936
15928
  }
15937
- function Lp(e, t, n) {
15929
+ function zp(e, t, n) {
15938
15930
  return e + (t - e) * n;
15939
15931
  }
15940
15932
  //#endregion
15941
15933
  //#region src/managers/IESManager.js
15942
- var Rp = class {
15934
+ var Bp = class {
15943
15935
  constructor(e, t = {}) {
15944
15936
  this.pathTracer = e, this._onReset = t.onReset || null, this.texture = null, this.entries = [], this._gridWidth = 128, this._gridHeight = 128;
15945
15937
  }
@@ -15950,11 +15942,11 @@ var Rp = class {
15950
15942
  try {
15951
15943
  let r = await fetch(e.url);
15952
15944
  if (!r.ok) throw Error(`HTTP ${r.status}`);
15953
- let i = Ap(await r.text(), e.name);
15945
+ let i = Mp(await r.text(), e.name);
15954
15946
  return {
15955
15947
  it: e,
15956
15948
  profile: i,
15957
- grid: jp(i, t, n)
15949
+ grid: Np(i, t, n)
15958
15950
  };
15959
15951
  } catch (t) {
15960
15952
  return console.warn(`IESManager: failed to load "${e.name}": ${t.message}`), null;
@@ -15968,14 +15960,14 @@ var Rp = class {
15968
15960
  let r = t[e];
15969
15961
  o[n + e * 4 + 0] = r, o[n + e * 4 + 1] = r, o[n + e * 4 + 2] = r, o[n + e * 4 + 3] = 255;
15970
15962
  }
15971
- let i = r[e].profile, c = Mp(i);
15963
+ let i = r[e].profile, c = Pp(i);
15972
15964
  s.push({
15973
15965
  name: r[e].it.name,
15974
15966
  index: e,
15975
15967
  maxCandela: i.maxCandela,
15976
15968
  photometricType: i.photometricType,
15977
15969
  suggestedAngle: c,
15978
- suggestedPenumbra: Np(i, c),
15970
+ suggestedPenumbra: Fp(i, c),
15979
15971
  lumens: i.lumens
15980
15972
  });
15981
15973
  }
@@ -16008,7 +16000,7 @@ var Rp = class {
16008
16000
  l = Number.isFinite(e.lumens) ? e.lumens : null, i.userData.ies = {
16009
16001
  name: e.name,
16010
16002
  index: e.index,
16011
- intensity: zp(n),
16003
+ intensity: Vp(n),
16012
16004
  fixtureLumens: l
16013
16005
  }, r && (Number.isFinite(e.suggestedAngle) && (i.angle = e.suggestedAngle, o = e.suggestedAngle), Number.isFinite(e.suggestedPenumbra) && (i.penumbra = e.suggestedPenumbra, s = e.suggestedPenumbra), i.decay = 2, c = 2);
16014
16006
  }
@@ -16031,44 +16023,44 @@ var Rp = class {
16031
16023
  return t && t.isSpotLight ? t : null;
16032
16024
  }
16033
16025
  };
16034
- function zp(e) {
16026
+ function Vp(e) {
16035
16027
  return Math.max(0, Math.min(1, e));
16036
16028
  }
16037
16029
  //#endregion
16038
16030
  //#region src/Processor/ToneMapCPU.js
16039
- var Bp = (e) => Math.min(Math.max(e, 0), 1);
16040
- function Vp(e, t, n, r, i) {
16041
- i[0] = Bp(e), i[1] = Bp(t), i[2] = Bp(n);
16042
- }
16043
- function Hp(e, t, n, r, i) {
16044
- i[0] = Bp(e * r), i[1] = Bp(t * r), i[2] = Bp(n * r);
16045
- }
16031
+ var Hp = (e) => Math.min(Math.max(e, 0), 1);
16046
16032
  function Up(e, t, n, r, i) {
16047
- e *= r, t *= r, n *= r, i[0] = Bp(e / (e + 1)), i[1] = Bp(t / (t + 1)), i[2] = Bp(n / (n + 1));
16033
+ i[0] = Hp(e), i[1] = Hp(t), i[2] = Hp(n);
16048
16034
  }
16049
16035
  function Wp(e, t, n, r, i) {
16036
+ i[0] = Hp(e * r), i[1] = Hp(t * r), i[2] = Hp(n * r);
16037
+ }
16038
+ function Gp(e, t, n, r, i) {
16039
+ e *= r, t *= r, n *= r, i[0] = Hp(e / (e + 1)), i[1] = Hp(t / (t + 1)), i[2] = Hp(n / (n + 1));
16040
+ }
16041
+ function Kp(e, t, n, r, i) {
16050
16042
  e = Math.max(e * r - .004, 0), t = Math.max(t * r - .004, 0), n = Math.max(n * r - .004, 0);
16051
16043
  let a = (e) => (e * (6.2 * e + .5) / (e * (6.2 * e + 1.7) + .06)) ** 2.2;
16052
16044
  i[0] = a(e), i[1] = a(t), i[2] = a(n);
16053
16045
  }
16054
- function Gp(e, t, n, r, i) {
16046
+ function qp(e, t, n, r, i) {
16055
16047
  e = e * r / .6, t = t * r / .6, n = n * r / .6;
16056
16048
  let a = .59719 * e + .35458 * t + .04823 * n, o = .076 * e + .90834 * t + .01566 * n, s = .0284 * e + .13383 * t + .83777 * n, c = (e) => (e * (e + .0245786) - 90537e-9) / (e * (.983729 * e + .432951) + .238081);
16057
- a = c(a), o = c(o), s = c(s), i[0] = Bp(1.60475 * a - .53108 * o - .07367 * s), i[1] = Bp(-.10208 * a + 1.10813 * o - .00605 * s), i[2] = Bp(-.00327 * a - .07276 * o + 1.07602 * s);
16049
+ a = c(a), o = c(o), s = c(s), i[0] = Hp(1.60475 * a - .53108 * o - .07367 * s), i[1] = Hp(-.10208 * a + 1.10813 * o - .00605 * s), i[2] = Hp(-.00327 * a - .07276 * o + 1.07602 * s);
16058
16050
  }
16059
- function Kp(e, t, n, r, i) {
16051
+ function Jp(e, t, n, r, i) {
16060
16052
  e *= r, t *= r, n *= r;
16061
16053
  let a = .6274 * e + .3293 * t + .0433 * n, o = .0691 * e + .9195 * t + .0113 * n, s = .0164 * e + .088 * t + .8956 * n, c = .856627153315983 * a + .0951212405381588 * o + .0482516061458583 * s, l = .137318972929847 * a + .761241990602591 * o + .101439036467562 * s, u = .11189821299995 * a + .0767994186031903 * o + .811302368396859 * s, d = -12.47393, f = 4.026069 - d;
16062
- c = Bp((Math.log2(Math.max(c, 1e-10)) - d) / f), l = Bp((Math.log2(Math.max(l, 1e-10)) - d) / f), u = Bp((Math.log2(Math.max(u, 1e-10)) - d) / f);
16054
+ c = Hp((Math.log2(Math.max(c, 1e-10)) - d) / f), l = Hp((Math.log2(Math.max(l, 1e-10)) - d) / f), u = Hp((Math.log2(Math.max(u, 1e-10)) - d) / f);
16063
16055
  let p = (e) => {
16064
16056
  let t = e * e, n = t * t;
16065
16057
  return 15.5 * n * t - 40.14 * n * e + 31.96 * n - 6.868 * t * e + .4298 * t + .1191 * e - .00232;
16066
16058
  };
16067
16059
  c = p(c), l = p(l), u = p(u);
16068
16060
  let m = 1.1271005818144368 * c - .11060664309660323 * l - .016493938717834573 * u, h = -.1413297634984383 * c + 1.157823702216272 * l - .016493938717834257 * u, g = -.14132976349843826 * c - .11060664309660294 * l + 1.2519364065950405 * u;
16069
- m = Math.max(0, m) ** 2.2, h = Math.max(0, h) ** 2.2, g = Math.max(0, g) ** 2.2, i[0] = Bp(1.6605 * m - .5876 * h - .0728 * g), i[1] = Bp(-.1246 * m + 1.1329 * h - .0083 * g), i[2] = Bp(-.0182 * m - .1006 * h + 1.1187 * g);
16061
+ m = Math.max(0, m) ** 2.2, h = Math.max(0, h) ** 2.2, g = Math.max(0, g) ** 2.2, i[0] = Hp(1.6605 * m - .5876 * h - .0728 * g), i[1] = Hp(-.1246 * m + 1.1329 * h - .0083 * g), i[2] = Hp(-.0182 * m - .1006 * h + 1.1187 * g);
16070
16062
  }
16071
- function qp(e, t, n, r, i) {
16063
+ function Yp(e, t, n, r, i) {
16072
16064
  let a = .76;
16073
16065
  e *= r, t *= r, n *= r;
16074
16066
  let o = Math.min(e, Math.min(t, n)), s = o < .08 ? o - 6.25 * o * o : .04;
@@ -16083,43 +16075,43 @@ function qp(e, t, n, r, i) {
16083
16075
  let f = 1 - 1 / (.15 * (c - u) + 1);
16084
16076
  i[0] = e + (u - e) * f, i[1] = t + (u - t) * f, i[2] = n + (u - n) * f;
16085
16077
  }
16086
- var Jp = new Map([
16087
- [jt, Vp],
16088
- [q, Hp],
16089
- [Kt, Up],
16090
- [Qe, Wp],
16091
- [Ue, Gp],
16092
- [Ge, Kp],
16093
- [kt, qp]
16094
- ]), Yp = 1 / 2.2;
16095
- function Xp(e) {
16078
+ var Xp = new Map([
16079
+ [jt, Up],
16080
+ [q, Wp],
16081
+ [Kt, Gp],
16082
+ [Qe, Kp],
16083
+ [Ue, qp],
16084
+ [Ge, Jp],
16085
+ [kt, Yp]
16086
+ ]), Zp = 1 / 2.2;
16087
+ function Qp(e) {
16096
16088
  return e <= .0031308 ? 12.92 * e : 1.055 * e ** (1 / 2.4) - .055;
16097
16089
  }
16098
- var Zp = .2126, Qp = .7152, $p = .0722;
16099
- function em(e, t) {
16090
+ var $p = .2126, em = .7152, tm = .0722;
16091
+ function nm(e, t) {
16100
16092
  if (t === 1) return;
16101
- let n = e[0] * Zp + e[1] * Qp + e[2] * $p;
16093
+ let n = e[0] * $p + e[1] * em + e[2] * tm;
16102
16094
  e[0] = n + (e[0] - n) * t, e[1] = n + (e[1] - n) * t, e[2] = n + (e[2] - n) * t;
16103
16095
  }
16104
16096
  //#endregion
16105
16097
  //#region src/Passes/OIDNDenoiser.js
16106
- var tm = ai("oidn"), nm = null, rm = null;
16107
- async function im() {
16108
- if (!nm) {
16098
+ var rm = ai("oidn"), im = null, am = null;
16099
+ async function om() {
16100
+ if (!im) {
16109
16101
  let [e, t] = await Promise.all([import("oidn-web"), import("@tensorflow/tfjs-core")]);
16110
- nm = e.initUNetFromURL, rm = t.engine;
16102
+ im = e.initUNetFromURL, am = t.engine;
16111
16103
  }
16112
- return nm;
16104
+ return im;
16113
16105
  }
16114
- function am() {
16115
- if (rm) try {
16116
- let e = rm();
16106
+ function sm() {
16107
+ if (am) try {
16108
+ let e = am();
16117
16109
  e?.registryFactory && "webgpu-oidn" in e.registryFactory && e.removeBackend("webgpu-oidn");
16118
16110
  } catch (e) {
16119
- tm.warn("failed to clear cached TFJS backend", e);
16111
+ rm.warn("failed to clear cached TFJS backend", e);
16120
16112
  }
16121
16113
  }
16122
- var om = new Float32Array(3), sm = {
16114
+ var cm = new Float32Array(3), lm = {
16123
16115
  QUALITY_MODELS: {
16124
16116
  fast: "rt_hdr_alb_nrm_small",
16125
16117
  balance: "rt_hdr_alb_nrm",
@@ -16131,7 +16123,7 @@ var om = new Float32Array(3), sm = {
16131
16123
  debugGbufferMaps: !0,
16132
16124
  tileSize: 256
16133
16125
  }
16134
- }, cm = class extends ut {
16126
+ }, um = class extends ut {
16135
16127
  constructor(e, t, n, r, i = {}) {
16136
16128
  if (super(), !e || !t || !n || !r) throw Error("OIDNDenoiser requires output canvas, renderer, scene, and camera");
16137
16129
  this.renderer = t, this.scene = n, this.camera = r, this.input = t.domElement, this.output = e, this.extractGBufferData = i.extractGBufferData || null, this.getMRTRenderTarget = i.getMRTRenderTarget || null, this.backendParamsGetter = i.backendParams || null, this.getGPUTextures = i.getGPUTextures || null, this.getExposure = i.getExposure || (() => 1), this.getToneMapping = i.getToneMapping || (() => Ue), this.getSaturation = i.getSaturation || (() => 1), this.getTransparentBackground = i.getTransparentBackground || (() => !1), this.isGPUMode = !!this.backendParamsGetter, this.gpuDevice = null, this._gpuInputBuffers = {
@@ -16142,14 +16134,14 @@ var om = new Float32Array(3), sm = {
16142
16134
  width: 0,
16143
16135
  height: 0
16144
16136
  }, this._gpuInputPadBuffer = null, this._gpuInputPaddedRowBytes = 0, this._alphaReadbackBuffer = null, this._alphaReadbackMapped = !1, this._cachedAlpha = null, this._cachedAlphaWidth = 0, this.config = {
16145
- ...sm.DEFAULT_OPTIONS,
16137
+ ...lm.DEFAULT_OPTIONS,
16146
16138
  ...i
16147
16139
  }, this.enabled = this.config.enableOIDN, this.quality = this.config.oidnQuality, this.debugGbufferMaps = this.config.debugGbufferMaps, this.tileSize = this.config.tileSize, this.state = {
16148
16140
  isDenoising: !1,
16149
16141
  isLoading: !1,
16150
16142
  abortController: null
16151
16143
  }, this._pendingStagingBuffers = /* @__PURE__ */ new Set(), this._pendingTileBlits = [], this.currentTZAUrl = null, this.unet = null, this._pendingStart = !1, this._initialize().catch((e) => {
16152
- tm.error("init failed:", e), this.dispatchEvent({
16144
+ rm.error("init failed:", e), this.dispatchEvent({
16153
16145
  type: "error",
16154
16146
  error: e
16155
16147
  });
@@ -16195,13 +16187,13 @@ var om = new Float32Array(3), sm = {
16195
16187
  let e = this.backendParamsGetter();
16196
16188
  this.gpuDevice = e?.device ?? null, t = e?.device ? e : void 0;
16197
16189
  }
16198
- this.unet = await (await im())(e, t, {
16190
+ this.unet = await (await om())(e, t, {
16199
16191
  aux: !0,
16200
16192
  hdr: !0,
16201
16193
  maxTileSize: this.tileSize
16202
- }), this.currentTZAUrl = e, this.dispatchEvent({ type: "loaded" }), tm.debug("UNet weights loaded:", e);
16194
+ }), this.currentTZAUrl = e, this.dispatchEvent({ type: "loaded" }), rm.debug("UNet weights loaded:", e);
16203
16195
  } catch (e) {
16204
- tm.error("UNet weights failed to load:", e), this.dispatchEvent({
16196
+ rm.error("UNet weights failed to load:", e), this.dispatchEvent({
16205
16197
  type: "error",
16206
16198
  error: /* @__PURE__ */ Error(`Denoiser loading failed: ${e.message}`)
16207
16199
  });
@@ -16210,14 +16202,14 @@ var om = new Float32Array(3), sm = {
16210
16202
  }
16211
16203
  }
16212
16204
  _generateTzaUrl() {
16213
- let { oidnWeightsBaseUrl: e } = cl(), { QUALITY_MODELS: t } = sm;
16205
+ let { oidnWeightsBaseUrl: e } = cl(), { QUALITY_MODELS: t } = lm;
16214
16206
  return `${e}${t[this.quality] || t.balance}.tza`;
16215
16207
  }
16216
16208
  async updateConfiguration(e) {
16217
16209
  Object.keys(e).some((t) => this.config[t] !== e[t]) && (Object.assign(this.config, e), this.quality = this.config.oidnQuality, this.debugGbufferMaps = this.config.debugGbufferMaps, this.tileSize = this.config.tileSize, await this._setupUNetDenoiser());
16218
16210
  }
16219
16211
  async updateQuality(e) {
16220
- if (!Object.prototype.hasOwnProperty.call(sm.QUALITY_MODELS, e)) throw Error(`Invalid quality setting: ${e}. Must be one of: ${Object.keys(sm.QUALITY_MODELS).join(", ")}`);
16212
+ if (!Object.prototype.hasOwnProperty.call(lm.QUALITY_MODELS, e)) throw Error(`Invalid quality setting: ${e}. Must be one of: ${Object.keys(lm.QUALITY_MODELS).join(", ")}`);
16221
16213
  await this.updateConfiguration({ oidnQuality: e });
16222
16214
  }
16223
16215
  async start() {
@@ -16228,7 +16220,7 @@ var om = new Float32Array(3), sm = {
16228
16220
  if (t) {
16229
16221
  this.renderer?.resetState?.(), this.input.style.opacity = "0";
16230
16222
  let t = performance.now() - e;
16231
- tm.debug(`denoise complete in ${Q.ms(t)} · quality ${this.quality}`);
16223
+ rm.debug(`denoise complete in ${Q.ms(t)} · quality ${this.quality}`);
16232
16224
  }
16233
16225
  return t;
16234
16226
  }
@@ -16238,7 +16230,7 @@ var om = new Float32Array(3), sm = {
16238
16230
  try {
16239
16231
  return await this._executeUNet(), !0;
16240
16232
  } catch (e) {
16241
- return e.name === "AbortError" ? tm.debug("denoise aborted") : tm.error("denoise error:", e), this.input.style.opacity = "1", !1;
16233
+ return e.name === "AbortError" ? rm.debug("denoise aborted") : rm.error("denoise error:", e), this.input.style.opacity = "1", !1;
16242
16234
  } finally {
16243
16235
  this.state.isDenoising = !1, this.state.abortController = null, this.dispatchEvent({ type: "end" });
16244
16236
  }
@@ -16248,11 +16240,11 @@ var om = new Float32Array(3), sm = {
16248
16240
  }
16249
16241
  async _executeUNetGPU() {
16250
16242
  let { width: e, height: t } = this.output;
16251
- if (!this.getGPUTextures) return tm.warn("GPU mode enabled but getGPUTextures not provided"), !1;
16243
+ if (!this.getGPUTextures) return rm.warn("GPU mode enabled but getGPUTextures not provided"), !1;
16252
16244
  let n = this.getGPUTextures();
16253
- if (!n?.color) return tm.warn("GPU textures not ready yet"), !1;
16245
+ if (!n?.color) return rm.warn("GPU textures not ready yet"), !1;
16254
16246
  let r = this.gpuDevice;
16255
- if (!r) return tm.warn("gpuDevice not available"), !1;
16247
+ if (!r) return rm.warn("gpuDevice not available"), !1;
16256
16248
  this._ensureGPUInputBuffers(e, t);
16257
16249
  let i = r.createCommandEncoder({ label: "oidn-tex-to-buf" }), a = e * 16, o = this._gpuInputPaddedRowBytes, s = o > a, c = this._gpuInputPadBuffer, l = (n, r) => {
16258
16250
  if (!s) i.copyTextureToBuffer({
@@ -16402,10 +16394,10 @@ var om = new Float32Array(3), sm = {
16402
16394
  }
16403
16395
  r.queue.submit([d.finish()]);
16404
16396
  let f = u.mapAsync(GPUMapMode.READ).then(() => {
16405
- let e = new Float32Array(u.getMappedRange()), t = new ImageData(o, s), r = this.getExposure(), c = this.getSaturation(), l = Jp.get(this.getToneMapping()) || Jp.get(Ue), d = this._cachedAlpha, f = this._cachedAlphaWidth;
16397
+ let e = new Float32Array(u.getMappedRange()), t = new ImageData(o, s), r = this.getExposure(), c = this.getSaturation(), l = Xp.get(this.getToneMapping()) || Xp.get(Ue), d = this._cachedAlpha, f = this._cachedAlphaWidth;
16406
16398
  for (let i = 0, a = e.length; i < a; i += 4) {
16407
16399
  let a = e[i] * r, s = e[i + 1] * r, u = e[i + 2] * r;
16408
- if (c !== 1 && (om[0] = a, om[1] = s, om[2] = u, em(om, c), a = om[0], s = om[1], u = om[2]), l(a, s, u, 1, om), t.data[i] = Xp(om[0]) * 255 + .5 | 0, t.data[i + 1] = Xp(om[1]) * 255 + .5 | 0, t.data[i + 2] = Xp(om[2]) * 255 + .5 | 0, d) {
16400
+ if (c !== 1 && (cm[0] = a, cm[1] = s, cm[2] = u, nm(cm, c), a = cm[0], s = cm[1], u = cm[2]), l(a, s, u, 1, cm), t.data[i] = Qp(cm[0]) * 255 + .5 | 0, t.data[i + 1] = Qp(cm[1]) * 255 + .5 | 0, t.data[i + 2] = Qp(cm[2]) * 255 + .5 | 0, d) {
16409
16401
  let e = (i >> 2) % o, r = (i >> 2) / o | 0;
16410
16402
  t.data[i + 3] = d[(n.y + r) * f + n.x + e];
16411
16403
  } else t.data[i + 3] = 255;
@@ -16432,7 +16424,7 @@ var om = new Float32Array(3), sm = {
16432
16424
  async _displayGPUOutput({ data: e, width: t, height: n }) {
16433
16425
  let r = this.gpuDevice;
16434
16426
  if (!r) {
16435
- tm.error("gpuDevice not available for output readback");
16427
+ rm.error("gpuDevice not available for output readback");
16436
16428
  return;
16437
16429
  }
16438
16430
  let i = t * n * 4 * 4, a = r.createBuffer({
@@ -16443,10 +16435,10 @@ var om = new Float32Array(3), sm = {
16443
16435
  try {
16444
16436
  let o = r.createCommandEncoder({ label: "oidn-readback" });
16445
16437
  o.copyBufferToBuffer(e, 0, a, 0, i), r.queue.submit([o.finish()]), await a.mapAsync(GPUMapMode.READ);
16446
- let s = new Float32Array(a.getMappedRange()), c = new ImageData(t, n), l = this.getExposure(), u = this.getSaturation(), d = Jp.get(this.getToneMapping()) || Jp.get(Ue), f = this._cachedAlpha;
16438
+ let s = new Float32Array(a.getMappedRange()), c = new ImageData(t, n), l = this.getExposure(), u = this.getSaturation(), d = Xp.get(this.getToneMapping()) || Xp.get(Ue), f = this._cachedAlpha;
16447
16439
  for (let e = 0, t = s.length; e < t; e += 4) {
16448
16440
  let t = s[e] * l, n = s[e + 1] * l, r = s[e + 2] * l;
16449
- u !== 1 && (om[0] = t, om[1] = n, om[2] = r, em(om, u), t = om[0], n = om[1], r = om[2]), d(t, n, r, 1, om), c.data[e] = Xp(om[0]) * 255 + .5 | 0, c.data[e + 1] = Xp(om[1]) * 255 + .5 | 0, c.data[e + 2] = Xp(om[2]) * 255 + .5 | 0, c.data[e + 3] = f ? f[e >> 2] : 255;
16441
+ u !== 1 && (cm[0] = t, cm[1] = n, cm[2] = r, nm(cm, u), t = cm[0], n = cm[1], r = cm[2]), d(t, n, r, 1, cm), c.data[e] = Qp(cm[0]) * 255 + .5 | 0, c.data[e + 1] = Qp(cm[1]) * 255 + .5 | 0, c.data[e + 2] = Qp(cm[2]) * 255 + .5 | 0, c.data[e + 3] = f ? f[e >> 2] : 255;
16450
16442
  }
16451
16443
  a.unmap(), this.ctx.putImageData(c, 0, 0);
16452
16444
  } finally {
@@ -16454,12 +16446,12 @@ var om = new Float32Array(3), sm = {
16454
16446
  }
16455
16447
  }
16456
16448
  abort() {
16457
- this._pendingStart = !1, !(!this.enabled || !this.state.isDenoising) && (this.state.abortController?.abort(), this._destroyPendingStagingBuffers(), this.input.style.opacity = "1", this.state.isDenoising = !1, this.dispatchEvent({ type: "end" }), tm.debug("denoise aborted"));
16449
+ this._pendingStart = !1, !(!this.enabled || !this.state.isDenoising) && (this.state.abortController?.abort(), this._destroyPendingStagingBuffers(), this.input.style.opacity = "1", this.state.isDenoising = !1, this.dispatchEvent({ type: "end" }), rm.debug("denoise aborted"));
16458
16450
  }
16459
16451
  setSize(e, t) {
16460
16452
  if (e <= 0 || t <= 0) throw Error(`Invalid dimensions: ${e}x${t}`);
16461
16453
  this.output.width = e, this.output.height = t, this._setupUNetDenoiser().catch((e) => {
16462
- tm.error("reinitialize after size change failed:", e);
16454
+ rm.error("reinitialize after size change failed:", e);
16463
16455
  });
16464
16456
  }
16465
16457
  _destroyPendingStagingBuffers() {
@@ -16467,13 +16459,13 @@ var om = new Float32Array(3), sm = {
16467
16459
  this._pendingStagingBuffers.clear();
16468
16460
  }
16469
16461
  dispose() {
16470
- this.abort(), this._destroyPendingStagingBuffers(), this.unet?.dispose(), am(), this._destroyGPUInputBuffers(), this.output?.parentNode && this.output.remove(), this.unet = null, this.ctx = null, this.state.abortController = null, this.removeAllListeners?.(), tm.debug("disposed");
16462
+ this.abort(), this._destroyPendingStagingBuffers(), this.unet?.dispose(), sm(), this._destroyGPUInputBuffers(), this.output?.parentNode && this.output.remove(), this.unet = null, this.ctx = null, this.state.abortController = null, this.removeAllListeners?.(), rm.debug("disposed");
16471
16463
  }
16472
- }, lm = "let e={ortRuntimeUrl:`https://cdn.jsdelivr.net/npm/onnxruntime-web@1.24.3/dist/ort.webgpu.bundle.min.mjs`,ortWasmPaths:`https://cdn.jsdelivr.net/npm/onnxruntime-web@1.24.3/dist/`,cacheNamespace:`rayzee`},t=null;async function n(){return t||(t=await import(e.ortRuntimeUrl),t.env.wasm.wasmPaths=e.ortWasmPaths,t.env.logLevel=`error`,t)}function r(){return`${e.cacheNamespace}:ai-upscaler-models`}const i=`models`;let a=null,o=null;function s(){return new Promise((e,t)=>{let n=indexedDB.open(r(),1);n.onupgradeneeded=()=>n.result.createObjectStore(i),n.onsuccess=()=>e(n.result),n.onerror=()=>t(n.error)})}async function c(e){try{let t=await s();return await new Promise((n,r)=>{let a=t.transaction(i,`readonly`).objectStore(i).get(e);a.onsuccess=()=>n(a.result||null),a.onerror=()=>r(a.error)})}catch{return null}}async function l(e,t){try{let n=await s();await new Promise((r,a)=>{let o=n.transaction(i,`readwrite`);o.objectStore(i).put(t,e),o.oncomplete=()=>r(),o.onerror=()=>a(o.error)})}catch{}}async function u(e){let t=await c(e);if(t)return console.log(`AI Upscaler Worker: model loaded from cache (${(t.byteLength/1024/1024).toFixed(1)}MB)`),t;let n=await fetch(e);if(!n.ok)throw Error(`Failed to fetch model: ${n.status}`);let r=await n.arrayBuffer();return l(e,r.slice(0)),r}async function d(e,t){if(a&&o===e){self.postMessage({type:`loaded`,backend:`webgpu`});return}a&&=(await a.release(),null);let[r,i]=await Promise.all([u(e),n()]);a=await i.InferenceSession.create(r,t),o=e;let s=512;try{let e=await navigator.gpu?.requestAdapter(),t=await e?.requestAdapterInfo?.()||e?.info,n=/apple|swiftshader|llvmpipe/i.test(t?.vendor||``)||/apple|swiftshader/i.test(t?.architecture||``),r=t?.device?.toLowerCase?.()?.includes(`integrated`)||/intel.*iris|intel.*uhd|intel.*hd|amd.*vega|radeon.*graphics/i.test(t?.description||``);s=n?128:r?256:512,console.log(`AI Upscaler Worker: GPU=\"${t?.description||t?.device||`unknown`}\", tileSize=${s}`)}catch{}let c=(r.byteLength/1024/1024).toFixed(1);console.log(`AI Upscaler Worker: model loaded (${c}MB), backend: webgpu`),self.postMessage({type:`loaded`,backend:`webgpu`,tileSize:s})}async function f(e,t,r,i){let o=await n(),s=a.inputNames[0],c=a.outputNames[0],l=new o.Tensor(`float32`,e,[1,3,r,t]),u=(await a.run({[s]:l}))[c].data;self.postMessage({type:`inferred`,outputData:u,id:i},[u.buffer])}self.onmessage=async t=>{let{type:n}=t.data;try{n===`load`?(t.data.ortRuntimeUrl&&(e.ortRuntimeUrl=t.data.ortRuntimeUrl),t.data.ortWasmPaths&&(e.ortWasmPaths=t.data.ortWasmPaths),t.data.cacheNamespace&&(e.cacheNamespace=t.data.cacheNamespace),await d(t.data.url,t.data.sessionOptions)):n===`infer`?await f(t.data.tileData,t.data.width,t.data.height,t.data.id):n===`dispose`&&a&&(await a.release(),a=null,o=null)}catch(e){self.postMessage({type:`error`,message:e.message,id:t.data?.id})}};", um = typeof self < "u" && self.Blob && new Blob(["URL.revokeObjectURL(import.meta.url);", lm], { type: "text/javascript;charset=utf-8" });
16473
- function dm(e) {
16464
+ }, dm = "let e={ortRuntimeUrl:`https://cdn.jsdelivr.net/npm/onnxruntime-web@1.24.3/dist/ort.webgpu.bundle.min.mjs`,ortWasmPaths:`https://cdn.jsdelivr.net/npm/onnxruntime-web@1.24.3/dist/`,cacheNamespace:`rayzee`},t=null;async function n(){return t||(t=await import(e.ortRuntimeUrl),t.env.wasm.wasmPaths=e.ortWasmPaths,t.env.logLevel=`error`,t)}function r(){return`${e.cacheNamespace}:ai-upscaler-models`}const i=`models`;let a=null,o=null;function s(){return new Promise((e,t)=>{let n=indexedDB.open(r(),1);n.onupgradeneeded=()=>n.result.createObjectStore(i),n.onsuccess=()=>e(n.result),n.onerror=()=>t(n.error)})}async function c(e){try{let t=await s();return await new Promise((n,r)=>{let a=t.transaction(i,`readonly`).objectStore(i).get(e);a.onsuccess=()=>n(a.result||null),a.onerror=()=>r(a.error)})}catch{return null}}async function l(e,t){try{let n=await s();await new Promise((r,a)=>{let o=n.transaction(i,`readwrite`);o.objectStore(i).put(t,e),o.oncomplete=()=>r(),o.onerror=()=>a(o.error)})}catch{}}async function u(e){let t=await c(e);if(t)return console.log(`AI Upscaler Worker: model loaded from cache (${(t.byteLength/1024/1024).toFixed(1)}MB)`),t;let n=await fetch(e);if(!n.ok)throw Error(`Failed to fetch model: ${n.status}`);let r=await n.arrayBuffer();return l(e,r.slice(0)),r}async function d(e,t){if(a&&o===e){self.postMessage({type:`loaded`,backend:`webgpu`});return}a&&=(await a.release(),null);let[r,i]=await Promise.all([u(e),n()]);a=await i.InferenceSession.create(r,t),o=e;let s=512;try{let e=await navigator.gpu?.requestAdapter(),t=await e?.requestAdapterInfo?.()||e?.info,n=/apple|swiftshader|llvmpipe/i.test(t?.vendor||``)||/apple|swiftshader/i.test(t?.architecture||``),r=t?.device?.toLowerCase?.()?.includes(`integrated`)||/intel.*iris|intel.*uhd|intel.*hd|amd.*vega|radeon.*graphics/i.test(t?.description||``);s=n?128:r?256:512,console.log(`AI Upscaler Worker: GPU=\"${t?.description||t?.device||`unknown`}\", tileSize=${s}`)}catch{}let c=(r.byteLength/1024/1024).toFixed(1);console.log(`AI Upscaler Worker: model loaded (${c}MB), backend: webgpu`),self.postMessage({type:`loaded`,backend:`webgpu`,tileSize:s})}async function f(e,t,r,i){let o=await n(),s=a.inputNames[0],c=a.outputNames[0],l=new o.Tensor(`float32`,e,[1,3,r,t]),u=(await a.run({[s]:l}))[c].data;self.postMessage({type:`inferred`,outputData:u,id:i},[u.buffer])}self.onmessage=async t=>{let{type:n}=t.data;try{n===`load`?(t.data.ortRuntimeUrl&&(e.ortRuntimeUrl=t.data.ortRuntimeUrl),t.data.ortWasmPaths&&(e.ortWasmPaths=t.data.ortWasmPaths),t.data.cacheNamespace&&(e.cacheNamespace=t.data.cacheNamespace),await d(t.data.url,t.data.sessionOptions)):n===`infer`?await f(t.data.tileData,t.data.width,t.data.height,t.data.id):n===`dispose`&&a&&(await a.release(),a=null,o=null)}catch(e){self.postMessage({type:`error`,message:e.message,id:t.data?.id})}};", fm = typeof self < "u" && self.Blob && new Blob(["URL.revokeObjectURL(import.meta.url);", dm], { type: "text/javascript;charset=utf-8" });
16465
+ function pm(e) {
16474
16466
  let t;
16475
16467
  try {
16476
- if (t = um && (self.URL || self.webkitURL).createObjectURL(um), !t) throw "";
16468
+ if (t = fm && (self.URL || self.webkitURL).createObjectURL(fm), !t) throw "";
16477
16469
  let n = new Worker(t, {
16478
16470
  type: "module",
16479
16471
  name: e?.name
@@ -16482,7 +16474,7 @@ function dm(e) {
16482
16474
  (self.URL || self.webkitURL).revokeObjectURL(t);
16483
16475
  }), n;
16484
16476
  } catch {
16485
- return new Worker("data:text/javascript;charset=utf-8," + encodeURIComponent(lm), {
16477
+ return new Worker("data:text/javascript;charset=utf-8," + encodeURIComponent(dm), {
16486
16478
  type: "module",
16487
16479
  name: e?.name
16488
16480
  });
@@ -16490,7 +16482,7 @@ function dm(e) {
16490
16482
  }
16491
16483
  //#endregion
16492
16484
  //#region src/Passes/AIUpscaler.js
16493
- var fm = {
16485
+ var mm = {
16494
16486
  fast: {
16495
16487
  2: "2x-spanx2-ch48.onnx",
16496
16488
  4: "4xNomos8k_span_otf_strong_fp32_opset17.onnx"
@@ -16504,17 +16496,17 @@ var fm = {
16504
16496
  4: "4xNomos2_hq_mosr_fp32.onnx"
16505
16497
  }
16506
16498
  };
16507
- function pm() {
16499
+ function hm() {
16508
16500
  let { upscalerModelBaseUrl: e } = cl(), t = {};
16509
- for (let n in fm) {
16501
+ for (let n in mm) {
16510
16502
  t[n] = {};
16511
- for (let r in fm[n]) t[n][r] = e + fm[n][r];
16503
+ for (let r in mm[n]) t[n][r] = e + mm[n][r];
16512
16504
  }
16513
16505
  return t;
16514
16506
  }
16515
- var mm = {
16507
+ var gm = {
16516
16508
  get QUALITY_PRESETS() {
16517
- return pm();
16509
+ return hm();
16518
16510
  },
16519
16511
  TILE_SIZE: 512,
16520
16512
  TILE_OVERLAP: 16,
@@ -16525,17 +16517,17 @@ var mm = {
16525
16517
  }],
16526
16518
  graphOptimizationLevel: "all"
16527
16519
  }
16528
- }, hm = class extends ut {
16520
+ }, _m = class extends ut {
16529
16521
  constructor(e, t, n = {}) {
16530
16522
  if (super(), !e || !t) throw Error("AIUpscaler requires output canvas and renderer");
16531
- this.renderer = t, this.input = t.domElement, this.output = e, this.getSourceCanvas = n.getSourceCanvas || null, this.getGPUTextures = n.getGPUTextures || null, this.getExposure = n.getExposure || (() => 1), this.getToneMapping = n.getToneMapping || (() => Ue), this.getSaturation = n.getSaturation || (() => 1), this.enabled = !1, this.hdr = !1, this.scaleFactor = n.scaleFactor || 2, this.quality = n.quality || "fast", this.tileSize = n.tileSize || mm.TILE_SIZE, this._tileSizeOverride = !!n.tileSize, this.state = {
16523
+ this.renderer = t, this.input = t.domElement, this.output = e, this.getSourceCanvas = n.getSourceCanvas || null, this.getGPUTextures = n.getGPUTextures || null, this.getExposure = n.getExposure || (() => 1), this.getToneMapping = n.getToneMapping || (() => Ue), this.getSaturation = n.getSaturation || (() => 1), this.enabled = !1, this.hdr = !1, this.scaleFactor = n.scaleFactor || 2, this.quality = n.quality || "fast", this.tileSize = n.tileSize || gm.TILE_SIZE, this._tileSizeOverride = !!n.tileSize, this.state = {
16532
16524
  isUpscaling: !1,
16533
16525
  isLoading: !1,
16534
16526
  abortController: null
16535
16527
  }, this._worker = null, this._currentModelUrl = null, this._tileId = 0, this._pendingWorkerHandlers = /* @__PURE__ */ new Set(), this._upscaledAlpha = null, this._upscaledAlphaWidth = 0, this._backupCanvas = null, this._baseWidth = e.width, this._baseHeight = e.height, this._hdrStagingBuffer = null, this._hdrStagingWidth = 0, this._hdrStagingHeight = 0;
16536
16528
  }
16537
16529
  async _ensureSession() {
16538
- let e = mm.QUALITY_PRESETS[this.quality];
16530
+ let e = gm.QUALITY_PRESETS[this.quality];
16539
16531
  if (!e) throw Error(`Unknown quality preset: ${this.quality}`);
16540
16532
  let t = e[this.scaleFactor];
16541
16533
  if (!t) throw Error(`No model for ${this.quality}/${this.scaleFactor}x`);
@@ -16545,14 +16537,14 @@ var mm = {
16545
16537
  message: `Loading ${this.scaleFactor}x upscale model...`
16546
16538
  });
16547
16539
  try {
16548
- this._worker ||= new dm(), await new Promise((e, n) => {
16540
+ this._worker ||= new pm(), await new Promise((e, n) => {
16549
16541
  let r = (t) => {
16550
16542
  t.data.type === "loaded" ? (this._worker.removeEventListener("message", r), t.data.tileSize && !this._tileSizeOverride && (this.tileSize = t.data.tileSize), console.log(`AI Upscaler: ${this.scaleFactor}x model loaded, backend: ${t.data.backend}, tileSize: ${this.tileSize}`), e()) : t.data.type === "error" && (this._worker.removeEventListener("message", r), n(Error(t.data.message)));
16551
16543
  }, { ortRuntimeUrl: i, ortWasmPaths: a, cacheNamespace: o } = cl();
16552
16544
  this._worker.addEventListener("message", r), this._worker.postMessage({
16553
16545
  type: "load",
16554
16546
  url: t,
16555
- sessionOptions: mm.SESSION_OPTIONS,
16547
+ sessionOptions: gm.SESSION_OPTIONS,
16556
16548
  ortRuntimeUrl: i,
16557
16549
  ortWasmPaths: a,
16558
16550
  cacheNamespace: o
@@ -16622,8 +16614,8 @@ var mm = {
16622
16614
  willReadFrequently: !0,
16623
16615
  alpha: !0
16624
16616
  });
16625
- this._cacheUpscaledAlpha(t, n * i, r * i), t.isHDR && (this._hdrToneMapFn = Jp.get(this.getToneMapping()) || Jp.get(Ue), this._hdrExposure = this.getExposure(), this._hdrSaturation = this.getSaturation(), this._tmOut = new Float32Array(3));
16626
- let o = mm.TILE_OVERLAP, s = this.tileSize, c = s - o * 2, l = Math.ceil(n / c), u = Math.ceil(r / c), d = l * u, f = 0;
16617
+ this._cacheUpscaledAlpha(t, n * i, r * i), t.isHDR && (this._hdrToneMapFn = Xp.get(this.getToneMapping()) || Xp.get(Ue), this._hdrExposure = this.getExposure(), this._hdrSaturation = this.getSaturation(), this._tmOut = new Float32Array(3));
16618
+ let o = gm.TILE_OVERLAP, s = this.tileSize, c = s - o * 2, l = Math.ceil(n / c), u = Math.ceil(r / c), d = l * u, f = 0;
16627
16619
  for (let o = 0; o < u; o++) for (let u = 0; u < l; u++) {
16628
16620
  if (e.aborted) throw new DOMException("Aborted", "AbortError");
16629
16621
  let l = Math.min(u * c, Math.max(0, n - s)), p = Math.min(o * c, Math.max(0, r - s)), m = Math.min(s, n - l), h = Math.min(s, r - p), g = this._extractTile(t, l, p, m, h), _ = await this._inferTile(g, m, h), v = l * i, y = p * i, b = m * i, x = h * i, S = this._tensorToImageData(_, b, x, v, y);
@@ -16696,7 +16688,7 @@ var mm = {
16696
16688
  let u = ((n + e) * o + (t + i)) * 4, d = e * r + i;
16697
16689
  if (s) {
16698
16690
  let e = this._hdrToneMapFn, t = this._hdrExposure, n = this._hdrSaturation, r = a[u] * t, i = a[u + 1] * t, o = a[u + 2] * t;
16699
- n !== 1 && (this._tmOut[0] = r, this._tmOut[1] = i, this._tmOut[2] = o, em(this._tmOut, n), r = this._tmOut[0], i = this._tmOut[1], o = this._tmOut[2]), e(r, i, o, 1, this._tmOut), l[d] = this._tmOut[0] ** +Yp, l[c + d] = this._tmOut[1] ** +Yp, l[2 * c + d] = this._tmOut[2] ** +Yp;
16691
+ n !== 1 && (this._tmOut[0] = r, this._tmOut[1] = i, this._tmOut[2] = o, nm(this._tmOut, n), r = this._tmOut[0], i = this._tmOut[1], o = this._tmOut[2]), e(r, i, o, 1, this._tmOut), l[d] = this._tmOut[0] ** +Zp, l[c + d] = this._tmOut[1] ** +Zp, l[2 * c + d] = this._tmOut[2] ** +Zp;
16700
16692
  } else l[d] = a[u] / 255, l[c + d] = a[u + 1] / 255, l[2 * c + d] = a[u + 2] / 255;
16701
16693
  }
16702
16694
  return l;
@@ -16754,10 +16746,10 @@ var mm = {
16754
16746
  this._backupCanvas = document.createElement("canvas"), this._backupCanvas.width = e.width, this._backupCanvas.height = e.height;
16755
16747
  let t = this._backupCanvas.getContext("2d");
16756
16748
  if (e.isHDR) {
16757
- let { data: n, width: r, height: i } = e, a = t.createImageData(r, i), o = a.data, s = Jp.get(this.getToneMapping()) || Jp.get(Ue), c = this.getExposure(), l = this.getSaturation(), u = new Float32Array(3);
16749
+ let { data: n, width: r, height: i } = e, a = t.createImageData(r, i), o = a.data, s = Xp.get(this.getToneMapping()) || Xp.get(Ue), c = this.getExposure(), l = this.getSaturation(), u = new Float32Array(3);
16758
16750
  for (let e = 0, t = r * i; e < t; e++) {
16759
16751
  let t = e * 4, r = n[t] * c, i = n[t + 1] * c, a = n[t + 2] * c;
16760
- l !== 1 && (u[0] = r, u[1] = i, u[2] = a, em(u, l), r = u[0], i = u[1], a = u[2]), s(r, i, a, 1, u), o[t] = u[0] ** +Yp * 255 + .5 | 0, o[t + 1] = u[1] ** +Yp * 255 + .5 | 0, o[t + 2] = u[2] ** +Yp * 255 + .5 | 0, o[t + 3] = 255;
16752
+ l !== 1 && (u[0] = r, u[1] = i, u[2] = a, nm(u, l), r = u[0], i = u[1], a = u[2]), s(r, i, a, 1, u), o[t] = u[0] ** +Zp * 255 + .5 | 0, o[t + 1] = u[1] ** +Zp * 255 + .5 | 0, o[t + 2] = u[2] ** +Zp * 255 + .5 | 0, o[t + 3] = 255;
16761
16753
  }
16762
16754
  t.putImageData(a, 0, 0);
16763
16755
  } else t.putImageData(e, 0, 0);
@@ -16769,7 +16761,7 @@ var mm = {
16769
16761
  this.hdr = !!e;
16770
16762
  }
16771
16763
  setQuality(e) {
16772
- if (!mm.QUALITY_PRESETS[e]) {
16764
+ if (!gm.QUALITY_PRESETS[e]) {
16773
16765
  console.warn(`AIUpscaler: Invalid quality "${e}", must be fast/balanced/quality`);
16774
16766
  return;
16775
16767
  }
@@ -16792,7 +16784,7 @@ var mm = {
16792
16784
  async dispose() {
16793
16785
  this.abort(), this._cleanupPendingWorkerHandlers(), this._worker &&= (this._worker.postMessage({ type: "dispose" }), this._worker.terminate(), null), this._currentModelUrl = null, this._backupCanvas = null, this._upscaledAlpha = null, this.state.abortController = null, this._hdrStagingBuffer?.destroy(), this._hdrStagingBuffer = null, this._hdrStagingWidth = 0, this._hdrStagingHeight = 0, console.log("AIUpscaler disposed");
16794
16786
  }
16795
- }, gm = class extends ut {
16787
+ }, vm = class extends ut {
16796
16788
  constructor({ renderer: e, mainCanvas: t, scene: n, camera: r, stages: i, pipeline: a, getExposure: o, getSaturation: s, getTransparentBg: c }) {
16797
16789
  super(), this.renderer = e, this.mainCanvas = t, this.denoiserCanvas = this._createDenoiserCanvas(t), this.scene = n, this.camera = r, this.pipeline = a, this._stages = i, this._getExposure = o, this._getSaturation = s, this._getTransparentBg = c, this.denoiser = null, this.upscaler = null, this._lastRenderWidth = 0, this._lastRenderHeight = 0, this._pendingStartUpscaler = null, this._denoiserStartHandler = null, this._denoiserEndHandler = null, this._upscalerResChangedHandler = null, this._upscalerStartHandler = null, this._upscalerProgressHandler = null, this._upscalerEndHandler = null;
16798
16790
  }
@@ -16813,7 +16805,7 @@ var mm = {
16813
16805
  setupDenoiser() {
16814
16806
  if (!this.denoiserCanvas) return;
16815
16807
  let e = this._stages.pathTracer;
16816
- this.denoiser = new cm(this.denoiserCanvas, this.renderer, this.scene, this.camera, {
16808
+ this.denoiser = new um(this.denoiserCanvas, this.renderer, this.scene, this.camera, {
16817
16809
  ...J,
16818
16810
  backendParams: () => ({
16819
16811
  device: this.renderer.backend.device,
@@ -16838,7 +16830,7 @@ var mm = {
16838
16830
  setupUpscaler() {
16839
16831
  if (!this.denoiserCanvas) return;
16840
16832
  let e = this._stages.pathTracer;
16841
- this.upscaler = new hm(this.denoiserCanvas, this.renderer, {
16833
+ this.upscaler = new _m(this.denoiserCanvas, this.renderer, {
16842
16834
  scaleFactor: J.upscalerScale || 2,
16843
16835
  quality: J.upscalerQuality || "fast",
16844
16836
  getSourceCanvas: () => this.denoiser?.enabled ? null : this.renderer.domElement,
@@ -16859,6 +16851,9 @@ var mm = {
16859
16851
  progress: e.progress
16860
16852
  }), this._upscalerEndHandler = () => this.dispatchEvent({ type: dr.UPSCALING_END }), this.upscaler.addEventListener("resolution_changed", this._upscalerResChangedHandler), this.upscaler.addEventListener("start", this._upscalerStartHandler), this.upscaler.addEventListener("progress", this._upscalerProgressHandler), this.upscaler.addEventListener("end", this._upscalerEndHandler);
16861
16853
  }
16854
+ get denoiserStrategy() {
16855
+ return this._stages.asvgf?.enabled ? "asvgf" : this._stages.edgeFilter?.enabled ? "edgeaware" : "none";
16856
+ }
16862
16857
  setDenoiserStrategy(e, t) {
16863
16858
  let n = this._stages;
16864
16859
  switch (n.asvgf && (n.asvgf.enabled = !1), n.variance && (n.variance.enabled = !1), n.bilateralFilter && (n.bilateralFilter.enabled = !1), n.edgeFilter && n.edgeFilter.setFilteringEnabled(!1), this._clearDenoiserTextures(), e) {
@@ -16983,7 +16978,7 @@ var mm = {
16983
16978
  let t = kr[e];
16984
16979
  t && (this._stages.asvgf?.updateParameters(t), this._stages.bilateralFilter?.updateParameters(t), this._stages.variance && t.varianceBoost !== void 0 && (this._stages.variance.varianceBoost.value = t.varianceBoost));
16985
16980
  }
16986
- }, _m = class {
16981
+ }, ym = class {
16987
16982
  constructor() {
16988
16983
  this.layer = "hud", this.visible = !1, this._tileBounds = null, this._imageWidth = 1, this._imageHeight = 1, this.enabled = !0, this._borderColor = "rgba(255, 0, 0, 0.6)", this._borderWidthRatio = 1 / 540, this._borderWidthMin = 1.5, this._borderWidthMax = 4;
16989
16984
  }
@@ -17007,7 +17002,7 @@ var mm = {
17007
17002
  dispose() {
17008
17003
  this.visible = !1;
17009
17004
  }
17010
- }, vm = class {
17005
+ }, bm = class {
17011
17006
  constructor(n, r) {
17012
17007
  this.layer = "scene", this._enabled = !0, this._outlineNode = xn(n, r, {
17013
17008
  selectedObjects: [],
@@ -17038,11 +17033,11 @@ var mm = {
17038
17033
  this._enabled = !1, this._outlineNode?.dispose(), this._material?.dispose(), this._quad = null;
17039
17034
  }
17040
17035
  };
17041
- function ym(e = !1) {
17036
+ function xm(e = !1) {
17042
17037
  let t = document.createElement("canvas");
17043
17038
  return t.style.cssText = "position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;" + (e ? "display:none;" : ""), t;
17044
17039
  }
17045
- function bm(e, t = Infinity) {
17040
+ function Sm(e, t = Infinity) {
17046
17041
  let n = e?.getBoundingClientRect();
17047
17042
  if (!n || n.width === 0 || n.height === 0) return null;
17048
17043
  let r = Math.min(window.devicePixelRatio || 1, 2), i = Math.round(n.width * r), a = Math.round(n.height * r), o = t / Math.max(i, a);
@@ -17053,9 +17048,9 @@ function bm(e, t = Infinity) {
17053
17048
  }
17054
17049
  //#endregion
17055
17050
  //#region src/managers/helpers/ViewOverlayRenderer.js
17056
- var xm = 4096, Sm = class {
17051
+ var Cm = 4096, wm = class {
17057
17052
  constructor() {
17058
- this.canvas = ym(!0), this._visible = !1, this.renderer = null, this._sizeSource = null;
17053
+ this.canvas = xm(!0), this._visible = !1, this.renderer = null, this._sizeSource = null;
17059
17054
  }
17060
17055
  async init({ device: e, sizeSource: t }) {
17061
17056
  this._sizeSource = t;
@@ -17072,7 +17067,7 @@ var xm = 4096, Sm = class {
17072
17067
  }
17073
17068
  syncSize() {
17074
17069
  if (!this.renderer) return;
17075
- let e = bm(this._sizeSource, xm);
17070
+ let e = Sm(this._sizeSource, Cm);
17076
17071
  !e || e.width === this.canvas.width && e.height === this.canvas.height || this.renderer.setSize(e.width, e.height, !1);
17077
17072
  }
17078
17073
  begin() {
@@ -17084,18 +17079,18 @@ var xm = 4096, Sm = class {
17084
17079
  dispose() {
17085
17080
  xr(this.renderer), this.renderer = null, this.canvas.parentElement?.removeChild(this.canvas);
17086
17081
  }
17087
- }, Cm = ai("overlay"), wm = (e, t) => e.visible && e.layer === t && e.render, Tm = class {
17082
+ }, Tm = ai("overlay"), Em = (e, t) => e.visible && e.layer === t && e.render, Dm = class {
17088
17083
  constructor(e) {
17089
- this.camera = e, this._helpers = /* @__PURE__ */ new Map(), this._hudCanvas = ym(), this._hudCtx = this._hudCanvas.getContext("2d"), this._helperScene = null, this._viewOverlay = null;
17084
+ this.camera = e, this._helpers = /* @__PURE__ */ new Map(), this._hudCanvas = xm(), this._hudCtx = this._hudCanvas.getContext("2d"), this._helperScene = null, this._viewOverlay = null;
17090
17085
  }
17091
17086
  async initViewRenderer({ device: e, sizeSource: t }) {
17092
17087
  if (!(!e || !t)) try {
17093
- this._viewOverlay = await new Sm().init({
17088
+ this._viewOverlay = await new wm().init({
17094
17089
  device: e,
17095
17090
  sizeSource: t
17096
17091
  });
17097
17092
  } catch (e) {
17098
- Cm.error("overlay surface unavailable — light gizmos, transform gizmo and outlines are disabled", e), this._viewOverlay = null;
17093
+ Tm.error("overlay surface unavailable — light gizmos, transform gizmo and outlines are disabled", e), this._viewOverlay = null;
17099
17094
  }
17100
17095
  }
17101
17096
  setHelperScene(e) {
@@ -17111,11 +17106,11 @@ var xm = 4096, Sm = class {
17111
17106
  }
17112
17107
  setupDefaultHelpers({ helperScene: e, meshScene: t, pipeline: n, denoisingManager: r, app: i, renderWidth: a, renderHeight: o }) {
17113
17108
  this.setHelperScene(e);
17114
- let s = new _m();
17109
+ let s = new ym();
17115
17110
  this.register("tiles", s), s.setRenderSize(a || 1, o || 1), i.addEventListener("resolution_changed", (e) => {
17116
17111
  s.setRenderSize(e.width, e.height);
17117
17112
  }), n.eventBus.on("pipeline:reset", () => s.hide()), this._wireDenoiserTileEvents(s, r);
17118
- let c = new vm(t, this.camera);
17113
+ let c = new bm(t, this.camera);
17119
17114
  this.register("outline", c);
17120
17115
  }
17121
17116
  _wireDenoiserTileEvents(e, t) {
@@ -17127,7 +17122,7 @@ var xm = 4096, Sm = class {
17127
17122
  }));
17128
17123
  }
17129
17124
  register(e, t) {
17130
- this._helpers.has(e) && (Cm.warn(`helper "${e}" already registered — replacing.`), this._helpers.get(e).dispose?.()), this._helpers.set(e, t);
17125
+ this._helpers.has(e) && (Tm.warn(`helper "${e}" already registered — replacing.`), this._helpers.get(e).dispose?.()), this._helpers.set(e, t);
17131
17126
  }
17132
17127
  unregister(e) {
17133
17128
  let t = this._helpers.get(e);
@@ -17165,16 +17160,16 @@ var xm = 4096, Sm = class {
17165
17160
  }
17166
17161
  _renderSceneLayer(e) {
17167
17162
  this._helperScene?.render(e, this.camera);
17168
- for (let t of this._helpers.values()) wm(t, "scene") && t.render(e, this.camera);
17163
+ for (let t of this._helpers.values()) Em(t, "scene") && t.render(e, this.camera);
17169
17164
  }
17170
17165
  _hasVisibleSceneOverlay() {
17171
17166
  if (this._helperScene?.isDrawing) return !0;
17172
- for (let e of this._helpers.values()) if (wm(e, "scene")) return !0;
17167
+ for (let e of this._helpers.values()) if (Em(e, "scene")) return !0;
17173
17168
  return !1;
17174
17169
  }
17175
17170
  refreshHUD() {
17176
17171
  let e = this._hudCanvas, t = this._hudCtx, n = !1;
17177
- for (let e of this._helpers.values()) if (wm(e, "hud")) {
17172
+ for (let e of this._helpers.values()) if (Em(e, "hud")) {
17178
17173
  n = !0;
17179
17174
  break;
17180
17175
  }
@@ -17183,10 +17178,10 @@ var xm = 4096, Sm = class {
17183
17178
  return;
17184
17179
  }
17185
17180
  e.style.display !== "" && (e.style.display = "");
17186
- let r = e.clientWidth, i = e.clientHeight, a = r > 0 && i > 0 ? bm(e) : null;
17181
+ let r = e.clientWidth, i = e.clientHeight, a = r > 0 && i > 0 ? Sm(e) : null;
17187
17182
  if (a) {
17188
17183
  (e.width !== a.width || e.height !== a.height) && (e.width = a.width, e.height = a.height), t.clearRect(0, 0, a.width, a.height), t.save(), t.scale(a.width / r, a.height / i);
17189
- for (let e of this._helpers.values()) wm(e, "hud") && e.render(t, r, i);
17184
+ for (let e of this._helpers.values()) Em(e, "hud") && e.render(t, r, i);
17190
17185
  t.restore(), e.style.display !== "" && (e.style.display = "");
17191
17186
  }
17192
17187
  }
@@ -17194,7 +17189,7 @@ var xm = 4096, Sm = class {
17194
17189
  for (let e of this._helpers.values()) e.dispose?.();
17195
17190
  this._helpers.clear(), this._viewOverlay?.dispose(), this._viewOverlay = null, this._hudCanvas.parentElement && this._hudCanvas.parentElement.removeChild(this._hudCanvas);
17196
17191
  }
17197
- }, Em = class extends ut {
17192
+ }, Om = class extends ut {
17198
17193
  constructor() {
17199
17194
  super(), this.mixer = null, this.timer = new nn(), this.actions = [], this.isPlaying = !1, this._scene = null, this._mixerRoot = null, this._meshes = null, this._meshTriRanges = null, this._posBuffer = null, this._tempVec = new cn(), this._skinnedCache = null, this._clipsCache = null, this._savedTimeScale = 1, this.onFinished = null, this.wakeCallback = null;
17200
17195
  }
@@ -17294,7 +17289,7 @@ var xm = 4096, Sm = class {
17294
17289
  dispose() {
17295
17290
  this.mixer &&= (this.mixer.stopAllAction(), this.mixer.uncacheRoot(this._mixerRoot), null), this.actions = [], this.isPlaying = !1, this.timer.reset(), this._scene = null, this._mixerRoot = null, this._meshes = null, this._meshTriRanges = null, this._posBuffer = null, this._skinnedCache = null, this._clipsCache = null;
17296
17291
  }
17297
- }, Dm = new cn(0, 0, -1), Om = class {
17292
+ }, km = new cn(0, 0, -1), Am = class {
17298
17293
  constructor({ camera: e, canvas: t, orbitControls: n, app: r }) {
17299
17294
  this._app = r, this._orbitControls = n, this._camera = e, this._controls = new Sn(e, t), this._gizmoScene = new Yt(), this._gizmoScene.add(this._controls.getHelper()), this._attached = null, this._isDragging = !1, this._meshes = null, this._meshTriRanges = null, this._posBuffer = null, this._normalBuffer = null, this._skinnedCache = null, this._normalCache = null, this._tempVec = new cn(), this._normalMatrix = new St(), this._refitInFlight = !1, this._baselineComputed = !1, this._tempForward = new cn(), this._lightTargetDistance = null, this._lastLightPosition = null, this._onDraggingChanged = this._onDraggingChanged.bind(this), this._onObjectChange = this._onObjectChange.bind(this), this._controls.addEventListener("dragging-changed", this._onDraggingChanged), this._controls.addEventListener("objectChange", this._onObjectChange);
17300
17295
  }
@@ -17315,7 +17310,7 @@ var xm = 4096, Sm = class {
17315
17310
  attach(e) {
17316
17311
  if (this._attached !== e && (this._controls.attach(e), this._attached = e, this._lightTargetDistance = null, this._lastLightPosition = null, e.isLight && e.target)) {
17317
17312
  let t = e.target.position.clone().sub(e.position), n = t.length();
17318
- n > 1e-4 ? (e.quaternion.setFromUnitVectors(Dm, t.normalize()), this._lightTargetDistance = n) : this._lightTargetDistance = 1, this._lastLightPosition = e.position.clone();
17313
+ n > 1e-4 ? (e.quaternion.setFromUnitVectors(km, t.normalize()), this._lightTargetDistance = n) : this._lightTargetDistance = 1, this._lastLightPosition = e.position.clone();
17319
17314
  }
17320
17315
  }
17321
17316
  detach() {
@@ -17427,7 +17422,7 @@ var xm = 4096, Sm = class {
17427
17422
  dispose() {
17428
17423
  this._controls.removeEventListener("dragging-changed", this._onDraggingChanged), this._controls.removeEventListener("objectChange", this._onObjectChange), this.detach(), this._gizmoScene.remove(this._controls.getHelper()), this._controls.dispose(), this._meshes = null, this._meshTriRanges = null, this._posBuffer = null, this._normalBuffer = null, this._skinnedCache = null, this._normalCache = null, this._baselineComputed = !1, this._tempForward = null, this._lightTargetDistance = null, this._lastLightPosition = null, this._app = null, this._orbitControls = null, this._camera = null, this._controls = null, this._gizmoScene = null;
17429
17424
  }
17430
- }, km = class {
17425
+ }, jm = class {
17431
17426
  constructor(e) {
17432
17427
  this.layer = "scene", this._transformManager = e, this._enabled = !0;
17433
17428
  }
@@ -17446,15 +17441,15 @@ var xm = 4096, Sm = class {
17446
17441
  dispose() {
17447
17442
  this._enabled = !1;
17448
17443
  }
17449
- }, Am = /* @__PURE__ */ new WeakMap(), jm = ai("engine"), Mm = class extends ut {
17444
+ }, Mm = /* @__PURE__ */ new WeakMap(), Nm = ai("engine"), Pm = class extends ut {
17450
17445
  constructor(e, t = {}) {
17451
17446
  super();
17452
17447
  try {
17453
- Am.get(e)?.dispose();
17448
+ Mm.get(e)?.dispose();
17454
17449
  } catch (e) {
17455
- jm.warn("prior canvas owner dispose failed", e);
17450
+ Nm.warn("prior canvas owner dispose failed", e);
17456
17451
  }
17457
- Am.set(e, this), this.canvas = e, this._autoResize = t.autoResize !== !1, this._container = t.container || null, this.settings = new wp(J), this.renderer = null, this.scene = null, this.meshScene = null, this._sceneHelpers = null, this.assetLoader = null, this._sdf = null, this._animRefitInFlight = !1, this._maxTextureSize = J.maxTextureSize, this.pipeline = null, this.stages = {}, this.cameraManager = null, this.lightManager = null, this.goboManager = null, this.iesManager = null, this.denoisingManager = null, this.overlayManager = null, this.interactionManager = null, this.transformManager = null, this.animationManager = new Em(), this.environmentManager = null, this.isInitialized = !1, this.pauseRendering = !1, this.pathTracerEnabled = !0, this.animationManagerId = null, this.needsReset = !1, this._loadingInProgress = !1, this._needsDisplayRefresh = !1, this._paused = !1, this._emissiveSamplingUserSet = !1, this.completion = new zf(), this._resizeDebounceTimer = null, this._trackedListeners = [], this._disposed = !1, this._deviceLost = !1, this._deterministic = !1, this._dispatchPinned = !1, this._deterministicRestore = null;
17452
+ Mm.set(e, this), this.canvas = e, this._autoResize = t.autoResize !== !1, this._container = t.container || null, this.settings = new Ep(J), this.renderer = null, this.scene = null, this.meshScene = null, this._sceneHelpers = null, this.assetLoader = null, this._sdf = null, this._animRefitInFlight = !1, this._maxTextureSize = J.maxTextureSize, this.pipeline = null, this.stages = {}, this.cameraManager = null, this.lightManager = null, this.goboManager = null, this.iesManager = null, this.denoisingManager = null, this.overlayManager = null, this.interactionManager = null, this.transformManager = null, this.animationManager = new Om(), this.environmentManager = null, this.isInitialized = !1, this.pauseRendering = !1, this.pathTracerEnabled = !0, this.animationManagerId = null, this.needsReset = !1, this._loadingInProgress = !1, this._needsDisplayRefresh = !1, this._paused = !1, this._emissiveSamplingUserSet = !1, this.completion = new Vf(), this._resizeDebounceTimer = null, this._trackedListeners = [], this._disposed = !1, this._deviceLost = !1, this._deterministic = !1, this._dispatchPinned = !1, this._deterministicRestore = null;
17458
17453
  }
17459
17454
  _addTrackedListener(e, t, n) {
17460
17455
  e && (e.addEventListener(t, n), this._trackedListeners.push({
@@ -17467,12 +17462,12 @@ var xm = 4096, Sm = class {
17467
17462
  for (let { target: e, type: t, handler: n } of this._trackedListeners) try {
17468
17463
  e.removeEventListener(t, n);
17469
17464
  } catch (e) {
17470
- jm.warn("failed to remove listener", t, e);
17465
+ Nm.warn("failed to remove listener", t, e);
17471
17466
  }
17472
17467
  this._trackedListeners.length = 0;
17473
17468
  }
17474
17469
  async init() {
17475
- return await this._initRenderer(), this._initCameraManager(), this._initScenes(), this._initAssetPipeline(), this._initPipeline(), await this._initManagers(), this._wireEvents(), this.stages.pathTracer.setTriangleData(new Float32Array(32), 0), this.stages.pathTracer.setBVHData(new Float32Array(16)), this.stages.pathTracer.materialData.setMaterialData(new Float32Array(16)), this.stages.pathTracer.setupMaterial(), this.isInitialized = !0, jm.debug("WebGPU path tracer app initialized"), this;
17470
+ return await this._initRenderer(), this._initCameraManager(), this._initScenes(), this._initAssetPipeline(), this._initPipeline(), await this._initManagers(), this._wireEvents(), this.stages.pathTracer.setTriangleData(new Float32Array(32), 0), this.stages.pathTracer.setBVHData(new Float32Array(16)), this.stages.pathTracer.materialData.setMaterialData(new Float32Array(16)), this.stages.pathTracer.setupMaterial(), this.isInitialized = !0, Nm.debug("WebGPU path tracer app initialized"), this;
17476
17471
  }
17477
17472
  animate() {
17478
17473
  if (!this._deviceLost) {
@@ -17482,7 +17477,7 @@ var xm = 4096, Sm = class {
17482
17477
  }
17483
17478
  if (this.cameraManager.controls && this.cameraManager.controls.update(), this.animationManager?.isPlaying && !this._animRefitInFlight) {
17484
17479
  let e = this.animationManager.update();
17485
- e && (this._animRefitInFlight = !0, this.refitBVH(e).catch((e) => jm.error("animation refit error:", e)).finally(() => {
17480
+ e && (this._animRefitInFlight = !0, this.refitBVH(e).catch((e) => Nm.error("animation refit error:", e)).finally(() => {
17486
17481
  this._animRefitInFlight = !1;
17487
17482
  }));
17488
17483
  }
@@ -17516,7 +17511,7 @@ var xm = 4096, Sm = class {
17516
17511
  this.animationManagerId &&= (cancelAnimationFrame(this.animationManagerId), null);
17517
17512
  }
17518
17513
  _handleDeviceLost(e) {
17519
- this._deviceLost || (this._deviceLost = !0, jm.error(`WebGPU device lost (${e?.reason || "unknown"}): ${e?.message || ""}`), this.stopAnimation(), this.dispatchEvent({
17514
+ this._deviceLost || (this._deviceLost = !0, Nm.error(`WebGPU device lost (${e?.reason || "unknown"}): ${e?.message || ""}`), this.stopAnimation(), this.dispatchEvent({
17520
17515
  type: dr.DEVICE_LOST,
17521
17516
  reason: e?.reason,
17522
17517
  message: e?.message
@@ -17554,7 +17549,7 @@ var xm = 4096, Sm = class {
17554
17549
  let e = je().value, t = k().value;
17555
17550
  e?._listeners?.dispose && (e._listeners.dispose.length = 0), t?._listeners?.dispose && (t._listeners.dispose.length = 0);
17556
17551
  } catch (e) {
17557
- jm.warn("failed to clear TSL texture singleton listeners", e);
17552
+ Nm.warn("failed to clear TSL texture singleton listeners", e);
17558
17553
  }
17559
17554
  xr(this.renderer), this.renderer = null, this.stages = {}, this.isInitialized = !1;
17560
17555
  }
@@ -17640,7 +17635,7 @@ var xm = 4096, Sm = class {
17640
17635
  try {
17641
17636
  await this.renderer.compileAsync(this.meshScene, this.cameraManager.camera);
17642
17637
  } catch (e) {
17643
- jm.warn("raster fallback precompile failed", e);
17638
+ Nm.warn("raster fallback precompile failed", e);
17644
17639
  }
17645
17640
  e.end("Pipeline precompile"), n && (hr({
17646
17641
  status: "Finalizing environment map...",
@@ -17778,7 +17773,7 @@ var xm = 4096, Sm = class {
17778
17773
  return Y;
17779
17774
  }
17780
17775
  _isRenderSizeSupported(e, t) {
17781
- return e > Y || t > Y ? (jm.warn(`render resolution ${e}×${t} exceeds the ${Y}px limit (compute storage textures are pre-allocated at ${Y}px). Ignoring resize — use a resolution ≤ ${Y}.`), !1) : !0;
17776
+ return e > Y || t > Y ? (Nm.warn(`render resolution ${e}×${t} exceeds the ${Y}px limit (compute storage textures are pre-allocated at ${Y}px). Ignoring resize — use a resolution ≤ ${Y}.`), !1) : !0;
17782
17777
  }
17783
17778
  onResize() {
17784
17779
  let e = this.canvas.clientWidth, t = this.canvas.clientHeight;
@@ -17890,6 +17885,39 @@ var xm = 4096, Sm = class {
17890
17885
  total: t + n
17891
17886
  };
17892
17887
  }
17888
+ async getKernelGPUTimings() {
17889
+ let e = this.renderer;
17890
+ if (!e?.backend?.trackTimestamp) return null;
17891
+ await e.resolveTimestampsAsync("compute");
17892
+ let t = e.backend.timestampQueryPool?.compute?.timestamps;
17893
+ if (!t || t.size === 0) return null;
17894
+ let n = /* @__PURE__ */ new Map(), r = this.stages?.pathTracer?._kernelManager?.kernels;
17895
+ if (r) for (let [e, t] of r) n.set(t.id, e);
17896
+ let i = [], a = -1;
17897
+ for (let [e, n] of t) {
17898
+ let t = e.split(":");
17899
+ if (t.length !== 4) continue;
17900
+ let r = Number(t[3].slice(1));
17901
+ Number.isFinite(r) && (i.push({
17902
+ nodeId: Number(t[2]),
17903
+ f: r,
17904
+ ms: n
17905
+ }), r > a && (a = r));
17906
+ }
17907
+ let o = {}, s = 0, c = 0;
17908
+ for (let e of i) {
17909
+ if (e.f !== a) continue;
17910
+ s += e.ms;
17911
+ let t = n.get(e.nodeId);
17912
+ t === void 0 ? c += e.ms : o[t] = (o[t] ?? 0) + e.ms;
17913
+ }
17914
+ return {
17915
+ kernels: o,
17916
+ total: s,
17917
+ unattributed: c,
17918
+ frame: a
17919
+ };
17920
+ }
17893
17921
  getCanvas() {
17894
17922
  if (!this.renderer?.domElement) return null;
17895
17923
  let e = this.denoisingManager;
@@ -18008,40 +18036,40 @@ var xm = 4096, Sm = class {
18008
18036
  let n = this.renderer.backend?.device;
18009
18037
  n?.lost && (n.lost.then((e) => {
18010
18038
  this._disposed || this._handleDeviceLost(e);
18011
- }), n.onuncapturederror = (e) => jm.error("WebGPU uncaptured error:", e.error)), r.setLTC(ln.init()), this.renderer.outputColorSpace = a, this.renderer.toneMapping = Ue, this.renderer.toneMappingExposure = 1, this.renderer.setPixelRatio(1);
18039
+ }), n.onuncapturederror = (e) => Nm.error("WebGPU uncaptured error:", e.error)), r.setLTC(ln.init()), this.renderer.outputColorSpace = a, this.renderer.toneMapping = Ue, this.renderer.toneMappingExposure = 1, this.renderer.setPixelRatio(1);
18012
18040
  }
18013
18041
  _initCameraManager() {
18014
- this.cameraManager = new Tp(this.canvas);
18042
+ this.cameraManager = new Dp(this.canvas);
18015
18043
  }
18016
18044
  _initScenes() {
18017
18045
  this.scene = new Yt(), this.meshScene = new Yt(), this._sceneHelpers = new Pn();
18018
18046
  }
18019
18047
  _initAssetPipeline() {
18020
- this._sdf = new Qc(), this.assetLoader = new xp(this.meshScene, this.cameraManager.camera, this.cameraManager.controls), this.assetLoader.setRenderer(this.renderer), this.assetLoader.createFloorPlane(), this._addTrackedListener(this.cameraManager.controls, "change", () => {
18048
+ this._sdf = new Qc(), this.assetLoader = new Cp(this.meshScene, this.cameraManager.camera, this.cameraManager.controls), this.assetLoader.setRenderer(this.renderer), this.assetLoader.createFloorPlane(), this._addTrackedListener(this.cameraManager.controls, "change", () => {
18021
18049
  this.needsReset = !0, this.wake();
18022
18050
  });
18023
18051
  }
18024
18052
  _initPipeline() {
18025
18053
  this._createStages();
18026
18054
  let { clientWidth: e, clientHeight: t } = this.canvas;
18027
- this.pipeline = new Rf(this.renderer, e || 1, t || 1), this.pipeline.addStage(this.stages.pathTracer), this.pipeline.addStage(this.stages.normalDepth), this.pipeline.addStage(this.stages.motionVector), this.pipeline.addStage(this.stages.asvgf), this.pipeline.addStage(this.stages.variance), this.pipeline.addStage(this.stages.bilateralFilter), this.pipeline.addStage(this.stages.edgeFilter), this.pipeline.addStage(this.stages.autoExposure), this.pipeline.addStage(this.stages.compositor);
18055
+ this.pipeline = new Bf(this.renderer, e || 1, t || 1), this.pipeline.addStage(this.stages.pathTracer), this.pipeline.addStage(this.stages.normalDepth), this.pipeline.addStage(this.stages.motionVector), this.pipeline.addStage(this.stages.asvgf), this.pipeline.addStage(this.stages.variance), this.pipeline.addStage(this.stages.bilateralFilter), this.pipeline.addStage(this.stages.edgeFilter), this.pipeline.addStage(this.stages.autoExposure), this.pipeline.addStage(this.stages.compositor);
18028
18056
  let n = this.canvas.clientWidth || 1, r = this.canvas.clientHeight || 1;
18029
18057
  this.pipeline.setSize(n, r);
18030
18058
  }
18031
18059
  async _initManagers() {
18032
- this.interactionManager = new Bf({
18060
+ this.interactionManager = new Hf({
18033
18061
  scene: this.meshScene,
18034
18062
  camera: this.cameraManager.camera,
18035
18063
  canvas: this.canvas,
18036
18064
  assetLoader: this.assetLoader,
18037
18065
  pathTracer: null,
18038
18066
  floorPlane: this.assetLoader.floorPlane
18039
- }), this.interactionManager.wireAppEvents(this), this.cameraManager.setInteractionManager(this.interactionManager), this.lightManager = new Ep(this.scene, this._sceneHelpers, this.stages.pathTracer, { onReset: () => this.reset() }), this.goboManager = new Dp(this.stages.pathTracer, { onReset: () => this.reset() }), this.iesManager = new Rp(this.stages.pathTracer, { onReset: () => this.reset() }), this._setupDenoisingManager(), await this._setupOverlayManager(), this.transformManager = new Om({
18067
+ }), this.interactionManager.wireAppEvents(this), this.cameraManager.setInteractionManager(this.interactionManager), this.lightManager = new Op(this.scene, this._sceneHelpers, this.stages.pathTracer, { onReset: () => this.reset() }), this.goboManager = new kp(this.stages.pathTracer, { onReset: () => this.reset() }), this.iesManager = new Bp(this.stages.pathTracer, { onReset: () => this.reset() }), this._setupDenoisingManager(), await this._setupOverlayManager(), this.transformManager = new Am({
18040
18068
  camera: this.cameraManager.camera,
18041
18069
  canvas: this.canvas,
18042
18070
  orbitControls: this.cameraManager.controls,
18043
18071
  app: this
18044
- }), this.overlayManager.register("transform", new km(this.transformManager)), this.interactionManager.setDependencies({
18072
+ }), this.overlayManager.register("transform", new jm(this.transformManager)), this.interactionManager.setDependencies({
18045
18073
  overlayManager: this.overlayManager,
18046
18074
  transformManager: this.transformManager,
18047
18075
  appDispatch: (e) => this.dispatchEvent(e),
@@ -18085,7 +18113,9 @@ var xm = 4096, Sm = class {
18085
18113
  stages: this.stages,
18086
18114
  renderer: this.renderer,
18087
18115
  resetCallback: () => this.reset(),
18088
- reconcileCompletion: () => this._reconcileCompletion()
18116
+ reconcileCompletion: () => this._reconcileCompletion(),
18117
+ denoisingManager: this.denoisingManager,
18118
+ cameraManager: this.cameraManager
18089
18119
  }), this.renderer.toneMappingExposure = this.settings.get("exposure") ?? 1, this.onResize(), this.resizeHandler = () => this.onResize(), this._autoResize && this._addTrackedListener(window, "resize", this.resizeHandler), this._onAssetLoaded = async (e) => {
18090
18120
  if (!this._loadingInProgress) {
18091
18121
  if (e.model) this._clearAppendedModels(), await this.loadSceneData();
@@ -18111,10 +18141,10 @@ var xm = 4096, Sm = class {
18111
18141
  this.transformManager?.setMeshData(this._sdf.meshes);
18112
18142
  }
18113
18143
  _createStages() {
18114
- this.stages.pathTracer = new tf(this.renderer, this.scene, this.cameraManager.camera), this.stages.normalDepth = new nf(this.renderer, { pathTracer: this.stages.pathTracer }), this.stages.motionVector = new rf(this.renderer, this.cameraManager.camera, { pathTracer: this.stages.pathTracer }), this.stages.asvgf = new sf(this.renderer, { enabled: !1 }), this.stages.variance = new uf(this.renderer, { enabled: !1 }), this.stages.bilateralFilter = new ff(this.renderer, { enabled: !1 }), this.stages.edgeFilter = new _f(this.renderer, { enabled: !1 }), this.stages.autoExposure = new wf(this.renderer, { enabled: J.autoExposure ?? !1 }), this.stages.compositor = new Tf(this.renderer, { saturation: this.settings.get("saturation") ?? J.saturation });
18144
+ this.stages.pathTracer = new rf(this.renderer, this.scene, this.cameraManager.camera), this.stages.normalDepth = new af(this.renderer, { pathTracer: this.stages.pathTracer }), this.stages.motionVector = new of(this.renderer, this.cameraManager.camera, { pathTracer: this.stages.pathTracer }), this.stages.asvgf = new lf(this.renderer, { enabled: !1 }), this.stages.variance = new ff(this.renderer, { enabled: !1 }), this.stages.bilateralFilter = new mf(this.renderer, { enabled: !1 }), this.stages.edgeFilter = new yf(this.renderer, { enabled: !1 }), this.stages.autoExposure = new Ef(this.renderer, { enabled: J.autoExposure ?? !1 }), this.stages.compositor = new Df(this.renderer, { saturation: this.settings.get("saturation") ?? J.saturation });
18115
18145
  }
18116
18146
  _setupDenoisingManager() {
18117
- this.denoisingManager = new gm({
18147
+ this.denoisingManager = new vm({
18118
18148
  renderer: this.renderer,
18119
18149
  mainCanvas: this.canvas,
18120
18150
  scene: this.scene,
@@ -18157,7 +18187,7 @@ var xm = 4096, Sm = class {
18157
18187
  this.scene.updateMatrixWorld(), this.overlayManager?.render();
18158
18188
  }
18159
18189
  async _setupOverlayManager() {
18160
- this.overlayManager = new Tm(this.cameraManager.camera), this.overlayManager.setupDefaultHelpers({
18190
+ this.overlayManager = new Dm(this.cameraManager.camera), this.overlayManager.setupDefaultHelpers({
18161
18191
  helperScene: this._sceneHelpers,
18162
18192
  meshScene: this.meshScene,
18163
18193
  pipeline: this.pipeline,
@@ -18188,7 +18218,7 @@ var xm = 4096, Sm = class {
18188
18218
  _forwardEvents(e, t) {
18189
18219
  if (e) for (let n of t) this._addTrackedListener(e, n, (e) => this.dispatchEvent(e));
18190
18220
  }
18191
- }, Nm = class {
18221
+ }, Fm = class {
18192
18222
  constructor(e) {
18193
18223
  this._app = e, this._cancelled = !1, this._rendering = !1;
18194
18224
  }
@@ -18286,4 +18316,4 @@ var xm = 4096, Sm = class {
18286
18316
  }
18287
18317
  };
18288
18318
  //#endregion
18289
- export { Pr as AF_DEFAULTS, kr as ASVGF_QUALITY_PRESETS, Nr as AUTO_FOCUS_MODES, Em as AnimationManager, Fr as BVH_LEAF_MARKERS, Mr as CAMERA_PRESETS, Ar as CAMERA_RANGES, Tp as CameraManager, Br as DEFAULT_TEXTURE_MATRIX, gm as DenoisingManager, J as ENGINE_DEFAULTS, dr as EngineEvents, Dp as GoboManager, Rp as IESManager, Hr as INTERACTIVE_RENDER_CONFIG, Bf as InteractionManager, Wr as LOG_LEVELS, Ep as LightManager, ii as Logger, Ur as MEMORY_CONSTANTS, Tm as OverlayManager, Vr as PRODUCTION_RENDER_CONFIG, Mm as PathTracerApp, Ef as PipelineContext, Rf as RenderPipeline, wp as RenderSettings, lr as RenderStage, jr as SKY_PRESETS, cr as StageExecutionMode, Ir as TEXTURE_CONSTANTS, X as TRIANGLE_DATA_LAYOUT, Om as TransformManager, uu as VRAMTracker, Nm as VideoRenderManager, cu as bufferBytes, Nf as clearBindingAuditFindings, sl as configureAssets, ai as createLogger, Q as fmt, cl as getAssetConfig, Mf as getBindingAuditFindings, jf as setBindingAudit, lu as textureBytes };
18319
+ export { Pr as AF_DEFAULTS, kr as ASVGF_QUALITY_PRESETS, Nr as AUTO_FOCUS_MODES, Om as AnimationManager, Fr as BVH_LEAF_MARKERS, Mr as CAMERA_PRESETS, Ar as CAMERA_RANGES, Dp as CameraManager, Br as DEFAULT_TEXTURE_MATRIX, vm as DenoisingManager, J as ENGINE_DEFAULTS, dr as EngineEvents, kp as GoboManager, Bp as IESManager, Hr as INTERACTIVE_RENDER_CONFIG, Hf as InteractionManager, Wr as LOG_LEVELS, Op as LightManager, ii as Logger, Ur as MEMORY_CONSTANTS, Dm as OverlayManager, Vr as PRODUCTION_RENDER_CONFIG, Pm as PathTracerApp, Of as PipelineContext, Bf as RenderPipeline, Ep as RenderSettings, lr as RenderStage, jr as SKY_PRESETS, cr as StageExecutionMode, Ir as TEXTURE_CONSTANTS, X as TRIANGLE_DATA_LAYOUT, Am as TransformManager, uu as VRAMTracker, Fm as VideoRenderManager, cu as bufferBytes, Ff as clearBindingAuditFindings, sl as configureAssets, ai as createLogger, Q as fmt, cl as getAssetConfig, Pf as getBindingAuditFindings, Nf as setBindingAudit, lu as textureBytes };