rayzee 7.21.0 → 7.22.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +75 -4
- package/dist/rayzee.es.js +634 -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 +4 -6
- package/src/Processor/KernelManager.js +17 -70
- package/src/Processor/QueueManager.js +4 -3
- package/src/Processor/SceneProcessor.js +12 -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 = !
|
|
4910
|
+
}, this.enableTreeletOptimization = !1, this.treeletSize = 5, this.treeletOptimizationPasses = 1, this.treeletMinImprovement = .02, this.treeletComplexityThreshold = 5e4, this.enableReinsertionOptimization = !0, this.reinsertionBatchSizeRatio = .02, this.reinsertionMaxIterations = 2, this.initializeBinArrays(), this._partResult = {
|
|
4906
4911
|
mid: 0,
|
|
4907
4912
|
lMinX: 0,
|
|
4908
4913
|
lMinY: 0,
|
|
@@ -4935,7 +4940,7 @@ var rc = {
|
|
|
4935
4940
|
e.objectMedian !== void 0 && (this.enableObjectMedianFallback = e.objectMedian), e.spatialMedian !== void 0 && (this.enableSpatialMedianFallback = e.spatialMedian);
|
|
4936
4941
|
}
|
|
4937
4942
|
setTreeletConfig(e) {
|
|
4938
|
-
e.enabled !== void 0 && (this.enableTreeletOptimization = e.enabled), e.size !== void 0 && (this.treeletSize = Math.max(3, Math.min(12, e.size))), e.passes !== void 0 && (this.treeletOptimizationPasses = Math.max(1, Math.min(3, e.passes))), e.minImprovement !== void 0 && (this.treeletMinImprovement = Math.max(.001, e.minImprovement));
|
|
4943
|
+
e.enabled !== void 0 && (this.enableTreeletOptimization = e.enabled), e.size !== void 0 && (this.treeletSize = Math.max(3, Math.min(12, e.size))), e.passes !== void 0 && (this.treeletOptimizationPasses = Math.max(1, Math.min(3, e.passes))), e.minImprovement !== void 0 && (this.treeletMinImprovement = Math.max(.001, e.minImprovement)), e.complexityThreshold !== void 0 && (this.treeletComplexityThreshold = e.complexityThreshold);
|
|
4939
4944
|
}
|
|
4940
4945
|
disableTreeletOptimization() {
|
|
4941
4946
|
this.enableTreeletOptimization = !1;
|
|
@@ -5082,26 +5087,26 @@ var rc = {
|
|
|
5082
5087
|
this.centroids = new Float32Array(a * 3), this.bMin = new Float32Array(a * 3), this.bMax = new Float32Array(a * 3), this.indices = new Uint32Array(a), this.mortonCodes = new Uint32Array(a), this.initializeTriangleArrays(), this.splitStats.initTime = performance.now() - o, this.sortTrianglesByMortonCode();
|
|
5083
5088
|
let s = performance.now(), c = this.buildNodeRecursive(0, a, t, n);
|
|
5084
5089
|
if (this.splitStats.sahBuildTime = performance.now() - s, this.enableTreeletOptimization && this.totalTriangles > 1e3) {
|
|
5085
|
-
let e = this.totalTriangles > this.treeletComplexityThreshold
|
|
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=!1,this.treeletSize=5,this.treeletOptimizationPasses=1,this.treeletMinImprovement=.02,this.treeletComplexityThreshold=5e4,this.enableReinsertionOptimization=!0,this.reinsertionBatchSizeRatio=.02,this.reinsertionMaxIterations=2,this.initializeBinArrays(),this._partResult={mid:0,lMinX:0,lMinY:0,lMinZ:0,lMaxX:0,lMaxY:0,lMaxZ:0,rMinX:0,rMinY:0,rMinZ:0,rMaxX:0,rMaxY:0,rMaxZ:0},this.centroids=null,this.bMin=null,this.bMax=null,this.indices=null,this.mortonCodes=null,this.triangles=null,this.reorderedTriangleData=null}initializeBinArrays(){let e=this.maxBins;this.binBoundsMin=new Float32Array(e*3),this.binBoundsMax=new Float32Array(e*3),this.binCounts=new Uint32Array(e),this.leftPrefixMin=new Float32Array(e*3),this.leftPrefixMax=new Float32Array(e*3),this.leftPrefixCount=new Uint32Array(e),this.rightPrefixMin=new Float32Array(e*3),this.rightPrefixMax=new Float32Array(e*3),this.rightPrefixCount=new Uint32Array(e)}getOptimalBinCount(e){return e<=16?this.minBins:e<=64?16:e<=256?32:e<=1024?48:this.maxBins}setAdaptiveBinConfig(e){e.minBins!==void 0&&(this.minBins=Math.max(4,e.minBins)),e.maxBins!==void 0&&(this.maxBins=Math.min(128,e.maxBins)),e.baseBins!==void 0&&(this.numBins=e.baseBins),e.maxBins!==void 0&&this.initializeBinArrays()}setMortonConfig(e){e.enabled!==void 0&&(this.useMortonCodes=e.enabled),e.bits!==void 0&&(this.mortonBits=Math.max(6,Math.min(10,e.bits))),e.threshold!==void 0&&(this.mortonClusterThreshold=Math.max(16,e.threshold))}setFallbackConfig(e){e.objectMedian!==void 0&&(this.enableObjectMedianFallback=e.objectMedian),e.spatialMedian!==void 0&&(this.enableSpatialMedianFallback=e.spatialMedian)}setTreeletConfig(e){e.enabled!==void 0&&(this.enableTreeletOptimization=e.enabled),e.size!==void 0&&(this.treeletSize=Math.max(3,Math.min(12,e.size))),e.passes!==void 0&&(this.treeletOptimizationPasses=Math.max(1,Math.min(3,e.passes))),e.minImprovement!==void 0&&(this.treeletMinImprovement=Math.max(.001,e.minImprovement)),e.complexityThreshold!==void 0&&(this.treeletComplexityThreshold=e.complexityThreshold)}disableTreeletOptimization(){this.enableTreeletOptimization=!1}setReinsertionConfig(e){e.enabled!==void 0&&(this.enableReinsertionOptimization=e.enabled),e.batchSizeRatio!==void 0&&(this.reinsertionBatchSizeRatio=Math.max(.005,Math.min(.1,e.batchSizeRatio))),e.maxIterations!==void 0&&(this.reinsertionMaxIterations=Math.max(1,Math.min(5,e.maxIterations)))}initializeTriangleArrays(){let e=this.totalTriangles,t=this.triangles,n=S.POSITION_A_OFFSET,r=S.POSITION_B_OFFSET,i=S.POSITION_C_OFFSET;for(let a=0;a<e;a++){let e=a*C,o=t[e+n],s=t[e+n+1],c=t[e+n+2],l=t[e+r],u=t[e+r+1],d=t[e+r+2],f=t[e+i],p=t[e+i+1],m=t[e+i+2],h=a*3;this.centroids[h]=(o+l+f)/3,this.centroids[h+1]=(s+u+p)/3,this.centroids[h+2]=(c+d+m)/3,this.bMin[h]=o<l?o<f?o:f:l<f?l:f,this.bMin[h+1]=s<u?s<p?s:p:u<p?u:p,this.bMin[h+2]=c<d?c<m?c:m:d<m?d:m,this.bMax[h]=o>l?o>f?o:f:l>f?l:f,this.bMax[h+1]=s>u?s>p?s:p:u>p?u:p,this.bMax[h+2]=c>d?c>m?c:m:d>m?d:m,this.indices[a]=a}}expandBits(e){return e=e*65537&4278190335,e=e*257&251719695,e=e*17&3272356035,e=e*5&1227133513,e}morton3D(e,t,n){return(this.expandBits(n)<<2)+(this.expandBits(t)<<1)+this.expandBits(e)}computeMortonCodeForIndex(e,t,n,r,i,a,o){let s=this.centroids,c=e*3,l=(1<<this.mortonBits)-1,u=i>0?(s[c]-t)/i:0,d=a>0?(s[c+1]-n)/a:0,f=o>0?(s[c+2]-r)/o:0,p=Math.max(0,Math.min(l,Math.floor(u*l))),m=Math.max(0,Math.min(l,Math.floor(d*l))),h=Math.max(0,Math.min(l,Math.floor(f*l)));return this.morton3D(p,m,h)}sortTrianglesByMortonCode(){let e=this.totalTriangles;if(!this.useMortonCodes||e<this.mortonClusterThreshold)return;let t=performance.now(),n=this.centroids,r=this.indices,i=1/0,a=1/0,o=1/0,s=-1/0,c=-1/0,l=-1/0;for(let t=0;t<e;t++){let e=r[t]*3,u=n[e],d=n[e+1],f=n[e+2];u<i&&(i=u),d<a&&(a=d),f<o&&(o=f),u>s&&(s=u),d>c&&(c=d),f>l&&(l=f)}let u=s-i,d=c-a,f=l-o,p=this.mortonCodes,m=(1<<this.mortonBits)-1,h=u>0?m/u:0,g=d>0?m/d:0,_=f>0?m/f:0;for(let t=0;t<e;t++){let e=r[t],s=e*3,c=(n[s]-i)*h,l=(n[s+1]-a)*g,u=(n[s+2]-o)*_;c=c<0?0:(c>m?m:c)|0,l=l<0?0:(l>m?m:l)|0,u=u<0?0:(u>m?m:u)|0,c=c*65537&4278190335,c=c*257&251719695,c=c*17&3272356035,c=c*5&1227133513,l=l*65537&4278190335,l=l*257&251719695,l=l*17&3272356035,l=l*5&1227133513,u=u*65537&4278190335,u=u*257&251719695,u=u*17&3272356035,u=u*5&1227133513,p[e]=(u<<2)+(l<<1)+c}let v=new Uint32Array(e),y=new Uint32Array(256);for(let t=0;t<32;t+=8){y.fill(0);for(let n=0;n<e;n++)y[p[r[n]]>>>t&255]++;let n=0;for(let e=0;e<256;e++){let t=y[e];y[e]=n,n+=t}for(let n=0;n<e;n++){let e=p[r[n]]>>>t&255;v[y[e]++]=r[n]}r.set(v)}this.splitStats.mortonSortTime+=performance.now()-t}build(e,t=30,n=null){if(this.totalTriangles=e.byteLength/(C*4),this.processedTriangles=0,this.lastProgressUpdate=performance.now(),!(this.useWorker&&null))return new Promise(r=>{r(this._buildSyncAndFlatten(e,t,n))})}_buildSyncAndFlatten(e,t,n){let r=this.buildSync(e,t,n);return{bvhData:this.flattenBVH(r),bvhRoot:!0,reorderedTriangles:this.reorderedTriangleData||null,originalToBvh:this.originalToBvhMap||null}}buildSync(t,r=30,i=null,a=null){let o=performance.now();this.totalNodes=0,this.processedTriangles=0,this.triangles=t,this.totalTriangles=t.byteLength/(C*4),this.lastProgressUpdate=performance.now(),this.splitStats={sahSplits:0,objectMedianSplits:0,spatialMedianSplits:0,failedSplits:0,avgBinsUsed:0,totalSplitAttempts:0,mortonSortTime:0,totalBuildTime:0,treeletOptimizationTime:0,treeletsProcessed:0,treeletsImproved:0,averageSAHImprovement:0,reinsertionOptimizationTime:0,reinsertionsApplied:0,reinsertionIterations:0,saOrderTime:0,initTime:0,sahBuildTime:0,reorderTime:0};let s=this.totalTriangles,c=performance.now();this.centroids=new Float32Array(s*3),this.bMin=new Float32Array(s*3),this.bMax=new Float32Array(s*3),this.indices=new Uint32Array(s),this.mortonCodes=new Uint32Array(s),this.initializeTriangleArrays(),this.splitStats.initTime=performance.now()-c,this.sortTrianglesByMortonCode();let l=performance.now(),u=this.buildNodeRecursive(0,s,r,i);if(this.splitStats.sahBuildTime=performance.now()-l,this.enableTreeletOptimization&&this.totalTriangles>1e3){let t=this.totalTriangles>this.treeletComplexityThreshold?3:this.treeletSize,n=new e(this.traversalCost,this.intersectionCost);n.setTreeletSize(t),n.setMinImprovement(this.treeletMinImprovement);let r=performance.now();for(let e=0;e<this.treeletOptimizationPasses;e++){let t=i?t=>{i(`Treelet optimization pass ${e+1}/${this.treeletOptimizationPasses}: ${t}`)}:null;try{n.optimizeBVH(u,t)}catch(t){x.error(`treelet optimizer failed in pass ${e+1}:`,t);break}let a=n.getStatistics(),o=performance.now()-r;if(a.treeletsImproved===0&&e>0||o>15e3)break}let a=performance.now()-r;this.splitStats.treeletOptimizationTime=a;let o=n.getStatistics();this.splitStats.treeletsProcessed=o.treeletsProcessed,this.splitStats.treeletsImproved=o.treeletsImproved,this.splitStats.averageSAHImprovement=o.averageSAHImprovement}if(this.enableReinsertionOptimization&&this.totalTriangles>1e3){let e=new n(this.traversalCost,this.intersectionCost);e.setBatchSizeRatio(this.reinsertionBatchSizeRatio),e.setMaxIterations(this.reinsertionMaxIterations);let t=i?e=>{i(e)}:null;try{e.optimizeBVH(u,t)}catch(e){x.error(`reinsertion optimizer failed:`,e)}let r=e.getStatistics();this.splitStats.reinsertionOptimizationTime=r.timeMs,this.splitStats.reinsertionsApplied=r.reinsertionsApplied,this.splitStats.reinsertionIterations=r.iterations}let d=performance.now();this.applySAOrdering(u),this.splitStats.saOrderTime=performance.now()-d;let f=performance.now(),p=this.triangles,m=a||new Float32Array(s*C);for(let e=0;e<s;e++){let t=this.indices[e]*C,n=e*C;m.set(p.subarray(t,t+C),n)}this.reorderedTriangleData=m;let h=new Uint32Array(s);for(let e=0;e<s;e++)h[this.indices[e]]=e;this.originalToBvhMap=h,this.splitStats.reorderTime=performance.now()-f,this.splitStats.totalBuildTime=performance.now()-o;let g=this.splitStats.totalBuildTime,v=this.splitStats;return x.debug(`${_.n(s)} tris → ${_.n(this.totalNodes)} nodes in ${_.ms(g)} | SAH ${v.sahSplits} objMed ${v.objectMedianSplits} spatMed ${v.spatialMedianSplits} failed ${v.failedSplits}`+(v.treeletsProcessed?` | treelets ${v.treeletsImproved}/${v.treeletsProcessed} improved`:``)+(v.reinsertionsApplied?` | reinsertions ${v.reinsertionsApplied}`:``)),i&&i(100),this.centroids=null,this.bMin=null,this.bMax=null,this.mortonCodes=null,u}updateProgress(e,t){if(!t)return;this.processedTriangles+=e;let n=performance.now();n-this.lastProgressUpdate<this.progressUpdateInterval||(this.lastProgressUpdate=n,t(Math.min(Math.floor(this.processedTriangles/this.totalTriangles*100),99)))}buildNodeRecursiveToDepth(e,t,n,r,i,a,o,s,c,l,u){let d=new w;this.totalNodes++;let f=t-e;if(a===void 0?this.updateNodeBounds(d,e,t):(d.minX=a,d.minY=o,d.minZ=s,d.maxX=c,d.maxY=l,d.maxZ=u),f<=this.maxLeafSize||n<=0)return d.triangleOffset=e,d.triangleCount=f,this.updateProgress(f,i),d;if(r<=0&&f>this.maxLeafSize*16){let r=this.frontierTasks.length;return d.triangleOffset=e,d.triangleCount=f,d.isFrontier=!0,d.frontierTaskId=r,this.frontierTasks.push({taskId:r,start:e,end:t,depth:n,preMinX:d.minX,preMinY:d.minY,preMinZ:d.minZ,preMaxX:d.maxX,preMaxY:d.maxY,preMaxZ:d.maxZ}),d}let p=this.findBestSplitPositionSAH(e,t,d);if(!p.success){if(this.splitStats.failedSplits++,r>0||f<=this.maxLeafSize*16)return d.triangleOffset=e,d.triangleCount=f,this.updateProgress(f,i),d;let a=this.frontierTasks.length;return d.triangleOffset=e,d.triangleCount=f,d.isFrontier=!0,d.frontierTaskId=a,this.frontierTasks.push({taskId:a,start:e,end:t,depth:n,preMinX:d.minX,preMinY:d.minY,preMinZ:d.minZ,preMaxX:d.maxX,preMaxY:d.maxY,preMaxZ:d.maxZ}),d}p.method===`SAH`?this.splitStats.sahSplits++:p.method===`object_median`?this.splitStats.objectMedianSplits++:p.method===`spatial_median`&&this.splitStats.spatialMedianSplits++,this.partitionWithBounds(e,t,p.axis,p.pos);let m=this._partResult,h=m.mid,g=m.lMinX,_=m.lMinY,v=m.lMinZ,y=m.lMaxX,b=m.lMaxY,x=m.lMaxZ,S=m.rMinX,C=m.rMinY,T=m.rMinZ,E=m.rMaxX,D=m.rMaxY,O=m.rMaxZ;return h===e||h===t?(d.triangleOffset=e,d.triangleCount=f,this.updateProgress(f,i),d):(d.leftChild=this.buildNodeRecursiveToDepth(e,h,n-1,r-1,i,g,_,v,y,b,x),d.rightChild=this.buildNodeRecursiveToDepth(h,t,n-1,r-1,i,S,C,T,E,D,O),d)}buildNodeRecursive(e,t,n,r,i,a,o,s,c,l){let u=new w;this.totalNodes++;let d=t-e;if(i===void 0?this.updateNodeBounds(u,e,t):(u.minX=i,u.minY=a,u.minZ=o,u.maxX=s,u.maxY=c,u.maxZ=l),d<=this.maxLeafSize||n<=0)return u.triangleOffset=e,u.triangleCount=d,this.updateProgress(d,r),u;let f=this.findBestSplitPositionSAH(e,t,u);if(!f.success)return this.splitStats.failedSplits++,u.triangleOffset=e,u.triangleCount=d,this.updateProgress(d,r),u;f.method===`SAH`?this.splitStats.sahSplits++:f.method===`object_median`?this.splitStats.objectMedianSplits++:f.method===`spatial_median`&&this.splitStats.spatialMedianSplits++,this.partitionWithBounds(e,t,f.axis,f.pos);let p=this._partResult,m=p.mid,h=p.lMinX,g=p.lMinY,_=p.lMinZ,v=p.lMaxX,y=p.lMaxY,b=p.lMaxZ,x=p.rMinX,S=p.rMinY,C=p.rMinZ,T=p.rMaxX,E=p.rMaxY,D=p.rMaxZ;return m===e||m===t?(u.triangleOffset=e,u.triangleCount=d,this.updateProgress(d,r),u):(u.leftChild=this.buildNodeRecursive(e,m,n-1,r,h,g,_,v,y,b),u.rightChild=this.buildNodeRecursive(m,t,n-1,r,x,S,C,T,E,D),u)}partitionWithBounds(e,t,n,r){let i=this.indices,a=this.centroids,o=this.bMin,s=this.bMax,c=e,l=t-1,u=1/0,d=1/0,f=1/0,p=-1/0,m=-1/0,h=-1/0,g=1/0,_=1/0,v=1/0,y=-1/0,b=-1/0,x=-1/0;for(;c<=l;){let e=i[c],t=e*3;a[t+n]<=r?(o[t]<u&&(u=o[t]),o[t+1]<d&&(d=o[t+1]),o[t+2]<f&&(f=o[t+2]),s[t]>p&&(p=s[t]),s[t+1]>m&&(m=s[t+1]),s[t+2]>h&&(h=s[t+2]),c++):(o[t]<g&&(g=o[t]),o[t+1]<_&&(_=o[t+1]),o[t+2]<v&&(v=o[t+2]),s[t]>y&&(y=s[t]),s[t+1]>b&&(b=s[t+1]),s[t+2]>x&&(x=s[t+2]),i[c]=i[l],i[l]=e,l--)}let S=this._partResult;return S.mid=c,S.lMinX=u,S.lMinY=d,S.lMinZ=f,S.lMaxX=p,S.lMaxY=m,S.lMaxZ=h,S.rMinX=g,S.rMinY=_,S.rMinZ=v,S.rMaxX=y,S.rMaxY=b,S.rMaxZ=x,S}updateNodeBounds(e,t,n){let r=1/0,i=1/0,a=1/0,o=-1/0,s=-1/0,c=-1/0,l=this.indices,u=this.bMin,d=this.bMax;for(let e=t;e<n;e++){let t=l[e]*3;u[t]<r&&(r=u[t]),u[t+1]<i&&(i=u[t+1]),u[t+2]<a&&(a=u[t+2]),d[t]>o&&(o=d[t]),d[t+1]>s&&(s=d[t+1]),d[t+2]>c&&(c=d[t+2])}e.minX=r,e.minY=i,e.minZ=a,e.maxX=o,e.maxY=s,e.maxZ=c}findBestSplitPositionSAH(e,t,n){let r=1/0,i=-1,a=0,o=this.computeSurfaceAreaFlat(n.minX,n.minY,n.minZ,n.maxX,n.maxY,n.maxZ),s=t-e,c=this.intersectionCost*s,l=this.getOptimalBinCount(s);this.splitStats.totalSplitAttempts++,this.splitStats.avgBinsUsed=(this.splitStats.avgBinsUsed*(this.splitStats.totalSplitAttempts-1)+l)/this.splitStats.totalSplitAttempts;let u=this.indices,d=this.centroids,f=this.bMin,p=this.bMax,m=this.binBoundsMin,h=this.binBoundsMax,g=this.binCounts,_=this.leftPrefixMin,v=this.leftPrefixMax,y=this.leftPrefixCount,b=this.rightPrefixMin,x=this.rightPrefixMax,S=this.rightPrefixCount,C=1/0,w=-1/0,T=1/0,E=-1/0,D=1/0,O=-1/0;for(let n=e;n<t;n++){let e=u[n]*3,t=d[e],r=d[e+1],i=d[e+2];t<C&&(C=t),t>w&&(w=t),r<T&&(T=r),r>E&&(E=r),i<D&&(D=i),i>O&&(O=i)}let k=[C,T,D],A=[w,E,O];for(let n=0;n<3;n++){let s=k[n],C=A[n];if(C-s<1e-6)continue;for(let e=0;e<l;e++){g[e]=0;let t=e*3;m[t]=1/0,m[t+1]=1/0,m[t+2]=1/0,h[t]=-1/0,h[t+1]=-1/0,h[t+2]=-1/0}let w=l/(C-s);for(let r=e;r<t;r++){let e=u[r],t=d[e*3+n],i=Math.floor((t-s)*w);i>=l&&(i=l-1),g[i]++;let a=i*3,o=e*3;f[o]<m[a]&&(m[a]=f[o]),f[o+1]<m[a+1]&&(m[a+1]=f[o+1]),f[o+2]<m[a+2]&&(m[a+2]=f[o+2]),p[o]>h[a]&&(h[a]=p[o]),p[o+1]>h[a+1]&&(h[a+1]=p[o+1]),p[o+2]>h[a+2]&&(h[a+2]=p[o+2])}y[0]=g[0],_[0]=m[0],_[1]=m[1],_[2]=m[2],v[0]=h[0],v[1]=h[1],v[2]=h[2];for(let e=1;e<l;e++){let t=e*3,n=(e-1)*3;y[e]=y[e-1]+g[e];let r=_[n],i=m[t],a=_[n+1],o=m[t+1],s=_[n+2],c=m[t+2];_[t]=r<i?r:i,_[t+1]=a<o?a:o,_[t+2]=s<c?s:c;let l=v[n],u=h[t],d=v[n+1],f=h[t+1],p=v[n+2],b=h[t+2];v[t]=l>u?l:u,v[t+1]=d>f?d:f,v[t+2]=p>b?p:b}let T=l-1,E=T*3;S[T]=g[T],b[E]=m[E],b[E+1]=m[E+1],b[E+2]=m[E+2],x[E]=h[E],x[E+1]=h[E+1],x[E+2]=h[E+2];for(let e=T-1;e>=0;e--){let t=e*3,n=(e+1)*3;S[e]=S[e+1]+g[e];let r=b[n],i=m[t],a=b[n+1],o=m[t+1],s=b[n+2],c=m[t+2];b[t]=r<i?r:i,b[t+1]=a<o?a:o,b[t+2]=s<c?s:c;let l=x[n],u=h[t],d=x[n+1],f=h[t+1],p=x[n+2],_=h[t+2];x[t]=l>u?l:u,x[t+1]=d>f?d:f,x[t+2]=p>_?p:_}for(let e=1;e<l;e++){let t=(e-1)*3,u=e*3,d=y[e-1],f=S[e];if(d===0||f===0)continue;let p=v[t]-_[t],m=v[t+1]-_[t+1],h=v[t+2]-_[t+2],g=2*(p*m+m*h+h*p),w=x[u]-b[u],T=x[u+1]-b[u+1],E=x[u+2]-b[u+2],D=2*(w*T+T*E+E*w),O=this.traversalCost+g/o*d*this.intersectionCost+D/o*f*this.intersectionCost;O<r&&O<c&&(r=O,i=n,a=s+(C-s)*e/l)}}return i===-1?this.enableObjectMedianFallback?this.findObjectMedianSplit(e,t):this.enableSpatialMedianFallback?this.findSpatialMedianSplit(e,t):{success:!1,method:`fallbacks_disabled`}:{success:!0,axis:i,pos:a,method:`SAH`,binsUsed:l}}findObjectMedianSplit(e,t){let n=this.indices,r=this.centroids,i=-1,a=-1;for(let o=0;o<3;o++){let s=1/0,c=-1/0;for(let i=e;i<t;i++){let e=r[n[i]*3+o];e<s&&(s=e),e>c&&(c=e)}let l=c-s;l>a&&(a=l,i=o)}if(i===-1||a<1e-10)return this.enableSpatialMedianFallback?this.findSpatialMedianSplit(e,t):{success:!1,method:`object_median_failed`};let o=t-e,s=e+Math.floor(o/2);this.quickselect(e,t,s,i);let c=r[n[s]*3+i],l=!0;for(let e=s+1;e<t;e++)if(r[n[e]*3+i]>c){l=!1;break}if(l){let a=-1/0;for(let t=e;t<s;t++){let e=r[n[t]*3+i];e>a&&(a=e)}if(a<c)c=(a+c)*.5;else return this.enableSpatialMedianFallback?this.findSpatialMedianSplit(e,t):{success:!1,method:`object_median_degenerate`}}return{success:!0,axis:i,pos:c,method:`object_median`}}findSpatialMedianSplit(e,t){let n=this.indices,r=this.centroids,i=this.bMin,a=this.bMax,o=-1,s=-1,c=0,l=0;for(let r=0;r<3;r++){let u=1/0,d=-1/0;for(let o=e;o<t;o++){let e=n[o]*3+r;i[e]<u&&(u=i[e]),a[e]>d&&(d=a[e])}let f=d-u;f>s&&(s=f,o=r,c=u,l=d)}if(o===-1||s<1e-12)return{success:!1,method:`spatial_median_failed`};let u=(c+l)*.5,d=t-e,f=0;for(let i=e;i<t;i++)r[n[i]*3+o]<=u&&f++;if(f===0||f===d){let i=e+Math.floor(d/2);this.quickselect(e,t,i,o);let a=r[n[i]*3+o],s=!0;for(let i=e;i<t;i++)if(r[n[i]*3+o]!==a){s=!1;break}if(s)return{success:!1,method:`spatial_median_degenerate`};let c=-1/0;for(let t=e;t<i;t++){let e=r[n[t]*3+o];e>c&&(c=e)}if(c<a)u=(c+a)*.5;else{let e=1/0;for(let a=i+1;a<t;a++){let t=r[n[a]*3+o];t<e&&(e=t)}u=(a+e)*.5}}return{success:!0,axis:o,pos:u,method:`spatial_median`}}quickselect(e,t,n,r){let i=this.indices,a=this.centroids,o=e,s=t-1;for(;o<s;){let e=o+s>>>1,t=a[i[o]*3+r],c=a[i[e]*3+r],l=a[i[s]*3+r];if(t>c){let t=i[o];i[o]=i[e],i[e]=t}if(t>l){let e=i[o];i[o]=i[s],i[s]=e}if(c>l){let t=i[e];i[e]=i[s],i[s]=t}let u=a[i[e]*3+r],d=o,f=s;for(;d<=f;){for(;a[i[d]*3+r]<u;)d++;for(;a[i[f]*3+r]>u;)f--;if(d<=f){let e=i[d];i[d]=i[f],i[f]=e,d++,f--}}f<n&&(o=d),d>n&&(s=f)}}applySAOrdering(e){if(!e||!e.leftChild)return;let t=[e],n=[];for(;t.length>0;){let e=t.pop();!e.leftChild||!e.rightChild||(n.push(e),t.push(e.leftChild),t.push(e.rightChild))}for(let e=n.length-1;e>=0;e--){let t=n[e],r=t.leftChild,i=t.rightChild,a=r.maxX-r.minX,o=r.maxY-r.minY,s=r.maxZ-r.minZ,c=i.maxX-i.minX,l=i.maxY-i.minY,u=i.maxZ-i.minZ;c*l+l*u+u*c>a*o+o*s+s*a&&(t.leftChild=i,t.rightChild=r)}}flattenBVH(e){let t=[],n=[e];for(;n.length>0;){let e=n.pop();e._flatIndex=t.length,t.push(e),e.rightChild&&n.push(e.rightChild),e.leftChild&&n.push(e.leftChild)}let r=new Float32Array(t.length*16);for(let e=0;e<t.length;e++){let n=t[e],i=e*16;if(n.leftChild){let e=n.leftChild,t=n.rightChild;r[i]=e.minX,r[i+1]=e.minY,r[i+2]=e.minZ,r[i+3]=e._flatIndex,r[i+4]=e.maxX,r[i+5]=e.maxY,r[i+6]=e.maxZ,r[i+7]=t._flatIndex,r[i+8]=t.minX,r[i+9]=t.minY,r[i+10]=t.minZ,r[i+12]=t.maxX,r[i+13]=t.maxY,r[i+14]=t.maxZ}else r[i]=n.triangleOffset,r[i+1]=n.triangleCount,r[i+3]=-1}return r}flattenBVHWithFrontier(e){let t=[],n=[e];for(;n.length>0;){let e=n.pop();e._flatIndex=t.length,t.push(e),e.rightChild&&n.push(e.rightChild),e.leftChild&&n.push(e.leftChild)}let r=new Float32Array(t.length*16),i=[];for(let e=0;e<t.length;e++){let n=t[e],a=e*16;if(n.leftChild){let e=n.leftChild,t=n.rightChild;r[a]=e.minX,r[a+1]=e.minY,r[a+2]=e.minZ,r[a+3]=e._flatIndex,r[a+4]=e.maxX,r[a+5]=e.maxY,r[a+6]=e.maxZ,r[a+7]=t._flatIndex,r[a+8]=t.minX,r[a+9]=t.minY,r[a+10]=t.minZ,r[a+12]=t.maxX,r[a+13]=t.maxY,r[a+14]=t.maxZ}else if(n.isFrontier){let t=n.frontierTaskId;r[a]=n.triangleOffset,r[a+1]=n.triangleCount,r[a+2]=t,r[a+3]=-2,i.push({taskId:t,flatIndex:e})}else r[a]=n.triangleOffset,r[a+1]=n.triangleCount,r[a+3]=-1}return{flatData:r,frontierMap:i,nodeCount:t.length}}assembleParallelBVH(e,t,n,r){let i=[...r].sort((e,t)=>e.taskId-t.taskId),a=t;for(let e=0;e<i.length;e++)a+=i[e].nodeCount;let o=new Float32Array(a*16);o.set(e);let s=new Map;for(let e of n)s.set(e.taskId,e.flatIndex);let c=t;for(let e=0;e<i.length;e++){let t=i[e],n=t.flatData,r=t.nodeCount,a=c*16;o.set(n,a);for(let e=0;e<r;e++){let t=a+e*16;o[t+3]!==-1&&(o[t+3]+=c,o[t+7]+=c)}let l=s.get(t.taskId);if(l!==void 0){let e=l*16,t=a;for(let n=0;n<16;n++)o[e+n]=o[t+n]}c+=r}return o}computeSurfaceAreaFlat(e,t,n,r,i,a){let o=r-e,s=i-t,c=a-n;return 2*(o*s+s*c+c*o)}};const E=y(`bvh`);self.onmessage=function(e){let t=e.data,n=t.type;b(t.logLevel),n===`buildPhase1`?D(t):n===`assemble`?O(t):k(t)};function D(e){let{sharedTriangleData:t,sharedCentroids:n,sharedBMin:r,sharedBMax:i,sharedIndices:a,sharedMortonCodes:o,triangleCount:s,depth:c,parallelDepth:l,reportProgress:u,treeletOptimization:d}=e;try{let e=new T;d&&e.setTreeletConfig(d);let f=u?e=>{self.postMessage({type:`progress`,progress:e})}:null;e.triangles=new Float32Array(t),e.centroids=new Float32Array(n),e.bMin=new Float32Array(r),e.bMax=new Float32Array(i),e.indices=new Uint32Array(a),e.mortonCodes=new Uint32Array(o),e.totalTriangles=s,e.totalNodes=0,e.processedTriangles=0,e.lastProgressUpdate=performance.now(),e.splitStats={sahSplits:0,objectMedianSplits:0,spatialMedianSplits:0,failedSplits:0,avgBinsUsed:0,totalSplitAttempts:0,mortonSortTime:0,totalBuildTime:0,treeletOptimizationTime:0,treeletsProcessed:0,treeletsImproved:0,averageSAHImprovement:0,initTime:0,sahBuildTime:0,reorderTime:0};let p=performance.now(),m=performance.now();e.initializeTriangleArrays(),e.splitStats.initTime=performance.now()-m,e.sortTrianglesByMortonCode(),e.frontierTasks=[];let h=performance.now(),g=e.buildNodeRecursiveToDepth(0,s,c,l,f);e.splitStats.sahBuildTime=performance.now()-h,e.applySAOrdering(g);let v=performance.now(),{flatData:y,frontierMap:b,nodeCount:x}=e.flattenBVHWithFrontier(g),S=performance.now()-v,C=performance.now()-p;E.debug(`phase 1 ${_.ms(C)} (init ${_.ms(e.splitStats.initTime)} · morton ${_.ms(e.splitStats.mortonSortTime)} · SAH ${_.ms(e.splitStats.sahBuildTime)} · flatten ${_.ms(S)}) · ${e.frontierTasks.length} frontier tasks`),self.postMessage({type:`phase1Result`,topFlatData:y,topNodeCount:x,frontierTasks:e.frontierTasks,frontierMap:b,splitStats:e.splitStats},[y.buffer])}catch(e){E.error(`phase 1 failed:`,e),self.postMessage({type:`error`,error:e.message})}}function O(e){let{topFlatData:t,topNodeCount:n,frontierMap:r,subtreeResults:i,sharedTriangleData:a,sharedIndices:o,sharedReorderBuffer:s,triangleCount:c}=e;try{let e=performance.now(),l=new T().assembleParallelBVH(t,n,r,i),u=new Uint32Array(o),d=new Float32Array(a),f=new Float32Array(s);for(let e=0;e<c;e++){let t=u[e]*32,n=e*32;f.set(d.subarray(t,t+32),n)}let p=new Uint32Array(c);for(let e=0;e<c;e++)p[u[e]]=e;let m=performance.now()-e;E.debug(`phase 3 assemble + reorder ${_.ms(m)} (${_.mb(l.byteLength)} BVH)`),self.postMessage({type:`assembleResult`,bvhData:l,originalToBvh:p,triangleCount:c},[l.buffer,p.buffer])}catch(e){E.error(`assembly failed:`,e),self.postMessage({type:`error`,error:e.message})}}function k(e){let{triangleData:t,triangleByteOffset:n,triangleByteLength:r,depth:i,reportProgress:a,treeletOptimization:o,reinsertionOptimization:s,sharedReorderBuffer:c,maxLeafSize:l,numBins:u,maxBins:d,minBins:f}=e,p=new T;l!==void 0&&(p.maxLeafSize=l),u!==void 0&&(p.numBins=u),d!==void 0&&(p.maxBins=d),f!==void 0&&(p.minBins=f);try{o&&p.setTreeletConfig(o),s&&p.setReinsertionConfig(s);let e=a?e=>{self.postMessage({progress:e})}:null,l=n===void 0?new Float32Array(t):new Float32Array(t,n,r/4),u=c?new Float32Array(c):null,d=p.buildSync(l,i,e,u),f=performance.now(),m=p.flattenBVH(d),h=performance.now()-f;E.debug(`flatten ${_.ms(h)} (${_.mb(m.byteLength)})`);let g=p.originalToBvhMap||null;if(c){let e=[m.buffer];g&&e.push(g.buffer),self.postMessage({bvhData:m,originalToBvh:g,triangleCount:l.length/32,treeletStats:p.splitStats},e)}else{let e=p.reorderedTriangleData,t=e.byteLength/128,n=[m.buffer,e.buffer];g&&n.push(g.buffer),self.postMessage({bvhData:m,triangles:e,originalToBvh:g,triangleCount:t,treeletStats:p.splitStats},n)}}catch(e){E.error(`build failed:`,e),self.postMessage({error:e.message})}}", mc = typeof self < "u" && self.Blob && new Blob(["URL.revokeObjectURL(import.meta.url);", pc], { type: "text/javascript;charset=utf-8" });
|
|
5541
5546
|
function hc(e) {
|
|
5542
5547
|
let t;
|
|
5543
5548
|
try {
|
|
@@ -5558,7 +5563,7 @@ function hc(e) {
|
|
|
5558
5563
|
}
|
|
5559
5564
|
//#endregion
|
|
5560
5565
|
//#region src/Processor/Workers/BVHSubtreeWorker.js?worker&inline
|
|
5561
|
-
var gc = "var e=class{constructor(e,t){this.traversalCost=e,this.intersectionCost=t,this.maxTreeletLeaves=7,this.minImprovement=.02,this.topologyCache=new Map;for(let e=3;e<=this.maxTreeletLeaves;e++)this.topologyCache.set(e,this.generateTopologies(e));this.stats={treeletsProcessed:0,treeletsImproved:0,totalSAHImprovement:0,averageSAHImprovement:0,optimizationTime:0}}generateTopologies(e){if(e===1)return[0];if(e===2)return[[0,1]];let t=[];for(let n=1;n<e;n++){let r=this.generateTopologies(n),i=this.generateTopologies(e-n);for(let e of r)for(let r of i)t.push([e,this.offsetTopology(r,n)])}return t}offsetTopology(e,t){return typeof e==`number`?e+t:[this.offsetTopology(e[0],t),this.offsetTopology(e[1],t)]}optimizeBVH(e){let t=performance.now();this.stats={treeletsProcessed:0,treeletsImproved:0,totalSAHImprovement:0,averageSAHImprovement:0,optimizationTime:0};let n=this.identifyTreeletRoots(e);for(let e=0;e<n.length;e++){if(performance.now()-t>3e4){console.warn(`TreeletOptimizer: timeout after ${e}/${n.length} treelets`);break}this.optimizeTreelet(n[e])}return this.stats.optimizationTime=performance.now()-t,this.stats.averageSAHImprovement=this.stats.treeletsProcessed>0?this.stats.totalSAHImprovement/this.stats.treeletsProcessed:0,e}identifyTreeletRoots(e){let t=[],n=new Set,r=[{node:e,visited:!1}];for(;r.length>0;){let e=r[r.length-1];if(e.visited){r.pop();let i=e.node;if(i.triangleCount>0||n.has(i))continue;let a=this.countLeaves(i);a>=3&&a<=this.maxTreeletLeaves&&(t.push(i),this.markSubtree(i,n))}else{e.visited=!0;let t=e.node;if(t.triangleCount>0)continue;t.rightChild&&r.push({node:t.rightChild,visited:!1}),t.leftChild&&r.push({node:t.leftChild,visited:!1})}}return t}countLeaves(e){return e?e.triangleCount>0?1:this.countLeaves(e.leftChild)+this.countLeaves(e.rightChild):0}markSubtree(e,t){e&&(t.add(e),!(e.triangleCount>0)&&(this.markSubtree(e.leftChild,t),this.markSubtree(e.rightChild,t)))}optimizeTreelet(e){let t=[];this.extractLeaves(e,t);let n=t.length;if(n<3||n>this.maxTreeletLeaves)return;this.stats.treeletsProcessed++;let r=this.evaluateSubtreeSAH(e),i=this.topologyCache.get(n);if(!i||i.length===0)return;let a=r,o=null,s=null;if(n<=5){let e=this.generatePermutations(n);for(let n of i)for(let r of e){let e=this.evaluateTopology(n,t,r);e<a&&(a=e,o=n,s=r)}}else{let e=Array.from({length:n},(e,t)=>t);for(let n of i){let r=this.evaluateTopology(n,t,e);r<a&&(a=r,o=n,s=e);let i=this.greedySwapOptimize(n,t,e,r);i.cost<a&&(a=i.cost,o=n,s=i.perm)}}let c=(r-a)/r;o&&c>this.minImprovement&&(this.reconstructTreelet(e,o,t,s),this.stats.treeletsImproved++,this.stats.totalSAHImprovement+=c)}extractLeaves(e,t){if(e){if(e.triangleCount>0){t.push({minX:e.minX,minY:e.minY,minZ:e.minZ,maxX:e.maxX,maxY:e.maxY,maxZ:e.maxZ,triangleOffset:e.triangleOffset,triangleCount:e.triangleCount});return}this.extractLeaves(e.leftChild,t),this.extractLeaves(e.rightChild,t)}}evaluateSubtreeSAH(e){if(!e)return 0;if(e.triangleCount>0)return this.surfaceAreaFlat(e.minX,e.minY,e.minZ,e.maxX,e.maxY,e.maxZ)*e.triangleCount*this.intersectionCost;let t=this.evaluateSubtreeSAH(e.leftChild),n=this.evaluateSubtreeSAH(e.rightChild);return this.surfaceAreaFlat(e.minX,e.minY,e.minZ,e.maxX,e.maxY,e.maxZ)*this.traversalCost+t+n}evaluateTopology(e,t,n){return this.evalTopoRecursive(e,t,n).cost}evalTopoRecursive(e,t,n){if(typeof e==`number`){let r=t[n[e]];return{cost:this.surfaceAreaFlat(r.minX,r.minY,r.minZ,r.maxX,r.maxY,r.maxZ)*r.triangleCount*this.intersectionCost,minX:r.minX,minY:r.minY,minZ:r.minZ,maxX:r.maxX,maxY:r.maxY,maxZ:r.maxZ}}let r=this.evalTopoRecursive(e[0],t,n),i=this.evalTopoRecursive(e[1],t,n),a=Math.min(r.minX,i.minX),o=Math.min(r.minY,i.minY),s=Math.min(r.minZ,i.minZ),c=Math.max(r.maxX,i.maxX),l=Math.max(r.maxY,i.maxY),u=Math.max(r.maxZ,i.maxZ);return{cost:this.surfaceAreaFlat(a,o,s,c,l,u)*this.traversalCost+r.cost+i.cost,minX:a,minY:o,minZ:s,maxX:c,maxY:l,maxZ:u}}surfaceAreaFlat(e,t,n,r,i,a){let o=r-e,s=i-t,c=a-n;return 2*(o*s+s*c+c*o)}generatePermutations(e){let t=[],n=Array.from({length:e},(e,t)=>t),r=i=>{if(i===e){t.push([...n]);return}for(let t=i;t<e;t++)[n[i],n[t]]=[n[t],n[i]],r(i+1),[n[i],n[t]]=[n[t],n[i]]};return r(0),t}greedySwapOptimize(e,t,n,r){let i=[...n],a=r,o=!0;for(;o;){o=!1;for(let n=0;n<i.length-1;n++)for(let r=n+1;r<i.length;r++){[i[n],i[r]]=[i[r],i[n]];let s=this.evaluateTopology(e,t,i);s<a?(a=s,o=!0):[i[n],i[r]]=[i[r],i[n]]}}return{perm:i,cost:a}}reconstructTreelet(e,t,n,r){let i=this.buildSubtree(t,n,r);e.minX=i.minX,e.minY=i.minY,e.minZ=i.minZ,e.maxX=i.maxX,e.maxY=i.maxY,e.maxZ=i.maxZ,e.leftChild=i.leftChild,e.rightChild=i.rightChild,e.triangleOffset=i.triangleOffset,e.triangleCount=i.triangleCount}buildSubtree(e,n,r){if(typeof e==`number`){let i=n[r[e]],a=new t;return a.minX=i.minX,a.minY=i.minY,a.minZ=i.minZ,a.maxX=i.maxX,a.maxY=i.maxY,a.maxZ=i.maxZ,a.triangleOffset=i.triangleOffset,a.triangleCount=i.triangleCount,a}let i=this.buildSubtree(e[0],n,r),a=this.buildSubtree(e[1],n,r),o=new t;return o.leftChild=i,o.rightChild=a,o.minX=Math.min(i.minX,a.minX),o.minY=Math.min(i.minY,a.minY),o.minZ=Math.min(i.minZ,a.minZ),o.maxX=Math.max(i.maxX,a.maxX),o.maxY=Math.max(i.maxY,a.maxY),o.maxZ=Math.max(i.maxZ,a.maxZ),o}setTreeletSize(e){this.maxTreeletLeaves=Math.max(3,Math.min(7,e));for(let e=3;e<=this.maxTreeletLeaves;e++)this.topologyCache.has(e)||this.topologyCache.set(e,this.generateTopologies(e))}setMinImprovement(e){this.minImprovement=Math.max(.001,e)}setMaxTreelets(){}getStatistics(){return{...this.stats}}},t=class{constructor(){this.minX=0,this.minY=0,this.minZ=0,this.maxX=0,this.maxY=0,this.maxZ=0,this.leftChild=null,this.rightChild=null,this.triangleOffset=0,this.triangleCount=0}},n=class{constructor(e,t){this.traversalCost=e,this.intersectionCost=t,this.batchSizeRatio=.02,this.maxIterations=2,this.timeBudgetMs=15e3,this.stats={reinsertionsApplied:0,iterations:0,timeMs:0}}setBatchSizeRatio(e){this.batchSizeRatio=Math.max(.005,Math.min(.1,e))}setMaxIterations(e){this.maxIterations=Math.max(1,Math.min(5,e))}getStatistics(){return{...this.stats}}surfaceArea(e){let t=e.maxX-e.minX,n=e.maxY-e.minY,r=e.maxZ-e.minZ;return t*n+n*r+r*t}buildParentMap(e){let t=new Map;t.set(e,{parent:null,isLeft:!1});let n=[e];for(;n.length>0;){let e=n.pop();e.triangleCount>0||(e.leftChild&&(t.set(e.leftChild,{parent:e,isLeft:!0}),n.push(e.leftChild)),e.rightChild&&(t.set(e.rightChild,{parent:e,isLeft:!1}),n.push(e.rightChild)))}return t}findCandidates(e,t,n){let r=[],i=[e];for(;i.length>0;){let a=i.pop();if(a!==e&&n.get(a).parent!==e){let e=this.surfaceArea(a);r.length<t?(r.push({node:a,cost:e}),r.length===t&&this._heapify(r)):e>r[0].cost&&(r[0]={node:a,cost:e},this._siftDown(r,0))}a.triangleCount===0&&(a.leftChild&&i.push(a.leftChild),a.rightChild&&i.push(a.rightChild))}return r}_heapify(e){for(let t=(e.length>>1)-1;t>=0;t--)this._siftDown(e,t)}_siftDown(e,t){let n=e.length;for(;;){let r=t,i=2*t+1,a=2*t+2;if(i<n&&e[i].cost<e[r].cost&&(r=i),a<n&&e[a].cost<e[r].cost&&(r=a),r===t)break;let o=e[t];e[t]=e[r],e[r]=o,t=r}}findReinsertion(e,t,n){let r=n.get(e),i=r.parent;if(!i)return null;let a=r.isLeft?i.rightChild:i.leftChild,o=this.surfaceArea(e),s=this.surfaceArea(i),c=null,l=0,u=s,d=a.minX,f=a.minY,p=a.minZ,m=a.maxX,h=a.maxY,g=a.maxZ,_=a,v=i,y=[];do{for(y.length=0,y.push(u,_);y.length>0;){let t=y.pop(),n=y.pop();if(n-o<=l)continue;let r=Math.min(t.minX,e.minX),i=Math.min(t.minY,e.minY),a=Math.min(t.minZ,e.minZ),s=Math.max(t.maxX,e.maxX),u=Math.max(t.maxY,e.maxY),d=Math.max(t.maxZ,e.maxZ),f=s-r,p=u-i,m=d-a,h=n-(f*p+p*m+m*f);if(h>l&&(c=t,l=h),t.triangleCount===0&&t.leftChild&&t.rightChild){let e=h+this.surfaceArea(t);y.push(e,t.leftChild),y.push(e,t.rightChild)}}let t=n.get(v);if(!t||t.parent===null)break;if(v!==i){d=Math.min(d,_.minX),f=Math.min(f,_.minY),p=Math.min(p,_.minZ),m=Math.max(m,_.maxX),h=Math.max(h,_.maxY),g=Math.max(g,_.maxZ);let e=m-d,t=h-f,n=g-p,r=e*t+t*n+n*e;u+=this.surfaceArea(v)-r}let r=t.parent;_=t.isLeft?r.rightChild:r.leftChild,v=r}while(n.get(v).parent!==null);return c===a||c===i?null:c?{from:e,to:c,areaDiff:l}:null}getConflicts(e,t,n){let r=n.get(e);return[t,e,r.isLeft?r.parent.rightChild:r.parent.leftChild,n.get(t).parent,r.parent]}reinsertNode(e,t,n){let r=n.get(e),i=r.parent,a=r.isLeft?i.rightChild:i.leftChild,o=n.get(i),s=o.parent,c=n.get(t),l=c.parent;o.isLeft?s.leftChild=a:s.rightChild=a,i.leftChild=e,i.rightChild=t,i.triangleOffset=0,i.triangleCount=0,i.minX=Math.min(e.minX,t.minX),i.minY=Math.min(e.minY,t.minY),i.minZ=Math.min(e.minZ,t.minZ),i.maxX=Math.max(e.maxX,t.maxX),i.maxY=Math.max(e.maxY,t.maxY),i.maxZ=Math.max(e.maxZ,t.maxZ),c.isLeft?l.leftChild=i:l.rightChild=i,n.set(a,{parent:s,isLeft:o.isLeft}),n.set(i,{parent:l,isLeft:c.isLeft}),n.set(e,{parent:i,isLeft:!0}),n.set(t,{parent:i,isLeft:!1}),this.refitFrom(s,n),this.refitFrom(l,n)}refitFrom(e,t){let n=e;for(;n;){if(n.triangleCount===0&&n.leftChild&&n.rightChild){let e=n.leftChild,t=n.rightChild;n.minX=Math.min(e.minX,t.minX),n.minY=Math.min(e.minY,t.minY),n.minZ=Math.min(e.minZ,t.minZ),n.maxX=Math.max(e.maxX,t.maxX),n.maxY=Math.max(e.maxY,t.maxY),n.maxZ=Math.max(e.maxZ,t.maxZ)}let e=t.get(n);n=e?e.parent:null}}optimizeBVH(e,t){let n=performance.now();this.stats={reinsertionsApplied:0,iterations:0,timeMs:0};for(let r=0;r<this.maxIterations&&!(performance.now()-n>this.timeBudgetMs);r++){let i=this.buildParentMap(e),a=i.size,o=Math.max(1,Math.floor(a*this.batchSizeRatio));t&&t(`Reinsertion iter ${r+1}/${this.maxIterations}: selecting ${o} candidates`);let s=this.findCandidates(e,o,i),c=[];for(let t=0;t<s.length&&!(performance.now()-n>this.timeBudgetMs);t++){let n=this.findReinsertion(s[t].node,e,i);n&&n.areaDiff>0&&c.push(n)}c.sort((e,t)=>t.areaDiff-e.areaDiff);let l=new Set,u=0;for(let e of c){let t=this.getConflicts(e.from,e.to,i);if(!t.some(e=>l.has(e))){for(let e of t)l.add(e);this.reinsertNode(e.from,e.to,i),u++}}if(this.stats.reinsertionsApplied+=u,this.stats.iterations=r+1,t&&t(`Reinsertion iter ${r+1}: applied ${u} reinsertions`),u===0)break}return this.stats.timeMs=performance.now()-n,this.stats}};const r={silent:0,error:1,warn:2,info:3,debug:4},i=`info`,a=`rayzeeLogLevel`,o=`rayzeeLogNamespaces`,s=`color:#7c8494`,c=`color:inherit`;let l=null,u=null;function d(e){try{return globalThis.localStorage?.getItem(e)??null}catch{return null}}function f(e,t){try{t===null?globalThis.localStorage?.removeItem(e):globalThis.localStorage?.setItem(e,t)}catch{}}function p(){if(l!==null)return l;let e=globalThis.__RAYZEE_LOG_LEVEL__;return e!==void 0&&e in r?(l=r[e],l):(l=r[d(a)]??r[i],l)}function m(){if(u!==null)return u;let e=globalThis.__RAYZEE_LOG_NS__??d(o);return u=e?String(e).split(`,`).map(e=>e.trim()).filter(Boolean):[],u}function h(e,t){if(t<r.debug)return!0;let n=m();return n.length===0||n.some(t=>e===t||e.startsWith(`${t}:`))}function g(e,t,n){if(e>p()||!h(t,e))return;let i=e===r.error?console.error:e===r.warn?console.warn:console.log,a=`[${t}]`;typeof n[0]==`string`?i(`%c${a}%c ${n[0]}`,s,c,...n.slice(1)):i(`%c${a}`,s,...n)}const _={n:e=>Number(e).toLocaleString(`en-US`),ms:e=>e<10?`${Number(e).toFixed(1)} ms`:`${Math.round(e)} ms`,mb:e=>{let t=e/(1024*1024);return t<10?`${t.toFixed(1)} MB`:`${Math.round(t)} MB`},px:(e,t)=>`${e}×${t}`,count:(e,t,n=`${t}s`)=>`${_.n(e)} ${Number(e)===1?t:n}`,list:e=>e.filter(Boolean).join(` · `)},v={levels:r,setLevel(e){return e in r?(globalThis.__RAYZEE_LOG_LEVEL__=e,l=r[e],f(a,e===i?null:e),e):(console.warn(`[log] unknown level '${e}' — expected one of ${Object.keys(r).join(`, `)}`),this.getLevel())},getLevel(){let e=p();return Object.keys(r).find(t=>r[t]===e)},isEnabled(e){return(r[e]??r.debug)<=p()},only(...e){let t=e.flat().filter(Boolean);return u=t,globalThis.__RAYZEE_LOG_NS__=t.join(`,`),f(o,t.length?t.join(`,`):null),t.length&&this.setLevel(`debug`),t},refresh(){return l=null,u=null,this.getLevel()}};function y(e){return{namespace:e,error:(...t)=>g(r.error,e,t),warn:(...t)=>g(r.warn,e,t),info:(...t)=>g(r.info,e,t),debug:(...t)=>g(r.debug,e,t),isEnabled:e=>v.isEnabled(e),summary(t,n=[]){let i=n.filter(Boolean);if(i.length===0||!console.groupCollapsed){g(r.info,e,[t]),i.forEach(t=>g(r.debug,e,[t]));return}r.info>p()||((p()>=r.debug&&console.group?console.group:console.groupCollapsed)(`%c[${e}]%c ${t}`,s,c),i.forEach(e=>console.log(e)),console.groupEnd())}}}const b=y(`bvh`),x={FLOATS_PER_TRIANGLE:32,POSITION_A_OFFSET:0,POSITION_B_OFFSET:4,POSITION_C_OFFSET:8,NORMAL_A_OFFSET:12,NORMAL_B_OFFSET:16,NORMAL_C_OFFSET:20,UV_AB_OFFSET:24,UV_C_MAT_OFFSET:28},S=x.FLOATS_PER_TRIANGLE;var C=class{constructor(){this.minX=0,this.minY=0,this.minZ=0,this.maxX=0,this.maxY=0,this.maxZ=0,this.leftChild=null,this.rightChild=null,this.triangleOffset=0,this.triangleCount=0}},w=class{constructor(){this.useWorker=!0,this.maxLeafSize=8,this.numBins=32,this.minBins=8,this.maxBins=64,this.totalNodes=0,this.processedTriangles=0,this.totalTriangles=0,this.lastProgressUpdate=0,this.progressUpdateInterval=100,this.traversalCost=1,this.intersectionCost=2.5,this.useMortonCodes=!0,this.mortonBits=10,this.mortonClusterThreshold=128,this.enableObjectMedianFallback=!0,this.enableSpatialMedianFallback=!0,this.splitStats={sahSplits:0,objectMedianSplits:0,spatialMedianSplits:0,failedSplits:0,avgBinsUsed:0,totalSplitAttempts:0,mortonSortTime:0,totalBuildTime:0,treeletOptimizationTime:0,treeletsProcessed:0,treeletsImproved:0,averageSAHImprovement:0,reinsertionOptimizationTime:0,reinsertionsApplied:0,reinsertionIterations:0},this.enableTreeletOptimization=!0,this.treeletSize=5,this.treeletOptimizationPasses=1,this.treeletMinImprovement=.02,this.maxTreeletDepth=3,this.maxTreeletsPerScene=20,this.treeletComplexityThreshold=5e4,this.enableReinsertionOptimization=!0,this.reinsertionBatchSizeRatio=.02,this.reinsertionMaxIterations=2,this.initializeBinArrays(),this._partResult={mid:0,lMinX:0,lMinY:0,lMinZ:0,lMaxX:0,lMaxY:0,lMaxZ:0,rMinX:0,rMinY:0,rMinZ:0,rMaxX:0,rMaxY:0,rMaxZ:0},this.centroids=null,this.bMin=null,this.bMax=null,this.indices=null,this.mortonCodes=null,this.triangles=null,this.reorderedTriangleData=null}initializeBinArrays(){let e=this.maxBins;this.binBoundsMin=new Float32Array(e*3),this.binBoundsMax=new Float32Array(e*3),this.binCounts=new Uint32Array(e),this.leftPrefixMin=new Float32Array(e*3),this.leftPrefixMax=new Float32Array(e*3),this.leftPrefixCount=new Uint32Array(e),this.rightPrefixMin=new Float32Array(e*3),this.rightPrefixMax=new Float32Array(e*3),this.rightPrefixCount=new Uint32Array(e)}getOptimalBinCount(e){return e<=16?this.minBins:e<=64?16:e<=256?32:e<=1024?48:this.maxBins}setAdaptiveBinConfig(e){e.minBins!==void 0&&(this.minBins=Math.max(4,e.minBins)),e.maxBins!==void 0&&(this.maxBins=Math.min(128,e.maxBins)),e.baseBins!==void 0&&(this.numBins=e.baseBins),e.maxBins!==void 0&&this.initializeBinArrays()}setMortonConfig(e){e.enabled!==void 0&&(this.useMortonCodes=e.enabled),e.bits!==void 0&&(this.mortonBits=Math.max(6,Math.min(10,e.bits))),e.threshold!==void 0&&(this.mortonClusterThreshold=Math.max(16,e.threshold))}setFallbackConfig(e){e.objectMedian!==void 0&&(this.enableObjectMedianFallback=e.objectMedian),e.spatialMedian!==void 0&&(this.enableSpatialMedianFallback=e.spatialMedian)}setTreeletConfig(e){e.enabled!==void 0&&(this.enableTreeletOptimization=e.enabled),e.size!==void 0&&(this.treeletSize=Math.max(3,Math.min(12,e.size))),e.passes!==void 0&&(this.treeletOptimizationPasses=Math.max(1,Math.min(3,e.passes))),e.minImprovement!==void 0&&(this.treeletMinImprovement=Math.max(.001,e.minImprovement))}disableTreeletOptimization(){this.enableTreeletOptimization=!1}setReinsertionConfig(e){e.enabled!==void 0&&(this.enableReinsertionOptimization=e.enabled),e.batchSizeRatio!==void 0&&(this.reinsertionBatchSizeRatio=Math.max(.005,Math.min(.1,e.batchSizeRatio))),e.maxIterations!==void 0&&(this.reinsertionMaxIterations=Math.max(1,Math.min(5,e.maxIterations)))}initializeTriangleArrays(){let e=this.totalTriangles,t=this.triangles,n=x.POSITION_A_OFFSET,r=x.POSITION_B_OFFSET,i=x.POSITION_C_OFFSET;for(let a=0;a<e;a++){let e=a*S,o=t[e+n],s=t[e+n+1],c=t[e+n+2],l=t[e+r],u=t[e+r+1],d=t[e+r+2],f=t[e+i],p=t[e+i+1],m=t[e+i+2],h=a*3;this.centroids[h]=(o+l+f)/3,this.centroids[h+1]=(s+u+p)/3,this.centroids[h+2]=(c+d+m)/3,this.bMin[h]=o<l?o<f?o:f:l<f?l:f,this.bMin[h+1]=s<u?s<p?s:p:u<p?u:p,this.bMin[h+2]=c<d?c<m?c:m:d<m?d:m,this.bMax[h]=o>l?o>f?o:f:l>f?l:f,this.bMax[h+1]=s>u?s>p?s:p:u>p?u:p,this.bMax[h+2]=c>d?c>m?c:m:d>m?d:m,this.indices[a]=a}}expandBits(e){return e=e*65537&4278190335,e=e*257&251719695,e=e*17&3272356035,e=e*5&1227133513,e}morton3D(e,t,n){return(this.expandBits(n)<<2)+(this.expandBits(t)<<1)+this.expandBits(e)}computeMortonCodeForIndex(e,t,n,r,i,a,o){let s=this.centroids,c=e*3,l=(1<<this.mortonBits)-1,u=i>0?(s[c]-t)/i:0,d=a>0?(s[c+1]-n)/a:0,f=o>0?(s[c+2]-r)/o:0,p=Math.max(0,Math.min(l,Math.floor(u*l))),m=Math.max(0,Math.min(l,Math.floor(d*l))),h=Math.max(0,Math.min(l,Math.floor(f*l)));return this.morton3D(p,m,h)}sortTrianglesByMortonCode(){let e=this.totalTriangles;if(!this.useMortonCodes||e<this.mortonClusterThreshold)return;let t=performance.now(),n=this.centroids,r=this.indices,i=1/0,a=1/0,o=1/0,s=-1/0,c=-1/0,l=-1/0;for(let t=0;t<e;t++){let e=r[t]*3,u=n[e],d=n[e+1],f=n[e+2];u<i&&(i=u),d<a&&(a=d),f<o&&(o=f),u>s&&(s=u),d>c&&(c=d),f>l&&(l=f)}let u=s-i,d=c-a,f=l-o,p=this.mortonCodes,m=(1<<this.mortonBits)-1,h=u>0?m/u:0,g=d>0?m/d:0,_=f>0?m/f:0;for(let t=0;t<e;t++){let e=r[t],s=e*3,c=(n[s]-i)*h,l=(n[s+1]-a)*g,u=(n[s+2]-o)*_;c=c<0?0:(c>m?m:c)|0,l=l<0?0:(l>m?m:l)|0,u=u<0?0:(u>m?m:u)|0,c=c*65537&4278190335,c=c*257&251719695,c=c*17&3272356035,c=c*5&1227133513,l=l*65537&4278190335,l=l*257&251719695,l=l*17&3272356035,l=l*5&1227133513,u=u*65537&4278190335,u=u*257&251719695,u=u*17&3272356035,u=u*5&1227133513,p[e]=(u<<2)+(l<<1)+c}let v=new Uint32Array(e),y=new Uint32Array(256);for(let t=0;t<32;t+=8){y.fill(0);for(let n=0;n<e;n++)y[p[r[n]]>>>t&255]++;let n=0;for(let e=0;e<256;e++){let t=y[e];y[e]=n,n+=t}for(let n=0;n<e;n++){let e=p[r[n]]>>>t&255;v[y[e]++]=r[n]}r.set(v)}this.splitStats.mortonSortTime+=performance.now()-t}build(e,t=30,n=null){if(this.totalTriangles=e.byteLength/(S*4),this.processedTriangles=0,this.lastProgressUpdate=performance.now(),!(this.useWorker&&null))return new Promise(r=>{r(this._buildSyncAndFlatten(e,t,n))})}_buildSyncAndFlatten(e,t,n){let r=this.buildSync(e,t,n);return{bvhData:this.flattenBVH(r),bvhRoot:!0,reorderedTriangles:this.reorderedTriangleData||null,originalToBvh:this.originalToBvhMap||null}}buildSync(t,r=30,i=null,a=null){let o=performance.now();this.totalNodes=0,this.processedTriangles=0,this.triangles=t,this.totalTriangles=t.byteLength/(S*4),this.lastProgressUpdate=performance.now(),this.splitStats={sahSplits:0,objectMedianSplits:0,spatialMedianSplits:0,failedSplits:0,avgBinsUsed:0,totalSplitAttempts:0,mortonSortTime:0,totalBuildTime:0,treeletOptimizationTime:0,treeletsProcessed:0,treeletsImproved:0,averageSAHImprovement:0,reinsertionOptimizationTime:0,reinsertionsApplied:0,reinsertionIterations:0,saOrderTime:0,initTime:0,sahBuildTime:0,reorderTime:0};let s=this.totalTriangles,c=performance.now();this.centroids=new Float32Array(s*3),this.bMin=new Float32Array(s*3),this.bMax=new Float32Array(s*3),this.indices=new Uint32Array(s),this.mortonCodes=new Uint32Array(s),this.initializeTriangleArrays(),this.splitStats.initTime=performance.now()-c,this.sortTrianglesByMortonCode();let l=performance.now(),u=this.buildNodeRecursive(0,s,r,i);if(this.splitStats.sahBuildTime=performance.now()-l,this.enableTreeletOptimization&&this.totalTriangles>1e3){let t=this.totalTriangles>this.treeletComplexityThreshold,n=t?3:this.treeletSize,r=t?10:this.maxTreeletsPerScene,a=new e(this.traversalCost,this.intersectionCost);a.setTreeletSize(n),a.setMinImprovement(this.treeletMinImprovement),a.setMaxTreelets(r);let o=performance.now();for(let e=0;e<this.treeletOptimizationPasses;e++){let t=i?t=>{i(`Treelet optimization pass ${e+1}/${this.treeletOptimizationPasses}: ${t}`)}:null;try{a.optimizeBVH(u,t)}catch(t){b.error(`treelet optimizer failed in pass ${e+1}:`,t);break}let n=a.getStatistics(),r=performance.now()-o;if(n.treeletsImproved===0&&e>0||r>15e3)break}let s=performance.now()-o;this.splitStats.treeletOptimizationTime=s;let c=a.getStatistics();this.splitStats.treeletsProcessed=c.treeletsProcessed,this.splitStats.treeletsImproved=c.treeletsImproved,this.splitStats.averageSAHImprovement=c.averageSAHImprovement}if(this.enableReinsertionOptimization&&this.totalTriangles>1e3){let e=new n(this.traversalCost,this.intersectionCost);e.setBatchSizeRatio(this.reinsertionBatchSizeRatio),e.setMaxIterations(this.reinsertionMaxIterations);let t=i?e=>{i(e)}:null;try{e.optimizeBVH(u,t)}catch(e){b.error(`reinsertion optimizer failed:`,e)}let r=e.getStatistics();this.splitStats.reinsertionOptimizationTime=r.timeMs,this.splitStats.reinsertionsApplied=r.reinsertionsApplied,this.splitStats.reinsertionIterations=r.iterations}let d=performance.now();this.applySAOrdering(u),this.splitStats.saOrderTime=performance.now()-d;let f=performance.now(),p=this.triangles,m=a||new Float32Array(s*S);for(let e=0;e<s;e++){let t=this.indices[e]*S,n=e*S;m.set(p.subarray(t,t+S),n)}this.reorderedTriangleData=m;let h=new Uint32Array(s);for(let e=0;e<s;e++)h[this.indices[e]]=e;this.originalToBvhMap=h,this.splitStats.reorderTime=performance.now()-f,this.splitStats.totalBuildTime=performance.now()-o;let g=this.splitStats.totalBuildTime,v=this.splitStats;return b.debug(`${_.n(s)} tris → ${_.n(this.totalNodes)} nodes in ${_.ms(g)} | SAH ${v.sahSplits} objMed ${v.objectMedianSplits} spatMed ${v.spatialMedianSplits} failed ${v.failedSplits}`+(v.treeletsProcessed?` | treelets ${v.treeletsImproved}/${v.treeletsProcessed} improved`:``)+(v.reinsertionsApplied?` | reinsertions ${v.reinsertionsApplied}`:``)),i&&i(100),this.centroids=null,this.bMin=null,this.bMax=null,this.mortonCodes=null,u}updateProgress(e,t){if(!t)return;this.processedTriangles+=e;let n=performance.now();n-this.lastProgressUpdate<this.progressUpdateInterval||(this.lastProgressUpdate=n,t(Math.min(Math.floor(this.processedTriangles/this.totalTriangles*100),99)))}buildNodeRecursiveToDepth(e,t,n,r,i,a,o,s,c,l,u){let d=new C;this.totalNodes++;let f=t-e;if(a===void 0?this.updateNodeBounds(d,e,t):(d.minX=a,d.minY=o,d.minZ=s,d.maxX=c,d.maxY=l,d.maxZ=u),f<=this.maxLeafSize||n<=0)return d.triangleOffset=e,d.triangleCount=f,this.updateProgress(f,i),d;if(r<=0&&f>this.maxLeafSize*16){let r=this.frontierTasks.length;return d.triangleOffset=e,d.triangleCount=f,d.isFrontier=!0,d.frontierTaskId=r,this.frontierTasks.push({taskId:r,start:e,end:t,depth:n,preMinX:d.minX,preMinY:d.minY,preMinZ:d.minZ,preMaxX:d.maxX,preMaxY:d.maxY,preMaxZ:d.maxZ}),d}let p=this.findBestSplitPositionSAH(e,t,d);if(!p.success){if(this.splitStats.failedSplits++,r>0||f<=this.maxLeafSize*16)return d.triangleOffset=e,d.triangleCount=f,this.updateProgress(f,i),d;let a=this.frontierTasks.length;return d.triangleOffset=e,d.triangleCount=f,d.isFrontier=!0,d.frontierTaskId=a,this.frontierTasks.push({taskId:a,start:e,end:t,depth:n,preMinX:d.minX,preMinY:d.minY,preMinZ:d.minZ,preMaxX:d.maxX,preMaxY:d.maxY,preMaxZ:d.maxZ}),d}p.method===`SAH`?this.splitStats.sahSplits++:p.method===`object_median`?this.splitStats.objectMedianSplits++:p.method===`spatial_median`&&this.splitStats.spatialMedianSplits++,this.partitionWithBounds(e,t,p.axis,p.pos);let m=this._partResult,h=m.mid,g=m.lMinX,_=m.lMinY,v=m.lMinZ,y=m.lMaxX,b=m.lMaxY,x=m.lMaxZ,S=m.rMinX,w=m.rMinY,T=m.rMinZ,E=m.rMaxX,D=m.rMaxY,O=m.rMaxZ;return h===e||h===t?(d.triangleOffset=e,d.triangleCount=f,this.updateProgress(f,i),d):(d.leftChild=this.buildNodeRecursiveToDepth(e,h,n-1,r-1,i,g,_,v,y,b,x),d.rightChild=this.buildNodeRecursiveToDepth(h,t,n-1,r-1,i,S,w,T,E,D,O),d)}buildNodeRecursive(e,t,n,r,i,a,o,s,c,l){let u=new C;this.totalNodes++;let d=t-e;if(i===void 0?this.updateNodeBounds(u,e,t):(u.minX=i,u.minY=a,u.minZ=o,u.maxX=s,u.maxY=c,u.maxZ=l),d<=this.maxLeafSize||n<=0)return u.triangleOffset=e,u.triangleCount=d,this.updateProgress(d,r),u;let f=this.findBestSplitPositionSAH(e,t,u);if(!f.success)return this.splitStats.failedSplits++,u.triangleOffset=e,u.triangleCount=d,this.updateProgress(d,r),u;f.method===`SAH`?this.splitStats.sahSplits++:f.method===`object_median`?this.splitStats.objectMedianSplits++:f.method===`spatial_median`&&this.splitStats.spatialMedianSplits++,this.partitionWithBounds(e,t,f.axis,f.pos);let p=this._partResult,m=p.mid,h=p.lMinX,g=p.lMinY,_=p.lMinZ,v=p.lMaxX,y=p.lMaxY,b=p.lMaxZ,x=p.rMinX,S=p.rMinY,w=p.rMinZ,T=p.rMaxX,E=p.rMaxY,D=p.rMaxZ;return m===e||m===t?(u.triangleOffset=e,u.triangleCount=d,this.updateProgress(d,r),u):(u.leftChild=this.buildNodeRecursive(e,m,n-1,r,h,g,_,v,y,b),u.rightChild=this.buildNodeRecursive(m,t,n-1,r,x,S,w,T,E,D),u)}partitionWithBounds(e,t,n,r){let i=this.indices,a=this.centroids,o=this.bMin,s=this.bMax,c=e,l=t-1,u=1/0,d=1/0,f=1/0,p=-1/0,m=-1/0,h=-1/0,g=1/0,_=1/0,v=1/0,y=-1/0,b=-1/0,x=-1/0;for(;c<=l;){let e=i[c],t=e*3;a[t+n]<=r?(o[t]<u&&(u=o[t]),o[t+1]<d&&(d=o[t+1]),o[t+2]<f&&(f=o[t+2]),s[t]>p&&(p=s[t]),s[t+1]>m&&(m=s[t+1]),s[t+2]>h&&(h=s[t+2]),c++):(o[t]<g&&(g=o[t]),o[t+1]<_&&(_=o[t+1]),o[t+2]<v&&(v=o[t+2]),s[t]>y&&(y=s[t]),s[t+1]>b&&(b=s[t+1]),s[t+2]>x&&(x=s[t+2]),i[c]=i[l],i[l]=e,l--)}let S=this._partResult;return S.mid=c,S.lMinX=u,S.lMinY=d,S.lMinZ=f,S.lMaxX=p,S.lMaxY=m,S.lMaxZ=h,S.rMinX=g,S.rMinY=_,S.rMinZ=v,S.rMaxX=y,S.rMaxY=b,S.rMaxZ=x,S}updateNodeBounds(e,t,n){let r=1/0,i=1/0,a=1/0,o=-1/0,s=-1/0,c=-1/0,l=this.indices,u=this.bMin,d=this.bMax;for(let e=t;e<n;e++){let t=l[e]*3;u[t]<r&&(r=u[t]),u[t+1]<i&&(i=u[t+1]),u[t+2]<a&&(a=u[t+2]),d[t]>o&&(o=d[t]),d[t+1]>s&&(s=d[t+1]),d[t+2]>c&&(c=d[t+2])}e.minX=r,e.minY=i,e.minZ=a,e.maxX=o,e.maxY=s,e.maxZ=c}findBestSplitPositionSAH(e,t,n){let r=1/0,i=-1,a=0,o=this.computeSurfaceAreaFlat(n.minX,n.minY,n.minZ,n.maxX,n.maxY,n.maxZ),s=t-e,c=this.intersectionCost*s,l=this.getOptimalBinCount(s);this.splitStats.totalSplitAttempts++,this.splitStats.avgBinsUsed=(this.splitStats.avgBinsUsed*(this.splitStats.totalSplitAttempts-1)+l)/this.splitStats.totalSplitAttempts;let u=this.indices,d=this.centroids,f=this.bMin,p=this.bMax,m=this.binBoundsMin,h=this.binBoundsMax,g=this.binCounts,_=this.leftPrefixMin,v=this.leftPrefixMax,y=this.leftPrefixCount,b=this.rightPrefixMin,x=this.rightPrefixMax,S=this.rightPrefixCount,C=1/0,w=-1/0,T=1/0,E=-1/0,D=1/0,O=-1/0;for(let n=e;n<t;n++){let e=u[n]*3,t=d[e],r=d[e+1],i=d[e+2];t<C&&(C=t),t>w&&(w=t),r<T&&(T=r),r>E&&(E=r),i<D&&(D=i),i>O&&(O=i)}let k=[C,T,D],A=[w,E,O];for(let n=0;n<3;n++){let s=k[n],C=A[n];if(C-s<1e-6)continue;for(let e=0;e<l;e++){g[e]=0;let t=e*3;m[t]=1/0,m[t+1]=1/0,m[t+2]=1/0,h[t]=-1/0,h[t+1]=-1/0,h[t+2]=-1/0}let w=l/(C-s);for(let r=e;r<t;r++){let e=u[r],t=d[e*3+n],i=Math.floor((t-s)*w);i>=l&&(i=l-1),g[i]++;let a=i*3,o=e*3;f[o]<m[a]&&(m[a]=f[o]),f[o+1]<m[a+1]&&(m[a+1]=f[o+1]),f[o+2]<m[a+2]&&(m[a+2]=f[o+2]),p[o]>h[a]&&(h[a]=p[o]),p[o+1]>h[a+1]&&(h[a+1]=p[o+1]),p[o+2]>h[a+2]&&(h[a+2]=p[o+2])}y[0]=g[0],_[0]=m[0],_[1]=m[1],_[2]=m[2],v[0]=h[0],v[1]=h[1],v[2]=h[2];for(let e=1;e<l;e++){let t=e*3,n=(e-1)*3;y[e]=y[e-1]+g[e];let r=_[n],i=m[t],a=_[n+1],o=m[t+1],s=_[n+2],c=m[t+2];_[t]=r<i?r:i,_[t+1]=a<o?a:o,_[t+2]=s<c?s:c;let l=v[n],u=h[t],d=v[n+1],f=h[t+1],p=v[n+2],b=h[t+2];v[t]=l>u?l:u,v[t+1]=d>f?d:f,v[t+2]=p>b?p:b}let T=l-1,E=T*3;S[T]=g[T],b[E]=m[E],b[E+1]=m[E+1],b[E+2]=m[E+2],x[E]=h[E],x[E+1]=h[E+1],x[E+2]=h[E+2];for(let e=T-1;e>=0;e--){let t=e*3,n=(e+1)*3;S[e]=S[e+1]+g[e];let r=b[n],i=m[t],a=b[n+1],o=m[t+1],s=b[n+2],c=m[t+2];b[t]=r<i?r:i,b[t+1]=a<o?a:o,b[t+2]=s<c?s:c;let l=x[n],u=h[t],d=x[n+1],f=h[t+1],p=x[n+2],_=h[t+2];x[t]=l>u?l:u,x[t+1]=d>f?d:f,x[t+2]=p>_?p:_}for(let e=1;e<l;e++){let t=(e-1)*3,u=e*3,d=y[e-1],f=S[e];if(d===0||f===0)continue;let p=v[t]-_[t],m=v[t+1]-_[t+1],h=v[t+2]-_[t+2],g=2*(p*m+m*h+h*p),w=x[u]-b[u],T=x[u+1]-b[u+1],E=x[u+2]-b[u+2],D=2*(w*T+T*E+E*w),O=this.traversalCost+g/o*d*this.intersectionCost+D/o*f*this.intersectionCost;O<r&&O<c&&(r=O,i=n,a=s+(C-s)*e/l)}}return i===-1?this.enableObjectMedianFallback?this.findObjectMedianSplit(e,t):this.enableSpatialMedianFallback?this.findSpatialMedianSplit(e,t):{success:!1,method:`fallbacks_disabled`}:{success:!0,axis:i,pos:a,method:`SAH`,binsUsed:l}}findObjectMedianSplit(e,t){let n=this.indices,r=this.centroids,i=-1,a=-1;for(let o=0;o<3;o++){let s=1/0,c=-1/0;for(let i=e;i<t;i++){let e=r[n[i]*3+o];e<s&&(s=e),e>c&&(c=e)}let l=c-s;l>a&&(a=l,i=o)}if(i===-1||a<1e-10)return this.enableSpatialMedianFallback?this.findSpatialMedianSplit(e,t):{success:!1,method:`object_median_failed`};let o=t-e,s=e+Math.floor(o/2);this.quickselect(e,t,s,i);let c=r[n[s]*3+i],l=!0;for(let e=s+1;e<t;e++)if(r[n[e]*3+i]>c){l=!1;break}if(l){let a=-1/0;for(let t=e;t<s;t++){let e=r[n[t]*3+i];e>a&&(a=e)}if(a<c)c=(a+c)*.5;else return this.enableSpatialMedianFallback?this.findSpatialMedianSplit(e,t):{success:!1,method:`object_median_degenerate`}}return{success:!0,axis:i,pos:c,method:`object_median`}}findSpatialMedianSplit(e,t){let n=this.indices,r=this.centroids,i=this.bMin,a=this.bMax,o=-1,s=-1,c=0,l=0;for(let r=0;r<3;r++){let u=1/0,d=-1/0;for(let o=e;o<t;o++){let e=n[o]*3+r;i[e]<u&&(u=i[e]),a[e]>d&&(d=a[e])}let f=d-u;f>s&&(s=f,o=r,c=u,l=d)}if(o===-1||s<1e-12)return{success:!1,method:`spatial_median_failed`};let u=(c+l)*.5,d=t-e,f=0;for(let i=e;i<t;i++)r[n[i]*3+o]<=u&&f++;if(f===0||f===d){let i=e+Math.floor(d/2);this.quickselect(e,t,i,o);let a=r[n[i]*3+o],s=!0;for(let i=e;i<t;i++)if(r[n[i]*3+o]!==a){s=!1;break}if(s)return{success:!1,method:`spatial_median_degenerate`};let c=-1/0;for(let t=e;t<i;t++){let e=r[n[t]*3+o];e>c&&(c=e)}if(c<a)u=(c+a)*.5;else{let e=1/0;for(let a=i+1;a<t;a++){let t=r[n[a]*3+o];t<e&&(e=t)}u=(a+e)*.5}}return{success:!0,axis:o,pos:u,method:`spatial_median`}}quickselect(e,t,n,r){let i=this.indices,a=this.centroids,o=e,s=t-1;for(;o<s;){let e=o+s>>>1,t=a[i[o]*3+r],c=a[i[e]*3+r],l=a[i[s]*3+r];if(t>c){let t=i[o];i[o]=i[e],i[e]=t}if(t>l){let e=i[o];i[o]=i[s],i[s]=e}if(c>l){let t=i[e];i[e]=i[s],i[s]=t}let u=a[i[e]*3+r],d=o,f=s;for(;d<=f;){for(;a[i[d]*3+r]<u;)d++;for(;a[i[f]*3+r]>u;)f--;if(d<=f){let e=i[d];i[d]=i[f],i[f]=e,d++,f--}}f<n&&(o=d),d>n&&(s=f)}}applySAOrdering(e){if(!e||!e.leftChild)return;let t=[e],n=[];for(;t.length>0;){let e=t.pop();!e.leftChild||!e.rightChild||(n.push(e),t.push(e.leftChild),t.push(e.rightChild))}for(let e=n.length-1;e>=0;e--){let t=n[e],r=t.leftChild,i=t.rightChild,a=r.maxX-r.minX,o=r.maxY-r.minY,s=r.maxZ-r.minZ,c=i.maxX-i.minX,l=i.maxY-i.minY,u=i.maxZ-i.minZ;c*l+l*u+u*c>a*o+o*s+s*a&&(t.leftChild=i,t.rightChild=r)}}flattenBVH(e){let t=[],n=[e];for(;n.length>0;){let e=n.pop();e._flatIndex=t.length,t.push(e),e.rightChild&&n.push(e.rightChild),e.leftChild&&n.push(e.leftChild)}let r=new Float32Array(t.length*16);for(let e=0;e<t.length;e++){let n=t[e],i=e*16;if(n.leftChild){let e=n.leftChild,t=n.rightChild;r[i]=e.minX,r[i+1]=e.minY,r[i+2]=e.minZ,r[i+3]=e._flatIndex,r[i+4]=e.maxX,r[i+5]=e.maxY,r[i+6]=e.maxZ,r[i+7]=t._flatIndex,r[i+8]=t.minX,r[i+9]=t.minY,r[i+10]=t.minZ,r[i+12]=t.maxX,r[i+13]=t.maxY,r[i+14]=t.maxZ}else r[i]=n.triangleOffset,r[i+1]=n.triangleCount,r[i+3]=-1}return r}flattenBVHWithFrontier(e){let t=[],n=[e];for(;n.length>0;){let e=n.pop();e._flatIndex=t.length,t.push(e),e.rightChild&&n.push(e.rightChild),e.leftChild&&n.push(e.leftChild)}let r=new Float32Array(t.length*16),i=[];for(let e=0;e<t.length;e++){let n=t[e],a=e*16;if(n.leftChild){let e=n.leftChild,t=n.rightChild;r[a]=e.minX,r[a+1]=e.minY,r[a+2]=e.minZ,r[a+3]=e._flatIndex,r[a+4]=e.maxX,r[a+5]=e.maxY,r[a+6]=e.maxZ,r[a+7]=t._flatIndex,r[a+8]=t.minX,r[a+9]=t.minY,r[a+10]=t.minZ,r[a+12]=t.maxX,r[a+13]=t.maxY,r[a+14]=t.maxZ}else if(n.isFrontier){let t=n.frontierTaskId;r[a]=n.triangleOffset,r[a+1]=n.triangleCount,r[a+2]=t,r[a+3]=-2,i.push({taskId:t,flatIndex:e})}else r[a]=n.triangleOffset,r[a+1]=n.triangleCount,r[a+3]=-1}return{flatData:r,frontierMap:i,nodeCount:t.length}}assembleParallelBVH(e,t,n,r){let i=[...r].sort((e,t)=>e.taskId-t.taskId),a=t;for(let e=0;e<i.length;e++)a+=i[e].nodeCount;let o=new Float32Array(a*16);o.set(e);let s=new Map;for(let e of n)s.set(e.taskId,e.flatIndex);let c=t;for(let e=0;e<i.length;e++){let t=i[e],n=t.flatData,r=t.nodeCount,a=c*16;o.set(n,a);for(let e=0;e<r;e++){let t=a+e*16;o[t+3]!==-1&&(o[t+3]+=c,o[t+7]+=c)}let l=s.get(t.taskId);if(l!==void 0){let e=l*16,t=a;for(let n=0;n<16;n++)o[e+n]=o[t+n]}c+=r}return o}computeSurfaceAreaFlat(e,t,n,r,i,a){let o=r-e,s=i-t,c=a-n;return 2*(o*s+s*c+c*o)}};self.onmessage=function(t){let{tasks:r,sharedTriangleData:i,sharedCentroids:a,sharedBMin:o,sharedBMax:s,sharedIndices:c,triangleCount:l,maxLeafSize:u,numBins:d,maxBins:f,minBins:p,treeletConfig:m,reinsertionConfig:h,reportProgress:g}=t.data;for(let t=0;t<r.length;t++){let _=r[t];try{let t=new w;t.maxLeafSize=u,t.numBins=d,t.maxBins=f,t.minBins=p,t.triangles=new Float32Array(i),t.centroids=new Float32Array(a),t.bMin=new Float32Array(o),t.bMax=new Float32Array(s),t.indices=new Uint32Array(c),t.totalTriangles=l,t.totalNodes=0,t.processedTriangles=0,t.lastProgressUpdate=performance.now(),t.splitStats={sahSplits:0,objectMedianSplits:0,spatialMedianSplits:0,failedSplits:0,avgBinsUsed:0,totalSplitAttempts:0,mortonSortTime:0,totalBuildTime:0,treeletOptimizationTime:0,treeletsProcessed:0,treeletsImproved:0,averageSAHImprovement:0,initTime:0,sahBuildTime:0,reorderTime:0};let r=g?e=>{self.postMessage({type:`progress`,taskId:_.taskId,progress:e})}:null,v=performance.now(),y=t.buildNodeRecursive(_.start,_.end,_.depth,r,_.preMinX,_.preMinY,_.preMinZ,_.preMaxX,_.preMaxY,_.preMaxZ);if(m&&m.enabled&&_.end-_.start>1e3){let n=_.end-_.start>5e4,r=n?3:m.size||5,i=n?10:20,a=new e(t.traversalCost,t.intersectionCost);a.setTreeletSize(r),a.setMinImprovement(m.minImprovement||.02),a.setMaxTreelets(i);let o=m.passes||1;for(let e=0;e<o;e++)try{a.optimizeBVH(y,null)}catch(t){console.error(`[BVHSubtreeWorker] Treelet pass ${e+1} error:`,t);break}}if(h&&h.enabled&&_.end-_.start>1e3){let e=new n(t.traversalCost,t.intersectionCost);h.batchSizeRatio&&e.setBatchSizeRatio(h.batchSizeRatio),h.maxIterations&&e.setMaxIterations(h.maxIterations);try{e.optimizeBVH(y,null)}catch(e){console.error(`[BVHSubtreeWorker] Reinsertion error:`,e)}}t.applySAOrdering(y);let b=t.flattenBVH(y),x=b.length/16,S=performance.now()-v;console.log(`[BVHSubtreeWorker] Task ${_.taskId}: ${(_.end-_.start).toLocaleString()} triangles, ${x} nodes, ${Math.round(S)}ms`),self.postMessage({type:`subtreeResult`,taskId:_.taskId,flatData:b,nodeCount:x},[b.buffer])}catch(e){console.error(`[BVHSubtreeWorker] Task ${_.taskId} error:`,e),self.postMessage({type:`error`,taskId:_.taskId,error:e.message})}}};", _c = typeof self < "u" && self.Blob && new Blob(["URL.revokeObjectURL(import.meta.url);", gc], { type: "text/javascript;charset=utf-8" });
|
|
5566
|
+
var gc = "var e=class{constructor(e,t){this.traversalCost=e,this.intersectionCost=t,this.maxTreeletLeaves=7,this.minImprovement=.02,this.topologyCache=new Map;for(let e=3;e<=this.maxTreeletLeaves;e++)this.topologyCache.set(e,this.generateTopologies(e));this.stats={treeletsProcessed:0,treeletsImproved:0,totalSAHImprovement:0,averageSAHImprovement:0,optimizationTime:0}}generateTopologies(e){if(e===1)return[0];if(e===2)return[[0,1]];let t=[];for(let n=1;n<e;n++){let r=this.generateTopologies(n),i=this.generateTopologies(e-n);for(let e of r)for(let r of i)t.push([e,this.offsetTopology(r,n)])}return t}offsetTopology(e,t){return typeof e==`number`?e+t:[this.offsetTopology(e[0],t),this.offsetTopology(e[1],t)]}optimizeBVH(e){let t=performance.now();this.stats={treeletsProcessed:0,treeletsImproved:0,totalSAHImprovement:0,averageSAHImprovement:0,optimizationTime:0};let n=this.identifyTreeletRoots(e);for(let e=0;e<n.length;e++){if(performance.now()-t>3e4){console.warn(`TreeletOptimizer: timeout after ${e}/${n.length} treelets`);break}this.optimizeTreelet(n[e])}return this.stats.optimizationTime=performance.now()-t,this.stats.averageSAHImprovement=this.stats.treeletsProcessed>0?this.stats.totalSAHImprovement/this.stats.treeletsProcessed:0,e}identifyTreeletRoots(e){let t=[],n=new Set,r=[{node:e,visited:!1}];for(;r.length>0;){let e=r[r.length-1];if(e.visited){r.pop();let i=e.node;if(i.triangleCount>0||n.has(i))continue;let a=this.countLeaves(i);a>=3&&a<=this.maxTreeletLeaves&&(t.push(i),this.markSubtree(i,n))}else{e.visited=!0;let t=e.node;if(t.triangleCount>0)continue;t.rightChild&&r.push({node:t.rightChild,visited:!1}),t.leftChild&&r.push({node:t.leftChild,visited:!1})}}return t}countLeaves(e){return e?e.triangleCount>0?1:this.countLeaves(e.leftChild)+this.countLeaves(e.rightChild):0}markSubtree(e,t){e&&(t.add(e),!(e.triangleCount>0)&&(this.markSubtree(e.leftChild,t),this.markSubtree(e.rightChild,t)))}optimizeTreelet(e){let t=[];this.extractLeaves(e,t);let n=t.length;if(n<3||n>this.maxTreeletLeaves)return;this.stats.treeletsProcessed++;let r=this.evaluateSubtreeSAH(e),i=this.topologyCache.get(n);if(!i||i.length===0)return;let a=r,o=null,s=null;if(n<=5){let e=this.generatePermutations(n);for(let n of i)for(let r of e){let e=this.evaluateTopology(n,t,r);e<a&&(a=e,o=n,s=r)}}else{let e=Array.from({length:n},(e,t)=>t);for(let n of i){let r=this.evaluateTopology(n,t,e);r<a&&(a=r,o=n,s=e);let i=this.greedySwapOptimize(n,t,e,r);i.cost<a&&(a=i.cost,o=n,s=i.perm)}}let c=(r-a)/r;o&&c>this.minImprovement&&(this.reconstructTreelet(e,o,t,s),this.stats.treeletsImproved++,this.stats.totalSAHImprovement+=c)}extractLeaves(e,t){if(e){if(e.triangleCount>0){t.push({minX:e.minX,minY:e.minY,minZ:e.minZ,maxX:e.maxX,maxY:e.maxY,maxZ:e.maxZ,triangleOffset:e.triangleOffset,triangleCount:e.triangleCount});return}this.extractLeaves(e.leftChild,t),this.extractLeaves(e.rightChild,t)}}evaluateSubtreeSAH(e){if(!e)return 0;if(e.triangleCount>0)return this.surfaceAreaFlat(e.minX,e.minY,e.minZ,e.maxX,e.maxY,e.maxZ)*e.triangleCount*this.intersectionCost;let t=this.evaluateSubtreeSAH(e.leftChild),n=this.evaluateSubtreeSAH(e.rightChild);return this.surfaceAreaFlat(e.minX,e.minY,e.minZ,e.maxX,e.maxY,e.maxZ)*this.traversalCost+t+n}evaluateTopology(e,t,n){return this.evalTopoRecursive(e,t,n).cost}evalTopoRecursive(e,t,n){if(typeof e==`number`){let r=t[n[e]];return{cost:this.surfaceAreaFlat(r.minX,r.minY,r.minZ,r.maxX,r.maxY,r.maxZ)*r.triangleCount*this.intersectionCost,minX:r.minX,minY:r.minY,minZ:r.minZ,maxX:r.maxX,maxY:r.maxY,maxZ:r.maxZ}}let r=this.evalTopoRecursive(e[0],t,n),i=this.evalTopoRecursive(e[1],t,n),a=Math.min(r.minX,i.minX),o=Math.min(r.minY,i.minY),s=Math.min(r.minZ,i.minZ),c=Math.max(r.maxX,i.maxX),l=Math.max(r.maxY,i.maxY),u=Math.max(r.maxZ,i.maxZ);return{cost:this.surfaceAreaFlat(a,o,s,c,l,u)*this.traversalCost+r.cost+i.cost,minX:a,minY:o,minZ:s,maxX:c,maxY:l,maxZ:u}}surfaceAreaFlat(e,t,n,r,i,a){let o=r-e,s=i-t,c=a-n;return 2*(o*s+s*c+c*o)}generatePermutations(e){let t=[],n=Array.from({length:e},(e,t)=>t),r=i=>{if(i===e){t.push([...n]);return}for(let t=i;t<e;t++)[n[i],n[t]]=[n[t],n[i]],r(i+1),[n[i],n[t]]=[n[t],n[i]]};return r(0),t}greedySwapOptimize(e,t,n,r){let i=[...n],a=r,o=!0;for(;o;){o=!1;for(let n=0;n<i.length-1;n++)for(let r=n+1;r<i.length;r++){[i[n],i[r]]=[i[r],i[n]];let s=this.evaluateTopology(e,t,i);s<a?(a=s,o=!0):[i[n],i[r]]=[i[r],i[n]]}}return{perm:i,cost:a}}reconstructTreelet(e,t,n,r){let i=this.buildSubtree(t,n,r);e.minX=i.minX,e.minY=i.minY,e.minZ=i.minZ,e.maxX=i.maxX,e.maxY=i.maxY,e.maxZ=i.maxZ,e.leftChild=i.leftChild,e.rightChild=i.rightChild,e.triangleOffset=i.triangleOffset,e.triangleCount=i.triangleCount}buildSubtree(e,n,r){if(typeof e==`number`){let i=n[r[e]],a=new t;return a.minX=i.minX,a.minY=i.minY,a.minZ=i.minZ,a.maxX=i.maxX,a.maxY=i.maxY,a.maxZ=i.maxZ,a.triangleOffset=i.triangleOffset,a.triangleCount=i.triangleCount,a}let i=this.buildSubtree(e[0],n,r),a=this.buildSubtree(e[1],n,r),o=new t;return o.leftChild=i,o.rightChild=a,o.minX=Math.min(i.minX,a.minX),o.minY=Math.min(i.minY,a.minY),o.minZ=Math.min(i.minZ,a.minZ),o.maxX=Math.max(i.maxX,a.maxX),o.maxY=Math.max(i.maxY,a.maxY),o.maxZ=Math.max(i.maxZ,a.maxZ),o}setTreeletSize(e){this.maxTreeletLeaves=Math.max(3,Math.min(7,e));for(let e=3;e<=this.maxTreeletLeaves;e++)this.topologyCache.has(e)||this.topologyCache.set(e,this.generateTopologies(e))}setMinImprovement(e){this.minImprovement=Math.max(.001,e)}getStatistics(){return{...this.stats}}},t=class{constructor(){this.minX=0,this.minY=0,this.minZ=0,this.maxX=0,this.maxY=0,this.maxZ=0,this.leftChild=null,this.rightChild=null,this.triangleOffset=0,this.triangleCount=0}},n=class{constructor(e,t){this.traversalCost=e,this.intersectionCost=t,this.batchSizeRatio=.02,this.maxIterations=2,this.timeBudgetMs=15e3,this.stats={reinsertionsApplied:0,iterations:0,timeMs:0}}setBatchSizeRatio(e){this.batchSizeRatio=Math.max(.005,Math.min(.1,e))}setMaxIterations(e){this.maxIterations=Math.max(1,Math.min(5,e))}getStatistics(){return{...this.stats}}surfaceArea(e){let t=e.maxX-e.minX,n=e.maxY-e.minY,r=e.maxZ-e.minZ;return t*n+n*r+r*t}buildParentMap(e){let t=new Map;t.set(e,{parent:null,isLeft:!1});let n=[e];for(;n.length>0;){let e=n.pop();e.triangleCount>0||(e.leftChild&&(t.set(e.leftChild,{parent:e,isLeft:!0}),n.push(e.leftChild)),e.rightChild&&(t.set(e.rightChild,{parent:e,isLeft:!1}),n.push(e.rightChild)))}return t}findCandidates(e,t,n){let r=[],i=[e];for(;i.length>0;){let a=i.pop();if(a!==e&&n.get(a).parent!==e){let e=this.surfaceArea(a);r.length<t?(r.push({node:a,cost:e}),r.length===t&&this._heapify(r)):e>r[0].cost&&(r[0]={node:a,cost:e},this._siftDown(r,0))}a.triangleCount===0&&(a.leftChild&&i.push(a.leftChild),a.rightChild&&i.push(a.rightChild))}return r}_heapify(e){for(let t=(e.length>>1)-1;t>=0;t--)this._siftDown(e,t)}_siftDown(e,t){let n=e.length;for(;;){let r=t,i=2*t+1,a=2*t+2;if(i<n&&e[i].cost<e[r].cost&&(r=i),a<n&&e[a].cost<e[r].cost&&(r=a),r===t)break;let o=e[t];e[t]=e[r],e[r]=o,t=r}}findReinsertion(e,t,n){let r=n.get(e),i=r.parent;if(!i)return null;let a=r.isLeft?i.rightChild:i.leftChild,o=this.surfaceArea(e),s=this.surfaceArea(i),c=null,l=0,u=s,d=a.minX,f=a.minY,p=a.minZ,m=a.maxX,h=a.maxY,g=a.maxZ,_=a,v=i,y=[];do{for(y.length=0,y.push(u,_);y.length>0;){let t=y.pop(),n=y.pop();if(n-o<=l)continue;let r=Math.min(t.minX,e.minX),i=Math.min(t.minY,e.minY),a=Math.min(t.minZ,e.minZ),s=Math.max(t.maxX,e.maxX),u=Math.max(t.maxY,e.maxY),d=Math.max(t.maxZ,e.maxZ),f=s-r,p=u-i,m=d-a,h=n-(f*p+p*m+m*f);if(h>l&&(c=t,l=h),t.triangleCount===0&&t.leftChild&&t.rightChild){let e=h+this.surfaceArea(t);y.push(e,t.leftChild),y.push(e,t.rightChild)}}let t=n.get(v);if(!t||t.parent===null)break;if(v!==i){d=Math.min(d,_.minX),f=Math.min(f,_.minY),p=Math.min(p,_.minZ),m=Math.max(m,_.maxX),h=Math.max(h,_.maxY),g=Math.max(g,_.maxZ);let e=m-d,t=h-f,n=g-p,r=e*t+t*n+n*e;u+=this.surfaceArea(v)-r}let r=t.parent;_=t.isLeft?r.rightChild:r.leftChild,v=r}while(n.get(v).parent!==null);return c===a||c===i?null:c?{from:e,to:c,areaDiff:l}:null}getConflicts(e,t,n){let r=n.get(e);return[t,e,r.isLeft?r.parent.rightChild:r.parent.leftChild,n.get(t).parent,r.parent]}reinsertNode(e,t,n){let r=n.get(e),i=r.parent,a=r.isLeft?i.rightChild:i.leftChild,o=n.get(i),s=o.parent,c=n.get(t),l=c.parent;o.isLeft?s.leftChild=a:s.rightChild=a,i.leftChild=e,i.rightChild=t,i.triangleOffset=0,i.triangleCount=0,i.minX=Math.min(e.minX,t.minX),i.minY=Math.min(e.minY,t.minY),i.minZ=Math.min(e.minZ,t.minZ),i.maxX=Math.max(e.maxX,t.maxX),i.maxY=Math.max(e.maxY,t.maxY),i.maxZ=Math.max(e.maxZ,t.maxZ),c.isLeft?l.leftChild=i:l.rightChild=i,n.set(a,{parent:s,isLeft:o.isLeft}),n.set(i,{parent:l,isLeft:c.isLeft}),n.set(e,{parent:i,isLeft:!0}),n.set(t,{parent:i,isLeft:!1}),this.refitFrom(s,n),this.refitFrom(l,n)}refitFrom(e,t){let n=e;for(;n;){if(n.triangleCount===0&&n.leftChild&&n.rightChild){let e=n.leftChild,t=n.rightChild;n.minX=Math.min(e.minX,t.minX),n.minY=Math.min(e.minY,t.minY),n.minZ=Math.min(e.minZ,t.minZ),n.maxX=Math.max(e.maxX,t.maxX),n.maxY=Math.max(e.maxY,t.maxY),n.maxZ=Math.max(e.maxZ,t.maxZ)}let e=t.get(n);n=e?e.parent:null}}optimizeBVH(e,t){let n=performance.now();this.stats={reinsertionsApplied:0,iterations:0,timeMs:0};for(let r=0;r<this.maxIterations&&!(performance.now()-n>this.timeBudgetMs);r++){let i=this.buildParentMap(e),a=i.size,o=Math.max(1,Math.floor(a*this.batchSizeRatio));t&&t(`Reinsertion iter ${r+1}/${this.maxIterations}: selecting ${o} candidates`);let s=this.findCandidates(e,o,i),c=[];for(let t=0;t<s.length&&!(performance.now()-n>this.timeBudgetMs);t++){let n=this.findReinsertion(s[t].node,e,i);n&&n.areaDiff>0&&c.push(n)}c.sort((e,t)=>t.areaDiff-e.areaDiff);let l=new Set,u=0;for(let e of c){let t=this.getConflicts(e.from,e.to,i);if(!t.some(e=>l.has(e))){for(let e of t)l.add(e);this.reinsertNode(e.from,e.to,i),u++}}if(this.stats.reinsertionsApplied+=u,this.stats.iterations=r+1,t&&t(`Reinsertion iter ${r+1}: applied ${u} reinsertions`),u===0)break}return this.stats.timeMs=performance.now()-n,this.stats}};const r={silent:0,error:1,warn:2,info:3,debug:4},i=`info`,a=`rayzeeLogLevel`,o=`rayzeeLogNamespaces`,s=`color:#7c8494`,c=`color:inherit`;let l=null,u=null;function d(e){try{return globalThis.localStorage?.getItem(e)??null}catch{return null}}function f(e,t){try{t===null?globalThis.localStorage?.removeItem(e):globalThis.localStorage?.setItem(e,t)}catch{}}function p(){if(l!==null)return l;let e=globalThis.__RAYZEE_LOG_LEVEL__;return e!==void 0&&e in r?(l=r[e],l):(l=r[d(a)]??r[i],l)}function m(){if(u!==null)return u;let e=globalThis.__RAYZEE_LOG_NS__??d(o);return u=e?String(e).split(`,`).map(e=>e.trim()).filter(Boolean):[],u}function h(e,t){if(t<r.debug)return!0;let n=m();return n.length===0||n.some(t=>e===t||e.startsWith(`${t}:`))}function g(e,t,n){if(e>p()||!h(t,e))return;let i=e===r.error?console.error:e===r.warn?console.warn:console.log,a=`[${t}]`;typeof n[0]==`string`?i(`%c${a}%c ${n[0]}`,s,c,...n.slice(1)):i(`%c${a}`,s,...n)}const _={n:e=>Number(e).toLocaleString(`en-US`),ms:e=>e<10?`${Number(e).toFixed(1)} ms`:`${Math.round(e)} ms`,mb:e=>{let t=e/(1024*1024);return t<10?`${t.toFixed(1)} MB`:`${Math.round(t)} MB`},px:(e,t)=>`${e}×${t}`,count:(e,t,n=`${t}s`)=>`${_.n(e)} ${Number(e)===1?t:n}`,list:e=>e.filter(Boolean).join(` · `)},v={levels:r,setLevel(e){return e in r?(globalThis.__RAYZEE_LOG_LEVEL__=e,l=r[e],f(a,e===i?null:e),e):(console.warn(`[log] unknown level '${e}' — expected one of ${Object.keys(r).join(`, `)}`),this.getLevel())},getLevel(){let e=p();return Object.keys(r).find(t=>r[t]===e)},isEnabled(e){return(r[e]??r.debug)<=p()},only(...e){let t=e.flat().filter(Boolean);return u=t,globalThis.__RAYZEE_LOG_NS__=t.join(`,`),f(o,t.length?t.join(`,`):null),t.length&&this.setLevel(`debug`),t},refresh(){return l=null,u=null,this.getLevel()}};function y(e){return{namespace:e,error:(...t)=>g(r.error,e,t),warn:(...t)=>g(r.warn,e,t),info:(...t)=>g(r.info,e,t),debug:(...t)=>g(r.debug,e,t),isEnabled:e=>v.isEnabled(e),summary(t,n=[]){let i=n.filter(Boolean);if(i.length===0||!console.groupCollapsed){g(r.info,e,[t]),i.forEach(t=>g(r.debug,e,[t]));return}r.info>p()||((p()>=r.debug&&console.group?console.group:console.groupCollapsed)(`%c[${e}]%c ${t}`,s,c),i.forEach(e=>console.log(e)),console.groupEnd())}}}const b=y(`bvh`),x={FLOATS_PER_TRIANGLE:32,POSITION_A_OFFSET:0,POSITION_B_OFFSET:4,POSITION_C_OFFSET:8,NORMAL_A_OFFSET:12,NORMAL_B_OFFSET:16,NORMAL_C_OFFSET:20,UV_AB_OFFSET:24,UV_C_MAT_OFFSET:28},S=x.FLOATS_PER_TRIANGLE;var C=class{constructor(){this.minX=0,this.minY=0,this.minZ=0,this.maxX=0,this.maxY=0,this.maxZ=0,this.leftChild=null,this.rightChild=null,this.triangleOffset=0,this.triangleCount=0}},w=class{constructor(){this.useWorker=!0,this.maxLeafSize=8,this.numBins=32,this.minBins=8,this.maxBins=64,this.totalNodes=0,this.processedTriangles=0,this.totalTriangles=0,this.lastProgressUpdate=0,this.progressUpdateInterval=100,this.traversalCost=1,this.intersectionCost=2.5,this.useMortonCodes=!0,this.mortonBits=10,this.mortonClusterThreshold=128,this.enableObjectMedianFallback=!0,this.enableSpatialMedianFallback=!0,this.splitStats={sahSplits:0,objectMedianSplits:0,spatialMedianSplits:0,failedSplits:0,avgBinsUsed:0,totalSplitAttempts:0,mortonSortTime:0,totalBuildTime:0,treeletOptimizationTime:0,treeletsProcessed:0,treeletsImproved:0,averageSAHImprovement:0,reinsertionOptimizationTime:0,reinsertionsApplied:0,reinsertionIterations:0},this.enableTreeletOptimization=!1,this.treeletSize=5,this.treeletOptimizationPasses=1,this.treeletMinImprovement=.02,this.treeletComplexityThreshold=5e4,this.enableReinsertionOptimization=!0,this.reinsertionBatchSizeRatio=.02,this.reinsertionMaxIterations=2,this.initializeBinArrays(),this._partResult={mid:0,lMinX:0,lMinY:0,lMinZ:0,lMaxX:0,lMaxY:0,lMaxZ:0,rMinX:0,rMinY:0,rMinZ:0,rMaxX:0,rMaxY:0,rMaxZ:0},this.centroids=null,this.bMin=null,this.bMax=null,this.indices=null,this.mortonCodes=null,this.triangles=null,this.reorderedTriangleData=null}initializeBinArrays(){let e=this.maxBins;this.binBoundsMin=new Float32Array(e*3),this.binBoundsMax=new Float32Array(e*3),this.binCounts=new Uint32Array(e),this.leftPrefixMin=new Float32Array(e*3),this.leftPrefixMax=new Float32Array(e*3),this.leftPrefixCount=new Uint32Array(e),this.rightPrefixMin=new Float32Array(e*3),this.rightPrefixMax=new Float32Array(e*3),this.rightPrefixCount=new Uint32Array(e)}getOptimalBinCount(e){return e<=16?this.minBins:e<=64?16:e<=256?32:e<=1024?48:this.maxBins}setAdaptiveBinConfig(e){e.minBins!==void 0&&(this.minBins=Math.max(4,e.minBins)),e.maxBins!==void 0&&(this.maxBins=Math.min(128,e.maxBins)),e.baseBins!==void 0&&(this.numBins=e.baseBins),e.maxBins!==void 0&&this.initializeBinArrays()}setMortonConfig(e){e.enabled!==void 0&&(this.useMortonCodes=e.enabled),e.bits!==void 0&&(this.mortonBits=Math.max(6,Math.min(10,e.bits))),e.threshold!==void 0&&(this.mortonClusterThreshold=Math.max(16,e.threshold))}setFallbackConfig(e){e.objectMedian!==void 0&&(this.enableObjectMedianFallback=e.objectMedian),e.spatialMedian!==void 0&&(this.enableSpatialMedianFallback=e.spatialMedian)}setTreeletConfig(e){e.enabled!==void 0&&(this.enableTreeletOptimization=e.enabled),e.size!==void 0&&(this.treeletSize=Math.max(3,Math.min(12,e.size))),e.passes!==void 0&&(this.treeletOptimizationPasses=Math.max(1,Math.min(3,e.passes))),e.minImprovement!==void 0&&(this.treeletMinImprovement=Math.max(.001,e.minImprovement)),e.complexityThreshold!==void 0&&(this.treeletComplexityThreshold=e.complexityThreshold)}disableTreeletOptimization(){this.enableTreeletOptimization=!1}setReinsertionConfig(e){e.enabled!==void 0&&(this.enableReinsertionOptimization=e.enabled),e.batchSizeRatio!==void 0&&(this.reinsertionBatchSizeRatio=Math.max(.005,Math.min(.1,e.batchSizeRatio))),e.maxIterations!==void 0&&(this.reinsertionMaxIterations=Math.max(1,Math.min(5,e.maxIterations)))}initializeTriangleArrays(){let e=this.totalTriangles,t=this.triangles,n=x.POSITION_A_OFFSET,r=x.POSITION_B_OFFSET,i=x.POSITION_C_OFFSET;for(let a=0;a<e;a++){let e=a*S,o=t[e+n],s=t[e+n+1],c=t[e+n+2],l=t[e+r],u=t[e+r+1],d=t[e+r+2],f=t[e+i],p=t[e+i+1],m=t[e+i+2],h=a*3;this.centroids[h]=(o+l+f)/3,this.centroids[h+1]=(s+u+p)/3,this.centroids[h+2]=(c+d+m)/3,this.bMin[h]=o<l?o<f?o:f:l<f?l:f,this.bMin[h+1]=s<u?s<p?s:p:u<p?u:p,this.bMin[h+2]=c<d?c<m?c:m:d<m?d:m,this.bMax[h]=o>l?o>f?o:f:l>f?l:f,this.bMax[h+1]=s>u?s>p?s:p:u>p?u:p,this.bMax[h+2]=c>d?c>m?c:m:d>m?d:m,this.indices[a]=a}}expandBits(e){return e=e*65537&4278190335,e=e*257&251719695,e=e*17&3272356035,e=e*5&1227133513,e}morton3D(e,t,n){return(this.expandBits(n)<<2)+(this.expandBits(t)<<1)+this.expandBits(e)}computeMortonCodeForIndex(e,t,n,r,i,a,o){let s=this.centroids,c=e*3,l=(1<<this.mortonBits)-1,u=i>0?(s[c]-t)/i:0,d=a>0?(s[c+1]-n)/a:0,f=o>0?(s[c+2]-r)/o:0,p=Math.max(0,Math.min(l,Math.floor(u*l))),m=Math.max(0,Math.min(l,Math.floor(d*l))),h=Math.max(0,Math.min(l,Math.floor(f*l)));return this.morton3D(p,m,h)}sortTrianglesByMortonCode(){let e=this.totalTriangles;if(!this.useMortonCodes||e<this.mortonClusterThreshold)return;let t=performance.now(),n=this.centroids,r=this.indices,i=1/0,a=1/0,o=1/0,s=-1/0,c=-1/0,l=-1/0;for(let t=0;t<e;t++){let e=r[t]*3,u=n[e],d=n[e+1],f=n[e+2];u<i&&(i=u),d<a&&(a=d),f<o&&(o=f),u>s&&(s=u),d>c&&(c=d),f>l&&(l=f)}let u=s-i,d=c-a,f=l-o,p=this.mortonCodes,m=(1<<this.mortonBits)-1,h=u>0?m/u:0,g=d>0?m/d:0,_=f>0?m/f:0;for(let t=0;t<e;t++){let e=r[t],s=e*3,c=(n[s]-i)*h,l=(n[s+1]-a)*g,u=(n[s+2]-o)*_;c=c<0?0:(c>m?m:c)|0,l=l<0?0:(l>m?m:l)|0,u=u<0?0:(u>m?m:u)|0,c=c*65537&4278190335,c=c*257&251719695,c=c*17&3272356035,c=c*5&1227133513,l=l*65537&4278190335,l=l*257&251719695,l=l*17&3272356035,l=l*5&1227133513,u=u*65537&4278190335,u=u*257&251719695,u=u*17&3272356035,u=u*5&1227133513,p[e]=(u<<2)+(l<<1)+c}let v=new Uint32Array(e),y=new Uint32Array(256);for(let t=0;t<32;t+=8){y.fill(0);for(let n=0;n<e;n++)y[p[r[n]]>>>t&255]++;let n=0;for(let e=0;e<256;e++){let t=y[e];y[e]=n,n+=t}for(let n=0;n<e;n++){let e=p[r[n]]>>>t&255;v[y[e]++]=r[n]}r.set(v)}this.splitStats.mortonSortTime+=performance.now()-t}build(e,t=30,n=null){if(this.totalTriangles=e.byteLength/(S*4),this.processedTriangles=0,this.lastProgressUpdate=performance.now(),!(this.useWorker&&null))return new Promise(r=>{r(this._buildSyncAndFlatten(e,t,n))})}_buildSyncAndFlatten(e,t,n){let r=this.buildSync(e,t,n);return{bvhData:this.flattenBVH(r),bvhRoot:!0,reorderedTriangles:this.reorderedTriangleData||null,originalToBvh:this.originalToBvhMap||null}}buildSync(t,r=30,i=null,a=null){let o=performance.now();this.totalNodes=0,this.processedTriangles=0,this.triangles=t,this.totalTriangles=t.byteLength/(S*4),this.lastProgressUpdate=performance.now(),this.splitStats={sahSplits:0,objectMedianSplits:0,spatialMedianSplits:0,failedSplits:0,avgBinsUsed:0,totalSplitAttempts:0,mortonSortTime:0,totalBuildTime:0,treeletOptimizationTime:0,treeletsProcessed:0,treeletsImproved:0,averageSAHImprovement:0,reinsertionOptimizationTime:0,reinsertionsApplied:0,reinsertionIterations:0,saOrderTime:0,initTime:0,sahBuildTime:0,reorderTime:0};let s=this.totalTriangles,c=performance.now();this.centroids=new Float32Array(s*3),this.bMin=new Float32Array(s*3),this.bMax=new Float32Array(s*3),this.indices=new Uint32Array(s),this.mortonCodes=new Uint32Array(s),this.initializeTriangleArrays(),this.splitStats.initTime=performance.now()-c,this.sortTrianglesByMortonCode();let l=performance.now(),u=this.buildNodeRecursive(0,s,r,i);if(this.splitStats.sahBuildTime=performance.now()-l,this.enableTreeletOptimization&&this.totalTriangles>1e3){let t=this.totalTriangles>this.treeletComplexityThreshold?3:this.treeletSize,n=new e(this.traversalCost,this.intersectionCost);n.setTreeletSize(t),n.setMinImprovement(this.treeletMinImprovement);let r=performance.now();for(let e=0;e<this.treeletOptimizationPasses;e++){let t=i?t=>{i(`Treelet optimization pass ${e+1}/${this.treeletOptimizationPasses}: ${t}`)}:null;try{n.optimizeBVH(u,t)}catch(t){b.error(`treelet optimizer failed in pass ${e+1}:`,t);break}let a=n.getStatistics(),o=performance.now()-r;if(a.treeletsImproved===0&&e>0||o>15e3)break}let a=performance.now()-r;this.splitStats.treeletOptimizationTime=a;let o=n.getStatistics();this.splitStats.treeletsProcessed=o.treeletsProcessed,this.splitStats.treeletsImproved=o.treeletsImproved,this.splitStats.averageSAHImprovement=o.averageSAHImprovement}if(this.enableReinsertionOptimization&&this.totalTriangles>1e3){let e=new n(this.traversalCost,this.intersectionCost);e.setBatchSizeRatio(this.reinsertionBatchSizeRatio),e.setMaxIterations(this.reinsertionMaxIterations);let t=i?e=>{i(e)}:null;try{e.optimizeBVH(u,t)}catch(e){b.error(`reinsertion optimizer failed:`,e)}let r=e.getStatistics();this.splitStats.reinsertionOptimizationTime=r.timeMs,this.splitStats.reinsertionsApplied=r.reinsertionsApplied,this.splitStats.reinsertionIterations=r.iterations}let d=performance.now();this.applySAOrdering(u),this.splitStats.saOrderTime=performance.now()-d;let f=performance.now(),p=this.triangles,m=a||new Float32Array(s*S);for(let e=0;e<s;e++){let t=this.indices[e]*S,n=e*S;m.set(p.subarray(t,t+S),n)}this.reorderedTriangleData=m;let h=new Uint32Array(s);for(let e=0;e<s;e++)h[this.indices[e]]=e;this.originalToBvhMap=h,this.splitStats.reorderTime=performance.now()-f,this.splitStats.totalBuildTime=performance.now()-o;let g=this.splitStats.totalBuildTime,v=this.splitStats;return b.debug(`${_.n(s)} tris → ${_.n(this.totalNodes)} nodes in ${_.ms(g)} | SAH ${v.sahSplits} objMed ${v.objectMedianSplits} spatMed ${v.spatialMedianSplits} failed ${v.failedSplits}`+(v.treeletsProcessed?` | treelets ${v.treeletsImproved}/${v.treeletsProcessed} improved`:``)+(v.reinsertionsApplied?` | reinsertions ${v.reinsertionsApplied}`:``)),i&&i(100),this.centroids=null,this.bMin=null,this.bMax=null,this.mortonCodes=null,u}updateProgress(e,t){if(!t)return;this.processedTriangles+=e;let n=performance.now();n-this.lastProgressUpdate<this.progressUpdateInterval||(this.lastProgressUpdate=n,t(Math.min(Math.floor(this.processedTriangles/this.totalTriangles*100),99)))}buildNodeRecursiveToDepth(e,t,n,r,i,a,o,s,c,l,u){let d=new C;this.totalNodes++;let f=t-e;if(a===void 0?this.updateNodeBounds(d,e,t):(d.minX=a,d.minY=o,d.minZ=s,d.maxX=c,d.maxY=l,d.maxZ=u),f<=this.maxLeafSize||n<=0)return d.triangleOffset=e,d.triangleCount=f,this.updateProgress(f,i),d;if(r<=0&&f>this.maxLeafSize*16){let r=this.frontierTasks.length;return d.triangleOffset=e,d.triangleCount=f,d.isFrontier=!0,d.frontierTaskId=r,this.frontierTasks.push({taskId:r,start:e,end:t,depth:n,preMinX:d.minX,preMinY:d.minY,preMinZ:d.minZ,preMaxX:d.maxX,preMaxY:d.maxY,preMaxZ:d.maxZ}),d}let p=this.findBestSplitPositionSAH(e,t,d);if(!p.success){if(this.splitStats.failedSplits++,r>0||f<=this.maxLeafSize*16)return d.triangleOffset=e,d.triangleCount=f,this.updateProgress(f,i),d;let a=this.frontierTasks.length;return d.triangleOffset=e,d.triangleCount=f,d.isFrontier=!0,d.frontierTaskId=a,this.frontierTasks.push({taskId:a,start:e,end:t,depth:n,preMinX:d.minX,preMinY:d.minY,preMinZ:d.minZ,preMaxX:d.maxX,preMaxY:d.maxY,preMaxZ:d.maxZ}),d}p.method===`SAH`?this.splitStats.sahSplits++:p.method===`object_median`?this.splitStats.objectMedianSplits++:p.method===`spatial_median`&&this.splitStats.spatialMedianSplits++,this.partitionWithBounds(e,t,p.axis,p.pos);let m=this._partResult,h=m.mid,g=m.lMinX,_=m.lMinY,v=m.lMinZ,y=m.lMaxX,b=m.lMaxY,x=m.lMaxZ,S=m.rMinX,w=m.rMinY,T=m.rMinZ,E=m.rMaxX,D=m.rMaxY,O=m.rMaxZ;return h===e||h===t?(d.triangleOffset=e,d.triangleCount=f,this.updateProgress(f,i),d):(d.leftChild=this.buildNodeRecursiveToDepth(e,h,n-1,r-1,i,g,_,v,y,b,x),d.rightChild=this.buildNodeRecursiveToDepth(h,t,n-1,r-1,i,S,w,T,E,D,O),d)}buildNodeRecursive(e,t,n,r,i,a,o,s,c,l){let u=new C;this.totalNodes++;let d=t-e;if(i===void 0?this.updateNodeBounds(u,e,t):(u.minX=i,u.minY=a,u.minZ=o,u.maxX=s,u.maxY=c,u.maxZ=l),d<=this.maxLeafSize||n<=0)return u.triangleOffset=e,u.triangleCount=d,this.updateProgress(d,r),u;let f=this.findBestSplitPositionSAH(e,t,u);if(!f.success)return this.splitStats.failedSplits++,u.triangleOffset=e,u.triangleCount=d,this.updateProgress(d,r),u;f.method===`SAH`?this.splitStats.sahSplits++:f.method===`object_median`?this.splitStats.objectMedianSplits++:f.method===`spatial_median`&&this.splitStats.spatialMedianSplits++,this.partitionWithBounds(e,t,f.axis,f.pos);let p=this._partResult,m=p.mid,h=p.lMinX,g=p.lMinY,_=p.lMinZ,v=p.lMaxX,y=p.lMaxY,b=p.lMaxZ,x=p.rMinX,S=p.rMinY,w=p.rMinZ,T=p.rMaxX,E=p.rMaxY,D=p.rMaxZ;return m===e||m===t?(u.triangleOffset=e,u.triangleCount=d,this.updateProgress(d,r),u):(u.leftChild=this.buildNodeRecursive(e,m,n-1,r,h,g,_,v,y,b),u.rightChild=this.buildNodeRecursive(m,t,n-1,r,x,S,w,T,E,D),u)}partitionWithBounds(e,t,n,r){let i=this.indices,a=this.centroids,o=this.bMin,s=this.bMax,c=e,l=t-1,u=1/0,d=1/0,f=1/0,p=-1/0,m=-1/0,h=-1/0,g=1/0,_=1/0,v=1/0,y=-1/0,b=-1/0,x=-1/0;for(;c<=l;){let e=i[c],t=e*3;a[t+n]<=r?(o[t]<u&&(u=o[t]),o[t+1]<d&&(d=o[t+1]),o[t+2]<f&&(f=o[t+2]),s[t]>p&&(p=s[t]),s[t+1]>m&&(m=s[t+1]),s[t+2]>h&&(h=s[t+2]),c++):(o[t]<g&&(g=o[t]),o[t+1]<_&&(_=o[t+1]),o[t+2]<v&&(v=o[t+2]),s[t]>y&&(y=s[t]),s[t+1]>b&&(b=s[t+1]),s[t+2]>x&&(x=s[t+2]),i[c]=i[l],i[l]=e,l--)}let S=this._partResult;return S.mid=c,S.lMinX=u,S.lMinY=d,S.lMinZ=f,S.lMaxX=p,S.lMaxY=m,S.lMaxZ=h,S.rMinX=g,S.rMinY=_,S.rMinZ=v,S.rMaxX=y,S.rMaxY=b,S.rMaxZ=x,S}updateNodeBounds(e,t,n){let r=1/0,i=1/0,a=1/0,o=-1/0,s=-1/0,c=-1/0,l=this.indices,u=this.bMin,d=this.bMax;for(let e=t;e<n;e++){let t=l[e]*3;u[t]<r&&(r=u[t]),u[t+1]<i&&(i=u[t+1]),u[t+2]<a&&(a=u[t+2]),d[t]>o&&(o=d[t]),d[t+1]>s&&(s=d[t+1]),d[t+2]>c&&(c=d[t+2])}e.minX=r,e.minY=i,e.minZ=a,e.maxX=o,e.maxY=s,e.maxZ=c}findBestSplitPositionSAH(e,t,n){let r=1/0,i=-1,a=0,o=this.computeSurfaceAreaFlat(n.minX,n.minY,n.minZ,n.maxX,n.maxY,n.maxZ),s=t-e,c=this.intersectionCost*s,l=this.getOptimalBinCount(s);this.splitStats.totalSplitAttempts++,this.splitStats.avgBinsUsed=(this.splitStats.avgBinsUsed*(this.splitStats.totalSplitAttempts-1)+l)/this.splitStats.totalSplitAttempts;let u=this.indices,d=this.centroids,f=this.bMin,p=this.bMax,m=this.binBoundsMin,h=this.binBoundsMax,g=this.binCounts,_=this.leftPrefixMin,v=this.leftPrefixMax,y=this.leftPrefixCount,b=this.rightPrefixMin,x=this.rightPrefixMax,S=this.rightPrefixCount,C=1/0,w=-1/0,T=1/0,E=-1/0,D=1/0,O=-1/0;for(let n=e;n<t;n++){let e=u[n]*3,t=d[e],r=d[e+1],i=d[e+2];t<C&&(C=t),t>w&&(w=t),r<T&&(T=r),r>E&&(E=r),i<D&&(D=i),i>O&&(O=i)}let k=[C,T,D],A=[w,E,O];for(let n=0;n<3;n++){let s=k[n],C=A[n];if(C-s<1e-6)continue;for(let e=0;e<l;e++){g[e]=0;let t=e*3;m[t]=1/0,m[t+1]=1/0,m[t+2]=1/0,h[t]=-1/0,h[t+1]=-1/0,h[t+2]=-1/0}let w=l/(C-s);for(let r=e;r<t;r++){let e=u[r],t=d[e*3+n],i=Math.floor((t-s)*w);i>=l&&(i=l-1),g[i]++;let a=i*3,o=e*3;f[o]<m[a]&&(m[a]=f[o]),f[o+1]<m[a+1]&&(m[a+1]=f[o+1]),f[o+2]<m[a+2]&&(m[a+2]=f[o+2]),p[o]>h[a]&&(h[a]=p[o]),p[o+1]>h[a+1]&&(h[a+1]=p[o+1]),p[o+2]>h[a+2]&&(h[a+2]=p[o+2])}y[0]=g[0],_[0]=m[0],_[1]=m[1],_[2]=m[2],v[0]=h[0],v[1]=h[1],v[2]=h[2];for(let e=1;e<l;e++){let t=e*3,n=(e-1)*3;y[e]=y[e-1]+g[e];let r=_[n],i=m[t],a=_[n+1],o=m[t+1],s=_[n+2],c=m[t+2];_[t]=r<i?r:i,_[t+1]=a<o?a:o,_[t+2]=s<c?s:c;let l=v[n],u=h[t],d=v[n+1],f=h[t+1],p=v[n+2],b=h[t+2];v[t]=l>u?l:u,v[t+1]=d>f?d:f,v[t+2]=p>b?p:b}let T=l-1,E=T*3;S[T]=g[T],b[E]=m[E],b[E+1]=m[E+1],b[E+2]=m[E+2],x[E]=h[E],x[E+1]=h[E+1],x[E+2]=h[E+2];for(let e=T-1;e>=0;e--){let t=e*3,n=(e+1)*3;S[e]=S[e+1]+g[e];let r=b[n],i=m[t],a=b[n+1],o=m[t+1],s=b[n+2],c=m[t+2];b[t]=r<i?r:i,b[t+1]=a<o?a:o,b[t+2]=s<c?s:c;let l=x[n],u=h[t],d=x[n+1],f=h[t+1],p=x[n+2],_=h[t+2];x[t]=l>u?l:u,x[t+1]=d>f?d:f,x[t+2]=p>_?p:_}for(let e=1;e<l;e++){let t=(e-1)*3,u=e*3,d=y[e-1],f=S[e];if(d===0||f===0)continue;let p=v[t]-_[t],m=v[t+1]-_[t+1],h=v[t+2]-_[t+2],g=2*(p*m+m*h+h*p),w=x[u]-b[u],T=x[u+1]-b[u+1],E=x[u+2]-b[u+2],D=2*(w*T+T*E+E*w),O=this.traversalCost+g/o*d*this.intersectionCost+D/o*f*this.intersectionCost;O<r&&O<c&&(r=O,i=n,a=s+(C-s)*e/l)}}return i===-1?this.enableObjectMedianFallback?this.findObjectMedianSplit(e,t):this.enableSpatialMedianFallback?this.findSpatialMedianSplit(e,t):{success:!1,method:`fallbacks_disabled`}:{success:!0,axis:i,pos:a,method:`SAH`,binsUsed:l}}findObjectMedianSplit(e,t){let n=this.indices,r=this.centroids,i=-1,a=-1;for(let o=0;o<3;o++){let s=1/0,c=-1/0;for(let i=e;i<t;i++){let e=r[n[i]*3+o];e<s&&(s=e),e>c&&(c=e)}let l=c-s;l>a&&(a=l,i=o)}if(i===-1||a<1e-10)return this.enableSpatialMedianFallback?this.findSpatialMedianSplit(e,t):{success:!1,method:`object_median_failed`};let o=t-e,s=e+Math.floor(o/2);this.quickselect(e,t,s,i);let c=r[n[s]*3+i],l=!0;for(let e=s+1;e<t;e++)if(r[n[e]*3+i]>c){l=!1;break}if(l){let a=-1/0;for(let t=e;t<s;t++){let e=r[n[t]*3+i];e>a&&(a=e)}if(a<c)c=(a+c)*.5;else return this.enableSpatialMedianFallback?this.findSpatialMedianSplit(e,t):{success:!1,method:`object_median_degenerate`}}return{success:!0,axis:i,pos:c,method:`object_median`}}findSpatialMedianSplit(e,t){let n=this.indices,r=this.centroids,i=this.bMin,a=this.bMax,o=-1,s=-1,c=0,l=0;for(let r=0;r<3;r++){let u=1/0,d=-1/0;for(let o=e;o<t;o++){let e=n[o]*3+r;i[e]<u&&(u=i[e]),a[e]>d&&(d=a[e])}let f=d-u;f>s&&(s=f,o=r,c=u,l=d)}if(o===-1||s<1e-12)return{success:!1,method:`spatial_median_failed`};let u=(c+l)*.5,d=t-e,f=0;for(let i=e;i<t;i++)r[n[i]*3+o]<=u&&f++;if(f===0||f===d){let i=e+Math.floor(d/2);this.quickselect(e,t,i,o);let a=r[n[i]*3+o],s=!0;for(let i=e;i<t;i++)if(r[n[i]*3+o]!==a){s=!1;break}if(s)return{success:!1,method:`spatial_median_degenerate`};let c=-1/0;for(let t=e;t<i;t++){let e=r[n[t]*3+o];e>c&&(c=e)}if(c<a)u=(c+a)*.5;else{let e=1/0;for(let a=i+1;a<t;a++){let t=r[n[a]*3+o];t<e&&(e=t)}u=(a+e)*.5}}return{success:!0,axis:o,pos:u,method:`spatial_median`}}quickselect(e,t,n,r){let i=this.indices,a=this.centroids,o=e,s=t-1;for(;o<s;){let e=o+s>>>1,t=a[i[o]*3+r],c=a[i[e]*3+r],l=a[i[s]*3+r];if(t>c){let t=i[o];i[o]=i[e],i[e]=t}if(t>l){let e=i[o];i[o]=i[s],i[s]=e}if(c>l){let t=i[e];i[e]=i[s],i[s]=t}let u=a[i[e]*3+r],d=o,f=s;for(;d<=f;){for(;a[i[d]*3+r]<u;)d++;for(;a[i[f]*3+r]>u;)f--;if(d<=f){let e=i[d];i[d]=i[f],i[f]=e,d++,f--}}f<n&&(o=d),d>n&&(s=f)}}applySAOrdering(e){if(!e||!e.leftChild)return;let t=[e],n=[];for(;t.length>0;){let e=t.pop();!e.leftChild||!e.rightChild||(n.push(e),t.push(e.leftChild),t.push(e.rightChild))}for(let e=n.length-1;e>=0;e--){let t=n[e],r=t.leftChild,i=t.rightChild,a=r.maxX-r.minX,o=r.maxY-r.minY,s=r.maxZ-r.minZ,c=i.maxX-i.minX,l=i.maxY-i.minY,u=i.maxZ-i.minZ;c*l+l*u+u*c>a*o+o*s+s*a&&(t.leftChild=i,t.rightChild=r)}}flattenBVH(e){let t=[],n=[e];for(;n.length>0;){let e=n.pop();e._flatIndex=t.length,t.push(e),e.rightChild&&n.push(e.rightChild),e.leftChild&&n.push(e.leftChild)}let r=new Float32Array(t.length*16);for(let e=0;e<t.length;e++){let n=t[e],i=e*16;if(n.leftChild){let e=n.leftChild,t=n.rightChild;r[i]=e.minX,r[i+1]=e.minY,r[i+2]=e.minZ,r[i+3]=e._flatIndex,r[i+4]=e.maxX,r[i+5]=e.maxY,r[i+6]=e.maxZ,r[i+7]=t._flatIndex,r[i+8]=t.minX,r[i+9]=t.minY,r[i+10]=t.minZ,r[i+12]=t.maxX,r[i+13]=t.maxY,r[i+14]=t.maxZ}else r[i]=n.triangleOffset,r[i+1]=n.triangleCount,r[i+3]=-1}return r}flattenBVHWithFrontier(e){let t=[],n=[e];for(;n.length>0;){let e=n.pop();e._flatIndex=t.length,t.push(e),e.rightChild&&n.push(e.rightChild),e.leftChild&&n.push(e.leftChild)}let r=new Float32Array(t.length*16),i=[];for(let e=0;e<t.length;e++){let n=t[e],a=e*16;if(n.leftChild){let e=n.leftChild,t=n.rightChild;r[a]=e.minX,r[a+1]=e.minY,r[a+2]=e.minZ,r[a+3]=e._flatIndex,r[a+4]=e.maxX,r[a+5]=e.maxY,r[a+6]=e.maxZ,r[a+7]=t._flatIndex,r[a+8]=t.minX,r[a+9]=t.minY,r[a+10]=t.minZ,r[a+12]=t.maxX,r[a+13]=t.maxY,r[a+14]=t.maxZ}else if(n.isFrontier){let t=n.frontierTaskId;r[a]=n.triangleOffset,r[a+1]=n.triangleCount,r[a+2]=t,r[a+3]=-2,i.push({taskId:t,flatIndex:e})}else r[a]=n.triangleOffset,r[a+1]=n.triangleCount,r[a+3]=-1}return{flatData:r,frontierMap:i,nodeCount:t.length}}assembleParallelBVH(e,t,n,r){let i=[...r].sort((e,t)=>e.taskId-t.taskId),a=t;for(let e=0;e<i.length;e++)a+=i[e].nodeCount;let o=new Float32Array(a*16);o.set(e);let s=new Map;for(let e of n)s.set(e.taskId,e.flatIndex);let c=t;for(let e=0;e<i.length;e++){let t=i[e],n=t.flatData,r=t.nodeCount,a=c*16;o.set(n,a);for(let e=0;e<r;e++){let t=a+e*16;o[t+3]!==-1&&(o[t+3]+=c,o[t+7]+=c)}let l=s.get(t.taskId);if(l!==void 0){let e=l*16,t=a;for(let n=0;n<16;n++)o[e+n]=o[t+n]}c+=r}return o}computeSurfaceAreaFlat(e,t,n,r,i,a){let o=r-e,s=i-t,c=a-n;return 2*(o*s+s*c+c*o)}};self.onmessage=function(t){let{tasks:r,sharedTriangleData:i,sharedCentroids:a,sharedBMin:o,sharedBMax:s,sharedIndices:c,triangleCount:l,maxLeafSize:u,numBins:d,maxBins:f,minBins:p,treeletConfig:m,reinsertionConfig:h,reportProgress:g}=t.data;for(let t=0;t<r.length;t++){let _=r[t];try{let t=new w;t.maxLeafSize=u,t.numBins=d,t.maxBins=f,t.minBins=p,t.triangles=new Float32Array(i),t.centroids=new Float32Array(a),t.bMin=new Float32Array(o),t.bMax=new Float32Array(s),t.indices=new Uint32Array(c),t.totalTriangles=l,t.totalNodes=0,t.processedTriangles=0,t.lastProgressUpdate=performance.now(),t.splitStats={sahSplits:0,objectMedianSplits:0,spatialMedianSplits:0,failedSplits:0,avgBinsUsed:0,totalSplitAttempts:0,mortonSortTime:0,totalBuildTime:0,treeletOptimizationTime:0,treeletsProcessed:0,treeletsImproved:0,averageSAHImprovement:0,initTime:0,sahBuildTime:0,reorderTime:0};let r=g?e=>{self.postMessage({type:`progress`,taskId:_.taskId,progress:e})}:null,v=performance.now(),y=t.buildNodeRecursive(_.start,_.end,_.depth,r,_.preMinX,_.preMinY,_.preMinZ,_.preMaxX,_.preMaxY,_.preMaxZ);if(m&&m.enabled&&_.end-_.start>1e3){let n=_.end-_.start>5e4,r=n?3:m.size||5,i=n?10:20,a=new e(t.traversalCost,t.intersectionCost);a.setTreeletSize(r),a.setMinImprovement(m.minImprovement||.02),a.setMaxTreelets(i);let o=m.passes||1;for(let e=0;e<o;e++)try{a.optimizeBVH(y,null)}catch(t){console.error(`[BVHSubtreeWorker] Treelet pass ${e+1} error:`,t);break}}if(h&&h.enabled&&_.end-_.start>1e3){let e=new n(t.traversalCost,t.intersectionCost);h.batchSizeRatio&&e.setBatchSizeRatio(h.batchSizeRatio),h.maxIterations&&e.setMaxIterations(h.maxIterations);try{e.optimizeBVH(y,null)}catch(e){console.error(`[BVHSubtreeWorker] Reinsertion error:`,e)}}t.applySAOrdering(y);let b=t.flattenBVH(y),x=b.length/16,S=performance.now()-v;console.log(`[BVHSubtreeWorker] Task ${_.taskId}: ${(_.end-_.start).toLocaleString()} triangles, ${x} nodes, ${Math.round(S)}ms`),self.postMessage({type:`subtreeResult`,taskId:_.taskId,flatData:b,nodeCount:x},[b.buffer])}catch(e){console.error(`[BVHSubtreeWorker] Task ${_.taskId} error:`,e),self.postMessage({type:`error`,taskId:_.taskId,error:e.message})}}};", _c = typeof self < "u" && self.Blob && new Blob(["URL.revokeObjectURL(import.meta.url);", gc], { type: "text/javascript;charset=utf-8" });
|
|
5562
5567
|
function vc(e) {
|
|
5563
5568
|
let t;
|
|
5564
5569
|
try {
|
|
@@ -7382,9 +7387,11 @@ var Zc = ai("scene"), Qc = class {
|
|
|
7382
7387
|
maxTextureSize: Ir.DEFAULT_MAX_TEXTURE_SIZE,
|
|
7383
7388
|
enableTextureCache: !0,
|
|
7384
7389
|
maxConcurrentTextureTasks: Math.min(navigator.hardwareConcurrency || 4, 6),
|
|
7390
|
+
enableTreeletOptimization: !1,
|
|
7385
7391
|
treeletSize: 7,
|
|
7386
7392
|
treeletOptimizationPasses: 1,
|
|
7387
7393
|
treeletMinImprovement: .01,
|
|
7394
|
+
treeletComplexityThreshold: 5e4,
|
|
7388
7395
|
...e
|
|
7389
7396
|
}, this.triangleData = null, this.triangleCount = 0, this.materials = [], this.maps = [], this.normalMaps = [], this.bumpMaps = [], this.roughnessMaps = [], this.metalnessMaps = [], this.emissiveMaps = [], this.displacementMaps = [], this.anisotropyMaps = [], this.transmissionMaps = [], this.clearcoatMaps = [], this.clearcoatRoughnessMaps = [], this.sheenColorMaps = [], this.sheenRoughnessMaps = [], this.iridescenceMaps = [], this.iridescenceThicknessMaps = [], this.specularIntensityMaps = [], this.specularColorMaps = [], this.directionalLights = [], this.cameras = [], this.spheres = [], this.bvhRoot = null, this.bvhData = null, this.materialData = null, this.instanceTable = null, this.originalToBvhMap = null, this._refitWorker = null, this._refitSharedBuffers = null, this._rebuildGeneration = 0, this._pendingRebuilds = /* @__PURE__ */ new Map(), this.srgbBucketTextures = null, this.linearBucketTextures = null, this.emissiveTriangleData = null, this.emissiveTriangleCount = 0, this.lightBVHNodeData = null, this.lightBVHNodeCount = 0, this.emissiveBitTrailMap = null, this._initProcessors(), this.isProcessing = !1, this.processingStage = null, this.performanceMetrics = {
|
|
7390
7397
|
textureCreationTime: 0,
|
|
@@ -7401,7 +7408,8 @@ var Zc = ai("scene"), Qc = class {
|
|
|
7401
7408
|
enabled: this.config.enableTreeletOptimization,
|
|
7402
7409
|
size: this.config.treeletSize,
|
|
7403
7410
|
passes: this.config.treeletOptimizationPasses,
|
|
7404
|
-
minImprovement: this.config.treeletMinImprovement
|
|
7411
|
+
minImprovement: this.config.treeletMinImprovement,
|
|
7412
|
+
complexityThreshold: this.config.treeletComplexityThreshold
|
|
7405
7413
|
}), this.textureCreator = new Lc({ maxTextureSize: this.config.maxTextureSize }), this.emissiveTriangleBuilder = new Kc(), this.tlasBuilder = new kc();
|
|
7406
7414
|
}
|
|
7407
7415
|
_log(e, t) {
|
|
@@ -7489,7 +7497,8 @@ var Zc = ai("scene"), Qc = class {
|
|
|
7489
7497
|
enabled: i !== !1,
|
|
7490
7498
|
size: this.config.treeletSize,
|
|
7491
7499
|
passes: this.config.treeletOptimizationPasses,
|
|
7492
|
-
minImprovement: this.config.treeletMinImprovement
|
|
7500
|
+
minImprovement: this.config.treeletMinImprovement,
|
|
7501
|
+
complexityThreshold: this.config.treeletComplexityThreshold
|
|
7493
7502
|
},
|
|
7494
7503
|
reinsertionOptimization: {
|
|
7495
7504
|
enabled: this.bvhBuilder.enableReinsertionOptimization,
|
|
@@ -7795,7 +7804,8 @@ var Zc = ai("scene"), Qc = class {
|
|
|
7795
7804
|
enabled: this.config.enableTreeletOptimization,
|
|
7796
7805
|
size: this.config.treeletSize,
|
|
7797
7806
|
passes: this.config.treeletOptimizationPasses,
|
|
7798
|
-
minImprovement: this.config.treeletMinImprovement
|
|
7807
|
+
minImprovement: this.config.treeletMinImprovement,
|
|
7808
|
+
complexityThreshold: this.config.treeletComplexityThreshold
|
|
7799
7809
|
})), this._log("Configuration updated", this.config);
|
|
7800
7810
|
}
|
|
7801
7811
|
async refitBVH(e, t) {
|
|
@@ -7956,7 +7966,8 @@ var Zc = ai("scene"), Qc = class {
|
|
|
7956
7966
|
enabled: s,
|
|
7957
7967
|
size: this.config.treeletSize,
|
|
7958
7968
|
passes: this.config.treeletOptimizationPasses,
|
|
7959
|
-
minImprovement: this.config.treeletMinImprovement
|
|
7969
|
+
minImprovement: this.config.treeletMinImprovement,
|
|
7970
|
+
complexityThreshold: this.config.treeletComplexityThreshold
|
|
7960
7971
|
},
|
|
7961
7972
|
reinsertionOptimization: {
|
|
7962
7973
|
enabled: this.bvhBuilder.enableReinsertionOptimization,
|
|
@@ -8745,7 +8756,7 @@ var vl = class {
|
|
|
8745
8756
|
ACTIVE_RAY_COUNT: 0,
|
|
8746
8757
|
ENTERING_COUNT: 1,
|
|
8747
8758
|
CONVERGED_COUNT: 2,
|
|
8748
|
-
|
|
8759
|
+
RESERVED_3: 3,
|
|
8749
8760
|
ACTIVE_PIXEL_COUNT: 4,
|
|
8750
8761
|
COUNT: 5
|
|
8751
8762
|
}, ru = {
|
|
@@ -8906,46 +8917,9 @@ var uu = class {
|
|
|
8906
8917
|
let e = (e) => (e / 1048576).toFixed(1), t = Object.entries(this.byCategory).map(([t, n]) => `${t}=${e(n)}`);
|
|
8907
8918
|
return `VRAM current=${e(this.current)}MB peak=${e(this.peak)}MB [${t.join(" ")}]`;
|
|
8908
8919
|
}
|
|
8909
|
-
}, du = ai("wavefront"), fu = {
|
|
8910
|
-
generate: [
|
|
8911
|
-
16,
|
|
8912
|
-
16,
|
|
8913
|
-
1
|
|
8914
|
-
],
|
|
8915
|
-
extend: [
|
|
8916
|
-
256,
|
|
8917
|
-
1,
|
|
8918
|
-
1
|
|
8919
|
-
],
|
|
8920
|
-
shade: [
|
|
8921
|
-
256,
|
|
8922
|
-
1,
|
|
8923
|
-
1
|
|
8924
|
-
],
|
|
8925
|
-
connect: [
|
|
8926
|
-
256,
|
|
8927
|
-
1,
|
|
8928
|
-
1
|
|
8929
|
-
],
|
|
8930
|
-
accumulate: [
|
|
8931
|
-
256,
|
|
8932
|
-
1,
|
|
8933
|
-
1
|
|
8934
|
-
],
|
|
8935
|
-
compact: [
|
|
8936
|
-
256,
|
|
8937
|
-
1,
|
|
8938
|
-
1
|
|
8939
|
-
],
|
|
8940
|
-
finalWrite: [
|
|
8941
|
-
16,
|
|
8942
|
-
16,
|
|
8943
|
-
1
|
|
8944
|
-
]
|
|
8945
|
-
}, pu = class {
|
|
8920
|
+
}, du = ai("wavefront"), fu = class {
|
|
8946
8921
|
constructor(e) {
|
|
8947
|
-
this.renderer = e, this.kernels = /* @__PURE__ */ new Map(), this.
|
|
8948
|
-
for (let [e, t] of Object.entries(fu)) this.workgroupSizes.set(e, t);
|
|
8922
|
+
this.renderer = e, this.kernels = /* @__PURE__ */ new Map(), this.timing = /* @__PURE__ */ new Map(), this.profiling = !1, this.profile = /* @__PURE__ */ new Map(), this._firstDispatches = [], this._firstDispatchFlush = null;
|
|
8949
8923
|
}
|
|
8950
8924
|
_recordFirstDispatch(e, t) {
|
|
8951
8925
|
this._firstDispatches.push({
|
|
@@ -8984,38 +8958,21 @@ var uu = class {
|
|
|
8984
8958
|
}, this.profile.set(e, i)), i.calls++, i.totalMs += r - n;
|
|
8985
8959
|
} else this.renderer.compute(t);
|
|
8986
8960
|
}
|
|
8987
|
-
|
|
8961
|
+
setDispatchForCount(e, t) {
|
|
8988
8962
|
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]),
|
|
8963
|
+
n && (n.dispatchSize = [
|
|
8964
|
+
Math.ceil(t / n.workgroupSize[0]),
|
|
9011
8965
|
1,
|
|
9012
8966
|
1
|
|
9013
|
-
];
|
|
8967
|
+
]);
|
|
9014
8968
|
}
|
|
9015
|
-
|
|
9016
|
-
|
|
9017
|
-
|
|
9018
|
-
|
|
8969
|
+
setDispatchForGrid(e, t, n) {
|
|
8970
|
+
let r = this.kernels.get(e);
|
|
8971
|
+
if (!r) return;
|
|
8972
|
+
let i = r.workgroupSize;
|
|
8973
|
+
r.dispatchSize = [
|
|
8974
|
+
Math.ceil(t / i[0]),
|
|
8975
|
+
Math.ceil(n / i[1]),
|
|
9019
8976
|
1
|
|
9020
8977
|
];
|
|
9021
8978
|
}
|
|
@@ -9051,7 +9008,66 @@ var uu = class {
|
|
|
9051
9008
|
dispose() {
|
|
9052
9009
|
clearTimeout(this._firstDispatchFlush), this._firstDispatchFlush = null, this._firstDispatches = [], this.kernels.clear(), this.timing.clear(), this.profile.clear();
|
|
9053
9010
|
}
|
|
9054
|
-
},
|
|
9011
|
+
}, pu = f(([e, t, n, r, i, a, o]) => {
|
|
9012
|
+
let s = U(0).toVar();
|
|
9013
|
+
return p(r.equal(N(1)), () => {
|
|
9014
|
+
let n = fe(i.x, i.y, e.x).toVar(), r = fe(a.y, a.x, e.y).toVar(), c = D(r).toVar(), l = U(0).toVar(), u = U(0).toVar(), d = U(0).toVar();
|
|
9015
|
+
p(o.equal(N(1)), () => {
|
|
9016
|
+
let e = U(t[2].x, 0, t[2].z).toVar();
|
|
9017
|
+
p(A(e, e).lessThan(j(1e-8)), () => {
|
|
9018
|
+
e.assign(U(t[1].x, 0, t[1].z));
|
|
9019
|
+
}), d.assign(I(e)), u.assign(U(0, 1, 0)), l.assign(O(u, d));
|
|
9020
|
+
}).Else(() => {
|
|
9021
|
+
l.assign(I(U(t[0]))), u.assign(I(U(t[1]))), d.assign(I(U(t[2])));
|
|
9022
|
+
}), s.assign(I(l.mul(Se(n).mul(c)).add(u.mul(Se(r))).sub(d.mul(D(n).mul(c)))));
|
|
9023
|
+
}).Else(() => {
|
|
9024
|
+
let r = U(e.x.mul(2).sub(1), j(1).sub(e.y.mul(2)), 1), i = n.mul(W(r, 1));
|
|
9025
|
+
s.assign(I(ue(t[0].xyz, t[1].xyz, t[2].xyz).mul(i.xyz.div(i.w))));
|
|
9026
|
+
}), s;
|
|
9027
|
+
}), mu = f(([e, t, n, r, i, a, o, s, c, l, u, d, f, m, h]) => {
|
|
9028
|
+
let g = U(n[3]).toVar(), _ = pu(e, n, r, i, a, o, s).toVar(), v = g.toVar(), y = _.toVar();
|
|
9029
|
+
return p(c.and(l.greaterThan(0)).and(u.lessThan(64)).and(d.greaterThan(.001)), () => {
|
|
9030
|
+
let e = l.div(u).mul(.001).mul(f).mul(m), r = qn(t), a = r.x.mul(h.max(.01)), o = r.y, s = U(0).toVar();
|
|
9031
|
+
p(i.equal(N(1)), () => {
|
|
9032
|
+
s.assign(ja({ N: _ }).mul(U(a, o, 0)));
|
|
9033
|
+
}).Else(() => {
|
|
9034
|
+
let e = I(U(n[0])), t = I(U(n[1]));
|
|
9035
|
+
s.assign(e.mul(a).add(t.mul(o)));
|
|
9036
|
+
}), v.assign(g.add(s.mul(e))), y.assign(I(g.add(_.mul(d)).sub(v)));
|
|
9037
|
+
}), ea({
|
|
9038
|
+
origin: v,
|
|
9039
|
+
direction: y
|
|
9040
|
+
});
|
|
9041
|
+
});
|
|
9042
|
+
function hu(e) {
|
|
9043
|
+
let { rayBufferRW: t, rngBufferRW: n, gBufferRW: r, resolution: i, frame: a, cameraWorldMatrix: o, cameraProjectionMatrixInverse: s, cameraProjection: c, panoLonRange: l, panoLatRange: u, panoLevelHorizon: d, enableDOF: m, focalLength: h, aperture: g, focusDistance: _, sceneScale: v, apertureScale: y, anamorphicRatio: b, renderWidth: x, chunkRowBase: C, chunkRows: w, transmissiveBounces: T, transparentBackground: E, auxGBufferEnabled: D, listDriven: O = !1, activeIndicesRO: k = null, counters: A = null } = e, ee = D.greaterThan(z(0)), te = (e, f, x) => {
|
|
9044
|
+
let S = H(j(e).add(.5), j(f).add(.5)), C = Un({ state: sr({
|
|
9045
|
+
pixelCoord: S,
|
|
9046
|
+
rayIndex: N(0),
|
|
9047
|
+
frame: a
|
|
9048
|
+
}).toVar() }).toVar(), w = or(S, N(1), N(1), C, i, a).toVar().sub(.5), D = H(S.x.add(w.x), S.y.sub(w.y)).div(i), O = ea.wrap(mu(D, C, o, s, c, l, u, d, m, h, g, _, v, y, b));
|
|
9049
|
+
Ml(t, x, O.origin, N(0), N(0)), Nl(t, x, O.direction, z(ru.ACTIVE)), Pl(t, x, W(1, 1, 1, 0).xyz, j(0)), Fl(t, x, W(U(0), L(E, j(1), j(0)))), p(ee, () => {
|
|
9050
|
+
El(r, x, U(0, 0, 1), j(1), U(0)), Yl(t, x, U(1));
|
|
9051
|
+
}), Ul(t, x, z(0), z(T), j(1), j(1), j(1)), n.element(x).assign(C);
|
|
9052
|
+
};
|
|
9053
|
+
return f(() => {
|
|
9054
|
+
if (O) {
|
|
9055
|
+
let e = M;
|
|
9056
|
+
p(e.lessThan(S(A.element(z(nu.ENTERING_COUNT)))), () => {
|
|
9057
|
+
let t = N(k.element(e)), n = t.add(C.mul(x));
|
|
9058
|
+
te(n.mod(x), n.div(x), z(t));
|
|
9059
|
+
});
|
|
9060
|
+
} else {
|
|
9061
|
+
let e = N(He.x).mul(16).add(N(se.x)), t = N(He.y).mul(16).add(N(se.y));
|
|
9062
|
+
p(e.lessThan(x).and(t.lessThan(w)), () => {
|
|
9063
|
+
te(e, t.add(C), z(t.mul(x).add(e)));
|
|
9064
|
+
});
|
|
9065
|
+
}
|
|
9066
|
+
});
|
|
9067
|
+
}
|
|
9068
|
+
//#endregion
|
|
9069
|
+
//#region src/TSL/BVHTraversal.js
|
|
9070
|
+
var gu = 32, _u = 512, vu = 4, yu = 8, bu = 1e8, xu = () => y("int", gu).toVar(), Su = G("\n fn RayTriangleGeometry( rayOrigin: vec3f, rayDir: vec3f, pA: vec3f, pB: vec3f, pC: vec3f, closestHitDst: f32, woopParams: vec4f ) -> vec4f {\n\n // Returns vec4(t, u, v, hit) where hit > 0.5 means intersection.\n // woopParams: (Sx, Sy, Sz, bitcast<f32>(packed kx|ky<<2|kz<<4))\n var result = vec4f( 1e20f, 0.0f, 0.0f, 0.0f );\n\n let Sx = woopParams.x;\n let Sy = woopParams.y;\n let Sz = woopParams.z;\n // Packed as regular f32 (values 0–42), not bitcast — avoids subnormal FTZ on Apple GPUs.\n let packed = i32( woopParams.w );\n let kx = packed & 3;\n let ky = ( packed >> 2 ) & 3;\n let kz = ( packed >> 4 ) & 3;\n\n let A = pA - rayOrigin;\n let B = pB - rayOrigin;\n let C = pC - rayOrigin;\n\n let Akz = A[ kz ];\n let Bkz = B[ kz ];\n let Ckz = C[ kz ];\n\n let Ax = A[ kx ] - Sx * Akz;\n let Ay = A[ ky ] - Sy * Akz;\n let Bx = B[ kx ] - Sx * Bkz;\n let By = B[ ky ] - Sy * Bkz;\n let Cx = C[ kx ] - Sx * Ckz;\n let Cy = C[ ky ] - Sy * Ckz;\n\n // Edge function tests — all three must share sign (or be exactly zero) for hit.\n let U = Cx * By - Cy * Bx;\n let V = Ax * Cy - Ay * Cx;\n let W = Bx * Ay - By * Ax;\n\n let neg = U < 0.0f || V < 0.0f || W < 0.0f;\n let pos = U > 0.0f || V > 0.0f || W > 0.0f;\n if ( !( neg && pos ) ) {\n\n let det = U + V + W;\n if ( det != 0.0f ) {\n\n let T = U * ( Sz * Akz ) + V * ( Sz * Bkz ) + W * ( Sz * Ckz );\n\n // Sign-aware bounds check on t (multiply both sides by sign(det) once).\n let detSign = select( -1.0f, 1.0f, det > 0.0f );\n let tSigned = T * detSign;\n let detAbs = abs( det );\n\n if ( tSigned > 0.0f && tSigned < closestHitDst * detAbs ) {\n\n // Match Möller-Trumbore convention: u = weight of B, v = weight of C.\n // In Woop's edge functions, U → weight of A, V → weight of B, W → weight of C.\n let invDet = 1.0f / det;\n result = vec4f( T * invDet, V * invDet, W * invDet, 1.0f );\n\n }\n\n }\n\n }\n\n return result;\n\n }\n"), Cu = G("\n fn computeWoopRayParams( rayDir: vec3f ) -> vec4f {\n\n let absDir = abs( rayDir );\n\n // kz = argmax(|dir|)\n var kz: i32 = 0;\n if ( absDir.y >= absDir.x ) { kz = 1; }\n if ( absDir.z >= absDir[ u32( kz ) ] ) { kz = 2; }\n\n var kx: i32 = ( kz + 1 ) % 3;\n var ky: i32 = ( kx + 1 ) % 3;\n\n // Preserve triangle winding when the dominant axis component is negative.\n if ( rayDir[ u32( kz ) ] < 0.0f ) {\n let tmp = kx;\n kx = ky;\n ky = tmp;\n }\n\n let dz = rayDir[ u32( kz ) ];\n let Sx = rayDir[ u32( kx ) ] / dz;\n let Sy = rayDir[ u32( ky ) ] / dz;\n let Sz = 1.0f / dz;\n\n let packed = kx | ( ky << 2 ) | ( kz << 4 );\n return vec4f( Sx, Sy, Sz, f32( packed ) );\n\n }\n"), wu = G("\n fn fastRayAABBDst( rayOrigin: vec3f, invDir: vec3f, boxMin: vec3f, boxMax: vec3f ) -> f32 {\n\n let t1 = ( boxMin - rayOrigin ) * invDir;\n let t2 = ( boxMax - rayOrigin ) * invDir;\n\n let tmin = min( t1, t2 );\n let tmax = max( t1, t2 );\n\n let tNear = max( max( tmin.x, tmin.y ), tmin.z );\n let tFar = min( min( tmax.x, tmax.y ), tmax.z ) * 1.00000024f; // Robust traversal: 2 ULP padding (Ize 2013)\n\n let isHit = tNear <= tFar && tFar > 0.0f;\n return select( 1e20f, max( tNear, 0.0f ), isHit );\n\n }\n"), Tu = (e) => f(([t, n, r, i]) => {
|
|
9055
9071
|
let a = i ?? T(!1), o = aa({
|
|
9056
9072
|
didHit: !1,
|
|
9057
9073
|
dst: j(0x56bc75e2d63100000),
|
|
@@ -9062,12 +9078,12 @@ var uu = class {
|
|
|
9062
9078
|
meshIndex: N(-1),
|
|
9063
9079
|
boxTests: N(0),
|
|
9064
9080
|
triTests: N(0)
|
|
9065
|
-
}).toVar(), s = N(-1).toVar(), c = j(0).toVar(), l = j(0).toVar(), u =
|
|
9081
|
+
}).toVar(), s = N(-1).toVar(), c = j(0).toVar(), l = j(0).toVar(), u = xu(), f = N(1).toVar();
|
|
9066
9082
|
u.element(N(0)).assign(N(0));
|
|
9067
|
-
let h = fe(U(1), xe(t.direction), me(t.direction, U(0))), g = fe(U(1).div(t.direction), U(
|
|
9068
|
-
return m(f.greaterThan(N(0)).and(x.lessThan(N(
|
|
9083
|
+
let h = fe(U(1), xe(t.direction), me(t.direction, U(0))), g = fe(U(1).div(t.direction), U(bu).mul(h), oe(_(t.direction), U(1e-8))).toVar(), v = t.origin, y = t.direction, b = Cu({ rayDir: y }).toVar(), x = N(0).toVar();
|
|
9084
|
+
return m(f.greaterThan(N(0)).and(x.lessThan(N(_u))), () => {
|
|
9069
9085
|
x.addAssign(1), f.subAssign(1);
|
|
9070
|
-
let t = u.element(f).toVar(), i = $(n, t, N(0), N(
|
|
9086
|
+
let t = u.element(f).toVar(), i = $(n, t, N(0), N(vu));
|
|
9071
9087
|
e && o.boxTests.addAssign(1), p(i.w.lessThan(0), () => {
|
|
9072
9088
|
p(i.w.greaterThan(j(-1.5)), () => {
|
|
9073
9089
|
let t = N(i.x).toVar(), n = N(i.y).toVar();
|
|
@@ -9076,7 +9092,7 @@ var uu = class {
|
|
|
9076
9092
|
end: n
|
|
9077
9093
|
}, ({ i: n }) => {
|
|
9078
9094
|
e && o.triTests.addAssign(1);
|
|
9079
|
-
let i = t.add(n).toVar(), u = $(r, i, N(0), N(
|
|
9095
|
+
let i = t.add(n).toVar(), u = $(r, i, N(0), N(yu)).xyz, d = $(r, i, N(1), N(yu)).xyz, f = $(r, i, N(2), N(yu)).xyz, m = Su({
|
|
9080
9096
|
rayOrigin: v,
|
|
9081
9097
|
rayDir: y,
|
|
9082
9098
|
pA: u,
|
|
@@ -9086,7 +9102,7 @@ var uu = class {
|
|
|
9086
9102
|
woopParams: b
|
|
9087
9103
|
});
|
|
9088
9104
|
p(m.w.greaterThan(.5), () => {
|
|
9089
|
-
let e = m.x, t = m.y, n = m.z, u = $(r, i, N(3), N(
|
|
9105
|
+
let e = m.x, t = m.y, n = m.z, u = $(r, i, N(3), N(yu)).xyz, d = $(r, i, N(4), N(yu)).xyz, f = $(r, i, N(5), N(yu)), h = f.xyz, g = N(f.w).toVar(), _ = j(1).sub(t).sub(n), v = y.dot(I(u.mul(_).add(d.mul(t)).add(h.mul(n))));
|
|
9090
9106
|
p(a.or(g.equal(N(2))).or(g.equal(N(0)).and(v.lessThan(-1e-4))).or(g.equal(N(1)).and(v.greaterThan(1e-4))), () => {
|
|
9091
9107
|
o.didHit.assign(!0), o.dst.assign(e), s.assign(i), c.assign(t), l.assign(n);
|
|
9092
9108
|
});
|
|
@@ -9095,17 +9111,17 @@ var uu = class {
|
|
|
9095
9111
|
d();
|
|
9096
9112
|
});
|
|
9097
9113
|
}).Else(() => {
|
|
9098
|
-
p(i.z.greaterThan(.5).and(f.lessThan(N(
|
|
9114
|
+
p(i.z.greaterThan(.5).and(f.lessThan(N(gu))), () => {
|
|
9099
9115
|
u.element(f).assign(N(i.x)), f.addAssign(1);
|
|
9100
9116
|
});
|
|
9101
9117
|
});
|
|
9102
9118
|
}).Else(() => {
|
|
9103
|
-
let e = $(n, t, N(1), N(
|
|
9119
|
+
let e = $(n, t, N(1), N(vu)), r = $(n, t, N(2), N(vu)), a = $(n, t, N(3), N(vu)), s = N(i.w).toVar(), c = N(e.w).toVar(), l = wu({
|
|
9104
9120
|
rayOrigin: v,
|
|
9105
9121
|
invDir: g,
|
|
9106
9122
|
boxMin: i.xyz,
|
|
9107
9123
|
boxMax: e.xyz
|
|
9108
|
-
}).toVar(), d =
|
|
9124
|
+
}).toVar(), d = wu({
|
|
9109
9125
|
rayOrigin: v,
|
|
9110
9126
|
invDir: g,
|
|
9111
9127
|
boxMin: r.xyz,
|
|
@@ -9113,21 +9129,21 @@ var uu = class {
|
|
|
9113
9129
|
}).toVar();
|
|
9114
9130
|
p(de(l, d).lessThan(o.dst), () => {
|
|
9115
9131
|
let e = l.lessThan(d);
|
|
9116
|
-
p(L(e, d, l).lessThan(o.dst).and(f.lessThan(N(
|
|
9132
|
+
p(L(e, d, l).lessThan(o.dst).and(f.lessThan(N(gu))), () => {
|
|
9117
9133
|
u.element(f).assign(L(e, c, s)), f.addAssign(1);
|
|
9118
|
-
}), p(f.lessThan(N(
|
|
9134
|
+
}), p(f.lessThan(N(gu)), () => {
|
|
9119
9135
|
u.element(f).assign(L(e, s, c)), f.addAssign(1);
|
|
9120
9136
|
});
|
|
9121
9137
|
});
|
|
9122
9138
|
});
|
|
9123
9139
|
}), p(o.didHit, () => {
|
|
9124
9140
|
o.hitPoint.assign(t.origin.add(t.direction.mul(o.dst)));
|
|
9125
|
-
let e = j(1).sub(c).sub(l), n = $(r, s, N(3), N(
|
|
9141
|
+
let e = j(1).sub(c).sub(l), n = $(r, s, N(3), N(yu)).xyz, i = $(r, s, N(4), N(yu)).xyz, a = $(r, s, N(5), N(yu)).xyz;
|
|
9126
9142
|
o.normal.assign(I(n.mul(e).add(i.mul(c)).add(a.mul(l))));
|
|
9127
|
-
let u = $(r, s, N(6), N(
|
|
9143
|
+
let u = $(r, s, N(6), N(yu)), d = $(r, s, N(7), N(yu));
|
|
9128
9144
|
o.uv.assign(u.xy.mul(e).add(u.zw.mul(c)).add(d.xy.mul(l))), o.materialIndex.assign(N(d.z)), o.meshIndex.assign(N(d.w)), o.triangleIndex.assign(s);
|
|
9129
9145
|
}), o;
|
|
9130
|
-
}),
|
|
9146
|
+
}), Eu = /* @__PURE__ */ Tu(!1), Du = /* @__PURE__ */ Tu(!0), Ou = f(([e, t, n, r]) => {
|
|
9131
9147
|
let i = aa({
|
|
9132
9148
|
didHit: !1,
|
|
9133
9149
|
dst: r,
|
|
@@ -9138,12 +9154,12 @@ var uu = class {
|
|
|
9138
9154
|
meshIndex: N(-1),
|
|
9139
9155
|
boxTests: N(0),
|
|
9140
9156
|
triTests: N(0)
|
|
9141
|
-
}).toVar(), a =
|
|
9157
|
+
}).toVar(), a = xu(), o = N(1).toVar();
|
|
9142
9158
|
a.element(N(0)).assign(N(0));
|
|
9143
|
-
let s = fe(U(1), xe(e.direction), me(e.direction, U(0))), c = fe(U(1).div(e.direction), U(
|
|
9144
|
-
return m(o.greaterThan(N(0)).and(i.didHit.not()).and(u.lessThan(N(
|
|
9159
|
+
let s = fe(U(1), xe(e.direction), me(e.direction, U(0))), c = fe(U(1).div(e.direction), U(bu).mul(s), oe(_(e.direction), U(1e-8))).toVar(), l = Cu({ rayDir: e.direction }).toVar(), u = N(0).toVar();
|
|
9160
|
+
return m(o.greaterThan(N(0)).and(i.didHit.not()).and(u.lessThan(N(_u))), () => {
|
|
9145
9161
|
u.addAssign(1), o.subAssign(1);
|
|
9146
|
-
let r = a.element(o).toVar(), s = $(t, r, N(0), N(
|
|
9162
|
+
let r = a.element(o).toVar(), s = $(t, r, N(0), N(vu));
|
|
9147
9163
|
p(s.w.lessThan(0), () => {
|
|
9148
9164
|
p(s.w.greaterThan(j(-1.5)), () => {
|
|
9149
9165
|
let t = N(s.x).toVar(), r = N(s.y).toVar();
|
|
@@ -9151,7 +9167,7 @@ var uu = class {
|
|
|
9151
9167
|
start: N(0),
|
|
9152
9168
|
end: r
|
|
9153
9169
|
}, ({ i: r }) => {
|
|
9154
|
-
let a = t.add(r).toVar(), o = $(n, a, N(0), N(
|
|
9170
|
+
let a = t.add(r).toVar(), o = $(n, a, N(0), N(yu)).xyz, s = $(n, a, N(1), N(yu)).xyz, c = $(n, a, N(2), N(yu)).xyz, u = Su({
|
|
9155
9171
|
rayOrigin: e.origin,
|
|
9156
9172
|
rayDir: e.direction,
|
|
9157
9173
|
pA: o,
|
|
@@ -9161,22 +9177,22 @@ var uu = class {
|
|
|
9161
9177
|
woopParams: l
|
|
9162
9178
|
});
|
|
9163
9179
|
p(u.w.greaterThan(.5), () => {
|
|
9164
|
-
let t = $(n, a, N(7), N(
|
|
9180
|
+
let t = $(n, a, N(7), N(yu));
|
|
9165
9181
|
i.didHit.assign(!0), i.dst.assign(u.x), i.materialIndex.assign(N(t.z)), i.meshIndex.assign(N(t.w)), i.hitPoint.assign(e.origin.add(e.direction.mul(u.x))), i.uv.assign(H(u.y, u.z)), i.triangleIndex.assign(a), d();
|
|
9166
9182
|
});
|
|
9167
9183
|
});
|
|
9168
9184
|
}).Else(() => {
|
|
9169
|
-
p(s.z.greaterThan(.5).and(o.lessThan(N(
|
|
9185
|
+
p(s.z.greaterThan(.5).and(o.lessThan(N(gu))), () => {
|
|
9170
9186
|
a.element(o).assign(N(s.x)), o.addAssign(1);
|
|
9171
9187
|
});
|
|
9172
9188
|
});
|
|
9173
9189
|
}).Else(() => {
|
|
9174
|
-
let n = $(t, r, N(1), N(
|
|
9190
|
+
let n = $(t, r, N(1), N(vu)), l = $(t, r, N(2), N(vu)), u = $(t, r, N(3), N(vu)), d = N(s.w).toVar(), f = N(n.w).toVar(), m = wu({
|
|
9175
9191
|
rayOrigin: e.origin,
|
|
9176
9192
|
invDir: c,
|
|
9177
9193
|
boxMin: s.xyz,
|
|
9178
9194
|
boxMax: n.xyz
|
|
9179
|
-
}).toVar(), h =
|
|
9195
|
+
}).toVar(), h = wu({
|
|
9180
9196
|
rayOrigin: e.origin,
|
|
9181
9197
|
invDir: c,
|
|
9182
9198
|
boxMin: l.xyz,
|
|
@@ -9184,66 +9200,33 @@ var uu = class {
|
|
|
9184
9200
|
}).toVar();
|
|
9185
9201
|
p(de(m, h).lessThan(i.dst), () => {
|
|
9186
9202
|
let e = m.lessThan(h);
|
|
9187
|
-
p(L(e, h, m).lessThan(i.dst).and(o.lessThan(N(
|
|
9203
|
+
p(L(e, h, m).lessThan(i.dst).and(o.lessThan(N(gu))), () => {
|
|
9188
9204
|
a.element(o).assign(L(e, f, d)), o.addAssign(1);
|
|
9189
|
-
}), p(o.lessThan(N(
|
|
9205
|
+
}), p(o.lessThan(N(gu)), () => {
|
|
9190
9206
|
a.element(o).assign(L(e, d, f)), o.addAssign(1);
|
|
9191
9207
|
});
|
|
9192
9208
|
});
|
|
9193
9209
|
});
|
|
9194
9210
|
}), i;
|
|
9195
|
-
}), Du = f(([e, t, n, r, i, a, o, s, c, l, u]) => {
|
|
9196
|
-
let d = U(e.xy, 1), f = r.mul(W(d, 1)), m = I(ue(n[0].xyz, n[1].xyz, n[2].xyz).mul(f.xyz.div(f.w))).toVar(), h = U(n[3]).toVar(), g = h.toVar(), _ = m.toVar();
|
|
9197
|
-
return p(i.and(a.greaterThan(0)).and(o.lessThan(64)).and(s.greaterThan(.001)), () => {
|
|
9198
|
-
let e = a.div(o).mul(.001).mul(c).mul(l), r = qn(t), i = r.x.mul(u.max(.01)), d = r.y, f = I(U(n[0])), p = I(U(n[1])), v = f.mul(i).add(p.mul(d)).mul(e);
|
|
9199
|
-
g.assign(h.add(v)), _.assign(I(h.add(m.mul(s)).sub(g)));
|
|
9200
|
-
}), ea({
|
|
9201
|
-
origin: g,
|
|
9202
|
-
direction: _
|
|
9203
|
-
});
|
|
9204
9211
|
});
|
|
9205
|
-
function Ou(e) {
|
|
9206
|
-
let { rayBufferRW: t, rngBufferRW: n, gBufferRW: r, resolution: i, frame: a, cameraWorldMatrix: o, cameraProjectionMatrixInverse: s, enableDOF: c, focalLength: l, aperture: u, focusDistance: d, sceneScale: m, apertureScale: h, anamorphicRatio: g, renderWidth: _, chunkRowBase: v, chunkRows: y, transmissiveBounces: b, transparentBackground: x, auxGBufferEnabled: C, listDriven: w = !1, activeIndicesRO: T = null, counters: E = null } = e, D = C.greaterThan(z(0)), O = (e, f, _) => {
|
|
9207
|
-
let v = H(j(e).add(.5), j(f).add(.5)), y = v.div(i).mul(2).sub(1).toVar();
|
|
9208
|
-
y.y.assign(y.y.negate());
|
|
9209
|
-
let S = Un({ state: sr({
|
|
9210
|
-
pixelCoord: v,
|
|
9211
|
-
rayIndex: N(0),
|
|
9212
|
-
frame: a
|
|
9213
|
-
}).toVar() }).toVar(), C = or(v, N(1), N(1), S, i, a).toVar(), w = H(2).div(i), T = C.sub(.5).mul(w), E = y.add(T), O = ea.wrap(Du(E, S, o, s, c, l, u, d, m, h, g));
|
|
9214
|
-
Ml(t, _, O.origin, N(0), N(0)), Nl(t, _, O.direction, z(ru.ACTIVE)), Pl(t, _, W(1, 1, 1, 0).xyz, j(0)), Fl(t, _, W(U(0), L(x, j(1), j(0)))), p(D, () => {
|
|
9215
|
-
El(r, _, U(0, 0, 1), j(1), U(0)), Yl(t, _, U(1));
|
|
9216
|
-
}), Ul(t, _, z(0), z(b), j(1), j(1), j(1)), n.element(_).assign(S);
|
|
9217
|
-
};
|
|
9218
|
-
return f(() => {
|
|
9219
|
-
if (w) {
|
|
9220
|
-
let e = M;
|
|
9221
|
-
p(e.lessThan(S(E.element(z(nu.ENTERING_COUNT)))), () => {
|
|
9222
|
-
let t = N(T.element(e)), n = t.add(v.mul(_));
|
|
9223
|
-
O(n.mod(_), n.div(_), z(t));
|
|
9224
|
-
});
|
|
9225
|
-
} else {
|
|
9226
|
-
let e = N(He.x).mul(16).add(N(se.x)), t = N(He.y).mul(16).add(N(se.y));
|
|
9227
|
-
p(e.lessThan(_).and(t.lessThan(y)), () => {
|
|
9228
|
-
O(e, t.add(v), z(t.mul(_).add(e)));
|
|
9229
|
-
});
|
|
9230
|
-
}
|
|
9231
|
-
});
|
|
9232
|
-
}
|
|
9233
9212
|
//#endregion
|
|
9234
9213
|
//#region src/TSL/ExtendKernel.js
|
|
9235
9214
|
function ku(e) {
|
|
9236
|
-
let { bvhBuffer: t, triangleBuffer: n,
|
|
9215
|
+
let { bvhBuffer: t, triangleBuffer: n, rayBufferRO: r, hitBufferRW: i, activeIndicesRO: a, counters: o, maxRayCount: s } = e;
|
|
9237
9216
|
return f(() => {
|
|
9238
|
-
let e = M,
|
|
9239
|
-
p(e.greaterThanEqual(
|
|
9217
|
+
let e = M, c = o ? S(o.element(z(nu.ENTERING_COUNT))) : s;
|
|
9218
|
+
p(e.greaterThanEqual(c), () => {
|
|
9240
9219
|
h();
|
|
9241
9220
|
});
|
|
9242
|
-
let l =
|
|
9243
|
-
|
|
9244
|
-
|
|
9245
|
-
})
|
|
9246
|
-
|
|
9221
|
+
let l = a.element(e);
|
|
9222
|
+
p(xl(r, l).bitAnd(z(ru.ACTIVE)).equal(z(0)), () => {
|
|
9223
|
+
h();
|
|
9224
|
+
});
|
|
9225
|
+
let u = ea({
|
|
9226
|
+
origin: yl(r, l).toVar(),
|
|
9227
|
+
direction: bl(r, l).toVar()
|
|
9228
|
+
}), d = Hl(r, l).stackDepth.greaterThan(z(0)), f = aa.wrap(Eu(u, t, n, d)).toVar();
|
|
9229
|
+
Vl(i, l, f.dst, z(f.triangleIndex), f.uv.x, f.uv.y, f.normal, z(f.materialIndex), z(f.meshIndex));
|
|
9247
9230
|
});
|
|
9248
9231
|
}
|
|
9249
9232
|
//#endregion
|
|
@@ -9528,7 +9511,7 @@ var Au = /* @__PURE__ */ G("\n fn equirectDirectionToUv( direction: vec3f, envir
|
|
|
9528
9511
|
selectionTotalWeight: A
|
|
9529
9512
|
});
|
|
9530
9513
|
}), Ku = f(([e, t]) => F(bo(e, t), 1e-8)), qu = f(([e, t, n, r]) => Ku(r, la.wrap(Na(n, e, t, r)))), Ju = f(([e, t, n, r, i, a, o, s, c, l, u, d, h, g, _, v, y, b, x, S, C, w, T, E, D, O, k, ee, te, ne, re, ie, M]) => {
|
|
9531
|
-
let P = U(0).toVar(), ae = U(0).toVar(), oe = e.add(t.mul(.001)).toVar(), se = f(([e, t, n]) => ys(e, t, n,
|
|
9514
|
+
let P = U(0).toVar(), ae = U(0).toVar(), oe = e.add(t.mul(.001)).toVar(), se = f(([e, t, n]) => ys(e, t, n, Ou, w, T, E));
|
|
9532
9515
|
return p(n.emissiveIntensity.lessThanEqual(10), () => {
|
|
9533
9516
|
let e = _.add(y).add(x).add(C).toVar(), f = e.greaterThan(N(0)).toVar(), w = j(0).toVar();
|
|
9534
9517
|
p(f, () => {
|
|
@@ -10417,7 +10400,7 @@ function Bd(e) {
|
|
|
10417
10400
|
});
|
|
10418
10401
|
let Jt = ia.wrap(Ju(ut, dt, q, Lt, Ut, Gt, Wt, st, Ye, Qe, je, Ae, $e, ie, P, oe, se, le, ue, de, pe, t, n, r, g, _, v, i, te, ne, re, y, T(!1))).shadowed.toVar(), Yt = L(st.greaterThan(0), Ee, j(1));
|
|
10419
10402
|
qe.assign(W(qe.xyz.add(Zu(Ke.mul(Jt).mul(Yt), j(st), ke, N(R))), qe.w)), Ve && p(Ie.equal(N(1)).and(Ne.greaterThan(N(0))), () => {
|
|
10420
|
-
let e = f(([e, i, a]) => ys(e, i, a,
|
|
10403
|
+
let e = f(([e, i, a]) => ys(e, i, a, Ou, t, n, r));
|
|
10421
10404
|
p(Le.greaterThan(N(0)), () => {
|
|
10422
10405
|
let t = cd.wrap(Pd(ut, dt, Ye, Qe, je, Ae, $e, a, a, Pe, n));
|
|
10423
10406
|
p(t.valid.and(t.pdf.greaterThan(0)), () => {
|
|
@@ -10485,50 +10468,46 @@ function Hd(e) {
|
|
|
10485
10468
|
}
|
|
10486
10469
|
var Ud = /* @__PURE__ */ G("\n fn nanInfToRed( c: vec3f ) -> vec3f {\n let isNan = c.x != c.x || c.y != c.y || c.z != c.z;\n let isInf = abs( c.x ) > 1e30f || abs( c.y ) > 1e30f || abs( c.z ) > 1e30f;\n if ( isNan || isInf ) { return vec3f( 1.0f, 0.0f, 0.0f ); }\n return vec3f( 0.0f );\n }\n");
|
|
10487
10470
|
function Wd(e) {
|
|
10488
|
-
let { rayBufferRO: t, gBufferRO: n, writeColorTex: r, writeNDTex: i, writeAlbedoTex: a, resolution: o, frame: s, enableAccumulation: c, hasPreviousAccumulated: l, accumulationAlpha: u, cameraIsMoving: d, transparentBackground: m, prevAccumTexture: h, prevAlbedoTexture: g, prevNormalDepthTexture: _, renderWidth: v, chunkRowBase: y, chunkRows: b, visMode: S, auxGBufferEnabled: C, cleanAuxNormalEnabled: w, counters: T, m2BufferRW: E, useAdaptiveSampling: D, noiseThreshold: O, adaptiveMinSamples: k, usePixelFreeze: A, pixelFreezeThreshold: ee,
|
|
10471
|
+
let { rayBufferRO: t, gBufferRO: n, writeColorTex: r, writeNDTex: i, writeAlbedoTex: a, resolution: o, frame: s, enableAccumulation: c, hasPreviousAccumulated: l, accumulationAlpha: u, cameraIsMoving: d, transparentBackground: m, prevAccumTexture: h, prevAlbedoTexture: g, prevNormalDepthTexture: _, renderWidth: v, chunkRowBase: y, chunkRows: b, visMode: S, auxGBufferEnabled: C, cleanAuxNormalEnabled: w, counters: T, m2BufferRW: E, useAdaptiveSampling: D, noiseThreshold: O, adaptiveMinSamples: k, usePixelFreeze: A, pixelFreezeThreshold: ee, streakBufferRW: te, frozenMaskRO: ne } = e, re = C.greaterThan(z(0)), ie = w.greaterThan(z(0)), M = D.greaterThan(N(0)), P = A.greaterThan(N(0));
|
|
10489
10472
|
return f(() => {
|
|
10490
10473
|
let e = N(He.x).mul(16).add(N(se.x)), f = N(He.y).mul(16).add(N(se.y));
|
|
10491
10474
|
p(e.lessThan(v).and(f.lessThan(b)), () => {
|
|
10492
|
-
let b = f.add(y), C = z(f.mul(v).add(e)), w = z(b.mul(v).add(e)), D = wl(t, C), A = D.xyz.toVar(),
|
|
10493
|
-
p(
|
|
10475
|
+
let b = f.add(y), C = z(f.mul(v).add(e)), w = z(b.mul(v).add(e)), D = wl(t, C), A = D.xyz.toVar(), oe = L(m, D.w, j(1)).toVar(), se = P.and(s.greaterThan(z(0))).and(ne.element(w).equal(z(1))).toVar(), ce = W(0).toVar(), le = W(0).xyz.toVar();
|
|
10476
|
+
p(re, () => {
|
|
10494
10477
|
let e = Dl(n, C);
|
|
10495
|
-
|
|
10478
|
+
ce.assign(Ol(e)), le.assign(W(kl(e), 0).xyz);
|
|
10496
10479
|
});
|
|
10497
|
-
let
|
|
10480
|
+
let ue = H(j(e).add(.5), j(b).add(.5)).div(o);
|
|
10498
10481
|
p(c.and(d.not()).and(s.greaterThan(z(0))).and(l).and(S.notEqual(N(11))), () => {
|
|
10499
|
-
let e = je(h,
|
|
10500
|
-
A.assign(L(
|
|
10501
|
-
|
|
10502
|
-
let e = je(_,
|
|
10503
|
-
|
|
10482
|
+
let e = je(h, ue, 0).toVar();
|
|
10483
|
+
A.assign(L(se, e.xyz, fe(e.xyz, D.xyz, u))), p(re, () => {
|
|
10484
|
+
le.assign(fe(je(g, ue, 0).xyz, le, u)), p(ie, () => {
|
|
10485
|
+
let e = je(_, ue, 0).xyz.mul(2).sub(1), t = ce.xyz.mul(2).sub(1).toVar(), n = fe(e, t, u).toVar(), r = ae(n), i = L(r.greaterThan(1e-4), n.div(r), t);
|
|
10486
|
+
ce.assign(W(i.mul(.5).add(.5), ce.w));
|
|
10504
10487
|
});
|
|
10505
10488
|
}), p(m, () => {
|
|
10506
|
-
|
|
10489
|
+
oe.assign(L(se, e.w, fe(e.w, D.w, u)));
|
|
10507
10490
|
});
|
|
10508
|
-
}), p(
|
|
10491
|
+
}), p(M, () => {
|
|
10509
10492
|
let e = Oa(D.xyz), t = fe(E.element(w).toVar(), e.mul(e), u).toVar();
|
|
10510
10493
|
E.element(w).assign(t);
|
|
10511
10494
|
let n = Oa(A).toVar(), r = t.sub(n.mul(n)).max(j(0)).div(j(s).add(1)).sqrt().toVar(), i = r.div(n.add(j(1e-4))), a = L(n.lessThan(j(1)), n.sqrt(), n), o = r.div(a.add(j(1e-4))).lessThan(O);
|
|
10512
10495
|
p(s.greaterThanEqual(z(k)).and(o), () => {
|
|
10513
10496
|
x(T.element(z(nu.CONVERGED_COUNT)), z(1));
|
|
10514
|
-
}), p(
|
|
10497
|
+
}), p(P, () => {
|
|
10515
10498
|
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
|
-
});
|
|
10499
|
+
te.element(w).assign(z(0));
|
|
10500
|
+
}), p(se.not().and(s.greaterThan(z(0))), () => {
|
|
10501
|
+
let e = L(s.greaterThanEqual(z(k)).and(i.lessThan(ee)), te.element(w).add(z(1)), z(0)).toVar();
|
|
10502
|
+
te.element(w).assign(e);
|
|
10524
10503
|
});
|
|
10525
10504
|
});
|
|
10526
10505
|
}), p(S.equal(N(11)), () => {
|
|
10527
10506
|
A.assign(Ud(A));
|
|
10528
10507
|
});
|
|
10529
|
-
let
|
|
10530
|
-
Ne(r,
|
|
10531
|
-
Ne(i,
|
|
10508
|
+
let F = Re(z(e), z(b));
|
|
10509
|
+
Ne(r, F, W(A, oe)).toWriteOnly(), p(re, () => {
|
|
10510
|
+
Ne(i, F, ce).toWriteOnly(), Ne(a, F, W(le, 1)).toWriteOnly();
|
|
10532
10511
|
});
|
|
10533
10512
|
});
|
|
10534
10513
|
});
|
|
@@ -10539,7 +10518,7 @@ var Gd = /* @__PURE__ */ G("\n fn visualizeDepth( depth: f32 ) -> vec3f {\n ret
|
|
|
10539
10518
|
let _ = W(1, 0, 1, 1).toVar(), v = ea({
|
|
10540
10519
|
origin: e,
|
|
10541
10520
|
direction: t
|
|
10542
|
-
}), y = aa.wrap(
|
|
10521
|
+
}), y = aa.wrap(Du(v, n, r).toVar());
|
|
10543
10522
|
return p(l.equal(N(7)), () => {
|
|
10544
10523
|
let e = j(y.triTests).div(u);
|
|
10545
10524
|
_.assign(L(e.lessThan(1), W(U(e), 1), W(1, 0, 0, 1)));
|
|
@@ -10626,7 +10605,7 @@ var Gd = /* @__PURE__ */ G("\n fn visualizeDepth( depth: f32 ) -> vec3f {\n ret
|
|
|
10626
10605
|
}).toVar(), h = ea({
|
|
10627
10606
|
origin: y.hitPoint.add(u.mul(.001)),
|
|
10628
10607
|
direction: m
|
|
10629
|
-
}), v = aa.wrap(
|
|
10608
|
+
}), v = aa.wrap(Du(h, n, r).toVar()), b = U(0).toVar();
|
|
10630
10609
|
p(v.didHit.not(), () => {
|
|
10631
10610
|
p(c, () => {
|
|
10632
10611
|
b.assign(Pu({
|
|
@@ -10680,21 +10659,19 @@ var Gd = /* @__PURE__ */ G("\n fn visualizeDepth( depth: f32 ) -> vec3f {\n ret
|
|
|
10680
10659
|
}), _;
|
|
10681
10660
|
});
|
|
10682
10661
|
function Yd(e) {
|
|
10683
|
-
let { writeColorTex: t, writeNDTex: n, writeAlbedoTex: r, resolution: i, renderWidth: a, renderHeight: o, cameraWorldMatrix: s, cameraProjectionMatrixInverse: c, cameraProjectionMatrix: l, cameraViewMatrix: u,
|
|
10662
|
+
let { writeColorTex: t, writeNDTex: n, writeAlbedoTex: r, resolution: i, renderWidth: a, renderHeight: o, cameraWorldMatrix: s, cameraProjectionMatrixInverse: c, cameraProjectionMatrix: l, cameraViewMatrix: u, cameraProjection: d, panoLonRange: m, panoLatRange: h, panoLevelHorizon: g, enableDOF: _, focalLength: v, aperture: y, focusDistance: b, sceneScale: x, apertureScale: S, anamorphicRatio: C, bvhBuffer: w, triangleBuffer: T, materialBuffer: E, envTexture: D, environmentMatrix: O, environmentIntensity: k, enableEnvironmentLight: A, visMode: ee, debugVisScale: te, frame: ne } = e;
|
|
10684
10663
|
return f(() => {
|
|
10685
10664
|
let e = N(He.x).mul(16).add(N(se.x)), f = N(He.y).mul(16).add(N(se.y));
|
|
10686
10665
|
p(e.lessThan(a).and(f.lessThan(o)), () => {
|
|
10687
|
-
let a = H(j(e).add(.5), j(f).add(.5)), o = Un({ state: z(f.mul(N(i.x)).add(e)).add(z(1)) }).toVar(),
|
|
10688
|
-
|
|
10689
|
-
|
|
10690
|
-
|
|
10691
|
-
let e = or(a, N(0), N(1), o, i, k);
|
|
10692
|
-
te.assign(W(e, 1, 1));
|
|
10666
|
+
let a = H(j(e).add(.5), j(f).add(.5)), o = Un({ state: z(f.mul(N(i.x)).add(e)).add(z(1)) }).toVar(), re = ea.wrap(mu(a.div(i), o, s, c, d, m, h, g, _, v, y, b, x, S, C)), ie = W(1, 0, 1, 1).toVar();
|
|
10667
|
+
p(ee.equal(N(9)), () => {
|
|
10668
|
+
let e = or(a, N(0), N(1), o, i, ne);
|
|
10669
|
+
ie.assign(W(e, 1, 1));
|
|
10693
10670
|
}).Else(() => {
|
|
10694
|
-
|
|
10671
|
+
ie.assign(Jd(re.origin, re.direction, w, T, E, D, O, k, A, ee, te, a, i, l, u, ne));
|
|
10695
10672
|
});
|
|
10696
|
-
let
|
|
10697
|
-
Ne(t,
|
|
10673
|
+
let M = Re(z(e), z(f));
|
|
10674
|
+
Ne(t, M, ie).toWriteOnly(), Ne(n, M, W(.5, .5, 1, 1)).toWriteOnly(), Ne(r, M, W(ie.xyz, 1)).toWriteOnly();
|
|
10698
10675
|
});
|
|
10699
10676
|
});
|
|
10700
10677
|
}
|
|
@@ -10740,16 +10717,33 @@ function Qd({ sortGlobalHistogram: e, bins: t = 256 }) {
|
|
|
10740
10717
|
}
|
|
10741
10718
|
function $d({ hitBufferRO: e, activeIndicesReadRO: t, sortedIndicesRW: n, sortGlobalHistogram: r, counters: i, bins: a = 256 }) {
|
|
10742
10719
|
return f(() => {
|
|
10743
|
-
let o = M, s =
|
|
10744
|
-
p(
|
|
10745
|
-
|
|
10746
|
-
|
|
10720
|
+
let o = M, s = se.x, c = jn("uint", a);
|
|
10721
|
+
p(s.lessThan(z(a)), () => {
|
|
10722
|
+
C(c.element(s), z(0));
|
|
10723
|
+
}), Ve();
|
|
10724
|
+
let l = S(i.element(z(nu.ENTERING_COUNT))), u = o.lessThan(l), d = z(0).toVar(), f = z(0).toVar();
|
|
10725
|
+
p(u, () => {
|
|
10726
|
+
d.assign(t.element(o)), f.assign(z(Bl(e, d)).clamp(z(0), z(a - 1))), x(c.element(f), z(1));
|
|
10727
|
+
}), Ve(), p(s.lessThan(z(a)), () => {
|
|
10728
|
+
let e = c.element(s), t = S(e);
|
|
10729
|
+
p(t.greaterThan(z(0)), () => {
|
|
10730
|
+
C(e, x(r.element(s), t));
|
|
10731
|
+
});
|
|
10732
|
+
}), Ve(), p(u, () => {
|
|
10733
|
+
n.element(x(c.element(f), z(1))).assign(d);
|
|
10747
10734
|
});
|
|
10748
10735
|
});
|
|
10749
10736
|
}
|
|
10750
10737
|
//#endregion
|
|
10751
10738
|
//#region src/Stages/PathTracer.js
|
|
10752
|
-
var ef = ai("wavefront"), tf =
|
|
10739
|
+
var ef = ai("wavefront"), tf = 256, nf = [
|
|
10740
|
+
"extend",
|
|
10741
|
+
"shade",
|
|
10742
|
+
"globalHist",
|
|
10743
|
+
"globalScatter",
|
|
10744
|
+
"compact",
|
|
10745
|
+
"compactCopyback"
|
|
10746
|
+
], rf = class extends dl {
|
|
10753
10747
|
constructor(e, t, n, r = {}) {
|
|
10754
10748
|
super(e, t, n, r), this.name = "PathTracer", this._packedBuffers = null, this._queueManager = null, this._kernelManager = null, this._gBufferAttr = null, this._m2Attr = null, this._streakAttr = null, this._frozenMaskAttr = null, this._dilateFrozenUniform = B(1, "int"), this._wavefrontReady = !1, this._auxGBufferEnabled = !1, this._auxGBufferUniform = B(0, "uint"), this._cleanAuxNormalEnabled = !1, this._cleanAuxNormalUniform = B(0, "uint"), this._useDynamicDispatch = !0, this._sortMaterials = !1, this._useSubgroupCompact = !1, this._lastBounceCounts = null, this._lastBounceCountsBudget = -1, this._readbackPending = !1, this._readbackEveryNFrames = 4, this._readbackFrameCounter = 0, this._readbackGeneration = 0, this._curveSizingValid = !1, this._bounceEarlyExitThreshold = 100, this._convergedFraction = 0, this._convergedReadbackPending = !1, this._lastActivePixelCount = 0, this._wfRenderWidth = B(1920, "int"), this._wfRenderHeight = B(1080, "int"), this._wfMaxRayCount = B(0, "uint"), this._wfCurrentBounce = B(0, "int"), this._wfChunkRowBase = B(0, "int"), this._wfChunkRows = B(0, "int"), this._wfIsFirstChunk = B(1, "uint"), this._pathBudget = 0, this._pathBudgetOverride = 0, this._chunkRows = 0, this._numChunks = 1, this.vramTracker = new uu(this.renderer), this._registerVRAMProviders(), ef.debug("initialized (wavefront)");
|
|
10755
10749
|
}
|
|
@@ -10824,11 +10818,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
10824
10818
|
let n = Math.min(l, c - t), r = this._setChunk(t, n, e), i = this.usePixelFreeze.value > 0, o = u && i && this._curveSizingValid && this._lastActivePixelCount > 0 ? this._lastActivePixelCount : r;
|
|
10825
10819
|
if (i) {
|
|
10826
10820
|
let e = Math.min(r, Math.ceil(o * 1.5) + 1024);
|
|
10827
|
-
a.
|
|
10828
|
-
Math.ceil(e / 256),
|
|
10829
|
-
1,
|
|
10830
|
-
1
|
|
10831
|
-
]), a.dispatch("resetFrameCounters"), a.dispatch("buildActivePixels"), a.dispatch("seedEnter"), a.dispatch("generateList");
|
|
10821
|
+
a.setDispatchForCount("generateList", e), a.dispatch("resetFrameCounters"), a.dispatch("buildActivePixels"), a.dispatch("seedEnter"), a.dispatch("generateList");
|
|
10832
10822
|
} else a.dispatch("generate"), a.dispatch("initActiveIndices");
|
|
10833
10823
|
for (let e = 0; e <= s; e++) {
|
|
10834
10824
|
this._wfCurrentBounce.value = e;
|
|
@@ -10839,20 +10829,11 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
10839
10829
|
let n = e - 1, i;
|
|
10840
10830
|
n < f && d[n] !== void 0 ? i = d[n] : f > 0 && (i = d[f - 1]), t = i > 0 ? i : r;
|
|
10841
10831
|
} else e === 0 && i && (t = o);
|
|
10842
|
-
let n = Math.min(r, Math.ceil(t * 1.5) + 1024)
|
|
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);
|
|
10832
|
+
let n = Math.min(r, Math.ceil(t * 1.5) + 1024);
|
|
10833
|
+
for (let e of nf) a.setDispatchForCount(e, n);
|
|
10848
10834
|
} else {
|
|
10849
10835
|
a.dispatch("enterFull");
|
|
10850
|
-
let e
|
|
10851
|
-
Math.ceil(r / 256),
|
|
10852
|
-
1,
|
|
10853
|
-
1
|
|
10854
|
-
];
|
|
10855
|
-
a.setDispatchCount("extend", e), a.setDispatchCount("shade", e), a.setDispatchCount("compact", e), a.setDispatchCount("globalHist", e), a.setDispatchCount("globalScatter", e);
|
|
10836
|
+
for (let e of nf) a.setDispatchForCount(e, r);
|
|
10856
10837
|
}
|
|
10857
10838
|
if (a.dispatch("extend"), this._sortMaterials && (a.dispatch("resetGlobalHist"), a.dispatch("globalHist"), a.dispatch("globalPrefix"), a.dispatch("globalScatter")), a.dispatch("shade"), a.dispatch("compact"), t ? a.dispatch("compactCopyback") : a.dispatch("snapshotBounceCount"), e < f && e < s && d[e] !== void 0 && d[e] <= this._bounceEarlyExitThreshold) break;
|
|
10858
10839
|
}
|
|
@@ -10962,7 +10943,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
10962
10943
|
let d = Te(this._streakAttr, "uint"), m = Te(this._streakAttr, "uint").toReadOnly();
|
|
10963
10944
|
_l(this.renderer, this._frozenMaskAttr), this._frozenMaskAttr = new o(new Uint32Array(l), 1);
|
|
10964
10945
|
let g = Te(this._frozenMaskAttr, "uint"), _ = Te(this._frozenMaskAttr, "uint").toReadOnly();
|
|
10965
|
-
this._queueManager ? this._queueManager.resize(this._packedBuffers.capacity) : this._queueManager = new iu(this._packedBuffers.capacity, this.renderer), this._kernelManager ||= new
|
|
10946
|
+
this._queueManager ? this._queueManager.resize(this._packedBuffers.capacity) : this._queueManager = new iu(this._packedBuffers.capacity, this.renderer), this._kernelManager ||= new fu(this.renderer);
|
|
10966
10947
|
let v = this._packedBuffers, y = this._queueManager;
|
|
10967
10948
|
this._wfRenderWidth.value = t, this._wfRenderHeight.value = n, this._wfMaxRayCount.value = Math.min(r, this._chunkRows * t);
|
|
10968
10949
|
let b = this.shaderBuilder.prevColorTexNode, w = this.shaderBuilder.prevAlbedoTexNode, T = this.shaderBuilder.prevNormalDepthTexNode, E = this.storageTextures.getWriteTextures(), D = y.getCounters(), O = y.getBounceCounts(), k = this._wfCurrentBounce, A = f(() => {
|
|
@@ -10989,11 +10970,11 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
10989
10970
|
});
|
|
10990
10971
|
});
|
|
10991
10972
|
this._kernelManager.register("initActiveIndices", te().compute([
|
|
10992
|
-
Math.ceil(this._chunkRows * t /
|
|
10973
|
+
Math.ceil(this._chunkRows * t / tf),
|
|
10993
10974
|
1,
|
|
10994
10975
|
1
|
|
10995
10976
|
], [
|
|
10996
|
-
|
|
10977
|
+
tf,
|
|
10997
10978
|
1,
|
|
10998
10979
|
1
|
|
10999
10980
|
]));
|
|
@@ -11005,6 +10986,10 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11005
10986
|
frame: this.seedFrame,
|
|
11006
10987
|
cameraWorldMatrix: this.cameraWorldMatrix,
|
|
11007
10988
|
cameraProjectionMatrixInverse: this.cameraProjectionMatrixInverse,
|
|
10989
|
+
cameraProjection: this.cameraProjection,
|
|
10990
|
+
panoLonRange: this.panoLonRange,
|
|
10991
|
+
panoLatRange: this.panoLatRange,
|
|
10992
|
+
panoLevelHorizon: this.panoLevelHorizon,
|
|
11008
10993
|
enableDOF: this.enableDOF,
|
|
11009
10994
|
focalLength: this.focalLength,
|
|
11010
10995
|
aperture: this.aperture,
|
|
@@ -11019,7 +11004,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11019
11004
|
transmissiveBounces: this.transmissiveBounces,
|
|
11020
11005
|
transparentBackground: this.transparentBackground,
|
|
11021
11006
|
auxGBufferEnabled: this._auxGBufferUniform
|
|
11022
|
-
}, ne =
|
|
11007
|
+
}, ne = hu(j);
|
|
11023
11008
|
this._kernelManager.register("generate", ne().compute([
|
|
11024
11009
|
Math.ceil(t / 16),
|
|
11025
11010
|
Math.ceil(this._chunkRows / 16),
|
|
@@ -11031,7 +11016,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11031
11016
|
]));
|
|
11032
11017
|
let re = this.pixelFreezeStability, ie = f(() => {
|
|
11033
11018
|
C(D.element(z(nu.ACTIVE_RAY_COUNT)), z(0)), p(this._wfIsFirstChunk.greaterThan(z(0)), () => {
|
|
11034
|
-
C(D.element(z(nu.CONVERGED_COUNT)), z(0))
|
|
11019
|
+
C(D.element(z(nu.CONVERGED_COUNT)), z(0));
|
|
11035
11020
|
});
|
|
11036
11021
|
});
|
|
11037
11022
|
this._kernelManager.register("resetFrameCounters", ie().compute([
|
|
@@ -11075,11 +11060,11 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11075
11060
|
});
|
|
11076
11061
|
});
|
|
11077
11062
|
this._kernelManager.register("buildActivePixels", P().compute([
|
|
11078
|
-
Math.ceil(this._chunkRows * t /
|
|
11063
|
+
Math.ceil(this._chunkRows * t / tf),
|
|
11079
11064
|
1,
|
|
11080
11065
|
1
|
|
11081
11066
|
], [
|
|
11082
|
-
|
|
11067
|
+
tf,
|
|
11083
11068
|
1,
|
|
11084
11069
|
1
|
|
11085
11070
|
]));
|
|
@@ -11096,18 +11081,18 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11096
11081
|
1,
|
|
11097
11082
|
1
|
|
11098
11083
|
]));
|
|
11099
|
-
let oe =
|
|
11084
|
+
let oe = hu({
|
|
11100
11085
|
...j,
|
|
11101
11086
|
listDriven: !0,
|
|
11102
11087
|
activeIndicesRO: y.activeIndicesRO.a,
|
|
11103
11088
|
counters: D
|
|
11104
11089
|
});
|
|
11105
11090
|
this._kernelManager.register("generateList", oe().compute([
|
|
11106
|
-
Math.ceil(i /
|
|
11091
|
+
Math.ceil(i / tf),
|
|
11107
11092
|
1,
|
|
11108
11093
|
1
|
|
11109
11094
|
], [
|
|
11110
|
-
|
|
11095
|
+
tf,
|
|
11111
11096
|
1,
|
|
11112
11097
|
1
|
|
11113
11098
|
]));
|
|
@@ -11123,7 +11108,6 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11123
11108
|
let he = ku({
|
|
11124
11109
|
bvhBuffer: se,
|
|
11125
11110
|
triangleBuffer: ce,
|
|
11126
|
-
materialBuffer: le,
|
|
11127
11111
|
rayBufferRO: v.rayBuffer.ro,
|
|
11128
11112
|
hitBufferRW: v.hitBuffer.rw,
|
|
11129
11113
|
activeIndicesRO: y.getActiveReadRO(),
|
|
@@ -11304,11 +11288,11 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11304
11288
|
}), L.element(e).assign(be.element(e));
|
|
11305
11289
|
});
|
|
11306
11290
|
this._kernelManager.register("compactCopyback", xe().compute([
|
|
11307
|
-
Math.ceil(i /
|
|
11291
|
+
Math.ceil(i / tf),
|
|
11308
11292
|
1,
|
|
11309
11293
|
1
|
|
11310
11294
|
], [
|
|
11311
|
-
|
|
11295
|
+
tf,
|
|
11312
11296
|
1,
|
|
11313
11297
|
1
|
|
11314
11298
|
]));
|
|
@@ -11340,7 +11324,6 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11340
11324
|
adaptiveMinSamples: this.adaptiveMinSamples,
|
|
11341
11325
|
usePixelFreeze: this.usePixelFreeze,
|
|
11342
11326
|
pixelFreezeThreshold: this.pixelFreezeThreshold,
|
|
11343
|
-
pixelFreezeStability: this.pixelFreezeStability,
|
|
11344
11327
|
streakBufferRW: d,
|
|
11345
11328
|
frozenMaskRO: _,
|
|
11346
11329
|
chunkRowBase: this._wfChunkRowBase,
|
|
@@ -11366,6 +11349,10 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11366
11349
|
cameraProjectionMatrixInverse: this.cameraProjectionMatrixInverse,
|
|
11367
11350
|
cameraProjectionMatrix: this.cameraProjectionMatrix,
|
|
11368
11351
|
cameraViewMatrix: this.cameraViewMatrix,
|
|
11352
|
+
cameraProjection: this.cameraProjection,
|
|
11353
|
+
panoLonRange: this.panoLonRange,
|
|
11354
|
+
panoLatRange: this.panoLatRange,
|
|
11355
|
+
panoLevelHorizon: this.panoLevelHorizon,
|
|
11369
11356
|
enableDOF: this.enableDOF,
|
|
11370
11357
|
focalLength: this.focalLength,
|
|
11371
11358
|
aperture: this.aperture,
|
|
@@ -11403,43 +11390,23 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11403
11390
|
}
|
|
11404
11391
|
_setWfDispatch() {
|
|
11405
11392
|
let e = this._wfRenderWidth.value, t = this._wfRenderHeight.value;
|
|
11406
|
-
this._kernelManager.
|
|
11407
|
-
Math.ceil(e / 16),
|
|
11408
|
-
Math.ceil(t / 16),
|
|
11409
|
-
1
|
|
11410
|
-
]);
|
|
11393
|
+
this._kernelManager.setDispatchForGrid("debug", e, t);
|
|
11411
11394
|
}
|
|
11412
11395
|
_setChunk(e, t, n) {
|
|
11413
11396
|
let r = this._wfRenderWidth.value, i = t * r;
|
|
11414
11397
|
this._wfChunkRowBase.value = e, this._wfChunkRows.value = t, this._wfIsFirstChunk.value = +(n === 0), this._wfMaxRayCount.value = i;
|
|
11415
11398
|
let a = this._kernelManager;
|
|
11416
|
-
return a.
|
|
11417
|
-
Math.ceil(r / 16),
|
|
11418
|
-
Math.ceil(t / 16),
|
|
11419
|
-
1
|
|
11420
|
-
]), a.setDispatchCount("finalWrite", [
|
|
11421
|
-
Math.ceil(r / 16),
|
|
11422
|
-
Math.ceil(t / 16),
|
|
11423
|
-
1
|
|
11424
|
-
]), a.setDispatchCount("initActiveIndices", [
|
|
11425
|
-
Math.ceil(i / 256),
|
|
11426
|
-
1,
|
|
11427
|
-
1
|
|
11428
|
-
]), a.setDispatchCount("buildActivePixels", [
|
|
11429
|
-
Math.ceil(i / 256),
|
|
11430
|
-
1,
|
|
11431
|
-
1
|
|
11432
|
-
]), i;
|
|
11399
|
+
return a.setDispatchForGrid("generate", r, t), a.setDispatchForGrid("finalWrite", r, t), a.setDispatchForCount("initActiveIndices", i), a.setDispatchForCount("buildActivePixels", i), i;
|
|
11433
11400
|
}
|
|
11434
11401
|
dispose() {
|
|
11435
11402
|
super.dispose(), this._packedBuffers?.dispose(), this._queueManager?.dispose(), this._kernelManager?.dispose(), this._gBufferAttr?.dispose?.(), this._m2Attr?.dispose?.(), this._streakAttr?.dispose?.(), this._frozenMaskAttr?.dispose?.(), this._packedBuffers = null, this._queueManager = null, this._kernelManager = null, this._gBufferAttr = null, this._m2Attr = null, this._streakAttr = null, this._frozenMaskAttr = null, this._wavefrontReady = !1;
|
|
11436
11403
|
}
|
|
11437
|
-
},
|
|
11404
|
+
}, af = class extends lr {
|
|
11438
11405
|
constructor(e, t = {}) {
|
|
11439
11406
|
super("NormalDepth", {
|
|
11440
11407
|
...t,
|
|
11441
11408
|
executionMode: cr.ALWAYS
|
|
11442
|
-
}), this.renderer = e, this.pathTracer = t.pathTracer, this._dirty = !0, this.cameraWorldMatrix = B(new Ct(), "mat4"), this.cameraProjectionMatrixInverse = B(new Ct(), "mat4"), this.resolutionWidth = B(t.width || 1), this.resolutionHeight = B(t.height || 1);
|
|
11409
|
+
}), this.renderer = e, this.pathTracer = t.pathTracer, this._dirty = !0, this.cameraWorldMatrix = B(new Ct(), "mat4"), this.cameraProjectionMatrixInverse = B(new Ct(), "mat4"), this.cameraProjection = B(0, "int"), this.panoLonRange = B(new sn(), "vec2"), this.panoLatRange = B(new sn(), "vec2"), this.panoLevelHorizon = B(1, "int"), this.resolutionWidth = B(t.width || 1), this.resolutionHeight = B(t.height || 1);
|
|
11443
11410
|
let n = t.width || 1, r = t.height || 1;
|
|
11444
11411
|
this._outputStorageTex = new s(Y, Y), this._outputStorageTex.type = ht, this._outputStorageTex.format = Bt, this._outputStorageTex.minFilter = Ot, this._outputStorageTex.magFilter = Ot, this._shadingStorageTex = new s(Y, Y), this._shadingStorageTex.type = ht, this._shadingStorageTex.format = Bt, this._shadingStorageTex.minFilter = Ot, this._shadingStorageTex.magFilter = Ot, this._shadingRT = new i(n, r, {
|
|
11445
11412
|
type: ht,
|
|
@@ -11479,18 +11446,18 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11479
11446
|
this._computeNode = f(([r, i]) => {
|
|
11480
11447
|
let l = N(He.x).mul(8).add(N(se.x)), u = N(He.y).mul(8).add(N(se.y));
|
|
11481
11448
|
p(l.lessThan(N(a)).and(u.lessThan(N(o))), () => {
|
|
11482
|
-
let d =
|
|
11449
|
+
let d = pu(H(j(l).add(.5).div(a), j(u).add(.5).div(o)), r, i, this.cameraProjection, this.panoLonRange, this.panoLatRange, this.panoLevelHorizon), f = ea({
|
|
11483
11450
|
origin: U(r[3]),
|
|
11484
|
-
direction:
|
|
11485
|
-
}),
|
|
11486
|
-
Ne(s, Re(z(l), z(u)),
|
|
11487
|
-
let
|
|
11488
|
-
p(
|
|
11489
|
-
let e = ta.wrap(za(
|
|
11490
|
-
|
|
11451
|
+
direction: d
|
|
11452
|
+
}), m = aa.wrap(Eu(f, t, e)), h = m.normal.mul(.5).add(.5), g = de(m.dst, j(65504)), _ = m.didHit.select(W(h, g), W(0, 0, 0, j(65504)));
|
|
11453
|
+
Ne(s, Re(z(l), z(u)), _).toWriteOnly();
|
|
11454
|
+
let v = m.normal.toVar();
|
|
11455
|
+
p(m.didHit, () => {
|
|
11456
|
+
let e = ta.wrap(za(m.materialIndex, n)).toVar(), t = pa.wrap(as(m.uv, e)).toVar(), r = cs(m.normal, e, t).toVar();
|
|
11457
|
+
v.assign(ls(r, e, t));
|
|
11491
11458
|
});
|
|
11492
|
-
let
|
|
11493
|
-
Ne(c, Re(z(l), z(u)),
|
|
11459
|
+
let y = m.didHit.select(W(v.mul(.5).add(.5), g), W(0, 0, 0, j(65504)));
|
|
11460
|
+
Ne(c, Re(z(l), z(u)), y).toWriteOnly();
|
|
11494
11461
|
});
|
|
11495
11462
|
})(r, i).compute([
|
|
11496
11463
|
this._dispatchX,
|
|
@@ -11506,7 +11473,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11506
11473
|
if (!this.enabled || !this._syncStorageBuffers()) return;
|
|
11507
11474
|
this._computeBuilt || this._buildCompute();
|
|
11508
11475
|
let t = this.pathTracer;
|
|
11509
|
-
if (t && (this.cameraWorldMatrix.value.copy(t.uniforms.get("cameraWorldMatrix").value), this.cameraProjectionMatrixInverse.value.copy(t.uniforms.get("cameraProjectionMatrixInverse").value)), !this._dirty && this._hasHistory) {
|
|
11476
|
+
if (t && (this.cameraWorldMatrix.value.copy(t.uniforms.get("cameraWorldMatrix").value), this.cameraProjectionMatrixInverse.value.copy(t.uniforms.get("cameraProjectionMatrixInverse").value), this.cameraProjection.value = t.uniforms.get("cameraProjection").value, this.panoLonRange.value.copy(t.uniforms.get("panoLonRange").value), this.panoLatRange.value.copy(t.uniforms.get("panoLatRange").value), this.panoLevelHorizon.value = t.uniforms.get("panoLevelHorizon").value), !this._dirty && this._hasHistory) {
|
|
11510
11477
|
let t = this._currentIdx === 0 ? this._rtA : this._rtB;
|
|
11511
11478
|
e.setTexture("pathtracer:normalDepth", t.texture), e.setTexture("pathtracer:prevNormalDepth", t.texture), e.setTexture("pathtracer:shadingNormal", this._shadingRT.texture);
|
|
11512
11479
|
return;
|
|
@@ -11544,7 +11511,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11544
11511
|
dispose() {
|
|
11545
11512
|
this._computeNode?.dispose(), this._outputStorageTex?.dispose(), this._shadingStorageTex?.dispose(), this._shadingRT?.dispose(), this._rtA?.dispose(), this._rtB?.dispose();
|
|
11546
11513
|
}
|
|
11547
|
-
},
|
|
11514
|
+
}, of = class extends lr {
|
|
11548
11515
|
constructor(e, t, n = {}) {
|
|
11549
11516
|
super("MotionVector", {
|
|
11550
11517
|
...n,
|
|
@@ -11664,7 +11631,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11664
11631
|
dispose() {
|
|
11665
11632
|
this._screenSpaceComputeNode?.dispose(), this._worldSpaceComputeNode?.dispose(), this._screenSpaceStorageTex?.dispose(), this._worldSpaceStorageTex?.dispose(), this.screenSpaceTarget?.dispose(), this.worldSpaceTarget?.dispose(), this._normalDepthTexNode?.dispose();
|
|
11666
11633
|
}
|
|
11667
|
-
},
|
|
11634
|
+
}, sf = (e) => L(e.equal(e), e, j(0)).clamp(0, 1e7), cf = (e) => U(sf(e.x), sf(e.y), sf(e.z)), lf = class extends lr {
|
|
11668
11635
|
constructor(e, t = {}) {
|
|
11669
11636
|
super("ASVGF", {
|
|
11670
11637
|
...t,
|
|
@@ -11705,7 +11672,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11705
11672
|
let e = this._colorTexNode, t = this._albedoTexNode, n = this._motionTexNode, r = this._readTemporalTexNode, i = this.gradientNoiseFloor, a = this.gradientSigmaScale, o = this._gradientStorageTex, s = this.resW, c = this.resH, l = Be("float", 144), u = Be("float", 144);
|
|
11706
11673
|
this._gradientNode = f(() => {
|
|
11707
11674
|
let d = se.x, f = se.y, m = f.mul(8).add(d), h = N(He.x).mul(8).sub(2).toVar(), g = N(He.y).mul(8).sub(2).toVar(), v = (i) => {
|
|
11708
|
-
let a = i.mod(z(12)), o = i.div(z(12)), d = h.add(N(a)).clamp(N(0), N(s).sub(1)), f = g.add(N(o)).clamp(N(0), N(c).sub(1)), p = R(e, P(d, f)).xyz, m = R(t, P(d, f)).xyz, _ = Oa(
|
|
11675
|
+
let a = i.mod(z(12)), o = i.div(z(12)), d = h.add(N(a)).clamp(N(0), N(s).sub(1)), f = g.add(N(o)).clamp(N(0), N(c).sub(1)), p = R(e, P(d, f)).xyz, m = R(t, P(d, f)).xyz, _ = Oa(cf(p.div(F(m, U(Er))))).toVar();
|
|
11709
11676
|
l.element(i).assign(_);
|
|
11710
11677
|
let v = R(n, P(d, f)), y = j(d).sub(v.x.mul(s)), b = j(f).sub(v.y.mul(c)), x = N(y.add(.5)).clamp(N(0), N(s).sub(1)), S = N(b.add(.5)).clamp(N(0), N(c).sub(1)), C = v.w.greaterThan(.5), w = R(r, P(x, S)).xyz, T = C.select(Oa(w), _);
|
|
11711
11678
|
u.element(i).assign(T);
|
|
@@ -11752,7 +11719,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11752
11719
|
return f(() => {
|
|
11753
11720
|
let f = N(He.x).mul(8).add(N(se.x)), y = N(He.y).mul(8).add(N(se.y));
|
|
11754
11721
|
p(f.lessThan(N(g)).and(y.lessThan(N(v))), () => {
|
|
11755
|
-
let b = P(f, y), x = R(t, b), S = x.xyz, C = x.w, w = R(n, b).xyz, T = F(w, U(Er)), E =
|
|
11722
|
+
let b = P(f, y), x = R(t, b), S = x.xyz, C = x.w, w = R(n, b).xyz, T = F(w, U(Er)), E = cf(S.div(T)), D = W(E, 1).toVar(), O = W(S, C).toVar();
|
|
11756
11723
|
p(m.greaterThan(.5).and(h.lessThan(.5)), () => {
|
|
11757
11724
|
let e = R(r, b), t = e.w.greaterThan(.5), n = j(f).sub(e.x.mul(g)), c = j(y).sub(e.y.mul(v)), m = n.greaterThanEqual(0).and(n.lessThan(j(g))).and(c.greaterThanEqual(0)).and(c.lessThan(j(v)));
|
|
11758
11725
|
p(t.and(m), () => {
|
|
@@ -11761,7 +11728,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11761
11728
|
return i.mul(l).mul(u);
|
|
11762
11729
|
}, se = oe(w, te, re), ce = oe(k, te, ie), le = oe(w, ne, M), ue = oe(k, ne, ae), pe = se.add(ce).add(le).add(ue);
|
|
11763
11730
|
p(pe.greaterThan(j(.01)), () => {
|
|
11764
|
-
let e = R(o, P(w, te)), t = R(o, P(k, te)), n = R(o, P(w, ne)), r = R(o, P(k, ne)), i = j(1).div(pe), a = e.xyz.mul(se).add(t.xyz.mul(ce)).add(n.xyz.mul(le)).add(r.xyz.mul(ue)).mul(i), c = e.w.mul(se).add(t.w.mul(ce)).add(n.w.mul(le)).add(r.w.mul(ue)).mul(i), f = R(s, b).x.mul(d).clamp(0, 1), p =
|
|
11731
|
+
let e = R(o, P(w, te)), t = R(o, P(k, te)), n = R(o, P(w, ne)), r = R(o, P(k, ne)), i = j(1).div(pe), a = e.xyz.mul(se).add(t.xyz.mul(ce)).add(n.xyz.mul(le)).add(r.xyz.mul(ue)).mul(i), c = e.w.mul(se).add(t.w.mul(ce)).add(n.w.mul(le)).add(r.w.mul(ue)).mul(i), f = R(s, b).x.mul(d).clamp(0, 1), p = cf(fe(a, E, fe(F(j(1).div(c.add(1)), u), j(1), f))), m = de(c.add(1), l);
|
|
11765
11732
|
D.assign(W(p, m)), O.assign(W(p.mul(T), C));
|
|
11766
11733
|
});
|
|
11767
11734
|
});
|
|
@@ -11879,7 +11846,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11879
11846
|
dispose() {
|
|
11880
11847
|
this._gradientNode?.dispose(), this._temporalNodeA?.dispose(), this._temporalNodeB?.dispose(), this._temporalTexA?.dispose(), this._temporalTexB?.dispose(), this._outputModulatedTex?.dispose(), this._gradientStorageTex?.dispose(), this._demodulatedRT?.dispose(), this._outputRT?.dispose(), this._gradientRT?.dispose(), this._heatmapComputeNode?.dispose(), this._heatmapStorageTex?.dispose(), this.heatmapTarget?.dispose(), this._colorTexNode?.dispose(), this._albedoTexNode?.dispose(), this._motionTexNode?.dispose(), this._normalDepthTexNode?.dispose(), this._prevNormalDepthTexNode?.dispose(), this._readTemporalTexNode?.dispose(), this._gradientReadTexNode?.dispose(), this._heatmapRawColorTexNode?.dispose(), this._heatmapColorTexNode?.dispose(), this._heatmapTemporalTexNode?.dispose(), this._heatmapNDTexNode?.dispose(), this._heatmapMotionTexNode?.dispose(), this._heatmapGradientTexNode?.dispose();
|
|
11881
11848
|
}
|
|
11882
|
-
},
|
|
11849
|
+
}, uf = (e) => L(e.equal(e), e, j(0)).clamp(0, 1e7), df = /* @__PURE__ */ G("\n fn temporalAccumulate(\n lum: f32,\n prevMean: f32,\n prevMeanSq: f32,\n alpha: f32,\n spatialVariance: f32,\n varianceBoost: f32\n ) -> vec4f {\n\n let newMean = prevMean + ( lum - prevMean ) * alpha;\n let newMeanSq = prevMeanSq + ( lum * lum - prevMeanSq ) * alpha;\n let temporalVariance = max( newMeanSq - newMean * newMean, 0.0 );\n\n return vec4f(\n newMean,\n newMeanSq,\n temporalVariance * varianceBoost,\n spatialVariance * varianceBoost\n );\n\n }\n"), ff = class extends lr {
|
|
11883
11850
|
constructor(e, t = {}) {
|
|
11884
11851
|
super("VarianceEstimation", {
|
|
11885
11852
|
...t,
|
|
@@ -11905,9 +11872,9 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11905
11872
|
let n = this._colorTexNode, r = this.temporalAlpha, i = this.varianceBoost, a = this.resW, o = this.resH, s = Be("float", 100);
|
|
11906
11873
|
return f(() => {
|
|
11907
11874
|
let c = se.x, l = se.y, u = l.mul(8).add(c), d = N(He.x).mul(8).sub(1), f = N(He.y).mul(8).sub(1), m = u.mod(10), h = u.div(10), g = R(n, P(d.add(N(m)).clamp(N(0), N(a).sub(1)), f.add(N(h)).clamp(N(0), N(o).sub(1)))).xyz;
|
|
11908
|
-
s.element(u).assign(
|
|
11875
|
+
s.element(u).assign(uf(Oa(g))), p(u.lessThan(z(36)), () => {
|
|
11909
11876
|
let e = u.add(z(64)), t = e.mod(10), r = e.div(10), i = R(n, P(d.add(N(t)).clamp(N(0), N(a).sub(1)), f.add(N(r)).clamp(N(0), N(o).sub(1)))).xyz;
|
|
11910
|
-
s.element(e).assign(
|
|
11877
|
+
s.element(e).assign(uf(Oa(i)));
|
|
11911
11878
|
}), Ve();
|
|
11912
11879
|
let _ = N(He.x).mul(8).add(N(c)), v = N(He.y).mul(8).add(N(l));
|
|
11913
11880
|
p(_.lessThan(N(a)).and(v.lessThan(N(o))), () => {
|
|
@@ -11918,7 +11885,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11918
11885
|
}
|
|
11919
11886
|
n.divAssign(9), a.divAssign(9);
|
|
11920
11887
|
let o = F(a.sub(n.mul(n)), j(0)), u = s.element(l.add(1).mul(10).add(c.add(1))), d = R(t, P(_, v));
|
|
11921
|
-
Ne(e, Re(z(_), z(v)),
|
|
11888
|
+
Ne(e, Re(z(_), z(v)), df(u, d.x, d.y, r, o, i)).toWriteOnly();
|
|
11922
11889
|
});
|
|
11923
11890
|
})().compute([
|
|
11924
11891
|
this._dispatchX,
|
|
@@ -11972,7 +11939,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
11972
11939
|
dispose() {
|
|
11973
11940
|
this._computeNodeA?.dispose(), this._computeNodeB?.dispose(), this._storageTexA?.dispose(), this._storageTexB?.dispose(), this._outputTarget?.dispose(), this._colorTexNode?.dispose(), this._readTexNodeA?.dispose(), this._readTexNodeB?.dispose();
|
|
11974
11941
|
}
|
|
11975
|
-
},
|
|
11942
|
+
}, pf = /* @__PURE__ */ G("\n fn bilateralWeight(\n centerLum: f32, sLum: f32,\n centerNormal: vec3f, sNormal: vec3f,\n centerDepth: f32, sDepth: f32,\n centerColor: vec3f, sColor: vec3f,\n kernelW: f32,\n sigmaL: f32, phiNorm: f32, phiDep: f32, phiCol: f32\n ) -> f32 {\n\n let lumW = exp( -abs( centerLum - sLum ) / sigmaL );\n // clamp dot to [0,1]: miss-ray normals decode to (-1,-1,-1) with\n // dot=3 → pow saturates to +inf → inf*0 = NaN. See project_tsl_pitfalls.\n // max(phiNorm, 1e-6): pow(0.0, 0.0) is undefined in WGSL and returned NaN on ~12%\n // of pixels when phiNormal was set to 0.\n let normW = pow( clamp( dot( centerNormal, sNormal ), 0.0, 1.0 ), max( phiNorm, 1e-6 ) );\n let depW = exp( -abs( centerDepth - sDepth ) / max( centerDepth * phiDep, 0.001 ) );\n let maxDiff = max( max( abs( centerColor.x - sColor.x ),\n abs( centerColor.y - sColor.y ) ),\n abs( centerColor.z - sColor.z ) );\n let avgLum = max( ( centerLum + sLum ) * 0.5, 0.0001 );\n let colW = exp( -( maxDiff / avgLum ) / max( phiCol, 0.0001 ) );\n return kernelW * lumW * normW * depW * colW;\n\n }\n"), mf = class extends lr {
|
|
11976
11943
|
constructor(e, t = {}) {
|
|
11977
11944
|
super("BilateralFiltering", {
|
|
11978
11945
|
...t,
|
|
@@ -12027,7 +11994,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12027
11994
|
return fe(t.z, F(t.z, t.w), d);
|
|
12028
11995
|
}, ee = k.select(A(p), x.w.mul(x.w)).toVar(), te = u.mul(we(F(ee, j(0)))).div(O).add(j(1e-4)), ne = U(0).toVar(), re = j(0).toVar(), ie = j(0).toVar();
|
|
12029
11996
|
for (let e = 0; e < 5; e++) for (let i = 0; i < 5; i++) {
|
|
12030
|
-
let a = i - 2, o = e - 2, u = y[e * 5 + i], d = f.add(m.mul(a)).clamp(N(0), N(_).sub(1)), p = b.add(m.mul(o)).clamp(N(0), N(v).sub(1)), h = R(t, P(d, p)), g = h.xyz, x = R(n, P(d, p)), C = R(r, P(d, p)).xyz.mul(2).sub(1), D = x.w, O =
|
|
11997
|
+
let a = i - 2, o = e - 2, u = y[e * 5 + i], d = f.add(m.mul(a)).clamp(N(0), N(_).sub(1)), p = b.add(m.mul(o)).clamp(N(0), N(v).sub(1)), h = R(t, P(d, p)), g = h.xyz, x = R(n, P(d, p)), C = R(r, P(d, p)).xyz.mul(2).sub(1), D = x.w, O = pf(E, Oa(g), w, C, T, D, S, g, j(u), te, c, l, s), ee = k.select(A(P(d, p)), h.w.mul(h.w));
|
|
12031
11998
|
ne.addAssign(g.mul(O)), re.addAssign(O), ie.addAssign(O.mul(O).mul(F(ee, j(0))));
|
|
12032
11999
|
}
|
|
12033
12000
|
let M = ne.div(F(re, j(1e-4))), ae = ie.div(F(re.mul(re), j(1e-8))), oe = h.equal(N(1)), se = oe.select(M.mul(D), M), ce = oe.select(R(o, p).w, we(F(ae, j(0))));
|
|
@@ -12086,7 +12053,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12086
12053
|
dispose() {
|
|
12087
12054
|
this._computeNodeA?.dispose(), this._computeNodeB?.dispose(), this._storageTexA?.dispose(), this._storageTexB?.dispose(), this._outputTarget?.dispose(), this._readTexNode?.dispose(), this._normalDepthTexNode?.dispose(), this._shadingNormalTexNode?.dispose(), this._albedoTexNode?.dispose(), this._varianceTexNode?.dispose(), this._srcAlphaTexNode?.dispose();
|
|
12088
12055
|
}
|
|
12089
|
-
},
|
|
12056
|
+
}, hf = 6e4, gf = (e) => L(e.equal(e), e, j(0)).clamp(0, 1e7), _f = (e) => U(gf(e.x), gf(e.y), gf(e.z)), vf = [
|
|
12090
12057
|
1 / 256,
|
|
12091
12058
|
4 / 256,
|
|
12092
12059
|
6 / 256,
|
|
@@ -12112,7 +12079,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12112
12079
|
6 / 256,
|
|
12113
12080
|
4 / 256,
|
|
12114
12081
|
1 / 256
|
|
12115
|
-
],
|
|
12082
|
+
], yf = class extends lr {
|
|
12116
12083
|
constructor(e, t = {}) {
|
|
12117
12084
|
super("EdgeAwareFiltering", {
|
|
12118
12085
|
...t,
|
|
@@ -12140,7 +12107,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12140
12107
|
return f(() => {
|
|
12141
12108
|
let o = N(He.x).mul(16).add(N(se.x)), s = N(He.y).mul(16).add(N(se.y));
|
|
12142
12109
|
p(o.lessThan(N(i)).and(s.lessThan(N(a))), () => {
|
|
12143
|
-
let i = P(o, s), a = R(e, i).xyz, c = R(t, i).w.lessThan(j(
|
|
12110
|
+
let i = P(o, s), a = R(e, i).xyz, c = R(t, i).w.lessThan(j(hf)), l = R(n, i).xyz, u = L(c, F(l, U(Er)), U(1)), d = _f(a.div(u));
|
|
12144
12111
|
Ne(r, Re(z(o), z(s)), W(d, 1)).toWriteOnly();
|
|
12145
12112
|
});
|
|
12146
12113
|
})().compute([
|
|
@@ -12158,12 +12125,12 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12158
12125
|
return f(() => {
|
|
12159
12126
|
let f = N(He.x).mul(16).add(N(se.x)), v = N(He.y).mul(16).add(N(se.y));
|
|
12160
12127
|
p(f.lessThan(N(g)).and(v.lessThan(N(_))), () => {
|
|
12161
|
-
let p = P(f, v), y = R(t, p), b = y.xyz, x = Oa(b), S = R(r, p).w, C = R(i, p).xyz.mul(2).sub(1), w = S.lessThan(j(
|
|
12128
|
+
let p = P(f, v), y = R(t, p), b = y.xyz, x = Oa(b), S = R(r, p).w, C = R(i, p).xyz.mul(2).sub(1), w = S.lessThan(j(hf)), T = L(w, j(1), j(0)), E = R(a, p).xyz, D = L(w, F(E, U(Er)), U(1)), O = F(Oa(D), j(Er)), k = h.equal(N(1)), ee = (e) => {
|
|
12162
12129
|
let t = R(o, e);
|
|
12163
12130
|
return F(t.z, t.w);
|
|
12164
12131
|
}, te = k.select(ee(p), y.w.mul(y.w)).toVar(), ne = c.mul(we(F(te, j(0)))).div(O).add(j(1e-4)), re = U(0).toVar(), ie = j(0).toVar(), M = j(0).toVar();
|
|
12165
12132
|
for (let e = 0; e < 5; e++) for (let n = 0; n < 5; n++) {
|
|
12166
|
-
let a = n - 2, o = e - 2, s =
|
|
12133
|
+
let a = n - 2, o = e - 2, s = vf[e * 5 + n], c = P(f.add(d.mul(a)).clamp(N(0), N(g).sub(1)), v.add(d.mul(o)).clamp(N(0), N(_).sub(1))), p = R(t, c), m = p.xyz, h = Oa(m), y = R(r, c).w, b = R(i, c).xyz.mul(2).sub(1), w = L(y.lessThan(j(hf)), j(1), j(0)), E = x.sub(h).abs().div(ne).negate().exp(), D = _e(A(C, b).clamp(0, 1), l), O = S.sub(y).abs().div(F(S.mul(u), j(.001))).negate().exp(), te = T.mul(w), ae = T.oneMinus().mul(w.oneMinus()), oe = te.add(ae), se = fe(j(1), D.mul(O), te), ce = j(s).mul(E).mul(se).mul(oe), le = k.select(ee(c), p.w.mul(p.w));
|
|
12167
12134
|
re.addAssign(m.mul(ce)), ie.addAssign(ce), M.addAssign(ce.mul(ce).mul(F(le, j(0))));
|
|
12168
12135
|
}
|
|
12169
12136
|
let ae = re.div(F(ie, j(1e-4))), oe = M.div(F(ie.mul(ie), j(1e-8))), se = m.equal(N(1)), ce = R(n, p).xyz, le = fe(ce, ae.mul(D), s), ue = se.select(le, ae), de = se.select(R(n, p).w, we(F(oe, j(0))));
|
|
@@ -12225,7 +12192,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12225
12192
|
dispose() {
|
|
12226
12193
|
this._computeDemod?.dispose(), this._computeAtrousA?.dispose(), this._computeAtrousB?.dispose(), this._demodTex?.dispose(), this._storageTexA?.dispose(), this._storageTexB?.dispose(), this.outputTarget?.dispose(), this._colorTexNode?.dispose(), this._ndTexNode?.dispose(), this._snTexNode?.dispose(), this._albedoTexNode?.dispose(), this._varTexNode?.dispose(), this._readTexNode?.dispose();
|
|
12227
12194
|
}
|
|
12228
|
-
},
|
|
12195
|
+
}, bf = 256, xf = -8, Sf = 6 - xf, Cf = Sf / bf, wf = 1e4, Tf = /* @__PURE__ */ G("\n fn adaptExposure(\n geoMean: f32,\n prevExposure: f32,\n keyValue: f32,\n minExp: f32,\n maxExp: f32,\n speedBright: f32,\n speedDark: f32,\n dt: f32,\n isFirstFrame: f32\n ) -> vec4f {\n\n let targetExp = clamp( keyValue / max( geoMean, 0.001 ), minExp, maxExp );\n var newExposure = targetExp;\n\n // Temporal smoothing (skip on first frame)\n if ( isFirstFrame < 0.5 ) {\n\n // Asymmetric speed: brighter scenes adapt faster\n let speed = select( speedDark, speedBright, targetExp < prevExposure );\n let alpha = 1.0 - exp( -dt * speed );\n newExposure = mix( prevExposure, targetExp, alpha );\n\n }\n\n return vec4f( newExposure, geoMean, targetExp, 1.0 );\n\n }\n"), Ef = class extends lr {
|
|
12229
12196
|
constructor(e, t = {}) {
|
|
12230
12197
|
super("AutoExposure", {
|
|
12231
12198
|
...t,
|
|
@@ -12241,7 +12208,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12241
12208
|
depthBuffer: !1,
|
|
12242
12209
|
stencilBuffer: !1
|
|
12243
12210
|
};
|
|
12244
|
-
this._downsampleTarget = new i(this.REDUCTION_SIZE, this.REDUCTION_SIZE, e), this._downsampleStorageTex = new s(this.REDUCTION_SIZE, this.REDUCTION_SIZE), this._downsampleStorageTex.type = ft, this._downsampleStorageTex.format = Bt, this._downsampleStorageTex.minFilter = Ot, this._downsampleStorageTex.magFilter = Ot, this._reductionStorageTex = new s(1, 1), this._reductionStorageTex.type = ft, this._reductionStorageTex.format = Bt, this._reductionStorageTex.minFilter = Ot, this._reductionStorageTex.magFilter = Ot, this._reductionReadTarget = new i(1, 1, e), this._adaptationResult = w(1, "vec4"), this._readbackBuffer = new n(16), this._readbackBuffer.name = "AutoExposureAdaptation", this._histogramBuffer = w(
|
|
12211
|
+
this._downsampleTarget = new i(this.REDUCTION_SIZE, this.REDUCTION_SIZE, e), this._downsampleStorageTex = new s(this.REDUCTION_SIZE, this.REDUCTION_SIZE), this._downsampleStorageTex.type = ft, this._downsampleStorageTex.format = Bt, this._downsampleStorageTex.minFilter = Ot, this._downsampleStorageTex.magFilter = Ot, this._reductionStorageTex = new s(1, 1), this._reductionStorageTex.type = ft, this._reductionStorageTex.format = Bt, this._reductionStorageTex.minFilter = Ot, this._reductionStorageTex.magFilter = Ot, this._reductionReadTarget = new i(1, 1, e), this._adaptationResult = w(1, "vec4"), this._readbackBuffer = new n(16), this._readbackBuffer.name = "AutoExposureAdaptation", this._histogramBuffer = w(bf, "uint").toAtomic();
|
|
12245
12212
|
}
|
|
12246
12213
|
_buildCompute() {
|
|
12247
12214
|
this._buildDownsampleCompute(), this._buildHistogramCompute(), this._buildHistogramAnalyzeCompute(), this._buildAdaptationCompute();
|
|
@@ -12275,7 +12242,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12275
12242
|
for (let i = 0; i < 16; i++) {
|
|
12276
12243
|
let a = r.mul(16).add(i), o = a.mod(64), s = a.div(64), c = R(e, P(N(o), N(s))), l = c.x, u = c.y;
|
|
12277
12244
|
p(u.greaterThan(0), () => {
|
|
12278
|
-
let e = z(l.div(u).sub(j(
|
|
12245
|
+
let e = z(l.div(u).sub(j(xf)).div(j(Sf)).mul(j(bf)).floor().clamp(0, j(bf - 1))), r = j(o).add(.5).div(j(64)), i = j(s).add(.5).div(j(64)), a = r.sub(.5), c = i.sub(.5), d = z(a.mul(a).add(c.mul(c)).mul(n).negate().exp().mul(j(wf)));
|
|
12279
12246
|
x(t.element(e), d);
|
|
12280
12247
|
});
|
|
12281
12248
|
}
|
|
@@ -12293,14 +12260,14 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12293
12260
|
let e = this._histogramBuffer, t = this._reductionStorageTex, n = this.lowPercentileU, r = this.highPercentileU;
|
|
12294
12261
|
this._histogramAnalyzeNode = f(() => {
|
|
12295
12262
|
let i = j(0).toVar();
|
|
12296
|
-
m(
|
|
12263
|
+
m(bf, ({ i: t }) => {
|
|
12297
12264
|
i.addAssign(j(S(e.element(t))));
|
|
12298
12265
|
});
|
|
12299
12266
|
let a = i.mul(n), o = i.mul(r), s = j(0).toVar(), c = j(0).toVar(), l = j(0).toVar(), u = j(0).toVar();
|
|
12300
|
-
m(
|
|
12267
|
+
m(bf, ({ i: t }) => {
|
|
12301
12268
|
let n = j(S(e.element(t)));
|
|
12302
12269
|
u.assign(s), s.addAssign(n), p(u.lessThan(o).and(s.greaterThan(a)), () => {
|
|
12303
|
-
let e = j(
|
|
12270
|
+
let e = j(xf).add(j(t).add(.5).mul(j(Cf)));
|
|
12304
12271
|
c.addAssign(e.mul(n)), l.addAssign(n);
|
|
12305
12272
|
});
|
|
12306
12273
|
});
|
|
@@ -12315,7 +12282,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12315
12282
|
_buildAdaptationCompute() {
|
|
12316
12283
|
let e = this._reductionReadTexNode, t = this._adaptationResult, n = this.keyValueU, r = this.minExposureU, i = this.maxExposureU, a = this.adaptSpeedBrightU, o = this.adaptSpeedDarkU, s = this.deltaTimeU, c = this.isFirstFrameU, l = this.previousExposureU;
|
|
12317
12284
|
this._adaptationComputeNode = f(() => {
|
|
12318
|
-
let u = R(e, P(N(0), N(0))).x, d =
|
|
12285
|
+
let u = R(e, P(N(0), N(0))).x, d = Tf(u, l, n, r, i, a, o, s, c);
|
|
12319
12286
|
t.element(z(0)).assign(d);
|
|
12320
12287
|
})().compute(1, [
|
|
12321
12288
|
1,
|
|
@@ -12379,7 +12346,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12379
12346
|
dispose() {
|
|
12380
12347
|
this._downsampleComputeNode?.dispose(), this._histogramComputeNode?.dispose(), this._histogramAnalyzeNode?.dispose(), this._adaptationComputeNode?.dispose(), this._downsampleTarget?.dispose(), this._downsampleStorageTex?.dispose(), this._reductionStorageTex?.dispose(), this._reductionReadTarget?.dispose(), this._readbackBuffer?.dispose(), this._inputTexNode?.dispose(), this._reductionReadTexNode?.dispose();
|
|
12381
12348
|
}
|
|
12382
|
-
},
|
|
12349
|
+
}, Df = class extends lr {
|
|
12383
12350
|
constructor(n, r = {}) {
|
|
12384
12351
|
super("Compositor", {
|
|
12385
12352
|
...r,
|
|
@@ -12405,7 +12372,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12405
12372
|
dispose() {
|
|
12406
12373
|
this._sourceTexNode?.dispose(), this.compositorMaterial?.dispose(), this.compositorQuad = null;
|
|
12407
12374
|
}
|
|
12408
|
-
},
|
|
12375
|
+
}, Of = class {
|
|
12409
12376
|
constructor() {
|
|
12410
12377
|
this.textures = /* @__PURE__ */ new Map(), this.renderTargets = /* @__PURE__ */ new Map(), this.uniforms = /* @__PURE__ */ new Map(), this.state = {
|
|
12411
12378
|
frame: 0,
|
|
@@ -12527,7 +12494,7 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12527
12494
|
dispose() {
|
|
12528
12495
|
this.textures.clear(), this.renderTargets.clear(), this.uniforms.clear(), this._stateChangeCallbacks.clear(), this.state = {};
|
|
12529
12496
|
}
|
|
12530
|
-
},
|
|
12497
|
+
}, kf = class extends ut {
|
|
12531
12498
|
constructor() {
|
|
12532
12499
|
super(), this._onceCallbacks = /* @__PURE__ */ new Map();
|
|
12533
12500
|
}
|
|
@@ -12565,38 +12532,38 @@ var ef = ai("wavefront"), tf = class extends dl {
|
|
|
12565
12532
|
eventNames() {
|
|
12566
12533
|
return this._listeners ? Object.keys(this._listeners) : [];
|
|
12567
12534
|
}
|
|
12568
|
-
},
|
|
12569
|
-
function
|
|
12570
|
-
|
|
12535
|
+
}, Af = !1, jf = [], Mf = /* @__PURE__ */ new WeakMap();
|
|
12536
|
+
function Nf(e) {
|
|
12537
|
+
Af = !!e;
|
|
12571
12538
|
}
|
|
12572
|
-
function
|
|
12573
|
-
return
|
|
12539
|
+
function Pf() {
|
|
12540
|
+
return jf.slice();
|
|
12574
12541
|
}
|
|
12575
|
-
function
|
|
12576
|
-
|
|
12542
|
+
function Ff() {
|
|
12543
|
+
jf.length = 0;
|
|
12577
12544
|
}
|
|
12578
|
-
function
|
|
12545
|
+
function If(e) {
|
|
12579
12546
|
let t = [];
|
|
12580
12547
|
for (let n of Object.keys(e)) e[n]?.isTextureNode === !0 && t.push(n);
|
|
12581
12548
|
return t;
|
|
12582
12549
|
}
|
|
12583
|
-
var
|
|
12584
|
-
function
|
|
12585
|
-
if (!
|
|
12550
|
+
var Lf = (e) => !e || !e.image || !(e.image.width > 0);
|
|
12551
|
+
function Rf(e, t, n) {
|
|
12552
|
+
if (!Af) {
|
|
12586
12553
|
n();
|
|
12587
12554
|
return;
|
|
12588
12555
|
}
|
|
12589
|
-
let r =
|
|
12556
|
+
let r = Mf.get(e);
|
|
12590
12557
|
if (r || (r = {
|
|
12591
12558
|
phase: "pending",
|
|
12592
12559
|
unboundAtCompile: []
|
|
12593
|
-
},
|
|
12594
|
-
n(), r.phase === "watch" &&
|
|
12560
|
+
}, Mf.set(e, r)), r.phase !== "pending") {
|
|
12561
|
+
n(), r.phase === "watch" && zf(e, r);
|
|
12595
12562
|
return;
|
|
12596
12563
|
}
|
|
12597
12564
|
let i = Object.prototype.hasOwnProperty.call(t, "compute"), a = t.compute;
|
|
12598
12565
|
t.compute = function(...t) {
|
|
12599
|
-
return r.phase === "pending" && (r.unboundAtCompile =
|
|
12566
|
+
return r.phase === "pending" && (r.unboundAtCompile = If(e).filter((t) => Lf(e[t].value)), r.phase = r.unboundAtCompile.length < 2 ? "done" : "watch"), a.apply(this, t);
|
|
12600
12567
|
};
|
|
12601
12568
|
try {
|
|
12602
12569
|
n();
|
|
@@ -12604,14 +12571,14 @@ function If(e, t, n) {
|
|
|
12604
12571
|
i ? t.compute = a : delete t.compute;
|
|
12605
12572
|
}
|
|
12606
12573
|
}
|
|
12607
|
-
function
|
|
12574
|
+
function zf(e, t) {
|
|
12608
12575
|
let n = [];
|
|
12609
12576
|
for (let r of t.unboundAtCompile) {
|
|
12610
12577
|
let t = e[r]?.value;
|
|
12611
|
-
if (
|
|
12578
|
+
if (Lf(t)) return;
|
|
12612
12579
|
t.isStorageTexture !== !0 && n.push(r);
|
|
12613
12580
|
}
|
|
12614
|
-
t.phase = "done", n.length !== 0 &&
|
|
12581
|
+
t.phase = "done", n.length !== 0 && jf.push({
|
|
12615
12582
|
stage: e.name,
|
|
12616
12583
|
nodes: n,
|
|
12617
12584
|
unboundAtCompile: t.unboundAtCompile.slice(),
|
|
@@ -12620,9 +12587,9 @@ function Lf(e, t) {
|
|
|
12620
12587
|
}
|
|
12621
12588
|
//#endregion
|
|
12622
12589
|
//#region src/Pipeline/RenderPipeline.js
|
|
12623
|
-
var
|
|
12590
|
+
var Bf = class {
|
|
12624
12591
|
constructor(e, t, n) {
|
|
12625
|
-
this.renderer = e, this.width = t, this.height = n, this.stages = [], this.context = new
|
|
12592
|
+
this.renderer = e, this.width = t, this.height = n, this.stages = [], this.context = new Of(), this.eventBus = new kf(), this.context.setState("width", t), this.context.setState("height", n), this.stats = {
|
|
12626
12593
|
enabled: !1,
|
|
12627
12594
|
logSkipped: !1,
|
|
12628
12595
|
timings: /* @__PURE__ */ new Map(),
|
|
@@ -12656,7 +12623,7 @@ var Rf = class {
|
|
|
12656
12623
|
}
|
|
12657
12624
|
try {
|
|
12658
12625
|
let n = this.stats.enabled ? performance.now() : 0;
|
|
12659
|
-
if (
|
|
12626
|
+
if (Rf(t, this.renderer, () => t.render(this.context, e)), this.stats.enabled) {
|
|
12660
12627
|
let e = performance.now() - n;
|
|
12661
12628
|
this.stats.timings.has(t.name) || this.stats.timings.set(t.name, []);
|
|
12662
12629
|
let r = this.stats.timings.get(t.name);
|
|
@@ -12754,7 +12721,7 @@ var Rf = class {
|
|
|
12754
12721
|
let e = this.getInfo();
|
|
12755
12722
|
console.group("[Pipeline] Info"), console.log("Stages:", e.stages), console.log("Context Textures:", e.textures), console.log("Context Render Targets:", e.renderTargets), console.log("Context Uniforms:", e.uniforms), console.log("Event Types:", e.events), console.log("State:", e.contextState), console.groupEnd();
|
|
12756
12723
|
}
|
|
12757
|
-
},
|
|
12724
|
+
}, Vf = class {
|
|
12758
12725
|
constructor() {
|
|
12759
12726
|
this.timeElapsed = 0, this.lastResetTime = performance.now(), this.renderCompleteDispatched = !1;
|
|
12760
12727
|
}
|
|
@@ -12776,7 +12743,7 @@ var Rf = class {
|
|
|
12776
12743
|
resumeFromPause() {
|
|
12777
12744
|
this.renderCompleteDispatched = !1, this.lastResetTime = performance.now() - this.timeElapsed * 1e3;
|
|
12778
12745
|
}
|
|
12779
|
-
},
|
|
12746
|
+
}, Hf = class extends ut {
|
|
12780
12747
|
constructor({ scene: e, camera: t, canvas: n, assetLoader: r, pathTracer: i, floorPlane: a }) {
|
|
12781
12748
|
super(), this.scene = e, this.camera = t, this.canvas = n, this.assetLoader = r, this.pathTracer = i, this.floorPlane = a, this.raycaster = new Ut(), this.focusMode = !1, this.focusPointIndicator = null, this.afPointPlacementMode = !1, this.handleAFPointClick = this.handleAFPointClick.bind(this), this.selectedObject = null, this.selectMode = !1, this.clickTimeout = null, this.mouseDownPosition = null, this.dragThreshold = 5, this.handleFocusClick = this.handleFocusClick.bind(this), this.handleSelectClick = this.handleSelectClick.bind(this), this.handleSelectDoubleClick = this.handleSelectDoubleClick.bind(this), this.handleMouseDown = this.handleMouseDown.bind(this), this.handleMouseUp = this.handleMouseUp.bind(this), this.handleContextMenu = this.handleContextMenu.bind(this), this.handleContextPointerDown = this.handleContextPointerDown.bind(this), this.handleContextPointerUp = this.handleContextPointerUp.bind(this), this.contextPointerDownPosition = null, this.canvas.addEventListener("pointerdown", this.handleContextPointerDown), this.canvas.addEventListener("pointerup", this.handleContextPointerUp), this.canvas.addEventListener("contextmenu", this.handleContextMenu), this._overlayManager = null, this._transformManager = null, this._appDispatch = null, this._orbitControls = null, this._helperScene = null;
|
|
12782
12749
|
}
|
|
@@ -13012,18 +12979,18 @@ var Rf = class {
|
|
|
13012
12979
|
dispose() {
|
|
13013
12980
|
this.canvas.removeEventListener("click", this.handleAFPointClick), this.canvas.removeEventListener("click", this.handleFocusClick), this.canvas.removeEventListener("mousedown", this.handleMouseDown), this.canvas.removeEventListener("mouseup", this.handleMouseUp), this.canvas.removeEventListener("click", this.handleSelectClick), this.canvas.removeEventListener("dblclick", this.handleSelectDoubleClick), this.canvas.removeEventListener("contextmenu", this.handleContextMenu), this.canvas.removeEventListener("pointerdown", this.handleContextPointerDown), this.canvas.removeEventListener("pointerup", this.handleContextPointerUp), this.clickTimeout &&= (clearTimeout(this.clickTimeout), null), this.mouseDownPosition = null, this.contextPointerDownPosition = null, this.focusPointIndicator &&= (this.scene.remove(this.focusPointIndicator), null), this.canvas.style.cursor = "auto", this.scene = null, this.camera = null, this.canvas = null, this.assetLoader = null, this.pathTracer = null, this.floorPlane = null, this.raycaster = null;
|
|
13014
12981
|
}
|
|
13015
|
-
},
|
|
12982
|
+
}, Uf = {
|
|
13016
12983
|
STRING: "string",
|
|
13017
12984
|
NUMBER: "number",
|
|
13018
12985
|
WORD: "word",
|
|
13019
12986
|
LBRACKET: "[",
|
|
13020
12987
|
RBRACKET: "]"
|
|
13021
|
-
},
|
|
13022
|
-
function
|
|
12988
|
+
}, Wf = (e) => e === " " || e === " " || e === "\n" || e === "\r" || e === "\f", Gf = (e) => e >= "0" && e <= "9", Kf = (e, t, n) => !!(Gf(e) || e === "." && Gf(t) || (e === "-" || e === "+") && (Gf(t) || t === "." && Gf(n)));
|
|
12989
|
+
function qf(e) {
|
|
13023
12990
|
let t = [], n = e.length, r = 0;
|
|
13024
12991
|
for (; r < n;) {
|
|
13025
12992
|
let i = e[r];
|
|
13026
|
-
if (
|
|
12993
|
+
if (Wf(i)) {
|
|
13027
12994
|
r++;
|
|
13028
12995
|
continue;
|
|
13029
12996
|
}
|
|
@@ -13032,11 +12999,11 @@ function Gf(e) {
|
|
|
13032
12999
|
continue;
|
|
13033
13000
|
}
|
|
13034
13001
|
if (i === "[") {
|
|
13035
|
-
t.push({ type:
|
|
13002
|
+
t.push({ type: Uf.LBRACKET }), r++;
|
|
13036
13003
|
continue;
|
|
13037
13004
|
}
|
|
13038
13005
|
if (i === "]") {
|
|
13039
|
-
t.push({ type:
|
|
13006
|
+
t.push({ type: Uf.RBRACKET }), r++;
|
|
13040
13007
|
continue;
|
|
13041
13008
|
}
|
|
13042
13009
|
if (i === "\"") {
|
|
@@ -13045,12 +13012,12 @@ function Gf(e) {
|
|
|
13045
13012
|
for (; r < n && e[r] !== "\"";) r++;
|
|
13046
13013
|
if (r >= n) throw Error("PBRT tokenizer: unterminated string literal");
|
|
13047
13014
|
t.push({
|
|
13048
|
-
type:
|
|
13015
|
+
type: Uf.STRING,
|
|
13049
13016
|
value: e.slice(i, r)
|
|
13050
13017
|
}), r++;
|
|
13051
13018
|
continue;
|
|
13052
13019
|
}
|
|
13053
|
-
if (
|
|
13020
|
+
if (Kf(i, e[r + 1], e[r + 2])) {
|
|
13054
13021
|
let i = r;
|
|
13055
13022
|
for (r++; r < n;) {
|
|
13056
13023
|
let t = e[r];
|
|
@@ -13060,16 +13027,16 @@ function Gf(e) {
|
|
|
13060
13027
|
let a = e.slice(i, r), o = Number(a);
|
|
13061
13028
|
if (Number.isNaN(o)) throw Error(`PBRT tokenizer: invalid number "${a}"`);
|
|
13062
13029
|
t.push({
|
|
13063
|
-
type:
|
|
13030
|
+
type: Uf.NUMBER,
|
|
13064
13031
|
value: o
|
|
13065
13032
|
});
|
|
13066
13033
|
continue;
|
|
13067
13034
|
}
|
|
13068
13035
|
{
|
|
13069
13036
|
let i = r;
|
|
13070
|
-
for (; r < n && !
|
|
13037
|
+
for (; r < n && !Wf(e[r]) && e[r] !== "\"" && e[r] !== "[" && e[r] !== "]" && e[r] !== "#";) r++;
|
|
13071
13038
|
t.push({
|
|
13072
|
-
type:
|
|
13039
|
+
type: Uf.WORD,
|
|
13073
13040
|
value: e.slice(i, r)
|
|
13074
13041
|
});
|
|
13075
13042
|
}
|
|
@@ -13078,7 +13045,7 @@ function Gf(e) {
|
|
|
13078
13045
|
}
|
|
13079
13046
|
//#endregion
|
|
13080
13047
|
//#region src/Processor/PBRT/PBRTMath.js
|
|
13081
|
-
function
|
|
13048
|
+
function Jf() {
|
|
13082
13049
|
return [
|
|
13083
13050
|
1,
|
|
13084
13051
|
0,
|
|
@@ -13098,7 +13065,7 @@ function Kf() {
|
|
|
13098
13065
|
1
|
|
13099
13066
|
];
|
|
13100
13067
|
}
|
|
13101
|
-
function
|
|
13068
|
+
function Yf(e, t) {
|
|
13102
13069
|
let n = e[0], r = e[1], i = e[2], a = e[3], o = e[4], s = e[5], c = e[6], l = e[7], u = e[8], d = e[9], f = e[10], p = e[11], m = e[12], h = e[13], g = e[14], _ = e[15], v = t[0], y = t[1], b = t[2], x = t[3], S = t[4], C = t[5], w = t[6], T = t[7], E = t[8], D = t[9], O = t[10], k = t[11], A = t[12], ee = t[13], te = t[14], j = t[15];
|
|
13103
13070
|
return [
|
|
13104
13071
|
n * v + o * y + u * b + m * x,
|
|
@@ -13119,7 +13086,7 @@ function qf(e, t) {
|
|
|
13119
13086
|
a * A + l * ee + p * te + _ * j
|
|
13120
13087
|
];
|
|
13121
13088
|
}
|
|
13122
|
-
function
|
|
13089
|
+
function Xf(e, t, n) {
|
|
13123
13090
|
return [
|
|
13124
13091
|
1,
|
|
13125
13092
|
0,
|
|
@@ -13139,7 +13106,7 @@ function Jf(e, t, n) {
|
|
|
13139
13106
|
1
|
|
13140
13107
|
];
|
|
13141
13108
|
}
|
|
13142
|
-
function
|
|
13109
|
+
function Zf(e, t, n) {
|
|
13143
13110
|
return [
|
|
13144
13111
|
e,
|
|
13145
13112
|
0,
|
|
@@ -13159,7 +13126,7 @@ function Yf(e, t, n) {
|
|
|
13159
13126
|
1
|
|
13160
13127
|
];
|
|
13161
13128
|
}
|
|
13162
|
-
function
|
|
13129
|
+
function Qf(e, t, n, r) {
|
|
13163
13130
|
let i = Math.hypot(t, n, r) || 1;
|
|
13164
13131
|
t /= i, n /= i, r /= i;
|
|
13165
13132
|
let a = e * Math.PI / 180, o = Math.cos(a), s = Math.sin(a), c = 1 - o, l = c * t * t + o, u = c * t * n - s * r, d = c * t * r + s * n, f = c * t * n + s * r, p = c * n * n + o, m = c * n * r - s * t;
|
|
@@ -13182,21 +13149,21 @@ function Xf(e, t, n, r) {
|
|
|
13182
13149
|
1
|
|
13183
13150
|
];
|
|
13184
13151
|
}
|
|
13185
|
-
function
|
|
13152
|
+
function $f(e, t) {
|
|
13186
13153
|
return [
|
|
13187
13154
|
e[0] - t[0],
|
|
13188
13155
|
e[1] - t[1],
|
|
13189
13156
|
e[2] - t[2]
|
|
13190
13157
|
];
|
|
13191
13158
|
}
|
|
13192
|
-
function
|
|
13159
|
+
function ep(e, t) {
|
|
13193
13160
|
return [
|
|
13194
13161
|
e[1] * t[2] - e[2] * t[1],
|
|
13195
13162
|
e[2] * t[0] - e[0] * t[2],
|
|
13196
13163
|
e[0] * t[1] - e[1] * t[0]
|
|
13197
13164
|
];
|
|
13198
13165
|
}
|
|
13199
|
-
function
|
|
13166
|
+
function tp(e) {
|
|
13200
13167
|
let t = Math.hypot(e[0], e[1], e[2]) || 1;
|
|
13201
13168
|
return [
|
|
13202
13169
|
e[0] / t,
|
|
@@ -13204,8 +13171,8 @@ function $f(e) {
|
|
|
13204
13171
|
e[2] / t
|
|
13205
13172
|
];
|
|
13206
13173
|
}
|
|
13207
|
-
function
|
|
13208
|
-
let r = $f(
|
|
13174
|
+
function np(e, t, n) {
|
|
13175
|
+
let r = tp($f(t, e)), i = tp(ep(tp(n), r)), a = ep(r, i);
|
|
13209
13176
|
return [
|
|
13210
13177
|
i[0],
|
|
13211
13178
|
i[1],
|
|
@@ -13225,9 +13192,9 @@ function ep(e, t, n) {
|
|
|
13225
13192
|
1
|
|
13226
13193
|
];
|
|
13227
13194
|
}
|
|
13228
|
-
function
|
|
13195
|
+
function rp(e) {
|
|
13229
13196
|
let t = e[0], n = e[1], r = e[2], i = e[3], a = e[4], o = e[5], s = e[6], c = e[7], l = e[8], u = e[9], d = e[10], f = e[11], p = e[12], m = e[13], h = e[14], g = e[15], _ = u * h * c - m * d * c + m * s * f - o * h * f - u * s * g + o * d * g, v = p * d * c - l * h * c - p * s * f + a * h * f + l * s * g - a * d * g, y = l * m * c - p * u * c + p * o * f - a * m * f - l * o * g + a * u * g, b = p * u * s - l * m * s - p * o * d + a * m * d + l * o * h - a * u * h, x = t * _ + n * v + r * y + i * b;
|
|
13230
|
-
if (x === 0) return
|
|
13197
|
+
if (x === 0) return Jf();
|
|
13231
13198
|
let S = 1 / x;
|
|
13232
13199
|
return [
|
|
13233
13200
|
_ * S,
|
|
@@ -13250,7 +13217,7 @@ function tp(e) {
|
|
|
13250
13217
|
}
|
|
13251
13218
|
//#endregion
|
|
13252
13219
|
//#region src/Processor/PBRT/PBRTParser.js
|
|
13253
|
-
var
|
|
13220
|
+
var ip = class {
|
|
13254
13221
|
constructor(e = {}) {
|
|
13255
13222
|
this.resolveInclude = e.resolveInclude || (() => {
|
|
13256
13223
|
throw Error("PBRTParser: Include used but no resolveInclude provided");
|
|
@@ -13264,14 +13231,14 @@ var np = class {
|
|
|
13264
13231
|
instances: [],
|
|
13265
13232
|
objects: /* @__PURE__ */ new Map(),
|
|
13266
13233
|
warnings: []
|
|
13267
|
-
}, this.ctm =
|
|
13234
|
+
}, this.ctm = Jf(), this.state = {
|
|
13268
13235
|
material: null,
|
|
13269
13236
|
areaLight: null,
|
|
13270
13237
|
reverseOrientation: !1
|
|
13271
13238
|
}, this.attributeStack = [], this.transformStack = [], this.coordSystems = /* @__PURE__ */ new Map(), this.currentObject = null, this.objectBeginCTM = null, this.dirStack = [""], this.tokens = [], this.pos = 0, this._warnedUnknown = /* @__PURE__ */ new Set();
|
|
13272
13239
|
}
|
|
13273
13240
|
parse(e, t = "") {
|
|
13274
|
-
return this.dirStack = [t], this._run(
|
|
13241
|
+
return this.dirStack = [t], this._run(qf(e)), this.ir;
|
|
13275
13242
|
}
|
|
13276
13243
|
_peek() {
|
|
13277
13244
|
return this.tokens[this.pos];
|
|
@@ -13281,12 +13248,12 @@ var np = class {
|
|
|
13281
13248
|
}
|
|
13282
13249
|
_expectNumber(e) {
|
|
13283
13250
|
let t = this._next();
|
|
13284
|
-
if (!t || t.type !==
|
|
13251
|
+
if (!t || t.type !== Uf.NUMBER) throw Error(`PBRT parser: expected number for ${e}, got ${t ? t.value : "EOF"}`);
|
|
13285
13252
|
return t.value;
|
|
13286
13253
|
}
|
|
13287
13254
|
_expectString(e) {
|
|
13288
13255
|
let t = this._next();
|
|
13289
|
-
if (!t || t.type !==
|
|
13256
|
+
if (!t || t.type !== Uf.STRING) throw Error(`PBRT parser: expected string for ${e}, got ${t ? t.value : "EOF"}`);
|
|
13290
13257
|
return t.value;
|
|
13291
13258
|
}
|
|
13292
13259
|
_readNumbers(e) {
|
|
@@ -13295,17 +13262,17 @@ var np = class {
|
|
|
13295
13262
|
return t;
|
|
13296
13263
|
}
|
|
13297
13264
|
_readBracketedOrBareNumbers(e) {
|
|
13298
|
-
if (this._peek() && this._peek().type ===
|
|
13265
|
+
if (this._peek() && this._peek().type === Uf.LBRACKET) {
|
|
13299
13266
|
this._next();
|
|
13300
13267
|
let e = [];
|
|
13301
|
-
for (; this._peek() && this._peek().type !==
|
|
13268
|
+
for (; this._peek() && this._peek().type !== Uf.RBRACKET;) e.push(this._expectNumber("transform element"));
|
|
13302
13269
|
return this._next(), e;
|
|
13303
13270
|
}
|
|
13304
13271
|
return this._readNumbers(e);
|
|
13305
13272
|
}
|
|
13306
13273
|
_parseParams() {
|
|
13307
13274
|
let e = {};
|
|
13308
|
-
for (; this._peek() && this._peek().type ===
|
|
13275
|
+
for (; this._peek() && this._peek().type === Uf.STRING;) {
|
|
13309
13276
|
let t = this._next().value.trim().split(/\s+/), n = t[0], r = t[1] === void 0 ? t[0] : t[1];
|
|
13310
13277
|
e[r] = {
|
|
13311
13278
|
type: n,
|
|
@@ -13316,23 +13283,23 @@ var np = class {
|
|
|
13316
13283
|
}
|
|
13317
13284
|
_parseParamValue() {
|
|
13318
13285
|
let e = [];
|
|
13319
|
-
if (this._peek() && this._peek().type ===
|
|
13320
|
-
for (this._next(); this._peek() && this._peek().type !==
|
|
13286
|
+
if (this._peek() && this._peek().type === Uf.LBRACKET) {
|
|
13287
|
+
for (this._next(); this._peek() && this._peek().type !== Uf.RBRACKET;) e.push(this._coerceValueToken(this._next()));
|
|
13321
13288
|
this._next();
|
|
13322
13289
|
} else e.push(this._coerceValueToken(this._next()));
|
|
13323
13290
|
return e;
|
|
13324
13291
|
}
|
|
13325
13292
|
_coerceValueToken(e) {
|
|
13326
13293
|
if (!e) throw Error("PBRT parser: unexpected EOF in parameter value");
|
|
13327
|
-
if (e.type ===
|
|
13328
|
-
if (e.type ===
|
|
13294
|
+
if (e.type === Uf.NUMBER || e.type === Uf.STRING) return e.value;
|
|
13295
|
+
if (e.type === Uf.WORD) return e.value === "true" ? !0 : e.value === "false" ? !1 : e.value;
|
|
13329
13296
|
throw Error(`PBRT parser: unexpected token in parameter value: ${e.type}`);
|
|
13330
13297
|
}
|
|
13331
13298
|
_run(e) {
|
|
13332
13299
|
let t = this.tokens, n = this.pos;
|
|
13333
13300
|
for (this.tokens = e, this.pos = 0; this.pos < this.tokens.length;) {
|
|
13334
13301
|
let e = this._next();
|
|
13335
|
-
if (e.type !==
|
|
13302
|
+
if (e.type !== Uf.WORD) throw Error(`PBRT parser: expected directive, got ${e.type} ${e.value ?? ""}`);
|
|
13336
13303
|
this._directive(e.value);
|
|
13337
13304
|
}
|
|
13338
13305
|
this.tokens = t, this.pos = n;
|
|
@@ -13340,25 +13307,25 @@ var np = class {
|
|
|
13340
13307
|
_directive(e) {
|
|
13341
13308
|
switch (e) {
|
|
13342
13309
|
case "Identity":
|
|
13343
|
-
this.ctm =
|
|
13310
|
+
this.ctm = Jf();
|
|
13344
13311
|
break;
|
|
13345
13312
|
case "Translate": {
|
|
13346
13313
|
let [e, t, n] = this._readNumbers(3);
|
|
13347
|
-
this.ctm =
|
|
13314
|
+
this.ctm = Yf(this.ctm, Xf(e, t, n));
|
|
13348
13315
|
break;
|
|
13349
13316
|
}
|
|
13350
13317
|
case "Scale": {
|
|
13351
13318
|
let [e, t, n] = this._readNumbers(3);
|
|
13352
|
-
this.ctm =
|
|
13319
|
+
this.ctm = Yf(this.ctm, Zf(e, t, n));
|
|
13353
13320
|
break;
|
|
13354
13321
|
}
|
|
13355
13322
|
case "Rotate": {
|
|
13356
13323
|
let [e, t, n, r] = this._readNumbers(4);
|
|
13357
|
-
this.ctm =
|
|
13324
|
+
this.ctm = Yf(this.ctm, Qf(e, t, n, r));
|
|
13358
13325
|
break;
|
|
13359
13326
|
}
|
|
13360
13327
|
case "LookAt": {
|
|
13361
|
-
let e = this._readNumbers(9), t =
|
|
13328
|
+
let e = this._readNumbers(9), t = np([
|
|
13362
13329
|
e[0],
|
|
13363
13330
|
e[1],
|
|
13364
13331
|
e[2]
|
|
@@ -13371,7 +13338,7 @@ var np = class {
|
|
|
13371
13338
|
e[7],
|
|
13372
13339
|
e[8]
|
|
13373
13340
|
]);
|
|
13374
|
-
this.ctm =
|
|
13341
|
+
this.ctm = Yf(this.ctm, rp(t));
|
|
13375
13342
|
break;
|
|
13376
13343
|
}
|
|
13377
13344
|
case "Transform":
|
|
@@ -13379,7 +13346,7 @@ var np = class {
|
|
|
13379
13346
|
break;
|
|
13380
13347
|
case "ConcatTransform": {
|
|
13381
13348
|
let e = this._readBracketedOrBareNumbers(16);
|
|
13382
|
-
this.ctm =
|
|
13349
|
+
this.ctm = Yf(this.ctm, e);
|
|
13383
13350
|
break;
|
|
13384
13351
|
}
|
|
13385
13352
|
case "CoordinateSystem":
|
|
@@ -13395,7 +13362,7 @@ var np = class {
|
|
|
13395
13362
|
this.ir.camera = {
|
|
13396
13363
|
type: e,
|
|
13397
13364
|
params: t,
|
|
13398
|
-
cameraToWorld:
|
|
13365
|
+
cameraToWorld: rp(this.ctm)
|
|
13399
13366
|
};
|
|
13400
13367
|
break;
|
|
13401
13368
|
}
|
|
@@ -13419,7 +13386,7 @@ var np = class {
|
|
|
13419
13386
|
this._skipTypeAndParams();
|
|
13420
13387
|
break;
|
|
13421
13388
|
case "WorldBegin":
|
|
13422
|
-
this.ctm =
|
|
13389
|
+
this.ctm = Jf(), this.state = {
|
|
13423
13390
|
material: null,
|
|
13424
13391
|
areaLight: null,
|
|
13425
13392
|
reverseOrientation: !1
|
|
@@ -13464,7 +13431,7 @@ var np = class {
|
|
|
13464
13431
|
this._readNumbers(2);
|
|
13465
13432
|
break;
|
|
13466
13433
|
case "MediumInterface":
|
|
13467
|
-
this._peek() && this._peek().type ===
|
|
13434
|
+
this._peek() && this._peek().type === Uf.STRING && this._next(), this._peek() && this._peek().type === Uf.STRING && this._next();
|
|
13468
13435
|
break;
|
|
13469
13436
|
case "MakeNamedMedium":
|
|
13470
13437
|
this._skipNamedAndParams();
|
|
@@ -13572,7 +13539,7 @@ var np = class {
|
|
|
13572
13539
|
}
|
|
13573
13540
|
}
|
|
13574
13541
|
_emitShape(e) {
|
|
13575
|
-
this.currentObject === null ? this.ir.shapes.push(e) : (e.relativeCTM =
|
|
13542
|
+
this.currentObject === null ? this.ir.shapes.push(e) : (e.relativeCTM = Yf(rp(this.objectBeginCTM), e.ctm), this.ir.objects.get(this.currentObject).push(e));
|
|
13576
13543
|
}
|
|
13577
13544
|
_include(e) {
|
|
13578
13545
|
let t = this.resolveInclude(e, this.dirStack[this.dirStack.length - 1]);
|
|
@@ -13581,13 +13548,13 @@ var np = class {
|
|
|
13581
13548
|
return;
|
|
13582
13549
|
}
|
|
13583
13550
|
let n = e.includes("/") ? e.slice(0, e.lastIndexOf("/")) : "";
|
|
13584
|
-
this.dirStack.push(n), this._run(
|
|
13551
|
+
this.dirStack.push(n), this._run(qf(t)), this.dirStack.pop();
|
|
13585
13552
|
}
|
|
13586
13553
|
_skipTypeAndParams() {
|
|
13587
|
-
this._peek() && this._peek().type ===
|
|
13554
|
+
this._peek() && this._peek().type === Uf.STRING && this._next(), this._parseParams();
|
|
13588
13555
|
}
|
|
13589
13556
|
_skipNamedAndParams() {
|
|
13590
|
-
this._peek() && this._peek().type ===
|
|
13557
|
+
this._peek() && this._peek().type === Uf.STRING && this._next(), this._parseParams();
|
|
13591
13558
|
}
|
|
13592
13559
|
_num(e, t) {
|
|
13593
13560
|
return e && e.value.length ? e.value[0] : t;
|
|
@@ -13601,7 +13568,7 @@ var np = class {
|
|
|
13601
13568
|
_warnUnknown(e) {
|
|
13602
13569
|
this._warnedUnknown.has(e) || (this._warnedUnknown.add(e), this._warn(`Unsupported directive ignored: ${e}`));
|
|
13603
13570
|
}
|
|
13604
|
-
},
|
|
13571
|
+
}, ap = {
|
|
13605
13572
|
au: [
|
|
13606
13573
|
1,
|
|
13607
13574
|
.78,
|
|
@@ -13657,12 +13624,12 @@ var np = class {
|
|
|
13657
13624
|
.9,
|
|
13658
13625
|
.9
|
|
13659
13626
|
]
|
|
13660
|
-
},
|
|
13627
|
+
}, op = [
|
|
13661
13628
|
.92,
|
|
13662
13629
|
.92,
|
|
13663
13630
|
.92
|
|
13664
13631
|
];
|
|
13665
|
-
function
|
|
13632
|
+
function sp(e) {
|
|
13666
13633
|
let t = Math.max(1e3, Math.min(4e4, e)) / 100, n, r, i;
|
|
13667
13634
|
t <= 66 ? (n = 255, r = 99.47 * Math.log(t) - 161.12) : (n = 329.7 * (t - 60) ** -.1332, r = 288.12 * (t - 60) ** -.0755), i = t >= 66 ? 255 : t <= 19 ? 0 : 138.52 * Math.log(t - 10) - 305.04;
|
|
13668
13635
|
let a = (e) => Math.max(0, Math.min(255, e)) / 255;
|
|
@@ -13672,15 +13639,15 @@ function ap(e) {
|
|
|
13672
13639
|
a(i) ** 2.2
|
|
13673
13640
|
];
|
|
13674
13641
|
}
|
|
13675
|
-
function
|
|
13642
|
+
function cp(e, t, n) {
|
|
13676
13643
|
let r = e[t];
|
|
13677
13644
|
return r && typeof r.value[0] == "number" ? r.value[0] : n;
|
|
13678
13645
|
}
|
|
13679
|
-
function
|
|
13646
|
+
function lp(e, t, n) {
|
|
13680
13647
|
let r = e[t];
|
|
13681
13648
|
return r && typeof r.value[0] == "string" ? r.value[0] : n;
|
|
13682
13649
|
}
|
|
13683
|
-
async function
|
|
13650
|
+
async function up(e, t, n, r = null) {
|
|
13684
13651
|
let i = e[t];
|
|
13685
13652
|
if (!i) return {
|
|
13686
13653
|
rgb: r,
|
|
@@ -13719,14 +13686,14 @@ async function cp(e, t, n, r = null) {
|
|
|
13719
13686
|
};
|
|
13720
13687
|
}
|
|
13721
13688
|
if (i.type === "blackbody") return {
|
|
13722
|
-
rgb:
|
|
13689
|
+
rgb: sp(i.value[0]),
|
|
13723
13690
|
texture: null
|
|
13724
13691
|
};
|
|
13725
13692
|
if (i.type === "spectrum") {
|
|
13726
13693
|
if (typeof i.value[0] == "string") {
|
|
13727
|
-
let e =
|
|
13728
|
-
return e &&
|
|
13729
|
-
rgb:
|
|
13694
|
+
let e = dp(i.value[0]);
|
|
13695
|
+
return e && ap[e] ? {
|
|
13696
|
+
rgb: ap[e].slice(),
|
|
13730
13697
|
texture: null
|
|
13731
13698
|
} : (n.warn(`named spectrum "${i.value[0]}" approximated to gray`), {
|
|
13732
13699
|
rgb: [
|
|
@@ -13754,18 +13721,18 @@ async function cp(e, t, n, r = null) {
|
|
|
13754
13721
|
texture: null
|
|
13755
13722
|
};
|
|
13756
13723
|
}
|
|
13757
|
-
function
|
|
13724
|
+
function dp(e) {
|
|
13758
13725
|
let t = e.toLowerCase().match(/metal-([a-z]+)/);
|
|
13759
13726
|
if (t) return t[1];
|
|
13760
|
-
for (let t of Object.keys(
|
|
13727
|
+
for (let t of Object.keys(ap)) if (e.toLowerCase().includes(t)) return t;
|
|
13761
13728
|
return null;
|
|
13762
13729
|
}
|
|
13763
|
-
function
|
|
13730
|
+
function fp(e, t) {
|
|
13764
13731
|
if (e.roughness && typeof e.roughness.value[0] == "number") return e.roughness.value[0];
|
|
13765
|
-
let n =
|
|
13732
|
+
let n = cp(e, "uroughness", null), r = cp(e, "vroughness", null);
|
|
13766
13733
|
return n !== null && r !== null ? (n + r) / 2 : n === null ? t : n;
|
|
13767
13734
|
}
|
|
13768
|
-
async function
|
|
13735
|
+
async function pp(e, t) {
|
|
13769
13736
|
let n = e?.type || "diffuse", r = e?.params || {}, i = new Et({
|
|
13770
13737
|
side: ct,
|
|
13771
13738
|
roughness: 1,
|
|
@@ -13777,7 +13744,7 @@ async function dp(e, t) {
|
|
|
13777
13744
|
};
|
|
13778
13745
|
switch (n) {
|
|
13779
13746
|
case "diffuse":
|
|
13780
|
-
o(await
|
|
13747
|
+
o(await up(r, "reflectance", t, [
|
|
13781
13748
|
.5,
|
|
13782
13749
|
.5,
|
|
13783
13750
|
.5
|
|
@@ -13785,14 +13752,14 @@ async function dp(e, t) {
|
|
|
13785
13752
|
break;
|
|
13786
13753
|
case "conductor":
|
|
13787
13754
|
case "metal": {
|
|
13788
|
-
let e = await
|
|
13755
|
+
let e = await up(r, "reflectance", t, null), n = r.eta, s = r.k, c = n && n.type === "spectrum" && typeof n.value[0] == "string";
|
|
13789
13756
|
if (e.rgb || e.texture) o(e);
|
|
13790
13757
|
else if (n && s && !c) {
|
|
13791
|
-
let e = (await
|
|
13758
|
+
let e = (await up(r, "eta", t, [
|
|
13792
13759
|
.2,
|
|
13793
13760
|
.92,
|
|
13794
13761
|
1.1
|
|
13795
|
-
])).rgb, n = (await
|
|
13762
|
+
])).rgb, n = (await up(r, "k", t, [
|
|
13796
13763
|
3.9,
|
|
13797
13764
|
2.45,
|
|
13798
13765
|
2.14
|
|
@@ -13802,28 +13769,28 @@ async function dp(e, t) {
|
|
|
13802
13769
|
i(e[1], n[1]),
|
|
13803
13770
|
i(e[2], n[2])
|
|
13804
13771
|
]);
|
|
13805
|
-
} else a(n ? (await
|
|
13806
|
-
i.metalness = 1, i.roughness =
|
|
13772
|
+
} else a(n ? (await up(r, "eta", t, op)).rgb || op : ap.cu);
|
|
13773
|
+
i.metalness = 1, i.roughness = fp(r, .1);
|
|
13807
13774
|
break;
|
|
13808
13775
|
}
|
|
13809
13776
|
case "dielectric":
|
|
13810
13777
|
case "thindielectric":
|
|
13811
|
-
i.transmission = 1, i.metalness = 0, i.color.setRGB(1, 1, 1), i.ior =
|
|
13778
|
+
i.transmission = 1, i.metalness = 0, i.color.setRGB(1, 1, 1), i.ior = cp(r, "eta", 1.5), i.roughness = fp(r, 0), i.thickness = n === "thindielectric" ? 0 : cp(r, "thickness", 0);
|
|
13812
13779
|
break;
|
|
13813
13780
|
case "coateddiffuse":
|
|
13814
|
-
o(await
|
|
13781
|
+
o(await up(r, "reflectance", t, [
|
|
13815
13782
|
.5,
|
|
13816
13783
|
.5,
|
|
13817
13784
|
.5
|
|
13818
|
-
])), i.roughness = .6, i.metalness = 0, i.clearcoat = 1, i.clearcoatRoughness =
|
|
13785
|
+
])), i.roughness = .6, i.metalness = 0, i.clearcoat = 1, i.clearcoatRoughness = fp(r, 0);
|
|
13819
13786
|
break;
|
|
13820
13787
|
case "diffusetransmission": {
|
|
13821
|
-
let e = await
|
|
13788
|
+
let e = await up(r, "transmittance", t, [
|
|
13822
13789
|
.25,
|
|
13823
13790
|
.25,
|
|
13824
13791
|
.25
|
|
13825
13792
|
]);
|
|
13826
|
-
o(await
|
|
13793
|
+
o(await up(r, "reflectance", t, [
|
|
13827
13794
|
.25,
|
|
13828
13795
|
.25,
|
|
13829
13796
|
.25
|
|
@@ -13836,9 +13803,9 @@ async function dp(e, t) {
|
|
|
13836
13803
|
i.transmission = 1, i.ior = 1, i.roughness = 0, i.color.setRGB(1, 1, 1);
|
|
13837
13804
|
break;
|
|
13838
13805
|
case "mix": {
|
|
13839
|
-
let e = r.materials?.value || [], n = Math.max(0, Math.min(1,
|
|
13806
|
+
let e = r.materials?.value || [], n = Math.max(0, Math.min(1, cp(r, "amount", .5))), a = e[0] ? t.namedMaterials?.get(e[0]) : null, o = e[1] ? t.namedMaterials?.get(e[1]) : null;
|
|
13840
13807
|
if (a && o) {
|
|
13841
|
-
let [e, r] = await Promise.all([
|
|
13808
|
+
let [e, r] = await Promise.all([pp(a, t), pp(o, t)]), s = (e, t) => e * (1 - n) + t * n;
|
|
13842
13809
|
i.color.lerpColors(e.color, r.color, n), i.roughness = s(e.roughness, r.roughness), i.metalness = s(e.metalness, r.metalness), i.ior = s(e.ior ?? 1.5, r.ior ?? 1.5), i.transmission = s(e.transmission ?? 0, r.transmission ?? 0), i.thickness = s(e.thickness ?? 0, r.thickness ?? 0), i.clearcoat = s(e.clearcoat ?? 0, r.clearcoat ?? 0), i.clearcoatRoughness = s(e.clearcoatRoughness ?? 0, r.clearcoatRoughness ?? 0), i.emissive.lerpColors(e.emissive, r.emissive, n), i.emissiveIntensity = s(e.emissiveIntensity ?? 0, r.emissiveIntensity ?? 0), i.map = (n < .5 ? e.map : r.map) || null;
|
|
13843
13810
|
break;
|
|
13844
13811
|
}
|
|
@@ -13848,7 +13815,7 @@ async function dp(e, t) {
|
|
|
13848
13815
|
case "subsurface":
|
|
13849
13816
|
case "hair":
|
|
13850
13817
|
case "measured":
|
|
13851
|
-
t.warn(`material "${n}" not supported — using diffuse approximation`), a((await
|
|
13818
|
+
t.warn(`material "${n}" not supported — using diffuse approximation`), a((await up(r, "reflectance", t, [
|
|
13852
13819
|
.5,
|
|
13853
13820
|
.5,
|
|
13854
13821
|
.5
|
|
@@ -13862,7 +13829,7 @@ async function dp(e, t) {
|
|
|
13862
13829
|
}
|
|
13863
13830
|
//#endregion
|
|
13864
13831
|
//#region src/Processor/PBRT/PBRTSceneBuilder.js
|
|
13865
|
-
var
|
|
13832
|
+
var mp = [
|
|
13866
13833
|
1,
|
|
13867
13834
|
0,
|
|
13868
13835
|
0,
|
|
@@ -13879,7 +13846,7 @@ var fp = [
|
|
|
13879
13846
|
0,
|
|
13880
13847
|
0,
|
|
13881
13848
|
1
|
|
13882
|
-
],
|
|
13849
|
+
], hp = class {
|
|
13883
13850
|
constructor(e = {}) {
|
|
13884
13851
|
this.resolvePLY = e.resolvePLY || (async () => null), this.resolveImage = e.resolveImage || (async () => null), this.resolveEnvironment = e.resolveEnvironment || e.resolveImage || (async () => null), this.convertHandedness = e.convertHandedness === !0, this.warnings = [], this.report = [], this._materialCache = /* @__PURE__ */ new Map(), this._textureCache = /* @__PURE__ */ new Map();
|
|
13885
13852
|
}
|
|
@@ -13915,7 +13882,7 @@ var fp = [
|
|
|
13915
13882
|
continue;
|
|
13916
13883
|
}
|
|
13917
13884
|
for (let e of i) {
|
|
13918
|
-
let i =
|
|
13885
|
+
let i = Yf(r.ctm, e.relativeCTM || e.ctm), a = await this._buildShapeMesh(e, i, `instance_${n++}`);
|
|
13919
13886
|
a && t.add(a);
|
|
13920
13887
|
}
|
|
13921
13888
|
}
|
|
@@ -13927,7 +13894,7 @@ var fp = [
|
|
|
13927
13894
|
i.map && !a && (this.warn(`${n} (${e.type}, "${e.material?.type || "diffuse"}") has a texture map but no UVs — dropping map, using base color`), o = i.clone(), o.map = null);
|
|
13928
13895
|
let s = new wt(r, o);
|
|
13929
13896
|
s.name = n;
|
|
13930
|
-
let c = this.convertHandedness ?
|
|
13897
|
+
let c = this.convertHandedness ? Yf(mp, t) : t;
|
|
13931
13898
|
new Ct().fromArray(c).decompose(s.position, s.quaternion, s.scale), s.updateMatrix(), r.computeBoundingBox();
|
|
13932
13899
|
let l = r.boundingBox ? r.boundingBox.clone().applyMatrix4(s.matrix).getSize(new cn()) : new cn();
|
|
13933
13900
|
return this.report.push({
|
|
@@ -13982,7 +13949,7 @@ var fp = [
|
|
|
13982
13949
|
return i.setAttribute("position", new dt(Float32Array.from(t), 3)), i.setIndex(r), i.computeVertexNormals(), i;
|
|
13983
13950
|
}
|
|
13984
13951
|
async _plyMesh(e) {
|
|
13985
|
-
let t =
|
|
13952
|
+
let t = lp(e, "filename", null);
|
|
13986
13953
|
if (!t) return this.warn("plymesh missing filename"), null;
|
|
13987
13954
|
try {
|
|
13988
13955
|
let e = await this.resolvePLY(t);
|
|
@@ -13992,10 +13959,10 @@ var fp = [
|
|
|
13992
13959
|
}
|
|
13993
13960
|
}
|
|
13994
13961
|
_sphere(e) {
|
|
13995
|
-
return new Zt(
|
|
13962
|
+
return new Zt(cp(e, "radius", 1), 48, 32);
|
|
13996
13963
|
}
|
|
13997
13964
|
_disk(e) {
|
|
13998
|
-
let t =
|
|
13965
|
+
let t = cp(e, "radius", 1), n = cp(e, "innerradius", 0), r = cp(e, "height", 0), i = [], a = [];
|
|
13999
13966
|
for (let e = 0; e < 48; e++) {
|
|
14000
13967
|
let o = e / 48 * Math.PI * 2, s = (e + 1) / 48 * Math.PI * 2, c = i.length / 3;
|
|
14001
13968
|
i.push(Math.cos(o) * n, Math.sin(o) * n, r), i.push(Math.cos(o) * t, Math.sin(o) * t, r), i.push(Math.cos(s) * t, Math.sin(s) * t, r), i.push(Math.cos(s) * n, Math.sin(s) * n, r), a.push(c, c + 1, c + 2, c, c + 2, c + 3);
|
|
@@ -14010,15 +13977,15 @@ var fp = [
|
|
|
14010
13977
|
resolveNamedTexture: (e) => this._resolveNamedTexture(e),
|
|
14011
13978
|
namedMaterials: this.ir.namedMaterials,
|
|
14012
13979
|
warn: (e) => this.warn(e)
|
|
14013
|
-
}, r = await
|
|
13980
|
+
}, r = await pp(e.material, n);
|
|
14014
13981
|
return e.areaLight && await this._applyAreaLight(r, e.areaLight, n), t.set(e.areaLight, r), r;
|
|
14015
13982
|
}
|
|
14016
13983
|
async _applyAreaLight(e, t, n) {
|
|
14017
|
-
let r = await
|
|
13984
|
+
let r = await up(t.params, "L", n, [
|
|
14018
13985
|
1,
|
|
14019
13986
|
1,
|
|
14020
13987
|
1
|
|
14021
|
-
]), i =
|
|
13988
|
+
]), i = cp(t.params, "scale", 1), a = r.rgb || [
|
|
14022
13989
|
1,
|
|
14023
13990
|
1,
|
|
14024
13991
|
1
|
|
@@ -14030,7 +13997,7 @@ var fp = [
|
|
|
14030
13997
|
let t = this.ir.namedTextures.get(e), n = null;
|
|
14031
13998
|
if (!t) this.warn(`named texture "${e}" not defined`);
|
|
14032
13999
|
else if (t.class === "imagemap") {
|
|
14033
|
-
let r =
|
|
14000
|
+
let r = lp(t.params, "filename", null);
|
|
14034
14001
|
if (r) try {
|
|
14035
14002
|
let t = await this.resolveImage(r);
|
|
14036
14003
|
t ? n = { texture: t } : this.warn(`image not found for texture "${e}": ${r}`);
|
|
@@ -14118,7 +14085,7 @@ var fp = [
|
|
|
14118
14085
|
return c.name = "PBRT Camera", c.up.copy(a.normalize()), c.position.copy(r), c.lookAt(o), c.updateMatrixWorld(!0), c;
|
|
14119
14086
|
}
|
|
14120
14087
|
_verticalFov(e, t) {
|
|
14121
|
-
let n =
|
|
14088
|
+
let n = cp(e, "fov", 90);
|
|
14122
14089
|
if (t >= 1) return n;
|
|
14123
14090
|
let r = n * Math.PI / 180;
|
|
14124
14091
|
return 2 * Math.atan(Math.tan(r / 2) / t) * 180 / Math.PI;
|
|
@@ -14126,7 +14093,7 @@ var fp = [
|
|
|
14126
14093
|
async _buildEnvironment(e) {
|
|
14127
14094
|
let t = e.find((e) => e.type === "infinite");
|
|
14128
14095
|
if (!t) return null;
|
|
14129
|
-
let n =
|
|
14096
|
+
let n = cp(t.params, "scale", 1), r = lp(t.params, "filename", null);
|
|
14130
14097
|
if (r) try {
|
|
14131
14098
|
let e = await this.resolveEnvironment(r);
|
|
14132
14099
|
if (e) return e.mapping = lt, { texture: e };
|
|
@@ -14134,7 +14101,7 @@ var fp = [
|
|
|
14134
14101
|
} catch (e) {
|
|
14135
14102
|
this.warn(`failed to load infinite-light image ${r}: ${e.message}`);
|
|
14136
14103
|
}
|
|
14137
|
-
let i = ((await
|
|
14104
|
+
let i = ((await up(t.params, "L", {
|
|
14138
14105
|
resolveNamedTexture: async () => null,
|
|
14139
14106
|
warn: (e) => this.warn(e)
|
|
14140
14107
|
}, [
|
|
@@ -14153,20 +14120,20 @@ var fp = [
|
|
|
14153
14120
|
_reportUnsupportedLights(e) {
|
|
14154
14121
|
for (let t of e) t.type !== "infinite" && this.warn(`light "${t.type}" not supported (only infinite lights and emissive area lights are mapped)`);
|
|
14155
14122
|
}
|
|
14156
|
-
},
|
|
14157
|
-
function
|
|
14123
|
+
}, gp = new TextDecoder();
|
|
14124
|
+
function _p(e) {
|
|
14158
14125
|
let t = e.replace(/\\/g, "/").split("/"), n = [];
|
|
14159
14126
|
for (let e of t) e === "" || e === "." || (e === ".." ? n.pop() : n.push(e));
|
|
14160
14127
|
return n.join("/");
|
|
14161
14128
|
}
|
|
14162
|
-
function
|
|
14163
|
-
return !e || t.startsWith("/") ?
|
|
14129
|
+
function vp(e, t) {
|
|
14130
|
+
return !e || t.startsWith("/") ? _p(t) : _p(`${e}/${t}`);
|
|
14164
14131
|
}
|
|
14165
|
-
var
|
|
14132
|
+
var yp = class {
|
|
14166
14133
|
constructor(e) {
|
|
14167
14134
|
this.byPath = /* @__PURE__ */ new Map(), this.byBase = /* @__PURE__ */ new Map();
|
|
14168
14135
|
for (let t in e) {
|
|
14169
|
-
let n =
|
|
14136
|
+
let n = _p(t).toLowerCase(), r = {
|
|
14170
14137
|
norm: n,
|
|
14171
14138
|
bytes: e[t]
|
|
14172
14139
|
};
|
|
@@ -14176,13 +14143,13 @@ var _p = class {
|
|
|
14176
14143
|
}
|
|
14177
14144
|
}
|
|
14178
14145
|
find(e) {
|
|
14179
|
-
let t =
|
|
14146
|
+
let t = _p(e).toLowerCase();
|
|
14180
14147
|
if (this.byPath.has(t)) return this.byPath.get(t).bytes;
|
|
14181
14148
|
let n = this.byBase.get(t.split("/").pop());
|
|
14182
14149
|
return n ? (n.find((e) => e.norm.endsWith("/" + t)) || n[0]).bytes : null;
|
|
14183
14150
|
}
|
|
14184
14151
|
};
|
|
14185
|
-
function
|
|
14152
|
+
function bp(e) {
|
|
14186
14153
|
let t = Object.keys(e).filter((e) => e.toLowerCase().endsWith(".pbrt"));
|
|
14187
14154
|
if (t.length === 0) return null;
|
|
14188
14155
|
let n = t.filter((e) => /(^|\/)(scene|main)\.pbrt$/i.test(e)), r = n.length ? n : t;
|
|
@@ -14191,17 +14158,17 @@ function vp(e) {
|
|
|
14191
14158
|
return n === r ? e.length - t.length : n - r;
|
|
14192
14159
|
}), r[0];
|
|
14193
14160
|
}
|
|
14194
|
-
async function
|
|
14195
|
-
let { vfs: t, plyParser: n, imageFromBytes: r, envFromBytes: i, convertHandedness: a } = e, o = new
|
|
14161
|
+
async function xp(e) {
|
|
14162
|
+
let { vfs: t, plyParser: n, imageFromBytes: r, envFromBytes: i, convertHandedness: a } = e, o = new yp(t), s = e.entryPath || bp(t);
|
|
14196
14163
|
if (!s) throw Error("PBRT loader: no .pbrt file found in archive");
|
|
14197
14164
|
let c = o.find(s);
|
|
14198
14165
|
if (!c) throw Error(`PBRT loader: entry "${s}" not readable`);
|
|
14199
|
-
let l = s.includes("/") ? s.slice(0, s.lastIndexOf("/")) : "", u = new
|
|
14200
|
-
let n = o.find(
|
|
14201
|
-
return n ?
|
|
14202
|
-
} }).parse(
|
|
14166
|
+
let l = s.includes("/") ? s.slice(0, s.lastIndexOf("/")) : "", u = new ip({ resolveInclude: (e, t) => {
|
|
14167
|
+
let n = o.find(vp(t, e)) || o.find(e);
|
|
14168
|
+
return n ? gp.decode(n) : null;
|
|
14169
|
+
} }).parse(gp.decode(c), l), d = (e) => e.buffer.slice(e.byteOffset, e.byteOffset + e.byteLength);
|
|
14203
14170
|
return {
|
|
14204
|
-
...await new
|
|
14171
|
+
...await new hp({
|
|
14205
14172
|
convertHandedness: a,
|
|
14206
14173
|
resolvePLY: async (e) => {
|
|
14207
14174
|
let t = o.find(e);
|
|
@@ -14221,7 +14188,7 @@ async function yp(e) {
|
|
|
14221
14188
|
}
|
|
14222
14189
|
//#endregion
|
|
14223
14190
|
//#region src/Processor/AssetLoader.js
|
|
14224
|
-
var
|
|
14191
|
+
var Sp = {
|
|
14225
14192
|
glb: {
|
|
14226
14193
|
type: "model",
|
|
14227
14194
|
name: "GLB (GLTF Binary)"
|
|
@@ -14286,7 +14253,7 @@ var bp = {
|
|
|
14286
14253
|
type: "archive",
|
|
14287
14254
|
name: "ZIP Archive"
|
|
14288
14255
|
}
|
|
14289
|
-
},
|
|
14256
|
+
}, Cp = class e extends ut {
|
|
14290
14257
|
constructor(e, t, n) {
|
|
14291
14258
|
super(), this.scene = e, this.camera = t, this.controls = n, this.targetModel = null, this._externalModel = null, this.floorPlane = null, this.sceneScale = 1, this.loaderCache = {}, this.uploadedFileInfo = null, this.animations = [], this.renderer = null, this._loadingManager = new vt(), this._loadCancelled = !1;
|
|
14292
14259
|
}
|
|
@@ -14332,7 +14299,7 @@ var bp = {
|
|
|
14332
14299
|
this.renderer = e;
|
|
14333
14300
|
}
|
|
14334
14301
|
getFileFormat(e) {
|
|
14335
|
-
return
|
|
14302
|
+
return Sp[e.split(".").pop().toLowerCase()] || null;
|
|
14336
14303
|
}
|
|
14337
14304
|
readFileAsArrayBuffer(e) {
|
|
14338
14305
|
return new Promise((t, n) => {
|
|
@@ -14467,7 +14434,7 @@ var bp = {
|
|
|
14467
14434
|
async loadArchiveFromFile(e, t) {
|
|
14468
14435
|
try {
|
|
14469
14436
|
let n = await this.readFileAsArrayBuffer(e), r = yn(new Uint8Array(n));
|
|
14470
|
-
return
|
|
14437
|
+
return bp(r) ? await this.loadPBRTFromZip(r, t) : await this.processObjMtlPairsInZip(r, t) || await this.findAndLoadModelFromZip(r, t);
|
|
14471
14438
|
} catch (e) {
|
|
14472
14439
|
throw console.error("Error loading ZIP archive:", e), e;
|
|
14473
14440
|
}
|
|
@@ -14481,7 +14448,7 @@ var bp = {
|
|
|
14481
14448
|
let { PLYLoader: e } = await import("three/examples/jsm/loaders/PLYLoader.js");
|
|
14482
14449
|
this.loaderCache.ply = new e();
|
|
14483
14450
|
}
|
|
14484
|
-
let { group: n, environment: r, report: i, warnings: a, entryPath: o } = await
|
|
14451
|
+
let { group: n, environment: r, report: i, warnings: a, entryPath: o } = await xp({
|
|
14485
14452
|
vfs: e,
|
|
14486
14453
|
plyParser: (e) => this.loaderCache.ply.parse(e),
|
|
14487
14454
|
imageFromBytes: (e, t) => this._pbrtTextureFromBytes(e, t),
|
|
@@ -14580,7 +14547,7 @@ var bp = {
|
|
|
14580
14547
|
}
|
|
14581
14548
|
for (let t in e) {
|
|
14582
14549
|
let n = t.split(".").pop().toLowerCase();
|
|
14583
|
-
if (
|
|
14550
|
+
if (Sp[n] && Sp[n].type === "model") return console.log(`Loading model file from ZIP: ${t}`), await this.loadModelFromZipEntry(e[t], t, n, e);
|
|
14584
14551
|
}
|
|
14585
14552
|
throw Error("No supported model files found in the ZIP archive");
|
|
14586
14553
|
}
|
|
@@ -15140,10 +15107,10 @@ var bp = {
|
|
|
15140
15107
|
getSupportedFormats(e = null) {
|
|
15141
15108
|
if (e) {
|
|
15142
15109
|
let t = {};
|
|
15143
|
-
for (let [n, r] of Object.entries(
|
|
15110
|
+
for (let [n, r] of Object.entries(Sp)) r.type === e && (t[n] = r);
|
|
15144
15111
|
return t;
|
|
15145
15112
|
}
|
|
15146
|
-
return
|
|
15113
|
+
return Sp;
|
|
15147
15114
|
}
|
|
15148
15115
|
dispose() {
|
|
15149
15116
|
for (let e in this.loaderCache) {
|
|
@@ -15155,7 +15122,7 @@ var bp = {
|
|
|
15155
15122
|
removeAllEventListeners() {
|
|
15156
15123
|
this._listeners = void 0;
|
|
15157
15124
|
}
|
|
15158
|
-
},
|
|
15125
|
+
}, wp = {
|
|
15159
15126
|
maxBounces: {
|
|
15160
15127
|
uniform: "maxBounces",
|
|
15161
15128
|
reset: !0
|
|
@@ -15224,6 +15191,10 @@ var bp = {
|
|
|
15224
15191
|
uniform: "globalIlluminationIntensity",
|
|
15225
15192
|
reset: !0
|
|
15226
15193
|
},
|
|
15194
|
+
panoramaLevelHorizon: {
|
|
15195
|
+
uniform: "panoLevelHorizon",
|
|
15196
|
+
reset: !0
|
|
15197
|
+
},
|
|
15227
15198
|
enableDOF: {
|
|
15228
15199
|
uniform: "enableDOF",
|
|
15229
15200
|
reset: !0
|
|
@@ -15304,6 +15275,18 @@ var bp = {
|
|
|
15304
15275
|
uniform: "debugVisScale",
|
|
15305
15276
|
reset: !0
|
|
15306
15277
|
},
|
|
15278
|
+
cameraProjection: {
|
|
15279
|
+
handler: "handleCameraProjection",
|
|
15280
|
+
reset: !0
|
|
15281
|
+
},
|
|
15282
|
+
panoramaLonRange: {
|
|
15283
|
+
handler: "handlePanoramaLonRange",
|
|
15284
|
+
reset: !0
|
|
15285
|
+
},
|
|
15286
|
+
panoramaLatRange: {
|
|
15287
|
+
handler: "handlePanoramaLatRange",
|
|
15288
|
+
reset: !0
|
|
15289
|
+
},
|
|
15307
15290
|
interactionModeEnabled: {
|
|
15308
15291
|
handler: "handleInteractionModeEnabled",
|
|
15309
15292
|
reset: !1
|
|
@@ -15326,18 +15309,27 @@ var bp = {
|
|
|
15326
15309
|
},
|
|
15327
15310
|
renderMode: { handler: "handleRenderMode" },
|
|
15328
15311
|
environmentRotation: { handler: "handleEnvironmentRotation" }
|
|
15329
|
-
},
|
|
15312
|
+
}, Tp = {
|
|
15330
15313
|
bounces: "maxBounces",
|
|
15331
15314
|
debugMode: "visMode"
|
|
15332
|
-
},
|
|
15315
|
+
}, Ep = class extends ut {
|
|
15333
15316
|
constructor(e = J) {
|
|
15334
15317
|
super(), this._values = /* @__PURE__ */ new Map(), this._pathTracer = null, this._resetCallback = null, this._handlers = {}, this._delegates = {}, this._initDefaults(e);
|
|
15335
15318
|
}
|
|
15336
|
-
bind(
|
|
15337
|
-
this._pathTracer = e.pathTracer, this._resetCallback =
|
|
15319
|
+
bind(e) {
|
|
15320
|
+
this._pathTracer = e.stages.pathTracer, this._resetCallback = e.resetCallback, this._delegates = {}, this._handlers = this._buildHandlers(e);
|
|
15338
15321
|
}
|
|
15339
|
-
_buildHandlers(e, t, n) {
|
|
15322
|
+
_buildHandlers({ stages: e, renderer: t, reconcileCompletion: n, denoisingManager: r, cameraManager: i }) {
|
|
15323
|
+
let a = new sn(), o = (t, n) => {
|
|
15324
|
+
a.set(n?.[0] ?? 0, n?.[1] ?? 0).multiplyScalar(xt.DEG2RAD), e.pathTracer?.setUniform(t, a);
|
|
15325
|
+
};
|
|
15340
15326
|
return {
|
|
15327
|
+
handleCameraProjection: (t) => {
|
|
15328
|
+
let n = t === "equirectangular";
|
|
15329
|
+
e.pathTracer?.setUniform("cameraProjection", +!!n), n && (r?.denoiserStrategy === "asvgf" && r.setDenoiserStrategy("edgeaware"), i?.setAutoFocusMode("manual"));
|
|
15330
|
+
},
|
|
15331
|
+
handlePanoramaLonRange: (e) => o("panoLonRange", e),
|
|
15332
|
+
handlePanoramaLatRange: (e) => o("panoLatRange", e),
|
|
15341
15333
|
handleTransparentBackground: (t) => {
|
|
15342
15334
|
e.pathTracer?.setUniform("transparentBackground", t), e.compositor?.setTransparentBackground(t);
|
|
15343
15335
|
},
|
|
@@ -15375,7 +15367,7 @@ var bp = {
|
|
|
15375
15367
|
let i = this._values.get(e);
|
|
15376
15368
|
if (i === t) return;
|
|
15377
15369
|
this._values.set(e, t);
|
|
15378
|
-
let a =
|
|
15370
|
+
let a = wp[e];
|
|
15379
15371
|
a && (this._applyRoute(a, t, i), (n === void 0 ? a.reset ?? !0 : n) && this._resetCallback?.(), r || this.dispatchEvent({
|
|
15380
15372
|
type: dr.SETTING_CHANGED,
|
|
15381
15373
|
key: e,
|
|
@@ -15389,7 +15381,7 @@ var bp = {
|
|
|
15389
15381
|
let e = this._values.get(n);
|
|
15390
15382
|
if (e === i) continue;
|
|
15391
15383
|
this._values.set(n, i);
|
|
15392
|
-
let a =
|
|
15384
|
+
let a = wp[n];
|
|
15393
15385
|
a && (this._applyRoute(a, i, e), (a.reset ?? !0) && (r = !0), t || this.dispatchEvent({
|
|
15394
15386
|
type: dr.SETTING_CHANGED,
|
|
15395
15387
|
key: n,
|
|
@@ -15407,7 +15399,7 @@ var bp = {
|
|
|
15407
15399
|
}
|
|
15408
15400
|
applyAll() {
|
|
15409
15401
|
for (let [e, t] of this._values) {
|
|
15410
|
-
let n =
|
|
15402
|
+
let n = wp[e];
|
|
15411
15403
|
n && this._applyRoute(n, t, void 0);
|
|
15412
15404
|
}
|
|
15413
15405
|
}
|
|
@@ -15415,10 +15407,10 @@ var bp = {
|
|
|
15415
15407
|
e.uniform ? (this._pathTracer?.setUniform(e.uniform, t), e.after && this._pathTracer?.[e.after]?.()) : e.handler ? this._handlers[e.handler]?.(t, n) : e.delegate && this._delegates[e.delegate]?.updateParam?.(e.param, t);
|
|
15416
15408
|
}
|
|
15417
15409
|
_initDefaults(e) {
|
|
15418
|
-
for (let t of Object.keys(
|
|
15419
|
-
for (let [t, n] of Object.entries(
|
|
15410
|
+
for (let t of Object.keys(wp)) t in e && this._values.set(t, e[t]);
|
|
15411
|
+
for (let [t, n] of Object.entries(Tp)) t in e && this._values.set(n, e[t]);
|
|
15420
15412
|
}
|
|
15421
|
-
},
|
|
15413
|
+
}, Dp = class extends ut {
|
|
15422
15414
|
constructor(e) {
|
|
15423
15415
|
super();
|
|
15424
15416
|
let t = e.clientWidth, n = e.clientHeight;
|
|
@@ -15584,7 +15576,7 @@ var bp = {
|
|
|
15584
15576
|
dispose() {
|
|
15585
15577
|
this.controls?.dispose();
|
|
15586
15578
|
}
|
|
15587
|
-
},
|
|
15579
|
+
}, Op = class extends ut {
|
|
15588
15580
|
constructor(e, t, n, r = {}) {
|
|
15589
15581
|
super(), this.scene = e, this.sceneHelpers = t, this.pathTracer = n, this._onReset = r.onReset || null;
|
|
15590
15582
|
}
|
|
@@ -15744,14 +15736,14 @@ var bp = {
|
|
|
15744
15736
|
], n.distance = e.distance ?? 0, n.penumbra = e.penumbra ?? 0, n.decay = e.decay ?? 2) : e.type === "PointLight" && (n.distance = e.distance ?? 0, n.decay = e.decay ?? 2);
|
|
15745
15737
|
return (e.type === "SpotLight" || e.type === "DirectionalLight") && e.userData?.gobo && (n.gobo = e.userData.gobo.name, n.goboIntensity = e.userData.gobo.intensity, n.goboInverted = !!e.userData.gobo.inverted, e.type === "DirectionalLight" && (n.goboScale = e.userData.gobo.scale ?? 5)), e.type === "SpotLight" && e.userData?.ies && (n.ies = e.userData.ies.name, n.iesIntensity = e.userData.ies.intensity ?? 1, n.fixtureLumens = e.userData.ies.fixtureLumens ?? null), n;
|
|
15746
15738
|
}
|
|
15747
|
-
},
|
|
15739
|
+
}, kp = class {
|
|
15748
15740
|
constructor(e, t = {}) {
|
|
15749
15741
|
this.pathTracer = e, this._onReset = t.onReset || null, this.texture = null, this.entries = [], this._size = 256;
|
|
15750
15742
|
}
|
|
15751
15743
|
async loadLibrary(e, { size: t = 256 } = {}) {
|
|
15752
15744
|
if (!Array.isArray(e) || e.length === 0) return [];
|
|
15753
15745
|
this._size = t;
|
|
15754
|
-
let n = await Promise.all(e.map((e) =>
|
|
15746
|
+
let n = await Promise.all(e.map((e) => Ap(e.url))), r = t, i = t, a = n.length, o = new Uint8Array(r * i * a * 4), s = document.createElement("canvas");
|
|
15755
15747
|
s.width = r, s.height = i;
|
|
15756
15748
|
let c = s.getContext("2d", { willReadFrequently: !0 });
|
|
15757
15749
|
for (let e = 0; e < a; e++) {
|
|
@@ -15780,7 +15772,7 @@ var bp = {
|
|
|
15780
15772
|
o.userData.gobo = {
|
|
15781
15773
|
name: e.name,
|
|
15782
15774
|
index: e.index,
|
|
15783
|
-
intensity:
|
|
15775
|
+
intensity: jp(r),
|
|
15784
15776
|
inverted: !!i,
|
|
15785
15777
|
scale: Math.max(1e-4, a)
|
|
15786
15778
|
};
|
|
@@ -15822,28 +15814,28 @@ var bp = {
|
|
|
15822
15814
|
return t && t.isSpotLight ? t : null;
|
|
15823
15815
|
}
|
|
15824
15816
|
};
|
|
15825
|
-
function
|
|
15817
|
+
function Ap(e) {
|
|
15826
15818
|
return new Promise((t, n) => {
|
|
15827
15819
|
let r = new Image();
|
|
15828
15820
|
r.crossOrigin = "anonymous", r.onload = () => t(r), r.onerror = () => n(/* @__PURE__ */ Error(`Failed to load gobo image: ${e}`)), r.src = e;
|
|
15829
15821
|
});
|
|
15830
15822
|
}
|
|
15831
|
-
function
|
|
15823
|
+
function jp(e) {
|
|
15832
15824
|
return Math.max(0, Math.min(1, e));
|
|
15833
15825
|
}
|
|
15834
15826
|
//#endregion
|
|
15835
15827
|
//#region src/Processor/IESParser.js
|
|
15836
|
-
function
|
|
15828
|
+
function Mp(e, t = "ies") {
|
|
15837
15829
|
let n = e.search(/TILT\s*=/i);
|
|
15838
15830
|
if (n < 0) throw Error(`IES (${t}): missing TILT line`);
|
|
15839
15831
|
let r = e.indexOf("\n", n);
|
|
15840
15832
|
if (r < 0) throw Error(`IES (${t}): truncated TILT line`);
|
|
15841
15833
|
let i = e.slice(n, r).match(/TILT\s*=\s*(\w+)/i), a = i ? i[1].toUpperCase() : "NONE", o = e.slice(r);
|
|
15842
15834
|
if (a === "INCLUDE") {
|
|
15843
|
-
let e =
|
|
15844
|
-
o =
|
|
15835
|
+
let e = Ip(o), t = 2 + 2 * Number(e[1]);
|
|
15836
|
+
o = Lp(o, t);
|
|
15845
15837
|
}
|
|
15846
|
-
let s =
|
|
15838
|
+
let s = Ip(o), c = 0, l = () => Number(s[c++]), u = l(), d = l(), f = l(), p = l(), m = l(), h = l();
|
|
15847
15839
|
l(), l(), l(), l();
|
|
15848
15840
|
let g = l();
|
|
15849
15841
|
if (l(), l(), !Number.isFinite(p) || p <= 0) throw Error(`IES (${t}): invalid vertical angle count ${p}`);
|
|
@@ -15869,18 +15861,18 @@ function Ap(e, t = "ies") {
|
|
|
15869
15861
|
name: t
|
|
15870
15862
|
};
|
|
15871
15863
|
}
|
|
15872
|
-
function
|
|
15864
|
+
function Np(e, t, n) {
|
|
15873
15865
|
let r = new Uint8Array(t * n), { verticalAngles: i, horizontalAngles: a, candela: o, maxCandela: s } = e;
|
|
15874
15866
|
if (s <= 0) return r;
|
|
15875
15867
|
let c = i[i.length - 1], l = a[a.length - 1], u = a[0], d = a.length === 1 || l === u;
|
|
15876
15868
|
for (let e = 0; e < n; e++) {
|
|
15877
|
-
let f = (e + .5) / n * c, p =
|
|
15869
|
+
let f = (e + .5) / n * c, p = Rp(i, f), m = Math.min(p + 1, i.length - 1), h = i[m] - i[p], g = h > 0 ? (f - i[p]) / h : 0;
|
|
15878
15870
|
for (let n = 0; n < t; n++) {
|
|
15879
15871
|
let i;
|
|
15880
|
-
if (d) i =
|
|
15872
|
+
if (d) i = zp(o[p][0], o[m][0], g);
|
|
15881
15873
|
else {
|
|
15882
|
-
let e = u + (n + .5) / t * (l - u), r =
|
|
15883
|
-
i =
|
|
15874
|
+
let e = u + (n + .5) / t * (l - u), r = Rp(a, e), s = Math.min(r + 1, a.length - 1), c = a[s] - a[r], d = c > 0 ? (e - a[r]) / c : 0, f = o[p][r], h = o[p][s], _ = o[m][r], v = o[m][s];
|
|
15875
|
+
i = zp(zp(f, h, d), zp(_, v, d), g);
|
|
15884
15876
|
}
|
|
15885
15877
|
let c = Math.min(1, Math.max(0, i / s));
|
|
15886
15878
|
r[e * t + n] = Math.round(c * 255);
|
|
@@ -15888,7 +15880,7 @@ function jp(e, t, n) {
|
|
|
15888
15880
|
}
|
|
15889
15881
|
return r;
|
|
15890
15882
|
}
|
|
15891
|
-
function
|
|
15883
|
+
function Pp(e, t = .1) {
|
|
15892
15884
|
let { verticalAngles: n, horizontalAngles: r, candela: i, maxCandela: a } = e, o = Math.PI / 4;
|
|
15893
15885
|
if (a <= 0 || !n?.length) return o;
|
|
15894
15886
|
let s = a * t, c = r.length, l = n[n.length - 1], u = !1;
|
|
@@ -15903,7 +15895,7 @@ function Mp(e, t = .1) {
|
|
|
15903
15895
|
let d = l * Math.PI / 180;
|
|
15904
15896
|
return Math.min(Math.max(d, 5 * Math.PI / 180), 89 * Math.PI / 180);
|
|
15905
15897
|
}
|
|
15906
|
-
function
|
|
15898
|
+
function Fp(e, t, n = .7) {
|
|
15907
15899
|
let { verticalAngles: r, horizontalAngles: i, candela: a, maxCandela: o } = e;
|
|
15908
15900
|
if (o <= 0 || !r?.length || t <= 0) return 0;
|
|
15909
15901
|
let s = o * n, c = i.length, l = 0;
|
|
@@ -15916,15 +15908,15 @@ function Np(e, t, n = .7) {
|
|
|
15916
15908
|
let u = t * 180 / Math.PI, d = u > 0 ? 1 - l / u : 0;
|
|
15917
15909
|
return Math.min(Math.max(d, 0), 1);
|
|
15918
15910
|
}
|
|
15919
|
-
function
|
|
15911
|
+
function Ip(e) {
|
|
15920
15912
|
return e.split(/\s+/).filter((e) => e.length > 0);
|
|
15921
15913
|
}
|
|
15922
|
-
function
|
|
15914
|
+
function Lp(e, t) {
|
|
15923
15915
|
let n = /\S+/g, r = 0;
|
|
15924
15916
|
for (; n.exec(e) !== null;) if (r++, r === t) return e.slice(n.lastIndex);
|
|
15925
15917
|
return "";
|
|
15926
15918
|
}
|
|
15927
|
-
function
|
|
15919
|
+
function Rp(e, t) {
|
|
15928
15920
|
if (t <= e[0]) return 0;
|
|
15929
15921
|
if (t >= e[e.length - 1]) return e.length - 1;
|
|
15930
15922
|
let n = 0, r = e.length - 1;
|
|
@@ -15934,12 +15926,12 @@ function Ip(e, t) {
|
|
|
15934
15926
|
}
|
|
15935
15927
|
return n;
|
|
15936
15928
|
}
|
|
15937
|
-
function
|
|
15929
|
+
function zp(e, t, n) {
|
|
15938
15930
|
return e + (t - e) * n;
|
|
15939
15931
|
}
|
|
15940
15932
|
//#endregion
|
|
15941
15933
|
//#region src/managers/IESManager.js
|
|
15942
|
-
var
|
|
15934
|
+
var Bp = class {
|
|
15943
15935
|
constructor(e, t = {}) {
|
|
15944
15936
|
this.pathTracer = e, this._onReset = t.onReset || null, this.texture = null, this.entries = [], this._gridWidth = 128, this._gridHeight = 128;
|
|
15945
15937
|
}
|
|
@@ -15950,11 +15942,11 @@ var Rp = class {
|
|
|
15950
15942
|
try {
|
|
15951
15943
|
let r = await fetch(e.url);
|
|
15952
15944
|
if (!r.ok) throw Error(`HTTP ${r.status}`);
|
|
15953
|
-
let i =
|
|
15945
|
+
let i = Mp(await r.text(), e.name);
|
|
15954
15946
|
return {
|
|
15955
15947
|
it: e,
|
|
15956
15948
|
profile: i,
|
|
15957
|
-
grid:
|
|
15949
|
+
grid: Np(i, t, n)
|
|
15958
15950
|
};
|
|
15959
15951
|
} catch (t) {
|
|
15960
15952
|
return console.warn(`IESManager: failed to load "${e.name}": ${t.message}`), null;
|
|
@@ -15968,14 +15960,14 @@ var Rp = class {
|
|
|
15968
15960
|
let r = t[e];
|
|
15969
15961
|
o[n + e * 4 + 0] = r, o[n + e * 4 + 1] = r, o[n + e * 4 + 2] = r, o[n + e * 4 + 3] = 255;
|
|
15970
15962
|
}
|
|
15971
|
-
let i = r[e].profile, c =
|
|
15963
|
+
let i = r[e].profile, c = Pp(i);
|
|
15972
15964
|
s.push({
|
|
15973
15965
|
name: r[e].it.name,
|
|
15974
15966
|
index: e,
|
|
15975
15967
|
maxCandela: i.maxCandela,
|
|
15976
15968
|
photometricType: i.photometricType,
|
|
15977
15969
|
suggestedAngle: c,
|
|
15978
|
-
suggestedPenumbra:
|
|
15970
|
+
suggestedPenumbra: Fp(i, c),
|
|
15979
15971
|
lumens: i.lumens
|
|
15980
15972
|
});
|
|
15981
15973
|
}
|
|
@@ -16008,7 +16000,7 @@ var Rp = class {
|
|
|
16008
16000
|
l = Number.isFinite(e.lumens) ? e.lumens : null, i.userData.ies = {
|
|
16009
16001
|
name: e.name,
|
|
16010
16002
|
index: e.index,
|
|
16011
|
-
intensity:
|
|
16003
|
+
intensity: Vp(n),
|
|
16012
16004
|
fixtureLumens: l
|
|
16013
16005
|
}, r && (Number.isFinite(e.suggestedAngle) && (i.angle = e.suggestedAngle, o = e.suggestedAngle), Number.isFinite(e.suggestedPenumbra) && (i.penumbra = e.suggestedPenumbra, s = e.suggestedPenumbra), i.decay = 2, c = 2);
|
|
16014
16006
|
}
|
|
@@ -16031,44 +16023,44 @@ var Rp = class {
|
|
|
16031
16023
|
return t && t.isSpotLight ? t : null;
|
|
16032
16024
|
}
|
|
16033
16025
|
};
|
|
16034
|
-
function
|
|
16026
|
+
function Vp(e) {
|
|
16035
16027
|
return Math.max(0, Math.min(1, e));
|
|
16036
16028
|
}
|
|
16037
16029
|
//#endregion
|
|
16038
16030
|
//#region src/Processor/ToneMapCPU.js
|
|
16039
|
-
var
|
|
16040
|
-
function Vp(e, t, n, r, i) {
|
|
16041
|
-
i[0] = Bp(e), i[1] = Bp(t), i[2] = Bp(n);
|
|
16042
|
-
}
|
|
16043
|
-
function Hp(e, t, n, r, i) {
|
|
16044
|
-
i[0] = Bp(e * r), i[1] = Bp(t * r), i[2] = Bp(n * r);
|
|
16045
|
-
}
|
|
16031
|
+
var Hp = (e) => Math.min(Math.max(e, 0), 1);
|
|
16046
16032
|
function Up(e, t, n, r, i) {
|
|
16047
|
-
|
|
16033
|
+
i[0] = Hp(e), i[1] = Hp(t), i[2] = Hp(n);
|
|
16048
16034
|
}
|
|
16049
16035
|
function Wp(e, t, n, r, i) {
|
|
16036
|
+
i[0] = Hp(e * r), i[1] = Hp(t * r), i[2] = Hp(n * r);
|
|
16037
|
+
}
|
|
16038
|
+
function Gp(e, t, n, r, i) {
|
|
16039
|
+
e *= r, t *= r, n *= r, i[0] = Hp(e / (e + 1)), i[1] = Hp(t / (t + 1)), i[2] = Hp(n / (n + 1));
|
|
16040
|
+
}
|
|
16041
|
+
function Kp(e, t, n, r, i) {
|
|
16050
16042
|
e = Math.max(e * r - .004, 0), t = Math.max(t * r - .004, 0), n = Math.max(n * r - .004, 0);
|
|
16051
16043
|
let a = (e) => (e * (6.2 * e + .5) / (e * (6.2 * e + 1.7) + .06)) ** 2.2;
|
|
16052
16044
|
i[0] = a(e), i[1] = a(t), i[2] = a(n);
|
|
16053
16045
|
}
|
|
16054
|
-
function
|
|
16046
|
+
function qp(e, t, n, r, i) {
|
|
16055
16047
|
e = e * r / .6, t = t * r / .6, n = n * r / .6;
|
|
16056
16048
|
let a = .59719 * e + .35458 * t + .04823 * n, o = .076 * e + .90834 * t + .01566 * n, s = .0284 * e + .13383 * t + .83777 * n, c = (e) => (e * (e + .0245786) - 90537e-9) / (e * (.983729 * e + .432951) + .238081);
|
|
16057
|
-
a = c(a), o = c(o), s = c(s), i[0] =
|
|
16049
|
+
a = c(a), o = c(o), s = c(s), i[0] = Hp(1.60475 * a - .53108 * o - .07367 * s), i[1] = Hp(-.10208 * a + 1.10813 * o - .00605 * s), i[2] = Hp(-.00327 * a - .07276 * o + 1.07602 * s);
|
|
16058
16050
|
}
|
|
16059
|
-
function
|
|
16051
|
+
function Jp(e, t, n, r, i) {
|
|
16060
16052
|
e *= r, t *= r, n *= r;
|
|
16061
16053
|
let a = .6274 * e + .3293 * t + .0433 * n, o = .0691 * e + .9195 * t + .0113 * n, s = .0164 * e + .088 * t + .8956 * n, c = .856627153315983 * a + .0951212405381588 * o + .0482516061458583 * s, l = .137318972929847 * a + .761241990602591 * o + .101439036467562 * s, u = .11189821299995 * a + .0767994186031903 * o + .811302368396859 * s, d = -12.47393, f = 4.026069 - d;
|
|
16062
|
-
c =
|
|
16054
|
+
c = Hp((Math.log2(Math.max(c, 1e-10)) - d) / f), l = Hp((Math.log2(Math.max(l, 1e-10)) - d) / f), u = Hp((Math.log2(Math.max(u, 1e-10)) - d) / f);
|
|
16063
16055
|
let p = (e) => {
|
|
16064
16056
|
let t = e * e, n = t * t;
|
|
16065
16057
|
return 15.5 * n * t - 40.14 * n * e + 31.96 * n - 6.868 * t * e + .4298 * t + .1191 * e - .00232;
|
|
16066
16058
|
};
|
|
16067
16059
|
c = p(c), l = p(l), u = p(u);
|
|
16068
16060
|
let m = 1.1271005818144368 * c - .11060664309660323 * l - .016493938717834573 * u, h = -.1413297634984383 * c + 1.157823702216272 * l - .016493938717834257 * u, g = -.14132976349843826 * c - .11060664309660294 * l + 1.2519364065950405 * u;
|
|
16069
|
-
m = Math.max(0, m) ** 2.2, h = Math.max(0, h) ** 2.2, g = Math.max(0, g) ** 2.2, i[0] =
|
|
16061
|
+
m = Math.max(0, m) ** 2.2, h = Math.max(0, h) ** 2.2, g = Math.max(0, g) ** 2.2, i[0] = Hp(1.6605 * m - .5876 * h - .0728 * g), i[1] = Hp(-.1246 * m + 1.1329 * h - .0083 * g), i[2] = Hp(-.0182 * m - .1006 * h + 1.1187 * g);
|
|
16070
16062
|
}
|
|
16071
|
-
function
|
|
16063
|
+
function Yp(e, t, n, r, i) {
|
|
16072
16064
|
let a = .76;
|
|
16073
16065
|
e *= r, t *= r, n *= r;
|
|
16074
16066
|
let o = Math.min(e, Math.min(t, n)), s = o < .08 ? o - 6.25 * o * o : .04;
|
|
@@ -16083,43 +16075,43 @@ function qp(e, t, n, r, i) {
|
|
|
16083
16075
|
let f = 1 - 1 / (.15 * (c - u) + 1);
|
|
16084
16076
|
i[0] = e + (u - e) * f, i[1] = t + (u - t) * f, i[2] = n + (u - n) * f;
|
|
16085
16077
|
}
|
|
16086
|
-
var
|
|
16087
|
-
[jt,
|
|
16088
|
-
[q,
|
|
16089
|
-
[Kt,
|
|
16090
|
-
[Qe,
|
|
16091
|
-
[Ue,
|
|
16092
|
-
[Ge,
|
|
16093
|
-
[kt,
|
|
16094
|
-
]),
|
|
16095
|
-
function
|
|
16078
|
+
var Xp = new Map([
|
|
16079
|
+
[jt, Up],
|
|
16080
|
+
[q, Wp],
|
|
16081
|
+
[Kt, Gp],
|
|
16082
|
+
[Qe, Kp],
|
|
16083
|
+
[Ue, qp],
|
|
16084
|
+
[Ge, Jp],
|
|
16085
|
+
[kt, Yp]
|
|
16086
|
+
]), Zp = 1 / 2.2;
|
|
16087
|
+
function Qp(e) {
|
|
16096
16088
|
return e <= .0031308 ? 12.92 * e : 1.055 * e ** (1 / 2.4) - .055;
|
|
16097
16089
|
}
|
|
16098
|
-
var
|
|
16099
|
-
function
|
|
16090
|
+
var $p = .2126, em = .7152, tm = .0722;
|
|
16091
|
+
function nm(e, t) {
|
|
16100
16092
|
if (t === 1) return;
|
|
16101
|
-
let n = e[0] *
|
|
16093
|
+
let n = e[0] * $p + e[1] * em + e[2] * tm;
|
|
16102
16094
|
e[0] = n + (e[0] - n) * t, e[1] = n + (e[1] - n) * t, e[2] = n + (e[2] - n) * t;
|
|
16103
16095
|
}
|
|
16104
16096
|
//#endregion
|
|
16105
16097
|
//#region src/Passes/OIDNDenoiser.js
|
|
16106
|
-
var
|
|
16107
|
-
async function
|
|
16108
|
-
if (!
|
|
16098
|
+
var rm = ai("oidn"), im = null, am = null;
|
|
16099
|
+
async function om() {
|
|
16100
|
+
if (!im) {
|
|
16109
16101
|
let [e, t] = await Promise.all([import("oidn-web"), import("@tensorflow/tfjs-core")]);
|
|
16110
|
-
|
|
16102
|
+
im = e.initUNetFromURL, am = t.engine;
|
|
16111
16103
|
}
|
|
16112
|
-
return
|
|
16104
|
+
return im;
|
|
16113
16105
|
}
|
|
16114
|
-
function
|
|
16115
|
-
if (
|
|
16116
|
-
let e =
|
|
16106
|
+
function sm() {
|
|
16107
|
+
if (am) try {
|
|
16108
|
+
let e = am();
|
|
16117
16109
|
e?.registryFactory && "webgpu-oidn" in e.registryFactory && e.removeBackend("webgpu-oidn");
|
|
16118
16110
|
} catch (e) {
|
|
16119
|
-
|
|
16111
|
+
rm.warn("failed to clear cached TFJS backend", e);
|
|
16120
16112
|
}
|
|
16121
16113
|
}
|
|
16122
|
-
var
|
|
16114
|
+
var cm = new Float32Array(3), lm = {
|
|
16123
16115
|
QUALITY_MODELS: {
|
|
16124
16116
|
fast: "rt_hdr_alb_nrm_small",
|
|
16125
16117
|
balance: "rt_hdr_alb_nrm",
|
|
@@ -16131,7 +16123,7 @@ var om = new Float32Array(3), sm = {
|
|
|
16131
16123
|
debugGbufferMaps: !0,
|
|
16132
16124
|
tileSize: 256
|
|
16133
16125
|
}
|
|
16134
|
-
},
|
|
16126
|
+
}, um = class extends ut {
|
|
16135
16127
|
constructor(e, t, n, r, i = {}) {
|
|
16136
16128
|
if (super(), !e || !t || !n || !r) throw Error("OIDNDenoiser requires output canvas, renderer, scene, and camera");
|
|
16137
16129
|
this.renderer = t, this.scene = n, this.camera = r, this.input = t.domElement, this.output = e, this.extractGBufferData = i.extractGBufferData || null, this.getMRTRenderTarget = i.getMRTRenderTarget || null, this.backendParamsGetter = i.backendParams || null, this.getGPUTextures = i.getGPUTextures || null, this.getExposure = i.getExposure || (() => 1), this.getToneMapping = i.getToneMapping || (() => Ue), this.getSaturation = i.getSaturation || (() => 1), this.getTransparentBackground = i.getTransparentBackground || (() => !1), this.isGPUMode = !!this.backendParamsGetter, this.gpuDevice = null, this._gpuInputBuffers = {
|
|
@@ -16142,14 +16134,14 @@ var om = new Float32Array(3), sm = {
|
|
|
16142
16134
|
width: 0,
|
|
16143
16135
|
height: 0
|
|
16144
16136
|
}, this._gpuInputPadBuffer = null, this._gpuInputPaddedRowBytes = 0, this._alphaReadbackBuffer = null, this._alphaReadbackMapped = !1, this._cachedAlpha = null, this._cachedAlphaWidth = 0, this.config = {
|
|
16145
|
-
...
|
|
16137
|
+
...lm.DEFAULT_OPTIONS,
|
|
16146
16138
|
...i
|
|
16147
16139
|
}, this.enabled = this.config.enableOIDN, this.quality = this.config.oidnQuality, this.debugGbufferMaps = this.config.debugGbufferMaps, this.tileSize = this.config.tileSize, this.state = {
|
|
16148
16140
|
isDenoising: !1,
|
|
16149
16141
|
isLoading: !1,
|
|
16150
16142
|
abortController: null
|
|
16151
16143
|
}, this._pendingStagingBuffers = /* @__PURE__ */ new Set(), this._pendingTileBlits = [], this.currentTZAUrl = null, this.unet = null, this._pendingStart = !1, this._initialize().catch((e) => {
|
|
16152
|
-
|
|
16144
|
+
rm.error("init failed:", e), this.dispatchEvent({
|
|
16153
16145
|
type: "error",
|
|
16154
16146
|
error: e
|
|
16155
16147
|
});
|
|
@@ -16195,13 +16187,13 @@ var om = new Float32Array(3), sm = {
|
|
|
16195
16187
|
let e = this.backendParamsGetter();
|
|
16196
16188
|
this.gpuDevice = e?.device ?? null, t = e?.device ? e : void 0;
|
|
16197
16189
|
}
|
|
16198
|
-
this.unet = await (await
|
|
16190
|
+
this.unet = await (await om())(e, t, {
|
|
16199
16191
|
aux: !0,
|
|
16200
16192
|
hdr: !0,
|
|
16201
16193
|
maxTileSize: this.tileSize
|
|
16202
|
-
}), this.currentTZAUrl = e, this.dispatchEvent({ type: "loaded" }),
|
|
16194
|
+
}), this.currentTZAUrl = e, this.dispatchEvent({ type: "loaded" }), rm.debug("UNet weights loaded:", e);
|
|
16203
16195
|
} catch (e) {
|
|
16204
|
-
|
|
16196
|
+
rm.error("UNet weights failed to load:", e), this.dispatchEvent({
|
|
16205
16197
|
type: "error",
|
|
16206
16198
|
error: /* @__PURE__ */ Error(`Denoiser loading failed: ${e.message}`)
|
|
16207
16199
|
});
|
|
@@ -16210,14 +16202,14 @@ var om = new Float32Array(3), sm = {
|
|
|
16210
16202
|
}
|
|
16211
16203
|
}
|
|
16212
16204
|
_generateTzaUrl() {
|
|
16213
|
-
let { oidnWeightsBaseUrl: e } = cl(), { QUALITY_MODELS: t } =
|
|
16205
|
+
let { oidnWeightsBaseUrl: e } = cl(), { QUALITY_MODELS: t } = lm;
|
|
16214
16206
|
return `${e}${t[this.quality] || t.balance}.tza`;
|
|
16215
16207
|
}
|
|
16216
16208
|
async updateConfiguration(e) {
|
|
16217
16209
|
Object.keys(e).some((t) => this.config[t] !== e[t]) && (Object.assign(this.config, e), this.quality = this.config.oidnQuality, this.debugGbufferMaps = this.config.debugGbufferMaps, this.tileSize = this.config.tileSize, await this._setupUNetDenoiser());
|
|
16218
16210
|
}
|
|
16219
16211
|
async updateQuality(e) {
|
|
16220
|
-
if (!Object.prototype.hasOwnProperty.call(
|
|
16212
|
+
if (!Object.prototype.hasOwnProperty.call(lm.QUALITY_MODELS, e)) throw Error(`Invalid quality setting: ${e}. Must be one of: ${Object.keys(lm.QUALITY_MODELS).join(", ")}`);
|
|
16221
16213
|
await this.updateConfiguration({ oidnQuality: e });
|
|
16222
16214
|
}
|
|
16223
16215
|
async start() {
|
|
@@ -16228,7 +16220,7 @@ var om = new Float32Array(3), sm = {
|
|
|
16228
16220
|
if (t) {
|
|
16229
16221
|
this.renderer?.resetState?.(), this.input.style.opacity = "0";
|
|
16230
16222
|
let t = performance.now() - e;
|
|
16231
|
-
|
|
16223
|
+
rm.debug(`denoise complete in ${Q.ms(t)} · quality ${this.quality}`);
|
|
16232
16224
|
}
|
|
16233
16225
|
return t;
|
|
16234
16226
|
}
|
|
@@ -16238,7 +16230,7 @@ var om = new Float32Array(3), sm = {
|
|
|
16238
16230
|
try {
|
|
16239
16231
|
return await this._executeUNet(), !0;
|
|
16240
16232
|
} catch (e) {
|
|
16241
|
-
return e.name === "AbortError" ?
|
|
16233
|
+
return e.name === "AbortError" ? rm.debug("denoise aborted") : rm.error("denoise error:", e), this.input.style.opacity = "1", !1;
|
|
16242
16234
|
} finally {
|
|
16243
16235
|
this.state.isDenoising = !1, this.state.abortController = null, this.dispatchEvent({ type: "end" });
|
|
16244
16236
|
}
|
|
@@ -16248,11 +16240,11 @@ var om = new Float32Array(3), sm = {
|
|
|
16248
16240
|
}
|
|
16249
16241
|
async _executeUNetGPU() {
|
|
16250
16242
|
let { width: e, height: t } = this.output;
|
|
16251
|
-
if (!this.getGPUTextures) return
|
|
16243
|
+
if (!this.getGPUTextures) return rm.warn("GPU mode enabled but getGPUTextures not provided"), !1;
|
|
16252
16244
|
let n = this.getGPUTextures();
|
|
16253
|
-
if (!n?.color) return
|
|
16245
|
+
if (!n?.color) return rm.warn("GPU textures not ready yet"), !1;
|
|
16254
16246
|
let r = this.gpuDevice;
|
|
16255
|
-
if (!r) return
|
|
16247
|
+
if (!r) return rm.warn("gpuDevice not available"), !1;
|
|
16256
16248
|
this._ensureGPUInputBuffers(e, t);
|
|
16257
16249
|
let i = r.createCommandEncoder({ label: "oidn-tex-to-buf" }), a = e * 16, o = this._gpuInputPaddedRowBytes, s = o > a, c = this._gpuInputPadBuffer, l = (n, r) => {
|
|
16258
16250
|
if (!s) i.copyTextureToBuffer({
|
|
@@ -16402,10 +16394,10 @@ var om = new Float32Array(3), sm = {
|
|
|
16402
16394
|
}
|
|
16403
16395
|
r.queue.submit([d.finish()]);
|
|
16404
16396
|
let f = u.mapAsync(GPUMapMode.READ).then(() => {
|
|
16405
|
-
let e = new Float32Array(u.getMappedRange()), t = new ImageData(o, s), r = this.getExposure(), c = this.getSaturation(), l =
|
|
16397
|
+
let e = new Float32Array(u.getMappedRange()), t = new ImageData(o, s), r = this.getExposure(), c = this.getSaturation(), l = Xp.get(this.getToneMapping()) || Xp.get(Ue), d = this._cachedAlpha, f = this._cachedAlphaWidth;
|
|
16406
16398
|
for (let i = 0, a = e.length; i < a; i += 4) {
|
|
16407
16399
|
let a = e[i] * r, s = e[i + 1] * r, u = e[i + 2] * r;
|
|
16408
|
-
if (c !== 1 && (
|
|
16400
|
+
if (c !== 1 && (cm[0] = a, cm[1] = s, cm[2] = u, nm(cm, c), a = cm[0], s = cm[1], u = cm[2]), l(a, s, u, 1, cm), t.data[i] = Qp(cm[0]) * 255 + .5 | 0, t.data[i + 1] = Qp(cm[1]) * 255 + .5 | 0, t.data[i + 2] = Qp(cm[2]) * 255 + .5 | 0, d) {
|
|
16409
16401
|
let e = (i >> 2) % o, r = (i >> 2) / o | 0;
|
|
16410
16402
|
t.data[i + 3] = d[(n.y + r) * f + n.x + e];
|
|
16411
16403
|
} else t.data[i + 3] = 255;
|
|
@@ -16432,7 +16424,7 @@ var om = new Float32Array(3), sm = {
|
|
|
16432
16424
|
async _displayGPUOutput({ data: e, width: t, height: n }) {
|
|
16433
16425
|
let r = this.gpuDevice;
|
|
16434
16426
|
if (!r) {
|
|
16435
|
-
|
|
16427
|
+
rm.error("gpuDevice not available for output readback");
|
|
16436
16428
|
return;
|
|
16437
16429
|
}
|
|
16438
16430
|
let i = t * n * 4 * 4, a = r.createBuffer({
|
|
@@ -16443,10 +16435,10 @@ var om = new Float32Array(3), sm = {
|
|
|
16443
16435
|
try {
|
|
16444
16436
|
let o = r.createCommandEncoder({ label: "oidn-readback" });
|
|
16445
16437
|
o.copyBufferToBuffer(e, 0, a, 0, i), r.queue.submit([o.finish()]), await a.mapAsync(GPUMapMode.READ);
|
|
16446
|
-
let s = new Float32Array(a.getMappedRange()), c = new ImageData(t, n), l = this.getExposure(), u = this.getSaturation(), d =
|
|
16438
|
+
let s = new Float32Array(a.getMappedRange()), c = new ImageData(t, n), l = this.getExposure(), u = this.getSaturation(), d = Xp.get(this.getToneMapping()) || Xp.get(Ue), f = this._cachedAlpha;
|
|
16447
16439
|
for (let e = 0, t = s.length; e < t; e += 4) {
|
|
16448
16440
|
let t = s[e] * l, n = s[e + 1] * l, r = s[e + 2] * l;
|
|
16449
|
-
u !== 1 && (
|
|
16441
|
+
u !== 1 && (cm[0] = t, cm[1] = n, cm[2] = r, nm(cm, u), t = cm[0], n = cm[1], r = cm[2]), d(t, n, r, 1, cm), c.data[e] = Qp(cm[0]) * 255 + .5 | 0, c.data[e + 1] = Qp(cm[1]) * 255 + .5 | 0, c.data[e + 2] = Qp(cm[2]) * 255 + .5 | 0, c.data[e + 3] = f ? f[e >> 2] : 255;
|
|
16450
16442
|
}
|
|
16451
16443
|
a.unmap(), this.ctx.putImageData(c, 0, 0);
|
|
16452
16444
|
} finally {
|
|
@@ -16454,12 +16446,12 @@ var om = new Float32Array(3), sm = {
|
|
|
16454
16446
|
}
|
|
16455
16447
|
}
|
|
16456
16448
|
abort() {
|
|
16457
|
-
this._pendingStart = !1, !(!this.enabled || !this.state.isDenoising) && (this.state.abortController?.abort(), this._destroyPendingStagingBuffers(), this.input.style.opacity = "1", this.state.isDenoising = !1, this.dispatchEvent({ type: "end" }),
|
|
16449
|
+
this._pendingStart = !1, !(!this.enabled || !this.state.isDenoising) && (this.state.abortController?.abort(), this._destroyPendingStagingBuffers(), this.input.style.opacity = "1", this.state.isDenoising = !1, this.dispatchEvent({ type: "end" }), rm.debug("denoise aborted"));
|
|
16458
16450
|
}
|
|
16459
16451
|
setSize(e, t) {
|
|
16460
16452
|
if (e <= 0 || t <= 0) throw Error(`Invalid dimensions: ${e}x${t}`);
|
|
16461
16453
|
this.output.width = e, this.output.height = t, this._setupUNetDenoiser().catch((e) => {
|
|
16462
|
-
|
|
16454
|
+
rm.error("reinitialize after size change failed:", e);
|
|
16463
16455
|
});
|
|
16464
16456
|
}
|
|
16465
16457
|
_destroyPendingStagingBuffers() {
|
|
@@ -16467,13 +16459,13 @@ var om = new Float32Array(3), sm = {
|
|
|
16467
16459
|
this._pendingStagingBuffers.clear();
|
|
16468
16460
|
}
|
|
16469
16461
|
dispose() {
|
|
16470
|
-
this.abort(), this._destroyPendingStagingBuffers(), this.unet?.dispose(),
|
|
16462
|
+
this.abort(), this._destroyPendingStagingBuffers(), this.unet?.dispose(), sm(), this._destroyGPUInputBuffers(), this.output?.parentNode && this.output.remove(), this.unet = null, this.ctx = null, this.state.abortController = null, this.removeAllListeners?.(), rm.debug("disposed");
|
|
16471
16463
|
}
|
|
16472
|
-
},
|
|
16473
|
-
function
|
|
16464
|
+
}, dm = "let e={ortRuntimeUrl:`https://cdn.jsdelivr.net/npm/onnxruntime-web@1.24.3/dist/ort.webgpu.bundle.min.mjs`,ortWasmPaths:`https://cdn.jsdelivr.net/npm/onnxruntime-web@1.24.3/dist/`,cacheNamespace:`rayzee`},t=null;async function n(){return t||(t=await import(e.ortRuntimeUrl),t.env.wasm.wasmPaths=e.ortWasmPaths,t.env.logLevel=`error`,t)}function r(){return`${e.cacheNamespace}:ai-upscaler-models`}const i=`models`;let a=null,o=null;function s(){return new Promise((e,t)=>{let n=indexedDB.open(r(),1);n.onupgradeneeded=()=>n.result.createObjectStore(i),n.onsuccess=()=>e(n.result),n.onerror=()=>t(n.error)})}async function c(e){try{let t=await s();return await new Promise((n,r)=>{let a=t.transaction(i,`readonly`).objectStore(i).get(e);a.onsuccess=()=>n(a.result||null),a.onerror=()=>r(a.error)})}catch{return null}}async function l(e,t){try{let n=await s();await new Promise((r,a)=>{let o=n.transaction(i,`readwrite`);o.objectStore(i).put(t,e),o.oncomplete=()=>r(),o.onerror=()=>a(o.error)})}catch{}}async function u(e){let t=await c(e);if(t)return console.log(`AI Upscaler Worker: model loaded from cache (${(t.byteLength/1024/1024).toFixed(1)}MB)`),t;let n=await fetch(e);if(!n.ok)throw Error(`Failed to fetch model: ${n.status}`);let r=await n.arrayBuffer();return l(e,r.slice(0)),r}async function d(e,t){if(a&&o===e){self.postMessage({type:`loaded`,backend:`webgpu`});return}a&&=(await a.release(),null);let[r,i]=await Promise.all([u(e),n()]);a=await i.InferenceSession.create(r,t),o=e;let s=512;try{let e=await navigator.gpu?.requestAdapter(),t=await e?.requestAdapterInfo?.()||e?.info,n=/apple|swiftshader|llvmpipe/i.test(t?.vendor||``)||/apple|swiftshader/i.test(t?.architecture||``),r=t?.device?.toLowerCase?.()?.includes(`integrated`)||/intel.*iris|intel.*uhd|intel.*hd|amd.*vega|radeon.*graphics/i.test(t?.description||``);s=n?128:r?256:512,console.log(`AI Upscaler Worker: GPU=\"${t?.description||t?.device||`unknown`}\", tileSize=${s}`)}catch{}let c=(r.byteLength/1024/1024).toFixed(1);console.log(`AI Upscaler Worker: model loaded (${c}MB), backend: webgpu`),self.postMessage({type:`loaded`,backend:`webgpu`,tileSize:s})}async function f(e,t,r,i){let o=await n(),s=a.inputNames[0],c=a.outputNames[0],l=new o.Tensor(`float32`,e,[1,3,r,t]),u=(await a.run({[s]:l}))[c].data;self.postMessage({type:`inferred`,outputData:u,id:i},[u.buffer])}self.onmessage=async t=>{let{type:n}=t.data;try{n===`load`?(t.data.ortRuntimeUrl&&(e.ortRuntimeUrl=t.data.ortRuntimeUrl),t.data.ortWasmPaths&&(e.ortWasmPaths=t.data.ortWasmPaths),t.data.cacheNamespace&&(e.cacheNamespace=t.data.cacheNamespace),await d(t.data.url,t.data.sessionOptions)):n===`infer`?await f(t.data.tileData,t.data.width,t.data.height,t.data.id):n===`dispose`&&a&&(await a.release(),a=null,o=null)}catch(e){self.postMessage({type:`error`,message:e.message,id:t.data?.id})}};", fm = typeof self < "u" && self.Blob && new Blob(["URL.revokeObjectURL(import.meta.url);", dm], { type: "text/javascript;charset=utf-8" });
|
|
16465
|
+
function pm(e) {
|
|
16474
16466
|
let t;
|
|
16475
16467
|
try {
|
|
16476
|
-
if (t =
|
|
16468
|
+
if (t = fm && (self.URL || self.webkitURL).createObjectURL(fm), !t) throw "";
|
|
16477
16469
|
let n = new Worker(t, {
|
|
16478
16470
|
type: "module",
|
|
16479
16471
|
name: e?.name
|
|
@@ -16482,7 +16474,7 @@ function dm(e) {
|
|
|
16482
16474
|
(self.URL || self.webkitURL).revokeObjectURL(t);
|
|
16483
16475
|
}), n;
|
|
16484
16476
|
} catch {
|
|
16485
|
-
return new Worker("data:text/javascript;charset=utf-8," + encodeURIComponent(
|
|
16477
|
+
return new Worker("data:text/javascript;charset=utf-8," + encodeURIComponent(dm), {
|
|
16486
16478
|
type: "module",
|
|
16487
16479
|
name: e?.name
|
|
16488
16480
|
});
|
|
@@ -16490,7 +16482,7 @@ function dm(e) {
|
|
|
16490
16482
|
}
|
|
16491
16483
|
//#endregion
|
|
16492
16484
|
//#region src/Passes/AIUpscaler.js
|
|
16493
|
-
var
|
|
16485
|
+
var mm = {
|
|
16494
16486
|
fast: {
|
|
16495
16487
|
2: "2x-spanx2-ch48.onnx",
|
|
16496
16488
|
4: "4xNomos8k_span_otf_strong_fp32_opset17.onnx"
|
|
@@ -16504,17 +16496,17 @@ var fm = {
|
|
|
16504
16496
|
4: "4xNomos2_hq_mosr_fp32.onnx"
|
|
16505
16497
|
}
|
|
16506
16498
|
};
|
|
16507
|
-
function
|
|
16499
|
+
function hm() {
|
|
16508
16500
|
let { upscalerModelBaseUrl: e } = cl(), t = {};
|
|
16509
|
-
for (let n in
|
|
16501
|
+
for (let n in mm) {
|
|
16510
16502
|
t[n] = {};
|
|
16511
|
-
for (let r in
|
|
16503
|
+
for (let r in mm[n]) t[n][r] = e + mm[n][r];
|
|
16512
16504
|
}
|
|
16513
16505
|
return t;
|
|
16514
16506
|
}
|
|
16515
|
-
var
|
|
16507
|
+
var gm = {
|
|
16516
16508
|
get QUALITY_PRESETS() {
|
|
16517
|
-
return
|
|
16509
|
+
return hm();
|
|
16518
16510
|
},
|
|
16519
16511
|
TILE_SIZE: 512,
|
|
16520
16512
|
TILE_OVERLAP: 16,
|
|
@@ -16525,17 +16517,17 @@ var mm = {
|
|
|
16525
16517
|
}],
|
|
16526
16518
|
graphOptimizationLevel: "all"
|
|
16527
16519
|
}
|
|
16528
|
-
},
|
|
16520
|
+
}, _m = class extends ut {
|
|
16529
16521
|
constructor(e, t, n = {}) {
|
|
16530
16522
|
if (super(), !e || !t) throw Error("AIUpscaler requires output canvas and renderer");
|
|
16531
|
-
this.renderer = t, this.input = t.domElement, this.output = e, this.getSourceCanvas = n.getSourceCanvas || null, this.getGPUTextures = n.getGPUTextures || null, this.getExposure = n.getExposure || (() => 1), this.getToneMapping = n.getToneMapping || (() => Ue), this.getSaturation = n.getSaturation || (() => 1), this.enabled = !1, this.hdr = !1, this.scaleFactor = n.scaleFactor || 2, this.quality = n.quality || "fast", this.tileSize = n.tileSize ||
|
|
16523
|
+
this.renderer = t, this.input = t.domElement, this.output = e, this.getSourceCanvas = n.getSourceCanvas || null, this.getGPUTextures = n.getGPUTextures || null, this.getExposure = n.getExposure || (() => 1), this.getToneMapping = n.getToneMapping || (() => Ue), this.getSaturation = n.getSaturation || (() => 1), this.enabled = !1, this.hdr = !1, this.scaleFactor = n.scaleFactor || 2, this.quality = n.quality || "fast", this.tileSize = n.tileSize || gm.TILE_SIZE, this._tileSizeOverride = !!n.tileSize, this.state = {
|
|
16532
16524
|
isUpscaling: !1,
|
|
16533
16525
|
isLoading: !1,
|
|
16534
16526
|
abortController: null
|
|
16535
16527
|
}, this._worker = null, this._currentModelUrl = null, this._tileId = 0, this._pendingWorkerHandlers = /* @__PURE__ */ new Set(), this._upscaledAlpha = null, this._upscaledAlphaWidth = 0, this._backupCanvas = null, this._baseWidth = e.width, this._baseHeight = e.height, this._hdrStagingBuffer = null, this._hdrStagingWidth = 0, this._hdrStagingHeight = 0;
|
|
16536
16528
|
}
|
|
16537
16529
|
async _ensureSession() {
|
|
16538
|
-
let e =
|
|
16530
|
+
let e = gm.QUALITY_PRESETS[this.quality];
|
|
16539
16531
|
if (!e) throw Error(`Unknown quality preset: ${this.quality}`);
|
|
16540
16532
|
let t = e[this.scaleFactor];
|
|
16541
16533
|
if (!t) throw Error(`No model for ${this.quality}/${this.scaleFactor}x`);
|
|
@@ -16545,14 +16537,14 @@ var mm = {
|
|
|
16545
16537
|
message: `Loading ${this.scaleFactor}x upscale model...`
|
|
16546
16538
|
});
|
|
16547
16539
|
try {
|
|
16548
|
-
this._worker ||= new
|
|
16540
|
+
this._worker ||= new pm(), await new Promise((e, n) => {
|
|
16549
16541
|
let r = (t) => {
|
|
16550
16542
|
t.data.type === "loaded" ? (this._worker.removeEventListener("message", r), t.data.tileSize && !this._tileSizeOverride && (this.tileSize = t.data.tileSize), console.log(`AI Upscaler: ${this.scaleFactor}x model loaded, backend: ${t.data.backend}, tileSize: ${this.tileSize}`), e()) : t.data.type === "error" && (this._worker.removeEventListener("message", r), n(Error(t.data.message)));
|
|
16551
16543
|
}, { ortRuntimeUrl: i, ortWasmPaths: a, cacheNamespace: o } = cl();
|
|
16552
16544
|
this._worker.addEventListener("message", r), this._worker.postMessage({
|
|
16553
16545
|
type: "load",
|
|
16554
16546
|
url: t,
|
|
16555
|
-
sessionOptions:
|
|
16547
|
+
sessionOptions: gm.SESSION_OPTIONS,
|
|
16556
16548
|
ortRuntimeUrl: i,
|
|
16557
16549
|
ortWasmPaths: a,
|
|
16558
16550
|
cacheNamespace: o
|
|
@@ -16622,8 +16614,8 @@ var mm = {
|
|
|
16622
16614
|
willReadFrequently: !0,
|
|
16623
16615
|
alpha: !0
|
|
16624
16616
|
});
|
|
16625
|
-
this._cacheUpscaledAlpha(t, n * i, r * i), t.isHDR && (this._hdrToneMapFn =
|
|
16626
|
-
let o =
|
|
16617
|
+
this._cacheUpscaledAlpha(t, n * i, r * i), t.isHDR && (this._hdrToneMapFn = Xp.get(this.getToneMapping()) || Xp.get(Ue), this._hdrExposure = this.getExposure(), this._hdrSaturation = this.getSaturation(), this._tmOut = new Float32Array(3));
|
|
16618
|
+
let o = gm.TILE_OVERLAP, s = this.tileSize, c = s - o * 2, l = Math.ceil(n / c), u = Math.ceil(r / c), d = l * u, f = 0;
|
|
16627
16619
|
for (let o = 0; o < u; o++) for (let u = 0; u < l; u++) {
|
|
16628
16620
|
if (e.aborted) throw new DOMException("Aborted", "AbortError");
|
|
16629
16621
|
let l = Math.min(u * c, Math.max(0, n - s)), p = Math.min(o * c, Math.max(0, r - s)), m = Math.min(s, n - l), h = Math.min(s, r - p), g = this._extractTile(t, l, p, m, h), _ = await this._inferTile(g, m, h), v = l * i, y = p * i, b = m * i, x = h * i, S = this._tensorToImageData(_, b, x, v, y);
|
|
@@ -16696,7 +16688,7 @@ var mm = {
|
|
|
16696
16688
|
let u = ((n + e) * o + (t + i)) * 4, d = e * r + i;
|
|
16697
16689
|
if (s) {
|
|
16698
16690
|
let e = this._hdrToneMapFn, t = this._hdrExposure, n = this._hdrSaturation, r = a[u] * t, i = a[u + 1] * t, o = a[u + 2] * t;
|
|
16699
|
-
n !== 1 && (this._tmOut[0] = r, this._tmOut[1] = i, this._tmOut[2] = o,
|
|
16691
|
+
n !== 1 && (this._tmOut[0] = r, this._tmOut[1] = i, this._tmOut[2] = o, nm(this._tmOut, n), r = this._tmOut[0], i = this._tmOut[1], o = this._tmOut[2]), e(r, i, o, 1, this._tmOut), l[d] = this._tmOut[0] ** +Zp, l[c + d] = this._tmOut[1] ** +Zp, l[2 * c + d] = this._tmOut[2] ** +Zp;
|
|
16700
16692
|
} else l[d] = a[u] / 255, l[c + d] = a[u + 1] / 255, l[2 * c + d] = a[u + 2] / 255;
|
|
16701
16693
|
}
|
|
16702
16694
|
return l;
|
|
@@ -16754,10 +16746,10 @@ var mm = {
|
|
|
16754
16746
|
this._backupCanvas = document.createElement("canvas"), this._backupCanvas.width = e.width, this._backupCanvas.height = e.height;
|
|
16755
16747
|
let t = this._backupCanvas.getContext("2d");
|
|
16756
16748
|
if (e.isHDR) {
|
|
16757
|
-
let { data: n, width: r, height: i } = e, a = t.createImageData(r, i), o = a.data, s =
|
|
16749
|
+
let { data: n, width: r, height: i } = e, a = t.createImageData(r, i), o = a.data, s = Xp.get(this.getToneMapping()) || Xp.get(Ue), c = this.getExposure(), l = this.getSaturation(), u = new Float32Array(3);
|
|
16758
16750
|
for (let e = 0, t = r * i; e < t; e++) {
|
|
16759
16751
|
let t = e * 4, r = n[t] * c, i = n[t + 1] * c, a = n[t + 2] * c;
|
|
16760
|
-
l !== 1 && (u[0] = r, u[1] = i, u[2] = a,
|
|
16752
|
+
l !== 1 && (u[0] = r, u[1] = i, u[2] = a, nm(u, l), r = u[0], i = u[1], a = u[2]), s(r, i, a, 1, u), o[t] = u[0] ** +Zp * 255 + .5 | 0, o[t + 1] = u[1] ** +Zp * 255 + .5 | 0, o[t + 2] = u[2] ** +Zp * 255 + .5 | 0, o[t + 3] = 255;
|
|
16761
16753
|
}
|
|
16762
16754
|
t.putImageData(a, 0, 0);
|
|
16763
16755
|
} else t.putImageData(e, 0, 0);
|
|
@@ -16769,7 +16761,7 @@ var mm = {
|
|
|
16769
16761
|
this.hdr = !!e;
|
|
16770
16762
|
}
|
|
16771
16763
|
setQuality(e) {
|
|
16772
|
-
if (!
|
|
16764
|
+
if (!gm.QUALITY_PRESETS[e]) {
|
|
16773
16765
|
console.warn(`AIUpscaler: Invalid quality "${e}", must be fast/balanced/quality`);
|
|
16774
16766
|
return;
|
|
16775
16767
|
}
|
|
@@ -16792,7 +16784,7 @@ var mm = {
|
|
|
16792
16784
|
async dispose() {
|
|
16793
16785
|
this.abort(), this._cleanupPendingWorkerHandlers(), this._worker &&= (this._worker.postMessage({ type: "dispose" }), this._worker.terminate(), null), this._currentModelUrl = null, this._backupCanvas = null, this._upscaledAlpha = null, this.state.abortController = null, this._hdrStagingBuffer?.destroy(), this._hdrStagingBuffer = null, this._hdrStagingWidth = 0, this._hdrStagingHeight = 0, console.log("AIUpscaler disposed");
|
|
16794
16786
|
}
|
|
16795
|
-
},
|
|
16787
|
+
}, vm = class extends ut {
|
|
16796
16788
|
constructor({ renderer: e, mainCanvas: t, scene: n, camera: r, stages: i, pipeline: a, getExposure: o, getSaturation: s, getTransparentBg: c }) {
|
|
16797
16789
|
super(), this.renderer = e, this.mainCanvas = t, this.denoiserCanvas = this._createDenoiserCanvas(t), this.scene = n, this.camera = r, this.pipeline = a, this._stages = i, this._getExposure = o, this._getSaturation = s, this._getTransparentBg = c, this.denoiser = null, this.upscaler = null, this._lastRenderWidth = 0, this._lastRenderHeight = 0, this._pendingStartUpscaler = null, this._denoiserStartHandler = null, this._denoiserEndHandler = null, this._upscalerResChangedHandler = null, this._upscalerStartHandler = null, this._upscalerProgressHandler = null, this._upscalerEndHandler = null;
|
|
16798
16790
|
}
|
|
@@ -16813,7 +16805,7 @@ var mm = {
|
|
|
16813
16805
|
setupDenoiser() {
|
|
16814
16806
|
if (!this.denoiserCanvas) return;
|
|
16815
16807
|
let e = this._stages.pathTracer;
|
|
16816
|
-
this.denoiser = new
|
|
16808
|
+
this.denoiser = new um(this.denoiserCanvas, this.renderer, this.scene, this.camera, {
|
|
16817
16809
|
...J,
|
|
16818
16810
|
backendParams: () => ({
|
|
16819
16811
|
device: this.renderer.backend.device,
|
|
@@ -16838,7 +16830,7 @@ var mm = {
|
|
|
16838
16830
|
setupUpscaler() {
|
|
16839
16831
|
if (!this.denoiserCanvas) return;
|
|
16840
16832
|
let e = this._stages.pathTracer;
|
|
16841
|
-
this.upscaler = new
|
|
16833
|
+
this.upscaler = new _m(this.denoiserCanvas, this.renderer, {
|
|
16842
16834
|
scaleFactor: J.upscalerScale || 2,
|
|
16843
16835
|
quality: J.upscalerQuality || "fast",
|
|
16844
16836
|
getSourceCanvas: () => this.denoiser?.enabled ? null : this.renderer.domElement,
|
|
@@ -16859,6 +16851,9 @@ var mm = {
|
|
|
16859
16851
|
progress: e.progress
|
|
16860
16852
|
}), this._upscalerEndHandler = () => this.dispatchEvent({ type: dr.UPSCALING_END }), this.upscaler.addEventListener("resolution_changed", this._upscalerResChangedHandler), this.upscaler.addEventListener("start", this._upscalerStartHandler), this.upscaler.addEventListener("progress", this._upscalerProgressHandler), this.upscaler.addEventListener("end", this._upscalerEndHandler);
|
|
16861
16853
|
}
|
|
16854
|
+
get denoiserStrategy() {
|
|
16855
|
+
return this._stages.asvgf?.enabled ? "asvgf" : this._stages.edgeFilter?.enabled ? "edgeaware" : "none";
|
|
16856
|
+
}
|
|
16862
16857
|
setDenoiserStrategy(e, t) {
|
|
16863
16858
|
let n = this._stages;
|
|
16864
16859
|
switch (n.asvgf && (n.asvgf.enabled = !1), n.variance && (n.variance.enabled = !1), n.bilateralFilter && (n.bilateralFilter.enabled = !1), n.edgeFilter && n.edgeFilter.setFilteringEnabled(!1), this._clearDenoiserTextures(), e) {
|
|
@@ -16983,7 +16978,7 @@ var mm = {
|
|
|
16983
16978
|
let t = kr[e];
|
|
16984
16979
|
t && (this._stages.asvgf?.updateParameters(t), this._stages.bilateralFilter?.updateParameters(t), this._stages.variance && t.varianceBoost !== void 0 && (this._stages.variance.varianceBoost.value = t.varianceBoost));
|
|
16985
16980
|
}
|
|
16986
|
-
},
|
|
16981
|
+
}, ym = class {
|
|
16987
16982
|
constructor() {
|
|
16988
16983
|
this.layer = "hud", this.visible = !1, this._tileBounds = null, this._imageWidth = 1, this._imageHeight = 1, this.enabled = !0, this._borderColor = "rgba(255, 0, 0, 0.6)", this._borderWidthRatio = 1 / 540, this._borderWidthMin = 1.5, this._borderWidthMax = 4;
|
|
16989
16984
|
}
|
|
@@ -17007,7 +17002,7 @@ var mm = {
|
|
|
17007
17002
|
dispose() {
|
|
17008
17003
|
this.visible = !1;
|
|
17009
17004
|
}
|
|
17010
|
-
},
|
|
17005
|
+
}, bm = class {
|
|
17011
17006
|
constructor(n, r) {
|
|
17012
17007
|
this.layer = "scene", this._enabled = !0, this._outlineNode = xn(n, r, {
|
|
17013
17008
|
selectedObjects: [],
|
|
@@ -17038,11 +17033,11 @@ var mm = {
|
|
|
17038
17033
|
this._enabled = !1, this._outlineNode?.dispose(), this._material?.dispose(), this._quad = null;
|
|
17039
17034
|
}
|
|
17040
17035
|
};
|
|
17041
|
-
function
|
|
17036
|
+
function xm(e = !1) {
|
|
17042
17037
|
let t = document.createElement("canvas");
|
|
17043
17038
|
return t.style.cssText = "position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;" + (e ? "display:none;" : ""), t;
|
|
17044
17039
|
}
|
|
17045
|
-
function
|
|
17040
|
+
function Sm(e, t = Infinity) {
|
|
17046
17041
|
let n = e?.getBoundingClientRect();
|
|
17047
17042
|
if (!n || n.width === 0 || n.height === 0) return null;
|
|
17048
17043
|
let r = Math.min(window.devicePixelRatio || 1, 2), i = Math.round(n.width * r), a = Math.round(n.height * r), o = t / Math.max(i, a);
|
|
@@ -17053,9 +17048,9 @@ function bm(e, t = Infinity) {
|
|
|
17053
17048
|
}
|
|
17054
17049
|
//#endregion
|
|
17055
17050
|
//#region src/managers/helpers/ViewOverlayRenderer.js
|
|
17056
|
-
var
|
|
17051
|
+
var Cm = 4096, wm = class {
|
|
17057
17052
|
constructor() {
|
|
17058
|
-
this.canvas =
|
|
17053
|
+
this.canvas = xm(!0), this._visible = !1, this.renderer = null, this._sizeSource = null;
|
|
17059
17054
|
}
|
|
17060
17055
|
async init({ device: e, sizeSource: t }) {
|
|
17061
17056
|
this._sizeSource = t;
|
|
@@ -17072,7 +17067,7 @@ var xm = 4096, Sm = class {
|
|
|
17072
17067
|
}
|
|
17073
17068
|
syncSize() {
|
|
17074
17069
|
if (!this.renderer) return;
|
|
17075
|
-
let e =
|
|
17070
|
+
let e = Sm(this._sizeSource, Cm);
|
|
17076
17071
|
!e || e.width === this.canvas.width && e.height === this.canvas.height || this.renderer.setSize(e.width, e.height, !1);
|
|
17077
17072
|
}
|
|
17078
17073
|
begin() {
|
|
@@ -17084,18 +17079,18 @@ var xm = 4096, Sm = class {
|
|
|
17084
17079
|
dispose() {
|
|
17085
17080
|
xr(this.renderer), this.renderer = null, this.canvas.parentElement?.removeChild(this.canvas);
|
|
17086
17081
|
}
|
|
17087
|
-
},
|
|
17082
|
+
}, Tm = ai("overlay"), Em = (e, t) => e.visible && e.layer === t && e.render, Dm = class {
|
|
17088
17083
|
constructor(e) {
|
|
17089
|
-
this.camera = e, this._helpers = /* @__PURE__ */ new Map(), this._hudCanvas =
|
|
17084
|
+
this.camera = e, this._helpers = /* @__PURE__ */ new Map(), this._hudCanvas = xm(), this._hudCtx = this._hudCanvas.getContext("2d"), this._helperScene = null, this._viewOverlay = null;
|
|
17090
17085
|
}
|
|
17091
17086
|
async initViewRenderer({ device: e, sizeSource: t }) {
|
|
17092
17087
|
if (!(!e || !t)) try {
|
|
17093
|
-
this._viewOverlay = await new
|
|
17088
|
+
this._viewOverlay = await new wm().init({
|
|
17094
17089
|
device: e,
|
|
17095
17090
|
sizeSource: t
|
|
17096
17091
|
});
|
|
17097
17092
|
} catch (e) {
|
|
17098
|
-
|
|
17093
|
+
Tm.error("overlay surface unavailable — light gizmos, transform gizmo and outlines are disabled", e), this._viewOverlay = null;
|
|
17099
17094
|
}
|
|
17100
17095
|
}
|
|
17101
17096
|
setHelperScene(e) {
|
|
@@ -17111,11 +17106,11 @@ var xm = 4096, Sm = class {
|
|
|
17111
17106
|
}
|
|
17112
17107
|
setupDefaultHelpers({ helperScene: e, meshScene: t, pipeline: n, denoisingManager: r, app: i, renderWidth: a, renderHeight: o }) {
|
|
17113
17108
|
this.setHelperScene(e);
|
|
17114
|
-
let s = new
|
|
17109
|
+
let s = new ym();
|
|
17115
17110
|
this.register("tiles", s), s.setRenderSize(a || 1, o || 1), i.addEventListener("resolution_changed", (e) => {
|
|
17116
17111
|
s.setRenderSize(e.width, e.height);
|
|
17117
17112
|
}), n.eventBus.on("pipeline:reset", () => s.hide()), this._wireDenoiserTileEvents(s, r);
|
|
17118
|
-
let c = new
|
|
17113
|
+
let c = new bm(t, this.camera);
|
|
17119
17114
|
this.register("outline", c);
|
|
17120
17115
|
}
|
|
17121
17116
|
_wireDenoiserTileEvents(e, t) {
|
|
@@ -17127,7 +17122,7 @@ var xm = 4096, Sm = class {
|
|
|
17127
17122
|
}));
|
|
17128
17123
|
}
|
|
17129
17124
|
register(e, t) {
|
|
17130
|
-
this._helpers.has(e) && (
|
|
17125
|
+
this._helpers.has(e) && (Tm.warn(`helper "${e}" already registered — replacing.`), this._helpers.get(e).dispose?.()), this._helpers.set(e, t);
|
|
17131
17126
|
}
|
|
17132
17127
|
unregister(e) {
|
|
17133
17128
|
let t = this._helpers.get(e);
|
|
@@ -17165,16 +17160,16 @@ var xm = 4096, Sm = class {
|
|
|
17165
17160
|
}
|
|
17166
17161
|
_renderSceneLayer(e) {
|
|
17167
17162
|
this._helperScene?.render(e, this.camera);
|
|
17168
|
-
for (let t of this._helpers.values())
|
|
17163
|
+
for (let t of this._helpers.values()) Em(t, "scene") && t.render(e, this.camera);
|
|
17169
17164
|
}
|
|
17170
17165
|
_hasVisibleSceneOverlay() {
|
|
17171
17166
|
if (this._helperScene?.isDrawing) return !0;
|
|
17172
|
-
for (let e of this._helpers.values()) if (
|
|
17167
|
+
for (let e of this._helpers.values()) if (Em(e, "scene")) return !0;
|
|
17173
17168
|
return !1;
|
|
17174
17169
|
}
|
|
17175
17170
|
refreshHUD() {
|
|
17176
17171
|
let e = this._hudCanvas, t = this._hudCtx, n = !1;
|
|
17177
|
-
for (let e of this._helpers.values()) if (
|
|
17172
|
+
for (let e of this._helpers.values()) if (Em(e, "hud")) {
|
|
17178
17173
|
n = !0;
|
|
17179
17174
|
break;
|
|
17180
17175
|
}
|
|
@@ -17183,10 +17178,10 @@ var xm = 4096, Sm = class {
|
|
|
17183
17178
|
return;
|
|
17184
17179
|
}
|
|
17185
17180
|
e.style.display !== "" && (e.style.display = "");
|
|
17186
|
-
let r = e.clientWidth, i = e.clientHeight, a = r > 0 && i > 0 ?
|
|
17181
|
+
let r = e.clientWidth, i = e.clientHeight, a = r > 0 && i > 0 ? Sm(e) : null;
|
|
17187
17182
|
if (a) {
|
|
17188
17183
|
(e.width !== a.width || e.height !== a.height) && (e.width = a.width, e.height = a.height), t.clearRect(0, 0, a.width, a.height), t.save(), t.scale(a.width / r, a.height / i);
|
|
17189
|
-
for (let e of this._helpers.values())
|
|
17184
|
+
for (let e of this._helpers.values()) Em(e, "hud") && e.render(t, r, i);
|
|
17190
17185
|
t.restore(), e.style.display !== "" && (e.style.display = "");
|
|
17191
17186
|
}
|
|
17192
17187
|
}
|
|
@@ -17194,7 +17189,7 @@ var xm = 4096, Sm = class {
|
|
|
17194
17189
|
for (let e of this._helpers.values()) e.dispose?.();
|
|
17195
17190
|
this._helpers.clear(), this._viewOverlay?.dispose(), this._viewOverlay = null, this._hudCanvas.parentElement && this._hudCanvas.parentElement.removeChild(this._hudCanvas);
|
|
17196
17191
|
}
|
|
17197
|
-
},
|
|
17192
|
+
}, Om = class extends ut {
|
|
17198
17193
|
constructor() {
|
|
17199
17194
|
super(), this.mixer = null, this.timer = new nn(), this.actions = [], this.isPlaying = !1, this._scene = null, this._mixerRoot = null, this._meshes = null, this._meshTriRanges = null, this._posBuffer = null, this._tempVec = new cn(), this._skinnedCache = null, this._clipsCache = null, this._savedTimeScale = 1, this.onFinished = null, this.wakeCallback = null;
|
|
17200
17195
|
}
|
|
@@ -17294,7 +17289,7 @@ var xm = 4096, Sm = class {
|
|
|
17294
17289
|
dispose() {
|
|
17295
17290
|
this.mixer &&= (this.mixer.stopAllAction(), this.mixer.uncacheRoot(this._mixerRoot), null), this.actions = [], this.isPlaying = !1, this.timer.reset(), this._scene = null, this._mixerRoot = null, this._meshes = null, this._meshTriRanges = null, this._posBuffer = null, this._skinnedCache = null, this._clipsCache = null;
|
|
17296
17291
|
}
|
|
17297
|
-
},
|
|
17292
|
+
}, km = new cn(0, 0, -1), Am = class {
|
|
17298
17293
|
constructor({ camera: e, canvas: t, orbitControls: n, app: r }) {
|
|
17299
17294
|
this._app = r, this._orbitControls = n, this._camera = e, this._controls = new Sn(e, t), this._gizmoScene = new Yt(), this._gizmoScene.add(this._controls.getHelper()), this._attached = null, this._isDragging = !1, this._meshes = null, this._meshTriRanges = null, this._posBuffer = null, this._normalBuffer = null, this._skinnedCache = null, this._normalCache = null, this._tempVec = new cn(), this._normalMatrix = new St(), this._refitInFlight = !1, this._baselineComputed = !1, this._tempForward = new cn(), this._lightTargetDistance = null, this._lastLightPosition = null, this._onDraggingChanged = this._onDraggingChanged.bind(this), this._onObjectChange = this._onObjectChange.bind(this), this._controls.addEventListener("dragging-changed", this._onDraggingChanged), this._controls.addEventListener("objectChange", this._onObjectChange);
|
|
17300
17295
|
}
|
|
@@ -17315,7 +17310,7 @@ var xm = 4096, Sm = class {
|
|
|
17315
17310
|
attach(e) {
|
|
17316
17311
|
if (this._attached !== e && (this._controls.attach(e), this._attached = e, this._lightTargetDistance = null, this._lastLightPosition = null, e.isLight && e.target)) {
|
|
17317
17312
|
let t = e.target.position.clone().sub(e.position), n = t.length();
|
|
17318
|
-
n > 1e-4 ? (e.quaternion.setFromUnitVectors(
|
|
17313
|
+
n > 1e-4 ? (e.quaternion.setFromUnitVectors(km, t.normalize()), this._lightTargetDistance = n) : this._lightTargetDistance = 1, this._lastLightPosition = e.position.clone();
|
|
17319
17314
|
}
|
|
17320
17315
|
}
|
|
17321
17316
|
detach() {
|
|
@@ -17427,7 +17422,7 @@ var xm = 4096, Sm = class {
|
|
|
17427
17422
|
dispose() {
|
|
17428
17423
|
this._controls.removeEventListener("dragging-changed", this._onDraggingChanged), this._controls.removeEventListener("objectChange", this._onObjectChange), this.detach(), this._gizmoScene.remove(this._controls.getHelper()), this._controls.dispose(), this._meshes = null, this._meshTriRanges = null, this._posBuffer = null, this._normalBuffer = null, this._skinnedCache = null, this._normalCache = null, this._baselineComputed = !1, this._tempForward = null, this._lightTargetDistance = null, this._lastLightPosition = null, this._app = null, this._orbitControls = null, this._camera = null, this._controls = null, this._gizmoScene = null;
|
|
17429
17424
|
}
|
|
17430
|
-
},
|
|
17425
|
+
}, jm = class {
|
|
17431
17426
|
constructor(e) {
|
|
17432
17427
|
this.layer = "scene", this._transformManager = e, this._enabled = !0;
|
|
17433
17428
|
}
|
|
@@ -17446,15 +17441,15 @@ var xm = 4096, Sm = class {
|
|
|
17446
17441
|
dispose() {
|
|
17447
17442
|
this._enabled = !1;
|
|
17448
17443
|
}
|
|
17449
|
-
},
|
|
17444
|
+
}, Mm = /* @__PURE__ */ new WeakMap(), Nm = ai("engine"), Pm = class extends ut {
|
|
17450
17445
|
constructor(e, t = {}) {
|
|
17451
17446
|
super();
|
|
17452
17447
|
try {
|
|
17453
|
-
|
|
17448
|
+
Mm.get(e)?.dispose();
|
|
17454
17449
|
} catch (e) {
|
|
17455
|
-
|
|
17450
|
+
Nm.warn("prior canvas owner dispose failed", e);
|
|
17456
17451
|
}
|
|
17457
|
-
|
|
17452
|
+
Mm.set(e, this), this.canvas = e, this._autoResize = t.autoResize !== !1, this._container = t.container || null, this.settings = new Ep(J), this.renderer = null, this.scene = null, this.meshScene = null, this._sceneHelpers = null, this.assetLoader = null, this._sdf = null, this._animRefitInFlight = !1, this._maxTextureSize = J.maxTextureSize, this.pipeline = null, this.stages = {}, this.cameraManager = null, this.lightManager = null, this.goboManager = null, this.iesManager = null, this.denoisingManager = null, this.overlayManager = null, this.interactionManager = null, this.transformManager = null, this.animationManager = new Om(), this.environmentManager = null, this.isInitialized = !1, this.pauseRendering = !1, this.pathTracerEnabled = !0, this.animationManagerId = null, this.needsReset = !1, this._loadingInProgress = !1, this._needsDisplayRefresh = !1, this._paused = !1, this._emissiveSamplingUserSet = !1, this.completion = new Vf(), this._resizeDebounceTimer = null, this._trackedListeners = [], this._disposed = !1, this._deviceLost = !1, this._deterministic = !1, this._dispatchPinned = !1, this._deterministicRestore = null;
|
|
17458
17453
|
}
|
|
17459
17454
|
_addTrackedListener(e, t, n) {
|
|
17460
17455
|
e && (e.addEventListener(t, n), this._trackedListeners.push({
|
|
@@ -17467,12 +17462,12 @@ var xm = 4096, Sm = class {
|
|
|
17467
17462
|
for (let { target: e, type: t, handler: n } of this._trackedListeners) try {
|
|
17468
17463
|
e.removeEventListener(t, n);
|
|
17469
17464
|
} catch (e) {
|
|
17470
|
-
|
|
17465
|
+
Nm.warn("failed to remove listener", t, e);
|
|
17471
17466
|
}
|
|
17472
17467
|
this._trackedListeners.length = 0;
|
|
17473
17468
|
}
|
|
17474
17469
|
async init() {
|
|
17475
|
-
return await this._initRenderer(), this._initCameraManager(), this._initScenes(), this._initAssetPipeline(), this._initPipeline(), await this._initManagers(), this._wireEvents(), this.stages.pathTracer.setTriangleData(new Float32Array(32), 0), this.stages.pathTracer.setBVHData(new Float32Array(16)), this.stages.pathTracer.materialData.setMaterialData(new Float32Array(16)), this.stages.pathTracer.setupMaterial(), this.isInitialized = !0,
|
|
17470
|
+
return await this._initRenderer(), this._initCameraManager(), this._initScenes(), this._initAssetPipeline(), this._initPipeline(), await this._initManagers(), this._wireEvents(), this.stages.pathTracer.setTriangleData(new Float32Array(32), 0), this.stages.pathTracer.setBVHData(new Float32Array(16)), this.stages.pathTracer.materialData.setMaterialData(new Float32Array(16)), this.stages.pathTracer.setupMaterial(), this.isInitialized = !0, Nm.debug("WebGPU path tracer app initialized"), this;
|
|
17476
17471
|
}
|
|
17477
17472
|
animate() {
|
|
17478
17473
|
if (!this._deviceLost) {
|
|
@@ -17482,7 +17477,7 @@ var xm = 4096, Sm = class {
|
|
|
17482
17477
|
}
|
|
17483
17478
|
if (this.cameraManager.controls && this.cameraManager.controls.update(), this.animationManager?.isPlaying && !this._animRefitInFlight) {
|
|
17484
17479
|
let e = this.animationManager.update();
|
|
17485
|
-
e && (this._animRefitInFlight = !0, this.refitBVH(e).catch((e) =>
|
|
17480
|
+
e && (this._animRefitInFlight = !0, this.refitBVH(e).catch((e) => Nm.error("animation refit error:", e)).finally(() => {
|
|
17486
17481
|
this._animRefitInFlight = !1;
|
|
17487
17482
|
}));
|
|
17488
17483
|
}
|
|
@@ -17516,7 +17511,7 @@ var xm = 4096, Sm = class {
|
|
|
17516
17511
|
this.animationManagerId &&= (cancelAnimationFrame(this.animationManagerId), null);
|
|
17517
17512
|
}
|
|
17518
17513
|
_handleDeviceLost(e) {
|
|
17519
|
-
this._deviceLost || (this._deviceLost = !0,
|
|
17514
|
+
this._deviceLost || (this._deviceLost = !0, Nm.error(`WebGPU device lost (${e?.reason || "unknown"}): ${e?.message || ""}`), this.stopAnimation(), this.dispatchEvent({
|
|
17520
17515
|
type: dr.DEVICE_LOST,
|
|
17521
17516
|
reason: e?.reason,
|
|
17522
17517
|
message: e?.message
|
|
@@ -17554,7 +17549,7 @@ var xm = 4096, Sm = class {
|
|
|
17554
17549
|
let e = je().value, t = k().value;
|
|
17555
17550
|
e?._listeners?.dispose && (e._listeners.dispose.length = 0), t?._listeners?.dispose && (t._listeners.dispose.length = 0);
|
|
17556
17551
|
} catch (e) {
|
|
17557
|
-
|
|
17552
|
+
Nm.warn("failed to clear TSL texture singleton listeners", e);
|
|
17558
17553
|
}
|
|
17559
17554
|
xr(this.renderer), this.renderer = null, this.stages = {}, this.isInitialized = !1;
|
|
17560
17555
|
}
|
|
@@ -17640,7 +17635,7 @@ var xm = 4096, Sm = class {
|
|
|
17640
17635
|
try {
|
|
17641
17636
|
await this.renderer.compileAsync(this.meshScene, this.cameraManager.camera);
|
|
17642
17637
|
} catch (e) {
|
|
17643
|
-
|
|
17638
|
+
Nm.warn("raster fallback precompile failed", e);
|
|
17644
17639
|
}
|
|
17645
17640
|
e.end("Pipeline precompile"), n && (hr({
|
|
17646
17641
|
status: "Finalizing environment map...",
|
|
@@ -17778,7 +17773,7 @@ var xm = 4096, Sm = class {
|
|
|
17778
17773
|
return Y;
|
|
17779
17774
|
}
|
|
17780
17775
|
_isRenderSizeSupported(e, t) {
|
|
17781
|
-
return e > Y || t > Y ? (
|
|
17776
|
+
return e > Y || t > Y ? (Nm.warn(`render resolution ${e}×${t} exceeds the ${Y}px limit (compute storage textures are pre-allocated at ${Y}px). Ignoring resize — use a resolution ≤ ${Y}.`), !1) : !0;
|
|
17782
17777
|
}
|
|
17783
17778
|
onResize() {
|
|
17784
17779
|
let e = this.canvas.clientWidth, t = this.canvas.clientHeight;
|
|
@@ -17890,6 +17885,39 @@ var xm = 4096, Sm = class {
|
|
|
17890
17885
|
total: t + n
|
|
17891
17886
|
};
|
|
17892
17887
|
}
|
|
17888
|
+
async getKernelGPUTimings() {
|
|
17889
|
+
let e = this.renderer;
|
|
17890
|
+
if (!e?.backend?.trackTimestamp) return null;
|
|
17891
|
+
await e.resolveTimestampsAsync("compute");
|
|
17892
|
+
let t = e.backend.timestampQueryPool?.compute?.timestamps;
|
|
17893
|
+
if (!t || t.size === 0) return null;
|
|
17894
|
+
let n = /* @__PURE__ */ new Map(), r = this.stages?.pathTracer?._kernelManager?.kernels;
|
|
17895
|
+
if (r) for (let [e, t] of r) n.set(t.id, e);
|
|
17896
|
+
let i = [], a = -1;
|
|
17897
|
+
for (let [e, n] of t) {
|
|
17898
|
+
let t = e.split(":");
|
|
17899
|
+
if (t.length !== 4) continue;
|
|
17900
|
+
let r = Number(t[3].slice(1));
|
|
17901
|
+
Number.isFinite(r) && (i.push({
|
|
17902
|
+
nodeId: Number(t[2]),
|
|
17903
|
+
f: r,
|
|
17904
|
+
ms: n
|
|
17905
|
+
}), r > a && (a = r));
|
|
17906
|
+
}
|
|
17907
|
+
let o = {}, s = 0, c = 0;
|
|
17908
|
+
for (let e of i) {
|
|
17909
|
+
if (e.f !== a) continue;
|
|
17910
|
+
s += e.ms;
|
|
17911
|
+
let t = n.get(e.nodeId);
|
|
17912
|
+
t === void 0 ? c += e.ms : o[t] = (o[t] ?? 0) + e.ms;
|
|
17913
|
+
}
|
|
17914
|
+
return {
|
|
17915
|
+
kernels: o,
|
|
17916
|
+
total: s,
|
|
17917
|
+
unattributed: c,
|
|
17918
|
+
frame: a
|
|
17919
|
+
};
|
|
17920
|
+
}
|
|
17893
17921
|
getCanvas() {
|
|
17894
17922
|
if (!this.renderer?.domElement) return null;
|
|
17895
17923
|
let e = this.denoisingManager;
|
|
@@ -18008,40 +18036,40 @@ var xm = 4096, Sm = class {
|
|
|
18008
18036
|
let n = this.renderer.backend?.device;
|
|
18009
18037
|
n?.lost && (n.lost.then((e) => {
|
|
18010
18038
|
this._disposed || this._handleDeviceLost(e);
|
|
18011
|
-
}), n.onuncapturederror = (e) =>
|
|
18039
|
+
}), n.onuncapturederror = (e) => Nm.error("WebGPU uncaptured error:", e.error)), r.setLTC(ln.init()), this.renderer.outputColorSpace = a, this.renderer.toneMapping = Ue, this.renderer.toneMappingExposure = 1, this.renderer.setPixelRatio(1);
|
|
18012
18040
|
}
|
|
18013
18041
|
_initCameraManager() {
|
|
18014
|
-
this.cameraManager = new
|
|
18042
|
+
this.cameraManager = new Dp(this.canvas);
|
|
18015
18043
|
}
|
|
18016
18044
|
_initScenes() {
|
|
18017
18045
|
this.scene = new Yt(), this.meshScene = new Yt(), this._sceneHelpers = new Pn();
|
|
18018
18046
|
}
|
|
18019
18047
|
_initAssetPipeline() {
|
|
18020
|
-
this._sdf = new Qc(), this.assetLoader = new
|
|
18048
|
+
this._sdf = new Qc(), this.assetLoader = new Cp(this.meshScene, this.cameraManager.camera, this.cameraManager.controls), this.assetLoader.setRenderer(this.renderer), this.assetLoader.createFloorPlane(), this._addTrackedListener(this.cameraManager.controls, "change", () => {
|
|
18021
18049
|
this.needsReset = !0, this.wake();
|
|
18022
18050
|
});
|
|
18023
18051
|
}
|
|
18024
18052
|
_initPipeline() {
|
|
18025
18053
|
this._createStages();
|
|
18026
18054
|
let { clientWidth: e, clientHeight: t } = this.canvas;
|
|
18027
|
-
this.pipeline = new
|
|
18055
|
+
this.pipeline = new Bf(this.renderer, e || 1, t || 1), this.pipeline.addStage(this.stages.pathTracer), this.pipeline.addStage(this.stages.normalDepth), this.pipeline.addStage(this.stages.motionVector), this.pipeline.addStage(this.stages.asvgf), this.pipeline.addStage(this.stages.variance), this.pipeline.addStage(this.stages.bilateralFilter), this.pipeline.addStage(this.stages.edgeFilter), this.pipeline.addStage(this.stages.autoExposure), this.pipeline.addStage(this.stages.compositor);
|
|
18028
18056
|
let n = this.canvas.clientWidth || 1, r = this.canvas.clientHeight || 1;
|
|
18029
18057
|
this.pipeline.setSize(n, r);
|
|
18030
18058
|
}
|
|
18031
18059
|
async _initManagers() {
|
|
18032
|
-
this.interactionManager = new
|
|
18060
|
+
this.interactionManager = new Hf({
|
|
18033
18061
|
scene: this.meshScene,
|
|
18034
18062
|
camera: this.cameraManager.camera,
|
|
18035
18063
|
canvas: this.canvas,
|
|
18036
18064
|
assetLoader: this.assetLoader,
|
|
18037
18065
|
pathTracer: null,
|
|
18038
18066
|
floorPlane: this.assetLoader.floorPlane
|
|
18039
|
-
}), this.interactionManager.wireAppEvents(this), this.cameraManager.setInteractionManager(this.interactionManager), this.lightManager = new
|
|
18067
|
+
}), this.interactionManager.wireAppEvents(this), this.cameraManager.setInteractionManager(this.interactionManager), this.lightManager = new Op(this.scene, this._sceneHelpers, this.stages.pathTracer, { onReset: () => this.reset() }), this.goboManager = new kp(this.stages.pathTracer, { onReset: () => this.reset() }), this.iesManager = new Bp(this.stages.pathTracer, { onReset: () => this.reset() }), this._setupDenoisingManager(), await this._setupOverlayManager(), this.transformManager = new Am({
|
|
18040
18068
|
camera: this.cameraManager.camera,
|
|
18041
18069
|
canvas: this.canvas,
|
|
18042
18070
|
orbitControls: this.cameraManager.controls,
|
|
18043
18071
|
app: this
|
|
18044
|
-
}), this.overlayManager.register("transform", new
|
|
18072
|
+
}), this.overlayManager.register("transform", new jm(this.transformManager)), this.interactionManager.setDependencies({
|
|
18045
18073
|
overlayManager: this.overlayManager,
|
|
18046
18074
|
transformManager: this.transformManager,
|
|
18047
18075
|
appDispatch: (e) => this.dispatchEvent(e),
|
|
@@ -18085,7 +18113,9 @@ var xm = 4096, Sm = class {
|
|
|
18085
18113
|
stages: this.stages,
|
|
18086
18114
|
renderer: this.renderer,
|
|
18087
18115
|
resetCallback: () => this.reset(),
|
|
18088
|
-
reconcileCompletion: () => this._reconcileCompletion()
|
|
18116
|
+
reconcileCompletion: () => this._reconcileCompletion(),
|
|
18117
|
+
denoisingManager: this.denoisingManager,
|
|
18118
|
+
cameraManager: this.cameraManager
|
|
18089
18119
|
}), this.renderer.toneMappingExposure = this.settings.get("exposure") ?? 1, this.onResize(), this.resizeHandler = () => this.onResize(), this._autoResize && this._addTrackedListener(window, "resize", this.resizeHandler), this._onAssetLoaded = async (e) => {
|
|
18090
18120
|
if (!this._loadingInProgress) {
|
|
18091
18121
|
if (e.model) this._clearAppendedModels(), await this.loadSceneData();
|
|
@@ -18111,10 +18141,10 @@ var xm = 4096, Sm = class {
|
|
|
18111
18141
|
this.transformManager?.setMeshData(this._sdf.meshes);
|
|
18112
18142
|
}
|
|
18113
18143
|
_createStages() {
|
|
18114
|
-
this.stages.pathTracer = new
|
|
18144
|
+
this.stages.pathTracer = new rf(this.renderer, this.scene, this.cameraManager.camera), this.stages.normalDepth = new af(this.renderer, { pathTracer: this.stages.pathTracer }), this.stages.motionVector = new of(this.renderer, this.cameraManager.camera, { pathTracer: this.stages.pathTracer }), this.stages.asvgf = new lf(this.renderer, { enabled: !1 }), this.stages.variance = new ff(this.renderer, { enabled: !1 }), this.stages.bilateralFilter = new mf(this.renderer, { enabled: !1 }), this.stages.edgeFilter = new yf(this.renderer, { enabled: !1 }), this.stages.autoExposure = new Ef(this.renderer, { enabled: J.autoExposure ?? !1 }), this.stages.compositor = new Df(this.renderer, { saturation: this.settings.get("saturation") ?? J.saturation });
|
|
18115
18145
|
}
|
|
18116
18146
|
_setupDenoisingManager() {
|
|
18117
|
-
this.denoisingManager = new
|
|
18147
|
+
this.denoisingManager = new vm({
|
|
18118
18148
|
renderer: this.renderer,
|
|
18119
18149
|
mainCanvas: this.canvas,
|
|
18120
18150
|
scene: this.scene,
|
|
@@ -18157,7 +18187,7 @@ var xm = 4096, Sm = class {
|
|
|
18157
18187
|
this.scene.updateMatrixWorld(), this.overlayManager?.render();
|
|
18158
18188
|
}
|
|
18159
18189
|
async _setupOverlayManager() {
|
|
18160
|
-
this.overlayManager = new
|
|
18190
|
+
this.overlayManager = new Dm(this.cameraManager.camera), this.overlayManager.setupDefaultHelpers({
|
|
18161
18191
|
helperScene: this._sceneHelpers,
|
|
18162
18192
|
meshScene: this.meshScene,
|
|
18163
18193
|
pipeline: this.pipeline,
|
|
@@ -18188,7 +18218,7 @@ var xm = 4096, Sm = class {
|
|
|
18188
18218
|
_forwardEvents(e, t) {
|
|
18189
18219
|
if (e) for (let n of t) this._addTrackedListener(e, n, (e) => this.dispatchEvent(e));
|
|
18190
18220
|
}
|
|
18191
|
-
},
|
|
18221
|
+
}, Fm = class {
|
|
18192
18222
|
constructor(e) {
|
|
18193
18223
|
this._app = e, this._cancelled = !1, this._rendering = !1;
|
|
18194
18224
|
}
|
|
@@ -18286,4 +18316,4 @@ var xm = 4096, Sm = class {
|
|
|
18286
18316
|
}
|
|
18287
18317
|
};
|
|
18288
18318
|
//#endregion
|
|
18289
|
-
export { Pr as AF_DEFAULTS, kr as ASVGF_QUALITY_PRESETS, Nr as AUTO_FOCUS_MODES,
|
|
18319
|
+
export { Pr as AF_DEFAULTS, kr as ASVGF_QUALITY_PRESETS, Nr as AUTO_FOCUS_MODES, Om as AnimationManager, Fr as BVH_LEAF_MARKERS, Mr as CAMERA_PRESETS, Ar as CAMERA_RANGES, Dp as CameraManager, Br as DEFAULT_TEXTURE_MATRIX, vm as DenoisingManager, J as ENGINE_DEFAULTS, dr as EngineEvents, kp as GoboManager, Bp as IESManager, Hr as INTERACTIVE_RENDER_CONFIG, Hf as InteractionManager, Wr as LOG_LEVELS, Op as LightManager, ii as Logger, Ur as MEMORY_CONSTANTS, Dm as OverlayManager, Vr as PRODUCTION_RENDER_CONFIG, Pm as PathTracerApp, Of as PipelineContext, Bf as RenderPipeline, Ep as RenderSettings, lr as RenderStage, jr as SKY_PRESETS, cr as StageExecutionMode, Ir as TEXTURE_CONSTANTS, X as TRIANGLE_DATA_LAYOUT, Am as TransformManager, uu as VRAMTracker, Fm as VideoRenderManager, cu as bufferBytes, Ff as clearBindingAuditFindings, sl as configureAssets, ai as createLogger, Q as fmt, cl as getAssetConfig, Pf as getBindingAuditFindings, Nf as setBindingAudit, lu as textureBytes };
|