rayzee 7.21.0 → 7.22.0
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/README.md +75 -4
- package/dist/rayzee.es.js +633 -604
- package/dist/rayzee.umd.js +52 -52
- package/package.json +1 -1
- package/src/EngineDefaults.js +6 -0
- package/src/PathTracerApp.js +76 -0
- package/src/Processor/BVHBuilder.js +1 -4
- package/src/Processor/KernelManager.js +17 -70
- package/src/Processor/QueueManager.js +4 -3
- package/src/Processor/SceneProcessor.js +10 -4
- package/src/Processor/TreeletOptimizer.js +0 -7
- package/src/RenderSettings.js +41 -6
- package/src/Stages/NormalDepth.js +16 -13
- package/src/Stages/PathTracer.js +29 -31
- package/src/TSL/BVHTraversal.js +1 -67
- package/src/TSL/CameraRay.js +141 -0
- package/src/TSL/DebugKernel.js +4 -5
- package/src/TSL/ExtendKernel.js +11 -3
- package/src/TSL/FinalWriteKernel.js +1 -14
- package/src/TSL/GenerateKernel.js +11 -8
- package/src/TSL/SortGlobalKernels.js +52 -7
- package/src/managers/DenoisingManager.js +13 -0
- package/src/managers/EnvironmentManager.js +6 -3
- package/src/managers/UniformManager.js +8 -1
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")
|
|
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.
|
|
4910
|
+
}, this.enableTreeletOptimization = !0, 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
|
|
5086
|
-
|
|
5087
|
-
let
|
|
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
|
|
5094
|
+
let i = n ? (t) => {
|
|
5090
5095
|
n(`Treelet optimization pass ${e + 1}/${this.treeletOptimizationPasses}: ${t}`);
|
|
5091
5096
|
} : null;
|
|
5092
5097
|
try {
|
|
5093
|
-
|
|
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
|
|
5099
|
-
if (
|
|
5103
|
+
let a = t.getStatistics(), o = performance.now() - r;
|
|
5104
|
+
if (a.treeletsImproved === 0 && e > 0 || o > 15e3) break;
|
|
5100
5105
|
}
|
|
5101
|
-
let
|
|
5102
|
-
this.splitStats.treeletOptimizationTime =
|
|
5103
|
-
let
|
|
5104
|
-
this.splitStats.treeletsProcessed =
|
|
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=!0,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=!0,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 {
|
|
@@ -7385,6 +7390,7 @@ var Zc = ai("scene"), Qc = class {
|
|
|
7385
7390
|
treeletSize: 7,
|
|
7386
7391
|
treeletOptimizationPasses: 1,
|
|
7387
7392
|
treeletMinImprovement: .01,
|
|
7393
|
+
treeletComplexityThreshold: 5e4,
|
|
7388
7394
|
...e
|
|
7389
7395
|
}, 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
7396
|
textureCreationTime: 0,
|
|
@@ -7401,7 +7407,8 @@ var Zc = ai("scene"), Qc = class {
|
|
|
7401
7407
|
enabled: this.config.enableTreeletOptimization,
|
|
7402
7408
|
size: this.config.treeletSize,
|
|
7403
7409
|
passes: this.config.treeletOptimizationPasses,
|
|
7404
|
-
minImprovement: this.config.treeletMinImprovement
|
|
7410
|
+
minImprovement: this.config.treeletMinImprovement,
|
|
7411
|
+
complexityThreshold: this.config.treeletComplexityThreshold
|
|
7405
7412
|
}), this.textureCreator = new Lc({ maxTextureSize: this.config.maxTextureSize }), this.emissiveTriangleBuilder = new Kc(), this.tlasBuilder = new kc();
|
|
7406
7413
|
}
|
|
7407
7414
|
_log(e, t) {
|
|
@@ -7489,7 +7496,8 @@ var Zc = ai("scene"), Qc = class {
|
|
|
7489
7496
|
enabled: i !== !1,
|
|
7490
7497
|
size: this.config.treeletSize,
|
|
7491
7498
|
passes: this.config.treeletOptimizationPasses,
|
|
7492
|
-
minImprovement: this.config.treeletMinImprovement
|
|
7499
|
+
minImprovement: this.config.treeletMinImprovement,
|
|
7500
|
+
complexityThreshold: this.config.treeletComplexityThreshold
|
|
7493
7501
|
},
|
|
7494
7502
|
reinsertionOptimization: {
|
|
7495
7503
|
enabled: this.bvhBuilder.enableReinsertionOptimization,
|
|
@@ -7795,7 +7803,8 @@ var Zc = ai("scene"), Qc = class {
|
|
|
7795
7803
|
enabled: this.config.enableTreeletOptimization,
|
|
7796
7804
|
size: this.config.treeletSize,
|
|
7797
7805
|
passes: this.config.treeletOptimizationPasses,
|
|
7798
|
-
minImprovement: this.config.treeletMinImprovement
|
|
7806
|
+
minImprovement: this.config.treeletMinImprovement,
|
|
7807
|
+
complexityThreshold: this.config.treeletComplexityThreshold
|
|
7799
7808
|
})), this._log("Configuration updated", this.config);
|
|
7800
7809
|
}
|
|
7801
7810
|
async refitBVH(e, t) {
|
|
@@ -7956,7 +7965,8 @@ var Zc = ai("scene"), Qc = class {
|
|
|
7956
7965
|
enabled: s,
|
|
7957
7966
|
size: this.config.treeletSize,
|
|
7958
7967
|
passes: this.config.treeletOptimizationPasses,
|
|
7959
|
-
minImprovement: this.config.treeletMinImprovement
|
|
7968
|
+
minImprovement: this.config.treeletMinImprovement,
|
|
7969
|
+
complexityThreshold: this.config.treeletComplexityThreshold
|
|
7960
7970
|
},
|
|
7961
7971
|
reinsertionOptimization: {
|
|
7962
7972
|
enabled: this.bvhBuilder.enableReinsertionOptimization,
|
|
@@ -8745,7 +8755,7 @@ var vl = class {
|
|
|
8745
8755
|
ACTIVE_RAY_COUNT: 0,
|
|
8746
8756
|
ENTERING_COUNT: 1,
|
|
8747
8757
|
CONVERGED_COUNT: 2,
|
|
8748
|
-
|
|
8758
|
+
RESERVED_3: 3,
|
|
8749
8759
|
ACTIVE_PIXEL_COUNT: 4,
|
|
8750
8760
|
COUNT: 5
|
|
8751
8761
|
}, ru = {
|
|
@@ -8906,46 +8916,9 @@ var uu = class {
|
|
|
8906
8916
|
let e = (e) => (e / 1048576).toFixed(1), t = Object.entries(this.byCategory).map(([t, n]) => `${t}=${e(n)}`);
|
|
8907
8917
|
return `VRAM current=${e(this.current)}MB peak=${e(this.peak)}MB [${t.join(" ")}]`;
|
|
8908
8918
|
}
|
|
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 {
|
|
8919
|
+
}, du = ai("wavefront"), fu = class {
|
|
8946
8920
|
constructor(e) {
|
|
8947
|
-
this.renderer = e, this.kernels = /* @__PURE__ */ new Map(), this.
|
|
8948
|
-
for (let [e, t] of Object.entries(fu)) this.workgroupSizes.set(e, t);
|
|
8921
|
+
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
8922
|
}
|
|
8950
8923
|
_recordFirstDispatch(e, t) {
|
|
8951
8924
|
this._firstDispatches.push({
|
|
@@ -8984,38 +8957,21 @@ var uu = class {
|
|
|
8984
8957
|
}, this.profile.set(e, i)), i.calls++, i.totalMs += r - n;
|
|
8985
8958
|
} else this.renderer.compute(t);
|
|
8986
8959
|
}
|
|
8987
|
-
|
|
8960
|
+
setDispatchForCount(e, t) {
|
|
8988
8961
|
let n = this.kernels.get(e);
|
|
8989
|
-
n && (n.dispatchSize =
|
|
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]),
|
|
8962
|
+
n && (n.dispatchSize = [
|
|
8963
|
+
Math.ceil(t / n.workgroupSize[0]),
|
|
9011
8964
|
1,
|
|
9012
8965
|
1
|
|
9013
|
-
];
|
|
8966
|
+
]);
|
|
9014
8967
|
}
|
|
9015
|
-
|
|
9016
|
-
|
|
9017
|
-
|
|
9018
|
-
|
|
8968
|
+
setDispatchForGrid(e, t, n) {
|
|
8969
|
+
let r = this.kernels.get(e);
|
|
8970
|
+
if (!r) return;
|
|
8971
|
+
let i = r.workgroupSize;
|
|
8972
|
+
r.dispatchSize = [
|
|
8973
|
+
Math.ceil(t / i[0]),
|
|
8974
|
+
Math.ceil(n / i[1]),
|
|
9019
8975
|
1
|
|
9020
8976
|
];
|
|
9021
8977
|
}
|
|
@@ -9051,7 +9007,66 @@ var uu = class {
|
|
|
9051
9007
|
dispose() {
|
|
9052
9008
|
clearTimeout(this._firstDispatchFlush), this._firstDispatchFlush = null, this._firstDispatches = [], this.kernels.clear(), this.timing.clear(), this.profile.clear();
|
|
9053
9009
|
}
|
|
9054
|
-
},
|
|
9010
|
+
}, pu = f(([e, t, n, r, i, a, o]) => {
|
|
9011
|
+
let s = U(0).toVar();
|
|
9012
|
+
return p(r.equal(N(1)), () => {
|
|
9013
|
+
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();
|
|
9014
|
+
p(o.equal(N(1)), () => {
|
|
9015
|
+
let e = U(t[2].x, 0, t[2].z).toVar();
|
|
9016
|
+
p(A(e, e).lessThan(j(1e-8)), () => {
|
|
9017
|
+
e.assign(U(t[1].x, 0, t[1].z));
|
|
9018
|
+
}), d.assign(I(e)), u.assign(U(0, 1, 0)), l.assign(O(u, d));
|
|
9019
|
+
}).Else(() => {
|
|
9020
|
+
l.assign(I(U(t[0]))), u.assign(I(U(t[1]))), d.assign(I(U(t[2])));
|
|
9021
|
+
}), s.assign(I(l.mul(Se(n).mul(c)).add(u.mul(Se(r))).sub(d.mul(D(n).mul(c)))));
|
|
9022
|
+
}).Else(() => {
|
|
9023
|
+
let r = U(e.x.mul(2).sub(1), j(1).sub(e.y.mul(2)), 1), i = n.mul(W(r, 1));
|
|
9024
|
+
s.assign(I(ue(t[0].xyz, t[1].xyz, t[2].xyz).mul(i.xyz.div(i.w))));
|
|
9025
|
+
}), s;
|
|
9026
|
+
}), mu = f(([e, t, n, r, i, a, o, s, c, l, u, d, f, m, h]) => {
|
|
9027
|
+
let g = U(n[3]).toVar(), _ = pu(e, n, r, i, a, o, s).toVar(), v = g.toVar(), y = _.toVar();
|
|
9028
|
+
return p(c.and(l.greaterThan(0)).and(u.lessThan(64)).and(d.greaterThan(.001)), () => {
|
|
9029
|
+
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();
|
|
9030
|
+
p(i.equal(N(1)), () => {
|
|
9031
|
+
s.assign(ja({ N: _ }).mul(U(a, o, 0)));
|
|
9032
|
+
}).Else(() => {
|
|
9033
|
+
let e = I(U(n[0])), t = I(U(n[1]));
|
|
9034
|
+
s.assign(e.mul(a).add(t.mul(o)));
|
|
9035
|
+
}), v.assign(g.add(s.mul(e))), y.assign(I(g.add(_.mul(d)).sub(v)));
|
|
9036
|
+
}), ea({
|
|
9037
|
+
origin: v,
|
|
9038
|
+
direction: y
|
|
9039
|
+
});
|
|
9040
|
+
});
|
|
9041
|
+
function hu(e) {
|
|
9042
|
+
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) => {
|
|
9043
|
+
let S = H(j(e).add(.5), j(f).add(.5)), C = Un({ state: sr({
|
|
9044
|
+
pixelCoord: S,
|
|
9045
|
+
rayIndex: N(0),
|
|
9046
|
+
frame: a
|
|
9047
|
+
}).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));
|
|
9048
|
+
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, () => {
|
|
9049
|
+
El(r, x, U(0, 0, 1), j(1), U(0)), Yl(t, x, U(1));
|
|
9050
|
+
}), Ul(t, x, z(0), z(T), j(1), j(1), j(1)), n.element(x).assign(C);
|
|
9051
|
+
};
|
|
9052
|
+
return f(() => {
|
|
9053
|
+
if (O) {
|
|
9054
|
+
let e = M;
|
|
9055
|
+
p(e.lessThan(S(A.element(z(nu.ENTERING_COUNT)))), () => {
|
|
9056
|
+
let t = N(k.element(e)), n = t.add(C.mul(x));
|
|
9057
|
+
te(n.mod(x), n.div(x), z(t));
|
|
9058
|
+
});
|
|
9059
|
+
} else {
|
|
9060
|
+
let e = N(He.x).mul(16).add(N(se.x)), t = N(He.y).mul(16).add(N(se.y));
|
|
9061
|
+
p(e.lessThan(x).and(t.lessThan(w)), () => {
|
|
9062
|
+
te(e, t.add(C), z(t.mul(x).add(e)));
|
|
9063
|
+
});
|
|
9064
|
+
}
|
|
9065
|
+
});
|
|
9066
|
+
}
|
|
9067
|
+
//#endregion
|
|
9068
|
+
//#region src/TSL/BVHTraversal.js
|
|
9069
|
+
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
9070
|
let a = i ?? T(!1), o = aa({
|
|
9056
9071
|
didHit: !1,
|
|
9057
9072
|
dst: j(0x56bc75e2d63100000),
|
|
@@ -9062,12 +9077,12 @@ var uu = class {
|
|
|
9062
9077
|
meshIndex: N(-1),
|
|
9063
9078
|
boxTests: N(0),
|
|
9064
9079
|
triTests: N(0)
|
|
9065
|
-
}).toVar(), s = N(-1).toVar(), c = j(0).toVar(), l = j(0).toVar(), u =
|
|
9080
|
+
}).toVar(), s = N(-1).toVar(), c = j(0).toVar(), l = j(0).toVar(), u = xu(), f = N(1).toVar();
|
|
9066
9081
|
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(
|
|
9068
|
-
return m(f.greaterThan(N(0)).and(x.lessThan(N(
|
|
9082
|
+
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();
|
|
9083
|
+
return m(f.greaterThan(N(0)).and(x.lessThan(N(_u))), () => {
|
|
9069
9084
|
x.addAssign(1), f.subAssign(1);
|
|
9070
|
-
let t = u.element(f).toVar(), i = $(n, t, N(0), N(
|
|
9085
|
+
let t = u.element(f).toVar(), i = $(n, t, N(0), N(vu));
|
|
9071
9086
|
e && o.boxTests.addAssign(1), p(i.w.lessThan(0), () => {
|
|
9072
9087
|
p(i.w.greaterThan(j(-1.5)), () => {
|
|
9073
9088
|
let t = N(i.x).toVar(), n = N(i.y).toVar();
|
|
@@ -9076,7 +9091,7 @@ var uu = class {
|
|
|
9076
9091
|
end: n
|
|
9077
9092
|
}, ({ i: n }) => {
|
|
9078
9093
|
e && o.triTests.addAssign(1);
|
|
9079
|
-
let i = t.add(n).toVar(), u = $(r, i, N(0), N(
|
|
9094
|
+
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
9095
|
rayOrigin: v,
|
|
9081
9096
|
rayDir: y,
|
|
9082
9097
|
pA: u,
|
|
@@ -9086,7 +9101,7 @@ var uu = class {
|
|
|
9086
9101
|
woopParams: b
|
|
9087
9102
|
});
|
|
9088
9103
|
p(m.w.greaterThan(.5), () => {
|
|
9089
|
-
let e = m.x, t = m.y, n = m.z, u = $(r, i, N(3), N(
|
|
9104
|
+
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
9105
|
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
9106
|
o.didHit.assign(!0), o.dst.assign(e), s.assign(i), c.assign(t), l.assign(n);
|
|
9092
9107
|
});
|
|
@@ -9095,17 +9110,17 @@ var uu = class {
|
|
|
9095
9110
|
d();
|
|
9096
9111
|
});
|
|
9097
9112
|
}).Else(() => {
|
|
9098
|
-
p(i.z.greaterThan(.5).and(f.lessThan(N(
|
|
9113
|
+
p(i.z.greaterThan(.5).and(f.lessThan(N(gu))), () => {
|
|
9099
9114
|
u.element(f).assign(N(i.x)), f.addAssign(1);
|
|
9100
9115
|
});
|
|
9101
9116
|
});
|
|
9102
9117
|
}).Else(() => {
|
|
9103
|
-
let e = $(n, t, N(1), N(
|
|
9118
|
+
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
9119
|
rayOrigin: v,
|
|
9105
9120
|
invDir: g,
|
|
9106
9121
|
boxMin: i.xyz,
|
|
9107
9122
|
boxMax: e.xyz
|
|
9108
|
-
}).toVar(), d =
|
|
9123
|
+
}).toVar(), d = wu({
|
|
9109
9124
|
rayOrigin: v,
|
|
9110
9125
|
invDir: g,
|
|
9111
9126
|
boxMin: r.xyz,
|
|
@@ -9113,21 +9128,21 @@ var uu = class {
|
|
|
9113
9128
|
}).toVar();
|
|
9114
9129
|
p(de(l, d).lessThan(o.dst), () => {
|
|
9115
9130
|
let e = l.lessThan(d);
|
|
9116
|
-
p(L(e, d, l).lessThan(o.dst).and(f.lessThan(N(
|
|
9131
|
+
p(L(e, d, l).lessThan(o.dst).and(f.lessThan(N(gu))), () => {
|
|
9117
9132
|
u.element(f).assign(L(e, c, s)), f.addAssign(1);
|
|
9118
|
-
}), p(f.lessThan(N(
|
|
9133
|
+
}), p(f.lessThan(N(gu)), () => {
|
|
9119
9134
|
u.element(f).assign(L(e, s, c)), f.addAssign(1);
|
|
9120
9135
|
});
|
|
9121
9136
|
});
|
|
9122
9137
|
});
|
|
9123
9138
|
}), p(o.didHit, () => {
|
|
9124
9139
|
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(
|
|
9140
|
+
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
9141
|
o.normal.assign(I(n.mul(e).add(i.mul(c)).add(a.mul(l))));
|
|
9127
|
-
let u = $(r, s, N(6), N(
|
|
9142
|
+
let u = $(r, s, N(6), N(yu)), d = $(r, s, N(7), N(yu));
|
|
9128
9143
|
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
9144
|
}), o;
|
|
9130
|
-
}),
|
|
9145
|
+
}), Eu = /* @__PURE__ */ Tu(!1), Du = /* @__PURE__ */ Tu(!0), Ou = f(([e, t, n, r]) => {
|
|
9131
9146
|
let i = aa({
|
|
9132
9147
|
didHit: !1,
|
|
9133
9148
|
dst: r,
|
|
@@ -9138,12 +9153,12 @@ var uu = class {
|
|
|
9138
9153
|
meshIndex: N(-1),
|
|
9139
9154
|
boxTests: N(0),
|
|
9140
9155
|
triTests: N(0)
|
|
9141
|
-
}).toVar(), a =
|
|
9156
|
+
}).toVar(), a = xu(), o = N(1).toVar();
|
|
9142
9157
|
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(
|
|
9144
|
-
return m(o.greaterThan(N(0)).and(i.didHit.not()).and(u.lessThan(N(
|
|
9158
|
+
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();
|
|
9159
|
+
return m(o.greaterThan(N(0)).and(i.didHit.not()).and(u.lessThan(N(_u))), () => {
|
|
9145
9160
|
u.addAssign(1), o.subAssign(1);
|
|
9146
|
-
let r = a.element(o).toVar(), s = $(t, r, N(0), N(
|
|
9161
|
+
let r = a.element(o).toVar(), s = $(t, r, N(0), N(vu));
|
|
9147
9162
|
p(s.w.lessThan(0), () => {
|
|
9148
9163
|
p(s.w.greaterThan(j(-1.5)), () => {
|
|
9149
9164
|
let t = N(s.x).toVar(), r = N(s.y).toVar();
|
|
@@ -9151,7 +9166,7 @@ var uu = class {
|
|
|
9151
9166
|
start: N(0),
|
|
9152
9167
|
end: r
|
|
9153
9168
|
}, ({ i: r }) => {
|
|
9154
|
-
let a = t.add(r).toVar(), o = $(n, a, N(0), N(
|
|
9169
|
+
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
9170
|
rayOrigin: e.origin,
|
|
9156
9171
|
rayDir: e.direction,
|
|
9157
9172
|
pA: o,
|
|
@@ -9161,22 +9176,22 @@ var uu = class {
|
|
|
9161
9176
|
woopParams: l
|
|
9162
9177
|
});
|
|
9163
9178
|
p(u.w.greaterThan(.5), () => {
|
|
9164
|
-
let t = $(n, a, N(7), N(
|
|
9179
|
+
let t = $(n, a, N(7), N(yu));
|
|
9165
9180
|
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
9181
|
});
|
|
9167
9182
|
});
|
|
9168
9183
|
}).Else(() => {
|
|
9169
|
-
p(s.z.greaterThan(.5).and(o.lessThan(N(
|
|
9184
|
+
p(s.z.greaterThan(.5).and(o.lessThan(N(gu))), () => {
|
|
9170
9185
|
a.element(o).assign(N(s.x)), o.addAssign(1);
|
|
9171
9186
|
});
|
|
9172
9187
|
});
|
|
9173
9188
|
}).Else(() => {
|
|
9174
|
-
let n = $(t, r, N(1), N(
|
|
9189
|
+
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
9190
|
rayOrigin: e.origin,
|
|
9176
9191
|
invDir: c,
|
|
9177
9192
|
boxMin: s.xyz,
|
|
9178
9193
|
boxMax: n.xyz
|
|
9179
|
-
}).toVar(), h =
|
|
9194
|
+
}).toVar(), h = wu({
|
|
9180
9195
|
rayOrigin: e.origin,
|
|
9181
9196
|
invDir: c,
|
|
9182
9197
|
boxMin: l.xyz,
|
|
@@ -9184,66 +9199,33 @@ var uu = class {
|
|
|
9184
9199
|
}).toVar();
|
|
9185
9200
|
p(de(m, h).lessThan(i.dst), () => {
|
|
9186
9201
|
let e = m.lessThan(h);
|
|
9187
|
-
p(L(e, h, m).lessThan(i.dst).and(o.lessThan(N(
|
|
9202
|
+
p(L(e, h, m).lessThan(i.dst).and(o.lessThan(N(gu))), () => {
|
|
9188
9203
|
a.element(o).assign(L(e, f, d)), o.addAssign(1);
|
|
9189
|
-
}), p(o.lessThan(N(
|
|
9204
|
+
}), p(o.lessThan(N(gu)), () => {
|
|
9190
9205
|
a.element(o).assign(L(e, d, f)), o.addAssign(1);
|
|
9191
9206
|
});
|
|
9192
9207
|
});
|
|
9193
9208
|
});
|
|
9194
9209
|
}), 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
9210
|
});
|
|
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
9211
|
//#endregion
|
|
9234
9212
|
//#region src/TSL/ExtendKernel.js
|
|
9235
9213
|
function ku(e) {
|
|
9236
|
-
let { bvhBuffer: t, triangleBuffer: n,
|
|
9214
|
+
let { bvhBuffer: t, triangleBuffer: n, rayBufferRO: r, hitBufferRW: i, activeIndicesRO: a, counters: o, maxRayCount: s } = e;
|
|
9237
9215
|
return f(() => {
|
|
9238
|
-
let e = M,
|
|
9239
|
-
p(e.greaterThanEqual(
|
|
9216
|
+
let e = M, c = o ? S(o.element(z(nu.ENTERING_COUNT))) : s;
|
|
9217
|
+
p(e.greaterThanEqual(c), () => {
|
|
9240
9218
|
h();
|
|
9241
9219
|
});
|
|
9242
|
-
let l =
|
|
9243
|
-
|
|
9244
|
-
|
|
9245
|
-
})
|
|
9246
|
-
|
|
9220
|
+
let l = a.element(e);
|
|
9221
|
+
p(xl(r, l).bitAnd(z(ru.ACTIVE)).equal(z(0)), () => {
|
|
9222
|
+
h();
|
|
9223
|
+
});
|
|
9224
|
+
let u = ea({
|
|
9225
|
+
origin: yl(r, l).toVar(),
|
|
9226
|
+
direction: bl(r, l).toVar()
|
|
9227
|
+
}), d = Hl(r, l).stackDepth.greaterThan(z(0)), f = aa.wrap(Eu(u, t, n, d)).toVar();
|
|
9228
|
+
Vl(i, l, f.dst, z(f.triangleIndex), f.uv.x, f.uv.y, f.normal, z(f.materialIndex), z(f.meshIndex));
|
|
9247
9229
|
});
|
|
9248
9230
|
}
|
|
9249
9231
|
//#endregion
|
|
@@ -9528,7 +9510,7 @@ var Au = /* @__PURE__ */ G("\n fn equirectDirectionToUv( direction: vec3f, envir
|
|
|
9528
9510
|
selectionTotalWeight: A
|
|
9529
9511
|
});
|
|
9530
9512
|
}), 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,
|
|
9513
|
+
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
9514
|
return p(n.emissiveIntensity.lessThanEqual(10), () => {
|
|
9533
9515
|
let e = _.add(y).add(x).add(C).toVar(), f = e.greaterThan(N(0)).toVar(), w = j(0).toVar();
|
|
9534
9516
|
p(f, () => {
|
|
@@ -10417,7 +10399,7 @@ function Bd(e) {
|
|
|
10417
10399
|
});
|
|
10418
10400
|
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
10401
|
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,
|
|
10402
|
+
let e = f(([e, i, a]) => ys(e, i, a, Ou, t, n, r));
|
|
10421
10403
|
p(Le.greaterThan(N(0)), () => {
|
|
10422
10404
|
let t = cd.wrap(Pd(ut, dt, Ye, Qe, je, Ae, $e, a, a, Pe, n));
|
|
10423
10405
|
p(t.valid.and(t.pdf.greaterThan(0)), () => {
|
|
@@ -10485,50 +10467,46 @@ function Hd(e) {
|
|
|
10485
10467
|
}
|
|
10486
10468
|
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
10469
|
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,
|
|
10470
|
+
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
10471
|
return f(() => {
|
|
10490
10472
|
let e = N(He.x).mul(16).add(N(se.x)), f = N(He.y).mul(16).add(N(se.y));
|
|
10491
10473
|
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(),
|
|
10493
|
-
p(
|
|
10474
|
+
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();
|
|
10475
|
+
p(re, () => {
|
|
10494
10476
|
let e = Dl(n, C);
|
|
10495
|
-
|
|
10477
|
+
ce.assign(Ol(e)), le.assign(W(kl(e), 0).xyz);
|
|
10496
10478
|
});
|
|
10497
|
-
let
|
|
10479
|
+
let ue = H(j(e).add(.5), j(b).add(.5)).div(o);
|
|
10498
10480
|
p(c.and(d.not()).and(s.greaterThan(z(0))).and(l).and(S.notEqual(N(11))), () => {
|
|
10499
|
-
let e = je(h,
|
|
10500
|
-
A.assign(L(
|
|
10501
|
-
|
|
10502
|
-
let e = je(_,
|
|
10503
|
-
|
|
10481
|
+
let e = je(h, ue, 0).toVar();
|
|
10482
|
+
A.assign(L(se, e.xyz, fe(e.xyz, D.xyz, u))), p(re, () => {
|
|
10483
|
+
le.assign(fe(je(g, ue, 0).xyz, le, u)), p(ie, () => {
|
|
10484
|
+
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);
|
|
10485
|
+
ce.assign(W(i.mul(.5).add(.5), ce.w));
|
|
10504
10486
|
});
|
|
10505
10487
|
}), p(m, () => {
|
|
10506
|
-
|
|
10488
|
+
oe.assign(L(se, e.w, fe(e.w, D.w, u)));
|
|
10507
10489
|
});
|
|
10508
|
-
}), p(
|
|
10490
|
+
}), p(M, () => {
|
|
10509
10491
|
let e = Oa(D.xyz), t = fe(E.element(w).toVar(), e.mul(e), u).toVar();
|
|
10510
10492
|
E.element(w).assign(t);
|
|
10511
10493
|
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
10494
|
p(s.greaterThanEqual(z(k)).and(o), () => {
|
|
10513
10495
|
x(T.element(z(nu.CONVERGED_COUNT)), z(1));
|
|
10514
|
-
}), p(
|
|
10496
|
+
}), p(P, () => {
|
|
10515
10497
|
p(s.equal(z(0)), () => {
|
|
10516
|
-
|
|
10517
|
-
}), p(
|
|
10518
|
-
|
|
10519
|
-
|
|
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
|
-
});
|
|
10498
|
+
te.element(w).assign(z(0));
|
|
10499
|
+
}), p(se.not().and(s.greaterThan(z(0))), () => {
|
|
10500
|
+
let e = L(s.greaterThanEqual(z(k)).and(i.lessThan(ee)), te.element(w).add(z(1)), z(0)).toVar();
|
|
10501
|
+
te.element(w).assign(e);
|
|
10524
10502
|
});
|
|
10525
10503
|
});
|
|
10526
10504
|
}), p(S.equal(N(11)), () => {
|
|
10527
10505
|
A.assign(Ud(A));
|
|
10528
10506
|
});
|
|
10529
|
-
let
|
|
10530
|
-
Ne(r,
|
|
10531
|
-
Ne(i,
|
|
10507
|
+
let F = Re(z(e), z(b));
|
|
10508
|
+
Ne(r, F, W(A, oe)).toWriteOnly(), p(re, () => {
|
|
10509
|
+
Ne(i, F, ce).toWriteOnly(), Ne(a, F, W(le, 1)).toWriteOnly();
|
|
10532
10510
|
});
|
|
10533
10511
|
});
|
|
10534
10512
|
});
|
|
@@ -10539,7 +10517,7 @@ var Gd = /* @__PURE__ */ G("\n fn visualizeDepth( depth: f32 ) -> vec3f {\n ret
|
|
|
10539
10517
|
let _ = W(1, 0, 1, 1).toVar(), v = ea({
|
|
10540
10518
|
origin: e,
|
|
10541
10519
|
direction: t
|
|
10542
|
-
}), y = aa.wrap(
|
|
10520
|
+
}), y = aa.wrap(Du(v, n, r).toVar());
|
|
10543
10521
|
return p(l.equal(N(7)), () => {
|
|
10544
10522
|
let e = j(y.triTests).div(u);
|
|
10545
10523
|
_.assign(L(e.lessThan(1), W(U(e), 1), W(1, 0, 0, 1)));
|
|
@@ -10626,7 +10604,7 @@ var Gd = /* @__PURE__ */ G("\n fn visualizeDepth( depth: f32 ) -> vec3f {\n ret
|
|
|
10626
10604
|
}).toVar(), h = ea({
|
|
10627
10605
|
origin: y.hitPoint.add(u.mul(.001)),
|
|
10628
10606
|
direction: m
|
|
10629
|
-
}), v = aa.wrap(
|
|
10607
|
+
}), v = aa.wrap(Du(h, n, r).toVar()), b = U(0).toVar();
|
|
10630
10608
|
p(v.didHit.not(), () => {
|
|
10631
10609
|
p(c, () => {
|
|
10632
10610
|
b.assign(Pu({
|
|
@@ -10680,21 +10658,19 @@ var Gd = /* @__PURE__ */ G("\n fn visualizeDepth( depth: f32 ) -> vec3f {\n ret
|
|
|
10680
10658
|
}), _;
|
|
10681
10659
|
});
|
|
10682
10660
|
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,
|
|
10661
|
+
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
10662
|
return f(() => {
|
|
10685
10663
|
let e = N(He.x).mul(16).add(N(se.x)), f = N(He.y).mul(16).add(N(se.y));
|
|
10686
10664
|
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(),
|
|
10688
|
-
|
|
10689
|
-
|
|
10690
|
-
|
|
10691
|
-
let e = or(a, N(0), N(1), o, i, k);
|
|
10692
|
-
te.assign(W(e, 1, 1));
|
|
10665
|
+
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();
|
|
10666
|
+
p(ee.equal(N(9)), () => {
|
|
10667
|
+
let e = or(a, N(0), N(1), o, i, ne);
|
|
10668
|
+
ie.assign(W(e, 1, 1));
|
|
10693
10669
|
}).Else(() => {
|
|
10694
|
-
|
|
10670
|
+
ie.assign(Jd(re.origin, re.direction, w, T, E, D, O, k, A, ee, te, a, i, l, u, ne));
|
|
10695
10671
|
});
|
|
10696
|
-
let
|
|
10697
|
-
Ne(t,
|
|
10672
|
+
let M = Re(z(e), z(f));
|
|
10673
|
+
Ne(t, M, ie).toWriteOnly(), Ne(n, M, W(.5, .5, 1, 1)).toWriteOnly(), Ne(r, M, W(ie.xyz, 1)).toWriteOnly();
|
|
10698
10674
|
});
|
|
10699
10675
|
});
|
|
10700
10676
|
}
|
|
@@ -10740,16 +10716,33 @@ function Qd({ sortGlobalHistogram: e, bins: t = 256 }) {
|
|
|
10740
10716
|
}
|
|
10741
10717
|
function $d({ hitBufferRO: e, activeIndicesReadRO: t, sortedIndicesRW: n, sortGlobalHistogram: r, counters: i, bins: a = 256 }) {
|
|
10742
10718
|
return f(() => {
|
|
10743
|
-
let o = M, s =
|
|
10744
|
-
p(
|
|
10745
|
-
|
|
10746
|
-
|
|
10719
|
+
let o = M, s = se.x, c = jn("uint", a);
|
|
10720
|
+
p(s.lessThan(z(a)), () => {
|
|
10721
|
+
C(c.element(s), z(0));
|
|
10722
|
+
}), Ve();
|
|
10723
|
+
let l = S(i.element(z(nu.ENTERING_COUNT))), u = o.lessThan(l), d = z(0).toVar(), f = z(0).toVar();
|
|
10724
|
+
p(u, () => {
|
|
10725
|
+
d.assign(t.element(o)), f.assign(z(Bl(e, d)).clamp(z(0), z(a - 1))), x(c.element(f), z(1));
|
|
10726
|
+
}), Ve(), p(s.lessThan(z(a)), () => {
|
|
10727
|
+
let e = c.element(s), t = S(e);
|
|
10728
|
+
p(t.greaterThan(z(0)), () => {
|
|
10729
|
+
C(e, x(r.element(s), t));
|
|
10730
|
+
});
|
|
10731
|
+
}), Ve(), p(u, () => {
|
|
10732
|
+
n.element(x(c.element(f), z(1))).assign(d);
|
|
10747
10733
|
});
|
|
10748
10734
|
});
|
|
10749
10735
|
}
|
|
10750
10736
|
//#endregion
|
|
10751
10737
|
//#region src/Stages/PathTracer.js
|
|
10752
|
-
var ef = ai("wavefront"), tf =
|
|
10738
|
+
var ef = ai("wavefront"), tf = 256, nf = [
|
|
10739
|
+
"extend",
|
|
10740
|
+
"shade",
|
|
10741
|
+
"globalHist",
|
|
10742
|
+
"globalScatter",
|
|
10743
|
+
"compact",
|
|
10744
|
+
"compactCopyback"
|
|
10745
|
+
], rf = class extends dl {
|
|
10753
10746
|
constructor(e, t, n, r = {}) {
|
|
10754
10747
|
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
10748
|
}
|
|
@@ -10824,11 +10817,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
10824
10817
|
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
10818
|
if (i) {
|
|
10826
10819
|
let e = Math.min(r, Math.ceil(o * 1.5) + 1024);
|
|
10827
|
-
a.
|
|
10828
|
-
Math.ceil(e / 256),
|
|
10829
|
-
1,
|
|
10830
|
-
1
|
|
10831
|
-
]), a.dispatch("resetFrameCounters"), a.dispatch("buildActivePixels"), a.dispatch("seedEnter"), a.dispatch("generateList");
|
|
10820
|
+
a.setDispatchForCount("generateList", e), a.dispatch("resetFrameCounters"), a.dispatch("buildActivePixels"), a.dispatch("seedEnter"), a.dispatch("generateList");
|
|
10832
10821
|
} else a.dispatch("generate"), a.dispatch("initActiveIndices");
|
|
10833
10822
|
for (let e = 0; e <= s; e++) {
|
|
10834
10823
|
this._wfCurrentBounce.value = e;
|
|
@@ -10839,20 +10828,11 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
10839
10828
|
let n = e - 1, i;
|
|
10840
10829
|
n < f && d[n] !== void 0 ? i = d[n] : f > 0 && (i = d[f - 1]), t = i > 0 ? i : r;
|
|
10841
10830
|
} else e === 0 && i && (t = o);
|
|
10842
|
-
let n = Math.min(r, Math.ceil(t * 1.5) + 1024)
|
|
10843
|
-
|
|
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);
|
|
10831
|
+
let n = Math.min(r, Math.ceil(t * 1.5) + 1024);
|
|
10832
|
+
for (let e of nf) a.setDispatchForCount(e, n);
|
|
10848
10833
|
} else {
|
|
10849
10834
|
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);
|
|
10835
|
+
for (let e of nf) a.setDispatchForCount(e, r);
|
|
10856
10836
|
}
|
|
10857
10837
|
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
10838
|
}
|
|
@@ -10962,7 +10942,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
10962
10942
|
let d = Te(this._streakAttr, "uint"), m = Te(this._streakAttr, "uint").toReadOnly();
|
|
10963
10943
|
_l(this.renderer, this._frozenMaskAttr), this._frozenMaskAttr = new o(new Uint32Array(l), 1);
|
|
10964
10944
|
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
|
|
10945
|
+
this._queueManager ? this._queueManager.resize(this._packedBuffers.capacity) : this._queueManager = new iu(this._packedBuffers.capacity, this.renderer), this._kernelManager ||= new fu(this.renderer);
|
|
10966
10946
|
let v = this._packedBuffers, y = this._queueManager;
|
|
10967
10947
|
this._wfRenderWidth.value = t, this._wfRenderHeight.value = n, this._wfMaxRayCount.value = Math.min(r, this._chunkRows * t);
|
|
10968
10948
|
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 +10969,11 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
10989
10969
|
});
|
|
10990
10970
|
});
|
|
10991
10971
|
this._kernelManager.register("initActiveIndices", te().compute([
|
|
10992
|
-
Math.ceil(this._chunkRows * t /
|
|
10972
|
+
Math.ceil(this._chunkRows * t / tf),
|
|
10993
10973
|
1,
|
|
10994
10974
|
1
|
|
10995
10975
|
], [
|
|
10996
|
-
|
|
10976
|
+
tf,
|
|
10997
10977
|
1,
|
|
10998
10978
|
1
|
|
10999
10979
|
]));
|
|
@@ -11005,6 +10985,10 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11005
10985
|
frame: this.seedFrame,
|
|
11006
10986
|
cameraWorldMatrix: this.cameraWorldMatrix,
|
|
11007
10987
|
cameraProjectionMatrixInverse: this.cameraProjectionMatrixInverse,
|
|
10988
|
+
cameraProjection: this.cameraProjection,
|
|
10989
|
+
panoLonRange: this.panoLonRange,
|
|
10990
|
+
panoLatRange: this.panoLatRange,
|
|
10991
|
+
panoLevelHorizon: this.panoLevelHorizon,
|
|
11008
10992
|
enableDOF: this.enableDOF,
|
|
11009
10993
|
focalLength: this.focalLength,
|
|
11010
10994
|
aperture: this.aperture,
|
|
@@ -11019,7 +11003,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11019
11003
|
transmissiveBounces: this.transmissiveBounces,
|
|
11020
11004
|
transparentBackground: this.transparentBackground,
|
|
11021
11005
|
auxGBufferEnabled: this._auxGBufferUniform
|
|
11022
|
-
}, ne =
|
|
11006
|
+
}, ne = hu(j);
|
|
11023
11007
|
this._kernelManager.register("generate", ne().compute([
|
|
11024
11008
|
Math.ceil(t / 16),
|
|
11025
11009
|
Math.ceil(this._chunkRows / 16),
|
|
@@ -11031,7 +11015,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11031
11015
|
]));
|
|
11032
11016
|
let re = this.pixelFreezeStability, ie = f(() => {
|
|
11033
11017
|
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))
|
|
11018
|
+
C(D.element(z(nu.CONVERGED_COUNT)), z(0));
|
|
11035
11019
|
});
|
|
11036
11020
|
});
|
|
11037
11021
|
this._kernelManager.register("resetFrameCounters", ie().compute([
|
|
@@ -11075,11 +11059,11 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11075
11059
|
});
|
|
11076
11060
|
});
|
|
11077
11061
|
this._kernelManager.register("buildActivePixels", P().compute([
|
|
11078
|
-
Math.ceil(this._chunkRows * t /
|
|
11062
|
+
Math.ceil(this._chunkRows * t / tf),
|
|
11079
11063
|
1,
|
|
11080
11064
|
1
|
|
11081
11065
|
], [
|
|
11082
|
-
|
|
11066
|
+
tf,
|
|
11083
11067
|
1,
|
|
11084
11068
|
1
|
|
11085
11069
|
]));
|
|
@@ -11096,18 +11080,18 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11096
11080
|
1,
|
|
11097
11081
|
1
|
|
11098
11082
|
]));
|
|
11099
|
-
let oe =
|
|
11083
|
+
let oe = hu({
|
|
11100
11084
|
...j,
|
|
11101
11085
|
listDriven: !0,
|
|
11102
11086
|
activeIndicesRO: y.activeIndicesRO.a,
|
|
11103
11087
|
counters: D
|
|
11104
11088
|
});
|
|
11105
11089
|
this._kernelManager.register("generateList", oe().compute([
|
|
11106
|
-
Math.ceil(i /
|
|
11090
|
+
Math.ceil(i / tf),
|
|
11107
11091
|
1,
|
|
11108
11092
|
1
|
|
11109
11093
|
], [
|
|
11110
|
-
|
|
11094
|
+
tf,
|
|
11111
11095
|
1,
|
|
11112
11096
|
1
|
|
11113
11097
|
]));
|
|
@@ -11123,7 +11107,6 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11123
11107
|
let he = ku({
|
|
11124
11108
|
bvhBuffer: se,
|
|
11125
11109
|
triangleBuffer: ce,
|
|
11126
|
-
materialBuffer: le,
|
|
11127
11110
|
rayBufferRO: v.rayBuffer.ro,
|
|
11128
11111
|
hitBufferRW: v.hitBuffer.rw,
|
|
11129
11112
|
activeIndicesRO: y.getActiveReadRO(),
|
|
@@ -11304,11 +11287,11 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11304
11287
|
}), L.element(e).assign(be.element(e));
|
|
11305
11288
|
});
|
|
11306
11289
|
this._kernelManager.register("compactCopyback", xe().compute([
|
|
11307
|
-
Math.ceil(i /
|
|
11290
|
+
Math.ceil(i / tf),
|
|
11308
11291
|
1,
|
|
11309
11292
|
1
|
|
11310
11293
|
], [
|
|
11311
|
-
|
|
11294
|
+
tf,
|
|
11312
11295
|
1,
|
|
11313
11296
|
1
|
|
11314
11297
|
]));
|
|
@@ -11340,7 +11323,6 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11340
11323
|
adaptiveMinSamples: this.adaptiveMinSamples,
|
|
11341
11324
|
usePixelFreeze: this.usePixelFreeze,
|
|
11342
11325
|
pixelFreezeThreshold: this.pixelFreezeThreshold,
|
|
11343
|
-
pixelFreezeStability: this.pixelFreezeStability,
|
|
11344
11326
|
streakBufferRW: d,
|
|
11345
11327
|
frozenMaskRO: _,
|
|
11346
11328
|
chunkRowBase: this._wfChunkRowBase,
|
|
@@ -11366,6 +11348,10 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11366
11348
|
cameraProjectionMatrixInverse: this.cameraProjectionMatrixInverse,
|
|
11367
11349
|
cameraProjectionMatrix: this.cameraProjectionMatrix,
|
|
11368
11350
|
cameraViewMatrix: this.cameraViewMatrix,
|
|
11351
|
+
cameraProjection: this.cameraProjection,
|
|
11352
|
+
panoLonRange: this.panoLonRange,
|
|
11353
|
+
panoLatRange: this.panoLatRange,
|
|
11354
|
+
panoLevelHorizon: this.panoLevelHorizon,
|
|
11369
11355
|
enableDOF: this.enableDOF,
|
|
11370
11356
|
focalLength: this.focalLength,
|
|
11371
11357
|
aperture: this.aperture,
|
|
@@ -11403,43 +11389,23 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11403
11389
|
}
|
|
11404
11390
|
_setWfDispatch() {
|
|
11405
11391
|
let e = this._wfRenderWidth.value, t = this._wfRenderHeight.value;
|
|
11406
|
-
this._kernelManager.
|
|
11407
|
-
Math.ceil(e / 16),
|
|
11408
|
-
Math.ceil(t / 16),
|
|
11409
|
-
1
|
|
11410
|
-
]);
|
|
11392
|
+
this._kernelManager.setDispatchForGrid("debug", e, t);
|
|
11411
11393
|
}
|
|
11412
11394
|
_setChunk(e, t, n) {
|
|
11413
11395
|
let r = this._wfRenderWidth.value, i = t * r;
|
|
11414
11396
|
this._wfChunkRowBase.value = e, this._wfChunkRows.value = t, this._wfIsFirstChunk.value = +(n === 0), this._wfMaxRayCount.value = i;
|
|
11415
11397
|
let a = this._kernelManager;
|
|
11416
|
-
return a.
|
|
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;
|
|
11398
|
+
return a.setDispatchForGrid("generate", r, t), a.setDispatchForGrid("finalWrite", r, t), a.setDispatchForCount("initActiveIndices", i), a.setDispatchForCount("buildActivePixels", i), i;
|
|
11433
11399
|
}
|
|
11434
11400
|
dispose() {
|
|
11435
11401
|
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
11402
|
}
|
|
11437
|
-
},
|
|
11403
|
+
}, af = class extends lr {
|
|
11438
11404
|
constructor(e, t = {}) {
|
|
11439
11405
|
super("NormalDepth", {
|
|
11440
11406
|
...t,
|
|
11441
11407
|
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);
|
|
11408
|
+
}), 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
11409
|
let n = t.width || 1, r = t.height || 1;
|
|
11444
11410
|
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
11411
|
type: ht,
|
|
@@ -11479,18 +11445,18 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11479
11445
|
this._computeNode = f(([r, i]) => {
|
|
11480
11446
|
let l = N(He.x).mul(8).add(N(se.x)), u = N(He.y).mul(8).add(N(se.y));
|
|
11481
11447
|
p(l.lessThan(N(a)).and(u.lessThan(N(o))), () => {
|
|
11482
|
-
let d =
|
|
11448
|
+
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
11449
|
origin: U(r[3]),
|
|
11484
|
-
direction:
|
|
11485
|
-
}),
|
|
11486
|
-
Ne(s, Re(z(l), z(u)),
|
|
11487
|
-
let
|
|
11488
|
-
p(
|
|
11489
|
-
let e = ta.wrap(za(
|
|
11490
|
-
|
|
11450
|
+
direction: d
|
|
11451
|
+
}), 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)));
|
|
11452
|
+
Ne(s, Re(z(l), z(u)), _).toWriteOnly();
|
|
11453
|
+
let v = m.normal.toVar();
|
|
11454
|
+
p(m.didHit, () => {
|
|
11455
|
+
let e = ta.wrap(za(m.materialIndex, n)).toVar(), t = pa.wrap(as(m.uv, e)).toVar(), r = cs(m.normal, e, t).toVar();
|
|
11456
|
+
v.assign(ls(r, e, t));
|
|
11491
11457
|
});
|
|
11492
|
-
let
|
|
11493
|
-
Ne(c, Re(z(l), z(u)),
|
|
11458
|
+
let y = m.didHit.select(W(v.mul(.5).add(.5), g), W(0, 0, 0, j(65504)));
|
|
11459
|
+
Ne(c, Re(z(l), z(u)), y).toWriteOnly();
|
|
11494
11460
|
});
|
|
11495
11461
|
})(r, i).compute([
|
|
11496
11462
|
this._dispatchX,
|
|
@@ -11506,7 +11472,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11506
11472
|
if (!this.enabled || !this._syncStorageBuffers()) return;
|
|
11507
11473
|
this._computeBuilt || this._buildCompute();
|
|
11508
11474
|
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) {
|
|
11475
|
+
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
11476
|
let t = this._currentIdx === 0 ? this._rtA : this._rtB;
|
|
11511
11477
|
e.setTexture("pathtracer:normalDepth", t.texture), e.setTexture("pathtracer:prevNormalDepth", t.texture), e.setTexture("pathtracer:shadingNormal", this._shadingRT.texture);
|
|
11512
11478
|
return;
|
|
@@ -11544,7 +11510,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11544
11510
|
dispose() {
|
|
11545
11511
|
this._computeNode?.dispose(), this._outputStorageTex?.dispose(), this._shadingStorageTex?.dispose(), this._shadingRT?.dispose(), this._rtA?.dispose(), this._rtB?.dispose();
|
|
11546
11512
|
}
|
|
11547
|
-
},
|
|
11513
|
+
}, of = class extends lr {
|
|
11548
11514
|
constructor(e, t, n = {}) {
|
|
11549
11515
|
super("MotionVector", {
|
|
11550
11516
|
...n,
|
|
@@ -11664,7 +11630,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11664
11630
|
dispose() {
|
|
11665
11631
|
this._screenSpaceComputeNode?.dispose(), this._worldSpaceComputeNode?.dispose(), this._screenSpaceStorageTex?.dispose(), this._worldSpaceStorageTex?.dispose(), this.screenSpaceTarget?.dispose(), this.worldSpaceTarget?.dispose(), this._normalDepthTexNode?.dispose();
|
|
11666
11632
|
}
|
|
11667
|
-
},
|
|
11633
|
+
}, 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
11634
|
constructor(e, t = {}) {
|
|
11669
11635
|
super("ASVGF", {
|
|
11670
11636
|
...t,
|
|
@@ -11705,7 +11671,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11705
11671
|
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
11672
|
this._gradientNode = f(() => {
|
|
11707
11673
|
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(
|
|
11674
|
+
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
11675
|
l.element(i).assign(_);
|
|
11710
11676
|
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
11677
|
u.element(i).assign(T);
|
|
@@ -11752,7 +11718,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11752
11718
|
return f(() => {
|
|
11753
11719
|
let f = N(He.x).mul(8).add(N(se.x)), y = N(He.y).mul(8).add(N(se.y));
|
|
11754
11720
|
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 =
|
|
11721
|
+
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
11722
|
p(m.greaterThan(.5).and(h.lessThan(.5)), () => {
|
|
11757
11723
|
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
11724
|
p(t.and(m), () => {
|
|
@@ -11761,7 +11727,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11761
11727
|
return i.mul(l).mul(u);
|
|
11762
11728
|
}, 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
11729
|
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 =
|
|
11730
|
+
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
11731
|
D.assign(W(p, m)), O.assign(W(p.mul(T), C));
|
|
11766
11732
|
});
|
|
11767
11733
|
});
|
|
@@ -11879,7 +11845,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11879
11845
|
dispose() {
|
|
11880
11846
|
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
11847
|
}
|
|
11882
|
-
},
|
|
11848
|
+
}, 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
11849
|
constructor(e, t = {}) {
|
|
11884
11850
|
super("VarianceEstimation", {
|
|
11885
11851
|
...t,
|
|
@@ -11905,9 +11871,9 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11905
11871
|
let n = this._colorTexNode, r = this.temporalAlpha, i = this.varianceBoost, a = this.resW, o = this.resH, s = Be("float", 100);
|
|
11906
11872
|
return f(() => {
|
|
11907
11873
|
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(
|
|
11874
|
+
s.element(u).assign(uf(Oa(g))), p(u.lessThan(z(36)), () => {
|
|
11909
11875
|
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(
|
|
11876
|
+
s.element(e).assign(uf(Oa(i)));
|
|
11911
11877
|
}), Ve();
|
|
11912
11878
|
let _ = N(He.x).mul(8).add(N(c)), v = N(He.y).mul(8).add(N(l));
|
|
11913
11879
|
p(_.lessThan(N(a)).and(v.lessThan(N(o))), () => {
|
|
@@ -11918,7 +11884,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11918
11884
|
}
|
|
11919
11885
|
n.divAssign(9), a.divAssign(9);
|
|
11920
11886
|
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)),
|
|
11887
|
+
Ne(e, Re(z(_), z(v)), df(u, d.x, d.y, r, o, i)).toWriteOnly();
|
|
11922
11888
|
});
|
|
11923
11889
|
})().compute([
|
|
11924
11890
|
this._dispatchX,
|
|
@@ -11972,7 +11938,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11972
11938
|
dispose() {
|
|
11973
11939
|
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
11940
|
}
|
|
11975
|
-
},
|
|
11941
|
+
}, 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
11942
|
constructor(e, t = {}) {
|
|
11977
11943
|
super("BilateralFiltering", {
|
|
11978
11944
|
...t,
|
|
@@ -12027,7 +11993,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12027
11993
|
return fe(t.z, F(t.z, t.w), d);
|
|
12028
11994
|
}, 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
11995
|
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 =
|
|
11996
|
+
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
11997
|
ne.addAssign(g.mul(O)), re.addAssign(O), ie.addAssign(O.mul(O).mul(F(ee, j(0))));
|
|
12032
11998
|
}
|
|
12033
11999
|
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 +12052,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12086
12052
|
dispose() {
|
|
12087
12053
|
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
12054
|
}
|
|
12089
|
-
},
|
|
12055
|
+
}, 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
12056
|
1 / 256,
|
|
12091
12057
|
4 / 256,
|
|
12092
12058
|
6 / 256,
|
|
@@ -12112,7 +12078,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12112
12078
|
6 / 256,
|
|
12113
12079
|
4 / 256,
|
|
12114
12080
|
1 / 256
|
|
12115
|
-
],
|
|
12081
|
+
], yf = class extends lr {
|
|
12116
12082
|
constructor(e, t = {}) {
|
|
12117
12083
|
super("EdgeAwareFiltering", {
|
|
12118
12084
|
...t,
|
|
@@ -12140,7 +12106,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12140
12106
|
return f(() => {
|
|
12141
12107
|
let o = N(He.x).mul(16).add(N(se.x)), s = N(He.y).mul(16).add(N(se.y));
|
|
12142
12108
|
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(
|
|
12109
|
+
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
12110
|
Ne(r, Re(z(o), z(s)), W(d, 1)).toWriteOnly();
|
|
12145
12111
|
});
|
|
12146
12112
|
})().compute([
|
|
@@ -12158,12 +12124,12 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12158
12124
|
return f(() => {
|
|
12159
12125
|
let f = N(He.x).mul(16).add(N(se.x)), v = N(He.y).mul(16).add(N(se.y));
|
|
12160
12126
|
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(
|
|
12127
|
+
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
12128
|
let t = R(o, e);
|
|
12163
12129
|
return F(t.z, t.w);
|
|
12164
12130
|
}, 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
12131
|
for (let e = 0; e < 5; e++) for (let n = 0; n < 5; n++) {
|
|
12166
|
-
let a = n - 2, o = e - 2, s =
|
|
12132
|
+
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
12133
|
re.addAssign(m.mul(ce)), ie.addAssign(ce), M.addAssign(ce.mul(ce).mul(F(le, j(0))));
|
|
12168
12134
|
}
|
|
12169
12135
|
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 +12191,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12225
12191
|
dispose() {
|
|
12226
12192
|
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
12193
|
}
|
|
12228
|
-
},
|
|
12194
|
+
}, 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
12195
|
constructor(e, t = {}) {
|
|
12230
12196
|
super("AutoExposure", {
|
|
12231
12197
|
...t,
|
|
@@ -12241,7 +12207,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12241
12207
|
depthBuffer: !1,
|
|
12242
12208
|
stencilBuffer: !1
|
|
12243
12209
|
};
|
|
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(
|
|
12210
|
+
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
12211
|
}
|
|
12246
12212
|
_buildCompute() {
|
|
12247
12213
|
this._buildDownsampleCompute(), this._buildHistogramCompute(), this._buildHistogramAnalyzeCompute(), this._buildAdaptationCompute();
|
|
@@ -12275,7 +12241,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12275
12241
|
for (let i = 0; i < 16; i++) {
|
|
12276
12242
|
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
12243
|
p(u.greaterThan(0), () => {
|
|
12278
|
-
let e = z(l.div(u).sub(j(
|
|
12244
|
+
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
12245
|
x(t.element(e), d);
|
|
12280
12246
|
});
|
|
12281
12247
|
}
|
|
@@ -12293,14 +12259,14 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12293
12259
|
let e = this._histogramBuffer, t = this._reductionStorageTex, n = this.lowPercentileU, r = this.highPercentileU;
|
|
12294
12260
|
this._histogramAnalyzeNode = f(() => {
|
|
12295
12261
|
let i = j(0).toVar();
|
|
12296
|
-
m(
|
|
12262
|
+
m(bf, ({ i: t }) => {
|
|
12297
12263
|
i.addAssign(j(S(e.element(t))));
|
|
12298
12264
|
});
|
|
12299
12265
|
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(
|
|
12266
|
+
m(bf, ({ i: t }) => {
|
|
12301
12267
|
let n = j(S(e.element(t)));
|
|
12302
12268
|
u.assign(s), s.addAssign(n), p(u.lessThan(o).and(s.greaterThan(a)), () => {
|
|
12303
|
-
let e = j(
|
|
12269
|
+
let e = j(xf).add(j(t).add(.5).mul(j(Cf)));
|
|
12304
12270
|
c.addAssign(e.mul(n)), l.addAssign(n);
|
|
12305
12271
|
});
|
|
12306
12272
|
});
|
|
@@ -12315,7 +12281,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12315
12281
|
_buildAdaptationCompute() {
|
|
12316
12282
|
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
12283
|
this._adaptationComputeNode = f(() => {
|
|
12318
|
-
let u = R(e, P(N(0), N(0))).x, d =
|
|
12284
|
+
let u = R(e, P(N(0), N(0))).x, d = Tf(u, l, n, r, i, a, o, s, c);
|
|
12319
12285
|
t.element(z(0)).assign(d);
|
|
12320
12286
|
})().compute(1, [
|
|
12321
12287
|
1,
|
|
@@ -12379,7 +12345,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12379
12345
|
dispose() {
|
|
12380
12346
|
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
12347
|
}
|
|
12382
|
-
},
|
|
12348
|
+
}, Df = class extends lr {
|
|
12383
12349
|
constructor(n, r = {}) {
|
|
12384
12350
|
super("Compositor", {
|
|
12385
12351
|
...r,
|
|
@@ -12405,7 +12371,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12405
12371
|
dispose() {
|
|
12406
12372
|
this._sourceTexNode?.dispose(), this.compositorMaterial?.dispose(), this.compositorQuad = null;
|
|
12407
12373
|
}
|
|
12408
|
-
},
|
|
12374
|
+
}, Of = class {
|
|
12409
12375
|
constructor() {
|
|
12410
12376
|
this.textures = /* @__PURE__ */ new Map(), this.renderTargets = /* @__PURE__ */ new Map(), this.uniforms = /* @__PURE__ */ new Map(), this.state = {
|
|
12411
12377
|
frame: 0,
|
|
@@ -12527,7 +12493,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12527
12493
|
dispose() {
|
|
12528
12494
|
this.textures.clear(), this.renderTargets.clear(), this.uniforms.clear(), this._stateChangeCallbacks.clear(), this.state = {};
|
|
12529
12495
|
}
|
|
12530
|
-
},
|
|
12496
|
+
}, kf = class extends ut {
|
|
12531
12497
|
constructor() {
|
|
12532
12498
|
super(), this._onceCallbacks = /* @__PURE__ */ new Map();
|
|
12533
12499
|
}
|
|
@@ -12565,38 +12531,38 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12565
12531
|
eventNames() {
|
|
12566
12532
|
return this._listeners ? Object.keys(this._listeners) : [];
|
|
12567
12533
|
}
|
|
12568
|
-
},
|
|
12569
|
-
function
|
|
12570
|
-
|
|
12534
|
+
}, Af = !1, jf = [], Mf = /* @__PURE__ */ new WeakMap();
|
|
12535
|
+
function Nf(e) {
|
|
12536
|
+
Af = !!e;
|
|
12571
12537
|
}
|
|
12572
|
-
function
|
|
12573
|
-
return
|
|
12538
|
+
function Pf() {
|
|
12539
|
+
return jf.slice();
|
|
12574
12540
|
}
|
|
12575
|
-
function
|
|
12576
|
-
|
|
12541
|
+
function Ff() {
|
|
12542
|
+
jf.length = 0;
|
|
12577
12543
|
}
|
|
12578
|
-
function
|
|
12544
|
+
function If(e) {
|
|
12579
12545
|
let t = [];
|
|
12580
12546
|
for (let n of Object.keys(e)) e[n]?.isTextureNode === !0 && t.push(n);
|
|
12581
12547
|
return t;
|
|
12582
12548
|
}
|
|
12583
|
-
var
|
|
12584
|
-
function
|
|
12585
|
-
if (!
|
|
12549
|
+
var Lf = (e) => !e || !e.image || !(e.image.width > 0);
|
|
12550
|
+
function Rf(e, t, n) {
|
|
12551
|
+
if (!Af) {
|
|
12586
12552
|
n();
|
|
12587
12553
|
return;
|
|
12588
12554
|
}
|
|
12589
|
-
let r =
|
|
12555
|
+
let r = Mf.get(e);
|
|
12590
12556
|
if (r || (r = {
|
|
12591
12557
|
phase: "pending",
|
|
12592
12558
|
unboundAtCompile: []
|
|
12593
|
-
},
|
|
12594
|
-
n(), r.phase === "watch" &&
|
|
12559
|
+
}, Mf.set(e, r)), r.phase !== "pending") {
|
|
12560
|
+
n(), r.phase === "watch" && zf(e, r);
|
|
12595
12561
|
return;
|
|
12596
12562
|
}
|
|
12597
12563
|
let i = Object.prototype.hasOwnProperty.call(t, "compute"), a = t.compute;
|
|
12598
12564
|
t.compute = function(...t) {
|
|
12599
|
-
return r.phase === "pending" && (r.unboundAtCompile =
|
|
12565
|
+
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
12566
|
};
|
|
12601
12567
|
try {
|
|
12602
12568
|
n();
|
|
@@ -12604,14 +12570,14 @@ function If(e, t, n) {
|
|
|
12604
12570
|
i ? t.compute = a : delete t.compute;
|
|
12605
12571
|
}
|
|
12606
12572
|
}
|
|
12607
|
-
function
|
|
12573
|
+
function zf(e, t) {
|
|
12608
12574
|
let n = [];
|
|
12609
12575
|
for (let r of t.unboundAtCompile) {
|
|
12610
12576
|
let t = e[r]?.value;
|
|
12611
|
-
if (
|
|
12577
|
+
if (Lf(t)) return;
|
|
12612
12578
|
t.isStorageTexture !== !0 && n.push(r);
|
|
12613
12579
|
}
|
|
12614
|
-
t.phase = "done", n.length !== 0 &&
|
|
12580
|
+
t.phase = "done", n.length !== 0 && jf.push({
|
|
12615
12581
|
stage: e.name,
|
|
12616
12582
|
nodes: n,
|
|
12617
12583
|
unboundAtCompile: t.unboundAtCompile.slice(),
|
|
@@ -12620,9 +12586,9 @@ function Lf(e, t) {
|
|
|
12620
12586
|
}
|
|
12621
12587
|
//#endregion
|
|
12622
12588
|
//#region src/Pipeline/RenderPipeline.js
|
|
12623
|
-
var
|
|
12589
|
+
var Bf = class {
|
|
12624
12590
|
constructor(e, t, n) {
|
|
12625
|
-
this.renderer = e, this.width = t, this.height = n, this.stages = [], this.context = new
|
|
12591
|
+
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
12592
|
enabled: !1,
|
|
12627
12593
|
logSkipped: !1,
|
|
12628
12594
|
timings: /* @__PURE__ */ new Map(),
|
|
@@ -12656,7 +12622,7 @@ var Rf = class {
|
|
|
12656
12622
|
}
|
|
12657
12623
|
try {
|
|
12658
12624
|
let n = this.stats.enabled ? performance.now() : 0;
|
|
12659
|
-
if (
|
|
12625
|
+
if (Rf(t, this.renderer, () => t.render(this.context, e)), this.stats.enabled) {
|
|
12660
12626
|
let e = performance.now() - n;
|
|
12661
12627
|
this.stats.timings.has(t.name) || this.stats.timings.set(t.name, []);
|
|
12662
12628
|
let r = this.stats.timings.get(t.name);
|
|
@@ -12754,7 +12720,7 @@ var Rf = class {
|
|
|
12754
12720
|
let e = this.getInfo();
|
|
12755
12721
|
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
12722
|
}
|
|
12757
|
-
},
|
|
12723
|
+
}, Vf = class {
|
|
12758
12724
|
constructor() {
|
|
12759
12725
|
this.timeElapsed = 0, this.lastResetTime = performance.now(), this.renderCompleteDispatched = !1;
|
|
12760
12726
|
}
|
|
@@ -12776,7 +12742,7 @@ var Rf = class {
|
|
|
12776
12742
|
resumeFromPause() {
|
|
12777
12743
|
this.renderCompleteDispatched = !1, this.lastResetTime = performance.now() - this.timeElapsed * 1e3;
|
|
12778
12744
|
}
|
|
12779
|
-
},
|
|
12745
|
+
}, Hf = class extends ut {
|
|
12780
12746
|
constructor({ scene: e, camera: t, canvas: n, assetLoader: r, pathTracer: i, floorPlane: a }) {
|
|
12781
12747
|
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
12748
|
}
|
|
@@ -13012,18 +12978,18 @@ var Rf = class {
|
|
|
13012
12978
|
dispose() {
|
|
13013
12979
|
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
12980
|
}
|
|
13015
|
-
},
|
|
12981
|
+
}, Uf = {
|
|
13016
12982
|
STRING: "string",
|
|
13017
12983
|
NUMBER: "number",
|
|
13018
12984
|
WORD: "word",
|
|
13019
12985
|
LBRACKET: "[",
|
|
13020
12986
|
RBRACKET: "]"
|
|
13021
|
-
},
|
|
13022
|
-
function
|
|
12987
|
+
}, 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)));
|
|
12988
|
+
function qf(e) {
|
|
13023
12989
|
let t = [], n = e.length, r = 0;
|
|
13024
12990
|
for (; r < n;) {
|
|
13025
12991
|
let i = e[r];
|
|
13026
|
-
if (
|
|
12992
|
+
if (Wf(i)) {
|
|
13027
12993
|
r++;
|
|
13028
12994
|
continue;
|
|
13029
12995
|
}
|
|
@@ -13032,11 +12998,11 @@ function Gf(e) {
|
|
|
13032
12998
|
continue;
|
|
13033
12999
|
}
|
|
13034
13000
|
if (i === "[") {
|
|
13035
|
-
t.push({ type:
|
|
13001
|
+
t.push({ type: Uf.LBRACKET }), r++;
|
|
13036
13002
|
continue;
|
|
13037
13003
|
}
|
|
13038
13004
|
if (i === "]") {
|
|
13039
|
-
t.push({ type:
|
|
13005
|
+
t.push({ type: Uf.RBRACKET }), r++;
|
|
13040
13006
|
continue;
|
|
13041
13007
|
}
|
|
13042
13008
|
if (i === "\"") {
|
|
@@ -13045,12 +13011,12 @@ function Gf(e) {
|
|
|
13045
13011
|
for (; r < n && e[r] !== "\"";) r++;
|
|
13046
13012
|
if (r >= n) throw Error("PBRT tokenizer: unterminated string literal");
|
|
13047
13013
|
t.push({
|
|
13048
|
-
type:
|
|
13014
|
+
type: Uf.STRING,
|
|
13049
13015
|
value: e.slice(i, r)
|
|
13050
13016
|
}), r++;
|
|
13051
13017
|
continue;
|
|
13052
13018
|
}
|
|
13053
|
-
if (
|
|
13019
|
+
if (Kf(i, e[r + 1], e[r + 2])) {
|
|
13054
13020
|
let i = r;
|
|
13055
13021
|
for (r++; r < n;) {
|
|
13056
13022
|
let t = e[r];
|
|
@@ -13060,16 +13026,16 @@ function Gf(e) {
|
|
|
13060
13026
|
let a = e.slice(i, r), o = Number(a);
|
|
13061
13027
|
if (Number.isNaN(o)) throw Error(`PBRT tokenizer: invalid number "${a}"`);
|
|
13062
13028
|
t.push({
|
|
13063
|
-
type:
|
|
13029
|
+
type: Uf.NUMBER,
|
|
13064
13030
|
value: o
|
|
13065
13031
|
});
|
|
13066
13032
|
continue;
|
|
13067
13033
|
}
|
|
13068
13034
|
{
|
|
13069
13035
|
let i = r;
|
|
13070
|
-
for (; r < n && !
|
|
13036
|
+
for (; r < n && !Wf(e[r]) && e[r] !== "\"" && e[r] !== "[" && e[r] !== "]" && e[r] !== "#";) r++;
|
|
13071
13037
|
t.push({
|
|
13072
|
-
type:
|
|
13038
|
+
type: Uf.WORD,
|
|
13073
13039
|
value: e.slice(i, r)
|
|
13074
13040
|
});
|
|
13075
13041
|
}
|
|
@@ -13078,7 +13044,7 @@ function Gf(e) {
|
|
|
13078
13044
|
}
|
|
13079
13045
|
//#endregion
|
|
13080
13046
|
//#region src/Processor/PBRT/PBRTMath.js
|
|
13081
|
-
function
|
|
13047
|
+
function Jf() {
|
|
13082
13048
|
return [
|
|
13083
13049
|
1,
|
|
13084
13050
|
0,
|
|
@@ -13098,7 +13064,7 @@ function Kf() {
|
|
|
13098
13064
|
1
|
|
13099
13065
|
];
|
|
13100
13066
|
}
|
|
13101
|
-
function
|
|
13067
|
+
function Yf(e, t) {
|
|
13102
13068
|
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
13069
|
return [
|
|
13104
13070
|
n * v + o * y + u * b + m * x,
|
|
@@ -13119,7 +13085,7 @@ function qf(e, t) {
|
|
|
13119
13085
|
a * A + l * ee + p * te + _ * j
|
|
13120
13086
|
];
|
|
13121
13087
|
}
|
|
13122
|
-
function
|
|
13088
|
+
function Xf(e, t, n) {
|
|
13123
13089
|
return [
|
|
13124
13090
|
1,
|
|
13125
13091
|
0,
|
|
@@ -13139,7 +13105,7 @@ function Jf(e, t, n) {
|
|
|
13139
13105
|
1
|
|
13140
13106
|
];
|
|
13141
13107
|
}
|
|
13142
|
-
function
|
|
13108
|
+
function Zf(e, t, n) {
|
|
13143
13109
|
return [
|
|
13144
13110
|
e,
|
|
13145
13111
|
0,
|
|
@@ -13159,7 +13125,7 @@ function Yf(e, t, n) {
|
|
|
13159
13125
|
1
|
|
13160
13126
|
];
|
|
13161
13127
|
}
|
|
13162
|
-
function
|
|
13128
|
+
function Qf(e, t, n, r) {
|
|
13163
13129
|
let i = Math.hypot(t, n, r) || 1;
|
|
13164
13130
|
t /= i, n /= i, r /= i;
|
|
13165
13131
|
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 +13148,21 @@ function Xf(e, t, n, r) {
|
|
|
13182
13148
|
1
|
|
13183
13149
|
];
|
|
13184
13150
|
}
|
|
13185
|
-
function
|
|
13151
|
+
function $f(e, t) {
|
|
13186
13152
|
return [
|
|
13187
13153
|
e[0] - t[0],
|
|
13188
13154
|
e[1] - t[1],
|
|
13189
13155
|
e[2] - t[2]
|
|
13190
13156
|
];
|
|
13191
13157
|
}
|
|
13192
|
-
function
|
|
13158
|
+
function ep(e, t) {
|
|
13193
13159
|
return [
|
|
13194
13160
|
e[1] * t[2] - e[2] * t[1],
|
|
13195
13161
|
e[2] * t[0] - e[0] * t[2],
|
|
13196
13162
|
e[0] * t[1] - e[1] * t[0]
|
|
13197
13163
|
];
|
|
13198
13164
|
}
|
|
13199
|
-
function
|
|
13165
|
+
function tp(e) {
|
|
13200
13166
|
let t = Math.hypot(e[0], e[1], e[2]) || 1;
|
|
13201
13167
|
return [
|
|
13202
13168
|
e[0] / t,
|
|
@@ -13204,8 +13170,8 @@ function $f(e) {
|
|
|
13204
13170
|
e[2] / t
|
|
13205
13171
|
];
|
|
13206
13172
|
}
|
|
13207
|
-
function
|
|
13208
|
-
let r = $f(
|
|
13173
|
+
function np(e, t, n) {
|
|
13174
|
+
let r = tp($f(t, e)), i = tp(ep(tp(n), r)), a = ep(r, i);
|
|
13209
13175
|
return [
|
|
13210
13176
|
i[0],
|
|
13211
13177
|
i[1],
|
|
@@ -13225,9 +13191,9 @@ function ep(e, t, n) {
|
|
|
13225
13191
|
1
|
|
13226
13192
|
];
|
|
13227
13193
|
}
|
|
13228
|
-
function
|
|
13194
|
+
function rp(e) {
|
|
13229
13195
|
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
|
|
13196
|
+
if (x === 0) return Jf();
|
|
13231
13197
|
let S = 1 / x;
|
|
13232
13198
|
return [
|
|
13233
13199
|
_ * S,
|
|
@@ -13250,7 +13216,7 @@ function tp(e) {
|
|
|
13250
13216
|
}
|
|
13251
13217
|
//#endregion
|
|
13252
13218
|
//#region src/Processor/PBRT/PBRTParser.js
|
|
13253
|
-
var
|
|
13219
|
+
var ip = class {
|
|
13254
13220
|
constructor(e = {}) {
|
|
13255
13221
|
this.resolveInclude = e.resolveInclude || (() => {
|
|
13256
13222
|
throw Error("PBRTParser: Include used but no resolveInclude provided");
|
|
@@ -13264,14 +13230,14 @@ var np = class {
|
|
|
13264
13230
|
instances: [],
|
|
13265
13231
|
objects: /* @__PURE__ */ new Map(),
|
|
13266
13232
|
warnings: []
|
|
13267
|
-
}, this.ctm =
|
|
13233
|
+
}, this.ctm = Jf(), this.state = {
|
|
13268
13234
|
material: null,
|
|
13269
13235
|
areaLight: null,
|
|
13270
13236
|
reverseOrientation: !1
|
|
13271
13237
|
}, 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
13238
|
}
|
|
13273
13239
|
parse(e, t = "") {
|
|
13274
|
-
return this.dirStack = [t], this._run(
|
|
13240
|
+
return this.dirStack = [t], this._run(qf(e)), this.ir;
|
|
13275
13241
|
}
|
|
13276
13242
|
_peek() {
|
|
13277
13243
|
return this.tokens[this.pos];
|
|
@@ -13281,12 +13247,12 @@ var np = class {
|
|
|
13281
13247
|
}
|
|
13282
13248
|
_expectNumber(e) {
|
|
13283
13249
|
let t = this._next();
|
|
13284
|
-
if (!t || t.type !==
|
|
13250
|
+
if (!t || t.type !== Uf.NUMBER) throw Error(`PBRT parser: expected number for ${e}, got ${t ? t.value : "EOF"}`);
|
|
13285
13251
|
return t.value;
|
|
13286
13252
|
}
|
|
13287
13253
|
_expectString(e) {
|
|
13288
13254
|
let t = this._next();
|
|
13289
|
-
if (!t || t.type !==
|
|
13255
|
+
if (!t || t.type !== Uf.STRING) throw Error(`PBRT parser: expected string for ${e}, got ${t ? t.value : "EOF"}`);
|
|
13290
13256
|
return t.value;
|
|
13291
13257
|
}
|
|
13292
13258
|
_readNumbers(e) {
|
|
@@ -13295,17 +13261,17 @@ var np = class {
|
|
|
13295
13261
|
return t;
|
|
13296
13262
|
}
|
|
13297
13263
|
_readBracketedOrBareNumbers(e) {
|
|
13298
|
-
if (this._peek() && this._peek().type ===
|
|
13264
|
+
if (this._peek() && this._peek().type === Uf.LBRACKET) {
|
|
13299
13265
|
this._next();
|
|
13300
13266
|
let e = [];
|
|
13301
|
-
for (; this._peek() && this._peek().type !==
|
|
13267
|
+
for (; this._peek() && this._peek().type !== Uf.RBRACKET;) e.push(this._expectNumber("transform element"));
|
|
13302
13268
|
return this._next(), e;
|
|
13303
13269
|
}
|
|
13304
13270
|
return this._readNumbers(e);
|
|
13305
13271
|
}
|
|
13306
13272
|
_parseParams() {
|
|
13307
13273
|
let e = {};
|
|
13308
|
-
for (; this._peek() && this._peek().type ===
|
|
13274
|
+
for (; this._peek() && this._peek().type === Uf.STRING;) {
|
|
13309
13275
|
let t = this._next().value.trim().split(/\s+/), n = t[0], r = t[1] === void 0 ? t[0] : t[1];
|
|
13310
13276
|
e[r] = {
|
|
13311
13277
|
type: n,
|
|
@@ -13316,23 +13282,23 @@ var np = class {
|
|
|
13316
13282
|
}
|
|
13317
13283
|
_parseParamValue() {
|
|
13318
13284
|
let e = [];
|
|
13319
|
-
if (this._peek() && this._peek().type ===
|
|
13320
|
-
for (this._next(); this._peek() && this._peek().type !==
|
|
13285
|
+
if (this._peek() && this._peek().type === Uf.LBRACKET) {
|
|
13286
|
+
for (this._next(); this._peek() && this._peek().type !== Uf.RBRACKET;) e.push(this._coerceValueToken(this._next()));
|
|
13321
13287
|
this._next();
|
|
13322
13288
|
} else e.push(this._coerceValueToken(this._next()));
|
|
13323
13289
|
return e;
|
|
13324
13290
|
}
|
|
13325
13291
|
_coerceValueToken(e) {
|
|
13326
13292
|
if (!e) throw Error("PBRT parser: unexpected EOF in parameter value");
|
|
13327
|
-
if (e.type ===
|
|
13328
|
-
if (e.type ===
|
|
13293
|
+
if (e.type === Uf.NUMBER || e.type === Uf.STRING) return e.value;
|
|
13294
|
+
if (e.type === Uf.WORD) return e.value === "true" ? !0 : e.value === "false" ? !1 : e.value;
|
|
13329
13295
|
throw Error(`PBRT parser: unexpected token in parameter value: ${e.type}`);
|
|
13330
13296
|
}
|
|
13331
13297
|
_run(e) {
|
|
13332
13298
|
let t = this.tokens, n = this.pos;
|
|
13333
13299
|
for (this.tokens = e, this.pos = 0; this.pos < this.tokens.length;) {
|
|
13334
13300
|
let e = this._next();
|
|
13335
|
-
if (e.type !==
|
|
13301
|
+
if (e.type !== Uf.WORD) throw Error(`PBRT parser: expected directive, got ${e.type} ${e.value ?? ""}`);
|
|
13336
13302
|
this._directive(e.value);
|
|
13337
13303
|
}
|
|
13338
13304
|
this.tokens = t, this.pos = n;
|
|
@@ -13340,25 +13306,25 @@ var np = class {
|
|
|
13340
13306
|
_directive(e) {
|
|
13341
13307
|
switch (e) {
|
|
13342
13308
|
case "Identity":
|
|
13343
|
-
this.ctm =
|
|
13309
|
+
this.ctm = Jf();
|
|
13344
13310
|
break;
|
|
13345
13311
|
case "Translate": {
|
|
13346
13312
|
let [e, t, n] = this._readNumbers(3);
|
|
13347
|
-
this.ctm =
|
|
13313
|
+
this.ctm = Yf(this.ctm, Xf(e, t, n));
|
|
13348
13314
|
break;
|
|
13349
13315
|
}
|
|
13350
13316
|
case "Scale": {
|
|
13351
13317
|
let [e, t, n] = this._readNumbers(3);
|
|
13352
|
-
this.ctm =
|
|
13318
|
+
this.ctm = Yf(this.ctm, Zf(e, t, n));
|
|
13353
13319
|
break;
|
|
13354
13320
|
}
|
|
13355
13321
|
case "Rotate": {
|
|
13356
13322
|
let [e, t, n, r] = this._readNumbers(4);
|
|
13357
|
-
this.ctm =
|
|
13323
|
+
this.ctm = Yf(this.ctm, Qf(e, t, n, r));
|
|
13358
13324
|
break;
|
|
13359
13325
|
}
|
|
13360
13326
|
case "LookAt": {
|
|
13361
|
-
let e = this._readNumbers(9), t =
|
|
13327
|
+
let e = this._readNumbers(9), t = np([
|
|
13362
13328
|
e[0],
|
|
13363
13329
|
e[1],
|
|
13364
13330
|
e[2]
|
|
@@ -13371,7 +13337,7 @@ var np = class {
|
|
|
13371
13337
|
e[7],
|
|
13372
13338
|
e[8]
|
|
13373
13339
|
]);
|
|
13374
|
-
this.ctm =
|
|
13340
|
+
this.ctm = Yf(this.ctm, rp(t));
|
|
13375
13341
|
break;
|
|
13376
13342
|
}
|
|
13377
13343
|
case "Transform":
|
|
@@ -13379,7 +13345,7 @@ var np = class {
|
|
|
13379
13345
|
break;
|
|
13380
13346
|
case "ConcatTransform": {
|
|
13381
13347
|
let e = this._readBracketedOrBareNumbers(16);
|
|
13382
|
-
this.ctm =
|
|
13348
|
+
this.ctm = Yf(this.ctm, e);
|
|
13383
13349
|
break;
|
|
13384
13350
|
}
|
|
13385
13351
|
case "CoordinateSystem":
|
|
@@ -13395,7 +13361,7 @@ var np = class {
|
|
|
13395
13361
|
this.ir.camera = {
|
|
13396
13362
|
type: e,
|
|
13397
13363
|
params: t,
|
|
13398
|
-
cameraToWorld:
|
|
13364
|
+
cameraToWorld: rp(this.ctm)
|
|
13399
13365
|
};
|
|
13400
13366
|
break;
|
|
13401
13367
|
}
|
|
@@ -13419,7 +13385,7 @@ var np = class {
|
|
|
13419
13385
|
this._skipTypeAndParams();
|
|
13420
13386
|
break;
|
|
13421
13387
|
case "WorldBegin":
|
|
13422
|
-
this.ctm =
|
|
13388
|
+
this.ctm = Jf(), this.state = {
|
|
13423
13389
|
material: null,
|
|
13424
13390
|
areaLight: null,
|
|
13425
13391
|
reverseOrientation: !1
|
|
@@ -13464,7 +13430,7 @@ var np = class {
|
|
|
13464
13430
|
this._readNumbers(2);
|
|
13465
13431
|
break;
|
|
13466
13432
|
case "MediumInterface":
|
|
13467
|
-
this._peek() && this._peek().type ===
|
|
13433
|
+
this._peek() && this._peek().type === Uf.STRING && this._next(), this._peek() && this._peek().type === Uf.STRING && this._next();
|
|
13468
13434
|
break;
|
|
13469
13435
|
case "MakeNamedMedium":
|
|
13470
13436
|
this._skipNamedAndParams();
|
|
@@ -13572,7 +13538,7 @@ var np = class {
|
|
|
13572
13538
|
}
|
|
13573
13539
|
}
|
|
13574
13540
|
_emitShape(e) {
|
|
13575
|
-
this.currentObject === null ? this.ir.shapes.push(e) : (e.relativeCTM =
|
|
13541
|
+
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
13542
|
}
|
|
13577
13543
|
_include(e) {
|
|
13578
13544
|
let t = this.resolveInclude(e, this.dirStack[this.dirStack.length - 1]);
|
|
@@ -13581,13 +13547,13 @@ var np = class {
|
|
|
13581
13547
|
return;
|
|
13582
13548
|
}
|
|
13583
13549
|
let n = e.includes("/") ? e.slice(0, e.lastIndexOf("/")) : "";
|
|
13584
|
-
this.dirStack.push(n), this._run(
|
|
13550
|
+
this.dirStack.push(n), this._run(qf(t)), this.dirStack.pop();
|
|
13585
13551
|
}
|
|
13586
13552
|
_skipTypeAndParams() {
|
|
13587
|
-
this._peek() && this._peek().type ===
|
|
13553
|
+
this._peek() && this._peek().type === Uf.STRING && this._next(), this._parseParams();
|
|
13588
13554
|
}
|
|
13589
13555
|
_skipNamedAndParams() {
|
|
13590
|
-
this._peek() && this._peek().type ===
|
|
13556
|
+
this._peek() && this._peek().type === Uf.STRING && this._next(), this._parseParams();
|
|
13591
13557
|
}
|
|
13592
13558
|
_num(e, t) {
|
|
13593
13559
|
return e && e.value.length ? e.value[0] : t;
|
|
@@ -13601,7 +13567,7 @@ var np = class {
|
|
|
13601
13567
|
_warnUnknown(e) {
|
|
13602
13568
|
this._warnedUnknown.has(e) || (this._warnedUnknown.add(e), this._warn(`Unsupported directive ignored: ${e}`));
|
|
13603
13569
|
}
|
|
13604
|
-
},
|
|
13570
|
+
}, ap = {
|
|
13605
13571
|
au: [
|
|
13606
13572
|
1,
|
|
13607
13573
|
.78,
|
|
@@ -13657,12 +13623,12 @@ var np = class {
|
|
|
13657
13623
|
.9,
|
|
13658
13624
|
.9
|
|
13659
13625
|
]
|
|
13660
|
-
},
|
|
13626
|
+
}, op = [
|
|
13661
13627
|
.92,
|
|
13662
13628
|
.92,
|
|
13663
13629
|
.92
|
|
13664
13630
|
];
|
|
13665
|
-
function
|
|
13631
|
+
function sp(e) {
|
|
13666
13632
|
let t = Math.max(1e3, Math.min(4e4, e)) / 100, n, r, i;
|
|
13667
13633
|
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
13634
|
let a = (e) => Math.max(0, Math.min(255, e)) / 255;
|
|
@@ -13672,15 +13638,15 @@ function ap(e) {
|
|
|
13672
13638
|
a(i) ** 2.2
|
|
13673
13639
|
];
|
|
13674
13640
|
}
|
|
13675
|
-
function
|
|
13641
|
+
function cp(e, t, n) {
|
|
13676
13642
|
let r = e[t];
|
|
13677
13643
|
return r && typeof r.value[0] == "number" ? r.value[0] : n;
|
|
13678
13644
|
}
|
|
13679
|
-
function
|
|
13645
|
+
function lp(e, t, n) {
|
|
13680
13646
|
let r = e[t];
|
|
13681
13647
|
return r && typeof r.value[0] == "string" ? r.value[0] : n;
|
|
13682
13648
|
}
|
|
13683
|
-
async function
|
|
13649
|
+
async function up(e, t, n, r = null) {
|
|
13684
13650
|
let i = e[t];
|
|
13685
13651
|
if (!i) return {
|
|
13686
13652
|
rgb: r,
|
|
@@ -13719,14 +13685,14 @@ async function cp(e, t, n, r = null) {
|
|
|
13719
13685
|
};
|
|
13720
13686
|
}
|
|
13721
13687
|
if (i.type === "blackbody") return {
|
|
13722
|
-
rgb:
|
|
13688
|
+
rgb: sp(i.value[0]),
|
|
13723
13689
|
texture: null
|
|
13724
13690
|
};
|
|
13725
13691
|
if (i.type === "spectrum") {
|
|
13726
13692
|
if (typeof i.value[0] == "string") {
|
|
13727
|
-
let e =
|
|
13728
|
-
return e &&
|
|
13729
|
-
rgb:
|
|
13693
|
+
let e = dp(i.value[0]);
|
|
13694
|
+
return e && ap[e] ? {
|
|
13695
|
+
rgb: ap[e].slice(),
|
|
13730
13696
|
texture: null
|
|
13731
13697
|
} : (n.warn(`named spectrum "${i.value[0]}" approximated to gray`), {
|
|
13732
13698
|
rgb: [
|
|
@@ -13754,18 +13720,18 @@ async function cp(e, t, n, r = null) {
|
|
|
13754
13720
|
texture: null
|
|
13755
13721
|
};
|
|
13756
13722
|
}
|
|
13757
|
-
function
|
|
13723
|
+
function dp(e) {
|
|
13758
13724
|
let t = e.toLowerCase().match(/metal-([a-z]+)/);
|
|
13759
13725
|
if (t) return t[1];
|
|
13760
|
-
for (let t of Object.keys(
|
|
13726
|
+
for (let t of Object.keys(ap)) if (e.toLowerCase().includes(t)) return t;
|
|
13761
13727
|
return null;
|
|
13762
13728
|
}
|
|
13763
|
-
function
|
|
13729
|
+
function fp(e, t) {
|
|
13764
13730
|
if (e.roughness && typeof e.roughness.value[0] == "number") return e.roughness.value[0];
|
|
13765
|
-
let n =
|
|
13731
|
+
let n = cp(e, "uroughness", null), r = cp(e, "vroughness", null);
|
|
13766
13732
|
return n !== null && r !== null ? (n + r) / 2 : n === null ? t : n;
|
|
13767
13733
|
}
|
|
13768
|
-
async function
|
|
13734
|
+
async function pp(e, t) {
|
|
13769
13735
|
let n = e?.type || "diffuse", r = e?.params || {}, i = new Et({
|
|
13770
13736
|
side: ct,
|
|
13771
13737
|
roughness: 1,
|
|
@@ -13777,7 +13743,7 @@ async function dp(e, t) {
|
|
|
13777
13743
|
};
|
|
13778
13744
|
switch (n) {
|
|
13779
13745
|
case "diffuse":
|
|
13780
|
-
o(await
|
|
13746
|
+
o(await up(r, "reflectance", t, [
|
|
13781
13747
|
.5,
|
|
13782
13748
|
.5,
|
|
13783
13749
|
.5
|
|
@@ -13785,14 +13751,14 @@ async function dp(e, t) {
|
|
|
13785
13751
|
break;
|
|
13786
13752
|
case "conductor":
|
|
13787
13753
|
case "metal": {
|
|
13788
|
-
let e = await
|
|
13754
|
+
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
13755
|
if (e.rgb || e.texture) o(e);
|
|
13790
13756
|
else if (n && s && !c) {
|
|
13791
|
-
let e = (await
|
|
13757
|
+
let e = (await up(r, "eta", t, [
|
|
13792
13758
|
.2,
|
|
13793
13759
|
.92,
|
|
13794
13760
|
1.1
|
|
13795
|
-
])).rgb, n = (await
|
|
13761
|
+
])).rgb, n = (await up(r, "k", t, [
|
|
13796
13762
|
3.9,
|
|
13797
13763
|
2.45,
|
|
13798
13764
|
2.14
|
|
@@ -13802,28 +13768,28 @@ async function dp(e, t) {
|
|
|
13802
13768
|
i(e[1], n[1]),
|
|
13803
13769
|
i(e[2], n[2])
|
|
13804
13770
|
]);
|
|
13805
|
-
} else a(n ? (await
|
|
13806
|
-
i.metalness = 1, i.roughness =
|
|
13771
|
+
} else a(n ? (await up(r, "eta", t, op)).rgb || op : ap.cu);
|
|
13772
|
+
i.metalness = 1, i.roughness = fp(r, .1);
|
|
13807
13773
|
break;
|
|
13808
13774
|
}
|
|
13809
13775
|
case "dielectric":
|
|
13810
13776
|
case "thindielectric":
|
|
13811
|
-
i.transmission = 1, i.metalness = 0, i.color.setRGB(1, 1, 1), i.ior =
|
|
13777
|
+
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
13778
|
break;
|
|
13813
13779
|
case "coateddiffuse":
|
|
13814
|
-
o(await
|
|
13780
|
+
o(await up(r, "reflectance", t, [
|
|
13815
13781
|
.5,
|
|
13816
13782
|
.5,
|
|
13817
13783
|
.5
|
|
13818
|
-
])), i.roughness = .6, i.metalness = 0, i.clearcoat = 1, i.clearcoatRoughness =
|
|
13784
|
+
])), i.roughness = .6, i.metalness = 0, i.clearcoat = 1, i.clearcoatRoughness = fp(r, 0);
|
|
13819
13785
|
break;
|
|
13820
13786
|
case "diffusetransmission": {
|
|
13821
|
-
let e = await
|
|
13787
|
+
let e = await up(r, "transmittance", t, [
|
|
13822
13788
|
.25,
|
|
13823
13789
|
.25,
|
|
13824
13790
|
.25
|
|
13825
13791
|
]);
|
|
13826
|
-
o(await
|
|
13792
|
+
o(await up(r, "reflectance", t, [
|
|
13827
13793
|
.25,
|
|
13828
13794
|
.25,
|
|
13829
13795
|
.25
|
|
@@ -13836,9 +13802,9 @@ async function dp(e, t) {
|
|
|
13836
13802
|
i.transmission = 1, i.ior = 1, i.roughness = 0, i.color.setRGB(1, 1, 1);
|
|
13837
13803
|
break;
|
|
13838
13804
|
case "mix": {
|
|
13839
|
-
let e = r.materials?.value || [], n = Math.max(0, Math.min(1,
|
|
13805
|
+
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
13806
|
if (a && o) {
|
|
13841
|
-
let [e, r] = await Promise.all([
|
|
13807
|
+
let [e, r] = await Promise.all([pp(a, t), pp(o, t)]), s = (e, t) => e * (1 - n) + t * n;
|
|
13842
13808
|
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
13809
|
break;
|
|
13844
13810
|
}
|
|
@@ -13848,7 +13814,7 @@ async function dp(e, t) {
|
|
|
13848
13814
|
case "subsurface":
|
|
13849
13815
|
case "hair":
|
|
13850
13816
|
case "measured":
|
|
13851
|
-
t.warn(`material "${n}" not supported — using diffuse approximation`), a((await
|
|
13817
|
+
t.warn(`material "${n}" not supported — using diffuse approximation`), a((await up(r, "reflectance", t, [
|
|
13852
13818
|
.5,
|
|
13853
13819
|
.5,
|
|
13854
13820
|
.5
|
|
@@ -13862,7 +13828,7 @@ async function dp(e, t) {
|
|
|
13862
13828
|
}
|
|
13863
13829
|
//#endregion
|
|
13864
13830
|
//#region src/Processor/PBRT/PBRTSceneBuilder.js
|
|
13865
|
-
var
|
|
13831
|
+
var mp = [
|
|
13866
13832
|
1,
|
|
13867
13833
|
0,
|
|
13868
13834
|
0,
|
|
@@ -13879,7 +13845,7 @@ var fp = [
|
|
|
13879
13845
|
0,
|
|
13880
13846
|
0,
|
|
13881
13847
|
1
|
|
13882
|
-
],
|
|
13848
|
+
], hp = class {
|
|
13883
13849
|
constructor(e = {}) {
|
|
13884
13850
|
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
13851
|
}
|
|
@@ -13915,7 +13881,7 @@ var fp = [
|
|
|
13915
13881
|
continue;
|
|
13916
13882
|
}
|
|
13917
13883
|
for (let e of i) {
|
|
13918
|
-
let i =
|
|
13884
|
+
let i = Yf(r.ctm, e.relativeCTM || e.ctm), a = await this._buildShapeMesh(e, i, `instance_${n++}`);
|
|
13919
13885
|
a && t.add(a);
|
|
13920
13886
|
}
|
|
13921
13887
|
}
|
|
@@ -13927,7 +13893,7 @@ var fp = [
|
|
|
13927
13893
|
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
13894
|
let s = new wt(r, o);
|
|
13929
13895
|
s.name = n;
|
|
13930
|
-
let c = this.convertHandedness ?
|
|
13896
|
+
let c = this.convertHandedness ? Yf(mp, t) : t;
|
|
13931
13897
|
new Ct().fromArray(c).decompose(s.position, s.quaternion, s.scale), s.updateMatrix(), r.computeBoundingBox();
|
|
13932
13898
|
let l = r.boundingBox ? r.boundingBox.clone().applyMatrix4(s.matrix).getSize(new cn()) : new cn();
|
|
13933
13899
|
return this.report.push({
|
|
@@ -13982,7 +13948,7 @@ var fp = [
|
|
|
13982
13948
|
return i.setAttribute("position", new dt(Float32Array.from(t), 3)), i.setIndex(r), i.computeVertexNormals(), i;
|
|
13983
13949
|
}
|
|
13984
13950
|
async _plyMesh(e) {
|
|
13985
|
-
let t =
|
|
13951
|
+
let t = lp(e, "filename", null);
|
|
13986
13952
|
if (!t) return this.warn("plymesh missing filename"), null;
|
|
13987
13953
|
try {
|
|
13988
13954
|
let e = await this.resolvePLY(t);
|
|
@@ -13992,10 +13958,10 @@ var fp = [
|
|
|
13992
13958
|
}
|
|
13993
13959
|
}
|
|
13994
13960
|
_sphere(e) {
|
|
13995
|
-
return new Zt(
|
|
13961
|
+
return new Zt(cp(e, "radius", 1), 48, 32);
|
|
13996
13962
|
}
|
|
13997
13963
|
_disk(e) {
|
|
13998
|
-
let t =
|
|
13964
|
+
let t = cp(e, "radius", 1), n = cp(e, "innerradius", 0), r = cp(e, "height", 0), i = [], a = [];
|
|
13999
13965
|
for (let e = 0; e < 48; e++) {
|
|
14000
13966
|
let o = e / 48 * Math.PI * 2, s = (e + 1) / 48 * Math.PI * 2, c = i.length / 3;
|
|
14001
13967
|
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 +13976,15 @@ var fp = [
|
|
|
14010
13976
|
resolveNamedTexture: (e) => this._resolveNamedTexture(e),
|
|
14011
13977
|
namedMaterials: this.ir.namedMaterials,
|
|
14012
13978
|
warn: (e) => this.warn(e)
|
|
14013
|
-
}, r = await
|
|
13979
|
+
}, r = await pp(e.material, n);
|
|
14014
13980
|
return e.areaLight && await this._applyAreaLight(r, e.areaLight, n), t.set(e.areaLight, r), r;
|
|
14015
13981
|
}
|
|
14016
13982
|
async _applyAreaLight(e, t, n) {
|
|
14017
|
-
let r = await
|
|
13983
|
+
let r = await up(t.params, "L", n, [
|
|
14018
13984
|
1,
|
|
14019
13985
|
1,
|
|
14020
13986
|
1
|
|
14021
|
-
]), i =
|
|
13987
|
+
]), i = cp(t.params, "scale", 1), a = r.rgb || [
|
|
14022
13988
|
1,
|
|
14023
13989
|
1,
|
|
14024
13990
|
1
|
|
@@ -14030,7 +13996,7 @@ var fp = [
|
|
|
14030
13996
|
let t = this.ir.namedTextures.get(e), n = null;
|
|
14031
13997
|
if (!t) this.warn(`named texture "${e}" not defined`);
|
|
14032
13998
|
else if (t.class === "imagemap") {
|
|
14033
|
-
let r =
|
|
13999
|
+
let r = lp(t.params, "filename", null);
|
|
14034
14000
|
if (r) try {
|
|
14035
14001
|
let t = await this.resolveImage(r);
|
|
14036
14002
|
t ? n = { texture: t } : this.warn(`image not found for texture "${e}": ${r}`);
|
|
@@ -14118,7 +14084,7 @@ var fp = [
|
|
|
14118
14084
|
return c.name = "PBRT Camera", c.up.copy(a.normalize()), c.position.copy(r), c.lookAt(o), c.updateMatrixWorld(!0), c;
|
|
14119
14085
|
}
|
|
14120
14086
|
_verticalFov(e, t) {
|
|
14121
|
-
let n =
|
|
14087
|
+
let n = cp(e, "fov", 90);
|
|
14122
14088
|
if (t >= 1) return n;
|
|
14123
14089
|
let r = n * Math.PI / 180;
|
|
14124
14090
|
return 2 * Math.atan(Math.tan(r / 2) / t) * 180 / Math.PI;
|
|
@@ -14126,7 +14092,7 @@ var fp = [
|
|
|
14126
14092
|
async _buildEnvironment(e) {
|
|
14127
14093
|
let t = e.find((e) => e.type === "infinite");
|
|
14128
14094
|
if (!t) return null;
|
|
14129
|
-
let n =
|
|
14095
|
+
let n = cp(t.params, "scale", 1), r = lp(t.params, "filename", null);
|
|
14130
14096
|
if (r) try {
|
|
14131
14097
|
let e = await this.resolveEnvironment(r);
|
|
14132
14098
|
if (e) return e.mapping = lt, { texture: e };
|
|
@@ -14134,7 +14100,7 @@ var fp = [
|
|
|
14134
14100
|
} catch (e) {
|
|
14135
14101
|
this.warn(`failed to load infinite-light image ${r}: ${e.message}`);
|
|
14136
14102
|
}
|
|
14137
|
-
let i = ((await
|
|
14103
|
+
let i = ((await up(t.params, "L", {
|
|
14138
14104
|
resolveNamedTexture: async () => null,
|
|
14139
14105
|
warn: (e) => this.warn(e)
|
|
14140
14106
|
}, [
|
|
@@ -14153,20 +14119,20 @@ var fp = [
|
|
|
14153
14119
|
_reportUnsupportedLights(e) {
|
|
14154
14120
|
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
14121
|
}
|
|
14156
|
-
},
|
|
14157
|
-
function
|
|
14122
|
+
}, gp = new TextDecoder();
|
|
14123
|
+
function _p(e) {
|
|
14158
14124
|
let t = e.replace(/\\/g, "/").split("/"), n = [];
|
|
14159
14125
|
for (let e of t) e === "" || e === "." || (e === ".." ? n.pop() : n.push(e));
|
|
14160
14126
|
return n.join("/");
|
|
14161
14127
|
}
|
|
14162
|
-
function
|
|
14163
|
-
return !e || t.startsWith("/") ?
|
|
14128
|
+
function vp(e, t) {
|
|
14129
|
+
return !e || t.startsWith("/") ? _p(t) : _p(`${e}/${t}`);
|
|
14164
14130
|
}
|
|
14165
|
-
var
|
|
14131
|
+
var yp = class {
|
|
14166
14132
|
constructor(e) {
|
|
14167
14133
|
this.byPath = /* @__PURE__ */ new Map(), this.byBase = /* @__PURE__ */ new Map();
|
|
14168
14134
|
for (let t in e) {
|
|
14169
|
-
let n =
|
|
14135
|
+
let n = _p(t).toLowerCase(), r = {
|
|
14170
14136
|
norm: n,
|
|
14171
14137
|
bytes: e[t]
|
|
14172
14138
|
};
|
|
@@ -14176,13 +14142,13 @@ var _p = class {
|
|
|
14176
14142
|
}
|
|
14177
14143
|
}
|
|
14178
14144
|
find(e) {
|
|
14179
|
-
let t =
|
|
14145
|
+
let t = _p(e).toLowerCase();
|
|
14180
14146
|
if (this.byPath.has(t)) return this.byPath.get(t).bytes;
|
|
14181
14147
|
let n = this.byBase.get(t.split("/").pop());
|
|
14182
14148
|
return n ? (n.find((e) => e.norm.endsWith("/" + t)) || n[0]).bytes : null;
|
|
14183
14149
|
}
|
|
14184
14150
|
};
|
|
14185
|
-
function
|
|
14151
|
+
function bp(e) {
|
|
14186
14152
|
let t = Object.keys(e).filter((e) => e.toLowerCase().endsWith(".pbrt"));
|
|
14187
14153
|
if (t.length === 0) return null;
|
|
14188
14154
|
let n = t.filter((e) => /(^|\/)(scene|main)\.pbrt$/i.test(e)), r = n.length ? n : t;
|
|
@@ -14191,17 +14157,17 @@ function vp(e) {
|
|
|
14191
14157
|
return n === r ? e.length - t.length : n - r;
|
|
14192
14158
|
}), r[0];
|
|
14193
14159
|
}
|
|
14194
|
-
async function
|
|
14195
|
-
let { vfs: t, plyParser: n, imageFromBytes: r, envFromBytes: i, convertHandedness: a } = e, o = new
|
|
14160
|
+
async function xp(e) {
|
|
14161
|
+
let { vfs: t, plyParser: n, imageFromBytes: r, envFromBytes: i, convertHandedness: a } = e, o = new yp(t), s = e.entryPath || bp(t);
|
|
14196
14162
|
if (!s) throw Error("PBRT loader: no .pbrt file found in archive");
|
|
14197
14163
|
let c = o.find(s);
|
|
14198
14164
|
if (!c) throw Error(`PBRT loader: entry "${s}" not readable`);
|
|
14199
|
-
let l = s.includes("/") ? s.slice(0, s.lastIndexOf("/")) : "", u = new
|
|
14200
|
-
let n = o.find(
|
|
14201
|
-
return n ?
|
|
14202
|
-
} }).parse(
|
|
14165
|
+
let l = s.includes("/") ? s.slice(0, s.lastIndexOf("/")) : "", u = new ip({ resolveInclude: (e, t) => {
|
|
14166
|
+
let n = o.find(vp(t, e)) || o.find(e);
|
|
14167
|
+
return n ? gp.decode(n) : null;
|
|
14168
|
+
} }).parse(gp.decode(c), l), d = (e) => e.buffer.slice(e.byteOffset, e.byteOffset + e.byteLength);
|
|
14203
14169
|
return {
|
|
14204
|
-
...await new
|
|
14170
|
+
...await new hp({
|
|
14205
14171
|
convertHandedness: a,
|
|
14206
14172
|
resolvePLY: async (e) => {
|
|
14207
14173
|
let t = o.find(e);
|
|
@@ -14221,7 +14187,7 @@ async function yp(e) {
|
|
|
14221
14187
|
}
|
|
14222
14188
|
//#endregion
|
|
14223
14189
|
//#region src/Processor/AssetLoader.js
|
|
14224
|
-
var
|
|
14190
|
+
var Sp = {
|
|
14225
14191
|
glb: {
|
|
14226
14192
|
type: "model",
|
|
14227
14193
|
name: "GLB (GLTF Binary)"
|
|
@@ -14286,7 +14252,7 @@ var bp = {
|
|
|
14286
14252
|
type: "archive",
|
|
14287
14253
|
name: "ZIP Archive"
|
|
14288
14254
|
}
|
|
14289
|
-
},
|
|
14255
|
+
}, Cp = class e extends ut {
|
|
14290
14256
|
constructor(e, t, n) {
|
|
14291
14257
|
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
14258
|
}
|
|
@@ -14332,7 +14298,7 @@ var bp = {
|
|
|
14332
14298
|
this.renderer = e;
|
|
14333
14299
|
}
|
|
14334
14300
|
getFileFormat(e) {
|
|
14335
|
-
return
|
|
14301
|
+
return Sp[e.split(".").pop().toLowerCase()] || null;
|
|
14336
14302
|
}
|
|
14337
14303
|
readFileAsArrayBuffer(e) {
|
|
14338
14304
|
return new Promise((t, n) => {
|
|
@@ -14467,7 +14433,7 @@ var bp = {
|
|
|
14467
14433
|
async loadArchiveFromFile(e, t) {
|
|
14468
14434
|
try {
|
|
14469
14435
|
let n = await this.readFileAsArrayBuffer(e), r = yn(new Uint8Array(n));
|
|
14470
|
-
return
|
|
14436
|
+
return bp(r) ? await this.loadPBRTFromZip(r, t) : await this.processObjMtlPairsInZip(r, t) || await this.findAndLoadModelFromZip(r, t);
|
|
14471
14437
|
} catch (e) {
|
|
14472
14438
|
throw console.error("Error loading ZIP archive:", e), e;
|
|
14473
14439
|
}
|
|
@@ -14481,7 +14447,7 @@ var bp = {
|
|
|
14481
14447
|
let { PLYLoader: e } = await import("three/examples/jsm/loaders/PLYLoader.js");
|
|
14482
14448
|
this.loaderCache.ply = new e();
|
|
14483
14449
|
}
|
|
14484
|
-
let { group: n, environment: r, report: i, warnings: a, entryPath: o } = await
|
|
14450
|
+
let { group: n, environment: r, report: i, warnings: a, entryPath: o } = await xp({
|
|
14485
14451
|
vfs: e,
|
|
14486
14452
|
plyParser: (e) => this.loaderCache.ply.parse(e),
|
|
14487
14453
|
imageFromBytes: (e, t) => this._pbrtTextureFromBytes(e, t),
|
|
@@ -14580,7 +14546,7 @@ var bp = {
|
|
|
14580
14546
|
}
|
|
14581
14547
|
for (let t in e) {
|
|
14582
14548
|
let n = t.split(".").pop().toLowerCase();
|
|
14583
|
-
if (
|
|
14549
|
+
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
14550
|
}
|
|
14585
14551
|
throw Error("No supported model files found in the ZIP archive");
|
|
14586
14552
|
}
|
|
@@ -15140,10 +15106,10 @@ var bp = {
|
|
|
15140
15106
|
getSupportedFormats(e = null) {
|
|
15141
15107
|
if (e) {
|
|
15142
15108
|
let t = {};
|
|
15143
|
-
for (let [n, r] of Object.entries(
|
|
15109
|
+
for (let [n, r] of Object.entries(Sp)) r.type === e && (t[n] = r);
|
|
15144
15110
|
return t;
|
|
15145
15111
|
}
|
|
15146
|
-
return
|
|
15112
|
+
return Sp;
|
|
15147
15113
|
}
|
|
15148
15114
|
dispose() {
|
|
15149
15115
|
for (let e in this.loaderCache) {
|
|
@@ -15155,7 +15121,7 @@ var bp = {
|
|
|
15155
15121
|
removeAllEventListeners() {
|
|
15156
15122
|
this._listeners = void 0;
|
|
15157
15123
|
}
|
|
15158
|
-
},
|
|
15124
|
+
}, wp = {
|
|
15159
15125
|
maxBounces: {
|
|
15160
15126
|
uniform: "maxBounces",
|
|
15161
15127
|
reset: !0
|
|
@@ -15224,6 +15190,10 @@ var bp = {
|
|
|
15224
15190
|
uniform: "globalIlluminationIntensity",
|
|
15225
15191
|
reset: !0
|
|
15226
15192
|
},
|
|
15193
|
+
panoramaLevelHorizon: {
|
|
15194
|
+
uniform: "panoLevelHorizon",
|
|
15195
|
+
reset: !0
|
|
15196
|
+
},
|
|
15227
15197
|
enableDOF: {
|
|
15228
15198
|
uniform: "enableDOF",
|
|
15229
15199
|
reset: !0
|
|
@@ -15304,6 +15274,18 @@ var bp = {
|
|
|
15304
15274
|
uniform: "debugVisScale",
|
|
15305
15275
|
reset: !0
|
|
15306
15276
|
},
|
|
15277
|
+
cameraProjection: {
|
|
15278
|
+
handler: "handleCameraProjection",
|
|
15279
|
+
reset: !0
|
|
15280
|
+
},
|
|
15281
|
+
panoramaLonRange: {
|
|
15282
|
+
handler: "handlePanoramaLonRange",
|
|
15283
|
+
reset: !0
|
|
15284
|
+
},
|
|
15285
|
+
panoramaLatRange: {
|
|
15286
|
+
handler: "handlePanoramaLatRange",
|
|
15287
|
+
reset: !0
|
|
15288
|
+
},
|
|
15307
15289
|
interactionModeEnabled: {
|
|
15308
15290
|
handler: "handleInteractionModeEnabled",
|
|
15309
15291
|
reset: !1
|
|
@@ -15326,18 +15308,27 @@ var bp = {
|
|
|
15326
15308
|
},
|
|
15327
15309
|
renderMode: { handler: "handleRenderMode" },
|
|
15328
15310
|
environmentRotation: { handler: "handleEnvironmentRotation" }
|
|
15329
|
-
},
|
|
15311
|
+
}, Tp = {
|
|
15330
15312
|
bounces: "maxBounces",
|
|
15331
15313
|
debugMode: "visMode"
|
|
15332
|
-
},
|
|
15314
|
+
}, Ep = class extends ut {
|
|
15333
15315
|
constructor(e = J) {
|
|
15334
15316
|
super(), this._values = /* @__PURE__ */ new Map(), this._pathTracer = null, this._resetCallback = null, this._handlers = {}, this._delegates = {}, this._initDefaults(e);
|
|
15335
15317
|
}
|
|
15336
|
-
bind(
|
|
15337
|
-
this._pathTracer = e.pathTracer, this._resetCallback =
|
|
15318
|
+
bind(e) {
|
|
15319
|
+
this._pathTracer = e.stages.pathTracer, this._resetCallback = e.resetCallback, this._delegates = {}, this._handlers = this._buildHandlers(e);
|
|
15338
15320
|
}
|
|
15339
|
-
_buildHandlers(e, t, n) {
|
|
15321
|
+
_buildHandlers({ stages: e, renderer: t, reconcileCompletion: n, denoisingManager: r, cameraManager: i }) {
|
|
15322
|
+
let a = new sn(), o = (t, n) => {
|
|
15323
|
+
a.set(n?.[0] ?? 0, n?.[1] ?? 0).multiplyScalar(xt.DEG2RAD), e.pathTracer?.setUniform(t, a);
|
|
15324
|
+
};
|
|
15340
15325
|
return {
|
|
15326
|
+
handleCameraProjection: (t) => {
|
|
15327
|
+
let n = t === "equirectangular";
|
|
15328
|
+
e.pathTracer?.setUniform("cameraProjection", +!!n), n && (r?.denoiserStrategy === "asvgf" && r.setDenoiserStrategy("edgeaware"), i?.setAutoFocusMode("manual"));
|
|
15329
|
+
},
|
|
15330
|
+
handlePanoramaLonRange: (e) => o("panoLonRange", e),
|
|
15331
|
+
handlePanoramaLatRange: (e) => o("panoLatRange", e),
|
|
15341
15332
|
handleTransparentBackground: (t) => {
|
|
15342
15333
|
e.pathTracer?.setUniform("transparentBackground", t), e.compositor?.setTransparentBackground(t);
|
|
15343
15334
|
},
|
|
@@ -15375,7 +15366,7 @@ var bp = {
|
|
|
15375
15366
|
let i = this._values.get(e);
|
|
15376
15367
|
if (i === t) return;
|
|
15377
15368
|
this._values.set(e, t);
|
|
15378
|
-
let a =
|
|
15369
|
+
let a = wp[e];
|
|
15379
15370
|
a && (this._applyRoute(a, t, i), (n === void 0 ? a.reset ?? !0 : n) && this._resetCallback?.(), r || this.dispatchEvent({
|
|
15380
15371
|
type: dr.SETTING_CHANGED,
|
|
15381
15372
|
key: e,
|
|
@@ -15389,7 +15380,7 @@ var bp = {
|
|
|
15389
15380
|
let e = this._values.get(n);
|
|
15390
15381
|
if (e === i) continue;
|
|
15391
15382
|
this._values.set(n, i);
|
|
15392
|
-
let a =
|
|
15383
|
+
let a = wp[n];
|
|
15393
15384
|
a && (this._applyRoute(a, i, e), (a.reset ?? !0) && (r = !0), t || this.dispatchEvent({
|
|
15394
15385
|
type: dr.SETTING_CHANGED,
|
|
15395
15386
|
key: n,
|
|
@@ -15407,7 +15398,7 @@ var bp = {
|
|
|
15407
15398
|
}
|
|
15408
15399
|
applyAll() {
|
|
15409
15400
|
for (let [e, t] of this._values) {
|
|
15410
|
-
let n =
|
|
15401
|
+
let n = wp[e];
|
|
15411
15402
|
n && this._applyRoute(n, t, void 0);
|
|
15412
15403
|
}
|
|
15413
15404
|
}
|
|
@@ -15415,10 +15406,10 @@ var bp = {
|
|
|
15415
15406
|
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
15407
|
}
|
|
15417
15408
|
_initDefaults(e) {
|
|
15418
|
-
for (let t of Object.keys(
|
|
15419
|
-
for (let [t, n] of Object.entries(
|
|
15409
|
+
for (let t of Object.keys(wp)) t in e && this._values.set(t, e[t]);
|
|
15410
|
+
for (let [t, n] of Object.entries(Tp)) t in e && this._values.set(n, e[t]);
|
|
15420
15411
|
}
|
|
15421
|
-
},
|
|
15412
|
+
}, Dp = class extends ut {
|
|
15422
15413
|
constructor(e) {
|
|
15423
15414
|
super();
|
|
15424
15415
|
let t = e.clientWidth, n = e.clientHeight;
|
|
@@ -15584,7 +15575,7 @@ var bp = {
|
|
|
15584
15575
|
dispose() {
|
|
15585
15576
|
this.controls?.dispose();
|
|
15586
15577
|
}
|
|
15587
|
-
},
|
|
15578
|
+
}, Op = class extends ut {
|
|
15588
15579
|
constructor(e, t, n, r = {}) {
|
|
15589
15580
|
super(), this.scene = e, this.sceneHelpers = t, this.pathTracer = n, this._onReset = r.onReset || null;
|
|
15590
15581
|
}
|
|
@@ -15744,14 +15735,14 @@ var bp = {
|
|
|
15744
15735
|
], 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
15736
|
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
15737
|
}
|
|
15747
|
-
},
|
|
15738
|
+
}, kp = class {
|
|
15748
15739
|
constructor(e, t = {}) {
|
|
15749
15740
|
this.pathTracer = e, this._onReset = t.onReset || null, this.texture = null, this.entries = [], this._size = 256;
|
|
15750
15741
|
}
|
|
15751
15742
|
async loadLibrary(e, { size: t = 256 } = {}) {
|
|
15752
15743
|
if (!Array.isArray(e) || e.length === 0) return [];
|
|
15753
15744
|
this._size = t;
|
|
15754
|
-
let n = await Promise.all(e.map((e) =>
|
|
15745
|
+
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
15746
|
s.width = r, s.height = i;
|
|
15756
15747
|
let c = s.getContext("2d", { willReadFrequently: !0 });
|
|
15757
15748
|
for (let e = 0; e < a; e++) {
|
|
@@ -15780,7 +15771,7 @@ var bp = {
|
|
|
15780
15771
|
o.userData.gobo = {
|
|
15781
15772
|
name: e.name,
|
|
15782
15773
|
index: e.index,
|
|
15783
|
-
intensity:
|
|
15774
|
+
intensity: jp(r),
|
|
15784
15775
|
inverted: !!i,
|
|
15785
15776
|
scale: Math.max(1e-4, a)
|
|
15786
15777
|
};
|
|
@@ -15822,28 +15813,28 @@ var bp = {
|
|
|
15822
15813
|
return t && t.isSpotLight ? t : null;
|
|
15823
15814
|
}
|
|
15824
15815
|
};
|
|
15825
|
-
function
|
|
15816
|
+
function Ap(e) {
|
|
15826
15817
|
return new Promise((t, n) => {
|
|
15827
15818
|
let r = new Image();
|
|
15828
15819
|
r.crossOrigin = "anonymous", r.onload = () => t(r), r.onerror = () => n(/* @__PURE__ */ Error(`Failed to load gobo image: ${e}`)), r.src = e;
|
|
15829
15820
|
});
|
|
15830
15821
|
}
|
|
15831
|
-
function
|
|
15822
|
+
function jp(e) {
|
|
15832
15823
|
return Math.max(0, Math.min(1, e));
|
|
15833
15824
|
}
|
|
15834
15825
|
//#endregion
|
|
15835
15826
|
//#region src/Processor/IESParser.js
|
|
15836
|
-
function
|
|
15827
|
+
function Mp(e, t = "ies") {
|
|
15837
15828
|
let n = e.search(/TILT\s*=/i);
|
|
15838
15829
|
if (n < 0) throw Error(`IES (${t}): missing TILT line`);
|
|
15839
15830
|
let r = e.indexOf("\n", n);
|
|
15840
15831
|
if (r < 0) throw Error(`IES (${t}): truncated TILT line`);
|
|
15841
15832
|
let i = e.slice(n, r).match(/TILT\s*=\s*(\w+)/i), a = i ? i[1].toUpperCase() : "NONE", o = e.slice(r);
|
|
15842
15833
|
if (a === "INCLUDE") {
|
|
15843
|
-
let e =
|
|
15844
|
-
o =
|
|
15834
|
+
let e = Ip(o), t = 2 + 2 * Number(e[1]);
|
|
15835
|
+
o = Lp(o, t);
|
|
15845
15836
|
}
|
|
15846
|
-
let s =
|
|
15837
|
+
let s = Ip(o), c = 0, l = () => Number(s[c++]), u = l(), d = l(), f = l(), p = l(), m = l(), h = l();
|
|
15847
15838
|
l(), l(), l(), l();
|
|
15848
15839
|
let g = l();
|
|
15849
15840
|
if (l(), l(), !Number.isFinite(p) || p <= 0) throw Error(`IES (${t}): invalid vertical angle count ${p}`);
|
|
@@ -15869,18 +15860,18 @@ function Ap(e, t = "ies") {
|
|
|
15869
15860
|
name: t
|
|
15870
15861
|
};
|
|
15871
15862
|
}
|
|
15872
|
-
function
|
|
15863
|
+
function Np(e, t, n) {
|
|
15873
15864
|
let r = new Uint8Array(t * n), { verticalAngles: i, horizontalAngles: a, candela: o, maxCandela: s } = e;
|
|
15874
15865
|
if (s <= 0) return r;
|
|
15875
15866
|
let c = i[i.length - 1], l = a[a.length - 1], u = a[0], d = a.length === 1 || l === u;
|
|
15876
15867
|
for (let e = 0; e < n; e++) {
|
|
15877
|
-
let f = (e + .5) / n * c, p =
|
|
15868
|
+
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
15869
|
for (let n = 0; n < t; n++) {
|
|
15879
15870
|
let i;
|
|
15880
|
-
if (d) i =
|
|
15871
|
+
if (d) i = zp(o[p][0], o[m][0], g);
|
|
15881
15872
|
else {
|
|
15882
|
-
let e = u + (n + .5) / t * (l - u), r =
|
|
15883
|
-
i =
|
|
15873
|
+
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];
|
|
15874
|
+
i = zp(zp(f, h, d), zp(_, v, d), g);
|
|
15884
15875
|
}
|
|
15885
15876
|
let c = Math.min(1, Math.max(0, i / s));
|
|
15886
15877
|
r[e * t + n] = Math.round(c * 255);
|
|
@@ -15888,7 +15879,7 @@ function jp(e, t, n) {
|
|
|
15888
15879
|
}
|
|
15889
15880
|
return r;
|
|
15890
15881
|
}
|
|
15891
|
-
function
|
|
15882
|
+
function Pp(e, t = .1) {
|
|
15892
15883
|
let { verticalAngles: n, horizontalAngles: r, candela: i, maxCandela: a } = e, o = Math.PI / 4;
|
|
15893
15884
|
if (a <= 0 || !n?.length) return o;
|
|
15894
15885
|
let s = a * t, c = r.length, l = n[n.length - 1], u = !1;
|
|
@@ -15903,7 +15894,7 @@ function Mp(e, t = .1) {
|
|
|
15903
15894
|
let d = l * Math.PI / 180;
|
|
15904
15895
|
return Math.min(Math.max(d, 5 * Math.PI / 180), 89 * Math.PI / 180);
|
|
15905
15896
|
}
|
|
15906
|
-
function
|
|
15897
|
+
function Fp(e, t, n = .7) {
|
|
15907
15898
|
let { verticalAngles: r, horizontalAngles: i, candela: a, maxCandela: o } = e;
|
|
15908
15899
|
if (o <= 0 || !r?.length || t <= 0) return 0;
|
|
15909
15900
|
let s = o * n, c = i.length, l = 0;
|
|
@@ -15916,15 +15907,15 @@ function Np(e, t, n = .7) {
|
|
|
15916
15907
|
let u = t * 180 / Math.PI, d = u > 0 ? 1 - l / u : 0;
|
|
15917
15908
|
return Math.min(Math.max(d, 0), 1);
|
|
15918
15909
|
}
|
|
15919
|
-
function
|
|
15910
|
+
function Ip(e) {
|
|
15920
15911
|
return e.split(/\s+/).filter((e) => e.length > 0);
|
|
15921
15912
|
}
|
|
15922
|
-
function
|
|
15913
|
+
function Lp(e, t) {
|
|
15923
15914
|
let n = /\S+/g, r = 0;
|
|
15924
15915
|
for (; n.exec(e) !== null;) if (r++, r === t) return e.slice(n.lastIndex);
|
|
15925
15916
|
return "";
|
|
15926
15917
|
}
|
|
15927
|
-
function
|
|
15918
|
+
function Rp(e, t) {
|
|
15928
15919
|
if (t <= e[0]) return 0;
|
|
15929
15920
|
if (t >= e[e.length - 1]) return e.length - 1;
|
|
15930
15921
|
let n = 0, r = e.length - 1;
|
|
@@ -15934,12 +15925,12 @@ function Ip(e, t) {
|
|
|
15934
15925
|
}
|
|
15935
15926
|
return n;
|
|
15936
15927
|
}
|
|
15937
|
-
function
|
|
15928
|
+
function zp(e, t, n) {
|
|
15938
15929
|
return e + (t - e) * n;
|
|
15939
15930
|
}
|
|
15940
15931
|
//#endregion
|
|
15941
15932
|
//#region src/managers/IESManager.js
|
|
15942
|
-
var
|
|
15933
|
+
var Bp = class {
|
|
15943
15934
|
constructor(e, t = {}) {
|
|
15944
15935
|
this.pathTracer = e, this._onReset = t.onReset || null, this.texture = null, this.entries = [], this._gridWidth = 128, this._gridHeight = 128;
|
|
15945
15936
|
}
|
|
@@ -15950,11 +15941,11 @@ var Rp = class {
|
|
|
15950
15941
|
try {
|
|
15951
15942
|
let r = await fetch(e.url);
|
|
15952
15943
|
if (!r.ok) throw Error(`HTTP ${r.status}`);
|
|
15953
|
-
let i =
|
|
15944
|
+
let i = Mp(await r.text(), e.name);
|
|
15954
15945
|
return {
|
|
15955
15946
|
it: e,
|
|
15956
15947
|
profile: i,
|
|
15957
|
-
grid:
|
|
15948
|
+
grid: Np(i, t, n)
|
|
15958
15949
|
};
|
|
15959
15950
|
} catch (t) {
|
|
15960
15951
|
return console.warn(`IESManager: failed to load "${e.name}": ${t.message}`), null;
|
|
@@ -15968,14 +15959,14 @@ var Rp = class {
|
|
|
15968
15959
|
let r = t[e];
|
|
15969
15960
|
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
15961
|
}
|
|
15971
|
-
let i = r[e].profile, c =
|
|
15962
|
+
let i = r[e].profile, c = Pp(i);
|
|
15972
15963
|
s.push({
|
|
15973
15964
|
name: r[e].it.name,
|
|
15974
15965
|
index: e,
|
|
15975
15966
|
maxCandela: i.maxCandela,
|
|
15976
15967
|
photometricType: i.photometricType,
|
|
15977
15968
|
suggestedAngle: c,
|
|
15978
|
-
suggestedPenumbra:
|
|
15969
|
+
suggestedPenumbra: Fp(i, c),
|
|
15979
15970
|
lumens: i.lumens
|
|
15980
15971
|
});
|
|
15981
15972
|
}
|
|
@@ -16008,7 +15999,7 @@ var Rp = class {
|
|
|
16008
15999
|
l = Number.isFinite(e.lumens) ? e.lumens : null, i.userData.ies = {
|
|
16009
16000
|
name: e.name,
|
|
16010
16001
|
index: e.index,
|
|
16011
|
-
intensity:
|
|
16002
|
+
intensity: Vp(n),
|
|
16012
16003
|
fixtureLumens: l
|
|
16013
16004
|
}, 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
16005
|
}
|
|
@@ -16031,44 +16022,44 @@ var Rp = class {
|
|
|
16031
16022
|
return t && t.isSpotLight ? t : null;
|
|
16032
16023
|
}
|
|
16033
16024
|
};
|
|
16034
|
-
function
|
|
16025
|
+
function Vp(e) {
|
|
16035
16026
|
return Math.max(0, Math.min(1, e));
|
|
16036
16027
|
}
|
|
16037
16028
|
//#endregion
|
|
16038
16029
|
//#region src/Processor/ToneMapCPU.js
|
|
16039
|
-
var
|
|
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
|
-
}
|
|
16030
|
+
var Hp = (e) => Math.min(Math.max(e, 0), 1);
|
|
16046
16031
|
function Up(e, t, n, r, i) {
|
|
16047
|
-
|
|
16032
|
+
i[0] = Hp(e), i[1] = Hp(t), i[2] = Hp(n);
|
|
16048
16033
|
}
|
|
16049
16034
|
function Wp(e, t, n, r, i) {
|
|
16035
|
+
i[0] = Hp(e * r), i[1] = Hp(t * r), i[2] = Hp(n * r);
|
|
16036
|
+
}
|
|
16037
|
+
function Gp(e, t, n, r, i) {
|
|
16038
|
+
e *= r, t *= r, n *= r, i[0] = Hp(e / (e + 1)), i[1] = Hp(t / (t + 1)), i[2] = Hp(n / (n + 1));
|
|
16039
|
+
}
|
|
16040
|
+
function Kp(e, t, n, r, i) {
|
|
16050
16041
|
e = Math.max(e * r - .004, 0), t = Math.max(t * r - .004, 0), n = Math.max(n * r - .004, 0);
|
|
16051
16042
|
let a = (e) => (e * (6.2 * e + .5) / (e * (6.2 * e + 1.7) + .06)) ** 2.2;
|
|
16052
16043
|
i[0] = a(e), i[1] = a(t), i[2] = a(n);
|
|
16053
16044
|
}
|
|
16054
|
-
function
|
|
16045
|
+
function qp(e, t, n, r, i) {
|
|
16055
16046
|
e = e * r / .6, t = t * r / .6, n = n * r / .6;
|
|
16056
16047
|
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] =
|
|
16048
|
+
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
16049
|
}
|
|
16059
|
-
function
|
|
16050
|
+
function Jp(e, t, n, r, i) {
|
|
16060
16051
|
e *= r, t *= r, n *= r;
|
|
16061
16052
|
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 =
|
|
16053
|
+
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
16054
|
let p = (e) => {
|
|
16064
16055
|
let t = e * e, n = t * t;
|
|
16065
16056
|
return 15.5 * n * t - 40.14 * n * e + 31.96 * n - 6.868 * t * e + .4298 * t + .1191 * e - .00232;
|
|
16066
16057
|
};
|
|
16067
16058
|
c = p(c), l = p(l), u = p(u);
|
|
16068
16059
|
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] =
|
|
16060
|
+
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
16061
|
}
|
|
16071
|
-
function
|
|
16062
|
+
function Yp(e, t, n, r, i) {
|
|
16072
16063
|
let a = .76;
|
|
16073
16064
|
e *= r, t *= r, n *= r;
|
|
16074
16065
|
let o = Math.min(e, Math.min(t, n)), s = o < .08 ? o - 6.25 * o * o : .04;
|
|
@@ -16083,43 +16074,43 @@ function qp(e, t, n, r, i) {
|
|
|
16083
16074
|
let f = 1 - 1 / (.15 * (c - u) + 1);
|
|
16084
16075
|
i[0] = e + (u - e) * f, i[1] = t + (u - t) * f, i[2] = n + (u - n) * f;
|
|
16085
16076
|
}
|
|
16086
|
-
var
|
|
16087
|
-
[jt,
|
|
16088
|
-
[q,
|
|
16089
|
-
[Kt,
|
|
16090
|
-
[Qe,
|
|
16091
|
-
[Ue,
|
|
16092
|
-
[Ge,
|
|
16093
|
-
[kt,
|
|
16094
|
-
]),
|
|
16095
|
-
function
|
|
16077
|
+
var Xp = new Map([
|
|
16078
|
+
[jt, Up],
|
|
16079
|
+
[q, Wp],
|
|
16080
|
+
[Kt, Gp],
|
|
16081
|
+
[Qe, Kp],
|
|
16082
|
+
[Ue, qp],
|
|
16083
|
+
[Ge, Jp],
|
|
16084
|
+
[kt, Yp]
|
|
16085
|
+
]), Zp = 1 / 2.2;
|
|
16086
|
+
function Qp(e) {
|
|
16096
16087
|
return e <= .0031308 ? 12.92 * e : 1.055 * e ** (1 / 2.4) - .055;
|
|
16097
16088
|
}
|
|
16098
|
-
var
|
|
16099
|
-
function
|
|
16089
|
+
var $p = .2126, em = .7152, tm = .0722;
|
|
16090
|
+
function nm(e, t) {
|
|
16100
16091
|
if (t === 1) return;
|
|
16101
|
-
let n = e[0] *
|
|
16092
|
+
let n = e[0] * $p + e[1] * em + e[2] * tm;
|
|
16102
16093
|
e[0] = n + (e[0] - n) * t, e[1] = n + (e[1] - n) * t, e[2] = n + (e[2] - n) * t;
|
|
16103
16094
|
}
|
|
16104
16095
|
//#endregion
|
|
16105
16096
|
//#region src/Passes/OIDNDenoiser.js
|
|
16106
|
-
var
|
|
16107
|
-
async function
|
|
16108
|
-
if (!
|
|
16097
|
+
var rm = ai("oidn"), im = null, am = null;
|
|
16098
|
+
async function om() {
|
|
16099
|
+
if (!im) {
|
|
16109
16100
|
let [e, t] = await Promise.all([import("oidn-web"), import("@tensorflow/tfjs-core")]);
|
|
16110
|
-
|
|
16101
|
+
im = e.initUNetFromURL, am = t.engine;
|
|
16111
16102
|
}
|
|
16112
|
-
return
|
|
16103
|
+
return im;
|
|
16113
16104
|
}
|
|
16114
|
-
function
|
|
16115
|
-
if (
|
|
16116
|
-
let e =
|
|
16105
|
+
function sm() {
|
|
16106
|
+
if (am) try {
|
|
16107
|
+
let e = am();
|
|
16117
16108
|
e?.registryFactory && "webgpu-oidn" in e.registryFactory && e.removeBackend("webgpu-oidn");
|
|
16118
16109
|
} catch (e) {
|
|
16119
|
-
|
|
16110
|
+
rm.warn("failed to clear cached TFJS backend", e);
|
|
16120
16111
|
}
|
|
16121
16112
|
}
|
|
16122
|
-
var
|
|
16113
|
+
var cm = new Float32Array(3), lm = {
|
|
16123
16114
|
QUALITY_MODELS: {
|
|
16124
16115
|
fast: "rt_hdr_alb_nrm_small",
|
|
16125
16116
|
balance: "rt_hdr_alb_nrm",
|
|
@@ -16131,7 +16122,7 @@ var om = new Float32Array(3), sm = {
|
|
|
16131
16122
|
debugGbufferMaps: !0,
|
|
16132
16123
|
tileSize: 256
|
|
16133
16124
|
}
|
|
16134
|
-
},
|
|
16125
|
+
}, um = class extends ut {
|
|
16135
16126
|
constructor(e, t, n, r, i = {}) {
|
|
16136
16127
|
if (super(), !e || !t || !n || !r) throw Error("OIDNDenoiser requires output canvas, renderer, scene, and camera");
|
|
16137
16128
|
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 +16133,14 @@ var om = new Float32Array(3), sm = {
|
|
|
16142
16133
|
width: 0,
|
|
16143
16134
|
height: 0
|
|
16144
16135
|
}, this._gpuInputPadBuffer = null, this._gpuInputPaddedRowBytes = 0, this._alphaReadbackBuffer = null, this._alphaReadbackMapped = !1, this._cachedAlpha = null, this._cachedAlphaWidth = 0, this.config = {
|
|
16145
|
-
...
|
|
16136
|
+
...lm.DEFAULT_OPTIONS,
|
|
16146
16137
|
...i
|
|
16147
16138
|
}, this.enabled = this.config.enableOIDN, this.quality = this.config.oidnQuality, this.debugGbufferMaps = this.config.debugGbufferMaps, this.tileSize = this.config.tileSize, this.state = {
|
|
16148
16139
|
isDenoising: !1,
|
|
16149
16140
|
isLoading: !1,
|
|
16150
16141
|
abortController: null
|
|
16151
16142
|
}, this._pendingStagingBuffers = /* @__PURE__ */ new Set(), this._pendingTileBlits = [], this.currentTZAUrl = null, this.unet = null, this._pendingStart = !1, this._initialize().catch((e) => {
|
|
16152
|
-
|
|
16143
|
+
rm.error("init failed:", e), this.dispatchEvent({
|
|
16153
16144
|
type: "error",
|
|
16154
16145
|
error: e
|
|
16155
16146
|
});
|
|
@@ -16195,13 +16186,13 @@ var om = new Float32Array(3), sm = {
|
|
|
16195
16186
|
let e = this.backendParamsGetter();
|
|
16196
16187
|
this.gpuDevice = e?.device ?? null, t = e?.device ? e : void 0;
|
|
16197
16188
|
}
|
|
16198
|
-
this.unet = await (await
|
|
16189
|
+
this.unet = await (await om())(e, t, {
|
|
16199
16190
|
aux: !0,
|
|
16200
16191
|
hdr: !0,
|
|
16201
16192
|
maxTileSize: this.tileSize
|
|
16202
|
-
}), this.currentTZAUrl = e, this.dispatchEvent({ type: "loaded" }),
|
|
16193
|
+
}), this.currentTZAUrl = e, this.dispatchEvent({ type: "loaded" }), rm.debug("UNet weights loaded:", e);
|
|
16203
16194
|
} catch (e) {
|
|
16204
|
-
|
|
16195
|
+
rm.error("UNet weights failed to load:", e), this.dispatchEvent({
|
|
16205
16196
|
type: "error",
|
|
16206
16197
|
error: /* @__PURE__ */ Error(`Denoiser loading failed: ${e.message}`)
|
|
16207
16198
|
});
|
|
@@ -16210,14 +16201,14 @@ var om = new Float32Array(3), sm = {
|
|
|
16210
16201
|
}
|
|
16211
16202
|
}
|
|
16212
16203
|
_generateTzaUrl() {
|
|
16213
|
-
let { oidnWeightsBaseUrl: e } = cl(), { QUALITY_MODELS: t } =
|
|
16204
|
+
let { oidnWeightsBaseUrl: e } = cl(), { QUALITY_MODELS: t } = lm;
|
|
16214
16205
|
return `${e}${t[this.quality] || t.balance}.tza`;
|
|
16215
16206
|
}
|
|
16216
16207
|
async updateConfiguration(e) {
|
|
16217
16208
|
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
16209
|
}
|
|
16219
16210
|
async updateQuality(e) {
|
|
16220
|
-
if (!Object.prototype.hasOwnProperty.call(
|
|
16211
|
+
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
16212
|
await this.updateConfiguration({ oidnQuality: e });
|
|
16222
16213
|
}
|
|
16223
16214
|
async start() {
|
|
@@ -16228,7 +16219,7 @@ var om = new Float32Array(3), sm = {
|
|
|
16228
16219
|
if (t) {
|
|
16229
16220
|
this.renderer?.resetState?.(), this.input.style.opacity = "0";
|
|
16230
16221
|
let t = performance.now() - e;
|
|
16231
|
-
|
|
16222
|
+
rm.debug(`denoise complete in ${Q.ms(t)} · quality ${this.quality}`);
|
|
16232
16223
|
}
|
|
16233
16224
|
return t;
|
|
16234
16225
|
}
|
|
@@ -16238,7 +16229,7 @@ var om = new Float32Array(3), sm = {
|
|
|
16238
16229
|
try {
|
|
16239
16230
|
return await this._executeUNet(), !0;
|
|
16240
16231
|
} catch (e) {
|
|
16241
|
-
return e.name === "AbortError" ?
|
|
16232
|
+
return e.name === "AbortError" ? rm.debug("denoise aborted") : rm.error("denoise error:", e), this.input.style.opacity = "1", !1;
|
|
16242
16233
|
} finally {
|
|
16243
16234
|
this.state.isDenoising = !1, this.state.abortController = null, this.dispatchEvent({ type: "end" });
|
|
16244
16235
|
}
|
|
@@ -16248,11 +16239,11 @@ var om = new Float32Array(3), sm = {
|
|
|
16248
16239
|
}
|
|
16249
16240
|
async _executeUNetGPU() {
|
|
16250
16241
|
let { width: e, height: t } = this.output;
|
|
16251
|
-
if (!this.getGPUTextures) return
|
|
16242
|
+
if (!this.getGPUTextures) return rm.warn("GPU mode enabled but getGPUTextures not provided"), !1;
|
|
16252
16243
|
let n = this.getGPUTextures();
|
|
16253
|
-
if (!n?.color) return
|
|
16244
|
+
if (!n?.color) return rm.warn("GPU textures not ready yet"), !1;
|
|
16254
16245
|
let r = this.gpuDevice;
|
|
16255
|
-
if (!r) return
|
|
16246
|
+
if (!r) return rm.warn("gpuDevice not available"), !1;
|
|
16256
16247
|
this._ensureGPUInputBuffers(e, t);
|
|
16257
16248
|
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
16249
|
if (!s) i.copyTextureToBuffer({
|
|
@@ -16402,10 +16393,10 @@ var om = new Float32Array(3), sm = {
|
|
|
16402
16393
|
}
|
|
16403
16394
|
r.queue.submit([d.finish()]);
|
|
16404
16395
|
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 =
|
|
16396
|
+
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
16397
|
for (let i = 0, a = e.length; i < a; i += 4) {
|
|
16407
16398
|
let a = e[i] * r, s = e[i + 1] * r, u = e[i + 2] * r;
|
|
16408
|
-
if (c !== 1 && (
|
|
16399
|
+
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
16400
|
let e = (i >> 2) % o, r = (i >> 2) / o | 0;
|
|
16410
16401
|
t.data[i + 3] = d[(n.y + r) * f + n.x + e];
|
|
16411
16402
|
} else t.data[i + 3] = 255;
|
|
@@ -16432,7 +16423,7 @@ var om = new Float32Array(3), sm = {
|
|
|
16432
16423
|
async _displayGPUOutput({ data: e, width: t, height: n }) {
|
|
16433
16424
|
let r = this.gpuDevice;
|
|
16434
16425
|
if (!r) {
|
|
16435
|
-
|
|
16426
|
+
rm.error("gpuDevice not available for output readback");
|
|
16436
16427
|
return;
|
|
16437
16428
|
}
|
|
16438
16429
|
let i = t * n * 4 * 4, a = r.createBuffer({
|
|
@@ -16443,10 +16434,10 @@ var om = new Float32Array(3), sm = {
|
|
|
16443
16434
|
try {
|
|
16444
16435
|
let o = r.createCommandEncoder({ label: "oidn-readback" });
|
|
16445
16436
|
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 =
|
|
16437
|
+
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
16438
|
for (let e = 0, t = s.length; e < t; e += 4) {
|
|
16448
16439
|
let t = s[e] * l, n = s[e + 1] * l, r = s[e + 2] * l;
|
|
16449
|
-
u !== 1 && (
|
|
16440
|
+
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
16441
|
}
|
|
16451
16442
|
a.unmap(), this.ctx.putImageData(c, 0, 0);
|
|
16452
16443
|
} finally {
|
|
@@ -16454,12 +16445,12 @@ var om = new Float32Array(3), sm = {
|
|
|
16454
16445
|
}
|
|
16455
16446
|
}
|
|
16456
16447
|
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" }),
|
|
16448
|
+
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
16449
|
}
|
|
16459
16450
|
setSize(e, t) {
|
|
16460
16451
|
if (e <= 0 || t <= 0) throw Error(`Invalid dimensions: ${e}x${t}`);
|
|
16461
16452
|
this.output.width = e, this.output.height = t, this._setupUNetDenoiser().catch((e) => {
|
|
16462
|
-
|
|
16453
|
+
rm.error("reinitialize after size change failed:", e);
|
|
16463
16454
|
});
|
|
16464
16455
|
}
|
|
16465
16456
|
_destroyPendingStagingBuffers() {
|
|
@@ -16467,13 +16458,13 @@ var om = new Float32Array(3), sm = {
|
|
|
16467
16458
|
this._pendingStagingBuffers.clear();
|
|
16468
16459
|
}
|
|
16469
16460
|
dispose() {
|
|
16470
|
-
this.abort(), this._destroyPendingStagingBuffers(), this.unet?.dispose(),
|
|
16461
|
+
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
16462
|
}
|
|
16472
|
-
},
|
|
16473
|
-
function
|
|
16463
|
+
}, 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" });
|
|
16464
|
+
function pm(e) {
|
|
16474
16465
|
let t;
|
|
16475
16466
|
try {
|
|
16476
|
-
if (t =
|
|
16467
|
+
if (t = fm && (self.URL || self.webkitURL).createObjectURL(fm), !t) throw "";
|
|
16477
16468
|
let n = new Worker(t, {
|
|
16478
16469
|
type: "module",
|
|
16479
16470
|
name: e?.name
|
|
@@ -16482,7 +16473,7 @@ function dm(e) {
|
|
|
16482
16473
|
(self.URL || self.webkitURL).revokeObjectURL(t);
|
|
16483
16474
|
}), n;
|
|
16484
16475
|
} catch {
|
|
16485
|
-
return new Worker("data:text/javascript;charset=utf-8," + encodeURIComponent(
|
|
16476
|
+
return new Worker("data:text/javascript;charset=utf-8," + encodeURIComponent(dm), {
|
|
16486
16477
|
type: "module",
|
|
16487
16478
|
name: e?.name
|
|
16488
16479
|
});
|
|
@@ -16490,7 +16481,7 @@ function dm(e) {
|
|
|
16490
16481
|
}
|
|
16491
16482
|
//#endregion
|
|
16492
16483
|
//#region src/Passes/AIUpscaler.js
|
|
16493
|
-
var
|
|
16484
|
+
var mm = {
|
|
16494
16485
|
fast: {
|
|
16495
16486
|
2: "2x-spanx2-ch48.onnx",
|
|
16496
16487
|
4: "4xNomos8k_span_otf_strong_fp32_opset17.onnx"
|
|
@@ -16504,17 +16495,17 @@ var fm = {
|
|
|
16504
16495
|
4: "4xNomos2_hq_mosr_fp32.onnx"
|
|
16505
16496
|
}
|
|
16506
16497
|
};
|
|
16507
|
-
function
|
|
16498
|
+
function hm() {
|
|
16508
16499
|
let { upscalerModelBaseUrl: e } = cl(), t = {};
|
|
16509
|
-
for (let n in
|
|
16500
|
+
for (let n in mm) {
|
|
16510
16501
|
t[n] = {};
|
|
16511
|
-
for (let r in
|
|
16502
|
+
for (let r in mm[n]) t[n][r] = e + mm[n][r];
|
|
16512
16503
|
}
|
|
16513
16504
|
return t;
|
|
16514
16505
|
}
|
|
16515
|
-
var
|
|
16506
|
+
var gm = {
|
|
16516
16507
|
get QUALITY_PRESETS() {
|
|
16517
|
-
return
|
|
16508
|
+
return hm();
|
|
16518
16509
|
},
|
|
16519
16510
|
TILE_SIZE: 512,
|
|
16520
16511
|
TILE_OVERLAP: 16,
|
|
@@ -16525,17 +16516,17 @@ var mm = {
|
|
|
16525
16516
|
}],
|
|
16526
16517
|
graphOptimizationLevel: "all"
|
|
16527
16518
|
}
|
|
16528
|
-
},
|
|
16519
|
+
}, _m = class extends ut {
|
|
16529
16520
|
constructor(e, t, n = {}) {
|
|
16530
16521
|
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 ||
|
|
16522
|
+
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
16523
|
isUpscaling: !1,
|
|
16533
16524
|
isLoading: !1,
|
|
16534
16525
|
abortController: null
|
|
16535
16526
|
}, 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
16527
|
}
|
|
16537
16528
|
async _ensureSession() {
|
|
16538
|
-
let e =
|
|
16529
|
+
let e = gm.QUALITY_PRESETS[this.quality];
|
|
16539
16530
|
if (!e) throw Error(`Unknown quality preset: ${this.quality}`);
|
|
16540
16531
|
let t = e[this.scaleFactor];
|
|
16541
16532
|
if (!t) throw Error(`No model for ${this.quality}/${this.scaleFactor}x`);
|
|
@@ -16545,14 +16536,14 @@ var mm = {
|
|
|
16545
16536
|
message: `Loading ${this.scaleFactor}x upscale model...`
|
|
16546
16537
|
});
|
|
16547
16538
|
try {
|
|
16548
|
-
this._worker ||= new
|
|
16539
|
+
this._worker ||= new pm(), await new Promise((e, n) => {
|
|
16549
16540
|
let r = (t) => {
|
|
16550
16541
|
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
16542
|
}, { ortRuntimeUrl: i, ortWasmPaths: a, cacheNamespace: o } = cl();
|
|
16552
16543
|
this._worker.addEventListener("message", r), this._worker.postMessage({
|
|
16553
16544
|
type: "load",
|
|
16554
16545
|
url: t,
|
|
16555
|
-
sessionOptions:
|
|
16546
|
+
sessionOptions: gm.SESSION_OPTIONS,
|
|
16556
16547
|
ortRuntimeUrl: i,
|
|
16557
16548
|
ortWasmPaths: a,
|
|
16558
16549
|
cacheNamespace: o
|
|
@@ -16622,8 +16613,8 @@ var mm = {
|
|
|
16622
16613
|
willReadFrequently: !0,
|
|
16623
16614
|
alpha: !0
|
|
16624
16615
|
});
|
|
16625
|
-
this._cacheUpscaledAlpha(t, n * i, r * i), t.isHDR && (this._hdrToneMapFn =
|
|
16626
|
-
let o =
|
|
16616
|
+
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));
|
|
16617
|
+
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
16618
|
for (let o = 0; o < u; o++) for (let u = 0; u < l; u++) {
|
|
16628
16619
|
if (e.aborted) throw new DOMException("Aborted", "AbortError");
|
|
16629
16620
|
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 +16687,7 @@ var mm = {
|
|
|
16696
16687
|
let u = ((n + e) * o + (t + i)) * 4, d = e * r + i;
|
|
16697
16688
|
if (s) {
|
|
16698
16689
|
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,
|
|
16690
|
+
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
16691
|
} else l[d] = a[u] / 255, l[c + d] = a[u + 1] / 255, l[2 * c + d] = a[u + 2] / 255;
|
|
16701
16692
|
}
|
|
16702
16693
|
return l;
|
|
@@ -16754,10 +16745,10 @@ var mm = {
|
|
|
16754
16745
|
this._backupCanvas = document.createElement("canvas"), this._backupCanvas.width = e.width, this._backupCanvas.height = e.height;
|
|
16755
16746
|
let t = this._backupCanvas.getContext("2d");
|
|
16756
16747
|
if (e.isHDR) {
|
|
16757
|
-
let { data: n, width: r, height: i } = e, a = t.createImageData(r, i), o = a.data, s =
|
|
16748
|
+
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
16749
|
for (let e = 0, t = r * i; e < t; e++) {
|
|
16759
16750
|
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,
|
|
16751
|
+
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
16752
|
}
|
|
16762
16753
|
t.putImageData(a, 0, 0);
|
|
16763
16754
|
} else t.putImageData(e, 0, 0);
|
|
@@ -16769,7 +16760,7 @@ var mm = {
|
|
|
16769
16760
|
this.hdr = !!e;
|
|
16770
16761
|
}
|
|
16771
16762
|
setQuality(e) {
|
|
16772
|
-
if (!
|
|
16763
|
+
if (!gm.QUALITY_PRESETS[e]) {
|
|
16773
16764
|
console.warn(`AIUpscaler: Invalid quality "${e}", must be fast/balanced/quality`);
|
|
16774
16765
|
return;
|
|
16775
16766
|
}
|
|
@@ -16792,7 +16783,7 @@ var mm = {
|
|
|
16792
16783
|
async dispose() {
|
|
16793
16784
|
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
16785
|
}
|
|
16795
|
-
},
|
|
16786
|
+
}, vm = class extends ut {
|
|
16796
16787
|
constructor({ renderer: e, mainCanvas: t, scene: n, camera: r, stages: i, pipeline: a, getExposure: o, getSaturation: s, getTransparentBg: c }) {
|
|
16797
16788
|
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
16789
|
}
|
|
@@ -16813,7 +16804,7 @@ var mm = {
|
|
|
16813
16804
|
setupDenoiser() {
|
|
16814
16805
|
if (!this.denoiserCanvas) return;
|
|
16815
16806
|
let e = this._stages.pathTracer;
|
|
16816
|
-
this.denoiser = new
|
|
16807
|
+
this.denoiser = new um(this.denoiserCanvas, this.renderer, this.scene, this.camera, {
|
|
16817
16808
|
...J,
|
|
16818
16809
|
backendParams: () => ({
|
|
16819
16810
|
device: this.renderer.backend.device,
|
|
@@ -16838,7 +16829,7 @@ var mm = {
|
|
|
16838
16829
|
setupUpscaler() {
|
|
16839
16830
|
if (!this.denoiserCanvas) return;
|
|
16840
16831
|
let e = this._stages.pathTracer;
|
|
16841
|
-
this.upscaler = new
|
|
16832
|
+
this.upscaler = new _m(this.denoiserCanvas, this.renderer, {
|
|
16842
16833
|
scaleFactor: J.upscalerScale || 2,
|
|
16843
16834
|
quality: J.upscalerQuality || "fast",
|
|
16844
16835
|
getSourceCanvas: () => this.denoiser?.enabled ? null : this.renderer.domElement,
|
|
@@ -16859,6 +16850,9 @@ var mm = {
|
|
|
16859
16850
|
progress: e.progress
|
|
16860
16851
|
}), 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
16852
|
}
|
|
16853
|
+
get denoiserStrategy() {
|
|
16854
|
+
return this._stages.asvgf?.enabled ? "asvgf" : this._stages.edgeFilter?.enabled ? "edgeaware" : "none";
|
|
16855
|
+
}
|
|
16862
16856
|
setDenoiserStrategy(e, t) {
|
|
16863
16857
|
let n = this._stages;
|
|
16864
16858
|
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 +16977,7 @@ var mm = {
|
|
|
16983
16977
|
let t = kr[e];
|
|
16984
16978
|
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
16979
|
}
|
|
16986
|
-
},
|
|
16980
|
+
}, ym = class {
|
|
16987
16981
|
constructor() {
|
|
16988
16982
|
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
16983
|
}
|
|
@@ -17007,7 +17001,7 @@ var mm = {
|
|
|
17007
17001
|
dispose() {
|
|
17008
17002
|
this.visible = !1;
|
|
17009
17003
|
}
|
|
17010
|
-
},
|
|
17004
|
+
}, bm = class {
|
|
17011
17005
|
constructor(n, r) {
|
|
17012
17006
|
this.layer = "scene", this._enabled = !0, this._outlineNode = xn(n, r, {
|
|
17013
17007
|
selectedObjects: [],
|
|
@@ -17038,11 +17032,11 @@ var mm = {
|
|
|
17038
17032
|
this._enabled = !1, this._outlineNode?.dispose(), this._material?.dispose(), this._quad = null;
|
|
17039
17033
|
}
|
|
17040
17034
|
};
|
|
17041
|
-
function
|
|
17035
|
+
function xm(e = !1) {
|
|
17042
17036
|
let t = document.createElement("canvas");
|
|
17043
17037
|
return t.style.cssText = "position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;" + (e ? "display:none;" : ""), t;
|
|
17044
17038
|
}
|
|
17045
|
-
function
|
|
17039
|
+
function Sm(e, t = Infinity) {
|
|
17046
17040
|
let n = e?.getBoundingClientRect();
|
|
17047
17041
|
if (!n || n.width === 0 || n.height === 0) return null;
|
|
17048
17042
|
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 +17047,9 @@ function bm(e, t = Infinity) {
|
|
|
17053
17047
|
}
|
|
17054
17048
|
//#endregion
|
|
17055
17049
|
//#region src/managers/helpers/ViewOverlayRenderer.js
|
|
17056
|
-
var
|
|
17050
|
+
var Cm = 4096, wm = class {
|
|
17057
17051
|
constructor() {
|
|
17058
|
-
this.canvas =
|
|
17052
|
+
this.canvas = xm(!0), this._visible = !1, this.renderer = null, this._sizeSource = null;
|
|
17059
17053
|
}
|
|
17060
17054
|
async init({ device: e, sizeSource: t }) {
|
|
17061
17055
|
this._sizeSource = t;
|
|
@@ -17072,7 +17066,7 @@ var xm = 4096, Sm = class {
|
|
|
17072
17066
|
}
|
|
17073
17067
|
syncSize() {
|
|
17074
17068
|
if (!this.renderer) return;
|
|
17075
|
-
let e =
|
|
17069
|
+
let e = Sm(this._sizeSource, Cm);
|
|
17076
17070
|
!e || e.width === this.canvas.width && e.height === this.canvas.height || this.renderer.setSize(e.width, e.height, !1);
|
|
17077
17071
|
}
|
|
17078
17072
|
begin() {
|
|
@@ -17084,18 +17078,18 @@ var xm = 4096, Sm = class {
|
|
|
17084
17078
|
dispose() {
|
|
17085
17079
|
xr(this.renderer), this.renderer = null, this.canvas.parentElement?.removeChild(this.canvas);
|
|
17086
17080
|
}
|
|
17087
|
-
},
|
|
17081
|
+
}, Tm = ai("overlay"), Em = (e, t) => e.visible && e.layer === t && e.render, Dm = class {
|
|
17088
17082
|
constructor(e) {
|
|
17089
|
-
this.camera = e, this._helpers = /* @__PURE__ */ new Map(), this._hudCanvas =
|
|
17083
|
+
this.camera = e, this._helpers = /* @__PURE__ */ new Map(), this._hudCanvas = xm(), this._hudCtx = this._hudCanvas.getContext("2d"), this._helperScene = null, this._viewOverlay = null;
|
|
17090
17084
|
}
|
|
17091
17085
|
async initViewRenderer({ device: e, sizeSource: t }) {
|
|
17092
17086
|
if (!(!e || !t)) try {
|
|
17093
|
-
this._viewOverlay = await new
|
|
17087
|
+
this._viewOverlay = await new wm().init({
|
|
17094
17088
|
device: e,
|
|
17095
17089
|
sizeSource: t
|
|
17096
17090
|
});
|
|
17097
17091
|
} catch (e) {
|
|
17098
|
-
|
|
17092
|
+
Tm.error("overlay surface unavailable — light gizmos, transform gizmo and outlines are disabled", e), this._viewOverlay = null;
|
|
17099
17093
|
}
|
|
17100
17094
|
}
|
|
17101
17095
|
setHelperScene(e) {
|
|
@@ -17111,11 +17105,11 @@ var xm = 4096, Sm = class {
|
|
|
17111
17105
|
}
|
|
17112
17106
|
setupDefaultHelpers({ helperScene: e, meshScene: t, pipeline: n, denoisingManager: r, app: i, renderWidth: a, renderHeight: o }) {
|
|
17113
17107
|
this.setHelperScene(e);
|
|
17114
|
-
let s = new
|
|
17108
|
+
let s = new ym();
|
|
17115
17109
|
this.register("tiles", s), s.setRenderSize(a || 1, o || 1), i.addEventListener("resolution_changed", (e) => {
|
|
17116
17110
|
s.setRenderSize(e.width, e.height);
|
|
17117
17111
|
}), n.eventBus.on("pipeline:reset", () => s.hide()), this._wireDenoiserTileEvents(s, r);
|
|
17118
|
-
let c = new
|
|
17112
|
+
let c = new bm(t, this.camera);
|
|
17119
17113
|
this.register("outline", c);
|
|
17120
17114
|
}
|
|
17121
17115
|
_wireDenoiserTileEvents(e, t) {
|
|
@@ -17127,7 +17121,7 @@ var xm = 4096, Sm = class {
|
|
|
17127
17121
|
}));
|
|
17128
17122
|
}
|
|
17129
17123
|
register(e, t) {
|
|
17130
|
-
this._helpers.has(e) && (
|
|
17124
|
+
this._helpers.has(e) && (Tm.warn(`helper "${e}" already registered — replacing.`), this._helpers.get(e).dispose?.()), this._helpers.set(e, t);
|
|
17131
17125
|
}
|
|
17132
17126
|
unregister(e) {
|
|
17133
17127
|
let t = this._helpers.get(e);
|
|
@@ -17165,16 +17159,16 @@ var xm = 4096, Sm = class {
|
|
|
17165
17159
|
}
|
|
17166
17160
|
_renderSceneLayer(e) {
|
|
17167
17161
|
this._helperScene?.render(e, this.camera);
|
|
17168
|
-
for (let t of this._helpers.values())
|
|
17162
|
+
for (let t of this._helpers.values()) Em(t, "scene") && t.render(e, this.camera);
|
|
17169
17163
|
}
|
|
17170
17164
|
_hasVisibleSceneOverlay() {
|
|
17171
17165
|
if (this._helperScene?.isDrawing) return !0;
|
|
17172
|
-
for (let e of this._helpers.values()) if (
|
|
17166
|
+
for (let e of this._helpers.values()) if (Em(e, "scene")) return !0;
|
|
17173
17167
|
return !1;
|
|
17174
17168
|
}
|
|
17175
17169
|
refreshHUD() {
|
|
17176
17170
|
let e = this._hudCanvas, t = this._hudCtx, n = !1;
|
|
17177
|
-
for (let e of this._helpers.values()) if (
|
|
17171
|
+
for (let e of this._helpers.values()) if (Em(e, "hud")) {
|
|
17178
17172
|
n = !0;
|
|
17179
17173
|
break;
|
|
17180
17174
|
}
|
|
@@ -17183,10 +17177,10 @@ var xm = 4096, Sm = class {
|
|
|
17183
17177
|
return;
|
|
17184
17178
|
}
|
|
17185
17179
|
e.style.display !== "" && (e.style.display = "");
|
|
17186
|
-
let r = e.clientWidth, i = e.clientHeight, a = r > 0 && i > 0 ?
|
|
17180
|
+
let r = e.clientWidth, i = e.clientHeight, a = r > 0 && i > 0 ? Sm(e) : null;
|
|
17187
17181
|
if (a) {
|
|
17188
17182
|
(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())
|
|
17183
|
+
for (let e of this._helpers.values()) Em(e, "hud") && e.render(t, r, i);
|
|
17190
17184
|
t.restore(), e.style.display !== "" && (e.style.display = "");
|
|
17191
17185
|
}
|
|
17192
17186
|
}
|
|
@@ -17194,7 +17188,7 @@ var xm = 4096, Sm = class {
|
|
|
17194
17188
|
for (let e of this._helpers.values()) e.dispose?.();
|
|
17195
17189
|
this._helpers.clear(), this._viewOverlay?.dispose(), this._viewOverlay = null, this._hudCanvas.parentElement && this._hudCanvas.parentElement.removeChild(this._hudCanvas);
|
|
17196
17190
|
}
|
|
17197
|
-
},
|
|
17191
|
+
}, Om = class extends ut {
|
|
17198
17192
|
constructor() {
|
|
17199
17193
|
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
17194
|
}
|
|
@@ -17294,7 +17288,7 @@ var xm = 4096, Sm = class {
|
|
|
17294
17288
|
dispose() {
|
|
17295
17289
|
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
17290
|
}
|
|
17297
|
-
},
|
|
17291
|
+
}, km = new cn(0, 0, -1), Am = class {
|
|
17298
17292
|
constructor({ camera: e, canvas: t, orbitControls: n, app: r }) {
|
|
17299
17293
|
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
17294
|
}
|
|
@@ -17315,7 +17309,7 @@ var xm = 4096, Sm = class {
|
|
|
17315
17309
|
attach(e) {
|
|
17316
17310
|
if (this._attached !== e && (this._controls.attach(e), this._attached = e, this._lightTargetDistance = null, this._lastLightPosition = null, e.isLight && e.target)) {
|
|
17317
17311
|
let t = e.target.position.clone().sub(e.position), n = t.length();
|
|
17318
|
-
n > 1e-4 ? (e.quaternion.setFromUnitVectors(
|
|
17312
|
+
n > 1e-4 ? (e.quaternion.setFromUnitVectors(km, t.normalize()), this._lightTargetDistance = n) : this._lightTargetDistance = 1, this._lastLightPosition = e.position.clone();
|
|
17319
17313
|
}
|
|
17320
17314
|
}
|
|
17321
17315
|
detach() {
|
|
@@ -17427,7 +17421,7 @@ var xm = 4096, Sm = class {
|
|
|
17427
17421
|
dispose() {
|
|
17428
17422
|
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
17423
|
}
|
|
17430
|
-
},
|
|
17424
|
+
}, jm = class {
|
|
17431
17425
|
constructor(e) {
|
|
17432
17426
|
this.layer = "scene", this._transformManager = e, this._enabled = !0;
|
|
17433
17427
|
}
|
|
@@ -17446,15 +17440,15 @@ var xm = 4096, Sm = class {
|
|
|
17446
17440
|
dispose() {
|
|
17447
17441
|
this._enabled = !1;
|
|
17448
17442
|
}
|
|
17449
|
-
},
|
|
17443
|
+
}, Mm = /* @__PURE__ */ new WeakMap(), Nm = ai("engine"), Pm = class extends ut {
|
|
17450
17444
|
constructor(e, t = {}) {
|
|
17451
17445
|
super();
|
|
17452
17446
|
try {
|
|
17453
|
-
|
|
17447
|
+
Mm.get(e)?.dispose();
|
|
17454
17448
|
} catch (e) {
|
|
17455
|
-
|
|
17449
|
+
Nm.warn("prior canvas owner dispose failed", e);
|
|
17456
17450
|
}
|
|
17457
|
-
|
|
17451
|
+
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
17452
|
}
|
|
17459
17453
|
_addTrackedListener(e, t, n) {
|
|
17460
17454
|
e && (e.addEventListener(t, n), this._trackedListeners.push({
|
|
@@ -17467,12 +17461,12 @@ var xm = 4096, Sm = class {
|
|
|
17467
17461
|
for (let { target: e, type: t, handler: n } of this._trackedListeners) try {
|
|
17468
17462
|
e.removeEventListener(t, n);
|
|
17469
17463
|
} catch (e) {
|
|
17470
|
-
|
|
17464
|
+
Nm.warn("failed to remove listener", t, e);
|
|
17471
17465
|
}
|
|
17472
17466
|
this._trackedListeners.length = 0;
|
|
17473
17467
|
}
|
|
17474
17468
|
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,
|
|
17469
|
+
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
17470
|
}
|
|
17477
17471
|
animate() {
|
|
17478
17472
|
if (!this._deviceLost) {
|
|
@@ -17482,7 +17476,7 @@ var xm = 4096, Sm = class {
|
|
|
17482
17476
|
}
|
|
17483
17477
|
if (this.cameraManager.controls && this.cameraManager.controls.update(), this.animationManager?.isPlaying && !this._animRefitInFlight) {
|
|
17484
17478
|
let e = this.animationManager.update();
|
|
17485
|
-
e && (this._animRefitInFlight = !0, this.refitBVH(e).catch((e) =>
|
|
17479
|
+
e && (this._animRefitInFlight = !0, this.refitBVH(e).catch((e) => Nm.error("animation refit error:", e)).finally(() => {
|
|
17486
17480
|
this._animRefitInFlight = !1;
|
|
17487
17481
|
}));
|
|
17488
17482
|
}
|
|
@@ -17516,7 +17510,7 @@ var xm = 4096, Sm = class {
|
|
|
17516
17510
|
this.animationManagerId &&= (cancelAnimationFrame(this.animationManagerId), null);
|
|
17517
17511
|
}
|
|
17518
17512
|
_handleDeviceLost(e) {
|
|
17519
|
-
this._deviceLost || (this._deviceLost = !0,
|
|
17513
|
+
this._deviceLost || (this._deviceLost = !0, Nm.error(`WebGPU device lost (${e?.reason || "unknown"}): ${e?.message || ""}`), this.stopAnimation(), this.dispatchEvent({
|
|
17520
17514
|
type: dr.DEVICE_LOST,
|
|
17521
17515
|
reason: e?.reason,
|
|
17522
17516
|
message: e?.message
|
|
@@ -17554,7 +17548,7 @@ var xm = 4096, Sm = class {
|
|
|
17554
17548
|
let e = je().value, t = k().value;
|
|
17555
17549
|
e?._listeners?.dispose && (e._listeners.dispose.length = 0), t?._listeners?.dispose && (t._listeners.dispose.length = 0);
|
|
17556
17550
|
} catch (e) {
|
|
17557
|
-
|
|
17551
|
+
Nm.warn("failed to clear TSL texture singleton listeners", e);
|
|
17558
17552
|
}
|
|
17559
17553
|
xr(this.renderer), this.renderer = null, this.stages = {}, this.isInitialized = !1;
|
|
17560
17554
|
}
|
|
@@ -17640,7 +17634,7 @@ var xm = 4096, Sm = class {
|
|
|
17640
17634
|
try {
|
|
17641
17635
|
await this.renderer.compileAsync(this.meshScene, this.cameraManager.camera);
|
|
17642
17636
|
} catch (e) {
|
|
17643
|
-
|
|
17637
|
+
Nm.warn("raster fallback precompile failed", e);
|
|
17644
17638
|
}
|
|
17645
17639
|
e.end("Pipeline precompile"), n && (hr({
|
|
17646
17640
|
status: "Finalizing environment map...",
|
|
@@ -17778,7 +17772,7 @@ var xm = 4096, Sm = class {
|
|
|
17778
17772
|
return Y;
|
|
17779
17773
|
}
|
|
17780
17774
|
_isRenderSizeSupported(e, t) {
|
|
17781
|
-
return e > Y || t > Y ? (
|
|
17775
|
+
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
17776
|
}
|
|
17783
17777
|
onResize() {
|
|
17784
17778
|
let e = this.canvas.clientWidth, t = this.canvas.clientHeight;
|
|
@@ -17890,6 +17884,39 @@ var xm = 4096, Sm = class {
|
|
|
17890
17884
|
total: t + n
|
|
17891
17885
|
};
|
|
17892
17886
|
}
|
|
17887
|
+
async getKernelGPUTimings() {
|
|
17888
|
+
let e = this.renderer;
|
|
17889
|
+
if (!e?.backend?.trackTimestamp) return null;
|
|
17890
|
+
await e.resolveTimestampsAsync("compute");
|
|
17891
|
+
let t = e.backend.timestampQueryPool?.compute?.timestamps;
|
|
17892
|
+
if (!t || t.size === 0) return null;
|
|
17893
|
+
let n = /* @__PURE__ */ new Map(), r = this.stages?.pathTracer?._kernelManager?.kernels;
|
|
17894
|
+
if (r) for (let [e, t] of r) n.set(t.id, e);
|
|
17895
|
+
let i = [], a = -1;
|
|
17896
|
+
for (let [e, n] of t) {
|
|
17897
|
+
let t = e.split(":");
|
|
17898
|
+
if (t.length !== 4) continue;
|
|
17899
|
+
let r = Number(t[3].slice(1));
|
|
17900
|
+
Number.isFinite(r) && (i.push({
|
|
17901
|
+
nodeId: Number(t[2]),
|
|
17902
|
+
f: r,
|
|
17903
|
+
ms: n
|
|
17904
|
+
}), r > a && (a = r));
|
|
17905
|
+
}
|
|
17906
|
+
let o = {}, s = 0, c = 0;
|
|
17907
|
+
for (let e of i) {
|
|
17908
|
+
if (e.f !== a) continue;
|
|
17909
|
+
s += e.ms;
|
|
17910
|
+
let t = n.get(e.nodeId);
|
|
17911
|
+
t === void 0 ? c += e.ms : o[t] = (o[t] ?? 0) + e.ms;
|
|
17912
|
+
}
|
|
17913
|
+
return {
|
|
17914
|
+
kernels: o,
|
|
17915
|
+
total: s,
|
|
17916
|
+
unattributed: c,
|
|
17917
|
+
frame: a
|
|
17918
|
+
};
|
|
17919
|
+
}
|
|
17893
17920
|
getCanvas() {
|
|
17894
17921
|
if (!this.renderer?.domElement) return null;
|
|
17895
17922
|
let e = this.denoisingManager;
|
|
@@ -18008,40 +18035,40 @@ var xm = 4096, Sm = class {
|
|
|
18008
18035
|
let n = this.renderer.backend?.device;
|
|
18009
18036
|
n?.lost && (n.lost.then((e) => {
|
|
18010
18037
|
this._disposed || this._handleDeviceLost(e);
|
|
18011
|
-
}), n.onuncapturederror = (e) =>
|
|
18038
|
+
}), 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
18039
|
}
|
|
18013
18040
|
_initCameraManager() {
|
|
18014
|
-
this.cameraManager = new
|
|
18041
|
+
this.cameraManager = new Dp(this.canvas);
|
|
18015
18042
|
}
|
|
18016
18043
|
_initScenes() {
|
|
18017
18044
|
this.scene = new Yt(), this.meshScene = new Yt(), this._sceneHelpers = new Pn();
|
|
18018
18045
|
}
|
|
18019
18046
|
_initAssetPipeline() {
|
|
18020
|
-
this._sdf = new Qc(), this.assetLoader = new
|
|
18047
|
+
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
18048
|
this.needsReset = !0, this.wake();
|
|
18022
18049
|
});
|
|
18023
18050
|
}
|
|
18024
18051
|
_initPipeline() {
|
|
18025
18052
|
this._createStages();
|
|
18026
18053
|
let { clientWidth: e, clientHeight: t } = this.canvas;
|
|
18027
|
-
this.pipeline = new
|
|
18054
|
+
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
18055
|
let n = this.canvas.clientWidth || 1, r = this.canvas.clientHeight || 1;
|
|
18029
18056
|
this.pipeline.setSize(n, r);
|
|
18030
18057
|
}
|
|
18031
18058
|
async _initManagers() {
|
|
18032
|
-
this.interactionManager = new
|
|
18059
|
+
this.interactionManager = new Hf({
|
|
18033
18060
|
scene: this.meshScene,
|
|
18034
18061
|
camera: this.cameraManager.camera,
|
|
18035
18062
|
canvas: this.canvas,
|
|
18036
18063
|
assetLoader: this.assetLoader,
|
|
18037
18064
|
pathTracer: null,
|
|
18038
18065
|
floorPlane: this.assetLoader.floorPlane
|
|
18039
|
-
}), this.interactionManager.wireAppEvents(this), this.cameraManager.setInteractionManager(this.interactionManager), this.lightManager = new
|
|
18066
|
+
}), 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
18067
|
camera: this.cameraManager.camera,
|
|
18041
18068
|
canvas: this.canvas,
|
|
18042
18069
|
orbitControls: this.cameraManager.controls,
|
|
18043
18070
|
app: this
|
|
18044
|
-
}), this.overlayManager.register("transform", new
|
|
18071
|
+
}), this.overlayManager.register("transform", new jm(this.transformManager)), this.interactionManager.setDependencies({
|
|
18045
18072
|
overlayManager: this.overlayManager,
|
|
18046
18073
|
transformManager: this.transformManager,
|
|
18047
18074
|
appDispatch: (e) => this.dispatchEvent(e),
|
|
@@ -18085,7 +18112,9 @@ var xm = 4096, Sm = class {
|
|
|
18085
18112
|
stages: this.stages,
|
|
18086
18113
|
renderer: this.renderer,
|
|
18087
18114
|
resetCallback: () => this.reset(),
|
|
18088
|
-
reconcileCompletion: () => this._reconcileCompletion()
|
|
18115
|
+
reconcileCompletion: () => this._reconcileCompletion(),
|
|
18116
|
+
denoisingManager: this.denoisingManager,
|
|
18117
|
+
cameraManager: this.cameraManager
|
|
18089
18118
|
}), 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
18119
|
if (!this._loadingInProgress) {
|
|
18091
18120
|
if (e.model) this._clearAppendedModels(), await this.loadSceneData();
|
|
@@ -18111,10 +18140,10 @@ var xm = 4096, Sm = class {
|
|
|
18111
18140
|
this.transformManager?.setMeshData(this._sdf.meshes);
|
|
18112
18141
|
}
|
|
18113
18142
|
_createStages() {
|
|
18114
|
-
this.stages.pathTracer = new
|
|
18143
|
+
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
18144
|
}
|
|
18116
18145
|
_setupDenoisingManager() {
|
|
18117
|
-
this.denoisingManager = new
|
|
18146
|
+
this.denoisingManager = new vm({
|
|
18118
18147
|
renderer: this.renderer,
|
|
18119
18148
|
mainCanvas: this.canvas,
|
|
18120
18149
|
scene: this.scene,
|
|
@@ -18157,7 +18186,7 @@ var xm = 4096, Sm = class {
|
|
|
18157
18186
|
this.scene.updateMatrixWorld(), this.overlayManager?.render();
|
|
18158
18187
|
}
|
|
18159
18188
|
async _setupOverlayManager() {
|
|
18160
|
-
this.overlayManager = new
|
|
18189
|
+
this.overlayManager = new Dm(this.cameraManager.camera), this.overlayManager.setupDefaultHelpers({
|
|
18161
18190
|
helperScene: this._sceneHelpers,
|
|
18162
18191
|
meshScene: this.meshScene,
|
|
18163
18192
|
pipeline: this.pipeline,
|
|
@@ -18188,7 +18217,7 @@ var xm = 4096, Sm = class {
|
|
|
18188
18217
|
_forwardEvents(e, t) {
|
|
18189
18218
|
if (e) for (let n of t) this._addTrackedListener(e, n, (e) => this.dispatchEvent(e));
|
|
18190
18219
|
}
|
|
18191
|
-
},
|
|
18220
|
+
}, Fm = class {
|
|
18192
18221
|
constructor(e) {
|
|
18193
18222
|
this._app = e, this._cancelled = !1, this._rendering = !1;
|
|
18194
18223
|
}
|
|
@@ -18286,4 +18315,4 @@ var xm = 4096, Sm = class {
|
|
|
18286
18315
|
}
|
|
18287
18316
|
};
|
|
18288
18317
|
//#endregion
|
|
18289
|
-
export { Pr as AF_DEFAULTS, kr as ASVGF_QUALITY_PRESETS, Nr as AUTO_FOCUS_MODES,
|
|
18318
|
+
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 };
|