diff --git a/.gitignore b/.gitignore index 30bc162..1c763d2 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,13 @@ -/node_modules \ No newline at end of file +/node_modules +/.worktrees/ +/deploy/arrival.local.env +*.tsbuildinfo +/.validation/ + +# Private analytics database files must never enter source/build artifacts. +*.sqlite +*.sqlite3 +*.db +*-wal +*-shm +*-journal diff --git a/.node-version b/.node-version new file mode 100644 index 0000000..60ade1a --- /dev/null +++ b/.node-version @@ -0,0 +1 @@ +24.19.0 diff --git a/.superpowers/sdd/surface-reflection/final-review-package.md b/.superpowers/sdd/surface-reflection/final-review-package.md deleted file mode 100644 index ca0b8dc..0000000 --- a/.superpowers/sdd/surface-reflection/final-review-package.md +++ /dev/null @@ -1,38 +0,0 @@ -# Final review package: Ref1 surface reflection - -The workspace is not a Git repository. Use the preserved shader baseline and the exact file list below as the complete change set. - -## Requirements - -Read: `D:/project/behind_glass/.superpowers/sdd/surface-reflection/task-1-brief.md`. - -## Changed product and regression files - -- Pre-edit shader: `D:/project/behind_glass/docs/qa-surface-reflection/baseline-mosaic.frag` -- Final shader: `D:/project/behind_glass/src/shaders/mosaic.frag` -- New regression: `D:/project/behind_glass/scripts/test-surface-reflection.mjs` - -The production shader differs from the baseline only in the final non-atlas reflection statement. Its SHA-256 is `5FB0AE93482AF46833B076EABFB0018E8BFEBA0A83BFD244DCD210371E450180`. - -## Reports and review history - -- Implementer/TDD report: `D:/project/behind_glass/docs/qa-surface-reflection/implementation-report.md` -- Controller browser QA: `D:/project/behind_glass/docs/qa-surface-reflection/visual-verification.md` -- Task review packages/results are summarized in `D:/project/behind_glass/.superpowers/sdd/surface-reflection/progress.md`. - -Task review required two test-only fix rounds. The final scoped review approved complete amplitude/output binding, constant-white mutation rejection, unchanged refraction expressions, complete effective atlas-source comparison, and earlier atlas-reflection mutation rejection. Production shader did not change during either fix. - -## Verification evidence - -- Focused command: `node scripts/test-surface-reflection.mjs` -- Focused output: `surface reflection source/math regression passed; constant-output and atlas-reflection mutations rejected` -- The implementation report records six existing scripts passing and `npm.cmd run build` exit 0 immediately after the production shader change. -- Controller browser QA observed no new runtime errors; only the pre-existing `X3595` warning remained. -- Gloss 0 pane crop was pixel-identical before/after. Default final reflection widened the changed crop coverage from 12.80% to 15.81% relative to gloss 0; the final-vs-baseline mean absolute change was 0.3106/255 and concentrated around the shared top-right light. - -## Known limits - -- No GPU screenshot of the intermediate broad-reflection-only stage was captured. -- Default-strength visual change is subtle; `after-glass-only.png` isolates it, while `before-default.png` and `after-default.png` are the primary same-condition result. -- Real-device mobile performance, continuous-video flicker, touch, and gyro were not measured. -- Existing Vite large-chunk advisory and shader `X3595` warning remain. diff --git a/.superpowers/sdd/surface-reflection/progress.md b/.superpowers/sdd/surface-reflection/progress.md deleted file mode 100644 index 2a9eae1..0000000 --- a/.superpowers/sdd/surface-reflection/progress.md +++ /dev/null @@ -1,22 +0,0 @@ -# SDD ledger — plan: .superpowers/sdd/surface-reflection/task-1-brief.md - -| Check | Produces / consumes | Result | -| --- | --- | --- | -| Task 1 internal consistency | Test invariants drive the requested shader-only behavior | Clean: the requested broad reflection and separated reflection edge weight are independently testable. | -| Task 1 file interfaces | `mosaic.frag` consumes existing camera, light, gloss, pane and normal uniforms; no new pass is required | Clean: current plan requires no interface change outside the shader. | -| Task 1 preservation constraints | New final-pass reflection must not enter atlas/palette/history or change refraction sampling | Clean: explicit write scope and invariants cover the boundary. | - -Environment: `D:\project\behind_glass` is not a Git repository, so native/manual worktree setup and SHA-based review packages are unavailable. Work proceeds in place with an exact pre-edit shader snapshot and file-based review package. - -Task 1 implementer: `01a0c9b1-382a-79e1-9f89-93e834836c4a` (Luna). Status: DONE_WITH_CONCERNS; automated verification reported green, GPU/browser visual comparison delegated to controller. - -Task 1: fix round 1/5 dispatched for two Important regression-test findings; production shader unchanged. - -Task 1: fix round 1/5 result (1 addressed, 1 open — complete atlas-path exclusion not covered; production shader unchanged). -Task 1: fix round 2/5 dispatched for the remaining complete atlas-path exclusion finding; production shader unchanged. - -Task 1: fix round 2/5 result (1 addressed, 0 open — complete effective atlas path compared with baseline; production shader unchanged). -Task 1: complete (file-based review clean; no Git commits because this workspace is not a repository). - -Final whole-change Astra review: clean; no Critical, Important, or Minor findings. Ready to retain in the non-Git workspace. -Ruling: retain this plan's `.superpowers/sdd/surface-reflection` workspace — no Git history exists to preserve the task brief, fix-round record, or review packages elsewhere — cost if wrong: hidden workspace clutter remains in the project. diff --git a/.superpowers/sdd/surface-reflection/task-1-brief.md b/.superpowers/sdd/surface-reflection/task-1-brief.md deleted file mode 100644 index 33e98df..0000000 --- a/.superpowers/sdd/surface-reflection/task-1-brief.md +++ /dev/null @@ -1,52 +0,0 @@ -# Task 1: Ref1 surface reflection - -Source plan: final work instruction in Codex task `01a0c768-534f-7660-9d86-c5ae50f71b1f`. - -## Goal - -Keep Ref1 option 2's large rectangular color planes and dark eye/nose readability while making the whole glass pane, including grass, read as glass. - -## Required implementation - -- Preserve the existing rectangular light reflection in `src/shaders/mosaic.frag`. -- Add a broad, soft, low-strength reflection component derived from the existing curved normal and current view direction. Reuse the current light/intersection model where possible; do not add an environment texture, render pass, render target, UI, or dependency. -- Composite both reflections after color-plane simplification and before output color-space conversion. Do not put reflection into `REGION_ATLAS`, palette selection, or history. -- Control both reflections with the existing `uGlossStrength`. At gloss 0 the new reflection contribution must be exactly zero. -- Keep the same signed curved normal for refraction and reflection. Reflection must respond to view direction, be stable when still, and vary spatially rather than applying a uniform white mix. -- Keep the refraction `edgeWeight` and all existing world-delta/sample-boundary behavior unchanged. Add a separate surface-reflection edge weight, starting from `mix(0.35, 1.0, edgeWeight)`, and tune only if visual comparison shows a bright rim. Both existing and new reflection use the surface-reflection weight. -- Keep the pane bounds so reflection does not spill onto the wooden reveal/frame or outside the glass. - -## Must remain unchanged - -- Grid 13, curvature +1, gloss 0.30, region/distortion 1, camera 0.50 defaults and option ranges. -- Ref1 option 2 palette fitting, dark rectangular color-plane preservation, 70 ms history, view-dependent refraction, photo/depth placement, manual framing, and inner window reveal. -- No original eye/nose pixel restoration, global blur, stronger black grid, per-cell random brightness, time animation, grass/pet masks, automatic framing, or changes to Reeded/Frosted. - -## TDD and automated verification - -Before production shader edits, add one minimal source/math regression script that fails for the missing behavior and then passes. It must check only this change's invariants: - -- gloss 0 removes both existing and broad reflection; -- surface reflection weight stays in range and does not replace the refraction edge weight; -- broad reflection is spatial/view dependent rather than a constant white mix; -- reflection composition remains outside `REGION_ATLAS` and before color-space conversion. - -Record the exact RED and GREEN commands/output. Label source/math assertions honestly; they are not GPU visual verification. Run the existing six scripts and `npm.cmd run build` after implementation. - -## Baseline and visual QA - -- Preserve the exact pre-edit `src/shaders/mosaic.frag` under `docs/qa-surface-reflection/baseline-mosaic.frag` before editing. -- Use dog1 with completed AI depth and fixed values: Final/Mosaic, Grid 13, curvature +1, gloss 0.30, region/distortion 1, light X/Y 0.60/0.80, depth scale 0.25, camera offset 0.50, photo zoom/pan 1/0/0. -- Capture same-viewport images for baseline, broad reflection only, and final edge separation when practical. Also inspect gloss 0/0.30/0.40, curvature -1/0/+1, camera 0.90, a portrait viewport, and one indoor image. -- Passing visual result: grass shows distinct curved surface reflection rather than uniform brightening; adjacent cells respond coherently; pane edges retain material without a bright rim or leakage; eyes/nose remain dark and face/grass do not wash out. -- Gloss 0 must remain visually equivalent to the baseline. Distortion 0 and other glass modes must retain existing behavior. - -## Write scope - -- Required: `src/shaders/mosaic.frag`, one narrowly scoped script under `scripts/`, `docs/qa-surface-reflection/` baseline/QA/report files. -- `src/main.ts` may be edited only if inspection proves the existing uniforms cannot support the required shader behavior; explain first in the report. -- Do not touch palette/history shaders, UI, camera, photo/depth placement, or window reveal. - -## Report contract - -Write `docs/qa-surface-reflection/implementation-report.md` with changed files, final coefficients and rationale, RED/GREEN evidence, full verification results, visual comparison paths, and remaining limitations. Do not claim GPU or mobile behavior that was not observed. diff --git a/.superpowers/sdd/surface-reflection/task-1-fix1-review-package.md b/.superpowers/sdd/surface-reflection/task-1-fix1-review-package.md deleted file mode 100644 index 0ae196c..0000000 --- a/.superpowers/sdd/surface-reflection/task-1-fix1-review-package.md +++ /dev/null @@ -1,20 +0,0 @@ -# Task 1 fix round 1 review package - -Review only the two Important findings from the first Astra review. - -## Files - -- Current regression (changed): `D:/project/behind_glass/scripts/test-surface-reflection.mjs` -- Updated report (changed): `D:/project/behind_glass/docs/qa-surface-reflection/implementation-report.md` -- Production shader (unchanged during fix): `D:/project/behind_glass/src/shaders/mosaic.frag` -- Preserved baseline: `D:/project/behind_glass/docs/qa-surface-reflection/baseline-mosaic.frag` -- Original task brief: `D:/project/behind_glass/.superpowers/sdd/surface-reflection/task-1-brief.md` - -## Fix evidence - -- Production shader SHA-256 remains `5FB0AE93482AF46833B076EABFB0018E8BFEBA0A83BFD244DCD210371E450180`. -- Current test SHA-256: `B924F91C82D0805C23C292BE613B21B6253E73C17C45F78D54E0AFAF6BC94A54`. -- Command: `node scripts/test-surface-reflection.mjs` -- Output: `surface reflection source/math regression passed; constant-output mutation rejected` - -The test now extracts complete individual statements, evaluates the actual `specGloss`, `broadReflection`, and final mix expression for representative inputs, compares refraction expressions to the preserved baseline, inspects the effective atlas branch, and asserts that a constant 50% white-output mutation is rejected. diff --git a/.superpowers/sdd/surface-reflection/task-1-fix2-review-package.md b/.superpowers/sdd/surface-reflection/task-1-fix2-review-package.md deleted file mode 100644 index a3bd591..0000000 --- a/.superpowers/sdd/surface-reflection/task-1-fix2-review-package.md +++ /dev/null @@ -1,19 +0,0 @@ -# Task 1 fix round 2 review package - -Review only the remaining atlas-exclusion finding from fix round 1. - -## Files - -- Current regression: `D:/project/behind_glass/scripts/test-surface-reflection.mjs` -- Updated report: `D:/project/behind_glass/docs/qa-surface-reflection/implementation-report.md` -- Unchanged production shader: `D:/project/behind_glass/src/shaders/mosaic.frag` -- Preserved baseline: `D:/project/behind_glass/docs/qa-surface-reflection/baseline-mosaic.frag` - -## Evidence - -- Production shader SHA-256 unchanged: `5FB0AE93482AF46833B076EABFB0018E8BFEBA0A83BFD244DCD210371E450180`. -- Current test SHA-256: `E4430C19827D0253C5E3EF073D702170C9552E3CAD09997D00D1C0405A66ED8A`. -- Command: `node scripts/test-surface-reflection.mjs` -- Output: `surface reflection source/math regression passed; constant-output and atlas-reflection mutations rejected` - -The test now compares the complete source segments executed while `REGION_ATLAS` is defined against the preserved baseline and applies a mutation that inserts gloss-dependent white mixing in an earlier atlas section. That mutation must be rejected. diff --git a/.superpowers/sdd/surface-reflection/task-1-review-package.md b/.superpowers/sdd/surface-reflection/task-1-review-package.md deleted file mode 100644 index 175af72..0000000 --- a/.superpowers/sdd/surface-reflection/task-1-review-package.md +++ /dev/null @@ -1,45 +0,0 @@ -# Task 1 review package - -This workspace is not a Git repository. Review the exact files below as the file-based equivalent of a task diff. - -## Required inputs - -- Task brief: `D:/project/behind_glass/.superpowers/sdd/surface-reflection/task-1-brief.md` -- Implementer report: `D:/project/behind_glass/docs/qa-surface-reflection/implementation-report.md` -- Pre-edit shader: `D:/project/behind_glass/docs/qa-surface-reflection/baseline-mosaic.frag` -- Current shader: `D:/project/behind_glass/src/shaders/mosaic.frag` -- New regression: `D:/project/behind_glass/scripts/test-surface-reflection.mjs` - -## Shader diff (`git diff --no-index --unified=10`) - -```diff -@@ -258,17 +258,17 @@ void main(){ - vec2 historyTexel=clamp(floor(fract(gridUv)*8.),vec2(0.),vec2(7.)); - vec2 historyUv=(cell*8.+historyTexel+.5)/uRegionAtlasSize; - vec4 splitHistory=texture2D(uRegionHistory,historyUv); - vec3 splitColor=splitHistory.a>.00001?splitHistory.rgb/splitHistory.a:radialColor; - vec3 candidateColor=mix(radialColor,splitColor,splitHistory.a); - color.rgb=mix(color.rgb,candidateColor,clamp(uRegionStrength*clamp(uStrength,0.,1.)*regionSurfaceValid(finalSceneUv,gh),0.,1.)); - } - #endif - #ifndef REGION_ATLAS - color.a=1.; -- vec3 v=normalize(uContentCameraPosition-gh),reflected=reflect(-v,nCurved); float lightT=(uLightPosition.z-gh.z)/safeZ(reflected.z); vec2 lightHit=gh.xy+reflected.xy*lightT; vec2 halfSize=vec2(.32,.42)*min(uPaneSize.x,uPaneSize.y); vec2 windowCoord=abs(lightHit-uLightPosition.xy)/halfSize; vec2 windowMask=1.-smoothstep(vec2(.45),vec2(1.15),windowCoord); float spec=windowMask.x*windowMask.y*step(.0001,reflected.z)*step(0.,lightT); float gloss=spec*clamp(uGlossStrength,0.,1.)*.12*edgeWeight*clamp(uStrength,0.,1.); color.rgb=mix(color.rgb,vec3(1.),gloss); gl_FragColor=color; -+ vec3 v=normalize(uContentCameraPosition-gh),reflected=reflect(-v,nCurved); float lightT=(uLightPosition.z-gh.z)/safeZ(reflected.z); vec2 lightHit=gh.xy+reflected.xy*lightT; vec2 halfSize=vec2(.32,.42)*min(uPaneSize.x,uPaneSize.y); vec2 windowCoord=abs(lightHit-uLightPosition.xy)/halfSize; vec2 windowMask=1.-smoothstep(vec2(.45),vec2(1.15),windowCoord); float surfaceReflectionWeight=mix(.35,1.,edgeWeight); float glossStrength=clamp(uGlossStrength,0.,1.); float spec=windowMask.x*windowMask.y*step(.0001,reflected.z)*step(0.,lightT); float specGloss=spec*glossStrength*.12*surfaceReflectionWeight*clamp(uStrength,0.,1.); vec2 broadWindowMask=1.-smoothstep(vec2(.15),vec2(1.75),windowCoord); float broadFacing=pow(max(dot(nCurved,v),0.),2.); float broadReflection=broadWindowMask.x*broadWindowMask.y*broadFacing*glossStrength*.035*surfaceReflectionWeight*clamp(uStrength,0.,1.); color.rgb=mix(color.rgb,vec3(1.),specGloss+broadReflection); gl_FragColor=color; - #include - #else - color.a=atlasEvidence; - gl_FragColor=color; - #endif - } -``` - -The test and report are new files and must be read in full. The exact shader baseline hash reported by the implementer is `CEE5F75C7A62A9146CBE451C661C2E0066EE57EB8963A7B0F56C281873F37E35`. - -## Controller visual evidence so far - -- `docs/qa-surface-reflection/before-default.png` -- `docs/qa-surface-reflection/after-default.png` -- Same 1280×720 dog1/AI-depth/default-condition capture. -- Frame-interior pixel comparison: mean absolute channel difference `0.3106/255`, max channel difference `14`, changed channels `13.85%`. -- This confirms a change but does not establish that the requested glass-surface improvement is visually sufficient. diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index b5150dc..0000000 --- a/AGENTS.md +++ /dev/null @@ -1,78 +0,0 @@ -# Pet Glass / Pet Behind Glass 프로젝트 지침 - -## 원본 요구사항 - -- 2026-10-06 최신 Base 비교: 사용자는 Base 입력 770에서 depth=1 영역이 실제 앞쪽 부위를 명확하게 추정하는지 테스트하도록 요청했다. 개발 비교에서 Small/Base를 선택하며 기본 Small은 유지한다. 최대 깊이 진단은 정규화 Float32 최대 1, 8비트 최대 1, ≥0.99 영역을 구분하고 위치·픽셀값·장면 간격을 표시한다. 거리 조절은 전체 최대 depth 표면을 기준으로 유지하며 코 검출이나 실제 측정 거리로 설명하지 않는다. Base는 비상업적 테스트 옵션이다. 결과/한계는 `docs/qa-ai-depth-base-2026-10-06/report.md`를 따른다. - -- 2026-10-06 최신 AI depth 입력: Depth Anything V2 Small의 추론 전처리 기준 크기를 770으로 사용한다. 종횡비와 14의 배수 정렬을 유지하며 WebGPU와 WASM 모두 공통 로더에서 적용한다. 사진 스냅샷의 긴 변 상한 1024, 8비트 출력, 128×128 Depth mesh, 사진 구도와 유리 설정은 유지한다. 검증 기록은 `docs/qa-ai-depth-770-2026-10-06/report.md`다. - -- 2026-10-06 최신 거리 조절: `사진–유리 거리`를 0–100%로 조절한다. 사진의 가장 앞쪽과 유리 사이 간격은 장면 단위 0.04–0.60이며 초기 0%는 기존 근접 배치다. RGB와 Depth를 공통 이동하고 굴절 기준 평면과 프레임 안쪽 가림도 함께 갱신한다. 거리 값은 사진 교체·AI depth 완료 후에도 유지하며 확대·팬을 자동 변경하지 않는다. 구현·검증은 `docs/qa-photo-glass-distance-2026-10-06/report.md`를 따른다. - -- 2026-10-06 최신 고방유리 작업: 첨부 실물 사진처럼 유리 자체의 반복 표면과 그 표면에 따른 사진 굴절을 우선한다. 확대 사진에 따른 후속 보정과 검증은 `docs/qa-gobang-facets-2026-10-06/report.md`를 따르며, 첫 구현 기록은 `docs/qa-gobang-surface-2026-10-06/report.md`에 보존한다. 둥근 사각 타일이나 삼각 보석 면을 목표로 삼지 않는다. 기본 고방유리는 색면 처리를 사용하지 않으며, 이전 색면 1 고정 지시는 보존된 Ref1 옵션 2 모드에 적용한다. 두 표현을 혼동하지 않는다. 자동 구도 변경 금지와 RGB/Depth 공통 배치는 유지한다. - -- 2026-09-14 최신 Ref1 옵션 정리: 색면 단순화와 Distortion을 1로 고정하고 해당 조절 UI를 제거한다. 주 조절은 Grid 10~24(큰 얼굴 권장12~16, 작은 얼굴/여러 마리20~24), 굴곡 −1~1, 광택, 시점 범위다. 기타 효과·깊이·조명·감도는 접힌 개발 비교로 이동하고 수동 구도는 유지한다. 초기 기준값 Grid13/굴곡+1/광택.3/Camera.5. 상세와 한계는 `docs/ref1-option-ranges.md`. 이전 기본값·노출 UI 지시보다 우선한다. - -- 2026-09-14 최신 옵션 지정: 현재 어두운 사각 색면 보존 구현과 설정을 **현재 프로젝트에서 Ref1 목표에 가장 근접한 두 번째 옵션(옵션 2)**으로 명시한다. 정확한 값은 `docs/ref1-option-2.md`를 따른다. 기존 기준안은 옵션 1로 보존하며, 옵션 2를 Ref2 목표로 해석하지 않는다. 이후 변경은 두 기준과 구분해 기록한다. - -- 2026-09-14 최신 색면 보호 방식: 눈·코 원본 윤곽만 붙여 놓은 인상을 없애기 위해 최종 픽셀의 보호/원본 RGB 복원 분기를 제거한다. 앞쪽 depth와 어두운 RGB의 증거는 셀의 사각 색면 대표색 선택에만 사용한다. 어두운 색면의 존재를 보존하며 원래 픽셀 모양을 보존하지 않는다. 아래의 픽셀별 안전 palette/원본 fallback 지시보다 우선한다. `docs/ref1-dark-color-planes.md` 참고. - -- 2026-09-14 최신 보호 범위 정정: 눈·코 보호는 원본 depth의 앞쪽(흰 부분)과 RGB의 어두운 특징이 겹치는 곳에 한정한다. 원본 상대 depth 0.80~0.95에서 보호를 부드럽게 증가시키며 기존 안전 palette/원본 fallback을 유지한다. 굴절 RGB와 같은 장면 위치에서 원본 depth를 읽는다. 색면 전체의 거리 감쇠 제거, 배경 단순화 및 시점 반응은 유지한다. 상세 구현·검증은 `docs/ref1-depth-protection.md`. - -- 2026-09-14 최종 사용자 정정: 실제 결과를 확인한 사용자가 눈·코 보호 예외를 유지하도록 다시 지시했다. 아래의 보호 제거 지시는 이 정정으로 대체한다. 어두운 형태가 밝은 색면에 흡수될 때 기존 안전 palette 우선 보호와 필요한 픽셀의 원본색 fallback을 복원한다. 사진 배경의 색면 강화, SSE 분할 선택, 시점 반응과 70ms 전환 보간은 유지한다. - -- 2026-09-14 최신 기준안 지정 및 추가 작업: 지금까지의 적용 내용과 비교 옵션을 **Ref1 목표에 가장 근접한 현재 기준안**으로 명시한다. 상세 값은 `docs/ref1-current-baseline.md`를 따른다. 사용자 최신 정정에 따라 눈·코의 어두운 픽셀/원본 RGB 보호 예외를 제거하고 얼굴과 사진 속 배경에 같은 색면 단순화를 적용한다. 눈·코 식별은 결과의 평가 기준이며 보호 로직을 강제하지 않는다. 아래 과거 눈·코 보호 지시보다 이 지시가 우선한다. 시점 반응, 70ms 색면 전환 보간, 자동 구도 조정 금지는 유지한다. - -- 2026-09-14 최신 레퍼런스 변경: 사용자는 주 시각 기준을 **Ref1**로 변경했다. Ref2의 근접 선명도·거리 반응 재현을 주 목표로 삼지 않는다. Ref1의 큰 사각 색면, 과감하게 단순화된 얼굴 윤곽, 적은 정보로 식별되는 눈·코를 우선 평가한다. 아래의 Ref2 우선 지시보다 이 지시가 우선한다. 자동 구도 조정 금지와 인접 셀의 공통 장면 일관성은 유지한다. Ref1 | Ref2 비교 배치에서는 Ref1을 주 기준, Ref2를 보조로 표시한다. 상세 기준: `docs/ref1-direction.md`. - -- 최신 사용자 요청: 자동 구도 조정을 하지 않는다. 사진 입력 및 자동 AI depth 완료 시 확대·팬·크롭을 자동 변경하지 않는다. 유리 근접 깊이 배치와 수동 구도 조절은 유지한다. 과거 자동 얼굴/앞쪽 영역 구도 지시보다 우선한다. - -- 최신 근접 배치 정정: 사용자는 얼굴 확대 프리셋만의 해결을 거부했다. 사진 입력 후 깊이 표면의 앞쪽을 유리 바로 뒤에 배치하여 공간적으로 가까운 인상을 구현한다. RGB/Depth 공통 배치와 굴절 교차 기준을 함께 갱신하며 유리 관통을 방지한다. 확대만으로 실제 간격을 바꿨다고 설명하지 않는다. 상세 기록: `docs/glass-contact.md`. - -- 최신 색면 실험: 일관된 굴절 위에 셀 내부 색상 양자화와 작은 색 영역의 경계 단순화를 추가한다. 전체 사진 블러나 저해상도 확대, 셀 전체 단색화로 대체하지 않는다. 눈·코의 작은 어두운 형태를 보호하고 색면 단순화 0에서 기존 출력을 복원한다. Ref1 | Ref2 비교 배치를 유지한다. 작업·검증 기록은 `docs/qa-regions/brief.md`. -- 최신 사용자 정정: 가까운 얼굴에서 색면 효과를 줄이는 거리 감쇠를 제거한다. 유효한 표면에는 유리와의 간격에 관계없이 설정된 색면 강도를 적용하고, 범위 밖 UV·배경 depth·역투영 실패·유리 앞/접촉 표면 검사는 유지한다. -- 최신 시점 굴절 보정: 기본 Mosaic에만 시점에 반응하는 셀 내부 굴절 이동을 더한다. 같은 현재 곡면 법선과 중앙 시점 굴절의 기울기 차이를 사용하고, 셀 경계는 고정하며 내부는 축별 cosine envelope로 움직인다. signed curvatureScale로 방향을 제어하고, atlas/final에 동일 계산을 적용한다. 이 항은 현재 평면 교점 광학 모델 안의 연출 근사다. 자동 구도, 입력 감도, 사진/Depth 배치와 다른 유리 효과는 바꾸지 않는다. -- 최신 Ref1 색면 보정: 큰 사각 얼굴·몸 색면과 적은 어두운 눈·코 형태를 우선한다. 기존 4색 palette에 셀별 최적 단일 축 분할(신뢰도 기반)과 radial grouping fallback을 사용한다. 어두운 눈·코는 palette 내 안전한 어두운 색으로 보호하고, 안전 palette 색이 없을 때만 해당 픽셀 원본색을 남긴다. 전체 셀 단색화, 원본 저해상도 확대, 전체 블러는 금지한다. region 0과 Distortion 0의 기존 동작을 유지하며, 시점 gain .18은 함께 유지한다. 상세 QA: `docs/ref1-shape-review.md`. -- 최신 시점/분할 전환 보정: Camera Offset 기본값은 .50, 최대값은 .90이며 입력 sensitivity 범위와 처리는 유지한다. 기본 Mosaic 외곽 taper는 1.25셀로 넓히고 다른 유리 모드는 .75셀을 유지한다. 셀 축 분할의 이산 메타데이터가 아니라 8×8 premultiplied 색·confidence field만 ping-pong history에서 70ms 지수 수렴시킨다. 카메라 이동은 history를 초기화하지 않으며 사진·depth·구도·격자·굴곡·강도·효과/모드·비활성화 변경은 초기화한다. 사진 구도 자동 변경은 금지한다. 실기기 FPS 및 영상 flicker 측정은 별도다. 상세 QA: `docs/ref1-shape-review.md`. - -- 2026-09-14 최신 시점 일관성 지시: 셀마다 독립된 사진 정보를 가진 듯한 임의 확대·크롭 표현을 배제한다. 조각 유리는 공통 장면과 카메라 광선, 부호 있는 곡면 법선에서 굴절 샘플 위치를 계산한다. 과거의 셀별 무작위 샘플 배율·중심 이동 지시와 충돌하면 이 지시를 우선한다. 강한 블러로 불일치를 숨기지 않는다. - -- 2026-09-14 재보정: 사용자는 과도한 흐림으로 사진/유리의 느낌이 사라지는 결과를 지적했다. 셀별 확대·위치 변화는 유지하되 눈·코 조각 내부 윤곽을 흐림으로 지우지 않는다. 해상감 저하를 일괄적인 강한 블러로 해석하지 않는다. - -- 2026-09-14 추가: Ref2처럼 유리 투과 시 셀별 세부 정보가 크게 줄고 눈·코 조각의 크기와 위치가 달라지는 표현을 강화한다. 전체 출력 해상도 저하나 단색 pixelation으로 대체하지 않는다. `Ref1 | Ref2` 아래 작업 이미지 비교 배치는 개발 모드와 로컬 배포 미리보기 모두에서 유지한다. 상세 기준은 `docs/glass-resolution-task.md`. - -- Mosaic 셀 굴곡은 관찰자 기준 -1=사진 쪽 오목, 0=셀 내부 평탄, +1=관찰자 쪽 볼록이다. 기본값 +0.65를 유지하며 부호가 있는 같은 곡면 법선을 굴절과 반사에 공유한다. 굴곡 0에서도 기존 셀별 기울기와 샘플링 효과는 유지한다. - -- 과거 Ref2 주 기준 지시는 위 최신 Ref1 변경으로 대체되었다. 사진 구도는 RGB/Depth에 같은 변환을 적용하고 원본 파일을 바꾸지 않는다. - -- 반복 쿠션형 인상을 줄이기 위해 중앙이 비교적 평탄하고 셀마다 약하게 비대칭인 곡면을 사용한다. 반사는 공통의 부드러운 직사각형 광원 형태를 근사하며 기존 조명 XY/광택 조절로 제어한다. 사진 리라이팅이나 시간 기반 반짝임은 추가하지 않는다. - -- 셀 내부는 얕은 사각 곡면으로 표현하고 같은 표면 법선을 굴절과 광택에 공유한다. 광택을 꺼도 곡면에 의한 사진 윤곽 변화가 남아야 한다. 격자는 화면 너비가 아닌 유리판 기준이며, 셀 샘플 영역을 과도하게 줄여 단색 블록이 되는 결과를 피한다. 모바일/데스크톱 같은 설정, 정지 화면 눈·코 식별, 드래그 시 유리 좌표 일관성을 시각 검증한다. - -- MVP에서는 사진 리라이팅을 제외한다. 사진의 기존 촬영 조명은 유지하고, 추가 광원은 Mosaic 유리 표면의 셀별 반사에만 적용한다. 공통 광원의 가로·세로 위치와 광택 강도를 조절하며, 셀별 반사는 시점에 따라 변하고 시간에 따른 임의 반짝임은 사용하지 않는다. 광택 0은 기존 Mosaic, Distortion 0은 기존 무효과 출력을 유지한다. - -- 최신 시각 보정 목표: 참고 이미지처럼 사각 셀마다 눈·코·얼굴 조각의 위치와 배율이 달라져야 한다. 원형 물결 왜곡과 검은 격자선만 강해지는 결과는 완료로 인정하지 않는다. -- Mosaic 보정은 기존 Depth/RenderTarget을 유지하고 셀별 샘플 영역·확대·압축과 미세한 퍼짐을 조절한다. 단색 pixelation으로 대체하지 않는다. 같은 사진·같은 구도의 정지 화면에서 시각 목표를 먼저 비교하고 시점 변화도 재검증한다. -- 최신 수정 지시서는 `docs/depth-task-brief.txt`이다. 기존 평면 기반 설명과 충돌하면 이 수정 지시서를 우선한다. -- 기존 Mosaic/Reeded/Frosted 렌즈 효과를 보존하면서 `PetDepthMesh → WebGLRenderTarget → Glass Shader`의 2-pass 구조로 확장한다. -- **반드시 Glass OFF에서 코·눈·얼굴의 실제 카메라 parallax를 먼저 검증하고, 그 다음 RenderTarget과 Glass 효과를 연결한다.** -- 사용자가 지정한 테스트 사진은 `public/assets/sample-pet.png`이다. 테스트 depth는 수작업/절차적 근사임을 명시하며 AI 추정 또는 실제 측정값으로 표현하지 않는다. 사진은 로컬 테스트에만 사용하며 게시 권한으로 간주하지 않는다. -- Depth 내부 규칙은 0=뒤, 1=앞이다. 이번에는 RGB+Depth 입력과 정적 depth를 우선하며 AI 추정 및 영상 매 프레임 depth 추정은 후순위다. -- `docs/task-brief.txt`에 사용자 작업지시서를 보존한다. -- Vite + TypeScript + Three.js + GLSL, Vanilla TS를 사용한다. React와 별도 백엔드는 사용하지 않는다. -- 미디어 처리는 브라우저 로컬에서 수행한다. -- 핵심은 PetPlane 앞에 위치한 GlassPlane의 **시점 의존 굴절**이다. Mosaic는 단순 pixelation이나 이미지 전체 평행 이동으로 대체하지 않는다. -- 원문 구현 우선순위를 따른다. Scene → 이미지 Texture → PetPlane → GlassPlane → Pointer drag → Mosaic → 시점 굴절 → VideoTexture → Reeded → Frosted → Gyroscope → UI polish. -- 모바일 우선, 미디어 contain, 자원 dispose/revoke, DPR 상한, 부드러운 시점 보간을 지킨다. - -## Karpathy Guidelines 적용 - -- 사용자가 요청한 `karpathy-guidelines`를 적용한다. 로컬 위치: `C:/Users/horoli/.codex/skills/karpathy-guidelines/SKILL.md`. -- 코딩 전에 가정과 완료 기준을 명시하고 불확실한 중요한 요구사항을 드러낸다. -- 요구사항을 충족하는 최소 구현을 우선하며 불필요한 추상화와 범위 밖 기능은 추가하지 않는다. -- 기존 코드가 생긴 이후에는 작업과 직접 관련 있는 부분만 수정한다. -- 빌드·타입 검사와 실제 동작 검증을 구분하고, 실행하지 못한 검증을 통과했다고 보고하지 않는다. -- 주요 단계와 최종 결과에 수정 파일, 구현 기능, 미완료 항목, 실행 방법, 셰이더 원리, 다음 개선점을 간단히 보고한다. - - - - diff --git a/README-서버실행.md b/README-서버실행.md new file mode 100644 index 0000000..c4eb188 --- /dev/null +++ b/README-서버실행.md @@ -0,0 +1,137 @@ +# Behind Glass 서버 배포본 + +- 버전: 2026-10-09 / 소스 7d82e3b1a9f083376bfd0b916568b1472dcb7f84 +- 최신 세로 시점 보정, 사진 위치 조절, 홈 확인, 새 사진 입력 시 조작값 초기화 포함. +- `dist`는 Fastify 집계가 **활성화된 서버용 빌드**입니다. 바로 사용해도 됩니다. +- Vite/TypeScript 원본, Fastify/SQLite 코드, lockfile, 라이선스, 운영 예시를 포함합니다. public/참고 이미지 중 dist와 동일한 파일은 중복 보관하지 않으며 복원 스크립트가 원래 경로로 복사합니다. Blender 원본 제작 파일은 제외했습니다. +- DB·개인 설정·인증정보·node_modules·Git 이력은 포함하지 않습니다. 기존 DB가 있다면 외부 저장 위치를 그대로 유지하세요. + +## 1. 설치 + +Node **24.x**가 필요합니다. 검증 버전은 `.node-version`의 24.19.0입니다. +ZIP을 풀고 `behind-glass` 폴더에서 실행하세요. + +```sh +node --version +npm ci +node --input-type=module -e "import Database from 'better-sqlite3'; const db = new Database(':memory:'); console.log(db.prepare('select sqlite_version() as version').get()); db.close()" +``` + +다른 PC의 node_modules를 복사하지 마세요. better-sqlite3는 대상 OS/CPU에 맞춰 설치해야 합니다. 미리 빌드된 바이너리가 없는 환경에서는 해당 서버의 네이티브 빌드 도구가 필요할 수 있습니다. + +### Windows / PowerShell 로컬 실행 + +이 PC는 nvm으로 Node 24.19.0을 설치·활성화했습니다. 다른 터미널에서도 `node --version`을 확인하세요. 빌드 명령은 Node 스크립트로 환경변수를 지정하므로 Windows와 Linux에서 동일하게 사용할 수 있습니다. + +```powershell +nvm use 24.19.0 +npm ci +node scripts/restore-source-assets.mjs +npm run build:server +npm run start:local +``` + +로컬 주소는 `http://127.0.0.1:3000`입니다. `start:local`은 `deploy/arrival.local.env`를 명시적으로 읽으며, 현재 PC의 DB는 `C:\Users\horoli\AppData\Local\BehindGlass\analytics.sqlite`에 저장합니다. 데이터 폴더는 현재 사용자와 SYSTEM만 접근하도록 설정했습니다. 이 설정 파일은 Git에서 제외됩니다. 실행 중인 터미널에서 Ctrl+C로 종료합니다. + +새 PC에서는 아래처럼 해당 계정의 경로로 설정 파일을 만들고, 데이터 폴더의 Windows ACL을 확인하세요. 기존 DB가 있다면 새 경로를 만들기 전에 기존 `DB_PATH`를 유지하세요. + +```powershell +$localDataPath = Join-Path $env:LOCALAPPDATA 'BehindGlass' +@( + 'NODE_ENV=development' + 'HOST=127.0.0.1' + 'PORT=3000' + 'PUBLIC_ORIGIN=http://127.0.0.1:3000' + "DB_PATH='$localDataPath\analytics.sqlite'" +) | Set-Content -LiteralPath 'deploy/arrival.local.env' -Encoding utf8 +``` + +`localhost`와 `127.0.0.1`은 서로 다른 origin입니다. 집계가 필요하면 설정과 동일한 주소로 접속하세요. 로컬 HTTP 실행은 PC 확인용이며, 실제 모바일 센서 확인은 HTTPS 배포 후 진행합니다. + +better-sqlite3 13.0.3은 플랫폼별 바이너리를 패키지에 포함합니다. npm이 이를 불필요하게 소스 빌드하지 않도록 lockfile에도 원래 패키지의 `gypfile: false`를 반영했습니다. npm의 설치 스크립트 허용 목록에는 고정된 ONNX Runtime 및 protobufjs 버전만 추가했습니다. 의존성 버전은 변경하지 않았습니다. + +Windows 집계 테스트의 파일 링크 검증은 개발자 모드 또는 링크 생성 권한이 있는 터미널에서 실행하세요. + +로컬 집계와 백업도 같은 설정 파일을 명시적으로 읽습니다. `npm ci`를 다시 실행하기 전에는 서버를 종료하세요. Windows에서는 실행 중인 서버가 SQLite DLL을 사용해 재설치 시 파일 삭제가 차단될 수 있습니다. + +```powershell +node --env-file=deploy/arrival.local.env server/metrics.mjs --month 2026-10 +node --env-file=deploy/arrival.local.env server/backup.mjs --output "$env:LOCALAPPDATA\BehindGlass\backups\analytics-2026-10-09.sqlite" +``` + +## 2. 실행 + +DB는 프로젝트 바깥의 영구 로컬 디스크에 둡니다. 아래는 현재 계정의 홈 폴더를 사용하는 예시입니다. **PUBLIC_ORIGIN은 실제 접속 HTTPS 주소로 바꾸세요.** 경로 없이 도메인(필요하면 포트)까지만 입력합니다. + +```sh +(umask 077; mkdir -p "$HOME/behind-glass-data") +DB_PATH="$HOME/behind-glass-data/analytics.sqlite" \ +PUBLIC_ORIGIN="https://your-domain.example" \ +NODE_ENV=production HOST=127.0.0.1 PORT=3000 npm start +``` + +처음 실행하면 빈 SQLite DB와 스키마가 만들어집니다. 기본 포트는 3000이며 nginx 뒤에서 사용할 수 있도록 127.0.0.1에만 바인딩합니다. SSH 종료 후에도 유지하려면 기존 프로세스 관리자 또는 `deploy/behind-glass.service.example`을 서버 경로·사용자에 맞춰 적용하세요. **단일 프로세스**로 실행하고 PM2 cluster/multiple workers는 사용하지 마세요. + +`deploy/arrival.env.example`은 예시입니다. 파일을 복사하는 것만으로 자동 로드되지는 않습니다. systemd의 EnvironmentFile 또는 Node의 명시적 `--env-file=/절대경로/arrival.env` 옵션을 사용하세요. 실제 설정 파일은 공개 폴더에 두지 마세요. + +## 3. nginx / HTTPS + +기존 HTTPS 도메인의 요청을 같은 Fastify 프로세스로 전달합니다. 정적 화면과 `/api`가 같은 origin이어야 합니다. 기존 server 블록 안의 location 예시: + +```nginx +location / { + proxy_pass http://127.0.0.1:3000; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Proto $scheme; +} +``` + +도메인·인증서·포트 충돌과 기존 location 설정을 확인한 뒤 적용하세요. 이 ZIP이 nginx나 시스템 설정을 자동 변경하지는 않습니다. 사진 처리는 브라우저 안에서 수행되며 AI 모델/WASM의 외부 다운로드에는 인터넷 연결이 필요합니다. 모바일 센서/보안 기능 확인은 실제 HTTPS 주소에서 진행하세요. + +이 서버에는 자체 로그인 기능이 없습니다. 현재 비공개 테스트 범위를 유지하려면 HTTPS 프록시에서 소유자 전용 접근제어도 설정하세요. 외부 공개는 포함된 사진과 리소스의 공개 범위를 확인한 후 별도로 진행하세요. + +현재 trustProxy는 false입니다. 리버스 프록시 뒤에서는 API 요청 제한(기본 60회/분)이 같은 연결 IP로 합산될 수 있으니 공개 트래픽을 늘리기 전에 프록시 신뢰 범위와 제한 정책을 검토하세요. Origin 검사는 로그인/인증을 대신하지 않습니다. + +## 4. 수정 후 다시 빌드 + +처음 재빌드하기 전에 아래 복원 명령을 한 번 실행하세요. 기존 dist에 들어 있는 같은 파일을 복사하므로 인터넷 다운로드가 아닙니다. 복원 전 dist를 지우지 마세요. + +```sh +node scripts/restore-source-assets.mjs +npm run build:server +``` + +주의: `npm run build`는 별도 정적 테스트 Site용이라 **집계가 비활성화**됩니다. 이 서버에서는 `build:server`를 사용하세요. 원본 소스에서 한 번 수정하더라도 각 서버의 재빌드·재배포는 별도로 해야 합니다. + +## 5. 확인 / 집계 / 백업 + +```sh +npm run test:arrival +curl http://127.0.0.1:3000/api/arrivals/count +DB_PATH="$HOME/behind-glass-data/analytics.sqlite" npm run --silent metrics -- --month 2026-10 +``` + +`test:arrival`은 임시 DB로 동작하며 운영 DB를 사용하지 않습니다. 실제 개인 사진의 성공한 도착만 누적하고 샘플 도착은 제외합니다. 방문 집계는 샘플 진입도 포함합니다. + +백업·복원 및 집계 기준은 `docs/arrival-backend-operations.md`를 참고하세요. DB/WAL/SHM은 dist/public 및 프로젝트 밖에 보관하세요. 서비스 계정만 읽고 쓸 수 있도록 데이터 폴더와 DB 권한을 제한하세요. + +## 검증 범위 + +### 현재 Windows 로컬 검증 (2026-10-09) + +- Node 24.19.0 / npm 11.17.0에서 일반 `npm ci`, SQLite 로딩, 정적 빌드 및 서버용 빌드를 확인했습니다. 최종 `dist`는 서버용 빌드입니다. +- `npm run test:arrival`은 서버 33개 + 클라이언트 73개, 총 106개 통과했습니다. +- 기존 전체 테스트는 470개 중 467개 통과했습니다. 다음 3개 테스트는 원래 배포본에 포함되지 않은 QA 자료 때문에 실패하며, 해당 원본 자료 복원이 필요합니다. 통과로 처리하거나 임의 자료로 대체하지 않았습니다. + - `scripts/test-cutout-worker.mjs`: `docs/qa-countryside-cutout-2026-10-07/runtime/sample-320.rgba` 누락 + - `scripts/test-original-photo-only.mjs`: `docs/reference-assets/countryside/open-house.png` 누락 + - `scripts/test-surface-reflection.mjs`: `docs/qa-surface-reflection/baseline-mosaic.frag` 누락 +- 실제 `127.0.0.1:3000` HTTP로 HTML, JS/CSS, 샘플 사진, GLB 및 ONNX 파일의 200 응답과 집계 API `{ "count": 0 }`를 확인했습니다. 다른 Origin은 403, 비공개 파일 경로는 404입니다. +- Windows 자산 경로 구분자를 정규화하고, 테스트 DB를 닫은 뒤 임시 파일을 삭제하도록 수정했습니다. AI 테스트의 파일 URL도 Windows에서 동작하도록 수정했습니다. +- `RELEASE-MANIFEST.json`은 수령한 원본 배포본의 체크섬 기록입니다. 이번 로컬 수정 파일의 체크섬과는 구분합니다. + +### 수령한 원본 릴리스의 검증 기록 + +- 이 릴리스의 서버용 빌드와 방문/도착 테스트를 실행했습니다. +- 최신 소스의 전체 자동 테스트 470개 및 두 빌드는 통과한 상태입니다. +- ZIP 추출본에서 Fastify inject + 실제 임시 SQLite로 정적 페이지와 집계/중복 처리를 확인했습니다. 네트워크 포트를 통한 실서비스 검증과는 다릅니다. +- 사용자의 서버 OS/CPU, nginx/HTTPS, 실제 모바일/WebGL/센서, 외부 AI 다운로드는 배포 후 확인해야 합니다. diff --git a/README.md b/README.md deleted file mode 100644 index df44eae..0000000 --- a/README.md +++ /dev/null @@ -1,51 +0,0 @@ -# Pet Behind Glass - -사진과 Depth Map으로 얕은 2.5D 장면을 만들고 그 렌더 결과를 유리 셰이더로 굴절시키는 브라우저 로컬 MVP입니다. Vite, TypeScript, Three.js, GLSL을 사용하며 별도 백엔드는 없습니다. 선택 사항인 AI depth 추론도 브라우저 안에서 실행합니다. - -```bash -npm install -npm run dev -npm run build -``` - -`샘플 반려동물 불러오기`를 누르면 사용자가 제공한 사진과 수작업 Depth Map이 **얼굴 확대 구도**의 Final로 표시됩니다. 사진 확대·가로 위치·세로 위치를 조절하거나 사진 구도 초기화로 원래 전체 구도로 돌아갈 수 있습니다. 일반 사진/영상 업로드는 전체 구도로 시작합니다. **Mosaic 스타일**에서 **조각 유리**(유리 가로 10칸, 강도 0.90)와 **촘촘 유리**(28칸, 강도 0.85)를 비교하세요. 셀마다 이미지 위치·확대율이 달라지며 검은 격자선과 원형 물결은 제거했습니다. Grid Size는 6~96으로 조절할 수 있습니다. **No Glass**는 깊이 시차를 확인하는 모드입니다. 직접 사용할 때는 사진 또는 영상 다음에 같은 종횡비의 Depth 이미지를 선택합니다. 새 RGB 미디어는 flat depth로 시작합니다. - -사진을 불러온 뒤 **AI 깊이 생성**을 누르면 Depth Anything V2 Small이 로컬에서 상대 깊이를 계산합니다. 처음 실행할 때 모델 파일을 Hugging Face에서 내려받습니다. 사진 데이터는 추론을 위해 브라우저 밖으로 전송하지 않습니다. 결과는 AI 추정으로 표시되고 No Glass 모드로 전환됩니다. 영상에서는 이 버튼을 사용할 수 없습니다. 자세한 출처와 Playwright smoke 실행법은 [AI depth 안내](docs/ai-depth.md)를 참조하세요. - -Mosaic의 **셀 굴곡**으로 얕은 곡면을 조절하고, **광택 강도**, **조명 가로**, **조명 세로**로 유리 표면의 반사를 조절할 수 있습니다. 하나의 공통 광원과 셀별 표면 방향으로 반사를 계산하며, 카메라 이동에도 반응합니다. 광택 0은 표면 반사만 끄고 곡면 굴절을 유지하며 Distortion 0에서는 광택도 꺼집니다. 사진 리라이팅은 MVP 범위에서 제외합니다. 조명 깊이는 고정이며 직사각형 광원을 향하는 반사 시선으로 창 모양을 근사합니다. 실제 환경맵이나 유리 내부 다중 반사는 없습니다. - -## 변경된 구조 - -QA 개선으로 Reeded/Frosted도 활성 효과의 출력을 유리판 안으로 제한합니다. 파일 선택은 Tab과 Enter로 접근할 수 있으며, 샘플의 수작업 Depth 안내는 로딩 이후에도 유지됩니다. 굴곡 +0.65 초과 구간은 높이 증가폭을 완만하게 압축해 강한 볼록의 과도한 이동을 소폭 줄였습니다. 기본값과 음수 구간은 유지합니다. - -셀 굴곡은 **−1 오목 / 0 평탄 / +1 볼록**으로 조절합니다. 양수는 관찰자 쪽으로 솟고 음수는 사진 쪽으로 들어가는 방향이며 기본값은 +0.65입니다. 0에서도 셀별 기울기와 조각별 확대·이동은 유지됩니다. 실제 유리 메시를 변형하는 대신 부호가 있는 높이함수의 법선으로 굴절과 반사를 함께 근사합니다. - -- `PetDepthMesh`: 128×128 세그먼트, 정점 Z를 `(depth-bias)*scale`로 이동. 규칙은 **0=뒤, 1=앞**, 기본 scale 0.25, 상한 0.4입니다. -- 실제 PerspectiveCamera가 보간 이동하여 코·눈·몸 사이의 시차를 만듭니다. Camera Offset 상한 0.6, camera z=3입니다. -- Final은 `content scene → WebGLRenderTarget → fullscreen glass scene`의 2-pass 구조입니다. DPR 상한은 1.5이며 RT는 선형 색상, 화면 출력에서 색공간을 변환합니다. -- Mosaic는 월드 유리판 기준 셀별 위치·축별 배율·미세 회전과 5개 주변 샘플을 사용합니다. 중앙이 비교적 평탄한 사각 곡면에 셀별 고정 비대칭을 주고, 같은 법선으로 굴절과 창 모양 반사를 계산합니다. 주 기준은 레퍼런스 2번입니다. 조각 유리는 변화가 작은 셀과 확대·압축 셀을 섞어 특징점과 넓은 색면이 공존하도록 하고, 촘촘 유리는 기존 설정을 유지합니다. 입력은 `uSceneTexture`이며 기존 Depth/RT 파이프라인과 Reeded/Frosted는 유지합니다. 활성 Mosaic에서 유리판 밖은 배경색으로 가려 외곽을 일정하게 유지합니다. Distortion 0 및 No Glass는 진단용 전체 장면을 표시하므로 확대된 사진이 유리판 밖까지 보일 수 있습니다. -- View Mode는 Final, RGB(평면 원본), Depth(평면 지도), No Glass(깊이 메시), Glass Only(배경 위 유리 진단)입니다. Depth Scale, Grid Size, Distortion, Camera Offset, View Sensitivity를 조절할 수 있습니다. - -## 주요 파일 - -- 수정: `src/main.ts`, `src/input/CameraController.ts`, 기존 Glass fragment 3개, `index.html`, `src/style.css`, `AGENTS.md`. -- 신규: `src/objects/PetDepthMesh.ts`, `src/depth/DepthMapLoader.ts`, `DepthProcessor.ts`, `StaticDepthProvider.ts`, `DepthDebug.ts`, `src/types/depth.ts`. -- 신규 셰이더: `src/shaders/petDepth.vert`, `petDepth.frag`, `glassScreen.vert`. -- 자산: `public/assets/sample-pet.png`, `sample-pet-depth.png`, `sample-pet-depth.json`. 재생성은 `scripts/create-sample-depth.ps1`. -- 명세와 검증: `docs/depth-task-brief.txt`, `depth-implementation-plan.md`, `depth-validation.md`. 기존 효과는 `docs/baseline-shaders/`에 비교용으로 보존했습니다. - -## 확인 결과와 한계 - -TypeScript 검사와 production build를 통과했습니다. 사용자 사진으로 Glass OFF 시차를 먼저 검증한 뒤 Glass를 연결했습니다. 브라우저에서 세 효과, RGB/Depth 업로드, 비율 오류, 강도 0 Final/No Glass 정렬·색상, 390px viewport의 가로 넘침을 확인했습니다. 상세 진단은 검증 기록을 참조하세요. - -테스트 Depth는 **수작업 가상 깊이**이며 AI 추정·실측 결과가 아닙니다. 보이지 않는 측면을 복원하지 않으므로 큰 이동에서는 사진이 늘어질 수 있습니다. 진단 좌표는 깊이 데이터와 카메라의 투영값으로, GPU 삼각형 보간과 작은 차이가 있을 수 있으며 화면 특징점 추적값은 아닙니다. - -기존 VideoTexture와 flat/static depth 경로는 유지했습니다. 실제 영상 파일의 재생·loop, 실기기 gyro 및 60fps 성능 측정은 이번 브라우저 검증에서 수행하지 않았습니다. 요청 경쟁·미디어 수명·센서 경로는 코드 검토했습니다. - -AI 추정은 `AiDepthProvider`와 별도 module worker로 연결했습니다. Depth Anything V2 Small의 상대 깊이는 실제 측정값이 아니며, 보이지 않는 측면이나 가려진 영역을 복원하지 않습니다. 실시간 영상 depth 추정과 완전한 3D 복원은 현재 범위가 아닙니다. - - - - - - diff --git a/RELEASE-MANIFEST.json b/RELEASE-MANIFEST.json new file mode 100644 index 0000000..558d246 --- /dev/null +++ b/RELEASE-MANIFEST.json @@ -0,0 +1,252 @@ +{ + "source_commit": "7d82e3b1a9f083376bfd0b916568b1472dcb7f84", + "analytics_enabled": true, + "restorable_duplicate_assets": { + "public/THIRD-PARTY-NOTICES.txt": "dist/THIRD-PARTY-NOTICES.txt", + "public/fonts/BMKkubulim.woff": "dist/fonts/BMKkubulim.woff", + "public/licenses/Threejs-MIT.txt": "dist/licenses/Threejs-MIT.txt", + "public/licenses/HuggingFace-Jinja-MIT.txt": "dist/licenses/HuggingFace-Jinja-MIT.txt", + "public/licenses/Driverjs-MIT.txt": "dist/licenses/Driverjs-MIT.txt", + "public/licenses/ONNX-Runtime-ThirdPartyNotices.txt": "dist/licenses/ONNX-Runtime-ThirdPartyNotices.txt", + "public/licenses/Apache-2.0.txt": "dist/licenses/Apache-2.0.txt", + "public/licenses/ONNX-Runtime-MIT.txt": "dist/licenses/ONNX-Runtime-MIT.txt", + "public/licenses/BMKkubulim-OFL.txt": "dist/licenses/BMKkubulim-OFL.txt", + "public/assets/samples/dog3.jpg": "dist/assets/samples/dog3.jpg", + "public/assets/samples/dog5.jpg": "dist/assets/samples/dog5.jpg", + "public/assets/samples/dog2.jpg": "dist/assets/samples/dog2.jpg", + "public/assets/samples/dog4.jpg": "dist/assets/samples/dog4.jpg", + "public/assets/samples/dog1.jpg": "dist/assets/samples/dog1.jpg", + "public/assets/window/grandma-house-surround.glb": "dist/assets/window/grandma-house-surround.glb", + "public/assets/window/grandma-wood-sash.glb": "dist/assets/window/grandma-wood-sash.glb", + "public/models/u2netp/LICENSES.txt": "dist/models/u2netp/LICENSES.txt", + "public/models/u2netp/manifest.json": "dist/models/u2netp/manifest.json", + "public/models/u2netp/model.onnx": "dist/models/u2netp/model.onnx", + "docs/qa-five-photos/reference2.png": "dist/assets/reference2-6y7JVIce.png", + "docs/qa-five-photos/reference1.png": "dist/assets/reference1-D4rK2azX.png" + }, + "files": { + ".node-version": "7e8a2fa94951112b894a3dbe3d05efef5e9263741fa49125f0a70f40fedab4cc", + ".gitignore": "e46e6a30de1c59f7c0dc7ffdd0b9c9188abfe37552e4b4bd5d4ff7e6bc4085bb", + "package.json": "ec1279ed591a049867763577a6eae4340dc85d639148d7500349ea280de5c21b", + "vite.config.ts": "24ea3953aff59683c53aced4b2e11909f27e5ef035586535f79fcb345ac6e886", + "index.html": "319cc210172cd81a8cd9544e5eb49847702dd7e9723e1b565cf07844e1420e05", + "tsconfig.json": "b41e76ea78ccc37d3b6e8370b80bb46b29227698a9bfed3efb3ca0fd97a696b4", + "package-lock.json": "43c0aa16b055aa974b28a55322b0e7164a55b9bb3e71c6cbae9b7604356175fc", + "docs/arrival-backend-operations.md": "17c3b79bc00dcb9a27abd02a7f65f4ae8e3f74122b46acb3ecfadfa657cf2f25", + "scripts/test-small-depth-ui.mjs": "70819a680e22974d824f7cf373c70e730e1bae0f340cd2f6ec4b17e631e845a2", + "scripts/test-render-demand-integration.mjs": "6165b4050ba9855e121b985800842be998a4446656fed8aeba73ed7f9492d1fc", + "scripts/test-ui-font.mjs": "79e328ba89aa55de50213b63a2abf36376341f475dd1b9b1814efd03f198f880", + "scripts/test-analytics-tracker.mjs": "501cf258206da83aabe14a56da2ffeaa0870b62f8c432d96e1dbf397ba2ad067", + "scripts/test-ai-depth-inference.mjs": "b2b588ff6b99b6432103344cf484af9810825f825dc74fc465fade46bc0a2abd", + "scripts/test-mesh-refraction.mjs": "7dede3518905823725062bd92c8b51e541d5a26b329e17d080980de16d465a48", + "scripts/test-arrival-count.mjs": "3fa213e578310a772c7de1b1334d39fde69707e356f6a55a0331111a0a609551", + "scripts/ai-depth-smoke.mjs": "1b3e91a3eb6bafbfcdbed6b5c9012c13a782b2c75ab134617c63d81af85941c5", + "scripts/test-peeking-grid.mjs": "ce5dd40612c1947cce53fe1672fb07d17288cd2981a910d4eb66816a94522382", + "scripts/test-pet-name.mjs": "fca07a2953ccb8116e4c84fbd17985dff772e62de8252322ebed452376ac9dd0", + "scripts/test-cutout-provider.mjs": "43e82268242a3ae15bb3bd245253d2009712c34570cc11d05566e636fde17dbf", + "scripts/test-house-surround.mjs": "8a559fc9d50bdf641cdf0dbca6356bcbc66fab1326bca2b04bfb326184d6c08f", + "scripts/test-export-ui.mjs": "3f0d5fb8208ffaeb780e39541377db9438a07748dc6d079e219d87bc43540028", + "scripts/test-arrival-db.mjs": "c13f6c7596c09297591ddb5411be2196ea93b4d09d056d28454350383226d78b", + "scripts/test-reveal-intersections.mjs": "dcbc84b40fe5d206ed6c3a48866664085e288f5a40544a93e3aadc37114b2620", + "scripts/test-portrait-framing.mjs": "e31ab043a8dc7c80fdc52888215cfaebdf02eb2fe5ff558f534a876c3dce1e07", + "scripts/test-image-paste.mjs": "c10b7a6e45b7e43384adb5ffef3ae64c10f66613ee76fbe9c5b167e66241e5d1", + "scripts/test-scene-hints.mjs": "f2398d0a2338002b75cbd019891a6da593b701d1708c1522eb126dfb01d834db", + "scripts/test-first-guide.mjs": "0219b92eb6b8842cfd7245c59310ca03c8ecd663b1decc672a8623e961e744c4", + "scripts/test-entry-notices.mjs": "2aa847ce95c26763094d08d812795273c74d2a9db4116e7faa9270f73400887c", + "scripts/test-peeking-ui.mjs": "1ed62dc54a3436331ac61034e03d7ff543d2458ea4b5a5c7c21b2a22fa9c4e75", + "scripts/test-window-reveal-sliding.mjs": "6f27adfa84597e1c0fbdc3db81cd77663324ce02a6698f83915435ca35523474", + "scripts/test-gyro-controller.mjs": "808011e15c2c525803e0ed3610b861d725ea24820468fe679227b357c26d8b57", + "scripts/test-depth-refraction.mjs": "ba6e99bba405dd568a09ad0648dcde244c0d20f64896a53f9fb6086e17ccfa5b", + "scripts/test-window-finish.mjs": "d9474e7f936c5c355bcf8ac9b580848b32fd182d5829ce8bc29bd46ec050db46", + "scripts/test-mobile-gyro-ui.mjs": "1ab9be89f49b16a9bf5a679296c919856780437910e4465fa9e516b1aab7cc74", + "scripts/test-region-axis-split.mjs": "727e2cfa4e733a03b4a1bc49b5f5eb444977736f079eea17799760996c2b8273", + "scripts/test-experimental-courtyard.mjs": "974c2d3efdfda92268df2890d35e0776b395ac9433a138d272187b84cfe6ac4a", + "scripts/test-room-peek.mjs": "8b98f9b76394760a719eb9dcfb9e2b507ea45141357bb9655121f9c851665d90", + "scripts/test-arrival-integration.mjs": "0746e2b555c17e707bc727e8fb56952faccd962e22d4f24e79ca0dcb76d4de2c", + "scripts/test-experience-ui.mjs": "283a888859e7fc4148980e79ef075324bd2fdc4f6a4e724a479b6b136a95e5c2", + "scripts/profile-photo-working-image.mjs": "6c4c07ce6a7ffe2076f891460bce23a0d8c2174ac649d758cfc9647d276c5a0a", + "scripts/test-region-atlas-dark-sampling.mjs": "e7b1f4a41f5c4dc426e40f1c6d3a3ab6f6fec414f879d79c91496e2282bb7050", + "scripts/test-camera-history.mjs": "be883741e70f9c69033bf3774d3edea2c6f4a280014908e7d1c4f8058b51e1e9", + "scripts/test-pocket-lining-clearance.mjs": "fa9afe45a83718050469a5c43aefbddfe90aaaf42464e9d0d7384ae6ef99d686", + "scripts/diagnose-stock-transmission.mjs": "1e5a4881d159a13cfac1e65fe663e526e756e985846666a2fcb2e418d7c90c4b", + "scripts/test-camera-envelope.mjs": "39bff56c2ee597538d8d34a8a647971554f7503bac73e28760b8f8ab108c52df", + "scripts/test-glass-controls.mjs": "322aab08624d63bad410962813e80007f98beb53df758c8f0b699f1538f7c46f", + "scripts/test-scene-zoom-materials.mjs": "9f3a84e8d5161dedbeb7d87d3a48ca448544b3bb52267f77c7a131b74e0dab4e", + "scripts/test-window-reveal-coverage.mjs": "8b1bdbbfa290a58e3d55f48049873dadddff0f055970552a97b53ea8c48376ab", + "scripts/test-peeking-composition.mjs": "da685dcfe486c7d5164226b18da08c5dbc1818a246de176fd5d4cd1d8460e6b5", + "scripts/test-peeking-integration.mjs": "dd54a27af0cb5a406c1b28b320e68077f0e9d1bce5887787ac0fd99cfab05178", + "scripts/test-cutout-mask.mjs": "2f6a23a7f80ab4aad0358a91b773e5d1b7f91d78f722a88a29d368f6b499740c", + "scripts/test-peeking-optics.mjs": "75fb8fc8ecbd569cacf9d219bd5cea882db141ae2ef43d1db33eb75fda7fc257", + "scripts/test-default-renderer.mjs": "bb2dbfd648f397014ac6af99aabe7b51680bed4bd1cad0700da594fc0297172e", + "scripts/test-scene-anchor.mjs": "93fe34a1d2a6f5cdc68e5e9b0082250406d844b4aa1fc4e1541bb61117416598", + "scripts/test-house-lighting.mjs": "26448032b216816211ab9988d9dc7c44db014c2fb88d991776703527eb5b9458", + "scripts/test-room-corner.mjs": "5721a55e233e3322501b3d5f9101060b0d8cc16867fb8e8308ef779ae01e211c", + "scripts/test-depth-evidence.mjs": "6ed26378435c1364376800226d199c5071e163e0a00a3a7f9a15f5bb2009a0e2", + "scripts/test-camera-composition.mjs": "de37bff5f51202d4301146f5ca3e421752c8c362be144adbb4d7db82bf3731de", + "scripts/test-car-journey.mjs": "a768a6d59cf7222a6f7abc57fa1485477fb31110809ff360e555b4b8a8b3ae19", + "scripts/test-render-recovery.mjs": "ed2387c8f688b15fc0255752c81c8c6fd05ed162727cd4f8273d05a6b28b7ae3", + "scripts/test-render-demand.mjs": "57a7a91723dac1f2967935c2e6ac2b423f90af520edf738eeeae35443c4c5268", + "scripts/test-blender-window-frame.mjs": "ebc4d2b40c553d970e4660ee084955f46f32af2291f5316c470ee0d68aeaa9a7", + "scripts/test-original-photo-only.mjs": "4ae95f68c87913b3fd760b2bc3299eaf8c0197c4edd2c4314a00dd5791cd548f", + "scripts/test-photo-working-image.mjs": "24036435b1cce57b28114a2dcbea134dfb04dddbbc3d5626e00593e6bdc9adbe", + "scripts/check-sites-build.mjs": "14656673a8661b4dc0a9bf5204cb0daca56229375229cea47c1b15177d506b8e", + "scripts/test-wall-peek-safety.mjs": "e51b34e0575d4c1f9abc11b45ff2624732edb5215e9f60dc738c1228f0989ff9", + "scripts/test-arrival-operations.mjs": "bac07b08d7736fc3aa488280a760ca8ca5d8fc58ba7e4c9f0c855fdca5f81d82", + "scripts/test-mosaic-depth-distance.mjs": "c8903e4e5abf6f7d74dd0152ddfae4a91e92d564aa276dc45c33d4c144acdb1b", + "scripts/test-surface-reflection.mjs": "63186186728847da329a8c42513e9cd6bf8ed9deaa59b4e56e72228871a48e33", + "scripts/test-arrival-api.mjs": "484724c5edb53f6c0c20ab5d0cb55d479562b4385e5831e920fb8716d3a3c004", + "scripts/test-cutout-preparation.mjs": "5dd08d221da4f1b5607bf2ccdfcacfe9d8328f5afd55c7f3301b13bd7fbaae47", + "scripts/test-mesh-refraction-material.mjs": "bca9c56de21ca6ac9d35bbb8e2e0e6499e9c361b391057efc6b77b15f78f5c91", + "scripts/test-photo-booth-ui.mjs": "05dbf52de72cec77f9527986f775dd8bbb38738f31c5cd7697f1134929e754e4", + "scripts/test-sample-loading.mjs": "26e9801c1358d8ce1db41b83bb5f3888a8598fd0f23aff283c30971d4a51d687", + "scripts/test-cutout-worker.mjs": "2a9dfe1c7de15aeb8ef7965a2ac483356fdc0d9799cc3329718c6bb75d1143b7", + "scripts/test-web-glass-comparison.mjs": "21b6928306134270baa26fe61c14bdc86a8899792f875a95db03761d97992d70", + "scripts/create-sample-depth.ps1": "cf1bff3f9d2f375c4f6b68810419d7454e564e5ef535cc03bcbf9adf535f3bc4", + "scripts/test-media-retry.mjs": "e3a5c54e74587eed6f7abd12af3276becd7aee7e4af030d878e2d5f169377484", + "scripts/test-analytics-transport.mjs": "aa1954ff5c73c5b6449fe86146307fe1c02b6d8555c92a228c6594575ecd5be7", + "scripts/test-mosaic-continuity.mjs": "d1357185518f670969933ff6d4b6212aca14705b2d846c88492b514e57d1873b", + "scripts/test-window-slide-controller.mjs": "d7e523da1ea87e9ac05eb90571327705a7ecb73087e75b60b73ddb9efac45bcd", + "scripts/create-fixtures.ps1": "3b4cf539f2e38b6e7b66b8dea74f1ce49308762e8ac2946d462c4c7fba8d9a7d", + "scripts/test-photo-metadata.mjs": "a01df0ffe8b1b5037722bd611dabf495b83176859d004e49c617786d557f782e", + "scripts/test-sliding-window-integration.mjs": "8c2d7ed068ff81f12b6b083e1847e5e4179e9f27ac060ec5923328204a4f4d2f", + "scripts/test-cutout-model.mjs": "1a2773517c40a40213d105d2a1ea9204e982e3c58245de0294314b4d8d0d5a58", + "scripts/test-media-working-image.mjs": "6afbec8379fe78bc804c5a6fa89074dee52e10428491908553e6b20937a10f39", + "scripts/test-tilt-integration.mjs": "1e795b668ed3f7155be0eb0dfb81f31dfd0107618c0aea183a0df614e0c97c3e", + "scripts/test-analytics-identity.mjs": "6092f5470bebf9ba20addfaafab9f3d1afe8c480169b822a3b5e35139d6fd963", + "scripts/test-journey-copy.mjs": "8c43709d317946fd3b56471fde2ff04ecbb619700d15d4a836acc65ef1936782", + "scripts/test-scene-gestures.mjs": "44562f453f488fefed36c6a57b70e57e0c0fad2b19c5852f1a95b5be1b21fb18", + "scripts/test-scene-export.mjs": "04e0369a708a47b705da60aa2265124f86948e92fa68ef9874f63277ada9ec85", + "deploy/arrival.env.example": "2b1a719560c2c8ca6ed1ae230bc467121d9e66ec67ff68c08f5f4d384da1c9c5", + "deploy/behind-glass.service.example": "091bb0f5a1af786ffbe95c44cc02cb9fccc195375498c4b9720bb65fe2fe41fe", + "deploy/README.md": "ab0ba976e4817a01a93b132a7e222469aca9dd17469c936c8eb13e00afe2aa3e", + "server/backup.mjs": "07677c4ec5e6b0607a377a58f39b81a5556fefe0e24b3c9c3aa33b66abcf1945", + "server/db.mjs": "258bbb7d7c615b8670f4b9f365aa68959057cc039ac5bfdc7f7370b32cb971c3", + "server/app.mjs": "22515f362223352a35fca636c80fe2112a1cdd3df6d4b2d5f82f86794fe2190d", + "server/config.mjs": "448e1ee5aa6bee188651fa2e6a76aa0c4801c04a99f1c6a0d909e486dd159ae6", + "server/metrics.mjs": "201cbdd47183ae2974943a459a7a1bb9eeb52b58facd1744f8074e39d5b93d0c", + "server/index.mjs": "2256dbb3dd1313e5e903e78d723629fdf3b6650e1f5801730f554eb9935f2bf2", + "dist/index.html": "b7fd8d6b089b2a26cb2a2e55c1f4f91b44060270923088c873423f5b8d3b75fb", + "dist/THIRD-PARTY-NOTICES.txt": "363444be9a1608577d2899b911c8908818bc64308e343e598503e7e17e7a4441", + "src/style.css": "971484e1a92c5253e7fcaea59d4ffc3253d935f36b4c0c94abd32a69fb814af4", + "src/main.ts": "c37e18efd3ee73ff6aca83a4297d42539954fc37e6c102b56771152ab2fc813e", + "src/vite-env.d.ts": "65996936fbb042915f7b74a200fcdde7e410f32a669b1ab9597cfaa4b0faddb5", + "scripts/support/render-corner-preview.py": "3b562334104ce0309bd60663d4e5cb0c22fca56f87cc8be56da22890135edd79", + "scripts/support/render-wall-peek-preview.py": "3fbb7fe0ef8c2cf593ee529cdde0498dbb2d6a63479ac8c73272c62edd69c41a", + "scripts/support/photo-fixtures.py": "6795db053051d283eacd1c041b532df74e03203fa1c2489b7c84daa3900945be", + "scripts/support/load-frame-geometry.mjs": "4ba4308e4acb084c9d902940fe91ae70fd483ea00979c956019e596b47d0ccc8", + "scripts/support/load-typescript.mjs": "6006b8c6b03088fff181f410e25b4e9c435742c76edd97a09f9cc72a062c1ada", + "scripts/support/compile-refraction-shaders.py": "bc0d541e12542d766779c4bc80bb6f064451e94add314b96891f25ede369acf9", + "scripts/support/mesh-refraction-reference.mjs": "1f2fbbc3eb366a765310d102e05942a7e2fd44ddfe7cf52cb1ad699ed2e043a0", + "scripts/support/export-wall-peek-preview.mjs": "53a93de16e8fb53a8e4857b2e6269cf3ddd42a9f36e695c32e15ed4ab62c8781", + "scripts/support/capture-courtyard-shaders.mjs": "e48b4644adab246a504a7c88ca9cf9a2658bdf5fb0cbc792bb831390062c191f", + "scripts/support/capture-refraction-shaders.mjs": "b534c8ce32b04aed1b2b9f7e35997b8d3b7d7b509726436d7201aa684a15abba", + "scripts/support/check-refraction-float32.mjs": "783fce5a26926801b490b468e3276f103f17f4a7036a020718b89ad62000319e", + "scripts/support/export-corner-preview.mjs": "dd86065eee645b0411ea3adfb5c04ec9a8b840136be720763c9dff8ca5f8a6a8", + "tests/fixtures/landscape.png": "b21cd0cea273d266d71b4c596d207ef859161c61eb15e7d3570c4d1445ba1ff0", + "tests/fixtures/portrait.png": "7ea3ad8bf3b7758745fbc3f8ef87ae8b156f3db38443ac3bab8b7c59d8c8f9a9", + "server/migrations/001-initial.sql": "6c33866ec2d5a5d02f85f0df17cd83ade64444efef21859da66626c4c5284967", + "dist/assets/cutout.worker-D417j0Nw.js": "c064073206e1c00b85b1fa24d2ce1cf4f4da69473ce1abcdc9c81ffa8e44b6a0", + "dist/assets/index-CAEr_JzP.css": "7130f48d6baf3539ff72901335aa071ed2fda81c12d290e031ca214b336405d5", + "dist/assets/reference2-6y7JVIce.png": "49253f44fb9af431e4a989121d77ff0547d0d5d1d19eb3193e59f9b205e166e7", + "dist/assets/reference1-D4rK2azX.png": "b49b9b98bcf6021ffac1deb42b01a3ac71bb9d785386564eaa6b07e45a73eda1", + "dist/assets/reference1-BphJMCNh.js": "daad4d741dfc516676c3a5b3a0ae07bb7f30085b66f2b67ba042852859316839", + "dist/assets/aiDepth.worker-BZp93h00.js": "717267733e29439f480b48cb809a5017074d7177ae6f65c4e009dfb9376e6542", + "dist/assets/reference2-DHNjbprc.js": "35404847b61cb2c846176741412a1599cdd740eda5cdf35a5501ee848191d15e", + "dist/assets/index-BYcEjj7E.js": "e11eacbe19cdd306adf68c4223a3f9b9b99cb874822bce6a79bc23a75131eb0a", + "dist/assets/CutoutPreparation-9rCu4swh.js": "26cce73c418bf163a42d2e27b94b10556121503a923f796a77e1c3cfd0a4a1ba", + "dist/assets/OriginalGlassRenderer-DLs_logl.js": "f584dc3549be15ccdd99218e23b83e97391abe8b11e2e683adb5b4a04632b0f5", + "dist/assets/PhysicalGlassComparison-B37yDBlH.js": "62f49bc47fa545d8e3783e93c721a9b73b49c596978fcffb8049b36b9e455667", + "dist/fonts/BMKkubulim.woff": "dc1e920bfdc5fd3b90189687e3f1ec3335e7a009015bca11d5b2348c4f4257ec", + "dist/licenses/Threejs-MIT.txt": "4c40a1ef62450b857c3b2aaf294936304cd552d965fbcd9d32d4c5bcf4ba4454", + "dist/licenses/HuggingFace-Jinja-MIT.txt": "d6e7b19451c1b3d1d66353bb4b1274138953b3bfd9ae60c56e77b1f548796982", + "dist/licenses/Driverjs-MIT.txt": "ec3ce3a08736fefd6a03a6d5b52b0705e6919fe06de9d7bd3fb63dcfb492d76d", + "dist/licenses/ONNX-Runtime-ThirdPartyNotices.txt": "143764b952fdb1a7c69ce653bfba74a7744d6a8a573bfb73e235fba356c83de3", + "dist/licenses/Apache-2.0.txt": "cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30", + "dist/licenses/ONNX-Runtime-MIT.txt": "2f07c72751aed99790b8a4869cf2311df85a860b22ded05fa22803587a48922c", + "dist/licenses/BMKkubulim-OFL.txt": "169d46b6a1c2f6911e4ab47a02429712fb13056d113b28641bfd30f1890861a1", + "dist/assets/samples/dog3.jpg": "bf28194cd5fc710daad57de5ffed26debc82acc29dafebae35be391302899351", + "dist/assets/samples/dog5.jpg": "96aaf29ee2b7e2674a4010c48c954f22ec8a7fd015a810238836e0de93d12787", + "dist/assets/samples/dog2.jpg": "3ce13e277857a170c54742f0142e88d64086d7aa4297b6d082979d903d68c535", + "dist/assets/samples/dog4.jpg": "fbeb1b3784d30b7e124048d5dc842280142cbd0ec190ca9a65e6c9dd2eb64a7e", + "dist/assets/samples/dog1.jpg": "0fd66828d61bbe523507965ec78924be13c4768059a5175f6bbf384cf11386c2", + "dist/assets/window/grandma-house-surround.glb": "3008b5a3af10b7987b335b00b92eb28c34ca585a7c36f9b33ea9e1c63fb10661", + "dist/assets/window/grandma-wood-sash.glb": "a524a0cacf180ded8e093e18350909da3c615a5335c45851c697113ad3b0b84c", + "dist/models/u2netp/LICENSES.txt": "8b5a8937086e2b62183d6bd45c475a0b335537ead8e785286632e71d33825725", + "dist/models/u2netp/manifest.json": "b53e25a84ff25ec51de295067772a15494c9267e7233ec7ce9b26ce1c8e1a2a4", + "dist/models/u2netp/model.onnx": "309c8469258dda742793dce0ebea8e6dd393174f89934733ecc8b14c76f4ddd8", + "src/cutout/cutout.worker.ts": "77e9c152077ca62848e705a4cff2cba2908fbf86857bd0a384374105a747c0df", + "src/cutout/CutoutPreparation.ts": "c348268e58fcc1564db390435add9fc891e2e1a63f249505abba99ffbf62eaf8", + "src/cutout/types.ts": "b67b05aef29185376d6c29ebe97ef2353ed0c32539dbc6627dc00da0e74d1464", + "src/cutout/CutoutMask.ts": "092d72cf2ddc4d9ae9417210221a0a05e97ffacec728e5f6a293f2d55518da14", + "src/cutout/U2NetPreprocess.ts": "43884223419d87b28dafdce66e28256e5c970a8c80e3ba55a5d4b7dff7963440", + "src/cutout/CutoutProvider.ts": "d6783a4cc4480e3d49ae9f90cae6c961d0f7119138339b2b0d7ccd8085166845", + "src/depth/StaticDepthProvider.ts": "87aeda3148edf695babccf1bdf3af7f4487332f7aea5ea6a46bd428b691a0036", + "src/depth/DepthInspection.ts": "52e4a88bf41046ad4cfe6dc23c0ce951ce7e0be92e80d581257ad23e787dc2b5", + "src/depth/DepthMapLoader.ts": "ceb0edff78bf39de079174eb3cba6798238f003c4710c8aa4d948ac976ad8a6d", + "src/depth/AiDepthProvider.ts": "e37fee06480b309432faa318702ef6815bfc3c3f3709afdd5fdedb80e14c6fd7", + "src/depth/DepthDebug.ts": "841343e79fcb0e96992a3ac7b60e6c6830c11db7a9715d7eb8d3eef1c070e648", + "src/depth/DepthProcessor.ts": "53ce822e344f4a853ca17782d81408091aa5fd2004c63fe69a4277fcb9c84ffd", + "src/depth/aiDepth.worker.ts": "afa2e42a88c1806264618ab603035ab2484dc96f64559ae7c4ef390988c9273f", + "src/state/PetName.ts": "b3377ed0bf099f8c531ce5ddce94a72a7b8ceb584518b7b239288621bfee830f", + "src/constants/depth.ts": "085e6dfe3a5a502be05649c02cc970b12268eb369b75cd8322f973877d187d93", + "src/constants/glass.ts": "a9d6b8ee9aa568eb779fd8d7fe420711b1c993ccceff7f93419fded80cca8b66", + "src/input/GyroController.ts": "456be70412a11415ebff570d7e7bbebf0e9967c1b5b1534ba3cc92f285d6cd0f", + "src/input/PhotoSnapshot.ts": "094df411553cff6c62bee313fc8032ab0c4cb9a9c18089a6651278a9a372b790", + "src/input/ImagePaste.ts": "04113265e8b0b6d13e28318b0b2c9ccf02df8e7b1af03360ae8a7001c094b75e", + "src/input/WindowSlideController.ts": "831c8c4154557e4baf30bd9563e6eb163ccd287849b0f1a163a5932c1a78261d", + "src/input/CameraController.ts": "b9fc7abc9441dc0af937eec68d42db517001709f1e8b3c877fea7713354634f6", + "src/input/CameraComposition.ts": "9a80d406dcaf0b120a42e1f1c8dd507553d492d28e1f5f97b3118e13d88d5365", + "src/input/PhotoMetadata.ts": "e815498f65a5f23978c9c734d5364bfeaf411cbf47c92f4131238e23455c4efb", + "src/input/SceneZoomController.ts": "e548ff6fb95014cfaf219e170dc740e6bbcbff840c3cd457ecbe65a9f840796d", + "src/input/PointerController.ts": "2abfc465cd9d7012094815e07d6f5fe9b7c1e1a7709084817b9cb0ecc1f27ab7", + "src/input/MediaLoader.ts": "bf4d191ee3fcd116be943c6b6c41f1979f9cbbf0dc95a5d0b03afaa7b4a0f21e", + "src/input/WorkingPhotoImage.ts": "e700686a95985102281e8847beb426024e320df54100f3f2003d2e59251cb11f", + "src/shaders/region-palette.frag": "414d12582ab598c38f1b431056117125eb05c46706d834dc2bde46a8f7f3302c", + "src/shaders/petDepth.vert": "00f653dcec9d9435a5ee630b50f4ab3a568d255f0bafe74f290be5b0266daf48", + "src/shaders/glassScreen.vert": "8f2938072df24f26d087484ff3d2f2e8affb7fd40dc9c68bbd7f4690c4c7245f", + "src/shaders/petDepth.frag": "c1c6b07294adf7a6504a4a9a3edfd26cbc0199946774d988107173d8e453e52d", + "src/shaders/reeded.frag": "7956af6774777e3ef97e8e07d485a91ff5c5a2da53a8384c83d03fed4565a3e3", + "src/shaders/common.vert": "5a319aa462ca313decd834bc136835f78ed5e32d094b7343af7e8a3d3d12946c", + "src/shaders/frosted.frag": "7e4c66c9ed2dfffc49480d8ea0d93cbb409b46aa61fff637b793dda974cf15bc", + "src/shaders/region-history.frag": "44676af542f25ae786c34a86ca85427a910509b34460c57cb48f5f2c348dce34", + "src/shaders/mosaic.frag": "02b533a829508e400da4e4cebc74a5540c204745e3fa250a69366199ba0f3175", + "src/objects/ExperimentalCourtyard.ts": "9662075ea4e9a3875d754a05105f27254bc545477083e95abc53496c5fdbcdf0", + "src/objects/WindowFinish.ts": "b0bae9fb033cbe413ff7198000814a35363dfbd0b99eea04f0f025dc55fd37e3", + "src/objects/PetDepthMesh.ts": "6199a07a3ce585a2f8392ce67937710a44b5a2b6a8b10789e7dbe8052ebb462b", + "src/objects/BlenderHouseSurround.ts": "71d05c3782183152ebb4e271fa44ebc41586cea8a525c4ef23cd965a094d925a", + "src/objects/PeekingComposition.ts": "c47ebd0d588a12134140b5ff66a8bfcaa019dba19d6418d321367a42fe5f85c0", + "src/objects/RoomComposition.ts": "19f613777f47728871cd9df439b306ebce0e39c8dcff93b82d92ab9a55902872", + "src/objects/PeekingDoorGrid.ts": "734a70cc0177debd1dbe2b7b9cc8293c9ed0c5ccab50f2fd7b5c707519d573a6", + "src/objects/WindowReveal.ts": "0f9acb54dfc900a5e60bbc74d6fc64b1b447340a1732c4eda8e112ac4849ead9", + "src/objects/BlenderWindowFrame.ts": "ea13f446b079b04d17a6fbf61e53dee5fd0f094d97232e20f23bde843e2daa5e", + "src/analytics/ArrivalTracker.ts": "924cfc3064bb1252a2034ec795c5ad121fa03462666911ba2a1a996d1229ddef", + "src/analytics/Identity.ts": "2be8081d5b94d3a796857616793252b438b0daf660132cd3a36934e27bbbf10b", + "src/analytics/Transport.ts": "44db06c4014a3666d757bc4751ec4051a61f722fa824d0d7c60747b7212fb587", + "src/types/depth.ts": "0e30ce168d303cb24120312809a87a156a40331b90690ff490d0f2a85e15b987", + "src/types/photo.ts": "2db604c87ee26b2760e05f912f5e3772561fb007be7dde88dc9bd9ada258df96", + "src/rendering/PhysicalGlassComparison.ts": "24517dfe84eb56bbf8955041526907c828452bfcd05aef90338e01b5a6cea1cd", + "src/rendering/SceneExport.ts": "9d18b4d4c800bd4d12611ec46bc6b4107c1a3ecad3b8924947471312356b804d", + "src/rendering/MeshRefraction.ts": "d5d1506fd5fc66b133fc50ce97e1117f74f463450122fb2f73709e3ac92cf553", + "src/rendering/OriginalGlassRenderer.ts": "23aba0fe89b987cf1795b885ca2832a45661d237d4e9f88593c68abdedea9b08", + "src/rendering/ExportPixels.ts": "51cde0a03f259cb217211a95a3fe7e4090e4f0dca38cb440adea21874620892d", + "src/rendering/ComparisonLayout.ts": "54337aee7476ecfd5f534d8da3dcbae1a72c07de0b348b698ba9c91d7a46ddd1", + "src/rendering/RenderDemand.ts": "d0f08678ac9dc37076e378f22242be68ac1a08e09e9b11e52c08a4d4e17d9a19", + "src/rendering/PatternedGlassGeometry.ts": "4e42ecd1622be62e2179aae6c2695dacd934e0cfa14a3eb9de6002ec896931be", + "src/rendering/MeshGlassRenderer.ts": "315090edd7670bf453943d98b0bc405db3b8c7fb9a553bdcdda83368469a357f", + "src/rendering/ComparisonMetrics.ts": "b3839dd96d3a7701c6261dfb77baf442c7f299cf7e3706696dd22a997e6edb76", + "src/ui/ExportUI.ts": "1f3dfc40ac64e36425b2c9b3f6c6f5e8b095b3a3998395bd3467e3a6031866af", + "src/ui/PeekingExperimentUI.ts": "434ba00f64187f3b4da874130f812c004a2cc75be28a4f702291c612ceb13e94", + "src/ui/SceneHints.ts": "44ad4fb1133583ff574eb5b6ab0135ba3822fd4dfc4bc92136f20ad09fb5fd82", + "src/ui/EntryNotices.ts": "ababe4b8ffa25e0a981521c5370eb75a680b5b6d6edaab4fcc2e1df579af4435", + "src/ui/RenderRecovery.ts": "582ba3bf3856f3aac285335297e7d1fa8c0f8c93c9a7449e9bb39bd8c6214462", + "src/ui/ExperienceUI.ts": "3ddffc88ec7b2084b45adfb5e208def5d1d0c95afee3be05f546e2d13814883a", + "src/ui/PhotoBoothUI.ts": "39f6ce557b3c9de581f58fb9c7c098bbaf9cee829fc840bef7923633601b1cc2", + "src/ui/peeking-experiment.css": "7c098babbe0e0d6141e3049a4e089e7cfcd6b8a0472b26eeb7153276553c4bcb", + "src/ui/ArrivalCount.ts": "8629fed45610eb22f4537c7c1cecf0d935b6458f123cad451152617cd6abfdb0", + "src/ui/FirstGuide.ts": "f132f3504feebd8ee0539e7d6929f98b28815ca0edbd7f264d9d5cb1881871fc", + "src/ui/themes.ts": "5ce403537c6f99a35c1982c61226494d957b0642021405da0a922398177fde48", + "src/ui/MobileDevice.ts": "e3f977cd5d0139f5c581a1cf9c0c60e0cc6dd242373dd27936d1f504f780688f", + "README-서버실행.md": "713e1657a2cfbe49d0787ba90d211b3776604e9403dbb483ee9db48fcee60aac", + "scripts/restore-source-assets.mjs": "e8613c9414f1257ace9d08d5fcbda38519a8e5239d493974a70177d45e942a3b" + } +} \ No newline at end of file diff --git a/deploy/README.md b/deploy/README.md new file mode 100644 index 0000000..5096a58 --- /dev/null +++ b/deploy/README.md @@ -0,0 +1,17 @@ +# Future server configuration examples + +These files are templates only. No service, account, directory outside the workspace, +firewall, proxy, DNS, or production configuration has been created or changed. + +1. Review the target OS/CPU and install the pinned Node 24 runtime. +2. Install source dependencies using the lockfile and build with `npm run build:server`. +3. Choose an existing or separately approved service account and private durable data directory. +4. Adapt `arrival.env.example`; production origin must be the approved real HTTPS origin. +5. Adapt `behind-glass.service.example` only if systemd is the approved process manager. + Check the actual Node executable path; `/usr/bin/node` is only an example. +6. Configure HTTPS and access controls separately after approval. Do not publish the existing + private sample/reference images more broadly than their approved owner-only scope. +7. Follow `docs/arrival-backend-operations.md` for backup, restore, metrics, and migration checks. + +The DB must remain outside source, build, and public roots. Do not package, upload, +or commit a live database, WAL/SHM, backups, credentials, or node_modules. diff --git a/deploy/arrival.env.example b/deploy/arrival.env.example new file mode 100644 index 0000000..b51e17b --- /dev/null +++ b/deploy/arrival.env.example @@ -0,0 +1,7 @@ +# Example only. Do not place the active environment file in dist/public. +# Replace paths and origin after the target server is reviewed. +NODE_ENV=production +HOST=127.0.0.1 +PORT=3000 +PUBLIC_ORIGIN=https://your-approved-host.example +DB_PATH=/var/lib/behind-glass/analytics.sqlite diff --git a/deploy/behind-glass.service.example b/deploy/behind-glass.service.example new file mode 100644 index 0000000..fccbe43 --- /dev/null +++ b/deploy/behind-glass.service.example @@ -0,0 +1,20 @@ +# Uninstalled example for a future Linux/systemd server. +# Confirm Node path, service account, directories, and permissions before use. +# Build with npm run build:server before starting this unit. +[Unit] +Description=Behind Glass static app and arrival API +After=network.target + +[Service] +Type=simple +User=behind-glass +Group=behind-glass +WorkingDirectory=/opt/behind-glass/current +EnvironmentFile=/etc/behind-glass/arrival.env +ExecStart=/usr/bin/node server/index.mjs +Restart=on-failure +RestartSec=5 +TimeoutStopSec=30 + +[Install] +WantedBy=multi-user.target diff --git a/dist/THIRD-PARTY-NOTICES.txt b/dist/THIRD-PARTY-NOTICES.txt index 85254c8..4734160 100644 --- a/dist/THIRD-PARTY-NOTICES.txt +++ b/dist/THIRD-PARTY-NOTICES.txt @@ -1,4 +1,4 @@ -Pet Behind Glass · AI depth third-party notices +Pet Behind Glass · third-party notices Depth Anything V2 Small Model: onnx-community/depth-anything-v2-small-ONNX @@ -10,8 +10,55 @@ The ONNX model weights are downloaded from Hugging Face by the browser when the AI depth feature is first used. They are not included in this application bundle. Transformers.js -Package: @huggingface/transformers 3.8.1 +Package: @huggingface/transformers 4.3.0 Project: https://github.com/huggingface/transformers.js License: Apache License 2.0 The full Apache License 2.0 text is provided in licenses/Apache-2.0.txt. + +배민 꾸불림체 / BM Kkubulim +Copyright: Woowa Brothers Corporation +Official font page: https://www.woowahan.com/fonts +Original font: https://woowahan-cdn.woowahan.com/static/fonts/BMKkubulim.otf?d35cc1bf +Official licensing notice: https://www.woowahan.com/fonts/license +License: SIL Open Font License 1.1 + +The complete font is self-hosted in fonts/BMKkubulim.woff. This is lossless WOFF +packaging of the official OTF, with all original font tables byte-preserved, +no subsetting, and no added WOFF metadata. The font is not sold separately. +The full copyright, reserved font names, intellectual-property notice and OFL +text are provided in licenses/BMKkubulim-OFL.txt. + +Three.js 0.169.0 +Project: https://github.com/mrdoob/three.js +License: MIT +Full copyright and license: licenses/Threejs-MIT.txt + +ONNX Runtime Web / Common +Project: https://github.com/microsoft/onnxruntime +Source revision recorded by the installed web runtime: 8d85527a0 +License: MIT, Copyright (c) Microsoft Corporation +Full license: licenses/ONNX-Runtime-MIT.txt +Upstream third-party notices: licenses/ONNX-Runtime-ThirdPartyNotices.txt +The upstream notice collection covers multiple build targets; inclusion here does +not mean every listed component is shipped in this browser build. + +Hugging Face Jinja 0.5.10 +Bundled by Transformers.js. License: MIT +Full copyright and license: licenses/HuggingFace-Jinja-MIT.txt + +Hugging Face Tokenizers 0.2.0 +Bundled by Transformers.js. License: Apache License 2.0 +Full license: licenses/Apache-2.0.txt + +Retained experimental U2Netp model / cutout resources +Model and source details, Apache-2.0 and rembg code MIT text: +models/u2netp/LICENSES.txt +The experiment is not exposed in the consumer settings. These notices are +retained because the resources remain in the application distribution. + +Driver.js 1.9.0 +Project: https://driverjs.com/ +Copyright (c) Kamran Ahmed +License: MIT +Full copyright and permission text: licenses/Driverjs-MIT.txt diff --git a/dist/assets/CutoutPreparation-9rCu4swh.js b/dist/assets/CutoutPreparation-9rCu4swh.js new file mode 100644 index 0000000..648b27e --- /dev/null +++ b/dist/assets/CutoutPreparation-9rCu4swh.js @@ -0,0 +1 @@ +import{t as e}from"./index-BYcEjj7E.js";function t(e,t,n){if(!Number.isInteger(t)||!Number.isInteger(n)||t<1||n<1||e.length!==t*n)throw Error(`누끼 크기를 읽지 못했어요. 다른 사진으로 다시 시도해 주세요.`);let r=t,i=n,a=0,o=0,s=0,c=0;for(let n=0;n=13){let e=n%t,c=Math.floor(n/t);r=Math.min(r,e),i=Math.min(i,c),a=Math.max(a,e+1),o=Math.max(o,c+1),s++}if(!s||c===e.length)throw Error(`강아지와 배경을 구분하지 못했어요. 다른 사진으로 다시 시도해 주세요.`);let l=new Uint8Array(e.length),u=new Int32Array(s),d=[];for(let r=0;r=t||d<0||d>=n)continue;let f=d*t+c;!l[f]&&e[f]>=13&&(l[f]=1,u[a++]=f)}}d.push(a)}let f=d.filter(e=>e>=s*.05).length,p=[];f>1&&p.push(`multiple-foreground`),s<16&&p.push(`tiny-foreground`);let m=Math.ceil(Math.max(t,n)*.01);return{bounds:{x0:Math.max(0,r-m),y0:Math.max(0,i-m),x1:Math.min(t,a+m),y1:Math.min(n,o+m)},largeComponentCount:f,warnings:p}}var n=class{worker=null;disposed=!1;pending=null;onStatus;constructor(e=()=>{}){this.onStatus=e}run(e,t){return this.disposed?Promise.reject(Error(`누끼 준비가 종료됐어요.`)):(this.cancel(),t.throwIfAborted(),new Promise((n,r)=>{let i=()=>this.cancel(),a={snapshot:e,signal:t,abort:i,fallback:!1,resolve:n,reject:r};this.pending=a,t.addEventListener(`abort`,i,{once:!0}),this.send(a).catch(e=>{this.pending===a&&this.fail(e)})}))}cancel(){let e=this.pending;this.pending=null,this.worker?.terminate(),this.worker=null,e&&(e.signal.removeEventListener(`abort`,e.abort),e.reject(new DOMException(`사진 준비를 취소했어요.`,`AbortError`)))}dispose(){this.disposed=!0,this.cancel()}fail(e){let t=this.pending;t&&(this.pending=null,this.worker?.terminate(),this.worker=null,t.signal.removeEventListener(`abort`,t.abort),t.reject(e instanceof Error?e:Error(`누끼를 준비하지 못했어요.`)))}async send(e){let n=await createImageBitmap(e.snapshot.bitmap);if(this.pending!==e||e.signal.aborted){n.close();return}let r;try{r=new Worker(new URL(`/assets/cutout.worker-D417j0Nw.js`,``+import.meta.url),{type:`module`})}catch(e){throw n.close(),e}this.worker=r,r.onmessage=n=>{if(this.worker!==r||this.pending!==e||n.data.id!==e.snapshot.requestId)return;let i=n.data;if(i.type===`status`){this.onStatus(i.id,i.message);return}if(r.terminate(),this.worker=null,i.type===`fallback`){if(e.fallback){this.fail(Error(`이 기기에서 누끼를 계산하지 못했어요.`));return}e.fallback=!0,this.send(e).catch(t=>{this.pending===e&&this.fail(t)});return}if(i.type===`error`){this.fail(Error(i.message));return}try{if(i.width!==e.snapshot.width||i.height!==e.snapshot.height)throw Error(`누끼 좌표가 사진과 맞지 않아요.`);let n=new Uint8Array(i.alpha),r=t(n,i.width,i.height);this.pending=null,e.signal.removeEventListener(`abort`,e.abort),e.resolve({requestId:i.id,width:i.width,height:i.height,alpha:n,...r,run:i.run})}catch(e){this.fail(e)}},r.onerror=t=>{this.worker===r&&this.pending===e&&this.fail(Error(t.message||`누끼 작업이 중단됐어요.`))},r.onmessageerror=()=>{this.worker===r&&this.pending===e&&this.fail(Error(`누끼 결과를 읽지 못했어요.`))};try{r.postMessage({type:`infer`,id:e.snapshot.requestId,image:n,forceWasm:e.fallback},[n])}catch(e){throw n.close(),e}}},r=class{nextId=0;pending=null;disposed=!1;results=new Set;provider=new n((e,t)=>{this.pending?.id===e&&!this.pending.controller.signal.aborted&&this.pending.onProgress(t)});async prepare(n,r=()=>{},o){if(this.disposed)throw Error(`누끼 준비가 종료됐어요.`);this.cancel(),o?.throwIfAborted();let s=new AbortController,c={id:++this.nextId,controller:s,onProgress:r};this.pending=c;let l=()=>s.abort(o?.reason);o?.addEventListener(`abort`,l,{once:!0});let u=null,d=``,f=``,p=new Image,m=new Image,h=!1,g=null,_=()=>{if(!h){h=!0;for(let e of[p,m])e.onload=e.onerror=null,e.removeAttribute(`src`);d&&URL.revokeObjectURL(d),f&&URL.revokeObjectURL(f),g&&this.results.delete(g)}},v=document.createElement(`canvas`);try{r(`사진 크기와 방향을 준비하는 중…`),u=await e(n,c.id,s.signal),s.signal.throwIfAborted();let o=await this.provider.run(u,s.signal);s.signal.throwIfAborted(),v.width=u.width,v.height=u.height;let l=v.getContext(`2d`);if(!l)throw Error(`사진 미리보기를 준비할 수 없어요.`);l.drawImage(u.bitmap,0,0);let h=await i(v);s.signal.throwIfAborted();let y=l.getImageData(0,0,v.width,v.height),b=new Uint8Array(o.alpha.length);for(let e=0;ee.toBlob(e=>{!e||e.type!==`image/png`?n(Error(`PNG 사진 미리보기를 만들지 못했어요.`)):t(e)},`image/png`))}function a(e,t,n){return new Promise((r,i)=>{let a=()=>{e.onload=e.onerror=null,n.removeEventListener(`abort`,o)},o=()=>{a(),i(new DOMException(`사진 준비를 취소했어요.`,`AbortError`))};e.onload=()=>{a(),r()},e.onerror=()=>{a(),i(Error(`PNG 사진 미리보기를 읽지 못했어요.`))},n.addEventListener(`abort`,o,{once:!0}),n.aborted?o():e.src=t})}export{r as CutoutPreparation}; \ No newline at end of file diff --git a/dist/assets/OriginalGlassRenderer-DLs_logl.js b/dist/assets/OriginalGlassRenderer-DLs_logl.js new file mode 100644 index 0000000..33dc3f4 --- /dev/null +++ b/dist/assets/OriginalGlassRenderer-DLs_logl.js @@ -0,0 +1,535 @@ +import{a as e,c as t,d as n,f as r,h as i,i as a,l as o,m as s,n as c,o as l,p as u,r as ee,u as d}from"./index-BYcEjj7E.js";var f=`uniform sampler2D uSceneTexture,uSceneDepth; +uniform sampler2D uProtectionDepthMap; +uniform mat4 uContentViewProjection,uContentInverseViewProjection; +uniform mat4 uPetWorldToLocal; +uniform vec3 uContentCameraPosition,uLightPosition,uBackgroundColor; +uniform float uGlassZ,uSourceZ,uGridSize,uStrength,uMosaicStyle,uCurvature,uGlossStrength; +uniform vec2 uViewOffset,uPetSize,uPaneSize; +uniform vec2 uDepthEvidenceRange,uDepthCorrection; +uniform float uEnvironmentStrength; +uniform vec4 uGobangSurface; +uniform float uGobangEnvironmentStrength; +uniform float uGobangBevelRound; +uniform vec4 uPaneRect; +uniform sampler2D uRegionPalette; +uniform sampler2D uRegionAtlas,uRegionHistory; +uniform vec2 uRegionAtlasSize,uRegionGridSize,uRegionPaletteSize; +uniform float uRegionStrength,uRegionAvailable; +varying vec2 vUv; +vec2 projectUv(vec3 p){vec4 c=uContentViewProjection*vec4(p,1.);float w=abs(c.w)<.0001?(c.w<0.?-.0001:.0001):c.w;return c.xy/w*.5+.5;} +vec4 sampleScene(vec2 uv){return texture2D(uSceneTexture,clamp(uv,0.,1.));} +vec4 samplePane(vec2 pane){return sampleScene(projectUv(vec3((pane-.5)*uPaneSize,uGlassZ)));} +float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);} +vec2 hash2(vec2 p){return vec2(hash(p),hash(p+vec2(19.19,73.73)));} +vec2 cellBlurStep(vec2 cell,vec2 cellSize,float style){ + if(style<=.5)return cellSize*mix(.006,.018,hash(cell+vec2(5.))); + return cellSize*mix(.006,.012,hash(cell+vec2(5.))); +} +vec4 sampleCell(vec2 pane,vec2 sourceUv,float strength,vec2 cell,vec2 cellSize,float style){ + vec2 center=mix(pane,sourceUv,strength); + vec2 blurOffset=strength*cellBlurStep(cell,cellSize,style); + vec4 color; + if(style<=.5){ + color=samplePane(center)*.6; + color+=samplePane(center+vec2(blurOffset.x,0.))*.1; + color+=samplePane(center-vec2(blurOffset.x,0.))*.1; + color+=samplePane(center+vec2(0.,blurOffset.y))*.1; + color+=samplePane(center-vec2(0.,blurOffset.y))*.1; + }else{ + color=samplePane(center)*.4; + color+=samplePane(center+vec2(blurOffset.x,0.))*.15; + color+=samplePane(center-vec2(blurOffset.x,0.))*.15; + color+=samplePane(center+vec2(0.,blurOffset.y))*.15; + color+=samplePane(center-vec2(0.,blurOffset.y))*.15; + } + return color; +} +float safeZ(float z){return abs(z)<.0001?(z<0.?-.0001:.0001):z;} +vec3 bend(vec3 i,vec3 n){vec3 r=refract(i,n,.75);return length(r)<.0001?i:r;} +float softLimit(float value,float limit){return value*limit/(limit+abs(value));} +float surfaceCurvature(){float curvature=clamp(uCurvature,-1.,1.),excess=max(curvature-.65,0.);return curvature-(.25/.35)*excess*excess;} +float signedCurvatureScale(){return clamp(surfaceCurvature()/.65,-1.25,1.25);} +float regionDistance(vec3 a,vec3 b){vec3 d=a-b;float y=dot(d,vec3(.299,.587,.114));return dot(d,d)+.35*y*y;} +float regionLuminance(vec3 c){return dot(c,vec3(.299,.587,.114));} +vec3 regionColor(vec2 cell,float index){vec2 uv=(vec2(cell.x*5.+index,cell.y)+.5)/uRegionPaletteSize;return texture2D(uRegionPalette,uv).rgb;} +float nearestRegion(vec3 color,vec2 cell){float best=0.,distance=regionDistance(color,regionColor(cell,0.));for(int i=1;i<4;i++){float candidate=regionDistance(color,regionColor(cell,float(i)));if(candidate1.||sceneUv.y<0.||sceneUv.y>1.)return false; + float depth=texture2D(uSceneDepth,sceneUv).x; + if(depth>=.999999)return false; + vec4 clip=vec4(sceneUv*2.-1.,depth*2.-1.,1.); + vec4 world=uContentInverseViewProjection*clip; + if(abs(world.w)<.0001)return false; + worldPoint=world.xyz/world.w; + return true; +} +float regionSurfaceValid(vec2 sceneUv,vec3 glassHit){ + vec3 worldPoint; + if(!reconstructScenePoint(sceneUv,worldPoint))return 0.; + float axialGap=glassHit.z-worldPoint.z; + if(axialGap<=.0001)return 0.; + return 1.; +} +float regionProtectionWeight(vec2 sceneUv){ + vec3 worldPoint; + if(!reconstructScenePoint(sceneUv,worldPoint))return 0.; + vec3 localPoint=(uPetWorldToLocal*vec4(worldPoint,1.)).xyz; + if(localPoint.x<-.5||localPoint.x>.5||localPoint.y<-.5||localPoint.y>.5)return 0.; + vec2 sourceUv=localPoint.xy+.5; + float sourceDepth=texture2D(uProtectionDepthMap,sourceUv).r; + if(uDepthEvidenceRange.y-uDepthEvidenceRange.x<.0001)return 0.; + return smoothstep(uDepthEvidenceRange.x,uDepthEvidenceRange.y,sourceDepth); +} +// Screen-depth refinement of an artistic ray. Occluded surfaces are unavailable; +// retain the original sample if the visible-depth solve cannot converge. +vec3 refineSceneHit(vec3 glassHit,vec3 ray,vec3 artisticHit,float cellWorld){ + vec3 planeHit=glassHit+ray*((uSourceZ-glassHit.z)/safeZ(ray.z)); + vec3 origin=glassHit+vec3(artisticHit.xy-planeHit.xy,0.); + vec3 hit=artisticHit,surface; + for(int iteration=0;iteration<3;iteration++){ + if(!reconstructScenePoint(projectUv(hit),surface))return artisticHit; + vec3 localPoint=(uPetWorldToLocal*vec4(surface,1.)).xyz; + if(any(greaterThan(abs(localPoint.xy),vec2(.5)))||surface.z>=uGlassZ-.0001)return artisticHit; + hit=origin+ray*((surface.z-origin.z)/safeZ(ray.z)); + } + if(!reconstructScenePoint(projectUv(hit),surface))return artisticHit; + if(surface.z>=uGlassZ-.0001)return artisticHit; + float confidence=1.-smoothstep(cellWorld*.05,cellWorld*.25,abs(hit.z-surface.z)); + // Compare at the same reference Z, so only the projected sampling position changes. + vec3 viewRay=hit-uContentCameraPosition; + vec3 projected=uContentCameraPosition+viewRay*((uSourceZ-uContentCameraPosition.z)/safeZ(viewRay.z)); + vec2 delta=projected.xy-artisticHit.xy; + float limit=cellWorld*uDepthCorrection.y; + delta*=min(1.,limit/max(length(delta),.00001)); + return artisticHit+vec3(delta*uDepthCorrection.x*confidence,0.); +} +#ifdef REGION_ATLAS +float regionAtlasEvidence(vec2 sceneUv,vec3 color,vec3 glassHit){ + if(regionSurfaceValid(sceneUv,glassHit)<=0.)return 0.; + return regionProtectionWeight(sceneUv)*(1.-smoothstep(.10,.20,regionLuminance(color))); +} +vec4 regionAtlasProbe(vec3 sceneHit,vec2 worldOffset,vec3 glassHit){ + vec2 probeSceneUv=projectUv(sceneHit+vec3(worldOffset,0.)); + vec4 probe=sampleScene(probeSceneUv); + return vec4(probe.rgb,regionAtlasEvidence(probeSceneUv,probe.rgb,glassHit)); +} +vec4 regionAtlasScore(vec3 centerColor,float centerEvidence,vec3 probeColor,float probeEvidence){ + float evidenceGain=probeEvidence-centerEvidence,darkGain=regionLuminance(centerColor)-regionLuminance(probeColor),blend=0.; + if(probeEvidence>.05&&evidenceGain>.02&&darkGain>.015)blend=min(.4,evidenceGain*2.)*min(1.,max(0.,darkGain*4.)); + return vec4(blend,probeEvidence,0.,0.); +} +vec3 regionAtlasRepresentative(vec3 centerColor,float centerEvidence,vec3 sceneHit,vec3 glassHit,out float evidence){ + vec3 bestColor=centerColor;float bestEvidence=centerEvidence,bestBlend=0.; + vec2 probeStep=uPaneSize/(uRegionGridSize*8.)*.25; + vec4 probe,score; + probe=regionAtlasProbe(sceneHit,vec2(probeStep.x,0.),glassHit);score=regionAtlasScore(centerColor,centerEvidence,probe.rgb,probe.a);if(score.x>bestBlend){bestColor=mix(centerColor,probe.rgb,score.x);bestEvidence=max(centerEvidence,probe.a);bestBlend=score.x;} + probe=regionAtlasProbe(sceneHit,vec2(-probeStep.x,0.),glassHit);score=regionAtlasScore(centerColor,centerEvidence,probe.rgb,probe.a);if(score.x>bestBlend){bestColor=mix(centerColor,probe.rgb,score.x);bestEvidence=max(centerEvidence,probe.a);bestBlend=score.x;} + probe=regionAtlasProbe(sceneHit,vec2(0.,probeStep.y),glassHit);score=regionAtlasScore(centerColor,centerEvidence,probe.rgb,probe.a);if(score.x>bestBlend){bestColor=mix(centerColor,probe.rgb,score.x);bestEvidence=max(centerEvidence,probe.a);bestBlend=score.x;} + probe=regionAtlasProbe(sceneHit,vec2(0.,-probeStep.y),glassHit);score=regionAtlasScore(centerColor,centerEvidence,probe.rgb,probe.a);if(score.x>bestBlend){bestColor=mix(centerColor,probe.rgb,score.x);bestEvidence=max(centerEvidence,probe.a);bestBlend=score.x;} + evidence=bestEvidence; + return bestColor; +} +#endif +void evaluateCell(vec2 cell,vec2 local,vec2 grid,vec2 cellSize,vec2 cellDimensions,float cellWorld,float opticalTravel,float style,out vec2 affineUv,out mat2 transform,out vec2 curvedSlope,out vec2 facetSlope){ + vec2 random=hash2(cell),widths; + if(style>.5){ + widths=mix(vec2(.82),vec2(1.12),hash2(cell+vec2(11.4,9.8))); + float angle=(random.x-.5)*.08,c=cos(angle),s=sin(angle); + transform=mat2(widths.x*c,-widths.y*s,widths.x*s,widths.y*c); + float centerJitter=.16; + vec2 sourceCenter=(cell+.5)/grid+(random-.5)*centerJitter*cellSize; + affineUv=sourceCenter+transform*(local*cellSize); + }else{ + // Default style keeps a single continuous image footprint across cells. + transform=mat2(1.); + affineUv=(cell+.5)/grid+local*cellSize; + } + + // Positive height bulges toward the observer (+Z); negative height is concave. + float curvature=clamp(uCurvature,-1.,1.),surfaceCurvatureValue=surfaceCurvature(); + vec2 q=clamp(2.*local,-1.,1.),q2=q*q,q3=q2*q,b=1.-q2*q2; + if(style>.5){ + float amplitude=mix(.92,1.08,hash(cell+vec2(41.7,17.3))),height=.009*cellWorld*surfaceCurvatureValue*amplitude; + vec2 skew=(hash2(cell+vec2(23.8,61.2))-.5)*.28;float asym=1.+dot(skew,q); + vec2 dhdq=height*vec2(-4.*q3.x*b.y*asym+b.x*b.y*skew.x,-4.*q3.y*b.x*asym+b.x*b.y*skew.y); + vec2 grad=-2.*dhdq/cellDimensions; + curvedSlope=grad+(random-.5)*.012;facetSlope=(random-.5)*.012; + }else{ + curvedSlope=.30*cellDimensions/max(abs(opticalTravel),.6)*signedCurvatureScale()*sin(6.2831853*local); + facetSlope=vec2(0.); + } +} +#ifndef REGION_ATLAS +// Broad prism faces, with narrow rounded transitions at the ridge and center. +// The height and slope meet at cell boundaries; no outline is painted on top. +float gobangProfile(float coordinate,out float derivative){ + float span=.5-uGobangSurface.y; + float t=clamp((abs(coordinate)-uGobangSurface.y)/span,0.,1.); + float rounding=uGobangBevelRound,ramp=t-rounding*.5,slope=1.; + if(t1.-rounding){ramp=1.-rounding-(1.-t)*(1.-t)/(2.*rounding);slope=(1.-t)/rounding;} + derivative=-slope*sign(coordinate)/(span*(1.-rounding)); + return 1.-ramp/(1.-rounding); +} +void gobangSurface(vec2 paneUv,vec2 grid,vec2 dimensions,float cellWorld,out float height,out vec3 normal){ + vec2 local=fract(paneUv*grid)-.5; + float dx,dy; + float px=gobangProfile(local.x,dx),py=gobangProfile(local.y,dy); + // Crossing directional ribs produce rectangular optical pieces. A minimum + // of X/Y profiles would instead produce conspicuous diagonal triangles. + float shape=.25*px+.55*py+.20*px*py; + vec2 shapeDerivative=vec2((.25+.20*py)*dx,(.55+.20*px)*dy); + // A small continuous ripple bends the ribs without independent cell crops. + vec2 phase=paneUv*grid*6.2831853; + float ripple=.008*sin(phase.x*3.+sin(phase.y))*sin(phase.y); + vec2 rippleDerivative=.008*6.2831853*vec2(3.*cos(phase.x*3.+sin(phase.y))*sin(phase.y),cos(phase.x*3.+sin(phase.y))*cos(phase.y)*sin(phase.y)+sin(phase.x*3.+sin(phase.y))*cos(phase.y)); + float amplitude=uGobangSurface.x*cellWorld*clamp(uCurvature,-1.,1.); + height=amplitude*(shape+ripple); + vec2 gradient=amplitude*(shapeDerivative+rippleDerivative)/dimensions; + normal=normalize(vec3(-gradient,1.)); +} +vec4 renderGobang(vec3 incident,vec3 glassHit,vec2 paneUv,vec2 grid,float cellWorld){ + vec2 dimensions=uPaneSize/grid; + float height;vec3 normal; + gobangSurface(paneUv,grid,dimensions,cellWorld,height,normal); + // Two refinements locate the shallow front surface along this camera ray. + vec3 frontHit=glassHit; + for(int iteration=0;iteration<2;iteration++){ + frontHit=uContentCameraPosition+incident*((uGlassZ+height-uContentCameraPosition.z)/safeZ(incident.z)); + gobangSurface(frontHit.xy/uPaneSize+.5,grid,dimensions,cellWorld,height,normal); + } + float ior=uGobangSurface.z; + vec3 internalRay=refract(incident,normal,1./ior); + float backZ=uGlassZ-uGobangSurface.w-uGobangSurface.x*cellWorld; + vec3 backHit=frontHit+internalRay*((backZ-frontHit.z)/safeZ(internalRay.z)); + vec3 exitRay=refract(internalRay,vec3(0.,0.,1.),ior); + float transmission=step(.0001,dot(exitRay,exitRay)); + if(transmission<.5)exitRay=incident; + vec3 sourceHit=backHit+exitRay*((uSourceZ-backHit.z)/safeZ(exitRay.z)); + vec3 straightSource=glassHit+incident*((uSourceZ-glassHit.z)/safeZ(incident.z)); + float edgeDistance=min(min(paneUv.x,paneUv.y),min(1.-paneUv.x,1.-paneUv.y)); + float paneWeight=smoothstep(0.,max(1./grid.x,1./grid.y)*.75,edgeDistance); + float amount=clamp(uStrength,0.,1.)*paneWeight; + sourceHit=mix(straightSource,sourceHit,amount); + // Reuse the visible-depth solve; hidden surfaces still fall back to the plane. + sourceHit=refineSceneHit(backHit,normalize(mix(incident,exitRay,amount)),sourceHit,cellWorld); + vec4 result=sampleScene(projectUv(sourceHit)); + + // One static room environment; the same surface normal controls its reflection. + vec3 viewDirection=-incident,reflected=reflect(incident,normal); + float fresnel=.04+.96*pow(1.-clamp(dot(normal,viewDirection),0.,1.),5.); + vec3 room=mix(vec3(.09,.13,.17),vec3(.78,.84,.86),smoothstep(-.4,.65,reflected.y)); + float lightTravel=(uLightPosition.z-frontHit.z)/safeZ(reflected.z); + vec2 lightUv=(frontHit.xy+reflected.xy*lightTravel-uLightPosition.xy)/(min(uPaneSize.x,uPaneSize.y)*vec2(.38,.52)); + vec2 window=1.-smoothstep(vec2(.75),vec2(1.1),abs(lightUv)); + float windowLight=window.x*window.y*step(0.,lightTravel)*step(.001,reflected.z); + room=mix(room,vec3(.94,.97,1.),windowLight); + float mullion=1.-smoothstep(.015,.06,abs(reflected.x+.12)); + room=mix(room,vec3(.12,.16,.20),mullion*.55); + float gloss=clamp(uGlossStrength,0.,1.); + float reflectionWeight=gloss*uGobangEnvironmentStrength*(.35+.65*fresnel)*amount; + reflectionWeight=mix(reflectionWeight,1.,(1.-transmission)*amount); + result.rgb=mix(result.rgb,room,reflectionWeight); + result.a=1.; + return result; +} +#endif +void main(){ + vec2 screenUv=vUv; +#ifdef REGION_ATLAS + vec2 atlasPixel=floor(vUv*uRegionAtlasSize),atlasCell=floor(atlasPixel/8.),atlasLocal=(mod(atlasPixel,8.)+.5)/8.; + vec2 atlasPaneUv=(atlasCell+atlasLocal)/uRegionGridSize; + screenUv=projectUv(vec3((atlasPaneUv-.5)*uPaneSize,uGlassZ)); +#endif + if(uStrength<=.001){ +#ifdef REGION_ATLAS + gl_FragColor=vec4(sampleScene(screenUv).rgb,0.); +#else + gl_FragColor=sampleScene(screenUv); + #include +#endif + return;} + vec4 f=uContentInverseViewProjection*vec4(screenUv*2.-1.,1.,1.);float fw=abs(f.w)<.0001?(f.w<0.?-.0001:.0001):f.w;vec3 farWorld=f.xyz/fw;vec3 i=normalize(farWorld-uContentCameraPosition);float gt=(uGlassZ-uContentCameraPosition.z)/safeZ(i.z);vec3 gh=uContentCameraPosition+i*gt; + vec2 paneUv=gh.xy/uPaneSize+.5;vec2 grid=vec2(uGridSize,max(1.,uGridSize*uPaneSize.y/uPaneSize.x));vec2 gridUv=paneUv*grid,cell=floor(gridUv),local=fract(gridUv)-.5,cellSize=1./grid;float style=clamp(uMosaicStyle,0.,2.),cellWorld=min(uPaneSize.x/grid.x,uPaneSize.y/grid.y); +#ifdef REGION_ATLAS + paneUv=atlasPaneUv;grid= uRegionGridSize;gridUv=paneUv*grid;cell=floor(gridUv);local=fract(gridUv)-.5;cellSize=1./grid;cellWorld=min(uPaneSize.x/grid.x,uPaneSize.y/grid.y); +#endif + if(paneUv.x<0.||paneUv.x>1.||paneUv.y<0.||paneUv.y>1.){ +#ifdef REGION_ATLAS + gl_FragColor=vec4(uBackgroundColor,0.); +#else + gl_FragColor=vec4(uBackgroundColor,1.); + #include +#endif + return;} +#ifndef REGION_ATLAS + if(style>1.5){ + gl_FragColor=renderGobang(i,gh,paneUv,grid,cellWorld); + #include + return; + } +#endif + vec2 cellDimensions=uPaneSize/grid; + float opticalTravel=-max(abs(uSourceZ-gh.z),.6); + vec2 affineUv,curvedSlope,facetSlope;mat2 transform; + evaluateCell(cell,local,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,affineUv,transform,curvedSlope,facetSlope); + if(style<=.5){ + vec2 smoothFacet=.003*vec2(sin(6.2831853*paneUv.x),sin(6.2831853*paneUv.y)); + curvedSlope+=smoothFacet;facetSlope=smoothFacet; + }else{ + vec2 edge=.5-abs(local),neighborSign=mix(vec2(-1.),vec2(1.),step(vec2(0.),local)); + float normalBlend=.16; + vec2 weights=1.-smoothstep(vec2(-normalBlend),vec2(normalBlend),edge); + float xSplitWeight=weights.x*(1.-weights.y),ySplitWeight=(1.-weights.x)*weights.y; + float diagonalSplitWeight=weights.x*weights.y,centerSplitWeight=(1.-weights.x)*(1.-weights.y); + if(weights.x>0.||weights.y>0.){ + vec2 neighborAffine,neighborCurved,neighborFacet;mat2 neighborTransform; + vec2 xWeight=vec2(xSplitWeight,0.); + vec2 yWeight=vec2(0.,ySplitWeight); + affineUv*=centerSplitWeight;transform*=centerSplitWeight;curvedSlope*=centerSplitWeight;facetSlope*=centerSplitWeight; + if(xWeight.x>0.){ + vec2 offset=vec2(neighborSign.x,0.); + evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); + affineUv+=neighborAffine*xWeight.x;transform+=neighborTransform*xWeight.x;curvedSlope+=neighborCurved*xWeight.x;facetSlope+=neighborFacet*xWeight.x; + } + if(yWeight.y>0.){ + vec2 offset=vec2(0.,neighborSign.y); + evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); + affineUv+=neighborAffine*yWeight.y;transform+=neighborTransform*yWeight.y;curvedSlope+=neighborCurved*yWeight.y;facetSlope+=neighborFacet*yWeight.y; + } + if(diagonalSplitWeight>0.){ + vec2 offset=neighborSign; + evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); + affineUv+=neighborAffine*diagonalSplitWeight;transform+=neighborTransform*diagonalSplitWeight;curvedSlope+=neighborCurved*diagonalSplitWeight;facetSlope+=neighborFacet*diagonalSplitWeight; + } + } + } + vec3 nCurved=normalize(vec3(curvedSlope,1.)),nFacet=normalize(vec3(facetSlope,1.)); + vec3 straightHit=gh+i*((uSourceZ-gh.z)/safeZ(i.z)); + vec3 curvedRay=bend(i,nCurved),curvedHit=gh+curvedRay*((uSourceZ-gh.z)/safeZ(curvedRay.z)); + // Keep the artistic Mosaic optical path independent of physical glass-to-photo contact distance. + vec2 rawDelta=(curvedRay.xy/safeZ(curvedRay.z)-i.xy/safeZ(i.z))*opticalTravel; + vec2 worldDelta=vec2(softLimit(rawDelta.x,cellWorld*.55),softLimit(rawDelta.y,cellWorld*.55)); + if(style>.5){ + vec3 facetRay=bend(i,nFacet);vec3 facetHit=gh+facetRay*((uSourceZ-gh.z)/safeZ(facetRay.z)); + vec2 base=facetHit.xy-straightHit.xy,curve=curvedHit.xy-facetHit.xy; + worldDelta=vec2(softLimit(base.x,cellWorld*.08),softLimit(base.y,cellWorld*.08)); + vec2 d=curve/cellWorld; + worldDelta+=vec2(.3*d.x/(.3+abs(d.x)),.3*d.y/(.3+abs(d.y)))*cellWorld; + }else{ + vec3 referenceI=normalize(gh-vec3(0.,0.,uContentCameraPosition.z)),referenceRay=bend(referenceI,nCurved); + vec2 incidenceDelta=curvedRay.xy/max(-curvedRay.z,.0001)-referenceRay.xy/max(-referenceRay.z,.0001); + vec2 boundedIncidence=incidenceDelta/sqrt(incidenceDelta*incidenceDelta+vec2(.025*.025)); + vec2 cellEnvelope=.5+.5*cos(6.2831853*local); + worldDelta+=boundedIncidence*cellEnvelope*cellDimensions*signedCurvatureScale()*.18; + } + vec2 sampleUv=affineUv+transform*(worldDelta/uPaneSize); + float edgeDistance=min(min(paneUv.x,paneUv.y),min(1.-paneUv.x,1.-paneUv.y));float edgeTaper=style<=.5?1.25:.75;float edgeWeight=smoothstep(0.,max(cellSize.x,cellSize.y)*edgeTaper,edgeDistance);float strength=clamp(uStrength,0.,1.)*edgeWeight; + vec4 color;vec3 sceneHit=straightHit+vec3(worldDelta*strength,0.);vec2 finalSceneUv=projectUv(sceneHit); + if(style<=.5){ + sceneHit=refineSceneHit(gh,normalize(mix(i,curvedRay,strength)),sceneHit,cellWorld); + finalSceneUv=projectUv(sceneHit); + } +#ifdef REGION_ATLAS + vec3 atlasCenterColor=sampleScene(finalSceneUv).rgb; + float atlasEvidence=regionProtectionWeight(finalSceneUv)*(1.-smoothstep(.10,.20,regionLuminance(atlasCenterColor))); +#endif +#ifdef REGION_ATLAS + if(style<=.5){ + float representativeEvidence=atlasEvidence; + color=vec4(regionAtlasRepresentative(atlasCenterColor,atlasEvidence,sceneHit,gh,representativeEvidence),representativeEvidence); + atlasEvidence=representativeEvidence; + }else{ + color=sampleCell(paneUv,sampleUv,strength,cell,cellSize,style); + } +#else + if(style<=.5){ + color=sampleScene(finalSceneUv); + }else{ + color=sampleCell(paneUv,sampleUv,strength,cell,cellSize,style); + } +#endif +#ifndef REGION_ATLAS + if(uRegionAvailable>.5&&uRegionStrength>.001&&uMosaicStyle<.5){ + vec3 p0=regionColor(cell,0.),p1=regionColor(cell,1.),p2=regionColor(cell,2.),p3=regionColor(cell,3.); + float ownLabel=nearestRegion(color.rgb,p0,p1,p2,p3);vec4 votes=vec4(0.);float totalWeight=0.,ownWeight=0.; + vec2 texelCoord=fract(gridUv)*8.-.5,anchor=floor(texelCoord+.5); + for(int y=-1;y<=1;y++)for(int x=-1;x<=1;x++){ + vec2 offset=vec2(float(x),float(y)),delta=anchor+offset-texelCoord; + float weight=pow(max(0.,1.-length(delta)/1.5),2.); + if(weight>0.){ + vec3 atlasColor=regionAtlasColor(cell,anchor+offset);float label=nearestRegion(atlasColor,p0,p1,p2,p3); + votes+=vec4(step(abs(label-vec4(0.,1.,2.,3.)),vec4(.1)))*weight;totalWeight+=weight; + ownWeight+=step(abs(label-ownLabel),.1)*weight; + } + } + float winningLabel=ownLabel,winningWeight=ownWeight; + if(votes.x>winningWeight){winningLabel=0.;winningWeight=votes.x;}if(votes.y>winningWeight){winningLabel=1.;winningWeight=votes.y;}if(votes.z>winningWeight){winningLabel=2.;winningWeight=votes.z;}if(votes.w>winningWeight){winningLabel=3.;winningWeight=votes.w;} + bool simplify=totalWeight>0.&&winningWeight/totalWeight>.55&&ownWeight/totalWeight<.40; + float radialLabel=simplify?winningLabel:ownLabel;vec3 radialColor=selectRegion(p0,p1,p2,p3,radialLabel); + vec2 historyTexel=clamp(floor(fract(gridUv)*8.),vec2(0.),vec2(7.)); + vec2 historyUv=(cell*8.+historyTexel+.5)/uRegionAtlasSize; + vec4 splitHistory=texture2D(uRegionHistory,historyUv); + vec3 splitColor=splitHistory.a>.00001?splitHistory.rgb/splitHistory.a:radialColor; + vec3 candidateColor=mix(radialColor,splitColor,splitHistory.a); + color.rgb=mix(color.rgb,candidateColor,clamp(uRegionStrength*clamp(uStrength,0.,1.)*regionSurfaceValid(finalSceneUv,gh),0.,1.)); + } +#endif +#ifndef REGION_ATLAS + color.a=1.; + vec3 v=normalize(uContentCameraPosition-gh),reflected=reflect(-v,nCurved); float lightT=(uLightPosition.z-gh.z)/safeZ(reflected.z); vec2 lightHit=gh.xy+reflected.xy*lightT; vec2 halfSize=vec2(.32,.42)*min(uPaneSize.x,uPaneSize.y); vec2 windowCoord=abs(lightHit-uLightPosition.xy)/halfSize; vec2 windowMask=1.-smoothstep(vec2(.45),vec2(1.15),windowCoord); float surfaceReflectionWeight=mix(.35,1.,edgeWeight); float glossStrength=clamp(uGlossStrength,0.,1.); float spec=windowMask.x*windowMask.y*step(.0001,reflected.z)*step(0.,lightT); float specGloss=spec*glossStrength*.12*surfaceReflectionWeight*clamp(uStrength,0.,1.); vec2 broadWindowMask=1.-smoothstep(vec2(.15),vec2(1.75),windowCoord); float broadFacing=pow(max(dot(nCurved,v),0.),2.); float broadReflection=broadWindowMask.x*broadWindowMask.y*broadFacing*glossStrength*.035*surfaceReflectionWeight*clamp(uStrength,0.,1.); color.rgb=mix(color.rgb,vec3(1.),specGloss+broadReflection); gl_FragColor=color; + // Common, static room environment. Reflected direction varies with the same + // curved normal as transmission; no image relighting or timed sparkle. + float fresnel=.04+.96*pow(1.-clamp(dot(nCurved,v),0.,1.),5.); + float environmentWeight=uEnvironmentStrength*glossStrength*(.35+.65*fresnel)*surfaceReflectionWeight*clamp(uStrength,0.,1.); + vec3 environmentColor=mix(vec3(.10,.13,.18),vec3(.65,.72,.80),smoothstep(-.35,.65,reflected.y)); + if(style<=.5)color.rgb=mix(color.rgb,environmentColor,environmentWeight); + gl_FragColor=color; + #include +#else + color.a=atlasEvidence; + gl_FragColor=color; +#endif +} +`,p=`uniform sampler2D uSceneTexture; uniform mat4 uContentViewProjection; uniform mat4 uContentInverseViewProjection; uniform vec3 uContentCameraPosition,uBackgroundColor; uniform float uSceneZoom; uniform float uGlassZ,uSourceZ,uGridSize,uStrength,uTime; uniform vec2 uSceneOffset,uViewOffset,uResolution,uPetSize,uPaneSize; +varying vec2 vUv; +// Preserve the existing 1x material coordinates as the common projection magnifies and translates. +vec2 patternScreenUv(vec2 uv){return (uv-.5-uSceneOffset*.5)/max(uSceneZoom,1.)+.5;} +vec2 projectUv(vec3 p){vec4 c=uContentViewProjection*vec4(p,1.);float w=abs(c.w)<.0001?(c.w<0.?-.0001:.0001):c.w;return c.xy/w*.5+.5;} vec4 sampleScene(vec2 uv){if(any(lessThan(uv,vec2(0.)))||any(greaterThan(uv,vec2(1.))))return vec4(.005605,.009721,.016807,1.);return texture2D(uSceneTexture,uv);} float hash(float x){return fract(sin(x*91.7)*43758.5453);} float safeZ(float z){return abs(z)<.0001?(z<0.?-.0001:.0001):z;} vec3 bend(vec3 i,vec3 n){vec3 r=refract(i,n,.75);return length(r)<.0001?i:r;} +void main(){if(uStrength<=.001){gl_FragColor=texture2D(uSceneTexture,vUv); +#include +return;}vec2 q=vUv*2.-1.;vec4 fh=uContentInverseViewProjection*vec4(q,1.,1.);float fwDen=abs(fh.w)<.0001?(fh.w<0.?-.0001:.0001):fh.w;vec3 fw=fh.xyz/fwDen;vec3 i=normalize(fw-uContentCameraPosition);float gt=(uGlassZ-uContentCameraPosition.z)/safeZ(i.z);vec3 gh=uContentCameraPosition+i*gt;vec2 paneUv=gh.xy/uPaneSize+.5;if(any(lessThan(paneUv,vec2(0.)))||any(greaterThan(paneUv,vec2(1.)))){gl_FragColor=vec4(uBackgroundColor,1.); +#include +return;}float count=max(1.,uGridSize*uPetSize.x/uPetSize.y),coord=patternScreenUv(vUv).x*count,cell=floor(coord),phase=fract(coord)*6.2831853,ridge=sin(phase+uViewOffset.x*.9),variation=mix(.92,1.08,hash(cell));vec3 r=bend(i,normalize(vec3(-ridge*.34*variation,0.,1.)));vec3 sh=gh+i*((uSourceZ-gh.z)/safeZ(i.z)),bh=gh+r*((uSourceZ-gh.z)/safeZ(r.z));vec2 ru=vUv+projectUv(bh)-projectUv(sh);vec2 uv=mix(vUv,ru,clamp(uStrength,0.,1.));vec4 c=sampleScene(uv);c.a=1.;gl_FragColor=c; +#include +} +`,m=`uniform sampler2D uSceneTexture; uniform mat4 uContentViewProjection; uniform mat4 uContentInverseViewProjection; uniform vec3 uContentCameraPosition,uBackgroundColor; uniform float uSceneZoom; uniform float uGlassZ,uSourceZ,uGridSize,uStrength,uTime; uniform vec2 uSceneOffset,uViewOffset,uResolution,uPetSize,uPaneSize; +varying vec2 vUv; +// Preserve the existing 1x material coordinates as the common projection magnifies and translates. +vec2 patternScreenUv(vec2 uv){return (uv-.5-uSceneOffset*.5)/max(uSceneZoom,1.)+.5;} +vec2 projectUv(vec3 p){vec4 c=uContentViewProjection*vec4(p,1.);float w=abs(c.w)<.0001?(c.w<0.?-.0001:.0001):c.w;return c.xy/w*.5+.5;} vec4 sampleScene(vec2 uv){if(any(lessThan(uv,vec2(0.)))||any(greaterThan(uv,vec2(1.))))return vec4(.005605,.009721,.016807,1.);return texture2D(uSceneTexture,uv);} float hash(vec2 p){return fract(sin(dot(p,vec2(41.3,17.9)))*15731.743);} float noise(vec2 p){vec2 i=floor(p),f=fract(p);f=f*f*(3.-2.*f);return mix(mix(hash(i),hash(i+vec2(1.,0.)),f.x),mix(hash(i+vec2(0.,1.)),hash(i+vec2(1.)),f.x),f.y);} float safeZ(float z){return abs(z)<.0001?(z<0.?-.0001:.0001):z;} vec3 bend(vec3 i,vec3 n){vec3 r=refract(i,n,.75);return length(r)<.0001?i:r;} +void main(){if(uStrength<=.001){gl_FragColor=texture2D(uSceneTexture,vUv); +#include +return;}vec2 q=vUv*2.-1.;vec4 fh=uContentInverseViewProjection*vec4(q,1.,1.);float fwDen=abs(fh.w)<.0001?(fh.w<0.?-.0001:.0001):fh.w;vec3 fw=fh.xyz/fwDen;vec3 i=normalize(fw-uContentCameraPosition);float gt=(uGlassZ-uContentCameraPosition.z)/safeZ(i.z);vec3 gh=uContentCameraPosition+i*gt;vec2 paneUv=gh.xy/uPaneSize+.5;if(any(lessThan(paneUv,vec2(0.)))||any(greaterThan(paneUv,vec2(1.)))){gl_FragColor=vec4(uBackgroundColor,1.); +#include +return;}vec2 st=patternScreenUv(vUv)*(uResolution/max(uResolution.y,1.)),np=st*9.+uViewOffset*.6,nn=vec2(noise(np),noise(np+vec2(23.7)))-vec2(.5);vec3 r=bend(i,normalize(vec3(nn*.32,1.)));vec3 sh=gh+i*((uSourceZ-gh.z)/safeZ(i.z)),bh=gh+r*((uSourceZ-gh.z)/safeZ(r.z));vec2 ru=vUv+projectUv(bh)-projectUv(sh),center=mix(vUv,ru,clamp(uStrength,0.,1.)),rad=vec2(.008)*uSceneZoom*clamp(uStrength,0.,1.);vec4 c=vec4(0.);c+=sampleScene(center+vec2(-rad.x,-rad.y));c+=sampleScene(center+vec2(0.,-rad.y));c+=sampleScene(center+vec2(rad.x,-rad.y));c+=sampleScene(center+vec2(-rad.x,0.));c+=sampleScene(center);c+=sampleScene(center+vec2(rad.x,0.));c+=sampleScene(center+vec2(-rad.x,rad.y));c+=sampleScene(center+vec2(0.,rad.y));c+=sampleScene(center+vec2(rad.x,rad.y));c/=9.;c.a=1.;gl_FragColor=c; +#include +} +`,h=`varying vec2 vUv; + +void main() { + vUv = uv; + gl_Position = vec4(position.xy, 0.0, 1.0); +} +`,g=`uniform sampler2D uRegionAtlas; +uniform vec2 uRegionAtlasSize,uRegionGridSize; +varying vec2 vUv; + +float regionLuminance(vec3 c){return dot(c,vec3(.299,.587,.114));} +float distanceColor(vec3 a,vec3 b){vec3 d=a-b;float y=dot(d,vec3(.299,.587,.114));return dot(d,d)+.35*y*y;} +float sideColorCost(vec4 votes,vec3 target,vec3 c0,vec3 c1,vec3 c2,vec3 c3){return votes.x*distanceColor(c0,target)+votes.y*distanceColor(c1,target)+votes.z*distanceColor(c2,target)+votes.w*distanceColor(c3,target);} +vec4 atlasSampleData(vec2 cell,vec2 local){vec2 uv=(cell*8.+local+.5)/uRegionAtlasSize;return texture2D(uRegionAtlas,uv);} +vec3 atlasSample(vec2 cell,vec2 local){return atlasSampleData(cell,local).rgb;} +float nearestLabel(vec3 color,vec3 c0,vec3 c1,vec3 c2,vec3 c3){float d0=distanceColor(color,c0),d1=distanceColor(color,c1),d2=distanceColor(color,c2),d3=distanceColor(color,c3);if(d0<=d1&&d0<=d2&&d0<=d3)return 0.;if(d1<=d2&&d1<=d3)return 1.;if(d2<=d3)return 2.;return 3.;} +float majorityLabel(vec4 votes){float label=0.,count=votes.x;if(votes.y>count){label=1.;count=votes.y;}if(votes.z>count){label=2.;count=votes.z;}if(votes.w>count)label=3.;return label;} +void main(){ + vec2 pixel=floor(gl_FragCoord.xy);float paletteIndex=mod(pixel.x,5.);vec3 cell=vec3(floor(pixel.x/5.),pixel.y,0.); + vec3 darkest=vec3(1.),lightest=vec3(0.);float minLum=2.,maxLum=-1.; + for(int y=0;y<8;y++)for(int x=0;x<8;x++){ + vec3 c=atlasSample(cell.xy,vec2(float(x),float(y)));float l=regionLuminance(c); + if(lmaxLum){maxLum=l;lightest=c;} + } + vec3 third=darkest;float thirdDistance=-1.; + for(int y=0;y<8;y++)for(int x=0;x<8;x++){ + vec3 c=atlasSample(cell.xy,vec2(float(x),float(y)));float d=min(distanceColor(c,darkest),distanceColor(c,lightest)); + if(d>thirdDistance){thirdDistance=d;third=c;} + } + vec3 fourth=darkest;float fourthDistance=-1.; + for(int y=0;y<8;y++)for(int x=0;x<8;x++){ + vec3 c=atlasSample(cell.xy,vec2(float(x),float(y)));float d=min(distanceColor(c,darkest),min(distanceColor(c,lightest),distanceColor(c,third))); + if(d>fourthDistance){fourthDistance=d;fourth=c;} + } + vec3 c0=darkest,c1=lightest,c2=third,c3=fourth; + for(int iteration=0;iteration<2;iteration++){ + vec3 sum0=vec3(0.),sum1=vec3(0.),sum2=vec3(0.),sum3=vec3(0.);float n0=0.,n1=0.,n2=0.,n3=0.; + for(int y=0;y<8;y++)for(int x=0;x<8;x++){ + vec3 c=atlasSample(cell.xy,vec2(float(x),float(y))); + float d0=distanceColor(c,c0),d1=distanceColor(c,c1),d2=distanceColor(c,c2),d3=distanceColor(c,c3); + if(d0<=d1&&d0<=d2&&d0<=d3){sum0+=c;n0+=1.;} + else if(d1<=d2&&d1<=d3){sum1+=c;n1+=1.;} + else if(d2<=d3){sum2+=c;n2+=1.;} + else{sum3+=c;n3+=1.;} + } + if(n0>0.)c0=sum0/n0;if(n1>0.)c1=sum1/n1;if(n2>0.)c2=sum2/n2;if(n3>0.)c3=sum3/n3; + } + + vec4 metadata=vec4(0.); + if(paletteIndex>3.5){ + vec4 wholeVotes=vec4(0.);float cellEvidence=0.; + for(int y=0;y<8;y++)for(int x=0;x<8;x++){ + vec4 sampleData=atlasSampleData(cell.xy,vec2(float(x),float(y)));vec3 c=sampleData.rgb;float label=nearestLabel(c,c0,c1,c2,c3); + wholeVotes+=vec4(step(abs(label-vec4(0.,1.,2.,3.)),vec4(.1))); + cellEvidence+=sampleData.a; + } + float singleMajority=max(max(wholeVotes.x,wholeVotes.y),max(wholeVotes.z,wholeVotes.w))/64.; + float bestCost=1e20,bestConfidence=0.,bestAxis=0.,bestCut=4.,bestA=0.,bestB=0.; + for(int axis=0;axis<2;axis++)for(int candidateIndex=0;candidateIndex<5;candidateIndex++){ + float cut=4.; + if(candidateIndex==1)cut=3.;else if(candidateIndex==2)cut=5.;else if(candidateIndex==3)cut=2.;else if(candidateIndex==4)cut=6.; + vec4 votesA=vec4(0.),votesB=vec4(0.),weightedVotesA=vec4(0.),weightedVotesB=vec4(0.); + for(int y=0;y<8;y++)for(int x=0;x<8;x++){ + vec4 sampleData=atlasSampleData(cell.xy,vec2(float(x),float(y)));vec3 c=sampleData.rgb;float label=nearestLabel(c,c0,c1,c2,c3); + vec4 oneHot=vec4(step(abs(label-vec4(0.,1.,2.,3.)),vec4(.1)));float sampleWeight=1.+3.*sampleData.a; + float coordinate=axis==0?float(x)+.5:float(y)+.5; + if(coordinate0.&&votesB[b]>0.){ + vec3 colorA=a==0?c0:(a==1?c1:(a==2?c2:c3)); + vec3 colorB=b==0?c0:(b==1?c1:(b==2?c2:c3)); + float candidateCost=sideColorCost(weightedVotesA,colorA,c0,c1,c2,c3)+sideColorCost(weightedVotesB,colorB,c0,c1,c2,c3); + if(candidateCost.5&&paletteIndex<1.5)result=c1; + else if(paletteIndex>1.5&&paletteIndex<2.5)result=c2; + else if(paletteIndex>2.5&&paletteIndex<3.5)result=c3; + gl_FragColor=paletteIndex>3.5?metadata:vec4(result,1.); +} +`,_=`uniform sampler2D uRegionPalette,uPreviousHistory; +uniform vec2 uRegionAtlasSize,uRegionGridSize,uRegionPaletteSize; +uniform float uHistoryBlend; +varying vec2 vUv; + +vec3 paletteColor(vec2 cell,float label){vec2 uv=(vec2(cell.x*5.+label,cell.y)+.5)/uRegionPaletteSize;return texture2D(uRegionPalette,uv).rgb;} +void main(){ + vec2 pixel=floor(vUv*uRegionAtlasSize),cell=floor(pixel/8.),local=(mod(pixel,8.)+.5)/8.; + vec2 metadataUv=(vec2(cell.x*5.+4.,cell.y)+.5)/uRegionPaletteSize; + vec4 metadata=texture2D(uRegionPalette,metadataUv); + float packed=floor(metadata.r*255.+.5),axis=floor(packed/8.),cut=packed-axis*8.; + float coordinate=axis<.5?local.x:local.y; + float label=coordinate=.9999){gl_FragColor=current;return;} + vec4 previous=texture2D(uPreviousHistory,vUv); + gl_FragColor=mix(previous,current,clamp(uHistoryBlend,0.,1.)); +} +`;function v(v){let{renderer:y,scene:b,frameScene:te,camera:x,petDepth:S,uniforms:C,depthUniforms:w,emptyTex:ne,regionHistoryUniform:T,state:E}=v,D=new n,O=new r({uniforms:C,vertexShader:h,fragmentShader:f}),k=new l(new d(2,2),O);D.add(k);let A=new n,j=new r({uniforms:C,vertexShader:h,fragmentShader:f,defines:{REGION_ATLAS:1},toneMapped:!1}),M=new l(new d(2,2),j);A.add(M);let N=new n,P={uRegionAtlas:{value:null},uRegionAtlasSize:C.uRegionAtlasSize,uRegionGridSize:C.uRegionGridSize},F=new r({uniforms:P,vertexShader:h,fragmentShader:g,toneMapped:!1}),I=new l(new d(2,2),F);N.add(I);let L=new o(-1,1,1,-1,0,1),R=new i(1,1,{colorSpace:``,type:e,depthBuffer:!0});R.depthTexture=new a(1,1,s),R.depthTexture.format=ee,C.uSceneDepth.value=R.depthTexture;let z=new i(104,104,{colorSpace:``,type:e,depthBuffer:!1,minFilter:t,magFilter:t}),B=new i(65,13,{colorSpace:``,type:u,depthBuffer:!1,minFilter:t,magFilter:t}),V=[0,1].map(()=>new i(104,104,{colorSpace:``,type:e,depthBuffer:!1,minFilter:t,magFilter:t})),H=new n,U={uRegionPalette:{value:B.texture},uPreviousHistory:{value:V[0].texture},uRegionAtlasSize:C.uRegionAtlasSize,uRegionGridSize:C.uRegionGridSize,uRegionPaletteSize:C.uRegionPaletteSize,uHistoryBlend:{value:1}},W=new r({uniforms:U,vertexShader:h,fragmentShader:_,toneMapped:!1}),G=new l(new d(2,2),W);H.add(G),C.uRegionPalette.value=B.texture,P.uRegionAtlas.value=z.texture;let K=``,q=``,J=0,Y=!1;function X(){let e=Math.max(1,Math.ceil(C.uGridSize.value)),t=Math.max(1,C.uGridSize.value*C.uPaneSize.value.y/Math.max(C.uPaneSize.value.x,.001)),n=Math.ceil(t),r=e*8,i=n*8,a=e*5,o=n,s=Math.max(r,i,a,o)<=y.capabilities.maxTextureSize,c=C.uRegionAvailable.value!==+!!s||s&&(z.width!==r||z.height!==i||B.width!==a||B.height!==o||V[0].width!==r||V[0].height!==i)||C.uRegionGridSize.value.x!==C.uGridSize.value||C.uRegionGridSize.value.y!==t;s&&(z.width!==r||z.height!==i)&&z.setSize(r,i),s&&(B.width!==a||B.height!==o)&&B.setSize(a,o);for(let e of V)s&&(e.width!==r||e.height!==i)&&e.setSize(r,i);C.uRegionAvailable.value=+!!s,C.uRegionAtlasSize.value.set(s?r:z.width,s?i:z.height),C.uRegionGridSize.value.set(C.uGridSize.value,t),C.uRegionPaletteSize.value.set(s?a:B.width,s?o:B.height),P.uRegionAtlas.value=z.texture,C.uRegionPalette.value=B.texture,C.uRegionAtlas.value=z.texture,c&&(K=``)}function Z(){let{mode:e,active:t,activeIsVideo:n,effect:r,style:i}=E(),a=C.uContentViewProjection.value.elements.map(e=>e.toFixed(4)).join(`,`),o=S.matrixWorld.elements.map(e=>e.toFixed(4)).join(`,`),s=w.uDepthMap.value;return[e,t.uuid,s.uuid,a,o,C.uGridSize.value,C.uStrength.value,C.uCurvature.value,C.uMosaicStyle.value,C.uPaneSize.value.x,C.uPaneSize.value.y,w.uDepthScale.value,w.uDepthBias.value,R.width,R.height,z.width,z.height].join(`|`)}function re(){let{mode:e,active:t,effect:n,style:r}=E(),i=S.matrixWorld.elements.map(e=>e.toFixed(4)).join(`,`),a=w.uDepthMap.value;return[e,n,r,t.uuid,a.uuid,C.uRegionAvailable.value,C.uGridSize.value,C.uMosaicStyle.value,C.uStrength.value,C.uRegionStrength.value,C.uCurvature.value,C.uGlassZ.value,C.uSourceZ.value,C.uPaneSize.value.x,C.uPaneSize.value.y,i,w.uDepthScale.value,w.uDepthBias.value,R.width,R.height,z.width,z.height,B.width,B.height].join(`|`)}function ie(){let e=y.getRenderTarget(),t=y.getClearColor(new c),n=y.getClearAlpha();y.setClearColor(0,0);for(let e of V)y.setRenderTarget(e),y.clear(!0,!1,!1);y.setRenderTarget(e),y.setClearColor(t,n),J=0,Y=!1,T.value=V[0].texture}function Q(e){let{mode:t,effect:n,style:r}=E(),i=re();if(i!==q&&(ie(),q=i),!((t===`final`||t===`glass`)&&n===`mosaic`&&r===`0`&&C.uRegionAvailable.value>.5&&C.uRegionStrength.value>.001&&C.uStrength.value>.001))return;let a=1-J;U.uPreviousHistory.value=V[J].texture,U.uHistoryBlend.value=Y?1-Math.exp(-e/.07):1,y.setRenderTarget(V[a]),y.render(H,L),y.setRenderTarget(null),J=a,Y=!0,T.value=V[J].texture}function ae(){let{effect:e,style:t,activeIsVideo:n}=E();if(!(e===`mosaic`&&t===`0`&&C.uRegionAvailable.value>.5&&C.uRegionStrength.value>.001&&C.uStrength.value>.001))return;let r=Z();(n||r!==K)&&(y.setRenderTarget(z),y.render(A,L),y.setRenderTarget(B),y.render(N,L),y.setRenderTarget(null),K=r)}function oe(e,t=null){let{mode:n}=E();if(n===`final`||n===`glass`){y.setRenderTarget(R),y.render(b,x),C.uSceneTexture.value=R.texture,ae(),Q(e),y.setRenderTarget(t),y.render(D,L);let n=y.autoClear;y.autoClear=!1,y.clearDepth(),y.render(te,x),y.autoClear=n}else Q(e),y.setRenderTarget(t),y.render(b,x)}let $=!1;return{render:oe,setEffect(e){O.fragmentShader=e===`reeded`?p:e===`frosted`?m:f,O.needsUpdate=!0},resize(e,t){R.setSize(e,t),X()},invalidate(){K=``,q=``,Y=!1},dispose(){if(!$){$=!0,R.dispose(),z.dispose(),B.dispose(),V.forEach(e=>e.dispose());for(let e of[k,M,I,G])e.geometry.dispose();for(let e of[O,j,F,W])e.dispose();D.clear(),A.clear(),N.clear(),H.clear()}}}}export{v as createOriginalGlassRenderer}; \ No newline at end of file diff --git a/dist/assets/PhysicalGlassComparison-B37yDBlH.js b/dist/assets/PhysicalGlassComparison-B37yDBlH.js new file mode 100644 index 0000000..da79c7d --- /dev/null +++ b/dist/assets/PhysicalGlassComparison-B37yDBlH.js @@ -0,0 +1 @@ +import{a as e,d as t,h as n,l as r,n as i,o as a,s as o,u as s}from"./index-BYcEjj7E.js";var c=class{renderer;background;targetA=new n(1,1,{type:e});targetB=new n(1,1,{type:e});blitMaterial=new o({toneMapped:!1,depthTest:!1,depthWrite:!1});blit=new a(new s(2,2),this.blitMaterial);blitScene=new t;blitCamera=new r(-1,1,1,-1,0,1);disposed=!1;constructor(e,t){this.renderer=e,this.background=t,this.blitScene.add(this.blit)}resize(e,t){for(let n of[this.targetA,this.targetB])(n.width!==e||n.height!==t)&&n.setSize(e,t)}composite(e,t){this.renderer.setRenderTarget(null),this.renderer.setScissorTest(!1);let n=this.renderer.getClearColor(new i),r=this.renderer.getClearAlpha();this.renderer.setClearColor(this.background,1),this.renderer.clear(),this.renderer.setClearColor(n,r),this.renderer.setScissorTest(!0);try{for(let n=0;n{let r={};for(var i in t)e(r,i,{get:t[i],enumerable:!0});return n||e(r,Symbol.toStringTag,{value:`Module`}),r})({InferenceSession:()=>Ae,TRACE:()=>xe,TRACE_EVENT_BEGIN:()=>Te,TRACE_EVENT_END:()=>Ee,TRACE_FUNC_BEGIN:()=>Ce,TRACE_FUNC_END:()=>we,Tensor:()=>ye,default:()=>tr,env:()=>C,registerBackend:()=>p}),n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.prototype.hasOwnProperty,o=(e=>typeof require<`u`?require:typeof Proxy<`u`?new Proxy(e,{get:(e,t)=>(typeof require<`u`?require:e)[t]}):e)(function(e){ +/*! +* ONNX Runtime Web v1.31.0-dev.20260914-8d85527a0 +* Copyright (c) Microsoft Corporation. All rights reserved. +* Licensed under the MIT License. +*/ +if(typeof require<`u`)return require.apply(this,arguments);throw Error(`Dynamic require of "`+e+`" is not supported`)}),s=(e,t,n)=>()=>{if(n)throw n[0];try{return e&&(t=e(e=0)),t}catch(e){throw n=[e],e}},c=(e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:!0})},l=(e,t,o,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(let c of i(t))!a.call(e,c)&&c!==o&&n(e,c,{get:()=>t[c],enumerable:!(s=r(t,c))||s.enumerable});return e},u=e=>l(n({},`__esModule`,{value:!0}),e),d,f,p,m,h,g=s(()=>{"use strict";d=/* @__PURE__ */ new Map,f=[],p=(e,t,n)=>{if(t&&typeof t.init==`function`&&typeof t.createInferenceSessionHandler==`function`){let r=d.get(e);if(r===void 0)d.set(e,{backend:t,priority:n});else{if(r.priority>n)return;if(r.priority===n&&r.backend!==t)throw Error(`cannot register backend "${e}" using priority ${n}`)}if(n>=0){let t=f.indexOf(e);t!==-1&&f.splice(t,1);for(let t=0;t{let t=d.get(e);if(!t)return`backend not found.`;if(t.initialized)return t.backend;if(t.aborted)return t.error;{let n=!!t.initPromise;try{return n||(t.initPromise=t.backend.init(e)),await t.initPromise,t.initialized=!0,t.backend}catch(e){return n||(t.error=`${e}`,t.aborted=!0),t.error}finally{delete t.initPromise}}},h=async e=>{let t=e.executionProviders||[],n=t.map(e=>typeof e==`string`?e:e.name),r=n.length===0?f:n,i,a=[],o=/* @__PURE__ */ new Set;for(let e of r){let t=await m(e);typeof t==`string`?a.push({name:e,err:t}):(i||=t,i===t&&o.add(e))}if(!i)throw Error(`no available backend found. ERR: ${a.map(e=>`[${e.name}] ${e.err}`).join(`, `)}`);for(let{name:e,err:t}of a)n.includes(e)&&console.warn(`removing requested execution provider "${e}" from session options because it is not available: ${t}`);let s=t.filter(e=>o.has(typeof e==`string`?e:e.name));return[i,new Proxy(e,{get:(e,t)=>t===`executionProviders`?s:Reflect.get(e,t)})]}}),_=s(()=>{"use strict";g()}),v,y=s(()=>{"use strict";v=`1.31.0-dev.20260911-2a43ec07e`}),b,x,S=s(()=>{"use strict";y(),b=`warning`,x={wasm:{},webgl:{},webgpu:{},versions:{common:v},set logLevel(e){if(e!==void 0){if(typeof e!=`string`||[`verbose`,`info`,`warning`,`error`,`fatal`].indexOf(e)===-1)throw Error(`Unsupported logging level: ${e}`);b=e}},get logLevel(){return b}},Object.defineProperty(x,"logLevel",{enumerable:!0})}),C,ee=s(()=>{"use strict";S(),C=x}),te,ne,re=s(()=>{"use strict";te=(e,t)=>{let n=typeof document<`u`?document.createElement(`canvas`):new OffscreenCanvas(1,1);n.width=e.dims[3],n.height=e.dims[2];let r=n.getContext(`2d`);if(r!=null){let i,a;t?.tensorLayout!==void 0&&t.tensorLayout===`NHWC`?(i=e.dims[2],a=e.dims[3]):(i=e.dims[3],a=e.dims[2]);let o=t?.format===void 0?`RGB`:t.format,s=t?.norm,c,l;s===void 0||s.mean===void 0?c=[255,255,255,255]:typeof s.mean==`number`?c=[s.mean,s.mean,s.mean,s.mean]:(c=[s.mean[0],s.mean[1],s.mean[2],0],s.mean[3]!==void 0&&(c[3]=s.mean[3])),s===void 0||s.bias===void 0?l=[0,0,0,0]:typeof s.bias==`number`?l=[s.bias,s.bias,s.bias,s.bias]:(l=[s.bias[0],s.bias[1],s.bias[2],0],s.bias[3]!==void 0&&(l[3]=s.bias[3]));let u=a*i,d=0,f=u,p=u*2,m=-1;o===`RGBA`?(d=0,f=u,p=u*2,m=u*3):o===`RGB`?(d=0,f=u,p=u*2):o===`RBG`&&(d=0,p=u,f=u*2);for(let t=0;t{let n=typeof document<`u`?document.createElement(`canvas`).getContext(`2d`):new OffscreenCanvas(1,1).getContext(`2d`),r;if(n!=null){let i,a,o;t?.tensorLayout!==void 0&&t.tensorLayout===`NHWC`?(i=e.dims[2],a=e.dims[1],o=e.dims[3]):(i=e.dims[3],a=e.dims[2],o=e.dims[1]);let s=t!==void 0&&t.format!==void 0?t.format:`RGB`,c=t?.norm,l,u;c===void 0||c.mean===void 0?l=[255,255,255,255]:typeof c.mean==`number`?l=[c.mean,c.mean,c.mean,c.mean]:(l=[c.mean[0],c.mean[1],c.mean[2],255],c.mean[3]!==void 0&&(l[3]=c.mean[3])),c===void 0||c.bias===void 0?u=[0,0,0,0]:typeof c.bias==`number`?u=[c.bias,c.bias,c.bias,c.bias]:(u=[c.bias[0],c.bias[1],c.bias[2],0],c.bias[3]!==void 0&&(u[3]=c.bias[3]));let d=a*i;if(t!==void 0&&(t.format!==void 0&&o===4&&t.format!==`RGBA`||o===3&&t.format!==`RGB`&&t.format!==`BGR`))throw Error(`Tensor format doesn't match input tensor dims`);let f=0,p=1,m=2,h=3,g=0,_=d,v=d*2,y=-1;s===`RGBA`?(g=0,_=d,v=d*2,y=d*3):s===`RGB`?(g=0,_=d,v=d*2):s===`RBG`&&(g=0,v=d,_=d*2),r=n.createImageData(i,a);for(let t=0;t{"use strict";ve(),ie=(e,t)=>{if(e===void 0)throw Error(`Image buffer must be defined`);if(t.height===void 0||t.width===void 0)throw Error(`Image height and width must be defined`);if(t.tensorLayout===`NHWC`)throw Error(`NHWC Tensor layout is not supported yet`);let{height:n,width:r}=t,i=t.norm??{mean:255,bias:0},a,o;a=typeof i.mean==`number`?[i.mean,i.mean,i.mean,i.mean]:[i.mean[0],i.mean[1],i.mean[2],i.mean[3]??255],o=typeof i.bias==`number`?[i.bias,i.bias,i.bias,i.bias]:[i.bias[0],i.bias[1],i.bias[2],i.bias[3]??0];let s=t.format===void 0?`RGBA`:t.format,c=t.tensorFormat!==void 0&&t.tensorFormat!==void 0?t.tensorFormat:`RGB`,l=n*r,u=c===`RGBA`?new Float32Array(l*4):new Float32Array(l*3),d=4,f=0,p=1,m=2,h=3,g=0,_=l,v=l*2,y=-1;s===`RGB`&&(d=3,f=0,p=1,m=2,h=-1),c===`RGBA`?y=l*3:c===`RBG`?(g=0,v=l,_=l*2):c===`BGR`&&(v=0,_=l,g=l*2);for(let t=0;t{let n=typeof HTMLImageElement<`u`&&e instanceof HTMLImageElement,r=typeof ImageData<`u`&&e instanceof ImageData,i=typeof ImageBitmap<`u`&&e instanceof ImageBitmap,a=typeof e==`string`,o,s=t??{},c=()=>{if(typeof document<`u`)return document.createElement(`canvas`);if(typeof OffscreenCanvas<`u`)return new OffscreenCanvas(1,1);throw Error(`Canvas is not supported`)},l=e=>typeof HTMLCanvasElement<`u`&&e instanceof HTMLCanvasElement||e instanceof OffscreenCanvas?e.getContext(`2d`):null;if(n){let n=c();n.width=e.width,n.height=e.height;let r=l(n);if(r!=null){let n=e.height,i=e.width;if(t!==void 0&&t.resizedHeight!==void 0&&t.resizedWidth!==void 0&&(n=t.resizedHeight,i=t.resizedWidth),t!==void 0){if(s=t,t.tensorFormat!==void 0)throw Error(`Image input config format must be RGBA for HTMLImageElement`);s.tensorFormat=`RGBA`,s.height=n,s.width=i}else s.tensorFormat=`RGBA`,s.height=n,s.width=i;r.drawImage(e,0,0),o=r.getImageData(0,0,i,n).data}else throw Error(`Can not access image data`)}else if(r){let n,r;if(t!==void 0&&t.resizedWidth!==void 0&&t.resizedHeight!==void 0?(n=t.resizedHeight,r=t.resizedWidth):(n=e.height,r=e.width),t!==void 0&&(s=t),s.format=`RGBA`,s.height=n,s.width=r,t!==void 0){let t=c();t.width=r,t.height=n;let i=l(t);if(i!=null)i.putImageData(e,0,0),o=i.getImageData(0,0,r,n).data;else throw Error(`Can not access image data`)}else o=e.data}else if(i){if(t===void 0)throw Error(`Please provide image config with format for Imagebitmap`);let n=c();n.width=e.width,n.height=e.height;let r=l(n);if(r!=null){let t=e.height,n=e.width;return r.drawImage(e,0,0,n,t),o=r.getImageData(0,0,n,t).data,s.height=t,s.width=n,ie(o,s)}throw Error(`Can not access image data`)}else{if(a)return new Promise((t,n)=>{let r=c(),i=l(r);if(!e||!i)return n();let a=new Image;a.crossOrigin=`Anonymous`,a.src=e,a.onload=()=>{r.width=a.width,r.height=a.height,i.drawImage(a,0,0,r.width,r.height);let e=i.getImageData(0,0,r.width,r.height);s.height=r.height,s.width=r.width,t(ie(e.data,s))}});throw Error(`Input data provided is not supported - aborted tensor creation`)}if(o!==void 0)return ie(o,s);throw Error(`Input data provided is not supported - aborted tensor creation`)},oe=(e,t)=>{let{width:n,height:r,download:i,dispose:a}=t;return new _e({location:`texture`,type:`float32`,texture:e,dims:[1,r,n,4],download:i,dispose:a})},se=(e,t)=>{let{dataType:n,dims:r,download:i,dispose:a}=t;return new _e({location:`gpu-buffer`,type:n??`float32`,gpuBuffer:e,dims:r,download:i,dispose:a})},ce=(e,t)=>{let{dataType:n,dims:r,download:i,dispose:a}=t;return new _e({location:`ml-tensor`,type:n??`float32`,mlTensor:e,dims:r,download:i,dispose:a})},le=(e,t,n)=>new _e({location:`cpu-pinned`,type:e,data:t,dims:n??[t.length]})}),w,T,de,fe,pe=s(()=>{"use strict";w=/* @__PURE__ */ new Map([[`float32`,Float32Array],[`uint8`,Uint8Array],[`int8`,Int8Array],[`uint16`,Uint16Array],[`int16`,Int16Array],[`int32`,Int32Array],[`bool`,Uint8Array],[`float64`,Float64Array],[`uint32`,Uint32Array],[`int4`,Uint8Array],[`uint4`,Uint8Array]]),T=/* @__PURE__ */ new Map([[Float32Array,`float32`],[Uint8Array,`uint8`],[Int8Array,`int8`],[Uint16Array,`uint16`],[Int16Array,`int16`],[Int32Array,`int32`],[Float64Array,`float64`],[Uint32Array,`uint32`]]),de=!1,fe=()=>{if(!de){de=!0;let e=typeof BigInt64Array<`u`&&BigInt64Array.from,t=typeof BigUint64Array<`u`&&BigUint64Array.from,n=globalThis.Float16Array,r=typeof n<`u`&&n.from;e&&(w.set(`int64`,BigInt64Array),T.set(BigInt64Array,`int64`)),t&&(w.set(`uint64`,BigUint64Array),T.set(BigUint64Array,`uint64`)),r?(w.set(`float16`,n),T.set(n,`float16`)):w.set(`float16`,Uint16Array)}}}),me,he,ge=s(()=>{"use strict";ve(),me=e=>{let t=1;for(let n=0;n{switch(e.location){case`cpu`:return new _e(e.type,e.data,t);case`cpu-pinned`:return new _e({location:`cpu-pinned`,data:e.data,type:e.type,dims:t});case`texture`:return new _e({location:`texture`,texture:e.texture,type:e.type,dims:t});case`gpu-buffer`:return new _e({location:`gpu-buffer`,gpuBuffer:e.gpuBuffer,type:e.type,dims:t});case`ml-tensor`:return new _e({location:`ml-tensor`,mlTensor:e.mlTensor,type:e.type,dims:t});default:throw Error(`tensorReshape: tensor location ${e.location} is not supported`)}}}),_e,ve=s(()=>{"use strict";re(),ue(),pe(),ge(),_e=class{constructor(e,t,n){fe();let r,i;if(typeof e==`object`&&`location`in e)switch(this.dataLocation=e.location,r=e.type,i=e.dims,e.location){case`cpu-pinned`:{let t=w.get(r);if(!t)throw TypeError(`unsupported type "${r}" to create tensor from pinned buffer`);if(!(e.data instanceof t))throw TypeError(`buffer should be of type ${t.name}`);this.cpuData=e.data;break}case`texture`:if(r!==`float32`)throw TypeError(`unsupported type "${r}" to create tensor from texture`);this.gpuTextureData=e.texture,this.downloader=e.download,this.disposer=e.dispose;break;case`gpu-buffer`:if(r!==`float32`&&r!==`float16`&&r!==`int32`&&r!==`int64`&&r!==`uint32`&&r!==`uint8`&&r!==`bool`&&r!==`uint4`&&r!==`int4`)throw TypeError(`unsupported type "${r}" to create tensor from gpu buffer`);this.gpuBufferData=e.gpuBuffer,this.downloader=e.download,this.disposer=e.dispose;break;case`ml-tensor`:if(r!==`float32`&&r!==`float16`&&r!==`int32`&&r!==`int64`&&r!==`uint32`&&r!==`uint64`&&r!==`int8`&&r!==`uint8`&&r!==`bool`&&r!==`uint4`&&r!==`int4`)throw TypeError(`unsupported type "${r}" to create tensor from MLTensor`);this.mlTensorData=e.mlTensor,this.downloader=e.download,this.disposer=e.dispose;break;default:throw Error(`Tensor constructor: unsupported location '${this.dataLocation}'`)}else{let a,o;if(typeof e==`string`){if(r=e,o=n,e===`string`){if(!Array.isArray(t))throw TypeError(`A string tensor's data must be a string array.`);a=t}else{let n=w.get(e);if(n===void 0)throw TypeError(`Unsupported tensor type: ${e}.`);if(Array.isArray(t)){if(e===`float16`&&n===Uint16Array||e===`uint4`||e===`int4`)throw TypeError(`Creating a ${e} tensor from number array is not supported. Please use ${n.name} as data.`);a=e===`uint64`||e===`int64`?n.from(t,BigInt):n.from(t)}else if(t instanceof n)a=t;else if(t instanceof Uint8ClampedArray){if(e===`uint8`)a=Uint8Array.from(t);else throw TypeError(`A Uint8ClampedArray tensor's data must be type of uint8`)}else if(e===`float16`&&t instanceof Uint16Array&&n!==Uint16Array)a=new globalThis.Float16Array(t.buffer,t.byteOffset,t.length);else throw TypeError(`A ${r} tensor's data must be type of ${n}`)}}else if(o=t,Array.isArray(e)){if(e.length===0)throw TypeError(`Tensor type cannot be inferred from an empty array.`);let t=typeof e[0];if(t===`string`)r=`string`,a=e;else if(t===`boolean`)r=`bool`,a=Uint8Array.from(e);else throw TypeError(`Invalid element type of data array: ${t}.`)}else if(e instanceof Uint8ClampedArray)r=`uint8`,a=Uint8Array.from(e);else{let t=T.get(e.constructor);if(t===void 0)throw TypeError(`Unsupported type for tensor data: ${e.constructor}.`);r=t,a=e}if(o===void 0)o=[a.length];else if(!Array.isArray(o))throw TypeError(`A tensor's dims must be a number array`);i=o,this.cpuData=a,this.dataLocation=`cpu`}let a=me(i);if(this.cpuData&&a!==this.cpuData.length&&(r!==`uint4`&&r!==`int4`||Math.ceil(a/2)!==this.cpuData.length))throw Error(`Tensor's size(${a}) does not match data length(${this.cpuData.length}).`);this.type=r,this.dims=i,this.size=a}static async fromImage(e,t){return ae(e,t)}static fromTexture(e,t){return oe(e,t)}static fromGpuBuffer(e,t){return se(e,t)}static fromMLTensor(e,t){return ce(e,t)}static fromPinnedBuffer(e,t,n){return le(e,t,n)}toDataURL(e){return te(this,e)}toImageData(e){return ne(this,e)}get data(){if(this.ensureValid(),!this.cpuData)throw Error("The data is not on CPU. Use `getData()` to download GPU data to CPU, or use `texture` or `gpuBuffer` property to access the GPU data directly.");return this.cpuData}get location(){return this.dataLocation}get texture(){if(this.ensureValid(),!this.gpuTextureData)throw Error(`The data is not stored as a WebGL texture.`);return this.gpuTextureData}get gpuBuffer(){if(this.ensureValid(),!this.gpuBufferData)throw Error(`The data is not stored as a WebGPU buffer.`);return this.gpuBufferData}get mlTensor(){if(this.ensureValid(),!this.mlTensorData)throw Error(`The data is not stored as a WebNN MLTensor.`);return this.mlTensorData}async getData(e){switch(this.ensureValid(),this.dataLocation){case`cpu`:case`cpu-pinned`:return this.data;case`texture`:case`gpu-buffer`:case`ml-tensor`:if(!this.downloader)throw Error(`The current tensor is not created with a specified data downloader.`);if(this.isDownloading)throw Error(`The current tensor is being downloaded.`);try{this.isDownloading=!0;let t=await this.downloader();return this.downloader=void 0,this.dataLocation=`cpu`,this.cpuData=t,e&&this.disposer&&(this.disposer(),this.disposer=void 0),t}finally{this.isDownloading=!1}default:throw Error(`cannot get data from location: ${this.dataLocation}`)}}dispose(){if(this.isDownloading)throw Error(`The current tensor is being downloaded.`);this.disposer&&=(this.disposer(),void 0),this.cpuData=void 0,this.gpuTextureData=void 0,this.gpuBufferData=void 0,this.mlTensorData=void 0,this.downloader=void 0,this.isDownloading=void 0,this.dataLocation=`none`}ensureValid(){if(this.dataLocation===`none`)throw Error(`The tensor is disposed.`)}reshape(e){if(this.ensureValid(),this.downloader||this.disposer)throw Error(`Cannot reshape a tensor that owns GPU resource.`);return he(this,e)}}}),ye,be=s(()=>{"use strict";ve(),ye=_e}),xe,Se,Ce,we,Te,Ee,De=s(()=>{"use strict";S(),xe=(e,t)=>{(typeof x.trace>`u`?!x.wasm.trace:!x.trace)||console.timeStamp(`${e}::ORT::${t}`)},Se=(e,t)=>{let n=(/* @__PURE__ */ Error()).stack?.split(/\r\n|\r|\n/g)||[],r=!1;for(let i=0;i{(typeof x.trace>`u`?!x.wasm.trace:!x.trace)||Se(`BEGIN`,e)},we=e=>{(typeof x.trace>`u`?!x.wasm.trace:!x.trace)||Se(`END`,e)},Te=e=>{(typeof x.trace>`u`?!x.wasm.trace:!x.trace)||console.time(`ORT::${e}`)},Ee=e=>{(typeof x.trace>`u`?!x.wasm.trace:!x.trace)||console.timeEnd(`ORT::${e}`)}}),Oe,ke=s(()=>{"use strict";g(),be(),De(),Oe=class e{constructor(e){this.handler=e}async run(e,t,n){Ce(),Te(`InferenceSession.run`);let r={},i={};if(typeof e!=`object`||!e||e instanceof ye||Array.isArray(e))throw TypeError(`'feeds' must be an object that use input names as keys and OnnxValue as corresponding values.`);let a=!0;if(typeof t==`object`){if(t===null)throw TypeError(`Unexpected argument[1]: cannot be null.`);if(t instanceof ye)throw TypeError(`'fetches' cannot be a Tensor`);if(Array.isArray(t)){if(t.length===0)throw TypeError(`'fetches' cannot be an empty array.`);a=!1;for(let e of t){if(typeof e!=`string`)throw TypeError(`'fetches' must be a string array or an object.`);if(this.outputNames.indexOf(e)===-1)throw RangeError(`'fetches' contains invalid output name: ${e}.`);r[e]=null}if(typeof n==`object`&&n)i=n;else if(typeof n<`u`)throw TypeError(`'options' must be an object.`)}else{let e=!1,o=Object.getOwnPropertyNames(t);for(let n of this.outputNames)if(o.indexOf(n)!==-1){let i=t[n];(i===null||i instanceof ye)&&(e=!0,a=!1,r[n]=i)}if(e){if(typeof n==`object`&&n)i=n;else if(typeof n<`u`)throw TypeError(`'options' must be an object.`)}else i=t}}else if(typeof t<`u`)throw TypeError(`Unexpected argument[1]: must be 'fetches' or 'options'.`);for(let t of this.inputNames)if(typeof e[t]>`u`)throw Error(`input '${t}' is missing in 'feeds'.`);if(a)for(let e of this.outputNames)r[e]=null;let o=await this.handler.run(e,r,i),s={};for(let e in o)if(Object.hasOwnProperty.call(o,e)){let t=o[e];s[e]=t instanceof ye?t:new ye(t.type,t.data,t.dims)}return Ee(`InferenceSession.run`),we(),s}async release(){return this.handler.dispose()}static async create(t,n,r,i){Ce(),Te(`InferenceSession.create`);let a,o={};if(typeof t==`string`){if(a=t,typeof n==`object`&&n)o=n;else if(typeof n<`u`)throw TypeError(`'options' must be an object.`)}else if(t instanceof Uint8Array){if(a=t,typeof n==`object`&&n)o=n;else if(typeof n<`u`)throw TypeError(`'options' must be an object.`)}else if(t instanceof ArrayBuffer||typeof SharedArrayBuffer<`u`&&t instanceof SharedArrayBuffer){let e=t,s=0,c=t.byteLength;if(typeof n==`object`&&n)o=n;else if(typeof n==`number`){if(s=n,!Number.isSafeInteger(s))throw RangeError(`'byteOffset' must be an integer.`);if(s<0||s>=e.byteLength)throw RangeError(`'byteOffset' is out of range [0, ${e.byteLength}).`);if(c=t.byteLength-s,typeof r==`number`){if(c=r,!Number.isSafeInteger(c))throw RangeError(`'byteLength' must be an integer.`);if(c<=0||s+c>e.byteLength)throw RangeError(`'byteLength' is out of range (0, ${e.byteLength-s}].`);if(typeof i==`object`&&i)o=i;else if(typeof i<`u`)throw TypeError(`'options' must be an object.`)}else if(typeof r<`u`)throw TypeError(`'byteLength' must be a number.`)}else if(typeof n<`u`)throw TypeError(`'options' must be an object.`);a=new Uint8Array(e,s,c)}else throw TypeError(`Unexpected argument[0]: must be 'path' or 'buffer'.`);let[s,c]=await h(o),l=await s.createInferenceSessionHandler(a,c);return Ee(`InferenceSession.create`),we(),new e(l)}startProfiling(){this.handler.startProfiling()}endProfiling(){this.handler.endProfiling()}get inputNames(){return this.handler.inputNames}get outputNames(){return this.handler.outputNames}get inputMetadata(){return this.handler.inputMetadata}get outputMetadata(){return this.handler.outputMetadata}}}),Ae,je=s(()=>{"use strict";ke(),Ae=Oe}),Me=s(()=>{"use strict";}),Ne=s(()=>{"use strict";}),Pe=s(()=>{"use strict";}),Fe=s(()=>{"use strict";}),Ie={};c(Ie,{InferenceSession:()=>Ae,TRACE:()=>xe,TRACE_EVENT_BEGIN:()=>Te,TRACE_EVENT_END:()=>Ee,TRACE_FUNC_BEGIN:()=>Ce,TRACE_FUNC_END:()=>we,Tensor:()=>ye,env:()=>C,registerBackend:()=>p});var Le=s(()=>{"use strict";_(),ee(),je(),be(),Me(),Ne(),De(),Pe(),Fe()}),Re=s(()=>{"use strict";}),ze={};c(ze,{default:()=>He});var Be,Ve,He,Ue=s(()=>{"use strict";Tn(),pt(),it(),Be=`ort-wasm-proxy-worker`,Ve=globalThis.self?.name===Be,Ve&&(self.onmessage=e=>{let{type:t,in:n}=e.data;try{switch(t){case`init-wasm`:ft(n.wasm).then(()=>{pn(n).then(()=>{postMessage({type:t})},e=>{postMessage({type:t,err:e})})},e=>{postMessage({type:t,err:e})});break;case`init-ep`:{let{epName:e,env:r}=n;mn(r,e).then(()=>{postMessage({type:t})},e=>{postMessage({type:t,err:e})});break}case`copy-from`:{let{buffer:e}=n,r=vn(e);postMessage({type:t,out:r});break}case`create`:{let{model:e,options:r}=n;yn(e,r).then(e=>{postMessage({type:t,out:e})},e=>{postMessage({type:t,err:e})});break}case`release`:bn(n),postMessage({type:t});break;case`run`:{let{sessionId:e,inputIndices:r,inputs:i,outputIndices:a,options:o}=n;Sn(e,r,i,a,Array(a.length).fill(null),o).then(e=>{e.some(e=>e[3]!==`cpu`)?postMessage({type:t,err:`Proxy does not support non-cpu tensor location.`}):postMessage({type:t,out:e},wn([...i,...e]))},e=>{postMessage({type:t,err:e})});break}case`end-profiling`:Cn(n),postMessage({type:t})}}catch(e){postMessage({type:t,err:e})}}),He=Ve?null:e=>new Worker(e??qe,{type:`module`,name:Be})}),We,Ge,Ke,qe,Je,Ye,Xe,Ze,Qe,$e,et,tt,nt,rt,it=s(()=>{"use strict";Re(),We=typeof location>`u`?void 0:location.origin,Ge=self.location.href>`file:`&&self.location.href<`file;`,Ke=()=>Ge?new URL(new URL(`ort.webgpu.min.mjs`,self.location.href).href,We).href:self.location.href,qe=Ke(),Je=()=>{if(qe&&!qe.startsWith(`blob:`))return qe.substring(0,qe.lastIndexOf(`/`)+1)},Ye=(e,t)=>{try{let n=t??qe;return(n?new URL(e,n):new URL(e)).origin===We}catch{return!1}},Xe=(e,t)=>{let n=t??qe;try{return(n?new URL(e,n):new URL(e)).href}catch{return}},Ze=(e,t)=>`${t??`./`}${e}`,Qe=async e=>{let t=await(await fetch(e,{credentials:`same-origin`})).blob();return URL.createObjectURL(t)},$e=async e=>(await import( +/*webpackIgnore:true*/ +/*@vite-ignore*/ +e)).default,et=(Ue(),u(ze)).default,tt=async()=>{if(!qe)throw Error(`Failed to load proxy worker: cannot determine the script source URL.`);if(Ye(qe))return[void 0,et()];let e=await Qe(qe);return[e,et(e)]},nt=void 0,rt=async(e,t,n,r)=>{let i=nt&&!(e||t);if(i){if(qe)i=Ye(qe)||r&&!n;else if(r&&!n)i=!0;else throw Error(`cannot determine the script source URL.`)}if(i)return[void 0,nt];{let r=`ort-wasm-simd-threaded.asyncify.mjs`,i=e??Xe(r,t),a=n&&i&&!Ye(i,t),o=a?await Qe(i):i??Ze(r,t);return[a?o:void 0,await $e(o)]}}}),at,ot,st,ct,lt,ut,dt,ft,E,pt=s(()=>{"use strict";it(),ot=!1,st=!1,ct=!1,lt=()=>{if(typeof SharedArrayBuffer>`u`)return!1;try{return typeof MessageChannel<`u`&&new MessageChannel().port1.postMessage(new SharedArrayBuffer(1)),WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,5,4,1,3,1,1,10,11,1,9,0,65,0,254,16,2,0,26,11]))}catch{return!1}},ut=()=>{try{return WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,10,30,1,28,0,65,0,253,15,253,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,253,186,1,26,11]))}catch{return!1}},dt=()=>{try{return WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,5,1,96,0,1,123,3,2,1,0,10,19,1,17,0,65,1,253,15,65,2,253,15,65,3,253,15,253,147,2,11]))}catch{return!1}},ft=async e=>{if(ot)return Promise.resolve();if(st)throw Error(`multiple calls to 'initializeWebAssembly()' detected.`);if(ct)throw Error(`previous call to 'initializeWebAssembly()' failed.`);st=!0;let t=e.initTimeout,n=e.numThreads;if(e.simd!==!1){if(e.simd===`relaxed`){if(!dt())throw Error(`Relaxed WebAssembly SIMD is not supported in the current environment.`)}else if(!ut())throw Error(`WebAssembly SIMD is not supported in the current environment.`)}let r=lt();n>1&&!r&&(typeof self<`u`&&!self.crossOriginIsolated&&console.warn(`env.wasm.numThreads is set to `+n+`, but this will not work unless you enable crossOriginIsolated mode. See https://web.dev/cross-origin-isolation-guide/ for more info.`),console.warn(`WebAssembly multi-threading is not supported in the current environment. Falling back to single-threading.`),e.numThreads=n=1);let i=e.wasmPaths,a=typeof i==`string`?i:void 0,o=i?.mjs,s=o?.href??o,c=i?.wasm,l=c?.href??c,u=e.wasmBinary,[d,f]=await rt(s,a,n>1,!!u||!!l),p=!1,m=[];if(t>0&&m.push(new Promise(e=>{setTimeout(()=>{p=!0,e()},t)})),m.push(new Promise((e,t)=>{let r={numThreads:n};if(u)r.wasmBinary=u,r.locateFile=e=>e;else if(l||a)r.locateFile=e=>l??a+e;else if(s&&s.indexOf(`blob:`)!==0)r.locateFile=e=>new URL(e,s).href;else if(d){let e=Je();e&&(r.locateFile=t=>e+t)}f(r).then(t=>{st=!1,ot=!0,at=t,e(),d&&URL.revokeObjectURL(d)},e=>{st=!1,ct=!0,t(e)})})),await Promise.race(m),p)throw Error(`WebAssembly backend initializing failed due to timeout: ${t}ms`)},E=()=>{if(ot&&at)return at;throw Error(`WebAssembly is not initialized yet.`)}}),mt,ht,D,gt=s(()=>{"use strict";pt(),mt=(e,t)=>{let n=E(),r=n.lengthBytesUTF8(e)+1,i=n._malloc(r);return n.stringToUTF8(e,i,r),t.push(i),i},ht=(e,t,n,r)=>{if(typeof e==`object`&&e){if(n.has(e))throw Error(`Circular reference in options`);n.add(e)}Object.entries(e).forEach(([e,i])=>{let a=t?t+e:e;if(typeof i==`object`)ht(i,a+`.`,n,r);else if(typeof i==`string`||typeof i==`number`)r(a,i.toString());else if(typeof i==`boolean`)r(a,i?`1`:`0`);else throw Error(`Can't handle extra config type: ${typeof i}`)})},D=e=>{let t=E(),n=t.stackSave();try{let n=t.PTR_SIZE,r=t.stackAlloc(2*n);t._OrtGetLastError(r,r+n);let i=Number(t.getValue(r,n===4?`i32`:`i64`)),a=t.getValue(r+n,`*`),o=a?t.UTF8ToString(a):``;throw Error(`${e} ERROR_CODE: ${i}, ERROR_MESSAGE: ${o}`)}finally{t.stackRestore(n)}}}),_t,vt=s(()=>{"use strict";pt(),gt(),_t=e=>{let t=E(),n=0,r=[],i=e||{};try{if(e?.logSeverityLevel===void 0)i.logSeverityLevel=2;else if(typeof e.logSeverityLevel!=`number`||!Number.isInteger(e.logSeverityLevel)||e.logSeverityLevel<0||e.logSeverityLevel>4)throw Error(`log severity level is not valid: ${e.logSeverityLevel}`);if(e?.logVerbosityLevel===void 0)i.logVerbosityLevel=0;else if(typeof e.logVerbosityLevel!=`number`||!Number.isInteger(e.logVerbosityLevel))throw Error(`log verbosity level is not valid: ${e.logVerbosityLevel}`);e?.terminate===void 0&&(i.terminate=!1);let a=0;return e?.tag!==void 0&&(a=mt(e.tag,r)),n=t._OrtCreateRunOptions(i.logSeverityLevel,i.logVerbosityLevel,!!i.terminate,a),n===0&&D(`Can't create run options.`),e?.extra!==void 0&&ht(e.extra,``,/* @__PURE__ */ new WeakSet,(e,i)=>{let a=mt(e,r),o=mt(i,r);t._OrtAddRunConfigEntry(n,a,o)!==0&&D(`Can't set a run config entry: ${e} - ${i}.`)}),[n,r]}catch(e){throw n!==0&&t._OrtReleaseRunOptions(n),r.forEach(e=>t._free(e)),e}}}),yt,bt,xt,St,Ct,wt,Tt,Et=s(()=>{"use strict";pt(),gt(),yt=e=>{switch(e){case`disabled`:return 0;case`basic`:return 1;case`extended`:return 2;case`layout`:return 3;case`all`:return 99;default:throw Error(`unsupported graph optimization level: ${e}`)}},bt=e=>{switch(e){case`sequential`:return 0;case`parallel`:return 1;default:throw Error(`unsupported execution mode: ${e}`)}},xt=e=>{e.extra||={},e.extra.session||(e.extra.session={});let t=e.extra.session;t.use_ort_model_bytes_directly||=`1`,e.executionProviders&&e.executionProviders.some(e=>(typeof e==`string`?e:e.name)===`webgpu`)&&(e.enableMemPattern=!1)},St=(e,t,n,r)=>{let i=mt(t,r),a=mt(n,r);E()._OrtAddSessionConfigEntry(e,i,a)!==0&&D(`Can't set a session config entry: ${t} - ${n}.`)},Ct=(e,t,n,r)=>{let i=mt(t,r),a=mt(n,r);e.push([i,a])},wt=async(e,t,n)=>{let r=t.executionProviders;for(let i of r){let r=typeof i==`string`?i:i.name,a=[];switch(r){case`webnn`:if(r=`WEBNN`,St(e,`session.disable_quant_qdq`,`1`,n),St(e,`session.disable_qdq_constant_folding`,`1`,n),typeof i!=`string`){let t=i?.deviceType;t&&St(e,`deviceType`,t,n)}break;case`webgpu`:{r=`WebGPU`;let e;if(typeof i!=`string`){let r=i;if(r.device){if(typeof GPUDevice<`u`&&r.device instanceof GPUDevice)e=r.device;else throw Error(`Invalid GPU device set in WebGPU EP options.`)}let{enableGraphCapture:o}=t;if(typeof o==`boolean`&&o&&Ct(a,`enableGraphCapture`,`1`,n),typeof r.preferredLayout==`string`&&Ct(a,`preferredLayout`,r.preferredLayout,n),r.forceCpuNodeNames){let e=Array.isArray(r.forceCpuNodeNames)?r.forceCpuNodeNames:[r.forceCpuNodeNames];Ct(a,`forceCpuNodeNames`,e.join(` +`),n)}r.validationMode&&Ct(a,`validationMode`,r.validationMode,n),typeof r.enableMatmulFp32Accumulation==`boolean`&&Ct(a,`enableMatmulFp32Accumulation`,r.enableMatmulFp32Accumulation?`1`:`0`,n);for(let e of[`storageBufferCacheMode`,`uniformBufferCacheMode`,`queryResolveBufferCacheMode`,`defaultBufferCacheMode`]){let t=r[e];if(t){if(t!==`disabled`&&t!==`lazyRelease`&&t!==`simple`&&t!==`bucket`)throw Error(`${e} must be one of 'disabled', 'lazyRelease', 'simple' or 'bucket': ${t}`);Ct(a,e,t,n)}}}let o=E().webgpuRegisterDevice(e);if(o){let[e,t,r]=o;Ct(a,`deviceId`,e.toString(),n),Ct(a,`webgpuInstance`,t.toString(),n),Ct(a,`webgpuDevice`,r.toString(),n)}}break;case`wasm`:case`cpu`:continue;default:throw Error(`not supported execution provider: ${r}`)}let o=mt(r,n),s=a.length,c=0,l=0;if(s>0){c=E()._malloc(s*E().PTR_SIZE),n.push(c),l=E()._malloc(s*E().PTR_SIZE),n.push(l);for(let e=0;e{let t=E(),n=0,r=[],i=e||{};xt(i);try{let e=yt(i.graphOptimizationLevel??`all`),a=bt(i.executionMode??`sequential`),o=typeof i.logId==`string`?mt(i.logId,r):0,s=i.logSeverityLevel??2;if(!Number.isInteger(s)||s<0||s>4)throw Error(`log severity level is not valid: ${s}`);let c=i.logVerbosityLevel??0;if(!Number.isInteger(c)||c<0||c>4)throw Error(`log verbosity level is not valid: ${c}`);let l=typeof i.optimizedModelFilePath==`string`?mt(i.optimizedModelFilePath,r):0;if(n=t._OrtCreateSessionOptions(e,!!i.enableCpuMemArena,!!i.enableMemPattern,a,!!i.enableProfiling,0,o,s,c,l),n===0&&D(`Can't create session options.`),i.executionProviders&&await wt(n,i,r),i.enableGraphCapture!==void 0){if(typeof i.enableGraphCapture!=`boolean`)throw Error(`enableGraphCapture must be a boolean value: ${i.enableGraphCapture}`);St(n,`enableGraphCapture`,i.enableGraphCapture.toString(),r)}if(i.freeDimensionOverrides)for(let[e,a]of Object.entries(i.freeDimensionOverrides)){if(typeof e!=`string`)throw Error(`free dimension override name must be a string: ${e}`);if(typeof a!=`number`||!Number.isInteger(a)||a<0)throw Error(`free dimension override value must be a non-negative integer: ${a}`);let i=mt(e,r);t._OrtAddFreeDimensionOverride(n,i,a)!==0&&D(`Can't set a free dimension override: ${e} - ${a}.`)}return i.extra!==void 0&&ht(i.extra,``,/* @__PURE__ */ new WeakSet,(e,t)=>{St(n,e,t,r)}),[n,r]}catch(e){throw n!==0&&t._OrtReleaseSessionOptions(n)!==0&&D(`Can't release session options.`),r.forEach(e=>t._free(e)),e}}}),Dt,Ot,kt,At,jt,Mt,Nt,Pt,Ft=s(()=>{"use strict";Dt=e=>{switch(e){case`int8`:return 3;case`uint8`:return 2;case`bool`:return 9;case`int16`:return 5;case`uint16`:return 4;case`int32`:return 6;case`uint32`:return 12;case`float16`:return 10;case`float32`:return 1;case`float64`:return 11;case`string`:return 8;case`int64`:return 7;case`uint64`:return 13;case`int4`:return 22;case`uint4`:return 21;default:throw Error(`unsupported data type: ${e}`)}},Ot=e=>{switch(e){case 3:return`int8`;case 2:return`uint8`;case 9:return`bool`;case 5:return`int16`;case 4:return`uint16`;case 6:return`int32`;case 12:return`uint32`;case 10:return`float16`;case 1:return`float32`;case 11:return`float64`;case 8:return`string`;case 7:return`int64`;case 13:return`uint64`;case 22:return`int4`;case 21:return`uint4`;default:throw Error(`unsupported data type: ${e}`)}},kt=(e,t)=>{let n=[-1,4,1,1,2,2,4,8,-1,1,2,8,4,8,-1,-1,-1,-1,-1,-1,-1,.5,.5][e],r=typeof t==`number`?t:t.reduce((e,t)=>e*t,1);return n>0?Math.ceil(r*n):void 0},At=e=>{switch(e){case`float16`:return typeof Float16Array<`u`?Float16Array:Uint16Array;case`float32`:return Float32Array;case`uint8`:return Uint8Array;case`int8`:return Int8Array;case`uint16`:return Uint16Array;case`int16`:return Int16Array;case`int32`:return Int32Array;case`bool`:return Uint8Array;case`float64`:return Float64Array;case`uint32`:return Uint32Array;case`int64`:return BigInt64Array;case`uint64`:return BigUint64Array;default:throw Error(`unsupported type: ${e}`)}},jt=e=>{switch(e){case`verbose`:return 0;case`info`:return 1;case`warning`:return 2;case`error`:return 3;case`fatal`:return 4;default:throw Error(`unsupported logging level: ${e}`)}},Mt=e=>e===`float32`||e===`float16`||e===`int32`||e===`int64`||e===`uint32`||e===`uint8`||e===`bool`||e===`uint4`||e===`int4`,Nt=e=>e===`float32`||e===`float16`||e===`int32`||e===`int64`||e===`uint32`||e===`uint64`||e===`int8`||e===`uint8`||e===`bool`||e===`uint4`||e===`int4`,Pt=e=>{switch(e){case`none`:return 0;case`cpu`:return 1;case`cpu-pinned`:return 2;case`texture`:return 3;case`gpu-buffer`:return 4;case`ml-tensor`:return 5;default:throw Error(`unsupported data location: ${e}`)}}}),It,Lt=s(()=>{"use strict";Re(),It=async e=>{if(typeof e==`string`){let t=await fetch(e);if(!t.ok)throw Error(`failed to load external data file: ${e}`);let n=t.headers.get(`Content-Length`),r=n?parseInt(n,10):0;if(r<1073741824)return new Uint8Array(await t.arrayBuffer());{if(!t.body)throw Error(`failed to load external data file: ${e}, no response body.`);let n=t.body.getReader(),i;try{i=new ArrayBuffer(r)}catch(e){if(e instanceof RangeError){let e=Math.ceil(r/65536);i=new WebAssembly.Memory({initial:e,maximum:e}).buffer}else throw e}let a=0;for(;;){let{done:e,value:t}=await n.read();if(e)break;let r=t.byteLength;new Uint8Array(i,a,r).set(t),a+=r}return new Uint8Array(i,0,r)}}return e instanceof Blob?new Uint8Array(await e.arrayBuffer()):e instanceof Uint8Array?e:new Uint8Array(e)}}),Rt,zt=s(()=>{"use strict";Ft(),Rt=(e,t)=>new(At(t))(e)}),Bt,Vt,Ht,Ut,Wt,Gt,Kt,qt=s(()=>{"use strict";Ft(),Bt=[`V`,`I`,`W`,`E`,`F`],Vt=(e,t)=>{console.log(`[${Bt[e]},${(/* @__PURE__ */ new Date()).toISOString()}]${t}`)},Wt=(e,t)=>{Ht=e,Ut=t},Gt=(e,t)=>{let n=jt(e);n>=jt(Ht)&&Vt(n,typeof t==`function`?t():t)},Kt=(...e)=>{Ut&&Gt(...e)}}),Jt,Yt,Xt,Zt,Qt,$t,en,tn,nn,rn,an,on=s(()=>{"use strict";Ft(),qt(),Jt=/* @__PURE__ */ new Map([[`float32`,32],[`float16`,16],[`int32`,32],[`uint32`,32],[`int64`,64],[`uint64`,64],[`int8`,8],[`uint8`,8],[`int4`,4],[`uint4`,4]]),Yt=(e,t)=>{if(t===`int32`)return e;let n=Jt.get(t);if(!n)throw Error(`WebNN backend does not support data type: ${t}`);let r=n/8;if(e.byteLength%r!==0)throw Error(`Invalid Uint8Array length - must be a multiple of ${r}.`);let i=e.byteLength/r,a=new(At(t))(e.buffer,e.byteOffset,i);switch(t){case`int64`:case`uint64`:{let e=new Int32Array(i);for(let t=0;t2147483647n||n<-2147483648n)throw Error(`Can not convert int64 data to int32 - value out of range.`);e[t]=Number(n)}return new Uint8Array(e.buffer)}case`int8`:case`uint8`:case`uint32`:{if(t===`uint32`&&a.some(e=>e>2147483647))throw Error(`Can not convert uint32 data to int32 - value out of range.`);let e=Int32Array.from(a,Number);return new Uint8Array(e.buffer)}default:throw Error(`Unsupported data conversion from ${t} to 'int32'`)}},Xt=(e,t)=>{if(t===`int32`)return e;if(e.byteLength%4!=0)throw Error(`Invalid Uint8Array length - must be a multiple of 4 (int32).`);let n=e.byteLength/4,r=new Int32Array(e.buffer,e.byteOffset,n);switch(t){case`int64`:{let e=BigInt64Array.from(r,BigInt);return new Uint8Array(e.buffer)}case`uint64`:{if(r.some(e=>e<0))throw Error(`Can not convert int32 data to uin64 - negative value found.`);let e=BigUint64Array.from(r,BigInt);return new Uint8Array(e.buffer)}case`int8`:{if(r.some(e=>e<-128||e>127))throw Error(`Can not convert int32 data to int8 - value out of range.`);let e=Int8Array.from(r,Number);return new Uint8Array(e.buffer)}case`uint8`:if(r.some(e=>e<0||e>255))throw Error(`Can not convert int32 data to uint8 - value out of range.`);return Uint8Array.from(r,Number);case`uint32`:{if(r.some(e=>e<0))throw Error(`Can not convert int32 data to uint32 - negative value found.`);let e=Uint32Array.from(r,Number);return new Uint8Array(e.buffer)}default:throw Error(`Unsupported data conversion from 'int32' to ${t}`)}},Zt=1,Qt=()=>Zt++,$t=/* @__PURE__ */ new Map([[`int8`,`int32`],[`uint8`,`int32`],[`uint32`,`int32`],[`int64`,`int32`]]),en=(e,t)=>{let n=Jt.get(e);if(!n)throw Error(`WebNN backend does not support data type: ${e}`);return t.length>0?Math.ceil(t.reduce((e,t)=>e*t)*n/8):0},tn=class{constructor(e){this.isDataConverted=!1;let{sessionId:t,context:n,tensor:r,dataType:i,shape:a,fallbackDataType:o}=e;this.sessionId=t,this.mlContext=n,this.mlTensor=r,this.dataType=i,this.tensorShape=a,this.fallbackDataType=o}get tensor(){return this.mlTensor}get type(){return this.dataType}get fallbackType(){return this.fallbackDataType}get shape(){return this.tensorShape}get byteLength(){return en(this.dataType,this.tensorShape)}destroy(){Kt(`verbose`,()=>`[WebNN] TensorWrapper.destroy`),this.mlTensor.destroy()}write(e){this.mlContext.writeTensor(this.mlTensor,e)}async read(e){if(this.fallbackDataType){let t=await this.mlContext.readTensor(this.mlTensor),n=Xt(new Uint8Array(t),this.dataType);if(e){(e instanceof ArrayBuffer?new Uint8Array(e):new Uint8Array(e.buffer,e.byteOffset,e.byteLength)).set(n);return}return new Uint8Array(n).buffer}return e?this.mlContext.readTensor(this.mlTensor,e):this.mlContext.readTensor(this.mlTensor)}canReuseTensor(e,t,n){return this.mlContext===e&&this.dataType===t&&this.tensorShape.length===n.length&&this.tensorShape.every((e,t)=>e===n[t])}setIsDataConverted(e){this.isDataConverted=e}},nn=class{constructor(e,t){this.tensorManager=e,this.wrapper=t}get tensorWrapper(){return this.wrapper}releaseTensor(){this.tensorWrapper&&(this.tensorManager.releaseTensor(this.tensorWrapper),this.wrapper=void 0)}async ensureTensor(e,t,n,r){let i=this.tensorManager.getMLContext(e),a=this.tensorManager.getMLOpSupportLimits(e),o;if(!a?.input.dataTypes.includes(t)){if(o=$t.get(t),!o||!a?.input.dataTypes.includes(o))throw Error(`WebNN backend does not support data type: ${t}`);Kt(`verbose`,()=>`[WebNN] TensorIdTracker.ensureTensor: fallback dataType from ${t} to ${o}`)}if(this.wrapper){if(this.wrapper.canReuseTensor(i,t,n))return this.wrapper.tensor;if(r){if(this.wrapper.byteLength!==en(t,n))throw Error(`Unable to copy data to tensor with different size.`);this.activeUpload=new Uint8Array(await this.wrapper.read())}this.tensorManager.releaseTensor(this.wrapper)}let s=typeof MLTensorUsage>`u`?void 0:MLTensorUsage.READ|MLTensorUsage.WRITE;return this.wrapper=await this.tensorManager.getCachedTensor(e,t,n,s,!0,!0,o),r&&this.activeUpload&&(this.wrapper.write(this.activeUpload),this.activeUpload=void 0),this.wrapper.tensor}upload(e){let t=e;if(this.wrapper){if(this.wrapper.fallbackType){if(this.wrapper.fallbackType===`int32`)t=Yt(e,this.wrapper.type),this.wrapper.setIsDataConverted(!0);else throw Error(`Unsupported fallback data type: ${this.wrapper.fallbackType}`)}if(e.byteLength===this.wrapper.byteLength){this.wrapper.write(t);return}Kt(`verbose`,()=>`Data size does not match tensor size. Releasing tensor.`),this.releaseTensor()}this.activeUpload?this.activeUpload.set(t):this.activeUpload=new Uint8Array(t)}async download(e){if(this.activeUpload){let t=this.wrapper?.isDataConverted?Xt(this.activeUpload,this.wrapper?.type):this.activeUpload;if(e){e instanceof ArrayBuffer?new Uint8Array(e).set(t):new Uint8Array(e.buffer,e.byteOffset,e.byteLength).set(t);return}return t.buffer}if(!this.wrapper)throw Error(`Tensor has not been created.`);return e?this.wrapper.read(e):this.wrapper.read()}},rn=class{constructor(e){this.backend=e,this.tensorTrackersById=/* @__PURE__ */ new Map,this.freeTensors=[],this.externalTensors=/* @__PURE__ */ new Set}getMLContext(e){let t=this.backend.getMLContext(e);if(!t)throw Error(`MLContext not found for session.`);return t}getMLOpSupportLimits(e){return this.backend.getMLOpSupportLimits(e)}reserveTensorId(){let e=Qt();return this.tensorTrackersById.set(e,new nn(this)),e}releaseTensorId(e){let t=this.tensorTrackersById.get(e);t&&(this.tensorTrackersById.delete(e),t.tensorWrapper&&this.releaseTensor(t.tensorWrapper))}async ensureTensor(e,t,n,r,i){Kt(`verbose`,()=>`[WebNN] TensorManager.ensureTensor {tensorId: ${t}, dataType: ${n}, shape: ${r}, copyOld: ${i}}`);let a=this.tensorTrackersById.get(t);if(!a)throw Error(`Tensor not found.`);return a.ensureTensor(e,n,r,i)}upload(e,t){let n=this.tensorTrackersById.get(e);if(!n)throw Error(`Tensor not found.`);n.upload(t)}async download(e,t){Kt(`verbose`,()=>`[WebNN] TensorManager.download {tensorId: ${e}, dstBuffer: ${t?.byteLength}}`);let n=this.tensorTrackersById.get(e);if(!n)throw Error(`Tensor not found.`);return n.download(t)}releaseTensorsForSession(e){for(let t of this.freeTensors)t.sessionId===e&&t.destroy();this.freeTensors=this.freeTensors.filter(t=>t.sessionId!==e)}registerTensor(e,t,n,r){let i=this.getMLContext(e),a=Qt(),o=new tn({sessionId:e,context:i,tensor:t,dataType:n,shape:r});return this.tensorTrackersById.set(a,new nn(this,o)),this.externalTensors.add(o),a}async getCachedTensor(e,t,n,r,i,a,o){let s=this.getMLContext(e);for(let[r,i]of this.freeTensors.entries())if(i.canReuseTensor(s,t,n)){Kt(`verbose`,()=>`[WebNN] Reusing tensor {dataType: ${t}, ${o?`fallbackDataType: ${o},`:``} shape: ${n}`);let i=this.freeTensors.splice(r,1)[0];return i.sessionId=e,i}Kt(`verbose`,()=>`[WebNN] MLContext.createTensor {dataType: ${t}, ${o?`fallbackDataType: ${o},`:``} shape: ${n}}`);let c=await s.createTensor({dataType:o??t,shape:n,dimensions:n,usage:r,writable:i,readable:a});return new tn({sessionId:e,context:s,tensor:c,dataType:t,shape:n,fallbackDataType:o})}releaseTensor(e){this.externalTensors.has(e)&&this.externalTensors.delete(e),this.freeTensors.push(e)}},an=(...e)=>new rn(...e)}),sn={};c(sn,{WebNNBackend:()=>un});var cn,ln,un,dn=s(()=>{"use strict";Ft(),pt(),zt(),on(),qt(),cn=/* @__PURE__ */ new Map([[1,`float32`],[10,`float16`],[6,`int32`],[12,`uint32`],[7,`int64`],[13,`uint64`],[22,`int4`],[21,`uint4`],[3,`int8`],[2,`uint8`],[9,`uint8`]]),ln=(e,t)=>{if(e===t)return!0;if(e===void 0||t===void 0)return!1;let n=Object.keys(e).sort(),r=Object.keys(t).sort();return n.length===r.length&&n.every((n,i)=>n===r[i]&&e[n]===t[n])},un=class{constructor(e){this.tensorManager=an(this),this.mlContextBySessionId=/* @__PURE__ */ new Map,this.sessionIdsByMLContext=/* @__PURE__ */ new Map,this.mlContextCache=[],this.sessionGraphInputs=/* @__PURE__ */ new Map,this.sessionGraphOutputs=/* @__PURE__ */ new Map,this.temporaryGraphInputs=[],this.temporaryGraphOutputs=[],this.temporarySessionTensorIds=/* @__PURE__ */ new Map,this.mlOpSupportLimitsBySessionId=/* @__PURE__ */ new Map,Wt(e.logLevel,!!e.debug)}get currentSessionId(){if(this.activeSessionId===void 0)throw Error(`No active session`);return this.activeSessionId}onRunStart(e){Kt(`verbose`,()=>`[WebNN] onRunStart {sessionId: ${e}}`),this.activeSessionId=e}onRunEnd(e){Kt(`verbose`,()=>`[WebNN] onRunEnd {sessionId: ${e}}`);let t=this.temporarySessionTensorIds.get(e);if(t){for(let e of t)Kt(`verbose`,()=>`[WebNN] releasing temporary tensor {tensorId: ${e}}`),this.tensorManager.releaseTensorId(e);this.temporarySessionTensorIds.delete(e),this.activeSessionId=void 0}}async createMLContext(e){if(e instanceof GPUDevice){let t=this.mlContextCache.findIndex(t=>t.gpuDevice===e);if(t!==-1)return this.mlContextCache[t].mlContext;{let t=await navigator.ml.createContext(e);return this.mlContextCache.push({gpuDevice:e,mlContext:t}),t}}if(e===void 0){let e=this.mlContextCache.findIndex(e=>e.options===void 0&&e.gpuDevice===void 0);if(e!==-1)return this.mlContextCache[e].mlContext;{let e=await navigator.ml.createContext();return this.mlContextCache.push({mlContext:e}),e}}let t=this.mlContextCache.findIndex(t=>ln(t.options,e));if(t!==-1)return this.mlContextCache[t].mlContext;{let t=await navigator.ml.createContext(e);return this.mlContextCache.push({options:e,mlContext:t}),t}}registerMLContext(e,t){this.mlContextBySessionId.set(e,t);let n=this.sessionIdsByMLContext.get(t);n||(n=/* @__PURE__ */ new Set,this.sessionIdsByMLContext.set(t,n)),n.add(e),this.mlOpSupportLimitsBySessionId.has(e)||this.mlOpSupportLimitsBySessionId.set(e,t.opSupportLimits()),this.temporaryGraphInputs.length>0&&(this.sessionGraphInputs.set(e,this.temporaryGraphInputs),this.temporaryGraphInputs=[]),this.temporaryGraphOutputs.length>0&&(this.sessionGraphOutputs.set(e,this.temporaryGraphOutputs),this.temporaryGraphOutputs=[])}onReleaseSession(e){this.sessionGraphInputs.delete(e),this.sessionGraphOutputs.delete(e);let t=this.mlContextBySessionId.get(e);if(!t)return;this.tensorManager.releaseTensorsForSession(e),this.mlContextBySessionId.delete(e),this.mlOpSupportLimitsBySessionId.delete(e);let n=this.sessionIdsByMLContext.get(t);if(n.delete(e),n.size===0){this.sessionIdsByMLContext.delete(t);let e=this.mlContextCache.findIndex(e=>e.mlContext===t);e!==-1&&this.mlContextCache.splice(e,1)}}getMLContext(e){return this.mlContextBySessionId.get(e)}getMLOpSupportLimits(e){return this.mlOpSupportLimitsBySessionId.get(e)}reserveTensorId(){return this.tensorManager.reserveTensorId()}releaseTensorId(e){Kt(`verbose`,()=>`[WebNN] releaseTensorId {tensorId: ${e}}`),this.tensorManager.releaseTensorId(e)}async ensureTensor(e,t,n,r,i){let a=cn.get(n);if(!a)throw Error(`Unsupported ONNX data type: ${n}`);return this.tensorManager.ensureTensor(e??this.currentSessionId,t,a,r,i)}async createTemporaryTensor(e,t,n){Kt(`verbose`,()=>`[WebNN] createTemporaryTensor {onnxDataType: ${t}, shape: ${n}}`);let r=cn.get(t);if(!r)throw Error(`Unsupported ONNX data type: ${t}`);let i=this.tensorManager.reserveTensorId();await this.tensorManager.ensureTensor(e,i,r,n,!1);let a=this.temporarySessionTensorIds.get(e);return a?a.push(i):this.temporarySessionTensorIds.set(e,[i]),i}uploadTensor(e,t){if(!E().shouldTransferToMLTensor)throw Error(`Trying to upload to a MLTensor while shouldTransferToMLTensor is false`);Kt(`verbose`,()=>`[WebNN] uploadTensor {tensorId: ${e}, data: ${t.byteLength}}`),this.tensorManager.upload(e,t)}async downloadTensor(e,t){return this.tensorManager.download(e,t)}createMLTensorDownloader(e,t){return async()=>{let n=await this.tensorManager.download(e);return Rt(n,t)}}registerMLTensor(e,t,n,r){let i=cn.get(n);if(!i)throw Error(`Unsupported ONNX data type: ${n}`);let a=this.tensorManager.registerTensor(e,t,i,r);return Kt(`verbose`,()=>`[WebNN] registerMLTensor {tensor: ${t}, dataType: ${i}, dimensions: ${r}} -> {tensorId: ${a}}`),a}registerGraphInput(e){this.temporaryGraphInputs.push(e)}registerGraphOutput(e){this.temporaryGraphOutputs.push(e)}isGraphInput(e,t){let n=this.sessionGraphInputs.get(e);return n?n.includes(t):!1}isGraphOutput(e,t){let n=this.sessionGraphOutputs.get(e);return n?n.includes(t):!1}isGraphInputOutputTypeSupported(e,t,n=!0){let r=cn.get(Dt(t)),i=this.mlOpSupportLimitsBySessionId.get(e);return typeof r>`u`?!1:n?!!i?.input.dataTypes.includes(r):!!i?.output.dataTypes.includes(r)}flush(){}}}),fn,pn,mn,hn,gn,_n,vn,yn,bn,xn,Sn,Cn,wn,Tn=s(()=>{"use strict";Le(),vt(),Et(),Ft(),pt(),gt(),Lt(),fn=(e,t)=>{E()._OrtInit(e,t)!==0&&D(`Can't initialize onnxruntime.`)},pn=async e=>{fn(e.wasm.numThreads,jt(e.logLevel))},mn=async(e,t)=>{E().asyncInit?.();let n=e.webgpu.adapter;if(t===`webgpu`){if(typeof navigator>`u`||!navigator.gpu)throw Error(`WebGPU is not supported in current environment`);if(n){if(typeof n.limits!=`object`||typeof n.features!=`object`||typeof n.requestDevice!=`function`)throw Error("Invalid GPU adapter set in `env.webgpu.adapter`. It must be a GPUAdapter object.")}else{let t=e.webgpu.powerPreference;if(t!==void 0&&t!==`low-power`&&t!==`high-performance`)throw Error(`Invalid powerPreference setting: "${t}"`);let r=e.webgpu.forceFallbackAdapter;if(r!==void 0&&typeof r!=`boolean`)throw Error(`Invalid forceFallbackAdapter setting: "${r}"`);if(n=await navigator.gpu.requestAdapter({powerPreference:t,forceFallbackAdapter:r}),!n)throw Error(`Failed to get GPU adapter. You may need to enable flag "--enable-unsafe-webgpu" if you are using Chrome.`)}}if(t===`webnn`&&(typeof navigator>`u`||!navigator.ml))throw Error(`WebNN is not supported in current environment`);if(t===`webgpu`&&E().webgpuInit(t=>{e.webgpu.device=t}),t===`webnn`){let t=new(dn(),u(sn)).WebNNBackend(e);E().webnnInit([t,()=>t.reserveTensorId(),e=>t.releaseTensorId(e),async(e,n,r,i,a)=>t.ensureTensor(e,n,r,i,a),(e,n)=>{t.uploadTensor(e,n)},async(e,n)=>t.downloadTensor(e,n),(e,n)=>t.registerMLContext(e,n),!!e.trace])}},hn=/* @__PURE__ */ new Map,gn=e=>{let t=E(),n=t.stackSave();try{let n=t.PTR_SIZE,r=t.stackAlloc(2*n);t._OrtGetInputOutputCount(e,r,r+n)!==0&&D(`Can't get session input/output count.`);let i=n===4?`i32`:`i64`;return[Number(t.getValue(r,i)),Number(t.getValue(r+n,i))]}finally{t.stackRestore(n)}},_n=(e,t)=>{let n=E(),r=n.stackSave(),i=0;try{let r=n.PTR_SIZE,a=n.stackAlloc(2*r);n._OrtGetInputOutputMetadata(e,t,a,a+r)!==0&&D(`Can't get session input/output metadata.`);let o=Number(n.getValue(a,`*`));i=Number(n.getValue(a+r,`*`));let s=n.HEAP32[i/4];if(s===0)return[o,0];let c=n.HEAPU32[i/4+1],l=[];for(let e=0;e{let t=E(),n=t._malloc(e.byteLength);if(n===0)throw Error(`Can't create a session. failed to allocate a buffer of size ${e.byteLength}.`);return t.HEAPU8.set(e,n),[n,e.byteLength]},yn=async(e,t)=>{let n,r,i=E();Array.isArray(e)?[n,r]=e:e.buffer===i.HEAPU8.buffer?[n,r]=[e.byteOffset,e.byteLength]:[n,r]=vn(e);let a=0,o=0,s=0,c=[],l=[],u=[];try{if([o,c]=await Tt(t),t?.externalData&&i.mountExternalData){let e=[];for(let n of t.externalData){let t=typeof n==`string`?n:n.path,r=typeof n==`string`?n:n.data;e.push(It(r).then(e=>{i.mountExternalData(t,e)}))}await Promise.all(e)}for(let e of t?.executionProviders??[])if((typeof e==`string`?e:e.name)===`webnn`){if(i.shouldTransferToMLTensor=!1,typeof e!=`string`){let t=e,n=t?.context,r=t?.gpuDevice,a=t?.deviceType,o=t?.powerPreference;i.currentContext=n||(r?await i.webnnCreateMLContext(r):await i.webnnCreateMLContext({deviceType:a,powerPreference:o}))}else i.currentContext=await i.webnnCreateMLContext();break}a=await i._OrtCreateSession(n,r,o),i.webgpuOnCreateSession?.(a),a===0&&D(`Can't create a session.`),i.jsepOnCreateSession?.(),i.currentContext&&(i.webnnRegisterMLContext(a,i.currentContext),i.currentContext=void 0,i.shouldTransferToMLTensor=!0);let[e,d]=gn(a),f=!!t?.enableGraphCapture,p=[],m=[],h=[],g=[],_=[];for(let t=0;te===`gpu-buffer`||e===`ml-tensor`||e===`ml-tensor-cpu-output`)&&(s=i._OrtCreateBinding(a),s===0&&D(`Can't create IO binding.`),v={handle:s,outputPreferredLocations:_,outputPreferredLocationsEncoded:_.map(e=>e===`ml-tensor-cpu-output`?`ml-tensor`:e).map(e=>Pt(e))}),hn.set(a,[a,l,u,v,f,!1]),[a,p,m,h,g]}catch(e){throw l.forEach(e=>i._OrtFree(e)),u.forEach(e=>i._OrtFree(e)),s!==0&&i._OrtReleaseBinding(s)!==0&&D(`Can't release IO binding.`),a!==0&&i._OrtReleaseSession(a)!==0&&D(`Can't release session.`),e}finally{i._free(n),o!==0&&i._OrtReleaseSessionOptions(o)!==0&&D(`Can't release session options.`),c.forEach(e=>i._free(e)),i.unmountExternalData?.()}},bn=e=>{let t=E(),n=hn.get(e);if(!n)throw Error(`cannot release session. invalid session id: ${e}`);let[r,i,a,o,s]=n;o&&(s&&t._OrtClearBoundOutputs(o.handle)!==0&&D(`Can't clear bound outputs.`),t._OrtReleaseBinding(o.handle)!==0&&D(`Can't release IO binding.`)),t.jsepOnReleaseSession?.(e),t.webnnOnReleaseSession?.(e),t.webgpuOnReleaseSession?.(e),i.forEach(e=>t._OrtFree(e)),a.forEach(e=>t._OrtFree(e)),t._OrtReleaseSession(r)!==0&&D(`Can't release session.`),hn.delete(e)},xn=async(e,t,n,r,i,a,o=!1)=>{if(!e){t.push(0);return}let s=E(),c=s.PTR_SIZE,l=e[0],u=e[1],d=e[3],f=d,p,m;if(l===`string`&&(d===`gpu-buffer`||d===`ml-tensor`))throw Error(`String tensor is not supported on GPU.`);if(o&&d!==`gpu-buffer`)throw Error(`External buffer must be provided for input/output index ${a} when enableGraphCapture is true.`);if(d===`gpu-buffer`){let t=e[2].gpuBuffer;m=kt(Dt(l),u);{let e=s.webgpuRegisterBuffer;if(!e)throw Error(`Tensor location "gpu-buffer" is not supported without using WebGPU.`);p=e(t,r)}}else if(d===`ml-tensor`){let t=e[2].mlTensor;m=kt(Dt(l),u);let n=s.webnnRegisterMLTensor;if(!n)throw Error(`Tensor location "ml-tensor" is not supported without using WebNN.`);p=n(r,t,Dt(l),u)}else{let t=e[2];if(Array.isArray(t)){m=c*t.length,p=s._malloc(m),n.push(p);for(let e=0;es.setValue(g+t*c,e,c===4?`i32`:`i64`));let e=s._OrtCreateTensor(Dt(l),p,m,g,u.length,Pt(f));e===0&&D(`Can't create tensor for input/output. session=${r}, index=${a}.`),t.push(e)}finally{s.stackRestore(h)}},Sn=async(e,t,n,r,i,a)=>{let o=E(),s=o.PTR_SIZE,c=hn.get(e);if(!c)throw Error(`cannot run inference. invalid session id: ${e}`);let l=c[0],u=c[1],d=c[2],f=c[3],p=c[4],m=c[5],h=t.length,g=r.length,_=0,v=[],y=[],b=[],x=[],S=[],C=o.stackSave(),ee=o.stackAlloc(h*s),te=o.stackAlloc(h*s),ne=o.stackAlloc(g*s),re=o.stackAlloc(g*s);try{[_,v]=_t(a),Te(`wasm prepareInputOutputTensor`);for(let r=0;re*t,1);u=Ot(a);let _=f?.outputPreferredLocations[r[t]];if(u===`string`){if(_===`gpu-buffer`||_===`ml-tensor`)throw Error(`String tensor is not supported on GPU.`);let e=[];for(let t=0;t0){let t=o.webgpuGetBuffer;if(!t)throw Error(`preferredLocation "gpu-buffer" is not supported without using WebGPU.`);let r=t(d),i=kt(a,g);if(i===void 0||!Mt(u))throw Error(`Unsupported data type: ${u}`);l=!0;{o.webgpuRegisterBuffer(r,e,d);let t=o.webgpuCreateDownloader(r,i,e);C.push([u,h,{gpuBuffer:r,download:async()=>{let e=await t();return new(At(u))(e)},dispose:()=>{o._OrtReleaseTensor(n)!==0&&D(`Can't release tensor.`)}},`gpu-buffer`])}}else if(_===`ml-tensor`&&g>0){let t=o.webnnEnsureTensor,r=o.webnnIsGraphInputOutputTypeSupported;if(!t||!r)throw Error(`preferredLocation "ml-tensor" is not supported without using WebNN.`);if(kt(a,g)===void 0||!Nt(u))throw Error(`Unsupported data type: ${u}`);if(!r(e,u,!1))throw Error(`preferredLocation "ml-tensor" for ${u} output is not supported by current WebNN Context.`);let i=await t(e,d,a,h,!1);l=!0,C.push([u,h,{mlTensor:i,download:o.webnnCreateMLTensorDownloader(d,u),dispose:()=>{o.webnnReleaseTensorId(d),o._OrtReleaseTensor(n)}},`ml-tensor`])}else if(_===`ml-tensor-cpu-output`&&g>0){let e=o.webnnCreateMLTensorDownloader(d,u)(),t=C.length;l=!0,ie.push((async()=>{let r=[t,await e];return o.webnnReleaseTensorId(d),o._OrtReleaseTensor(n),r})()),C.push([u,h,[],`cpu`])}else{let e=new(At(u))(g);new Uint8Array(e.buffer,e.byteOffset,e.byteLength).set(o.HEAPU8.subarray(d,d+e.byteLength)),C.push([u,h,e,`cpu`])}}finally{o.stackRestore(a),u===`string`&&d&&o._free(d),l||o._OrtReleaseTensor(n)}}f&&!p&&(o._OrtClearBoundOutputs(f.handle)!==0&&D(`Can't clear bound outputs.`),hn.set(e,[l,u,d,f,p,!1]));for(let[e,t]of await Promise.all(ie))C[e][2]=t;return Ee(`wasm ProcessOutputTensor`),C}finally{o.webnnOnRunEnd?.(l),o.stackRestore(C),n.forEach(e=>{e&&e[3]===`gpu-buffer`&&o.webgpuUnregisterBuffer(e[2].gpuBuffer)}),i.forEach(e=>{e&&e[3]===`gpu-buffer`&&o.webgpuUnregisterBuffer(e[2].gpuBuffer)}),y.forEach(e=>o._OrtReleaseTensor(e)),b.forEach(e=>o._OrtReleaseTensor(e)),x.forEach(e=>o._free(e)),_!==0&&o._OrtReleaseRunOptions(_),v.forEach(e=>o._free(e))}},Cn=e=>{let t=E(),n=hn.get(e);if(!n)throw Error(`invalid session id`);let r=n[0],i=t._OrtEndProfiling(r);i===0&&D(`Can't get an profile file name.`),t._OrtFree(i)},wn=e=>{let t=[];for(let n of e){let e=n[2];!Array.isArray(e)&&`buffer`in e&&t.push(e.buffer)}return t}}),En,Dn,On,kn,An,jn,Mn,Nn,Pn,Fn,In,Ln,Rn,zn,Bn,Vn,Hn,Un,Wn=s(()=>{"use strict";Le(),Tn(),pt(),it(),En=()=>!!C.wasm.proxy&&typeof document<`u`,On=!1,kn=!1,An=!1,Nn=/* @__PURE__ */ new Map,Pn=(e,t)=>{let n=Nn.get(e);n?n.push(t):Nn.set(e,[t])},Fn=()=>{if(On||!kn||An||!Dn)throw Error(`worker not ready`)},In=e=>{switch(e.data.type){case`init-wasm`:On=!1,e.data.err?(An=!0,Mn[1](e.data.err)):(kn=!0,Mn[0]()),jn&&=(URL.revokeObjectURL(jn),void 0);break;case`init-ep`:case`copy-from`:case`create`:case`release`:case`run`:case`end-profiling`:{let t=Nn.get(e.data.type);e.data.err?t.shift()[1](e.data.err):t.shift()[0](e.data.out);break}}},Ln=async()=>{if(!kn){if(On)throw Error(`multiple calls to 'initWasm()' detected.`);if(An)throw Error(`previous call to 'initWasm()' failed.`);if(On=!0,En())return new Promise((e,t)=>{Dn?.terminate(),tt().then(([n,r])=>{try{Dn=r,Dn.onerror=e=>t(e),Dn.onmessage=In,Mn=[e,t];let i={type:`init-wasm`,in:C};if(!i.in.wasm.wasmPaths&&n){let e=Je();e&&(i.in.wasm.wasmPaths=e)}Dn.postMessage(i),jn=n}catch(e){t(e)}},t)});try{await ft(C.wasm),await pn(C),kn=!0}catch(e){throw An=!0,e}finally{On=!1}}},Rn=async e=>{if(En())return Fn(),new Promise((t,n)=>{Pn(`init-ep`,[t,n]);let r={type:`init-ep`,in:{epName:e,env:C}};Dn.postMessage(r)});await mn(C,e)},zn=async e=>En()?(Fn(),new Promise((t,n)=>{Pn(`copy-from`,[t,n]);let r={type:`copy-from`,in:{buffer:e}};Dn.postMessage(r,[e.buffer])})):vn(e),Bn=async(e,t)=>{if(En()){if(t?.preferredOutputLocation)throw Error(`session option "preferredOutputLocation" is not supported for proxy.`);return Fn(),new Promise((n,r)=>{Pn(`create`,[n,r]);let i={type:`create`,in:{model:e,options:{...t}}},a=[];e instanceof Uint8Array&&a.push(e.buffer),Dn.postMessage(i,a)})}return yn(e,t)},Vn=async e=>{if(En())return Fn(),new Promise((t,n)=>{Pn(`release`,[t,n]);let r={type:`release`,in:e};Dn.postMessage(r)});bn(e)},Hn=async(e,t,n,r,i,a)=>{if(En()){if(n.some(e=>e[3]!==`cpu`))throw Error(`input tensor on GPU is not supported for proxy.`);if(i.some(e=>e))throw Error(`pre-allocated output tensor is not supported for proxy.`);return Fn(),new Promise((i,o)=>{Pn(`run`,[i,o]);let s=n,c={type:`run`,in:{sessionId:e,inputIndices:t,inputs:s,outputIndices:r,options:a}};Dn.postMessage(c,wn(s))})}return Sn(e,t,n,r,i,a)},Un=async e=>{if(En())return Fn(),new Promise((t,n)=>{Pn(`end-profiling`,[t,n]);let r={type:`end-profiling`,in:e};Dn.postMessage(r)});Cn(e)}}),Gn,Kn,qn,Jn=s(()=>{"use strict";Le(),Wn(),Ft(),Re(),Lt(),Gn=(e,t)=>{switch(e.location){case`cpu`:return[e.type,e.dims,e.data,`cpu`];case`gpu-buffer`:return[e.type,e.dims,{gpuBuffer:e.gpuBuffer},`gpu-buffer`];case`ml-tensor`:return[e.type,e.dims,{mlTensor:e.mlTensor},`ml-tensor`];default:throw Error(`invalid data location: ${e.location} for ${t()}`)}},Kn=e=>{switch(e[3]){case`cpu`:return new ye(e[0],e[2],e[1]);case`gpu-buffer`:{let t=e[0];if(!Mt(t))throw Error(`not supported data type: ${t} for deserializing GPU tensor`);let{gpuBuffer:n,download:r,dispose:i}=e[2];return ye.fromGpuBuffer(n,{dataType:t,dims:e[1],download:r,dispose:i})}case`ml-tensor`:{let t=e[0];if(!Nt(t))throw Error(`not supported data type: ${t} for deserializing MLTensor tensor`);let{mlTensor:n,download:r,dispose:i}=e[2];return ye.fromMLTensor(n,{dataType:t,dims:e[1],download:r,dispose:i})}default:throw Error(`invalid data location: ${e[3]}`)}},qn=class{async fetchModelAndCopyToWasmMemory(e){return zn(await It(e))}async loadModel(e,t){Ce();let n;n=typeof e==`string`?await this.fetchModelAndCopyToWasmMemory(e):e,[this.sessionId,this.inputNames,this.outputNames,this.inputMetadata,this.outputMetadata]=await Bn(n,t),we()}async dispose(){return Vn(this.sessionId)}async run(e,t,n){Ce();let r=[],i=[];Object.entries(e).forEach(e=>{let t=e[0],n=e[1],a=this.inputNames.indexOf(t);if(a===-1)throw Error(`invalid input '${t}'`);r.push(n),i.push(a)});let a=[],o=[];Object.entries(t).forEach(e=>{let t=e[0],n=e[1],r=this.outputNames.indexOf(t);if(r===-1)throw Error(`invalid output '${t}'`);a.push(n),o.push(r)});let s=r.map((e,t)=>Gn(e,()=>`input "${this.inputNames[i[t]]}"`)),c=a.map((e,t)=>e?Gn(e,()=>`output "${this.outputNames[o[t]]}"`):null),l=await Hn(this.sessionId,i,s,o,c,n),u={};for(let e=0;eZn,initializeFlags:()=>Xn,wasmBackend:()=>Qn});var Xn,Zn,Qn,$n=s(()=>{"use strict";Le(),Wn(),Jn(),Xn=()=>{(typeof C.wasm.initTimeout!=`number`||C.wasm.initTimeout<0)&&(C.wasm.initTimeout=0);let e=C.wasm.simd;if(typeof e!=`boolean`&&e!==void 0&&e!==`fixed`&&e!==`relaxed`&&(console.warn(`Property "env.wasm.simd" is set to unknown value "${e}". Reset it to \`false\` and ignore SIMD feature checking.`),C.wasm.simd=!1),typeof C.wasm.proxy!=`boolean`&&(C.wasm.proxy=!1),typeof C.wasm.trace!=`boolean`&&(C.wasm.trace=!1),typeof C.wasm.numThreads!=`number`||!Number.isInteger(C.wasm.numThreads)||C.wasm.numThreads<=0){if(typeof self<`u`&&!self.crossOriginIsolated)C.wasm.numThreads=1;else{let e=typeof navigator>`u`?o(`node:os`).cpus().length:navigator.hardwareConcurrency;C.wasm.numThreads=Math.min(4,Math.ceil((e||1)/2))}}},Zn=class{async init(e){Xn(),await Ln(),await Rn(e)}async createInferenceSessionHandler(e,t){let n=new qn;return await n.loadModel(e,t),n}},Qn=new Zn});Le(),Le(),Le();var er=`1.31.0-dev.20260914-8d85527a0`,tr=Ie;{let e=($n(),u(Yn)).wasmBackend;p(`webgpu`,e,5),p(`webnn`,e,5),p(`cpu`,e,10),p(`wasm`,e,10)}Object.defineProperty(C.versions,"web",{value:er,enumerable:!0});let nr=`warning`;Object.defineProperty({wasm:{},webgl:{},webgpu:{},versions:{common:`1.30.0`},set logLevel(e){if(e!==void 0){if(typeof e!=`string`||[`verbose`,`info`,`warning`,`error`,`fatal`].indexOf(e)===-1)throw Error(`Unsupported logging level: ${e}`);nr=e}},get logLevel(){return nr}},"logLevel",{enumerable:!0});let rr=(e,t)=>{let n=typeof document<`u`?document.createElement(`canvas`):new OffscreenCanvas(1,1);n.width=e.dims[3],n.height=e.dims[2];let r=n.getContext(`2d`);if(r!=null){let i,a;t?.tensorLayout!==void 0&&t.tensorLayout===`NHWC`?(i=e.dims[2],a=e.dims[3]):(i=e.dims[3],a=e.dims[2]);let o=t?.format===void 0?`RGB`:t.format,s=t?.norm,c,l;s===void 0||s.mean===void 0?c=[255,255,255,255]:typeof s.mean==`number`?c=[s.mean,s.mean,s.mean,s.mean]:(c=[s.mean[0],s.mean[1],s.mean[2],0],s.mean[3]!==void 0&&(c[3]=s.mean[3])),s===void 0||s.bias===void 0?l=[0,0,0,0]:typeof s.bias==`number`?l=[s.bias,s.bias,s.bias,s.bias]:(l=[s.bias[0],s.bias[1],s.bias[2],0],s.bias[3]!==void 0&&(l[3]=s.bias[3]));let u=a*i,d=0,f=u,p=u*2,m=-1;o===`RGBA`?(d=0,f=u,p=u*2,m=u*3):o===`RGB`?(d=0,f=u,p=u*2):o===`RBG`&&(d=0,p=u,f=u*2);for(let t=0;t{let n=typeof document<`u`?document.createElement(`canvas`).getContext(`2d`):new OffscreenCanvas(1,1).getContext(`2d`),r;if(n!=null){let i,a,o;t?.tensorLayout!==void 0&&t.tensorLayout===`NHWC`?(i=e.dims[2],a=e.dims[1],o=e.dims[3]):(i=e.dims[3],a=e.dims[2],o=e.dims[1]);let s=t===void 0||t.format===void 0?`RGB`:t.format,c=t?.norm,l,u;c===void 0||c.mean===void 0?l=[255,255,255,255]:typeof c.mean==`number`?l=[c.mean,c.mean,c.mean,c.mean]:(l=[c.mean[0],c.mean[1],c.mean[2],255],c.mean[3]!==void 0&&(l[3]=c.mean[3])),c===void 0||c.bias===void 0?u=[0,0,0,0]:typeof c.bias==`number`?u=[c.bias,c.bias,c.bias,c.bias]:(u=[c.bias[0],c.bias[1],c.bias[2],0],c.bias[3]!==void 0&&(u[3]=c.bias[3]));let d=a*i;if(t!==void 0&&(t.format!==void 0&&o===4&&t.format!==`RGBA`||o===3&&t.format!==`RGB`&&t.format!==`BGR`))throw Error(`Tensor format doesn't match input tensor dims`);let f=0,p=1,m=2,h=3,g=0,_=d,v=d*2,y=-1;s===`RGBA`?(g=0,_=d,v=d*2,y=d*3):s===`RGB`?(g=0,_=d,v=d*2):s===`RBG`&&(g=0,v=d,_=d*2),r=n.createImageData(i,a);for(let t=0;t{if(e===void 0)throw Error(`Image buffer must be defined`);if(t.height===void 0||t.width===void 0)throw Error(`Image height and width must be defined`);if(t.tensorLayout===`NHWC`)throw Error(`NHWC Tensor layout is not supported yet`);let{height:n,width:r}=t,i=t.norm??{mean:255,bias:0},a,o;a=typeof i.mean==`number`?[i.mean,i.mean,i.mean,i.mean]:[i.mean[0],i.mean[1],i.mean[2],i.mean[3]??255],o=typeof i.bias==`number`?[i.bias,i.bias,i.bias,i.bias]:[i.bias[0],i.bias[1],i.bias[2],i.bias[3]??0];let s=t.format===void 0?`RGBA`:t.format,c=t.tensorFormat===void 0||t.tensorFormat===void 0?`RGB`:t.tensorFormat,l=n*r,u=c===`RGBA`?new Float32Array(l*4):new Float32Array(l*3),d=4,f=0,p=1,m=2,h=3,g=0,_=l,v=l*2,y=-1;s===`RGB`&&(d=3,f=0,p=1,m=2,h=-1),c===`RGBA`?y=l*3:c===`RBG`?(g=0,v=l,_=l*2):c===`BGR`&&(v=0,_=l,g=l*2);for(let t=0;t{let n=typeof HTMLImageElement<`u`&&e instanceof HTMLImageElement,r=typeof ImageData<`u`&&e instanceof ImageData,i=typeof ImageBitmap<`u`&&e instanceof ImageBitmap,a=typeof e==`string`,o,s=t??{},c=()=>{if(typeof document<`u`)return document.createElement(`canvas`);if(typeof OffscreenCanvas<`u`)return new OffscreenCanvas(1,1);throw Error(`Canvas is not supported`)},l=e=>typeof HTMLCanvasElement<`u`&&e instanceof HTMLCanvasElement||e instanceof OffscreenCanvas?e.getContext(`2d`):null;if(n){let n=c();n.width=e.width,n.height=e.height;let r=l(n);if(r!=null){let n=e.height,i=e.width;if(t!==void 0&&t.resizedHeight!==void 0&&t.resizedWidth!==void 0&&(n=t.resizedHeight,i=t.resizedWidth),t!==void 0){if(s=t,t.tensorFormat!==void 0)throw Error(`Image input config format must be RGBA for HTMLImageElement`);s.tensorFormat=`RGBA`,s.height=n,s.width=i}else s.tensorFormat=`RGBA`,s.height=n,s.width=i;r.drawImage(e,0,0),o=r.getImageData(0,0,i,n).data}else throw Error(`Can not access image data`)}else if(r){let n,r;if(t!==void 0&&t.resizedWidth!==void 0&&t.resizedHeight!==void 0?(n=t.resizedHeight,r=t.resizedWidth):(n=e.height,r=e.width),t!==void 0&&(s=t),s.format=`RGBA`,s.height=n,s.width=r,t!==void 0){let t=c();t.width=r,t.height=n;let i=l(t);if(i!=null)i.putImageData(e,0,0),o=i.getImageData(0,0,r,n).data;else throw Error(`Can not access image data`)}else o=e.data}else if(i){if(t===void 0)throw Error(`Please provide image config with format for Imagebitmap`);let n=c();n.width=e.width,n.height=e.height;let r=l(n);if(r!=null){let t=e.height,n=e.width;return r.drawImage(e,0,0,n,t),o=r.getImageData(0,0,n,t).data,s.height=t,s.width=n,ar(o,s)}throw Error(`Can not access image data`)}else if(a)return new Promise((t,n)=>{let r=c(),i=l(r);if(!e||!i)return n();let a=new Image;a.crossOrigin=`Anonymous`,a.src=e,a.onload=()=>{r.width=a.width,r.height=a.height,i.drawImage(a,0,0,r.width,r.height);let e=i.getImageData(0,0,r.width,r.height);s.height=r.height,s.width=r.width,t(ar(e.data,s))}});else throw Error(`Input data provided is not supported - aborted tensor creation`);if(o!==void 0)return ar(o,s);throw Error(`Input data provided is not supported - aborted tensor creation`)},sr=(e,t)=>{let{width:n,height:r,download:i,dispose:a}=t;return new _r({location:`texture`,type:`float32`,texture:e,dims:[1,r,n,4],download:i,dispose:a})},cr=(e,t)=>{let{dataType:n,dims:r,download:i,dispose:a}=t;return new _r({location:`gpu-buffer`,type:n??`float32`,gpuBuffer:e,dims:r,download:i,dispose:a})},lr=(e,t)=>{let{dataType:n,dims:r,download:i,dispose:a}=t;return new _r({location:`ml-tensor`,type:n??`float32`,mlTensor:e,dims:r,download:i,dispose:a})},ur=(e,t,n)=>new _r({location:`cpu-pinned`,type:e,data:t,dims:n??[t.length]}),dr=/* @__PURE__ */ new Map([[`float32`,Float32Array],[`uint8`,Uint8Array],[`int8`,Int8Array],[`uint16`,Uint16Array],[`int16`,Int16Array],[`int32`,Int32Array],[`bool`,Uint8Array],[`float64`,Float64Array],[`uint32`,Uint32Array],[`int4`,Uint8Array],[`uint4`,Uint8Array]]),fr=/* @__PURE__ */ new Map([[Float32Array,`float32`],[Uint8Array,`uint8`],[Int8Array,`int8`],[Uint16Array,`uint16`],[Int16Array,`int16`],[Int32Array,`int32`],[Float64Array,`float64`],[Uint32Array,`uint32`]]),pr=!1,mr=()=>{if(!pr){pr=!0;let e=typeof BigInt64Array<`u`&&BigInt64Array.from,t=typeof BigUint64Array<`u`&&BigUint64Array.from,n=globalThis.Float16Array,r=n!==void 0&&n.from;e&&(dr.set(`int64`,BigInt64Array),fr.set(BigInt64Array,`int64`)),t&&(dr.set(`uint64`,BigUint64Array),fr.set(BigUint64Array,`uint64`)),r?(dr.set(`float16`,n),fr.set(n,`float16`)):dr.set(`float16`,Uint16Array)}},hr=e=>{let t=1;for(let n=0;n{switch(e.location){case`cpu`:return new _r(e.type,e.data,t);case`cpu-pinned`:return new _r({location:`cpu-pinned`,data:e.data,type:e.type,dims:t});case`texture`:return new _r({location:`texture`,texture:e.texture,type:e.type,dims:t});case`gpu-buffer`:return new _r({location:`gpu-buffer`,gpuBuffer:e.gpuBuffer,type:e.type,dims:t});case`ml-tensor`:return new _r({location:`ml-tensor`,mlTensor:e.mlTensor,type:e.type,dims:t});default:throw Error(`tensorReshape: tensor location ${e.location} is not supported`)}};var _r=class{constructor(e,t,n){mr();let r,i;if(typeof e==`object`&&`location`in e)switch(this.dataLocation=e.location,r=e.type,i=e.dims,e.location){case`cpu-pinned`:{let t=dr.get(r);if(!t)throw TypeError(`unsupported type "${r}" to create tensor from pinned buffer`);if(!(e.data instanceof t))throw TypeError(`buffer should be of type ${t.name}`);this.cpuData=e.data;break}case`texture`:if(r!==`float32`)throw TypeError(`unsupported type "${r}" to create tensor from texture`);this.gpuTextureData=e.texture,this.downloader=e.download,this.disposer=e.dispose;break;case`gpu-buffer`:if(r!==`float32`&&r!==`float16`&&r!==`int32`&&r!==`int64`&&r!==`uint32`&&r!==`uint8`&&r!==`bool`&&r!==`uint4`&&r!==`int4`)throw TypeError(`unsupported type "${r}" to create tensor from gpu buffer`);this.gpuBufferData=e.gpuBuffer,this.downloader=e.download,this.disposer=e.dispose;break;case`ml-tensor`:if(r!==`float32`&&r!==`float16`&&r!==`int32`&&r!==`int64`&&r!==`uint32`&&r!==`uint64`&&r!==`int8`&&r!==`uint8`&&r!==`bool`&&r!==`uint4`&&r!==`int4`)throw TypeError(`unsupported type "${r}" to create tensor from MLTensor`);this.mlTensorData=e.mlTensor,this.downloader=e.download,this.disposer=e.dispose;break;default:throw Error(`Tensor constructor: unsupported location '${this.dataLocation}'`)}else{let a,o;if(typeof e==`string`){if(r=e,o=n,e===`string`){if(!Array.isArray(t))throw TypeError(`A string tensor's data must be a string array.`);a=t}else{let n=dr.get(e);if(n===void 0)throw TypeError(`Unsupported tensor type: ${e}.`);if(Array.isArray(t)){if(e===`float16`&&n===Uint16Array||e===`uint4`||e===`int4`)throw TypeError(`Creating a ${e} tensor from number array is not supported. Please use ${n.name} as data.`);a=e===`uint64`||e===`int64`?n.from(t,BigInt):n.from(t)}else if(t instanceof n)a=t;else if(t instanceof Uint8ClampedArray){if(e===`uint8`)a=Uint8Array.from(t);else throw TypeError(`A Uint8ClampedArray tensor's data must be type of uint8`)}else if(e===`float16`&&t instanceof Uint16Array&&n!==Uint16Array)a=new globalThis.Float16Array(t.buffer,t.byteOffset,t.length);else throw TypeError(`A ${r} tensor's data must be type of ${n}`)}}else if(o=t,Array.isArray(e)){if(e.length===0)throw TypeError(`Tensor type cannot be inferred from an empty array.`);let t=typeof e[0];if(t===`string`)r=`string`,a=e;else if(t===`boolean`)r=`bool`,a=Uint8Array.from(e);else throw TypeError(`Invalid element type of data array: ${t}.`)}else if(e instanceof Uint8ClampedArray)r=`uint8`,a=Uint8Array.from(e);else{let t=fr.get(e.constructor);if(t===void 0)throw TypeError(`Unsupported type for tensor data: ${e.constructor}.`);r=t,a=e}if(o===void 0)o=[a.length];else if(!Array.isArray(o))throw TypeError(`A tensor's dims must be a number array`);i=o,this.cpuData=a,this.dataLocation=`cpu`}let a=hr(i);if(this.cpuData&&a!==this.cpuData.length&&(r!==`uint4`&&r!==`int4`||Math.ceil(a/2)!==this.cpuData.length))throw Error(`Tensor's size(${a}) does not match data length(${this.cpuData.length}).`);this.type=r,this.dims=i,this.size=a}static async fromImage(e,t){return or(e,t)}static fromTexture(e,t){return sr(e,t)}static fromGpuBuffer(e,t){return cr(e,t)}static fromMLTensor(e,t){return lr(e,t)}static fromPinnedBuffer(e,t,n){return ur(e,t,n)}toDataURL(e){return rr(this,e)}toImageData(e){return ir(this,e)}get data(){if(this.ensureValid(),!this.cpuData)throw Error("The data is not on CPU. Use `getData()` to download GPU data to CPU, or use `texture` or `gpuBuffer` property to access the GPU data directly.");return this.cpuData}get location(){return this.dataLocation}get texture(){if(this.ensureValid(),!this.gpuTextureData)throw Error(`The data is not stored as a WebGL texture.`);return this.gpuTextureData}get gpuBuffer(){if(this.ensureValid(),!this.gpuBufferData)throw Error(`The data is not stored as a WebGPU buffer.`);return this.gpuBufferData}get mlTensor(){if(this.ensureValid(),!this.mlTensorData)throw Error(`The data is not stored as a WebNN MLTensor.`);return this.mlTensorData}async getData(e){switch(this.ensureValid(),this.dataLocation){case`cpu`:case`cpu-pinned`:return this.data;case`texture`:case`gpu-buffer`:case`ml-tensor`:if(!this.downloader)throw Error(`The current tensor is not created with a specified data downloader.`);if(this.isDownloading)throw Error(`The current tensor is being downloaded.`);try{this.isDownloading=!0;let t=await this.downloader();return this.downloader=void 0,this.dataLocation=`cpu`,this.cpuData=t,e&&this.disposer&&(this.disposer(),this.disposer=void 0),t}finally{this.isDownloading=!1}default:throw Error(`cannot get data from location: ${this.dataLocation}`)}}dispose(){if(this.isDownloading)throw Error(`The current tensor is being downloaded.`);this.disposer&&=(this.disposer(),void 0),this.cpuData=void 0,this.gpuTextureData=void 0,this.gpuBufferData=void 0,this.mlTensorData=void 0,this.downloader=void 0,this.isDownloading=void 0,this.dataLocation=`none`}ensureValid(){if(this.dataLocation===`none`)throw Error(`The tensor is disposed.`)}reshape(e){if(this.ensureValid(),this.downloader||this.disposer)throw Error(`Cannot reshape a tensor that owns GPU resource.`);return gr(this,e)}};let vr=_r;var yr={url:self.location.href},br=Object.defineProperty,xr=(e,t)=>{for(var n in t)br(e,n,{get:t[n],enumerable:!0})},Sr={},Cr={},wr={},Tr=`4.3.0`,Er=typeof self<`u`,Dr=!Zr(Sr),Or=!Zr(Cr),kr=Er&&`caches`in self,Ar=globalThis.Deno!==void 0;globalThis.Bun;var jr=Ar&&kr&&!Dr,Mr=typeof process<`u`,Nr=Mr&&process?.release?.name===`node`&&!jr,Pr=typeof window<`u`&&window.document!==void 0,Fr=Er&&[`DedicatedWorkerGlobalScope`,`ServiceWorkerGlobalScope`,`SharedWorkerGlobalScope`].includes(self.constructor?.name),Ir=Pr||Fr||jr,Lr=Nr||typeof navigator<`u`&&`gpu`in navigator,Rr=typeof navigator<`u`&&`ml`in navigator,zr=typeof crypto<`u`&&typeof crypto.getRandomValues==`function`,Br=typeof chrome<`u`&&chrome.runtime!==void 0&&typeof chrome.runtime.id==`string`,Vr=typeof ServiceWorkerGlobalScope<`u`&&Er&&self instanceof ServiceWorkerGlobalScope,Hr=(()=>{if(typeof navigator>`u`)return!1;let e=navigator.userAgent;if(!((navigator.vendor||``).indexOf(`Apple`)>-1&&!e.match(/CriOS|FxiOS|EdgiOS|OPiOS|mercury|brave/i)&&!e.includes(`Chrome`)&&!e.includes(`Android`)))return!1;let t=e.match(/Version\/(\d+)/);return t?parseInt(t[1],10)<26:!1})(),O=Object.freeze({IS_BROWSER_ENV:Pr,IS_WEBWORKER_ENV:Fr,IS_WEB_ENV:Ir,IS_SERVICE_WORKER_ENV:Vr,IS_DENO_WEB_RUNTIME:jr,IS_WEB_CACHE_AVAILABLE:kr,IS_WEBGPU_AVAILABLE:Lr,IS_WEBNN_AVAILABLE:Rr,IS_SAFARI_BELOW_26:Hr,IS_PROCESS_AVAILABLE:Mr,IS_NODE_ENV:Nr,IS_FS_AVAILABLE:Dr,IS_PATH_AVAILABLE:Or,IS_CRYPTO_AVAILABLE:zr,IS_CHROME_AVAILABLE:Br}),Ur=Dr&&Or,Wr=`./`;if(Ur){let e=self.location.href;e?Wr=Cr.dirname(Cr.dirname(wr.fileURLToPath(e))):typeof __dirname<`u`&&(Wr=Cr.dirname(__dirname))}var Gr=Ur?Cr.join(Wr,`/.cache/`):null,Kr=`/models/`,qr=Ur?Cr.join(Wr,Kr):Kr,Jr=typeof globalThis.fetch==`function`?globalThis.fetch.bind(globalThis):void 0,Yr=Object.freeze({DEBUG:10,INFO:20,WARNING:30,ERROR:40,NONE:50}),Xr=Yr.WARNING,k={version:Tr,backends:{onnx:{}},get logLevel(){return Xr},set logLevel(e){Xr=e,k.backends.onnx?.setLogLevel?.(e)},allowRemoteModels:!0,remoteHost:`https://huggingface.co/`,remotePathTemplate:`{model}/resolve/{revision}/`,allowLocalModels:!(Pr||Fr||jr),localModelPath:qr,useFS:Dr,useBrowserCache:kr,useFSCache:Dr,cacheDir:Gr,useCustomCache:!1,customCache:null,useWasmCache:kr||Dr,cacheKey:`transformers-cache`,experimental_useCrossOriginStorage:!1,fetch:Jr};function Zr(e){return Object.keys(e).length===0}var Qr=class{constructor(){let e=function(...t){return e._call(...t)};return Object.setPrototypeOf(e,new.target.prototype)}_call(...e){throw Error(`Must implement _call method in subclass`)}};function $r(e,t){e&&e(t)}var ei=class extends Qr{constructor(e,t){super(),this.callback=e,this.files_loading=t,this.loads=/* @__PURE__ */ new Map}_call(e){if(e.status===`progress`){this.files_loading[e.file]={loaded:e.loaded,total:e.total};let t=Object.values(this.files_loading).reduce((e,t)=>e+t.loaded,0),n=Object.values(this.files_loading).reduce((e,t)=>e+t.total,0),r=n>0?t/n*100:0;this.callback({status:`progress_total`,name:e.name,progress:r,loaded:t,total:n,files:structuredClone(this.files_loading)})}this.callback(e)}};function ti(e){return Number.isInteger(e)||typeof e==`bigint`}function ni(e){return e==null||e===-1}function ri(e){let t=[],n=e;for(;Array.isArray(n);)t.push(n.length),n=n[0];return t}function ii(...e){return Array.prototype.concat.apply([],e)}function ai(...e){return e.reduce((e,t)=>e.flatMap(e=>t.map(t=>[e,t])))}function oi(e,t){return Math.abs((e+t)%(2*t)-t)}function si(e,t){return Object.assign({},...t.map(t=>{if(e[t]!==void 0)return{[t]:e[t]}}))}function ci(e,t){let n=0;for(let r of e)r===t&&++n;return n}var A={error(...e){k.logLevel<=Yr.ERROR&&console.error(...e)},warn(...e){k.logLevel<=Yr.WARNING&&console.warn(...e)},info(...e){k.logLevel<=Yr.INFO&&console.log(...e)},debug(...e){k.logLevel<=Yr.DEBUG&&console.log(...e)},log(...e){this.info(...e)}},li=class{constructor(e){this.trie=this._build_trie(e)}_build_trie(e){let t=/* @__PURE__ */ Object.create(null);for(let n of e){let e=t;for(let t=0;tr&&t.push(e.slice(r,i)),t.push(o),i+=o.length,r=i):++i}return r{try{return new RegExp(e,t)}catch(n){if(!(n instanceof SyntaxError))throw n;let r=/* @__PURE__ */ new Map,i=e.replace(/(\\[pP])\{([^}=]+)\}/g,(t,n,i,a)=>{let o=0;for(let t=a-1;t>=0&&e[t]===`\\`;--t)++o;if(o%2==1)return t;let s=r.get(i);if(s===void 0){try{RegExp(`\\p{${i}}`,`u`),s=i}catch{s=`Script=${i}`}r.set(i,s)}return`${n}{${s}}`});if(i===e)throw n;try{return new RegExp(i,t)}catch{throw n}}},fi=e=>e.replace(/ \./g,`.`).replace(/ \?/g,`?`).replace(/ \!/g,`!`).replace(/ ,/g,`,`).replace(/ \' /g,`'`).replace(/ n't/g,`n't`).replace(/ 'm/g,`'m`).replace(/ 's/g,`'s`).replace(/ 've/g,`'ve`).replace(/ 're/g,`'re`),pi=(e,t=!0)=>{if(e.Regex!==void 0)return di(Zi(zi(e.Regex)),`gu`);if(e.String!==void 0){let n=Qi(e.String);return new RegExp(t?n:`(${n})`,`gu`)}return console.warn(`Unknown pattern type:`,e),null},mi=`\\p{Alphabetic}\\p{M}\\p{Nd}\\p{Pc}`,hi=`${mi}\\u00B2\\u00B3\\u00B9\\u00BC-\\u00BE`,gi=`[${hi}]`,_i=`[^${hi}]`,vi=`(?:(?|[:=!>])/,Ai=/^\\([pPxu])\{([^}]*)\}/,ji=/^\{(\d+(?:,\d*)?|,\d+)\}/,Mi=/^\[:(\^?)(\p{Alphabetic}+):\]/u,Ni=/^\[:\^:\]/,Pi=/^\[(?:\.[^\]]*\.\]|=[^\]]*=\])/,Fi=/^(?:\\x[0-9A-Fa-f]{2}|\\u[0-9A-Fa-f]{4}|\\c[A-Za-z])/,Ii=e=>e>=`A`&&e<=`Z`||e>=`a`&&e<=`z`,Li=(e,t)=>String.fromCodePoint(e.codePointAt(t)),Ri=e=>{if(!/^[0-9A-Fa-f]{1,8}$/.test(e))return null;let t=Number.parseInt(e,16);if(t>127)return null;let n=String.fromCharCode(t);return Ii(n)?`[${n.toLowerCase()}${n.toUpperCase()}]`:null},zi=e=>e.replace(/\[\^\(\\s\|\[([^\]]+)\]\)\]/g,`[^()|\\s$1]`),Bi=`[\\s\\S]`,Vi=256,Hi=()=>({fragment:``,alternatives:[],tail:null,contains_complex_set:!1}),Ui=e=>{throw SyntaxError(`Unsupported range with a set-valued character-class operand at index ${e}`)},Wi=(e,t,n,r=!0)=>{e.tail===`range`&&Ui(n),e.alternatives.push(t),e.tail=`set`,e.contains_complex_set=e.contains_complex_set||r},Gi=(e,t,n=!1,r=-1)=>{if(n&&e.tail===`range`&&Ui(r),e.tail===`range`){e.fragment+=t,e.tail=`complete_range`;return}e.fragment+=t,e.tail=n?`set`:`scalar`,e.contains_complex_set=e.contains_complex_set||n},Ki=(e,t,n)=>{let r=Ai.exec(e.slice(t));if(r){let[e,i,a]=r;return i===`P`&&a===`Word`?Wi(n,`[^${mi}]`,t):Gi(n,i===`x`?`\\u{${a}}`:i===`p`&&a===`Word`?mi:e,i===`p`||i===`P`,t),t+e.length}let i=Fi.exec(e.slice(t));if(i)return Gi(n,i[0]),t+i[0].length;if(t+1>=e.length)throw SyntaxError(`Unterminated escape in character class at index ${t}`);let a=Li(e,t+1),o=t+1+a.length,s=Ei.get(a);if(s!==void 0)return Gi(n,s),o;let c=Ti.get(a);if(c!==void 0)return Wi(n,c,t),o;let l=wi.get(a),u,d=!1;return l===void 0?u=/[A-Za-z0-9]/.test(a)||Oi.includes(a)||a===`-`?`\\${a}`:a:(u=l,d=a!==`a`&&a!==`e`),Gi(n,u,d,t),o},qi=e=>e.length===1?e[0]:`(?:(?=(?:${e.join(`|`)}))${Bi})`,Ji=e=>qi(e.fragment.length===0?e.alternatives:[`[${e.fragment}]`,...e.alternatives]),Yi=e=>{let t=di(`^(?:${e})$`,`u`),n=``;for(let e=0;e<26;++e){let r=String.fromCharCode(65+e),i=String.fromCharCode(97+e),a=t.test(r);a!==t.test(i)&&(n+=a?i:r)}return n},Xi=(e,t,n,r=!0,i=1)=>{if(i>Vi)throw SyntaxError(`Maximum character-class nesting depth of ${Vi} exceeded at index ${t}`);let a=t+1,o=e[a]===`^`;o&&++a;let s=a,c=[Hi()],l=c[0],u=!1;for(;a1?SyntaxError(`Malformed character-class intersection with an empty operand at index ${a}`):SyntaxError(`Empty character class at index ${t}`);let e=c.some(e=>e.contains_complex_set);if(o&&c.length>1&&u)throw SyntaxError(`Unsupported outer-negated character-class intersection with a nested negated class containing a Unicode property, POSIX class, or shorthand at index ${t}`);let i=Ji(c[0]),d=i;if(c.length>1){let e=``;for(let t=1;t0&&(f?(p+=e,d=`[${p}]`):d=qi([d,`[${e}]`]))}return{atom:o?f?`[^${p}]`:`(?:(?!${d})${Bi})`:d,end:a+1,negated:o,contains_complex_set:e,contains_nested_negated_complex_set:u}}if(e.startsWith(`&&`,a)){if(l.tail===null)throw SyntaxError(`Malformed character-class intersection with an empty operand at index ${a}`);l=Hi(),c.push(l),a+=2;continue}if(d===`[`){let t=e.slice(a);if(Ni.test(t))throw SyntaxError(`Malformed empty negated POSIX character class at index ${a}`);let r=Mi.exec(t);if(r){let[,e,t]=r,i=Di.get(t);if(i===void 0)throw SyntaxError(`Unsupported POSIX character class "${t}" at index ${a}`);if(n&&e&&(t===`lower`||t===`upper`))throw SyntaxError(`Unsupported negated POSIX ${t} class inside an inline case-insensitive group`);e?Wi(l,`[^${i}]`,a):Gi(l,i,!0,a),a+=r[0].length;continue}if(Pi.test(t))throw SyntaxError(`Unsupported POSIX collating or equivalence bracket expression at index ${a}`);let o=Xi(e,a,n,!1,i+1);Wi(l,o.atom,a,o.contains_complex_set),u||=o.contains_nested_negated_complex_set||o.negated&&o.contains_complex_set,a=o.end;continue}if(d===`-`){let t=e[a+1]===`]`||e.startsWith(`&&`,a+1);l.tail===`set`&&!t&&Ui(a),l.tail===null||l.tail===`range`||l.tail===`complete_range`||t?Gi(l,`\\-`):(l.fragment+=`-`,l.tail=`range`),++a;continue}Gi(l,d===`^`&&l.fragment.length===0?`\\^`:d),a+=d.length}throw SyntaxError(`${c.length>1?`Unterminated character-class intersection`:`Unterminated character class`} at index ${t}`)},Zi=e=>{let t=``,n=-1,r=!1,i=!1,a=[],o=e=>{n=t.length,t+=e,r=!1};for(let s=0;s=e.length){t+=c;break}let a=Li(e,s+1);if(s+=1+a.length,a===`G`)continue;let l=Ei.get(a);if(l!==void 0){o(l);continue}let u=Ci.get(a),d;d=u===void 0?/[A-Za-z0-9]/.test(a)||Oi.includes(a)?`\\${a}`:a:u,o(d);continue}switch(c){case`[`:{let t=Xi(e,s,i);o(t.atom),s=t.end;continue}case`]`:o(`\\]`),++s;continue;case`.`:o(`[^\\n]`),++s;continue;case`^`:o(bi),++s;continue;case`$`:o(xi),++s;continue;case`(`:{let n=e.startsWith(`(?i:`,s),o=n?`(?i:`:ki.exec(e.slice(s))?.[0]??`(`,c=n||o===`(?>`?`(?:`:o;a.push([t.length,i]),n&&(i=!0),t+=c,r=!1,s+=o.length;continue}case`)`:t+=c,[n,i]=a.pop()??[-1,!1],r=!1,++s;continue;case`|`:t+=c,n=-1,r=!1,++s;continue;case`{`:{let i=ji.exec(e.slice(s));if(!i||n<0){o(`\\{`),++s;continue}let a=i[1].startsWith(`,`)?`0${i[1]}`:i[1];s+=i[0].length;let c=e[s];c===`+`||c===`*`?(t=`${t.slice(0,n)}(?:${t.slice(n)}{${a}})${c}`,++s):t+=`{${a}}`,r=!0;continue}case`}`:o(`\\}`),++s;continue;case`+`:if(r){++s;continue}t+=c,r=!0,++s;continue;case`*`:case`?`:t+=c,r=!0,++s;continue;default:o(i&&Ii(c)?`[${c.toLowerCase()}${c.toUpperCase()}]`:c),s+=c.length;continue}}return t},Qi=e=>e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`),$i=(e,t,n)=>{let r=[],i=0;for(;ie>=19968&&e<=40959||e>=13312&&e<=19903||e>=131072&&e<=173791||e>=173824&&e<=177983||e>=177984&&e<=178207||e>=178208&&e<=183983||e>=63744&&e<=64255||e>=194560&&e<=195103,ta=e=>Number.isInteger(e)||typeof e==`bigint`,na=e=>{let t=0;for(let n of e)++t;return t},ra=e=>sa(e.toLowerCase()),ia=(...e)=>Array.prototype.concat.apply([],e),aa=e=>new Map(Object.entries(e)),oa=(e,t)=>{let n=[],r=0;for(let i of e.matchAll(t)){let t=i[0];r0&&n.push(t),r=i.index+t.length}return re.replace(/\p{M}/gu,``),ca=(e,t,n=[])=>{if(!e||Array.isArray(e)||typeof e!=`object`)return`${t} must be a valid object`;for(let r of n)if(!(r in e))return`${t} must contain a "${r}" property`;return null},la=e=>e.match(/\S+/g)||[],ua=class{constructor(){let e=function(...t){return e._call(...t)};return Object.setPrototypeOf(e,new.target.prototype)}},da=class extends ua{constructor(e){super(),this.config=e}_call(e){return this.normalize(e)}},fa=class extends da{tokenize_chinese_chars(e){let t=[];for(let n=0;ne.normalize(`NFKC`)).join(`~`):e.normalize(`NFKC`),e}},ma=class extends da{constructor(e){super(e),this.normalizers=(e.normalizers??[]).map(e=>Ea(e))}normalize(e){return this.normalizers.reduce((e,t)=>t?t.normalize(e):e,e)}},ha=class extends da{constructor(e){super(e),this.pattern=pi(this.config.pattern??{})}normalize(e){return this.pattern===null?e:e.replaceAll(this.pattern,this.config.content??``)}},ga=class extends da{constructor(){super(...arguments),this.form=`NFC`}normalize(e){return e=e.normalize(this.form),e}},_a=class extends ga{constructor(){super(...arguments),this.form=`NFC`}},va=class extends ga{constructor(){super(...arguments),this.form=`NFD`}},ya=class extends ga{constructor(){super(...arguments),this.form=`NFKC`}},ba=class extends ga{constructor(){super(...arguments),this.form=`NFKD`}},xa=class extends da{normalize(e){return this.config.strip_left&&this.config.strip_right?e=e.trim():(this.config.strip_left&&(e=e.trimStart()),this.config.strip_right&&(e=e.trimEnd())),e}},Sa=class extends da{normalize(e){return sa(e)}},Ca=class extends da{normalize(e){return e.toLowerCase()}},wa=class extends da{normalize(e){return e=this.config.prepend+e,e}};function Ta(e){if(e===null)return null;switch(e.type){case`BertNormalizer`:return new fa(e);case`Precompiled`:return new pa(e);case`Sequence`:return new ma(e);case`Replace`:return new ha(e);case`NFC`:return new _a(e);case`NFD`:return new va(e);case`NFKC`:return new ya(e);case`NFKD`:return new ba(e);case`Strip`:return new xa(e);case`StripAccents`:return new Sa(e);case`Lowercase`:return new Ca(e);case`Prepend`:return new wa(e);default:throw Error(`Unknown Normalizer type: ${e.type}`)}}var Ea=Ta,Da=class extends ua{pre_tokenize(e,t){return(Array.isArray(e)?e.map(e=>this.pre_tokenize_text(e,t)):this.pre_tokenize_text(e,t)).flat()}_call(e,t){return this.pre_tokenize(e,t)}},Oa=(()=>{let e=[...Array.from({length:94},(e,t)=>t+33),...Array.from({length:12},(e,t)=>t+161),...Array.from({length:82},(e,t)=>t+174)],t=e.slice(),n=0;for(let r=0;r<256;++r)e.includes(r)||(e.push(r),t.push(256+n),n+=1);let r=t.map(e=>String.fromCharCode(e));return Object.fromEntries(e.map((e,t)=>[e,r[t]]))})(),ka=(e=>Object.fromEntries(Object.entries(e).map(([e,t])=>[t,e])))(Oa),Aa=`\\p{P}\\u0021-\\u002F\\u003A-\\u0040\\u005B-\\u0060\\u007B-\\u007E`,ja=class extends Da{constructor(e){super(),this.config=e,this.add_prefix_space=this.config.add_prefix_space??!1,this.trim_offsets=this.config.trim_offsets??!1,this.use_regex=this.config.use_regex??!0,this.pattern=/'s|'t|'re|'ve|'m|'ll|'d| ?\p{L}+| ?\p{N}+| ?[^\s\p{L}\p{N}]+|\s+(?!\S)|\s+/gu,this.byte_encoder=Oa,this.text_encoder=new TextEncoder}pre_tokenize_text(e,t){return this.add_prefix_space&&!e.startsWith(` `)&&(e=` `+e),(this.use_regex?e.match(this.pattern)||[]:[e]).map(e=>Array.from(this.text_encoder.encode(e),e=>this.byte_encoder[e]).join(``))}},Ma=class extends Da{pre_tokenize_text(e,t){return e.match(/\w+|[^\w\s]+/g)||[]}},Na=class extends Da{constructor(e){super(),this.replacement=e.replacement??`▁`,this.str_rep=e.str_rep||this.replacement,this.prepend_scheme=e.prepend_scheme??`always`}pre_tokenize_text(e,t){let{section_index:n=void 0}=t??{},r=e.replaceAll(` `,this.str_rep);return!r.startsWith(this.replacement)&&(this.prepend_scheme===`always`||this.prepend_scheme===`first`&&n===0)&&(r=this.str_rep+r),[r]}},Pa=class extends Da{constructor(e){super(),this.config=e,this.pattern=pi(this.config.pattern??{},this.config.invert??!0)}pre_tokenize_text(e){return this.pattern===null?[]:this.config.invert?(e.match(this.pattern)||[]).filter(e=>e):this.config.behavior?.toLowerCase()===`removed`?e.split(this.pattern).filter(e=>e):oa(e,this.pattern)}},Fa=class extends Da{constructor(e){super(),this.config=e,this.pattern=RegExp(`[^${Aa}]+|[${Aa}]+`,`gu`)}pre_tokenize_text(e){return e.match(this.pattern)||[]}},Ia=class extends Da{constructor(e){super(),this.config=e;let t=`[^\\d]+|\\d${this.config.individual_digits?``:`+`}`;this.pattern=new RegExp(t,`gu`)}pre_tokenize_text(e){return e.match(this.pattern)||[]}},La=class extends Da{constructor(){super(),this.pattern=RegExp(`[^\\s${Aa}]+|[${Aa}]`,`gu`)}pre_tokenize_text(e,t){return e.trim().match(this.pattern)||[]}},Ra=class extends Da{constructor(e){super(),this.config=e,this.pattern=pi(this.config.pattern??{}),this.content=this.config.content??``}pre_tokenize_text(e){return this.pattern===null?[e]:[e.replaceAll(this.pattern,this.config.content??``)]}},za=class extends Da{constructor(e){super(),this.tokenizers=(e.pretokenizers??[]).map(e=>Ua(e))}pre_tokenize_text(e,t){return this.tokenizers.reduce((e,n)=>n?n.pre_tokenize(e,t):e,[e])}},Ba=class extends Da{pre_tokenize_text(e){return la(e)}},Va=class extends Da{constructor(e){super(),this.config=e,this._length=e.length}pre_tokenize_text(e){let t=[];for(let n=0;nthis.max_input_chars_per_word){t.push(this.unk_token);continue}let r=!1,i=0,a=[];for(;i0&&(r=this.config.continuing_subword_prefix+r),this.tokens_to_ids.has(r)){n=r;break}--t}if(n===null){r=!0;break}a.push(n),i=t}r?t.push(this.unk_token):t.push(...a)}return t}},Ka=class e{constructor(e,t){this.is_leaf=e,this.children=t}static default(){return new e(!1,/* @__PURE__ */ new Map)}},qa=class{constructor(){this.root=Ka.default()}extend(e){for(let t of e)this.push(t)}push(e){let t=this.root;for(let n of e){let e=t.children.get(n);e===void 0&&(e=Ka.default(),t.children.set(n,e)),t=e}t.is_leaf=!0}*common_prefix_search(e,t=0){let n=this.root;if(n===void 0)return;let r=``;for(let i=t;i[]),this.end_nodes=Array.from({length:this.len+1},()=>[]);let r=new Ja(this.bos_token_id??0,0,0,0,0),i=new Ja(this.eos_token_id??0,1,this.len,0,0);this.nodes.push(r.clone()),this.nodes.push(i.clone()),this.begin_nodes[this.len].push(i),this.end_nodes[0].push(r)}insert(e,t,n,r){let i=this.nodes.length,a=new Ja(r,i,e,t,n);this.begin_nodes[e].push(a),this.end_nodes[e+t].push(a),this.nodes.push(a)}viterbi(){let e=this.len,t=0;for(;t<=e;){if(this.begin_nodes[t].length==0)return[];for(let e of this.begin_nodes[t]){e.prev=null;let n=0,r=null;for(let i of this.end_nodes[t]){let t=i.backtrace_score+e.score;(r===null||t>n)&&(r=i.clone(),n=t)}if(r!==null)e.prev=r,e.backtrace_score=n;else return[]}++t}let n=[],r=this.begin_nodes[e][0].prev;if(r===null)return[];let i=r.clone();for(;i.prev!==null;)n.push(i.clone()),i=i.clone().prev.clone();return n.reverse(),n}piece(e){return this.chars.slice(e.pos,e.pos+e.length).join(``)}tokens(){return this.viterbi().map(e=>this.piece(e))}token_ids(){return this.viterbi().map(e=>e.token_id)}};function Xa(e){if(e.length===0)throw Error(`Array must not be empty`);let t=e[0],n=0;for(let r=1;r[e,t])),this.bos_token=` `,this.bos_token_id=this.tokens_to_ids.get(this.bos_token),this.eos_token=t,this.eos_token_id=this.tokens_to_ids.get(this.eos_token),this.unk_token=this.vocab[this.unk_token_id],this.min_score=Xa(this.scores)[0],this.unk_score=this.min_score-10,this.scores[this.unk_token_id]=this.unk_score,this.trie=new qa,this.trie.extend(this.vocab),this.fuse_unk=!0}populate_nodes(e){let t=e.chars,n=0;for(;ne>t,t=1/0){this._heap=[],this._comparator=e,this._max_size=t}get size(){return this._heap.length}is_empty(){return this.size===0}peek(){return this._heap[0]}push(...e){return this.extend(e)}extend(e){for(let t of e)if(this.size0&&this._swap(0,t),this._heap.pop(),this._sift_down(),e}replace(e){let t=this.peek();return this._heap[0]=e,this._sift_down(),t}_parent(e){return(e+1>>>1)-1}_left(e){return(e<<1)+1}_right(e){return e+1<<1}_greater(e,t){return this._comparator(this._heap[e],this._heap[t])}_swap(e,t){let n=this._heap[e];this._heap[e]=this._heap[t],this._heap[t]=n}_sift_up(){this._sift_up_from(this.size-1)}_sift_up_from(e){for(;e>0&&this._greater(e,this._parent(e));)this._swap(e,this._parent(e)),e=this._parent(e)}_sift_down(){let e=0;for(;this._left(e)this.capacity&&this.cache.delete(this.cache.keys().next().value)}clear(){this.cache.clear()}},eo=class extends Wa{constructor(e){super(e),this.tokens_to_ids=aa(e.vocab),this.unk_token_id=this.tokens_to_ids.get(e.unk_token),this.unk_token=e.unk_token,this.vocab=Array(this.tokens_to_ids.size);for(let[e,t]of this.tokens_to_ids)this.vocab[t]=e;let t=Array.isArray(e.merges[0]);this.merges=t?e.merges:e.merges.map(e=>e.split(` `,2)),this.bpe_ranks=new Map(this.merges.map((e,t)=>[JSON.stringify(e),t])),this.end_of_word_suffix=e.end_of_word_suffix,this.continuing_subword_suffix=e.continuing_subword_suffix??null,this.byte_fallback=this.config.byte_fallback??!1,this.byte_fallback&&(this.text_encoder=new TextEncoder),this.ignore_merges=this.config.ignore_merges??!1,this.max_length_to_cache=256,this.cache_capacity=1e4,this.cache=new $a(this.cache_capacity)}clear_cache(){this.cache.clear()}bpe(e){if(e.length===0)return[];let t=this.cache.get(e);if(t!==void 0)return t;let n=Array.from(e);this.end_of_word_suffix&&(n[n.length-1]+=this.end_of_word_suffix);let r=[];if(n.length>1){let e=new Qa((e,t)=>e.score`<0x${e.toString(16).toUpperCase().padStart(2,`0`)}>`);e.every(e=>this.tokens_to_ids.has(e))?t.push(...e):this.unk_token!=null&&t.push(this.unk_token)}else this.unk_token!=null&&t.push(this.unk_token)}return t}},to=class extends Wa{constructor(e,t){super(e);let n=e.vocab;this.tokens_to_ids=aa(t.target_lang?n[t.target_lang]:n),this.bos_token=t.bos_token,this.bos_token_id=this.tokens_to_ids.get(this.bos_token),this.eos_token=t.eos_token,this.eos_token_id=this.tokens_to_ids.get(this.eos_token),this.pad_token=t.pad_token,this.pad_token_id=this.tokens_to_ids.get(this.pad_token),this.unk_token=t.unk_token,this.unk_token_id=this.tokens_to_ids.get(this.unk_token),this.vocab=Array(this.tokens_to_ids.size);for(let[e,t]of this.tokens_to_ids)this.vocab[t]=e}encode(e){return e}};function no(e,t){switch(e.type){case`WordPiece`:return new Ga(e);case`Unigram`:return new Za(e,t.eos_token);case`BPE`:return new eo(e);default:if(e.vocab)return Array.isArray(e.vocab)?new Za(e,t.eos_token):Object.hasOwn(e,`continuing_subword_prefix`)&&Object.hasOwn(e,`unk_token`)?Object.hasOwn(e,`merges`)?new eo(e):new Ga(e):new to(e,{target_lang:t.target_lang,bos_token:t.bos_token,eos_token:t.eos_token,pad_token:t.pad_token,unk_token:t.unk_token});throw Error(`Unknown TokenizerModel type: ${e?.type}`)}}var ro=no,io=class extends ua{constructor(e){super(),this.config=e}_call(e,...t){return this.post_process(e,...t)}},ao=class extends io{post_process(e,t=null,n=!0){let r=t===null?this.config.single:this.config.pair,i=[],a=[];for(let o of r)`SpecialToken`in o?n&&(i.push(o.SpecialToken.id),a.push(o.SpecialToken.type_id)):`Sequence`in o&&(o.Sequence.id===`A`?(i=ia(i,e),a=ia(a,Array(e.length).fill(o.Sequence.type_id))):o.Sequence.id===`B`&&(i=ia(i,t),a=ia(a,Array(t.length).fill(o.Sequence.type_id))));return{tokens:i,token_type_ids:a}}},oo=class extends io{post_process(e,t=null){return{tokens:e,tokens_pair:t}}},so=class extends io{constructor(e){super(e),this.sep=e.sep,this.cls=e.cls}post_process(e,t=null,n=!0){n&&(e=ia([this.cls[0]],e,[this.sep[0]]));let r=Array(e.length).fill(0);if(t){let i=[],a=n?[this.sep[0]]:[];e=ia(e,i,t,a),r=ia(r,Array(t.length+i.length+a.length).fill(1))}return{tokens:e,token_type_ids:r}}},co=class extends io{constructor(e){super(e),this.sep=e.sep,this.cls=e.cls}post_process(e,t,n=!0){n&&(e=ia([this.cls[0]],e,[this.sep[0]]));let r=Array(e.length).fill(0);if(t){let i=n?[this.sep[0]]:[],a=n?[this.sep[0]]:[];e=ia(e,i,t,a),r=ia(r,Array(t.length+i.length+a.length).fill(1))}return{tokens:e,token_type_ids:r}}},lo=class extends io{constructor(e){super(e),this.processors=(e.processors??[]).map(e=>fo(e))}post_process(e,t=null,n=!0){let r={tokens:e,tokens_pair:t};for(let e of this.processors)r=e.post_process(r.tokens,r.tokens_pair,n);return r}};function uo(e){if(e===null)return null;switch(e.type){case`TemplateProcessing`:return new ao(e);case`ByteLevel`:return new oo(e);case`BertProcessing`:return new so(e);case`RobertaProcessing`:return new co(e);case`Sequence`:return new lo(e);default:throw Error(`Unknown PostProcessor type: ${e.type}`)}}var fo=uo,po=class extends ua{constructor(e){super(),this.config=e,this.added_tokens=[],this.end_of_word_suffix=null,this.trim_offsets=`trim_offsets`in e&&e.trim_offsets}_call(e){return this.decode(e)}decode(e){return this.decode_chain(e).join(``)}},mo=class extends po{constructor(e){super(e),this.byte_decoder=ka,this.text_decoder=new TextDecoder(`utf-8`,{fatal:!1,ignoreBOM:!0}),this.end_of_word_suffix=null}convert_tokens_to_string(e){let t=e.join(``),n=new Uint8Array([...t].map(e=>this.byte_decoder[e]));return this.text_decoder.decode(n)}decode_chain(e){let t=[],n=[];for(let r of e)this.added_tokens.find(e=>e.content===r)===void 0?n.push(r):(n.length>0&&(t.push(this.convert_tokens_to_string(n)),n=[]),t.push(r));return n.length>0&&t.push(this.convert_tokens_to_string(n)),t}},ho=class extends po{constructor(e){super(e),this.cleanup=e.cleanup}decode_chain(e){return e.map((e,t)=>{if(t!==0){let t=this.config.prefix;e=t&&e.startsWith(t)?e.replace(t,``):` `+e}return this.cleanup&&(e=fi(e)),e})}},go=class extends po{constructor(e){super(e),this.replacement=e.replacement??`▁`}decode_chain(e){let t=[];for(let n=0;nt.replaceAll(this.suffix,n===e.length-1?``:` `))}},vo=class extends po{constructor(e){super(e),this.pad_token=e.pad_token??``,this.word_delimiter_token=e.word_delimiter_token??``,this.cleanup=e.cleanup}convert_tokens_to_string(e){if(e.length===0)return``;let t=[e[0]];for(let n=1;ne!==this.pad_token).join(``);return this.cleanup&&(n=fi(n).replaceAll(this.word_delimiter_token,` `).trim()),n}decode_chain(e){return[this.convert_tokens_to_string(e)]}},yo=class extends po{constructor(e){super(e),this.decoders=(e.decoders??[]).map(e=>To(e))}decode_chain(e){return this.decoders.reduce((e,t)=>t.decode_chain(e),e)}},bo=class extends po{constructor(e){super(e),this.pattern=pi(this.config.pattern)}decode_chain(e){let t=this.config.content??``,n=this.pattern;return n===null?e:e.map(e=>e.replaceAll(n,t))}},xo=class extends po{decode_chain(e){return[e.join(``)]}},So=class extends po{constructor(e){super(e),this.content=e.content??``,this.start=e.start??0,this.stop=e.stop??0}decode_chain(e){return e.map(e=>{let t=0;for(let n=0;n`)){let t=parseInt(r.slice(3,5),16);isNaN(t)||(e=t)}if(e!==null)n.push(e);else{if(n.length>0){let e=this.text_decoder.decode(Uint8Array.from(n));t.push(e),n=[]}t.push(r)}}if(n.length>0){let e=this.text_decoder.decode(Uint8Array.from(n));t.push(e),n=[]}return t}};function wo(e){if(e===null)return null;switch(e.type){case`ByteLevel`:return new mo(e);case`WordPiece`:return new ho(e);case`Metaspace`:return new go(e);case`BPEDecoder`:return new _o(e);case`CTC`:return new vo(e);case`Sequence`:return new yo(e);case`Replace`:return new bo(e);case`Fuse`:return new xo(e);case`Strip`:return new So(e);case`ByteFallback`:return new Co(e);default:throw Error(`Unknown Decoder type: ${e.type}`)}}var To=wo,Eo=class{constructor(e,t){let n=ca(e,`Tokenizer`,[`model`,`decoder`,`post_processor`,`pre_tokenizer`,`normalizer`]);if(n)throw Error(n);let r=ca(t,`Config`);if(r)throw Error(r);this.tokenizer=e,this.config=t,this.normalizer=Ea(this.tokenizer.normalizer),this.pre_tokenizer=Ua(this.tokenizer.pre_tokenizer),this.model=ro(this.tokenizer.model,this.config),this.post_processor=fo(this.tokenizer.post_processor),this.decoder=To(this.tokenizer.decoder),this.special_tokens=[],this.all_special_ids=[],this.added_tokens=[];let i=[],a=[];this.added_tokens_map=/* @__PURE__ */ new Map;for(let e of this.tokenizer.added_tokens){let t=new ui(e);if(this.added_tokens.push(t),this.model.tokens_to_ids.set(t.content,t.id),this.model.vocab[t.id]=t.content,t.special&&(this.special_tokens.push(t.content),this.all_special_ids.push(t.id)),this.added_tokens_map.set(t.content,t),t.normalized&&this.normalizer!==null){let e=this.normalizer(t.content);a.push(e),this.added_tokens_map.set(e,t)}else i.push(t.content)}(this.config.additional_special_tokens??[]).forEach(e=>{this.special_tokens.includes(e)||this.special_tokens.push(e)}),this.decoder&&(this.decoder.added_tokens=this.added_tokens,this.decoder.end_of_word_suffix=this.model.end_of_word_suffix),this.splitter_unnormalized=new li(i),this.splitter_normalized=new li(a),this.remove_space=this.config.remove_space,this.clean_up_tokenization_spaces=this.config.clean_up_tokenization_spaces??!0,this.do_lowercase_and_remove_accent=this.config.do_lowercase_and_remove_accent??!1}encode(e,{text_pair:t=null,add_special_tokens:n=!0,return_token_type_ids:r=null}={}){let{tokens:i,token_type_ids:a}=this.tokenize_helper(e,{text_pair:t,add_special_tokens:n}),o=i.map(e=>this.added_tokens_map.get(e)?.id??this.model.tokens_to_ids.get(e)??this.model.unk_token_id),s={ids:o,tokens:i,attention_mask:Array(o.length).fill(1)};return r&&a&&(s.token_type_ids=a),s}decode(e,t={}){if(!Array.isArray(e)||e.length===0||!ta(e[0]))throw Error(`token_ids must be a non-empty array of integers.`);let n=e.map(e=>this.model.vocab[Number(e)]??this.model.unk_token);t.skip_special_tokens&&(n=n.filter(e=>!this.special_tokens.includes(e)));let r=this.decoder?this.decoder(n):n.join(` `);return this.decoder&&this.decoder.end_of_word_suffix&&(r=r.replaceAll(this.decoder.end_of_word_suffix,` `),t.skip_special_tokens&&(r=r.trim())),(t.clean_up_tokenization_spaces??this.clean_up_tokenization_spaces)&&(r=fi(r)),r}tokenize(e,{text_pair:t=null,add_special_tokens:n=!1}={}){return this.tokenize_helper(e,{text_pair:t,add_special_tokens:n}).tokens}encode_text(e){if(e===null)return null;let t=this.splitter_unnormalized.split(e);return t.forEach((e,n)=>{let r=this.added_tokens_map.get(e);r&&(r.lstrip&&n>0&&(t[n-1]=t[n-1].trimEnd()),r.rstrip&&n{if(e.length===0)return[];if(this.added_tokens_map.has(e))return[e];if(this.remove_space===!0&&(e=e.trim().split(/\s+/).join(` `)),this.do_lowercase_and_remove_accent&&(e=ra(e)),this.normalizer!==null&&(e=this.normalizer(e)),e.length===0)return[];let n=this.splitter_normalized.split(e);return n.forEach((e,t)=>{let r=this.added_tokens_map.get(e);r&&(r.lstrip&&t>0&&(n[t-1]=n[t-1].trimEnd()),r.rstrip&&t{if(e.length===0)return[];if(this.added_tokens_map.has(e))return[e];let n=this.pre_tokenizer===null?[e]:this.pre_tokenizer(e,{section_index:t});return this.model(n)})})}tokenize_helper(e,{text_pair:t=null,add_special_tokens:n=!0}){let r=this.encode_text(e),i=this.encode_text(t||null);return this.post_processor?this.post_processor(r,i,n):{tokens:ia(r??[],i??[])}}token_to_id(e){return this.model.tokens_to_ids.get(e)}id_to_token(e){return this.model.vocab[e]}get_added_tokens_decoder(){let e=/* @__PURE__ */ new Map;for(let t of this.added_tokens)e.set(t.id,t);return e}get_vocab(e=!0){let t=/* @__PURE__ */ new Map;for(let n=0;nt in e?Do(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,ko=(e,t,n)=>(Oo(e,typeof t==`symbol`?t:t+``,n),n),j=Object.freeze({Text:`Text`,NumericLiteral:`NumericLiteral`,StringLiteral:`StringLiteral`,Identifier:`Identifier`,Equals:`Equals`,OpenParen:`OpenParen`,CloseParen:`CloseParen`,OpenStatement:`OpenStatement`,CloseStatement:`CloseStatement`,OpenExpression:`OpenExpression`,CloseExpression:`CloseExpression`,OpenSquareBracket:`OpenSquareBracket`,CloseSquareBracket:`CloseSquareBracket`,OpenCurlyBracket:`OpenCurlyBracket`,CloseCurlyBracket:`CloseCurlyBracket`,Comma:`Comma`,Dot:`Dot`,Colon:`Colon`,Pipe:`Pipe`,CallOperator:`CallOperator`,AdditiveBinaryOperator:`AdditiveBinaryOperator`,MultiplicativeBinaryOperator:`MultiplicativeBinaryOperator`,ExponentiationBinaryOperator:`ExponentiationBinaryOperator`,ComparisonBinaryOperator:`ComparisonBinaryOperator`,UnaryOperator:`UnaryOperator`,Comment:`Comment`}),Ao=class{constructor(e,t){this.value=e,this.type=t}};function jo(e){return/\w/.test(e)}function Mo(e){return/[0-9]/.test(e)}function No(e){return/\s/.test(e)}var Po=[[`{%`,j.OpenStatement],[`%}`,j.CloseStatement],[`{{`,j.OpenExpression],[`}}`,j.CloseExpression],[`(`,j.OpenParen],[`)`,j.CloseParen],[`{`,j.OpenCurlyBracket],[`}`,j.CloseCurlyBracket],[`[`,j.OpenSquareBracket],[`]`,j.CloseSquareBracket],[`,`,j.Comma],[`.`,j.Dot],[`:`,j.Colon],[`|`,j.Pipe],[`<=`,j.ComparisonBinaryOperator],[`>=`,j.ComparisonBinaryOperator],[`==`,j.ComparisonBinaryOperator],[`!=`,j.ComparisonBinaryOperator],[`<`,j.ComparisonBinaryOperator],[`>`,j.ComparisonBinaryOperator],[`+`,j.AdditiveBinaryOperator],[`-`,j.AdditiveBinaryOperator],[`~`,j.AdditiveBinaryOperator],[`**`,j.ExponentiationBinaryOperator],[`*`,j.MultiplicativeBinaryOperator],[`//`,j.MultiplicativeBinaryOperator],[`/`,j.MultiplicativeBinaryOperator],[`%`,j.MultiplicativeBinaryOperator],[`=`,j.Equals]],Fo=/* @__PURE__ */ new Map([[`n`,` +`],[`t`,` `],[`r`,`\r`],[`b`,`\b`],[`f`,`\f`],[`v`,`\v`],[`'`,`'`],[`"`,`"`],[`\\`,`\\`]]);function Io(e,t={}){return e.endsWith(` +`)&&(e=e.slice(0,-1)),t.lstrip_blocks&&(e=e.replace(/^[ \t]*({[#%-])/gm,`$1`)),t.trim_blocks&&(e=e.replace(/([#%-]})\n/g,`$1`)),e.replace(/(\s*){%(-?)\s*(?:end)?generation\s*(-?)%}(\s*)/gs,(e,t,n,r,i)=>(n?``:t)+(r?``:i))}function Lo(e,t={}){let n=[],r=Io(e,t),i=0,a=0,o=e=>{let t=``;for(;e(r[i]);){if(r[i]===`\\`){if(++i,i>=r.length)throw SyntaxError(`Unexpected end of input`);let e=r[i++],n=Fo.get(e);if(n===void 0)throw SyntaxError(`Unexpected escaped character: ${e}`);t+=n;continue}if(t+=r[i++],i>=r.length)throw SyntaxError(`Unexpected end of input`)}return t},s=()=>{let e=n.at(-1);e&&e.type===j.Text&&(e.value=e.value.trimEnd(),e.value===``&&n.pop())},c=()=>{for(;i0){n.push(new Ao(e,j.Text));continue}}if(r[i]===`{`&&r[i+1]===`#`){i+=2;let e=r[i]===`-`;e&&++i;let t=``;for(;r[i]!==`#`||r[i+1]!==`}`;){if(i+2>=r.length)throw SyntaxError(`Missing end of comment tag`);t+=r[i++]}let a=t.endsWith(`-`);a&&(t=t.slice(0,-1)),e&&s(),n.push(new Ao(t,j.Comment)),i+=2,a&&c();continue}if(r.slice(i,i+3)===`{%-`){s(),n.push(new Ao(`{%`,j.OpenStatement)),i+=3;continue}if(r.slice(i,i+3)===`{{-`){s(),n.push(new Ao(`{{`,j.OpenExpression)),a=0,i+=3;continue}if(o(No),r.slice(i,i+3)===`-%}`){n.push(new Ao(`%}`,j.CloseStatement)),i+=3,c();continue}if(r.slice(i,i+3)===`-}}`){n.push(new Ao(`}}`,j.CloseExpression)),i+=3,c();continue}let t=r[i];if(t===`-`||t===`+`){let e=n.at(-1)?.type;if(e===j.Text||e===void 0)throw SyntaxError(`Unexpected character: ${t}`);switch(e){case j.Identifier:case j.NumericLiteral:case j.StringLiteral:case j.CloseParen:case j.CloseSquareBracket:break;default:{++i;let e=o(Mo);if(e.length>0&&r[i]===`.`&&Mo(r[i+1])){++i;let t=o(Mo);e=`${e}.${t}`}n.push(new Ao(`${t}${e}`,e.length>0?j.NumericLiteral:j.UnaryOperator));continue}}}for(let[e,t]of Po)if(!(e===`}}`&&a>0)&&r.slice(i,i+e.length)===e){n.push(new Ao(e,t)),t===j.OpenExpression?a=0:t===j.OpenCurlyBracket?++a:t===j.CloseCurlyBracket&&--a,i+=e.length;continue main}if(t===`'`||t===`"`){++i;let e=o(e=>e!==t);n.push(new Ao(e,j.StringLiteral)),++i;continue}if(Mo(t)){let e=o(Mo);if(n.at(-1)?.type!==j.Dot&&r[i]===`.`&&Mo(r[i+1])){++i;let t=o(Mo);e=`${e}.${t}`}n.push(new Ao(e,j.NumericLiteral));continue}if(jo(t)){let e=o(jo);n.push(new Ao(e,j.Identifier));continue}throw SyntaxError(`Unexpected character: ${t}`)}return n}var Ro=class{type=`Statement`},zo=class extends Ro{constructor(e){super(),this.body=e}type=`Program`},Bo=class extends Ro{constructor(e,t,n){super(),this.test=e,this.body=t,this.alternate=n}type=`If`},Vo=class extends Ro{constructor(e,t,n,r){super(),this.loopvar=e,this.iterable=t,this.body=n,this.defaultBlock=r}type=`For`},Ho=class extends Ro{type=`Break`},Uo=class extends Ro{type=`Continue`},Wo=class extends Ro{constructor(e,t,n){super(),this.assignee=e,this.value=t,this.body=n}type=`Set`},Go=class extends Ro{constructor(e,t,n){super(),this.name=e,this.args=t,this.body=n}type=`Macro`},Ko=class extends Ro{constructor(e){super(),this.value=e}type=`Comment`},qo=class extends Ro{type=`Expression`},Jo=class extends qo{constructor(e,t,n){super(),this.object=e,this.property=t,this.computed=n}type=`MemberExpression`},Yo=class extends qo{constructor(e,t){super(),this.callee=e,this.args=t}type=`CallExpression`},Xo=class extends qo{constructor(e){super(),this.value=e}type=`Identifier`},Zo=class extends qo{constructor(e){super(),this.value=e}type=`Literal`},Qo=class extends Zo{type=`IntegerLiteral`},$o=class extends Zo{type=`FloatLiteral`},es=class extends Zo{type=`StringLiteral`},ts=class extends Zo{type=`ArrayLiteral`},ns=class extends Zo{type=`TupleLiteral`},rs=class extends Zo{type=`ObjectLiteral`},is=class extends qo{constructor(e,t,n){super(),this.operator=e,this.left=t,this.right=n}type=`BinaryExpression`},as=class extends qo{constructor(e,t){super(),this.operand=e,this.filter=t}type=`FilterExpression`},os=class extends Ro{constructor(e,t){super(),this.filter=e,this.body=t}type=`FilterStatement`},ss=class extends qo{constructor(e,t){super(),this.lhs=e,this.test=t}type=`SelectExpression`},cs=class extends qo{constructor(e,t,n){super(),this.operand=e,this.negate=t,this.test=n}type=`TestExpression`},ls=class extends qo{constructor(e,t){super(),this.operator=e,this.argument=t}type=`UnaryExpression`},us=class extends qo{constructor(e=void 0,t=void 0,n=void 0){super(),this.start=e,this.stop=t,this.step=n}type=`SliceExpression`},ds=class extends qo{constructor(e,t){super(),this.key=e,this.value=t}type=`KeywordArgumentExpression`},fs=class extends qo{constructor(e){super(),this.argument=e}type=`SpreadExpression`},ps=class extends qo{constructor(e){super(),this.argument=e}type=`KeywordSpreadExpression`},ms=class extends Ro{constructor(e,t,n){super(),this.call=e,this.callerArgs=t,this.body=n}type=`CallStatement`},hs=class extends qo{constructor(e,t,n){super(),this.condition=e,this.trueExpr=t,this.falseExpr=n}type=`Ternary`};function gs(e){let t=new zo([]),n=0;function r(t,r){let i=e[n++];if(!i||i.type!==t)throw Error(`Parser Error: ${r}. ${i.type} !== ${t}.`);return i}function i(e){if(!c(e))throw SyntaxError(`Expected ${e}`);++n}function a(){switch(e[n].type){case j.Comment:return new Ko(e[n++].value);case j.Text:return l();case j.OpenStatement:return u();case j.OpenExpression:return d();default:throw SyntaxError(`Unexpected token type: ${e[n].type}`)}}function o(...t){return n+t.length<=e.length&&t.every((t,r)=>t===e[n+r].type)}function s(...t){return e[n]?.type===j.OpenStatement&&e[n+1]?.type===j.Identifier&&t.includes(e[n+1]?.value)}function c(...t){return n+t.length<=e.length&&t.every((t,r)=>e[n+r].type===`Identifier`&&t===e[n+r].value)}function l(){return new es(r(j.Text,`Expected text token`).value)}function u(){if(r(j.OpenStatement,`Expected opening statement token`),e[n].type!==j.Identifier)throw SyntaxError(`Unknown statement, got ${e[n].type}`);let t=e[n].value,c;switch(t){case`set`:++n,c=f();break;case`if`:++n,c=p(),r(j.OpenStatement,`Expected {% token`),i(`endif`),r(j.CloseStatement,`Expected %} token`);break;case`macro`:++n,c=m(),r(j.OpenStatement,`Expected {% token`),i(`endmacro`),r(j.CloseStatement,`Expected %} token`);break;case`for`:++n,c=g(),r(j.OpenStatement,`Expected {% token`),i(`endfor`),r(j.CloseStatement,`Expected %} token`);break;case`call`:{++n;let e=null;o(j.OpenParen)&&(e=ne(`parameters`));let t=w();if(t.type!==`Identifier`)throw SyntaxError(`Expected identifier following call statement`);let l=ne(`call`);r(j.CloseStatement,`Expected closing statement token`);let u=[];for(;!s(`endcall`);)u.push(a());r(j.OpenStatement,`Expected '{%'`),i(`endcall`),r(j.CloseStatement,`Expected closing statement token`),c=new ms(new Yo(t,l),e,u);break}case`break`:++n,r(j.CloseStatement,`Expected closing statement token`),c=new Ho;break;case`continue`:++n,r(j.CloseStatement,`Expected closing statement token`),c=new Uo;break;case`filter`:{++n;let e=w();e instanceof Xo&&o(j.OpenParen)&&(e=te(e)),r(j.CloseStatement,`Expected closing statement token`);let t=[];for(;!s(`endfilter`);)t.push(a());r(j.OpenStatement,`Expected '{%'`),i(`endfilter`),r(j.CloseStatement,`Expected '%}'`),c=new os(e,t);break}default:throw SyntaxError(`Unknown statement type: ${t}`)}return c}function d(){r(j.OpenExpression,`Expected opening expression token`);let e=_();return r(j.CloseExpression,`Expected closing expression token`),e}function f(){let e=h(),t=null,c=[];if(o(j.Equals))++n,t=h();else{for(r(j.CloseStatement,`Expected %} token`);!s(`endset`);)c.push(a());r(j.OpenStatement,`Expected {% token`),i(`endset`)}return r(j.CloseStatement,`Expected closing statement token`),new Wo(e,t,c)}function p(){let e=_();r(j.CloseStatement,`Expected closing statement token`);let t=[],i=[];for(;!s(`elif`,`else`,`endif`);)t.push(a());if(s(`elif`)){++n,++n;let e=p();i.push(e)}else if(s(`else`))for(++n,++n,r(j.CloseStatement,`Expected closing statement token`);!s(`endif`);)i.push(a());return new Bo(e,t,i)}function m(){let e=w();if(e.type!==`Identifier`)throw SyntaxError(`Expected identifier following macro statement`);let t=ne(`parameters`);r(j.CloseStatement,`Expected closing statement token`);let n=[];for(;!s(`endmacro`);)n.push(a());return new Go(e,t,n)}function h(e=!1){let t=e?w:_,r=[t()],i=o(j.Comma);for(;i&&(++n,r.push(t()),o(j.Comma)););return i?new ns(r):r[0]}function g(){let e=h(!0);if(!(e instanceof Xo||e instanceof ns))throw SyntaxError(`Expected identifier/tuple for the loop variable, got ${e.type} instead`);if(!c(`in`))throw SyntaxError("Expected `in` keyword following loop variable");++n;let t=_();r(j.CloseStatement,`Expected closing statement token`);let i=[];for(;!s(`endfor`,`else`);)i.push(a());let o=[];if(s(`else`))for(++n,++n,r(j.CloseStatement,`Expected closing statement token`);!s(`endfor`);)o.push(a());return new Vo(e,t,i,o)}function _(){return v()}function v(){let e=y();if(c(`if`)){++n;let t=y();return c(`else`)?(++n,new hs(t,e,v())):new ss(e,t)}return e}function y(){let t=b();for(;c(`or`);){let r=e[n];++n;let i=b();t=new is(r,t,i)}return t}function b(){let t=x();for(;c(`and`);){let r=e[n];++n;let i=x();t=new is(r,t,i)}return t}function x(){let t;for(;c(`not`);){let r=e[n];++n,t=new ls(r,x())}return t??S()}function S(){let t=C();for(;;){let r;if(c(`not`,`in`))r=new Ao(`not in`,j.Identifier),n+=2;else if(c(`in`))r=e[n++];else if(o(j.ComparisonBinaryOperator))r=e[n++];else break;let i=C();t=new is(r,t,i)}return t}function C(){let t=oe();for(;o(j.AdditiveBinaryOperator);){let r=e[n];++n;let i=oe();t=new is(r,t,i)}return t}function ee(){let e=ae(w());return o(j.OpenParen)?te(e):e}function te(e){let t=new Yo(e,ne(`call`));return t=ae(t),o(j.OpenParen)&&(t=te(t)),t}function ne(e){r(j.OpenParen,`Expected opening parenthesis for arguments list`);let t=re(e);return r(j.CloseParen,`Expected closing parenthesis for arguments list`),t}function re(t){let r=[],i=/* @__PURE__ */ new Set,a=!1,s=!1;for(;!o(j.CloseParen);){let c=o(j.ExponentiationBinaryOperator),l=o(j.MultiplicativeBinaryOperator)&&e[n].value===`*`;if(t===`parameters`&&(c||l))throw SyntaxError(`Argument unpacking is not allowed in parameter declarations`);if(c){if(++n,r.push(new ps(_())),o(j.Comma)&&++n,!o(j.CloseParen))throw SyntaxError("Expected closing parenthesis: `**` must be applied to the final argument");break}let u;if(l){if(s)throw SyntaxError("Only one `*` argument unpacking is allowed");s=!0,++n,u=new fs(_())}else{if(u=_(),o(j.Equals)){if(++n,!(u instanceof Xo))throw SyntaxError(t===`parameters`?`Expected identifier for parameter declaration`:`Expected identifier for keyword argument`);let e=_();u=new ds(u,e)}if(t===`parameters`){if(!(u instanceof Xo||u instanceof ds))throw SyntaxError(`Expected identifier for parameter declaration`);let e=u instanceof Xo?u.value:u.key.value;if(i.has(e))throw SyntaxError(`Duplicate parameter name: ${e}`);i.add(e)}if(u instanceof ds)a=!0;else if(a)throw SyntaxError(t===`call`?`Positional arguments must come before keyword arguments`:`Non-default argument follows default argument`);else if(s)throw SyntaxError("Positional arguments must not follow `*` argument unpacking")}r.push(u),o(j.Comma)&&++n}return r}function ie(){let e=[],t=!1;for(;!o(j.CloseSquareBracket);)o(j.Colon)?(e.push(void 0),++n,t=!0):(e.push(_()),o(j.Colon)&&(++n,t=!0));if(e.length===0)throw SyntaxError(`Expected at least one argument for member/slice expression`);if(t){if(e.length>3)throw SyntaxError(`Expected 0-3 arguments for slice expression`);return new us(...e)}return e[0]}function ae(t){for(;o(j.Dot)||o(j.OpenSquareBracket);){let i=e[n];++n;let a,o=i.type===j.OpenSquareBracket;if(o)a=ie(),r(j.CloseSquareBracket,`Expected closing square bracket`);else if(a=w(),a.type!==`Identifier`&&a.type!==`IntegerLiteral`)throw SyntaxError(`Expected identifier or integer following dot operator`);t=new Jo(t,a,o)}return t}function oe(){let t=se();for(;o(j.MultiplicativeBinaryOperator);){let r=e[n++],i=se();t=new is(r,t,i)}return t}function se(){let t=ce();for(;o(j.ExponentiationBinaryOperator);){let r=e[n++],i=ce();t=new is(r,t,i)}return t}function ce(){let e=le();for(;c(`is`);){++n;let t=c(`not`);t&&++n;let r=w();if(!(r instanceof Xo))throw SyntaxError(`Expected identifier for the test`);e=new cs(e,t,r)}return e}function le(){let e=ue();for(;o(j.Pipe);){++n;let t=w();if(!(t instanceof Xo))throw SyntaxError(`Expected identifier for the filter`);o(j.OpenParen)&&(t=te(t)),e=new as(e,t)}return e}function ue(){let t=e[n];if(t&&(t.type===j.UnaryOperator||t.type===j.AdditiveBinaryOperator)&&(t.value===`-`||t.value===`+`)){let t=e[n++];return new ls(t,ue())}return ee()}function w(){let t=e[n++];switch(t.type){case j.NumericLiteral:{let e=t.value;return e.includes(`.`)?new $o(Number(e)):new Qo(Number(e))}case j.StringLiteral:{let r=t.value;for(;o(j.StringLiteral);)r+=e[n++].value;return new es(r)}case j.Identifier:return new Xo(t.value);case j.OpenParen:{let e=h();return r(j.CloseParen,"Expected closing parenthesis, got ${tokens[current].type} instead."),e}case j.OpenSquareBracket:{let e=[];for(;!o(j.CloseSquareBracket);)e.push(_()),o(j.Comma)&&++n;return++n,new ts(e)}case j.OpenCurlyBracket:{let e=/* @__PURE__ */ new Map;for(;!o(j.CloseCurlyBracket);){let t=_();r(j.Colon,`Expected colon between key and value in object literal`);let i=_();e.set(t,i),o(j.Comma)&&++n}return++n,new rs(e)}default:throw SyntaxError(`Unexpected token: ${t.type}`)}}for(;n0)for(let i=e;it;i+=n)r.push(i);return r}function vs(e,t,n,r=1){let i=Math.sign(r);i>=0?(t=(t??=0)<0?Math.max(e.length+t,0):Math.min(t,e.length),n=(n??=e.length)<0?Math.max(e.length+n,0):Math.min(n,e.length)):(t=(t??=e.length-1)<0?Math.max(e.length+t,-1):Math.min(t,e.length-1),n=(n??=-1)<-1?Math.max(e.length+n,-1):Math.min(n,e.length-1));let a=[];for(let o=t;i*oe.toUpperCase())}function bs(e){return xs(/* @__PURE__ */ new Date,e)}function xs(e,t){let n=new Intl.DateTimeFormat(void 0,{month:`long`}),r=new Intl.DateTimeFormat(void 0,{month:`short`}),i=e=>e<10?`0`+e:e.toString();return t.replace(/%[YmdbBHM%]/g,t=>{switch(t){case`%Y`:return e.getFullYear().toString();case`%m`:return i(e.getMonth()+1);case`%d`:return i(e.getDate());case`%b`:return r.format(e);case`%B`:return n.format(e);case`%H`:return i(e.getHours());case`%M`:return i(e.getMinutes());case`%%`:return`%`;default:return t}})}function Ss(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function Cs(e,t,n,r){if(r===0)return e;let i=r==null||r<0?1/0:r,a=t.length===0?/* @__PURE__ */ RegExp(`(?=)`,`gu`):new RegExp(Ss(t),`gu`);return e.replaceAll(a,e=>i>0?(--i,n):e)}var ws=class extends Error{},Ts=class extends Error{},Es=/* @__PURE__ */ new Map,Ds=class{type=`RuntimeValue`;value;get builtins(){return Es}constructor(e=void 0){this.value=e}__bool__(){return new F(!!this.value)}toString(){return String(this.value)}},M=class extends Ds{type=`IntegerValue`},N=class extends Ds{type=`FloatValue`;toString(){return Object.is(this.value,-0)?`-0.0`:this.value%1==0?this.value.toFixed(1):this.value.toString()}},P=class extends Ds{type=`StringValue`;_builtins;get builtins(){return this._builtins??=/* @__PURE__ */ new Map([[`upper`,new L(()=>new P(this.value.toUpperCase()))],[`lower`,new L(()=>new P(this.value.toLowerCase()))],[`strip`,new L(()=>new P(this.value.trim()))],[`title`,new L(()=>new P(ys(this.value)))],[`capitalize`,new L(()=>new P(this.value.charAt(0).toUpperCase()+this.value.slice(1)))],[`length`,new M(this.value.length)],[`rstrip`,new L(()=>new P(this.value.trimEnd()))],[`lstrip`,new L(()=>new P(this.value.trimStart()))],[`startswith`,new L(e=>{if(e.length===0)throw Error(`startswith() requires at least one argument`);let t=e[0];if(t instanceof P)return new F(this.value.startsWith(t.value));if(t instanceof I){for(let e of t.value){if(!(e instanceof P))throw Error(`startswith() tuple elements must be strings`);if(this.value.startsWith(e.value))return new F(!0)}return new F(!1)}throw Error(`startswith() argument must be a string or tuple of strings`)})],[`endswith`,new L(e=>{if(e.length===0)throw Error(`endswith() requires at least one argument`);let t=e[0];if(t instanceof P)return new F(this.value.endsWith(t.value));if(t instanceof I){for(let e of t.value){if(!(e instanceof P))throw Error(`endswith() tuple elements must be strings`);if(this.value.endsWith(e.value))return new F(!0)}return new F(!1)}throw Error(`endswith() argument must be a string or tuple of strings`)})],[`split`,new L(e=>{let t=e[0]??new R;if(!(t instanceof P||t instanceof R))throw Error(`sep argument must be a string or null`);let n=e[1]??new M(-1);if(!(n instanceof M))throw Error(`maxsplit argument must be a number`);let r=[];if(t instanceof R){let e=this.value.trimStart();for(let{0:t,index:i}of e.matchAll(/\S+/g)){if(n.value!==-1&&r.length>=n.value&&i!==void 0){r.push(t+e.slice(i+t.length));break}r.push(t)}}else{if(t.value===``)throw Error(`empty separator`);r=this.value.split(t.value),n.value!==-1&&r.length>n.value&&r.push(r.splice(n.value).join(t.value))}return new I(r.map(e=>new P(e)))})],[`replace`,new L(e=>{if(e.length<2)throw Error(`replace() requires at least two arguments`);let t=e[0],n=e[1];if(!(t instanceof P&&n instanceof P))throw Error(`replace() arguments must be strings`);let r;if(r=e.length>2?e[2].type===`KeywordArgumentsValue`?e[2].value.get(`count`)??new R:e[2]:new R,!(r instanceof M||r instanceof R))throw Error(`replace() count argument must be a number or null`);return new P(Cs(this.value,t.value,n.value,r.value))})]])}},F=class extends Ds{type=`BooleanValue`},Os=/[\x7f-\uffff]/g;function ks(e){return e.replace(Os,e=>`\\u`+e.charCodeAt(0).toString(16).padStart(4,`0`))}function As(e,t={},n=0,r=!0){let{indent:i=null,ensureAscii:a=!1,separators:o=null,sortKeys:s=!1}=t,c,l;switch(o?[c,l]=o:i?(c=`,`,l=`: `):(c=`, `,l=`: `),e.type){case`NullValue`:return`null`;case`UndefinedValue`:return r?`null`:`undefined`;case`IntegerValue`:case`FloatValue`:case`BooleanValue`:return JSON.stringify(e.value);case`StringValue`:{let t=JSON.stringify(e.value);return a&&(t=ks(t)),t}case`ArrayValue`:case`NamespaceValue`:case`ObjectValue`:{let o=i?` `.repeat(i):``,u=` +`+o.repeat(n),d=u+o;if(e.type===`ArrayValue`){let a=e.value.map(e=>As(e,t,n+1,r));return i?`[${d}${a.join(`${c}${d}`)}${u}]`:`[${a.join(c)}]`}{let o=Array.from(e.value.entries());s&&(o=o.sort(([e],[t])=>e.localeCompare(t)));let f=o.map(([e,o])=>{let s=JSON.stringify(e);a&&(s=ks(s));let c=`${s}${l}${As(o,t,n+1,r)}`;return i?`${d}${c}`:c});return i?`{${f.join(c)}${u}}`:`{${f.join(c)}}`}}default:throw Error(`Cannot convert to JSON: ${e.type}`)}}var js=class extends Ds{type=`ObjectValue`;_builtins;__bool__(){return new F(this.value.size>0)}get builtins(){return this._builtins??=/* @__PURE__ */ new Map([[`get`,new L(([e,t])=>{if(!(e instanceof P))throw Error(`Object key must be a string: got ${e.type}`);return this.value.get(e.value)??t??new R})],[`items`,new L(()=>this.items())],[`keys`,new L(()=>this.keys())],[`values`,new L(()=>this.values())],[`dictsort`,new L(e=>{let t=/* @__PURE__ */ new Map,n=e.filter(e=>e instanceof Ms?(t=e.value,!1):!0),r=n.at(0)??t.get(`case_sensitive`)??new F(!1);if(!(r instanceof F))throw Error(`case_sensitive must be a boolean`);let i=n.at(1)??t.get(`by`)??new P(`key`);if(!(i instanceof P))throw Error(`by must be a string`);if(![`key`,`value`].includes(i.value))throw Error(`by must be either 'key' or 'value'`);let a=n.at(2)??t.get(`reverse`)??new F(!1);if(!(a instanceof F))throw Error(`reverse must be a boolean`);return new I(Array.from(this.value.entries()).map(([e,t])=>new I([new P(e),t])).sort((e,t)=>{let n=i.value===`key`?0:1,o=e.value[n],s=t.value[n],c=Us(o,s,r.value);return a.value?-c:c}))})]])}items(){return new I(Array.from(this.value.entries()).map(([e,t])=>new I([new P(e),t])))}keys(){return new I(Array.from(this.value.keys()).map(e=>new P(e)))}values(){return new I(Array.from(this.value.values()))}toString(){return As(this,{},0,!1)}},Ms=class extends js{type=`KeywordArgumentsValue`},Ns=class extends Ds{type=`NamespaceValue`;toString(){return As(this,{},0,!1)}},I=class extends Ds{type=`ArrayValue`;_builtins;get builtins(){return this._builtins??=/* @__PURE__ */ new Map([[`length`,new M(this.value.length)]])}__bool__(){return new F(this.value.length>0)}toString(){return As(this,{},0,!1)}},Ps=class extends I{type=`TupleValue`},L=class extends Ds{type=`FunctionValue`},R=class extends Ds{type=`NullValue`},z=class extends Ds{type=`UndefinedValue`};function Fs(e){let t;if(e instanceof I?t=e.value:e instanceof P&&(t=Array.from(e.value,e=>new P(e))),!t||t.length!==2)throw Error(`namespace expected an object or an iterable of [key, value] pairs`);let[n,r]=t;if(!(n instanceof P))throw Error(`namespace keys must be strings`);return[n,r]}var Is=class{constructor(e){this.parent=e}variables=/* @__PURE__ */ new Map([[`namespace`,new L(e=>{let t=e.slice(),n;if(t.at(-1)instanceof Ms&&(n=t.pop()),t.length>1)throw Error(`namespace expected at most 1 argument, got ${t.length}`);let r=/* @__PURE__ */ new Map;if(t.length===1){let e=t[0];if(e instanceof js)for(let[t,n]of e.value)r.set(t,n);else if(e instanceof I)for(let t of e.value){let[e,n]=Fs(t);r.set(e.value,n)}else throw Error(`'${e.type}' object is not iterable`)}if(n)for(let[e,t]of n.value)r.set(e,t);return new Ns(r)})]]);tests=Is.TESTS;set(e,t){return this.declareVariable(e,Js(t))}declareVariable(e,t){if(this.variables.has(e))throw SyntaxError(`Variable already declared: ${e}`);return this.variables.set(e,t),t}setVariable(e,t){return this.variables.set(e,t),t}resolve(e){if(this.variables.has(e))return this;if(this.parent)return this.parent.resolve(e);throw Error(`Unknown variable: ${e}`)}lookupVariable(e){try{return this.resolve(e).variables.get(e)??new z}catch{return new z}}},Ls=Is;ko(Ls,`TESTS`,/* @__PURE__ */ new Map([[`boolean`,e=>e.type===`BooleanValue`],[`callable`,e=>e instanceof L],[`odd`,e=>{if(!(e instanceof M))throw Error(`cannot odd on ${e.type}`);return e.value%2!=0}],[`even`,e=>{if(!(e instanceof M))throw Error(`cannot even on ${e.type}`);return e.value%2==0}],[`false`,e=>e.type===`BooleanValue`&&!e.value],[`true`,e=>e.type===`BooleanValue`&&e.value],[`none`,e=>e.type===`NullValue`],[`string`,e=>e.type===`StringValue`],[`number`,e=>e instanceof M||e instanceof N],[`integer`,e=>e instanceof M],[`iterable`,e=>e.type===`ArrayValue`||e.type===`StringValue`],[`mapping`,e=>e instanceof js],[`sequence`,e=>e instanceof I||e instanceof js||e instanceof P],[`lower`,e=>{let t=e.value;return e.type===`StringValue`&&t===t.toLowerCase()}],[`upper`,e=>{let t=e.value;return e.type===`StringValue`&&t===t.toUpperCase()}],[`none`,e=>e.type===`NullValue`],[`defined`,e=>e.type!==`UndefinedValue`],[`undefined`,e=>e.type===`UndefinedValue`],[`equalto`,(e,t)=>e.value===t.value],[`eq`,(e,t)=>e.value===t.value]]));function Rs(e){e.set(`false`,!1),e.set(`true`,!0),e.set(`none`,null),e.set(`raise_exception`,e=>{throw Error(e)}),e.set(`range`,_s),e.set(`strftime_now`,bs),e.set(`True`,!0),e.set(`False`,!1),e.set(`None`,null)}function zs(e){return e instanceof js||e instanceof Ns}function Bs(e){return e instanceof M||e instanceof N||e instanceof F}function Vs(e){return e instanceof F?Number(e.value):e.value}function Hs(e,t){let n=t.split(`.`),r=e;for(let e of n)if(zs(r))r=r.value.get(e)??new z;else if(r instanceof I){let t=parseInt(e,10);if(!isNaN(t)&&t>=0&&tr)}if(e.type!==t.type)throw Error(`Cannot compare different types: ${e.type} and ${t.type}`);switch(e.type){case`StringValue`:{let r=e.value,i=t.value;return n||(r=r.toLowerCase(),i=i.toLowerCase()),ri)}default:throw Error(`Cannot compare type: ${e.type}`)}}function Ws(e){if(e.type===`Identifier`)return{name:e.value};let t=e;return{name:t.key.value,defaultValue:t.value}}function Gs(e){return e===`kwargs`||e===`varargs`}function Ks(e,t){let n=/* @__PURE__ */ new Set,r=/* @__PURE__ */ new Set,i=e=>{Gs(e)&&n.add(e)},a=e=>{if(e.type===`Identifier`)i(e.value);else if(e.type===`TupleLiteral`)for(let t of e.value)a(t)},o=e=>{i(Ws(e).name)},s=e=>{for(let t of e){let e=Ws(t);e.defaultValue&&l(e.defaultValue)}},c=e=>{e.type===`CallExpression`&&l(e.args)},l=e=>{if(Array.isArray(e)){for(let t of e)l(t);return}if(e instanceof Map){for(let[t,n]of e)l(t),l(n);return}if(e instanceof Ro)switch(e.type){case`For`:{let t=e;if(a(t.loopvar),t.iterable.type===`SelectExpression`){let e=t.iterable;l(e.lhs),l(t.body),l(t.defaultBlock),l(e.test);return}l(t.iterable),l(t.body),l(t.defaultBlock);return}case`Set`:{let t=e;a(t.assignee),l(t.value),l(t.body);return}case`Macro`:{let t=e;for(let e of t.args)o(e);s(t.args),l(t.body);return}case`CallStatement`:{let t=e;l(t.call);for(let e of t.callerArgs??[])o(e);s(t.callerArgs??[]),l(t.body);return}case`FilterStatement`:{let t=e;l(t.body),c(t.filter);return}case`Identifier`:{let t=e.value;Gs(t)&&!n.has(t)&&r.add(t);return}case`MemberExpression`:{let t=e;l(t.object),t.computed&&l(t.property);return}case`FilterExpression`:{let t=e;l(t.operand),c(t.filter);return}case`TestExpression`:l(e.operand);return;case`SelectExpression`:{let t=e;l(t.test),l(t.lhs);return}case`KeywordArgumentExpression`:l(e.value);return;default:for(let t of Object.values(e))l(t)}};for(let t of e)o(t);return l(t),r}var qs=class{global;constructor(e){this.global=e??new Ls}run(e){return this.evaluate(e,this.global)}evaluateBinaryExpression(e,t){let n=this.evaluate(e.left,t);switch(e.operator.value){case`and`:return n.__bool__().value?this.evaluate(e.right,t):n;case`or`:return n.__bool__().value?n:this.evaluate(e.right,t)}let r=this.evaluate(e.right,t);switch(e.operator.value){case`==`:return new F(n.value==r.value);case`!=`:return new F(n.value!=r.value)}if(n instanceof z||r instanceof z){if(r instanceof z&&[`in`,`not in`].includes(e.operator.value))return new F(e.operator.value===`not in`);throw Error(`Cannot perform operation ${e.operator.value} on undefined values`)}if(n instanceof R||r instanceof R)throw Error(`Cannot perform operation on null values`);if(e.operator.value===`~`)return new P(n.value.toString()+r.value.toString());if(e.operator.value===`**`&&Bs(n)&&Bs(r)){let e=Vs(n),t=Vs(r);if(e===0&&t<0)throw Error(`0.0 cannot be raised to a negative power`);let i=e**t;if(!Number.isFinite(i))throw Error(`Exponentiation result is not a finite real number`);return n instanceof N||r instanceof N||t<0?new N(i):new M(i)}if((n instanceof M||n instanceof N)&&(r instanceof M||r instanceof N)){let t=n.value,i=r.value;switch(e.operator.value){case`+`:case`-`:case`*`:{let a=e.operator.value===`+`?t+i:e.operator.value===`-`?t-i:t*i;return n instanceof N||r instanceof N?new N(a):new M(a)}case`/`:return new N(t/i);case`//`:{let e=Math.floor(t/i);return n instanceof N||r instanceof N?new N(e):new M(e)}case`%`:{let e=t%i;return n instanceof N||r instanceof N?new N(e):new M(e)}case`<`:return new F(t`:return new F(t>i);case`>=`:return new F(t>=i);case`<=`:return new F(t<=i)}}else if(n instanceof I&&r instanceof I)switch(e.operator.value){case`+`:return new I(n.value.concat(r.value))}else if(r instanceof I){let t=r.value.find(e=>e.value===n.value)!==void 0;switch(e.operator.value){case`in`:return new F(t);case`not in`:return new F(!t)}}if(n instanceof P||r instanceof P)switch(e.operator.value){case`+`:return new P(n.value.toString()+r.value.toString())}if(n instanceof P&&r instanceof P)switch(e.operator.value){case`in`:return new F(r.value.includes(n.value));case`not in`:return new F(!r.value.includes(n.value))}if(n instanceof P&&r instanceof js)switch(e.operator.value){case`in`:return new F(r.value.has(n.value));case`not in`:return new F(!r.value.has(n.value))}throw SyntaxError(`Unknown operator "${e.operator.value}" between ${n.type} and ${r.type}`)}evaluateArguments(e,t){let n=[],r=/* @__PURE__ */ new Map,i=(e,t)=>{if(r.has(e))throw Error(`Got multiple values for keyword argument '${e}'`);r.set(e,t)};for(let r of e)if(r.type===`SpreadExpression`){let e=r,i=this.evaluate(e.argument,t);if(!(i instanceof I))throw Error(`Cannot unpack non-iterable type: ${i.type}`);for(let e of i.value)n.push(e)}else r.type!==`KeywordArgumentExpression`&&r.type!==`KeywordSpreadExpression`&&n.push(this.evaluate(r,t));for(let n of e)if(n.type===`KeywordArgumentExpression`){let e=n;i(e.key.value,this.evaluate(e.value,t))}else if(n.type===`KeywordSpreadExpression`){let e=n,r=this.evaluate(e.argument,t);if(!(r instanceof js))throw Error(`Argument after ** must be a mapping, not ${r.type}`);for(let[e,t]of r.value)i(e,t)}return[n,r]}applyFilter(e,t,n){if(t.type===`Identifier`){let r=t;if(r.value===`safe`)return e;if(r.value===`tojson`)return new P(As(e,{}));if(e instanceof I)switch(r.value){case`list`:return e;case`first`:return e.value[0];case`last`:return e.value[e.value.length-1];case`length`:return new M(e.value.length);case`reverse`:return new I(e.value.slice().reverse());case`sort`:return new I(e.value.slice().sort((e,t)=>Us(e,t,!1)));case`join`:return new P(e.value.map(e=>e.value).join(``));case`string`:return new P(As(e,{},0,!1));case`unique`:{let t=/* @__PURE__ */ new Set,n=[];for(let r of e.value)t.has(r.value)||(t.add(r.value),n.push(r));return new I(n)}default:throw Error(`Unknown ArrayValue filter: ${r.value}`)}else if(e instanceof P)switch(r.value){case`length`:case`upper`:case`lower`:case`title`:case`capitalize`:{let t=e.builtins.get(r.value);if(t instanceof L)return t.value([],n);if(t instanceof M)return t;throw Error(`Unknown StringValue filter: ${r.value}`)}case`trim`:return new P(e.value.trim());case`indent`:return new P(e.value.split(` +`).map((e,t)=>t===0||e.length===0?e:` `+e).join(` +`));case`join`:case`string`:return e;case`int`:{let t=parseInt(e.value,10);return new M(isNaN(t)?0:t)}case`float`:{let t=parseFloat(e.value);return new N(isNaN(t)?0:t)}default:throw Error(`Unknown StringValue filter: ${r.value}`)}else if(e instanceof M||e instanceof N)switch(r.value){case`abs`:return e instanceof M?new M(Math.abs(e.value)):new N(Math.abs(e.value));case`int`:return new M(Math.floor(e.value));case`float`:return new N(e.value);case`string`:return new P(e.toString());default:throw Error(`Unknown NumericValue filter: ${r.value}`)}else if(e instanceof js)switch(r.value){case`items`:return new I(Array.from(e.value.entries()).map(([e,t])=>new I([new P(e),t])));case`length`:return new M(e.value.size);default:{let t=e.builtins.get(r.value);if(t)return t instanceof L?t.value([],n):t;throw Error(`Unknown ObjectValue filter: ${r.value}`)}}else if(e instanceof F)switch(r.value){case`bool`:return new F(e.value);case`int`:return new M(+!!e.value);case`float`:return new N(+!!e.value);case`string`:return new P(e.value?`true`:`false`);default:throw Error(`Unknown BooleanValue filter: ${r.value}`)}throw Error(`Cannot apply filter "${r.value}" to type: ${e.type}`)}if(t.type===`CallExpression`){let r=t;if(r.callee.type!==`Identifier`)throw Error(`Unknown filter: ${r.callee.type}`);let i=r.callee.value;if(i===`tojson`){let[,t]=this.evaluateArguments(r.args,n),i=t.get(`indent`)??new R;if(!(i instanceof M||i instanceof R))throw Error(`If set, indent must be a number`);let a=t.get(`ensure_ascii`)??new F(!1);if(!(a instanceof F))throw Error(`If set, ensure_ascii must be a boolean`);let o=t.get(`sort_keys`)??new F(!1);if(!(o instanceof F))throw Error(`If set, sort_keys must be a boolean`);let s=t.get(`separators`)??new R,c=null;if(s instanceof I||s instanceof Ps){if(s.value.length!==2)throw Error(`separators must be a tuple of two strings`);let[e,t]=s.value;if(!(e instanceof P)||!(t instanceof P))throw Error(`separators must be a tuple of two strings`);c=[e.value,t.value]}else if(!(s instanceof R))throw Error(`If set, separators must be a tuple of two strings`);return new P(As(e,{indent:i.value,ensureAscii:a.value,sortKeys:o.value,separators:c}))}if(i===`join`){let t;if(e instanceof P)t=Array.from(e.value);else if(e instanceof I)t=e.value.map(e=>e.value);else throw Error(`Cannot apply filter "${i}" to type: ${e.type}`);let[a,o]=this.evaluateArguments(r.args,n),s=a.at(0)??o.get(`separator`)??new P(``);if(!(s instanceof P))throw Error(`separator must be a string`);return new P(t.join(s.value))}if(i===`int`||i===`float`){let[t,a]=this.evaluateArguments(r.args,n),o=t.at(0)??a.get(`default`)??(i===`int`?new M(0):new N(0));if(e instanceof P){let t=i===`int`?parseInt(e.value,10):parseFloat(e.value);return isNaN(t)?o:i===`int`?new M(t):new N(t)}if(e instanceof M||e instanceof N)return e;if(e instanceof F)return i===`int`?new M(+!!e.value):new N(+!!e.value);throw Error(`Cannot apply filter "${i}" to type: ${e.type}`)}if(i==="default"){let[t,i]=this.evaluateArguments(r.args,n),a=t[0]??new P(``),o=t[1]??i.get(`boolean`)??new F(!1);if(!(o instanceof F))throw Error("`default` filter flag must be a boolean");return e instanceof z||o.value&&!e.__bool__().value?a:e}if(e instanceof I){switch(i){case`sort`:{let[t,i]=this.evaluateArguments(r.args,n),a=t.at(0)??i.get(`reverse`)??new F(!1);if(!(a instanceof F))throw Error(`reverse must be a boolean`);let o=t.at(1)??i.get(`case_sensitive`)??new F(!1);if(!(o instanceof F))throw Error(`case_sensitive must be a boolean`);let s=t.at(2)??i.get(`attribute`)??new R;if(!(s instanceof P||s instanceof M||s instanceof R))throw Error(`attribute must be a string, integer, or null`);let c=e=>s instanceof R?e:Hs(e,s instanceof M?String(s.value):s.value);return new I(e.value.slice().sort((e,t)=>{let n=Us(c(e),c(t),o.value);return a.value?-n:n}))}case`selectattr`:case`rejectattr`:{let t=i===`selectattr`;if(e.value.some(e=>!zs(e)))throw Error(`\`${i}\` can only be applied to array of objects`);if(r.args.some(e=>e.type!==`StringLiteral`))throw Error(`arguments of \`${i}\` must be strings`);let[a,o,s]=r.args.map(e=>this.evaluate(e,n)),c;if(o){let e=n.tests.get(o.value);if(!e)throw Error(`Unknown test: ${o.value}`);c=e}else c=(...e)=>e[0].__bool__().value;return new I(e.value.filter(e=>{let n=e.value.get(a.value),r=n?c(n,s):!1;return t?r:!r}))}case`map`:{let[,t]=this.evaluateArguments(r.args,n);if(t.has(`attribute`)){let n=t.get(`attribute`);if(!(n instanceof P))throw Error(`attribute must be a string`);let r=t.get(`default`);return new I(e.value.map(e=>{if(!zs(e))throw Error(`items in map must be an object`);let t=Hs(e,n.value);return t instanceof z?r??new z:t}))}throw Error("`map` expressions without `attribute` set are not currently supported.")}}throw Error(`Unknown ArrayValue filter: ${i}`)}if(e instanceof P){switch(i){case`indent`:{let[t,i]=this.evaluateArguments(r.args,n),a=t.at(0)??i.get(`width`)??new M(4);if(!(a instanceof M))throw Error(`width must be a number`);let o=t.at(1)??i.get(`first`)??new F(!1),s=t.at(2)??i.get(`blank`)??new F(!1),c=e.value.split(` +`),l=` `.repeat(a.value);return new P(c.map((e,t)=>!o.value&&t===0||!s.value&&e.length===0?e:l+e).join(` +`))}case`replace`:{let t=e.builtins.get(`replace`);if(!(t instanceof L))throw Error(`replace filter not available`);let[i,a]=this.evaluateArguments(r.args,n);return t.value([...i,new Ms(a)],n)}}throw Error(`Unknown StringValue filter: ${i}`)}if(e instanceof js){let t=e.builtins.get(i);if(t&&t instanceof L){let[e,i]=this.evaluateArguments(r.args,n);return i.size>0&&e.push(new Ms(i)),t.value(e,n)}throw Error(`Unknown ObjectValue filter: ${i}`)}throw Error(`Cannot apply filter "${i}" to type: ${e.type}`)}throw Error(`Unknown filter: ${t.type}`)}evaluateFilterExpression(e,t){let n=this.evaluate(e.operand,t);return this.applyFilter(n,e.filter,t)}evaluateTestExpression(e,t){let n=this.evaluate(e.operand,t),r=t.tests.get(e.test.value);if(!r)throw Error(`Unknown test: ${e.test.value}`);let i=r(n);return new F(e.negate?!i:i)}evaluateSelectExpression(e,t){return this.evaluate(e.test,t).__bool__().value?this.evaluate(e.lhs,t):new z}evaluateUnaryExpression(e,t){let n=this.evaluate(e.argument,t);switch(e.operator.value){case`not`:return new F(!n.value);case`+`:case`-`:{let t=e.operator.value===`-`?-1:1;if(n instanceof M||n instanceof N||n instanceof F){let e=t*(n instanceof F?+!!n.value:n.value);return n instanceof N?new N(e):new M(e)}throw SyntaxError(`Unknown operator "${e.operator.value}" for ${n.type}`)}default:throw SyntaxError(`Unknown operator: ${e.operator.value}`)}}evaluateTernaryExpression(e,t){return this.evaluate(e.condition,t).__bool__().value?this.evaluate(e.trueExpr,t):this.evaluate(e.falseExpr,t)}evalProgram(e,t){return this.evaluateBlock(e.body,t)}evaluateBlock(e,t){let n=``;for(let r of e){let e=this.evaluate(r,t);e.type!==`NullValue`&&e.type!==`UndefinedValue`&&(n+=e.toString())}return new P(n)}evaluateIdentifier(e,t){return t.lookupVariable(e.value)}evaluateCallExpression(e,t){let[n,r]=this.evaluateArguments(e.args,t);r.size>0&&n.push(new Ms(r));let i=this.evaluate(e.callee,t);if(i.type!==`FunctionValue`)throw Error(`Cannot call something that is not a function: got ${i.type}`);return i.value(n,t)}evaluateSliceExpression(e,t,n){if(!(e instanceof I||e instanceof P))throw Error(`Slice object must be an array or string`);let r=this.evaluate(t.start,n),i=this.evaluate(t.stop,n),a=this.evaluate(t.step,n);if(!(r instanceof M||r instanceof z))throw Error(`Slice start must be numeric or undefined`);if(!(i instanceof M||i instanceof z))throw Error(`Slice stop must be numeric or undefined`);if(!(a instanceof M||a instanceof z))throw Error(`Slice step must be numeric or undefined`);return e instanceof I?new I(vs(e.value,r.value,i.value,a.value)):new P(vs(Array.from(e.value),r.value,i.value,a.value).join(``))}evaluateMemberExpression(e,t){let n=this.evaluate(e.object,t),r;if(e.computed){if(e.property.type===`SliceExpression`)return this.evaluateSliceExpression(n,e.property,t);r=this.evaluate(e.property,t)}else r=e.property.type===`IntegerLiteral`?new M(e.property.value):new P(e.property.value);let i;if(zs(n)){if(!(r instanceof P))throw Error(`Cannot access property with non-string: got ${r.type}`);i=n.value.get(r.value)??(n instanceof js?n.builtins.get(r.value):void 0)}else if(n instanceof I||n instanceof P){if(r instanceof M)i=n.value.at(r.value),n instanceof P&&(i=new P(n.value.at(r.value)));else if(r instanceof P)i=n.builtins.get(r.value);else throw Error(`Cannot access property with non-string/non-number: got ${r.type}`)}else{if(!(r instanceof P))throw Error(`Cannot access property with non-string: got ${r.type}`);i=n.builtins.get(r.value)}return i instanceof Ds?i:new z}evaluateSet(e,t){let n=e.value?this.evaluate(e.value,t):this.evaluateBlock(e.body,t);if(e.assignee.type===`Identifier`){let r=e.assignee.value;t.setVariable(r,n)}else if(e.assignee.type===`TupleLiteral`){let r=e.assignee;if(!(n instanceof I))throw Error(`Cannot unpack non-iterable type in set: ${n.type}`);let i=n.value;if(i.length!==r.value.length)throw Error(`Too ${r.value.length>i.length?`few`:`many`} items to unpack in set`);for(let e=0;et.setVariable(e.loopvar.value,c);else if(e.loopvar.type===`TupleLiteral`){let t=e.loopvar;if(c.type!==`ArrayValue`)throw Error(`Cannot unpack non-iterable type: ${c.type}`);let n=c;if(t.value.length!==n.value.length)throw Error(`Too ${t.value.length>n.value.length?`few`:`many`} items to unpack`);l=e=>{for(let r=0;r0?a[t-1]:new z],[`nextitem`,t0)throw Error(`macro ${e} takes no keyword argument '${o.keys().next().value}'`);if(n.has(`varargs`))i.setVariable(`varargs`,new I(a.slice(t.length)));else if(a.length>t.length)throw Error(`macro ${e} takes not more than ${t.length} argument(s)`);for(let[e,t]of s)i.setVariable(e,this.evaluate(t,i))}evaluateMacro(e,t){let n=Ks(e.args,e.body);return t.setVariable(e.name.value,new L((t,r)=>{let i=new Ls(r);return this.bindMacroArguments(`'${e.name.value}'`,e.args,n,t,i),this.evaluateBlock(e.body,i)})),new R}evaluateCallStatement(e,t){let n=e.callerArgs??[],r=Ks(n,e.body),i=new L(i=>{let a=new Ls(t);return this.bindMacroArguments(`None`,n,r,i,a),this.evaluateBlock(e.body,a)}),[a,o]=this.evaluateArguments(e.call.args,t);a.push(new Ms(o));let s=this.evaluate(e.call.callee,t);if(s.type!==`FunctionValue`)throw Error(`Cannot call something that is not a function: got ${s.type}`);let c=new Ls(t);return c.setVariable(`caller`,i),s.value(a,c)}evaluateFilterStatement(e,t){let n=this.evaluateBlock(e.body,t);return this.applyFilter(n,e.filter,t)}evaluate(e,t){if(!e)return new z;switch(e.type){case`Program`:return this.evalProgram(e,t);case`Set`:return this.evaluateSet(e,t);case`If`:return this.evaluateIf(e,t);case`For`:return this.evaluateFor(e,t);case`Macro`:return this.evaluateMacro(e,t);case`CallStatement`:return this.evaluateCallStatement(e,t);case`Break`:throw new ws;case`Continue`:throw new Ts;case`IntegerLiteral`:return new M(e.value);case`FloatLiteral`:return new N(e.value);case`StringLiteral`:return new P(e.value);case`ArrayLiteral`:return new I(e.value.map(e=>this.evaluate(e,t)));case`TupleLiteral`:return new Ps(e.value.map(e=>this.evaluate(e,t)));case`ObjectLiteral`:{let n=/* @__PURE__ */ new Map;for(let[r,i]of e.value){let e=this.evaluate(r,t);if(!(e instanceof P))throw Error(`Object keys must be strings: got ${e.type}`);n.set(e.value,this.evaluate(i,t))}return new js(n)}case`Identifier`:return this.evaluateIdentifier(e,t);case`CallExpression`:return this.evaluateCallExpression(e,t);case`MemberExpression`:return this.evaluateMemberExpression(e,t);case`UnaryExpression`:return this.evaluateUnaryExpression(e,t);case`BinaryExpression`:return this.evaluateBinaryExpression(e,t);case`FilterExpression`:return this.evaluateFilterExpression(e,t);case`FilterStatement`:return this.evaluateFilterStatement(e,t);case`TestExpression`:return this.evaluateTestExpression(e,t);case`SelectExpression`:return this.evaluateSelectExpression(e,t);case`Ternary`:return this.evaluateTernaryExpression(e,t);case`Comment`:return new R;default:throw SyntaxError(`Unknown node type: ${e.type}`)}}};function Js(e){switch(typeof e){case`number`:return Number.isInteger(e)?new M(e):new N(e);case`string`:return new P(e);case`boolean`:return new F(e);case`undefined`:return new z;case`object`:return e===null?new R:Array.isArray(e)?new I(e.map(Js)):new js(new Map(Object.entries(e).map(([e,t])=>[e,Js(t)])));case`function`:return new L((t,n)=>Js(e(...t.map(e=>e.value))??null));default:throw Error(`Cannot convert to runtime value: ${e}`)}}var Ys=` +`,Xs=`{%- `,Zs=` -%}`,B=Object.freeze({CONDITIONAL:0,LOGICAL_OR:1,LOGICAL_AND:2,LOGICAL_NOT:3,COMPARISON:4,ADDITIVE:5,MULTIPLICATIVE:6,EXPONENTIATION:7,TEST:8,FILTER:9,UNARY_SIGN:10,ATOM:11});function Qs(e){switch(e.operator.type){case`ExponentiationBinaryOperator`:return B.EXPONENTIATION;case`MultiplicativeBinaryOperator`:return B.MULTIPLICATIVE;case`AdditiveBinaryOperator`:return B.ADDITIVE;case`ComparisonBinaryOperator`:return B.COMPARISON;case`Identifier`:return e.operator.value===`and`?B.LOGICAL_AND:e.operator.value===`in`||e.operator.value===`not in`?B.COMPARISON:B.LOGICAL_OR}return B.LOGICAL_OR}function $s(e){switch(e.type){case`SelectExpression`:case`Ternary`:return B.CONDITIONAL;case`BinaryExpression`:return Qs(e);case`UnaryExpression`:return e.operator.value===`not`?B.LOGICAL_NOT:B.UNARY_SIGN;case`TestExpression`:return B.TEST;case`FilterExpression`:return B.FILTER;default:return B.ATOM}}function ec(e,t){let n=V(e);return $s(e)ac(e,t,n)).join(Ys)}function ic(e){return e.map(e=>V(e)).join(`, `)}function ac(e,t,n){let r=n.repeat(t);switch(e.type){case`Program`:return rc(e.body,t,n);case`If`:return oc(e,t,n);case`For`:return sc(e,t,n);case`Set`:return cc(e,t,n);case`Macro`:return lc(e,t,n);case`Break`:return r+nc(`break`);case`Continue`:return r+nc(`continue`);case`CallStatement`:return uc(e,t,n);case`FilterStatement`:return dc(e,t,n);case`Comment`:return r+`{# `+e.value+` #}`;default:return r+`{{- `+V(e)+` -}}`}}function oc(e,t,n){let r=n.repeat(t),i=[],a=e;for(;a&&(i.push({test:a.test,body:a.body}),a.alternate.length===1&&a.alternate[0].type===`If`);)a=a.alternate[0];let o=r+nc(`if`,V(i[0].test))+Ys+rc(i[0].body,t+1,n);for(let e=1;e0&&(o+=Ys+r+nc(`else`)+Ys+rc(a.alternate,t+1,n)),o+=Ys+r+nc(`endif`),o}function sc(e,t,n){let r=n.repeat(t),i=``;if(e.iterable.type===`SelectExpression`){let t=e.iterable;i=`${V(t.lhs)} if ${V(t.test)}`}else i=V(e.iterable);let a=r+nc(`for`,V(e.loopvar),`in`,i)+Ys+rc(e.body,t+1,n);return e.defaultBlock.length>0&&(a+=Ys+r+nc(`else`)+Ys+rc(e.defaultBlock,t+1,n)),a+=Ys+r+nc(`endfor`),a}function cc(e,t,n){let r=n.repeat(t),i=V(e.assignee),a=e.value?V(e.value):``,o=r+nc(`set`,`${i}${e.value?` = `+a:``}`);return e.body.length===0?o:o+Ys+rc(e.body,t+1,n)+Ys+r+nc(`endset`)}function lc(e,t,n){let r=n.repeat(t),i=ic(e.args);return r+nc(`macro`,`${e.name.value}(${i})`)+Ys+rc(e.body,t+1,n)+Ys+r+nc(`endmacro`)}function uc(e,t,n){let r=n.repeat(t),i=e.callerArgs&&e.callerArgs.length>0?`(${ic(e.callerArgs)})`:``,a=V(e.call),o=r+nc(`call${i}`,a)+Ys;return o+=rc(e.body,t+1,n)+Ys,o+=r+nc(`endcall`),o}function dc(e,t,n){let r=n.repeat(t),i=r+nc(`filter`,e.filter.type===`Identifier`?e.filter.value:V(e.filter))+Ys;return i+=rc(e.body,t+1,n)+Ys,i+=r+nc(`endfilter`),i}function V(e){switch(e.type){case`SpreadExpression`:return`*${V(e.argument)}`;case`KeywordSpreadExpression`:return`**${V(e.argument)}`;case`Identifier`:return e.value;case`IntegerLiteral`:return`${e.value}`;case`FloatLiteral`:{let t=e.value;return Object.is(t,-0)?`-0.0`:t%1==0?t.toFixed(1):t.toString()}case`StringLiteral`:return JSON.stringify(e.value);case`BinaryExpression`:{let t=e,n=Qs(t),r=ec(t.left,n),i=ec(t.right,n+1);return`${r} ${t.operator.value} ${i}`}case`UnaryExpression`:{let t=e,n=t.argument.type===`UnaryExpression`?$s(t):B.ATOM;return t.operator.value+(t.operator.value===`not`?` `:``)+ec(t.argument,n)}case`CallExpression`:{let t=e,n=ic(t.args);return`${V(t.callee)}(${n})`}case`MemberExpression`:{let t=e,n=ec(t.object,B.ATOM),r=V(t.property);return!t.computed&&t.property.type!==`Identifier`&&t.property.type!==`IntegerLiteral`&&(r=`(${r})`),t.computed?`${n}[${r}]`:`${n}.${r}`}case`FilterExpression`:{let t=e,n=ec(t.operand,B.FILTER);return t.filter.type===`CallExpression`?`${n} | ${V(t.filter)}`:`${n} | ${t.filter.value}`}case`SelectExpression`:{let t=e;return`${ec(t.lhs,B.LOGICAL_OR)} if ${ec(t.test,B.LOGICAL_OR)}`}case`TestExpression`:{let t=e;return`${ec(t.operand,B.TEST)} is${t.negate?` not`:``} ${t.test.value}`}case`ArrayLiteral`:case`TupleLiteral`:{let t=ic(e.value),n=e.type===`ArrayLiteral`?`[]`:`()`;return`${n[0]}${t}${n[1]}`}case`ObjectLiteral`:return`{${Array.from(e.value.entries()).map(([e,t])=>`${V(e)}: ${V(t)}`).join(`, `)}}`;case`SliceExpression`:{let t=e;return`${t.start?V(t.start):``}:${t.stop?V(t.stop):``}${t.step?`:${V(t.step)}`:``}`}case`KeywordArgumentExpression`:{let t=e;return`${t.key.value}=${V(t.value)}`}case`Ternary`:{let t=e;return`${ec(t.trueExpr,B.LOGICAL_OR)} if ${ec(t.condition,B.LOGICAL_OR)} else ${ec(t.falseExpr,B.CONDITIONAL)}`}default:throw Error(`Unknown expression type: ${e.type}`)}}var fc=class{parsed;constructor(e){let t=Lo(e,{lstrip_blocks:!0,trim_blocks:!0});this.parsed=gs(t)}render(e){let t=new Ls;if(Rs(t),e)for(let[n,r]of Object.entries(e))t.set(n,r);return new qs(t).run(this.parsed).value}format(e){return tc(this.parsed,e?.indent||` `)}},pc={txt:`text/plain`,html:`text/html`,css:`text/css`,js:`text/javascript`,json:`application/json`,png:`image/png`,jpg:`image/jpeg`,jpeg:`image/jpeg`,gif:`image/gif`},mc=class e{constructor(e){if(this.filePath=e,this.headers=new Headers,this.exists=Sr.existsSync(e),this.exists){this.status=200,this.statusText=`OK`;let t=Sr.statSync(e);this.headers.set(`content-length`,t.size.toString()),this.updateContentType();let n=Sr.createReadStream(e);this.body=new ReadableStream({start(e){n.on(`data`,t=>e.enqueue(t)),n.on(`end`,()=>e.close()),n.on(`error`,t=>e.error(t))},cancel(){n.destroy()}})}else this.status=404,this.statusText=`Not Found`,this.body=null}updateContentType(){let e=this.filePath.toString().split(`.`).pop().toLowerCase();this.headers.set(`content-type`,pc[e]??`application/octet-stream`)}clone(){let t=new e(this.filePath);return t.exists=this.exists,t.status=this.status,t.statusText=this.statusText,t.headers=new Headers(this.headers),t}async arrayBuffer(){return(await Sr.promises.readFile(this.filePath)).buffer}async blob(){let e=await Sr.promises.readFile(this.filePath);return new Blob([e],{type:this.headers.get(`content-type`)})}async text(){return await Sr.promises.readFile(this.filePath,`utf8`)}async json(){return JSON.parse(await this.text())}},hc=class{constructor(e){this._mt=/* @__PURE__ */ new Uint32Array(624),this._idx=625,this._gauss_next=null,this._random_fn=this.random.bind(this),this.seed(e)}seed(e){if(e==null){if(O.IS_CRYPTO_AVAILABLE){let t=/* @__PURE__ */ new Uint32Array(1);crypto.getRandomValues(t),e=t[0]}else e=Date.now()>>>0}let t=this._mt,n=(e,t)=>Math.imul(e,t)>>>0,r=[];for(let t=e||0;t>0;t=Math.floor(t/4294967296))r.push(t&4294967295);r.length||r.push(0),t[0]=19650218;for(let e=1;e<624;++e)t[e]=n(1812433253,t[e-1]^t[e-1]>>>30)+e>>>0;let i=1,a=0;for(let e=Math.max(624,r.length);e>0;--e,++i,++a)i>=624&&(t[0]=t[623],i=1),a>=r.length&&(a=0),t[i]=(t[i]^n(t[i-1]^t[i-1]>>>30,1664525))+r[a]+a>>>0;for(let e=623;e>0;--e,++i)i>=624&&(t[0]=t[623],i=1),t[i]=(t[i]^n(t[i-1]^t[i-1]>>>30,1566083941))-i>>>0;t[0]=2147483648,this._idx=624,this._gauss_next=null}_int32(){let e=this._mt;if(this._idx>=624){for(let t=0;t<624;++t){let n=e[t]&2147483648|e[(t+1)%624]&2147483647;e[t]=(e[(t+397)%624]^n>>>1^(n&1?2567483615:0))>>>0}this._idx=0}let t=e[this._idx++];return t^=t>>>11,t^=t<<7&2636928640,t^=t<<15&4022730752,t^=t>>>18,t>>>0}random(){return((this._int32()>>>5)*67108864+(this._int32()>>>6))/9007199254740992}gauss(e=0,t=1){let n=this._gauss_next;if(this._gauss_next=null,n===null){let e=this.random()*2*Math.PI,t=Math.sqrt(-2*Math.log(1-this.random()));n=Math.cos(e)*t,this._gauss_next=Math.sin(e)*t}return e+n*t}shuffle(e){for(let t=e.length-1;t>0;--t){let n=32-Math.clz32(t+1),r=this._int32()>>>32-n;for(;r>t;)r=this._int32()>>>32-n;let i=e[t];e[t]=e[r],e[r]=i}}choices(e,t){return e[gc(this._random_fn,t)]}};function gc(e,t){let n=0;for(let e=0;egc(vc.random,e),bc=new hc,xc=class{constructor(e){this.path=e}async match(e){let t=new mc(Cr.join(this.path,e));if(t.exists)return t}async put(e,t,n=void 0){let r=Cr.join(this.path,e),i=r+`.tmp.${O.IS_PROCESS_AVAILABLE?process.pid:Date.now()}.${bc._int32().toString(36)}`;try{let e=t.headers.get(`Content-Length`),a=parseInt(e??`0`),o=0;await Sr.promises.mkdir(Cr.dirname(r),{recursive:!0});let s=Sr.createWriteStream(i),c=t.body.getReader();for(;;){let{done:e,value:t}=await c.read();if(e)break;await new Promise((e,n)=>{s.write(t,t=>{if(t){n(t);return}e()})}),o+=t.length;let r=a?o/a*100:0;n?.({progress:r,loaded:o,total:a})}await new Promise((e,t)=>{s.close(n=>n?t(n):e())}),await Sr.promises.rename(i,r)}catch(e){try{await Sr.promises.unlink(i)}catch{}throw e}}async delete(e){let t=Cr.join(this.path,e);try{return await Sr.promises.unlink(t),!0}catch{return!1}}},Sc={400:`Bad request error occurred while trying to load file`,401:`Unauthorized access to file`,403:`Forbidden access to file`,404:`Could not locate file`,408:`Request timeout error occurred while trying to load file`,500:`Internal server error error occurred while trying to load file`,502:`Bad gateway error occurred while trying to load file`,503:`Service unavailable error occurred while trying to load file`,504:`Gateway timeout error occurred while trying to load file`},Cc=100,wc=/^(\b[\w\-.]+\b\/)?\b[\w\-.]{1,96}\b$/;function Tc(...e){return e=e.map((t,n)=>(n&&(t=t.replace(/* @__PURE__ */ RegExp(`^/`),``)),n!==e.length-1&&(t=t.replace(/* @__PURE__ */ RegExp(`/$`),``)),t)),e.join(`/`)}function Ec(e,t=null,n=null){let r;try{r=new URL(e)}catch{return!1}return!(t&&!t.includes(r.protocol)||n&&!n.includes(r.hostname))}function Dc(e){return!(!wc.test(e)||e.includes(`..`)||e.includes(`--`)||e.endsWith(`.git`)||e.endsWith(`.ipynb`))}function Oc(e,t={},...n){return JSON.stringify([e,t.revision??`main`,t.cache_dir??null,t.local_files_only??!1,...n])}var kc=class extends Error{constructor(e,{status:t=null}={}){super(e),this.name=`ModelFileNotFoundError`,this.status=t}},Ac=/* @__PURE__ */ new Set([401,403,404]);function jc(e,t,n){if(!n)return null;let r=`${Sc[e]??`Error (${e}) occurred while trying to load file`}: "${t}".`;throw Ac.has(e)?new kc(r,{status:e}):Error(r)}async function Mc(e,t,n){let r=e.headers.get(`Content-Length`),i=r?parseInt(r,10):n??0;r===null&&!n&&A.warn(`Unable to determine content-length from response headers. Will expand buffer when needed.`);let a=new Uint8Array(i),o=0,s=e.body.getReader();async function c(){let{done:e,value:n}=await s.read();if(e)return;let r=o+n.length;if(r>i){i=r;let e=new Uint8Array(i);e.set(a),a=e}return a.set(n,o),o=r,t({progress:o/i*100,loaded:o,total:i}),c()}return await c(),a}function Nc(e){return Ec(e,[`blob:`])}function Pc(e,{allowUnresolved:t=!1}={}){let n;if(typeof location<`u`&&location.href)n=location.href;else if(yr!==void 0&&self.location.href)n=self.location.href;else return e;try{return new URL(e,n).href}catch(n){if(!t)throw n;return e}}var Fc=`SHA-256`,Ic=`experimental_transformers-hash-cache`,Lc=e=>({algorithm:Fc,value:e}),Rc=class{#e=null;_getHashCache=()=>(this.#e??=caches.open(Ic),this.#e);static isAvailable=()=>typeof navigator<`u`&&`crossOriginStorage`in navigator;match=async e=>{let t=await this._getFileHash(e);if(t)try{let e=await(await navigator.crossOriginStorage.requestFileHandle(Lc(t))).getFile();return new Response(e,{headers:{"Content-Length":String(e.size)}})}catch{return}};put=async(e,t)=>{let n=await this._getFileHash(e);if(n){let e=await t.blob();await this._storeBlobInCOS(e,n)}else this._processAndStore(e,t.body)};_storeBlobInCOS=async(e,t)=>{let n=await(await navigator.crossOriginStorage.requestFileHandle(Lc(t),{create:!0,origins:`*`})).createWritable();await n.write(e),await n.close()};_processAndStore=async(e,t)=>{try{let n=[];for await(let e of t)n.push(e);let r=new Blob(n),i=await this._getBlobHash(r);await this._storeBlobInCOS(r,i);try{await(await this._getHashCache()).put(e,new Response(i))}catch{}}catch{}};delete=async e=>{try{return await(await this._getHashCache()).delete(e)}catch{return!1}};_getFileHash=async e=>{try{let t=await this._getHashCache(),n=await t.match(e);if(n)return n.text();let r=await this._getLfsFileHash(e);return r?(await t.put(e,new Response(r)),r):null}catch{return null}};_getLfsFileHash=async e=>{if(!e.includes(`/resolve/`))return null;let t=e.replace(`/resolve/`,`/raw/`);try{let e=(await fetch(t).then(e=>e.text())).match(/^oid sha256:([0-9a-f]+)$/m);return e?e[1]:null}catch{return null}};_getBlobHash=async e=>{let t=await e.arrayBuffer(),n=await crypto.subtle.digest(Fc,t);return Array.from(new Uint8Array(n)).map(e=>e.toString(16).padStart(2,`0`)).join(``)}};async function zc(e=null){let t=null;if(k.useCustomCache){if(!k.customCache)throw Error("`env.useCustomCache=true`, but `env.customCache` is not defined.");if(!k.customCache.match||!k.customCache.put)throw Error("`env.customCache` must be an object which implements the `match` and `put` functions of the Web Cache API. For more information, see https://developer.mozilla.org/en-US/docs/Web/API/Cache");t=k.customCache}if(!t&&k.experimental_useCrossOriginStorage&&Rc.isAvailable()&&(t=new Rc),!t&&k.useBrowserCache){if(typeof caches>`u`)throw Error(`Browser cache is not available in this environment.`);try{t=await caches.open(k.cacheKey)}catch(e){A.warn(`An error occurred while opening the browser cache:`,e)}}if(!t&&k.useFSCache){if(!O.IS_FS_AVAILABLE)throw Error(`File System Cache is not available in this environment.`);t=new xc(e??k.cacheDir)}return t}async function Bc(e,...t){for(let n of t)try{let t=await e.match(n);if(t)return t}catch{continue}}var Vc=new class{#e;#t;constructor(e){this.#e=e,this.#t=/* @__PURE__ */ new Map}get(e){if(!this.#t.has(e))return;let t=this.#t.get(e);return this.#t.delete(e),this.#t.set(e,t),t}put(e,t){this.#t.has(e)&&this.#t.delete(e),this.#t.set(e,t),this.#t.size>this.#e&&this.#t.delete(this.#t.keys().next().value)}delete(e){return this.#t.delete(e)}clear(){this.#t.clear()}}(100);function Hc(e,t){let n=Vc.get(e);if(n!==void 0)return n;let r=t().then(e=>e,t=>(Vc.delete(e),Promise.reject(t)));return Vc.put(e,r),r}async function Uc(e){if(!Ec(e,[`http:`,`https:`]))return null;let t=qc(e);return t.set(`Range`,`bytes=0-0`),k.fetch(e,{method:`GET`,headers:t,cache:`no-store`})}function Wc(e,t,n={}){return Hc(Oc(e,n,t),()=>Gc(e,t,n))}async function Gc(e,t,n){let r=await zc(n?.cache_dir),{localPath:i,remoteURL:a,proposedCacheKey:o,validModelId:s}=Jc(e,t,n,r),c=await Yc(r,i,o);if(c!==void 0&&typeof c!=`string`){let e=c.headers.get(`content-length`),t=c.headers.get(`content-type`);return{exists:!0,size:e?parseInt(e,10):void 0,contentType:t||void 0,fromCache:!0}}if(k.allowLocalModels&&!Ec(i,[`http:`,`https:`]))try{let e=await Kc(i);if(typeof e!=`string`&&e.status!==404){let t=e.headers.get(`content-length`),n=e.headers.get(`content-type`);return{exists:!0,size:t?parseInt(t,10):void 0,contentType:n||void 0,fromCache:!1}}}catch{}if(k.allowRemoteModels&&!n.local_files_only&&s){let e=await Uc(a);if(e&&e.status>=200&&e.status<300){let t,n=e.headers.get(`content-type`);if(e.status===206){let n=e.headers.get(`content-range`);if(n){let e=n.match(/bytes \d+-\d+\/(\d+)/);e&&(t=parseInt(e[1],10))}}else if(e.status===200)try{await e.body?.cancel()}catch{}if(t===void 0){let n=e.headers.get(`content-length`);t=n?parseInt(n,10):void 0}return{exists:!0,size:t,contentType:n||void 0,fromCache:!1}}e&&e.status!==404&&e.status!==416&&jc(e.status,a,!0)}return{exists:!1,fromCache:!1}}async function Kc(e){return k.useFS&&!Ec(e,[`http:`,`https:`,`blob:`])?new mc(e instanceof URL?e.protocol===`file:`?e.pathname:e.toString():e):k.fetch(e,{headers:qc(e)})}function qc(e){let t=typeof process<`u`&&process?.release?.name===`node`,n=new Headers;if(t){let t=!!{}.TESTING_REMOTELY,r=k.version;if(n.set(`User-Agent`,`transformers.js/${r}; is_ci/${t};`),Ec(e,[`http:`,`https:`],[`huggingface.co`,`hf.co`])){let e={}.HF_TOKEN??{}.HF_ACCESS_TOKEN;e&&n.set(`Authorization`,`Bearer ${e}`)}}return n}function Jc(e,t,n={},r=null){let i=n.revision??`main`,a=Tc(e,t),o=Dc(e),s=o?Tc(k.localModelPath,a):a,c=Tc(k.remoteHost,k.remotePathTemplate.replaceAll(`{model}`,e).replaceAll(`{revision}`,encodeURIComponent(i)),t);return{requestURL:a,localPath:s,remoteURL:c,proposedCacheKey:r instanceof xc?i===`main`?a:Tc(e,i,t):c,validModelId:o}}async function Yc(e,t,n){if(e)return await Bc(e,t,n)}async function Xc(e,t,n,r,i,a,o={}){if(await n.match(r)===void 0&&!(typeof Cache<`u`&&n instanceof Cache&&!Ec(Pc(r,{allowUnresolved:!0}),[`http:`,`https:`]))){if(!a){let a=o.progress_callback?n=>$r(o.progress_callback,{status:`progress`,name:e,file:t,...n}):void 0;await n.put(r,i,a)}else if(typeof i!=`string`){let e=new Headers(i.headers);e.set(`content-length`,a.byteLength.toString()),await n.put(r,new Response(a,{headers:e})).catch(e=>{A.warn(`Unable to add response to browser cache: ${e}.`)})}}}async function Zc(e,t,n=!0,r={},i=!1,a=null){let{requestURL:o,localPath:s,remoteURL:c,proposedCacheKey:l,validModelId:u}=Jc(e,t,r,a),d,f=!1,p;p=await Yc(a,s,l);let m=p!==void 0;if(m)d=l;else{if(k.allowLocalModels){if(!Ec(o,[`http:`,`https:`]))try{p=await Kc(s),d=s}catch(e){A.warn(`Unable to load from local path "${s}": "${e}"`)}else if(r.local_files_only)throw Error(`\`local_files_only=true\`, but attempted to load a remote file from: ${o}.`);else if(!k.allowRemoteModels)throw Error(`\`env.allowRemoteModels=false\`, but attempted to load a remote file from: ${o}.`)}if(p===void 0||typeof p!=`string`&&p.status===404){if(r.local_files_only||!k.allowRemoteModels){if(n)throw new kc(`\`local_files_only=true\` or \`env.allowRemoteModels=false\` and file was not found locally at "${s}".`);return null}if(!u)throw new kc(`Local file missing at "${s}" and download aborted due to invalid model ID "${e}".`);if(p=await Kc(c),p.status!==200)return jc(p.status,c,n);d=l}f=a&&typeof Response<`u`&&p instanceof Response&&p.status===200}$r(r.progress_callback,{status:`download`,name:e,file:t});let h;if(!(O.IS_NODE_ENV&&i)){let n;if(typeof p!=`string`){if(!r.progress_callback)n=new Uint8Array(await p.arrayBuffer());else if(m&&typeof navigator<`u`&&/firefox/i.test(navigator.userAgent))n=new Uint8Array(await p.arrayBuffer()),$r(r.progress_callback,{status:`progress`,name:e,file:t,progress:100,loaded:n.length,total:n.length});else{let i,a=p.headers.get(`content-length`);if(a)i=parseInt(a,10);else try{let n=await Wc(e,t,r);n.size&&(i=n.size)}catch{}n=await Mc(p,n=>{$r(r.progress_callback,{status:`progress`,name:e,file:t,...n})},i)}}h=n}if(f&&d&&typeof p!=`string`&&await Xc(e,t,a,d,p,h,r),O.IS_NODE_ENV&&i&&r.progress_callback&&typeof p!=`string`){let n=parseInt(p.headers.get(`content-length`),10)||0;$r(r.progress_callback,{status:`progress`,name:e,file:t,progress:100,loaded:n,total:n})}if($r(r.progress_callback,{status:`done`,name:e,file:t}),h){if(!O.IS_NODE_ENV&&i)throw Error(`Cannot return path in a browser environment.`);return h}if(p instanceof mc)return p.filePath;let g=await a?.match(d);if(g instanceof mc)return g.filePath;if(g instanceof Response)return new Uint8Array(await g.arrayBuffer());if(typeof g==`string`)return g;throw Error(`Unable to get model file path or buffer.`)}var Qc=/* @__PURE__ */ new Map;async function $c(e,t,n=!0,r={},i=!1){if(!k.allowLocalModels){if(r.local_files_only)throw Error("Invalid configuration detected: local models are disabled (`env.allowLocalModels=false`) but you have requested to only use local models (`local_files_only=true`).");if(!k.allowRemoteModels)throw Error("Invalid configuration detected: both local and remote models are disabled. Fix by setting `env.allowLocalModels` or `env.allowRemoteModels` to `true`.")}let a=Oc(e,r,t,n,i),{progress_callback:o}=r,s=o instanceof ei?o.loads:Qc,c=s.get(a);return c||($r(o,{status:`initiate`,name:e,file:t}),c=zc(r.cache_dir).then(a=>Zc(e,t,n,r,i,a)),s===Qc&&(c=c.finally(()=>Qc.delete(a))),s.set(a,c)),await c}async function el(e,t,n=!0,r={}){let i=await $c(e,t,n,r,!1);return i===null?null:new TextDecoder(`utf-8`).decode(i)}async function tl(e,t,n=!0,r={}){let i=await el(e,t,n,r);return i===null?{}:JSON.parse(i)}function nl(e,[t,n,r],[i,a],o=`bilinear`,s=!1){let c=a/r,l=i/n,u=new e.constructor(i*a*t),d=n*r,f=i*a;for(let o=0;o=0;--e)i[e]=a,r[e]=t[n[e]],a*=r[e];let a=n.map((e,t)=>i[n.indexOf(t)]),o=new e.constructor(e.length);for(let n=0;n=0;--e)r+=i%t[e]*a[e],i=Math.floor(i/t[e]);o[r]=e[n]}return[o,r]}function il(e){let t=sl(e)[0],n=e.map(e=>Math.exp(e-t)),r=n.reduce((e,t)=>e+t,0);return n.map(e=>e/r)}function al(e){let t=sl(e)[0],n=0;for(let r=0;re-t-r)}function ol(e){if(e.length===0)throw Error(`Array must not be empty`);let t=e[0],n=0;for(let r=1;rt&&(t=e[r],n=r);return[t,n]}function cl(e){return e>0&&!(e&e-1)}var ll=class{constructor(e){if(this.size=e|0,this.size<=1||!cl(this.size))throw Error(`FFT size must be a power of two larger than 1`);this._csize=e<<1,this.table=new Float64Array(this.size*2);for(let e=0;ee;e<<=1)++t;this._width=t%2==0?t-1:t,this._bitrev=new Int32Array(1<>>t&3)<>>1);for(let t=0;t>>1]=e[t];return n}toComplexArray(e,t){let n=t||this.createComplexArray();for(let t=0;t>>1],n[t+1]=0;return n}transform(e,t){if(e===t)throw Error(`Input and output buffers must be different`);this._transform4(e,t,1)}realTransform(e,t){if(e===t)throw Error(`Input and output buffers must be different`);this._realTransform4(e,t,1)}inverseTransform(e,t){if(e===t)throw Error(`Input and output buffers must be different`);this._transform4(e,t,-1);for(let t=0;t>=2;i>=2;i>>=2){a=r/i<<1;let t=a>>>2;for(o=0;o>>1,i>>>1)}else for(o=0,s=0;o>>1,i>>>1,n)}let l=this.table;for(i>>=2;i>=2;i>>=2){a=r/i<<1;let t=a>>>1,s=t>>>1,c=s>>>1;for(o=0;o>>1;for(let t=2;t>1;++t){let n=(t+1-e)**2/2,r=Math.sqrt(s**2+c**2)**n,o=n*Math.atan2(c,s),l=2*t;i[l]=r*Math.cos(o),i[l+1]=r*Math.sin(o),a[l]=i[l],a[l+1]=-i[l+1]}this._slicedChirpBuffer=i.subarray(t,n),this._f=new ll(r>>1),this._f.transform(this._chirpBuffer,a)}_transform(e,t,n){let r=this._buffer1,i=this._buffer2,a=this._outBuffer1,o=this._outBuffer2,s=this._chirpBuffer,c=this._slicedChirpBuffer,l=this._a;if(n)for(let e=0;e>1];r[e]=i*c[e],r[n]=i*c[n]}else for(let e=0;e=e.length&&(i=2*(e.length-1)-i),r[a++]=e[i]}r.sort(),n[t]=r[i]}return n}function pl(e,t){let n=10**t;return Math.round(e*n)/n}function ml(e){let t=Math.round(e);return Math.abs(e)%1==.5?t%2==0?t:t-1:t}function hl(e){let t=e.length,n=e[0].length,r=[t+1,n+1],i=Array.from({length:r[0]},()=>Array(r[1]).fill(1/0));i[0][0]=0;let a=Array.from({length:r[0]},()=>Array(r[1]).fill(-1));for(let t=1;t0||s>0;)switch(c.push(o-1),l.push(s-1),a[o][s]){case 0:--o,--s;break;case 1:--o;break;case 2:--s;break;default:throw Error(`Internal error in dynamic time warping. Unexpected trace[${o}, ${s}]. Please file a bug report.`)}return c.reverse(),l.reverse(),[c,l]}var gl=/* @__PURE__ */ (function(){let e=null;return function(t){if(!e){e=/* @__PURE__ */ new Float32Array(65536);let t=/* @__PURE__ */ new ArrayBuffer(4),n=new Uint32Array(t),r=new Float32Array(t);for(let t=0;t>10,s=t&1023;if(o===31)i=a|2139095040|s<<13;else if(o===0){if(s===0)i=a;else{let e=113;for(;!(s&1024);)s<<=1,--e;s&=-1025,i=a|e<<23|s<<13}}else i=a|o+112<<23|s<<13;n[0]=i,e[t]=r[0]}}let n=t.length,r=e,i=new Float32Array(n);for(let e=0;e[`webgpu`,`cuda`,`dml`,`webnn-gpu`].includes(e))}if(wl.includes(e))return[xl[e]??e];throw Error(`Unsupported device: "${e}". Should be one of: ${wl.join(`, `)}.`)}var Al=Promise.resolve(),jl=null;async function Ml(){if(jl)return jl;if(!(k.useWasmCache&&typeof Ll?.wasm?.wasmPaths==`object`&&Ll?.wasm?.wasmPaths?.wasm&&Ll?.wasm?.wasmPaths?.mjs)){if(O.IS_DENO_WEB_RUNTIME)throw Error(`env.useWasmCache=false is not supported in Deno's web runtime. Remove the useWasmCache override.`);return jl=Promise.resolve(),jl}return jl=(async()=>{let e=Ll.wasm.wasmPaths,t=!1;await Promise.all([e.wasm&&!Nc(e.wasm)?(async()=>{try{let n=await yl(Pc(e.wasm));n&&(Ll.wasm.wasmBinary=n,t=!0)}catch(e){A.warn(`Failed to pre-load WASM binary:`,e)}})():Promise.resolve(),e.mjs&&!Nc(e.mjs)?(async()=>{try{let t=await bl(Pc(e.mjs));t&&(Ll.wasm.wasmPaths.mjs=t)}catch(e){A.warn(`Failed to pre-load WASM factory:`,e)}})():Promise.resolve()]),t||(Ll.wasm.wasmPaths.mjs=e.mjs)})(),jl}async function Nl(e,t,n){await Ml();let r=Sl(k.logLevel??Yr.WARNING),i=()=>Ol.create(e,{logSeverityLevel:r,...t}),a=await(O.IS_WEB_ENV?Al=Al.then(i):i());return a.config=n,a}var Pl=Promise.resolve();async function Fl(e,t){let n=()=>e.run(t);return O.IS_WEB_ENV?Pl=Pl.then(n):n()}function Il(e){return e instanceof El.Tensor}var Ll=El?.env;function Rl(){return Ll?.wasm?.proxy}if(Ll){let e=function(e){Ll.logLevel=Cl[Sl(e)]};if(Ll.wasm){if(!(typeof ServiceWorkerGlobalScope<`u`&&self instanceof ServiceWorkerGlobalScope)&&Ll.versions?.web&&!Ll.wasm.wasmPaths){let e=`https://cdn.jsdelivr.net/npm/onnxruntime-web@${Ll.versions.web}/dist/`,t=`.asyncify`;O.IS_SAFARI_BELOW_26&&!O.IS_WEBGPU_AVAILABLE&&(t=``),Ll.wasm.wasmPaths={mjs:`${e}ort-wasm-simd-threaded${t}.mjs`,wasm:`${e}ort-wasm-simd-threaded${t}.wasm`}}Ll.wasm.proxy=!1}Ll.webgpu&&(Ll.webgpu.powerPreference=`high-performance`),e(k.logLevel??Yr.WARNING),k.backends.onnx={...Ll,setLogLevel:e}}var zl=async(e,t,n)=>{let r=await Nl(new Uint8Array(e),t);return(async e=>{let t=Rl(),i=Object.fromEntries(Object.entries(e).map(([e,n])=>[e,(t?n.clone():n).ort_tensor])),a=await Fl(r,i);return Array.isArray(n)?n.map(e=>new H(a[e])):new H(a[n])})},Bl=class{static session_options={};static get nearest_interpolate_4d(){return this._nearest_interpolate_4d||=zl([8,10,18,0,58,129,1,10,41,10,1,120,10,0,10,0,10,1,115,18,1,121,34,6,82,101,115,105,122,101,42,18,10,4,109,111,100,101,34,7,110,101,97,114,101,115,116,160,1,3,18,1,114,90,31,10,1,120,18,26,10,24,8,1,18,20,10,3,18,1,98,10,3,18,1,99,10,3,18,1,104,10,3,18,1,119,90,15,10,1,115,18,10,10,8,8,7,18,4,10,2,8,4,98,31,10,1,121,18,26,10,24,8,1,18,20,10,3,18,1,98,10,3,18,1,99,10,3,18,1,104,10,3,18,1,119,66,2,16,21],this.session_options,`y`),this._nearest_interpolate_4d}static get bilinear_interpolate_4d(){return this._bilinear_interpolate_4d||=zl([8,9,18,0,58,128,1,10,40,10,1,120,10,0,10,0,10,1,115,18,1,121,34,6,82,101,115,105,122,101,42,17,10,4,109,111,100,101,34,6,108,105,110,101,97,114,160,1,3,18,1,114,90,31,10,1,120,18,26,10,24,8,1,18,20,10,3,18,1,98,10,3,18,1,99,10,3,18,1,104,10,3,18,1,119,90,15,10,1,115,18,10,10,8,8,7,18,4,10,2,8,4,98,31,10,1,121,18,26,10,24,8,1,18,20,10,3,18,1,98,10,3,18,1,99,10,3,18,1,104,10,3,18,1,119,66,2,16,20],this.session_options,`y`),this._bilinear_interpolate_4d}static get bicubic_interpolate_4d(){return this._bicubic_interpolate_4d||=zl([8,9,18,0,58,127,10,39,10,1,120,10,0,10,0,10,1,115,18,1,121,34,6,82,101,115,105,122,101,42,16,10,4,109,111,100,101,34,5,99,117,98,105,99,160,1,3,18,1,114,90,31,10,1,120,18,26,10,24,8,1,18,20,10,3,18,1,98,10,3,18,1,99,10,3,18,1,104,10,3,18,1,119,90,15,10,1,115,18,10,10,8,8,7,18,4,10,2,8,4,98,31,10,1,121,18,26,10,24,8,1,18,20,10,3,18,1,98,10,3,18,1,99,10,3,18,1,104,10,3,18,1,119,66,2,16,20],this.session_options,`y`),this._bicubic_interpolate_4d}static get matmul(){return this._matmul||=zl([8,9,18,0,58,55,10,17,10,1,97,10,1,98,18,1,99,34,6,77,97,116,77,117,108,18,1,114,90,9,10,1,97,18,4,10,2,8,1,90,9,10,1,98,18,4,10,2,8,1,98,9,10,1,99,18,4,10,2,8,1,66,2,16,20],this.session_options,`c`),this._matmul}static get stft(){return this._stft||=zl([8,7,18,0,58,148,1,10,38,10,1,115,10,1,106,10,1,119,10,1,108,18,1,111,34,4,83,84,70,84,42,15,10,8,111,110,101,115,105,100,101,100,24,1,160,1,2,18,1,115,90,26,10,1,115,18,21,10,19,8,1,18,15,10,3,18,1,98,10,3,18,1,115,10,3,18,1,99,90,11,10,1,106,18,6,10,4,8,7,18,0,90,16,10,1,119,18,11,10,9,8,1,18,5,10,3,18,1,119,90,11,10,1,108,18,6,10,4,8,7,18,0,98,31,10,1,111,18,26,10,24,8,1,18,20,10,3,18,1,98,10,3,18,1,102,10,3,18,1,100,10,3,18,1,99,66,2,16,17],this.session_options,`o`),this._stft}static get rfft(){return this._rfft||=zl([8,9,58,93,10,33,10,1,120,10,0,10,1,97,18,1,121,34,3,68,70,84,42,15,10,8,111,110,101,115,105,100,101,100,24,1,160,1,2,18,1,100,90,19,10,1,120,18,14,10,12,8,1,18,8,10,0,10,0,10,2,8,1,90,11,10,1,97,18,6,10,4,8,7,18,0,98,19,10,1,121,18,14,10,12,8,1,18,8,10,0,10,0,10,2,8,2,66,2,16,20],this.session_options,`y`),this._rfft}static get top_k(){return this._top_k||=zl([8,10,18,0,58,73,10,18,10,1,120,10,1,107,18,1,118,18,1,105,34,4,84,111,112,75,18,1,116,90,9,10,1,120,18,4,10,2,8,1,90,15,10,1,107,18,10,10,8,8,7,18,4,10,2,8,1,98,9,10,1,118,18,4,10,2,8,1,98,9,10,1,105,18,4,10,2,8,7,66,2,16,21],this.session_options,[`v`,`i`]),this._top_k}static get slice(){return this._slice||=zl([8,7,18,0,58,96,10,25,10,1,120,10,1,115,10,1,101,10,1,97,10,1,116,18,1,121,34,5,83,108,105,99,101,18,1,114,90,9,10,1,120,18,4,10,2,8,1,90,9,10,1,115,18,4,10,2,8,7,90,9,10,1,101,18,4,10,2,8,7,90,9,10,1,97,18,4,10,2,8,7,90,9,10,1,116,18,4,10,2,8,7,98,9,10,1,121,18,4,10,2,8,1,66,2,16,13],this.session_options,`y`),this._slice}},Vl=Object.freeze({auto:`auto`,gpu:`gpu`,cpu:`cpu`,wasm:`wasm`,webgpu:`webgpu`,cuda:`cuda`,dml:`dml`,coreml:`coreml`,webnn:`webnn`,"webnn-npu":`webnn-npu`,"webnn-gpu":`webnn-gpu`,"webnn-cpu":`webnn-cpu`}),Hl=O.IS_NODE_ENV?`cpu`:`wasm`;function Ul(e,t,{warn:n}={}){return e?typeof e==`string`?e:e.hasOwnProperty(t)?e[t]:(n&&n(`device not specified for "${t}". Using the default device (${Hl}).`),Hl):Hl}var Wl=/* @__PURE__ */ (function(){let e;return async function(){if(e===void 0){if(!O.IS_WEBGPU_AVAILABLE)e=!1;else try{e=(await navigator.gpu.requestAdapter()).features.has(`shader-f16`)}catch{e=!1}}return e}})(),Gl=Object.freeze({auto:`auto`,fp32:`fp32`,fp16:`fp16`,q8:`q8`,int8:`int8`,uint8:`uint8`,q4:`q4`,bnb4:`bnb4`,q4f16:`q4f16`,q2:`q2`,q2f16:`q2f16`,q1:`q1`,q1f16:`q1f16`}),Kl=Gl.fp32,ql=Object.freeze({[Vl.wasm]:Gl.q8}),Jl=Object.freeze({[Gl.fp32]:``,[Gl.fp16]:`_fp16`,[Gl.int8]:`_int8`,[Gl.uint8]:`_uint8`,[Gl.q8]:`_quantized`,[Gl.q4]:`_q4`,[Gl.q2]:`_q2`,[Gl.q1]:`_q1`,[Gl.q4f16]:`_q4f16`,[Gl.q2f16]:`_q2f16`,[Gl.q1f16]:`_q1f16`,[Gl.bnb4]:`_bnb4`});function Yl(e,t,n,{configDtype:r=null,warn:i}={}){let a,o=!1;e&&typeof e!=`string`?e.hasOwnProperty(t)?a=e[t]:(a=null,o=!0):a=e;let s;if(a===Gl.auto){if(r){let e=typeof r==`string`?r:r?.[t];if(e&&e!==Gl.auto&&Gl.hasOwnProperty(e))return e}s=ql[n]??Kl}else s=a&&Gl.hasOwnProperty(a)?a:ql[n]??Kl;return o&&i&&i(`dtype not specified for "${t}". Using the default dtype (${s}) for this device (${n}).`),s}var Xl=Object.freeze({float32:Float32Array,float16:typeof Float16Array<`u`?Float16Array:Uint16Array,float64:Float64Array,string:Array,int8:Int8Array,uint8:Uint8Array,int16:Int16Array,uint16:Uint16Array,int32:Int32Array,uint32:Uint32Array,int64:BigInt64Array,uint64:BigUint64Array,bool:Uint8Array,uint4:Uint8Array,int4:Int8Array}),H=class e{get dims(){return this.ort_tensor.dims}set dims(e){this.ort_tensor.dims=e}get type(){return this.ort_tensor.type}get data(){return this.ort_tensor.data}get size(){return this.ort_tensor.size}get location(){return this.ort_tensor.location}ort_tensor;constructor(...e){return this.ort_tensor=Il(e[0])?e[0]:new vr(e[0],e[1],e[2]),new Proxy(this,{get:(e,t)=>{if(typeof t==`string`){let n=Number(t);if(Number.isInteger(n))return e._getitem(n)}return e[t]},set:(e,t,n)=>e[t]=n})}dispose(){this.ort_tensor.dispose()}*[Symbol.iterator](){let[e,...t]=this.dims;if(t.length>0){let n=t.reduce((e,t)=>e*t);for(let r=0;r0){let e=r.reduce((e,t)=>e*t);return this._subarray(t,e,r)}return new e(this.type,[this.data[t]],r)}_subarray(t,n,r){let i=t*n,a=(t+1)*n,o=`subarray`in this.data?this.data.subarray(i,a):this.data.slice(i,a);return new e(this.type,o,r)}item(){let e=this.data;if(e.length!==1)throw Error(`a Tensor with ${e.length} elements cannot be converted to Scalar`);return e[0]}tolist(){return Zl(this.data,this.dims)}sigmoid(){return this.clone().sigmoid_()}sigmoid_(){let e=this.data;for(let t=0;t0||r>0&&n<0?r+n:r}return this}clone(){return new e(this.type,this.data.slice(),this.dims.slice())}slice(...t){let n=[],r=[];for(let e=0;ea)throw Error(`Invalid slice: ${i}`);let o=[Math.max(t,0),Math.min(a,this.dims[e])];r.push(o),n.push(o[1]-o[0])}else throw Error(`Invalid slice: ${i}`)}let i=r.map(([e,t])=>t-e),a=i.reduce((e,t)=>e*t),o=this.data,s=new o.constructor(a),c=this.stride(),l=!0;for(let e=1;e=0;--n){let e=i[n];t+=(a%e+r[n][0])*c[n],a=Math.floor(a/e)}s[e]=o[t]}return new e(this.type,s,n)}permute(...e){return Ql(this,e)}transpose(...e){return this.permute(...e)}sum(e=null,t=!1){return this.norm(1,e,t)}norm(t=`fro`,n=null,r=!1){if(t===`fro`)t=2;else if(typeof t==`string`)throw Error(`Unsupported norm: ${t}`);let i=this.data,a=i instanceof BigInt64Array||i instanceof BigUint64Array;if(a&&t!==1)throw Error(`Expected a floating point tensor as input. Got ${this.type}`);let o,s;if(a?(o=(e,t)=>e+t,s=0n):(o=(e,n)=>e+n**t,s=0),n===null){let n=i.reduce(o,s);return t!==1&&(n**=1/t),new e(this.type,[n],[])}let[c,l,u]=uu(o,this,n,r);if(t!==1)for(let e=0;e=0;--r){let e=this.dims[r];if(r!==t){let t=i%e;n+=t*a,a*=this.dims[r]}i=Math.floor(i/e)}r[e]/=i[n]}return this}normalize(e=2,t=1){return this.clone().normalize_(e,t)}stride(){return pu(this.dims)}squeeze(t=null){return new e(this.type,this.data,ou(this.dims,t))}squeeze_(e=null){return this.dims=ou(this.dims,e),this}unsqueeze(t){return new e(this.type,this.data,su(this.dims,t))}unsqueeze_(e){return this.dims=su(this.dims,e),this}flatten_(e=0,t=-1){t=(t+this.dims.length)%this.dims.length;let n=this.dims.slice(0,e),r=this.dims.slice(e,t+1),i=this.dims.slice(t+1);return this.dims=[...n,r.reduce((e,t)=>e*t,1),...i],this}flatten(e=0,t=-1){return this.clone().flatten_(e,t)}view(...t){let n=-1;for(let e=0;er===n?e:e*t,1);t[n]=r.length/e}return new e(this.type,r,t)}neg_(){let e=this.data;for(let t=0;tt);return new e(`bool`,n,this.dims)}lt(t){let n=new Uint8Array(this.data.length),r=this.data;for(let e=0;eMath.min(e,t),this,t,n,1/0);return new e(r,i,a)}max(t=null,n=!1){if(t===null){let t=sl(this.data)[0];return new e(this.type,[t],[])}let[r,i,a]=uu((e,t)=>Math.max(e,t),this,t,n,-1/0);return new e(r,i,a)}argmin(t=null,n=!1){if(t!==null)throw Error("`dim !== null` not yet implemented.");let r=ol(this.data)[1];return new e(`int64`,[BigInt(r)],[])}argmax(t=null,n=!1){if(t!==null)throw Error("`dim !== null` not yet implemented.");let r=sl(this.data)[1];return new e(`int64`,[BigInt(r)],[])}repeat(...t){if(t.lengthe===1)){if(t.length===this.dims.length)return this.clone();let n=t.length-this.dims.length,r=Array(n).fill(1).concat(this.dims);return new e(this.type,this.data.slice(),r)}let n=t.length-this.dims.length,r=Array(n).fill(1).concat(this.dims),i=r.map((e,n)=>e*t[n]),a=i.reduce((e,t)=>e*t,1),o=this.data,s=new o.constructor(a),c=pu(r),l=pu(i);for(let e=0;eBigInt(Math.floor(e)):BigInt;else if(this.type===`float16`&&t==`float32`&&this.data instanceof Uint16Array)return new e(t,gl(this.data),this.dims);return new e(t,Xl[t].from(this.data,n),this.dims)}};function Zl(e,t){let n=e.length;if(n!==(t.length===0?1:t.reduce((e,t)=>e*t)))throw Error(`cannot reshape array of size ${n} into shape (${t})`);let r=e;for(let e=t.length-1;e>=0;e--)r=r.reduce((n,r)=>{let i=n[n.length-1];return i.lengthnew H(`int64`,e,[e.length]);async function iu(e,t,n,r,i){return await(await Bl.slice)({x:e,s:ru(t),e:ru(n),a:ru(r),t:ru(i??Array(r.length).fill(1))})}function au(e,t){let n=e.data,r=t.data,i=[e.dims[0],e.dims[2]],a=new n.constructor(i[0]*i[1]),[o,s,c]=e.dims,l=0;for(let e=0;ee!==1):typeof t==`number`?e[t]===1&&e.splice(t,1):Array.isArray(t)&&(e=e.filter((e,n)=>e!==1||!t.includes(n))),e}function su(e,t){return t=cu(t,e.length+1),e=e.slice(),e.splice(t,0,1),e}function cu(e,t,n=null,r=!0){if(e<-t||e>=t){if(r)throw Error(`IndexError: index ${e} is out of bounds for dimension${n===null?``:` `+n} with size ${t}`);return e<-t?0:t}return e<0&&(e=(e%t+t)%t),e}function U(e,t=0){t=cu(t,e[0].dims.length);let n=e[0].dims.slice();n[t]=e.reduce((e,n)=>e+n.dims[t],0);let r=n.reduce((e,t)=>e*t,1),i=new e[0].data.constructor(r),a=e[0].type;if(t===0){let t=0;for(let n of e){let e=n.data;i.set(e,t),t+=e.length}}else{let r=0;for(let a=0;a=0;--i){let e=s[i],l=o%e;i===t&&(l+=r),a+=l*c,c*=n[i],o=Math.floor(o/e)}i[a]=o[e]}r+=s[t]}}return new H(a,i,n)}function lu(e,t=0){return U(e.map(e=>e.unsqueeze(t)),t)}function uu(e,t,n,r=!1,i=null){let a=t.data,o=t.dims;n=cu(n,o.length);let s=o.slice();s[n]=1;let c=new a.constructor(a.length/o[n]);i!==null&&c.fill(i);for(let t=0;t=0;--e){let t=o[e];if(e!==n){let n=i%t;r+=n*a,a*=s[e]}i=Math.floor(i/t)}c[r]=e(c[r],a[t],t,r)}return r||s.splice(n,1),[t.type,c,s]}function du(e,t=null,n=1,r=!1){let i=e.data,a=e.dims;if(t===null){let t=i.reduce((e,t)=>e+t,0)/i.length,r=Math.sqrt(i.reduce((e,n)=>e+(n-t)**2,0)/(i.length-n)),a=new H(e.type,[t],[]);return[new H(e.type,[r],[]),a]}t=cu(t,a.length);let o=fu(e,t,r),s=o.data,[c,l,u]=uu((e,t,n,r)=>e+(t-s[r])**2,e,t,r);for(let e=0;ee+t,0);return new H(e.type,[t/i.length],[])}t=cu(t,r.length);let[a,o,s]=uu((e,t)=>e+t,e,t,n);if(r[t]!==1)for(let e=0;e=0;--n)t[n]=r,r*=e[n];return t}function mu(e,t,n,r){return new H(n,new r(e.reduce((e,t)=>e*t,1)).fill(t),e)}function hu(e,t){let n,r;if(typeof t==`number`)n=`float32`,r=Float32Array;else if(typeof t==`bigint`)n=`int64`,r=BigInt64Array;else if(typeof t==`boolean`)n=`bool`,r=Uint8Array;else throw Error(`Unsupported data type: ${typeof t}`);return mu(e,t,n,r)}function gu(e,t){return hu(e.dims,t)}function _u(e){return mu(e,1n,`int64`,BigInt64Array)}function vu(e){return _u(e.dims)}function yu(e){return mu(e,0n,`int64`,BigInt64Array)}function bu(e){return yu(e.dims)}function xu(e){let t=e.reduce((e,t)=>e*t,1);return new H(`float32`,Float32Array.from({length:t},()=>vc.gauss()),e)}function Su(e,t){if(e.dims.length!==2)throw Error(`The tensor must have 2 dimensions`);if(e.dims.at(-1)%8!=0)throw Error(`The last dimension of the tensor must be a multiple of 8`);if(![`binary`,`ubinary`].includes(t))throw Error(`The precision must be either 'binary' or 'ubinary'`);let n=t===`binary`,r=n?`int8`:`uint8`,i=n?Int8Array:Uint8Array,a=e.data,o=new i(a.length/8);for(let e=0;e0),r=Math.floor(e/8),i=e%8;o[r]|=t<<7-i,n&&i===0&&(o[r]-=128)}return new H(r,o,[e.dims[0],e.dims[1]/8])}async function Cu(e){if(!e)throw Error(`modelId is required for get_tokenizer_files`);return(await Wc(e,`tokenizer_config.json`,{})).exists?[`tokenizer.json`,`tokenizer_config.json`]:[]}async function wu(e,t){let n=await Cu(e);return await Promise.all(n.map(n=>tl(e,n,!0,t)))}function Tu(e){let t=e.dims;switch(t.length){case 1:return e.tolist();case 2:if(t[0]!==1)throw Error("Unable to decode tensor with `batch size !== 1`. Use `tokenizer.batch_decode(...)` for batched inputs.");return e.tolist()[0];default:throw Error(`Expected tensor to have 1-2 dimensions, got ${t.length}.`)}}var Eu=[`bos_token`,`eos_token`,`unk_token`,`sep_token`,`pad_token`,`cls_token`,`mask_token`];function Du(e,t,n,r){for(let i of Object.keys(e)){let a=t-e[i].length,o=n(i),s=Array(a).fill(o);e[i]=r===`right`?ii(e[i],s):ii(s,e[i])}}function Ou(e,t){for(let n of Object.keys(e))e[n].length=t}function ku(e,...t){for(let n of t){if(!Object.hasOwn(e,n))continue;let t=e[n];if(t){if(typeof t==`object`){if(t.__type===`AddedToken`)return t.content;throw Error(`Unknown token: ${t}`)}return t}}return null}function Au(e){let t=[];for(let n of e.get_added_tokens_decoder().values())n.special&&t.push(n);return t}var W=class extends Qr{return_token_type_ids=!1;padding_side=`right`;constructor(e,t){if(super(),this._tokenizerJSON=e,this._tokenizerConfig=t,this._tokenizer=new Eo(e,t),this.config=t,this.padding_side=t.padding_side??this.padding_side,this.mask_token=ku(t,`mask_token`),this.mask_token_id=this._tokenizer.token_to_id(this.mask_token),this.pad_token=ku(t,`pad_token`,`eos_token`),this.pad_token_id=this._tokenizer.token_to_id(this.pad_token),this.sep_token=ku(t,`sep_token`),this.sep_token_id=this._tokenizer.token_to_id(this.sep_token),this.unk_token=ku(t,`unk_token`),this.unk_token_id=this._tokenizer.token_to_id(this.unk_token),this.bos_token=ku(t,`bos_token`),this.bos_token_id=this._tokenizer.token_to_id(this.bos_token),this.eos_token=ku(t,`eos_token`),this.eos_token_id=this._tokenizer.token_to_id(this.eos_token),this.chat_template=t.chat_template??null,Array.isArray(this.chat_template)){let e=/* @__PURE__ */ Object.create(null);for(let{name:t,template:n}of this.chat_template){if(typeof t!=`string`||typeof n!=`string`)throw Error(`Chat template must be a list of objects with "name" and "template" properties`);e[t]=n}this.chat_template=e}this._compiled_template_cache=/* @__PURE__ */ new Map;let n=Au(this._tokenizer);this.all_special_ids=n.map(e=>e.id),this.all_special_tokens=n.map(e=>e.content)}static async from_pretrained(e,{progress_callback:t=null,config:n=null,cache_dir:r=null,local_files_only:i=!1,revision:a=`main`}={}){let o=await wu(e,{progress_callback:t,config:n,cache_dir:r,local_files_only:i,revision:a});return new this(...o)}get_vocab(){return this._tokenizer.get_vocab()}get model_max_length(){return this._tokenizerConfig.model_max_length??1/0}get add_eos_token(){return this._tokenizerConfig.add_eos_token}get add_bos_token(){return this._tokenizerConfig.add_bos_token}convert_tokens_to_ids(e){return typeof e==`string`?this._tokenizer.token_to_id(e):e.map(e=>this._tokenizer.token_to_id(e))}_call(e,t={}){let{text_pair:n=null,add_special_tokens:r=!0,padding:i=!1,return_token_type_ids:a=null}=t,{truncation:o=null,max_length:s=null}=t,c=t.return_tensor??!0,l=Array.isArray(e),u;if(l){if(e.length===0)throw Error(`text array must be non-empty`);if(n!==null){if(!Array.isArray(n))throw Error(`text_pair must also be an array`);if(e.length!==n.length)throw Error(`text and text_pair must have the same length`);u=e.map((e,t)=>this._encode_plus(e,{text_pair:n[t],add_special_tokens:r,return_token_type_ids:a}))}else u=e.map(e=>this._encode_plus(e,{add_special_tokens:r,return_token_type_ids:a}))}else{if(e==null)throw Error(`text may not be null or undefined`);if(Array.isArray(n))throw Error("When specifying `text_pair`, since `text` is a string, `text_pair` must also be a string (i.e., not an array).");u=[this._encode_plus(e,{text_pair:n,add_special_tokens:r,return_token_type_ids:a})]}if(s===null?s=this.model_max_length:o===null&&(i===!0?(A.warn("`max_length` is ignored when `padding: true` and there is no truncation strategy. To pad to max length, use `padding: 'max_length'`."),s=this.model_max_length):i===!1&&(A.warn("Truncation was not explicitly activated but `max_length` is provided a specific value, please use `truncation: true` to explicitly truncate examples to max length."),o=!0)),i===!0&&(s=Math.min(sl(u.map(e=>e.input_ids.length))[0],s??1/0)),s=Math.min(s,this.model_max_length??1/0),i||o)for(let e=0;es?o&&Ou(u[e],s):i&&Du(u[e],s,e=>e===`input_ids`?this.pad_token_id:0,this.padding_side);let d={};if(c){if(!(i&&o)&&u.some(e=>{for(let t of Object.keys(e))if(e[t].length!==u[0][t]?.length)return!0;return!1}))throw Error(`Unable to create tensor, you should probably activate truncation and/or padding with 'padding=true' and 'truncation=true' to have batched tensors with the same length.`);let e=[u.length,u[0].input_ids.length];for(let t of Object.keys(u[0]))d[t]=new H(`int64`,BigInt64Array.from(u.flatMap(e=>e[t]).map(BigInt)),e)}else{for(let e of Object.keys(u[0]))d[e]=u.map(t=>t[e]);if(!l)for(let e of Object.keys(d))d[e]=d[e][0]}return d}_encode_text(e){return e===null?null:this._tokenizer.encode(e).tokens}_encode_plus(e,{text_pair:t=null,add_special_tokens:n=!0,return_token_type_ids:r=null}={}){let{ids:i,attention_mask:a,token_type_ids:o}=this._tokenizer.encode(e,{text_pair:t,add_special_tokens:n,return_token_type_ids:r??this.return_token_type_ids});return{input_ids:i,attention_mask:a,...o?{token_type_ids:o}:{}}}tokenize(e,{pair:t=null,add_special_tokens:n=!1}={}){return this._tokenizer.tokenize(e,{text_pair:t,add_special_tokens:n})}encode(e,{text_pair:t=null,add_special_tokens:n=!0,return_token_type_ids:r=null}={}){return this._tokenizer.encode(e,{text_pair:t,add_special_tokens:n,return_token_type_ids:r}).ids}batch_decode(e,t={}){return e instanceof H&&(e=e.tolist()),e.map(e=>this.decode(e,t))}decode(e,t={}){if(e instanceof H&&(e=Tu(e)),!Array.isArray(e)||e.length===0||!ti(e[0]))throw Error(`token_ids must be a non-empty array of integers.`);return this.decode_single(e,t)}decode_single(e,{skip_special_tokens:t=!1,clean_up_tokenization_spaces:n=null}){return this._tokenizer.decode(e,{skip_special_tokens:t,clean_up_tokenization_spaces:n})}get_chat_template({chat_template:e=null,tools:t=null}={}){if(this.chat_template&&typeof this.chat_template==`object`){let n=this.chat_template;if(e!==null&&Object.hasOwn(n,e))e=n[e];else if(e===null){if(t!==null&&`tool_use`in n)e=n.tool_use;else if(`default`in n)e=n.default;else throw Error(`This model has multiple chat templates with no default specified! Please either pass a chat template or the name of the template you wish to use to the 'chat_template' argument. Available template names are ${Object.keys(n).sort()}.`)}}else if(e===null){if(this.chat_template)e=this.chat_template;else throw Error(`Cannot use apply_chat_template() because tokenizer.chat_template is not set and no template argument was passed! For information about writing templates and setting the tokenizer.chat_template attribute, please see the documentation at https://huggingface.co/docs/transformers/main/en/chat_templating`)}return e}apply_chat_template(e,t={}){let{tools:n=null,documents:r=null,chat_template:i=null,add_generation_prompt:a=!1,tokenize:o=!0,padding:s=!1,truncation:c=!1,max_length:l=null,return_tensor:u=!0,return_dict:d=!0,tokenizer_kwargs:f={},...p}=t;if(i=this.get_chat_template({chat_template:i,tools:n}),typeof i!=`string`)throw Error(`chat_template must be a string, but got ${typeof i}`);let m=this._compiled_template_cache.get(i);m===void 0&&(m=new fc(i),this._compiled_template_cache.set(i,m));let h=/* @__PURE__ */ Object.create(null);for(let e of Eu){let t=ku(this.config,e);t&&(h[e]=t)}let g=m.render({messages:e,add_generation_prompt:a,tools:n,documents:r,...h,...p});if(o){let e=this._call(g,{add_special_tokens:!1,padding:s,truncation:c,max_length:l,return_tensor:u,...f});return d?e:e.input_ids}return g}};function ju(e,t,n,r){if(!(`language_codes`in e)||!Array.isArray(e.language_codes))throw Error("Tokenizer must have `language_codes` attribute set and it should be an array of language ids.");if(!(`languageRegex`in e)||!(e.languageRegex instanceof RegExp))throw Error("Tokenizer must have `languageRegex` attribute set and it should be a regular expression.");if(!(`lang_to_token`in e)||typeof e.lang_to_token!=`function`)throw Error("Tokenizer must have `lang_to_token` attribute set and it should be a function.");let i=r.src_lang,a=r.tgt_lang;if(!e.language_codes.includes(a))throw Error(`Target language code "${a}" is not valid. Must be one of: {${e.language_codes.join(`, `)}}`);if(i!==void 0){if(!e.language_codes.includes(i))throw Error(`Source language code "${i}" is not valid. Must be one of: {${e.language_codes.join(`, `)}}`);let t=e._tokenizer.post_processor?.config;if(t&&`single`in t){for(let n of t.single)if(`SpecialToken`in n&&e.languageRegex.test(n.SpecialToken.id)){n.SpecialToken.id=e.lang_to_token(i);break}}}return r.forced_bos_token_id=e._tokenizer.token_to_id(e.lang_to_token(a)),e._call(t,n)}var Mu={};xr(Mu,{AlbertTokenizer:()=>Nu,AutoTokenizer:()=>G,BartTokenizer:()=>Pu,BertTokenizer:()=>Fu,BlenderbotSmallTokenizer:()=>Iu,BlenderbotTokenizer:()=>Lu,BloomTokenizer:()=>Ru,CLIPTokenizer:()=>Bu,CamembertTokenizer:()=>zu,CodeGenTokenizer:()=>Hu,CodeLlamaTokenizer:()=>Vu,CohereAsrTokenizer:()=>Wu,CohereTokenizer:()=>Uu,ConvBertTokenizer:()=>Gu,DebertaTokenizer:()=>qu,DebertaV2Tokenizer:()=>Ku,DistilBertTokenizer:()=>Ju,ElectraTokenizer:()=>Yu,EsmTokenizer:()=>Xu,FalconTokenizer:()=>Zu,GPT2Tokenizer:()=>ed,GPTNeoXTokenizer:()=>$u,GemmaTokenizer:()=>Qu,HerbertTokenizer:()=>td,LlamaTokenizer:()=>nd,M2M100Tokenizer:()=>rd,MBart50Tokenizer:()=>od,MBartTokenizer:()=>ad,MPNetTokenizer:()=>ld,MarianTokenizer:()=>id,MgpstrTokenizer:()=>sd,MobileBertTokenizer:()=>cd,NllbTokenizer:()=>ud,NougatTokenizer:()=>dd,PreTrainedTokenizer:()=>W,Qwen2Tokenizer:()=>fd,RoFormerTokenizer:()=>md,RobertaTokenizer:()=>pd,SiglipTokenizer:()=>hd,SpeechT5Tokenizer:()=>gd,SqueezeBertTokenizer:()=>_d,T5Tokenizer:()=>vd,TokenizersBackend:()=>W,VitsTokenizer:()=>bd,Wav2Vec2CTCTokenizer:()=>xd,WhisperTokenizer:()=>Od,XLMRobertaTokenizer:()=>kd,XLMTokenizer:()=>Ad});var Nu=class extends W{return_token_type_ids=!0},Pu=class extends W{},Fu=class extends W{return_token_type_ids=!0},Iu=class extends W{},Lu=class extends W{},Ru=class extends W{},zu=class extends W{},Bu=class extends W{},Vu=class extends W{},Hu=class extends W{},Uu=class extends W{},Wu=class extends W{},Gu=class extends W{return_token_type_ids=!0},Ku=class extends W{return_token_type_ids=!0},qu=class extends W{return_token_type_ids=!0},Ju=class extends W{},Yu=class extends W{return_token_type_ids=!0},Xu=class extends W{},Zu=class extends W{},Qu=class extends W{},$u=class extends W{},ed=class extends W{},td=class extends W{return_token_type_ids=!0},nd=class extends W{padding_side=`left`},rd=class extends W{constructor(e,t){super(e,t),this.languageRegex=/^__[a-z]{2,3}__$/,this.language_codes=this.all_special_tokens.filter(e=>this.languageRegex.test(e)).map(e=>e.slice(2,-2)),this.lang_to_token=e=>`__${e}__`}_build_translation_inputs(e,t,n){return ju(this,e,t,n)}},id=class extends W{constructor(e,t){super(e,t),this.languageRegex=/^(>>\w+<<)\s*/g,this.supported_language_codes=Array.from(this.get_vocab().keys()).filter(e=>this.languageRegex.test(e)),A.warn('WARNING: `MarianTokenizer` is not yet supported by Hugging Face\'s "fast" tokenizers library. Therefore, you may experience slightly inaccurate results.')}_encode_text(e){if(e===null)return null;let[t,...n]=e.trim().split(this.languageRegex);if(n.length===0)return super._encode_text(t);if(n.length===2){let[e,t]=n;return this.supported_language_codes.includes(e)||A.warn(`Unsupported language code "${e}" detected, which may lead to unexpected behavior. Should be one of: ${JSON.stringify(this.supported_language_codes)}`),ii([e],super._encode_text(t))}}},ad=class extends W{constructor(e,t){super(e,t),this.languageRegex=/^[a-z]{2}_[A-Z]{2}$/,this.language_codes=this.all_special_tokens.filter(e=>this.languageRegex.test(e)).map(e=>e),this.lang_to_token=e=>e}_build_translation_inputs(e,t,n){return ju(this,e,t,n)}},od=class extends ad{},sd=class extends W{},cd=class extends W{return_token_type_ids=!0},ld=class extends W{},ud=class extends W{constructor(e,t){super(e,t),this.languageRegex=/^[a-z]{3}_[A-Z][a-z]{3}$/,this.language_codes=this.all_special_tokens.filter(e=>this.languageRegex.test(e)),this.lang_to_token=e=>e}_build_translation_inputs(e,t,n){return ju(this,e,t,n)}},dd=class extends W{},fd=class extends W{},pd=class extends W{},md=class extends W{return_token_type_ids=!0},hd=class extends W{},gd=class extends W{},_d=class extends W{return_token_type_ids=!0},vd=class extends W{},yd=class extends po{decode_chain(e){let t=``;for(let n=1;n[t,e]),[`burmese`,`my`],[`valencian`,`ca`],[`flemish`,`nl`],[`haitian`,`ht`],[`letzeburgesch`,`lb`],[`pushto`,`ps`],[`panjabi`,`pa`],[`moldavian`,`ro`],[`moldovan`,`ro`],[`sinhalese`,`si`],[`castilian`,`es`]]);function Td(e){e=e.toLowerCase();let t=wd.get(e);if(t===void 0){let n=e.match(/^<\|([a-z]{2})\|>$/);if(n&&(e=n[1]),Cd.has(e))t=e;else{let t=e.length===2?Cd.keys():Cd.values();throw Error(`Language "${e}" is not supported. Must be one of: ${JSON.stringify(Array.from(t))}`)}}return t}var Ed=/* @__PURE__ */ RegExp(`^[\\p{P}\\u0021-\\u002F\\u003A-\\u0040\\u005B-\\u0060\\u007B-\\u007E]+$`,`gu`),Dd=.1,Od=class extends W{get timestamp_begin(){return this._tokenizer.token_to_id(`<|notimestamps|>`)+1}_decode_asr(e,{return_timestamps:t=!1,return_language:n=!1,time_precision:r=null,force_full_sequences:i=!0}={}){if(r===null)throw Error(`Must specify time_precision`);let a=null,o=t===`word`;function s(){return{language:a,timestamp:[null,null],text:``}}let c=[],l=s(),u=0,d=this.timestamp_begin,f=d+1500,p=[],m=[],h=!1,g=null,_=new Set(this.all_special_ids);for(let n of e){let e=n.tokens,i=o?n.token_timestamps:null,v=null,y=d;if(`stride`in n){let[t,i,a]=n.stride;if(u-=i,g=t-a,i&&(y=i/r+d),a)for(let t=e.length-1;t>=0;--t){let n=Number(e[t]);if(n>=d){if(v!==null&&(n-d)*r=d&&g<=f){let e=pl((g-d)*r+u,2);if(v!==null&&g>=v)h=!0;else if(h||p.length>0&&g0&&l.timestamp[1]!==null))for(let e of l.words)e.timestamp[1]>l.timestamp[1]&&l.timestamp[1]>=e.timestamp[0]&&(e.timestamp[1]=l.timestamp[1]);c.push(l),p=[],b=[],m=[],x=[],l=s()}}else if(b.push(g),o){let e=pl(i[n]+u,2),t;if(n+10?(p.push(b),o&&m.push(x)):p.every(e=>e.length===0)&&(l=s(),p=[],b=[],m=[],x=[])}if(p.length>0){if(i&&t)throw Error(`Whisper did not predict an ending timestamp, which can happen if audio is cut off in the middle of a word. Also make sure WhisperTimeStampLogitsProcessor was used during generation.`);let[e,n]=this.findLongestCommonSequence(p,m),r=this.decode(e);l.text=r,o&&(l.words=this.collateWordTimestamps(e,n,a)),c.push(l)}let v=/* @__PURE__ */ Object.create(null),y=c.map(e=>e.text).join(``);if(t||n){for(let e=0;e0,o=a?[]:null,s=a?t[0]:null;for(let c=1;ce===g[n]&&s[i+n][0]-Dd<=t[c][m+n][0]).length:p.filter((e,t)=>e===g[t]).length;let v=e/1e4,y=_/e+v;_>1&&y>u&&(u=y,d=[i,o,m,h])}let[p,m,h,g]=d,_=Math.floor((m+p)/2),v=Math.floor((g+h)/2);if(a&&u===0&&r>0){let e=s[r-1][0],n=t[c].findIndex(t=>t[0]>=e);v=n===-1?l.length:n}i.push(...n.slice(0,_)),n=l.slice(v),r=n.length,a&&(o.push(...s.slice(0,_)),s=t[c].slice(v))}return i.push(...n),a?(o.push(...s),[i,o]):[i,[]]}collateWordTimestamps(e,t,n){let[r,i,a]=this.combineTokensIntoWords(e,n),o=[];for(let e=0;e=r){let e=((t-r)*n).toFixed(2);i.push(`<|${e}|>`),i.push([])}else i[i.length-1].push(t);return i=i.map(e=>typeof e==`string`?e:super.decode(e,t)),i.join(``)}splitTokensOnUnicode(e){let t=this.decode(e,{decode_with_timestamps:!0}),n=[],r=[],i=[],a=[],o=[],s=0;for(let c=0;c=this._tokenizer.token_to_id(`<|endoftext|>`),d=s.startsWith(` `),f=s.trim(),p=Ed.test(f);if(u||d||p||i.length===0)i.push(s),a.push(c),o.push(l);else{let e=i.length-1;i[e]+=s,a[e].push(...c),o[e].push(...l)}}return[i,a,o]}mergePunctuations(e,t,n,r,i){let a=structuredClone(e),o=structuredClone(t),s=structuredClone(n),c=a.length-2,l=a.length-1;for(;c>=0;)a[c].startsWith(` `)&&r.includes(a[c].trim())?(a[l]=a[c]+a[l],o[l]=ii(o[c],o[l]),s[l]=ii(s[c],s[l]),a[c]=``,o[c]=[],s[c]=[]):l=c,--c;for(c=0,l=1;le),o.filter(e=>e.length>0),s.filter(e=>e.length>0)]}},kd=class extends W{},Ad=class extends W{return_token_type_ids=!0;constructor(e,t){super(e,t),A.warn('WARNING: `XLMTokenizer` is not yet supported by Hugging Face\'s "fast" tokenizers library. Therefore, you may experience slightly inaccurate results.')}},G=class{static async from_pretrained(e,{progress_callback:t=null,config:n=null,cache_dir:r=null,local_files_only:i=!1,revision:a=`main`}={}){let[o,s]=await wu(e,{progress_callback:t,config:n,cache_dir:r,local_files_only:i,revision:a}),c=s.tokenizer_class?.replace(/Fast$/,``)??`PreTrainedTokenizer`,l=Mu[c];return l||=(A.warn(`Unknown tokenizer class "${c}", attempting to construct from base class.`),W),new l(o,s)}},jd=`https://github.com/huggingface/transformers.js/issues/new/choose`,Md=`preprocessor_config.json`,Nd=`preprocessor_config.json`,Pd=`processor_config.json`,Fd=`chat_template.jinja`,K=class extends Qr{static classes=[`image_processor_class`,`tokenizer_class`,`feature_extractor_class`];static uses_processor_config=!1;static uses_chat_template_file=!1;constructor(e,t,n){super(),this.config=e,this.components=t,this.chat_template=n}get image_processor(){return this.components.image_processor}get tokenizer(){return this.components.tokenizer}get feature_extractor(){return this.components.feature_extractor}apply_chat_template(e,t={}){if(!this.tokenizer)throw Error(`Unable to apply chat template without a tokenizer.`);return this.tokenizer.apply_chat_template(e,{tokenize:!1,chat_template:this.chat_template??void 0,...t})}batch_decode(...e){if(!this.tokenizer)throw Error(`Unable to decode without a tokenizer.`);return this.tokenizer.batch_decode(...e)}decode(...e){if(!this.tokenizer)throw Error(`Unable to decode without a tokenizer.`);return this.tokenizer.decode(...e)}async _call(e,...t){for(let n of[this.image_processor,this.feature_extractor,this.tokenizer])if(n)return n(e,...t);throw Error(`No image processor, feature extractor, or tokenizer found.`)}static async from_pretrained(e,t={}){let[n,r,i]=await Promise.all([this.uses_processor_config?tl(e,Pd,!0,t):{},Promise.all(this.classes.filter(e=>e in this).map(async n=>{let r=await this[n].from_pretrained(e,t);return[n.replace(/_class$/,``),r]})).then(Object.fromEntries),this.uses_chat_template_file?el(e,Fd,!0,t):null]);return new this(n,r,i)}},Id={};xr(Id,{ChatterboxProcessor:()=>jf,CohereAsrProcessor:()=>Nf,Florence2Processor:()=>xm,Gemma3Processor:()=>Sm,Gemma3nProcessor:()=>Cm,Gemma4Processor:()=>wm,Glm46VProcessor:()=>Em,GraniteSpeechProcessor:()=>Dm,GroundingDinoProcessor:()=>km,Idefics3Processor:()=>Nm,JinaCLIPProcessor:()=>Fm,Lfm2VlProcessor:()=>Im,LlavaProcessor:()=>Lm,MgpstrProcessor:()=>zm,MoonshineProcessor:()=>Bm,OwlViTProcessor:()=>Vm,PaliGemmaProcessor:()=>Wm,Phi3VProcessor:()=>qm,PixtralProcessor:()=>Jm,Processor:()=>K,PyAnnoteProcessor:()=>Ym,Qwen2VLProcessor:()=>Tm,Qwen2_5_VLProcessor:()=>Xm,Qwen3VLProcessor:()=>Zm,Sam2Processor:()=>$m,Sam2VideoProcessor:()=>eh,SamProcessor:()=>Qm,SmolVLMProcessor:()=>Nm,SpeechT5Processor:()=>th,UltravoxProcessor:()=>nh,VLChatProcessor:()=>Pm,VoxtralProcessor:()=>sh,VoxtralRealtimeProcessor:()=>ph,Wav2Vec2Processor:()=>mh,Wav2Vec2ProcessorWithLM:()=>hh,WhisperProcessor:()=>gh});var Ld=class extends Qr{constructor(e){super(),this.config=e}static async from_pretrained(e,t={}){let n=await tl(e,Md,!0,t);return new this(n)}};function Rd(e,t){if(!(e instanceof Float32Array||e instanceof Float64Array))throw Error(`${t} expects input to be a Float32Array or a Float64Array, but got ${e?.constructor?.name??typeof e} instead. If using the feature extractor directly, remember to use \`load_audio(url, sampling_rate)\` to obtain the raw audio data of the file/url.`)}var zd={};xr(zd,{ASTFeatureExtractor:()=>uf,ChatterboxFeatureExtractor:()=>ff,ClapFeatureExtractor:()=>pf,CohereAsrFeatureExtractor:()=>gf,DacFeatureExtractor:()=>_f,EncodecFeatureExtractor:()=>df,FeatureExtractor:()=>Ld,Gemma3nAudioFeatureExtractor:()=>vf,Gemma4AudioFeatureExtractor:()=>yf,GraniteSpeechFeatureExtractor:()=>bf,MoonshineFeatureExtractor:()=>xf,ParakeetFeatureExtractor:()=>hf,PyAnnoteFeatureExtractor:()=>Sf,SeamlessM4TFeatureExtractor:()=>Cf,SnacFeatureExtractor:()=>wf,SpeechT5FeatureExtractor:()=>Tf,VoxtralRealtimeFeatureExtractor:()=>Of,Wav2Vec2FeatureExtractor:()=>Ef,WeSpeakerFeatureExtractor:()=>Df,WhisperFeatureExtractor:()=>kf});var Bd={fromWeb:()=>{}};async function Vd(e,t){if(O.IS_BROWSER_ENV){if(O.IS_WEBWORKER_ENV)throw Error(`Unable to save a file from a Web Worker.`);let n=URL.createObjectURL(t),r=document.createElement(`a`);r.href=n,r.download=e,r.click(),r.remove(),URL.revokeObjectURL(n)}else if(O.IS_FS_AVAILABLE){let n=t.stream();Bd.fromWeb(n),Sr.createWriteStream(e),await void 0}else throw Error(`Unable to save because filesystem is disabled in this environment.`)}async function Hd(e,t){if(typeof AudioContext>`u`)throw Error("Unable to load audio from path/URL since `AudioContext` is not available in your environment. Instead, audio data should be passed directly to the pipeline/processor. For more information and some example code, see https://huggingface.co/docs/transformers.js/guides/node-audio-processing.");let n=await(await Kc(e)).arrayBuffer(),r=new AudioContext({sampleRate:t});t===void 0&&A.warn(`No sampling rate provided, using default of ${r.sampleRate}Hz.`);let i=await r.decodeAudioData(n),a;if(i.numberOfChannels===2){let e=Math.sqrt(2),t=i.getChannelData(0),n=i.getChannelData(1);a=new Float32Array(t.length);for(let r=0;r2595*Math.log10(1+e/700),kaldi:e=>1127*Math.log(1+e/700),slaney:(e,t=1e3,n=15,r=27/Math.log(6.4))=>e>=t?n+Math.log(e/t)*r:3*e/200};function Jd(e,t=`htk`){let n=qd[t];if(!n)throw Error(`mel_scale should be one of "htk", "slaney" or "kaldi".`);return typeof e==`number`?n(e):e.map(e=>n(e))}var Yd={htk:e=>700*(10**(e/2595)-1),kaldi:e=>700*(Math.exp(e/1127)-1),slaney:(e,t=1e3,n=15,r=Math.log(6.4)/27)=>e>=n?t*Math.exp(r*(e-n)):200*e/3};function Xd(e,t=`htk`){let n=Yd[t];if(!n)throw Error(`mel_scale should be one of "htk", "slaney" or "kaldi".`);return typeof e==`number`?n(e):e.map(e=>n(e))}function Zd(e,t){let n=Float64Array.from({length:t.length-1},(e,n)=>t[n+1]-t[n]),r=Array.from({length:e.length},()=>Array(t.length));for(let n=0;nArray(e.length));for(let t=0;te+r*n)}function $d(e,t,n,r,i,a=null,o=`htk`,s=!1){if(a!==null&&a!==`slaney`)throw Error(`norm must be one of null or "slaney"`);if(e<2)throw Error(`Require num_frequency_bins: ${e} >= 2`);if(n>r)throw Error(`Require min_frequency: ${n} <= max_frequency: ${r}`);let c=Qd(Jd(n,o),Jd(r,o),t+2),l=Xd(c,o),u;if(s){let t=i/((e-1)*2);u=Jd(Float64Array.from({length:e},(e,n)=>n*t),o),l=c}else u=Qd(0,Math.floor(i/2),e);let d=Zd(u,l);if(a!==null&&a===`slaney`)for(let n=0;ni)throw Error(`frame_length (${n}) may not be larger than fft_length (${i})`);if(te!==n)throw Error(`Length of the window (${te}) must equal frame_length (${n})`);if(r<=0)throw Error(`hop_length must be greater than zero`);if(a===null&&d!==null)throw Error("You have provided `mel_filters` but `power` is `None`. Mel spectrogram computation is not yet supported for complex-valued spectrogram. Specify `power` to fix this issue.");if(!u)throw Error("`preemphasis_htk_flavor=false` is not currently supported.");if(o){let t=Math.floor(n/2);switch(s){case`reflect`:e=ef(e,t,t);break;case`constant`:{let n=new e.constructor(e.length+2*t);n.set(e,t),e=n;break}case`semicausal`:{let n=new e.constructor(e.length+t);n.set(e,t),e=n;break}default:throw Error(`pad_mode="${s}" not implemented yet.`)}}let ne=Math.floor(1+Math.floor((e.length-n)/r));y!==null&&nene?x&&(ae=b):ae=ie=b);let oe=new dl(i),se=new Float64Array(i),ce=new Float64Array(oe.outputBufferSize),le=new Float32Array(re*ae);for(let i=0;i=1;--e)se[e]-=l*se[e-1];se[0]*=1-l}for(let e=0;ee**.85);break;default:throw Error(`Unknown window type ${t}.`)}if(n&&(o=o.subarray(0,e)),r===null||e===r)return o;if(e>r)throw Error(`Length of the window (${e}) may not be larger than frame_length (${r})`);let s=new Float64Array(r),c=i?Math.floor((r-e)/2):0;return s.set(o,c),s}function sf(e,t){let n=e.reduce((e,t)=>e+t.length,0),r=/* @__PURE__ */ new ArrayBuffer(44),i=new DataView(r);return cf(i,0,`RIFF`),i.setUint32(4,36+n*4,!0),cf(i,8,`WAVE`),cf(i,12,`fmt `),i.setUint32(16,16,!0),i.setUint16(20,3,!0),i.setUint16(22,1,!0),i.setUint32(24,t,!0),i.setUint32(28,t*4,!0),i.setUint16(32,4,!0),i.setUint16(34,32,!0),cf(i,36,`data`),i.setUint32(40,n*4,!0),new Blob([r,...e.map(e=>e.buffer instanceof ArrayBuffer?new Uint8Array(e.buffer,e.byteOffset,e.byteLength):e.slice())],{type:`audio/wav`})}function cf(e,t,n){for(let r=0;re+t.length,0),t=new Float32Array(e),n=0;for(let e of this.audio)t.set(e,n),n+=e.length;return t}return this.audio}toBlob(){let e=this.audio;return e instanceof Float32Array&&(e=[e]),sf(e,this.sampling_rate)}async save(e){return Vd(e,this.toBlob())}},uf=class extends Ld{constructor(e){super(e);let t=this.config.sampling_rate,n=$d(257,this.config.num_mel_bins,20,Math.floor(t/2),t,null,`kaldi`,!0);this.mel_filters=n,this.window=of(400,`hann`,{periodic:!1}),this.mean=this.config.mean,this.std=this.config.std}async _extract_fbank_features(e,t){return af(e,this.window,400,160,{fft_length:512,power:2,center:!1,preemphasis:.97,mel_filters:this.mel_filters,log_mel:`log`,mel_floor:1.192092955078125e-7,remove_dc_offset:!0,max_num_frames:t,transpose:!0})}async _call(e){Rd(e,`ASTFeatureExtractor`);let t=await this._extract_fbank_features(e,this.config.max_length);if(this.config.do_normalize){let e=this.std*2,n=t.data;for(let t=0;t0){if(n===`rand_trunc`){let n=Math.floor(vc.random()*(a+1));e=e.subarray(n,n+t),i=await this._extract_fbank_features(e,this.mel_filters_slaney,this.config.nb_max_samples)}else throw Error(`Truncation strategy "${n}" not implemented`)}else{if(a<0){let n=new Float64Array(t);if(n.set(e),r===`repeat`)for(let r=e.length;r=1;--n)e[n]-=t*e[n-1];return await af(e,this.window,this.window.length,this.config.hop_length,{fft_length:this.config.n_fft,power:2,mel_filters:this.config.mel_filters,log_mel:`log`,mel_floor:-1/0,pad_mode:`constant`,center:!0,transpose:!0,mel_offset:2**-24})}async _call(e){Rd(e,`ParakeetFeatureExtractor`);let t=await this._extract_fbank_features(e),n=Math.floor((e.length+Math.floor(this.config.n_fft/2)*2-this.config.n_fft)/this.config.hop_length),r=t.data;r.fill(0,n*t.dims[1]);let[i,a]=t.dims,o=new Float64Array(a),s=new Float64Array(a);for(let e=0;e1?n-1:1;for(let e=0;e=l){s.push(e.slice(c,l));break}let t=Math.max(c,c+a-o),n=Math.min(c+a,l),i;i=n<=t?c+a:this._find_split_point_energy(e,t,n,r),i=Math.max(c+1,Math.min(i,l)),s.push(e.slice(c,i)),c=i}return s}_find_split_point_energy(e,t,n,r){let i=n-t;if(i<=r)return Math.floor((t+n)/2);let a=1/0,o=t,s=i-r;for(let n=0;n<=s;n+=r){let i=0;for(let a=0;at&&(e=e.slice(0,t)),r&&e.length%i!==0){let t=i-e.length%i,n=new Float64Array(e.length+t);n.set(e),this.config.padding_value!==0&&n.fill(this.config.padding_value,e.length),e=n}let a=await this._extract_fbank_features(e,this.config.max_length),o=hu([1,a.dims[0]],!0);return{input_features:a.unsqueeze_(0),input_features_mask:o}}},yf=class extends vf{async _extract_fbank_features(e,t){let{frame_length:n,hop_length:r,fft_length:i}=this.config,a=Math.floor(n/2),o=Math.floor((e.length+a-(n+1))/r)+1;return af(e,this.window,n,r,{fft_length:i,center:!0,pad_mode:`semicausal`,onesided:!0,preemphasis:this.config.preemphasis,preemphasis_htk_flavor:this.config.preemphasis_htk_flavor,mel_filters:this.mel_filters,log_mel:`log`,mel_floor:this.config.mel_floor,mel_floor_mode:`add`,remove_dc_offset:!1,transpose:!0,max_num_frames:o})}async _call(e,t={}){Rd(e,`Gemma4AudioFeatureExtractor`);let n=e.length,r=await super._call(e,t),{input_features:i}=r,[,a,o]=i.dims,{frame_length:s,hop_length:c}=this.config,l=Math.floor(s/2),u=s+1,d=new Uint8Array(n+l+(t.pad_to_multiple_of??128));d.fill(1,l,l+n);let f=new Uint8Array(a);for(let e=0;e({id:e,start:t*n,end:r*n,confidence:i/(r-t)})))}return r}},Cf=class extends Ld{constructor(e){super(e);let t=this.config.sampling_rate,n=$d(257,this.config.num_mel_bins,20,Math.floor(t/2),t,null,`kaldi`,!0);this.mel_filters=n,this.window=of(400,`povey`,{periodic:!1})}async _extract_fbank_features(e,t){return e=e.map(e=>e*32768),af(e,this.window,400,160,{fft_length:512,power:2,center:!1,preemphasis:.97,mel_filters:this.mel_filters,log_mel:`log`,mel_floor:1.192092955078125e-7,remove_dc_offset:!0,max_num_frames:t,transpose:!0})}async _call(e,{padding:t=!0,pad_to_multiple_of:n=2,do_normalize_per_mel_bins:r=!0,return_attention_mask:i=!0}={}){Rd(e,`SeamlessM4TFeatureExtractor`);let a=await this._extract_fbank_features(e,this.config.max_length);if(r){let[e,t]=a.dims,n=a.data;for(let r=0;r0){let n=new Float32Array(t*(e+s));n.set(r),n.fill(this.config.padding_value,r.length);let c=e+s;a=new H(a.type,n,[c,t]),i&&(o=new H(`int64`,new BigInt64Array(c),[1,c]),o.data.fill(1n,0,e))}}let[s,c]=a.dims,l=this.config.stride;if(s%l!==0)throw Error(`The number of frames (${s}) must be a multiple of the stride (${l}).`);let u=a.view(1,Math.floor(s/l),c*l),d={input_features:u};if(i){let e=u.dims[1],t=new BigInt64Array(e);if(o){let e=o.data;for(let n=1,r=0;ne+t,0)/e.length,n=e.reduce((e,n)=>e+(n-t)**2,0)/e.length;return e.map(e=>(e-t)/Math.sqrt(n+1e-7))}async _call(e){Rd(e,`Wav2Vec2FeatureExtractor`),e instanceof Float64Array&&(e=new Float32Array(e));let t=e;this.config.do_normalize&&(t=this._zero_mean_unit_var_norm(t));let n=[1,t.length];return{input_values:new H(`float32`,t,n),attention_mask:new H(`int64`,new BigInt64Array(t.length).fill(1n),n)}}},Df=class extends Ld{constructor(e){super(e);let t=this.config.sampling_rate,n=$d(257,this.config.num_mel_bins,20,Math.floor(t/2),t,null,`kaldi`,!0);this.mel_filters=n,this.window=of(400,`hamming`,{periodic:!1}),this.min_num_frames=this.config.min_num_frames}async _extract_fbank_features(e){return e=e.map(e=>e*32768),af(e,this.window,400,160,{fft_length:512,power:2,center:!1,preemphasis:.97,mel_filters:this.mel_filters,log_mel:`log`,mel_floor:1.192092955078125e-7,remove_dc_offset:!0,transpose:!0,min_num_frames:this.min_num_frames})}async _call(e){Rd(e,`WeSpeakerFeatureExtractor`);let t=(await this._extract_fbank_features(e)).unsqueeze_(0);if(this.config.fbank_centering_span===null){let e=t.mean(1).data,n=t.data,[r,i,a]=t.dims;for(let t=0;tr?(e.length>this.config.n_samples&&A.warn("Attempting to extract features for audio longer than 30 seconds. If using a pipeline to extract transcript from a long audio clip, remember to specify `chunk_length_s` and/or `stride_length_s`."),n=e.slice(0,r)):(n=new Float32Array(r),n.set(e)),{input_features:(await this._extract_fbank_features(n)).unsqueeze_(0)}}},Af=class{static async from_pretrained(e,t={}){let n=await tl(e,Md,!0,t),r=n.feature_extractor_type,i=zd[r];if(!i)throw Error(`Unknown feature_extractor_type: '${r}'. Please report this at ${jd}.`);return new i(n)}},jf=class extends K{static tokenizer_class=G;static feature_extractor_class=Af;async _call(e,t=null){let n=this.tokenizer(e),r=t?await this.feature_extractor(t):{};return{...n,...r}}},Mf=/* @__PURE__ */ new Set([`ja`,`zh`]),Nf=class extends K{static tokenizer_class=G;static feature_extractor_class=Af;static uses_processor_config=!0;get_decoder_prompt_ids(e=`en`){let t=[`▁`,`<|startofcontext|>`,`<|startoftranscript|>`,`<|emo:undefined|>`,`<|${e}|>`,`<|${e}|>`,`<|pnc|>`,`<|noitn|>`,`<|notimestamp|>`,`<|nodiarize|>`];return this.tokenizer.convert_tokens_to_ids(t)}static join_chunks(e,t=`en`){let n=e.filter(e=>e&&e.trim());if(n.length===0)return``;let r=Mf.has(t)?``:` `;return[n[0].trimEnd(),...n.slice(1).map(e=>e.trim())].join(r)}async _call(e){return await this.feature_extractor(e)}},Pf={},Ff,If,Lf;if(O.IS_WEB_ENV)Ff=(e,t)=>{if(!self.OffscreenCanvas)throw Error(`OffscreenCanvas not supported by this environment.`);return new self.OffscreenCanvas(e,t)},Lf=self.createImageBitmap,If=self.ImageData;else if(Pf)Lf=async e=>{let t=(await e.metadata()).channels,{data:n,info:r}=await e.rotate().raw().toBuffer({resolveWithObject:!0}),i=new Bf(new Uint8ClampedArray(n),r.width,r.height,r.channels);return t!==void 0&&t!==r.channels&&i.convert(t),i};else throw Error(`Unable to load image processing library.`);var Rf={0:`nearest`,1:`lanczos`,2:`bilinear`,3:`bicubic`,4:`box`,5:`hamming`},zf=/* @__PURE__ */ new Map([[`png`,`image/png`],[`jpg`,`image/jpeg`],[`jpeg`,`image/jpeg`],[`gif`,`image/gif`]]),Bf=class e{constructor(e,t,n,r){this.data=e,this.width=t,this.height=n,this.channels=r}get size(){return[this.width,this.height]}static async read(t){if(t instanceof e)return t;if(typeof t==`string`||t instanceof URL)return await this.fromURL(t);if(t instanceof Blob)return await this.fromBlob(t);if(typeof HTMLCanvasElement<`u`&&t instanceof HTMLCanvasElement||typeof OffscreenCanvas<`u`&&t instanceof OffscreenCanvas)return this.fromCanvas(t);throw Error(`Unsupported input type: ${typeof t}`)}static fromCanvas(t){if(!O.IS_WEB_ENV)throw Error(`fromCanvas() is only supported in browser environments.`);let n=t.getContext(`2d`).getImageData(0,0,t.width,t.height).data;return new e(n,t.width,t.height,4)}static async fromURL(e){let t=await Kc(e);if(t.status!==200)throw Error(`Unable to read image from "${e}" (${t.status} ${t.statusText})`);let n=await t.blob();return this.fromBlob(n)}static async fromBlob(e){if(O.IS_WEB_ENV){let t=await Lf(e),n=Ff(t.width,t.height).getContext(`2d`);return n.drawImage(t,0,0),new this(n.getImageData(0,0,t.width,t.height).data,t.width,t.height,4)}{let t=Pf(await e.arrayBuffer());return await Lf(t)}}static fromTensor(t,n=`CHW`){if(t.dims.length!==3)throw Error(`Tensor should have 3 dimensions, but has ${t.dims.length} dimensions.`);if(n===`CHW`)t=t.permute(1,2,0);else if(n!==`HWC`)throw Error(`Unsupported channel format: ${n}`);if(!(t.data instanceof Uint8ClampedArray||t.data instanceof Uint8Array))throw Error(`Unsupported tensor type: ${t.type}`);switch(t.dims[2]){case 1:case 2:case 3:case 4:return new e(t.data,t.dims[1],t.dims[0],t.dims[2]);default:throw Error(`Unsupported number of channels: ${t.dims[2]}`)}}grayscale(){if(this.channels===1)return this;let e=new Uint8ClampedArray(this.width*this.height*1);switch(this.channels){case 3:case 4:for(let t=0,n=0;t=0?c=r:u=-r,i>=0?l=i:d=-i,s.drawImage(o,c,l,t,n,u,d,t,n),new e(s.getImageData(0,0,t,n).data,t,n,4).convert(a)}{let e=this.toSharp();if(r>=0&&i>=0)e=e.extract({left:Math.floor(r),top:Math.floor(i),width:t,height:n});else if(r<=0&&i<=0){let a=Math.floor(-i),o=Math.floor(-r);e=e.extend({top:a,left:o,right:t-this.width-o,bottom:n-this.height-a})}else{let a=[0,0],o=0;i<0?(a[0]=Math.floor(-i),a[1]=n-this.height-a[0]):o=Math.floor(i);let s=[0,0],c=0;r<0?(s[0]=Math.floor(-r),s[1]=t-this.width-s[0]):c=Math.floor(r),e=e.extend({top:a[0],bottom:a[1],left:s[0],right:s[1]}).extract({left:c,top:o,width:t,height:n})}return await Lf(e)}}async toBlob(e=`image/png`,t=1){if(!O.IS_WEB_ENV)throw Error(`toBlob() is only supported in browser environments.`);return await this.toCanvas().convertToBlob({type:e,quality:t})}toTensor(e=`CHW`){let t=new H(`uint8`,new Uint8Array(this.data),[this.height,this.width,this.channels]);if(e!==`HWC`){if(e===`CHW`)t=t.permute(2,0,1);else throw Error(`Unsupported channel format: ${e}`)}return t}toCanvas(){if(!O.IS_WEB_ENV)throw Error(`toCanvas() is only supported in browser environments.`);let e=this.clone().rgba(),t=Ff(e.width,e.height),n=new If(e.data,e.width,e.height);return t.getContext(`2d`).putImageData(n,0,0),t}split(){let{data:t,width:n,height:r,channels:i}=this,a=t.constructor,o=t.length/i,s=Array.from({length:i},()=>new a(o));for(let e=0;enew e(t,n,r,1))}_update(e,t,n,r=null){return this.data=e,this.width=t,this.height=n,r!==null&&(this.channels=r),this}clone(){return new e(this.data.slice(),this.width,this.height,this.channels)}convert(e){if(this.channels===e)return this;switch(e){case 1:this.grayscale();break;case 3:this.rgb();break;case 4:this.rgba();break;default:throw Error(`Conversion failed due to unsupported number of channels: ${this.channels}`)}return this}async save(e){if(O.IS_WEB_ENV){if(O.IS_WEBWORKER_ENV)throw Error(`Unable to save an image from a Web Worker.`);let t=e.split(`.`).pop().toLowerCase(),n=zf.get(t)??`image/png`;return Vd(e,await this.toBlob(n))}if(O.IS_FS_AVAILABLE)await this.toSharp().toFile(e);else throw Error(`Unable to save the image because filesystem is disabled in this environment.`)}toSharp(){if(O.IS_WEB_ENV)throw Error(`toSharp() is only supported in server-side environments.`);return Pf(this.data,{raw:{width:this.width,height:this.height,channels:this.channels}})}};Bf.read.bind(Bf);function Vf(e,t,n=0,r=null){let i=e/t,a=ml(i)*t;return r!==null&&a>r&&(a=Math.floor(i)*t),at&&i.push(e)}else{let e=sl(n.data)[1];if(e===c-1||(a=il(n.data),a[e]e*o[(t+1)%2])),u.boxes.push(n),u.classes.push(t),u.scores.push(a[t])}}l.push(u)}return l}function Gf(e,t=null){let n=e.logits,r=n.dims[0];if(t!==null&&t.length!==r)throw Error(`Make sure that you pass in as many target sizes as the batch dimension of the logits`);let i=[];for(let e=0;el[n]&&(l[n]=t[n],u[n]=e)}let d=Array(a.dims[0]);for(let e=0;ee!==void 0);i.push({segmentation:c,labels:f})}return i}function Kf(e,t,n,r){let i=[],a=[],o=[];for(let s=0;sn&&(i.push(l),a.push(d),o.push(u))}return[i,a,o]}function qf(e,t,n,r=.5,i=.8){let a=[],o=0,s=0,c=t[n].data;for(let t=0;t=r&&++s;let l=o>0&&s>0;return l&&=o/s>i,[l,a]}function Jf(e,t,n,r,i,a=null,o=null){let[s,c]=o??e[0].dims,l=new H(`int32`,new Int32Array(s*c),[s,c]),u=[];if(o!==null)for(let t=0;tf[e]&&(d[e]=n,f[e]=i[e])}let p=0,m=l.data;for(let a=0;a200)throw Error(`absolute aspect ratio must be smaller than 200, got ${Math.max(e,t)/Math.min(e,t)}`);let o=Math.round(e/n)*n,s=Math.round(t/n)*n;if(a*o*s>i){let r=Math.sqrt(a*e*t/i);o=Math.max(n,Math.floor(e/r/n)*n),s=Math.max(n,Math.floor(t/r/n)*n)}else if(a*o*si?c=Math.floor(i*s/r):i>r&&(s=Math.floor(r*c/i)),await e.resize(c,s,{resample:n}))}async crop_margin(e,t=200){let n=e.clone().grayscale(),r=ol(n.data)[0],i=sl(n.data)[0]-r;if(i===0)return e;let a=t/255,o=n.width,s=n.height,c=0,l=0,u=n.data;for(let e=0;ethis.preprocess(e)));return{pixel_values:lu(n.map(e=>e.pixel_values),0),original_sizes:n.map(e=>e.original_size),reshaped_input_sizes:n.map(e=>e.reshaped_input_size)}}static async from_pretrained(e,t={}){let n=await tl(e,Nd,!0,t);return new this(n)}},Qf={};xr(Qf,{BeitFeatureExtractor:()=>$f,BitImageProcessor:()=>ep,CHMv2ImageProcessor:()=>np,CLIPFeatureExtractor:()=>ip,CLIPImageProcessor:()=>rp,ChineseCLIPFeatureExtractor:()=>tp,ConvNextFeatureExtractor:()=>op,ConvNextImageProcessor:()=>ap,DINOv3ViTImageProcessor:()=>dp,DPTFeatureExtractor:()=>hp,DPTImageProcessor:()=>mp,DeiTFeatureExtractor:()=>cp,DeiTImageProcessor:()=>sp,DetrFeatureExtractor:()=>up,DetrImageProcessor:()=>lp,DonutFeatureExtractor:()=>pp,DonutImageProcessor:()=>fp,EfficientNetImageProcessor:()=>gp,GLPNFeatureExtractor:()=>Cp,Gemma3ImageProcessor:()=>_p,Gemma4ImageProcessor:()=>bp,Glm46VImageProcessor:()=>Sp,GroundingDinoImageProcessor:()=>wp,Idefics3ImageProcessor:()=>Tp,ImageFeatureExtractor:()=>q,ImageProcessor:()=>q,JinaCLIPImageProcessor:()=>Dp,Lfm2VlImageProcessor:()=>Np,LlavaOnevisionImageProcessor:()=>Pp,Mask2FormerImageProcessor:()=>Lp,MaskFormerFeatureExtractor:()=>Ip,MaskFormerImageProcessor:()=>Fp,MobileNetV1FeatureExtractor:()=>zp,MobileNetV1ImageProcessor:()=>Rp,MobileNetV2FeatureExtractor:()=>Vp,MobileNetV2ImageProcessor:()=>Bp,MobileNetV3FeatureExtractor:()=>Up,MobileNetV3ImageProcessor:()=>Hp,MobileNetV4FeatureExtractor:()=>Gp,MobileNetV4ImageProcessor:()=>Wp,MobileViTFeatureExtractor:()=>qp,MobileViTImageProcessor:()=>Kp,NougatImageProcessor:()=>Jp,OwlViTFeatureExtractor:()=>Xp,OwlViTImageProcessor:()=>Yp,Owlv2ImageProcessor:()=>Zp,Phi3VImageProcessor:()=>rm,PixtralImageProcessor:()=>im,PvtImageProcessor:()=>am,Qwen2VLImageProcessor:()=>xp,RTDetrImageProcessor:()=>om,Sam2ImageProcessor:()=>sm,Sam3ImageProcessor:()=>sm,SamImageProcessor:()=>sm,SapiensFeatureExtractor:()=>lm,SapiensImageProcessor:()=>cm,SegformerFeatureExtractor:()=>dm,SegformerImageProcessor:()=>um,SiglipImageProcessor:()=>fm,SmolVLMImageProcessor:()=>Tp,Swin2SRImageProcessor:()=>pm,VLMImageProcessor:()=>Ep,ViTFeatureExtractor:()=>hm,ViTImageProcessor:()=>mm,VitMatteImageProcessor:()=>gm,VitPoseImageProcessor:()=>_m,YolosFeatureExtractor:()=>ym,YolosImageProcessor:()=>vm});var $f=class extends q{},ep=class extends q{},tp=class extends q{},np=class extends q{},rp=class extends q{},ip=class extends rp{},ap=class extends q{constructor(e){super(e),this.crop_pct=this.config.crop_pct??224/256}async resize(e){let t=this.size?.shortest_edge;if(t===void 0)throw Error(`Size dictionary must contain 'shortest_edge' key.`);if(t<384){let n=Math.floor(t/this.crop_pct),[r,i]=this.get_resize_output_image_size(e,{shortest_edge:n});e=await e.resize(r,i,{resample:this.resample}),e=await e.center_crop(t,t)}else e=await e.resize(t,t,{resample:this.resample});return e}},op=class extends ap{},sp=class extends q{},cp=class extends sp{},lp=class extends q{async _call(e){let t=await super._call(e),n=hu([t.pixel_values.dims[0],64,64],1n);return{...t,pixel_mask:n}}post_process_object_detection(...e){return Wf(...e)}post_process_panoptic_segmentation(...e){return Xf(...e)}post_process_instance_segmentation(...e){return Zf(...e)}},up=class extends lp{},dp=class extends q{},fp=class extends q{pad_image(e,t,n,r={}){let[i,a,o]=t,s=this.image_mean;Array.isArray(this.image_mean)||(s=Array(o).fill(s));let c=this.image_std;Array.isArray(c)||(c=Array(o).fill(s));let l=s.map((e,t)=>-e/c[t]);return super.pad_image(e,t,n,{center:!0,constant_values:l,...r})}},pp=class extends fp{},mp=class extends q{},hp=class extends mp{},gp=class extends q{constructor(e){super(e),this.include_top=this.config.include_top??!0,this.include_top&&(this.image_std=this.image_std.map(e=>e*e))}},_p=class extends q{};function vp(e,t,n,r,i){let a=r*n**2,o=Math.sqrt(a/(e*t)),s=i*n,c=Math.floor(o*e/s)*s,l=Math.floor(o*t/s)*s;if(c===0&&l===0)throw Error(`Attempting to resize to a 0 x 0 image. Resized height should be divisible by \`pooling_kernel_size * patch_size\`=${s}.`);let u=Math.floor(r/i**2)*s;return c===0?(c=s,l=Math.min(Math.floor(t/e)*s,u)):l===0&&(l=s,c=Math.min(Math.floor(e/t)*s,u)),[c,l]}function yp(e,t,n,r,i,a,o){let s=Math.floor(t/i),c=Math.floor(n/i),l=s*c,u=i*i*r,d=new Float32Array(a*u),f=0;for(let t=0;ta),0));let l=a.dims[0]/o,u=a.dims[1],d=Math.floor(a.dims[2]/c),f=Math.floor(a.dims[3]/c);return{pixel_values:a.view(l,o,u,Math.floor(d/s),s,c,Math.floor(f/s),s,c).permute(0,3,6,4,7,2,1,5,8).view(l*d*f,u*o*c*c),image_grid_thw:new H(`int64`,[l,d,f],[1,3]),original_sizes:r,reshaped_input_sizes:i}}},Sp=class extends xp{get_resize_output_image_size(e,t){let n=this.patch_size*this.merge_size,r=this.config.temporal_patch_size??2;return Yf(e.height,e.width,n,this.min_pixels,this.max_pixels,r)}},Cp=class extends q{},wp=class extends q{async _call(e){let t=await super._call(e),n=t.pixel_values.dims,r=_u([n[0],n[2],n[3]]);return{...t,pixel_mask:r}}},Tp=class extends q{constructor(e){super(e),this.do_image_splitting=e.do_image_splitting??!0,this.max_image_size=e.max_image_size}get_resize_for_vision_encoder(e,t){let[n,r]=e.dims.slice(-2),i=r/n;return r>=n?(r=Math.ceil(r/t)*t,n=Math.floor(r/i),n=Math.ceil(n/t)*t):(n=Math.ceil(n/t)*t,r=Math.floor(n*i),r=Math.ceil(r/t)*t),{height:n,width:r}}async _call(e,{do_image_splitting:t=null,return_row_col_info:n=!1}={}){let r;if(!Array.isArray(e))r=[[e]];else{if(e.length===0||!e[0])throw Error(`No images provided.`);r=Array.isArray(e[0])?e:[e]}let i=[],a=[],o=[],s=[],c=[];for(let e of r){let n=await Promise.all(e.map(e=>this.preprocess(e)));s.push(...n.map(e=>e.original_size)),c.push(...n.map(e=>e.reshaped_input_size)),n.forEach(e=>e.pixel_values.unsqueeze_(0));let{longest_edge:r}=this.max_image_size,l;if(t??this.do_image_splitting){let e=Array(n.length),t=Array(n.length);l=await Promise.all(n.map(async(n,i)=>{let a=this.get_resize_for_vision_encoder(n.pixel_values,r),o=await eu(n.pixel_values,{size:[a.height,a.width]}),{frames:s,num_splits_h:c,num_splits_w:l}=await this.split_image(o,this.max_image_size);return e[i]=c,t[i]=l,U(s,0)})),a.push(e),o.push(t)}else{let e=[r,r];l=await Promise.all(n.map(t=>eu(t.pixel_values,{size:e}))),a.push(Array(n.length).fill(0)),o.push(Array(n.length).fill(0))}i.push(U(l,0))}let l=i.length,[u,d,f,p]=i[0].dims,m,h;if(l===1)m=i[0].unsqueeze_(0),h=hu([l,u,f,p],!0);else{let e=Math.max(...i.map(e=>e.dims.at(0)));h=hu([l,e,f,p],!0);let t=h.data,n=e*f*p;for(let r=0;rn||o>r){s=Math.ceil(a/n),c=Math.ceil(o/r);let t=Math.ceil(a/s),l=Math.ceil(o/c);for(let n=0;ne*this.rescale_factor)}pad_image(e,t,n,r){return super.pad_image(e,t,n,{constant_values:this.constant_values,center:!0,...r})}},Dp=class extends q{constructor(e){let{resize_mode:t,fill_color:n,interpolation:r,size:i,...a}=e,o=t===`squash`?{width:i,height:i}:t===`shortest`?{shortest_edge:i}:{longest_edge:i},s=r===`bicubic`?3:2;super({...a,size:o,resample:s,do_center_crop:!0,crop_size:i,do_normalize:!0})}};function Op(e,t){return Math.round(e/t)*t}function kp(e,t,n,r,i){let a=1/0,o=[1,1],s=n*r;for(let n of t){let t=Math.abs(e-n[0]/n[1]);t.5*i*i*n[0]*n[1]&&(o=n)}return o}function Ap(e,t){let n=[],r=/* @__PURE__ */ new Set;for(let i=e;i<=t;++i)for(let a=1;a<=i;++a)for(let o=1;o<=i;++o){let i=a*o;if(i>=e&&i<=t){let e=a<<16|o;r.has(e)||(r.add(e),n.push([a,o]))}}return n.sort((e,t)=>e[0]*e[1]-t[0]*t[1])}function jp(e,t){let[n,r,i,a]=e.dims,o=Math.floor(i/t),s=Math.floor(a/t),c=t*t*r,l=e.data,u=new Float32Array(n*o*s*c),d=i*a;for(let e=0;ethis.max_image_tokens*(this.encoder_patch_size*this.downsample_factor)**2*this.max_pixels_tolerance}_get_grid_layout(e,t){let n=Ap(this.min_tiles,this.max_tiles),[r,i]=kp(t/e,n,t,e,this.tile_size);return{grid_width:r,grid_height:i,target_width:this.tile_size*r,target_height:this.tile_size*i}}async _call(e,{return_row_col_info:t=null}={}){let n;n=Array.isArray(e)?Array.isArray(e[0])?e:[e]:[[e]];let r=[],i=[],a=[],o=[],s=[],c=[];for(let e of n){let t=await Promise.all(e.map(e=>this.preprocess(e,{do_pad:!1})));for(let{pixel_values:e}of t){let[,t,n]=e.dims,l=e.unsqueeze_(0),u=this.encoder_patch_size*this.downsample_factor,d=u**2,[f,p]=Yf(Math.max(u,t),Math.max(u,n),u,this.min_image_tokens*d,this.max_image_tokens*d).map(e=>Math.max(u,e)),m,h=1,g=1,_=this._is_image_too_large(t,n),v=this.do_image_splitting&&(this.min_tiles!==1||this.max_tiles!==1);if(_&&v){let{grid_width:e,grid_height:r,target_width:i,target_height:a}=this._get_grid_layout(t,n);h=r,g=e;let o=await eu(l,{size:[a,i]});m=[];for(let t=0;t(e-this.image_mean[t])/this.image_std[t]);return super.pad_image(e,t,{width:s,height:o},{center:!0,constant_values:c,...r})}async _call(e,{num_crops:t=null}={}){if(this._num_crops=t??=this.config.num_crops,t<4||nm(t)%1!=0)throw Error(`num_crops must be a square number >= 4`);Array.isArray(e)||(e=[e]);let n=e.length,r=await Promise.all(e.map(e=>this.preprocess(e))),i=r.map(e=>e.original_size),a=r.map(e=>e.reshaped_input_size),o=[];for(let{pixel_values:e}of r){e.unsqueeze_(0);let[n,r]=e.dims.slice(-2),i=await eu(e,{size:[Qp,Qp],mode:`bicubic`});if(t>0){let a=[],s=nm(t),c=tm(r/s),l=tm(n/s);for(let t=0;te.map(e=>Qp*em(e/Qp)));return{pixel_values:s,original_sizes:i,reshaped_input_sizes:a,image_sizes:new H(`int64`,c.flat(),[n,2]),num_img_tokens:c.map(([e,t])=>this.calc_num_image_tokens_from_image_size(t,e))}}},im=class extends q{get_resize_output_image_size(e,t){let{longest_edge:n}=t;if(n===void 0)throw Error(`size must contain 'longest_edge'`);let[r,i]=e.size,a=Math.max(r,i)/n,o=r,s=i;a>1&&(o=Math.floor(r/a),s=Math.floor(i/a));let{patch_size:c,spatial_merge_size:l}=this.config;if(!l)throw Error(`config must contain 'spatial_merge_size'`);let u=c*l,d=Math.floor((o-1)/u)+1,f=Math.floor((s-1)/u)+1;return[d*u,f*u]}},am=class extends q{},om=class extends q{post_process_object_detection(...e){return Wf(...e)}},sm=class extends q{reshape_input_points(e,t,n,r=!1){e=structuredClone(e);let i=ri(e);if(i.length===3)r||(i=[1,...i]),e=[e];else if(i.length!==4)throw Error("The input_points must be a 4D tensor of shape `batch_size`, `point_batch_size`, `nb_points_per_image`, `2`.");for(let r=0;re!==t.dims[n]))throw Error(`The first ${n.length} dimensions of 'input_points' and 'input_labels' must be the same.`);return new H(`int64`,e.flat(1/0).map(BigInt),n)}async _call(e,{input_points:t=null,input_labels:n=null,input_boxes:r=null}={}){let i=await super._call(e);if(t&&(i.input_points=this.reshape_input_points(t,i.original_sizes,i.reshaped_input_sizes)),n){if(!i.input_points)throw Error("`input_points` must be provided if `input_labels` are provided.");i.input_labels=this.add_input_labels(n,i.input_points)}return r&&(i.input_boxes=this.reshape_input_points(r,i.original_sizes,i.reshaped_input_sizes,!0)),i}async post_process_masks(e,t,n,{mask_threshold:r=0,binarize:i=!0,pad_size:a=null}={}){let o=[];a=a??this.pad_size??this.size;let s=[a.height,a.width];for(let a=0;ar&&(t[n]=1);u=new H(`bool`,t,u.dims)}o.push(u)}return o}generate_crop_boxes(e,t,{crop_n_layers:n=0,overlap_ratio:r=512/1500,points_per_crop:i=32,crop_n_points_downscale_factor:a=1}={}){}},cm=class extends q{post_process_semantic_segmentation(...e){return Gf(...e)}},lm=class extends cm{},um=class extends q{post_process_semantic_segmentation(...e){return Gf(...e)}},dm=class extends um{},fm=class extends q{},pm=class extends q{pad_image(e,t,n,r={}){let[i,a,o]=t;return super.pad_image(e,t,{width:a+(n-a%n)%n,height:i+(n-i%n)%n},{mode:`symmetric`,center:!1,constant_values:-1,...r})}},mm=class extends q{},hm=class extends mm{},gm=class extends q{async _call(e,t){Array.isArray(e)||(e=[e]),Array.isArray(t)||(t=[t]);let n=await Promise.all(e.map(e=>this.preprocess(e))),r=await Promise.all(t.map(e=>this.preprocess(e,{do_normalize:!1,do_convert_rgb:!1,do_convert_grayscale:!0})));return{pixel_values:lu(n.map((e,t)=>U([e.pixel_values,r[t].pixel_values],0)),0),original_sizes:n.map(e=>e.original_size),reshaped_input_sizes:n.map(e=>e.reshaped_input_size)}}},_m=class extends q{post_process_pose_estimation(e,t,{threshold:n=null}={}){let r=e.tolist(),[i,a,o,s]=e.dims,c=[];for(let e=0;e/gm,bboxes:/([^<]+)?/gm},this.size_per_bin=1e3}construct_prompts(e){typeof e==`string`&&(e=[e]);let t=[];for(let n of e)if(this.task_prompts_without_inputs.has(n))t.push(this.task_prompts_without_inputs.get(n));else{for(let[e,r]of this.task_prompts_with_input)if(n.includes(e)){t.push(r.replaceAll(`{input}`,n).replaceAll(e,``));break}t.length!==e.length&&t.push(n)}return t}post_process_generation(e,t,n){let r=this.tasks_answer_post_processing_type.get(t)??`pure_text`;e=e.replaceAll(``,``).replaceAll(``,``);let i;switch(r){case`pure_text`:i=e;break;case`description_with_bboxes`:case`bboxes`:case`phrase_grounding`:case`ocr`:let a=r===`ocr`?`quad_boxes`:`bboxes`,o=e.matchAll(this.regexes[a]),s=[],c=[];for(let[e,t,...r]of o)s.push(t?t.trim():s.at(-1)??``),c.push(r.map((e,t)=>(Number(e)+.5)/this.size_per_bin*n[t%2]));i={labels:s,[a]:c};break;default:throw Error(`Task "${t}" (of type "${r}") not yet implemented.`)}return{[t]:i}}async _call(e,t=null,n={}){if(!e&&!t)throw Error(`Either text or images must be provided`);let r=await this.image_processor(e,n),i=t?this.tokenizer(this.construct_prompts(t),n):{};return{...r,...i}}},Sm=class extends K{static tokenizer_class=G;static image_processor_class=bm;static uses_processor_config=!0;static uses_chat_template_file=!0;constructor(e,t,n){super(e,t,n),this.image_seq_length=this.config.image_seq_length;let{boi_token:r,image_token:i,eoi_token:a}=this.tokenizer.config;this.boi_token=r,this.image_token=i,this.eoi_token=a;let o=i.repeat(this.image_seq_length);this.full_image_sequence=` + +${r}${o}${a} + +`}async _call(e,t=null,n={}){typeof e==`string`&&(e=[e]);let r;return t&&(r=await this.image_processor(t,n),e=e.map(e=>e.replaceAll(this.boi_token,this.full_image_sequence))),{...this.tokenizer(e,n),...r}}},Cm=class extends K{static image_processor_class=bm;static feature_extractor_class=Af;static tokenizer_class=G;static uses_processor_config=!0;static uses_chat_template_file=!0;constructor(e,t,n){super(e,t,n),this.audio_seq_length=this.config.audio_seq_length,this.image_seq_length=this.config.image_seq_length;let{audio_token_id:r,boa_token:i,audio_token:a,eoa_token:o,image_token_id:s,boi_token:c,image_token:l,eoi_token:u}=this.tokenizer.config;this.audio_token_id=r,this.boa_token=i,this.audio_token=a;let d=a.repeat(this.audio_seq_length);this.full_audio_sequence=` + +${i}${d}${o} + +`,this.image_token_id=s,this.boi_token=c,this.image_token=l;let f=l.repeat(this.image_seq_length);this.full_image_sequence=` + +${c}${f}${u} + +`}async _call(e,t=null,n=null,r={}){typeof e==`string`&&(e=[e]);let i;n&&(i=await this.feature_extractor(n,r),e=e.map(e=>e.replaceAll(this.audio_token,this.full_audio_sequence)));let a;return t&&(a=await this.image_processor(t,r),e=e.map(e=>e.replaceAll(this.image_token,this.full_image_sequence))),{...this.tokenizer(e,r),...a,...i}}},wm=class extends K{static uses_processor_config=!0;static uses_chat_template_file=!0;constructor(e,t,n){super(e,t,n),this.audio_ms_per_token=this.config.audio_ms_per_token??40,this.audio_seq_length=this.config.audio_seq_length??750,this.image_seq_length=this.config.image_seq_length??280;let{audio_token:r,boa_token:i,eoa_token:a,image_token:o,boi_token:s,eoi_token:c}=this.tokenizer.config;this.audio_token=r,this.boa_token=i,this.eoa_token=a,this.image_token=o,this.boi_token=s,this.eoi_token=c}static async from_pretrained(e,t={}){let[n,r,i]=await Promise.all([tl(e,Pd,!0,t),G.from_pretrained(e,t),el(e,Fd,!1,t)]),a={tokenizer:r};return n.image_processor&&(a.image_processor=new bp(n.image_processor)),n.feature_extractor&&(a.feature_extractor=new yf(n.feature_extractor)),new this(n,a,i)}_compute_audio_num_tokens(e,t){let n=Math.round(t*20/1e3),r=Math.round(t*10/1e3),i=Math.floor(n/2),a=Math.floor((e+i-n-1)/r)+1;if(a<=0)return 0;for(let e=0;e<2;++e)a=Math.floor((a-1)/2)+1;return Math.min(a,this.audio_seq_length)}async _call(e,t=null,n=null,r={}){typeof e==`string`&&(e=[e]);let i;if(t){i=await this.image_processor(t,r);let n=i.num_soft_tokens_per_image,a=0;e=e.map(e=>e.replaceAll(this.image_token,()=>` + +${this.boi_token}${this.image_token.repeat(n[a++])}${this.eoi_token} + +`))}let a;if(n){let t=Array.isArray(n)?n:[n];a=await this.feature_extractor(t[0],r);let i=this.feature_extractor.config.sampling_rate??16e3,o=0;e=e.map(e=>e.replaceAll(this.audio_token,()=>` + +${this.boa_token}${this.audio_token.repeat(this._compute_audio_num_tokens(t[o++].length,i))}${this.eoa_token} + +`))}return{...this.tokenizer(e,r),...i,...a}}},Tm=class extends K{static image_processor_class=bm;static tokenizer_class=G;static image_token=`<|image_pad|>`;async _call(e,t=null,...n){Array.isArray(e)||(e=[e]);let r,i;if(t&&(r=await this.image_processor(t),i=r.image_grid_thw),i){let t=this.image_processor.config.merge_size**2,n=0,r=this.constructor.image_token,a=i.tolist();e=e.map(e=>{for(;e.includes(r);){let i=Number(a[n++].reduce((e,t)=>e*t,1n));e=e.replace(r,`<|placeholder|>`.repeat(Math.floor(i/t)))}return e.replaceAll(`<|placeholder|>`,r)})}return{...this.tokenizer(e),...r}}},Em=class extends Tm{static image_token=`<|image|>`},Dm=class extends K{static tokenizer_class=G;static feature_extractor_class=Af;static uses_processor_config=!0;_get_num_audio_features(e){let{hop_length:t}=this.feature_extractor.config.melspec_kwargs,{projector_window_size:n,projector_downsample_rate:r}=this.feature_extractor.config,i=Math.floor(n/r),a=Math.floor(e/t)+1,o=Math.floor(a/2);return Math.ceil(o/n)*i}async _call(e,t=null,n={}){if(Array.isArray(e))throw Error(`Batched inputs are not supported yet.`);let r={};if(t){let{input_features:n}=await this.feature_extractor(t);r.input_features=n;let i=this._get_num_audio_features(t.length);r.input_features_mask=new H(`bool`,new Uint8Array(i).fill(1),[1,i]);let a=this.config.audio_token??`<|audio|>`;if(!e.includes(a))throw Error(`The input text does not contain the audio token ${a}.`);e=e.replaceAll(a,a.repeat(i))}return{...this.tokenizer(e,{add_special_tokens:!1,...n}),...r}}};function Om(e,t){let n=e.dims.at(-1)-1,r=e.tolist();r.fill(!1,0,1),r.fill(!1,n);let i=t.tolist();return r.map((e,t)=>e?t:null).filter(e=>e!==null).map(e=>i[e])}var km=class extends K{static tokenizer_class=G;static image_processor_class=bm;async _call(e,t,n={}){let r=e?await this.image_processor(e,n):{};return{...t?this.tokenizer(t,n):{},...r}}post_process_grounded_object_detection(e,t,{box_threshold:n=.25,text_threshold:r=.25,target_sizes:i=null}={}){let{logits:a,pred_boxes:o}=e,s=a.dims[0];if(i!==null&&i.length!==s)throw Error(`Make sure that you pass in as many target sizes as the batch dimension of the logits`);let c=a.dims.at(1),l=a.sigmoid(),u=l.max(-1).tolist(),d=o.tolist().map(e=>e.map(e=>Uf(e))),f=[];for(let e=0;ee.map((e,t)=>e*a[(t+1)%2])));let o=u[e],s=[],p=[],m=[];for(let i=0;i`+i.repeat(e);o+=` +`}return o+=` +${r}${a}`+i.repeat(e)+`${r}`,o}function jm(e,t,n,r){return`${t}${r}`+n.repeat(e)+`${t}`}function Mm(e,t,n,r,i,a){return e===0&&t===0?jm(n,r,i,a):Am(n,e,t,r,i,a)}var Nm=class extends K{static image_processor_class=bm;static tokenizer_class=G;static uses_processor_config=!0;fake_image_token=``;image_token=``;global_img_token=``;async _call(e,t=null,n={}){n.return_row_col_info??=!0;let r;t&&(r=await this.image_processor(t,n)),Array.isArray(e)||(e=[e]);let i=r.rows??[Array(e.length).fill(0)],a=r.cols??[Array(e.length).fill(0)],o=this.config.image_seq_len,s=[],c=[];for(let t=0;tMm(e,l[t],o,this.fake_image_token,this.image_token,this.global_img_token)),d=n.split(this.image_token);if(d.length===0)throw Error(`The image token should be present in the text.`);let f=d[0];for(let e=0;ee.images).flatMap(e=>e.images).map(e=>Bf.read(e)));let r=this.tokenizer,i=r.apply_chat_template(e,{tokenize:!1,add_generation_prompt:!0,chat_template:n}),a=e=>r.encode(e,{add_special_tokens:!1}),o=i.split(this.image_tag),s=o.length-1;if(t.length!==s)throw Error(`Number of images provided (${t.length}) does not match number of "${this.image_tag}" image tags (${s})`);let[c,l,u]=r.convert_tokens_to_ids([this.image_tag,this.image_start_tag,this.image_end_tag]),d=a(o[0]),f=Array(d.length).fill(!1);for(let e=1;e0){let e=await this.image_processor(t);return e.pixel_values.unsqueeze_(0),{...m,...e}}return m}},Fm=class extends K{static tokenizer_class=G;static image_processor_class=bm;async _call(e=null,t=null,n={}){if(!e&&!t)throw Error(`Either text or images must be provided`);let r=e?this.tokenizer(e,n):{},i=t?await this.image_processor(t,n):{};return{...r,...i}}},Im=class extends K{static tokenizer_class=G;static image_processor_class=bm;async _call(e,t=null,n={}){let{image_rows:r,image_cols:i,image_sizes:a,...o}=await this.image_processor(e,{...n,return_row_col_info:!0});if(t){let e=this.config.image_token??``,{tile_size:n=512,downsample_factor:o=2,encoder_patch_size:s=16,use_thumbnail:c=!0}=this.image_processor.config,l=e=>Math.ceil(Math.floor(e/s)/o),u=l(n)**2,d=this.config.image_start_token??`<|image_start|>`,f=this.config.image_end_token??`<|image_end|>`,p=this.config.image_thumbnail??`<|img_thumbnail|>`;Array.isArray(t)||(t=[t]);let m=0;t=t.map(t=>{let n=t.split(e);return n[0]+n.slice(1).map(t=>{let n=m++,[o,s]=a[n],h=r[n],g=i[n],_=l(o)*l(s),v=d;if(h>1||g>1){let t=e.repeat(u);for(let e=0;e`+t;c&&(v+=p+e.repeat(_))}else v+=e.repeat(_);return v+f+t}).join(``)})}return{...o,...t?this.tokenizer(t,n):{}}}},Lm=class extends K{static tokenizer_class=G;static image_processor_class=bm;static uses_processor_config=!0;async _call(e,t=null,n={}){let r=await this.image_processor(e,n);if(t){let[e,n]=r.pixel_values.dims.slice(-2),{image_token:i,patch_size:a,num_additional_image_tokens:o}=this.config,s=Math.floor(e/a)*Math.floor(n/a)+o;t=structuredClone(t),Array.isArray(t)||(t=[t]);for(let e=0;e0?i.reduce((e,t)=>e*t,1):0;c.push(n),s.push(a)}return[i(c),s]}char_decode(e){return this.char_tokenizer.batch_decode(e).map(e=>e.replaceAll(` `,``))}bpe_decode(e){return this.bpe_tokenizer.batch_decode(e)}wp_decode(e){return this.wp_tokenizer.batch_decode(e).map(e=>e.replaceAll(` `,``))}batch_decode([e,t,n]){let[r,i]=this._decode_helper(e,`char`),[a,o]=this._decode_helper(t,`bpe`),[s,c]=this._decode_helper(n,`wp`),l=[],u=[];for(let e=0;e`;function Um(e,t,n,r,i){return`${r.repeat(n*i)}${t}${e} +`}var Wm=class extends K{static tokenizer_class=G;static image_processor_class=bm;static uses_processor_config=!1;async _call(e,t=null,n={}){t||=(A.warn(`You are using PaliGemma without a text prefix. It will perform as a picture-captioning model.`),``),Array.isArray(e)||(e=[e]),Array.isArray(t)||(t=[t]);let r=this.tokenizer.bos_token,i=this.image_processor.config.image_seq_length,a;t.some(e=>e.includes(Hm))?a=t.map(e=>{let t=e.replaceAll(Hm,Hm.repeat(i)),n=t.lastIndexOf(Hm),a=n===-1?0:n+Hm.length;return t.slice(0,a)+r+t.slice(a)+` +`}):(A.warn("You are passing both `text` and `images` to `PaliGemmaProcessor`. The processor expects special image tokens in the text, as many tokens as there are images per each text. It is recommended to add `` tokens in the very beginning of your text. For this call, we will infer how many images each text has and add special tokens."),a=t.map(t=>Um(t,r,i,Hm,e.length)));let o=this.tokenizer(a,n);return{...await this.image_processor(e,n),...o}}},Gm=`<|image|>`,Km=/<\|image_\d+\|>/g,qm=class extends K{static image_processor_class=bm;static tokenizer_class=G;async _call(e,t=null,{padding:n=!0,truncation:r=!0,num_crops:i=null}={}){Array.isArray(e)||(e=[e]);let a,o;if(t){o=await this.image_processor(t,{num_crops:i});let{num_img_tokens:s}=o,c=e.map((e,t)=>e.split(Km).join(Gm.repeat(s[t])));a=this.tokenizer(c,{padding:n,truncation:r});let l=this.tokenizer._tokenizer.token_to_id(Gm);a.input_ids.map_(e=>e==l?-e:e)}else a=this.tokenizer(e);return{...a,...o}}},Jm=class extends K{static tokenizer_class=G;static image_processor_class=bm;static uses_processor_config=!0;async _call(e,t=null,n={}){let r=await this.image_processor(e,n);if(t){let[e,n]=r.pixel_values.dims.slice(-2),{image_token:i,image_break_token:a,image_end_token:o,patch_size:s,spatial_merge_size:c}=this.config,l=s*c,u=Math.floor(e/l),d=Math.floor(n/l);t=structuredClone(t),Array.isArray(t)||(t=[t]);for(let e=0;eoh(e,o)),c=s.map(e=>e.length),l=s.flat(),u=(await Promise.all(l.map(e=>this.feature_extractor(e,n)))).map(e=>e.input_features);r.audio_values=u.length>1?U(u,0):u[0];let d=i[0];for(let e=0;e0){if(l>Cc)throw Error(`The number of external data chunks (${l}) exceeds the maximum allowed value (${Cc}).`);let t=Th(o,l);for(let n of t){let t=`${r.subfolder??``}/${n}`;c.push(new Promise(async(i,a)=>{let o=await $c(e,t,!0,r,s);i(o instanceof Uint8Array?{path:n,data:o}:n)}))}}else a.externalData!==void 0&&(c=a.externalData.map(async t=>{if(typeof t.data==`string`){let n=await $c(e,t.data,!0,r);return{...t,data:n}}return t}));return Promise.all(c)}async function Oh(e,t,n,r=!1,i=void 0){let a=n.config?.[`transformers.js_config`]??{},o=Ul(n.device??a.device,t,{warn:e=>A.info(e)}),s=kl(o),c=a.device_config??{};c.hasOwnProperty(o)&&(a={...a,...c[o]});let l=Yl(n.dtype??a.dtype,t,o,{configDtype:a.dtype,warn:e=>A.info(e)});if(!Jl.hasOwnProperty(l))throw Error(`Invalid dtype: ${l}. Should be one of: ${Object.keys(Gl).join(`, `)}`);if(o===`webgpu`&&!O.IS_NODE_ENV&&l===Gl.fp16&&!await Wl())throw Error(`The device (${o}) does not support fp16.`);let u=Jl[l],d={...n.session_options};d.executionProviders??=s;let f=a.free_dimension_overrides;f?d.freeDimensionOverrides??=f:o.startsWith(`webnn`)&&!d.freeDimensionOverrides&&A.warn(`WebNN does not currently support dynamic shapes and requires 'free_dimension_overrides' to be set in config.json, preferably as a field within config["transformers.js_config"]["device_config"]["${o}"]. When 'free_dimension_overrides' is not set, you may experience significant performance degradation.`);let p=Eh(e,t,n,u),m=await Dh(e,t,u,n,n.use_external_data_format??a.use_external_data_format,d);if(m.length>0&&(!O.IS_NODE_ENV||m.some(e=>typeof e!=`string`))&&(d.externalData=m),r&&o===`webgpu`){let e=bh(n.config,{prefix:`present`,session_name:i});if(e.size>0&&!Rl()){let t={};for(let n of e)t[n]=`gpu-buffer`;d.preferredOutputLocation=t}}return{buffer_or_path:await p,session_options:d,session_config:{dtype:l,device:o}}}async function kh(e,t,n,r=void 0){return Object.fromEntries(await Promise.all(Object.keys(t).map(async i=>{let a=r?.[i]??!1,{buffer_or_path:o,session_options:s,session_config:c}=await Oh(e,t[i],n,a,i);return[i,await Nl(o,s,c)]})))}function Ah(e){for(let t in e)Il(e[t])?e[t]=new H(e[t]):typeof e[t]==`object`&&Ah(e[t]);return e}async function J(e,t){let n=jh(e,t);try{return Ah(await Fl(e,Object.fromEntries(Object.entries(n).map(([e,t])=>{let n=t.ort_tensor;return O.IS_NODE_ENV&&typeof Float16Array<`u`&&n.cpuData instanceof Float16Array&&(n.cpuData=new Uint16Array(n.cpuData.buffer)),[e,n]}))))}catch(e){let t=Object.fromEntries(Object.entries(n).map(([e,t])=>{let n={type:t.type,dims:t.dims,location:t.location};return n.location!==`gpu-buffer`&&(n.data=t.data),[e,n]}));throw A.error(`An error occurred during model execution: "${e}".`),A.error(`Inputs given to model:`,t),e}}function jh(e,t){let n=/* @__PURE__ */ Object.create(null),r=[];for(let i of e.inputNames){let e=t[i];if(!(e instanceof H)){r.push(i);continue}n[i]=Rl()?e.clone():e}if(r.length>0)throw Error(`An error occurred during model execution: "Missing the following inputs: ${r.join(`, `)}.`);let i=Object.keys(t).length,a=e.inputNames.length;if(i>a){let n=Object.keys(t).filter(t=>!e.inputNames.includes(t));A.warn(`WARNING: Too many inputs were provided (${i} > ${a}). The following inputs will be ignored: "${n.join(`, `)}".`)}return n}var Mh=class{},Nh=class extends Mh{constructor({last_hidden_state:e,hidden_states:t=null,attentions:n=null}){super(),this.last_hidden_state=e,this.hidden_states=t,this.attentions=n}},Y=class extends Mh{constructor({logits:e,...t}){super(),this.logits=e;let n=Object.values(t);n.length>0&&(this.attentions=n)}},Ph=class extends Mh{constructor({logits:e}){super(),this.logits=e}},Fh=class extends Mh{constructor({logits:e}){super(),this.logits=e}},Ih=class extends Mh{constructor({start_logits:e,end_logits:t}){super(),this.start_logits=e,this.end_logits=t}},Lh=class extends Mh{constructor({logits:e}){super(),this.logits=e}},Rh=class extends Mh{constructor({logits:e,past_key_values:t}){super(),this.logits=e,this.past_key_values=t}},zh=class extends Mh{constructor({logits:e,past_key_values:t,encoder_outputs:n,decoder_attentions:r=null,cross_attentions:i=null}){super(),this.logits=e,this.past_key_values=t,this.encoder_outputs=n,this.decoder_attentions=r,this.cross_attentions=i}},Bh=class extends Mh{constructor({alphas:e}){super(),this.alphas=e}},Vh=class extends Qr{_call(e,t){throw Error("`_call` should be implemented in a subclass")}},Hh=class extends Qr{_call(e,t){throw Error("`_call` should be implemented in a subclass")}},Uh=class extends Qr{constructor(){super(),this.processors=[]}push(e){this.processors.push(e)}extend(e){this.processors.push(...e)}_call(e,t){let n=t;for(let t of this.processors)n=t(e,n);return n}[Symbol.iterator](){return this.processors.values()}},Wh=class extends Vh{constructor(e){super(),this.bos_token_id=e}_call(e,t){for(let n=0;n=1&&i[i.length-1]>=this.timestamp_begin,o=i.length<2||i[i.length-2]>=this.timestamp_begin;if(a&&(o?r.subarray(this.timestamp_begin).fill(-1/0):r.subarray(0,this.eos_token_id).fill(-1/0)),e[n].length===this.begin_index&&this.max_initial_timestamp_index!==null){let e=this.timestamp_begin+this.max_initial_timestamp_index;r.subarray(e+1).fill(-1/0)}let s=al(r);Math.log(s.subarray(this.timestamp_begin).map(Math.exp).reduce((e,t)=>e+t))>sl(s.subarray(0,this.timestamp_begin))[0]&&r.subarray(0,this.timestamp_begin).fill(-1/0)}return t}},Yh=class extends Vh{constructor(e){super(),this.no_repeat_ngram_size=e}getNgrams(e){let t=e.length,n=[];for(let r=0;r1 to use the classifier-free guidance processor, got guidance scale ${e}.`);this.guidance_scale=e}_call(e,t){if(t.dims[0]!==2*e.length)throw Error(`Logits should have twice the batch size of the input ids, the first half of batches corresponding to the conditional inputs, and the second half of batches corresponding to the unconditional inputs. Got batch size ${t.dims[0]} for the logits and ${e.length} for the input ids.`);let n=e.length,r=t.slice([0,n],null),i=t.slice([n,t.dims[0]],null);for(let e=0;ee.length>=this.max_length)}},og=class extends rg{constructor(e){super(),Array.isArray(e)||(e=[e]),this.eos_token_id=e}_call(e,t){return e.map(e=>{let t=e.at(-1);return this.eos_token_id.some(e=>t==e)})}},sg=class extends Qr{constructor(e){super(),this.generation_config=e}async _call(e){return this.sample(e)}async sample(e){throw Error(`sample should be implemented in subclasses.`)}getLogits(e,t){let n=e.dims.at(-1),r=e.data;if(t===-1)r=r.slice(-n);else{let e=t*n;r=r.slice(e,e+n)}return r}randomSelect(e){return yc(e)}static getSampler(e){if(e.do_sample)return new lg(e);if(e.num_beams>1)return new ug(e);if(e.num_return_sequences>1)throw Error(`num_return_sequences has to be 1 when doing greedy search, but is ${e.num_return_sequences}.`);return new cg(e)}},cg=class extends sg{async sample(e){let t=sl(e.data)[1];return[[BigInt(t),0]]}},lg=class extends sg{async sample(e){let t=e.dims.at(-1);this.generation_config.top_k>0&&(t=Math.min(this.generation_config.top_k,t));let[n,r]=await nu(e,t),i=il(n.data);return Array.from({length:this.generation_config.num_beams},()=>{let e=this.randomSelect(i);return[r.data[e],Math.log(i[e])]})}},ug=class extends sg{async sample(e){let t=e.dims.at(-1);this.generation_config.top_k>0&&(t=Math.min(this.generation_config.top_k,t));let[n,r]=await nu(e,t),i=il(n.data);return Array.from({length:this.generation_config.num_beams},(e,t)=>[r.data[t],Math.log(i[t])])}},dg=class{constructor(e){if(e)for(let t in e){if(t in this)throw TypeError(`Key "${t}" conflicts with an existing property on DynamicCache`);let n=e[t];if(!(n instanceof H))throw TypeError(`Expected a Tensor for key "${t}", got ${typeof n}`);this[t]=n}}get_seq_length(){let e=this;if(Object.keys(e).length===0)return 0;for(let t in e)if(t.startsWith(`past_key_values.`))return e[t].dims.at(-2);throw Error(`Unable to determine sequence length from the cache.`)}update(e){for(let t in e){let n=this[t],r=e[t];n&&n!==r&&n.location===`gpu-buffer`&&n.dispose(),this[t]=r}}async dispose(){let e=[];for(let t of Object.values(this))t.location===`gpu-buffer`&&e.push(t.dispose());await Promise.all(e)}},X={EncoderOnly:0,EncoderDecoder:1,Seq2Seq:2,Vision2Seq:3,DecoderOnly:4,DecoderOnlyWithoutHead:5,MaskGeneration:6,ImageTextToText:7,Musicgen:8,MultiModality:9,Phi3V:10,AudioTextToText:11,AutoEncoder:12,ImageAudioTextToText:13,Supertonic:14,Chatterbox:15,VoxtralRealtime:16},fg={[X.DecoderOnly]:{sessions:(e,t)=>({model:t.model_file_name??`model`}),cache_sessions:{model:!0},optional_configs:{generation_config:`generation_config.json`}},[X.DecoderOnlyWithoutHead]:{sessions:(e,t)=>({model:t.model_file_name??`model`})},[X.Seq2Seq]:{sessions:()=>({model:`encoder_model`,decoder_model_merged:`decoder_model_merged`}),cache_sessions:{decoder_model_merged:!0},optional_configs:{generation_config:`generation_config.json`}},[X.Vision2Seq]:{sessions:()=>({model:`encoder_model`,decoder_model_merged:`decoder_model_merged`}),cache_sessions:{decoder_model_merged:!0},optional_configs:{generation_config:`generation_config.json`}},[X.Musicgen]:{sessions:()=>({model:`text_encoder`,decoder_model_merged:`decoder_model_merged`,encodec_decode:`encodec_decode`}),cache_sessions:{decoder_model_merged:!0},optional_configs:{generation_config:`generation_config.json`}},[X.EncoderDecoder]:{sessions:()=>({model:`encoder_model`,decoder_model_merged:`decoder_model_merged`}),cache_sessions:{decoder_model_merged:!0}},[X.MaskGeneration]:{sessions:()=>({model:`vision_encoder`,prompt_encoder_mask_decoder:`prompt_encoder_mask_decoder`})},[X.ImageTextToText]:{text_only_sessions:{embed_tokens:`embed_tokens`,decoder_model_merged:`decoder_model_merged`},sessions:(e,t,n)=>{let r={...fg[X.ImageTextToText].text_only_sessions};return n||(r.vision_encoder=`vision_encoder`),e.is_encoder_decoder&&(r.model=`encoder_model`),r},cache_sessions:{decoder_model_merged:!0},optional_configs:{generation_config:`generation_config.json`}},[X.AudioTextToText]:{text_only_sessions:{embed_tokens:`embed_tokens`,decoder_model_merged:`decoder_model_merged`},sessions:(e,t,n)=>{let r={...fg[X.AudioTextToText].text_only_sessions};return n||(r.audio_encoder=`audio_encoder`),r},cache_sessions:{decoder_model_merged:!0},optional_configs:{generation_config:`generation_config.json`}},[X.ImageAudioTextToText]:{text_only_sessions:{embed_tokens:`embed_tokens`,decoder_model_merged:`decoder_model_merged`},sessions:(e,t,n)=>{let r={...fg[X.ImageAudioTextToText].text_only_sessions};return n||(r.audio_encoder=`audio_encoder`,r.vision_encoder=`vision_encoder`),r},cache_sessions:{decoder_model_merged:!0},optional_configs:{generation_config:`generation_config.json`}},[X.Phi3V]:{sessions:()=>({prepare_inputs_embeds:`prepare_inputs_embeds`,model:`model`,vision_encoder:`vision_encoder`}),cache_sessions:{model:!0},optional_configs:{generation_config:`generation_config.json`}},[X.MultiModality]:{sessions:()=>({prepare_inputs_embeds:`prepare_inputs_embeds`,model:`language_model`,lm_head:`lm_head`,gen_head:`gen_head`,gen_img_embeds:`gen_img_embeds`,image_decode:`image_decode`}),cache_sessions:{model:!0},optional_configs:{generation_config:`generation_config.json`}},[X.AutoEncoder]:{sessions:()=>({encoder_model:`encoder_model`,decoder_model:`decoder_model`})},[X.Supertonic]:{sessions:()=>({text_encoder:`text_encoder`,latent_denoiser:`latent_denoiser`,voice_decoder:`voice_decoder`})},[X.Chatterbox]:{sessions:()=>({embed_tokens:`embed_tokens`,speech_encoder:`speech_encoder`,model:`language_model`,conditional_decoder:`conditional_decoder`}),cache_sessions:{model:!0},optional_configs:{generation_config:`generation_config.json`}},[X.VoxtralRealtime]:{text_only_sessions:{embed_tokens:`embed_tokens`,decoder_model_merged:`decoder_model_merged`},sessions:(e,t,n)=>{let r={...fg[X.VoxtralRealtime].text_only_sessions};return n||(r.audio_encoder=`audio_encoder`),r},cache_sessions:{decoder_model_merged:!0,audio_encoder:!0},optional_configs:{generation_config:`generation_config.json`}},default:{sessions:(e,t)=>({model:t.model_file_name??`model`})}};function pg(e){return fg[e]?.text_only_sessions??null}function mg(e,t,n={}){let r=fg[e]??fg.default;return{sessions:r.sessions(t,n,n.textOnly??!1),cache_sessions:r.cache_sessions,optional_configs:r.optional_configs}}function hg(e,{warn:t=!0}={}){let n=e.architectures||[];for(let e of n){let t=wg.get(e);if(t!==void 0)return t}if(e.model_type){let t=wg.get(e.model_type);if(t!==void 0)return t;for(let t of Object.values(vg))if(t.has(e.model_type)){let n=wg.get(t.get(e.model_type));if(n!==void 0)return n}}if(t){let t=n.length>0?n.join(`, `):`(none)`;A.warn(`[resolve_model_type] Architecture(s) not found in MODEL_TYPE_MAPPING: [${t}] for model type '${e.model_type}'. Falling back to EncoderOnly (single model.onnx file). If you encounter issues, please report at: ${jd}`)}return X.EncoderOnly}function gg(e,{config:t=null,cache_dir:n=null,local_files_only:r=!1,revision:i=`main`}={}){return t===null?Hc(Oc(e,{cache_dir:n,local_files_only:r,revision:i}),()=>Ch.from_pretrained(e,{config:t,cache_dir:n,local_files_only:r,revision:i})):Ch.from_pretrained(e,{config:t,cache_dir:n,local_files_only:r,revision:i})}async function _g(e,{config:t=null,dtype:n=null,device:r=null,model_file_name:i=null}={}){t=await gg(e,{config:t});let a=[`config.json`],o=t[`transformers.js_config`]??{},s=o.use_external_data_format,c=`onnx`,l=r??o.device,u=n??o.dtype,d=hg(t),f=(e,t=null)=>{t??=e;let n=Ul(l,e),r=Jl[Yl(u,e,n)]??``,i=`${t}${r}.onnx`,o=`${c}/${i}`;a.push(o);let d=wh(s,i,e);for(let e of Th(i,d)){let t=`${c}/${e}`;a.push(t)}},{sessions:p,optional_configs:m}=mg(d,t,{model_file_name:i});for(let[e,t]of Object.entries(p))f(e,t);if(m)for(let e of Object.values(m))a.push(e);return a}var vg=null;function yg(e){vg=e}function bg(e){if(e instanceof H)return e;if(e.length===0)throw Error(`items must be non-empty`);if(Array.isArray(e[0])){if(e.some(t=>t.length!==e[0].length))throw Error(`Unable to create tensor, you should probably activate truncation and/or padding with 'padding=True' and/or 'truncation=True' to have batched tensors with the same length.`);return new H(`int64`,BigInt64Array.from(e.flat().map(e=>BigInt(e))),[e.length,e[0].length])}return new H(`int64`,BigInt64Array.from(e.map(e=>BigInt(e))),[1,e.length])}function xg(e){return new H(`bool`,[e],[1])}var Sg={[X.DecoderOnly]:{can_generate:!0,forward:Fg,prepare_inputs:Vg},[X.DecoderOnlyWithoutHead]:{can_generate:!1,forward:Fg,prepare_inputs:Vg},[X.Seq2Seq]:{can_generate:!0,forward:Dg,prepare_inputs:Hg},[X.Vision2Seq]:{can_generate:!0,forward:Dg,prepare_inputs:Hg},[X.Musicgen]:{can_generate:!0,forward:Dg},[X.EncoderDecoder]:{can_generate:!1,forward:Dg},[X.ImageTextToText]:{can_generate:!0,forward:Rg,prepare_inputs:Ug},[X.AudioTextToText]:{can_generate:!0,forward:Lg,prepare_inputs:Ug},[X.ImageAudioTextToText]:{can_generate:!0,prepare_inputs:Ug},[X.Phi3V]:{can_generate:!0,prepare_inputs:Ug},[X.MultiModality]:{can_generate:!0},[X.AutoEncoder]:{can_generate:!1,forward:kg},[X.Chatterbox]:{can_generate:!0,forward:Og},[X.VoxtralRealtime]:{can_generate:!0,prepare_inputs:Vg},default:{can_generate:!1,forward:Og}};function Cg(e,t){let n=wg.get(e),r=!1,i=t?.architectures?.[0];if(i&&i!==e&&e?.endsWith(`ForCausalLM`)&&i.endsWith(`ForConditionalGeneration`)){let e=wg.get(i);e!==void 0&&(n=e,r=!0)}let a=Sg[n]??Sg.default,o=fg[n]??fg.default;return{typeConfig:{...a,...o},textOnly:r,modelType:n}}var wg=/* @__PURE__ */ new Map,Tg=/* @__PURE__ */ new Map,Eg=/* @__PURE__ */ new Map,Z=class extends Qr{main_input_name=`input_ids`;forward_params=[`input_ids`,`attention_mask`];_return_dict_in_generate_keys=null;constructor(e,t,n){super(),this.config=e,this.sessions=t,this.configs=n;let{typeConfig:r}=Cg(Eg.get(this.constructor),e);this.can_generate=r.can_generate,this._forward=r.forward,this._prepare_inputs_for_generation=r.prepare_inputs,this.can_generate&&this.forward_params.push(`past_key_values`),this.custom_config=this.config[`transformers.js_config`]??{}}async dispose(){let e=[];for(let t of Object.values(this.sessions))e.push(t.release?.());return await Promise.all(e)}static async from_pretrained(e,{progress_callback:t=null,config:n=null,cache_dir:r=null,local_files_only:i=!1,revision:a=`main`,model_file_name:o=null,subfolder:s=`onnx`,device:c=null,dtype:l=null,use_external_data_format:u=null,session_options:d={}}={}){let f={progress_callback:t,config:n,cache_dir:r,local_files_only:i,revision:a,model_file_name:o,subfolder:s,device:c,dtype:l,use_external_data_format:u,session_options:d},p=Eg.get(this);n=f.config=await Ch.from_pretrained(e,f);let{typeConfig:m,textOnly:h,modelType:g}=Cg(p,n);if(g===void 0){let e=p??n?.model_type;e!==`custom`&&A.warn(`Model type for '${e}' not found, assuming encoder-only architecture. Please report this at ${jd}.`)}if(t&&!(t instanceof ei)){let r={};try{let t=await _g(e,{config:n,dtype:l,device:c,model_file_name:o});(await Promise.all(t.map(t=>Wc(e,t,f)))).forEach((e,n)=>{if(e.exists){let i=t[n]===`config.json`;r[t[n]]={loaded:i?e.size??0:0,total:e.size??0}}})}catch(e){A.warn(`Unable to fetch model file metadata for total progress tracking: ${e}`)}Object.keys(r).length>0&&(f.progress_callback=new ei(t,r))}let _=[kh(e,m.sessions(n,f,h),f,m.cache_sessions)];m.optional_configs&&_.push(qg(e,m.optional_configs,f));let v=await Promise.all(_);return new this(n,...v)}async _call(e){return await this.forward(e)}async forward(e){return await this._forward(this,e)}get generation_config(){return this.configs?.generation_config??null}_get_logits_processor(e,t,n=null){let r=new Uh;if(e.repetition_penalty!==null&&e.repetition_penalty!==1&&r.push(new Xh(e.repetition_penalty)),e.no_repeat_ngram_size!==null&&e.no_repeat_ngram_size>0&&r.push(new Yh(e.no_repeat_ngram_size)),e.bad_words_ids!==null&&r.push(new $h(e.bad_words_ids,e.eos_token_id)),e.min_length!==null&&e.eos_token_id!==null&&e.min_length>0&&r.push(new Zh(e.min_length,e.eos_token_id)),e.min_new_tokens!==null&&e.eos_token_id!==null&&e.min_new_tokens>0&&r.push(new Qh(t,e.min_new_tokens,e.eos_token_id)),e.forced_bos_token_id!==null&&r.push(new Wh(e.forced_bos_token_id)),e.forced_eos_token_id!==null&&r.push(new Gh(e.max_length,e.forced_eos_token_id)),e.suppress_tokens!==null&&r.push(new Kh(e.suppress_tokens)),e.begin_suppress_tokens!==null){let n=t>1||e.forced_bos_token_id===null?t:t+1;r.push(new qh(e.begin_suppress_tokens,n))}return e.guidance_scale!==null&&e.guidance_scale>1&&r.push(new eg(e.guidance_scale)),e.temperature===0&&e.do_sample&&(A.warn("`do_sample` changed to false because `temperature: 0` implies greedy sampling (always selecting the most likely token), which is incompatible with `do_sample: true`."),e.do_sample=!1),e.do_sample&&e.temperature!==null&&e.temperature!==1&&r.push(new tg(e.temperature)),n!==null&&r.extend(n),r}_prepare_generation_config(e,t,n=ng){let r={...this.config};for(let e of[`decoder`,`generator`,`text_config`])e in r&&Object.assign(r,r[e]);let i=new n(r);return Object.assign(i,this.generation_config??{}),e&&Object.assign(i,e),t&&Object.assign(i,si(t,Object.getOwnPropertyNames(i))),i}_get_stopping_criteria(e,t=null){let n=new ig;return e.max_length!==null&&n.push(new ag(e.max_length,this.config.max_position_embeddings??null)),e.eos_token_id!==null&&n.push(new og(e.eos_token_id)),t&&n.extend(t),n}_validate_model_class(){if(!this.can_generate){let e=[vg.MODEL_FOR_CAUSAL_LM_MAPPING_NAMES,vg.MODEL_FOR_VISION_2_SEQ_MAPPING_NAMES,vg.MODEL_FOR_SEQ_TO_SEQ_CAUSAL_LM_MAPPING_NAMES,vg.MODEL_FOR_SPEECH_SEQ_2_SEQ_MAPPING_NAMES].filter(Boolean),t=Eg.get(this.constructor),n=/* @__PURE__ */ new Set,r=this.config.model_type;for(let t of e){let e=t?.get(r);e&&n.add(e)}let i=`The current model class (${t}) is not compatible with \`.generate()\`, as it doesn't have a language model head.`;throw n.size>0&&(i+=` Please use the following class instead: ${[...n].join(`, `)}`),Error(i)}}prepare_inputs_for_generation(...e){if(!this._prepare_inputs_for_generation)throw Error(`prepare_inputs_for_generation is not implemented for this model.`);return this._prepare_inputs_for_generation(this,...e)}_update_model_kwargs_for_generation({generated_input_ids:e,outputs:t,model_inputs:n,is_encoder_decoder:r}){return n.past_key_values=Ag(t,n.past_key_values),n.input_ids=new H(`int64`,e.flat(),[e.length,1]),r?`decoder_attention_mask`in n&&(n.decoder_attention_mask=U([n.decoder_attention_mask,_u([n.decoder_attention_mask.dims[0],1])],1)):n.attention_mask=U([n.attention_mask,_u([n.attention_mask.dims[0],1])],1),n.position_ids=null,n}_prepare_model_inputs({inputs:e,bos_token_id:t,model_kwargs:n}){let r=si(n,this.forward_params),i=this.main_input_name;if(i in r){if(e)throw Error("`inputs`: {inputs}` were passed alongside {input_name} which is not allowed. Make sure to either pass {inputs} or {input_name}=...")}else r[i]=e;return{inputs_tensor:r[i],model_inputs:r,model_input_name:i}}async _prepare_encoder_decoder_kwargs_for_generation({inputs_tensor:e,model_inputs:t,model_input_name:n,generation_config:r}){if(this.sessions.model.inputNames.includes(`inputs_embeds`)&&!t.inputs_embeds&&`_prepare_inputs_embeds`in this){let{input_ids:e,pixel_values:n,attention_mask:r,...i}=t,a=await this._prepare_inputs_embeds(t);t={...i,...si(a,[`inputs_embeds`,`attention_mask`])}}let{last_hidden_state:i}=await Og(this,t);if(r.guidance_scale!==null&&r.guidance_scale>1)i=U([i,gu(i,0)],0),`attention_mask`in t&&(t.attention_mask=U([t.attention_mask,bu(t.attention_mask)],0));else if(t.decoder_input_ids){let e=bg(t.decoder_input_ids).dims[0];if(e!==i.dims[0]){if(i.dims[0]!==1)throw Error(`The encoder outputs have a different batch size (${i.dims[0]}) than the decoder inputs (${e}).`);i=U(Array.from({length:e},()=>i),0)}}return t.encoder_outputs=i,t}_prepare_decoder_input_ids_for_generation({batch_size:e,model_input_name:t,model_kwargs:n,decoder_start_token_id:r,bos_token_id:i,generation_config:a}){let{decoder_input_ids:o,...s}=n;if(!(o instanceof H)){if(o)Array.isArray(o[0])||(o=Array.from({length:e},()=>o));else if(r??=i,this.config.model_type===`musicgen`)o=Array.from({length:e*this.config.decoder.num_codebooks},()=>[r]);else if(Array.isArray(r)){if(r.length!==e)throw Error(`\`decoder_start_token_id\` expected to have length ${e} but got ${r.length}`);o=r}else o=Array.from({length:e},()=>[r]);o=bg(o)}return s.decoder_attention_mask=vu(o),{input_ids:o,model_inputs:s}}async generate({inputs:e=null,generation_config:t=null,logits_processor:n=null,stopping_criteria:r=null,streamer:i=null,...a}){this._validate_model_class(),t=this._prepare_generation_config(t,a);let{inputs_tensor:o,model_inputs:s,model_input_name:c}=this._prepare_model_inputs({inputs:e,model_kwargs:a}),l=this.config.is_encoder_decoder;l&&(`encoder_outputs`in s||(s=await this._prepare_encoder_decoder_kwargs_for_generation({inputs_tensor:o,model_inputs:s,model_input_name:c,generation_config:t})));let u;l?{input_ids:u,model_inputs:s}=this._prepare_decoder_input_ids_for_generation({batch_size:s[c].dims.at(0),model_input_name:c,model_kwargs:s,decoder_start_token_id:t.decoder_start_token_id,bos_token_id:t.bos_token_id,generation_config:t}):u=s[c];let d=u.dims.at(-1);t.max_new_tokens!==null&&(t.max_length=d+t.max_new_tokens);let f=this._get_logits_processor(t,d,n),p=this._get_stopping_criteria(t,r),m=s[c].dims.at(0),h=sg.getSampler(t),g=Array(m).fill(0),_=u.tolist();i&&i.put(_);let v,y={},b={};for(;;){if(s=this.prepare_inputs_for_generation(_,s,t),v=await this.forward(s),t.return_dict_in_generate){if(t.output_attentions){let e=jg(v);for(let t in e)t in y||(y[t]=[]),y[t].push(e[t])}else this._return_dict_in_generate_keys&&Object.assign(b,si(v,this._return_dict_in_generate_keys))}let e=f(_,v.logits.slice(null,-1,null).to(`float32`)),n=[];for(let t=0;te))break;s=this._update_model_kwargs_for_generation({generated_input_ids:n,outputs:v,model_inputs:s,is_encoder_decoder:l})}i&&i.end();let x=new H(`int64`,_.flat(),[_.length,_[0].length]),S=Ag(v,s.past_key_values),C=new Set(Object.values(S));for(let e of Object.values(v))e.location===`gpu-buffer`&&!C.has(e)&&e.dispose();return`past_key_values`in a||t.return_dict_in_generate||await S.dispose(),t.return_dict_in_generate?{sequences:x,past_key_values:S,...y,...b}:x}async _encode_input(e,t,n){if(!Object.hasOwn(this.sessions,e))throw Error(`Model does not have a ${e} session.`);let r=this.sessions[e];return(await J(r,si(t,r.inputNames)))[n]}async encode_image(e){return this._encode_input(`vision_encoder`,e,`image_features`)}async encode_text(e){return this._encode_input(`embed_tokens`,e,`inputs_embeds`)}async encode_audio(e){return this._encode_input(`audio_encoder`,e,`audio_features`)}};async function Dg(e,t){let{encoder_outputs:n,input_ids:r,decoder_input_ids:i,decoder_attention_mask:a,...o}=t;return n||=(await Og(e,si(t,e.sessions.model.inputNames))).last_hidden_state,o.input_ids=i,o.encoder_hidden_states=n,e.sessions.decoder_model_merged.inputNames.includes(`encoder_attention_mask`)&&(o.encoder_attention_mask=t.attention_mask),a&&!o.attention_mask&&(o.attention_mask=a),await Fg(e,o,!0)}async function Og(e,t){let n=e.sessions.model,r=si(t,n.inputNames);if(n.inputNames.includes(`inputs_embeds`)&&!r.inputs_embeds){if(!t.input_ids)throw Error("Both `input_ids` and `inputs_embeds` are missing in the model inputs.");r.inputs_embeds=await e.encode_text({input_ids:t.input_ids})}if(n.inputNames.includes(`token_type_ids`)&&!r.token_type_ids){if(!r.input_ids)throw Error("Both `input_ids` and `token_type_ids` are missing in the model inputs.");r.token_type_ids=bu(r.input_ids)}if(n.inputNames.includes(`pixel_mask`)&&!r.pixel_mask){if(!r.pixel_values)throw Error("Both `pixel_values` and `pixel_mask` are missing in the model inputs.");let e=r.pixel_values.dims;r.pixel_mask=_u([e[0],e[2],e[3]])}return await J(n,r)}async function kg(e,t){let n=await e.encode(t);return await e.decode(n)}function Ag(e,t){let n=/* @__PURE__ */ Object.create(null);for(let r in e)if(r.startsWith(`present`)){let i=r.replace(`present_ssm`,`past_ssm`).replace(`present_conv`,`past_conv`).replace(`present_recurrent`,`past_recurrent`).replace(`present_compressor`,`past_compressor`).replace(`present_indexer`,`past_indexer`).replace(`present`,`past_key_values`);n[i]=r.includes(`encoder`)&&t?t[i]:e[r]}return t?(t.update(n),t):new dg(n)}function jg(e){let t={};for(let n of[`cross_attentions`,`encoder_attentions`,`decoder_attentions`])for(let r in e)r.startsWith(n)&&(n in t||(t[n]=[]),t[n].push(e[r]));return t}function Mg(e,t){return e.map(e=>typeof e==`number`?e:t[e]??0)}function Ng(e,t,n){if(n&&Object.keys(n).length>0)return Object.assign(t,n),n;let r=e.sessions.decoder_model_merged??e.sessions.model,i=(t[e.main_input_name]??t.attention_mask)?.dims?.[0]??1,a=bh(e.config),o=e.config?.normalized_config?.num_heads,s={batch_size:i};typeof o==`number`&&(s[`batch_size x num_heads`]=i*o);let c=/* @__PURE__ */ Object.create(null);for(let e of r.inputMetadata){if(!a.has(e.name))continue;let n=Mg(e.shape,s),r=n.reduce((e,t)=>e*t,1),i=Xl[e.type],o=new H(e.type,new i(r),n);t[e.name]=o,c[e.name]=o}return n?(n.update(c),n):new dg(c)}function Pg(e,t,n){t.num_logits_to_keep||(e.sessions.decoder_model_merged??e.sessions.model)?.inputNames.includes(`num_logits_to_keep`)&&(t.num_logits_to_keep=new H(`int64`,[n],[]))}async function Fg(e,t,n=!1){let r=e.sessions[n?`decoder_model_merged`:`model`],{past_key_values:i,...a}=t;return r.inputNames.includes(`use_cache_branch`)&&(a.use_cache_branch=xg(i!=null&&Object.keys(i).length>0)),r.inputNames.includes(`position_ids`)&&a.attention_mask&&!a.position_ids&&(a.position_ids=Bg(a,i,+!![`paligemma`,`gemma3_text`,`gemma3`].includes(e.config.model_type))),Pg(e,a,0n),Ng(e,a,i),await J(r,si(a,r.inputNames))}async function Ig(e,{encode_function:t,merge_function:n,modality_input_names:r,modality_output_name:i,input_ids:a=null,attention_mask:o=null,position_ids:s=null,inputs_embeds:c=null,past_key_values:l=null,generation_config:u=null,logits_processor:d=null,num_logits_to_keep:f=null,...p}){if(!c){c=await e.encode_text({input_ids:a,...p});let s=si(p,r);if(Object.keys(s).length>0){if(a.dims[1]!==1){let e=await t({...s,...p});({inputs_embeds:c,attention_mask:o}=n({[i]:e,inputs_embeds:c,input_ids:a,attention_mask:o}))}else if(l&&a.dims[1]===1){let e=a.dims[1],t=l.get_seq_length();o=U([_u([a.dims[0],t]),o.slice(null,[o.dims[1]-e,o.dims[1]])],1)}}}if(!s&&[`qwen2_vl`,`qwen2_vl_text`,`qwen2_5_vl`,`qwen2_5_vl_text`,`qwen3_vl`,`qwen3_vl_text`,`qwen3_vl_moe`,`qwen3_vl_moe_text`,`qwen3_5`,`qwen3_5_text`,`qwen3_5_moe`,`qwen3_5_moe_text`,`glm_ocr`,`glm_ocr_text`].includes(e.config.model_type)){let{image_grid_thw:t,video_grid_thw:n}=p;[s]=e.get_rope_index(a,t,n,o)}return await Fg(e,{inputs_embeds:c,past_key_values:l,attention_mask:o,position_ids:s,generation_config:u,logits_processor:d,num_logits_to_keep:f},!0)}async function Lg(e,t){return await Ig(e,{...t,modality_input_names:[`audio_values`,`input_features`],modality_output_name:`audio_features`,encode_function:e.encode_audio.bind(e),merge_function:e._merge_input_ids_with_audio_features.bind(e)})}async function Rg(e,t){return await Ig(e,{...t,modality_input_names:[`pixel_values`],modality_output_name:`image_features`,encode_function:e.encode_image.bind(e),merge_function:e._merge_input_ids_with_image_features.bind(e)})}function zg(e,t=0){let[n,r]=e.dims,i=e.data,a=new BigInt64Array(i.length);for(let e=0;ee.dims[1]||i[e.at(-1)])),Pg(e,n,1n),{...n,decoder_input_ids:bg(t)}}function Ug(e,...t){return e.config.is_encoder_decoder?Hg(e,...t):Vg(e,...t)}function Wg({modality_token_id:e,inputs_embeds:t,modality_features:n,input_ids:r,attention_mask:i}){let a=r.tolist().map(t=>t.reduce((t,n,r)=>(n==e&&t.push(r),t),[])),o=a.reduce((e,t)=>e+t.length,0),s=n.dims[0];if(o!==s)throw Error(`Number of tokens and features do not match: tokens: ${o}, features ${s}`);let c=0;for(let e=0;e[r,await tl(e,t[r],!1,n)])))}var Jg={};xr(Jg,{ASTForAudioClassification:()=>d_,ASTModel:()=>u_,ASTPreTrainedModel:()=>l_,AfmoeForCausalLM:()=>a_,AfmoeModel:()=>i_,AfmoePreTrainedModel:()=>r_,AlbertForMaskedLM:()=>$g,AlbertForQuestionAnswering:()=>Qg,AlbertForSequenceClassification:()=>Zg,AlbertModel:()=>Xg,AlbertPreTrainedModel:()=>Yg,ApertusForCausalLM:()=>n_,ApertusModel:()=>t_,ApertusPreTrainedModel:()=>e_,ArceeForCausalLM:()=>c_,ArceeModel:()=>s_,ArceePreTrainedModel:()=>o_,BartForConditionalGeneration:()=>m_,BartForSequenceClassification:()=>h_,BartModel:()=>p_,BartPretrainedModel:()=>f_,BaseModelOutput:()=>Nh,BeitForImageClassification:()=>v_,BeitModel:()=>__,BeitPreTrainedModel:()=>g_,BertForMaskedLM:()=>x_,BertForQuestionAnswering:()=>w_,BertForSequenceClassification:()=>S_,BertForTokenClassification:()=>C_,BertModel:()=>b_,BertPreTrainedModel:()=>y_,BlenderbotForConditionalGeneration:()=>D_,BlenderbotModel:()=>E_,BlenderbotPreTrainedModel:()=>T_,BlenderbotSmallForConditionalGeneration:()=>A_,BlenderbotSmallModel:()=>k_,BlenderbotSmallPreTrainedModel:()=>O_,BloomForCausalLM:()=>N_,BloomModel:()=>M_,BloomPreTrainedModel:()=>j_,CHMv2ForDepthEstimation:()=>q_,CHMv2PreTrainedModel:()=>K_,CLIPModel:()=>$_,CLIPPreTrainedModel:()=>Q_,CLIPSegForImageSegmentation:()=>ov,CLIPSegModel:()=>av,CLIPSegPreTrainedModel:()=>iv,CLIPTextModel:()=>ev,CLIPTextModelWithProjection:()=>tv,CLIPVisionModel:()=>nv,CLIPVisionModelWithProjection:()=>rv,CamembertForMaskedLM:()=>I_,CamembertForQuestionAnswering:()=>z_,CamembertForSequenceClassification:()=>L_,CamembertForTokenClassification:()=>R_,CamembertModel:()=>F_,CamembertPreTrainedModel:()=>P_,CausalLMOutput:()=>Lh,CausalLMOutputWithPast:()=>Rh,ChatterboxModel:()=>U_,ChatterboxPreTrainedModel:()=>H_,ChineseCLIPModel:()=>G_,ChineseCLIPPreTrainedModel:()=>W_,ClapAudioModelWithProjection:()=>Z_,ClapModel:()=>Y_,ClapPreTrainedModel:()=>J_,ClapTextModelWithProjection:()=>X_,CodeGenForCausalLM:()=>lv,CodeGenModel:()=>cv,CodeGenPreTrainedModel:()=>sv,Cohere2ForCausalLM:()=>hv,Cohere2Model:()=>mv,Cohere2PreTrainedModel:()=>pv,CohereAsrForConditionalGeneration:()=>vv,CohereAsrModel:()=>_v,CohereAsrPreTrainedModel:()=>gv,CohereForCausalLM:()=>fv,CohereModel:()=>dv,CoherePreTrainedModel:()=>uv,ConvBertForMaskedLM:()=>xv,ConvBertForQuestionAnswering:()=>wv,ConvBertForSequenceClassification:()=>Sv,ConvBertForTokenClassification:()=>Cv,ConvBertModel:()=>bv,ConvBertPreTrainedModel:()=>yv,ConvNextForImageClassification:()=>Dv,ConvNextModel:()=>Ev,ConvNextPreTrainedModel:()=>Tv,ConvNextV2ForImageClassification:()=>Av,ConvNextV2Model:()=>kv,ConvNextV2PreTrainedModel:()=>Ov,DFineForObjectDetection:()=>Lv,DFineModel:()=>Iv,DFinePreTrainedModel:()=>Fv,DINOv3ConvNextModel:()=>Ay,DINOv3ConvNextPreTrainedModel:()=>ky,DINOv3ViTModel:()=>My,DINOv3ViTPreTrainedModel:()=>jy,DPTForDepthEstimation:()=>Uy,DPTModel:()=>Hy,DPTPreTrainedModel:()=>Vy,DacDecoderModel:()=>Uv,DacDecoderOutput:()=>zv,DacEncoderModel:()=>Hv,DacEncoderOutput:()=>Rv,DacModel:()=>Vv,DacPreTrainedModel:()=>Bv,DebertaForMaskedLM:()=>Kv,DebertaForQuestionAnswering:()=>Yv,DebertaForSequenceClassification:()=>qv,DebertaForTokenClassification:()=>Jv,DebertaModel:()=>Gv,DebertaPreTrainedModel:()=>Wv,DebertaV2ForMaskedLM:()=>iy,DebertaV2ForQuestionAnswering:()=>sy,DebertaV2ForSequenceClassification:()=>ay,DebertaV2ForTokenClassification:()=>oy,DebertaV2Model:()=>ry,DebertaV2PreTrainedModel:()=>ny,DecisionTransformerModel:()=>ly,DecisionTransformerPreTrainedModel:()=>cy,DeepseekV3ForCausalLM:()=>Qv,DeepseekV3Model:()=>Zv,DeepseekV3PreTrainedModel:()=>Xv,DeepseekV4ForCausalLM:()=>ty,DeepseekV4Model:()=>ey,DeepseekV4PreTrainedModel:()=>$v,DeiTForImageClassification:()=>fy,DeiTModel:()=>dy,DeiTPreTrainedModel:()=>uy,DepthAnythingForDepthEstimation:()=>my,DepthAnythingPreTrainedModel:()=>py,DepthProForDepthEstimation:()=>gy,DepthProPreTrainedModel:()=>hy,DetrForObjectDetection:()=>yy,DetrForSegmentation:()=>by,DetrModel:()=>vy,DetrObjectDetectionOutput:()=>xy,DetrPreTrainedModel:()=>_y,DetrSegmentationOutput:()=>Sy,Dinov2ForImageClassification:()=>Ty,Dinov2Model:()=>wy,Dinov2PreTrainedModel:()=>Cy,Dinov2WithRegistersForImageClassification:()=>Oy,Dinov2WithRegistersModel:()=>Dy,Dinov2WithRegistersPreTrainedModel:()=>Ey,DistilBertForMaskedLM:()=>Ry,DistilBertForQuestionAnswering:()=>Ly,DistilBertForSequenceClassification:()=>Fy,DistilBertForTokenClassification:()=>Iy,DistilBertModel:()=>Py,DistilBertPreTrainedModel:()=>Ny,DonutSwinModel:()=>By,DonutSwinPreTrainedModel:()=>zy,EdgeTamModel:()=>AE,EfficientNetForImageClassification:()=>Ky,EfficientNetModel:()=>Gy,EfficientNetPreTrainedModel:()=>Wy,ElectraForMaskedLM:()=>Yy,ElectraForQuestionAnswering:()=>Qy,ElectraForSequenceClassification:()=>Xy,ElectraForTokenClassification:()=>Zy,ElectraModel:()=>Jy,ElectraPreTrainedModel:()=>qy,Ernie4_5ForCausalLM:()=>tb,Ernie4_5Model:()=>eb,Ernie4_5PretrainedModel:()=>$y,EsmForMaskedLM:()=>ib,EsmForSequenceClassification:()=>ab,EsmForTokenClassification:()=>ob,EsmModel:()=>rb,EsmPreTrainedModel:()=>nb,EuroBertForMaskedLM:()=>lb,EuroBertForSequenceClassification:()=>ub,EuroBertForTokenClassification:()=>db,EuroBertModel:()=>cb,EuroBertPreTrainedModel:()=>sb,ExaoneForCausalLM:()=>mb,ExaoneModel:()=>pb,ExaonePreTrainedModel:()=>fb,FalconForCausalLM:()=>_b,FalconH1ForCausalLM:()=>bb,FalconH1Model:()=>yb,FalconH1PreTrainedModel:()=>vb,FalconModel:()=>gb,FalconPreTrainedModel:()=>hb,FastViTForImageClassification:()=>Cb,FastViTModel:()=>Sb,FastViTPreTrainedModel:()=>xb,Florence2ForConditionalGeneration:()=>Tb,Florence2PreTrainedModel:()=>wb,GLPNForDepthEstimation:()=>ax,GLPNModel:()=>ix,GLPNPreTrainedModel:()=>rx,GPT2LMHeadModel:()=>bx,GPT2Model:()=>yx,GPT2PreTrainedModel:()=>vx,GPTBigCodeForCausalLM:()=>cx,GPTBigCodeModel:()=>sx,GPTBigCodePreTrainedModel:()=>ox,GPTJForCausalLM:()=>Cx,GPTJModel:()=>Sx,GPTJPreTrainedModel:()=>xx,GPTNeoForCausalLM:()=>dx,GPTNeoModel:()=>ux,GPTNeoPreTrainedModel:()=>lx,GPTNeoXForCausalLM:()=>mx,GPTNeoXModel:()=>px,GPTNeoXPreTrainedModel:()=>fx,Gemma2ForCausalLM:()=>jb,Gemma2Model:()=>Ab,Gemma2PreTrainedModel:()=>kb,Gemma3ForCausalLM:()=>zb,Gemma3ForConditionalGeneration:()=>Rb,Gemma3Model:()=>Lb,Gemma3PreTrainedModel:()=>Ib,Gemma3nForCausalLM:()=>Hb,Gemma3nForConditionalGeneration:()=>Vb,Gemma3nPreTrainedModel:()=>Bb,Gemma4ForCausalLM:()=>Wb,Gemma4ForConditionalGeneration:()=>Ub,GemmaForCausalLM:()=>Ob,GemmaModel:()=>Db,GemmaPreTrainedModel:()=>Eb,GlmForCausalLM:()=>qb,GlmModel:()=>Kb,GlmMoeDsaForCausalLM:()=>Xb,GlmMoeDsaModel:()=>Yb,GlmMoeDsaPreTrainedModel:()=>Jb,GlmOcrForConditionalGeneration:()=>nx,GlmPreTrainedModel:()=>Gb,GptOssForCausalLM:()=>_x,GptOssModel:()=>gx,GptOssPreTrainedModel:()=>hx,GraniteForCausalLM:()=>Ex,GraniteModel:()=>Tx,GraniteMoeHybridForCausalLM:()=>kx,GraniteMoeHybridModel:()=>Ox,GraniteMoeHybridPreTrainedModel:()=>Dx,GranitePreTrainedModel:()=>wx,GraniteSpeechForConditionalGeneration:()=>Mx,GroundingDinoForObjectDetection:()=>Px,GroundingDinoPreTrainedModel:()=>Nx,GroupViTModel:()=>Ix,GroupViTPreTrainedModel:()=>Fx,HeliumForCausalLM:()=>zx,HeliumModel:()=>Rx,HeliumPreTrainedModel:()=>Lx,HieraForImageClassification:()=>Hx,HieraModel:()=>Vx,HieraPreTrainedModel:()=>Bx,HrmTextForCausalLM:()=>Gx,HrmTextModel:()=>Wx,HrmTextPreTrainedModel:()=>Ux,HubertForCTC:()=>$x,HubertForSequenceClassification:()=>eS,HubertModel:()=>Qx,HubertPreTrainedModel:()=>Zx,HunYuanDenseV1ForCausalLM:()=>rS,HunYuanDenseV1Model:()=>nS,HunYuanDenseV1PreTrainedModel:()=>tS,IJepaForImageClassification:()=>sS,IJepaModel:()=>oS,IJepaPreTrainedModel:()=>aS,Idefics3ForConditionalGeneration:()=>iS,ImageMattingOutput:()=>Bh,JAISLMHeadModel:()=>uS,JAISModel:()=>lS,JAISPreTrainedModel:()=>cS,JinaCLIPModel:()=>fS,JinaCLIPPreTrainedModel:()=>dS,JinaCLIPTextModel:()=>pS,JinaCLIPVisionModel:()=>mS,Lfm2ForCausalLM:()=>_S,Lfm2Model:()=>gS,Lfm2MoeForCausalLM:()=>xS,Lfm2MoeModel:()=>bS,Lfm2MoePreTrainedModel:()=>yS,Lfm2PreTrainedModel:()=>hS,Lfm2VlForConditionalGeneration:()=>SS,LightOnOcrForConditionalGeneration:()=>vS,LiteWhisperForConditionalGeneration:()=>zO,Llama4ForCausalLM:()=>DS,Llama4PreTrainedModel:()=>ES,LlamaForCausalLM:()=>TS,LlamaModel:()=>wS,LlamaPreTrainedModel:()=>CS,LlavaForConditionalGeneration:()=>Nb,LlavaOnevisionForConditionalGeneration:()=>Nb,LlavaPreTrainedModel:()=>Mb,LlavaQwen2ForCausalLM:()=>Fb,LongT5ForConditionalGeneration:()=>AS,LongT5Model:()=>kS,LongT5PreTrainedModel:()=>OS,M2M100ForConditionalGeneration:()=>NS,M2M100Model:()=>MS,M2M100PreTrainedModel:()=>jS,MBartForCausalLM:()=>WS,MBartForConditionalGeneration:()=>HS,MBartForSequenceClassification:()=>US,MBartModel:()=>VS,MBartPreTrainedModel:()=>BS,MPNetForMaskedLM:()=>ow,MPNetForQuestionAnswering:()=>lw,MPNetForSequenceClassification:()=>sw,MPNetForTokenClassification:()=>cw,MPNetModel:()=>aw,MPNetPreTrainedModel:()=>iw,MT5ForConditionalGeneration:()=>hw,MT5Model:()=>mw,MT5PreTrainedModel:()=>pw,MarianMTModel:()=>IS,MarianModel:()=>FS,MarianPreTrainedModel:()=>PS,MaskFormerForInstanceSegmentation:()=>zS,MaskFormerModel:()=>RS,MaskFormerPreTrainedModel:()=>LS,MaskedLMOutput:()=>Fh,Metric3DForDepthEstimation:()=>KS,Metric3DPreTrainedModel:()=>GS,Metric3Dv2ForDepthEstimation:()=>JS,Metric3Dv2PreTrainedModel:()=>qS,MgpstrForSceneTextRecognition:()=>ZS,MgpstrModelOutput:()=>YS,MgpstrPreTrainedModel:()=>XS,MimiDecoderModel:()=>rC,MimiDecoderOutput:()=>$S,MimiEncoderModel:()=>nC,MimiEncoderOutput:()=>QS,MimiModel:()=>tC,MimiPreTrainedModel:()=>eC,Ministral3ForCausalLM:()=>lC,Ministral3Model:()=>cC,Ministral3PreTrainedModel:()=>sC,MinistralForCausalLM:()=>oC,MinistralModel:()=>aC,MinistralPreTrainedModel:()=>iC,Mistral3ForConditionalGeneration:()=>pC,Mistral4ForCausalLM:()=>gC,Mistral4Model:()=>hC,Mistral4PreTrainedModel:()=>mC,MistralForCausalLM:()=>fC,MistralModel:()=>dC,MistralPreTrainedModel:()=>uC,MobileBertForMaskedLM:()=>yC,MobileBertForQuestionAnswering:()=>xC,MobileBertForSequenceClassification:()=>bC,MobileBertModel:()=>vC,MobileBertPreTrainedModel:()=>_C,MobileLLMForCausalLM:()=>wC,MobileLLMModel:()=>CC,MobileLLMPreTrainedModel:()=>SC,MobileNetV1ForImageClassification:()=>DC,MobileNetV1ForSemanticSegmentation:()=>OC,MobileNetV1Model:()=>EC,MobileNetV1PreTrainedModel:()=>TC,MobileNetV2ForImageClassification:()=>jC,MobileNetV2ForSemanticSegmentation:()=>MC,MobileNetV2Model:()=>AC,MobileNetV2PreTrainedModel:()=>kC,MobileNetV3ForImageClassification:()=>FC,MobileNetV3ForSemanticSegmentation:()=>IC,MobileNetV3Model:()=>PC,MobileNetV3PreTrainedModel:()=>NC,MobileNetV4ForImageClassification:()=>zC,MobileNetV4ForSemanticSegmentation:()=>BC,MobileNetV4Model:()=>RC,MobileNetV4PreTrainedModel:()=>LC,MobileViTForImageClassification:()=>UC,MobileViTModel:()=>HC,MobileViTPreTrainedModel:()=>VC,MobileViTV2ForImageClassification:()=>KC,MobileViTV2Model:()=>GC,MobileViTV2PreTrainedModel:()=>WC,ModelOutput:()=>Mh,ModernBertDecoderForCausalLM:()=>ew,ModernBertDecoderModel:()=>$C,ModernBertDecoderPreTrainedModel:()=>QC,ModernBertForMaskedLM:()=>YC,ModernBertForSequenceClassification:()=>XC,ModernBertForTokenClassification:()=>ZC,ModernBertModel:()=>JC,ModernBertPreTrainedModel:()=>qC,Moondream1ForConditionalGeneration:()=>Pb,MoonshineForConditionalGeneration:()=>rw,MoonshineModel:()=>nw,MoonshinePreTrainedModel:()=>tw,MptForCausalLM:()=>fw,MptModel:()=>dw,MptPreTrainedModel:()=>uw,MultiModalityCausalLM:()=>_w,MultiModalityPreTrainedModel:()=>gw,MusicgenForCausalLM:()=>bw,MusicgenForConditionalGeneration:()=>xw,MusicgenModel:()=>yw,MusicgenPreTrainedModel:()=>vw,NanoChatForCausalLM:()=>ww,NanoChatModel:()=>Cw,NanoChatPreTrainedModel:()=>Sw,NemotronHForCausalLM:()=>Dw,NemotronHModel:()=>Ew,NemotronHPreTrainedModel:()=>Tw,NeoBertForMaskedLM:()=>Aw,NeoBertForQuestionAnswering:()=>Nw,NeoBertForSequenceClassification:()=>jw,NeoBertForTokenClassification:()=>Mw,NeoBertModel:()=>kw,NeoBertPreTrainedModel:()=>Ow,NomicBertModel:()=>Fw,NomicBertPreTrainedModel:()=>Pw,OPTForCausalLM:()=>nT,OPTModel:()=>tT,OPTPreTrainedModel:()=>eT,Olmo2ForCausalLM:()=>Vw,Olmo2Model:()=>Bw,Olmo2PreTrainedModel:()=>zw,Olmo3ForCausalLM:()=>Ww,Olmo3Model:()=>Uw,Olmo3PreTrainedModel:()=>Hw,OlmoForCausalLM:()=>Rw,OlmoHybridForCausalLM:()=>qw,OlmoHybridModel:()=>Kw,OlmoHybridPreTrainedModel:()=>Gw,OlmoModel:()=>Lw,OlmoPreTrainedModel:()=>Iw,OpenAIPrivacyFilterForTokenClassification:()=>Xw,OpenAIPrivacyFilterModel:()=>Yw,OpenAIPrivacyFilterPreTrainedModel:()=>Jw,OpenELMForCausalLM:()=>$w,OpenELMModel:()=>Qw,OpenELMPreTrainedModel:()=>Zw,OwlViTForObjectDetection:()=>cT,OwlViTModel:()=>sT,OwlViTPreTrainedModel:()=>oT,Owlv2ForObjectDetection:()=>aT,Owlv2Model:()=>iT,Owlv2PreTrainedModel:()=>rT,PaliGemmaForConditionalGeneration:()=>lT,ParakeetForCTC:()=>dT,ParakeetPreTrainedModel:()=>uT,PatchTSMixerForPrediction:()=>mT,PatchTSMixerModel:()=>pT,PatchTSMixerPreTrainedModel:()=>fT,PatchTSTForPrediction:()=>_T,PatchTSTModel:()=>gT,PatchTSTPreTrainedModel:()=>hT,Phi3ForCausalLM:()=>CT,Phi3Model:()=>ST,Phi3PreTrainedModel:()=>xT,Phi3VForCausalLM:()=>TT,Phi3VPreTrainedModel:()=>wT,PhiForCausalLM:()=>bT,PhiModel:()=>yT,PhiPreTrainedModel:()=>vT,PreTrainedModel:()=>Z,PvtForImageClassification:()=>OT,PvtModel:()=>DT,PvtPreTrainedModel:()=>ET,PyAnnoteForAudioFrameClassification:()=>jT,PyAnnoteModel:()=>AT,PyAnnotePreTrainedModel:()=>kT,QuestionAnsweringModelOutput:()=>Ih,Qwen2ForCausalLM:()=>PT,Qwen2Model:()=>NT,Qwen2MoeForCausalLM:()=>LT,Qwen2MoeModel:()=>IT,Qwen2MoePreTrainedModel:()=>FT,Qwen2PreTrainedModel:()=>MT,Qwen2VLForCausalLM:()=>$b,Qwen2VLForConditionalGeneration:()=>Qb,Qwen2VLPreTrainedModel:()=>Zb,Qwen2_5_VLForCausalLM:()=>tx,Qwen2_5_VLForConditionalGeneration:()=>ex,Qwen3ForCausalLM:()=>BT,Qwen3Model:()=>zT,Qwen3MoeForCausalLM:()=>UT,Qwen3MoeModel:()=>HT,Qwen3MoePreTrainedModel:()=>VT,Qwen3NextForCausalLM:()=>KT,Qwen3NextModel:()=>GT,Qwen3NextPreTrainedModel:()=>WT,Qwen3PreTrainedModel:()=>RT,Qwen3VLForCausalLM:()=>JT,Qwen3VLForConditionalGeneration:()=>qT,Qwen3VLMoeForCausalLM:()=>XT,Qwen3VLMoeForConditionalGeneration:()=>YT,Qwen3_5ForCausalLM:()=>QT,Qwen3_5ForConditionalGeneration:()=>ZT,Qwen3_5MoeForCausalLM:()=>eE,Qwen3_5MoeForConditionalGeneration:()=>$T,RFDetrForObjectDetection:()=>oE,RFDetrModel:()=>aE,RFDetrObjectDetectionOutput:()=>sE,RFDetrPreTrainedModel:()=>iE,RTDetrForObjectDetection:()=>Nv,RTDetrModel:()=>Mv,RTDetrObjectDetectionOutput:()=>Pv,RTDetrPreTrainedModel:()=>jv,RTDetrV2ForObjectDetection:()=>SE,RTDetrV2Model:()=>xE,RTDetrV2ObjectDetectionOutput:()=>CE,RTDetrV2PreTrainedModel:()=>bE,ResNetForImageClassification:()=>rE,ResNetModel:()=>nE,ResNetPreTrainedModel:()=>tE,RoFormerForMaskedLM:()=>gE,RoFormerForQuestionAnswering:()=>yE,RoFormerForSequenceClassification:()=>_E,RoFormerForTokenClassification:()=>vE,RoFormerModel:()=>hE,RoFormerPreTrainedModel:()=>mE,RobertaForMaskedLM:()=>uE,RobertaForQuestionAnswering:()=>pE,RobertaForSequenceClassification:()=>dE,RobertaForTokenClassification:()=>fE,RobertaModel:()=>lE,RobertaPreTrainedModel:()=>cE,Sam2ImageSegmentationOutput:()=>DE,Sam2Model:()=>kE,Sam2PreTrainedModel:()=>OE,Sam3TrackerModel:()=>jE,SamImageSegmentationOutput:()=>wE,SamModel:()=>EE,SamPreTrainedModel:()=>TE,SapiensForDepthEstimation:()=>PE,SapiensForNormalEstimation:()=>FE,SapiensForSemanticSegmentation:()=>NE,SapiensPreTrainedModel:()=>ME,SegformerForImageClassification:()=>RE,SegformerForSemanticSegmentation:()=>zE,SegformerModel:()=>LE,SegformerPreTrainedModel:()=>IE,Seq2SeqLMOutput:()=>zh,SequenceClassifierOutput:()=>Y,SiglipModel:()=>VE,SiglipPreTrainedModel:()=>BE,SiglipTextModel:()=>HE,SiglipVisionModel:()=>UE,SmolLM3ForCausalLM:()=>KE,SmolLM3Model:()=>GE,SmolLM3PreTrainedModel:()=>WE,SmolVLMForConditionalGeneration:()=>qE,SnacDecoderModel:()=>ZE,SnacEncoderModel:()=>XE,SnacModel:()=>YE,SnacPreTrainedModel:()=>JE,SolarOpenForCausalLM:()=>eD,SolarOpenModel:()=>$E,SolarOpenPreTrainedModel:()=>QE,SpeechT5ForSpeechToText:()=>rD,SpeechT5ForTextToSpeech:()=>iD,SpeechT5HifiGan:()=>aD,SpeechT5Model:()=>nD,SpeechT5PreTrainedModel:()=>tD,SqueezeBertForMaskedLM:()=>cD,SqueezeBertForQuestionAnswering:()=>uD,SqueezeBertForSequenceClassification:()=>lD,SqueezeBertModel:()=>sD,SqueezeBertPreTrainedModel:()=>oD,StableLmForCausalLM:()=>pD,StableLmModel:()=>fD,StableLmPreTrainedModel:()=>dD,Starcoder2ForCausalLM:()=>gD,Starcoder2Model:()=>hD,Starcoder2PreTrainedModel:()=>mD,StyleTextToSpeech2Model:()=>vD,StyleTextToSpeech2PreTrainedModel:()=>_D,SupertonicForConditionalGeneration:()=>bD,SupertonicPreTrainedModel:()=>yD,Swin2SRForImageSuperResolution:()=>DD,Swin2SRModel:()=>ED,Swin2SRPreTrainedModel:()=>TD,SwinForImageClassification:()=>CD,SwinForSemanticSegmentation:()=>wD,SwinModel:()=>SD,SwinPreTrainedModel:()=>xD,T5ForConditionalGeneration:()=>AD,T5Model:()=>kD,T5PreTrainedModel:()=>OD,TableTransformerForObjectDetection:()=>ND,TableTransformerModel:()=>MD,TableTransformerObjectDetectionOutput:()=>PD,TableTransformerPreTrainedModel:()=>jD,TokenClassifierOutput:()=>Ph,TrOCRForCausalLM:()=>ID,TrOCRPreTrainedModel:()=>FD,UltravoxModel:()=>jx,UltravoxPreTrainedModel:()=>Ax,UniSpeechForCTC:()=>zD,UniSpeechForSequenceClassification:()=>BD,UniSpeechModel:()=>RD,UniSpeechPreTrainedModel:()=>LD,UniSpeechSatForAudioFrameClassification:()=>GD,UniSpeechSatForCTC:()=>UD,UniSpeechSatForSequenceClassification:()=>WD,UniSpeechSatModel:()=>HD,UniSpeechSatPreTrainedModel:()=>VD,VaultGemmaForCausalLM:()=>JD,VaultGemmaModel:()=>qD,VaultGemmaPreTrainedModel:()=>KD,ViTForImageClassification:()=>QD,ViTMAEModel:()=>eO,ViTMAEPreTrainedModel:()=>$D,ViTMSNForImageClassification:()=>rO,ViTMSNModel:()=>nO,ViTMSNPreTrainedModel:()=>tO,ViTModel:()=>ZD,ViTPreTrainedModel:()=>XD,VisionEncoderDecoderModel:()=>YD,VitMatteForImageMatting:()=>aO,VitMattePreTrainedModel:()=>iO,VitPoseForPoseEstimation:()=>sO,VitPosePreTrainedModel:()=>oO,VitsModel:()=>uO,VitsModelOutput:()=>cO,VitsPreTrainedModel:()=>lO,VoxtralForConditionalGeneration:()=>dO,VoxtralRealtimeForConditionalGeneration:()=>xO,VoxtralRealtimePreTrainedModel:()=>bO,Wav2Vec2BertForCTC:()=>wO,Wav2Vec2BertForSequenceClassification:()=>TO,Wav2Vec2BertModel:()=>CO,Wav2Vec2BertPreTrainedModel:()=>SO,Wav2Vec2ForAudioFrameClassification:()=>Xx,Wav2Vec2ForCTC:()=>Jx,Wav2Vec2ForSequenceClassification:()=>Yx,Wav2Vec2Model:()=>qx,Wav2Vec2PreTrainedModel:()=>Kx,WavLMForAudioFrameClassification:()=>MO,WavLMForCTC:()=>kO,WavLMForSequenceClassification:()=>AO,WavLMForXVector:()=>jO,WavLMModel:()=>OO,WavLMPreTrainedModel:()=>DO,WeSpeakerResNetModel:()=>PO,WeSpeakerResNetPreTrainedModel:()=>NO,WhisperForConditionalGeneration:()=>RO,WhisperModel:()=>LO,WhisperPreTrainedModel:()=>IO,XLMForQuestionAnswering:()=>GO,XLMForSequenceClassification:()=>UO,XLMForTokenClassification:()=>WO,XLMModel:()=>VO,XLMPreTrainedModel:()=>BO,XLMRobertaForMaskedLM:()=>JO,XLMRobertaForQuestionAnswering:()=>ZO,XLMRobertaForSequenceClassification:()=>YO,XLMRobertaForTokenClassification:()=>XO,XLMRobertaModel:()=>qO,XLMRobertaPreTrainedModel:()=>KO,XLMWithLMHeadModel:()=>HO,XVectorOutput:()=>EO,YolosForObjectDetection:()=>ek,YolosModel:()=>$O,YolosObjectDetectionOutput:()=>tk,YolosPreTrainedModel:()=>QO,YoutuForCausalLM:()=>ik,YoutuModel:()=>rk,YoutuPreTrainedModel:()=>nk,ZayaForCausalLM:()=>sk,ZayaModel:()=>ok,ZayaPreTrainedModel:()=>ak});var Yg=class extends Z{},Xg=class extends Yg{},Zg=class extends Yg{async _call(e){return new Y(await super._call(e))}},Qg=class extends Yg{async _call(e){return new Ih(await super._call(e))}},$g=class extends Yg{async _call(e){return new Fh(await super._call(e))}},e_=class extends Z{},t_=class extends e_{},n_=class extends e_{},r_=class extends Z{},i_=class extends r_{},a_=class extends r_{},o_=class extends Z{},s_=class extends o_{},c_=class extends o_{},l_=class extends Z{},u_=class extends l_{},d_=class extends l_{},f_=class extends Z{},p_=class extends f_{},m_=class extends f_{},h_=class extends f_{async _call(e){return new Y(await super._call(e))}},g_=class extends Z{},__=class extends g_{},v_=class extends g_{async _call(e){return new Y(await super._call(e))}},y_=class extends Z{},b_=class extends y_{},x_=class extends y_{async _call(e){return new Fh(await super._call(e))}},S_=class extends y_{async _call(e){return new Y(await super._call(e))}},C_=class extends y_{async _call(e){return new Ph(await super._call(e))}},w_=class extends y_{async _call(e){return new Ih(await super._call(e))}},T_=class extends Z{},E_=class extends T_{},D_=class extends T_{},O_=class extends Z{},k_=class extends O_{},A_=class extends O_{},j_=class extends Z{},M_=class extends j_{},N_=class extends j_{},P_=class extends Z{},F_=class extends P_{},I_=class extends P_{async _call(e){return new Fh(await super._call(e))}},L_=class extends P_{async _call(e){return new Y(await super._call(e))}},R_=class extends P_{async _call(e){return new Ph(await super._call(e))}},z_=class extends P_{async _call(e){return new Ih(await super._call(e))}},B_=4299n,V_=6561n,H_=class extends Z{forward_params=[`input_ids`,`inputs_embeds`,`attention_mask`,`position_ids`,`audio_values`,`exaggeration`,`audio_features`,`audio_tokens`,`speaker_embeddings`,`speaker_features`,`past_key_values`];main_input_name=`input_ids`;_return_dict_in_generate_keys=[`audio_tokens`,`speaker_embeddings`,`speaker_features`]},U_=class extends H_{async encode_speech(e){return J(this.sessions.speech_encoder,{audio_values:e})}async forward({input_ids:e=null,attention_mask:t=null,audio_values:n=null,exaggeration:r=null,position_ids:i=null,inputs_embeds:a=null,past_key_values:o=null,generation_config:s=null,logits_processor:c=null,num_logits_to_keep:l=null,audio_features:u=null,audio_tokens:d=null,speaker_embeddings:f=null,speaker_features:p=null,...m}){let h;if(!a){let s=this.sessions.embed_tokens.inputNames,c={input_ids:e};if(s.includes(`exaggeration`)){if(!(r instanceof H)){let t=e.dims[0];if(r==null)r=hu([t],.5);else if(typeof r==`number`)r=hu([t],r);else if(Array.isArray(r))r=new H(`float32`,r,[t]);else throw Error("Unsupported type for `exaggeration` input")}c.exaggeration=r}if(s.includes(`position_ids`)&&(c.position_ids=i),{inputs_embeds:a}=await J(this.sessions.embed_tokens,c),u&&d&&f&&p&&(h={audio_features:u,audio_tokens:d,speaker_embeddings:f,speaker_features:p}),h||n)h??=await this.encode_speech(n),a=U([h.audio_features,a],1),t=_u([a.dims[0],a.dims[1]]);else{let e=a.dims[1];if(!o||e!==1)throw Error(`Incorrect state encountered during generation.`);let n=o.get_seq_length();t=_u([a.dims[0],n+e])}}return{...await Fg(this,{inputs_embeds:a,past_key_values:o,attention_mask:t,generation_config:s,logits_processor:c,num_logits_to_keep:l},!1),...h}}prepare_inputs_for_generation(e,t,n){return!t.position_ids&&this.sessions.embed_tokens.inputNames.includes(`position_ids`)&&(t.position_ids=t.input_ids.dims[1]===1?new H(`int64`,Array.from({length:e.length},(t,n)=>e[n].length-e[n].findLastIndex(e=>e==V_)-1),[e.length,1]):new H(`int64`,t.input_ids.tolist().map(e=>{let t=0;return e.map(e=>e>=V_?0:t++)}).flat(),t.input_ids.dims)),t.input_ids.dims[1]===1&&(delete t.audio_values,delete t.audio_features,delete t.audio_tokens,delete t.speaker_embeddings,delete t.speaker_features),Vg(this,e,t,n)}async generate(e){let t=e.past_key_values,{sequences:n,audio_tokens:r,speaker_embeddings:i,speaker_features:a,past_key_values:o}=await super.generate({...e,return_dict_in_generate:!0});try{let t=n.slice(null,[e.input_ids.dims[1],-1]),o=U([r,t,hu([t.dims[0],3],B_)],1),{waveform:s}=await J(this.sessions.conditional_decoder,{speech_tokens:o,speaker_features:a,speaker_embeddings:i});return s}finally{o!==t&&await o?.dispose()}}},W_=class extends Z{},G_=class extends W_{},K_=class extends Z{},q_=class extends K_{},J_=class extends Z{},Y_=class extends J_{},X_=class extends J_{static async from_pretrained(e,t={}){return super.from_pretrained(e,{...t,model_file_name:t.model_file_name??`text_model`})}},Z_=class extends J_{static async from_pretrained(e,t={}){return super.from_pretrained(e,{...t,model_file_name:t.model_file_name??`audio_model`})}},Q_=class extends Z{},$_=class extends Q_{},ev=class extends Q_{static async from_pretrained(e,t={}){return super.from_pretrained(e,{...t,model_file_name:t.model_file_name??`text_model`})}},tv=class extends Q_{static async from_pretrained(e,t={}){return super.from_pretrained(e,{...t,model_file_name:t.model_file_name??`text_model`})}},nv=class extends Q_{static async from_pretrained(e,t={}){return super.from_pretrained(e,{...t,model_file_name:t.model_file_name??`vision_model`})}},rv=class extends Q_{static async from_pretrained(e,t={}){return super.from_pretrained(e,{...t,model_file_name:t.model_file_name??`vision_model`})}},iv=class extends Z{},av=class extends iv{},ov=class extends iv{},sv=class extends Z{},cv=class extends sv{},lv=class extends sv{},uv=class extends Z{},dv=class extends uv{},fv=class extends uv{},pv=class extends Z{},mv=class extends pv{},hv=class extends pv{},gv=class extends Z{requires_attention_mask=!1;main_input_name=`input_features`;forward_params=[`input_features`,`decoder_input_ids`,`decoder_attention_mask`,`past_key_values`]},_v=class extends gv{},vv=class extends gv{},yv=class extends Z{},bv=class extends yv{},xv=class extends yv{async _call(e){return new Fh(await super._call(e))}},Sv=class extends yv{async _call(e){return new Y(await super._call(e))}},Cv=class extends yv{async _call(e){return new Ph(await super._call(e))}},wv=class extends yv{async _call(e){return new Ih(await super._call(e))}},Tv=class extends Z{},Ev=class extends Tv{},Dv=class extends Tv{async _call(e){return new Y(await super._call(e))}},Ov=class extends Z{},kv=class extends Ov{},Av=class extends Ov{async _call(e){return new Y(await super._call(e))}},jv=class extends Z{},Mv=class extends jv{},Nv=class extends jv{async _call(e){return new Pv(await super._call(e))}},Pv=class extends Mh{constructor({logits:e,pred_boxes:t}){super(),this.logits=e,this.pred_boxes=t}},Fv=class extends Z{},Iv=class extends Fv{},Lv=class extends Fv{async _call(e){return new Pv(await super._call(e))}},Rv=class extends Mh{constructor({audio_codes:e}){super(),this.audio_codes=e}},zv=class extends Mh{constructor({audio_values:e}){super(),this.audio_values=e}},Bv=class extends Z{main_input_name=`input_values`;forward_params=[`input_values`]},Vv=class extends Bv{async encode(e){return new Rv(await J(this.sessions.encoder_model,e))}async decode(e){return new zv(await J(this.sessions.decoder_model,e))}},Hv=class extends Bv{static async from_pretrained(e,t={}){return super.from_pretrained(e,{...t,model_file_name:t.model_file_name??`encoder_model`})}},Uv=class extends Bv{static async from_pretrained(e,t={}){return super.from_pretrained(e,{...t,model_file_name:t.model_file_name??`decoder_model`})}},Wv=class extends Z{},Gv=class extends Wv{},Kv=class extends Wv{async _call(e){return new Fh(await super._call(e))}},qv=class extends Wv{async _call(e){return new Y(await super._call(e))}},Jv=class extends Wv{async _call(e){return new Ph(await super._call(e))}},Yv=class extends Wv{async _call(e){return new Ih(await super._call(e))}},Xv=class extends Z{},Zv=class extends Xv{},Qv=class extends Xv{},$v=class extends Z{},ey=class extends $v{},ty=class extends $v{},ny=class extends Z{},ry=class extends ny{},iy=class extends ny{async _call(e){return new Fh(await super._call(e))}},ay=class extends ny{async _call(e){return new Y(await super._call(e))}},oy=class extends ny{async _call(e){return new Ph(await super._call(e))}},sy=class extends ny{async _call(e){return new Ih(await super._call(e))}},cy=class extends Z{},ly=class extends cy{},uy=class extends Z{},dy=class extends uy{},fy=class extends uy{async _call(e){return new Y(await super._call(e))}},py=class extends Z{},my=class extends py{},hy=class extends Z{},gy=class extends hy{},_y=class extends Z{},vy=class extends _y{},yy=class extends _y{async _call(e){return new xy(await super._call(e))}},by=class extends _y{async _call(e){return new Sy(await super._call(e))}},xy=class extends Mh{constructor({logits:e,pred_boxes:t}){super(),this.logits=e,this.pred_boxes=t}},Sy=class extends Mh{constructor({logits:e,pred_boxes:t,pred_masks:n}){super(),this.logits=e,this.pred_boxes=t,this.pred_masks=n}},Cy=class extends Z{},wy=class extends Cy{},Ty=class extends Cy{async _call(e){return new Y(await super._call(e))}},Ey=class extends Z{},Dy=class extends Ey{},Oy=class extends Ey{async _call(e){return new Y(await super._call(e))}},ky=class extends Z{},Ay=class extends ky{},jy=class extends Z{},My=class extends jy{},Ny=class extends Z{},Py=class extends Ny{},Fy=class extends Ny{async _call(e){return new Y(await super._call(e))}},Iy=class extends Ny{async _call(e){return new Ph(await super._call(e))}},Ly=class extends Ny{async _call(e){return new Ih(await super._call(e))}},Ry=class extends Ny{async _call(e){return new Fh(await super._call(e))}},zy=class extends Z{},By=class extends zy{},Vy=class extends Z{},Hy=class extends Vy{},Uy=class extends Vy{},Wy=class extends Z{},Gy=class extends Wy{},Ky=class extends Wy{async _call(e){return new Y(await super._call(e))}},qy=class extends Z{},Jy=class extends qy{},Yy=class extends qy{async _call(e){return new Fh(await super._call(e))}},Xy=class extends qy{async _call(e){return new Y(await super._call(e))}},Zy=class extends qy{async _call(e){return new Ph(await super._call(e))}},Qy=class extends qy{async _call(e){return new Ih(await super._call(e))}},$y=class extends Z{},eb=class extends $y{},tb=class extends $y{},nb=class extends Z{},rb=class extends nb{},ib=class extends nb{async _call(e){return new Fh(await super._call(e))}},ab=class extends nb{async _call(e){return new Y(await super._call(e))}},ob=class extends nb{async _call(e){return new Ph(await super._call(e))}},sb=class extends Z{},cb=class extends sb{},lb=class extends sb{async _call(e){return new Fh(await super._call(e))}},ub=class extends sb{async _call(e){return new Y(await super._call(e))}},db=class extends sb{async _call(e){return new Ph(await super._call(e))}},fb=class extends Z{},pb=class extends fb{},mb=class extends fb{},hb=class extends Z{},gb=class extends hb{},_b=class extends hb{},vb=class extends Z{},yb=class extends vb{},bb=class extends vb{},xb=class extends Z{},Sb=class extends xb{},Cb=class extends xb{async _call(e){return new Y(await super._call(e))}},wb=class extends Z{forward_params=[`input_ids`,`inputs_embeds`,`attention_mask`,`pixel_values`,`encoder_outputs`,`decoder_input_ids`,`decoder_inputs_embeds`,`decoder_attention_mask`,`past_key_values`];main_input_name=`inputs_embeds`},Tb=class extends wb{_merge_input_ids_with_image_features({inputs_embeds:e,image_features:t,input_ids:n,attention_mask:r}){return{inputs_embeds:U([t,e],1),attention_mask:U([_u(t.dims.slice(0,2)),r],1)}}async _prepare_inputs_embeds({input_ids:e,pixel_values:t,inputs_embeds:n,attention_mask:r}){if(!e&&!t)throw Error("Either `input_ids` or `pixel_values` should be provided.");let i,a;return e&&(i=await this.encode_text({input_ids:e})),t&&(a=await this.encode_image({pixel_values:t})),i&&a?{inputs_embeds:n,attention_mask:r}=this._merge_input_ids_with_image_features({inputs_embeds:i,image_features:a,input_ids:e,attention_mask:r}):n=i||a,{inputs_embeds:n,attention_mask:r}}async forward({input_ids:e,pixel_values:t,attention_mask:n,decoder_input_ids:r,decoder_attention_mask:i,encoder_outputs:a,past_key_values:o,inputs_embeds:s,decoder_inputs_embeds:c,num_logits_to_keep:l=null}){if(s||({inputs_embeds:s,attention_mask:n}=await this._prepare_inputs_embeds({input_ids:e,pixel_values:t,inputs_embeds:s,attention_mask:n})),!a){let{last_hidden_state:e}=await Og(this,{inputs_embeds:s,attention_mask:n});a=e}if(!c){if(!r)throw Error("Either `decoder_input_ids` or `decoder_inputs_embeds` should be provided.");c=await this.encode_text({input_ids:r})}let u={inputs_embeds:c,attention_mask:i,encoder_attention_mask:n,encoder_hidden_states:a,past_key_values:o,num_logits_to_keep:l};return await Fg(this,u,!0)}},Eb=class extends Z{},Db=class extends Eb{},Ob=class extends Eb{},kb=class extends Z{},Ab=class extends kb{},jb=class extends kb{},Mb=class extends Z{forward_params=[`input_ids`,`attention_mask`,`pixel_values`,`position_ids`,`past_key_values`]},Nb=class extends Mb{_merge_input_ids_with_image_features(e){let t=e.image_features.dims.at(-1),n=e.image_features.view(-1,t);return Gg({image_token_id:this.config.image_token_index??this.config.image_token_id,...e,image_features:n})}},Pb=class extends Nb{},Fb=class extends Nb{},Ib=class extends Z{},Lb=class extends Ib{},Rb=class extends Nb{},zb=class extends Rb{},Bb=class extends Z{forward_params=[`input_ids`,`attention_mask`,`inputs_embeds`,`per_layer_inputs`,`position_ids`,`pixel_values`,`input_features`,`input_features_mask`,`past_key_values`]},Vb=class extends Bb{async forward({input_ids:e=null,attention_mask:t=null,pixel_values:n=null,input_features:r=null,input_features_mask:i=null,position_ids:a=null,inputs_embeds:o=null,per_layer_inputs:s=null,past_key_values:c=null,generation_config:l=null,logits_processor:u=null,num_logits_to_keep:d=null,...f}){if((!o||!s)&&({inputs_embeds:o,per_layer_inputs:s}=await J(this.sessions.embed_tokens,{input_ids:e}),e.dims[1]!==1)){if(n){let{image_features:r}=await this._encode_vision({pixel_values:n,...f});({inputs_embeds:o,attention_mask:t}=this._merge_input_ids_with_image_features({image_features:r,inputs_embeds:o,input_ids:e,attention_mask:t}))}if(r){let{audio_features:n}=await J(this.sessions.audio_encoder,{input_features:r,input_features_mask:i});({inputs_embeds:o,attention_mask:t}=this._merge_input_ids_with_audio_features({audio_features:n,inputs_embeds:o,input_ids:e,attention_mask:t}))}}return await Fg(this,{inputs_embeds:o,per_layer_inputs:s,past_key_values:c,attention_mask:t,position_ids:a,generation_config:l,logits_processor:u,num_logits_to_keep:d},!0)}_encode_vision(e){return J(this.sessions.vision_encoder,{pixel_values:e.pixel_values})}_merge_input_ids_with_image_features(e){let t=e.image_features.dims.at(-1),n=e.image_features.view(-1,t);return Gg({image_token_id:this.config.image_token_id,...e,image_features:n})}_merge_input_ids_with_audio_features(e){let t=e.audio_features.dims.at(-1),n=e.audio_features.view(-1,t);return Kg({audio_token_id:this.config.audio_token_id,...e,audio_features:n})}},Hb=class extends Vb{},Ub=class extends Vb{forward_params=[`input_ids`,`attention_mask`,`inputs_embeds`,`per_layer_inputs`,`position_ids`,`pixel_values`,`image_position_ids`,`input_features`,`input_features_mask`,`past_key_values`];_encode_vision(e){return J(this.sessions.vision_encoder,{pixel_values:e.pixel_values,pixel_position_ids:e.image_position_ids})}},Wb=class extends Ub{},Gb=class extends Z{},Kb=class extends Gb{},qb=class extends Gb{},Jb=class extends Z{},Yb=class extends Jb{},Xb=class extends Jb{},Zb=class extends Z{forward_params=[`input_ids`,`attention_mask`,`position_ids`,`past_key_values`,`pixel_values`,`image_grid_thw`]},Qb=class extends Zb{image_grid_thw_name=`grid_thw`;_get_text_only_rope_index(e,t){if(t){let{data:e,dims:n}=zg(t),r=BigInt64Array.from({length:3*e.length},(t,n)=>e[n%e.length]),i=Array.from({length:n[0]},(t,r)=>sl(e.subarray(n[1]*r,n[1]*(r+1)))[0]+1n+BigInt(n[1]));return[new H(`int64`,r,[3,...n]),new H(`int64`,i,[i.length,1])]}{let[t,n]=e.dims;return[new H(`int64`,BigInt64Array.from({length:3*t*n},(e,r)=>BigInt(Math.floor(r%n/t))),[3,...e.dims]),yu([t,1])]}}_reorder_and_write_positions(e,t,n,r){let i=e.reduce((e,t)=>e+t.length,0),a=Array(i),o=0;for(let t=0;t<3;++t)for(let n of e){let e=n.length/3;for(let r=t*e;r<(t+1)*e;++r)a[o++]=n[r]}let s=0;for(let e=0;e(t==s&&e.push(n),e),[]).map(e=>c[e+1]),u=l.filter(e=>e==a).length,d=l.filter(e=>e==o).length,f=[],p=0,m=u,h=d;for(let e=0;et>p&&e==a),s=c.findIndex((e,t)=>t>p&&e==o),l=m>0&&e!==-1?e:c.length+1,u=h>0&&s!==-1?s:c.length+1,d,g,_,v;l0?sl(f.at(-1))[0]+1:0;f.push(Array.from({length:3*S},(e,t)=>C+t%S));let ee=S+C,te=y*b*x,ne=Array.from({length:te},(e,t)=>ee+Math.floor(t/(b*x))),re=Array.from({length:te},(e,t)=>ee+Math.floor(t/x)%b),ie=Array.from({length:te},(e,t)=>ee+t%x);f.push([ne,re,ie].flat()),p=d+te}if(p0?sl(f.at(-1))[0]+1:0,t=c.length-p;f.push(Array.from({length:3*t},(n,r)=>e+r%t))}return f}get_rope_index(e,t,n,r){let{vision_config:i}=this.config,a=i.spatial_merge_size??2;if(t||n){let i=e.tolist();r||=vu(e);let o=r.tolist(),s=Array.from({length:3},()=>Array.from({length:e.dims[0]},()=>Array.from({length:e.dims[1]},()=>0))),c=t?t.tolist():[],l=n?n.tolist():[],u={image_index:0,video_index:0},d=[];for(let e=0;eo[e][n]==1),n=this._get_multimodal_rope_positions({filtered_ids:t,image_grid_thw_list:c,video_grid_thw_list:l,spatial_merge_size:a,state:u}),r=this._reorder_and_write_positions(n,o[e],s,e);d.push(sl(r)[0]+1-i[e].length)}return[new H(`int64`,s.flat(1/0),[3,e.dims[0],e.dims[1]]),new H(`int64`,d,[d.length,1])]}return this._get_text_only_rope_index(e,r)}async encode_image({pixel_values:e,image_grid_thw:t}){return(await J(this.sessions.vision_encoder,{pixel_values:e,[this.image_grid_thw_name]:t})).image_features}_merge_input_ids_with_image_features(e){return Gg({image_token_id:this.config.image_token_id,...e})}prepare_inputs_for_generation(e,t,n){if(Pg(this,t,1n),!t.attention_mask||t.position_ids||!(this.sessions.decoder_model_merged??this.sessions.model).inputNames.includes(`position_ids`))return t;if(!t.past_key_values)[t.position_ids,t.rope_deltas]=this.get_rope_index(t.input_ids,t.image_grid_thw,t.video_grid_thw,t.attention_mask);else{t.pixel_values=null;let e=t.past_key_values.get_seq_length();if(en+e);t.position_ids=lu([r,r,r],0)}}return t}},$b=class extends Qb{},ex=class extends Qb{image_grid_thw_name=`image_grid_thw`},tx=class extends $b{image_grid_thw_name=`image_grid_thw`},nx=class extends ex{get_vision_position_ids(e,t,n,r){let i=Math.floor(t[0]/n),a=Math.floor(t[1]/r),o=Math.floor(t[2]/r),s=a*o*i,c=Array.from({length:s},()=>e),l=Array.from({length:s},(t,n)=>e+Math.floor(n/(o*i))),u=Array.from({length:s},(t,n)=>e+n%o);return[...c,...l,...u]}_get_multimodal_rope_positions({filtered_ids:e,image_grid_thw_list:t,video_grid_thw_list:n,spatial_merge_size:r,state:i}){let{image_token_id:a}=this.config,o=[],s=0,c=+(e[0]==a);for(let t=1;t<=e.length;++t){let n=tl+n%e)),l+=e}else{let e=t[i.image_index++].map(Number),n=e[0];u.push(this.get_vision_position_ids(l,e,n,r)),l+=Math.max(e[1],e[2])/r}return u}},rx=class extends Z{},ix=class extends rx{},ax=class extends rx{},ox=class extends Z{},sx=class extends ox{},cx=class extends ox{},lx=class extends Z{},ux=class extends lx{},dx=class extends lx{},fx=class extends Z{},px=class extends fx{},mx=class extends fx{},hx=class extends Z{},gx=class extends hx{},_x=class extends hx{},vx=class extends Z{},yx=class extends vx{},bx=class extends vx{},xx=class extends Z{},Sx=class extends xx{},Cx=class extends xx{},wx=class extends Z{},Tx=class extends wx{},Ex=class extends wx{},Dx=class extends Z{},Ox=class extends Dx{},kx=class extends Dx{},Ax=class extends Z{forward_params=[`input_ids`,`attention_mask`,`position_ids`,`audio_values`,`past_key_values`]},jx=class extends Ax{_merge_input_ids_with_audio_features(e){let t=e.audio_features.dims.at(-1),n=e.audio_features.view(-1,t);return Kg({audio_token_id:this.config.ignore_index??this.config.audio_token_id??this.config.audio_token_index,...e,audio_features:n})}},Mx=class extends jx{forward_params=[`input_ids`,`attention_mask`,`input_features`,`past_key_values`]},Nx=class extends Z{},Px=class extends Nx{},Fx=class extends Z{},Ix=class extends Fx{},Lx=class extends Z{},Rx=class extends Lx{},zx=class extends Lx{},Bx=class extends Z{},Vx=class extends Bx{},Hx=class extends Bx{async _call(e){return new Y(await super._call(e))}},Ux=class extends Z{},Wx=class extends Ux{},Gx=class extends Ux{forward_params=[`input_ids`,`attention_mask`,`token_type_ids`,`past_key_values`];prepare_inputs_for_generation(e,t,n){let r=Vg(this,e,t,n);return r.token_type_ids=(r.past_key_values?bu:vu)(r.input_ids),r}},Kx=class extends Z{},qx=class extends Kx{},Jx=class extends Kx{async _call(e){return new Lh(await super._call(e))}},Yx=class extends Kx{async _call(e){return new Y(await super._call(e))}},Xx=class extends Kx{async _call(e){return new Ph(await super._call(e))}},Zx=class extends Z{},Qx=class extends Kx{},$x=class extends Kx{async _call(e){return new Lh(await super._call(e))}},eS=class extends Kx{async _call(e){return new Y(await super._call(e))}},tS=class extends Z{},nS=class extends tS{},rS=class extends tS{},iS=class extends Nb{forward_params=[`input_ids`,`attention_mask`,`pixel_values`,`pixel_attention_mask`,`position_ids`,`past_key_values`]},aS=class extends Z{},oS=class extends aS{},sS=class extends aS{async _call(e){return new Y(await super._call(e))}},cS=class extends Z{},lS=class extends cS{},uS=class extends cS{},dS=class extends Z{},fS=class extends dS{async forward(e){let t=!e.input_ids,n=!e.pixel_values;if(t&&n)throw Error("Either `input_ids` or `pixel_values` should be provided.");if(t&&(e.input_ids=_u([e.pixel_values.dims[0],1])),n){let{image_size:t}=this.config.vision_config;e.pixel_values=hu([0,3,t,t],0)}let{text_embeddings:r,image_embeddings:i,l2norm_text_embeddings:a,l2norm_image_embeddings:o}=await super.forward(e),s={};return t||(s.text_embeddings=r,s.l2norm_text_embeddings=a),n||(s.image_embeddings=i,s.l2norm_image_embeddings=o),s}},pS=class extends dS{static async from_pretrained(e,t={}){return super.from_pretrained(e,{...t,model_file_name:t.model_file_name??`text_model`})}},mS=class extends dS{static async from_pretrained(e,t={}){return super.from_pretrained(e,{...t,model_file_name:t.model_file_name??`vision_model`})}},hS=class extends Z{},gS=class extends hS{},_S=class extends hS{},vS=class extends Nb{},yS=class extends Z{},bS=class extends yS{},xS=class extends yS{},SS=class extends Nb{forward_params=[`input_ids`,`attention_mask`,`pixel_values`,`pixel_attention_mask`,`spatial_shapes`,`position_ids`,`past_key_values`]},CS=class extends Z{},wS=class extends CS{},TS=class extends CS{},ES=class extends Z{},DS=class extends ES{},OS=class extends Z{},kS=class extends OS{},AS=class extends OS{},jS=class extends Z{},MS=class extends jS{},NS=class extends jS{},PS=class extends Z{},FS=class extends PS{},IS=class extends PS{},LS=class extends Z{},RS=class extends LS{},zS=class extends LS{},BS=class extends Z{},VS=class extends BS{},HS=class extends BS{},US=class extends BS{async _call(e){return new Y(await super._call(e))}},WS=class extends BS{},GS=class extends Z{},KS=class extends GS{},qS=class extends Z{},JS=class extends qS{},YS=class extends Mh{constructor({char_logits:e,bpe_logits:t,wp_logits:n}){super(),this.char_logits=e,this.bpe_logits=t,this.wp_logits=n}get logits(){return[this.char_logits,this.bpe_logits,this.wp_logits]}},XS=class extends Z{},ZS=class extends XS{async _call(e){return new YS(await super._call(e))}},QS=class extends Mh{constructor({audio_codes:e}){super(),this.audio_codes=e}},$S=class extends Mh{constructor({audio_values:e}){super(),this.audio_values=e}},eC=class extends Z{main_input_name=`input_values`;forward_params=[`input_values`]},tC=class extends eC{async encode(e){return new QS(await J(this.sessions.encoder_model,e))}async decode(e){return new $S(await J(this.sessions.decoder_model,e))}},nC=class extends eC{static async from_pretrained(e,t={}){return super.from_pretrained(e,{...t,model_file_name:t.model_file_name??`encoder_model`})}},rC=class extends eC{static async from_pretrained(e,t={}){return super.from_pretrained(e,{...t,model_file_name:t.model_file_name??`decoder_model`})}},iC=class extends Z{},aC=class extends iC{},oC=class extends iC{},sC=class extends Z{},cC=class extends sC{},lC=class extends sC{},uC=class extends Z{},dC=class extends uC{},fC=class extends uC{},pC=class extends Nb{},mC=class extends Z{},hC=class extends mC{},gC=class extends mC{},_C=class extends Z{},vC=class extends _C{},yC=class extends _C{async _call(e){return new Fh(await super._call(e))}},bC=class extends _C{async _call(e){return new Y(await super._call(e))}},xC=class extends _C{async _call(e){return new Ih(await super._call(e))}},SC=class extends Z{},CC=class extends SC{},wC=class extends SC{},TC=class extends Z{},EC=class extends TC{},DC=class extends TC{async _call(e){return new Y(await super._call(e))}},OC=class extends TC{},kC=class extends Z{},AC=class extends kC{},jC=class extends kC{async _call(e){return new Y(await super._call(e))}},MC=class extends kC{},NC=class extends Z{},PC=class extends NC{},FC=class extends NC{async _call(e){return new Y(await super._call(e))}},IC=class extends NC{},LC=class extends Z{},RC=class extends LC{},zC=class extends LC{async _call(e){return new Y(await super._call(e))}},BC=class extends LC{},VC=class extends Z{},HC=class extends VC{},UC=class extends VC{async _call(e){return new Y(await super._call(e))}},WC=class extends Z{},GC=class extends WC{},KC=class extends WC{async _call(e){return new Y(await super._call(e))}},qC=class extends Z{},JC=class extends qC{},YC=class extends qC{async _call(e){return new Fh(await super._call(e))}},XC=class extends qC{async _call(e){return new Y(await super._call(e))}},ZC=class extends qC{async _call(e){return new Ph(await super._call(e))}},QC=class extends Z{},$C=class extends QC{},ew=class extends QC{},tw=class extends Z{requires_attention_mask=!1;main_input_name=`input_values`;forward_params=[`input_values`,`decoder_input_ids`,`past_key_values`]},nw=class extends tw{},rw=class extends tw{},iw=class extends Z{},aw=class extends iw{},ow=class extends iw{async _call(e){return new Fh(await super._call(e))}},sw=class extends iw{async _call(e){return new Y(await super._call(e))}},cw=class extends iw{async _call(e){return new Ph(await super._call(e))}},lw=class extends iw{async _call(e){return new Ih(await super._call(e))}},uw=class extends Z{},dw=class extends uw{},fw=class extends uw{},pw=class extends Z{},mw=class extends pw{},hw=class extends pw{},gw=class extends Z{},_w=class extends gw{forward_params=[`input_ids`,`pixel_values`,`images_seq_mask`,`images_emb_mask`,`attention_mask`,`position_ids`,`past_key_values`];constructor(...e){super(...e),this._generation_mode=`text`}async forward(e){let t=this._generation_mode??`text`,n;if(t===`text`||!e.past_key_values){let t=this.sessions.prepare_inputs_embeds;n=await J(t,si(e,t.inputNames))}else{let t=this.sessions.gen_img_embeds;n=await J(t,si({image_ids:e.input_ids},t.inputNames))}let r={...e,...n},i=await Fg(this,r),a=this.sessions[t===`text`?`lm_head`:`gen_head`];if(!a)throw Error(`Unable to find "${a}" generation head`);let o=await J(a,si(i,a.inputNames));return{...n,...i,...o}}prepare_inputs_for_generation(e,t,n){let r=!!t.past_key_values;return Pg(this,t,1n),n.guidance_scale!==null&&n.guidance_scale>1&&(r?t.input_ids=U([t.input_ids,t.input_ids],0):(t.input_ids=U([t.input_ids,gu(t.input_ids,BigInt(n.pad_token_id))],0),t.attention_mask=U([t.attention_mask,gu(t.attention_mask,0n)],0))),(r||!t.pixel_values)&&(t.pixel_values=hu([0,0,3,384,384],1)),r&&(t.images_seq_mask=new H(`bool`,[,].fill(!0).fill(!1,0,1),[1,1]),t.images_emb_mask=new H(`bool`,[].fill(!1),[1,1,0])),t}async generate(e){return this._generation_mode=`text`,super.generate(e)}async generate_images(e){this._generation_mode=`image`;let t=(e.inputs??e[this.main_input_name]).dims[1],n=(await super.generate(e)).slice(null,[t,null]),r=this.sessions.image_decode,{decoded_image:i}=await J(r,{generated_tokens:n}),a=i.add_(1).mul_(255/2).clamp_(0,255).to(`uint8`),o=[];for(let e of a){let t=Bf.fromTensor(e);o.push(t)}return o}},vw=class extends Z{},yw=class extends vw{},bw=class extends vw{},xw=class extends Z{forward_params=[`input_ids`,`attention_mask`,`encoder_outputs`,`decoder_input_ids`,`decoder_attention_mask`,`past_key_values`];_apply_and_filter_by_delay_pattern_mask(e){let[t,n]=e.dims,r=this.config.decoder.num_codebooks,i=n-r,a=0;for(let t=0;t0&&o<=i&&(e.data[a++]=e.data[t])}let o=Math.floor(t/r),s=a/(o*r);return new H(e.type,e.data.slice(0,a),[o,r,s])}prepare_inputs_for_generation(e,t,n){let r=BigInt(this.config.decoder.pad_token_id),i=structuredClone(e);for(let e=0;e=t&&(i[e][t]=r);return n.guidance_scale!==null&&n.guidance_scale>1&&(i=i.concat(i)),Hg(this,i,t,n)}async generate(e){let t=await super.generate(e),n=this._apply_and_filter_by_delay_pattern_mask(t).unsqueeze_(0),{audio_values:r}=await J(this.sessions.encodec_decode,{audio_codes:n});return r}},Sw=class extends Z{},Cw=class extends Sw{},ww=class extends Sw{},Tw=class extends Z{},Ew=class extends Tw{},Dw=class extends Tw{},Ow=class extends Z{},kw=class extends Ow{},Aw=class extends Ow{async _call(e){return new Fh(await super._call(e))}},jw=class extends Ow{async _call(e){return new Y(await super._call(e))}},Mw=class extends Ow{async _call(e){return new Ph(await super._call(e))}},Nw=class extends Ow{async _call(e){return new Ih(await super._call(e))}},Pw=class extends Z{},Fw=class extends Pw{},Iw=class extends Z{},Lw=class extends Iw{},Rw=class extends Iw{},zw=class extends Z{},Bw=class extends zw{},Vw=class extends zw{},Hw=class extends Z{},Uw=class extends Hw{},Ww=class extends Hw{},Gw=class extends Z{},Kw=class extends Gw{},qw=class extends Gw{},Jw=class extends Z{},Yw=class extends Jw{},Xw=class extends Jw{async _call(e){return new Y(await super._call(e))}},Zw=class extends Z{},Qw=class extends Zw{},$w=class extends Zw{},eT=class extends Z{},tT=class extends eT{},nT=class extends eT{},rT=class extends Z{},iT=class extends rT{},aT=class extends rT{},oT=class extends Z{},sT=class extends oT{},cT=class extends oT{},lT=class extends Nb{},uT=class extends Z{},dT=class extends uT{async _call(e){return new Lh(await super._call(e))}},fT=class extends Z{},pT=class extends fT{},mT=class extends fT{},hT=class extends Z{},gT=class extends hT{},_T=class extends hT{},vT=class extends Z{},yT=class extends vT{},bT=class extends vT{},xT=class extends Z{},ST=class extends xT{},CT=class extends xT{},wT=class extends Z{forward_params=[`input_ids`,`inputs_embeds`,`attention_mask`,`position_ids`,`pixel_values`,`image_sizes`,`past_key_values`]},TT=class extends wT{async forward({input_ids:e=null,attention_mask:t=null,pixel_values:n=null,image_sizes:r=null,position_ids:i=null,inputs_embeds:a=null,past_key_values:o=null,generation_config:s=null,logits_processor:c=null,num_logits_to_keep:l=null,...u}){if(!a){let t;if(n&&e.dims[1]!==1){if(!r)throw Error("`image_sizes` must be provided when `pixel_values` is provided.");({image_features:t}=await J(this.sessions.vision_encoder,{pixel_values:n,image_sizes:r}))}else{let e=this.config.normalized_config.hidden_size;t=new H(`float32`,[],[0,e])}({inputs_embeds:a}=await J(this.sessions.prepare_inputs_embeds,{input_ids:e,image_features:t}))}return await Fg(this,{inputs_embeds:a,past_key_values:o,attention_mask:t,position_ids:i,generation_config:s,logits_processor:c,num_logits_to_keep:l},!1)}},ET=class extends Z{},DT=class extends ET{},OT=class extends ET{async _call(e){return new Y(await super._call(e))}},kT=class extends Z{},AT=class extends kT{},jT=class extends kT{async _call(e){return new Ph(await super._call(e))}},MT=class extends Z{},NT=class extends MT{},PT=class extends MT{},FT=class extends Z{},IT=class extends FT{},LT=class extends FT{},RT=class extends Z{},zT=class extends RT{},BT=class extends RT{},VT=class extends Z{},HT=class extends VT{},UT=class extends VT{},WT=class extends Z{},GT=class extends WT{},KT=class extends WT{},qT=class extends ex{},JT=class extends tx{},YT=class extends qT{},XT=class extends JT{},ZT=class extends qT{},QT=class extends ZT{},$T=class extends ZT{},eE=class extends QT{},tE=class extends Z{},nE=class extends tE{},rE=class extends tE{async _call(e){return new Y(await super._call(e))}},iE=class extends Z{},aE=class extends iE{},oE=class extends iE{async _call(e){return new sE(await super._call(e))}},sE=class extends Pv{},cE=class extends Z{},lE=class extends cE{},uE=class extends cE{async _call(e){return new Fh(await super._call(e))}},dE=class extends cE{async _call(e){return new Y(await super._call(e))}},fE=class extends cE{async _call(e){return new Ph(await super._call(e))}},pE=class extends cE{async _call(e){return new Ih(await super._call(e))}},mE=class extends Z{},hE=class extends mE{},gE=class extends mE{async _call(e){return new Fh(await super._call(e))}},_E=class extends mE{async _call(e){return new Y(await super._call(e))}},vE=class extends mE{async _call(e){return new Ph(await super._call(e))}},yE=class extends mE{async _call(e){return new Ih(await super._call(e))}},bE=class extends Z{},xE=class extends bE{},SE=class extends bE{async _call(e){return new CE(await super._call(e))}},CE=class extends Pv{},wE=class extends Mh{constructor({iou_scores:e,pred_masks:t}){super(),this.iou_scores=e,this.pred_masks=t}},TE=class extends Z{},EE=class extends TE{async get_image_embeddings({pixel_values:e}){return await Og(this,{pixel_values:e})}async forward(e){e=!e.image_embeddings||!e.image_positional_embeddings?{...e,...await this.get_image_embeddings(e)}:{...e},e.input_labels??=_u(e.input_points.dims.slice(0,-1));let t={image_embeddings:e.image_embeddings,image_positional_embeddings:e.image_positional_embeddings};return e.input_points&&(t.input_points=e.input_points),e.input_labels&&(t.input_labels=e.input_labels),e.input_boxes&&(t.input_boxes=e.input_boxes),await J(this.sessions.prompt_encoder_mask_decoder,t)}async _call(e){return new wE(await super._call(e))}},DE=class extends Mh{constructor({iou_scores:e,pred_masks:t,object_score_logits:n}){super(),this.iou_scores=e,this.pred_masks=t,this.object_score_logits=n}},OE=class extends Z{},kE=class extends OE{async get_image_embeddings({pixel_values:e}){return await Og(this,{pixel_values:e})}async forward(e){let{num_feature_levels:t}=this.config.vision_config;if(e=Array.from({length:t},(e,t)=>`image_embeddings.${t}`).some(t=>!e[t])?{...e,...await this.get_image_embeddings(e)}:{...e},e.input_points){if(e.input_boxes&&e.input_boxes.dims[1]!==1)throw Error("When both `input_points` and `input_boxes` are provided, the number of boxes per image must be 1.");let t=e.input_points.dims;e.input_labels??=_u(t.slice(0,-1)),e.input_boxes??=hu([t[0],0,4],0)}else if(e.input_boxes){let t=e.input_boxes.dims;e.input_labels=hu([t[0],t[1],0],-1n),e.input_points=hu([t[0],1,0,2],0)}else throw Error("At least one of `input_points` or `input_boxes` must be provided.");let n=this.sessions.prompt_encoder_mask_decoder;return await J(n,si(e,n.inputNames))}async _call(e){return new DE(await super._call(e))}},AE=class extends kE{},jE=class extends kE{},ME=class extends Z{},NE=class extends ME{},PE=class extends ME{},FE=class extends ME{},IE=class extends Z{},LE=class extends IE{},RE=class extends IE{},zE=class extends IE{},BE=class extends Z{},VE=class extends BE{},HE=class extends BE{static async from_pretrained(e,t={}){return super.from_pretrained(e,{...t,model_file_name:t.model_file_name??`text_model`})}},UE=class extends Q_{static async from_pretrained(e,t={}){return super.from_pretrained(e,{...t,model_file_name:t.model_file_name??`vision_model`})}},WE=class extends Z{},GE=class extends WE{},KE=class extends WE{},qE=class extends iS{},JE=class extends Z{main_input_name=`input_values`;forward_params=[`input_values`]},YE=class extends JE{async encode(e){return await J(this.sessions.encoder_model,e)}async decode(e){return await J(this.sessions.decoder_model,e)}},XE=class extends JE{static async from_pretrained(e,t={}){return super.from_pretrained(e,{...t,model_file_name:t.model_file_name??`encoder_model`})}},ZE=class extends JE{static async from_pretrained(e,t={}){return super.from_pretrained(e,{...t,model_file_name:t.model_file_name??`decoder_model`})}},QE=class extends Z{},$E=class extends QE{},eD=class extends QE{},tD=class extends Z{},nD=class extends tD{},rD=class extends tD{},iD=class extends tD{async generate_speech(e,t,{threshold:n=.5,minlenratio:r=0,maxlenratio:i=20,vocoder:a=null}={}){let o={input_ids:e},{encoder_outputs:s,encoder_attention_mask:c}=await Og(this,o),l=s.dims[1]/this.config.reduction_factor,u=Math.floor(l*i),d=Math.floor(l*r),f=this.config.num_mel_bins,p=[],m=null,h=null,g=0;for(;;){++g;let e=xg(!!h),r;r=h?h.output_sequence_out:new H(`float32`,new Float32Array(f),[1,1,f]);let i={use_cache_branch:e,output_sequence:r,encoder_attention_mask:c,speaker_embeddings:t,encoder_hidden_states:s};Ng(this,i,m),h=await J(this.sessions.decoder_model_merged,i),m=Ag(h,m);let{prob:a,spectrum:o}=h;if(p.push(o),g>=d&&(Array.from(a.data).filter(e=>e>=n).length>0||g>=u))break}let _=U(p),{waveform:v}=await J(a.sessions.model,{spectrogram:_});return{spectrogram:_,waveform:v}}},aD=class extends Z{main_input_name=`spectrogram`},oD=class extends Z{},sD=class extends oD{},cD=class extends oD{async _call(e){return new Fh(await super._call(e))}},lD=class extends oD{async _call(e){return new Y(await super._call(e))}},uD=class extends oD{async _call(e){return new Ih(await super._call(e))}},dD=class extends Z{},fD=class extends dD{},pD=class extends dD{},mD=class extends Z{},hD=class extends mD{},gD=class extends mD{},_D=class extends Z{},vD=class extends _D{},yD=class extends Z{},bD=class extends yD{async generate_speech({input_ids:e,attention_mask:t,style:n,num_inference_steps:r=5,speed:i=1.05}){let{sampling_rate:a,chunk_compress_factor:o,base_chunk_size:s,latent_dim:c}=this.config,{last_hidden_state:l,durations:u}=await J(this.sessions.text_encoder,{input_ids:e,attention_mask:t,style:n}),d=u.div(i).mul_(a),f=s*o,p=d.data,m=Int32Array.from(p,e=>Math.ceil(e/f)),h=Math.max(...m),g=e.dims[0],_=new BigInt64Array(g*h);for(let e=0;ee*t,1),r=Xl[e.type];c[e.name]=new H(e.type,new r(n),t)}let f=Xl[d],p=new H(d,new f(s*fO),[1,s,fO]),m=t[Symbol.asyncIterator]?.()??t[Symbol.iterator]?.();if(!m)throw Error(`input_features must be iterable or async iterable`);return{encoder_session:i,enc_kv_cache:c,enc_padding_cache:p,enc_past_seq_len:0,audio_embed_queue:[],audio_embed_total_tokens:0,audio_queue_offset:0,audio_consumed:0,stream_exhausted:!1,chunks_iter:m,text_hidden_size:n.hidden_size}}async function gO(e,t){let n=t.dims[2],r=Math.floor((pO+n-3)/2)+1,i=new H(`int64`,BigInt64Array.from({length:r},(t,n)=>BigInt(e.enc_past_seq_len+n)),[1,r]),a=e.enc_past_seq_len+r,o=_u([1,a]),{audio_embeds:s,present_padding_cache:c,...l}=await J(e.encoder_session,{input_features:t,attention_mask:o,position_ids:i,past_padding_cache:e.enc_padding_cache,...e.enc_kv_cache});e.enc_padding_cache.location===`gpu-buffer`&&e.enc_padding_cache.dispose(),e.enc_padding_cache=c;for(let t in l)if(t.startsWith(`present.`)){let n=t.replace(`present`,`past_key_values`),r=e.enc_kv_cache[n];r?.location===`gpu-buffer`&&r.dispose(),e.enc_kv_cache[n]=l[t]}return e.enc_past_seq_len=a,s}async function _O(e,t){for(;e.audio_embed_total_tokens0&&e.audio_embed_queue.length>0;){let t=e.audio_embed_queue[0],n=t.tokens-e.audio_queue_offset,o=Math.min(a,n),s=e.audio_queue_offset*e.text_hidden_size;for(let n=0;n=t.tokens&&(e.audio_embed_queue.shift(),e.audio_queue_offset=0)}e.audio_consumed+=n-a}var yO=class extends rg{constructor(e){super(),this._s=e}_call(e){let t=this._s.stream_exhausted&&this._s.audio_embed_queue.length===0;return e.map(()=>t)}},bO=class extends Z{forward_params=[`input_ids`,`attention_mask`,`position_ids`,`past_key_values`]},xO=class extends bO{async forward({input_ids:e,past_key_values:t,...n}){let r=e.dims[1],i=mO.get(this);i&&await _O(i,i.audio_consumed+r);let{inputs_embeds:a}=await J(this.sessions.embed_tokens,{input_ids:e});i&&vO(i,a,r);let o={inputs_embeds:a,...n};Ng(this,o,t);let s=this.sessions.decoder_model_merged;return await J(s,si(o,s.inputNames))}async generate({input_features:e,stopping_criteria:t,...n}){if(!e)throw Error(`input_features (generator/iterable) must be provided`);let r=hO(this,e);mO.set(this,r);let i=new ig;i.push(new yO(r)),t&&i.extend(t);try{return await super.generate({...n,stopping_criteria:i})}finally{r.enc_kv_cache.dispose(),mO.delete(this)}}},SO=class extends Z{},CO=class extends SO{},wO=class extends SO{async _call(e){return new Lh(await super._call(e))}},TO=class extends SO{async _call(e){return new Y(await super._call(e))}},EO=class extends Mh{constructor({logits:e,embeddings:t}){super(),this.logits=e,this.embeddings=t}},DO=class extends Z{},OO=class extends DO{},kO=class extends DO{async _call(e){return new Lh(await super._call(e))}},AO=class extends DO{async _call(e){return new Y(await super._call(e))}},jO=class extends DO{async _call(e){return new EO(await super._call(e))}},MO=class extends DO{async _call(e){return new Ph(await super._call(e))}},NO=class extends Z{},PO=class extends NO{},FO=class extends ng{return_timestamps=null;return_token_timestamps=null;num_frames=null;alignment_heads=null;task=null;language=null;no_timestamps_token_id=null;prompt_ids=null;is_multilingual=null;lang_to_id=null;task_to_id=null;max_initial_timestamp_index=1},IO=class extends Z{requires_attention_mask=!1;main_input_name=`input_features`;forward_params=[`input_features`,`attention_mask`,`decoder_input_ids`,`decoder_attention_mask`,`past_key_values`]},LO=class extends IO{},RO=class extends IO{_prepare_generation_config(e,t){return super._prepare_generation_config(e,t,FO)}_retrieve_init_tokens(e){let t=[e.decoder_start_token_id],n=e.language,r=e.task;if(e.is_multilingual){n||=(A.warn(`No language specified - defaulting to English (en).`),`en`);let i=`<|${Td(n)}|>`;t.push(e.lang_to_id[i]),t.push(e.task_to_id[r??`transcribe`])}else if(n||r)throw Error("Cannot specify `task` or `language` for an English-only model. If the model is intended to be multilingual, pass `is_multilingual=true` to generate, or update the generation config.");return!e.return_timestamps&&e.no_timestamps_token_id&&t.at(-1)!==e.no_timestamps_token_id?t.push(e.no_timestamps_token_id):e.return_timestamps&&t.at(-1)===e.no_timestamps_token_id&&(A.warn("<|notimestamps|> prompt token is removed from generation_config since `return_timestamps` is set to `true`."),t.pop()),t.filter(e=>e!=null)}async generate({inputs:e=null,generation_config:t=null,logits_processor:n=null,stopping_criteria:r=null,...i}){t=this._prepare_generation_config(t,i);let a=i.decoder_input_ids instanceof H?Tu(i.decoder_input_ids):i.decoder_input_ids??this._retrieve_init_tokens(t);if(t.return_timestamps&&(n??=new Uh,n.push(new Jh(t,a))),t.begin_suppress_tokens&&(n??=new Uh,n.push(new qh(t.begin_suppress_tokens,a.length))),t.return_token_timestamps){if(!t.alignment_heads)throw Error("Model generation config has no `alignment_heads`, token-level timestamps not available. See https://gist.github.com/hollance/42e32852f24243b748ae6bc1f985b13a on how to add this property to the generation config.");t.task===`translate`&&A.warn(`Token-level timestamps may not be reliable for task 'translate'.`),t.output_attentions=!0,t.return_dict_in_generate=!0}if(t.return_timestamps&&!i.max_new_tokens)return this._generate_with_seek({inputs:e,generation_config:t,logits_processor:n,init_tokens:a,kwargs:i});let o=await super.generate({inputs:e,generation_config:t,logits_processor:n,decoder_input_ids:a,...i});return t.return_token_timestamps&&(o.token_timestamps=this._extract_token_timestamps(o,t.alignment_heads,t.num_frames,.02,a.length)),o}async _generate_with_seek({inputs:e,generation_config:t,logits_processor:n,init_tokens:r,kwargs:i}){let a=t.no_timestamps_token_id+1,o=Array.isArray(t.eos_token_id)?t.eos_token_id[0]:t.eos_token_id,s=t.return_token_timestamps,c=e,l=c.dims[2],u=2*this.config.max_source_positions,d=0,f=[],p=[];for(;de+n)}if(v.length>0&&v.at(-1)===o&&v.pop(),v.length===0)break;let b=v.map(e=>e>=a),x=v.length>=2&&b[v.length-1]&&!b[v.length-2],S=[];for(let e=0;e0){if(x)C=e-d;else{let e=S.at(-1);C=(v[e-1]-a)*2,ee=e}}else C=e-d;let te=Math.floor(d/2),ne=a+1500;for(let e=0;e=a&&(v[e]=Math.min(v[e]+te,ne));f.push(...v.slice(0,ee)),y&&p.push(...y.slice(0,ee)),d+=C}f.push(o);let m=[...r,...f];if(s){let e=new H(`int64`,m.map(BigInt),[1,m.length]),t=[...Array(r.length).fill(0),...p,0];return{sequences:e,token_timestamps:new H(`float32`,new Float32Array(t),[1,t.length])}}return new H(`int64`,m.map(BigInt),[1,m.length])}_extract_token_timestamps(e,t,n=null,r=.02,i=0){if(!e.cross_attentions)throw Error("Model outputs must contain cross attentions to extract timestamps. This is most likely because the model was not exported with `output_attentions=True`.");n??A.warn("`num_frames` has not been set, meaning the entire audio will be analyzed. This may lead to inaccurate token-level timestamps for short audios (< 30 seconds).");let a=this.config.median_filter_width;a===void 0&&(A.warn("Model config has no `median_filter_width`, using default value of 7."),a=7);let o=e.cross_attentions,s=Array.from({length:this.config.decoder_layers},(e,t)=>U(o.map(e=>e[t]),2)),c=lu(t.map(([e,t])=>{if(e>=s.length)throw Error(`Layer index ${e} is out of bounds for cross attentions (length ${s.length}).`);return n?s[e].slice(null,t,null,[0,n]):s[e].slice(null,t)})).permute(1,0,2,3),[l,u]=du(c,-2,0,!0),d=c.clone();for(let e=0;e0?d.slice(null,null,[i,d.dims[2]],null):d,1)],p=e.sequences.dims,m=new H(`float32`,new Float32Array(p[0]*p[1]),p);for(let e=0;et[n+1]-t[n])).map(e=>!!e),o=[];for(let e=0;e0&&s.push(o.at(-1)),m[e].data.set(s)}return m}},zO=class extends RO{},BO=class extends Z{},VO=class extends BO{},HO=class extends BO{async _call(e){return new Fh(await super._call(e))}},UO=class extends BO{async _call(e){return new Y(await super._call(e))}},WO=class extends BO{async _call(e){return new Ph(await super._call(e))}},GO=class extends BO{async _call(e){return new Ih(await super._call(e))}},KO=class extends Z{},qO=class extends KO{},JO=class extends KO{async _call(e){return new Fh(await super._call(e))}},YO=class extends KO{async _call(e){return new Y(await super._call(e))}},XO=class extends KO{async _call(e){return new Ph(await super._call(e))}},ZO=class extends KO{async _call(e){return new Ih(await super._call(e))}},QO=class extends Z{},$O=class extends QO{},ek=class extends QO{async _call(e){return new tk(await super._call(e))}},tk=class extends Mh{constructor({logits:e,pred_boxes:t}){super(),this.logits=e,this.pred_boxes=t}},nk=class extends Z{},rk=class extends nk{},ik=class extends nk{},ak=class extends Z{},ok=class extends ak{},sk=class extends ak{},ck=/* @__PURE__ */ new Map([[`bert`,`BertModel`],[`eurobert`,`EuroBertModel`],[`neobert`,`NeoBertModel`],[`modernbert`,`ModernBertModel`],[`nomic_bert`,`NomicBertModel`],[`roformer`,`RoFormerModel`],[`electra`,`ElectraModel`],[`esm`,`EsmModel`],[`convbert`,`ConvBertModel`],[`camembert`,`CamembertModel`],[`deberta`,`DebertaModel`],[`deberta-v2`,`DebertaV2Model`],[`mpnet`,`MPNetModel`],[`albert`,`AlbertModel`],[`distilbert`,`DistilBertModel`],[`roberta`,`RobertaModel`],[`xlm`,`XLMModel`],[`xlm-roberta`,`XLMRobertaModel`],[`clap`,`ClapModel`],[`clip`,`CLIPModel`],[`clipseg`,`CLIPSegModel`],[`chinese_clip`,`ChineseCLIPModel`],[`siglip`,`SiglipModel`],[`jina_clip`,`JinaCLIPModel`],[`mobilebert`,`MobileBertModel`],[`squeezebert`,`SqueezeBertModel`],[`wav2vec2`,`Wav2Vec2Model`],[`wav2vec2-bert`,`Wav2Vec2BertModel`],[`unispeech`,`UniSpeechModel`],[`unispeech-sat`,`UniSpeechSatModel`],[`hubert`,`HubertModel`],[`wavlm`,`WavLMModel`],[`audio-spectrogram-transformer`,`ASTModel`],[`vits`,`VitsModel`],[`pyannote`,`PyAnnoteModel`],[`wespeaker-resnet`,`WeSpeakerResNetModel`],[`detr`,`DetrModel`],[`rt_detr`,`RTDetrModel`],[`rt_detr_v2`,`RTDetrV2Model`],[`rf_detr`,`RFDetrModel`],[`d_fine`,`DFineModel`],[`table-transformer`,`TableTransformerModel`],[`vit`,`ViTModel`],[`ijepa`,`IJepaModel`],[`pvt`,`PvtModel`],[`vit_msn`,`ViTMSNModel`],[`vit_mae`,`ViTMAEModel`],[`groupvit`,`GroupViTModel`],[`fastvit`,`FastViTModel`],[`mobilevit`,`MobileViTModel`],[`mobilevitv2`,`MobileViTV2Model`],[`owlvit`,`OwlViTModel`],[`owlv2`,`Owlv2Model`],[`beit`,`BeitModel`],[`deit`,`DeiTModel`],[`hiera`,`HieraModel`],[`convnext`,`ConvNextModel`],[`convnextv2`,`ConvNextV2Model`],[`dinov2`,`Dinov2Model`],[`dinov2_with_registers`,`Dinov2WithRegistersModel`],[`dinov3_vit`,`DINOv3ViTModel`],[`dinov3_convnext`,`DINOv3ConvNextModel`],[`resnet`,`ResNetModel`],[`swin`,`SwinModel`],[`swin2sr`,`Swin2SRModel`],[`donut-swin`,`DonutSwinModel`],[`yolos`,`YolosModel`],[`dpt`,`DPTModel`],[`glpn`,`GLPNModel`],[`hifigan`,`SpeechT5HifiGan`],[`efficientnet`,`EfficientNetModel`],[`decision_transformer`,`DecisionTransformerModel`],[`patchtst`,`PatchTSTModel`],[`patchtsmixer`,`PatchTSMixerModel`],[`mobilenet_v1`,`MobileNetV1Model`],[`mobilenet_v2`,`MobileNetV2Model`],[`mobilenet_v3`,`MobileNetV3Model`],[`mobilenet_v4`,`MobileNetV4Model`],[`maskformer`,`MaskFormerModel`],[`mgp-str`,`MgpstrForSceneTextRecognition`],[`style_text_to_speech_2`,`StyleTextToSpeech2Model`],[`openai_privacy_filter`,`OpenAIPrivacyFilterModel`]]),lk=/* @__PURE__ */ new Map([[`t5`,`T5Model`],[`longt5`,`LongT5Model`],[`mt5`,`MT5Model`],[`bart`,`BartModel`],[`mbart`,`MBartModel`],[`marian`,`MarianModel`],[`whisper`,`WhisperModel`],[`cohere_asr`,`CohereAsrModel`],[`m2m_100`,`M2M100Model`],[`blenderbot`,`BlenderbotModel`],[`blenderbot-small`,`BlenderbotSmallModel`]]),uk=/* @__PURE__ */ new Map([[`mimi`,`MimiModel`],[`dac`,`DacModel`],[`snac`,`SnacModel`]]),dk=/* @__PURE__ */ new Map([[`bloom`,`BloomModel`],[`jais`,`JAISModel`],[`gpt2`,`GPT2Model`],[`gpt_oss`,`GptOssModel`],[`gptj`,`GPTJModel`],[`gpt_bigcode`,`GPTBigCodeModel`],[`gpt_neo`,`GPTNeoModel`],[`gpt_neox`,`GPTNeoXModel`],[`codegen`,`CodeGenModel`],[`llama`,`LlamaModel`],[`apertus`,`ApertusModel`],[`nanochat`,`NanoChatModel`],[`arcee`,`ArceeModel`],[`afmoe`,`AfmoeModel`],[`lfm2`,`Lfm2Model`],[`lfm2_moe`,`Lfm2MoeModel`],[`smollm3`,`SmolLM3Model`],[`exaone`,`ExaoneModel`],[`olmo`,`OlmoModel`],[`olmo2`,`Olmo2Model`],[`olmo3`,`Olmo3Model`],[`olmo_hybrid`,`OlmoHybridModel`],[`mobilellm`,`MobileLLMModel`],[`granite`,`GraniteModel`],[`granitemoehybrid`,`GraniteMoeHybridModel`],[`cohere`,`CohereModel`],[`cohere2`,`Cohere2Model`],[`gemma`,`GemmaModel`],[`gemma2`,`Gemma2Model`],[`vaultgemma`,`VaultGemmaModel`],[`gemma3_text`,`Gemma3Model`],[`helium`,`HeliumModel`],[`glm`,`GlmModel`],[`glm_moe_dsa`,`GlmMoeDsaModel`],[`openelm`,`OpenELMModel`],[`qwen2`,`Qwen2Model`],[`qwen2_moe`,`Qwen2MoeModel`],[`qwen3`,`Qwen3Model`],[`qwen3_moe`,`Qwen3MoeModel`],[`qwen3_next`,`Qwen3NextModel`],[`phi`,`PhiModel`],[`phi3`,`Phi3Model`],[`mpt`,`MptModel`],[`opt`,`OPTModel`],[`mistral`,`MistralModel`],[`mistral4`,`Mistral4Model`],[`ministral`,`MinistralModel`],[`ministral3`,`Ministral3Model`],[`ernie4_5`,`Ernie4_5ForCausalLM`],[`starcoder2`,`Starcoder2Model`],[`deepseek_v3`,`DeepseekV3Model`],[`deepseek_v4`,`DeepseekV4Model`],[`falcon`,`FalconModel`],[`falcon_h1`,`FalconH1Model`],[`nemotron_h`,`NemotronHModel`],[`solar_open`,`SolarOpenModel`],[`stablelm`,`StableLmModel`],[`modernbert-decoder`,`ModernBertDecoderModel`],[`hunyuan_v1_dense`,`HunYuanDenseV1Model`],[`youtu`,`YoutuModel`],[`zaya`,`ZayaModel`],[`hrm_text`,`HrmTextModel`]]),fk=/* @__PURE__ */ new Map([[`speecht5`,`SpeechT5ForSpeechToText`],[`whisper`,`WhisperForConditionalGeneration`],[`lite-whisper`,`LiteWhisperForConditionalGeneration`],[`moonshine`,`MoonshineForConditionalGeneration`],[`cohere_asr`,`CohereAsrForConditionalGeneration`]]),pk=/* @__PURE__ */ new Map([[`speecht5`,`SpeechT5ForTextToSpeech`]]),mk=/* @__PURE__ */ new Map([[`vits`,`VitsModel`],[`musicgen`,`MusicgenForConditionalGeneration`],[`supertonic`,`SupertonicForConditionalGeneration`]]),hk=/* @__PURE__ */ new Map([[`bert`,`BertForSequenceClassification`],[`eurobert`,`EuroBertForSequenceClassification`],[`neobert`,`NeoBertForSequenceClassification`],[`modernbert`,`ModernBertForSequenceClassification`],[`roformer`,`RoFormerForSequenceClassification`],[`electra`,`ElectraForSequenceClassification`],[`esm`,`EsmForSequenceClassification`],[`convbert`,`ConvBertForSequenceClassification`],[`camembert`,`CamembertForSequenceClassification`],[`deberta`,`DebertaForSequenceClassification`],[`deberta-v2`,`DebertaV2ForSequenceClassification`],[`mpnet`,`MPNetForSequenceClassification`],[`albert`,`AlbertForSequenceClassification`],[`distilbert`,`DistilBertForSequenceClassification`],[`roberta`,`RobertaForSequenceClassification`],[`xlm`,`XLMForSequenceClassification`],[`xlm-roberta`,`XLMRobertaForSequenceClassification`],[`bart`,`BartForSequenceClassification`],[`mbart`,`MBartForSequenceClassification`],[`mobilebert`,`MobileBertForSequenceClassification`],[`squeezebert`,`SqueezeBertForSequenceClassification`]]),gk=/* @__PURE__ */ new Map([[`bert`,`BertForTokenClassification`],[`eurobert`,`EuroBertForTokenClassification`],[`neobert`,`NeoBertForTokenClassification`],[`modernbert`,`ModernBertForTokenClassification`],[`roformer`,`RoFormerForTokenClassification`],[`electra`,`ElectraForTokenClassification`],[`esm`,`EsmForTokenClassification`],[`convbert`,`ConvBertForTokenClassification`],[`camembert`,`CamembertForTokenClassification`],[`deberta`,`DebertaForTokenClassification`],[`deberta-v2`,`DebertaV2ForTokenClassification`],[`mpnet`,`MPNetForTokenClassification`],[`distilbert`,`DistilBertForTokenClassification`],[`roberta`,`RobertaForTokenClassification`],[`xlm`,`XLMForTokenClassification`],[`xlm-roberta`,`XLMRobertaForTokenClassification`],[`openai_privacy_filter`,`OpenAIPrivacyFilterForTokenClassification`]]),_k=/* @__PURE__ */ new Map([[`t5`,`T5ForConditionalGeneration`],[`longt5`,`LongT5ForConditionalGeneration`],[`mt5`,`MT5ForConditionalGeneration`],[`bart`,`BartForConditionalGeneration`],[`mbart`,`MBartForConditionalGeneration`],[`marian`,`MarianMTModel`],[`m2m_100`,`M2M100ForConditionalGeneration`],[`blenderbot`,`BlenderbotForConditionalGeneration`],[`blenderbot-small`,`BlenderbotSmallForConditionalGeneration`]]),vk=/* @__PURE__ */ new Map([[`bloom`,`BloomForCausalLM`],[`gpt2`,`GPT2LMHeadModel`],[`gpt_oss`,`GptOssForCausalLM`],[`jais`,`JAISLMHeadModel`],[`gptj`,`GPTJForCausalLM`],[`gpt_bigcode`,`GPTBigCodeForCausalLM`],[`gpt_neo`,`GPTNeoForCausalLM`],[`gpt_neox`,`GPTNeoXForCausalLM`],[`codegen`,`CodeGenForCausalLM`],[`llama`,`LlamaForCausalLM`],[`nanochat`,`NanoChatForCausalLM`],[`apertus`,`ApertusForCausalLM`],[`llama4_text`,`Llama4ForCausalLM`],[`arcee`,`ArceeForCausalLM`],[`afmoe`,`AfmoeForCausalLM`],[`lfm2`,`Lfm2ForCausalLM`],[`lfm2_moe`,`Lfm2MoeForCausalLM`],[`smollm3`,`SmolLM3ForCausalLM`],[`exaone`,`ExaoneForCausalLM`],[`olmo`,`OlmoForCausalLM`],[`olmo2`,`Olmo2ForCausalLM`],[`olmo3`,`Olmo3ForCausalLM`],[`olmo_hybrid`,`OlmoHybridForCausalLM`],[`mobilellm`,`MobileLLMForCausalLM`],[`granite`,`GraniteForCausalLM`],[`granitemoehybrid`,`GraniteMoeHybridForCausalLM`],[`cohere`,`CohereForCausalLM`],[`cohere2`,`Cohere2ForCausalLM`],[`gemma`,`GemmaForCausalLM`],[`gemma2`,`Gemma2ForCausalLM`],[`vaultgemma`,`VaultGemmaForCausalLM`],[`gemma3_text`,`Gemma3ForCausalLM`],[`gemma3`,`Gemma3ForCausalLM`],[`helium`,`HeliumForCausalLM`],[`glm`,`GlmForCausalLM`],[`glm_moe_dsa`,`GlmMoeDsaForCausalLM`],[`openelm`,`OpenELMForCausalLM`],[`qwen2`,`Qwen2ForCausalLM`],[`qwen2_moe`,`Qwen2MoeForCausalLM`],[`qwen3`,`Qwen3ForCausalLM`],[`qwen3_moe`,`Qwen3MoeForCausalLM`],[`qwen3_next`,`Qwen3NextForCausalLM`],[`qwen2_vl`,`Qwen2VLForCausalLM`],[`qwen2_5_vl`,`Qwen2_5_VLForCausalLM`],[`qwen3_vl`,`Qwen3VLForCausalLM`],[`qwen3_vl_moe`,`Qwen3VLMoeForCausalLM`],[`qwen3_5`,`Qwen3_5ForCausalLM`],[`qwen3_5_text`,`Qwen3_5ForCausalLM`],[`qwen3_5_moe`,`Qwen3_5MoeForCausalLM`],[`gemma3n`,`Gemma3nForCausalLM`],[`gemma4`,`Gemma4ForCausalLM`],[`phi`,`PhiForCausalLM`],[`phi3`,`Phi3ForCausalLM`],[`mpt`,`MptForCausalLM`],[`opt`,`OPTForCausalLM`],[`mbart`,`MBartForCausalLM`],[`mistral`,`MistralForCausalLM`],[`mistral4`,`Mistral4ForCausalLM`],[`ministral`,`MinistralForCausalLM`],[`ministral3`,`Ministral3ForCausalLM`],[`ernie4_5`,`Ernie4_5ForCausalLM`],[`starcoder2`,`Starcoder2ForCausalLM`],[`deepseek_v3`,`DeepseekV3ForCausalLM`],[`deepseek_v4`,`DeepseekV4ForCausalLM`],[`falcon`,`FalconForCausalLM`],[`falcon_h1`,`FalconH1ForCausalLM`],[`nemotron_h`,`NemotronHForCausalLM`],[`trocr`,`TrOCRForCausalLM`],[`solar_open`,`SolarOpenForCausalLM`],[`stablelm`,`StableLmForCausalLM`],[`modernbert-decoder`,`ModernBertDecoderForCausalLM`],[`hunyuan_v1_dense`,`HunYuanDenseV1ForCausalLM`],[`youtu`,`YoutuForCausalLM`],[`zaya`,`ZayaForCausalLM`],[`hrm_text`,`HrmTextForCausalLM`],[`phi3_v`,`Phi3VForCausalLM`]]),yk=/* @__PURE__ */ new Map([[`multi_modality`,`MultiModalityCausalLM`]]),bk=/* @__PURE__ */ new Map([[`bert`,`BertForMaskedLM`],[`eurobert`,`EuroBertForMaskedLM`],[`neobert`,`NeoBertForMaskedLM`],[`modernbert`,`ModernBertForMaskedLM`],[`roformer`,`RoFormerForMaskedLM`],[`electra`,`ElectraForMaskedLM`],[`esm`,`EsmForMaskedLM`],[`convbert`,`ConvBertForMaskedLM`],[`camembert`,`CamembertForMaskedLM`],[`deberta`,`DebertaForMaskedLM`],[`deberta-v2`,`DebertaV2ForMaskedLM`],[`mpnet`,`MPNetForMaskedLM`],[`albert`,`AlbertForMaskedLM`],[`distilbert`,`DistilBertForMaskedLM`],[`roberta`,`RobertaForMaskedLM`],[`xlm`,`XLMWithLMHeadModel`],[`xlm-roberta`,`XLMRobertaForMaskedLM`],[`mobilebert`,`MobileBertForMaskedLM`],[`squeezebert`,`SqueezeBertForMaskedLM`]]),xk=/* @__PURE__ */ new Map([[`bert`,`BertForQuestionAnswering`],[`neobert`,`NeoBertForQuestionAnswering`],[`roformer`,`RoFormerForQuestionAnswering`],[`electra`,`ElectraForQuestionAnswering`],[`convbert`,`ConvBertForQuestionAnswering`],[`camembert`,`CamembertForQuestionAnswering`],[`deberta`,`DebertaForQuestionAnswering`],[`deberta-v2`,`DebertaV2ForQuestionAnswering`],[`mpnet`,`MPNetForQuestionAnswering`],[`albert`,`AlbertForQuestionAnswering`],[`distilbert`,`DistilBertForQuestionAnswering`],[`roberta`,`RobertaForQuestionAnswering`],[`xlm`,`XLMForQuestionAnswering`],[`xlm-roberta`,`XLMRobertaForQuestionAnswering`],[`mobilebert`,`MobileBertForQuestionAnswering`],[`squeezebert`,`SqueezeBertForQuestionAnswering`]]),Sk=/* @__PURE__ */ new Map([[`vision-encoder-decoder`,`VisionEncoderDecoderModel`],[`idefics3`,`Idefics3ForConditionalGeneration`],[`smolvlm`,`SmolVLMForConditionalGeneration`]]),Ck=/* @__PURE__ */ new Map([[`llava`,`LlavaForConditionalGeneration`],[`llava_onevision`,`LlavaOnevisionForConditionalGeneration`],[`moondream1`,`Moondream1ForConditionalGeneration`],[`florence2`,`Florence2ForConditionalGeneration`],[`qwen2_vl`,`Qwen2VLForConditionalGeneration`],[`qwen2_5_vl`,`Qwen2_5_VLForConditionalGeneration`],[`qwen3_vl`,`Qwen3VLForConditionalGeneration`],[`qwen3_vl_moe`,`Qwen3VLMoeForConditionalGeneration`],[`qwen3_5`,`Qwen3_5ForConditionalGeneration`],[`qwen3_5_moe`,`Qwen3_5MoeForConditionalGeneration`],[`lfm2_vl`,`Lfm2VlForConditionalGeneration`],[`idefics3`,`Idefics3ForConditionalGeneration`],[`smolvlm`,`SmolVLMForConditionalGeneration`],[`paligemma`,`PaliGemmaForConditionalGeneration`],[`llava_qwen2`,`LlavaQwen2ForCausalLM`],[`gemma3`,`Gemma3ForConditionalGeneration`],[`gemma3n`,`Gemma3nForConditionalGeneration`],[`gemma4`,`Gemma4ForConditionalGeneration`],[`mistral3`,`Mistral3ForConditionalGeneration`],[`lighton_ocr`,`LightOnOcrForConditionalGeneration`],[`glm_ocr`,`GlmOcrForConditionalGeneration`]]),wk=/* @__PURE__ */ new Map([[`granite_speech`,`GraniteSpeechForConditionalGeneration`],[`ultravox`,`UltravoxModel`],[`voxtral`,`VoxtralForConditionalGeneration`],[`voxtral_realtime`,`VoxtralRealtimeForConditionalGeneration`]]),Tk=/* @__PURE__ */ new Map([[`vision-encoder-decoder`,`VisionEncoderDecoderModel`]]),Ek=/* @__PURE__ */ new Map([[`vit`,`ViTForImageClassification`],[`ijepa`,`IJepaForImageClassification`],[`pvt`,`PvtForImageClassification`],[`vit_msn`,`ViTMSNForImageClassification`],[`fastvit`,`FastViTForImageClassification`],[`mobilevit`,`MobileViTForImageClassification`],[`mobilevitv2`,`MobileViTV2ForImageClassification`],[`beit`,`BeitForImageClassification`],[`deit`,`DeiTForImageClassification`],[`hiera`,`HieraForImageClassification`],[`convnext`,`ConvNextForImageClassification`],[`convnextv2`,`ConvNextV2ForImageClassification`],[`dinov2`,`Dinov2ForImageClassification`],[`dinov2_with_registers`,`Dinov2WithRegistersForImageClassification`],[`resnet`,`ResNetForImageClassification`],[`swin`,`SwinForImageClassification`],[`segformer`,`SegformerForImageClassification`],[`efficientnet`,`EfficientNetForImageClassification`],[`mobilenet_v1`,`MobileNetV1ForImageClassification`],[`mobilenet_v2`,`MobileNetV2ForImageClassification`],[`mobilenet_v3`,`MobileNetV3ForImageClassification`],[`mobilenet_v4`,`MobileNetV4ForImageClassification`]]),Dk=/* @__PURE__ */ new Map([[`detr`,`DetrForObjectDetection`],[`rt_detr`,`RTDetrForObjectDetection`],[`rt_detr_v2`,`RTDetrV2ForObjectDetection`],[`rf_detr`,`RFDetrForObjectDetection`],[`d_fine`,`DFineForObjectDetection`],[`table-transformer`,`TableTransformerForObjectDetection`],[`yolos`,`YolosForObjectDetection`]]),Ok=/* @__PURE__ */ new Map([[`owlvit`,`OwlViTForObjectDetection`],[`owlv2`,`Owlv2ForObjectDetection`],[`grounding-dino`,`GroundingDinoForObjectDetection`]]),kk=/* @__PURE__ */ new Map([[`detr`,`DetrForSegmentation`],[`clipseg`,`CLIPSegForImageSegmentation`]]),Ak=/* @__PURE__ */ new Map([[`segformer`,`SegformerForSemanticSegmentation`],[`sapiens`,`SapiensForSemanticSegmentation`],[`swin`,`SwinForSemanticSegmentation`],[`mobilenet_v1`,`MobileNetV1ForSemanticSegmentation`],[`mobilenet_v2`,`MobileNetV2ForSemanticSegmentation`],[`mobilenet_v3`,`MobileNetV3ForSemanticSegmentation`],[`mobilenet_v4`,`MobileNetV4ForSemanticSegmentation`]]),jk=/* @__PURE__ */ new Map([[`detr`,`DetrForSegmentation`],[`maskformer`,`MaskFormerForInstanceSegmentation`]]),Mk=/* @__PURE__ */ new Map([[`sam`,`SamModel`],[`sam2`,`Sam2Model`],[`edgetam`,`EdgeTamModel`],[`sam3_tracker`,`Sam3TrackerModel`]]),Nk=/* @__PURE__ */ new Map([[`wav2vec2`,`Wav2Vec2ForCTC`],[`wav2vec2-bert`,`Wav2Vec2BertForCTC`],[`unispeech`,`UniSpeechForCTC`],[`unispeech-sat`,`UniSpeechSatForCTC`],[`wavlm`,`WavLMForCTC`],[`hubert`,`HubertForCTC`],[`parakeet_ctc`,`ParakeetForCTC`]]),Pk=/* @__PURE__ */ new Map([[`wav2vec2`,`Wav2Vec2ForSequenceClassification`],[`wav2vec2-bert`,`Wav2Vec2BertForSequenceClassification`],[`unispeech`,`UniSpeechForSequenceClassification`],[`unispeech-sat`,`UniSpeechSatForSequenceClassification`],[`wavlm`,`WavLMForSequenceClassification`],[`hubert`,`HubertForSequenceClassification`],[`audio-spectrogram-transformer`,`ASTForAudioClassification`]]),Fk=/* @__PURE__ */ new Map([[`wavlm`,`WavLMForXVector`]]),Ik=/* @__PURE__ */ new Map([[`unispeech-sat`,`UniSpeechSatForAudioFrameClassification`],[`wavlm`,`WavLMForAudioFrameClassification`],[`wav2vec2`,`Wav2Vec2ForAudioFrameClassification`],[`pyannote`,`PyAnnoteForAudioFrameClassification`]]),Lk=/* @__PURE__ */ new Map([[`vitmatte`,`VitMatteForImageMatting`]]),Rk=/* @__PURE__ */ new Map([[`patchtst`,`PatchTSTForPrediction`],[`patchtsmixer`,`PatchTSMixerForPrediction`]]),zk=/* @__PURE__ */ new Map([[`swin2sr`,`Swin2SRForImageSuperResolution`]]),Bk=/* @__PURE__ */ new Map([[`chmv2`,`CHMv2ForDepthEstimation`],[`dpt`,`DPTForDepthEstimation`],[`depth_anything`,`DepthAnythingForDepthEstimation`],[`glpn`,`GLPNForDepthEstimation`],[`sapiens`,`SapiensForDepthEstimation`],[`depth_pro`,`DepthProForDepthEstimation`],[`metric3d`,`Metric3DForDepthEstimation`],[`metric3dv2`,`Metric3Dv2ForDepthEstimation`]]),Vk=/* @__PURE__ */ new Map([[`sapiens`,`SapiensForNormalEstimation`]]),Hk=/* @__PURE__ */ new Map([[`vitpose`,`VitPoseForPoseEstimation`]]),Uk=/* @__PURE__ */ new Map([[`clip`,`CLIPVisionModelWithProjection`],[`siglip`,`SiglipVisionModel`],[`jina_clip`,`JinaCLIPVisionModel`]]),Wk=[[ck,X.EncoderOnly],[lk,X.EncoderDecoder],[dk,X.DecoderOnlyWithoutHead],[uk,X.AutoEncoder],[hk,X.EncoderOnly],[gk,X.EncoderOnly],[_k,X.Seq2Seq],[fk,X.Seq2Seq],[vk,X.DecoderOnly],[yk,X.MultiModality],[bk,X.EncoderOnly],[xk,X.EncoderOnly],[Sk,X.Vision2Seq],[Ck,X.ImageTextToText],[wk,X.AudioTextToText],[Ek,X.EncoderOnly],[kk,X.EncoderOnly],[jk,X.EncoderOnly],[Ak,X.EncoderOnly],[Lk,X.EncoderOnly],[Rk,X.EncoderOnly],[zk,X.EncoderOnly],[Bk,X.EncoderOnly],[Vk,X.EncoderOnly],[Hk,X.EncoderOnly],[Dk,X.EncoderOnly],[Ok,X.EncoderOnly],[Mk,X.MaskGeneration],[Nk,X.EncoderOnly],[Pk,X.EncoderOnly],[pk,X.Seq2Seq],[mk,X.EncoderOnly],[Fk,X.EncoderOnly],[Ik,X.EncoderOnly],[Uk,X.EncoderOnly]];for(let[e,t]of Wk)for(let n of e.values()){wg.set(n,t);let e=Jg[n];Eg.set(e,n),Tg.set(n,e)}var Gk=[[`MusicgenForConditionalGeneration`,xw,X.Musicgen],[`Phi3VForCausalLM`,TT,X.Phi3V],[`CLIPTextModelWithProjection`,tv,X.EncoderOnly],[`SiglipTextModel`,HE,X.EncoderOnly],[`JinaCLIPTextModel`,pS,X.EncoderOnly],[`ClapTextModelWithProjection`,X_,X.EncoderOnly],[`ClapAudioModelWithProjection`,Z_,X.EncoderOnly],[`DacEncoderModel`,Hv,X.EncoderOnly],[`DacDecoderModel`,Uv,X.EncoderOnly],[`MimiEncoderModel`,nC,X.EncoderOnly],[`MimiDecoderModel`,rC,X.EncoderOnly],[`SnacEncoderModel`,XE,X.EncoderOnly],[`SnacDecoderModel`,ZE,X.EncoderOnly],[`Gemma3nForConditionalGeneration`,Vb,X.ImageAudioTextToText],[`Gemma4ForConditionalGeneration`,Ub,X.ImageAudioTextToText],[`SupertonicForConditionalGeneration`,bD,X.Supertonic],[`ChatterboxModel`,U_,X.Chatterbox],[`VoxtralRealtimeForConditionalGeneration`,xO,X.VoxtralRealtime]];for(let[e,t,n]of Gk)wg.set(e,n),Eg.set(t,e),Tg.set(e,t);var Kk=/* @__PURE__ */ new Map([[`modnet`,kk],[`birefnet`,kk],[`isnet`,kk],[`ben`,kk]]);for(let[e,t]of Kk.entries())t.set(e,`PreTrainedModel`),wg.set(e,X.EncoderOnly),Tg.set(e,Z);var qk=new Set(Kk.keys());wg.set(`PreTrainedModel`,X.EncoderOnly),Eg.set(Z,`PreTrainedModel`);var Q={MODEL_FOR_SEQUENCE_CLASSIFICATION_MAPPING_NAMES:hk,MODEL_FOR_TOKEN_CLASSIFICATION_MAPPING_NAMES:gk,MODEL_FOR_TEXT_TO_SPECTROGRAM_MAPPING_NAMES:pk,MODEL_FOR_TEXT_TO_WAVEFORM_MAPPING_NAMES:mk,MODEL_FOR_MASKED_LM_MAPPING_NAMES:bk,MODEL_FOR_QUESTION_ANSWERING_MAPPING_NAMES:xk,MODEL_FOR_IMAGE_CLASSIFICATION_MAPPING_NAMES:Ek,MODEL_FOR_IMAGE_SEGMENTATION_MAPPING_NAMES:kk,MODEL_FOR_SEMANTIC_SEGMENTATION_MAPPING_NAMES:Ak,MODEL_FOR_UNIVERSAL_SEGMENTATION_MAPPING_NAMES:jk,MODEL_FOR_OBJECT_DETECTION_MAPPING_NAMES:Dk,MODEL_FOR_ZERO_SHOT_OBJECT_DETECTION_MAPPING_NAMES:Ok,MODEL_FOR_MASK_GENERATION_MAPPING_NAMES:Mk,MODEL_FOR_CTC_MAPPING_NAMES:Nk,MODEL_FOR_AUDIO_CLASSIFICATION_MAPPING_NAMES:Pk,MODEL_FOR_AUDIO_XVECTOR_MAPPING_NAMES:Fk,MODEL_FOR_AUDIO_FRAME_CLASSIFICATION_MAPPING_NAMES:Ik,MODEL_FOR_DOCUMENT_QUESTION_ANSWERING_MAPPING_NAMES:Tk,MODEL_FOR_IMAGE_MATTING_MAPPING_NAMES:Lk,MODEL_FOR_IMAGE_TO_IMAGE_MAPPING_NAMES:zk,MODEL_FOR_DEPTH_ESTIMATION_MAPPING_NAMES:Bk,MODEL_FOR_NORMAL_ESTIMATION_MAPPING_NAMES:Vk,MODEL_FOR_POSE_ESTIMATION_MAPPING_NAMES:Hk,MODEL_FOR_IMAGE_FEATURE_EXTRACTION_MAPPING_NAMES:Uk,MODEL_FOR_IMAGE_TEXT_TO_TEXT_MAPPING_NAMES:Ck,MODEL_FOR_AUDIO_TEXT_TO_TEXT_MAPPING_NAMES:wk,MODEL_FOR_SEQ_TO_SEQ_CAUSAL_LM_MAPPING_NAMES:_k,MODEL_FOR_SPEECH_SEQ_2_SEQ_MAPPING_NAMES:fk,MODEL_FOR_CAUSAL_LM_MAPPING_NAMES:vk,MODEL_FOR_VISION_2_SEQ_MAPPING_NAMES:Sk};yg(Q);var $=class{static MODEL_CLASS_MAPPINGS=null;static BASE_IF_FAIL=!1;static supports(e){if(!this.MODEL_CLASS_MAPPINGS)return!1;for(let t of this.MODEL_CLASS_MAPPINGS)if(t.has(e))return!0;return this.BASE_IF_FAIL}static async from_pretrained(e,{progress_callback:t=null,config:n=null,cache_dir:r=null,local_files_only:i=!1,revision:a=`main`,model_file_name:o=null,subfolder:s=`onnx`,device:c=null,dtype:l=null,use_external_data_format:u=null,session_options:d={}}={}){let f={progress_callback:t,config:n,cache_dir:r,local_files_only:i,revision:a,model_file_name:o,subfolder:s,device:c,dtype:l,use_external_data_format:u,session_options:d};if(f.config=await Ch.from_pretrained(e,f),!this.MODEL_CLASS_MAPPINGS)throw Error("`MODEL_CLASS_MAPPINGS` not implemented for this type of `AutoClass`: "+this.name);let{model_type:p}=f.config;for(let t of this.MODEL_CLASS_MAPPINGS){let n=t.get(p);if(!n){for(let e of t.values())if(e[0]===p){n=e;break}if(!n)continue}return await Jg[n].from_pretrained(e,f)}if(this.BASE_IF_FAIL)return qk.has(p)||A.warn(`Unknown model class "${p}", attempting to construct from base class.`),await Z.from_pretrained(e,f);throw Error(`Unsupported model type: ${p}`)}},Jk=class extends ${static MODEL_CLASS_MAPPINGS=Wk.map(e=>e[0]);static BASE_IF_FAIL=!0},Yk=class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_SEQUENCE_CLASSIFICATION_MAPPING_NAMES]},Xk=class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_TOKEN_CLASSIFICATION_MAPPING_NAMES]},Zk=class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_SEQ_TO_SEQ_CAUSAL_LM_MAPPING_NAMES]},Qk=class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_SPEECH_SEQ_2_SEQ_MAPPING_NAMES]},$k=class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_TEXT_TO_SPECTROGRAM_MAPPING_NAMES]},eA=class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_TEXT_TO_WAVEFORM_MAPPING_NAMES]},tA=class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_CAUSAL_LM_MAPPING_NAMES]},nA=class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_MASKED_LM_MAPPING_NAMES]},rA=class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_QUESTION_ANSWERING_MAPPING_NAMES]},iA=class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_VISION_2_SEQ_MAPPING_NAMES]},aA=class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_IMAGE_CLASSIFICATION_MAPPING_NAMES]},oA=class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_IMAGE_SEGMENTATION_MAPPING_NAMES]},sA=class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_SEMANTIC_SEGMENTATION_MAPPING_NAMES]},cA=class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_UNIVERSAL_SEGMENTATION_MAPPING_NAMES]},lA=class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_OBJECT_DETECTION_MAPPING_NAMES]},uA=class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_ZERO_SHOT_OBJECT_DETECTION_MAPPING_NAMES]};(class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_MASK_GENERATION_MAPPING_NAMES]});var dA=class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_CTC_MAPPING_NAMES]},fA=class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_AUDIO_CLASSIFICATION_MAPPING_NAMES]};(class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_AUDIO_XVECTOR_MAPPING_NAMES]}),class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_AUDIO_FRAME_CLASSIFICATION_MAPPING_NAMES]};var pA=class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_DOCUMENT_QUESTION_ANSWERING_MAPPING_NAMES]};(class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_IMAGE_MATTING_MAPPING_NAMES]});var mA=class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_IMAGE_TO_IMAGE_MAPPING_NAMES]},hA=class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_DEPTH_ESTIMATION_MAPPING_NAMES]};(class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_NORMAL_ESTIMATION_MAPPING_NAMES]}),class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_POSE_ESTIMATION_MAPPING_NAMES]};var gA=class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_IMAGE_FEATURE_EXTRACTION_MAPPING_NAMES]};(class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_IMAGE_TEXT_TO_TEXT_MAPPING_NAMES]}),class extends ${static MODEL_CLASS_MAPPINGS=[Q.MODEL_FOR_AUDIO_TEXT_TO_TEXT_MAPPING_NAMES]};async function _A(e){return Array.isArray(e)||(e=[e]),await Promise.all(e.map(e=>Bf.read(e)))}async function vA(e,t){return Array.isArray(e)||(e=[e]),await Promise.all(e.map(e=>typeof e==`string`||e instanceof URL?Ud(e,t):e instanceof Float64Array?new Float32Array(e):e))}function yA(e,t){t&&(e=e.map(e=>e|0));let[n,r,i,a]=e;return{xmin:n,ymin:r,xmax:i,ymax:a}}var bA=class extends Qr{constructor({task:e,model:t,tokenizer:n=null,processor:r=null}){super(),this.task=e,this.model=t,this.tokenizer=n,this.processor=r}async dispose(){await this.model.dispose()}},xA=class extends bA{async _call(e,{top_k:t=1}={}){let n=this.tokenizer(e,{padding:!0,truncation:!0}),r=await this.model(n),{problem_type:i,id2label:a}=this.model.config,o=i===`multi_label_classification`?e=>e.sigmoid():e=>new H(`float32`,il(e.data),e.dims),s=[];for(let e of r.logits){let n=await nu(o(e),t),r=n[0].tolist(),i=n[1].tolist().map((e,t)=>({label:a?a[e]:`LABEL_${e}`,score:r[t]}));t===1?s.push(...i):s.push(i)}return Array.isArray(e)||t===1?s:s[0]}},SA=class extends bA{async _call(e,{ignore_labels:t=[`O`],aggregation_strategy:n=`none`}={}){if(n!==`none`&&n!==`simple`)throw Error(`Invalid aggregation_strategy: "${n}". Must be one of "none" or "simple".`);let r=Array.isArray(e),i=this.tokenizer(r?e:[e],{padding:!0,truncation:!0}),a=(await this.model(i)).logits,o=this.model.config.id2label,s=[];for(let e=0;e{let o=0,s=[];for(let n=i;ne==u),i=a[e].tolist(),f=o[e].tolist();for(let n=1;ne==t[n])!==-1)&&(i[n]=-1/0,f[n]=-1/0);let p=il(i).map((e,t)=>[e,t]),m=il(f).map((e,t)=>[e,t]);p[0][0]=0,m[0][0]=0;let h=ai(p,m).filter(e=>e[0][1]<=e[1][1]).map(e=>[e[0][1],e[1][1],e[0][0]*e[1][0]]).sort((e,t)=>t[2]-e[2]),g=[];for(let e=0;ee==n);if(c===-1)throw Error(`Mask token (${r}) not found in text.`);let l=a[e][c],u=await nu(new H(`float32`,il(l.data),l.dims),t),d=u[0].tolist(),f=u[1].tolist();o.push(f.map((e,t)=>{let n=i.slice();return n[c]=e,{score:d[t],token:Number(e),token_str:this.tokenizer.decode([e]),sequence:this.tokenizer.decode(n,{skip_special_tokens:!0})}}))}return Array.isArray(e)?o:o[0]}},DA=class extends bA{_default_generation_config={max_new_tokens:256};_key=`generated_text`;async _call(e,t={}){Array.isArray(e)||(e=[e]),this.model.config.prefix&&(e=e.map(e=>this.model.config.prefix+e));let n=this.model.config.task_specific_params;n&&n[this.task]&&n[this.task].prefix&&(e=e.map(e=>n[this.task].prefix+e));let r=this.tokenizer,i={padding:!0,truncation:!0},a;a=this.task===`translation`&&`_build_translation_inputs`in r?r._build_translation_inputs(e,i,t):r(e,i);let o=await this.model.generate({...a,...this._default_generation_config,...t});return r.batch_decode(o,{skip_special_tokens:!0}).map(e=>({[this._key]:e}))}},OA=class extends DA{_key=`summary_text`},kA=class extends DA{_key=`translation_text`};function AA(e){return Array.isArray(e)&&e.every(e=>`role`in e&&`content`in e)}var jA=class extends bA{_default_generation_config={max_new_tokens:256};async _call(e,t={}){let{add_special_tokens:n,return_full_text:r,tools:i,documents:a,chat_template:o,tokenizer_encode_kwargs:s,...c}=t,l=!1,u=!1,d=n??(this.tokenizer.add_bos_token||this.tokenizer.add_eos_token)??!1,f=s,p;if(typeof e==`string`)p=e=[e];else if(Array.isArray(e)&&e.every(e=>typeof e==`string`))l=!0,p=e;else{if(AA(e))e=[e];else if(Array.isArray(e)&&e.every(AA))l=!0;else throw Error(`Input must be a string, an array of strings, a Chat, or an array of Chats`);u=!0;let t={tokenize:!1,add_generation_prompt:!0,...si({tools:i,documents:a,chat_template:o},[`tools`,`documents`,`chat_template`]),...f};p=e.map(e=>this.tokenizer.apply_chat_template(e,t)),d=!1,f=void 0}let m=u?!1:r??!0;this.tokenizer.padding_side=`left`;let h=this.tokenizer(p,{add_special_tokens:d,padding:!0,truncation:!0,...f}),g=await this.model.generate({...h,...this._default_generation_config,...c}),_=this.tokenizer.batch_decode(g,{skip_special_tokens:!0}),v;!m&&h.input_ids.dims.at(-1)>0&&(v=this.tokenizer.batch_decode(h.input_ids,{skip_special_tokens:!0}).map(e=>e.length));let y=Array.from({length:e.length},e=>[]);for(let t=0;t<_.length;++t){let n=Math.floor(t/g.dims[0]*e.length);v&&(_[t]=_[t].slice(v[n])),y[n].push({generated_text:u?[...e[n],{role:`assistant`,content:_[t]}]:_[t]})}return!l&&y.length===1?y[0]:y}},MA=class extends bA{constructor(e){super(e),this.label2id=Object.fromEntries(Object.entries(this.model.config.label2id).map(([e,t])=>[e.toLowerCase(),t])),this.entailment_id=this.label2id.entailment,this.entailment_id===void 0&&(A.warn(`Could not find 'entailment' in label2id mapping. Using 2 as entailment_id.`),this.entailment_id=2),this.contradiction_id=this.label2id.contradiction??this.label2id.not_entailment,this.contradiction_id===void 0&&(A.warn(`Could not find 'contradiction' in label2id mapping. Using 0 as contradiction_id.`),this.contradiction_id=0)}async _call(e,t,{hypothesis_template:n=`This example is {}.`,multi_label:r=!1}={}){let i=Array.isArray(e);i||(e=[e]),Array.isArray(t)||(t=[t]);let a=t.map(e=>n.replace(`{}`,e)),o=r||t.length===1,s=[];for(let n of e){let e=[];for(let t of a){let r=this.tokenizer(n,{text_pair:t,padding:!0,truncation:!0}),i=await this.model(r);o?e.push([i.logits.data[this.contradiction_id],i.logits.data[this.entailment_id]]):e.push(i.logits.data[this.entailment_id])}let r=(o?e.map(e=>il(e)[1]):il(e)).map((e,t)=>[e,t]).sort((e,t)=>t[0]-e[0]);s.push({sequence:n,labels:r.map(e=>t[e[1]]),scores:r.map(e=>e[0])})}return i?s:s[0]}},NA=class extends bA{async _call(e,{top_k:t=5}={}){let n=this.processor.feature_extractor.config.sampling_rate,r=await vA(e,n),i=this.model.config.id2label,a=[];for(let e of r){let n=await this.processor(e),r=(await this.model(n)).logits[0],o=await nu(new H(`float32`,il(r.data),r.dims),t),s=o[0].tolist(),c=o[1].tolist().map((e,t)=>({label:i?i[e]:`LABEL_${e}`,score:s[t]}));a.push(c)}return Array.isArray(e)?a:a[0]}},PA=class extends bA{async _call(e,t,{hypothesis_template:n=`This is a sound of {}.`}={}){let r=!Array.isArray(e);r&&(e=[e]);let i=t.map(e=>n.replace(`{}`,e)),a=this.tokenizer(i,{padding:!0,truncation:!0}),o=this.processor.feature_extractor.config.sampling_rate,s=await vA(e,o),c=[];for(let e of s){let n=await this.processor(e),r=il((await this.model({...a,...n})).logits_per_audio.data);c.push([...r].map((e,n)=>({score:e,label:t[n]})))}return r?c[0]:c}},FA=class extends bA{_default_generation_config={};async _call(e,t={}){switch(t={...this._default_generation_config,...t},this.model.config.model_type){case`whisper`:case`lite-whisper`:return this._call_whisper(e,t);case`wav2vec2`:case`wav2vec2-bert`:case`unispeech`:case`unispeech-sat`:case`hubert`:case`parakeet_ctc`:return this._call_wav2vec2(e,t);case`moonshine`:return this._call_moonshine(e,t);case`cohere_asr`:return this._call_cohere_asr(e,t);default:throw Error(`AutomaticSpeechRecognitionPipeline does not support model type '${this.model.config.model_type}'.`)}}async _call_wav2vec2(e,t){t.language&&A.warn('`language` parameter is not yet supported for `wav2vec2` models, defaulting to "English".'),t.task&&A.warn('`task` parameter is not yet supported for `wav2vec2` models, defaulting to "transcribe".');let n=!Array.isArray(e),r=n?[e]:e,i=this.processor.feature_extractor.config.sampling_rate,a=await vA(r,i),o=[];for(let e of a){let t=await this.processor(e),n=(await this.model(t)).logits[0],r=[];for(let e of n)r.push(sl(e.data)[1]);let i=this.tokenizer.decode(r,{skip_special_tokens:!0}).trim();o.push({text:i})}return n?o[0]:o}async _call_whisper(e,t){let n=t.return_timestamps??!1,r=t.chunk_length_s??0,i=t.force_full_sequences??!1,a=t.stride_length_s??null,o={...t};n===`word`&&(o.return_token_timestamps=!0,o.return_timestamps=!0);let s=!Array.isArray(e),c=s?[e]:e,l=this.processor.feature_extractor.config,u=l.chunk_length/this.model.config.max_source_positions,d=l.hop_length,f=l.sampling_rate,p=await vA(c,f),m=[];for(let e of p){let t=[];if(r>0){if(a===null)a=r/6;else if(r<=a)throw Error("`chunk_length_s` must be larger than `stride_length_s`.");let n=f*r,i=f*a,o=n-2*i,s=0;for(;;){let r=s+n,a=e.subarray(s,r),c=await this.processor(a),l=s===0,u=r>=e.length;if(t.push({stride:[a.length,l?0:i,u?0:i],input_features:c.input_features,is_last:u}),u)break;s+=o}}else t=[{stride:[e.length,0,0],input_features:(await this.processor(e)).input_features,is_last:!0}];for(let e of t){o.num_frames=Math.floor(e.stride[0]/d);let t=await this.model.generate({inputs:e.input_features,...o});if(n===`word`){let n=t.sequences.tolist()[0],r=t.token_timestamps.tolist()[0],i=this.tokenizer.timestamp_begin,a=Math.max(n.findIndex(e=>Number(e)>=i),0);e.tokens=n.slice(a),e.token_timestamps=r.slice(a).map(e=>pl(e,2))}else e.tokens=t[0].tolist();e.stride=e.stride.map(e=>e/f)}let[s,c]=this.tokenizer._decode_asr(t,{time_precision:u,return_timestamps:n,force_full_sequences:i});m.push({text:s,...c})}return s?m[0]:m}async _call_moonshine(e,t){let n=!Array.isArray(e),r=n?[e]:e,i=this.processor.feature_extractor.config.sampling_rate,a=await vA(r,i),o=[];for(let e of a){let n=await this.processor(e),r=Math.floor(e.length/i)*6,a=await this.model.generate({max_new_tokens:r,...t,...n}),s=this.tokenizer.batch_decode(a,{skip_special_tokens:!0})[0];o.push({text:s})}return n?o[0]:o}async _call_cohere_asr(e,t){let n=!Array.isArray(e),r=n?[e]:e,i=this.processor.feature_extractor,a=i.config.sampling_rate,o=await vA(r,a),s=t.language??`en`,c=this.processor.get_decoder_prompt_ids(s),l=[];for(let e of o){let n=i.split_audio(e),r=[];for(let e of n){let n=await this.processor(e),i=await this.model.generate({...n,decoder_input_ids:c,...t}),a=this.tokenizer.decode(i[0].tolist(),{skip_special_tokens:!0}).trim();r.push(a)}let a=this.processor.constructor.join_chunks(r,s);l.push({text:a})}return n?l[0]:l}},IA=class extends bA{DEFAULT_VOCODER_ID=`Xenova/speecht5_hifigan`;constructor(e){super(e),this.vocoder=e.vocoder??null}async _prepare_speaker_embeddings(e,t){if((typeof e==`string`||e instanceof URL)&&(e=new Float32Array(await(await k.fetch(e)).arrayBuffer())),e instanceof Float32Array)e=new H(`float32`,e,[e.length]);else if(!(e instanceof H))throw Error("Speaker embeddings must be a `Tensor`, `Float32Array`, `string`, or `URL`.");if(t>1){if(e.dims[0]===1)e=e.repeat(t,1);else if(e.dims[0]!==t)throw Error(`Expected speaker embeddings batch size to be 1 or ${t}, but got ${e.dims[0]}.`)}return e}_postprocess_waveform(e,t,n,r=null){let i=t.data,[a,o]=t.dims,s=r?r.data:null,c=[];for(let e=0;e({generated_text:e.trim()}));a.push(r)}return n?a:a[0]}},RA=class extends bA{async _call(e,{top_k:t=5}={}){let n=await _A(e),{pixel_values:r}=await this.processor(n),i=await this.model({pixel_values:r}),{id2label:a}=this.model.config,o=[];for(let e of i.logits){let n=await nu(new H(`float32`,il(e.data),e.dims),t),r=n[0].tolist(),i=n[1].tolist().map((e,t)=>({label:a?a[e]:`LABEL_${e}`,score:r[t]}));o.push(i)}return Array.isArray(e)?o:o[0]}},zA={panoptic:`post_process_panoptic_segmentation`,instance:`post_process_instance_segmentation`,semantic:`post_process_semantic_segmentation`},BA=class extends bA{async _call(e,{threshold:t=.5,mask_threshold:n=.5,overlap_mask_area_threshold:r=.8,label_ids_to_fuse:i=null,target_sizes:a=null,subtask:o=null}={}){if(Array.isArray(e)&&e.length!==1)throw Error(`Image segmentation pipeline currently only supports a batch size of 1.`);let s=await _A(e),c=s.map(e=>[e.height,e.width]),l=await this.processor(s),{inputNames:u,outputNames:d}=this.model.sessions.model;if(!u.includes(`pixel_values`)){if(u.length!==1)throw Error(`Expected a single input name, but got ${u.length} inputs: ${u}.`);let e=u[0];if(e in l)throw Error(`Input name ${e} already exists in the inputs.`);l[e]=l.pixel_values}let f=await this.model(l),p=null;if(o!==null)p=zA[o];else if(this.processor.image_processor){for(let[e,t]of Object.entries(zA))if(t in this.processor.image_processor){p=this.processor.image_processor[t].bind(this.processor.image_processor),o=e;break}}let m=this.model.config.id2label,h=[];if(!o){let e=f[d[0]];for(let t=0;te<-1e-5||e>1.00001)&&r.sigmoid_();let i=await Bf.fromTensor(r.mul_(255).to(`uint8`)).resize(n[1],n[0]);h.push({label:null,score:null,mask:i})}}else if(o===`panoptic`||o===`instance`){let e=p(f,t,n,r,i,a??c)[0],o=e.segmentation;for(let t of e.segments_info){let e=new Uint8ClampedArray(o.data.length);for(let n=0;n{let n=e.clone();return n.putAlpha(r[t].mask),n});return Array.isArray(e)?i:i[0]}},model:[oA,sA,cA],default:{model:`Xenova/modnet`},type:`image`},"zero-shot-image-classification":{pipeline:class extends bA{async _call(e,t,{hypothesis_template:n=`This is a photo of {}`}={}){let r=Array.isArray(e),i=await _A(e),a=t.map(e=>n.replace(`{}`,e)),o=this.tokenizer(a,{padding:this.model.config.model_type!==`siglip`||`max_length`,truncation:!0}),{pixel_values:s}=await this.processor(i),c=await this.model({...o,pixel_values:s}),l=this.model.config.model_type===`siglip`?e=>e.sigmoid().data:e=>il(e.data),u=[];for(let e of c.logits_per_image){let n=[...l(e)].map((e,n)=>({score:e,label:t[n]}));n.sort((e,t)=>t.score-e.score),u.push(n)}return r?u:u[0]}},model:Jk,default:{model:`Xenova/clip-vit-base-patch32`},type:`multimodal`},"object-detection":{pipeline:class extends bA{async _call(e,{threshold:t=.9,percentage:n=!1}={}){let r=Array.isArray(e);if(r&&e.length!==1)throw Error(`Object detection pipeline currently only supports a batch size of 1.`);let i=await _A(e),a=n?null:i.map(e=>[e.height,e.width]),{pixel_values:o,pixel_mask:s}=await this.processor(i),c=await this.model({pixel_values:o,pixel_mask:s}),l=this.processor.image_processor.post_process_object_detection(c,t,a),{id2label:u}=this.model.config,d=l.map(e=>e.boxes.map((t,r)=>({score:e.scores[r],label:u[e.classes[r]],box:yA(t,!n)})));return r?d:d[0]}},model:lA,default:{model:`Xenova/detr-resnet-50`},type:`multimodal`},"zero-shot-object-detection":{pipeline:class extends bA{async _call(e,t,{threshold:n=.1,top_k:r=null,percentage:i=!1}={}){let a=Array.isArray(e),o=await _A(e),s=this.tokenizer(t,{padding:!0,truncation:!0}),c=await this.processor(o),l=[];for(let e=0;e({score:e.scores[n],label:e.labels[n],box:yA(t,!i)}))}else{let e=this.processor.image_processor.post_process_object_detection(f,n,u,!0)[0];p=e.boxes.map((n,r)=>({score:e.scores[r],label:t[e.classes[r]],box:yA(n,!i)}))}p.sort((e,t)=>t.score-e.score),r!==null&&(p=p.slice(0,r)),l.push(p)}return a?l:l[0]}},model:uA,default:{model:`Xenova/owlvit-base-patch32`},type:`multimodal`},"document-question-answering":{pipeline:class extends bA{_default_generation_config={max_new_tokens:256};async _call(e,t,n={}){if(Array.isArray(e)){if(e.length!==1)throw Error(`Document Question Answering pipeline currently only supports a batch size of 1.`);e=e[0]}let r=(await _A(e))[0],{pixel_values:i}=await this.processor(r),a=`${t}`,o=this.tokenizer(a,{add_special_tokens:!1,padding:!0,truncation:!0}).input_ids,s=await this.model.generate({inputs:i,max_length:this.model.config.decoder.max_position_embeddings,decoder_input_ids:o,...this._default_generation_config,...n}),c=this.tokenizer.batch_decode(s)[0].match(/(.*?)<\/s_answer>/),l=null;return c&&c.length>=2&&(l=c[1].trim()),[{answer:l}]}},model:pA,default:{model:`Xenova/donut-base-finetuned-docvqa`},type:`multimodal`},"image-to-image":{pipeline:class extends bA{async _call(e){let t=await _A(e),n=await this.processor(t),r=await this.model(n),i=[];for(let e of r.reconstruction){let t=e.squeeze().clamp_(0,1).mul_(255).round_().to(`uint8`);i.push(Bf.fromTensor(t))}return Array.isArray(e)?i:i[0]}},model:mA,default:{model:`Xenova/swin2SR-classical-sr-x2-64`},type:`image`},"depth-estimation":{pipeline:class extends bA{async _call(e){let t=await _A(e),n=await this.processor(t),{predicted_depth:r}=await this.model(n),i=[];for(let e=0;e`onnx/${e}`);return s.filter(e=>!e.startsWith(`onnx/`)||t.some(t=>e.startsWith(t)))}}return s}async function KA(e,t=null,{progress_callback:n=null,config:r=null,cache_dir:i=null,local_files_only:a=!1,revision:o=`main`,device:s=null,dtype:c=null,subfolder:l=`onnx`,use_external_data_format:u=null,model_file_name:d=null,session_options:f={}}={}){e=HA[e]??e;let p=VA[e.split(`_`,1)[0]];if(!p)throw Error(`Unsupported pipeline: ${e}. Must be one of [${Object.keys(VA)}]`);t||(t=p.default.model,A.info(`No model specified. Using default model: "${t}".`),!c&&p.default.dtype&&(c=p.default.dtype));let m=await GA(e,t,{device:s,dtype:c}),h={};if(n)try{(await Promise.all(m.map(async e=>Wc(t,e)))).forEach((e,t)=>{e.exists&&(h[m[t]]={loaded:0,total:e.size??0})})}catch(e){A.warn(`Unable to fetch model file metadata for total progress tracking: ${e}`)}let g={progress_callback:n?new ei(n,h):void 0,config:r,cache_dir:i,local_files_only:a,revision:o,device:s,dtype:c,subfolder:l,use_external_data_format:u,model_file_name:d,session_options:f},_=m.includes(`tokenizer.json`),v=m.includes(`preprocessor_config.json`),y=p.model,b;if(Array.isArray(y)){let n=r??await Ch.from_pretrained(t,g),{model_type:i}=n,a=y.find(e=>e.supports(i));if(!a)throw Error(`Unsupported model type "${i}" for task "${e}". None of the candidate model classes support this type.`);b=a.from_pretrained(t,{...g,config:n})}else b=y.from_pretrained(t,g);let[x,S,C]=await Promise.all([_?G.from_pretrained(t,g):null,v?_h.from_pretrained(t,g):null,b]),ee={task:e,model:C};x&&(ee.tokenizer=x),S&&(ee.processor=S),$r(n,{status:`ready`,task:e,model:t});let te=p.pipeline;return new te(ee)}O.IS_PROCESS_AVAILABLE,Object.keys(Jl);let qA={inputSize:770,modelId:`onnx-community/depth-anything-v2-small-ONNX`,modelName:`Small`},JA=KA,YA=self,XA=null,ZA=null;function QA(e,t=[]){YA.postMessage(e,t)}function $A(e,t){QA({type:`status`,id:e,message:t})}async function ej(e,t){$A(t,`출발 준비 중…`);let n=await JA(`depth-estimation`,qA.modelId,{device:e.device,dtype:e.dtype,progress_callback:e=>{e.status===`progress`?$A(t,`출발 준비 중 · ${Math.round(e.progress??0)}%`):(e.status===`initiate`||e.status===`download`)&&$A(t,`출발 준비 중…`)}});return n.processor.image_processor.size={width:qA.inputSize,height:qA.inputSize},n}async function tj(e,t){if(XA&&ZA?.device===t.device&&ZA.dtype===t.dtype)return XA;let n=XA;return XA=null,ZA=null,n&&await n.dispose(),XA=await ej(t,e),ZA={...t},XA}function nj(e){let{predicted_depth:t}=e,[n,r]=t.dims.slice(-2),i=t.data;if(!r||!n||i.length!==r*n)throw Error(`모델이 유효한 depth 크기를 반환하지 않았습니다.`);let a=1/0,o=-1/0;for(let e=0;e{let n=performance.now(),r;try{r=await tj(e,t)}finally{i+=performance.now()-n}$A(e,`내비게이션으로 길을 찾는 중…`);let s=performance.now();try{let e=await r(o);if(Array.isArray(e))throw Error(`단일 사진 결과를 읽을 수 없습니다.`);return e}finally{a+=performance.now()-s}},d;try{d=await u(l)}catch(t){if(l.device!==`webgpu`)throw t;let n=XA;XA=null,ZA=null;let r=performance.now();try{await n?.dispose()}catch{}i+=performance.now()-r,QA({type:`fallback`,id:e,preparationMs:i,inferenceMs:a});return}try{let t=nj(d),n=t.values.buffer,o=t.normalizedValues.buffer,s={model:`small`,...l,preparationMs:i,inferenceMs:a,totalMs:performance.now()-r};QA({type:`result`,id:e,width:t.width,height:t.height,values:n,normalizedValues:o,run:s},[n,o])}finally{d.predicted_depth.dispose()}}catch(t){QA({type:`error`,id:e,message:t instanceof Error?t.message:`AI depth 생성에 실패했습니다.`})}finally{t.close()}}YA.addEventListener(`message`,e=>{e.data.type===`infer`&&ij(e.data)})})(); \ No newline at end of file diff --git a/dist/assets/aiDepth.worker-DnfO2O4Q.js b/dist/assets/aiDepth.worker-DnfO2O4Q.js deleted file mode 100644 index a81fffe..0000000 --- a/dist/assets/aiDepth.worker-DnfO2O4Q.js +++ /dev/null @@ -1,2896 +0,0 @@ -var n1=Object.defineProperty;var o1=($s,Gr,jn)=>Gr in $s?n1($s,Gr,{enumerable:!0,configurable:!0,writable:!0,value:jn}):$s[Gr]=jn;var J=($s,Gr,jn)=>o1($s,typeof Gr!="symbol"?Gr+"":Gr,jn);(function(){"use strict";const $s=new Map,Gr=[],jn=(e,r,t)=>{if(r&&typeof r.init=="function"&&typeof r.createInferenceSessionHandler=="function"){const s=$s.get(e);if(s===void 0)$s.set(e,{backend:r,priority:t});else{if(s.priority>t)return;if(s.priority===t&&s.backend!==r)throw new Error(`cannot register backend "${e}" using priority ${t}`)}if(t>=0){const o=Gr.indexOf(e);o!==-1&&Gr.splice(o,1);for(let n=0;n{const r=$s.get(e);if(!r)return"backend not found.";if(r.initialized)return r.backend;if(r.aborted)return r.error;{const t=!!r.initPromise;try{return t||(r.initPromise=r.backend.init(e)),await r.initPromise,r.initialized=!0,r.backend}catch(s){return t||(r.error=`${s}`,r.aborted=!0),r.error}finally{delete r.initPromise}}},Jv=async e=>{const r=e.executionProviders||[],t=r.map(l=>typeof l=="string"?l:l.name),s=t.length===0?Gr:t;let o;const n=[],a=new Set;for(const l of s){const c=await Xv(l);typeof c=="string"?n.push({name:l,err:c}):(o||(o=c),o===c&&a.add(l))}if(!o)throw new Error(`no available backend found. ERR: ${n.map(l=>`[${l.name}] ${l.err}`).join(", ")}`);for(const{name:l,err:c}of n)t.includes(l)&&console.warn(`removing requested execution provider "${l}" from session options because it is not available: ${c}`);const i=r.filter(l=>a.has(typeof l=="string"?l:l.name));return[o,new Proxy(e,{get:(l,c)=>c==="executionProviders"?i:Reflect.get(l,c)})]},Yv="1.21.0";let Gu="warning";const ms={wasm:{},webgl:{},webgpu:{},versions:{common:Yv},set logLevel(e){if(e!==void 0){if(typeof e!="string"||["verbose","info","warning","error","fatal"].indexOf(e)===-1)throw new Error(`Unsupported logging level: ${e}`);Gu=e}},get logLevel(){return Gu}};Object.defineProperty(ms,"logLevel",{enumerable:!0});const Zv=ms,ex=(e,r)=>{const t=typeof document<"u"?document.createElement("canvas"):new OffscreenCanvas(1,1);t.width=e.dims[3],t.height=e.dims[2];const s=t.getContext("2d");if(s!=null){let o,n;(r==null?void 0:r.tensorLayout)!==void 0&&r.tensorLayout==="NHWC"?(o=e.dims[2],n=e.dims[3]):(o=e.dims[3],n=e.dims[2]);const a=(r==null?void 0:r.format)!==void 0?r.format:"RGB",i=r==null?void 0:r.norm;let l,c;i===void 0||i.mean===void 0?l=[255,255,255,255]:typeof i.mean=="number"?l=[i.mean,i.mean,i.mean,i.mean]:(l=[i.mean[0],i.mean[1],i.mean[2],0],i.mean[3]!==void 0&&(l[3]=i.mean[3])),i===void 0||i.bias===void 0?c=[0,0,0,0]:typeof i.bias=="number"?c=[i.bias,i.bias,i.bias,i.bias]:(c=[i.bias[0],i.bias[1],i.bias[2],0],i.bias[3]!==void 0&&(c[3]=i.bias[3]));const p=n*o;let d=0,u=p,f=p*2,_=-1;a==="RGBA"?(d=0,u=p,f=p*2,_=p*3):a==="RGB"?(d=0,u=p,f=p*2):a==="RBG"&&(d=0,f=p,u=p*2);for(let b=0;b{const t=typeof document<"u"?document.createElement("canvas").getContext("2d"):new OffscreenCanvas(1,1).getContext("2d");let s;if(t!=null){let o,n,a;(r==null?void 0:r.tensorLayout)!==void 0&&r.tensorLayout==="NHWC"?(o=e.dims[2],n=e.dims[1],a=e.dims[3]):(o=e.dims[3],n=e.dims[2],a=e.dims[1]);const i=r!==void 0&&r.format!==void 0?r.format:"RGB",l=r==null?void 0:r.norm;let c,p;l===void 0||l.mean===void 0?c=[255,255,255,255]:typeof l.mean=="number"?c=[l.mean,l.mean,l.mean,l.mean]:(c=[l.mean[0],l.mean[1],l.mean[2],255],l.mean[3]!==void 0&&(c[3]=l.mean[3])),l===void 0||l.bias===void 0?p=[0,0,0,0]:typeof l.bias=="number"?p=[l.bias,l.bias,l.bias,l.bias]:(p=[l.bias[0],l.bias[1],l.bias[2],0],l.bias[3]!==void 0&&(p[3]=l.bias[3]));const d=n*o;if(r!==void 0&&(r.format!==void 0&&a===4&&r.format!=="RGBA"||a===3&&r.format!=="RGB"&&r.format!=="BGR"))throw new Error("Tensor format doesn't match input tensor dims");const u=4;let f=0,_=1,b=2,k=3,w=0,y=d,$=d*2,T=-1;i==="RGBA"?(w=0,y=d,$=d*2,T=d*3):i==="RGB"?(w=0,y=d,$=d*2):i==="RBG"&&(w=0,$=d,y=d*2),s=t.createImageData(o,n);for(let M=0;M{if(e===void 0)throw new Error("Image buffer must be defined");if(r.height===void 0||r.width===void 0)throw new Error("Image height and width must be defined");if(r.tensorLayout==="NHWC")throw new Error("NHWC Tensor layout is not supported yet");const{height:t,width:s}=r,o=r.norm??{mean:255,bias:0};let n,a;typeof o.mean=="number"?n=[o.mean,o.mean,o.mean,o.mean]:n=[o.mean[0],o.mean[1],o.mean[2],o.mean[3]??255],typeof o.bias=="number"?a=[o.bias,o.bias,o.bias,o.bias]:a=[o.bias[0],o.bias[1],o.bias[2],o.bias[3]??0];const i=r.format!==void 0?r.format:"RGBA",l=r.tensorFormat!==void 0&&r.tensorFormat!==void 0?r.tensorFormat:"RGB",c=t*s,p=l==="RGBA"?new Float32Array(c*4):new Float32Array(c*3);let d=4,u=0,f=1,_=2,b=3,k=0,w=c,y=c*2,$=-1;i==="RGB"&&(d=3,u=0,f=1,_=2,b=-1),l==="RGBA"?$=c*3:l==="RBG"?(k=0,y=c,w=c*2):l==="BGR"&&(y=0,w=c,k=c*2);for(let M=0;M{const t=typeof HTMLImageElement<"u"&&e instanceof HTMLImageElement,s=typeof ImageData<"u"&&e instanceof ImageData,o=typeof ImageBitmap<"u"&&e instanceof ImageBitmap,n=typeof e=="string";let a,i=r??{};const l=()=>{if(typeof document<"u")return document.createElement("canvas");if(typeof OffscreenCanvas<"u")return new OffscreenCanvas(1,1);throw new Error("Canvas is not supported")},c=p=>typeof HTMLCanvasElement<"u"&&p instanceof HTMLCanvasElement||p instanceof OffscreenCanvas?p.getContext("2d"):null;if(t){const p=l();p.width=e.width,p.height=e.height;const d=c(p);if(d!=null){let u=e.height,f=e.width;if(r!==void 0&&r.resizedHeight!==void 0&&r.resizedWidth!==void 0&&(u=r.resizedHeight,f=r.resizedWidth),r!==void 0){if(i=r,r.tensorFormat!==void 0)throw new Error("Image input config format must be RGBA for HTMLImageElement");i.tensorFormat="RGBA",i.height=u,i.width=f}else i.tensorFormat="RGBA",i.height=u,i.width=f;d.drawImage(e,0,0),a=d.getImageData(0,0,f,u).data}else throw new Error("Can not access image data")}else if(s){let p,d;if(r!==void 0&&r.resizedWidth!==void 0&&r.resizedHeight!==void 0?(p=r.resizedHeight,d=r.resizedWidth):(p=e.height,d=e.width),r!==void 0&&(i=r),i.format="RGBA",i.height=p,i.width=d,r!==void 0){const u=l();u.width=d,u.height=p;const f=c(u);if(f!=null)f.putImageData(e,0,0),a=f.getImageData(0,0,d,p).data;else throw new Error("Can not access image data")}else a=e.data}else if(o){if(r===void 0)throw new Error("Please provide image config with format for Imagebitmap");const p=l();p.width=e.width,p.height=e.height;const d=c(p);if(d!=null){const u=e.height,f=e.width;return d.drawImage(e,0,0,f,u),a=d.getImageData(0,0,f,u).data,i.height=u,i.width=f,yi(a,i)}else throw new Error("Can not access image data")}else{if(n)return new Promise((p,d)=>{const u=l(),f=c(u);if(!e||!f)return d();const _=new Image;_.crossOrigin="Anonymous",_.src=e,_.onload=()=>{u.width=_.width,u.height=_.height,f.drawImage(_,0,0,u.width,u.height);const b=f.getImageData(0,0,u.width,u.height);i.height=u.height,i.width=u.width,p(yi(b.data,i))}});throw new Error("Input data provided is not supported - aborted tensor creation")}if(a!==void 0)return yi(a,i);throw new Error("Input data provided is not supported - aborted tensor creation")},sx=(e,r)=>{const{width:t,height:s,download:o,dispose:n}=r,a=[1,s,t,4];return new os({location:"texture",type:"float32",texture:e,dims:a,download:o,dispose:n})},nx=(e,r)=>{const{dataType:t,dims:s,download:o,dispose:n}=r;return new os({location:"gpu-buffer",type:t??"float32",gpuBuffer:e,dims:s,download:o,dispose:n})},ox=(e,r)=>{const{dataType:t,dims:s,download:o,dispose:n}=r;return new os({location:"ml-tensor",type:t??"float32",mlTensor:e,dims:s,download:o,dispose:n})},ax=(e,r,t)=>new os({location:"cpu-pinned",type:e,data:r,dims:t??[r.length]}),Nn=new Map([["float32",Float32Array],["uint8",Uint8Array],["int8",Int8Array],["uint16",Uint16Array],["int16",Int16Array],["int32",Int32Array],["bool",Uint8Array],["float64",Float64Array],["uint32",Uint32Array],["int4",Uint8Array],["uint4",Uint8Array]]),ea=new Map([[Float32Array,"float32"],[Uint8Array,"uint8"],[Int8Array,"int8"],[Uint16Array,"uint16"],[Int16Array,"int16"],[Int32Array,"int32"],[Float64Array,"float64"],[Uint32Array,"uint32"]]);let Ku=!1;const ix=()=>{if(!Ku){Ku=!0;const e=typeof BigInt64Array<"u"&&BigInt64Array.from,r=typeof BigUint64Array<"u"&&BigUint64Array.from,t=globalThis.Float16Array,s=typeof t<"u"&&t.from;e&&(Nn.set("int64",BigInt64Array),ea.set(BigInt64Array,"int64")),r&&(Nn.set("uint64",BigUint64Array),ea.set(BigUint64Array,"uint64")),s?(Nn.set("float16",t),ea.set(t,"float16")):Nn.set("float16",Uint16Array)}},lx=e=>{let r=1;for(let t=0;t{switch(e.location){case"cpu":return new os(e.type,e.data,r);case"cpu-pinned":return new os({location:"cpu-pinned",data:e.data,type:e.type,dims:r});case"texture":return new os({location:"texture",texture:e.texture,type:e.type,dims:r});case"gpu-buffer":return new os({location:"gpu-buffer",gpuBuffer:e.gpuBuffer,type:e.type,dims:r});case"ml-tensor":return new os({location:"ml-tensor",mlTensor:e.mlTensor,type:e.type,dims:r});default:throw new Error(`tensorReshape: tensor location ${e.location} is not supported`)}};let os=class{constructor(r,t,s){ix();let o,n;if(typeof r=="object"&&"location"in r)switch(this.dataLocation=r.location,o=r.type,n=r.dims,r.location){case"cpu-pinned":{const i=Nn.get(o);if(!i)throw new TypeError(`unsupported type "${o}" to create tensor from pinned buffer`);if(!(r.data instanceof i))throw new TypeError(`buffer should be of type ${i.name}`);this.cpuData=r.data;break}case"texture":{if(o!=="float32")throw new TypeError(`unsupported type "${o}" to create tensor from texture`);this.gpuTextureData=r.texture,this.downloader=r.download,this.disposer=r.dispose;break}case"gpu-buffer":{if(o!=="float32"&&o!=="float16"&&o!=="int32"&&o!=="int64"&&o!=="uint32"&&o!=="uint8"&&o!=="bool"&&o!=="uint4"&&o!=="int4")throw new TypeError(`unsupported type "${o}" to create tensor from gpu buffer`);this.gpuBufferData=r.gpuBuffer,this.downloader=r.download,this.disposer=r.dispose;break}case"ml-tensor":{if(o!=="float32"&&o!=="float16"&&o!=="int32"&&o!=="int64"&&o!=="uint32"&&o!=="uint64"&&o!=="int8"&&o!=="uint8"&&o!=="bool"&&o!=="uint4"&&o!=="int4")throw new TypeError(`unsupported type "${o}" to create tensor from MLTensor`);this.mlTensorData=r.mlTensor,this.downloader=r.download,this.disposer=r.dispose;break}default:throw new Error(`Tensor constructor: unsupported location '${this.dataLocation}'`)}else{let i,l;if(typeof r=="string")if(o=r,l=s,r==="string"){if(!Array.isArray(t))throw new TypeError("A string tensor's data must be a string array.");i=t}else{const c=Nn.get(r);if(c===void 0)throw new TypeError(`Unsupported tensor type: ${r}.`);if(Array.isArray(t)){if(r==="float16"&&c===Uint16Array||r==="uint4"||r==="int4")throw new TypeError(`Creating a ${r} tensor from number array is not supported. Please use ${c.name} as data.`);r==="uint64"||r==="int64"?i=c.from(t,BigInt):i=c.from(t)}else if(t instanceof c)i=t;else if(t instanceof Uint8ClampedArray)if(r==="uint8")i=Uint8Array.from(t);else throw new TypeError("A Uint8ClampedArray tensor's data must be type of uint8");else if(r==="float16"&&t instanceof Uint16Array&&c!==Uint16Array)i=new globalThis.Float16Array(t.buffer,t.byteOffset,t.length);else throw new TypeError(`A ${o} tensor's data must be type of ${c}`)}else if(l=t,Array.isArray(r)){if(r.length===0)throw new TypeError("Tensor type cannot be inferred from an empty array.");const c=typeof r[0];if(c==="string")o="string",i=r;else if(c==="boolean")o="bool",i=Uint8Array.from(r);else throw new TypeError(`Invalid element type of data array: ${c}.`)}else if(r instanceof Uint8ClampedArray)o="uint8",i=Uint8Array.from(r);else{const c=ea.get(r.constructor);if(c===void 0)throw new TypeError(`Unsupported type for tensor data: ${r.constructor}.`);o=c,i=r}if(l===void 0)l=[i.length];else if(!Array.isArray(l))throw new TypeError("A tensor's dims must be a number array");n=l,this.cpuData=i,this.dataLocation="cpu"}const a=lx(n);if(this.cpuData&&a!==this.cpuData.length&&!((o==="uint4"||o==="int4")&&Math.ceil(a/2)===this.cpuData.length))throw new Error(`Tensor's size(${a}) does not match data length(${this.cpuData.length}).`);this.type=o,this.dims=n,this.size=a}static async fromImage(r,t){return rx(r,t)}static fromTexture(r,t){return sx(r,t)}static fromGpuBuffer(r,t){return nx(r,t)}static fromMLTensor(r,t){return ox(r,t)}static fromPinnedBuffer(r,t,s){return ax(r,t,s)}toDataURL(r){return ex(this,r)}toImageData(r){return tx(this,r)}get data(){if(this.ensureValid(),!this.cpuData)throw new Error("The data is not on CPU. Use `getData()` to download GPU data to CPU, or use `texture` or `gpuBuffer` property to access the GPU data directly.");return this.cpuData}get location(){return this.dataLocation}get texture(){if(this.ensureValid(),!this.gpuTextureData)throw new Error("The data is not stored as a WebGL texture.");return this.gpuTextureData}get gpuBuffer(){if(this.ensureValid(),!this.gpuBufferData)throw new Error("The data is not stored as a WebGPU buffer.");return this.gpuBufferData}get mlTensor(){if(this.ensureValid(),!this.mlTensorData)throw new Error("The data is not stored as a WebNN MLTensor.");return this.mlTensorData}async getData(r){switch(this.ensureValid(),this.dataLocation){case"cpu":case"cpu-pinned":return this.data;case"texture":case"gpu-buffer":case"ml-tensor":{if(!this.downloader)throw new Error("The current tensor is not created with a specified data downloader.");if(this.isDownloading)throw new Error("The current tensor is being downloaded.");try{this.isDownloading=!0;const t=await this.downloader();return this.downloader=void 0,this.dataLocation="cpu",this.cpuData=t,r&&this.disposer&&(this.disposer(),this.disposer=void 0),t}finally{this.isDownloading=!1}}default:throw new Error(`cannot get data from location: ${this.dataLocation}`)}}dispose(){if(this.isDownloading)throw new Error("The current tensor is being downloaded.");this.disposer&&(this.disposer(),this.disposer=void 0),this.cpuData=void 0,this.gpuTextureData=void 0,this.gpuBufferData=void 0,this.mlTensorData=void 0,this.downloader=void 0,this.isDownloading=void 0,this.dataLocation="none"}ensureValid(){if(this.dataLocation==="none")throw new Error("The tensor is disposed.")}reshape(r){if(this.ensureValid(),this.downloader||this.disposer)throw new Error("Cannot reshape a tensor that owns GPU resource.");return cx(this,r)}};const Vn=os,Hu=(e,r)=>{(typeof ms.trace>"u"?!ms.wasm.trace:!ms.trace)||console.timeStamp(`${e}::ORT::${r}`)},qu=(e,r)=>{var o;const t=((o=new Error().stack)==null?void 0:o.split(/\r\n|\r|\n/g))||[];let s=!1;for(let n=0;n{(typeof ms.trace>"u"?!ms.wasm.trace:!ms.trace)||qu("BEGIN",e)},xi=e=>{(typeof ms.trace>"u"?!ms.wasm.trace:!ms.trace)||qu("END",e)};var ux=Object.freeze({__proto__:null,InferenceSession:class Hv{constructor(r){this.handler=r}async run(r,t,s){vi();const o={};let n={};if(typeof r!="object"||r===null||r instanceof Vn||Array.isArray(r))throw new TypeError("'feeds' must be an object that use input names as keys and OnnxValue as corresponding values.");let a=!0;if(typeof t=="object"){if(t===null)throw new TypeError("Unexpected argument[1]: cannot be null.");if(t instanceof Vn)throw new TypeError("'fetches' cannot be a Tensor");if(Array.isArray(t)){if(t.length===0)throw new TypeError("'fetches' cannot be an empty array.");a=!1;for(const c of t){if(typeof c!="string")throw new TypeError("'fetches' must be a string array or an object.");if(this.outputNames.indexOf(c)===-1)throw new RangeError(`'fetches' contains invalid output name: ${c}.`);o[c]=null}if(typeof s=="object"&&s!==null)n=s;else if(typeof s<"u")throw new TypeError("'options' must be an object.")}else{let c=!1;const p=Object.getOwnPropertyNames(t);for(const d of this.outputNames)if(p.indexOf(d)!==-1){const u=t[d];(u===null||u instanceof Vn)&&(c=!0,a=!1,o[d]=u)}if(c){if(typeof s=="object"&&s!==null)n=s;else if(typeof s<"u")throw new TypeError("'options' must be an object.")}else n=t}}else if(typeof t<"u")throw new TypeError("Unexpected argument[1]: must be 'fetches' or 'options'.");for(const c of this.inputNames)if(typeof r[c]>"u")throw new Error(`input '${c}' is missing in 'feeds'.`);if(a)for(const c of this.outputNames)o[c]=null;const i=await this.handler.run(r,o,n),l={};for(const c in i)if(Object.hasOwnProperty.call(i,c)){const p=i[c];p instanceof Vn?l[c]=p:l[c]=new Vn(p.type,p.data,p.dims)}return xi(),l}async release(){return this.handler.dispose()}static async create(r,t,s,o){vi();let n,a={};if(typeof r=="string"){if(n=r,typeof t=="object"&&t!==null)a=t;else if(typeof t<"u")throw new TypeError("'options' must be an object.")}else if(r instanceof Uint8Array){if(n=r,typeof t=="object"&&t!==null)a=t;else if(typeof t<"u")throw new TypeError("'options' must be an object.")}else if(r instanceof ArrayBuffer||typeof SharedArrayBuffer<"u"&&r instanceof SharedArrayBuffer){const p=r;let d=0,u=r.byteLength;if(typeof t=="object"&&t!==null)a=t;else if(typeof t=="number"){if(d=t,!Number.isSafeInteger(d))throw new RangeError("'byteOffset' must be an integer.");if(d<0||d>=p.byteLength)throw new RangeError(`'byteOffset' is out of range [0, ${p.byteLength}).`);if(u=r.byteLength-d,typeof s=="number"){if(u=s,!Number.isSafeInteger(u))throw new RangeError("'byteLength' must be an integer.");if(u<=0||d+u>p.byteLength)throw new RangeError(`'byteLength' is out of range (0, ${p.byteLength-d}].`);if(typeof o=="object"&&o!==null)a=o;else if(typeof o<"u")throw new TypeError("'options' must be an object.")}else if(typeof s<"u")throw new TypeError("'byteLength' must be a number.")}else if(typeof t<"u")throw new TypeError("'options' must be an object.");n=new Uint8Array(p,d,u)}else throw new TypeError("Unexpected argument[0]: must be 'path' or 'buffer'.");const[i,l]=await Jv(a),c=await i.createInferenceSessionHandler(n,l);return xi(),new Hv(c)}startProfiling(){this.handler.startProfiling()}endProfiling(){this.handler.endProfiling()}get inputNames(){return this.handler.inputNames}get outputNames(){return this.handler.outputNames}},TRACE:Hu,TRACE_FUNC_BEGIN:vi,TRACE_FUNC_END:xi,Tensor:Vn,env:Zv,registerBackend:jn});/*! - * ONNX Runtime Web v1.22.0-dev.20250409-89f8206ba4 - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. - */var Ti=Object.defineProperty,dx=Object.getOwnPropertyDescriptor,px=Object.getOwnPropertyNames,mx=Object.prototype.hasOwnProperty,hx=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(r,t)=>(typeof require<"u"?require:r)[t]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')}),Ue=(e,r)=>()=>(e&&(r=e(e=0)),r),Un=(e,r)=>{for(var t in r)Ti(e,t,{get:r[t],enumerable:!0})},_x=(e,r,t,s)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of px(r))!mx.call(e,o)&&o!==t&&Ti(e,o,{get:()=>r[o],enumerable:!(s=dx(r,o))||s.enumerable});return e},uo=e=>_x(Ti({},"__esModule",{value:!0}),e),po,Zs,mn,Qu,Xu,Ju=Ue(()=>{po=new Map,Zs=[],mn=(e,r,t)=>{if(r&&typeof r.init=="function"&&typeof r.createInferenceSessionHandler=="function"){let s=po.get(e);if(s===void 0)po.set(e,{backend:r,priority:t});else{if(s.priority>t)return;if(s.priority===t&&s.backend!==r)throw new Error(`cannot register backend "${e}" using priority ${t}`)}if(t>=0){let o=Zs.indexOf(e);o!==-1&&Zs.splice(o,1);for(let n=0;n{let r=po.get(e);if(!r)return"backend not found.";if(r.initialized)return r.backend;if(r.aborted)return r.error;{let t=!!r.initPromise;try{return t||(r.initPromise=r.backend.init(e)),await r.initPromise,r.initialized=!0,r.backend}catch(s){return t||(r.error=`${s}`,r.aborted=!0),r.error}finally{delete r.initPromise}}},Xu=async e=>{let r=e.executionProviders||[],t=r.map(l=>typeof l=="string"?l:l.name),s=t.length===0?Zs:t,o,n=[],a=new Set;for(let l of s){let c=await Qu(l);typeof c=="string"?n.push({name:l,err:c}):(o||(o=c),o===c&&a.add(l))}if(!o)throw new Error(`no available backend found. ERR: ${n.map(l=>`[${l.name}] ${l.err}`).join(", ")}`);for(let{name:l,err:c}of n)t.includes(l)&&console.warn(`removing requested execution provider "${l}" from session options because it is not available: ${c}`);let i=r.filter(l=>a.has(typeof l=="string"?l:l.name));return[o,new Proxy(e,{get:(l,c)=>c==="executionProviders"?i:Reflect.get(l,c)})]}}),fx=Ue(()=>{Ju()}),Yu,gx=Ue(()=>{Yu="1.22.0-dev.20250409-89f8206ba4"}),Ei,as,Zu=Ue(()=>{gx(),Ei="warning",as={wasm:{},webgl:{},webgpu:{},versions:{common:Yu},set logLevel(e){if(e!==void 0){if(typeof e!="string"||["verbose","info","warning","error","fatal"].indexOf(e)===-1)throw new Error(`Unsupported logging level: ${e}`);Ei=e}},get logLevel(){return Ei}},Object.defineProperty(as,"logLevel",{enumerable:!0})}),tr,wx=Ue(()=>{Zu(),tr=as}),ed,td,Mx=Ue(()=>{ed=(e,r)=>{let t=typeof document<"u"?document.createElement("canvas"):new OffscreenCanvas(1,1);t.width=e.dims[3],t.height=e.dims[2];let s=t.getContext("2d");if(s!=null){let o,n;(r==null?void 0:r.tensorLayout)!==void 0&&r.tensorLayout==="NHWC"?(o=e.dims[2],n=e.dims[3]):(o=e.dims[3],n=e.dims[2]);let a=(r==null?void 0:r.format)!==void 0?r.format:"RGB",i=r==null?void 0:r.norm,l,c;i===void 0||i.mean===void 0?l=[255,255,255,255]:typeof i.mean=="number"?l=[i.mean,i.mean,i.mean,i.mean]:(l=[i.mean[0],i.mean[1],i.mean[2],0],i.mean[3]!==void 0&&(l[3]=i.mean[3])),i===void 0||i.bias===void 0?c=[0,0,0,0]:typeof i.bias=="number"?c=[i.bias,i.bias,i.bias,i.bias]:(c=[i.bias[0],i.bias[1],i.bias[2],0],i.bias[3]!==void 0&&(c[3]=i.bias[3]));let p=n*o,d=0,u=p,f=p*2,_=-1;a==="RGBA"?(d=0,u=p,f=p*2,_=p*3):a==="RGB"?(d=0,u=p,f=p*2):a==="RBG"&&(d=0,f=p,u=p*2);for(let b=0;b{let t=typeof document<"u"?document.createElement("canvas").getContext("2d"):new OffscreenCanvas(1,1).getContext("2d"),s;if(t!=null){let o,n,a;(r==null?void 0:r.tensorLayout)!==void 0&&r.tensorLayout==="NHWC"?(o=e.dims[2],n=e.dims[1],a=e.dims[3]):(o=e.dims[3],n=e.dims[2],a=e.dims[1]);let i=r!==void 0&&r.format!==void 0?r.format:"RGB",l=r==null?void 0:r.norm,c,p;l===void 0||l.mean===void 0?c=[255,255,255,255]:typeof l.mean=="number"?c=[l.mean,l.mean,l.mean,l.mean]:(c=[l.mean[0],l.mean[1],l.mean[2],255],l.mean[3]!==void 0&&(c[3]=l.mean[3])),l===void 0||l.bias===void 0?p=[0,0,0,0]:typeof l.bias=="number"?p=[l.bias,l.bias,l.bias,l.bias]:(p=[l.bias[0],l.bias[1],l.bias[2],0],l.bias[3]!==void 0&&(p[3]=l.bias[3]));let d=n*o;if(r!==void 0&&(r.format!==void 0&&a===4&&r.format!=="RGBA"||a===3&&r.format!=="RGB"&&r.format!=="BGR"))throw new Error("Tensor format doesn't match input tensor dims");let u=4,f=0,_=1,b=2,k=3,w=0,y=d,$=d*2,T=-1;i==="RGBA"?(w=0,y=d,$=d*2,T=d*3):i==="RGB"?(w=0,y=d,$=d*2):i==="RBG"&&(w=0,$=d,y=d*2),s=t.createImageData(o,n);for(let M=0;M{Ci(),ta=(e,r)=>{if(e===void 0)throw new Error("Image buffer must be defined");if(r.height===void 0||r.width===void 0)throw new Error("Image height and width must be defined");if(r.tensorLayout==="NHWC")throw new Error("NHWC Tensor layout is not supported yet");let{height:t,width:s}=r,o=r.norm??{mean:255,bias:0},n,a;typeof o.mean=="number"?n=[o.mean,o.mean,o.mean,o.mean]:n=[o.mean[0],o.mean[1],o.mean[2],o.mean[3]??255],typeof o.bias=="number"?a=[o.bias,o.bias,o.bias,o.bias]:a=[o.bias[0],o.bias[1],o.bias[2],o.bias[3]??0];let i=r.format!==void 0?r.format:"RGBA",l=r.tensorFormat!==void 0&&r.tensorFormat!==void 0?r.tensorFormat:"RGB",c=t*s,p=l==="RGBA"?new Float32Array(c*4):new Float32Array(c*3),d=4,u=0,f=1,_=2,b=3,k=0,w=c,y=c*2,$=-1;i==="RGB"&&(d=3,u=0,f=1,_=2,b=-1),l==="RGBA"?$=c*3:l==="RBG"?(k=0,y=c,w=c*2):l==="BGR"&&(y=0,w=c,k=c*2);for(let T=0;T{let t=typeof HTMLImageElement<"u"&&e instanceof HTMLImageElement,s=typeof ImageData<"u"&&e instanceof ImageData,o=typeof ImageBitmap<"u"&&e instanceof ImageBitmap,n=typeof e=="string",a,i=r??{},l=()=>{if(typeof document<"u")return document.createElement("canvas");if(typeof OffscreenCanvas<"u")return new OffscreenCanvas(1,1);throw new Error("Canvas is not supported")},c=p=>typeof HTMLCanvasElement<"u"&&p instanceof HTMLCanvasElement||p instanceof OffscreenCanvas?p.getContext("2d"):null;if(t){let p=l();p.width=e.width,p.height=e.height;let d=c(p);if(d!=null){let u=e.height,f=e.width;if(r!==void 0&&r.resizedHeight!==void 0&&r.resizedWidth!==void 0&&(u=r.resizedHeight,f=r.resizedWidth),r!==void 0){if(i=r,r.tensorFormat!==void 0)throw new Error("Image input config format must be RGBA for HTMLImageElement");i.tensorFormat="RGBA",i.height=u,i.width=f}else i.tensorFormat="RGBA",i.height=u,i.width=f;d.drawImage(e,0,0),a=d.getImageData(0,0,f,u).data}else throw new Error("Can not access image data")}else if(s){let p,d;if(r!==void 0&&r.resizedWidth!==void 0&&r.resizedHeight!==void 0?(p=r.resizedHeight,d=r.resizedWidth):(p=e.height,d=e.width),r!==void 0&&(i=r),i.format="RGBA",i.height=p,i.width=d,r!==void 0){let u=l();u.width=d,u.height=p;let f=c(u);if(f!=null)f.putImageData(e,0,0),a=f.getImageData(0,0,d,p).data;else throw new Error("Can not access image data")}else a=e.data}else if(o){if(r===void 0)throw new Error("Please provide image config with format for Imagebitmap");let p=l();p.width=e.width,p.height=e.height;let d=c(p);if(d!=null){let u=e.height,f=e.width;return d.drawImage(e,0,0,f,u),a=d.getImageData(0,0,f,u).data,i.height=u,i.width=f,ta(a,i)}else throw new Error("Can not access image data")}else{if(n)return new Promise((p,d)=>{let u=l(),f=c(u);if(!e||!f)return d();let _=new Image;_.crossOrigin="Anonymous",_.src=e,_.onload=()=>{u.width=_.width,u.height=_.height,f.drawImage(_,0,0,u.width,u.height);let b=f.getImageData(0,0,u.width,u.height);i.height=u.height,i.width=u.width,p(ta(b.data,i))}});throw new Error("Input data provided is not supported - aborted tensor creation")}if(a!==void 0)return ta(a,i);throw new Error("Input data provided is not supported - aborted tensor creation")},sd=(e,r)=>{let{width:t,height:s,download:o,dispose:n}=r,a=[1,s,t,4];return new es({location:"texture",type:"float32",texture:e,dims:a,download:o,dispose:n})},nd=(e,r)=>{let{dataType:t,dims:s,download:o,dispose:n}=r;return new es({location:"gpu-buffer",type:t??"float32",gpuBuffer:e,dims:s,download:o,dispose:n})},od=(e,r)=>{let{dataType:t,dims:s,download:o,dispose:n}=r;return new es({location:"ml-tensor",type:t??"float32",mlTensor:e,dims:s,download:o,dispose:n})},ad=(e,r,t)=>new es({location:"cpu-pinned",type:e,data:r,dims:t??[r.length]})}),hn,mo,Pi,id,yx=Ue(()=>{hn=new Map([["float32",Float32Array],["uint8",Uint8Array],["int8",Int8Array],["uint16",Uint16Array],["int16",Int16Array],["int32",Int32Array],["bool",Uint8Array],["float64",Float64Array],["uint32",Uint32Array],["int4",Uint8Array],["uint4",Uint8Array]]),mo=new Map([[Float32Array,"float32"],[Uint8Array,"uint8"],[Int8Array,"int8"],[Uint16Array,"uint16"],[Int16Array,"int16"],[Int32Array,"int32"],[Float64Array,"float64"],[Uint32Array,"uint32"]]),Pi=!1,id=()=>{if(!Pi){Pi=!0;let e=typeof BigInt64Array<"u"&&BigInt64Array.from,r=typeof BigUint64Array<"u"&&BigUint64Array.from,t=globalThis.Float16Array,s=typeof t<"u"&&t.from;e&&(hn.set("int64",BigInt64Array),mo.set(BigInt64Array,"int64")),r&&(hn.set("uint64",BigUint64Array),mo.set(BigUint64Array,"uint64")),s?(hn.set("float16",t),mo.set(t,"float16")):hn.set("float16",Uint16Array)}}}),ld,cd,vx=Ue(()=>{Ci(),ld=e=>{let r=1;for(let t=0;t{switch(e.location){case"cpu":return new es(e.type,e.data,r);case"cpu-pinned":return new es({location:"cpu-pinned",data:e.data,type:e.type,dims:r});case"texture":return new es({location:"texture",texture:e.texture,type:e.type,dims:r});case"gpu-buffer":return new es({location:"gpu-buffer",gpuBuffer:e.gpuBuffer,type:e.type,dims:r});case"ml-tensor":return new es({location:"ml-tensor",mlTensor:e.mlTensor,type:e.type,dims:r});default:throw new Error(`tensorReshape: tensor location ${e.location} is not supported`)}}}),es,Ci=Ue(()=>{Mx(),bx(),yx(),vx(),es=class{constructor(e,r,t){id();let s,o;if(typeof e=="object"&&"location"in e)switch(this.dataLocation=e.location,s=e.type,o=e.dims,e.location){case"cpu-pinned":{let a=hn.get(s);if(!a)throw new TypeError(`unsupported type "${s}" to create tensor from pinned buffer`);if(!(e.data instanceof a))throw new TypeError(`buffer should be of type ${a.name}`);this.cpuData=e.data;break}case"texture":{if(s!=="float32")throw new TypeError(`unsupported type "${s}" to create tensor from texture`);this.gpuTextureData=e.texture,this.downloader=e.download,this.disposer=e.dispose;break}case"gpu-buffer":{if(s!=="float32"&&s!=="float16"&&s!=="int32"&&s!=="int64"&&s!=="uint32"&&s!=="uint8"&&s!=="bool"&&s!=="uint4"&&s!=="int4")throw new TypeError(`unsupported type "${s}" to create tensor from gpu buffer`);this.gpuBufferData=e.gpuBuffer,this.downloader=e.download,this.disposer=e.dispose;break}case"ml-tensor":{if(s!=="float32"&&s!=="float16"&&s!=="int32"&&s!=="int64"&&s!=="uint32"&&s!=="uint64"&&s!=="int8"&&s!=="uint8"&&s!=="bool"&&s!=="uint4"&&s!=="int4")throw new TypeError(`unsupported type "${s}" to create tensor from MLTensor`);this.mlTensorData=e.mlTensor,this.downloader=e.download,this.disposer=e.dispose;break}default:throw new Error(`Tensor constructor: unsupported location '${this.dataLocation}'`)}else{let a,i;if(typeof e=="string")if(s=e,i=t,e==="string"){if(!Array.isArray(r))throw new TypeError("A string tensor's data must be a string array.");a=r}else{let l=hn.get(e);if(l===void 0)throw new TypeError(`Unsupported tensor type: ${e}.`);if(Array.isArray(r)){if(e==="float16"&&l===Uint16Array||e==="uint4"||e==="int4")throw new TypeError(`Creating a ${e} tensor from number array is not supported. Please use ${l.name} as data.`);e==="uint64"||e==="int64"?a=l.from(r,BigInt):a=l.from(r)}else if(r instanceof l)a=r;else if(r instanceof Uint8ClampedArray)if(e==="uint8")a=Uint8Array.from(r);else throw new TypeError("A Uint8ClampedArray tensor's data must be type of uint8");else if(e==="float16"&&r instanceof Uint16Array&&l!==Uint16Array)a=new globalThis.Float16Array(r.buffer,r.byteOffset,r.length);else throw new TypeError(`A ${s} tensor's data must be type of ${l}`)}else if(i=r,Array.isArray(e)){if(e.length===0)throw new TypeError("Tensor type cannot be inferred from an empty array.");let l=typeof e[0];if(l==="string")s="string",a=e;else if(l==="boolean")s="bool",a=Uint8Array.from(e);else throw new TypeError(`Invalid element type of data array: ${l}.`)}else if(e instanceof Uint8ClampedArray)s="uint8",a=Uint8Array.from(e);else{let l=mo.get(e.constructor);if(l===void 0)throw new TypeError(`Unsupported type for tensor data: ${e.constructor}.`);s=l,a=e}if(i===void 0)i=[a.length];else if(!Array.isArray(i))throw new TypeError("A tensor's dims must be a number array");o=i,this.cpuData=a,this.dataLocation="cpu"}let n=ld(o);if(this.cpuData&&n!==this.cpuData.length&&!((s==="uint4"||s==="int4")&&Math.ceil(n/2)===this.cpuData.length))throw new Error(`Tensor's size(${n}) does not match data length(${this.cpuData.length}).`);this.type=s,this.dims=o,this.size=n}static async fromImage(e,r){return rd(e,r)}static fromTexture(e,r){return sd(e,r)}static fromGpuBuffer(e,r){return nd(e,r)}static fromMLTensor(e,r){return od(e,r)}static fromPinnedBuffer(e,r,t){return ad(e,r,t)}toDataURL(e){return ed(this,e)}toImageData(e){return td(this,e)}get data(){if(this.ensureValid(),!this.cpuData)throw new Error("The data is not on CPU. Use `getData()` to download GPU data to CPU, or use `texture` or `gpuBuffer` property to access the GPU data directly.");return this.cpuData}get location(){return this.dataLocation}get texture(){if(this.ensureValid(),!this.gpuTextureData)throw new Error("The data is not stored as a WebGL texture.");return this.gpuTextureData}get gpuBuffer(){if(this.ensureValid(),!this.gpuBufferData)throw new Error("The data is not stored as a WebGPU buffer.");return this.gpuBufferData}get mlTensor(){if(this.ensureValid(),!this.mlTensorData)throw new Error("The data is not stored as a WebNN MLTensor.");return this.mlTensorData}async getData(e){switch(this.ensureValid(),this.dataLocation){case"cpu":case"cpu-pinned":return this.data;case"texture":case"gpu-buffer":case"ml-tensor":{if(!this.downloader)throw new Error("The current tensor is not created with a specified data downloader.");if(this.isDownloading)throw new Error("The current tensor is being downloaded.");try{this.isDownloading=!0;let r=await this.downloader();return this.downloader=void 0,this.dataLocation="cpu",this.cpuData=r,e&&this.disposer&&(this.disposer(),this.disposer=void 0),r}finally{this.isDownloading=!1}}default:throw new Error(`cannot get data from location: ${this.dataLocation}`)}}dispose(){if(this.isDownloading)throw new Error("The current tensor is being downloaded.");this.disposer&&(this.disposer(),this.disposer=void 0),this.cpuData=void 0,this.gpuTextureData=void 0,this.gpuBufferData=void 0,this.mlTensorData=void 0,this.downloader=void 0,this.isDownloading=void 0,this.dataLocation="none"}ensureValid(){if(this.dataLocation==="none")throw new Error("The tensor is disposed.")}reshape(e){if(this.ensureValid(),this.downloader||this.disposer)throw new Error("Cannot reshape a tensor that owns GPU resource.");return cd(this,e)}}}),hs,ud=Ue(()=>{Ci(),hs=es}),ho,Si,_s,is,dd=Ue(()=>{Zu(),ho=(e,r)=>{(typeof as.trace>"u"?!as.wasm.trace:!as.trace)||console.timeStamp(`${e}::ORT::${r}`)},Si=(e,r)=>{var o;let t=((o=new Error().stack)==null?void 0:o.split(/\r\n|\r|\n/g))||[],s=!1;for(let n=0;n{(typeof as.trace>"u"?!as.wasm.trace:!as.trace)||Si("BEGIN",e)},is=e=>{(typeof as.trace>"u"?!as.wasm.trace:!as.trace)||Si("END",e)}}),pd,xx=Ue(()=>{Ju(),ud(),dd(),pd=class qv{constructor(r){this.handler=r}async run(r,t,s){_s();let o={},n={};if(typeof r!="object"||r===null||r instanceof hs||Array.isArray(r))throw new TypeError("'feeds' must be an object that use input names as keys and OnnxValue as corresponding values.");let a=!0;if(typeof t=="object"){if(t===null)throw new TypeError("Unexpected argument[1]: cannot be null.");if(t instanceof hs)throw new TypeError("'fetches' cannot be a Tensor");if(Array.isArray(t)){if(t.length===0)throw new TypeError("'fetches' cannot be an empty array.");a=!1;for(let c of t){if(typeof c!="string")throw new TypeError("'fetches' must be a string array or an object.");if(this.outputNames.indexOf(c)===-1)throw new RangeError(`'fetches' contains invalid output name: ${c}.`);o[c]=null}if(typeof s=="object"&&s!==null)n=s;else if(typeof s<"u")throw new TypeError("'options' must be an object.")}else{let c=!1,p=Object.getOwnPropertyNames(t);for(let d of this.outputNames)if(p.indexOf(d)!==-1){let u=t[d];(u===null||u instanceof hs)&&(c=!0,a=!1,o[d]=u)}if(c){if(typeof s=="object"&&s!==null)n=s;else if(typeof s<"u")throw new TypeError("'options' must be an object.")}else n=t}}else if(typeof t<"u")throw new TypeError("Unexpected argument[1]: must be 'fetches' or 'options'.");for(let c of this.inputNames)if(typeof r[c]>"u")throw new Error(`input '${c}' is missing in 'feeds'.`);if(a)for(let c of this.outputNames)o[c]=null;let i=await this.handler.run(r,o,n),l={};for(let c in i)if(Object.hasOwnProperty.call(i,c)){let p=i[c];p instanceof hs?l[c]=p:l[c]=new hs(p.type,p.data,p.dims)}return is(),l}async release(){return this.handler.dispose()}static async create(r,t,s,o){_s();let n,a={};if(typeof r=="string"){if(n=r,typeof t=="object"&&t!==null)a=t;else if(typeof t<"u")throw new TypeError("'options' must be an object.")}else if(r instanceof Uint8Array){if(n=r,typeof t=="object"&&t!==null)a=t;else if(typeof t<"u")throw new TypeError("'options' must be an object.")}else if(r instanceof ArrayBuffer||typeof SharedArrayBuffer<"u"&&r instanceof SharedArrayBuffer){let p=r,d=0,u=r.byteLength;if(typeof t=="object"&&t!==null)a=t;else if(typeof t=="number"){if(d=t,!Number.isSafeInteger(d))throw new RangeError("'byteOffset' must be an integer.");if(d<0||d>=p.byteLength)throw new RangeError(`'byteOffset' is out of range [0, ${p.byteLength}).`);if(u=r.byteLength-d,typeof s=="number"){if(u=s,!Number.isSafeInteger(u))throw new RangeError("'byteLength' must be an integer.");if(u<=0||d+u>p.byteLength)throw new RangeError(`'byteLength' is out of range (0, ${p.byteLength-d}].`);if(typeof o=="object"&&o!==null)a=o;else if(typeof o<"u")throw new TypeError("'options' must be an object.")}else if(typeof s<"u")throw new TypeError("'byteLength' must be a number.")}else if(typeof t<"u")throw new TypeError("'options' must be an object.");n=new Uint8Array(p,d,u)}else throw new TypeError("Unexpected argument[0]: must be 'path' or 'buffer'.");let[i,l]=await Xu(a),c=await i.createInferenceSessionHandler(n,l);return is(),new qv(c)}startProfiling(){this.handler.startProfiling()}endProfiling(){this.handler.endProfiling()}get inputNames(){return this.handler.inputNames}get outputNames(){return this.handler.outputNames}get inputMetadata(){return this.handler.inputMetadata}get outputMetadata(){return this.handler.outputMetadata}}}),$i,Tx=Ue(()=>{xx(),$i=pd}),Ex=Ue(()=>{}),Px=Ue(()=>{}),Cx=Ue(()=>{}),Sx=Ue(()=>{}),md={};Un(md,{InferenceSession:()=>$i,TRACE:()=>ho,TRACE_FUNC_BEGIN:()=>_s,TRACE_FUNC_END:()=>is,Tensor:()=>hs,env:()=>tr,registerBackend:()=>mn});var fs=Ue(()=>{fx(),wx(),Tx(),ud(),Ex(),Px(),dd(),Cx(),Sx()}),ki=Ue(()=>{}),hd={};Un(hd,{default:()=>_d});var Ii,Ai,_d,$x=Ue(()=>{var e;Qg(),_n(),ji(),Ii="ort-wasm-proxy-worker",Ai=((e=globalThis.self)==null?void 0:e.name)===Ii,Ai&&(self.onmessage=r=>{let{type:t,in:s}=r.data;try{switch(t){case"init-wasm":Ui(s.wasm).then(()=>{rc(s).then(()=>{postMessage({type:t})},o=>{postMessage({type:t,err:o})})},o=>{postMessage({type:t,err:o})});break;case"init-ep":{let{epName:o,env:n}=s;sc(n,o).then(()=>{postMessage({type:t})},a=>{postMessage({type:t,err:a})});break}case"copy-from":{let{buffer:o}=s,n=ba(o);postMessage({type:t,out:n});break}case"create":{let{model:o,options:n}=s;oc(o,n).then(a=>{postMessage({type:t,out:a})},a=>{postMessage({type:t,err:a})});break}case"release":ac(s),postMessage({type:t});break;case"run":{let{sessionId:o,inputIndices:n,inputs:a,outputIndices:i,options:l}=s;lc(o,n,a,i,new Array(i.length).fill(null),l).then(c=>{c.some(p=>p[3]!=="cpu")?postMessage({type:t,err:"Proxy does not support non-cpu tensor location."}):postMessage({type:t,out:c},uc([...a,...c]))},c=>{postMessage({type:t,err:c})});break}case"end-profiling":cc(s),postMessage({type:t});break;default:}}catch(o){postMessage({type:t,err:o})}}),_d=Ai?null:r=>new Worker(r??ts,{type:"module",name:Ii})}),fd={};Un(fd,{default:()=>gd});var Fi,Oi,gd,wd,kx=Ue(()=>{var e,r;Oi=(Fi=self.location.href,async function(t={}){var ao;var s,o,n=t,a=new Promise((h,E)=>{s=h,o=E}),i=typeof window=="object",l=typeof WorkerGlobalScope<"u",c=l&&((ao=self.name)==null?void 0:ao.startsWith("em-pthread"));n.mountExternalData=(h,E)=>{h.startsWith("./")&&(h=h.substring(2)),(n.Eb||(n.Eb=new Map)).set(h,E)},n.unmountExternalData=()=>{delete n.Eb};var p=globalThis.SharedArrayBuffer??new WebAssembly.Memory({initial:0,maximum:0,pc:!0}).buffer.constructor;let d=h=>async(...E)=>{var A;try{if(n.Fb)throw Error("Session already started");let z=n.Fb={dc:E[0],errors:[]},V=await h(...E);if(n.Fb!==z)throw Error("Session mismatch");(A=n.Jb)==null||A.flush();let ce=z.errors;if(0Re),0{if(h==="webgpu"){[n.Jb,n.Ub,n.Yb,n.Kb,n.Xb,n.jb,n.Zb,n.ac,n.Vb,n.Wb,n.$b]=E;let A=n.Jb;n.jsepRegisterBuffer=(z,V,ce,Pe)=>A.registerBuffer(z,V,ce,Pe),n.jsepGetBuffer=z=>A.getBuffer(z),n.jsepCreateDownloader=(z,V,ce)=>A.createDownloader(z,V,ce),n.jsepOnCreateSession=z=>{A.onCreateSession(z)},n.jsepOnReleaseSession=z=>{A.onReleaseSession(z)},n.jsepOnRunStart=z=>A.onRunStart(z),n.bc=(z,V)=>{A.upload(z,V)}}else if(h==="webnn"){let A=E[0];[n.nc,n.Nb,n.webnnEnsureTensor,n.Ob,n.webnnDownloadTensor]=E.slice(1),n.webnnReleaseTensorId=n.Nb,n.webnnUploadTensor=n.Ob,n.webnnOnRunStart=z=>A.onRunStart(z),n.webnnOnRunEnd=A.onRunEnd.bind(A),n.webnnRegisterMLContext=(z,V)=>{A.registerMLContext(z,V)},n.webnnOnReleaseSession=z=>{A.onReleaseSession(z)},n.webnnCreateMLTensorDownloader=(z,V)=>A.createMLTensorDownloader(z,V),n.webnnRegisterMLTensor=(z,V,ce,Pe)=>A.registerMLTensor(z,V,ce,Pe),n.webnnCreateMLContext=z=>A.createMLContext(z),n.webnnRegisterMLConstant=(z,V,ce,Pe,Re,Je)=>A.registerMLConstant(z,V,ce,Pe,Re,n.Eb,Je),n.webnnRegisterGraphInput=A.registerGraphInput.bind(A),n.webnnIsGraphInput=A.isGraphInput.bind(A),n.webnnCreateTemporaryTensor=A.createTemporaryTensor.bind(A),n.webnnIsInt64Supported=A.isInt64Supported.bind(A)}};let u=()=>{let h=(E,A,z)=>(...V)=>{let ce=xr,Pe=A==null?void 0:A();V=E(...V);let Re=A==null?void 0:A();return Pe!==Re&&(E=Re,z(Pe),A=z=null),xr!=ce?new Promise((Je,it)=>{Yr={resolve:Je,reject:it}}):V};(()=>{for(let E of["_OrtAppendExecutionProvider","_OrtCreateSession","_OrtRun","_OrtRunWithBinding","_OrtBindInput"])n[E]=h(n[E],()=>n[E],A=>n[E]=A)})(),d!==void 0&&(n._OrtRun=d(n._OrtRun),n._OrtRunWithBinding=d(n._OrtRunWithBinding)),u=void 0};n.asyncInit=()=>{u==null||u()};var f,_,b=Object.assign({},n),k=(h,E)=>{throw E},w="";(i||l)&&(l?w=self.location.href:typeof document<"u"&&document.currentScript&&(w=document.currentScript.src),Fi&&(w=Fi),w=w.startsWith("blob:")?"":w.slice(0,w.replace(/[?#].*/,"").lastIndexOf("/")+1),l&&(_=h=>{var E=new XMLHttpRequest;return E.open("GET",h,!1),E.responseType="arraybuffer",E.send(null),new Uint8Array(E.response)}),f=async h=>{if(oe(h))return new Promise((A,z)=>{var V=new XMLHttpRequest;V.open("GET",h,!0),V.responseType="arraybuffer",V.onload=()=>{V.status==200||V.status==0&&V.response?A(V.response):z(V.status)},V.onerror=z,V.send(null)});var E=await fetch(h,{credentials:"same-origin"});if(E.ok)return E.arrayBuffer();throw Error(E.status+" : "+E.url)});var y=console.log.bind(console),$=console.error.bind(console),T=y,M=$;Object.assign(n,b),b=null;var x,v,C,F,D,K,U,j,se,q,re,Z,ae,_e=n.wasmBinary,pe=!1,oe=h=>h.startsWith("file://");function G(){return x.buffer!=F.buffer&&O(),F}function B(){return x.buffer!=F.buffer&&O(),D}function Q(){return x.buffer!=F.buffer&&O(),K}function le(){return x.buffer!=F.buffer&&O(),U}function ee(){return x.buffer!=F.buffer&&O(),j}function Se(){return x.buffer!=F.buffer&&O(),se}function De(){return x.buffer!=F.buffer&&O(),q}function Ne(){return x.buffer!=F.buffer&&O(),ae}if(c){let h=function(E){try{var A=E.data,z=A.Bb;if(z==="load"){let V=[];self.onmessage=ce=>V.push(ce),self.startWorker=()=>{postMessage({Bb:"loaded"});for(let ce of V)h(ce);self.onmessage=h};for(let ce of A.Rb)n[ce]&&!n[ce].proxy||(n[ce]=(...Pe)=>{postMessage({Bb:"callHandler",Qb:ce,args:Pe})},ce=="print"&&(T=n[ce]),ce=="printErr"&&(M=n[ce]));x=A.kc,O(),Ae(A.lc)}else if(z==="run"){nn(A.Ab),to(A.Ab,0,0,1,0,0),Ur(),de(A.Ab),te||(Vo(),te=!0);try{cr(A.fc,A.Hb)}catch(V){if(V!="unwind")throw V}}else A.target!=="setimmediate"&&(z==="checkMailbox"?te&&Te():z&&(M(`worker: received unknown command ${z}`),M(A)))}catch(V){throw ro(),V}};var Ae,te=!1;M=function(...E){E=E.join(" "),console.error(E)},self.alert=function(...E){postMessage({Bb:"alert",text:E.join(" "),ic:In()})},self.onunhandledrejection=E=>{throw E.reason||E},self.onmessage=h}function O(){var h=x.buffer;n.HEAP8=F=new Int8Array(h),n.HEAP16=K=new Int16Array(h),n.HEAPU8=D=new Uint8Array(h),n.HEAPU16=U=new Uint16Array(h),n.HEAP32=j=new Int32Array(h),n.HEAPU32=se=new Uint32Array(h),n.HEAPF32=q=new Float32Array(h),n.HEAPF64=ae=new Float64Array(h),n.HEAP64=re=new BigInt64Array(h),n.HEAPU64=Z=new BigUint64Array(h)}function me(){c?startWorker(n):mt.Ca()}c||(x=new WebAssembly.Memory({initial:256,maximum:65536,shared:!0}),O());var xe,be=0,Ce=null;function $e(){if(--be==0&&Ce){var h=Ce;Ce=null,h()}}function Me(h){throw M(h="Aborted("+h+")"),pe=!0,h=new WebAssembly.RuntimeError(h+". Build with -sASSERTIONS for more info."),o(h),h}function Le(){return{a:{L:He,Aa:ke,b:ls,$:gt,A:Jr,pa:$t,X:H,Z:R,qa:W,na:X,ga:ue,ma:Ee,J:et,Y:ot,V:rt,oa:St,W:lt,va:Dt,E:Os,Q:Hs,O:Ls,D:us,u:Wr,r:je,P:Ve,z:I,R:N,ja:Y,T:Ge,aa:qe,M:tt,F:bt,ia:de,sa:jt,t:Jt,Ba:yr,w:ds,o:_r,l:qr,c:Hr,n:Rs,j:Ea,v:Pa,p:on,f:Ca,s:Sa,m:$a,e:ka,k:Ia,i:an,g:Aa,d:Fa,da:Oa,ea:Da,fa:La,ba:Jn,ca:Ao,N:Yn,xa:gc,ua:Fo,h:Ra,C:ja,G:Na,ta:Ba,x:Va,ra:Ua,U:Wa,q:za,y:Oo,K:Ga,S:Ka,za:Do,ya:Ha,ka:qa,la:zo,_:ft,B:Qa,I:Bo,ha:Zn,H:Ro,a:x,wa:ze}}}var we={829644:(h,E,A,z,V)=>{if(n===void 0||!n.Eb)return 1;if((h=Yt(Number(h>>>0))).startsWith("./")&&(h=h.substring(2)),!(h=n.Eb.get(h)))return 2;if(E=Number(E>>>0),A=Number(A>>>0),z=Number(z>>>0),E+A>h.byteLength)return 3;try{let ce=h.subarray(E,E+A);switch(V){case 0:B().set(ce,z>>>0);break;case 1:n.mc?n.mc(z,ce):n.bc(z,ce);break;default:return 4}return 0}catch{return 4}},830468:(h,E,A)=>{n.Ob(h,B().subarray(E>>>0,E+A>>>0))},830532:()=>n.nc(),830574:h=>{n.Nb(h)},830611:()=>{n.Vb()},830642:()=>{n.Wb()},830671:()=>{n.$b()},830696:h=>n.Ub(h),830729:h=>n.Yb(h),830761:(h,E,A)=>{n.Kb(Number(h),Number(E),Number(A),!0)},830824:(h,E,A)=>{n.Kb(Number(h),Number(E),Number(A))},830881:()=>typeof wasmOffsetConverter<"u",830938:h=>{n.jb("Abs",h,void 0)},830989:h=>{n.jb("Neg",h,void 0)},831040:h=>{n.jb("Floor",h,void 0)},831093:h=>{n.jb("Ceil",h,void 0)},831145:h=>{n.jb("Reciprocal",h,void 0)},831203:h=>{n.jb("Sqrt",h,void 0)},831255:h=>{n.jb("Exp",h,void 0)},831306:h=>{n.jb("Erf",h,void 0)},831357:h=>{n.jb("Sigmoid",h,void 0)},831412:(h,E,A)=>{n.jb("HardSigmoid",h,{alpha:E,beta:A})},831491:h=>{n.jb("Log",h,void 0)},831542:h=>{n.jb("Sin",h,void 0)},831593:h=>{n.jb("Cos",h,void 0)},831644:h=>{n.jb("Tan",h,void 0)},831695:h=>{n.jb("Asin",h,void 0)},831747:h=>{n.jb("Acos",h,void 0)},831799:h=>{n.jb("Atan",h,void 0)},831851:h=>{n.jb("Sinh",h,void 0)},831903:h=>{n.jb("Cosh",h,void 0)},831955:h=>{n.jb("Asinh",h,void 0)},832008:h=>{n.jb("Acosh",h,void 0)},832061:h=>{n.jb("Atanh",h,void 0)},832114:h=>{n.jb("Tanh",h,void 0)},832166:h=>{n.jb("Not",h,void 0)},832217:(h,E,A)=>{n.jb("Clip",h,{min:E,max:A})},832286:h=>{n.jb("Clip",h,void 0)},832338:(h,E)=>{n.jb("Elu",h,{alpha:E})},832396:h=>{n.jb("Gelu",h,void 0)},832448:h=>{n.jb("Relu",h,void 0)},832500:(h,E)=>{n.jb("LeakyRelu",h,{alpha:E})},832564:(h,E)=>{n.jb("ThresholdedRelu",h,{alpha:E})},832634:(h,E)=>{n.jb("Cast",h,{to:E})},832692:h=>{n.jb("Add",h,void 0)},832743:h=>{n.jb("Sub",h,void 0)},832794:h=>{n.jb("Mul",h,void 0)},832845:h=>{n.jb("Div",h,void 0)},832896:h=>{n.jb("Pow",h,void 0)},832947:h=>{n.jb("Equal",h,void 0)},833e3:h=>{n.jb("Greater",h,void 0)},833055:h=>{n.jb("GreaterOrEqual",h,void 0)},833117:h=>{n.jb("Less",h,void 0)},833169:h=>{n.jb("LessOrEqual",h,void 0)},833228:(h,E,A,z,V)=>{n.jb("ReduceMean",h,{keepDims:!!E,noopWithEmptyAxes:!!A,axes:z?Array.from(ee().subarray(Number(z)>>>0,Number(V)>>>0)):[]})},833403:(h,E,A,z,V)=>{n.jb("ReduceMax",h,{keepDims:!!E,noopWithEmptyAxes:!!A,axes:z?Array.from(ee().subarray(Number(z)>>>0,Number(V)>>>0)):[]})},833577:(h,E,A,z,V)=>{n.jb("ReduceMin",h,{keepDims:!!E,noopWithEmptyAxes:!!A,axes:z?Array.from(ee().subarray(Number(z)>>>0,Number(V)>>>0)):[]})},833751:(h,E,A,z,V)=>{n.jb("ReduceProd",h,{keepDims:!!E,noopWithEmptyAxes:!!A,axes:z?Array.from(ee().subarray(Number(z)>>>0,Number(V)>>>0)):[]})},833926:(h,E,A,z,V)=>{n.jb("ReduceSum",h,{keepDims:!!E,noopWithEmptyAxes:!!A,axes:z?Array.from(ee().subarray(Number(z)>>>0,Number(V)>>>0)):[]})},834100:(h,E,A,z,V)=>{n.jb("ReduceL1",h,{keepDims:!!E,noopWithEmptyAxes:!!A,axes:z?Array.from(ee().subarray(Number(z)>>>0,Number(V)>>>0)):[]})},834273:(h,E,A,z,V)=>{n.jb("ReduceL2",h,{keepDims:!!E,noopWithEmptyAxes:!!A,axes:z?Array.from(ee().subarray(Number(z)>>>0,Number(V)>>>0)):[]})},834446:(h,E,A,z,V)=>{n.jb("ReduceLogSum",h,{keepDims:!!E,noopWithEmptyAxes:!!A,axes:z?Array.from(ee().subarray(Number(z)>>>0,Number(V)>>>0)):[]})},834623:(h,E,A,z,V)=>{n.jb("ReduceSumSquare",h,{keepDims:!!E,noopWithEmptyAxes:!!A,axes:z?Array.from(ee().subarray(Number(z)>>>0,Number(V)>>>0)):[]})},834803:(h,E,A,z,V)=>{n.jb("ReduceLogSumExp",h,{keepDims:!!E,noopWithEmptyAxes:!!A,axes:z?Array.from(ee().subarray(Number(z)>>>0,Number(V)>>>0)):[]})},834983:h=>{n.jb("Where",h,void 0)},835036:(h,E,A)=>{n.jb("Transpose",h,{perm:E?Array.from(ee().subarray(Number(E)>>>0,Number(A)>>>0)):[]})},835160:(h,E,A,z)=>{n.jb("DepthToSpace",h,{blocksize:E,mode:Yt(A),format:z?"NHWC":"NCHW"})},835293:(h,E,A,z)=>{n.jb("DepthToSpace",h,{blocksize:E,mode:Yt(A),format:z?"NHWC":"NCHW"})},835426:(h,E,A,z,V,ce,Pe,Re,Je,it,xt,Rt,Qt,Er,Ys)=>{n.jb("ConvTranspose",h,{format:Je?"NHWC":"NCHW",autoPad:E,dilations:[A],group:z,kernelShape:[V],pads:[ce,Pe],strides:[Re],wIsConst:()=>!!G()[it>>>0],outputPadding:xt?Array.from(ee().subarray(Number(xt)>>>0,Number(Rt)>>>0)):[],outputShape:Qt?Array.from(ee().subarray(Number(Qt)>>>0,Number(Er)>>>0)):[],activation:Yt(Ys)})},835859:(h,E,A,z,V,ce,Pe,Re,Je,it,xt,Rt,Qt,Er)=>{n.jb("ConvTranspose",h,{format:Re?"NHWC":"NCHW",autoPad:E,dilations:Array.from(ee().subarray(Number(A)>>>0,2+(Number(A)>>>0)>>>0)),group:z,kernelShape:Array.from(ee().subarray(Number(V)>>>0,2+(Number(V)>>>0)>>>0)),pads:Array.from(ee().subarray(Number(ce)>>>0,4+(Number(ce)>>>0)>>>0)),strides:Array.from(ee().subarray(Number(Pe)>>>0,2+(Number(Pe)>>>0)>>>0)),wIsConst:()=>!!G()[Je>>>0],outputPadding:it?Array.from(ee().subarray(Number(it)>>>0,Number(xt)>>>0)):[],outputShape:Rt?Array.from(ee().subarray(Number(Rt)>>>0,Number(Qt)>>>0)):[],activation:Yt(Er)})},836520:(h,E,A,z,V,ce,Pe,Re,Je,it,xt,Rt,Qt,Er,Ys)=>{n.jb("ConvTranspose",h,{format:Je?"NHWC":"NCHW",autoPad:E,dilations:[A],group:z,kernelShape:[V],pads:[ce,Pe],strides:[Re],wIsConst:()=>!!G()[it>>>0],outputPadding:xt?Array.from(ee().subarray(Number(xt)>>>0,Number(Rt)>>>0)):[],outputShape:Qt?Array.from(ee().subarray(Number(Qt)>>>0,Number(Er)>>>0)):[],activation:Yt(Ys)})},836953:(h,E,A,z,V,ce,Pe,Re,Je,it,xt,Rt,Qt,Er)=>{n.jb("ConvTranspose",h,{format:Re?"NHWC":"NCHW",autoPad:E,dilations:Array.from(ee().subarray(Number(A)>>>0,2+(Number(A)>>>0)>>>0)),group:z,kernelShape:Array.from(ee().subarray(Number(V)>>>0,2+(Number(V)>>>0)>>>0)),pads:Array.from(ee().subarray(Number(ce)>>>0,4+(Number(ce)>>>0)>>>0)),strides:Array.from(ee().subarray(Number(Pe)>>>0,2+(Number(Pe)>>>0)>>>0)),wIsConst:()=>!!G()[Je>>>0],outputPadding:it?Array.from(ee().subarray(Number(it)>>>0,Number(xt)>>>0)):[],outputShape:Rt?Array.from(ee().subarray(Number(Rt)>>>0,Number(Qt)>>>0)):[],activation:Yt(Er)})},837614:(h,E)=>{n.jb("GlobalAveragePool",h,{format:E?"NHWC":"NCHW"})},837705:(h,E,A,z,V,ce,Pe,Re,Je,it,xt,Rt,Qt,Er)=>{n.jb("AveragePool",h,{format:Er?"NHWC":"NCHW",auto_pad:E,ceil_mode:A,count_include_pad:z,storage_order:V,dilations:ce?Array.from(ee().subarray(Number(ce)>>>0,Number(Pe)>>>0)):[],kernel_shape:Re?Array.from(ee().subarray(Number(Re)>>>0,Number(Je)>>>0)):[],pads:it?Array.from(ee().subarray(Number(it)>>>0,Number(xt)>>>0)):[],strides:Rt?Array.from(ee().subarray(Number(Rt)>>>0,Number(Qt)>>>0)):[]})},838184:(h,E)=>{n.jb("GlobalAveragePool",h,{format:E?"NHWC":"NCHW"})},838275:(h,E,A,z,V,ce,Pe,Re,Je,it,xt,Rt,Qt,Er)=>{n.jb("AveragePool",h,{format:Er?"NHWC":"NCHW",auto_pad:E,ceil_mode:A,count_include_pad:z,storage_order:V,dilations:ce?Array.from(ee().subarray(Number(ce)>>>0,Number(Pe)>>>0)):[],kernel_shape:Re?Array.from(ee().subarray(Number(Re)>>>0,Number(Je)>>>0)):[],pads:it?Array.from(ee().subarray(Number(it)>>>0,Number(xt)>>>0)):[],strides:Rt?Array.from(ee().subarray(Number(Rt)>>>0,Number(Qt)>>>0)):[]})},838754:(h,E)=>{n.jb("GlobalMaxPool",h,{format:E?"NHWC":"NCHW"})},838841:(h,E,A,z,V,ce,Pe,Re,Je,it,xt,Rt,Qt,Er)=>{n.jb("MaxPool",h,{format:Er?"NHWC":"NCHW",auto_pad:E,ceil_mode:A,count_include_pad:z,storage_order:V,dilations:ce?Array.from(ee().subarray(Number(ce)>>>0,Number(Pe)>>>0)):[],kernel_shape:Re?Array.from(ee().subarray(Number(Re)>>>0,Number(Je)>>>0)):[],pads:it?Array.from(ee().subarray(Number(it)>>>0,Number(xt)>>>0)):[],strides:Rt?Array.from(ee().subarray(Number(Rt)>>>0,Number(Qt)>>>0)):[]})},839316:(h,E)=>{n.jb("GlobalMaxPool",h,{format:E?"NHWC":"NCHW"})},839403:(h,E,A,z,V,ce,Pe,Re,Je,it,xt,Rt,Qt,Er)=>{n.jb("MaxPool",h,{format:Er?"NHWC":"NCHW",auto_pad:E,ceil_mode:A,count_include_pad:z,storage_order:V,dilations:ce?Array.from(ee().subarray(Number(ce)>>>0,Number(Pe)>>>0)):[],kernel_shape:Re?Array.from(ee().subarray(Number(Re)>>>0,Number(Je)>>>0)):[],pads:it?Array.from(ee().subarray(Number(it)>>>0,Number(xt)>>>0)):[],strides:Rt?Array.from(ee().subarray(Number(Rt)>>>0,Number(Qt)>>>0)):[]})},839878:(h,E,A,z,V)=>{n.jb("Gemm",h,{alpha:E,beta:A,transA:z,transB:V})},839982:h=>{n.jb("MatMul",h,void 0)},840036:(h,E,A,z)=>{n.jb("ArgMax",h,{keepDims:!!E,selectLastIndex:!!A,axis:z})},840144:(h,E,A,z)=>{n.jb("ArgMin",h,{keepDims:!!E,selectLastIndex:!!A,axis:z})},840252:(h,E)=>{n.jb("Softmax",h,{axis:E})},840315:(h,E)=>{n.jb("Concat",h,{axis:E})},840375:(h,E,A,z,V)=>{n.jb("Split",h,{axis:E,numOutputs:A,splitSizes:z?Array.from(ee().subarray(Number(z)>>>0,Number(V)>>>0)):[]})},840531:h=>{n.jb("Expand",h,void 0)},840585:(h,E)=>{n.jb("Gather",h,{axis:Number(E)})},840656:(h,E)=>{n.jb("GatherElements",h,{axis:Number(E)})},840735:(h,E)=>{n.jb("GatherND",h,{batch_dims:Number(E)})},840814:(h,E,A,z,V,ce,Pe,Re,Je,it,xt)=>{n.jb("Resize",h,{antialias:E,axes:A?Array.from(ee().subarray(Number(A)>>>0,Number(z)>>>0)):[],coordinateTransformMode:Yt(V),cubicCoeffA:ce,excludeOutside:Pe,extrapolationValue:Re,keepAspectRatioPolicy:Yt(Je),mode:Yt(it),nearestMode:Yt(xt)})},841176:(h,E,A,z,V,ce,Pe)=>{n.jb("Slice",h,{starts:E?Array.from(ee().subarray(Number(E)>>>0,Number(A)>>>0)):[],ends:z?Array.from(ee().subarray(Number(z)>>>0,Number(V)>>>0)):[],axes:ce?Array.from(ee().subarray(Number(ce)>>>0,Number(Pe)>>>0)):[]})},841440:h=>{n.jb("Tile",h,void 0)},841492:(h,E,A)=>{n.jb("InstanceNormalization",h,{epsilon:E,format:A?"NHWC":"NCHW"})},841606:(h,E,A)=>{n.jb("InstanceNormalization",h,{epsilon:E,format:A?"NHWC":"NCHW"})},841720:h=>{n.jb("Range",h,void 0)},841773:(h,E)=>{n.jb("Einsum",h,{equation:Yt(E)})},841854:(h,E,A,z,V)=>{n.jb("Pad",h,{mode:E,value:A,pads:z?Array.from(ee().subarray(Number(z)>>>0,Number(V)>>>0)):[]})},841997:(h,E,A,z,V,ce)=>{n.jb("BatchNormalization",h,{epsilon:E,momentum:A,spatial:!!V,trainingMode:!!z,format:ce?"NHWC":"NCHW"})},842166:(h,E,A,z,V,ce)=>{n.jb("BatchNormalization",h,{epsilon:E,momentum:A,spatial:!!V,trainingMode:!!z,format:ce?"NHWC":"NCHW"})},842335:(h,E,A)=>{n.jb("CumSum",h,{exclusive:Number(E),reverse:Number(A)})},842432:(h,E,A)=>{n.jb("DequantizeLinear",h,{axis:E,blockSize:A})},842522:(h,E,A,z,V)=>{n.jb("GridSample",h,{align_corners:E,mode:Yt(A),padding_mode:Yt(z),format:V?"NHWC":"NCHW"})},842692:(h,E,A,z,V)=>{n.jb("GridSample",h,{align_corners:E,mode:Yt(A),padding_mode:Yt(z),format:V?"NHWC":"NCHW"})},842862:(h,E)=>{n.jb("ScatterND",h,{reduction:Yt(E)})},842947:(h,E,A,z,V,ce,Pe,Re,Je)=>{n.jb("Attention",h,{numHeads:E,isUnidirectional:A,maskFilterValue:z,scale:V,doRotary:ce,qkvHiddenSizes:Pe?Array.from(ee().subarray(Number(Re)>>>0,Number(Re)+Pe>>>0)):[],pastPresentShareBuffer:!!Je})},843219:h=>{n.jb("BiasAdd",h,void 0)},843274:h=>{n.jb("BiasSplitGelu",h,void 0)},843335:h=>{n.jb("FastGelu",h,void 0)},843391:(h,E,A,z,V,ce,Pe,Re,Je,it,xt,Rt,Qt,Er,Ys,Ja)=>{n.jb("Conv",h,{format:Rt?"NHWC":"NCHW",auto_pad:E,dilations:A?Array.from(ee().subarray(Number(A)>>>0,Number(z)>>>0)):[],group:V,kernel_shape:ce?Array.from(ee().subarray(Number(ce)>>>0,Number(Pe)>>>0)):[],pads:Re?Array.from(ee().subarray(Number(Re)>>>0,Number(Je)>>>0)):[],strides:it?Array.from(ee().subarray(Number(it)>>>0,Number(xt)>>>0)):[],w_is_const:()=>!!G()[Number(Qt)>>>0],activation:Yt(Er),activation_params:Ys?Array.from(De().subarray(Number(Ys)>>>0,Number(Ja)>>>0)):[]})},843975:h=>{n.jb("Gelu",h,void 0)},844027:(h,E,A,z,V,ce,Pe,Re,Je)=>{n.jb("GroupQueryAttention",h,{numHeads:E,kvNumHeads:A,scale:z,softcap:V,doRotary:ce,rotaryInterleaved:Pe,smoothSoftmax:Re,localWindowSize:Je})},844244:(h,E,A,z)=>{n.jb("LayerNormalization",h,{axis:E,epsilon:A,simplified:!!z})},844355:(h,E,A,z)=>{n.jb("LayerNormalization",h,{axis:E,epsilon:A,simplified:!!z})},844466:(h,E,A,z,V,ce)=>{n.jb("MatMulNBits",h,{k:E,n:A,accuracyLevel:z,bits:V,blockSize:ce})},844593:(h,E,A,z,V,ce)=>{n.jb("MultiHeadAttention",h,{numHeads:E,isUnidirectional:A,maskFilterValue:z,scale:V,doRotary:ce})},844752:(h,E)=>{n.jb("QuickGelu",h,{alpha:E})},844816:(h,E,A,z,V)=>{n.jb("RotaryEmbedding",h,{interleaved:!!E,numHeads:A,rotaryEmbeddingDim:z,scale:V})},844955:(h,E,A)=>{n.jb("SkipLayerNormalization",h,{epsilon:E,simplified:!!A})},845057:(h,E,A)=>{n.jb("SkipLayerNormalization",h,{epsilon:E,simplified:!!A})},845159:(h,E,A,z)=>{n.jb("GatherBlockQuantized",h,{gatherAxis:E,quantizeAxis:A,blockSize:z})},845280:h=>{n.Zb(h)},845314:(h,E)=>n.ac(Number(h),Number(E),n.Fb.dc,n.Fb.errors)};function ke(h,E,A){return Fr(async()=>{await n.Xb(Number(h),Number(E),Number(A))})}function He(){return typeof wasmOffsetConverter<"u"}class Fe{constructor(E){J(this,"name","ExitStatus");this.message=`Program terminated with exit(${E})`,this.status=E}}var Ze=h=>{h.terminate(),h.onmessage=()=>{}},We=[],yt=h=>{Lt.length==0&&(Gs(),Ws(Lt[0]));var E=Lt.pop();if(!E)return 6;kt.push(E),fr[h.Ab]=E,E.Ab=h.Ab;var A={Bb:"run",fc:h.ec,Hb:h.Hb,Ab:h.Ab};return E.postMessage(A,h.Mb),0},Qe=0,Oe=(h,E,...A)=>{for(var z=2*A.length,V=Dn(),ce=no(8*z),Pe=ce>>>3,Re=0;Re>>0]=Je)}return h=Uo(h,0,z,ce,E),On(V),h};function ze(h){if(c)return Oe(0,1,h);if(C=h,!(0{if(C=h,c)throw pt(h),"unwind";ze(h)},Lt=[],kt=[],Mr=[],fr={},Ut=h=>{var E=h.Ab;delete fr[E],Lt.push(h),kt.splice(kt.indexOf(h),1),h.Ab=0,Wo(E)};function Ur(){Mr.forEach(h=>h())}var Ws=h=>new Promise(E=>{h.onmessage=V=>{var ce=(V=V.data).Bb;if(V.Gb&&V.Gb!=In()){var Pe=fr[V.Gb];Pe?Pe.postMessage(V,V.Mb):M(`Internal error! Worker sent a message "${ce}" to target pthread ${V.Gb}, but that thread no longer exists!`)}else ce==="checkMailbox"?Te():ce==="spawnThread"?yt(V):ce==="cleanupThread"?Ut(fr[V.hc]):ce==="loaded"?(h.loaded=!0,E(h)):ce==="alert"?alert(`Thread ${V.ic}: ${V.text}`):V.target==="setimmediate"?h.postMessage(V):ce==="callHandler"?n[V.Qb](...V.args):ce&&M(`worker sent an unknown command ${ce}`)},h.onerror=V=>{throw M(`worker sent an error! ${V.filename}:${V.lineno}: ${V.message}`),V};var A,z=[];for(A of[])n.propertyIsEnumerable(A)&&z.push(A);h.postMessage({Bb:"load",Rb:z,kc:x,lc:v})});function Gs(){var h=new Worker((()=>{let E=URL;return self.location.href>"file:"&&self.location.href<"file;"?new E("ort.bundle.min.mjs",self.location.href):new URL(self.location.href)})(),{type:"module",workerData:"em-pthread",name:"em-pthread"});Lt.push(h)}var nn=h=>{O();var E=Se()[h+52>>>2>>>0];h=Se()[h+56>>>2>>>0],so(E,E-h),On(E)},cr=(h,E)=>{Qe=0,h=Ho(h,E),0>>=0);throw E>>>=0,A>>>=0,Se()[z.Ib+16>>>2>>>0]=0,Se()[z.Ib+4>>>2>>>0]=E,Se()[z.Ib+8>>>2>>>0]=A,h}function Ks(h,E,A,z){return c?Oe(2,1,h,E,A,z):gt(h,E,A,z)}function gt(h,E,A,z){if(h>>>=0,A>>>=0,z>>>=0,p===void 0)return 6;var V=[];return c&&V.length===0?Ks(h,E>>>=0,A,z):(h={ec:A,Ab:h,Hb:z,Mb:V},c?(h.Bb="spawnThread",postMessage(h,V),0):yt(h))}var Is=typeof TextDecoder<"u"?new TextDecoder:void 0,As=(h,E=0,A=NaN)=>{var z=(E>>>=0)+A;for(A=E;h[A]&&!(A>=z);)++A;if(16(V=(240&V)==224?(15&V)<<12|ce<<6|Pe:(7&V)<<18|ce<<12|Pe<<6|63&h[E++])?z+=String.fromCharCode(V):(V-=65536,z+=String.fromCharCode(55296|V>>10,56320|1023&V))}}else z+=String.fromCharCode(V)}return z},Yt=(h,E)=>(h>>>=0)?As(B(),h,E):"";function Jr(h,E,A){return c?Oe(3,1,h,E,A):0}function $t(h,E){if(c)return Oe(4,1,h,E)}var Fs=h=>{for(var E=0,A=0;A=z?E++:2047>=z?E+=2:55296<=z&&57343>=z?(E+=4,++A):E+=3}return E},S=(h,E,A)=>{var z=B();if(E>>>=0,0=Pe&&(Pe=65536+((1023&Pe)<<10)|1023&h.charCodeAt(++ce)),127>=Pe){if(E>=A)break;z[E++>>>0]=Pe}else{if(2047>=Pe){if(E+1>=A)break;z[E++>>>0]=192|Pe>>6}else{if(65535>=Pe){if(E+2>=A)break;z[E++>>>0]=224|Pe>>12}else{if(E+3>=A)break;z[E++>>>0]=240|Pe>>18,z[E++>>>0]=128|Pe>>12&63}z[E++>>>0]=128|Pe>>6&63}z[E++>>>0]=128|63&Pe}}z[E>>>0]=0,h=E-V}else h=0;return h};function H(h,E){if(c)return Oe(5,1,h,E)}function R(h,E,A){if(c)return Oe(6,1,h,E,A)}function W(h,E,A){return c?Oe(7,1,h,E,A):0}function X(h,E){if(c)return Oe(8,1,h,E)}function ue(h,E,A){if(c)return Oe(9,1,h,E,A)}function Ee(h,E,A,z){if(c)return Oe(10,1,h,E,A,z)}function et(h,E,A,z){if(c)return Oe(11,1,h,E,A,z)}function ot(h,E,A,z){if(c)return Oe(12,1,h,E,A,z)}function rt(h){if(c)return Oe(13,1,h)}function St(h,E){if(c)return Oe(14,1,h,E)}function lt(h,E,A){if(c)return Oe(15,1,h,E,A)}var Ot,at,Dt=()=>Me(""),Wt=h=>{for(var E="";B()[h>>>0];)E+=Ot[B()[h++>>>0]];return E},Br={},br={};function Rr(h,E,A={}){return function(z,V,ce={}){var Pe=V.name;if(!z)throw new at(`type "${Pe}" must have a positive integer typeid pointer`);if(br.hasOwnProperty(z)){if(ce.Sb)return;throw new at(`Cannot register type '${Pe}' twice`)}br[z]=V,Br.hasOwnProperty(z)&&(V=Br[z],delete Br[z],V.forEach(Re=>Re()))}(h,E,A)}var Ts=(h,E,A)=>{switch(E){case 1:return A?z=>G()[z>>>0]:z=>B()[z>>>0];case 2:return A?z=>Q()[z>>>1>>>0]:z=>le()[z>>>1>>>0];case 4:return A?z=>ee()[z>>>2>>>0]:z=>Se()[z>>>2>>>0];case 8:return A?z=>re[z>>>3]:z=>Z[z>>>3];default:throw new TypeError(`invalid integer width (${E}): ${h}`)}};function Os(h,E,A){A>>>=0,Rr(h>>>=0,{name:E=Wt(E>>>0),fromWireType:z=>z,toWireType:function(z,V){if(typeof V!="bigint"&&typeof V!="number")throw V=V===null?"null":(z=typeof V)=="object"||z==="array"||z==="function"?V.toString():""+V,new TypeError(`Cannot convert "${V}" to ${this.name}`);return typeof V=="number"&&(V=BigInt(V)),V},Cb:gr,readValueFromPointer:Ts(E,A,E.indexOf("u")==-1),Db:null})}var gr=8;function Hs(h,E,A,z){Rr(h>>>=0,{name:E=Wt(E>>>0),fromWireType:function(V){return!!V},toWireType:function(V,ce){return ce?A:z},Cb:gr,readValueFromPointer:function(V){return this.fromWireType(B()[V>>>0])},Db:null})}var cs=[],jr=[];function Hr(h){9<(h>>>=0)&&--jr[h+1]==0&&(jr[h]=void 0,cs.push(h))}var ur=h=>{if(!h)throw new at("Cannot use deleted val. handle = "+h);return jr[h]},mr=h=>{switch(h){case void 0:return 2;case null:return 4;case!0:return 6;case!1:return 8;default:let E=cs.pop()||jr.length;return jr[E]=h,jr[E+1]=1,E}};function Es(h){return this.fromWireType(Se()[h>>>2>>>0])}var Ds={name:"emscripten::val",fromWireType:h=>{var E=ur(h);return Hr(h),E},toWireType:(h,E)=>mr(E),Cb:gr,readValueFromPointer:Es,Db:null};function Ls(h){return Rr(h>>>0,Ds)}var zs=(h,E)=>{switch(E){case 4:return function(A){return this.fromWireType(De()[A>>>2>>>0])};case 8:return function(A){return this.fromWireType(Ne()[A>>>3>>>0])};default:throw new TypeError(`invalid float width (${E}): ${h}`)}};function us(h,E,A){A>>>=0,Rr(h>>>=0,{name:E=Wt(E>>>0),fromWireType:z=>z,toWireType:(z,V)=>V,Cb:gr,readValueFromPointer:zs(E,A),Db:null})}function Wr(h,E,A,z,V){if(h>>>=0,A>>>=0,E=Wt(E>>>0),V===-1&&(V=4294967295),V=Re=>Re,z===0){var ce=32-8*A;V=Re=>Re<>>ce}var Pe=E.includes("unsigned")?function(Re,Je){return Je>>>0}:function(Re,Je){return Je};Rr(h,{name:E,fromWireType:V,toWireType:Pe,Cb:gr,readValueFromPointer:Ts(E,A,z!==0),Db:null})}function je(h,E,A){function z(ce){var Pe=Se()[ce>>>2>>>0];return ce=Se()[ce+4>>>2>>>0],new V(G().buffer,ce,Pe)}var V=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,BigInt64Array,BigUint64Array][E];Rr(h>>>=0,{name:A=Wt(A>>>0),fromWireType:z,Cb:gr,readValueFromPointer:z},{Sb:!0})}function Ve(h,E){Rr(h>>>=0,{name:E=Wt(E>>>0),fromWireType:function(A){for(var z,V=Se()[A>>>2>>>0],ce=A+4,Pe=ce,Re=0;Re<=V;++Re){var Je=ce+Re;Re!=V&&B()[Je>>>0]!=0||(Pe=Yt(Pe,Je-Pe),z===void 0?z=Pe:(z+="\0",z+=Pe),Pe=Je+1)}return Zr(A),z},toWireType:function(A,z){z instanceof ArrayBuffer&&(z=new Uint8Array(z));var V=typeof z=="string";if(!(V||z instanceof Uint8Array||z instanceof Uint8ClampedArray||z instanceof Int8Array))throw new at("Cannot pass non-string to std::string");var ce=V?Fs(z):z.length,Pe=An(4+ce+1),Re=Pe+4;if(Se()[Pe>>>2>>>0]=ce,V)S(z,Re,ce+1);else if(V)for(V=0;V>>0]=Je}else for(V=0;V>>0]=z[V];return A!==null&&A.push(Zr,Pe),Pe},Cb:gr,readValueFromPointer:Es,Db(A){Zr(A)}})}var st=typeof TextDecoder<"u"?new TextDecoder("utf-16le"):void 0,qt=(h,E)=>{for(var A=h>>1,z=A+E/2;!(A>=z)&&le()[A>>>0];)++A;if(32<(A<<=1)-h&&st)return st.decode(B().slice(h,A));for(A="",z=0;!(z>=E/2);++z){var V=Q()[h+2*z>>>1>>>0];if(V==0)break;A+=String.fromCharCode(V)}return A},qs=(h,E,A)=>{if(A??(A=2147483647),2>A)return 0;var z=E;A=(A-=2)<2*h.length?A/2:h.length;for(var V=0;V>>1>>>0]=ce,E+=2}return Q()[E>>>1>>>0]=0,E-z},Bs=h=>2*h.length,Qs=(h,E)=>{for(var A=0,z="";!(A>=E/4);){var V=ee()[h+4*A>>>2>>>0];if(V==0)break;++A,65536<=V?(V-=65536,z+=String.fromCharCode(55296|V>>10,56320|1023&V)):z+=String.fromCharCode(V)}return z},En=(h,E,A)=>{if(E>>>=0,A??(A=2147483647),4>A)return 0;var z=E;A=z+A-4;for(var V=0;V=ce&&(ce=65536+((1023&ce)<<10)|1023&h.charCodeAt(++V)),ee()[E>>>2>>>0]=ce,(E+=4)+4>A)break}return ee()[E>>>2>>>0]=0,E-z},he=h=>{for(var E=0,A=0;A=z&&++A,E+=4}return E};function I(h,E,A){if(h>>>=0,E>>>=0,A=Wt(A>>>=0),E===2)var z=qt,V=qs,ce=Bs,Pe=Re=>le()[Re>>>1>>>0];else E===4&&(z=Qs,V=En,ce=he,Pe=Re=>Se()[Re>>>2>>>0]);Rr(h,{name:A,fromWireType:Re=>{for(var Je,it=Se()[Re>>>2>>>0],xt=Re+4,Rt=0;Rt<=it;++Rt){var Qt=Re+4+Rt*E;Rt!=it&&Pe(Qt)!=0||(xt=z(xt,Qt-xt),Je===void 0?Je=xt:(Je+="\0",Je+=xt),xt=Qt+E)}return Zr(Re),Je},toWireType:(Re,Je)=>{if(typeof Je!="string")throw new at(`Cannot pass non-string to C++ string type ${A}`);var it=ce(Je),xt=An(4+it+E);return Se()[xt>>>2>>>0]=it/E,V(Je,xt+4,it+E),Re!==null&&Re.push(Zr,xt),xt},Cb:gr,readValueFromPointer:Es,Db(Re){Zr(Re)}})}function N(h,E){Rr(h>>>=0,{Tb:!0,name:E=Wt(E>>>0),Cb:0,fromWireType:()=>{},toWireType:()=>{}})}function Y(h){to(h>>>0,!l,1,!i,131072,!1),Ur()}var ie=h=>{if(!pe)try{if(h(),!(0>>=0,typeof Atomics.jc=="function"&&(Atomics.jc(ee(),h>>>2,h).value.then(Te),h+=128,Atomics.store(ee(),h>>>2,1))}var Te=()=>{var h=In();h&&(de(h),ie(Ko))};function Ge(h,E){(h>>>=0)==E>>>0?setTimeout(Te):c?postMessage({Gb:h,Bb:"checkMailbox"}):(h=fr[h])&&h.postMessage({Bb:"checkMailbox"})}var Xe=[];function qe(h,E,A,z,V){for(E>>>=0,z/=2,Xe.length=z,A=V>>>0>>>3,V=0;V>>0];return(E?we[E]:eo[h])(...Xe)}var tt=()=>{Qe=0};function bt(h){h>>>=0,c?postMessage({Bb:"cleanupThread",hc:h}):Ut(fr[h])}function jt(h){}var Bt=(h,E)=>{var A=br[h];if(A===void 0)throw h=No(h),A=Wt(h),Zr(h),new at(`${E} has unknown type ${A}`);return A},nr=(h,E,A)=>{var z=[];return h=h.toWireType(z,A),z.length&&(Se()[E>>>2>>>0]=mr(z)),h};function Jt(h,E,A){return E>>>=0,A>>>=0,h=ur(h>>>0),E=Bt(E,"emval::as"),nr(E,A,h)}function yr(h,E){return E>>>=0,h=ur(h>>>0),(E=Bt(E,"emval::as")).toWireType(null,h)}var vr=h=>{try{h()}catch(E){Me(E)}},hr=0,xr=null,Cr=0,ss=[],rr={},Tr={},Ar=0,Yr=null,Ps=[];function Fr(h){return function(E){if(!pe){if(hr===0){var A=!1,z=!1;E((V=0)=>{if(!pe&&(Cr=V,A=!0,z)){hr=2,vr(()=>Qo(xr)),typeof MainLoop<"u"&&MainLoop.Pb&&MainLoop.resume(),V=!1;try{var ce=function(){var Je=ee()[xr+8>>>2>>>0];return Je=mt[Tr[Je]],--Qe,Je()}()}catch(Je){ce=Je,V=!0}var Pe=!1;if(!xr){var Re=Yr;Re&&(Yr=null,(V?Re.reject:Re.resolve)(ce),Pe=!0)}if(V&&!Pe)throw ce}}),z=!0,A||(hr=1,xr=function(){var V=An(65548),ce=V+12;Se()[V>>>2>>>0]=ce,Se()[V+4>>>2>>>0]=ce+65536,ce=ss[0];var Pe=rr[ce];return Pe===void 0&&(Pe=Ar++,rr[ce]=Pe,Tr[Pe]=ce),ce=Pe,ee()[V+8>>>2>>>0]=ce,V}(),typeof MainLoop<"u"&&MainLoop.Pb&&MainLoop.pause(),vr(()=>qo(xr)))}else hr===2?(hr=0,vr(Xo),Zr(xr),xr=null,Ps.forEach(ie)):Me(`invalid state: ${hr}`);return Cr}}(E=>{h().then(E)})}function ds(h){return h>>>=0,Fr(async()=>{var E=await ur(h);return mr(E)})}var dr=[];function _r(h,E,A,z){return A>>>=0,z>>>=0,(h=dr[h>>>0])(null,E=ur(E>>>0),A,z)}var wr={},or=h=>{var E=wr[h];return E===void 0?Wt(h):E};function qr(h,E,A,z,V){return A>>>=0,z>>>=0,V>>>=0,(h=dr[h>>>0])(E=ur(E>>>0),E[A=or(A)],z,V)}var Xs=()=>typeof globalThis=="object"?globalThis:Function("return this")();function Rs(h){return(h>>>=0)==0?mr(Xs()):(h=or(h),mr(Xs()[h]))}var xa=h=>{var E=dr.length;return dr.push(h),E},Ta=(h,E)=>{for(var A=Array(h),z=0;z>>2>>>0],"parameter "+z);return A},$o=(h,E)=>Object.defineProperty(E,"name",{value:h});function Ea(h,E,A){var z=(E=Ta(h,E>>>0)).shift();h--;var V=`return function (obj, func, destructorsRef, args) { -`,ce=0,Pe=[];A===0&&Pe.push("obj");for(var Re=["retType"],Je=[z],it=0;itxt.name).join(", ")}) => ${z.name}>`,xa($o(A,h))}function Pa(h){return h=or(h>>>0),mr(n[h])}function on(h,E){return E>>>=0,h=ur(h>>>0),E=ur(E),mr(h[E])}function Ca(h){9<(h>>>=0)&&(jr[h+1]+=1)}function Sa(){return mr([])}function $a(h){h=ur(h>>>0);for(var E=Array(h.length),A=0;A>>0))}function Ia(){return mr({})}function an(h){for(var E=ur(h>>>=0);E.length;){var A=E.pop();E.pop()(A)}Hr(h)}function Aa(h,E,A){E>>>=0,A>>>=0,h=ur(h>>>0),E=ur(E),A=ur(A),h[E]=A}function Fa(h,E){return E>>>=0,h=(h=Bt(h>>>0,"_emval_take_value")).readValueFromPointer(E),mr(h)}function Oa(h,E){h=-9007199254740992>h||9007199254740992>>=0,h=new Date(1e3*h),ee()[E>>>2>>>0]=h.getUTCSeconds(),ee()[E+4>>>2>>>0]=h.getUTCMinutes(),ee()[E+8>>>2>>>0]=h.getUTCHours(),ee()[E+12>>>2>>>0]=h.getUTCDate(),ee()[E+16>>>2>>>0]=h.getUTCMonth(),ee()[E+20>>>2>>>0]=h.getUTCFullYear()-1900,ee()[E+24>>>2>>>0]=h.getUTCDay(),h=(h.getTime()-Date.UTC(h.getUTCFullYear(),0,1,0,0,0,0))/864e5|0,ee()[E+28>>>2>>>0]=h}var ko=h=>h%4==0&&(h%100!=0||h%400==0),Io=[0,31,60,91,121,152,182,213,244,274,305,335],Xn=[0,31,59,90,120,151,181,212,243,273,304,334];function Da(h,E){h=-9007199254740992>h||9007199254740992>>=0,h=new Date(1e3*h),ee()[E>>>2>>>0]=h.getSeconds(),ee()[E+4>>>2>>>0]=h.getMinutes(),ee()[E+8>>>2>>>0]=h.getHours(),ee()[E+12>>>2>>>0]=h.getDate(),ee()[E+16>>>2>>>0]=h.getMonth(),ee()[E+20>>>2>>>0]=h.getFullYear()-1900,ee()[E+24>>>2>>>0]=h.getDay();var A=(ko(h.getFullYear())?Io:Xn)[h.getMonth()]+h.getDate()-1|0;ee()[E+28>>>2>>>0]=A,ee()[E+36>>>2>>>0]=-60*h.getTimezoneOffset(),A=new Date(h.getFullYear(),6,1).getTimezoneOffset();var z=new Date(h.getFullYear(),0,1).getTimezoneOffset();h=0|(A!=z&&h.getTimezoneOffset()==Math.min(z,A)),ee()[E+32>>>2>>>0]=h}function La(h){h>>>=0;var E=new Date(ee()[h+20>>>2>>>0]+1900,ee()[h+16>>>2>>>0],ee()[h+12>>>2>>>0],ee()[h+8>>>2>>>0],ee()[h+4>>>2>>>0],ee()[h>>>2>>>0],0),A=ee()[h+32>>>2>>>0],z=E.getTimezoneOffset(),V=new Date(E.getFullYear(),6,1).getTimezoneOffset(),ce=new Date(E.getFullYear(),0,1).getTimezoneOffset(),Pe=Math.min(ce,V);return 0>A?ee()[h+32>>>2>>>0]=+(V!=ce&&Pe==z):0>>2>>>0]=E.getDay(),A=(ko(E.getFullYear())?Io:Xn)[E.getMonth()]+E.getDate()-1|0,ee()[h+28>>>2>>>0]=A,ee()[h>>>2>>>0]=E.getSeconds(),ee()[h+4>>>2>>>0]=E.getMinutes(),ee()[h+8>>>2>>>0]=E.getHours(),ee()[h+12>>>2>>>0]=E.getDate(),ee()[h+16>>>2>>>0]=E.getMonth(),ee()[h+20>>>2>>>0]=E.getYear(),h=E.getTime(),BigInt(isNaN(h)?-1:h/1e3)}function Jn(h,E,A,z,V,ce,Pe){return c?Oe(16,1,h,E,A,z,V,ce,Pe):-52}function Ao(h,E,A,z,V,ce){if(c)return Oe(17,1,h,E,A,z,V,ce)}var Js={},za=()=>performance.timeOrigin+performance.now();function Yn(h,E){if(c)return Oe(18,1,h,E);if(Js[h]&&(clearTimeout(Js[h].id),delete Js[h]),!E)return 0;var A=setTimeout(()=>{delete Js[h],ie(()=>Go(h,performance.timeOrigin+performance.now()))},E);return Js[h]={id:A,qc:E},0}function gc(h,E,A,z){h>>>=0,E>>>=0,A>>>=0,z>>>=0;var V=new Date().getFullYear(),ce=new Date(V,0,1).getTimezoneOffset();V=new Date(V,6,1).getTimezoneOffset();var Pe=Math.max(ce,V);Se()[h>>>2>>>0]=60*Pe,ee()[E>>>2>>>0]=+(ce!=V),h=(E=Re=>{var Je=Math.abs(Re);return`UTC${0<=Re?"-":"+"}${String(Math.floor(Je/60)).padStart(2,"0")}${String(Je%60).padStart(2,"0")}`})(ce),E=E(V),VDate.now();function Fo(h,E,A){return 0<=h&&3>=h?(h===0?h=Date.now():h=performance.timeOrigin+performance.now(),re[A>>>0>>>3]=BigInt(Math.round(1e6*h)),0):28}var Pn=[],Cn=(h,E)=>{Pn.length=0;for(var A;A=B()[h++>>>0];){var z=A!=105;E+=(z&=A!=112)&&E%8?4:0,Pn.push(A==112?Se()[E>>>2>>>0]:A==106?re[E>>>3]:A==105?ee()[E>>>2>>>0]:Ne()[E>>>3>>>0]),E+=z?8:4}return Pn};function Ra(h,E,A){return h>>>=0,E=Cn(E>>>0,A>>>0),we[h](...E)}function ja(h,E,A){return h>>>=0,E=Cn(E>>>0,A>>>0),we[h](...E)}var Na=()=>{};function Va(h,E){return M(Yt(h>>>0,E>>>0))}var Ua=()=>{throw Qe+=1,"unwind"};function Wa(){return 4294901760}var Oo=()=>navigator.hardwareConcurrency;function Ga(){return Me("Cannot use emscripten_pc_get_function without -sUSE_OFFSET_CONVERTER"),0}function Ka(h){h>>>=0;var E=B().length;if(h<=E||4294901760=A;A*=2){var z=E*(1+.2/A);z=Math.min(z,h+100663296);e:{z=(Math.min(4294901760,65536*Math.ceil(Math.max(h,z)/65536))-x.buffer.byteLength+65535)/65536|0;try{x.grow(z),O();var V=1;break e}catch{}V=void 0}if(V)return!0}return!1}var ln=()=>(Me("Cannot use convertFrameToPC (needed by __builtin_return_address) without -sUSE_OFFSET_CONVERTER"),0),cn={},Sn=h=>{h.forEach(E=>{ln()})};function Do(){var h=Error().stack.toString().split(` -`);return h[0]=="Error"&&h.shift(),Sn(h),cn.Lb=ln(),cn.cc=h,cn.Lb}function Ha(h,E,A){if(h>>>=0,E>>>=0,cn.Lb==h)var z=cn.cc;else(z=Error().stack.toString().split(` -`))[0]=="Error"&&z.shift(),Sn(z);for(var V=3;z[V]&&ln()!=h;)++V;for(h=0;h>>2>>>0]=ln();return h}var $n,Cs={},Lo=()=>{if(!$n){var h,E={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:(typeof navigator=="object"&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8",_:"./this.program"};for(h in Cs)Cs[h]===void 0?delete E[h]:E[h]=Cs[h];var A=[];for(h in E)A.push(`${h}=${E[h]}`);$n=A}return $n};function qa(h,E){if(c)return Oe(19,1,h,E);h>>>=0,E>>>=0;var A=0;return Lo().forEach((z,V)=>{var ce=E+A;for(V=Se()[h+4*V>>>2>>>0]=ce,ce=0;ce>>0]=z.charCodeAt(ce);G()[V>>>0]=0,A+=z.length+1}),0}function zo(h,E){if(c)return Oe(20,1,h,E);h>>>=0,E>>>=0;var A=Lo();Se()[h>>>2>>>0]=A.length;var z=0;return A.forEach(V=>z+=V.length+1),Se()[E>>>2>>>0]=z,0}function Qa(h){return c?Oe(21,1,h):52}function Bo(h,E,A,z){return c?Oe(22,1,h,E,A,z):52}function Zn(h,E,A,z){return c?Oe(23,1,h,E,A,z):70}var Xa=[null,[],[]];function Ro(h,E,A,z){if(c)return Oe(24,1,h,E,A,z);E>>>=0,A>>>=0,z>>>=0;for(var V=0,ce=0;ce>>2>>>0],Re=Se()[E+4>>>2>>>0];E+=8;for(var Je=0;Je>>0],xt=Xa[h];it===0||it===10?((h===1?T:M)(As(xt)),xt.length=0):xt.push(it)}V+=Re}return Se()[z>>>2>>>0]=V,0}c||function(){for(var h=n.numThreads-1;h--;)Gs();We.unshift(()=>{be++,function(E){c?E():Promise.all(Lt.map(Ws)).then(E)}(()=>$e())})}();for(var jo=Array(256),kn=0;256>kn;++kn)jo[kn]=String.fromCharCode(kn);Ot=jo,at=n.BindingError=class extends Error{constructor(h){super(h),this.name="BindingError"}},n.InternalError=class extends Error{constructor(h){super(h),this.name="InternalError"}},jr.push(0,1,void 0,1,null,1,!0,1,!1,1),n.count_emval_handles=()=>jr.length/2-5-cs.length;var mt,eo=[ze,pt,Ks,Jr,$t,H,R,W,X,ue,Ee,et,ot,rt,St,lt,Jn,Ao,Yn,qa,zo,Qa,Bo,Zn,Ro];(async function(){function h(z,V){return mt=z.exports,mt=function(){var ce=mt,Pe={};for(let[Re,Je]of Object.entries(ce))Pe[Re]=typeof Je=="function"?(...it)=>{ss.push(Re);try{return Je(...it)}finally{pe||(ss.pop(),xr&&hr===1&&ss.length===0&&(hr=0,Qe+=1,vr(oo),typeof Fibers<"u"&&Fibers.rc()))}}:Je;return Pe}(),mt=function(){var ce=mt,Pe=Je=>it=>Je(it)>>>0,Re=Je=>()=>Je()>>>0;return(ce=Object.assign({},ce)).Da=Pe(ce.Da),ce.fb=Re(ce.fb),ce.hb=Pe(ce.hb),ce.tb=Pe(ce.tb),ce.ub=Re(ce.ub),ce.__cxa_get_exception_ptr=Pe(ce.__cxa_get_exception_ptr),ce}(),Mr.push(mt.ib),v=V,$e(),mt}be++;var E=Le();if(n.instantiateWasm)return new Promise(z=>{n.instantiateWasm(E,(V,ce)=>{h(V,ce),z(V.exports)})});if(c)return new Promise(z=>{Ae=V=>{var ce=new WebAssembly.Instance(V,Le());z(h(ce,V))}});xe??(xe=n.locateFile?n.locateFile?n.locateFile("ort-wasm-simd-threaded.jsep.wasm",w):w+"ort-wasm-simd-threaded.jsep.wasm":new URL("/assets/ort-wasm-simd-threaded.jsep-B0T3yYHD.wasm",self.location.href).href);try{var A=await async function(z){var V=xe;if(!_e&&typeof WebAssembly.instantiateStreaming=="function"&&!oe(V))try{var ce=fetch(V,{credentials:"same-origin"});return await WebAssembly.instantiateStreaming(ce,z)}catch(Pe){M(`wasm streaming compile failed: ${Pe}`),M("falling back to ArrayBuffer instantiation")}return async function(Pe,Re){try{var Je=await async function(it){if(!_e)try{var xt=await f(it);return new Uint8Array(xt)}catch{}if(it==xe&&_e)it=new Uint8Array(_e);else{if(!_)throw"both async and sync fetching of the wasm failed";it=_(it)}return it}(Pe);return await WebAssembly.instantiate(Je,Re)}catch(it){M(`failed to asynchronously prepare wasm: ${it}`),Me(it)}}(V,z)}(E);return h(A.instance,A.module)}catch(z){return o(z),Promise.reject(z)}})();var No=h=>(No=mt.Da)(h),Vo=()=>(Vo=mt.Ea)();n._OrtInit=(h,E)=>(n._OrtInit=mt.Fa)(h,E),n._OrtGetLastError=(h,E)=>(n._OrtGetLastError=mt.Ga)(h,E),n._OrtCreateSessionOptions=(h,E,A,z,V,ce,Pe,Re,Je,it)=>(n._OrtCreateSessionOptions=mt.Ha)(h,E,A,z,V,ce,Pe,Re,Je,it),n._OrtAppendExecutionProvider=(h,E,A,z,V)=>(n._OrtAppendExecutionProvider=mt.Ia)(h,E,A,z,V),n._OrtAddFreeDimensionOverride=(h,E,A)=>(n._OrtAddFreeDimensionOverride=mt.Ja)(h,E,A),n._OrtAddSessionConfigEntry=(h,E,A)=>(n._OrtAddSessionConfigEntry=mt.Ka)(h,E,A),n._OrtReleaseSessionOptions=h=>(n._OrtReleaseSessionOptions=mt.La)(h),n._OrtCreateSession=(h,E,A)=>(n._OrtCreateSession=mt.Ma)(h,E,A),n._OrtReleaseSession=h=>(n._OrtReleaseSession=mt.Na)(h),n._OrtGetInputOutputCount=(h,E,A)=>(n._OrtGetInputOutputCount=mt.Oa)(h,E,A),n._OrtGetInputOutputMetadata=(h,E,A,z)=>(n._OrtGetInputOutputMetadata=mt.Pa)(h,E,A,z),n._OrtFree=h=>(n._OrtFree=mt.Qa)(h),n._OrtCreateTensor=(h,E,A,z,V,ce)=>(n._OrtCreateTensor=mt.Ra)(h,E,A,z,V,ce),n._OrtGetTensorData=(h,E,A,z,V)=>(n._OrtGetTensorData=mt.Sa)(h,E,A,z,V),n._OrtReleaseTensor=h=>(n._OrtReleaseTensor=mt.Ta)(h),n._OrtCreateRunOptions=(h,E,A,z)=>(n._OrtCreateRunOptions=mt.Ua)(h,E,A,z),n._OrtAddRunConfigEntry=(h,E,A)=>(n._OrtAddRunConfigEntry=mt.Va)(h,E,A),n._OrtReleaseRunOptions=h=>(n._OrtReleaseRunOptions=mt.Wa)(h),n._OrtCreateBinding=h=>(n._OrtCreateBinding=mt.Xa)(h),n._OrtBindInput=(h,E,A)=>(n._OrtBindInput=mt.Ya)(h,E,A),n._OrtBindOutput=(h,E,A,z)=>(n._OrtBindOutput=mt.Za)(h,E,A,z),n._OrtClearBoundOutputs=h=>(n._OrtClearBoundOutputs=mt._a)(h),n._OrtReleaseBinding=h=>(n._OrtReleaseBinding=mt.$a)(h),n._OrtRunWithBinding=(h,E,A,z,V)=>(n._OrtRunWithBinding=mt.ab)(h,E,A,z,V),n._OrtRun=(h,E,A,z,V,ce,Pe,Re)=>(n._OrtRun=mt.bb)(h,E,A,z,V,ce,Pe,Re),n._OrtEndProfiling=h=>(n._OrtEndProfiling=mt.cb)(h),n._JsepOutput=(h,E,A)=>(n._JsepOutput=mt.db)(h,E,A),n._JsepGetNodeName=h=>(n._JsepGetNodeName=mt.eb)(h);var In=()=>(In=mt.fb)(),Zr=n._free=h=>(Zr=n._free=mt.gb)(h),An=n._malloc=h=>(An=n._malloc=mt.hb)(h),to=(h,E,A,z,V,ce)=>(to=mt.kb)(h,E,A,z,V,ce),ro=()=>(ro=mt.lb)(),Uo=(h,E,A,z,V)=>(Uo=mt.mb)(h,E,A,z,V),Wo=h=>(Wo=mt.nb)(h),Fn=h=>(Fn=mt.ob)(h),Go=(h,E)=>(Go=mt.pb)(h,E),Ko=()=>(Ko=mt.qb)(),so=(h,E)=>(so=mt.rb)(h,E),On=h=>(On=mt.sb)(h),no=h=>(no=mt.tb)(h),Dn=()=>(Dn=mt.ub)(),Ho=n.dynCall_ii=(h,E)=>(Ho=n.dynCall_ii=mt.vb)(h,E),qo=h=>(qo=mt.wb)(h),oo=()=>(oo=mt.xb)(),Qo=h=>(Qo=mt.yb)(h),Xo=()=>(Xo=mt.zb)();return n.stackSave=()=>Dn(),n.stackRestore=h=>On(h),n.stackAlloc=h=>no(h),n.setValue=function(h,E,A="i8"){switch(A.endsWith("*")&&(A="*"),A){case"i1":case"i8":G()[h>>>0]=E;break;case"i16":Q()[h>>>1>>>0]=E;break;case"i32":ee()[h>>>2>>>0]=E;break;case"i64":re[h>>>3]=BigInt(E);break;case"float":De()[h>>>2>>>0]=E;break;case"double":Ne()[h>>>3>>>0]=E;break;case"*":Se()[h>>>2>>>0]=E;break;default:Me(`invalid type for setValue: ${A}`)}},n.getValue=function(h,E="i8"){switch(E.endsWith("*")&&(E="*"),E){case"i1":case"i8":return G()[h>>>0];case"i16":return Q()[h>>>1>>>0];case"i32":return ee()[h>>>2>>>0];case"i64":return re[h>>>3];case"float":return De()[h>>>2>>>0];case"double":return Ne()[h>>>3>>>0];case"*":return Se()[h>>>2>>>0];default:Me(`invalid type for getValue: ${E}`)}},n.UTF8ToString=Yt,n.stringToUTF8=S,n.lengthBytesUTF8=Fs,function h(){if(0{ki(),Di=typeof location>"u"?void 0:location.origin,Li=self.location.href>"file:"&&self.location.href<"file;",Md=()=>{{if(Li){let e=URL;return new URL(new e("ort.bundle.min.mjs",self.location.href).href,Di).href}return self.location.href}},ts=Md(),bd=()=>{if(ts&&!ts.startsWith("blob:"))return ts.substring(0,ts.lastIndexOf("/")+1)},ra=(e,r)=>{try{let t=r??ts;return(t?new URL(e,t):new URL(e)).origin===Di}catch{return!1}},yd=(e,r)=>{let t=r??ts;try{return(t?new URL(e,t):new URL(e)).href}catch{return}},vd=(e,r)=>`${r??"./"}${e}`,zi=async e=>{let r=await(await fetch(e,{credentials:"same-origin"})).blob();return URL.createObjectURL(r)},xd=async e=>(await import(e)).default,Bi=($x(),uo(hd)).default,Td=async()=>{if(!ts)throw new Error("Failed to load proxy worker: cannot determine the script source URL.");if(ra(ts))return[void 0,Bi()];let e=await zi(ts);return[e,Bi(e)]},Ri=(kx(),uo(fd)).default,Ed=async(e,r,t)=>{if(!e&&!r&&Ri&&ts&&ra(ts))return[void 0,Ri];{let s="ort-wasm-simd-threaded.jsep.mjs",o=e??yd(s,r),n=t&&o&&!ra(o,r),a=n?await zi(o):o??vd(s,r);return[n?a:void 0,await xd(a)]}}}),Ni,sa,_o,Vi,Pd,Cd,Sd,Ui,Zt,_n=Ue(()=>{ji(),sa=!1,_o=!1,Vi=!1,Pd=()=>{if(typeof SharedArrayBuffer>"u")return!1;try{return typeof MessageChannel<"u"&&new MessageChannel().port1.postMessage(new SharedArrayBuffer(1)),WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,5,4,1,3,1,1,10,11,1,9,0,65,0,254,16,2,0,26,11]))}catch{return!1}},Cd=()=>{try{return WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,10,30,1,28,0,65,0,253,15,253,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,253,186,1,26,11]))}catch{return!1}},Sd=()=>{try{return WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,5,1,96,0,1,123,3,2,1,0,10,19,1,17,0,65,1,253,15,65,2,253,15,65,3,253,15,253,147,2,11]))}catch{return!1}},Ui=async e=>{if(sa)return Promise.resolve();if(_o)throw new Error("multiple calls to 'initializeWebAssembly()' detected.");if(Vi)throw new Error("previous call to 'initializeWebAssembly()' failed.");_o=!0;let r=e.initTimeout,t=e.numThreads;if(e.simd!==!1){if(e.simd==="relaxed"){if(!Sd())throw new Error("Relaxed WebAssembly SIMD is not supported in the current environment.")}else if(!Cd())throw new Error("WebAssembly SIMD is not supported in the current environment.")}let s=Pd();t>1&&!s&&(typeof self<"u"&&!self.crossOriginIsolated&&console.warn("env.wasm.numThreads is set to "+t+", but this will not work unless you enable crossOriginIsolated mode. See https://web.dev/cross-origin-isolation-guide/ for more info."),console.warn("WebAssembly multi-threading is not supported in the current environment. Falling back to single-threading."),e.numThreads=t=1);let o=e.wasmPaths,n=typeof o=="string"?o:void 0,a=o==null?void 0:o.mjs,i=(a==null?void 0:a.href)??a,l=o==null?void 0:o.wasm,c=(l==null?void 0:l.href)??l,p=e.wasmBinary,[d,u]=await Ed(i,n,t>1),f=!1,_=[];if(r>0&&_.push(new Promise(b=>{setTimeout(()=>{f=!0,b()},r)})),_.push(new Promise((b,k)=>{let w={numThreads:t};if(p)w.wasmBinary=p;else if(c||n)w.locateFile=y=>c??n+y;else if(i&&i.indexOf("blob:")!==0)w.locateFile=y=>new URL(y,i).href;else if(d){let y=bd();y&&(w.locateFile=$=>y+$)}u(w).then(y=>{_o=!1,sa=!0,Ni=y,b(),d&&URL.revokeObjectURL(d)},y=>{_o=!1,Vi=!0,k(y)})})),await Promise.race(_),f)throw new Error(`WebAssembly backend initializing failed due to timeout: ${r}ms`)},Zt=()=>{if(sa&&Ni)return Ni;throw new Error("WebAssembly is not initialized yet.")}}),gs,na,Xt,Wi=Ue(()=>{_n(),gs=(e,r)=>{let t=Zt(),s=t.lengthBytesUTF8(e)+1,o=t._malloc(s);return t.stringToUTF8(e,o,s),r.push(o),o},na=(e,r,t,s)=>{if(typeof e=="object"&&e!==null){if(t.has(e))throw new Error("Circular reference in options");t.add(e)}Object.entries(e).forEach(([o,n])=>{let a=r?r+o:o;if(typeof n=="object")na(n,a+".",t,s);else if(typeof n=="string"||typeof n=="number")s(a,n.toString());else if(typeof n=="boolean")s(a,n?"1":"0");else throw new Error(`Can't handle extra config type: ${typeof n}`)})},Xt=e=>{let r=Zt(),t=r.stackSave();try{let s=r.PTR_SIZE,o=r.stackAlloc(2*s);r._OrtGetLastError(o,o+s);let n=Number(r.getValue(o,s===4?"i32":"i64")),a=r.getValue(o+s,"*"),i=a?r.UTF8ToString(a):"";throw new Error(`${e} ERROR_CODE: ${n}, ERROR_MESSAGE: ${i}`)}finally{r.stackRestore(t)}}}),$d,Ix=Ue(()=>{_n(),Wi(),$d=e=>{let r=Zt(),t=0,s=[],o=e||{};try{if((e==null?void 0:e.logSeverityLevel)===void 0)o.logSeverityLevel=2;else if(typeof e.logSeverityLevel!="number"||!Number.isInteger(e.logSeverityLevel)||e.logSeverityLevel<0||e.logSeverityLevel>4)throw new Error(`log serverity level is not valid: ${e.logSeverityLevel}`);if((e==null?void 0:e.logVerbosityLevel)===void 0)o.logVerbosityLevel=0;else if(typeof e.logVerbosityLevel!="number"||!Number.isInteger(e.logVerbosityLevel))throw new Error(`log verbosity level is not valid: ${e.logVerbosityLevel}`);(e==null?void 0:e.terminate)===void 0&&(o.terminate=!1);let n=0;return(e==null?void 0:e.tag)!==void 0&&(n=gs(e.tag,s)),t=r._OrtCreateRunOptions(o.logSeverityLevel,o.logVerbosityLevel,!!o.terminate,n),t===0&&Xt("Can't create run options."),(e==null?void 0:e.extra)!==void 0&&na(e.extra,"",new WeakSet,(a,i)=>{let l=gs(a,s),c=gs(i,s);r._OrtAddRunConfigEntry(t,l,c)!==0&&Xt(`Can't set a run config entry: ${a} - ${i}.`)}),[t,s]}catch(n){throw t!==0&&r._OrtReleaseRunOptions(t),s.forEach(a=>r._free(a)),n}}}),kd,Id,Ad,fo,Fd,Od,Ax=Ue(()=>{_n(),Wi(),kd=e=>{switch(e){case"disabled":return 0;case"basic":return 1;case"extended":return 2;case"all":return 99;default:throw new Error(`unsupported graph optimization level: ${e}`)}},Id=e=>{switch(e){case"sequential":return 0;case"parallel":return 1;default:throw new Error(`unsupported execution mode: ${e}`)}},Ad=e=>{e.extra||(e.extra={}),e.extra.session||(e.extra.session={});let r=e.extra.session;r.use_ort_model_bytes_directly||(r.use_ort_model_bytes_directly="1"),e.executionProviders&&e.executionProviders.some(t=>(typeof t=="string"?t:t.name)==="webgpu")&&(e.enableMemPattern=!1)},fo=(e,r,t,s)=>{let o=gs(r,s),n=gs(t,s);Zt()._OrtAddSessionConfigEntry(e,o,n)!==0&&Xt(`Can't set a session config entry: ${r} - ${t}.`)},Fd=async(e,r,t)=>{for(let s of r){let o=typeof s=="string"?s:s.name,n=[];switch(o){case"webnn":if(o="WEBNN",typeof s!="string"){let p=s==null?void 0:s.deviceType;p&&fo(e,"deviceType",p,t)}break;case"webgpu":if(o="JS",typeof s!="string"){let p=s;if(p!=null&&p.preferredLayout){if(p.preferredLayout!=="NCHW"&&p.preferredLayout!=="NHWC")throw new Error(`preferredLayout must be either 'NCHW' or 'NHWC': ${p.preferredLayout}`);fo(e,"preferredLayout",p.preferredLayout,t)}}break;case"wasm":case"cpu":continue;default:throw new Error(`not supported execution provider: ${o}`)}let a=gs(o,t),i=n.length,l=0,c=0;if(i>0){l=Zt()._malloc(i*Zt().PTR_SIZE),t.push(l),c=Zt()._malloc(i*Zt().PTR_SIZE),t.push(c);for(let p=0;p{let r=Zt(),t=0,s=[],o=e||{};Ad(o);try{let n=kd(o.graphOptimizationLevel??"all"),a=Id(o.executionMode??"sequential"),i=typeof o.logId=="string"?gs(o.logId,s):0,l=o.logSeverityLevel??2;if(!Number.isInteger(l)||l<0||l>4)throw new Error(`log serverity level is not valid: ${l}`);let c=o.logVerbosityLevel??0;if(!Number.isInteger(c)||c<0||c>4)throw new Error(`log verbosity level is not valid: ${c}`);let p=typeof o.optimizedModelFilePath=="string"?gs(o.optimizedModelFilePath,s):0;if(t=r._OrtCreateSessionOptions(n,!!o.enableCpuMemArena,!!o.enableMemPattern,a,!!o.enableProfiling,0,i,l,c,p),t===0&&Xt("Can't create session options."),o.executionProviders&&await Fd(t,o.executionProviders,s),o.enableGraphCapture!==void 0){if(typeof o.enableGraphCapture!="boolean")throw new Error(`enableGraphCapture must be a boolean value: ${o.enableGraphCapture}`);fo(t,"enableGraphCapture",o.enableGraphCapture.toString(),s)}if(o.freeDimensionOverrides)for(let[d,u]of Object.entries(o.freeDimensionOverrides)){if(typeof d!="string")throw new Error(`free dimension override name must be a string: ${d}`);if(typeof u!="number"||!Number.isInteger(u)||u<0)throw new Error(`free dimension override value must be a non-negative integer: ${u}`);let f=gs(d,s);r._OrtAddFreeDimensionOverride(t,f,u)!==0&&Xt(`Can't set a free dimension override: ${d} - ${u}.`)}return o.extra!==void 0&&na(o.extra,"",new WeakSet,(d,u)=>{fo(t,d,u,s)}),[t,s]}catch(n){throw t!==0&&r._OrtReleaseSessionOptions(t)!==0&&Xt("Can't release session options."),s.forEach(a=>r._free(a)),n}}}),Wn,js,fn,Gi,oa,Ki,Hi,qi,Mt=Ue(()=>{Wn=e=>{switch(e){case"int8":return 3;case"uint8":return 2;case"bool":return 9;case"int16":return 5;case"uint16":return 4;case"int32":return 6;case"uint32":return 12;case"float16":return 10;case"float32":return 1;case"float64":return 11;case"string":return 8;case"int64":return 7;case"uint64":return 13;case"int4":return 22;case"uint4":return 21;default:throw new Error(`unsupported data type: ${e}`)}},js=e=>{switch(e){case 3:return"int8";case 2:return"uint8";case 9:return"bool";case 5:return"int16";case 4:return"uint16";case 6:return"int32";case 12:return"uint32";case 10:return"float16";case 1:return"float32";case 11:return"float64";case 8:return"string";case 7:return"int64";case 13:return"uint64";case 22:return"int4";case 21:return"uint4";default:throw new Error(`unsupported data type: ${e}`)}},fn=(e,r)=>{let t=[-1,4,1,1,2,2,4,8,-1,1,2,8,4,8,-1,-1,-1,-1,-1,-1,-1,.5,.5][e],s=typeof r=="number"?r:r.reduce((o,n)=>o*n,1);return t>0?Math.ceil(s*t):void 0},Gi=e=>{switch(e){case"float16":return typeof Float16Array<"u"&&Float16Array.from?Float16Array:Uint16Array;case"float32":return Float32Array;case"uint8":return Uint8Array;case"int8":return Int8Array;case"uint16":return Uint16Array;case"int16":return Int16Array;case"int32":return Int32Array;case"bool":return Uint8Array;case"float64":return Float64Array;case"uint32":return Uint32Array;case"int64":return BigInt64Array;case"uint64":return BigUint64Array;default:throw new Error(`unsupported type: ${e}`)}},oa=e=>{switch(e){case"verbose":return 0;case"info":return 1;case"warning":return 2;case"error":return 3;case"fatal":return 4;default:throw new Error(`unsupported logging level: ${e}`)}},Ki=e=>e==="float32"||e==="float16"||e==="int32"||e==="int64"||e==="uint32"||e==="uint8"||e==="bool"||e==="uint4"||e==="int4",Hi=e=>e==="float32"||e==="float16"||e==="int32"||e==="int64"||e==="uint32"||e==="uint64"||e==="int8"||e==="uint8"||e==="bool"||e==="uint4"||e==="int4",qi=e=>{switch(e){case"none":return 0;case"cpu":return 1;case"cpu-pinned":return 2;case"texture":return 3;case"gpu-buffer":return 4;case"ml-tensor":return 5;default:throw new Error(`unsupported data location: ${e}`)}}}),Qi,Dd=Ue(()=>{ki(),Qi=async e=>{if(typeof e=="string"){let r=await fetch(e);if(!r.ok)throw new Error(`failed to load external data file: ${e}`);let t=r.headers.get("Content-Length"),s=t?parseInt(t,10):0;if(s<1073741824)return new Uint8Array(await r.arrayBuffer());{if(!r.body)throw new Error(`failed to load external data file: ${e}, no response body.`);let o=r.body.getReader(),n;try{n=new ArrayBuffer(s)}catch(i){if(i instanceof RangeError){let l=Math.ceil(s/65536);n=new WebAssembly.Memory({initial:l,maximum:l}).buffer}else throw i}let a=0;for(;;){let{done:i,value:l}=await o.read();if(i)break;let c=l.byteLength;new Uint8Array(n,a,c).set(l),a+=c}return new Uint8Array(n,0,s)}}else return e instanceof Blob?new Uint8Array(await e.arrayBuffer()):e instanceof Uint8Array?e:new Uint8Array(e)}}),Ld,zd,Bd,Rd,Xi,jd,zt,Ns=Ue(()=>{Mt(),Ld=["V","I","W","E","F"],zd=(e,r)=>{console.log(`[${Ld[e]},${new Date().toISOString()}]${r}`)},Xi=(e,r)=>{Bd=e,Rd=r},jd=(e,r)=>{let t=oa(e),s=oa(Bd);t>=s&&zd(t,typeof r=="function"?r():r)},zt=(...e)=>{Rd&&jd(...e)}}),Nd,Gn,ye,aa,Vd,Ud,Wd,Pt=Ue(()=>{Nd=class{static calcMatMulShape(e,r){return e[1]!==r[0]?void 0:[e[0],r[1]]}},Gn=class{static calcShape(e,r,t=!1){let s=e.length,o=r.length;if(s===0)return r;if(o===0)return e;let n=Math.max(e.length,r.length),a=new Array(n);if(t){if(s<2||o<2)return;let i=Nd.calcMatMulShape([e[s-2],e[s-1]],[r[o-2],r[o-1]]);if(i===void 0)return;[a[n-2],a[n-1]]=i}for(let i=t?3:1;i<=n;i++){let l=s-i<0?1:e[s-i],c=o-i<0?1:r[o-i];if(l!==c&&l>1&&c>1)return;let p=Math.max(l,c);if(l&&c)a[n-i]=Math.max(l,c);else{if(p>1)return;a[n-i]=0}}return a}static isValidBroadcast(e,r){let t=e.length,s=r.length;if(t>s)return!1;for(let o=1;o<=t;o++)if(e[t-o]!==1&&e[t-o]!==r[s-o])return!1;return!0}},ye=class bi{static size(r){return bi.getSizeFromDimensionRange(r,0,r.length)}static convertShape(r,t=4){let s=r.length;if(s===0)return[];let o=new Array(s),n=s-1;for(;n>=0;){if(r[n]%t===0){o[n]=r[n]/t;break}if(t%r[n]!==0)throw new Error("cannot convert shape");o[n]=1,t/=r[n],n--}for(n--;n>=0;n--)o[n]=r[n];return o}static sizeFromDimension(r,t){if(t<0||t>r.length)throw new Error(`invalid dimension of ${t} for sizeFromDimension as Tensor has ${r.length} dimensions.`);return bi.getSizeFromDimensionRange(r,t,r.length)}static sizeToDimension(r,t){if(t<0||t>r.length)throw new Error(`invalid dimension of ${t} for sizeToDimension as Tensor has ${r.length} dimensions.`);return bi.getSizeFromDimensionRange(r,0,t)}static getSizeFromDimensionRange(r,t,s){let o=1;for(let n=t;n=0;--o)s[o]=s[o+1]*r[o+1];return s}static normalizeAxis(r,t){if(r<-t&&r>=t)throw new Error("unsupported axis for this operation.");return r<0?r+t:r}static normalizeAxes(r,t){return r.map(s=>this.normalizeAxis(s,t??r.length))}static sortBasedOnPerm(r,t){return t?t.map(s=>r[s]):r.slice().reverse()}static padShape(r,t){let s=r.length;return r.map((o,n)=>o+t[n]+t[n+s])}static areEqual(r,t){return r.length!==t.length?!1:r.every((s,o)=>s===t[o])}},aa=class Zo{static adjustPoolAttributes(r,t,s,o,n,a){if(!r&&s.length!==t.length-2)throw new Error("length of specified kernel shapes should be 2 less than length of input dimensions");if(r)for(let i=0;i=s.length?s.push(t[i+2]):s[i]=t[i+2];for(let i=0;i=s[i]||a[i+s.length]>=s[i])throw new Error("pads should be smaller than kernel")}}static adjustPadsBasedOnAutoPad(r,t,s,o,n,a,i){if(i){if(n.length!==2*(r.length-2))throw new Error("length of pads should be twice the length of data dimensions");if(t.length!==r.length-2)throw new Error("length of strides should be the length of data dimensions");if(o.length!==r.length-2)throw new Error("length of kernel shapes should be the length of data dimensions");for(let l=0;l{Mt(),Ji=(e,r)=>new(Gi(r))(e)}),Yi,Zi,Kd,el,Hd,tl,rl,sl,qd,Qd,Fx=Ue(()=>{Ns(),Yi=(e,r=!0)=>{if(e.byteLength%8!==0)throw new Error("Invalid Uint8Array length - must be a multiple of 8 (BigInt).");let t=e.byteLength/8,s=new BigInt64Array(e.buffer,e.byteOffset,t),o=new Int32Array(t);for(let n=0;n2147483647n||a<-2147483648n)throw new Error(`Overflow occurred when converting BigInt to Int32 at index ${n}: ${a}`);o[n]=Number(a)}return r?new Uint8Array(o.buffer):o},Zi=(e,r=!0)=>{if(e.byteLength%4!==0)throw new Error("Invalid Uint8Array length - must be a multiple of 4 (Int32).");let t=e.byteLength/4,s=new Int32Array(e.buffer,e.byteOffset,t),o=BigInt64Array.from(s,BigInt);return r?new Uint8Array(o.buffer):o},Kd=1,el=()=>Kd++,Hd=new Map([["float32",32],["float16",16],["int32",32],["uint32",32],["int64",64],["uint64",64],["int8",8],["uint8",8],["int4",4],["uint4",4]]),tl=(e,r)=>{let t=Hd.get(e);if(!t)throw new Error("Unsupported data type.");return r.length>0?Math.ceil(r.reduce((s,o)=>s*o)*t/8):0},rl=class{constructor(e){this.shouldConvertInt64toInt32=!1,this.isInt64ToInt32Converted=!1;let{sessionId:r,context:t,tensor:s,dataType:o,shape:n,shouldConvertInt64toInt32:a=!1}=e;this.sessionId=r,this.mlContext=t,this.mlTensor=s,this.dataType=o,this.tensorShape=n,this.shouldConvertInt64toInt32=a}get tensor(){return this.mlTensor}get type(){return this.dataType}get shape(){return this.tensorShape}get byteLength(){return tl(this.dataType,this.tensorShape)}destroy(){zt("verbose",()=>"[WebNN] TensorWrapper.destroy"),this.mlTensor.destroy()}write(e){this.mlContext.writeTensor(this.mlTensor,e)}async read(e,r){if(e){let t=await this.mlContext.readTensor(this.mlTensor),s=Zi(new Uint8Array(t));if(r){(r instanceof ArrayBuffer?new Uint8Array(r):new Uint8Array(r.buffer,r.byteOffset,r.byteLength)).set(s);return}else return s.buffer}else return r?this.mlContext.readTensor(this.mlTensor,r):this.mlContext.readTensor(this.mlTensor)}canReuseTensor(e,r,t){return this.mlContext===e&&this.dataType===r&&this.tensorShape.length===t.length&&this.tensorShape.every((s,o)=>s===t[o])}setIsInt64ToInt32Converted(e){this.isInt64ToInt32Converted=e}},sl=class{constructor(e,r){this.tensorManager=e,this.wrapper=r}get tensorWrapper(){return this.wrapper}releaseTensor(){this.tensorWrapper&&(this.tensorManager.releaseTensor(this.tensorWrapper),this.wrapper=void 0)}async ensureTensor(e,r,t,s){let o=r,n=this.tensorManager.getMLContext(e),a=o==="int64"&&!n.opSupportLimits().input.dataTypes.includes("int64");if(a&&(o="int32",zt("verbose",()=>"[WebNN] TensorIdTracker.ensureTensor: convert dataType from int64 to int32")),this.wrapper){if(this.wrapper.canReuseTensor(n,o,t))return this.wrapper.tensor;if(s){if(this.wrapper.byteLength!==tl(o,t))throw new Error("Unable to copy data to tensor with different size.");this.activeUpload=new Uint8Array(await this.wrapper.read())}this.tensorManager.releaseTensor(this.wrapper)}let i=typeof MLTensorUsage>"u"?void 0:MLTensorUsage.READ|MLTensorUsage.WRITE;return this.wrapper=await this.tensorManager.getCachedTensor(e,o,t,i,!0,!0,a),s&&this.activeUpload&&(this.wrapper.write(this.activeUpload),this.activeUpload=void 0),this.wrapper.tensor}upload(e){let r=e;if(this.wrapper)if(this.wrapper.shouldConvertInt64toInt32&&(r=Yi(e,!0),this.wrapper.setIsInt64ToInt32Converted(!0)),r.byteLength===this.wrapper.byteLength){this.wrapper.write(r);return}else zt("verbose",()=>"Data size does not match tensor size. Releasing tensor."),this.releaseTensor();this.activeUpload?this.activeUpload.set(r):this.activeUpload=new Uint8Array(r)}async download(e){var r,t,s;if(this.activeUpload){let o=(r=this.wrapper)!=null&&r.isInt64ToInt32Converted?Zi(this.activeUpload):this.activeUpload;if(e){e instanceof ArrayBuffer?new Uint8Array(e).set(o):new Uint8Array(e.buffer,e.byteOffset,e.byteLength).set(o);return}else return o.buffer}if(!this.wrapper)throw new Error("Tensor has not been created.");return e?this.wrapper.read((t=this.wrapper)==null?void 0:t.shouldConvertInt64toInt32,e):this.wrapper.read((s=this.wrapper)==null?void 0:s.shouldConvertInt64toInt32)}},qd=class{constructor(e){this.backend=e,this.tensorTrackersById=new Map,this.freeTensors=[],this.externalTensors=new Set}getMLContext(e){let r=this.backend.getMLContext(e);if(!r)throw new Error("MLContext not found for session.");return r}reserveTensorId(){let e=el();return this.tensorTrackersById.set(e,new sl(this)),e}releaseTensorId(e){let r=this.tensorTrackersById.get(e);r&&(this.tensorTrackersById.delete(e),r.tensorWrapper&&this.releaseTensor(r.tensorWrapper))}async ensureTensor(e,r,t,s,o){zt("verbose",()=>`[WebNN] TensorManager.ensureTensor {tensorId: ${r}, dataType: ${t}, shape: ${s}, copyOld: ${o}}`);let n=this.tensorTrackersById.get(r);if(!n)throw new Error("Tensor not found.");return n.ensureTensor(e,t,s,o)}upload(e,r){let t=this.tensorTrackersById.get(e);if(!t)throw new Error("Tensor not found.");t.upload(r)}async download(e,r){zt("verbose",()=>`[WebNN] TensorManager.download {tensorId: ${e}, dstBuffer: ${r==null?void 0:r.byteLength}}`);let t=this.tensorTrackersById.get(e);if(!t)throw new Error("Tensor not found.");return t.download(r)}releaseTensorsForSession(e){for(let r of this.freeTensors)r.sessionId===e&&r.destroy();this.freeTensors=this.freeTensors.filter(r=>r.sessionId!==e)}registerTensor(e,r,t,s){let o=this.getMLContext(e),n=el(),a=new rl({sessionId:e,context:o,tensor:r,dataType:t,shape:s});return this.tensorTrackersById.set(n,new sl(this,a)),this.externalTensors.add(a),n}async getCachedTensor(e,r,t,s,o,n,a=!1){let i=this.getMLContext(e);for(let[c,p]of this.freeTensors.entries())if(p.canReuseTensor(i,r,t)){zt("verbose",()=>`[WebNN] Reusing tensor {dataType: ${r}, shape: ${t}}`);let d=this.freeTensors.splice(c,1)[0];return d.sessionId=e,d}zt("verbose",()=>`[WebNN] MLContext.createTensor {dataType: ${r}, shape: ${t}}`);let l=await i.createTensor({dataType:r,shape:t,dimensions:t,usage:s,writable:o,readable:n});return new rl({sessionId:e,context:i,tensor:l,dataType:r,shape:t,shouldConvertInt64toInt32:a})}releaseTensor(e){this.externalTensors.has(e)&&this.externalTensors.delete(e),this.freeTensors.push(e)}},Qd=(...e)=>new qd(...e)}),ia,Xd,Jd,Ox=Ue(()=>{Mt(),_n(),Gd(),Fx(),Ns(),ia=new Map([[1,"float32"],[10,"float16"],[6,"int32"],[12,"uint32"],[7,"int64"],[13,"uint64"],[22,"int4"],[21,"uint4"],[3,"int8"],[2,"uint8"],[9,"uint8"]]),Xd=(e,r)=>{if(e===r)return!0;if(e===void 0||r===void 0)return!1;let t=Object.keys(e).sort(),s=Object.keys(r).sort();return t.length===s.length&&t.every((o,n)=>o===s[n]&&e[o]===r[o])},Jd=class{constructor(e){this.tensorManager=Qd(this),this.mlContextBySessionId=new Map,this.sessionIdsByMLContext=new Map,this.mlContextCache=[],this.sessionGraphInputs=new Map,this.temporaryGraphInputs=[],this.temporarySessionTensorIds=new Map,Xi(e.logLevel,!!e.debug)}get currentSessionId(){if(this.activeSessionId===void 0)throw new Error("No active session");return this.activeSessionId}onRunStart(e){zt("verbose",()=>`[WebNN] onRunStart {sessionId: ${e}}`),this.activeSessionId=e}onRunEnd(e){zt("verbose",()=>`[WebNN] onRunEnd {sessionId: ${e}}`);let r=this.temporarySessionTensorIds.get(e);if(r){for(let t of r)zt("verbose",()=>`[WebNN] releasing temporary tensor {tensorId: ${t}}`),this.tensorManager.releaseTensorId(t);this.temporarySessionTensorIds.delete(e),this.activeSessionId=void 0}}async createMLContext(e){if(e instanceof GPUDevice){let t=this.mlContextCache.findIndex(s=>s.gpuDevice===e);if(t!==-1)return this.mlContextCache[t].mlContext;{let s=await navigator.ml.createContext(e);return this.mlContextCache.push({gpuDevice:e,mlContext:s}),s}}else if(e===void 0){let t=this.mlContextCache.findIndex(s=>s.options===void 0&&s.gpuDevice===void 0);if(t!==-1)return this.mlContextCache[t].mlContext;{let s=await navigator.ml.createContext();return this.mlContextCache.push({mlContext:s}),s}}let r=this.mlContextCache.findIndex(t=>Xd(t.options,e));if(r!==-1)return this.mlContextCache[r].mlContext;{let t=await navigator.ml.createContext(e);return this.mlContextCache.push({options:e,mlContext:t}),t}}registerMLContext(e,r){this.mlContextBySessionId.set(e,r);let t=this.sessionIdsByMLContext.get(r);t||(t=new Set,this.sessionIdsByMLContext.set(r,t)),t.add(e),this.temporaryGraphInputs.length>0&&(this.sessionGraphInputs.set(e,this.temporaryGraphInputs),this.temporaryGraphInputs=[])}onReleaseSession(e){this.sessionGraphInputs.delete(e);let r=this.mlContextBySessionId.get(e);if(!r)return;this.tensorManager.releaseTensorsForSession(e),this.mlContextBySessionId.delete(e);let t=this.sessionIdsByMLContext.get(r);if(t.delete(e),t.size===0){this.sessionIdsByMLContext.delete(r);let s=this.mlContextCache.findIndex(o=>o.mlContext===r);s!==-1&&this.mlContextCache.splice(s,1)}}getMLContext(e){return this.mlContextBySessionId.get(e)}reserveTensorId(){return this.tensorManager.reserveTensorId()}releaseTensorId(e){zt("verbose",()=>`[WebNN] releaseTensorId {tensorId: ${e}}`),this.tensorManager.releaseTensorId(e)}async ensureTensor(e,r,t,s,o){let n=ia.get(t);if(!n)throw new Error(`Unsupported ONNX data type: ${t}`);return this.tensorManager.ensureTensor(e??this.currentSessionId,r,n,s,o)}async createTemporaryTensor(e,r,t){zt("verbose",()=>`[WebNN] createTemporaryTensor {onnxDataType: ${r}, shape: ${t}}`);let s=ia.get(r);if(!s)throw new Error(`Unsupported ONNX data type: ${r}`);let o=this.tensorManager.reserveTensorId();await this.tensorManager.ensureTensor(e,o,s,t,!1);let n=this.temporarySessionTensorIds.get(e);return n?n.push(o):this.temporarySessionTensorIds.set(e,[o]),o}uploadTensor(e,r){if(!Zt().shouldTransferToMLTensor)throw new Error("Trying to upload to a MLTensor while shouldTransferToMLTensor is false");zt("verbose",()=>`[WebNN] uploadTensor {tensorId: ${e}, data: ${r.byteLength}}`),this.tensorManager.upload(e,r)}async downloadTensor(e,r){return this.tensorManager.download(e,r)}createMLTensorDownloader(e,r){return async()=>{let t=await this.tensorManager.download(e);return Ji(t,r)}}registerMLTensor(e,r,t,s){let o=ia.get(t);if(!o)throw new Error(`Unsupported ONNX data type: ${t}`);let n=this.tensorManager.registerTensor(e,r,o,s);return zt("verbose",()=>`[WebNN] registerMLTensor {tensor: ${r}, dataType: ${o}, dimensions: ${s}} -> {tensorId: ${n}}`),n}registerMLConstant(e,r,t,s,o,n,a=!1){if(!n)throw new Error("External mounted files are not available.");let i=e;e.startsWith("./")&&(i=e.substring(2));let l=n.get(i);if(!l)throw new Error(`File with name ${i} not found in preloaded files.`);if(r+t>l.byteLength)throw new Error("Out of bounds: data offset and length exceed the external file data size.");let c=l.slice(r,r+t).buffer,p;switch(o.dataType){case"float32":p=new Float32Array(c);break;case"float16":p=typeof Float16Array<"u"&&Float16Array.from?new Float16Array(c):new Uint16Array(c);break;case"int32":p=new Int32Array(c);break;case"uint32":p=new Uint32Array(c);break;case"int64":a?(p=Yi(new Uint8Array(c),!1),o.dataType="int32"):p=new BigInt64Array(c);break;case"uint64":p=new BigUint64Array(c);break;case"int8":p=new Int8Array(c);break;case"int4":case"uint4":case"uint8":p=new Uint8Array(c);break;default:throw new Error(`Unsupported data type: ${o.dataType} in creating WebNN Constant from external data.`)}return zt("verbose",()=>`[WebNN] registerMLConstant {dataType: ${o.dataType}, shape: ${o.shape}}} ${a?"(Note: it was int64 data type and registered to int32 as workaround)":""}`),s.constant(o,p)}registerGraphInput(e){this.temporaryGraphInputs.push(e)}isGraphInput(e,r){let t=this.sessionGraphInputs.get(e);return t?t.includes(r):!1}isInt64Supported(e){var r;return!!((r=this.mlContextBySessionId.get(e))!=null&&r.opSupportLimits().input.dataTypes.includes("int64"))}flush(){}}}),nl=Ue(()=>{}),ol,la,ca,Yd,Zd,al,il,ep,tp,Dx=Ue(()=>{Ns(),nl(),ol=new Map([[64,250],[128,200],[256,200],[512,200],[2048,230],[4096,200],[8192,50],[16384,50],[32768,50],[65536,50],[131072,50],[262144,50],[524288,50],[1048576,50],[2097152,30],[4194304,20],[8388608,10],[12582912,10],[16777216,10],[26214400,15],[33554432,22],[44236800,2],[58982400,6],[67108864,6],[134217728,6],[167772160,6]]),la=[],ca=e=>Math.ceil(Number(e)/16)*16,Yd=e=>{for(let r=0;rZd++,il=async(e,r,t,s)=>{let o=ca(t),n=e.device.createBuffer({size:o,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ});try{let a=e.getCommandEncoder();e.endComputePass(),a.copyBufferToBuffer(r,0,n,0,o),e.flush(),await n.mapAsync(GPUMapMode.READ);let i=n.getMappedRange();if(s){let l=s();return l.set(new Uint8Array(i,0,t)),l}else return new Uint8Array(i.slice(0,t))}finally{n.destroy()}},ep=class{constructor(e){this.backend=e,this.storageCache=new Map,this.freeBuffers=new Map,this.freeUniformBuffers=new Map,this.buffersPending=[],this.capturedPendingBuffers=new Map;for(let[r]of ol)la.push(r),this.freeBuffers.set(r,[]),this.freeUniformBuffers.set(r,[]);this.sessionCount=0}upload(e,r){let t=r.buffer,s=r.byteOffset,o=r.byteLength,n=ca(o),a=this.storageCache.get(e);if(!a)throw new Error("gpu data for uploading does not exist");if(Number(a.originalSize)!==o)throw new Error(`inconsistent data size. gpu data size=${a.originalSize}, data size=${o}`);let i=this.backend.device.createBuffer({mappedAtCreation:!0,size:n,usage:GPUBufferUsage.MAP_WRITE|GPUBufferUsage.COPY_SRC}),l=i.getMappedRange();new Uint8Array(l).set(new Uint8Array(t,s,o)),i.unmap();let c=this.backend.device.createCommandEncoder();c.copyBufferToBuffer(i,0,a.gpuData.buffer,0,n),this.backend.device.queue.submit([c.finish()]),i.destroy(),zt("verbose",()=>`[WebGPU] GpuDataManager.upload(id=${e})`)}memcpy(e,r){let t=this.storageCache.get(e);if(!t)throw new Error("source gpu data for memcpy does not exist");let s=this.storageCache.get(r);if(!s)throw new Error("destination gpu data for memcpy does not exist");if(t.originalSize!==s.originalSize)throw new Error("inconsistent source and destination gpu data size");let o=ca(t.originalSize),n=this.backend.getCommandEncoder();this.backend.endComputePass(),n.copyBufferToBuffer(t.gpuData.buffer,0,s.gpuData.buffer,0,o)}registerExternalBuffer(e,r,t){let s;if(t){if(s=t[0],e===t[1])return zt("verbose",()=>`[WebGPU] GpuDataManager.registerExternalBuffer(size=${r}) => id=${s}, buffer is the same, skip.`),s;if(this.backend.capturedCommandList.has(this.backend.currentSessionId))throw new Error(`Registering a different external buffer under graph capture mode is not supported yet. - Please use the previous external buffer!`)}else s=al();return this.storageCache.set(s,{gpuData:{id:s,type:0,buffer:e},originalSize:r}),zt("verbose",()=>`[WebGPU] GpuDataManager.registerExternalBuffer(size=${r}) => id=${s}, registered.`),s}unregisterExternalBuffer(e){e!==void 0&&(this.storageCache.delete(e),zt("verbose",()=>`[WebGPU] GpuDataManager.unregisterExternalBuffer() => id=${e}`))}create(e,r=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST){let t=Yd(e),s,o=(r&GPUBufferUsage.STORAGE)===GPUBufferUsage.STORAGE,n=(r&GPUBufferUsage.UNIFORM)===GPUBufferUsage.UNIFORM;if(o||n){let i=(o?this.freeBuffers:this.freeUniformBuffers).get(t);i?i.length>0?s=i.pop():s=this.backend.device.createBuffer({size:t,usage:r}):s=this.backend.device.createBuffer({size:t,usage:r})}else s=this.backend.device.createBuffer({size:t,usage:r});let a={id:al(),type:0,buffer:s};return this.storageCache.set(a.id,{gpuData:a,originalSize:Number(e)}),zt("verbose",()=>`[WebGPU] GpuDataManager.create(size=${e}) => id=${a.id}`),a}get(e){var r;return(r=this.storageCache.get(e))==null?void 0:r.gpuData}release(e){let r=typeof e=="bigint"?Number(e):e,t=this.storageCache.get(r);if(!t){if(this.storageCache.size===0)return 0;throw new Error("releasing data does not exist")}return zt("verbose",()=>`[WebGPU] GpuDataManager.release(id=${r}), gpuDataId=${t.gpuData.id}`),this.storageCache.delete(r),this.buffersPending.push(t.gpuData.buffer),t.originalSize}async download(e,r){let t=this.storageCache.get(Number(e));if(!t)throw new Error("data does not exist");await il(this.backend,t.gpuData.buffer,t.originalSize,r)}refreshPendingBuffers(){if(this.buffersPending.length!==0)if(this.backend.sessionStatus==="default"){for(let e of this.buffersPending){let r=ol.get(e.size);if((e.usage&GPUBufferUsage.STORAGE)===GPUBufferUsage.STORAGE){let t=this.freeBuffers.get(e.size)||[];r===void 0||t.length>=r?e.destroy():t.push(e)}else if((e.usage&GPUBufferUsage.UNIFORM)===GPUBufferUsage.UNIFORM){let t=this.freeUniformBuffers.get(e.size)||[];r===void 0||t.length>=r?e.destroy():t.push(e)}else e.destroy()}this.buffersPending=[]}else{let e=this.capturedPendingBuffers.get(this.backend.currentSessionId);e||(e=[],this.capturedPendingBuffers.set(this.backend.currentSessionId,e));for(let r of this.buffersPending)e.push(r);this.buffersPending=[]}}dispose(){this.freeBuffers.forEach(e=>{e.forEach(r=>{r.destroy()})}),this.freeUniformBuffers.forEach(e=>{e.forEach(r=>{r.destroy()})}),this.storageCache.forEach(e=>{e.gpuData.buffer.destroy()}),this.capturedPendingBuffers.forEach(e=>{e.forEach(r=>{r.destroy()})}),this.storageCache=new Map,this.freeBuffers=new Map,this.freeUniformBuffers=new Map,this.capturedPendingBuffers=new Map}onCreateSession(){this.sessionCount+=1}onReleaseSession(e){let r=this.capturedPendingBuffers.get(e);r&&(r.forEach(t=>{t.destroy()}),this.capturedPendingBuffers.delete(e)),this.sessionCount-=1,this.sessionCount===0&&(zt("warning",()=>"[WebGPU] Clearing webgpu buffer cache"),this.storageCache.forEach(t=>{t.gpuData.buffer.destroy()}),this.storageCache=new Map)}},tp=(...e)=>new ep(...e)}),rp,Kt,pr=Ue(()=>{rp=class{constructor(e){Object.assign(this,e)}get cacheKey(){return this.key||(this.key=Object.getOwnPropertyNames(this).sort().map(e=>`${this[e]}`).join(";")),this.key}},Kt=e=>new rp(e)}),Kn,ua,Ir,Vr,dt,lr,ll,Hn,en,ct,go,Ie,nt,sp,cl,np,op,Ct=Ue(()=>{Mt(),Pt(),Kn=64,ua=(e,r)=>{if(r===3)throw new Error("vec3 has same alignment as vec4, use vec4 instead");switch(Number(e)){case 10:return r>1?`vec${r}`:"f16";case 1:return r>1?`vec${r}`:"f32";case 6:return r>1?`vec${r}`:"i32";case 12:return r>1?`vec${r}`:"u32";case 7:if(r>1)throw new Error("currently not supported vecX of uint64 yet");return["vec2","i32"];case 13:if(r>1)throw new Error("currently not supported vecX of uint64 yet");return["vec2","u32"];case 9:if(r!==4)throw new Error("bool must be vec4");return["u32","vec4"];case 22:return"i32";case 21:return"u32";default:throw new Error(`Unknown data type: ${e}`)}},Ir=(e,r=1)=>{let t=ua(e,r);return typeof t=="string"?t:t[0]},Vr=(e,r=1)=>{let t=ua(e,r);return typeof t=="string"?t:t[1]},dt=(...e)=>{let r=[];return e.forEach(t=>{t.length!==0&&r.push({type:12,data:t},{type:12,data:ye.computeStrides(t)})}),r},lr=e=>e%4===0?4:e%2===0?2:1,ll=(e="f32",r,t="0")=>!r||r===1?`${e}(${t})`:`vec${r}<${e}>(${t})`,Hn=(e,r,t)=>e==="f32"?t:r===1?`f32(${t})`:`vec${r}(${t})`,en=(e,r)=>r===4?`(${e}.x + ${e}.y + ${e}.z + ${e}.w)`:r===2?`(${e}.x + ${e}.y)`:r===3?`(${e}.x + ${e}.y + ${e}.z)`:e,ct=(e,r,t,s)=>e.startsWith("uniforms.")&&t>4?typeof r=="string"?s==="f16"?`${e}[(${r}) / 8][(${r}) % 8 / 4][(${r}) % 8 % 4]`:`${e}[(${r}) / 4][(${r}) % 4]`:s==="f16"?`${e}[${Math.floor(r/8)}][${Math.floor(r%8/4)}][${r%8%4}]`:`${e}[${Math.floor(r/4)}][${r%4}]`:t>1?`${e}[${r}]`:e,go=(e,r,t,s,o)=>{let n=typeof t=="number",a=n?t:t.length,i=[...new Array(a).keys()],l=a<2?"u32":a<=4?`vec${a}`:`array`,c=ua(r,o),p=typeof c=="string"?c:c[1],d=typeof c=="string"?c:c[0],u={indices:l,value:p,storage:d,tensor:r},f=oe=>typeof oe=="string"?oe:`${oe}u`,_={offsetToIndices:!1,indicesToOffset:!1,broadcastedIndicesToOffset:!1,set:!1,setByIndices:!1,get:!1,getByIndices:!1},b=n?"uniforms.":"",k=`${b}${e}_shape`,w=`${b}${e}_strides`,y="";for(let oe=0;oe ${u.indices} { - var indices: ${u.indices}; - var current = offset; - ${y} - return indices; - }`,T=oe=>(_.offsetToIndices=!0,a<2?oe:`o2i_${e}(${oe})`),M=[];if(a>=2)for(let oe=a-1;oe>=0;oe--)M.push(`${ct(w,oe,a)} * (indices[${oe}])`);let x=a<2?"":` - fn i2o_${e}(indices: ${u.indices}) -> u32 { - return ${M.join("+")}; - }`,v=oe=>(_.indicesToOffset=!0,a<2?oe:`i2o_${e}(${oe})`),C=(...oe)=>a===0?"0u":`${u.indices}(${oe.map(f).join(",")})`,F=(oe,G)=>a<2?`${oe}`:`${ct(oe,G,a)}`,D=(oe,G,B)=>a<2?`${oe}=${B};`:`${ct(oe,G,a)}=${B};`,K={},U=(oe,G)=>{_.broadcastedIndicesToOffset=!0;let B=`${G.name}broadcastedIndicesTo${e}Offset`;if(B in K)return`${B}(${oe})`;let Q=[];for(let le=a-1;le>=0;le--){let ee=G.indicesGet("outputIndices",le+G.rank-a);Q.push(`${F(w,le)} * (${ee} % ${F(k,le)})`)}return K[B]=`fn ${B}(outputIndices: ${G.type.indices}) -> u32 { - return ${Q.length>0?Q.join("+"):"0u"}; - }`,`${B}(${oe})`},j=(oe,G)=>(()=>{if(u.storage===u.value)return`${e}[${oe}]=${G};`;if(u.storage==="vec2"&&u.value==="i32")return`${e}[${oe}]=vec2(u32(${G}), select(0u, 0xFFFFFFFFu, ${G} < 0));`;if(u.storage==="vec2"&&u.value==="u32")return`${e}[${oe}]=vec2(u32(${G}), 0u);`;if(u.storage==="u32"&&u.value==="vec4")return`${e}[${oe}]=dot(vec4(0x1, 0x100, 0x10000, 0x1000000), vec4(${G}));`;throw new Error(`not supported combination of storage type ${u.storage} and value type ${u.value} yet`)})(),se=oe=>(()=>{if(u.storage===u.value)return`${e}[${oe}]`;if(u.storage==="vec2"&&u.value==="i32")return`i32(${e}[${oe}].x)`;if(u.storage==="vec2"&&u.value==="u32")return`u32(${e}[${oe}].x)`;if(u.storage==="u32"&&u.value==="vec4")return`vec4(bool(${e}[${oe}] & 0xFFu), bool(${e}[${oe}] & 0xFF00u), bool(${e}[${oe}] & 0xFF0000u), bool(${e}[${oe}] & 0xFF000000u))`;throw new Error(`not supported combination of storage type ${u.storage} and value type ${u.value} yet`)})(),q=a<2?"":` - fn get_${e}ByIndices(indices: ${u.indices}) -> ${p} { - return ${se(`i2o_${e}(indices)`)}; - }`,re=a<2?"":(()=>{let oe=i.map(B=>`d${B}: u32`).join(", "),G=i.map(B=>`d${B}`).join(", ");return` - fn get_${e}(${oe}) -> ${p} { - return get_${e}ByIndices(${C(G)}); - }`})(),Z=(...oe)=>{if(oe.length!==a)throw new Error(`indices length must be ${a}`);let G=oe.map(f).join(",");return a===0?se("0u"):a===1?se(G[0]):(_.get=!0,_.getByIndices=!0,_.indicesToOffset=!0,`get_${e}(${G})`)},ae=oe=>a<2?se(oe):(_.getByIndices=!0,_.indicesToOffset=!0,`get_${e}ByIndices(${oe})`),_e=a<2?"":` - fn set_${e}ByIndices(indices: ${u.indices}, value: ${p}) { - ${j(`i2o_${e}(indices)`,"value")} - }`,pe=a<2?"":(()=>{let oe=i.map(B=>`d${B}: u32`).join(", "),G=i.map(B=>`d${B}`).join(", ");return` - fn set_${e}(${oe}, value: ${p}) { - set_${e}ByIndices(${C(G)}, value); - }`})();return{impl:()=>{let oe=[],G=!1;return _.offsetToIndices&&(oe.push($),G=!0),_.indicesToOffset&&(oe.push(x),G=!0),_.broadcastedIndicesToOffset&&(Object.values(K).forEach(B=>oe.push(B)),G=!0),_.set&&(oe.push(pe),G=!0),_.setByIndices&&(oe.push(_e),G=!0),_.get&&(oe.push(re),G=!0),_.getByIndices&&(oe.push(q),G=!0),!n&&G&&oe.unshift(`const ${k} = ${u.indices}(${t.join(",")});`,`const ${w} = ${u.indices}(${ye.computeStrides(t).join(",")});`),oe.join(` -`)},type:u,offsetToIndices:T,indicesToOffset:v,broadcastedIndicesToOffset:U,indices:C,indicesGet:F,indicesSet:D,set:(...oe)=>{if(oe.length!==a+1)throw new Error(`indices length must be ${a}`);let G=oe[a];if(typeof G!="string")throw new Error("value must be string");let B=oe.slice(0,a).map(f).join(",");return a===0?j("0u",G):a===1?j(B[0],G):(_.set=!0,_.setByIndices=!0,_.indicesToOffset=!0,`set_${e}(${B}, ${G})`)},setByOffset:j,setByIndices:(oe,G)=>a<2?j(oe,G):(_.setByIndices=!0,_.indicesToOffset=!0,`set_${e}ByIndices(${oe}, ${G});`),get:Z,getByOffset:se,getByIndices:ae,usage:s,name:e,strides:w,shape:k,rank:a}},Ie=(e,r,t,s=1)=>go(e,r,t,"input",s),nt=(e,r,t,s=1)=>go(e,r,t,"output",s),sp=(e,r,t)=>go(e,r,t,"atomicOutput",1),cl=(e,r,t,s=1)=>go(e,r,t,"internal",s),np=class{constructor(e,r){this.normalizedDispatchGroup=e,this.limits=r,this.internalVariables=[],this.variables=[],this.uniforms=[],this.variableIndex=0}guardAgainstOutOfBoundsWorkgroupSizes(e){return`if (global_idx >= ${typeof e=="number"?`${e}u`:e}) { return; }`}mainStart(e=Kn){let r=typeof e=="number"?e:e[0],t=typeof e=="number"?1:e[1],s=typeof e=="number"?1:e[2];if(r>this.limits.maxComputeWorkgroupSizeX||t>this.limits.maxComputeWorkgroupSizeY||s>this.limits.maxComputeWorkgroupSizeZ)throw new Error(`workgroup size [${r}, ${t}, ${s}] exceeds the maximum workgroup size [${this.limits.maxComputeWorkgroupSizeX}, ${this.limits.maxComputeWorkgroupSizeY}, ${this.limits.maxComputeWorkgroupSizeZ}].`);if(r*t*s>this.limits.maxComputeInvocationsPerWorkgroup)throw new Error(`workgroup size [${r}, ${t}, ${s}] exceeds the maximum workgroup invocations ${this.limits.maxComputeInvocationsPerWorkgroup}.`);let o=this.normalizedDispatchGroup[1]===1&&this.normalizedDispatchGroup[2]===1,n=o?`@builtin(global_invocation_id) global_id : vec3, - @builtin(workgroup_id) workgroup_id : vec3, - @builtin(local_invocation_index) local_idx : u32, - @builtin(local_invocation_id) local_id : vec3`:`@builtin(global_invocation_id) global_id : vec3, - @builtin(local_invocation_id) local_id : vec3, - @builtin(local_invocation_index) local_idx : u32, - @builtin(workgroup_id) workgroup_id : vec3, - @builtin(num_workgroups) num_workgroups : vec3`,a=o?`let global_idx = global_id.x; - let workgroup_index = workgroup_id.x;`:`let workgroup_index = workgroup_id.z * num_workgroups[0] * num_workgroups[1] + - workgroup_id.y * num_workgroups[0] + workgroup_id.x; - let global_idx = workgroup_index * ${r*t*s}u + local_idx;`;return`@compute @workgroup_size(${r}, ${t}, ${s}) - fn main(${n}) { - ${a} - `}appendVariableUniforms(e){e.rank!==0&&(e.shape.startsWith("uniforms.")&&this.uniforms.push({name:e.shape.replace("uniforms.",""),type:"u32",length:e.rank}),e.strides.startsWith("uniforms.")&&this.uniforms.push({name:e.strides.replace("uniforms.",""),type:"u32",length:e.rank}))}declareVariable(e,r){if(e.usage==="internal")throw new Error("cannot use internal variable with declareVariable(). use registerInternalVariables() instead.");this.variables.push(e),this.appendVariableUniforms(e);let t=e.usage==="input"?"read":"read_write",s=e.usage==="atomicOutput"?"atomic":e.type.storage;return`@group(0) @binding(${r}) var ${e.name}: array<${s}>;`}declareVariables(...e){return e.map(r=>this.declareVariable(r,this.variableIndex++)).join(` -`)}registerInternalVariable(e){if(e.usage!=="internal")throw new Error("cannot use input or output variable with registerInternalVariable(). use declareVariables() instead.");this.internalVariables.push(e),this.appendVariableUniforms(e)}registerInternalVariables(...e){return e.forEach(r=>this.registerInternalVariable(r)),this}registerUniform(e,r,t=1){return this.uniforms.push({name:e,type:r,length:t}),this}registerUniforms(e){return this.uniforms=this.uniforms.concat(e),this}uniformDeclaration(){if(this.uniforms.length===0)return"";let e=[];for(let{name:r,type:t,length:s}of this.uniforms)if(s&&s>4)t==="f16"?e.push(`@align(16) ${r}:array, ${Math.ceil(s/8)}>`):e.push(`${r}:array, ${Math.ceil(s/4)}>`);else{let o=s==null||s===1?t:`vec${s}<${t}>`;e.push(`${r}:${o}`)}return` - struct Uniforms { ${e.join(", ")} }; - @group(0) @binding(${this.variableIndex}) var uniforms: Uniforms;`}get additionalImplementations(){return this.uniformDeclaration()+this.variables.map(e=>e.impl()).join(` -`)+this.internalVariables.map(e=>e.impl()).join(` -`)}get variablesInfo(){if(this.uniforms.length===0)return;let e=r=>[12,10,1,6][["u32","f16","f32","i32"].indexOf(r)];return this.uniforms.map(r=>[e(r.type),r.length??1])}},op=(e,r)=>new np(e,r)}),ap,ul,ip,lp,cp,up,rs,dp,pp,tn=Ue(()=>{Mt(),Pt(),pr(),Ct(),ap=(e,r)=>{if(!e||e.length!==1)throw new Error("Transpose requires 1 input.");if(r.length!==0&&r.length!==e[0].dims.length)throw new Error(`perm size ${r.length} does not match input rank ${e[0].dims.length}`)},ul=(e,r)=>r.length!==0?r:[...new Array(e).keys()].reverse(),ip=(e,r)=>ye.sortBasedOnPerm(e,ul(e.length,r)),lp=(e,r,t,s)=>{let o=`fn perm(i: ${s.type.indices}) -> ${t.type.indices} { - var a: ${t.type.indices};`;for(let n=0;n{let t=[],s=[];for(let o=0;o{let t=0;for(let s=0;s{let t=e.dataType,s=e.dims.length,o=ul(s,r),n=ip(e.dims,o),a=e.dims,i=n,l=s<2||up(o,e.dims),c;if(l)return c=_=>{let b=Ie("input",t,a,4),k=nt("output",t,i,4);return` - ${_.registerUniform("output_size","u32").declareVariables(b,k)} - ${_.mainStart()} - ${_.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} - output[global_idx] = input[global_idx]; - }`},{name:"TransposeCopy",shaderCache:{inputDependencies:["type"]},getRunData:()=>{let _=ye.size(n);return{outputs:[{dims:n,dataType:e.dataType}],dispatchGroup:{x:Math.ceil(_/64/4)},programUniforms:[{type:12,data:Math.ceil(_/4)}]}},getShaderSource:c};let{newShape:p,newPerm:d}=cp(e.dims,o),u=ye.areEqual(d,[2,3,1]),f=ye.areEqual(d,[3,1,2]);if(p.length===2||u||f){a=u?[p[0],p[1]*p[2]]:f?[p[0]*p[1],p[2]]:p,i=[a[1],a[0]];let _=16;return c=b=>{let k=Ie("a",t,a.length),w=nt("output",t,i.length);return` - ${b.registerUniform("output_size","u32").declareVariables(k,w)} - var tile : array, ${_}>; - ${b.mainStart([_,_,1])} - let stride = (uniforms.output_shape[1] - 1) / ${_} + 1; - let workgroup_id_x = workgroup_index % stride; - let workgroup_id_y = workgroup_index / stride; - let input_col = workgroup_id_y * ${_}u + local_id.x; - let input_row = workgroup_id_x * ${_}u + local_id.y; - if (input_row < uniforms.a_shape[0] && input_col < uniforms.a_shape[1]) { - tile[local_id.y][local_id.x] = ${k.getByIndices(`${k.type.indices}(input_row, input_col)`)}; - } - workgroupBarrier(); - - let output_col = workgroup_id_x * ${_}u + local_id.x; - let output_row = workgroup_id_y * ${_}u + local_id.y; - if (output_row < uniforms.output_shape[0] && output_col < uniforms.output_shape[1]) { - ${w.setByIndices(`${w.type.indices}(output_row, output_col)`,"tile[local_id.x][local_id.y]")} - } - }`},{name:"TransposeShared",shaderCache:{inputDependencies:["type"]},getRunData:()=>{let b=ye.size(n);return{outputs:[{dims:n,dataType:e.dataType}],dispatchGroup:{x:Math.ceil(i[1]/_),y:Math.ceil(i[0]/_)},programUniforms:[{type:12,data:b},...dt(a,i)]}},getShaderSource:c}}return c=_=>{let b=Ie("a",t,a.length),k=nt("output",t,i.length);return` - ${_.registerUniform("output_size","u32").declareVariables(b,k)} - - ${lp(o,s,b,k)} - - ${_.mainStart()} - ${_.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} - - let indices = ${k.offsetToIndices("global_idx")}; - let aIndices = perm(indices); - - ${k.setByOffset("global_idx",b.getByIndices("aIndices"))} - }`},{name:"Transpose",shaderCache:{hint:`${r}`,inputDependencies:["rank"]},getRunData:()=>{let _=ye.size(n);return{outputs:[{dims:n,dataType:e.dataType}],dispatchGroup:{x:Math.ceil(_/64)},programUniforms:[{type:12,data:_},...dt(a,i)]}},getShaderSource:c}},dp=(e,r)=>{ap(e.inputs,r.perm),e.compute(rs(e.inputs[0],r.perm))},pp=e=>Kt({perm:e.perm})}),mp,hp,_p,fp,gp,wp,Mp,bp,yp,vp,ws,xp,Tp,Ep,Pp,Cp,Sp,$p,kp,Ip,Ap,Lx=Ue(()=>{Mt(),Pt(),Ct(),pl(),tn(),mp={max:"select(bestValue, candidate, candidate > bestValue)",min:"select(bestValue, candidate, candidate < bestValue)",mean:"bestValue + candidate",sum:"bestValue + candidate",prod:"bestValue * candidate",sumSquare:"bestValue + candidate * candidate",logSumExp:"bestValue + exp(candidate)",l1:"bestValue + abs(candidate)",l2:"bestValue + candidate * candidate",logSum:"bestValue + candidate"},hp={max:"select(bestValue, candidate, candidate > bestValue)",min:"select(bestValue, candidate, candidate < bestValue)",mean:"bestValue + candidate",sum:"bestValue + candidate",prod:"bestValue * candidate",sumSquare:"bestValue + candidate",logSumExp:"bestValue + candidate",l1:"bestValue + candidate",l2:"bestValue + candidate",logSum:"bestValue + candidate"},_p={max:"_A[offset]",min:"_A[offset]",mean:"0",sum:"0",prod:"1",sumSquare:"0",logSumExp:"0",l1:"0",l2:"0",logSum:"0"},fp={max:"bestValue",min:"bestValue",sum:"bestValue",prod:"bestValue",sumSquare:"bestValue",logSumExp:"log(bestValue)",l1:"bestValue",l2:"sqrt(bestValue)",logSum:"log(bestValue)"},gp=(e,r)=>{let t=[];for(let s=r-e;s{let t=[],s=e.length;for(let n=0;ne[n]);return[t,o]},Mp=(e,r)=>{let t=e.length+r.length,s=[],o=0;for(let n=0;n{for(let t=0;t{let t=[];if(!bp(e,r)){for(let s=0;st.push(s))}return t},vp=(e,r,t,s,o,n,a)=>{let i=t[0].dims,l=ye.size(n),c=ye.size(a),p=Ie("_A",t[0].dataType,i),d=nt("output",o,n),u=64;l===1&&(u=256);let f=` - var aBestValues : array; - `,_=b=>` - ${b.registerUniform("reduceSize","u32").declareVariables(p,d)} - ${f} - fn DIV_CEIL(a : u32, b : u32) -> u32 { - return ((a - 1u) / b + 1u); - } - ${b.mainStart(u)} - - let outputIndex = global_idx / ${u}; - let offset = outputIndex * uniforms.reduceSize; - - var bestValue = f32(${_p[s]}); - let Length = uniforms.reduceSize; - for (var k = local_idx; k < Length; k = k + ${u}) { - let candidate = f32(${p.getByOffset("offset + k")}); - bestValue = ${mp[s]}; - } - aBestValues[local_idx] = bestValue; - workgroupBarrier(); - - var reduceSize = min(Length, ${u}u); - for (var currentSize = reduceSize / 2u; reduceSize > 1u; - currentSize = reduceSize / 2u) { - let interval = DIV_CEIL(reduceSize, 2u); - if (local_idx < currentSize) { - let candidate = aBestValues[local_idx + interval]; - bestValue = ${hp[s]}; - aBestValues[local_idx] = bestValue; - } - reduceSize = interval; - workgroupBarrier(); - } - - if (local_idx == 0u) { - ${d.setByOffset("outputIndex",`${s==="mean"?`${d.type.storage}(bestValue / f32(uniforms.reduceSize))`:`${d.type.storage}(${fp[s]})`}`)}; - } - }`;return{name:e,shaderCache:{hint:`${r};${u}`,inputDependencies:["type"]},getShaderSource:_,getRunData:()=>({outputs:[{dims:n,dataType:o}],dispatchGroup:{x:l},programUniforms:[{type:12,data:c}]})}},ws=(e,r,t,s)=>{let o=e.inputs.length===1?t:dl(e.inputs,t),n=o.axes;n.length===0&&!o.noopWithEmptyAxes&&(n=e.inputs[0].dims.map((f,_)=>_));let a=ye.normalizeAxes(n,e.inputs[0].dims.length),i=a,l=e.inputs[0],c=yp(i,e.inputs[0].dims.length);c.length>0&&(l=e.compute(rs(e.inputs[0],c),{inputs:[0],outputs:[-1]})[0],i=gp(i.length,l.dims.length));let[p,d]=wp(l.dims,i),u=p;o.keepDims&&(u=Mp(p,a)),e.compute(vp(r,o.cacheKey,[l],s,e.inputs[0].dataType,u,d),{inputs:[l]})},xp=(e,r)=>{ws(e,"ReduceMeanShared",r,"mean")},Tp=(e,r)=>{ws(e,"ReduceL1Shared",r,"l1")},Ep=(e,r)=>{ws(e,"ReduceL2Shared",r,"l2")},Pp=(e,r)=>{ws(e,"ReduceLogSumExpShared",r,"logSumExp")},Cp=(e,r)=>{ws(e,"ReduceMaxShared",r,"max")},Sp=(e,r)=>{ws(e,"ReduceMinShared",r,"min")},$p=(e,r)=>{ws(e,"ReduceProdShared",r,"prod")},kp=(e,r)=>{ws(e,"ReduceSumShared",r,"sum")},Ip=(e,r)=>{ws(e,"ReduceSumSquareShared",r,"sumSquare")},Ap=(e,r)=>{ws(e,"ReduceLogSumShared",r,"logSum")}}),Ms,Fp,da,dl,bs,Op,Dp,Lp,zp,Bp,Rp,jp,Np,Vp,Up,ys,Wp,Gp,Kp,Hp,qp,Qp,Xp,Jp,Yp,Zp,pl=Ue(()=>{Mt(),Pt(),pr(),Ct(),Lx(),Ms=e=>{if(!e||e.length===0||e.length>2)throw new Error("Reduce op requires 1 or 2 inputs.");if(e.length===2&&e[1].dims.length!==1)throw new Error("Invalid axes input dims.")},Fp=e=>["","",`var value = ${e.getByIndices("input_indices")};`,""],da=(e,r,t,s,o,n,a=!1,i=!1)=>{let l=[],c=t[0].dims,p=c.length,d=ye.normalizeAxes(o,p),u=!i&&d.length===0;c.forEach((b,k)=>{u||d.indexOf(k)>=0?a&&l.push(1):l.push(b)});let f=l.length,_=ye.size(l);return{name:e,shaderCache:r,getShaderSource:b=>{let k=[],w=Ie("_A",t[0].dataType,p),y=nt("output",n,f),$=s(w,y,d),T=$[2];for(let M=0,x=0;M=0?(a&&x++,T=`for(var j${M}: u32 = 0; j${M} < ${c[M]}; j${M}++) { - ${$[2].includes("last_index")?`let last_index = j${M};`:""} - ${w.indicesSet("input_indices",M,`j${M}`)} - ${T} - }`):(k.push(`${w.indicesSet("input_indices",M,y.indicesGet("output_indices",x))};`),x++);return` - - ${b.registerUniform("output_size","u32").declareVariables(w,y)} - - ${b.mainStart()} - ${b.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} - var input_indices: ${w.type.indices}; - let output_indices = ${y.offsetToIndices("global_idx")}; - - ${k.join(` -`)} - ${$[0]} // init ops for reduce max/min - ${$[1]} - ${T} - ${$[3]} - ${$.length===4?y.setByOffset("global_idx","value"):$.slice(4).join(` -`)} - }`},getRunData:()=>({outputs:[{dims:l,dataType:n}],dispatchGroup:{x:Math.ceil(_/64)},programUniforms:[{type:12,data:_},...dt(c,l)]})}},dl=(e,r)=>{let t=[];return e[1].dims[0]>0&&e[1].getBigInt64Array().forEach(s=>t.push(Number(s))),Kt({axes:t,keepDims:r.keepDims,noopWithEmptyAxes:r.noopWithEmptyAxes})},bs=(e,r,t,s)=>{let o=e.inputs,n=o.length===1?t:dl(o,t);e.compute(da(r,{hint:n.cacheKey,inputDependencies:["rank"]},[o[0]],n.noopWithEmptyAxes&&n.axes.length===0?Fp:s,n.axes,o[0].dataType,n.keepDims,n.noopWithEmptyAxes),{inputs:[0]})},Op=(e,r)=>{Ms(e.inputs),bs(e,"ReduceLogSum",r,(t,s)=>[`var value = ${s.type.storage}(0);`,"",`value += ${t.getByIndices("input_indices")};`,"value = log(value);"])},Dp=(e,r)=>{Ms(e.inputs),bs(e,"ReduceL1",r,(t,s)=>[`var value = ${s.type.storage}(0);`,"",`value += abs(${t.getByIndices("input_indices")});`,""])},Lp=(e,r)=>{Ms(e.inputs),bs(e,"ReduceL2",r,(t,s)=>[`var t = ${s.type.value}(0); var value = ${s.type.value}(0);`,"",`t = ${t.getByIndices("input_indices")}; value += (t * t);`,"value = sqrt(value);"])},zp=(e,r)=>{Ms(e.inputs),bs(e,"ReduceLogSumExp",r,(t,s)=>[`var value = ${s.type.storage}(0);`,"",`value += exp(${t.getByIndices("input_indices")});`,"value = log(value);"])},Bp=(e,r)=>{Ms(e.inputs),bs(e,"ReduceMax",r,(t,s,o)=>{let n=[];for(let a=0;a=0||o.length===0)&&n.push(t.indicesSet("input_indices",a,0));return[`${n.join(` -`)}`,`var value = ${t.getByIndices("input_indices")};`,`value = max(value, ${t.getByIndices("input_indices")});`,""]})},Rp=(e,r)=>{Ms(e.inputs),bs(e,"ReduceMean",r,(t,s,o)=>{let n=1;for(let a=0;a=0||o.length===0)&&(n*=e.inputs[0].dims[a]);return["var sum = f32(0);","",`sum += f32(${t.getByIndices("input_indices")});`,`let value = ${s.type.value}(sum / ${n});`]})},jp=(e,r)=>{Ms(e.inputs),bs(e,"ReduceMin",r,(t,s,o)=>{let n=[];for(let a=0;a=0||o.length===0)&&n.push(`input_indices[${a}] = 0;`);return[`${n.join(` -`)}`,`var value = ${t.getByIndices("input_indices")};`,`value = min(value, ${t.getByIndices("input_indices")});`,""]})},Np=(e,r)=>{Ms(e.inputs),bs(e,"ReduceProd",r,(t,s)=>[`var value = ${s.type.storage}(1);`,"",`value *= ${t.getByIndices("input_indices")};`,""])},Vp=(e,r)=>{Ms(e.inputs),bs(e,"ReduceSum",r,(t,s)=>[`var value = ${s.type.storage}(0);`,"",`value += ${t.getByIndices("input_indices")};`,""])},Up=(e,r)=>{Ms(e.inputs),bs(e,"ReduceSumSquare",r,(t,s)=>[`var t = ${s.type.value}(0); var value = ${s.type.value}(0);`,"",`t = ${t.getByIndices("input_indices")}; value += t * t;`,""])},ys=(e,r,t)=>{if(r.length===0)return t;let s=1,o=1;for(let n=0;n1024},Wp=(e,r)=>{ys(e.inputs[0].dims,r.axes,r.noopWithEmptyAxes)?Rp(e,r):xp(e,r)},Gp=(e,r)=>{ys(e.inputs[0].dims,r.axes,r.noopWithEmptyAxes)?Dp(e,r):Tp(e,r)},Kp=(e,r)=>{ys(e.inputs[0].dims,r.axes,r.noopWithEmptyAxes)?Lp(e,r):Ep(e,r)},Hp=(e,r)=>{ys(e.inputs[0].dims,r.axes,r.noopWithEmptyAxes)?zp(e,r):Pp(e,r)},qp=(e,r)=>{ys(e.inputs[0].dims,r.axes,r.noopWithEmptyAxes)?Bp(e,r):Cp(e,r)},Qp=(e,r)=>{ys(e.inputs[0].dims,r.axes,r.noopWithEmptyAxes)?jp(e,r):Sp(e,r)},Xp=(e,r)=>{ys(e.inputs[0].dims,r.axes,r.noopWithEmptyAxes)?Np(e,r):$p(e,r)},Jp=(e,r)=>{ys(e.inputs[0].dims,r.axes,r.noopWithEmptyAxes)?Vp(e,r):kp(e,r)},Yp=(e,r)=>{ys(e.inputs[0].dims,r.axes,r.noopWithEmptyAxes)?Up(e,r):Ip(e,r)},Zp=(e,r)=>{ys(e.inputs[0].dims,r.axes,r.noopWithEmptyAxes)?Op(e,r):Ap(e,r)}}),ml,em,tm,hl,zx=Ue(()=>{Mt(),pr(),pl(),ml=e=>{if(!e||e.length===0||e.length>2)throw new Error("ArgMinMaxOp op requires 1 or 2 inputs.");if(e[0].dataType!==1)throw new Error("Invalid input type.")},em=(e,r)=>{ml(e.inputs);let t=(s,o,n)=>{let a=[];for(let i=0;i=0||n.length===0)&&a.push(`input_indices[${i}] = 0;`);return[`${a.join(` -`)}`,`var value = ${s.getByIndices("input_indices")}; -var best_index : i32 = 0;`,`if (${s.getByIndices("input_indices")} ${r.selectLastIndex>0?"<=":"<"} value) { - value = ${s.getByIndices("input_indices")}; - best_index = i32(last_index); - }`,"",o.setByOffset("global_idx","best_index")]};e.compute(da("ArgMin",{hint:r.cacheKey,inputDependencies:["rank"]},[e.inputs[0]],t,[r.axis],7,r.keepDims),{inputs:[0]})},tm=(e,r)=>{ml(e.inputs);let t=(s,o,n)=>{let a=[];for(let i=0;i=0||n.length===0)&&a.push(`input_indices[${i}] = 0;`);return[`${a.join(` -`)}`,`var value = ${s.getByIndices("input_indices")}; -var best_index : i32 = 0;`,`if (${s.getByIndices("input_indices")} ${r.selectLastIndex>0?">=":">"} value) { - value = ${s.getByIndices("input_indices")}; - best_index = i32(last_index); - }`,"",o.setByOffset("global_idx","best_index")]};e.compute(da("argMax",{hint:r.cacheKey,inputDependencies:["rank"]},[e.inputs[0]],t,[r.axis],7,r.keepDims),{inputs:[0]})},hl=e=>Kt(e)}),rm,pa,sm,nm,om,wo,am,im,_l=Ue(()=>{Mt(),Pt(),nl(),Ct(),rm=(e,r)=>{let t=e[0],s=e[1],o=e[2],n=e[3],a=e[4],i=e[5];if(a&&i)throw new Error("Attention cannot have both past and attention_bias");if(t.dims.length!==3)throw new Error('Input "input" must have 3 dimensions');let l=t.dims[0],c=t.dims[1],p=t.dims[2];if(o.dims.length!==1)throw new Error('Input "bias" is expected to have 1 dimensions');if(s.dims.length!==2)throw new Error('Input "weights" is expected to have 2 dimensions');if(s.dims[0]!==p)throw new Error("Input 1 dimension 0 should have same length as dimension 2 of input 0");if(o.dims[0]!==s.dims[1])throw new Error('Input "bias" dimension 0 should have same length as dimension 1 of input "weights"');let d=o.dims[0]/3,u=d,f=u;if(r.qkvHiddenSizes.length>0){if(r.qkvHiddenSizes.length!==3)throw new Error("qkv_hidden_sizes attribute should have 3 elements");for(let $ of r.qkvHiddenSizes)if($%r.numHeads!==0)throw new Error("qkv_hidden_sizes should be divisible by num_heads");d=r.qkvHiddenSizes[0],u=r.qkvHiddenSizes[1],f=r.qkvHiddenSizes[2]}let _=c;if(d!==u)throw new Error("qkv_hidden_sizes first element should be same as the second");if(o.dims[0]!==d+u+f)throw new Error('Input "bias" dimension 0 should have same length as sum of Q/K/V hidden sizes');let b=0;if(a){if(u!==f)throw new Error('Input "past" expect k_hidden_size == v_hidden_size');if(a.dims.length!==5)throw new Error('Input "past" must have 5 dimensions');if(a.dims[0]!==2)throw new Error('Input "past" first dimension must be 2');if(a.dims[1]!==l)throw new Error('Input "past" second dimension must be batch_size');if(a.dims[2]!==r.numHeads)throw new Error('Input "past" third dimension must be num_heads');if(a.dims[4]!==u/r.numHeads)throw new Error('Input "past" fifth dimension must be k_hidden_size / num_heads');r.pastPresentShareBuffer||(b=a.dims[3])}let k=_+b,w=-1,y=0;if(n)throw new Error("Mask not supported");if(a)throw new Error("past is not supported");if(i){if(i.dims.length!==4)throw new Error('Input "attention_bias" must have 4 dimensions');if(i.dims[0]!==l||i.dims[1]!==r.numHeads||i.dims[2]!==c||i.dims[3]!==k)throw new Error('Expect "attention_bias" shape (batch_size, num_heads, sequence_length, total_sequence_length)')}return{batchSize:l,sequenceLength:c,pastSequenceLength:b,kvSequenceLength:_,totalSequenceLength:k,maxSequenceLength:w,inputHiddenSize:p,hiddenSize:d,vHiddenSize:f,headSize:Math.floor(d/r.numHeads),vHeadSize:Math.floor(f/r.numHeads),numHeads:r.numHeads,isUnidirectional:!1,pastPresentShareBuffer:!1,maskFilterValue:r.maskFilterValue,maskType:y,scale:r.scale,broadcastResPosBias:!1,passPastInKv:!1,qkvFormat:1}},pa=(e,r,t)=>r&&e?` - let total_sequence_length_input = u32(${r.getByOffset("0")}); - let present_sequence_length = max(total_sequence_length_input, uniforms.past_sequence_length); - let is_subsequent_prompt: bool = sequence_length > 1 && sequence_length != total_sequence_length_input; - let is_first_prompt: bool = is_subsequent_prompt == false && sequence_length == total_sequence_length_input; - total_sequence_length = u32(${e==null?void 0:e.getByOffset("batchIdx")}) + 1; - var past_sequence_length: u32 = 0; - if (is_first_prompt == false) { - past_sequence_length = total_sequence_length - sequence_length; - } - `:` - ${t?"let past_sequence_length = uniforms.past_sequence_length":""}; - let present_sequence_length = total_sequence_length; - `,sm=(e,r,t,s,o,n,a,i)=>{let l=lr(a?1:n),c=64,p=n/l;p{let y=nt("x",e.dataType,e.dims,l),$=[y],T=a?Ie("seq_lens",a.dataType,a.dims):void 0;T&&$.push(T);let M=i?Ie("total_sequence_length_input",i.dataType,i.dims):void 0;M&&$.push(M);let x=Vr(e.dataType),v=[{name:"batch_size",type:"u32"},{name:"num_heads",type:"u32"},{name:"past_sequence_length",type:"u32"},{name:"sequence_length",type:"u32"},{name:"total_sequence_length",type:"u32"},{name:"elements_per_thread",type:"u32"}];return` - var thread_max: array; - var thread_sum: array; - ${w.registerUniforms(v).declareVariables(...$)} - ${w.mainStart([c,1,1])} - let batchIdx = workgroup_id.z / uniforms.num_heads; - let headIdx = workgroup_id.z % uniforms.num_heads; - let sequence_length = uniforms.sequence_length; - var total_sequence_length = uniforms.total_sequence_length; - ${pa(T,M,!1)} - let local_offset = local_idx * uniforms.elements_per_thread; - let offset = (global_idx / ${c}) * uniforms.total_sequence_length + local_offset; - let seq_causal_length = ${a?"u32(past_sequence_length + workgroup_id.y + 1)":"total_sequence_length"}; - var thread_max_vector = ${_}(-3.402823e+38f); - for (var i: u32 = 0; i < uniforms.elements_per_thread && i + local_offset < seq_causal_length; i++) { - thread_max_vector = max(${_}(x[offset + i]), thread_max_vector); - } - thread_max[local_idx] = ${(()=>{switch(l){case 1:return"thread_max_vector";case 2:return"max(thread_max_vector.x, thread_max_vector.y)";case 4:return"max(max(thread_max_vector.x, thread_max_vector.y), max(thread_max_vector.z, thread_max_vector.w))";default:throw new Error(`Unsupported components: ${l}`)}})()}; - workgroupBarrier(); - - var max_value = f32(-3.402823e+38f); - for (var i = 0u; i < ${c}; i++) { - max_value = max(thread_max[i], max_value); - } - - var sum_vector = ${_}(0); - for (var i: u32 = 0; i < uniforms.elements_per_thread && i + local_offset < seq_causal_length; i++) { - sum_vector += exp(${_}(x[offset + i]) - max_value); - } - thread_sum[local_idx] = ${(()=>{switch(l){case 1:return"sum_vector";case 2:return"sum_vector.x + sum_vector.y";case 4:return"sum_vector.x + sum_vector.y + sum_vector.z + sum_vector.w";default:throw new Error(`Unsupported components: ${l}`)}})()}; - workgroupBarrier(); - - var sum: f32 = 0; - for (var i = 0u; i < ${c}; i++) { - sum += thread_sum[i]; - } - - if (sum == 0) { - for (var i: u32 = 0; i < uniforms.elements_per_thread && i + local_offset < seq_causal_length; i++) { - x[offset + i] = ${y.type.value}(${x}(1.0) / ${x}(seq_causal_length)); - } - } else { - for (var i: u32 = 0; i < uniforms.elements_per_thread && i + local_offset < seq_causal_length; i++) { - var f32input = ${_}(x[offset + i]); - x[offset + i] = ${y.type.value}(exp(f32input - max_value) / sum); - } - } - ${a?` - for (var total_seq_id: u32 = seq_causal_length; total_seq_id + local_offset < uniforms.total_sequence_length; total_seq_id++) { - x[offset + total_seq_id] = ${y.type.value}(${x}(0)); - }`:""}; - }`};return{name:"AttentionProbsSoftmax",shaderCache:{hint:`${c};${f};${l}`,inputDependencies:b},getShaderSource:k,getRunData:()=>({outputs:[],dispatchGroup:{x:1,y:o,z:r*t},programUniforms:u})}},nm=(e,r,t,s,o,n,a,i,l)=>{let c=a+n.kvSequenceLength,p=[n.batchSize,n.numHeads,n.sequenceLength,c],d=e>1&&s,u=n.kvNumHeads?n.kvNumHeads:n.numHeads,f=d?[n.batchSize,u,c,n.headSize]:void 0,_=n.nReps?n.nReps:1,b=n.scale===0?1/Math.sqrt(n.headSize):n.scale,k=lr(n.headSize),w=n.headSize/k,y=12,$={x:Math.ceil(c/y),y:Math.ceil(n.sequenceLength/y),z:n.batchSize*n.numHeads},T=[{type:12,data:n.sequenceLength},{type:12,data:w},{type:12,data:c},{type:12,data:n.numHeads},{type:12,data:n.headSize},{type:1,data:b},{type:12,data:a},{type:12,data:n.kvSequenceLength},{type:12,data:_}],M=d&&s&&ye.size(s.dims)>0,x=["type","type"];M&&x.push("type"),o&&x.push("type"),i&&x.push("type"),l&&x.push("type");let v=[{dims:p,dataType:r.dataType,gpuDataType:0}];d&&v.push({dims:f,dataType:r.dataType,gpuDataType:0});let C=F=>{let D=Ie("q",r.dataType,r.dims,k),K=Ie("key",t.dataType,t.dims,k),U=[D,K];if(M){let _e=Ie("past_key",s.dataType,s.dims,k);U.push(_e)}o&&U.push(Ie("attention_bias",o.dataType,o.dims));let j=i?Ie("seq_lens",i.dataType,i.dims):void 0;j&&U.push(j);let se=l?Ie("total_sequence_length_input",l.dataType,l.dims):void 0;se&&U.push(se);let q=nt("output",r.dataType,p),re=[q];d&&re.push(nt("present_key",r.dataType,f,k));let Z=Vr(1,k),ae=[{name:"M",type:"u32"},{name:"K",type:"u32"},{name:"N",type:"u32"},{name:"num_heads",type:"u32"},{name:"head_size",type:"u32"},{name:"alpha",type:"f32"},{name:"past_sequence_length",type:"u32"},{name:"kv_sequence_length",type:"u32"},{name:"n_reps",type:"u32"}];return` - const TILE_SIZE = ${y}u; - - var tileQ: array<${D.type.storage}, ${y*y}>; - var tileK: array<${D.type.storage}, ${y*y}>; - ${F.registerUniforms(ae).declareVariables(...U,...re)} - ${F.mainStart([y,y,1])} - // x holds the N and y holds the M - let headIdx = workgroup_id.z % uniforms.num_heads; - let kvHeadIdx = ${_===1?"headIdx":"headIdx / uniforms.n_reps"}; - let kv_num_heads = ${_===1?"uniforms.num_heads":"uniforms.num_heads / uniforms.n_reps"}; - let batchIdx = workgroup_id.z / uniforms.num_heads; - let m = workgroup_id.y * TILE_SIZE; - let n = workgroup_id.x * TILE_SIZE; - let sequence_length = uniforms.M; - var total_sequence_length = uniforms.N; - ${pa(j,se,!0)} - let absKvHeadIdx = batchIdx * kv_num_heads + kvHeadIdx; - let qOffset = workgroup_id.z * uniforms.M * uniforms.K + m * uniforms.K; - ${M&&d?"let pastKeyOffset = absKvHeadIdx * uniforms.past_sequence_length * uniforms.K;":""}; - let kOffset = absKvHeadIdx * uniforms.kv_sequence_length * uniforms.K; - ${d?"let presentKeyOffset = absKvHeadIdx * uniforms.N * uniforms.K;":""} - var value = ${Z}(0); - for (var w: u32 = 0u; w < uniforms.K; w += TILE_SIZE) { - if (global_id.y < uniforms.M && w + local_id.x < uniforms.K) { - tileQ[TILE_SIZE * local_id.y + local_id.x] = q[qOffset + local_id.y * uniforms.K + w + local_id.x]; - } - if (n + local_id.y < uniforms.N && w + local_id.x < uniforms.K) { - var idx = TILE_SIZE * local_id.y + local_id.x; - ${M&&d?` - if (n + local_id.y < past_sequence_length) { - tileK[idx] = past_key[pastKeyOffset + (n + local_id.y) * uniforms.K + w + local_id.x]; - } else if (n + local_id.y - past_sequence_length < uniforms.kv_sequence_length) { - tileK[idx] = key[kOffset + (n + local_id.y - past_sequence_length) * uniforms.K + w + local_id.x]; - }`:` - if (n + local_id.y < uniforms.kv_sequence_length) { - tileK[idx] = key[kOffset + (n + local_id.y) * uniforms.K + w + local_id.x]; - }`} - ${d?`if (n + local_id.y < present_sequence_length) { - present_key[presentKeyOffset + (n + local_id.y) * uniforms.K + w + local_id.x] = tileK[idx]; - }`:""} - } - workgroupBarrier(); - - for (var k: u32 = 0u; k < TILE_SIZE && w+k < uniforms.K; k++) { - value += ${Z}(tileQ[TILE_SIZE * local_id.y + k] * tileK[TILE_SIZE * local_id.x + k]); - } - - workgroupBarrier(); - } - - if (global_id.y < uniforms.M && global_id.x < total_sequence_length) { - let headOffset = workgroup_id.z * uniforms.M * uniforms.N; - let outputIdx = headOffset + global_id.y * uniforms.N + global_id.x; - var sum: f32 = ${(()=>{switch(k){case 1:return"value";case 2:return"value.x + value.y";case 4:return"value.x + value.y + value.z + value.w";default:throw new Error(`Unsupported components: ${k}`)}})()}; - output[outputIdx] = ${q.type.value} (sum * uniforms.alpha) + ${o?"attention_bias[outputIdx]":"0.0"}; - } - }`};return{name:"AttentionProbs",shaderCache:{hint:`${k};${o!==void 0};${s!==void 0};${e}`,inputDependencies:x},getRunData:()=>({outputs:v,dispatchGroup:$,programUniforms:T}),getShaderSource:C}},om=(e,r,t,s,o,n,a=void 0,i=void 0)=>{let l=n+o.kvSequenceLength,c=o.nReps?o.nReps:1,p=o.vHiddenSize*c,d=e>1&&s,u=o.kvNumHeads?o.kvNumHeads:o.numHeads,f=d?[o.batchSize,u,l,o.headSize]:void 0,_=[o.batchSize,o.sequenceLength,p],b=12,k={x:Math.ceil(o.vHeadSize/b),y:Math.ceil(o.sequenceLength/b),z:o.batchSize*o.numHeads},w=[{type:12,data:o.sequenceLength},{type:12,data:l},{type:12,data:o.vHeadSize},{type:12,data:o.numHeads},{type:12,data:o.headSize},{type:12,data:p},{type:12,data:n},{type:12,data:o.kvSequenceLength},{type:12,data:c}],y=d&&s&&ye.size(s.dims)>0,$=["type","type"];y&&$.push("type"),a&&$.push("type"),i&&$.push("type");let T=[{dims:_,dataType:r.dataType,gpuDataType:0}];d&&T.push({dims:f,dataType:r.dataType,gpuDataType:0});let M=x=>{let v=Ie("probs",r.dataType,r.dims),C=Ie("v",t.dataType,t.dims),F=[v,C];y&&F.push(Ie("past_value",s.dataType,s.dims));let D=a?Ie("seq_lens",a.dataType,a.dims):void 0;a&&F.push(D);let K=i?Ie("total_sequence_length_input",i.dataType,i.dims):void 0;i&&F.push(K);let U=[nt("output",r.dataType,_)];d&&U.push(nt("present_value",r.dataType,f));let j=[{name:"M",type:"u32"},{name:"K",type:"u32"},{name:"N",type:"u32"},{name:"num_heads",type:"u32"},{name:"head_size",type:"u32"},{name:"v_hidden_size",type:"u32"},{name:"past_sequence_length",type:"u32"},{name:"kv_sequence_length",type:"u32"},{name:"n_reps",type:"u32"}];return` - const TILE_SIZE = ${b}u; - var tileQ: array<${v.type.value}, ${b*b}>; - var tileV: array<${v.type.value}, ${b*b}>; - ${x.registerUniforms(j).declareVariables(...F,...U)} - ${x.mainStart([b,b,1])} - let headIdx = workgroup_id.z % uniforms.num_heads; - let batchIdx = workgroup_id.z / uniforms.num_heads; - let kvHeadIdx = ${c===1?"headIdx":"headIdx / uniforms.n_reps"}; - let kv_num_heads = ${c===1?"uniforms.num_heads":"uniforms.num_heads / uniforms.n_reps"}; - let m = global_id.y; - let n = global_id.x; - let sequence_length = uniforms.M; - var total_sequence_length = uniforms.K; - ${pa(D,K,!0)} - let offsetA = workgroup_id.z * uniforms.M * uniforms.K + m * uniforms.K; - let absKvHeadIdx = batchIdx * kv_num_heads + kvHeadIdx; // kvHeadIdx is relative to the batch - ${y&&d?"let pastValueOffset = absKvHeadIdx * uniforms.N * uniforms.past_sequence_length + n;":""}; - let vOffset = absKvHeadIdx * uniforms.N * uniforms.kv_sequence_length + n; - ${d?"let presentValueOffset = absKvHeadIdx * uniforms.N * uniforms.K + n;":""} - var value = ${v.type.storage}(0); - for (var w: u32 = 0u; w < uniforms.K; w += TILE_SIZE) { - if (m < uniforms.M && w + local_id.x < uniforms.K) { - tileQ[TILE_SIZE * local_id.y + local_id.x] = probs[offsetA + w + local_id.x]; - } - if (n < uniforms.N && w + local_id.y < uniforms.K) { - var idx = TILE_SIZE * local_id.y + local_id.x; - ${y&&d?` - if (w + local_id.y < past_sequence_length) { - tileV[idx] = past_value[pastValueOffset + (w + local_id.y) * uniforms.N]; - } else if (w + local_id.y - past_sequence_length < uniforms.kv_sequence_length) { - tileV[idx] = v[vOffset + (w + local_id.y - past_sequence_length) * uniforms.N]; - } - `:` - if (w + local_id.y < uniforms.kv_sequence_length) { - tileV[idx] = v[vOffset + (w + local_id.y) * uniforms.N]; - }`} - ${d?` - if (w + local_id.y < present_sequence_length) { - present_value[presentValueOffset + (w + local_id.y) * uniforms.N] = tileV[idx]; - }`:""} - } - workgroupBarrier(); - for (var k: u32 = 0u; k < TILE_SIZE && w+k < total_sequence_length; k++) { - value += tileQ[TILE_SIZE * local_id.y + k] * tileV[TILE_SIZE * k + local_id.x]; - } - workgroupBarrier(); - } - - // we need to transpose output from BNSH_v to BSND_v - if (m < uniforms.M && n < uniforms.N) { - let outputIdx = batchIdx * uniforms.M * uniforms.v_hidden_size + m * uniforms.v_hidden_size - + headIdx * uniforms.N + n; - output[outputIdx] = value; - } - }`};return{name:"AttentionScore",shaderCache:{hint:`${s!==void 0};${e}`,inputDependencies:$},getRunData:()=>({outputs:T,dispatchGroup:k,programUniforms:w}),getShaderSource:M}},wo=(e,r,t,s,o,n,a,i,l,c,p=void 0,d=void 0)=>{let u=Math.min(e.outputCount,1+(a?1:0)+(i?1:0)),f=u>1?c.pastSequenceLength:0,_=f+c.kvSequenceLength,b=l&&ye.size(l.dims)>0?l:void 0,k=[r,t];u>1&&a&&ye.size(a.dims)>0&&k.push(a),b&&k.push(b),p&&k.push(p),d&&k.push(d);let w=e.compute(nm(u,r,t,a,b,c,f,p,d),{inputs:k,outputs:u>1?[-1,1]:[-1]})[0];e.compute(sm(w,c.batchSize,c.numHeads,f,c.sequenceLength,_,p,d),{inputs:p&&d?[w,p,d]:[w],outputs:[]});let y=[w,s];u>1&&i&&ye.size(i.dims)>0&&y.push(i),p&&y.push(p),d&&y.push(d),e.compute(om(u,w,s,i,c,f,p,d),{inputs:y,outputs:u>1?[0,2]:[0]})},am=(e,r)=>{let t=[r.batchSize,r.numHeads,r.sequenceLength,r.headSize],s=r.sequenceLength,o=r.inputHiddenSize,n=r.headSize,a=12,i={x:Math.ceil(r.headSize/a),y:Math.ceil(r.sequenceLength/a),z:r.batchSize*r.numHeads},l=[e.inputs[0],e.inputs[1],e.inputs[2]],c=[{type:12,data:s},{type:12,data:o},{type:12,data:n},{type:12,data:r.numHeads},{type:12,data:r.headSize},{type:12,data:r.hiddenSize},{type:12,data:r.hiddenSize+r.hiddenSize+r.vHiddenSize}],p=d=>{let u=nt("output_q",l[0].dataType,t),f=nt("output_k",l[0].dataType,t),_=nt("output_v",l[0].dataType,t),b=Ie("input",l[0].dataType,l[0].dims),k=Ie("weight",l[1].dataType,l[1].dims),w=Ie("bias",l[2].dataType,l[2].dims),y=b.type.storage,$=[{name:"M",type:"u32"},{name:"K",type:"u32"},{name:"N",type:"u32"},{name:"num_heads",type:"u32"},{name:"head_size",type:"u32"},{name:"hidden_size",type:"u32"},{name:"ldb",type:"u32"}];return` - const TILE_SIZE = ${a}u; - var tileInput: array<${y}, ${a*a}>; - var tileWeightQ: array<${y}, ${a*a}>; - var tileWeightK: array<${y}, ${a*a}>; - var tileWeightV: array<${y}, ${a*a}>; - ${d.registerUniforms($).declareVariables(b,k,w,u,f,_)} - ${d.mainStart([a,a,1])} - let batchIndex = workgroup_id.z / uniforms.num_heads; - let headNumber = workgroup_id.z % uniforms.num_heads; - let m = global_id.y; - let n = global_id.x; - - let inputOffset = batchIndex * (uniforms.M * uniforms.K) + m * uniforms.K; - let biasOffsetQ = headNumber * uniforms.head_size; - let biasOffsetK = uniforms.hidden_size + biasOffsetQ; - let biasOffsetV = uniforms.hidden_size + biasOffsetK; - - var valueQ = ${y}(0); - var valueK = ${y}(0); - var valueV = ${y}(0); - for (var w: u32 = 0u; w < uniforms.K; w += TILE_SIZE) { - if (m < uniforms.M && w + local_id.x < uniforms.K) { - tileInput[TILE_SIZE * local_id.y + local_id.x] = input[inputOffset + w + local_id.x]; - } - if (n < uniforms.N && w + local_id.y < uniforms.K) { - let offset = n + (w + local_id.y) * uniforms.ldb; - tileWeightQ[TILE_SIZE * local_id.y + local_id.x] = weight[biasOffsetQ + offset]; - tileWeightK[TILE_SIZE * local_id.y + local_id.x] = weight[biasOffsetK + offset]; - tileWeightV[TILE_SIZE * local_id.y + local_id.x] = weight[biasOffsetV + offset]; - } - workgroupBarrier(); - for (var k: u32 = 0u; k({outputs:[{dims:t,dataType:e.inputs[0].dataType,gpuDataType:0},{dims:t,dataType:e.inputs[0].dataType,gpuDataType:0},{dims:t,dataType:e.inputs[0].dataType,gpuDataType:0}],dispatchGroup:i,programUniforms:c}),getShaderSource:p},{inputs:l,outputs:[-1,-1,-1]})},im=(e,r)=>{let t=rm(e.inputs,r),[s,o,n]=am(e,t);return wo(e,s,o,n,e.inputs[4],void 0,void 0,void 0,e.inputs[5],t)}}),lm,cm,um,dm,Bx=Ue(()=>{fs(),Mt(),Pt(),pr(),Ct(),lm=(e,r)=>{if(!e||e.length!==5)throw new Error("BatchNormalization requires 5 inputs");let t=(s,o,n)=>{let a=o.length;if(a!==s.length)throw new Error(`${n}: num dimensions != ${a}`);o.forEach((i,l)=>{if(i!==s[l])throw new Error(`${n}: dim[${l}] do not match`)})};if(e[0].dims.length>1){let s=r.format==="NHWC"?r.spatial?e[0].dims.slice(-1):e[0].dims.slice(-1).concat(e[0].dims.slice(1,e[0].dims.length-1)):e[0].dims.slice(1,r.spatial?2:void 0);t(e[1].dims,s,"Invalid input scale"),t(e[2].dims,s,"Invalid input B"),t(e[3].dims,s,"Invalid input mean"),t(e[4].dims,s,"Invalid input var")}else t(e[1].dims,[1],"Invalid input scale"),t(e[2].dims,[1],"Invalid input B"),t(e[3].dims,[1],"Invalid input mean"),t(e[4].dims,[1],"Invalid input var")},cm=(e,r)=>{let{epsilon:t,spatial:s,format:o}=r,n=e[0].dims,a=s?lr(n[n.length-1]):1,i=o==="NHWC"&&n.length>1?a:1,l=ye.size(n)/a,c=s,p=c?n.length:n,d=Ie("x",e[0].dataType,e[0].dims,a),u=Ie("scale",e[1].dataType,e[1].dims,i),f=Ie("bias",e[2].dataType,e[2].dims,i),_=Ie("inputMean",e[3].dataType,e[3].dims,i),b=Ie("inputVar",e[4].dataType,e[4].dims,i),k=nt("y",e[0].dataType,p,a),w=()=>{let $="";if(s)$=`let cOffset = ${n.length===1?"0u":o==="NHWC"?`outputIndices[${n.length-1}] / ${a}`:"outputIndices[1]"};`;else if(o==="NCHW")$=` - ${k.indicesSet("outputIndices","0","0")} - let cOffset = ${k.indicesToOffset("outputIndices")};`;else{$=`var cIndices = ${u.type.indices}(0); - cIndices[0] = outputIndices[${n.length-1}];`;for(let T=1;T` - const epsilon = ${t}; - ${$.registerUniform("outputSize","u32").declareVariables(d,u,f,_,b,k)} - ${$.mainStart()} - ${$.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.outputSize")} - var outputIndices = ${k.offsetToIndices(`global_idx * ${a}`)}; - ${w()} - let scale = ${u.getByOffset("cOffset")}; - let bias = ${f.getByOffset("cOffset")}; - let inputMean = ${_.getByOffset("cOffset")}; - let inputVar = ${b.getByOffset("cOffset")}; - let x = ${d.getByOffset("global_idx")}; - let value = (x - inputMean) * inverseSqrt(inputVar + epsilon) * scale + bias; - ${k.setByOffset("global_idx","value")} - }`;return{name:"BatchNormalization",shaderCache:{hint:`${r.epsilon}_${r.format}_${s}_${a}`,inputDependencies:c?["rank","type","type","type","type"]:void 0},getShaderSource:y,getRunData:()=>({outputs:[{dims:e[0].dims,dataType:e[0].dataType}],dispatchGroup:{x:Math.ceil(l/64)},programUniforms:c?[{type:12,data:l},...dt(n)]:[{type:12,data:l}]})}},um=e=>Kt(e),dm=(e,r)=>{let{inputs:t,outputCount:s}=e,o=um({...r,outputCount:s});if(tr.webgpu.validateInputContent&&lm(t,o),r.trainingMode)throw new Error("BatchNormalization trainingMode is not supported yet.");e.compute(cm(t,o))}}),pm,mm,hm,Rx=Ue(()=>{Pt(),Ct(),pm=e=>{if(e[0].dims.length!==3)throw new Error("input should have 3 dimensions");if(![320,640,1280].includes(e[0].dims[2]))throw new Error("number of channels should be 320, 640 or 1280");if(e[1].dims.length!==1)throw new Error("bias is expected to have 1 dimensions");if(e[0].dims[2]!==e[1].dims[0])throw new Error("last dimension of input and bias are not the same")},mm=e=>{let r=e[0].dims,t=e[0].dims[2],s=ye.size(r)/4,o=e[0].dataType,n=Ie("input",o,r,4),a=Ie("bias",o,[t],4),i=Ie("residual",o,r,4),l=nt("output",o,r,4);return{name:"BiasAdd",getRunData:()=>({outputs:[{dims:r,dataType:e[0].dataType}],dispatchGroup:{x:Math.ceil(s/64)}}),getShaderSource:c=>` - const channels = ${t}u / 4; - ${c.declareVariables(n,a,i,l)} - - ${c.mainStart()} - ${c.guardAgainstOutOfBoundsWorkgroupSizes(s)} - let value = ${n.getByOffset("global_idx")} - + ${a.getByOffset("global_idx % channels")} + ${i.getByOffset("global_idx")}; - ${l.setByOffset("global_idx","value")} - }`}},hm=e=>{pm(e.inputs),e.compute(mm(e.inputs))}}),_m,Vt,fm,gm,wm,Mm,bm,ym,vm,xm,Tm,Em,Pm,Cm,Sm,$m,Mo,km,ma,Im,Am,Fm,Om,Dm,Lm,zm,Bm,Rm,jm,Nm,Vm,Um,Wm,Gm,Km,fl,Hm,gl,wl,qm,Qm,Xm,Jm,Ym,Zm,Ml=Ue(()=>{Mt(),Pt(),pr(),Ct(),_m=(e,r,t,s,o,n,a)=>{let i=Math.ceil(r/4),l="";typeof o=="string"?l=`${o}(a)`:l=o("a");let c=Ie("inputData",t,[i],4),p=nt("outputData",s,[i],4),d=[{name:"vec_size",type:"u32"}];return a&&d.push(...a),` - ${e.registerUniforms(d).declareVariables(c,p)} - - ${n??""} - - ${e.mainStart()} - ${e.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.vec_size")} - - let a = ${c.getByOffset("global_idx")}; - ${p.setByOffset("global_idx",l)} - }`},Vt=(e,r,t,s,o,n=e.dataType,a,i)=>{let l=[{type:12,data:Math.ceil(ye.size(e.dims)/4)}];return a&&l.push(...a),{name:r,shaderCache:{hint:o,inputDependencies:["type"]},getShaderSource:c=>_m(c,ye.size(e.dims),e.dataType,n,t,s,i),getRunData:c=>({outputs:[{dims:e.dims,dataType:n}],dispatchGroup:{x:Math.ceil(ye.size(c[0].dims)/64/4)},programUniforms:l})}},fm=e=>{e.compute(Vt(e.inputs[0],"Abs","abs"))},gm=e=>{e.compute(Vt(e.inputs[0],"Acos","acos"))},wm=e=>{e.compute(Vt(e.inputs[0],"Acosh","acosh"))},Mm=e=>{e.compute(Vt(e.inputs[0],"Asin","asin"))},bm=e=>{e.compute(Vt(e.inputs[0],"Asinh","asinh"))},ym=e=>{e.compute(Vt(e.inputs[0],"Atan","atan"))},vm=e=>{e.compute(Vt(e.inputs[0],"Atanh","atanh"))},xm=e=>Kt(e),Tm=(e,r)=>{let t;switch(r.to){case 10:t="vec4";break;case 1:t="vec4";break;case 12:t="vec4";break;case 6:t="vec4";break;case 9:t="vec4";break;default:throw new RangeError(`not supported type (specified in attribute 'to' from 'Cast' operator): ${r.to}`)}e.compute(Vt(e.inputs[0],"Cast",t,void 0,r.cacheKey,r.to))},Em=e=>{let r,t,s=e.length>=2&&e[1].data!==0,o=e.length>=3&&e[2].data!==0;switch(e[0].dataType){case 1:r=s?e[1].getFloat32Array()[0]:-34028234663852886e22,t=o?e[2].getFloat32Array()[0]:34028234663852886e22;break;case 10:r=s?e[1].getUint16Array()[0]:64511,t=o?e[2].getUint16Array()[0]:31743;break;default:throw new Error("Unsupport data type")}return Kt({min:r,max:t})},Pm=(e,r)=>{let t=r||Em(e.inputs),s=Vr(e.inputs[0].dataType);e.compute(Vt(e.inputs[0],"Clip",o=>`clamp(${o}, vec4<${s}>(uniforms.min), vec4<${s}>(uniforms.max))`,void 0,t.cacheKey,void 0,[{type:e.inputs[0].dataType,data:t.min},{type:e.inputs[0].dataType,data:t.max}],[{name:"min",type:s},{name:"max",type:s}]),{inputs:[0]})},Cm=e=>{e.compute(Vt(e.inputs[0],"Ceil","ceil"))},Sm=e=>{e.compute(Vt(e.inputs[0],"Cos","cos"))},$m=e=>{e.compute(Vt(e.inputs[0],"Cosh","cosh"))},Mo=e=>Kt(e),km=(e,r)=>{let t=Vr(e.inputs[0].dataType);e.compute(Vt(e.inputs[0],"Elu",s=>`elu_vf32(${s})`,` - const elu_alpha_ = ${t}(${r.alpha}); - - fn elu_f32(a: ${t}) -> ${t} { - return select((exp(a) - 1.0) * elu_alpha_, a, a >= 0.0); - } - - fn elu_vf32(v: vec4<${t}>) -> vec4<${t}> { - return vec4(elu_f32(v.x), elu_f32(v.y), elu_f32(v.z), elu_f32(v.w)); - }`,r.cacheKey))},ma=(e="f32")=>` -const r0: ${e} = 0.3275911; -const r1: ${e} = 0.254829592; -const r2: ${e} = -0.284496736; -const r3: ${e} = 1.421413741; -const r4: ${e} = -1.453152027; -const r5: ${e} = 1.061405429; - -fn erf_vf32(v: vec4<${e}>) -> vec4<${e}> { - let absv = abs(v); - let x = 1.0 / (1.0 + r0 * absv); - return sign(v) * (1.0 - ((((r5 * x + r4) * x + r3) * x + r2) * x + r1) * x * exp(-absv * absv)); -}`,Im=e=>{let r=Vr(e.inputs[0].dataType);e.compute(Vt(e.inputs[0],"Erf",t=>`erf_vf32(${t})`,ma(r)))},Am=e=>{e.compute(Vt(e.inputs[0],"Exp","exp"))},Fm=e=>{e.compute(Vt(e.inputs[0],"Floor","floor"))},Om=e=>{let r=Vr(e.inputs[0].dataType);e.compute(Vt(e.inputs[0],"Gelu",t=>`0.5 * ${t} * (1.0 + erf_vf32(${t} * 0.7071067811865475))`,ma(r)))},Dm=(e,r)=>{let t=Vr(e.inputs[0].dataType);e.compute(Vt(e.inputs[0],"LeakyRelu",s=>`select(leaky_relu_alpha_ * ${s}, ${s}, ${s} >= vec4<${t}>(0.0))`,`const leaky_relu_alpha_ = ${t}(${r.alpha});`,r.cacheKey))},Lm=e=>{e.compute(Vt(e.inputs[0],"Not",r=>`!${r}`))},zm=e=>{e.compute(Vt(e.inputs[0],"Neg",r=>`-${r}`))},Bm=e=>{e.compute(Vt(e.inputs[0],"Reciprocal",r=>`1.0/${r}`))},Rm=e=>{let r=Vr(e.inputs[0].dataType);e.compute(Vt(e.inputs[0],"Relu",t=>`select(vec4<${r}>(0.0), ${t}, ${t} > vec4<${r}>(0.0))`))},jm=e=>{e.compute(Vt(e.inputs[0],"Sigmoid",r=>`(1.0 / (1.0 + exp(-${r})))`))},Nm=e=>Kt(e),Vm=(e,r)=>{let t=Vr(e.inputs[0].dataType);e.compute(Vt(e.inputs[0],"HardSigmoid",s=>`max(vec4<${t}>(0.0), min(vec4<${t}>(1.0), ${r.alpha} * ${s} + vec4<${t}>(${r.beta})))`,void 0,r.cacheKey))},Um=e=>{e.compute(Vt(e.inputs[0],"Sin","sin"))},Wm=e=>{e.compute(Vt(e.inputs[0],"Sinh","sinh"))},Gm=e=>{e.compute(Vt(e.inputs[0],"Sqrt","sqrt"))},Km=e=>{e.compute(Vt(e.inputs[0],"Tan","tan"))},fl=e=>`sign(${e}) * (1 - exp(-2 * abs(${e}))) / (1 + exp(-2 * abs(${e})))`,Hm=e=>{e.compute(Vt(e.inputs[0],"Tanh",fl))},gl=(e="f32")=>` -const fast_gelu_a: ${e} = 0.5; -const fast_gelu_b: ${e} = 0.7978845608028654; -const fast_gelu_c: ${e} = 0.035677408136300125; - -fn tanh_v(v: vec4<${e}>) -> vec4<${e}> { - return ${fl("v")}; -} -`,wl=e=>`(fast_gelu_a + fast_gelu_a * tanh_v(${e} * (fast_gelu_c * ${e} * ${e} + fast_gelu_b))) * ${e}`,qm=e=>{let r=Vr(e.inputs[0].dataType);e.compute(Vt(e.inputs[0],"FastGelu",wl,gl(r),void 0,e.inputs[0].dataType))},Qm=(e,r)=>{let t=Vr(e.inputs[0].dataType);return e.compute(Vt(e.inputs[0],"ThresholdedRelu",s=>`select(vec4<${t}>(0.0), ${s}, ${s} > thresholded_relu_alpha_)`,`const thresholded_relu_alpha_ = vec4<${t}>(${r.alpha});`,r.cacheKey)),0},Xm=e=>{e.compute(Vt(e.inputs[0],"Log","log"))},Jm=(e,r)=>` -const alpha = vec4<${e}>(${r}); -const one = ${e}(1.0); -const zero = ${e}(0.0); - -fn quick_gelu_impl(x: vec4<${e}>) -> vec4<${e}> { - let v = x *alpha; - var x1 : vec4<${e}>; - for (var i = 0; i < 4; i = i + 1) { - if (v[i] >= zero) { - x1[i] = one / (one + exp(-v[i])); - } else { - x1[i] = one - one / (one + exp(v[i])); - } - } - return x * x1; -} -`,Ym=e=>`quick_gelu_impl(${e})`,Zm=(e,r)=>{let t=Vr(e.inputs[0].dataType);e.compute(Vt(e.inputs[0],"QuickGelu",Ym,Jm(t,r.alpha),r.cacheKey,e.inputs[0].dataType))}}),eh,th,rh,jx=Ue(()=>{Pt(),Ct(),Ml(),eh=e=>{if(e[0].dims.length!==3)throw new Error("input should have 3 dimensions");if(![2560,5120,10240].includes(e[0].dims[2]))throw new Error("hidden state should be 2560, 5120 or 10240");if(e[1].dims.length!==1)throw new Error("bias is expected to have 1 dimensions");if(e[0].dims[2]!==e[1].dims[0])throw new Error("last dimension of input and bias are not the same")},th=e=>{let r=e[0].dims.slice();r[2]=r[2]/2;let t=Ie("input",e[0].dataType,e[0].dims,4),s=Ie("bias",e[0].dataType,[e[0].dims[2]],4),o=nt("output",e[0].dataType,r,4),n=ye.size(r)/4,a=Ir(e[0].dataType);return{name:"BiasSplitGelu",getRunData:()=>({outputs:[{dims:r,dataType:e[0].dataType}],dispatchGroup:{x:Math.ceil(n/64)}}),getShaderSource:i=>` - const M_SQRT2 = sqrt(2.0); - const halfChannels = ${e[0].dims[2]/4/2}u; - - ${i.declareVariables(t,s,o)} - - ${ma(a)} - - ${i.mainStart()} - ${i.guardAgainstOutOfBoundsWorkgroupSizes(n)} - let biasIdx = global_idx % halfChannels; - let batchIndex = global_idx / halfChannels; - let inputOffset = biasIdx + batchIndex * halfChannels * 2; - let valueLeft = input[inputOffset] + bias[biasIdx]; - let valueRight = input[inputOffset + halfChannels] + bias[biasIdx + halfChannels]; - let geluRight = valueRight * 0.5 * (erf_vf32(valueRight / M_SQRT2) + 1); - - ${o.setByOffset("global_idx","valueLeft * geluRight")} - }`}},rh=e=>{eh(e.inputs),e.compute(th(e.inputs))}}),sh,nh,vs,oh,ah,ih,lh,ch,uh,dh,ph,mh,hh,Nx=Ue(()=>{Mt(),Pt(),Ct(),sh=(e,r,t,s,o,n,a,i,l,c,p,d)=>{let u,f;typeof i=="string"?u=f=(y,$)=>`${i}((${y}),(${$}))`:typeof i=="function"?u=f=i:(u=i.scalar,f=i.vector);let _=nt("outputData",p,s.length,4),b=Ie("aData",l,r.length,4),k=Ie("bData",c,t.length,4),w;if(o)if(n){let y=ye.size(r)===1,$=ye.size(t)===1,T=r.length>0&&r[r.length-1]%4===0,M=t.length>0&&t[t.length-1]%4===0;y||$?w=_.setByOffset("global_idx",f(y?`${b.type.value}(${b.getByOffset("0")}.x)`:b.getByOffset("global_idx"),$?`${k.type.value}(${k.getByOffset("0")}.x)`:k.getByOffset("global_idx"))):w=` - let outputIndices = ${_.offsetToIndices("global_idx * 4u")}; - let offsetA = ${b.broadcastedIndicesToOffset("outputIndices",_)}; - let offsetB = ${k.broadcastedIndicesToOffset("outputIndices",_)}; - ${_.setByOffset("global_idx",f(a||T?b.getByOffset("offsetA / 4u"):`${b.type.value}(${b.getByOffset("offsetA / 4u")}[offsetA % 4u])`,a||M?k.getByOffset("offsetB / 4u"):`${k.type.value}(${k.getByOffset("offsetB / 4u")}[offsetB % 4u])`))} - `}else w=_.setByOffset("global_idx",f(b.getByOffset("global_idx"),k.getByOffset("global_idx")));else{if(!n)throw new Error("no necessary to use scalar implementation for element-wise binary op implementation.");let y=($,T,M="")=>{let x=`aData[indexA${T}][componentA${T}]`,v=`bData[indexB${T}][componentB${T}]`;return` - let outputIndices${T} = ${_.offsetToIndices(`global_idx * 4u + ${T}u`)}; - let offsetA${T} = ${b.broadcastedIndicesToOffset(`outputIndices${T}`,_)}; - let offsetB${T} = ${k.broadcastedIndicesToOffset(`outputIndices${T}`,_)}; - let indexA${T} = offsetA${T} / 4u; - let indexB${T} = offsetB${T} / 4u; - let componentA${T} = offsetA${T} % 4u; - let componentB${T} = offsetB${T} % 4u; - ${$}[${T}] = ${M}(${u(x,v)}); - `};p===9?w=` - var data = vec4(0); - ${y("data",0,"u32")} - ${y("data",1,"u32")} - ${y("data",2,"u32")} - ${y("data",3,"u32")} - outputData[global_idx] = dot(vec4(0x1, 0x100, 0x10000, 0x1000000), vec4(data));`:w=` - ${y("outputData[global_idx]",0)} - ${y("outputData[global_idx]",1)} - ${y("outputData[global_idx]",2)} - ${y("outputData[global_idx]",3)} - `}return` - ${e.registerUniform("vec_size","u32").declareVariables(b,k,_)} - - ${d??""} - - ${e.mainStart()} - ${e.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.vec_size")} - ${w} - }`},nh=(e,r,t,s,o,n,a=t.dataType)=>{let i=t.dims.map(b=>Number(b)??1),l=s.dims.map(b=>Number(b)??1),c=!ye.areEqual(i,l),p=i,d=ye.size(i),u=!1,f=!1,_=[c];if(c){let b=Gn.calcShape(i,l,!1);if(!b)throw new Error("Can't perform binary op on the given tensors");p=b.slice(),d=ye.size(p);let k=ye.size(i)===1,w=ye.size(l)===1,y=i.length>0&&i[i.length-1]%4===0,$=l.length>0&&l[l.length-1]%4===0;_.push(k),_.push(w),_.push(y),_.push($);let T=1;for(let M=1;Mb.toString()).join("_"),inputDependencies:["rank","rank"]},getShaderSource:b=>sh(b,i,l,p,u,c,f,o,t.dataType,s.dataType,a,n),getRunData:()=>({outputs:[{dims:p,dataType:a}],dispatchGroup:{x:Math.ceil(d/64/4)},programUniforms:[{type:12,data:Math.ceil(ye.size(p)/4)},...dt(i,l,p)]})}},vs=(e,r,t,s,o,n)=>{e.compute(nh(r,o??"",e.inputs[0],e.inputs[1],t,s,n))},oh=e=>{vs(e,"Add",(r,t)=>`${r}+${t}`)},ah=e=>{vs(e,"Div",(r,t)=>`${r}/${t}`)},ih=e=>{vs(e,"Equal",{scalar:(r,t)=>`u32(${r}==${t})`,vector:(r,t)=>`vec4(${r}==${t})`},void 0,void 0,9)},lh=e=>{vs(e,"Mul",(r,t)=>`${r}*${t}`)},ch=e=>{let r=Ie("input",e.inputs[0].dataType,e.inputs[0].dims).type.value;vs(e,"Pow",{scalar:(t,s)=>`pow_custom(${t},${s})`,vector:(t,s)=>`pow_vector_custom(${t},${s})`},` - fn pow_custom(a : ${r}, b : ${r}) -> ${r} { - if (b == ${r}(0.0)) { - return ${r}(1.0); - } else if (a < ${r}(0.0) && f32(b) != floor(f32(b))) { - return ${r}(pow(f32(a), f32(b))); // NaN - } - return select(sign(a), ${r}(1.0), round(f32(abs(b) % ${r}(2.0))) != 1.0) * ${r}(${r==="i32"?"round":""}(pow(f32(abs(a)), f32(b)))); - } - fn pow_vector_custom(a : vec4<${r}>, b : vec4<${r}>) -> vec4<${r}> { - // TODO: implement vectorized pow - return vec4<${r}>(pow_custom(a.x, b.x), pow_custom(a.y, b.y), pow_custom(a.z, b.z), pow_custom(a.w, b.w)); - } - `)},uh=e=>{vs(e,"Sub",(r,t)=>`${r}-${t}`)},dh=e=>{vs(e,"Greater",{scalar:(r,t)=>`u32(${r}>${t})`,vector:(r,t)=>`vec4(${r}>${t})`},void 0,void 0,9)},ph=e=>{vs(e,"Less",{scalar:(r,t)=>`u32(${r}<${t})`,vector:(r,t)=>`vec4(${r}<${t})`},void 0,void 0,9)},mh=e=>{vs(e,"GreaterOrEqual",{scalar:(r,t)=>`u32(${r}>=${t})`,vector:(r,t)=>`vec4(${r}>=${t})`},void 0,void 0,9)},hh=e=>{vs(e,"LessOrEqual",{scalar:(r,t)=>`u32(${r}<=${t})`,vector:(r,t)=>`vec4(${r}<=${t})`},void 0,void 0,9)}}),_h,fh,gh,wh,Mh,bh,Vx=Ue(()=>{Mt(),Pt(),pr(),Ct(),_h=(e,r)=>{if(!e||e.length<1)throw new Error("too few inputs");let t=0,s=e[t],o=s.dataType,n=s.dims.length;e.forEach((a,i)=>{if(i!==t){if(a.dataType!==o)throw new Error("input tensors should be one type");if(a.dims.length!==n)throw new Error("input tensors should have the same shape");a.dims.forEach((l,c)=>{if(c!==r&&l!==s.dims[c])throw new Error("non concat dimensions must match")})}})},fh=(e,r)=>` - fn calculateInputIndex(index: u32) -> u32 { - let sizeInConcatAxis = array(${r}); - for (var i: u32 = 0u; i < ${e}; i += 1u ) { - if (index < sizeInConcatAxis[i]) { - return i; - } - } - return ${e}u; - }`,gh=(e,r)=>{let t=e.length,s=[];for(let o=0;o{let o=ye.size(t),n=new Array(e.length),a=new Array(e.length),i=0,l=[],c=[],p=[{type:12,data:o}];for(let b=0;b`uniforms.sizeInConcatAxis${b}`).join(","),_=b=>` - - ${(()=>{b.registerUniform("outputSize","u32");for(let k=0;k(${f}); - ${u} -= sizeInConcatAxis[inputIndex - 1u]; - } - - ${gh(a,d)} - }`;return{name:"Concat",shaderCache:{hint:`${r}`,inputDependencies:l},getRunData:()=>({outputs:[{dims:t,dataType:s}],dispatchGroup:{x:Math.ceil(o/64)},programUniforms:p}),getShaderSource:_}},Mh=(e,r)=>{let t=e.inputs,s=t[0].dims,o=ye.normalizeAxis(r.axis,s.length);_h(t,o);let n=s.slice();n[o]=t.reduce((i,l)=>i+(l.dims.length>o?l.dims[o]:0),0);let a=t.filter(i=>ye.size(i.dims)>0);e.compute(wh(a,o,n,t[0].dataType),{inputs:a})},bh=e=>Kt({axis:e.axis})}),gn,wn,Mn,bl,bn=Ue(()=>{Mt(),Pt(),gn=(e,r,t="f32")=>{switch(e.activation){case"Relu":return`value = max(value, ${r}(0.0));`;case"Sigmoid":return`value = (${r}(1.0) / (${r}(1.0) + exp(-value)));`;case"Clip":return`value = clamp(value, ${r}(${t}(uniforms.clip_min)), ${r}(${t}(uniforms.clip_max)));`;case"HardSigmoid":return`value = max(${r}(0.0), min(${r}(1.0), ${t}(uniforms.alpha) * value + ${t}(uniforms.beta)));`;case"LeakyRelu":return`value = select(${t}(uniforms.alpha) * value, value, value >= ${r}(0.0));`;case"Tanh":return`let e2x = exp(-2.0 * abs(value)); - value = sign(value) * (1.0 - e2x) / (1.0 + e2x); - `;case"":return"";default:throw new Error(`Unsupported activation ${e.activation}`)}},wn=(e,r)=>{e.activation==="Clip"?r.push({type:1,data:e.clipMax},{type:1,data:e.clipMin}):e.activation==="HardSigmoid"?r.push({type:1,data:e.alpha},{type:1,data:e.beta}):e.activation==="LeakyRelu"&&r.push({type:1,data:e.alpha})},Mn=(e,r)=>{e.activation==="Clip"?r.push({name:"clip_max",type:"f32"},{name:"clip_min",type:"f32"}):e.activation==="HardSigmoid"?r.push({name:"alpha",type:"f32"},{name:"beta",type:"f32"}):e.activation==="LeakyRelu"&&r.push({name:"alpha",type:"f32"})},bl=e=>{let r=(e==null?void 0:e.activation)||"";if(r==="HardSigmoid"){let[t,s]=(e==null?void 0:e.activation_params)||[.2,.5];return{activation:r,alpha:t,beta:s}}else if(r==="Clip"){let[t,s]=(e==null?void 0:e.activation_params)||[Ud,Wd];return{activation:r,clipMax:s,clipMin:t}}else if(r==="LeakyRelu"){let[t]=(e==null?void 0:e.activation_params)||[.01];return{activation:r,alpha:t}}return{activation:r}}}),Lr,yh,yl=Ue(()=>{Lr=(e,r)=>{switch(e){case 1:return r;case 2:return`vec2<${r}>`;case 3:return`vec3<${r}>`;case 4:return`vec4<${r}>`;default:throw new Error(`${e}-component is not supported.`)}},yh=e=>` - ${e?"value = value + getBiasByOutputCoords(coords);":""} - `}),vh,Ux=Ue(()=>{vh=e=>` -fn getIndexFromCoords4D(coords : vec4, shape : vec4) -> i32 { - return dot(coords, vec4( - shape.y * shape.z * shape.w, shape.z * shape.w, shape.w, 1)); -} -fn getOutputIndexFromCoords(coords : vec4) -> i32 { - return dot(coords, vec4( - i32(${e}.x), i32(${e}.y), i32(${e}.z), 1)); -} -`}),bo,vl,xl=Ue(()=>{Mt(),Pt(),Ct(),bn(),bo=(e,r,t,s,o)=>{let n=s-t;return` - ${Array.from({length:t}).map((a,i)=>` - if (${ct(r.shape,i,r.rank)} != 1) { - ${r.indicesSet(e,i,ct(o,i+n,s))} - } else { - ${r.indicesSet(e,i,0)} - }`).join("")} -`},vl=(e,r,t,s,o=!1,n)=>{let a=e[0].dims,i=e[1].dims,l=a[a.length-2],c=i[i.length-1],p=a[a.length-1],d=lr(c),u=lr(p),f=lr(l),_=ye.size(t)/d/f,b=e.length>2,k=s?s.slice(0,-2):t.slice(0,-2),w=[ye.size(k),l,c],y=[{type:12,data:_},{type:12,data:l},{type:12,data:c},{type:12,data:p}];wn(r,y),y.push(...dt(k,a,i)),b&&y.push(...dt(e[2].dims)),y.push(...dt(w));let $=T=>{let M=cl("batch_dims",e[0].dataType,k.length),x=Ie("a",e[0].dataType,a.length,u),v=Ie("b",e[1].dataType,i.length,d),C=nt("output",e[0].dataType,w.length,d),F=Ir(C.type.tensor),D=gn(r,C.type.value,F),K=[x,v],U="";if(b){let q=o?d:1;K.push(Ie("bias",e[2].dataType,e[2].dims.length,q)),U=`${o?`value += bias[col / ${q}];`:`value += ${C.type.value}(bias[row + i]);`}`}let j=[{name:"output_size",type:"u32"},{name:"M",type:"u32"},{name:"N",type:"u32"},{name:"K",type:"u32"}];Mn(r,j);let se=()=>{let q=`var a_data: ${x.type.value};`;for(let re=0;re; - for (var k: u32 = 0u; k < uniforms.K; k = k + ${u}) { - ${se()} - } - for (var i = 0u; i < ${f}u; i++) { - var value = values[i]; - ${U} - ${D} - let cur_indices = ${C.type.indices}(batch, row + i, col); - let offset = ${C.indicesToOffset("cur_indices")}; - ${C.setByOffset(`offset / ${d}`,"value")}; - } - } - `};return{name:"MatMulNaive",shaderCache:{hint:`${r.activation};${d};${u};${f};${o}`,inputDependencies:b?["rank","rank","rank"]:["rank","rank"]},getRunData:()=>({outputs:[{dims:n?n(t):t,dataType:e[0].dataType}],dispatchGroup:{x:Math.ceil(_/64)},programUniforms:y}),getShaderSource:$}}}),xh,Th,Tl,El,Eh,Pl,Ph,ha,Cl=Ue(()=>{Mt(),Pt(),Ct(),bn(),xl(),yl(),xh=(e,r)=>e?` - mm_Asub[inputRow][inputCol] = mm_readA(batch, - kStart + inputRow, - globalRowStart / innerElementSize + inputCol${r?", batchIndices":""}); - `:` - mm_Asub[inputRow][inputCol] = mm_readA(batch, - globalRow + innerRow, - kStart / innerElementSize + inputCol${r?", batchIndices":""}); - `,Th=(e,r)=>e?` - let ACached0 = mm_Asub[k * innerElementSize][localRow]; - let ACached1 = mm_Asub[k * innerElementSize + 1][localRow]; - let ACached2 = mm_Asub[k * innerElementSize + 2][localRow]; - ${r===3?"":"let ACached3 = mm_Asub[k * innerElementSize + 3][localRow];"} - for (var i = 0; i < rowPerThread; i = i + 1) { - acc[i] = BCached0 * ACached0[i] + acc[i]; - acc[i] = BCached1 * ACached1[i] + acc[i]; - acc[i] = BCached2 * ACached2[i] + acc[i]; - ${r===3?"":"acc[i] = BCached3 * ACached3[i] + acc[i];"} - }`:` - for (var i = 0; i < rowPerThread; i = i + 1) { - let ACached = mm_Asub[tileRow + i][k]; - acc[i] = BCached0 * ACached.x + acc[i]; - acc[i] = BCached1 * ACached.y + acc[i]; - acc[i] = BCached2 * ACached.z + acc[i]; - ${r===3?"":"acc[i] = BCached3 * ACached.w + acc[i];"} - }`,Tl=(e,r,t="f32",s,o=!1,n=32,a=!1,i=32)=>{let l=r[1]*e[1],c=r[0]*e[0],p=o?l:n,d=o?n:l,u=p/r[0],f=n/r[1];if(!((o&&u===4&&e[1]===4||!o&&(u===3||u===4))&&p%r[0]===0&&n%r[1]===0&&e[0]===4))throw new Error(`If transposeA ${o} is true, innerElementSize ${u} and workPerThread[1] ${e[1]} must be 4. - Otherwise, innerElementSize ${u} must be 3 or 4. - tileAWidth ${p} must be divisible by workgroupSize[0]${r[0]}. tileInner ${n} must be divisible by workgroupSize[1] ${r[1]}. colPerThread ${e[0]} must be 4.`);return` -var mm_Asub: array, ${p/u}>, ${d}>; -var mm_Bsub: array, ${c/e[0]}>, ${n}>; - -const rowPerThread = ${e[1]}; -const colPerThread = ${e[0]}; -const innerElementSize = ${u}; -const tileInner = ${n}; - -@compute @workgroup_size(${r[0]}, ${r[1]}, ${r[2]}) -fn main(@builtin(local_invocation_id) localId : vec3, - @builtin(global_invocation_id) globalId : vec3, - @builtin(workgroup_id) workgroupId : vec3) { - let localRow = i32(localId.y); - let tileRow = localRow * rowPerThread; - let tileCol = i32(localId.x); - - let globalRow =i32(globalId.y) * rowPerThread; - let globalCol = i32(globalId.x); - let batch = ${a?"0":"i32(globalId.z)"}; - ${s?`let batchIndices = ${s.offsetToIndices("u32(batch)")};`:""} - let globalRowStart = i32(workgroupId.y) * ${l}; - - let num_tiles = ${a?`${Math.ceil(i/n)}`:"(uniforms.dim_inner - 1) / tileInner + 1"}; - var kStart = ${a?`i32(globalId.z) * ${i}`:"0"}; - - var acc: array, rowPerThread>; - - // Loop over shared dimension. - let tileRowB = localRow * ${f}; - for (var t = 0; t < num_tiles; t = t + 1) { - // Load one tile of A into local memory. - for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) { - let inputRow = tileRow + innerRow; - let inputCol = tileCol; - ${xh(o,s)} - } - - // Load one tile of B into local memory. - for (var innerRow = 0; innerRow < ${f}; innerRow = innerRow + 1) { - let inputRow = tileRowB + innerRow; - let inputCol = tileCol; - mm_Bsub[inputRow][inputCol] = mm_readB(batch, kStart + inputRow, globalCol${s?", batchIndices":""}); - } - kStart = kStart + tileInner; - workgroupBarrier(); - - // Compute acc values for a single thread. - for (var k = 0; k < tileInner / innerElementSize; k = k + 1) { - let BCached0 = mm_Bsub[k * innerElementSize][tileCol]; - let BCached1 = mm_Bsub[k * innerElementSize + 1][tileCol]; - let BCached2 = mm_Bsub[k * innerElementSize + 2][tileCol]; - ${u===3?"":"let BCached3 = mm_Bsub[k * innerElementSize + 3][tileCol];"} - - ${Th(o,u)} - } - - workgroupBarrier(); - } - - for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) { - mm_write(batch, globalRow + innerRow, globalCol, acc[innerRow]); - } -}`},El=(e,r)=>e?` - mm_Asub[inputRow][inputCol] = mm_readA(batch, - kStart + inputRow, - globalRowStart + inputCol${r?", batchIndices":""}); - `:` - mm_Asub[inputRow][inputCol] = mm_readA(batch, - globalRowStart + inputRow, - kStart + inputCol${r?", batchIndices":""}); - `,Eh=e=>e?"let ACached = mm_Asub[k][tileRow + innerRow];":"let ACached = mm_Asub[tileRow + innerRow][k];",Pl=(e,r,t="f32",s,o=!1,n=32,a=!1,i=32,l=!1)=>{let c=e[1]*r[1],p=e[0]*r[0],d=o?c:n,u=o?n:c;if(!(u%r[1]===0&&d%r[0]===0&&n%r[1]===0))throw new Error(`tileAHight ${u} must be divisible by workgroupSize[1]${r[1]}, tileAWidth ${d} must be divisible by workgroupSize[0]${r[0]}, tileInner ${n} must be divisible by workgroupSize[1]${r[1]}`);let f=u/r[1],_=d/r[0],b=n/r[1],k=l?` - let localRow = i32(localId.y); - let localCol = i32(localId.x); - let globalRowStart = i32(workgroupId.y) * ${c}; - let globalColStart = i32(workgroupId.x) * ${p}; - - // Loop over shared dimension. - for (var t = 0; t < num_tiles; t = t + 1) { - // Load one tile of A into local memory. - for (var inputRow = localRow; inputRow < ${u}; inputRow = inputRow + ${r[1]}) { - for (var inputCol = localCol; inputCol < ${d}; inputCol = inputCol + ${r[0]}) { - ${El(o,s)} - } - } - // Load one tile of B into local memory. - for (var inputRow = localRow; inputRow < ${n}; inputRow = inputRow + ${r[1]}) { - for (var inputCol = localCol; inputCol < ${p}; inputCol = inputCol + ${r[0]}) { - mm_Bsub[inputRow][inputCol] = mm_readB(batch, - kStart + inputRow, - globalColStart + inputCol${s?", batchIndices":""}); - } - } - kStart = kStart + tileInner; - workgroupBarrier(); - - // Compute acc values for a single thread. - var BCached : array<${t}, colPerThread>; - for (var k = 0; k < tileInner; k = k + 1) { - for (var inner = 0; inner < colPerThread; inner = inner + 1) { - BCached[inner] = mm_Bsub[k][localCol + inner * ${r[0]}]; - } - for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) { - let ACached = ${o?`mm_Asub[k][localRow + innerRow * ${r[1]}];`:`mm_Asub[localRow + innerRow * ${r[1]}][k];`} - for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) { - acc[innerRow][innerCol] = acc[innerRow][innerCol] + - ACached * BCached[innerCol]; - } - } - } - workgroupBarrier(); - } - for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) { - let gRow = globalRowStart + localRow + innerRow * ${r[1]}; - for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) { - let gCol = globalColStart + localCol + innerCol * ${r[0]}; - mm_write(batch, gRow, gCol, acc[innerRow][innerCol]); - } - } - `:` -let tileRow = i32(localId.y) * rowPerThread; -let tileCol = i32(localId.x) * colPerThread; - -let globalRow = i32(globalId.y) * rowPerThread; -let globalCol = i32(globalId.x) * colPerThread; -let globalRowStart = i32(workgroupId.y) * ${c}; - -let tileRowA = i32(localId.y) * ${f}; -let tileColA = i32(localId.x) * ${_}; -let tileRowB = i32(localId.y) * ${b}; -// Loop over shared dimension. -for (var t = 0; t < num_tiles; t = t + 1) { - // Load one tile of A into local memory. - for (var innerRow = 0; innerRow < ${f}; innerRow = innerRow + 1) { - for (var innerCol = 0; innerCol < ${_}; innerCol = innerCol + 1) { - let inputRow = tileRowA + innerRow; - let inputCol = tileColA + innerCol; - ${El(o,s)} - } - } - - // Load one tile of B into local memory. - for (var innerRow = 0; innerRow < ${b}; innerRow = innerRow + 1) { - for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) { - let inputRow = tileRowB + innerRow; - let inputCol = tileCol + innerCol; - mm_Bsub[inputRow][inputCol] = mm_readB(batch, - kStart + inputRow, - globalCol + innerCol${s?", batchIndices":""}); - } - } - kStart = kStart + tileInner; - workgroupBarrier(); - - // Compute acc values for a single thread. - var BCached : array<${t}, colPerThread>; - for (var k = 0; k < tileInner; k = k + 1) { - for (var inner = 0; inner < colPerThread; inner = inner + 1) { - BCached[inner] = mm_Bsub[k][tileCol + inner]; - } - - for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) { - ${Eh(o)} - for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) { - acc[innerRow][innerCol] = acc[innerRow][innerCol] + ACached * BCached[innerCol]; - } - } - } - - workgroupBarrier(); -} - -for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) { - for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) { - mm_write(batch, globalRow + innerRow, globalCol + innerCol, - acc[innerRow][innerCol]); - } -} -`;return` - var mm_Asub : array, ${u}>; - var mm_Bsub : array, ${n}>; - const rowPerThread = ${e[1]}; - const colPerThread = ${e[0]}; - const tileInner = ${n}; - -@compute @workgroup_size(${r[0]}, ${r[1]}, ${r[2]}) -fn main(@builtin(local_invocation_id) localId : vec3, - @builtin(global_invocation_id) globalId : vec3, - @builtin(workgroup_id) workgroupId : vec3) { - let batch = ${a?"0":"i32(globalId.z)"}; - ${s?`let batchIndices = ${s.offsetToIndices("u32(batch)")};`:""} - let num_tiles = ${a?`${Math.ceil(i/n)}`:"(uniforms.dim_inner - 1) / tileInner + 1"}; - var kStart = ${a?`i32(globalId.z) * ${i}`:"0"}; - - var acc : array, rowPerThread>; - ${k} - } -`},Ph=(e,r,t,s,o=!1)=>{let[n,a,i,l]=s,c=Ir(s[0].type.tensor);return` - fn mm_readA(batch: i32, row: i32, colIn: i32, batchIndices: ${n.type.indices}) -> ${Lr(e,c)} { - var value = ${Lr(e,c)}(0.0); - let col = colIn * ${e}; - if(row < uniforms.dim_a_outer && col < uniforms.dim_inner) - { - var aIndices: ${a.type.indices}; - ${bo("aIndices",a,a.rank-2,n.rank,"batchIndices")} - ${a.indicesSet("aIndices",a.rank-2,"u32(row)")} - ${a.indicesSet("aIndices",a.rank-1,"u32(colIn)")} - value = ${a.getByIndices("aIndices")}; - } - return value; - } - - fn mm_readB(batch: i32, row: i32, colIn: i32, batchIndices: ${n.type.indices}) -> ${Lr(e,c)} { - var value = ${Lr(e,c)}(0.0); - let col = colIn * ${e}; - if(row < uniforms.dim_inner && col < uniforms.dim_b_outer) - { - var bIndices: ${i.type.indices}; - ${bo("bIndices",i,i.rank-2,n.rank,"batchIndices")} - ${i.indicesSet("bIndices",i.rank-2,"u32(row)")} - ${i.indicesSet("bIndices",i.rank-1,"u32(colIn)")} - value = ${i.getByIndices("bIndices")}; - } - return value; - } - - fn mm_write(batch: i32, row: i32, colIn: i32, valueIn: ${Lr(e,c)}) { - let col = colIn * ${e}; - if (row < uniforms.dim_a_outer && col < uniforms.dim_b_outer) { - var value = valueIn; - let coords = vec3(batch, row, colIn); - ${r?`value = value + ${o?"bias[colIn]":`${Lr(e,c)}(bias[row])`};`:""} - ${t} - ${l.setByIndices("vec3(coords)","value")} - } - } - `},ha=(e,r,t,s,o=!1,n)=>{let a=e[0].dims,i=e[1].dims,l=a.slice(0,-2),c=i.slice(0,-2),p=s?s.slice(0,-2):t.slice(0,-2),d=ye.size(p),u=a[a.length-2],f=a[a.length-1],_=i[i.length-1],b=f%4===0&&_%4===0,k=u<=8?[4,1,1]:[4,4,1],w=[8,8,1],y=[Math.ceil(_/w[0]/k[0]),Math.ceil(u/w[1]/k[1]),Math.ceil(d/w[2]/k[2])],$=b?4:1,T=[...l,u,f/$],M=T.length,x=[...c,f,_/$],v=x.length,C=[d,u,_/$],F=[{type:6,data:u},{type:6,data:_},{type:6,data:f}];wn(r,F),F.push(...dt(p,T,x));let D=["rank","rank"],K=e.length>2;K&&(F.push(...dt(e[2].dims)),D.push("rank")),F.push(...dt(C));let U=j=>{let se=p.length,q=cl("batchDims",e[0].dataType,se,1),re=Ir(e[0].dataType),Z=Ie("a",e[0].dataType,M,$),ae=Ie("b",e[1].dataType,v,$),_e=nt("result",e[0].dataType,C.length,$),pe=[Z,ae];if(K){let le=o?$:1;pe.push(Ie("bias",e[2].dataType,e[2].dims.length,le))}let oe=[{name:"dim_a_outer",type:"i32"},{name:"dim_b_outer",type:"i32"},{name:"dim_inner",type:"i32"}];Mn(r,oe);let G=Ir(_e.type.tensor),B=gn(r,_e.type.value,G),Q=Ph($,K,B,[q,Z,ae,_e],o);return` - ${j.registerUniforms(oe).registerInternalVariables(q).declareVariables(...pe,_e)} - ${Q} - ${b?Tl(k,w,re,q):Pl(k,w,re,q)} - `};return{name:"MatMul",shaderCache:{hint:`${k};${r.activation};${b};${o}`,inputDependencies:D},getRunData:()=>({outputs:[{dims:n?n(t):t,dataType:e[0].dataType}],dispatchGroup:{x:y[0],y:y[1],z:y[2]},programUniforms:F}),getShaderSource:U}}}),Ch,Sh,Wx=Ue(()=>{Mt(),Ns(),Ct(),bn(),yl(),Ux(),Cl(),Ch=(e,r,t,s,o=!1,n,a=4,i=4,l=4,c="f32")=>{let p=F=>{switch(F){case 1:return"resData = x[xIndex];";case 3:return`resData = vec3<${c}>(x[xIndex], x[xIndex + 1], x[xIndex + 2]);`;case 4:return"resData = x[xIndex / 4];";default:throw new Error(`innerElementSize ${F} is not supported.`)}},d=F=>{switch(F){case 1:return"return w[row * i32(uniforms.w_shape[3]) + colIn];";case 4:return"return w[row * i32(uniforms.w_shape[3]) / 4 + colIn];";default:throw new Error(`innerElementSize ${F} is not supported.`)}},u=e?` - let coord = vec4(batch, xRow, xCol, xCh); - `:` - let coord = vec4(batch, xCh, xRow, xCol); - `,f=e?` - let coords = vec4( - batch, - row / outWidth, - row % outWidth, - col); - `:` - let coords = vec4( - batch, - row, - col / outWidth, - col % outWidth); - `,_=e?"i32(uniforms.x_shape[1])":"i32(uniforms.x_shape[2])",b=e?"i32(uniforms.x_shape[2])":"i32(uniforms.x_shape[3])",k=e?"row":"col",w=e?"col":"row",y=` - let inChannels = i32(uniforms.w_shape[2]); - let outWidth = ${e?"i32(uniforms.result_shape[2])":"i32(uniforms.result_shape[3])"}; - let outRow = ${k} / outWidth; - let outCol = ${k} % outWidth; - - let WRow = ${w} / (i32(uniforms.w_shape[1]) * inChannels); - let WCol = ${w} / inChannels % i32(uniforms.w_shape[1]); - let xRow = outRow * uniforms.stride[0] + uniforms.dilation[0] * WRow - uniforms.pad[0]; - let xCol = outCol * uniforms.stride[1] + uniforms.dilation[1] * WCol - uniforms.pad[1]; - let xCh = ${w} % inChannels; - var resData = ${Lr(a,c)}(0.0); - // The bounds checking is always needed since we use it to pad zero for - // the 'same' padding type. - if (xRow >= 0 && xRow < ${_} && xCol >= 0 && xCol < ${b}) { - ${u} - let xIndex = getIndexFromCoords4D(coord, vec4(uniforms.x_shape)); - ${p(a)} - } - return resData;`,$=e?r&&s?` - let col = colIn * ${a}; - ${y}`:` - let col = colIn * ${a}; - if (row < uniforms.dim_a_outer && col < uniforms.dim_inner) { - ${y} - } - return ${Lr(a,c)}(0.0);`:s&&t?` - let col = colIn * ${a}; - ${y}`:` - let col = colIn * ${a}; - if (row < uniforms.dim_inner && col < uniforms.dim_b_outer) { - ${y} - } - return ${Lr(a,c)}(0.0);`,T=e?s&&t?d(i):` - let col = colIn * ${i}; - if (row < uniforms.dim_inner && col < uniforms.dim_b_outer) { - ${d(i)} - } - return ${Lr(i,c)}(0.0);`:` - let col = colIn * ${i}; - if (row < uniforms.dim_inner && col < uniforms.dim_a_outer) { - ${d(i)} - } - return ${Lr(i,c)}(0.0);`,M=Lr(l,c),x=Lr(e?a:i,c),v=Lr(e?i:a,c),C=gn(n,M,c);return` - fn mm_readA(batch: i32, row : i32, colIn : i32) -> ${x} { - ${e?$:T} - } - - fn mm_readB(batch: i32, row : i32, colIn : i32) -> ${v} { - ${e?T:$} - } - - fn mm_write(batch: i32, row : i32, colIn : i32, valueIn : ${M}) { - let col = colIn * ${l}; - if (row < uniforms.dim_a_outer && col < uniforms.dim_b_outer) - { - var value = valueIn; - let outWidth = ${e?"i32(uniforms.result_shape[2])":"i32(uniforms.result_shape[3])"}; - ${f} - ${yh(o)} - ${C} - setOutputAtCoords(coords[0], coords[1], coords[2], coords[3], value); - } - }`},Sh=(e,r,t,s,o,n,a,i,l)=>{let c=r.format==="NHWC",p=c?e[0].dims[3]:e[0].dims[1],d=t[0],u=c?t[2]:t[3],f=c?t[1]:t[2],_=c?t[3]:t[1],b=c&&(p%4===0||p%3===0)&&_%4===0,k=c?_:u*f,w=c?u*f:_,y=[8,8,1],$=s<=8?[4,1,1]:[4,4,1],T=[Math.ceil(k/y[0]/$[0]),Math.ceil(w/y[1]/$[1]),Math.ceil(d/y[2]/$[2])];zt("verbose",()=>`[conv2d_mm_webgpu] dispatch = ${T}`);let M=b?c&&p%4!==0?3:4:1,x=y[1]*$[1],v=y[0]*$[0],C=Math.max(y[0]*M,y[1]),F=s%x===0,D=o%v===0,K=n%C===0,U=b?[M,4,4]:[1,1,1],j=[{type:6,data:s},{type:6,data:o},{type:6,data:n},{type:6,data:[r.pads[0],r.pads[1]]},{type:6,data:r.strides},{type:6,data:r.dilations}];wn(r,j),j.push(...dt(e[0].dims,e[1].dims));let se=["rank","rank"];a&&(j.push(...dt(e[2].dims)),se.push("rank")),j.push(...dt(t));let q=re=>{let Z=[{name:"dim_a_outer",type:"i32"},{name:"dim_b_outer",type:"i32"},{name:"dim_inner",type:"i32"},{name:"pad",type:"i32",length:2},{name:"stride",type:"i32",length:2},{name:"dilation",type:"i32",length:2}];Mn(r,Z);let ae=b?4:1,_e=Ir(e[0].dataType),pe=` - fn setOutputAtIndex(flatIndex : i32, value : ${b?`vec4<${_e}>`:_e}) { - result[flatIndex] = ${b?`vec4<${_e}>`:_e}(value); - } - fn setOutputAtCoords(d0 : i32, d1 : i32, d2 : i32, d3 : i32, value : ${b?`vec4<${_e}>`:_e}) { - let flatIndex = getOutputIndexFromCoords(vec4(d0, d1, d2, d3)); - setOutputAtIndex(flatIndex ${b?"/ 4":""}, value); - }`,oe=Ie("x",e[0].dataType,e[0].dims.length,M===3?1:M),G=Ie("w",e[1].dataType,e[1].dims.length,ae),B=[oe,G],Q=nt("result",e[0].dataType,t.length,ae);if(a){let le=Ie("bias",e[2].dataType,e[2].dims.length,ae);B.push(le),pe+=` - fn getBiasByOutputCoords(coords : vec4) -> ${b?`vec4<${_e}>`:_e} { - return bias[coords.${c?"w":"y"}${b?"/ 4":""}]; - }`}return` - ${vh("uniforms.result_strides")} - //struct Uniforms { xShape : vec4, wShape : vec4, outShape : vec4, - // outShapeStrides: vec3, filterDims : vec2, pad : vec2, stride : vec2, - // dilation : vec2, dimAOuter : i32, dimBOuter : i32, dimInner : i32 }; - ${re.registerUniforms(Z).declareVariables(...B,Q)} - ${pe} - ${Ch(c,F,D,K,a,r,U[0],U[1],U[2],_e)} - ${b?Tl($,y,_e,void 0,!c,C):Pl($,y,_e,void 0,!c,C,!1,void 0,i)}`};return{name:"Conv2DMatMul",shaderCache:{hint:`${r.cacheKey};${M};${b};${F};${D};${K};${x};${v};${C}`,inputDependencies:se},getRunData:()=>({outputs:[{dims:l?l(t):t,dataType:e[0].dataType}],dispatchGroup:{x:T[0],y:T[1],z:T[2]},programUniforms:j}),getShaderSource:q}}}),$h,Sl,yo,kh,$l,Ih,Ah,Fh,Gx=Ue(()=>{Mt(),Ns(),Pt(),Ct(),bn(),yl(),$h=e=>{let r=1;for(let t=0;ttypeof e=="number"?[e,e,e]:e,yo=(e,r)=>r<=1?e:e+(e-1)*(r-1),kh=(e,r,t,s=1)=>{let o=yo(r,s);return Math.floor((e[0]*(t-1)-t+o)/2)},$l=(e,r,t,s,o)=>{o==null&&(o=kh(e,r[0],s[0]));let n=[0,0,0,t];for(let a=0;a<3;a++)e[a]+2*o>=r[a]&&(n[a]=Math.trunc((e[a]-r[a]+2*o)/s[a]+1));return n},Ih=(e,r,t,s,o,n,a,i,l,c)=>{let p,d,u,f;if(e==="VALID"&&(e=0),typeof e=="number"){p={top:e,bottom:e,left:e,right:e,front:e,back:e};let _=$l([r,t,s,1],[i,l,c],1,[o,n,a],e);d=_[0],u=_[1],f=_[2]}else if(Array.isArray(e)){if(!e.every((b,k,w)=>b===w[0]))throw Error(`Unsupported padding parameter: ${e}`);p={top:e[0],bottom:e[1],left:e[2],right:e[3],front:e[4],back:e[5]};let _=$l([r,t,s,1],[i,l,c],1,[o,n,a],e[0]);d=_[0],u=_[1],f=_[2]}else if(e==="SAME_UPPER"){d=Math.ceil(r/o),u=Math.ceil(t/n),f=Math.ceil(s/a);let _=(d-1)*o+i-r,b=(u-1)*n+l-t,k=(f-1)*a+c-s,w=Math.floor(_/2),y=_-w,$=Math.floor(b/2),T=b-$,M=Math.floor(k/2),x=k-M;p={top:$,bottom:T,left:M,right:x,front:w,back:y}}else throw Error(`Unknown padding parameter: ${e}`);return{padInfo:p,outDepth:d,outHeight:u,outWidth:f}},Ah=(e,r,t,s,o,n=!1,a="channelsLast")=>{let i,l,c,p,d;if(a==="channelsLast")[i,l,c,p,d]=e;else if(a==="channelsFirst")[i,d,l,c,p]=e;else throw new Error(`Unknown dataFormat ${a}`);let[u,,f,_,b]=r,[k,w,y]=Sl(t),[$,T,M]=Sl(s),x=yo(f,$),v=yo(_,T),C=yo(b,M),{padInfo:F,outDepth:D,outHeight:K,outWidth:U}=Ih(o,l,c,p,k,w,y,x,v,C),j=n?u*d:u,se=[0,0,0,0,0];return a==="channelsFirst"?se=[i,j,D,K,U]:a==="channelsLast"&&(se=[i,D,K,U,j]),{batchSize:i,dataFormat:a,inDepth:l,inHeight:c,inWidth:p,inChannels:d,outDepth:D,outHeight:K,outWidth:U,outChannels:j,padInfo:F,strideDepth:k,strideHeight:w,strideWidth:y,filterDepth:f,filterHeight:_,filterWidth:b,effectiveFilterDepth:x,effectiveFilterHeight:v,effectiveFilterWidth:C,dilationDepth:$,dilationHeight:T,dilationWidth:M,inShape:e,outShape:se,filterShape:r}},Fh=(e,r,t,s,o,n)=>{let a=n==="channelsLast";a?e[0].dims[3]:e[0].dims[1];let i=[64,1,1],l={x:t.map((k,w)=>w)},c=[Math.ceil($h(l.x.map(k=>t[k]))/i[0]),1,1];zt("verbose",()=>`[conv3d_naive_webgpu] dispatch = ${c}`);let p=1,d=ye.size(t),u=[{type:12,data:d},{type:12,data:s},{type:12,data:o},{type:12,data:r.strides},{type:12,data:r.dilations}];wn(r,u),u.push(...dt(e[0].dims,e[1].dims));let f=["rank","rank"],_=e.length===3;_&&(u.push(...dt(e[2].dims)),f.push("rank")),u.push(...dt(t));let b=k=>{let w=[{name:"output_size",type:"u32"},{name:"filter_dims",type:"u32",length:s.length},{name:"pads",type:"u32",length:o.length},{name:"strides",type:"u32",length:r.strides.length},{name:"dilations",type:"u32",length:r.dilations.length}];Mn(r,w);let y=1,$=Ir(e[0].dataType),T=Ie("x",e[0].dataType,e[0].dims.length,p),M=Ie("W",e[1].dataType,e[1].dims.length,y),x=[T,M],v=nt("result",e[0].dataType,t.length,y),C="";if(_){let K=Ie("bias",e[2].dataType,e[2].dims.length,y);x.push(K),C+=` - fn getBiasByOutputCoords(coords : array) -> ${$} { - return bias[${a?ct("coords",4,5):ct("coords",1,5)}]; - }`}let F=Lr(p,$),D=gn(r,F,$);return` - ${C} - fn getX(d0 : u32, d1 : u32, d2 : u32, d3 : u32, d4 : u32) -> f32 { - let aIndices = array(d0, d1, d2, d3, d4); - return ${T.getByIndices("aIndices")}; - } - fn getW(d0 : u32, d1 : u32, d2 : u32, d3 : u32, d4 : u32) -> f32 { - let aIndices = array(d0, d1, d2, d3, d4); - return ${M.getByIndices("aIndices")}; - } - ${k.registerUniforms(w).declareVariables(...x,v)} - ${k.mainStart()} - ${k.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} - let coords = ${v.offsetToIndices("global_idx")}; - let batch = ${ct("coords",0,T.rank)}; - let d2 = ${a?ct("coords",T.rank-1,T.rank):ct("coords",1,T.rank)}; - let xFRCCorner = vec3(${a?ct("coords",1,T.rank):ct("coords",2,T.rank)}, - ${a?ct("coords",2,T.rank):ct("coords",3,T.rank)}, - ${a?ct("coords",3,T.rank):ct("coords",4,T.rank)}) * uniforms.strides - uniforms.pads; - let xFCorner = xFRCCorner.x; - let xRCorner = xFRCCorner.y; - let xCCorner = xFRCCorner.z; - let xShapeY = ${a?ct("uniforms.x_shape",1,T.rank):ct("uniforms.x_shape",2,T.rank)}; - let xShapeZ = ${a?ct("uniforms.x_shape",2,T.rank):ct("uniforms.x_shape",3,T.rank)}; - let xShapeW = ${a?ct("uniforms.x_shape",3,T.rank):ct("uniforms.x_shape",4,T.rank)}; - let xShapeU = ${a?ct("uniforms.x_shape",4,T.rank):ct("uniforms.x_shape",1,T.rank)}; - let inputDepthNearestVec4 = (xShapeU / 4) * 4; - let inputDepthVec4Remainder = xShapeU % 4; - - var value = 0.0; - for (var wF = 0u; wF < uniforms.filter_dims[0]; wF++) { - let xF = xFCorner + wF * uniforms.dilations[0]; - if (xF < 0 || xF >= xShapeY) { - continue; - } - - for (var wR = 0u; wR < uniforms.filter_dims[1]; wR++) { - let xR = xRCorner + wR * uniforms.dilations[1]; - if (xR < 0 || xR >= xShapeZ) { - continue; - } - - for (var wC = 0u; wC < uniforms.filter_dims[2]; wC++) { - let xC = xCCorner + wC * uniforms.dilations[2]; - if (xC < 0 || xC >= xShapeW) { - continue; - } - - for (var d1 = 0u; d1 < inputDepthNearestVec4; d1 += 4) { - ${a?`let xValues = vec4( - getX(batch, xF, xR, xC, d1), - getX(batch, xF, xR, xC, d1 + 1), - getX(batch, xF, xR, xC, d1 + 2), - getX(batch, xF, xR, xC, d1 + 3)); - `:`let xValues = vec4( - getX(batch, d1, xF, xR, xC), - getX(batch, d1 + 1, xF, xR, xC), - getX(batch, d1 + 2, xF, xR, xC), - getX(batch, d1 + 3, xF, xR, xC)); - `} - let wValues = vec4( - getW(d2, d1, wF, wR, wC), - getW(d2, d1 + 1, wF, wR, wC), - getW(d2, d1 + 2, wF, wR, wC), - getW(d2, d1 + 3, wF, wR, wC)); - value += dot(xValues, wValues); - } - if (inputDepthVec4Remainder == 1) { - ${a?`value += getX(batch, xF, xR, xC, inputDepthNearestVec4) - * getW(d2, inputDepthNearestVec4, wF, wR, wC);`:`value += getX(batch, inputDepthNearestVec4, xF, xR, xC) - * getW(d2, inputDepthNearestVec4, wF, wR, wC);`} - } else if (inputDepthVec4Remainder == 2) { - ${a?`let xValues = vec2( - getX(batch, xF, xR, xC, inputDepthNearestVec4), - getX(batch, xF, xR, xC, inputDepthNearestVec4 + 1)); - `:`let xValues = vec2( - getX(batch, inputDepthNearestVec4, xF, xR, xC), - getX(batch, inputDepthNearestVec4 + 1, xF, xR, xC)); - `} - let wValues = vec2( - getW(d2, inputDepthNearestVec4, wF, wR, wC), - getW(d2, inputDepthNearestVec4 + 1, wF, wR, wC)); - value += dot(xValues, wValues); - } else if (inputDepthVec4Remainder == 3) { - ${a?`let xValues = vec3( - getX(batch, xF, xR, xC, inputDepthNearestVec4), - getX(batch, xF, xR, xC, inputDepthNearestVec4 + 1), - getX(batch, xF, xR, xC, inputDepthNearestVec4 + 2)); - `:`let xValues = vec3( - getX(batch, inputDepthNearestVec4, xF, xR, xC), - getX(batch, inputDepthNearestVec4 + 1, xF, xR, xC), - getX(batch, inputDepthNearestVec4 + 2, xF, xR, xC)); - `} - let wValues = vec3( - getW(d2, inputDepthNearestVec4, wF, wR, wC), - getW(d2, inputDepthNearestVec4 + 1, wF, wR, wC), - getW(d2, inputDepthNearestVec4 + 2, wF, wR, wC)); - value += dot(xValues, wValues); - } - } - } - } - ${_?"value = value + getBiasByOutputCoords(coords)":""}; - ${D} - result[global_idx] = f32(value); - }`};return{name:"Conv3DNaive",shaderCache:{hint:`${r.cacheKey};${a};${p};${_}`,inputDependencies:f},getRunData:()=>({outputs:[{dims:t,dataType:e[0].dataType}],dispatchGroup:{x:c[0],y:c[1],z:c[2]},programUniforms:u}),getShaderSource:b}}}),Oh,Dh,Kx=Ue(()=>{Mt(),Pt(),Ct(),bn(),Oh=(e,r,t,s)=>{let o=e.length>2,n=o?"value += b[output_channel];":"",a=e[0].dims,i=e[1].dims,l=r.format==="NHWC",c=l?t[3]:t[1],p=c/r.group,d=l&&p>=4?lr(c):1,u=ye.size(t)/d,f=[{type:12,data:u},{type:12,data:r.dilations},{type:12,data:[r.strides[0],r.strides[1]]},{type:12,data:[r.pads[0],r.pads[1]]},{type:12,data:p}];wn(r,f),f.push(...dt(a,[i[0],i[1],i[2],i[3]/d]));let _=o?["rank","rank","rank"]:["rank","rank"];f.push(...dt([t[0],t[1],t[2],t[3]/d]));let b=k=>{let w=nt("output",e[0].dataType,t.length,d),y=Ir(w.type.tensor),$=gn(r,w.type.value,y),T=Ie("x",e[0].dataType,a.length),M=Ie("w",e[1].dataType,i.length,d),x=[T,M];o&&x.push(Ie("b",e[2].dataType,e[2].dims,d));let v=[{name:"output_size",type:"u32"},{name:"dilations",type:"u32",length:r.dilations.length},{name:"strides",type:"u32",length:2},{name:"pads",type:"u32",length:2},{name:"output_channels_per_group",type:"u32"}];Mn(r,v);let C=l?` - for (var wHeight: u32 = 0u; wHeight < uniforms.w_shape[0]; wHeight++) { - let xHeight = xRCCorner.x + wHeight * uniforms.dilations[0]; - - if (xHeight < 0u || xHeight >= uniforms.x_shape[1]) { - continue; - } - - for (var wWidth: u32 = 0u; wWidth < uniforms.w_shape[1]; wWidth++) { - let xWidth = xRCCorner.y + wWidth * uniforms.dilations[1]; - if (xWidth < 0u || xWidth >= uniforms.x_shape[2]) { - continue; - } - - for (var wInChannel: u32 = 0u; wInChannel < uniforms.w_shape[2]; wInChannel++) { - let input_channel = in_channel_offset + wInChannel; - let xVal = ${T.get("batch","xHeight","xWidth","input_channel")}; - let wVal = ${M.get("wHeight","wWidth","wInChannel","output_channel")}; - value += xVal * wVal; - } - } - } - `:` - for (var wInChannel: u32 = 0u; wInChannel < uniforms.w_shape[1]; wInChannel++) { - let input_channel = in_channel_offset + wInChannel; - for (var wHeight: u32 = 0u; wHeight < uniforms.w_shape[2]; wHeight++) { - let xHeight = xRCCorner.x + wHeight * uniforms.dilations[0]; - - if (xHeight < 0u || xHeight >= uniforms.x_shape[2]) { - continue; - } - - for (var wWidth: u32 = 0u; wWidth < uniforms.w_shape[3]; wWidth++) { - let xWidth = xRCCorner.y + wWidth * uniforms.dilations[1]; - if (xWidth < 0u || xWidth >= uniforms.x_shape[3]) { - continue; - } - - let xVal = ${T.get("batch","input_channel","xHeight","xWidth")}; - let wVal = ${M.get("output_channel","wInChannel","wHeight","wWidth")}; - value += xVal * wVal; - } - } - } - `;return` - ${k.registerUniforms(v).declareVariables(...x,w)} - - ${k.mainStart()} - ${k.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} - - let outputIndices = ${w.offsetToIndices("global_idx")}; - let batch: u32 = outputIndices[0]; - let output_channel: u32 = outputIndices[${l?3:1}]; - let xRCCorner: vec2 = vec2(outputIndices[${l?1:2}], outputIndices[${l?2:3}]) * uniforms.strides - uniforms.pads; - let group_id: u32 = output_channel * ${d} / uniforms.output_channels_per_group; - var in_channel_offset = group_id * uniforms.w_shape[${l?2:1}]; - - var value: ${w.type.value} = ${w.type.value}(0); - ${C} - ${n} - ${$} - ${w.setByOffset("global_idx","value")} - }`};return{name:"GroupedConv",shaderCache:{hint:`${r.cacheKey}_${d}`,inputDependencies:_},getRunData:()=>({outputs:[{dims:s?s(t):t,dataType:e[0].dataType}],dispatchGroup:{x:Math.ceil(u/64)},programUniforms:f}),getShaderSource:b}},Dh=(e,r,t,s)=>{let o=e.length>2,n=lr(t[3]),a=lr(t[2]),i=ye.size(t)/n/a,l=[e[0].dims[0],e[0].dims[1],e[0].dims[2],e[0].dims[3]/n],c=[e[1].dims[0],e[1].dims[1],e[1].dims[2],e[1].dims[3]/n],p=[t[0],t[1],t[2],t[3]/n],d=[{type:12,data:i},{type:6,data:[r.strides[0],r.strides[1]]},{type:6,data:[r.pads[0],r.pads[1]]}];wn(r,d),d.push(...dt(l,c,p));let u=(a-1)*r.strides[1]+c[1],f=_=>{let b=nt("output",e[0].dataType,p.length,n),k=Ir(b.type.tensor),w=gn(r,b.type.value,k),y=Ie("x",e[0].dataType,l.length,n),$=Ie("w",e[1].dataType,c.length,n),T=[y,$];o&&T.push(Ie("b",e[2].dataType,e[2].dims,n));let M=o?"value += b[output_channel];":"",x=[{name:"output_size",type:"u32"},{name:"strides",type:"i32",length:2},{name:"pads",type:"i32",length:2}];return Mn(r,x),` - ${_.registerUniforms(x).declareVariables(...T,b)} - ${_.mainStart()} - ${_.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} - let width0 = uniforms.output_shape[3]; - let output_channel = global_idx % width0; - var index1 = global_idx / width0; - let width1 = uniforms.output_shape[2] / ${a}u; - let col = (index1 % width1) * ${a}u; - index1 = index1 / width1; - let row = index1 % uniforms.output_shape[1]; - let batch = index1 / uniforms.output_shape[1]; - - let x_corner = vec2(i32(row), i32(col)) * uniforms.strides - uniforms.pads; - - var x_vals: array<${y.type.value}, ${u}>; - var values: array<${b.type.value}, ${a}>; - let input_channel = output_channel; - // Use constant instead of uniform can give better performance for w's height/width. - for (var w_height: u32 = 0u; w_height < ${c[0]}; w_height++) { - let x_height = x_corner.x + i32(w_height); - if (x_height >= 0 && u32(x_height) < uniforms.x_shape[1]) { - for (var i = 0; i < ${u}; i++) { - let x_width = x_corner.y + i; - if (x_width >= 0 && u32(x_width) < uniforms.x_shape[2]) { - x_vals[i] = ${y.get("batch","u32(x_height)","u32(x_width)","input_channel")}; - } else { - x_vals[i] = ${y.type.value}(0); - } - } - for (var w_width: u32 = 0u; w_width < ${c[1]}; w_width++) { - let w_val = ${$.get("w_height","w_width","0","output_channel")}; - for (var i = 0u; i < ${a}u; i++) { - values[i] = fma(x_vals[i * u32(uniforms.strides[1]) + w_width], w_val, values[i]); - } - } - } - } - - for (var i = 0u; i < ${a}u; i++) { - var value = values[i]; - ${M} - ${w} - ${b.set("batch","row","col + i","output_channel","value")}; - } - }`};return{name:"GroupedConv-Vectorize",shaderCache:{hint:`${r.cacheKey};${n};${a};${u};${c[0]};${c[1]}`,inputDependencies:o?["rank","rank","type"]:["rank","rank"]},getRunData:()=>({outputs:[{dims:s?s(t):t,dataType:e[0].dataType}],dispatchGroup:{x:Math.ceil(i/64)},programUniforms:d}),getShaderSource:f}}}),Lh,_a,zh,fa,kl,Il,Bh,Rh,Al,Hx=Ue(()=>{Pt(),Wx(),Gx(),Cl(),Kx(),bn(),xl(),tn(),Lh=(e,r,t,s,o,n)=>{let a=e[0],i=e.slice(n?1:2,n?3:4),l=i.length,c=r[0],p=r.slice(2).map((u,f)=>u+(u-1)*(t[f]-1)),d=i.map((u,f)=>u+s[f]+s[f+l]).map((u,f)=>Math.floor((u-p[f]+o[f])/o[f]));return d.splice(0,0,a),d.splice(n?3:1,0,c),d},_a=[2,3,1,0],zh=(e,r)=>{if(!e||e.length!==2&&e.length!==3)throw new Error("Conv requires 2 or 3 inputs");if(e[0].dims.length>5)throw new Error("greater than 5D is not supported");if(e[0].dims.length!==e[1].dims.length)throw new Error("filter does not have same dimension as input");let t=e[0].dims[r.format==="NHWC"?e[0].dims.length-1:1],s=e[1].dims[1]*r.group;if(t!==s)throw new Error("FILTER_IN_CHANNEL should be equal to DATA_CHANNEL");if(e.length===3&&(e[2].dims.length!==1||e[1].dims[0]!==e[2].dims[0]))throw new Error("invalid bias");let o=e[0].dims.length-2;if(r.dilations.length!==o)throw new Error(`dilations should be ${o}D`);if(r.strides.length!==o)throw new Error(`strides should be ${o}D`);if(r.pads.length!==o*2)throw new Error(`pads should be ${o*2}D`);if(r.kernelShape.length!==0&&r.kernelShape.length!==e[1].dims.length-2)throw new Error("invalid kernel shape")},fa=(e,r)=>{let t=e.kernelShape.slice();t.length{let r=bl(e),t=e.format,s=["NOTSET","VALID","SAME_UPPER","SAME_LOWER"][e.auto_pad],o=e.dilations,n=e.group,a=e.kernel_shape,i=e.pads,l=e.strides,c=e.w_is_const();return{autoPad:s,format:t,dilations:o,group:n,kernelShape:a,pads:i,strides:l,wIsConst:c,...r,cacheKey:`${e.format};${r.activation};`}},Il=(e,r,t,s)=>{let o=t.format==="NHWC",n=Lh(r[0].dims,r[1].dims,t.dilations,t.pads,t.strides,o);if(t.group!==1){let x=[r[0]];if(o){let v=e.kernelCustomData.wT??e.compute(rs(r[1],_a),{inputs:[1],outputs:[t.wIsConst?-2:-1]})[0];t.wIsConst&&!e.kernelCustomData.wT&&(e.kernelCustomData.wT=v),x.push(v)}else x.push(r[1]);r.length===3&&x.push(r[2]),!e.adapterInfo.isArchitecture("ampere")&&o&&r[1].dims[0]===t.group&&r[1].dims[1]===1&&t.dilations[0]===1&&t.dilations[1]===1?e.compute(Dh(x,t,n,s),{inputs:x}):e.compute(Oh(x,t,n,s),{inputs:x});return}let a=r.length===3,i=r[0].dims[o?1:2],l=r[0].dims[o?2:3],c=r[0].dims[o?3:1],p=r[1].dims[2],d=r[1].dims[3],u=n[o?1:2],f=n[o?2:3],_=n[o?3:1],b=o&&p===i&&d===l&&t.pads[0]===0&&t.pads[1]===0;if(b||p===1&&d===1&&t.dilations[0]===1&&t.dilations[1]===1&&t.strides[0]===1&&t.strides[1]===1&&t.pads[0]===0&&t.pads[1]===0){let x=n[0],v,C,F,D=[];if(o){let j=e.kernelCustomData.wT??e.compute(rs(r[1],_a),{inputs:[1],outputs:[t.wIsConst?-2:-1]})[0];if(t.wIsConst&&!e.kernelCustomData.wT&&(e.kernelCustomData.wT=j),b){let se=i*l*c;v=r[0].reshape([1,x,se]),C=j.reshape([1,se,_]),F=[1,x,_]}else v=r[0].reshape([x,i*l,c]),C=j.reshape([1,c,_]),F=[x,u*f,_];D.push(v),D.push(C)}else v=r[0].reshape([x,c,i*l]),C=r[1].reshape([1,_,c]),F=[x,_,u*f],D.push(C),D.push(v);a&&D.push(r[2]);let K=F[2],U=D[0].dims[D[0].dims.length-1];K<8&&U<8?e.compute(vl(D,t,n,F,o,s),{inputs:D}):e.compute(ha(D,t,n,F,o,s),{inputs:D});return}let k=!0,w=e.kernelCustomData.wT??e.compute(rs(r[1],_a),{inputs:[1],outputs:[t.wIsConst?-2:-1]})[0];t.wIsConst&&!e.kernelCustomData.wT&&(e.kernelCustomData.wT=w);let y=[r[0],w];a&&y.push(r[2]);let $=o?u*f:_,T=o?_:u*f,M=p*d*c;e.compute(Sh(y,t,n,$,T,M,a,k,s),{inputs:y})},Bh=(e,r)=>{let t=r.format==="NHWC",s=[e.inputs[0].reshape(t?[e.inputs[0].dims[0],1,e.inputs[0].dims[1],e.inputs[0].dims[2]]:[e.inputs[0].dims[0],e.inputs[0].dims[1],1,e.inputs[0].dims[2]]),e.inputs[1].reshape([e.inputs[1].dims[0],e.inputs[1].dims[1],1,e.inputs[1].dims[2]])];e.inputs.length===3&&s.push(e.inputs[2]);let o=[0,r.pads[0],0,r.pads[1]],n=[1].concat(r.strides),a=[1].concat(r.dilations),i=[1].concat(r.kernelShape),l=fa({...r,pads:o,strides:n,dilations:a,kernelShape:i},s);Il(e,s,l,c=>t?[c[0],c[2],c[3]]:[c[0],c[1],c[3]])},Rh=(e,r,t)=>{let s=t.format==="NHWC"?"channelsLast":"channelsFirst",o=fa(t,r),n=t.autoPad==="NOTSET"?t.pads:t.autoPad,a=Ah(r[0].dims,r[1].dims,t.strides,t.dilations,n,!1,s);e.compute(Fh(r,o,a.outShape,[a.filterDepth,a.filterHeight,a.filterWidth],[a.padInfo.front,a.padInfo.top,a.padInfo.left],s))},Al=(e,r)=>{if(zh(e.inputs,r),e.inputs[0].dims.length===3)Bh(e,r);else if(e.inputs[0].dims.length===5)Rh(e,e.inputs,r);else{let t=fa(r,e.inputs);Il(e,e.inputs,t)}}}),jh,qx=Ue(()=>{Mt(),Ns(),Pt(),Ct(),jh=(e,r,t)=>{let s=e.length>2,o=r.outputShape,n=r.format==="NHWC",a=r.group,i=e[1].dims,l=i[2]/a,c=i[3],p=n?lr(l):1,d=n&&c===1&&l>=4,u=d?Math.floor(l/4)*4:Math.floor(l/p)*p,f=l-u,_=n?lr(c):1,b=n?c===1?p:_:1,k=ye.size(o)/_,w=[Math.ceil(k/64),1,1];zt("verbose",()=>`[conv2d_backprop_webgpu] dispatch = ${w}`);let y=["rank","rank"],$=[r.strides[0],r.strides[1]],T=[r.kernelShape[n?1:2],r.kernelShape[n?2:3]],M=[r.dilations[0],r.dilations[1]],x=[T[0]+(r.dilations[0]<=1?0:(r.kernelShape[n?1:2]-1)*(r.dilations[0]-1)),T[1]+(r.dilations[1]<=1?0:(r.kernelShape[n?2:3]-1)*(r.dilations[1]-1))],v=[x[0]-1-Math.floor((r.pads[0]+r.pads[2])/2),x[1]-1-Math.floor((r.pads[1]+r.pads[3])/2)],C=[{type:12,data:k},{type:12,data:$},{type:12,data:T},{type:12,data:M},{type:12,data:x},{type:6,data:v},{type:12,data:u},{type:12,data:l},{type:12,data:c},...dt(e[0].dims,e[1].dims)];s&&(C.push(...dt(e[2].dims)),y.push("rank")),C.push(...dt(o));let F=D=>{let K=[{name:"output_size",type:"u32"},{name:"strides",type:"u32",length:$.length},{name:"filter_dims",type:"u32",length:T.length},{name:"dilations",type:"u32",length:T.length},{name:"effective_filter_dims",type:"u32",length:x.length},{name:"pads",type:"i32",length:v.length},{name:"input_channels_per_group_int",type:"u32"},{name:"input_channels_per_group",type:"u32"},{name:"output_channels_per_group",type:"u32"}],U=Ir(e[0].dataType),j=n?1:2,se=n?2:3,q=n?3:1,re=Ie("W",e[1].dataType,e[1].dims.length,b),Z=Ie("Dy",e[0].dataType,e[0].dims.length,p),ae=[Z,re];s&&ae.push(Ie("bias",e[2].dataType,[o[q]].length,_));let _e=nt("result",e[0].dataType,o.length,_),pe=()=>{let B="";if(d)p===4?B+=` - let xValue = ${Z.getByOffset("x_offset")}; - let wValue = ${re.getByOffset("w_offset")}; - dotProd = dotProd + dot(xValue, wValue); - x_offset += 1u; - w_offset += 1u;`:p===2?B+=` - dotProd = dotProd + dot(vec4<${U}>(${Z.getByOffset("x_offset")}, ${Z.getByOffset("x_offset + 1u")}), vec4<${U}>(${re.getByOffset("w_offset")}, ${re.getByOffset("w_offset + 1u")})); - x_offset += 2u; - w_offset += 2u;`:p===1&&(B+=` - dotProd = dotProd + dot(vec4<${U}>(${Z.getByOffset("x_offset")}, ${Z.getByOffset("x_offset + 1u")}, ${Z.getByOffset("x_offset + 2u")}, ${Z.getByOffset("x_offset + 3u")}), vec4<${U}>(${re.getByOffset("w_offset")}, ${re.getByOffset("w_offset + 1u")}, ${re.getByOffset("w_offset + 2u")}, ${re.getByOffset("w_offset + 3u")})); - x_offset += 4u; - w_offset += 4u;`);else if(B+=` - let xValue = ${n?Z.getByOffset(`${Z.indicesToOffset(`${Z.type.indices}(batch, idyR, idyC, inputChannel)`)} / ${p}`):Z.get("batch","inputChannel","idyR","idyC")}; - `,p===1)B+=` - let w_offset = ${re.indicesToOffset(`${re.type.indices}(u32(wRPerm), u32(wCPerm), inputChannel, wOutChannel)`)}; - let wValue = ${re.getByOffset(`w_offset / ${b}`)}; - dotProd = dotProd + xValue * wValue;`;else for(let Q=0;Q{if(f===0)return"";if(!d)throw new Error(`packInputAs4 ${d} is not true.`);let B="";if(p===1){B+="dotProd = dotProd";for(let Q=0;Q(i32(r), i32(c)) - uniforms.pads; - let dyRCorner = dyCorner.x; - let dyCCorner = dyCorner.y; - let groupId = d1 / uniforms.output_channels_per_group; - let wOutChannel = d1 - groupId * uniforms.output_channels_per_group; - // Convolve dy(?, ?, d2) with w(:, :, d1, d2) to compute dx(xR, xC, d1). - // ? = to be determined. : = across all values in that axis. - var dotProd = ${_e.type.value}(0.0); - var wR: u32 = 0; - if (uniforms.dilations.x == 1) { - // Minimum wR >= 0 that satisfies (dyRCorner + wR) % (uniforms.strides.x) == 0 - wR = u32(((dyRCorner + i32(uniforms.strides.x) - 1) / i32(uniforms.strides.x)) * i32(uniforms.strides.x) - dyRCorner); - } - for (; wR < uniforms.effective_filter_dims.x; wR = wR + 1) { - if (wR % uniforms.dilations.x != 0) { - continue; - } - let dyR = (${U}(dyRCorner) + ${U}(wR)) / ${U}(uniforms.strides[0]); - let wRPerm = uniforms.filter_dims.x - 1 - wR / uniforms.dilations.x; - if (dyR < 0.0 || dyR >= ${U}(uniforms.Dy_shape[${j}]) || fract(dyR) > 0.0 || - wRPerm < 0) { - continue; - } - let idyR: u32 = u32(dyR); - var wC: u32 = 0; - if (uniforms.dilations.y == 1) { - // Minimum wC >= 0 that satisfies (dyCCorner + wC) % (uniforms.strides.y) == 0 - wC = u32(((dyCCorner + i32(uniforms.strides.y) - 1) / i32(uniforms.strides.y)) * i32(uniforms.strides.y) - dyCCorner); - } - for (; wC < uniforms.effective_filter_dims.y; wC = wC + 1) { - if (wC % uniforms.dilations.y != 0) { - continue; - } - let dyC = (${U}(dyCCorner) + ${U}(wC)) / ${U}(uniforms.strides.y); - let wCPerm = uniforms.filter_dims.y - 1 - wC / uniforms.dilations.y; - if (dyC < 0.0 || dyC >= ${U}(uniforms.Dy_shape[${se}]) || - fract(dyC) > 0.0 || wCPerm < 0) { - continue; - } - let idyC: u32 = u32(dyC); - var inputChannel = groupId * uniforms.input_channels_per_group; - ${d?` - var x_offset = ${Z.indicesToOffset(`${Z.type.indices}(batch, idyR, idyC, inputChannel)`)} / ${p}; - var w_offset = ${re.indicesToOffset(`${re.type.indices}(wRPerm, wCPerm, inputChannel, wOutChannel)`)} / ${b}; - `:""} - for (var d2: u32 = 0; d2 < uniforms.input_channels_per_group_int; d2 = d2 + ${d?4:p}) { - ${pe()} - inputChannel = inputChannel + ${d?4:p}; - } - ${oe()} - wC = wC + uniforms.strides.y - 1; - } - wR = wR + uniforms.strides[0] - 1; - } - let value = dotProd${s?` + bias[d1 / ${_}]`:""}; - ${_e.setByOffset("global_idx","value")}; - `;return` - ${D.registerUniforms(K).declareVariables(...ae,_e)} - ${D.mainStart()} - ${D.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")}; - ${G}}`};return{name:"ConvTranspose2D",shaderCache:{hint:`${r.cacheKey};${p}${b}${_}${d}${f}`,inputDependencies:y},getRunData:()=>({dispatchGroup:{x:w[0],y:w[1],z:w[2]},outputs:[{dims:t?t(o):o,dataType:e[0].dataType}],programUniforms:C}),getShaderSource:F}}}),Nh,Vh,Uh,Fl,Wh,Gh,Ol,Kh,Hh,Qx=Ue(()=>{qx(),bn(),tn(),Nh=(e,r,t,s,o,n)=>(e-1)*r+t+(s-1)*o+1-n,Vh=(e,r,t,s,o)=>{let n=Math.floor(e/2);r==="SAME_UPPER"?(t[s]=n,t[o]=e-n):r==="SAME_LOWER"&&(t[s]=e-n,t[o]=n)},Uh=(e,r,t,s,o,n,a,i,l,c)=>{let p=e.length-2,d=c.length===0;l.length{let t=e.kernelShape.slice();if(e.kernelShape.length===0||e.kernelShape.reduce((d,u)=>d*u,1)===0){t.length=0;for(let d=2;dd+u,0)===0){let d=r[0].dims.length-2;l=new Array(d).fill(1)}let c=e.strides.slice();if(c.reduce((d,u)=>d+u,0)===0){let d=r[0].dims.length-2;c=new Array(d).fill(1)}Uh(i,t,l,e.autoPad,e.group,o,c,s,a,n);let p=Object.assign({},e);return Object.assign(p,{kernelShape:t,pads:o,outputPadding:a,outputShape:n,dilations:l,strides:c}),p},Wh=e=>{let r=bl(e),t=e.format,s=["NOTSET","VALID","SAME_UPPER","SAME_LOWER"][typeof e.autoPad>"u"?0:e.autoPad],o=e.dilations,n=e.group,a=e.kernelShape,i=e.pads,l=e.strides,c=e.wIsConst(),p=e.outputPadding,d=e.outputShape;return{autoPad:s,format:t,dilations:o,group:n,kernelShape:a,outputPadding:p,outputShape:d,pads:i,strides:l,wIsConst:c,...r,cacheKey:`${e.format};${r.activation};`}},Gh=(e,r)=>{if(!e||e.length!==2&&e.length!==3)throw new Error("Conv requires 2 or 3 inputs");if(e[0].dims.length!==4&&e[0].dims.length!==3)throw new Error("currently only support 2-dimensional conv");if(e[0].dims.length!==e[1].dims.length)throw new Error("filter does not have same dimension as input");let t=e[0].dims[r.format==="NHWC"?e[0].dims.length-1:1],s=e[1].dims[0];if(t!==s)throw new Error("FILTER_IN_CHANNEL should be equal to DATA_CHANNEL");let o=e[1].dims[1]*r.group;if(e.length===3&&(e[2].dims.length!==1||e[2].dims[0]!==o))throw new Error("invalid bias");let n=e[0].dims.length-2;if(r.dilations.reduce((a,i)=>a+i,0)>0&&r.dilations.length!==n)throw new Error(`dilations should be ${n}D`);if(r.strides.reduce((a,i)=>a+i,0)>0&&r.strides.length!==n)throw new Error(`strides should be ${n}D`);if(r.pads.reduce((a,i)=>a+i,0)>0&&r.pads.length!==n*2)throw new Error(`pads should be ${n*2}D`);if(r.outputPadding.length!==n&&r.outputPadding.length!==0)throw new Error(`output_padding should be ${n}D`);if(r.kernelShape.reduce((a,i)=>a+i,0)>0&&r.kernelShape.length!==0&&r.kernelShape.length!==e[1].dims.length-2)throw new Error("invalid kernel shape");if(r.outputShape.length!==0&&r.outputShape.length!==e[0].dims.length-2)throw new Error("invalid output shape")},Ol=(e,r,t,s)=>{let o=e.kernelCustomData.wT??e.compute(rs(r[1],[2,3,0,1]),{inputs:[1],outputs:[t.wIsConst?-2:-1]})[0];t.wIsConst&&!e.kernelCustomData.wT&&(e.kernelCustomData.wT=o);let n=[r[0],o];r.length===3&&n.push(r[2]),e.compute(jh(n,t,s),{inputs:n})},Kh=(e,r)=>{let t=r.format==="NHWC",s=[e.inputs[0].reshape(t?[e.inputs[0].dims[0],1,e.inputs[0].dims[1],e.inputs[0].dims[2]]:[e.inputs[0].dims[0],e.inputs[0].dims[1],1,e.inputs[0].dims[2]]),e.inputs[1].reshape([e.inputs[1].dims[0],e.inputs[1].dims[1],1,e.inputs[1].dims[2]])];e.inputs.length===3&&s.push(e.inputs[2]);let o=r.kernelShape;(o.length===0||o[0]===0)&&(o=[e.inputs[1].dims[2]]);let n=r.dilations;(n.length===0||n[0]===0)&&(n=[1]);let a=r.strides;(a.length===0||a[0]===0)&&(a=[1]);let i=r.pads;i.length===0&&(i=[0,0]),i=[0,i[0],0,i[1]],a=[1].concat(a),n=[1].concat(n),o=[1].concat(o);let l=r.outputPadding;l=[0].concat(l);let c=Fl({...r,pads:i,strides:a,dilations:n,kernelShape:o,outputPadding:l},s);Ol(e,s,c,p=>t?[p[0],p[2],p[3]]:[p[0],p[1],p[3]])},Hh=(e,r)=>{if(Gh(e.inputs,r),e.inputs[0].dims.length===3)Kh(e,r);else{let t=Fl(r,e.inputs);Ol(e,e.inputs,t)}}}),qh,Qh,Xh,Xx=Ue(()=>{Mt(),Pt(),pr(),Ct(),qh=(e,r,t,s)=>{let o=ye.size(r),n=r.length,a=Ie("input",e,n),i=nt("output",e,n),l=t.dataType===6?t.getInt32Array()[0]:Number(t.getBigInt64Array()[0]),c=ye.normalizeAxis(l,n),p=d=>{let u=` i32(${a.indicesGet("inputIndices","uniforms.axis")}) `,f=ct("uniforms.input_shape","uniforms.axis",n),_=s.reverse?u+(s.exclusive?" + 1":""):"0",b=s.reverse?f:u+(s.exclusive?"":" + 1");return` - ${d.registerUniform("outputSize","u32").registerUniform("axis","u32").declareVariables(a,i)} - ${d.mainStart()} - ${d.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.outputSize")} - var inputIndices = ${i.offsetToIndices("global_idx")}; - var sum = ${i.type.value}(0); - let first : i32 = ${_}; - let last : i32 = ${b}; - for (var i : i32 = first; i < last; i++) { - ${a.indicesSet("inputIndices","uniforms.axis","u32(i)")}; - sum = sum + ${a.getByIndices("inputIndices")}; - } - ${i.setByOffset("global_idx","sum")}; - }`};return{name:"CumSum",shaderCache:{hint:s.cacheKey,inputDependencies:["rank"]},getRunData:()=>({outputs:[{dims:r,dataType:e}],dispatchGroup:{x:Math.ceil(o/64)},programUniforms:[{type:12,data:o},{type:12,data:c},...dt(r,r)]}),getShaderSource:p}},Qh=(e,r)=>{let t=e.inputs[0].dims,s=e.inputs[0].dataType,o=e.inputs[1];e.compute(qh(s,t,o,r),{inputs:[0]})},Xh=e=>{let r=e.exclusive===1,t=e.reverse===1;return Kt({exclusive:r,reverse:t})}}),Jh,Yh,Zh,e_,t_,Jx=Ue(()=>{Mt(),Pt(),pr(),Ct(),Jh=e=>{if(!e||e.length!==1)throw new Error("DepthToSpace requires 1 input.");if(e[0].dims.length!==4)throw new Error("DepthToSpace requires 4D input.")},Yh=(e,r,t,s)=>{let o=[];o.push(`fn perm(i: ${s.type.indices}) -> ${t.type.indices} { - var a: ${t.type.indices};`);for(let n=0;n{let t,s,o,n,a,i,l=r.format==="NHWC",c=r.blocksize,p=r.mode==="DCR";l?([t,s,o,n]=e.dims,a=p?[t,s,o,c,c,n/c**2]:[t,s,o,n/c**2,c,c],i=p?[0,1,3,2,4,5]:[0,1,4,2,5,3]):([t,s,o,n]=[e.dims[0],e.dims[2],e.dims[3],e.dims[1]],a=p?[t,c,c,n/c**2,s,o]:[t,n/c**2,c,c,s,o],i=p?[0,3,4,1,5,2]:[0,1,4,2,5,3]);let d=e.reshape(a),u=d.dims.length,f=e.dataType,_=Ie("a",f,u),b=nt("output",f,u),k=w=>` - ${w.registerUniform("output_size","u32").declareVariables(_,b)} - - ${Yh(i,u,_,b)} - - ${w.mainStart()} - ${w.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} - - let indices = ${b.offsetToIndices("global_idx")}; - let aIndices = perm(indices); - - ${b.setByOffset("global_idx",_.getByIndices("aIndices"))} - }`;return{name:"DepthToSpace",shaderCache:{hint:`${e.dims};${r.blocksize};${r.mode}`,inputDependencies:["rank"]},getRunData:w=>{let y=l?[t,s*c,o*c,n/c**2]:[t,n/c**2,s*c,o*c],$=ye.size(y),T=d.dims,M=ye.sortBasedOnPerm(T,i);return{outputs:[{dims:y,dataType:w[0].dataType}],dispatchGroup:{x:Math.ceil($/64)},programUniforms:[{type:12,data:$},...dt(T,M)]}},getShaderSource:k}},e_=(e,r)=>{Jh(e.inputs),e.compute(Zh(e.inputs[0],r))},t_=e=>Kt({blocksize:e.blocksize,mode:e.mode,format:e.format})}),ga,vo,Dl,r_,s_,n_,o_,Ll,a_,i_,l_,Yx=Ue(()=>{Mt(),Pt(),pr(),Ct(),ga="[a-zA-Z]|\\.\\.\\.",vo="("+ga+")+",Dl="^"+vo+"$",r_="("+vo+",)*"+vo,s_="^"+r_+"$",n_=class{constructor(e=-1){this.symbolToIndices=new Map,this.inputIndex=e}addSymbol(e,r){let t=this.symbolToIndices.get(e);t===void 0?t=[r]:t.push(r),this.symbolToIndices.set(e,t)}},o_=class{constructor(e,r){var o;this.equation=r,this.hasEllipsis=!1,this.symbolToInfo=new Map,this.lhs=new Array,this.outputDims=[];let[t,s]=r.includes("->")?r.split("->",2):[r,""];if(!t.match(RegExp(s_)))throw new Error("Invalid LHS term");if(t.split(",").forEach((n,a)=>{let i=e[a].dims.slice();if(!n.match(RegExp(Dl)))throw new Error("Invalid LHS term");let l=this.processTerm(n,!0,i,a);this.lhs.push(l)}),s==="")s+=[...this.symbolToInfo.entries()].filter(([n,a])=>a.count===1||n==="...").map(([n])=>n).join("");else if(!s.match(RegExp(vo)))throw new Error("Invalid RHS");(o=s.match(RegExp(ga,"g")))==null||o.forEach(n=>{if(n==="...")this.outputDims=this.outputDims.concat(this.ellipsisDims);else{let a=this.symbolToInfo.get(n);if(a===void 0)throw new Error("Invalid RHS symbol");this.outputDims.push(a.dimValue)}}),this.rhs=this.processTerm(s,!1,this.outputDims)}addSymbol(e,r,t){let s=this.symbolToInfo.get(e);if(s!==void 0){if(s.dimValue!==r&&s.count!==1)throw new Error("Dimension mismatch");s.count++,s.inputIndices.push(t)}else s={count:1,dimValue:r,inputIndices:[t]};this.symbolToInfo.set(e,s)}processTerm(e,r,t,s=-1){let o=t.length,n=!1,a=[],i=0;if(!e.match(RegExp(Dl))&&!r&&e!=="")throw new Error("Invalid LHS term");let l=e.match(RegExp(ga,"g")),c=new n_(s);return l==null||l.forEach((p,d)=>{if(p==="..."){if(n)throw new Error("Only one ellipsis is allowed per input term");n=!0;let u=o-l.length+1;if(u<0)throw new Error("Ellipsis out of bounds");if(a=t.slice(i,i+u),this.hasEllipsis){if(this.ellipsisDims.length!==a.length||this.ellipsisDims.toString()!==a.toString())throw new Error("Ellipsis dimensions mismatch")}else if(r)this.hasEllipsis=!0,this.ellipsisDims=a;else throw new Error("Ellipsis must be specified in the LHS");for(let f=0;fe+"_max",a_=(e,r,t,s)=>{let o=e.map(c=>c.length).map((c,p)=>Ie(`input${p}`,r,c)),n=ye.size(s),a=nt("output",r,s.length),i=[...t.symbolToInfo.keys()].filter(c=>!t.rhs.symbolToIndices.has(c)),l=c=>{let p=[],d="var prod = 1.0;",u="var sum = 0.0;",f="sum += prod;",_=[],b=[],k=[],w=[],y=t.symbolToInfo.size===t.rhs.symbolToIndices.size;t.symbolToInfo.forEach((T,M)=>{var x;if(t.rhs.symbolToIndices.has(M)){let v=(x=t.rhs.symbolToIndices.get(M))==null?void 0:x[0];v!==void 0&&t.lhs.forEach((C,F)=>{if(T.inputIndices.includes(F)){let D=C.symbolToIndices.get(M);if(D===void 0)throw new Error("Invalid symbol error");D.forEach(K=>{p.push(`${o[F].indicesSet(`input${F}Indices`,K,a.indicesGet("outputIndices",v))}`)})}})}else t.lhs.forEach((v,C)=>{if(T.inputIndices.includes(C)){let F=v.symbolToIndices.get(M);if(F===void 0)throw new Error("Invalid symbol error");F.forEach(D=>{_.push(`${o[C].indicesSet(`input${C}Indices`,D,`${M}`)}`)}),w.push(`prod *= ${o[C].getByIndices(`input${C}Indices`)};`)}}),b.push(`for(var ${M}: u32 = 0; ${M} < uniforms.${Ll(M)}; ${M}++) {`),k.push("}")});let $=y?[...p,`let sum = ${o.map((T,M)=>T.getByIndices(`input${M}Indices`)).join(" * ")};`]:[...p,u,...b,..._,d,...w,f,...k];return` - ${c.registerUniforms(i.map(T=>({name:`${Ll(T)}`,type:"u32"}))).registerUniform("outputSize","u32").declareVariables(...o,a)} - - ${c.mainStart()} - ${c.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.outputSize")} - var outputIndices = ${a.offsetToIndices("global_idx")}; - ${o.map((T,M)=>`var input${M}Indices: ${o[M].type.indices};`).join(` -`)} - ${$.join(` -`)}; - ${a.setByOffset("global_idx","sum")}; - }`};return{name:"Einsum",shaderCache:{hint:t.equation,inputDependencies:e.map(()=>"rank")},getRunData:()=>{let c=i.filter(d=>t.symbolToInfo.has(d)).map(d=>{var u;return{type:12,data:((u=t.symbolToInfo.get(d))==null?void 0:u.dimValue)||0}});c.push({type:12,data:n});let p=e.map((d,u)=>[...dt(d)]).reduce((d,u)=>d.concat(u),c);return p.push(...dt(s)),{outputs:[{dims:s,dataType:r}],dispatchGroup:{x:Math.ceil(n/64)},programUniforms:p}},getShaderSource:l}},i_=(e,r)=>{let t=new o_(e.inputs,r.equation),s=t.outputDims,o=e.inputs.map((n,a)=>n.dims);e.compute(a_(o,e.inputs[0].dataType,t,s))},l_=e=>{let r=e.equation.replace(/\s+/g,"");return Kt({equation:r})}}),c_,zl,u_,d_,p_,Zx=Ue(()=>{Mt(),Pt(),Ct(),c_=e=>{if(!e||e.length!==2)throw new Error("Expand requires 2 input.");let r=e[0].dims,t=Array.from(e[1].getBigInt64Array(),Number),s=t.length{let t=e.length-r.length,s=[];for(let o=0;oe.length>r.length?zl(e,r):zl(r,e),d_=e=>{let r=e[0].dims,t=Array.from(e[1].getBigInt64Array(),Number),s=u_(r,t),o=e[0].dataType,n=o===9||ye.size(r)===1,a=o===9||r.length>0&&r[r.length-1]%4===0?4:1,i=n||s.length>0&&s[s.length-1]%4===0?4:1,l=Math.ceil(ye.size(s)/i),c=d=>{let u=Ie("input",o,r.length,a),f=nt("output",o,s.length,i),_;if(o===9){let b=(k,w,y="")=>` - let outputIndices${w} = ${f.offsetToIndices(`outputOffset + ${w}u`)}; - let offset${w} = ${u.broadcastedIndicesToOffset(`outputIndices${w}`,f)}; - let index${w} = offset${w} / 4u; - let component${w} = offset${w} % 4u; - ${k}[${w}] = ${y}(${u.getByOffset(`index${w}`)}[component${w}]); - `;_=` - let outputOffset = global_idx * ${i}; - var data = vec4(0); - ${b("data",0,"u32")} - ${b("data",1,"u32")} - ${b("data",2,"u32")} - ${b("data",3,"u32")} - ${f.setByOffset("global_idx","data")} - }`}else _=` - let outputIndices = ${f.offsetToIndices(`global_idx * ${i}`)}; - let inputOffset = ${u.broadcastedIndicesToOffset("outputIndices",f)}; - let data = ${f.type.value}(${u.getByOffset(`inputOffset / ${a}`)}); - ${f.setByOffset("global_idx","data")} - }`;return` - ${d.registerUniform("vec_size","u32").declareVariables(u,f)} - ${d.mainStart()} - ${d.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.vec_size")} - ${_}`},p=[{type:12,data:l},...dt(r,s)];return{name:"Expand",shaderCache:{hint:`${s.length};${a}${i}`,inputDependencies:["rank"]},getShaderSource:c,getRunData:()=>({outputs:[{dims:s,dataType:e[0].dataType}],dispatchGroup:{x:Math.ceil(l/64)},programUniforms:p})}},p_=e=>{c_(e.inputs),e.compute(d_(e.inputs),{inputs:[0]})}}),m_,h_,eT=Ue(()=>{Mt(),Pt(),Ct(),Ml(),m_=e=>{let r=e[0].dataType,t=ye.size(e[0].dims),s=ye.size(e[1].dims),o=s%4===0,n=a=>{let i=Ie("x",r,[1],4),l=Ie("bias",r,[1],4),c=nt("y",r,[1],4),p=[{name:"output_vec_size",type:"u32"},{name:"bias_size",type:"u32"}],d=f=>` - let bias${f}_offset: u32 = (global_idx * 4 + ${f}) % uniforms.bias_size; - let bias${f} = ${l.getByOffset(`bias${f}_offset / 4`)}[bias${f}_offset % 4];`,u=o?` - let bias = ${l.getByOffset("global_idx % (uniforms.bias_size / 4)")};`:`${d(0)}${d(1)}${d(2)}${d(3)} - let bias = ${i.type.value}(bias0, bias1, bias2, bias3);`;return`${a.registerUniforms(p).declareVariables(i,l,c)} - - ${gl(Vr(r))} - - ${a.mainStart(Kn)} - ${a.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_vec_size")} - - let x = ${i.getByOffset("global_idx")}; - ${u} - let x_in = x + bias; - ${c.setByOffset("global_idx",wl("x_in"))} - }`};return{name:"FastGeluWithBias",shaderCache:{hint:`${o}`,inputDependencies:["type","type"]},getShaderSource:n,getRunData:a=>({outputs:[{dims:a[0].dims,dataType:a[0].dataType}],programUniforms:[{type:12,data:Math.ceil(t/4)},{type:12,data:s}],dispatchGroup:{x:Math.ceil(t/Kn/4)}})}},h_=e=>{e.inputs.length<2||ye.size(e.inputs[1].dims)===0?qm(e):e.compute(m_(e.inputs))}}),__,f_,g_,w_,tT=Ue(()=>{Mt(),Pt(),pr(),Ct(),__=e=>{if(!e||e.length!==2)throw new Error("Gather requires 2 inputs.")},f_=(e,r)=>{let t=e[0].dims,s=e[1].dims,o=t.length,n=ye.normalizeAxis(r.axis,o),a=t.slice(0);a.splice(n,1,...s);let i=t[n],l=e[0].dataType===9?4:1,c=Math.ceil(ye.size(a)/l),p=[{type:12,data:c},{type:6,data:i},{type:12,data:n},...dt(e[0].dims,e[1].dims,a)],d=u=>{let f=Ie("data",e[0].dataType,e[0].dims.length,l),_=Ie("inputIndices",e[1].dataType,e[1].dims.length),b=nt("output",e[0].dataType,a.length,l),k=y=>{let $=s.length,T=`var indicesIndices${y} = ${_.type.indices}(0);`;for(let M=0;M<$;M++)T+=`${$>1?`indicesIndices${y}[${M}]`:`indicesIndices${y}`} = ${a.length>1?`outputIndices${y}[uniforms.axis + ${M}]`:`outputIndices${y}`};`;T+=` - var idx${y} = ${_.getByIndices(`indicesIndices${y}`)}; - if (idx${y} < 0) { - idx${y} = idx${y} + uniforms.axisDimLimit; - } - var dataIndices${y} : ${f.type.indices}; - `;for(let M=0,x=0;M1?`dataIndices${y}[${M}]`:`dataIndices${y}`} = u32(idx${y});`,x+=$):(T+=`${o>1?`dataIndices${y}[${M}]`:`dataIndices${y}`} = ${a.length>1?`outputIndices${y}[${x}]`:`outputIndices${y}`};`,x++);return T},w;if(e[0].dataType===9){let y=($,T,M="")=>` - let outputIndices${T} = ${b.offsetToIndices(`outputOffset + ${T}u`)}; - ${k(T)}; - let offset${T} = ${f.indicesToOffset(`dataIndices${T}`)}; - let index${T} = offset${T} / 4u; - let component${T} = offset${T} % 4u; - ${$}[${T}] = ${M}(${f.getByOffset(`index${T}`)}[component${T}]); - `;w=` - let outputOffset = global_idx * ${l}; - var value = vec4(0); - ${y("value",0,"u32")} - ${y("value",1,"u32")} - ${y("value",2,"u32")} - ${y("value",3,"u32")} - ${b.setByOffset("global_idx","value")} - `}else w=` - let outputIndices = ${b.offsetToIndices("global_idx")}; - ${k("")}; - let value = ${f.getByIndices("dataIndices")}; - ${b.setByOffset("global_idx","value")}; - `;return` - ${u.registerUniform("outputSize","u32").registerUniform("axisDimLimit","i32").registerUniform("axis","u32").declareVariables(f,_,b)} - ${u.mainStart()} - ${u.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.outputSize")} - ${w} - }`};return{name:"Gather",shaderCache:{hint:r.cacheKey,inputDependencies:["rank","rank"]},getRunData:()=>({outputs:[{dims:a,dataType:e[0].dataType}],dispatchGroup:{x:Math.ceil(c/64)},programUniforms:p}),getShaderSource:d}},g_=e=>Kt({axis:e.axis}),w_=(e,r)=>{let t=e.inputs;__(t),e.compute(f_(e.inputs,r))}}),M_,b_,y_,rT=Ue(()=>{Mt(),Pt(),Ct(),M_=(e,r,t,s,o,n,a,i,l)=>{let c=[{type:12,data:n},{type:12,data:s},{type:12,data:o},{type:12,data:t},{type:12,data:a},{type:12,data:i},{type:12,data:l}],p=[n];c.push(...dt(r.dims,p));let d=u=>{let f=Ie("indices_data",r.dataType,r.dims.length),_=nt("input_slice_offsets_data",12,1,1),b=[f,_],k=[{name:"output_size",type:"u32"},{name:"batch_dims",type:"u32"},{name:"input_dims",type:"u32",length:o.length},{name:"sizes_from_slice_dims_data",type:"u32",length:t.length},{name:"num_slices_per_batch",type:"u32"},{name:"input_batch_stride",type:"u32"},{name:"num_slice_dims",type:"u32"}];return` - ${u.registerUniforms(k).declareVariables(...b)} - ${u.mainStart()} - ${u.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} - let batch_idx = global_idx / uniforms.num_slices_per_batch; - let base_offset = batch_idx * uniforms.input_batch_stride; - - let slice_indices_base_offset = global_idx * uniforms.num_slice_dims; - var relative_slice_offset = 0; - for (var dim_idx = 0u; dim_idx < uniforms.num_slice_dims; dim_idx ++) { - var index = i32(indices_data[dim_idx + slice_indices_base_offset].x); - let input_dim_idx = uniforms.batch_dims + dim_idx; - if (index < 0) { - ${o.length===1?"index += i32(uniforms.input_dims);":"index += i32(uniforms.input_dims[input_dim_idx]);"} - } - ${t.length===1?"relative_slice_offset += index * i32(uniforms.sizes_from_slice_dims_data);":"relative_slice_offset += index * i32(uniforms.sizes_from_slice_dims_data[dim_idx]);"} - } - - input_slice_offsets_data[global_idx] = base_offset + u32(relative_slice_offset); - }`};return e.compute({name:"computeSliceOffsets",shaderCache:{hint:`${o.length}_${t.length}`,inputDependencies:["rank"]},getRunData:()=>({outputs:[{dims:p,dataType:e.inputs[1].dataType}],dispatchGroup:{x:Math.ceil(n/64)},programUniforms:c}),getShaderSource:d},{inputs:[r],outputs:[-1]})[0]},b_=(e,r)=>{let t=e.inputs,s=t[0].dims,o=t[0].dataType,n=t[1].dims,a=n[n.length-1],i=ye.sizeToDimension(n,n.length-1),l=ye.sizeFromDimension(s,r.batchDims+a),c=ye.sizeToDimension(s,r.batchDims),p=ye.sizeFromDimension(s,r.batchDims),d=i/c,u=new Array(a),f=l;for(let T=0;Ts.length)throw new Error("last dimension of indices must not be larger than rank of input tensor");let k=n.slice(0,-1).concat(s.slice(b)),w=ye.size(k),y=[{type:12,data:w},{type:12,data:l},...dt(t[0].dims,_.dims,k)],$=T=>{let M=Ie("data",t[0].dataType,t[0].dims.length),x=Ie("slice_offsets",12,_.dims.length),v=nt("output",t[0].dataType,k.length);return` - ${T.registerUniform("output_size","u32").registerUniform("slice_size","u32").declareVariables(M,x,v)} - ${T.mainStart()} - ${T.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} - let slice_offset = slice_offsets[global_idx / uniforms.slice_size]; - output[global_idx] = data[u32(slice_offset) + global_idx % uniforms.slice_size]; - }`};e.compute({name:"GatherND",shaderCache:{hint:r.cacheKey,inputDependencies:["rank","rank"]},getRunData:()=>({outputs:[{dims:k,dataType:o}],dispatchGroup:{x:Math.ceil(w/64)},programUniforms:y}),getShaderSource:$},{inputs:[t[0],_]})},y_=e=>({batchDims:e.batch_dims,cacheKey:""})}),v_,x_,T_,E_,sT=Ue(()=>{Mt(),Pt(),pr(),Ct(),v_=(e,r)=>{if(e.length<3||e.length>4)throw new Error("GatherBlockQuantized requires 3 or 4 inputs.");let t=ye.normalizeAxis(r.quantizeAxis,e[0].dims.length),s=r.blockSize,o=e[0],n=e[2],a=e.length===4?e[3]:void 0;if(n.dims.length!==o.dims.length||!o.dims.map((i,l)=>l===t?Math.ceil(i/s)===n.dims[l]:i===n.dims[l]).reduce((i,l)=>i&&l,!0))throw new Error("Scales must have the same rank as the input tensor and the dims should match except on gatherAxis.");if(a){if(a.dataType!==o.dataType)throw new Error("Zero point must have the same data type as the input tensor.");if(a.dims.length!==n.dims.length||!a.dims.map((i,l)=>i===n.dims[l]).reduce((i,l)=>i&&l,!0))throw new Error("Zero point must have the same rank as the input tensor and the dims should match except on quantizeAxis.")}},x_=(e,r)=>{let t=e[0].dims,s=e[1].dims,o=t.length,n=ye.normalizeAxis(r.gatherAxis,o),a=ye.normalizeAxis(r.quantizeAxis,o),i=t.slice(0);i.splice(n,1,...s);let l=ye.size(i),c=e[2].dataType,p=e[0].dataType===22,d=[{type:12,data:l},{type:12,data:a},{type:12,data:n},{type:12,data:r.blockSize},...dt(...e.map((f,_)=>f.dims),i)],u=f=>{let _=Ie("data",e[0].dataType,e[0].dims.length),b=Ie("inputIndices",e[1].dataType,e[1].dims.length),k=Ie("scales",e[2].dataType,e[2].dims.length),w=e.length>3?Ie("zeroPoint",e[3].dataType,e[3].dims.length):void 0,y=nt("output",c,i.length),$=[_,b,k];w&&$.push(w);let T=[{name:"output_size",type:"u32"},{name:"quantize_axis",type:"u32"},{name:"gather_axis",type:"u32"},{name:"block_size",type:"u32"}];return` - ${f.registerUniforms(T).declareVariables(...$,y)} - ${f.mainStart()} - let output_indices = ${y.offsetToIndices("global_idx")}; - var indices_indices = ${b.type.indices}(0); - ${s.length>1?` - for (var i: u32 = 0; i < ${s.length}; i++) { - let index = ${y.indicesGet("output_indices","uniforms.gather_axis + i")}; - ${b.indicesSet("indices_indices","i","index")}; - }`:`indices_indices = ${y.indicesGet("output_indices","uniforms.gather_axis")};`}; - var data_indices = ${_.type.indices}(0); - for (var i: u32 = 0; i < uniforms.gather_axis; i++) { - let index = ${y.indicesGet("output_indices","i")}; - ${_.indicesSet("data_indices","i","index")}; - } - var index_from_indices = ${b.getByIndices("indices_indices")}; - if (index_from_indices < 0) { - index_from_indices += ${t[n]}; - } - ${_.indicesSet("data_indices","uniforms.gather_axis","u32(index_from_indices)")}; - for (var i = uniforms.gather_axis + 1; i < ${i.length}; i++) { - let index = ${y.indicesGet("output_indices",`i + ${s.length} - 1`)}; - ${_.indicesSet("data_indices","i","index")}; - } - let data_offset = ${_.indicesToOffset("data_indices")}; - let data_index = data_offset % 8; - // Convert 4-bit packed data to 8-bit packed data. - let packed_4bit_quantized_data = ${_.getByOffset("data_offset / 8")}; - let packed_8bit_quantized_data = (packed_4bit_quantized_data >> (4 * (data_index % 2))) & 0x0f0f0f0f; - let quantized_data_vec = ${p?"unpack4xI8":"unpack4xU8"}(u32(packed_8bit_quantized_data)); - let quantized_data = quantized_data_vec[data_index / 2]; - var scale_indices = data_indices; - let quantize_axis_index = ${k.indicesGet("data_indices","uniforms.quantize_axis")} / uniforms.block_size; - ${k.indicesSet("scale_indices","uniforms.quantize_axis","quantize_axis_index")}; - var scale = ${k.getByIndices("scale_indices")}; - ${w?` - let zero_point_indices = scale_indices; - let zero_point_offset = ${w.indicesToOffset("zero_point_indices")}; - let zero_point_index = zero_point_offset % 8; - let packed_4bit_zero_points = ${w.getByOffset("zero_point_offset / 8")}; - let packed_8bit_zero_points = (packed_4bit_zero_points >> (4 * (zero_point_index % 2))) & 0x0f0f0f0f; - let zero_point_vec = ${p?"unpack4xI8":"unpack4xU8"}(u32(packed_8bit_zero_points)); - let zero_point = zero_point_vec[zero_point_index / 2];`:"var zero_point = 0"}; - let dequantized_data = ${Vr(c)}(quantized_data - zero_point) * scale; - ${y.setByOffset("global_idx","dequantized_data")}; - }`};return{name:"GatherBlockQuantized",shaderCache:{hint:`${r.cacheKey};${e.filter((f,_)=>_!==1).map(f=>f.dims.join("_")).join(";")}`,inputDependencies:Array.from({length:e.length},(f,_)=>"rank")},getRunData:()=>({outputs:[{dims:i,dataType:c}],dispatchGroup:{x:Math.ceil(l/64)},programUniforms:d}),getShaderSource:u}},T_=(e,r)=>{let t=e.inputs;v_(t,r),e.compute(x_(e.inputs,r))},E_=e=>Kt({blockSize:e.blockSize,gatherAxis:e.gatherAxis,quantizeAxis:e.quantizeAxis})}),P_,C_,S_,$_,nT=Ue(()=>{Mt(),Pt(),pr(),Ct(),P_=e=>{if(!e||e.length!==2)throw new Error("GatherElements requires 2 inputs.");if(e[0].dims.length<1)throw new Error("GatherElements requires that the data input be rank >= 1.");if(e[0].dims.length!==e[1].dims.length)throw new Error(`GatherElements requires that the data input and - indices input tensors be of same rank.`)},C_=(e,r)=>{let t=e[0].dims,s=e[0].dataType,o=t.length,n=e[1].dims,a=e[1].dataType,i=ye.normalizeAxis(r.axis,o),l=t[i],c=n.slice(0),p=ye.size(c),d=Ie("input",s,o),u=Ie("indicesInput",a,n.length),f=nt("output",s,c.length),_=[{type:12,data:p},{type:6,data:l},{type:12,data:i}];return _.push(...dt(t,n,c)),{name:"GatherElements",shaderCache:{inputDependencies:["rank","rank"]},getRunData:()=>({outputs:[{dims:c,dataType:e[0].dataType}],dispatchGroup:{x:Math.ceil(p/64)},programUniforms:_}),getShaderSource:b=>` - ${b.registerUniform("outputSize","u32").registerUniform("axisDimLimit","i32").registerUniform("axis","u32").declareVariables(d,u,f)} - ${b.mainStart()} - ${b.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.outputSize")} - - let outputIndices = ${f.offsetToIndices("global_idx")}; - - var idx = ${u.getByOffset("global_idx")}; - if (idx < 0) { - idx = idx + uniforms.axisDimLimit; - } - var inputIndices = ${d.type.indices}(outputIndices); - ${d.indicesSet("inputIndices","uniforms.axis","u32(idx)")}; - let value = ${d.getByIndices("inputIndices")}; - - ${f.setByOffset("global_idx","value")}; - }`}},S_=e=>Kt({axis:e.axis}),$_=(e,r)=>{let t=e.inputs;P_(t),e.compute(C_(e.inputs,r))}}),k_,I_,A_,F_,oT=Ue(()=>{Mt(),Pt(),Ct(),k_=e=>{if(!e)throw new Error("Input is missing");if(e.length<2||e.length>3)throw new Error("Invaid input number.");if(e.length===3&&e[2].dims.length>2)throw new Error("Invalid input shape of C");if(e[0].dataType!==e[1].dataType||e.length===3&&e[0].dataType!==e[2].dataType)throw new Error("Input types are mismatched")},I_=(e,r)=>{let t=e[0].dims.slice(),s=e[1].dims.slice(),[o,n,a]=Vd.getShapeOfGemmResult(t,r.transA,s,r.transB,e.length===3?e[2].dims:void 0),i=[o,n];if(!i)throw new Error("Can't use gemm on the given tensors");let l=16,c=Math.ceil(n/l),p=Math.ceil(o/l),d=!0,u=ye.size(i),f=[{type:12,data:d?c:u},{type:12,data:o},{type:12,data:n},{type:12,data:a},{type:1,data:r.alpha},{type:1,data:r.beta}],_=["type","type"];e.length===3&&(f.push(...dt(e[2].dims)),_.push("rank")),f.push(...dt(i));let b=w=>{let y="";r.transA&&r.transB?y="value += a[k * uniforms.M + m] * b[n * uniforms.K + k];":r.transA&&!r.transB?y="value += a[k * uniforms.M + m] * b[k * uniforms.N + n];":!r.transA&&r.transB?y="value += a[m * uniforms.K + k] * b[n * uniforms.K + k];":!r.transA&&!r.transB&&(y="value += a[m * uniforms.K + k] * b[k * uniforms.N + n];");let $=r.alpha===1?"":"value *= uniforms.alpha;",T=Ie("a",e[0].dataType,e[0].dims),M=Ie("b",e[1].dataType,e[1].dims),x=T.type.value,v=null,C=[T,M];e.length===3&&(v=Ie("c",e[2].dataType,e[2].dims.length),C.push(v));let F=nt("output",e[0].dataType,i.length);C.push(F);let D=[{name:"output_size",type:"u32"},{name:"M",type:"u32"},{name:"N",type:"u32"},{name:"K",type:"u32"},{name:"alpha",type:"f32"},{name:"beta",type:"f32"}];return` - ${w.registerUniforms(D).declareVariables(...C)} - - ${w.mainStart()} - ${w.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} - - let m = global_idx / uniforms.N; - let n = global_idx % uniforms.N; - - var value = ${x}(0); - for (var k: u32 = 0u; k < uniforms.K; k++) { - ${y} - } - - ${$} - ${v!=null?`let cOffset = ${v.broadcastedIndicesToOffset("vec2(m, n)",F)}; value += ${x}(uniforms.beta) * ${v.getByOffset("cOffset")};`:""} - output[global_idx] = value; - }`},k=w=>{let y=Ie("a",e[0].dataType,e[0].dims),$=Ie("b",e[1].dataType,e[1].dims),T=null,M=[y,$];e.length===3&&(T=Ie("c",e[2].dataType,e[2].dims.length),M.push(T));let x=nt("output",e[0].dataType,i.length);M.push(x);let v=[{name:"num_tile_n",type:"u32"},{name:"M",type:"u32"},{name:"N",type:"u32"},{name:"K",type:"u32"},{name:"alpha",type:"f32"},{name:"beta",type:"f32"}],C="",F="";r.transA&&r.transB?(F=` - var col = tile_row_start + local_id.x; - var row = k_start + local_id.y; - if (col < uniforms.M && row < uniforms.K) { - tile_a[local_id.y][local_id.x] = a[row * uniforms.M + col]; - } else { - tile_a[local_id.y][local_id.x] = ${y.type.value}(0); - } - - col = k_start + local_id.x; - row = tile_col_start + local_id.y; - if (col < uniforms.K && row < uniforms.N) { - tile_b[local_id.y][local_id.x] = b[row * uniforms.K + col]; - } else { - tile_b[local_id.y][local_id.x] = ${$.type.value}(0); - } - `,C="value += tile_a[k][local_id.y] * tile_b[local_id.x][k];"):r.transA&&!r.transB?(F=` - var col = tile_row_start + local_id.x; - var row = k_start + local_id.y; - if (col < uniforms.M && row < uniforms.K) { - tile_a[local_id.y][local_id.x] = a[row * uniforms.M + col]; - } else { - tile_a[local_id.y][local_id.x] = ${y.type.value}(0); - } - - col = tile_col_start + local_id.x; - row = k_start + local_id.y; - if (col < uniforms.N && row < uniforms.K) { - tile_b[local_id.y][local_id.x] = b[row * uniforms.N + col]; - } else { - tile_b[local_id.y][local_id.x] = ${$.type.value}(0); - } - `,C="value += tile_a[k][local_id.y] * tile_b[k][local_id.x];"):!r.transA&&r.transB?(F=` - var col = k_start + local_id.x; - var row = tile_row_start + local_id.y; - if (col < uniforms.K && row < uniforms.M) { - tile_a[local_id.y][local_id.x] = a[row * uniforms.K + col]; - } else { - tile_a[local_id.y][local_id.x] = ${y.type.value}(0); - } - - col = k_start + local_id.x; - row = tile_col_start + local_id.y; - if (col < uniforms.K && row < uniforms.N) { - tile_b[local_id.y][local_id.x] = b[row * uniforms.K + col]; - } else { - tile_b[local_id.y][local_id.x] = ${$.type.value}(0); - } - `,C="value += tile_a[local_id.y][k] * tile_b[local_id.x][k];"):!r.transA&&!r.transB&&(F=` - var col = k_start + local_id.x; - var row = tile_row_start + local_id.y; - if (col < uniforms.K && row < uniforms.M) { - tile_a[local_id.y][local_id.x] = a[row * uniforms.K + col]; - } else { - tile_a[local_id.y][local_id.x] = ${y.type.value}(0); - } - - col = tile_col_start + local_id.x; - row = k_start + local_id.y; - if (col < uniforms.N && row < uniforms.K) { - tile_b[local_id.y][local_id.x] = b[row * uniforms.N + col]; - } else { - tile_b[local_id.y][local_id.x] = ${$.type.value}(0); - } - `,C="value += tile_a[local_id.y][k] * tile_b[k][local_id.x];");let D=r.alpha===1?"":"value *= uniforms.alpha;";return` - ${w.registerUniforms(v).declareVariables(...M)} - var tile_a: array, ${l}>; - var tile_b: array, ${l}>; - ${w.mainStart([l,l,1])} - let tile_col_start = (workgroup_index % uniforms.num_tile_n) * ${l}; - let tile_row_start = (workgroup_index / uniforms.num_tile_n) * ${l}; - let num_tiles = (uniforms.K - 1) / ${l} + 1; - var k_start = 0u; - var value = ${x.type.value}(0); - for (var t: u32 = 0u; t < num_tiles; t++) { - ${F} - k_start = k_start + ${l}; - workgroupBarrier(); - - for (var k: u32 = 0u; k < ${l}; k++) { - ${C} - } - workgroupBarrier(); - } - - ${D} - let m = tile_row_start + local_id.y; - let n = tile_col_start + local_id.x; - ${T!=null?`let cOffset = ${T.broadcastedIndicesToOffset("vec2(m, n)",x)}; value += ${x.type.value}(uniforms.beta) * ${T.getByOffset("cOffset")};`:""} - if (m < uniforms.M && n < uniforms.N) { - output[m * uniforms.N + n] = value; - } - }`};return d?{name:"GemmShared",shaderCache:{hint:`${r.cacheKey}`,inputDependencies:_},getRunData:()=>({outputs:[{dims:i,dataType:e[0].dataType}],dispatchGroup:{x:c*p},programUniforms:f}),getShaderSource:k}:{name:"Gemm",shaderCache:{hint:`${r.cacheKey}`,inputDependencies:_},getRunData:()=>({outputs:[{dims:i,dataType:e[0].dataType}],dispatchGroup:{x:Math.ceil(u/64)},programUniforms:f}),getShaderSource:b}},A_=e=>{let r=e.transA,t=e.transB,s=e.alpha,o=e.beta;return{transA:r,transB:t,alpha:s,beta:o,cacheKey:`${e.transA};${e.transB};${e.alpha===1}`}},F_=(e,r)=>{k_(e.inputs),e.compute(I_(e.inputs,r))}}),ks,Vs,yn,vn,O_,D_,L_,z_,B_,R_,j_,N_,V_,U_,aT=Ue(()=>{Mt(),Pt(),pr(),Ct(),[ks,Vs,yn,vn]=[0,1,2,3],O_=e=>{if(e[0].dims.length!==4)throw new Error("only 4-D tensor is supported.");if(e[0].dims.length!==e[1].dims.length)throw new Error("input dimensions must be equal to grid dimensions");if(e[0].dims.length-2!==e[1].dims[e[1].dims.length-1])throw new Error(`last dimension of grid must be equal to ${e[0].dims.length-2}`);if(e[0].dims[0]!==e[1].dims[0])throw new Error("grid batch size must match input batch size")},D_=` - fn gs_get_cubic_coeffs(x: f32) -> vec4 { - let cubic_alpha = -0.75f; - let x_abs = abs(x); - var coeffs: vec4; - coeffs[0] = (((cubic_alpha * (x_abs + 1) - 5 * cubic_alpha) * (x_abs + 1) + 8 * cubic_alpha) * (x_abs + 1) - 4 * cubic_alpha); - coeffs[1] = (((cubic_alpha + 2) * x_abs - (cubic_alpha + 3)) * x_abs * x_abs + 1); - coeffs[2] = (((cubic_alpha + 2) * (1 - x_abs) - (cubic_alpha + 3)) * (1 - x_abs) * (1 - x_abs) + 1); - coeffs[3] = (((cubic_alpha * (2 - x_abs) - 5 * cubic_alpha) * (2 - x_abs) + 8 * cubic_alpha) * (2 - x_abs) - 4 * cubic_alpha); - return coeffs; - } -`,L_=e=>` - fn gs_bicubic_interpolate(p: mat4x4<${e}>, x: f32, y: f32) -> ${e} { - var v: vec4; - var coeffs = gs_get_cubic_coeffs(x); - for (var i = 0; i < 4; i++) { - v[i] = coeffs[0] * p[i][0] + coeffs[1] * p[i][1] + coeffs[2] * p[i][2] + coeffs[3] * p[i][3]; - } - coeffs = gs_get_cubic_coeffs(y); - let pixel = ${e}(coeffs[0] * v[0] + coeffs[1] * v[1] + coeffs[2] * v[2] + coeffs[3] * v[3]); - return pixel; - } -`,z_=e=>` - fn gs_denormalize(n: f32, length: i32) -> f32 { - ${e.alignCorners===0?` - // alignCorners: false => [-1, 1] to [-0.5, length - 0.5] - return ((n + 1.0) * f32(length) - 1.0) / 2.0; - `:` - // alignCorners: true => [-1, 1] to [0, length - 1] - return (n + 1.0) / 2.0 * (f32(length - 1)); - `} - } -`,B_=e=>` - ${e.paddingMode==="reflection"?` - fn gs_reflect(x: i32, x_min: f32, x_max: f32) -> u32 { - var dx = 0.0; - var fx = f32(x); - let range = x_max - x_min; - if (fx < x_min) { - dx = x_min - fx; - let n = u32(dx / range); - let r = dx - f32(n) * range; - if (n % 2 == 0) { - fx = x_min + r; - } else { - fx = x_max - r; - } - } else if (fx > x_max) { - dx = fx - x_max; - let n = u32(dx / range); - let r = dx - f32(n) * range; - if (n % 2 == 0) { - fx = x_max - r; - } else { - fx = x_min + r; - } - } - return u32(fx); - }`:""} -`,R_=(e,r,t)=>` - fn pixel_at_grid(r: i32, c: i32, H: i32, W: i32, batch: u32, channel: u32, border: vec4) -> ${r} { - var pixel = ${r}(0); - var indices = vec4(0); - indices[${ks}] = batch; - indices[${Vs}] = channel;`+(()=>{switch(t.paddingMode){case"zeros":return` - if (r >= 0 && r < H && c >=0 && c < W) { - indices[${yn}] = u32(r); - indices[${vn}] = u32(c); - } else { - return ${r}(0); - } - `;case"border":return` - indices[${yn}] = u32(clamp(r, 0, H - 1)); - indices[${vn}] = u32(clamp(c, 0, W - 1)); - `;case"reflection":return` - indices[${yn}] = gs_reflect(r, border[1], border[3]); - indices[${vn}] = gs_reflect(c, border[0], border[2]); - `;default:throw new Error(`padding mode ${t.paddingMode} is not supported`)}})()+` - return ${e.getByIndices("indices")}; - } -`,j_=(e,r,t)=>(()=>{switch(t.mode){case"nearest":return` - let result = pixel_at_grid(i32(round(y)), i32(round(x)), H_in, W_in, indices[${ks}], indices[${Vs}], border); - `;case"bilinear":return` - let x1 = i32(floor(x)); - let y1 = i32(floor(y)); - let x2 = x1 + 1; - let y2 = y1 + 1; - - let p11 = pixel_at_grid(y1, x1, H_in, W_in, indices[${ks}], indices[${Vs}], border); - let p12 = pixel_at_grid(y1, x2, H_in, W_in, indices[${ks}], indices[${Vs}], border); - let p21 = pixel_at_grid(y2, x1, H_in, W_in, indices[${ks}], indices[${Vs}], border); - let p22 = pixel_at_grid(y2, x2, H_in, W_in, indices[${ks}], indices[${Vs}], border); - - let dx2 = ${r}(f32(x2) - x); - let dx1 = ${r}(x - f32(x1)); - let dy2 = ${r}(f32(y2) - y); - let dy1 = ${r}(y - f32(y1)); - let result = dy2 * (dx2 * p11 + dx1 * p12) + dy1 * (dx2 * p21 + dx1 * p22); - `;case"bicubic":return` - let x0 = i32(floor(x)) - 1; - let y0 = i32(floor(y)) - 1; - var p: mat4x4<${r}>; - for (var h = 0; h < 4; h++) { - for (var w = 0; w < 4; w++) { - p[h][w] = pixel_at_grid(h + y0, w + x0, H_in, W_in, indices[${ks}], indices[${Vs}], border); - } - } - - let dx = x - f32(x0 + 1); - let dy = y - f32(y0 + 1); - let result = gs_bicubic_interpolate(p, dx, dy); - `;default:throw new Error(`mode ${t.mode} is not supported`)}})()+`${e.setByOffset("global_idx","result")}`,N_=(e,r)=>{let t=Ie("x",e[0].dataType,e[0].dims.length),s=[e[1].dims[0],e[1].dims[1],e[1].dims[2]],o=Ie("grid",e[1].dataType,s.length,2),n=[e[0].dims[0],e[0].dims[1],e[1].dims[1],e[1].dims[2]];r.format==="NHWC"&&(n=[e[0].dims[0],e[1].dims[1],e[1].dims[2],e[0].dims[3]],[ks,Vs,yn,vn]=[0,3,1,2]);let a=nt("output",e[0].dataType,n.length),i=t.type.value,l=ye.size(n),c=[{type:12,data:l},...dt(e[0].dims,s,n)],p=d=>` - ${d.registerUniform("output_size","u32").declareVariables(t,o,a)} - ${D_} - ${L_(i)} - ${z_(r)} - ${B_(r)} - ${R_(t,i,r)} - - ${d.mainStart()} - ${d.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} - let H_in = i32(uniforms.x_shape[${yn}]); - let W_in = i32(uniforms.x_shape[${vn}]); - - ${r.alignCorners===0?` - let x_min = -0.5; - let x_max = f32(W_in) - 0.5; - let y_min = -0.5; - let y_max = f32(H_in) - 0.5; - `:` - let x_min = 0.0; - let x_max = f32(W_in) - 1.0; - let y_min = 0.0; - let y_max = f32(H_in) - 1.0; - `}; - let border = vec4(x_min, y_min, x_max, y_max); - - let indices = ${a.offsetToIndices("global_idx")}; - var grid_indices = vec3(indices[${ks}], indices[${yn}], indices[${vn}]); - let nxy = ${o.getByIndices("grid_indices")}; - var x = gs_denormalize(f32(nxy[0]), W_in); - var y = gs_denormalize(f32(nxy[1]), H_in); - - ${j_(a,i,r)} - }`;return{name:"GridSample",shaderCache:{hint:`${r.cacheKey}`,inputDependencies:["type","type"]},getRunData:d=>{let u=ye.size(n);return{outputs:[{dims:n,dataType:d[0].dataType}],dispatchGroup:{x:Math.ceil(u/64)},programUniforms:c}},getShaderSource:p}},V_=(e,r)=>{O_(e.inputs),e.compute(N_(e.inputs,r))},U_=e=>Kt({alignCorners:e.align_corners,mode:e.mode,paddingMode:e.padding_mode,format:e.format})}),Kr,W_,G_,Bl,K_,xo,H_,q_=Ue(()=>{Mt(),Pt(),pr(),nl(),_l(),Ct(),tn(),Kr=(e,r)=>e.length>r&&e[r].dims.length>0?e[r]:void 0,W_=(e,r)=>{let t=e[0],s=Kr(e,1),o=Kr(e,2),n=Kr(e,3),a=Kr(e,4),i=Kr(e,5),l=Kr(e,6),c=Kr(e,7);if(t.dims.length!==3&&t.dims.length!==5)throw new Error("Input query is expected to have 3 or 5 dimensions");let p=t.dims[0],d=t.dims[1],u=t.dims.length===3?t.dims[2]:r.numHeads*t.dims[4],f=d,_=0,b=0,k=Math.floor(u/r.numHeads);if(l&&c&&ye.size(l.dims)&&ye.size(c.dims)){if(l.dims.length!==4)throw new Error('Input "past_key" is expected to have 4 dimensions');if(l.dims[0]!==p||l.dims[1]!==r.numHeads||l.dims[3]!==k)throw new Error('Input "past_key" shape (batch_size, num_heads, past_sequence_length, head_size)');if(c.dims[0]!==p||c.dims[1]!==r.numHeads||c.dims[3]!==k)throw new Error('Input "past_value" shape (batch_size, num_heads, past_sequence_length, head_size)');if(l.dims[2]!==c.dims[2])throw new Error('Input "past_key" and "past_value" shall have same dim 2 (past_sequence_length)');if(c.dims.length!==4)throw new Error('Input "past_value" is expected to have 4 dimensions');_=l.dims[2],b=l.dims[2]}else if(l&&ye.size(l.dims)||c&&ye.size(c.dims))throw new Error('Input "past_key" and "past_value" shall be both present or both absent');let w;if(s&&ye.size(s.dims)>0){if(t.dims.length!==3)throw new Error('Input "query" is expected to have 3 dimensions when key is given');if(s.dims.length<3||s.dims.length>5)throw new Error('Input "key" is expected to have 3, 4, or 5 dimensions');if(t.dims[0]!==s.dims[0])throw new Error('Input "query" and "key" shall have same dim 0 (batch size)');if(s.dims.length===3){if(s.dims[2]!==t.dims[2])throw new Error('Input "query" and "key" shall have same dim 2 (hidden_size)');w=2,f=s.dims[1]}else if(s.dims.length===5){if(s.dims[2]!==r.numHeads||s.dims[3]!==2||s.dims[4]!==k)throw new Error('Expect "key" shape (batch_size, kv_sequence_length, num_heads, 2, head_size) for packed kv');if(o)throw new Error('Expect "value" be none when "key" has packed kv format.');w=5,f=s.dims[1]}else{if(s.dims[1]!==r.numHeads||s.dims[3]!==k)throw new Error('Expect "key" shape (batch_size, num_heads, kv_sequence_length, head_size) for past_key');w=0,f=s.dims[2]}}else{if(t.dims.length!==5)throw new Error('Input "query" is expected to have 5 dimensions when key is empty');if(t.dims[2]!==r.numHeads||t.dims[3]!==3)throw new Error('Expect "query" shape (batch_size, kv_sequence_length, num_heads, 3, head_size) for packed kv');w=3}if(n&&ye.size(n.dims)>0){if(n.dims.length!==1)throw new Error('Input "bias" is expected to have 1 dimension');if(s&&s.dims.length===5&&s.dims[3]===2)throw new Error("bias is not allowed for packed kv.")}let y=_+f,$=0;if(a&&ye.size(a.dims)>0){$=8;let v=a.dims;throw v.length===1?v[0]===p?$=1:v[0]===3*p+2&&($=3):v.length===2&&v[0]===p&&v[1]===y&&($=5),$===8?new Error('Input "key_padding_mask" shape shall be (batch_size) or (batch_size, total_sequence_length)'):new Error("Mask not supported")}let T=!1,M=u;if(o&&ye.size(o.dims)>0){if(o.dims.length!==3&&o.dims.length!==4)throw new Error('Input "value" is expected to have 3 or 4 dimensions');if(t.dims[0]!==o.dims[0])throw new Error('Input "query" and "value" shall have same dim 0 (batch_size)');if(o.dims.length===3){if(f!==o.dims[1])throw new Error('Input "key" and "value" shall have the same dim 1 (kv_sequence_length)');M=o.dims[2]}else{if(f!==o.dims[2])throw new Error('Input "key" and "value" shall have the same dim 2 (kv_sequence_length)');M=o.dims[1]*o.dims[3],T=!0}}let x=!1;if(a&&ye.size(a.dims)>0)throw new Error("Key padding mask is not supported");if(i&&ye.size(i.dims)>0){if(i.dims.length!==4)throw new Error('Input "attention_bias" is expected to have 4 dimensions');if(i.dims[0]!==p||i.dims[1]!==r.numHeads||i.dims[2]!==d||i.dims[3]!==y)throw new Error('Expect "attention_bias" shape (batch_size, num_heads, sequence_length, total_sequence_length)')}return{batchSize:p,sequenceLength:d,pastSequenceLength:_,kvSequenceLength:f,totalSequenceLength:y,maxSequenceLength:b,inputHiddenSize:0,hiddenSize:u,vHiddenSize:M,headSize:k,vHeadSize:Math.floor(M/r.numHeads),numHeads:r.numHeads,isUnidirectional:!1,pastPresentShareBuffer:!1,maskFilterValue:r.maskFilterValue,maskType:$,scale:r.scale,broadcastResPosBias:x,passPastInKv:T,qkvFormat:w}},G_=e=>Kt({...e}),Bl=Kt({perm:[0,2,1,3]}),K_=(e,r,t,s,o,n,a)=>{let i=[s,o,n],l=ye.size(i),c=[{type:12,data:l},{type:12,data:a},{type:12,data:n}],p=d=>{let u=nt("qkv_with_bias",r.dataType,i),f=Ie("qkv",r.dataType,i),_=Ie("bias",t.dataType,i),b=[{name:"output_size",type:"u32"},{name:"bias_offset",type:"u32"},{name:"hidden_size",type:"u32"}];return` - ${d.registerUniforms(b).declareVariables(f,_,u)} - ${d.mainStart()} - ${d.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} - let bias_offset_idx = (global_idx % uniforms.hidden_size) + uniforms.bias_offset; - - qkv_with_bias[global_idx] = qkv[global_idx] + bias[bias_offset_idx]; - }`};return e.compute({name:"MultiHeadAttentionAddBias",shaderCache:{inputDependencies:["type","type"]},getRunData:()=>({outputs:[{dims:i,dataType:r.dataType,gpuDataType:0}],dispatchGroup:{x:Math.ceil(l/64)},programUniforms:c}),getShaderSource:p},{inputs:[r,t],outputs:[-1]})[0]},xo=(e,r,t,s,o,n,a,i)=>{let l=n;if(a&&ye.size(a.dims)>0){if(s===1)throw new Error("AddBiasReshape is not implemented. Please export your model with packed QKV or KV");return l=K_(e,n,a,r,s,t*o,i),l=l.reshape([r,s,t,o]),t===1||s===1?l:e.compute(rs(l,Bl.perm),{inputs:[l],outputs:[-1]})[0]}else return n.dims.length===3&&(l=n.reshape([r,s,t,o])),t===1||s===1?l:e.compute(rs(l,Bl.perm),{inputs:[l],outputs:[-1]})[0]},H_=(e,r)=>{let t=W_(e.inputs,r),s=e.inputs[0],o=Kr(e.inputs,1),n=Kr(e.inputs,2),a=Kr(e.inputs,3),i=Kr(e.inputs,4),l=Kr(e.inputs,5),c=Kr(e.inputs,6),p=Kr(e.inputs,7);if(s.dims.length===5)throw new Error("Packed QKV is not implemented");if((o==null?void 0:o.dims.length)===5)throw new Error("Packed KV is not implemented");let d=o&&n&&o.dims.length===4&&n.dims.length===4,u=xo(e,t.batchSize,t.numHeads,t.sequenceLength,t.headSize,s,a,0);if(d)return wo(e,u,o,n,i,void 0,c,p,l,t);if(!o||!n)throw new Error("key and value must be provided");let f=xo(e,t.batchSize,t.numHeads,t.kvSequenceLength,t.headSize,o,a,t.hiddenSize),_=xo(e,t.batchSize,t.numHeads,t.kvSequenceLength,t.vHeadSize,n,a,2*t.hiddenSize);wo(e,u,f,_,i,void 0,c,p,l,t)}}),Q_,X_,J_,Y_,Rl,Z_,ef,tf=Ue(()=>{Mt(),Pt(),pr(),Ct(),Q_=e=>{if(!e||e.length<1)throw new Error("too few inputs")},X_=(e,r)=>{let t=[],s=r.numOutputs;return e[1].dims[0]>0&&(e[1].getBigInt64Array().forEach(o=>t.push(Number(o))),s=t.length),Kt({numOutputs:s,axis:r.axis,splitSizes:t})},J_=e=>` -fn calculateOutputIndex(index: u32) -> u32 { - for (var i: u32 = 0u; i < ${e}u; i += 1u ) { - if (index < ${ct("uniforms.size_in_split_axis","i",e)}) { - return i; - } - } - return ${e}u; -}`,Y_=e=>{let r=e.length,t=[];for(let s=0;s{let t=e[0].dims,s=ye.size(t),o=e[0].dataType,n=ye.normalizeAxis(r.axis,t.length),a=new Array(r.numOutputs),i=Ie("input",o,t.length),l=new Array(r.numOutputs),c=[],p=[],d=0,u=[{type:12,data:s}];for(let _=0;_` - ${_.registerUniform("input_size","u32").registerUniform("size_in_split_axis","u32",l.length).declareVariables(i,...a)} - ${J_(l.length)} - ${Y_(a)} - - ${_.mainStart()} - ${_.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.input_size")} - - var indices = ${i.offsetToIndices("global_idx")}; - var index = ${i.indicesGet("indices",n)}; - let output_number = calculateOutputIndex(index); - if (output_number != 0) { - index -= ${ct("uniforms.size_in_split_axis","output_number - 1u",l.length)}; - ${i.indicesSet("indices",n,"index")}; - } - writeBufferData(output_number, indices, global_idx); - }`;return{name:"Split",shaderCache:{hint:r.cacheKey,inputDependencies:["rank"]},getShaderSource:f,getRunData:()=>({outputs:c,dispatchGroup:{x:Math.ceil(s/64)},programUniforms:u})}},Z_=(e,r)=>{Q_(e.inputs);let t=e.inputs.length===1?r:X_(e.inputs,r);e.compute(Rl(e.inputs,t),{inputs:[0]})},ef=e=>{let r=e.axis,t=e.splitSizes,s=e.numOutputs<0?t.length:e.numOutputs;if(s!==t.length)throw new Error("numOutputs and splitSizes lengh must be equal");return Kt({axis:r,numOutputs:s,splitSizes:t})}}),rf,wa,sf,nf=Ue(()=>{Mt(),Pt(),pr(),Ct(),rf=(e,r)=>{let[t,s,o,n]=e,{numHeads:a,rotaryEmbeddingDim:i}=r;if(t.dims.length!==3&&t.dims.length!==4)throw new Error(`Input 'x' is expected to have 3 or 4 dimensions, got ${t.dims.length}`);if(!ye.areEqual(s.dims,[])&&!ye.areEqual(s.dims,[1])&&s.dims.length!==2)throw new Error(`Input 'position_ids' is expected to have 0, 1, or 2 dimensions, got ${s.dims.length}`);if(o.dims.length!==2)throw new Error(`Input 'cos_cache' is expected to have 2 dimensions, got ${o.dims.length}`);if(n.dims.length!==2)throw new Error(`Input 'sin_cache' is expected to have 2 dimensions, got ${n.dims.length}`);if(!ye.areEqual(o.dims,n.dims))throw new Error("Inputs 'cos_cache' and 'sin_cache' are expected to have the same shape");if(i>0&&a===0)throw new Error("num_heads must be provided if rotary_embedding_dim is specified");let l=t.dims[0],c=t.dims[t.dims.length-2],p=o.dims[0],d=ye.sizeFromDimension(t.dims,1)/c,u=i===0?o.dims[1]*2:d/a;if(i>u)throw new Error("rotary_embedding_dim must be less than or equal to head_size");if(s.dims.length===2){if(l!==s.dims[0])throw new Error(`Input 'position_ids' dimension 0 should be of size batch_size, got ${s.dims[0]}`);if(c!==s.dims[1])throw new Error(`Input 'position_ids' dimension 1 should be of size sequence_length, got ${s.dims[1]}`)}if(u/2!==o.dims[1]&&i/2!==o.dims[1])throw new Error(`Input 'cos_cache' dimension 1 should be same as head_size / 2 or rotary_embedding_dim / 2, got ${o.dims[1]}`);if(c>p)throw new Error("Updating cos_cache and sin_cache in RotaryEmbedding is not currently supported")},wa=(e,r)=>{let{interleaved:t,numHeads:s,rotaryEmbeddingDim:o,scale:n}=r,a=e[0].dims[0],i=ye.sizeFromDimension(e[0].dims,1),l=e[0].dims[e[0].dims.length-2],c=i/l,p=e[2].dims[1],d=o===0?p*2:c/s,u=new Array(a,l,c/d,d-p),f=ye.computeStrides(u),_=[{type:1,data:n},{type:12,data:u},{type:12,data:f},...e[0].dims.length===3?new Array({type:12,data:[i,c,d,1]}):[],...e[0].dims.length===4?new Array({type:12,data:[i,d,l*d,1]}):[],...dt(e[0].dims,e[1].dims,e[2].dims,e[3].dims,e[0].dims)],b=k=>{let w=Ie("input",e[0].dataType,e[0].dims.length),y=Ie("position_ids",e[1].dataType,e[1].dims.length),$=Ie("cos_cache",e[2].dataType,e[2].dims.length),T=Ie("sin_cache",e[3].dataType,e[3].dims.length),M=nt("output",e[0].dataType,e[0].dims.length);return k.registerUniforms([{name:"scale",type:"f32"},{name:"global_shape",type:"u32",length:u.length},{name:"global_strides",type:"u32",length:f.length},{name:"input_output_strides",type:"u32",length:f.length}]),` - ${k.declareVariables(w,y,$,T,M)} - - ${k.mainStart(Kn)} - let half_rotary_emb_dim = uniforms.${$.name}_shape[1]; - let bsnh = global_idx / uniforms.global_strides % uniforms.global_shape; - let size = uniforms.global_shape[0] * uniforms.global_strides[0]; - ${k.guardAgainstOutOfBoundsWorkgroupSizes("size")} - - if (bsnh[3] < half_rotary_emb_dim) { - let position_ids_idx = - ${y.broadcastedIndicesToOffset("bsnh.xy",nt("",y.type.tensor,2))}; - let position_id = - u32(${y.getByOffset("position_ids_idx")}) + select(0, bsnh[1], position_ids_idx == 0); - let i = dot(bsnh, uniforms.input_output_strides) + select(0, bsnh[3], ${t}); - let j = i + select(half_rotary_emb_dim, 1, ${t}); - let re = ${w.getByOffset("i")} * ${$.get("position_id","bsnh[3]")} - - ${w.getByOffset("j")} * ${T.get("position_id","bsnh[3]")}; - ${M.setByOffset("i","re")} - let im = ${w.getByOffset("i")} * ${T.get("position_id","bsnh[3]")} + - ${w.getByOffset("j")} * ${$.get("position_id","bsnh[3]")}; - ${M.setByOffset("j","im")} - } else { - let k = dot(bsnh, uniforms.input_output_strides) + half_rotary_emb_dim; - ${M.setByOffset("k",w.getByOffset("k"))} - } - }`};return{name:"RotaryEmbedding",shaderCache:{hint:Kt({interleaved:t}).cacheKey,inputDependencies:["rank","rank","rank","rank"]},getShaderSource:b,getRunData:()=>({outputs:[{dims:e[0].dims,dataType:e[0].dataType}],dispatchGroup:{x:Math.ceil(ye.size(u)/Kn)},programUniforms:_})}},sf=(e,r)=>{rf(e.inputs,r),e.compute(wa(e.inputs,r))}}),of,af,jl,lf,cf,iT=Ue(()=>{pr(),Mt(),_l(),q_(),tf(),tn(),nf(),Ct(),of=(e,r)=>{if(r.doRotary&&e.length<=7)throw new Error("cos_cache and sin_cache inputs are required if do_rotary is specified");let t=e[0],s=e[1],o=e[2],n=e[3],a=e[4];if(r.doRotary!==0&&e.length<=7)throw new Error("cos_cast and sin_cache are expected if do_rotary attribute is non-zero");if(r.localWindowSize!==-1)throw new Error("Local attention is not supported");if(r.softcap!==0)throw new Error("Softcap is not supported");if(r.rotaryInterleaved!==0)throw new Error("Rotary interleaved is not supported");if(r.smoothSoftmax)throw new Error("Smooth softmax is not supported");if(t.dims.length!==3&&t.dims.length!==5)throw new Error("Input query is expected to have 3 or 5 dimensions");let i=!1,l=t.dims[0],c=t.dims[1],p=t.dims.length===3?i?t.dims[2]/3:t.dims[2]:r.numHeads*t.dims[4],d=c,u=0,f=!s||s.dims.length===0,_=Math.floor(f?p/(r.numHeads+2*r.kvNumHeads):p/r.numHeads);f&&(p=_*r.numHeads);let b=n&&n.dims.length!==0,k=a&&a.dims.length!==0;if(b&&n.dims.length===4&&n.dims[0]===l&&n.dims[1]!==r.kvNumHeads&&n.dims[2]===r.kvNumHeads&&n.dims[3]===_)throw new Error("BSNH pastKey/pastValue is not supported");if(b&&k){if(n.dims.length!==4)throw new Error('Input "past_key" is expected to have 4 dimensions');if(a.dims.length!==4)throw new Error('Input "past_value" is expected to have 4 dimensions');u=n.dims[2]}else if(b||k)throw new Error('Input "past_key" and "past_value" shall be both present or both absent');let w=1;if(s&&s.dims.length>0){if(t.dims.length!==3)throw new Error('Input "query" is expected to have 3 dimensions when key is given');if(s.dims.length<3||s.dims.length>5)throw new Error('Input "key" is expected to have 3, 4, or 5 dimensions');if(t.dims[0]!==s.dims[0])throw new Error('Input "query" and "key" shall have same dim 0 (batch size)');if(s.dims.length===3){if(t.dims[2]%s.dims[2]!==0)throw new Error('Dimension 2 of "query" should be a multiple of "key"');d=s.dims[1]}else if(s.dims.length===5){if(s.dims[2]!==r.numHeads||s.dims[3]!==2||s.dims[4]!==_)throw new Error('Expect "key" shape (batch_size, kv_sequence_length, num_heads, 2, head_size) for packed kv');if(o)throw new Error('Expect "value" be none when "key" has packed kv format.');d=s.dims[1]}else{if(s.dims[1]!==r.numHeads||s.dims[3]!==_)throw new Error('Expect "key" shape (batch_size, num_heads, kv_sequence_length, head_size) for past_key');d=s.dims[2]}}else{if(t.dims.length!==3&&t.dims.length!==5)throw new Error('Input "query" is expected to have 3 or 5 dimensions when key is empty');if(t.dims.length===5&&(t.dims[2]!==r.numHeads||t.dims[3]!==3))throw new Error('Expect "query" shape (batch_size, kv_sequence_length, num_heads, 3, head_size) for packed kv');w=3}let y=0,$=!1,T=r.kvNumHeads?_*r.kvNumHeads:p;if(o&&o.dims.length>0){if(o.dims.length!==3&&o.dims.length!==4)throw new Error('Input "value" is expected to have 3 or 4 dimensions');if(t.dims[0]!==o.dims[0])throw new Error('Input "query" and "value" shall have same dim 0 (batch_size)');if(o.dims.length===3){if(d!==o.dims[1])throw new Error('Input "key" and "value" shall have the same dim 1 (kv_sequence_length)');T=o.dims[2]}else{if(d!==o.dims[2])throw new Error('Input "past_key" and "past_value" shall have the same dim 2 (kv_sequence_length)');T=o.dims[1]*o.dims[3],$=!0}}let M=e.length>4?e[5]:void 0;if(M&&M.dims.length!==1&&M.dims[0]!==l)throw new Error('Input "seqlens" is expected to have 1 dimension and the same dim 0 as batch_size');return{batchSize:l,sequenceLength:c,pastSequenceLength:u,kvSequenceLength:d,totalSequenceLength:-1,maxSequenceLength:-1,inputHiddenSize:0,hiddenSize:p,vHiddenSize:T,headSize:_,vHeadSize:Math.floor(T/r.kvNumHeads),numHeads:r.numHeads,kvNumHeads:r.kvNumHeads,nReps:r.numHeads/r.kvNumHeads,pastPresentShareBuffer:!1,maskType:y,scale:r.scale,broadcastResPosBias:!1,passPastInKv:$,qkvFormat:w}},af=Kt({perm:[0,2,1,3]}),jl=(e,r,t)=>{let s=r,o=t.kvNumHeads;return r.dims.length===3&&t.kvSequenceLength!==0&&(s=r.reshape([t.batchSize,t.kvSequenceLength,o,t.headSize]),s=e.compute(rs(s,af.perm),{inputs:[s],outputs:[-1]})[0]),s},lf=(e,r,t,s)=>{let o=7,n=["type","type"],a=[e*r],i=e*r,l=[{type:12,data:i},{type:12,data:r},{type:12,data:e}],c=p=>{let d=Ie("seq_lens",t.dataType,t.dims),u=Ie("total_seq_lens",s.dataType,s.dims),f=nt("pos_ids",o,a),_=[{name:"output_size",type:"u32"},{name:"sequence_length",type:"u32"},{name:"batch_size",type:"u32"}];return` - ${p.registerUniforms(_).declareVariables(d,u,f)} - ${p.mainStart()} - ${p.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} - let total_sequence_length = u32(${u.getByOffset("0")}); - let is_subsequent_prompt = uniforms.sequence_length > 1 && uniforms.sequence_length != total_sequence_length; - let is_first_prompt = !is_subsequent_prompt && uniforms.sequence_length == total_sequence_length; - let batch_idx = global_idx / uniforms.sequence_length; - let sequence_idx = i32(global_idx % uniforms.sequence_length); - var pos_id: i32 = 0; - let seqlen = ${d.getByOffset("batch_idx")}; - let total_seqlen = seqlen + 1; - if (is_first_prompt) { - if (sequence_idx < total_seqlen) { - pos_id = sequence_idx; - } else { - pos_id = 1; - } - ${f.setByOffset("global_idx","pos_id")} - } else if (is_subsequent_prompt) { - let past_seqlen = total_seqlen - i32(uniforms.sequence_length); - if (past_seqlen + sequence_idx < total_seqlen) { - pos_id = past_seqlen + sequence_idx; - } else { - pos_id = 1; - } - ${f.setByOffset("global_idx","pos_id")} - } else if (global_idx < uniforms.batch_size) { - ${f.setByOffset("global_idx","seqlen")} - }; - } - `};return{name:"GeneratePositionIds",shaderCache:{hint:`${e};${r}`,inputDependencies:n},getRunData:()=>({outputs:[{dims:a,dataType:o}],dispatchGroup:{x:Math.ceil(i/64)},programUniforms:l}),getShaderSource:c}},cf=(e,r)=>{var T;let t=of(e.inputs,r);if(e.inputs[0].dims.length===5)throw new Error("Packed QKV is not implemented");if(((T=e.inputs[1])==null?void 0:T.dims.length)===5)throw new Error("Packed KV is not implemented");let s=e.inputs[0],o=e.inputs[1]&&e.inputs[1].dims.length>0?e.inputs[1]:void 0,n=e.inputs[2]&&e.inputs[2].dims.length>0?e.inputs[2]:void 0,a=e.inputs[3]&&e.inputs[3].dims.length!==0?e.inputs[3]:void 0,i=e.inputs[4]&&e.inputs[4].dims.length!==0?e.inputs[4]:void 0,l=e.inputs.length>4?e.inputs[5]:void 0,c=e.inputs.length>5?e.inputs[6]:void 0,p=t.kvNumHeads?t.kvNumHeads:t.numHeads,d=Kt({axis:2,numOutputs:3,splitSizes:[t.numHeads*t.headSize,p*t.headSize,p*t.headSize]}),[u,f,_]=!o&&!n?e.compute(Rl([s],d),{inputs:[s],outputs:[-1,-1,-1]}):[s,o,n],b,k;if(r.doRotary){let M=e.compute(lf(t.batchSize,t.sequenceLength,l,c),{inputs:[l,c],outputs:[-1]})[0],x=e.inputs[7],v=e.inputs[8],C=Kt({interleaved:r.rotaryInterleaved!==0,numHeads:t.numHeads,rotaryEmbeddingDim:0,scale:r.scale}),F=[u,M,x,v],D=[-1];b=e.compute(wa(F,C),{inputs:F,outputs:D})[0],F.splice(0,1,f);let K=Kt({interleaved:r.rotaryInterleaved!==0,numHeads:t.kvNumHeads,rotaryEmbeddingDim:0,scale:r.scale});k=e.compute(wa(F,K),{inputs:F,outputs:D})[0]}let w=xo(e,t.batchSize,t.numHeads,t.sequenceLength,t.headSize,r.doRotary?b:u,void 0,0),y=jl(e,r.doRotary?k:f,t),$=jl(e,_,t);wo(e,w,y,$,void 0,void 0,a,i,void 0,t,l,c)}}),Nl,uf,df,pf,lT=Ue(()=>{Mt(),Pt(),tn(),Ct(),Nl=(e,r,t,s,o,n,a,i)=>{let l=lr(n),c=l===1?"f32":`vec${l}f`,p=l===1?"vec2f":`mat2x${l}f`,d=o*a,u=64;d===1&&(u=256);let f=[o,a,n/l],_=[o,a,2],b=["rank","type","type"],k=[];k.push(...dt(f,_));let w=y=>{let $=Ie("x",r.dataType,3,l),T=Ie("scale",t.dataType,t.dims),M=Ie("bias",s.dataType,s.dims),x=nt("output",1,3,2),v=[$,T,M,x];return` - var workgroup_shared : array<${p}, ${u}>; - const workgroup_size = ${u}u; - ${y.declareVariables(...v)} - ${y.mainStart(u)} - let batch = workgroup_index / uniforms.x_shape[1]; - let channel = workgroup_index % uniforms.x_shape[1]; - let hight = uniforms.x_shape[2]; - // initialize workgroup memory - var sum = ${c}(0); - var squared_sum = ${c}(0); - for (var h = local_idx; h < hight; h += workgroup_size) { - let value = ${c}(${$.get("batch","channel","h")}); - sum += value; - squared_sum += value * value; - } - workgroup_shared[local_idx] = ${p}(sum, squared_sum); - workgroupBarrier(); - - for (var currSize = workgroup_size >> 1; currSize > 0; currSize = currSize >> 1) { - if (local_idx < currSize) { - workgroup_shared[local_idx] = workgroup_shared[local_idx] + workgroup_shared[local_idx + currSize]; - } - workgroupBarrier(); - } - if (local_idx == 0) { - let sum_final = ${en("workgroup_shared[0][0]",l)} / f32(hight * ${l}); - let squared_sum_final = ${en("workgroup_shared[0][1]",l)} / f32(hight * ${l}); - - let inv_std_dev = inverseSqrt(squared_sum_final - sum_final * sum_final + f32(${i})); - let channel_scale = inv_std_dev * f32(scale[channel]); - let channel_shift = f32(bias[channel]) - sum_final * channel_scale; - output[workgroup_index] = vec2f(channel_scale, channel_shift); - } - }`};return e.compute({name:"InstanceNormComputeChannelScaleShift",shaderCache:{hint:`${l};${i};${u}`,inputDependencies:b},getRunData:()=>({outputs:[{dims:_,dataType:1}],dispatchGroup:{x:d},programUniforms:k}),getShaderSource:w},{inputs:[r,t,s],outputs:[-1]})[0]},uf=(e,r,t)=>{let s=r[0].dims,o=s,n=2,a=s[0],i=s[1],l=ye.sizeFromDimension(s,n),c=lr(l),p=ye.size(o)/c,d=Nl(e,r[0],r[1],r[2],a,l,i,t.epsilon),u=[a,i,l/c],f=[a,i],_=["type","none"],b=k=>{let w=Ie("x",r[0].dataType,u.length,c),y=Ie("scale_shift",1,f.length,2),$=nt("output",r[0].dataType,u.length,c),T=[w,y,$];return` - ${k.registerUniform("output_size","u32").declareVariables(...T)} - ${k.mainStart()} - ${k.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} - let outputIndices = ${$.offsetToIndices("global_idx")}; - let batch = outputIndices[0]; - let channel = outputIndices[1]; - let scale_shift = ${y.getByIndices("vec2(batch, channel)")}; - let value = ${w.getByOffset("global_idx")} * ${$.type.value}(scale_shift.x) + ${$.type.value}(scale_shift.y); - ${$.setByOffset("global_idx","value")}; - }`};e.compute({name:"InstanceNormalization",shaderCache:{hint:`${c}`,inputDependencies:_},getRunData:()=>({outputs:[{dims:o,dataType:r[0].dataType}],dispatchGroup:{x:Math.ceil(p/64)},programUniforms:[{type:12,data:p},...dt(u,f,u)]}),getShaderSource:b},{inputs:[r[0],d]})},df=(e,r,t)=>{let s=r[0].dims,o=s,n=s[0],a=s[s.length-1],i=ye.sizeFromDimension(s,1)/a,l=lr(a),c=ye.size(o)/l,p=[{type:12,data:i},{type:12,data:Math.floor(a/l)}],d=["type","type"],u=!1,f=[0,s.length-1];for(let w=0;ws[f[y]])),b=Nl(e,_,r[1],r[2],n,i,a,t.epsilon),k=w=>{let y=Ir(r[0].dataType),$=l===1?"vec2f":`mat${l}x2f`,T=v=>{let C=v===0?"x":"y",F=l===1?"f32":`vec${l}f`;switch(l){case 1:return`${y}(${F}(scale.${C}))`;case 2:return`vec2<${y}>(${F}(scale[0].${C}, scale[1].${C}))`;case 4:return`vec4<${y}>(${F}(scale[0].${C}, scale[1].${C}, scale[2].${C}, scale[3].${C}))`;default:throw new Error(`Not supported compoents ${l}`)}},M=Ie("input",r[0].dataType,r[0].dims,l),x=nt("output",r[0].dataType,o,l);return` - @group(0) @binding(0) var input : array<${M.type.storage}>; - @group(0) @binding(1) var scale_input : array<${$}>; - @group(0) @binding(2) var output : array<${x.type.storage}>; - struct Uniforms {H: u32, C : u32}; - @group(0) @binding(3) var uniforms: Uniforms; - - ${w.mainStart()} - let current_image_number = global_idx / (uniforms.C * uniforms.H); - let current_channel_number = global_idx % uniforms.C; - - let scale_offset = current_image_number * uniforms.C + current_channel_number; - let scale = scale_input[scale_offset]; - output[global_idx] = fma(input[global_idx], ${T(0)}, ${T(1)}); - }`};e.compute({name:"InstanceNormalizationNHWC",shaderCache:{hint:`${l}`,inputDependencies:d},getRunData:()=>({outputs:[{dims:o,dataType:r[0].dataType}],dispatchGroup:{x:Math.ceil(c/64)},programUniforms:p}),getShaderSource:k},{inputs:[r[0],b]})},pf=(e,r)=>{r.format==="NHWC"?df(e,e.inputs,r):uf(e,e.inputs,r)}}),mf,hf,_f,cT=Ue(()=>{Mt(),Pt(),Ct(),mf=e=>{if(!e||e.length<2)throw new Error("layerNorm requires at least 2 inputs.")},hf=(e,r,t)=>{let s=r.simplified,o=e[0].dims,n=e[1],a=!s&&e[2],i=o,l=ye.normalizeAxis(r.axis,o.length),c=ye.sizeToDimension(o,l),p=ye.sizeFromDimension(o,l),d=ye.size(n.dims),u=a?ye.size(a.dims):0;if(d!==p||a&&u!==p)throw new Error(`Size of X.shape()[axis:] == ${p}. - Size of scale and bias (if provided) must match this. - Got scale size of ${d} and bias size of ${u}`);let f=[];for(let M=0;M1,y=t>2,$=M=>{let x=Ir(e[0].dataType),v=[Ie("x",e[0].dataType,e[0].dims,_),Ie("scale",n.dataType,n.dims,_)];a&&v.push(Ie("bias",a.dataType,a.dims,_)),v.push(nt("output",e[0].dataType,i,_)),w&&v.push(nt("mean_data_output",1,f)),y&&v.push(nt("inv_std_output",1,f));let C=[{name:"norm_count",type:"u32"},{name:"norm_size",type:"f32"},{name:"norm_size_vectorized",type:"u32"},{name:"epsilon",type:"f32"}];return` - ${M.registerUniforms(C).declareVariables(...v)} - ${M.mainStart()} - ${M.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.norm_count")} - let offset = global_idx * uniforms.norm_size_vectorized; - var mean_vector = ${ll("f32",_)}; - var mean_square_vector = ${ll("f32",_)}; - - for (var h: u32 = 0u; h < uniforms.norm_size_vectorized; h++) { - let value = ${Hn(x,_,"x[h + offset]")}; - mean_vector += value; - mean_square_vector += value * value; - } - let mean = ${en("mean_vector",_)} / uniforms.norm_size; - let inv_std_dev = inverseSqrt(${en("mean_square_vector",_)} / uniforms.norm_size ${s?"":"- mean * mean"} + uniforms.epsilon); - - for (var j: u32 = 0; j < uniforms.norm_size_vectorized; j++) { - let f32input = ${Hn(x,_,"x[j + offset]")}; - let f32scale = ${Hn(x,_,"scale[j]")}; - output[j + offset] = ${v[0].type.value}((f32input ${s?"":"- mean"}) * inv_std_dev * f32scale - ${a?`+ ${Hn(x,_,"bias[j]")}`:""} - ); - } - - ${w?"mean_data_output[global_idx] = mean":""}; - ${y?"inv_std_output[global_idx] = inv_std_dev":""}; - }`},T=[{dims:i,dataType:e[0].dataType}];return w&&T.push({dims:f,dataType:1}),y&&T.push({dims:f,dataType:1}),{name:"LayerNormalization",shaderCache:{hint:`${_};${t};${s}`,inputDependencies:b},getRunData:()=>({outputs:T,dispatchGroup:{x:Math.ceil(c/64)},programUniforms:k}),getShaderSource:$}},_f=(e,r)=>{mf(e.inputs),e.compute(hf(e.inputs,r,e.outputCount))}}),ff,gf,uT=Ue(()=>{Pt(),xl(),Cl(),ff=e=>{if(!e||e.length!==2)throw new Error("MatMul requires 2 inputs.");if(e[0].dims[e[0].dims.length-1]!==e[1].dims[e[1].dims.length-2])throw new Error("shared dimension does not match.")},gf=e=>{ff(e.inputs);let r=Gn.calcShape(e.inputs[0].dims,e.inputs[1].dims,!0);if(!r)throw new Error("Can't use matmul on the given tensors");let t=r[r.length-1],s=e.inputs[0].dims[e.inputs[0].dims.length-1];if(t<8&&s<8)e.compute(vl(e.inputs,{activation:""},r));else{let o=r[r.length-2],n=ye.size(e.inputs[0].dims.slice(0,-2)),a=ye.size(e.inputs[1].dims.slice(0,-2));if(n!==1&&o===1&&a===1){let i=e.inputs[0].reshape([1,n,s]),l=e.inputs[1].reshape([1,s,t]),c=[1,n,t],p=[i,l];e.compute(ha(p,{activation:""},r,c),{inputs:p})}else e.compute(ha(e.inputs,{activation:""},r))}}}),wf,Mf,bf,yf,vf,dT=Ue(()=>{Mt(),Pt(),pr(),Ct(),wf=(e,r)=>{if(e.length<3||e.length>4)throw new Error("MatMulNBits requires 3 or 4 inputs");let t=e[0],s=t.dims.length;if(t.dims[s-1]!==r.k)throw new Error("The last dim of input shape does not match the k value");let o=Math.floor((r.k+r.blockSize-1)/r.blockSize),n=r.blockSize/8*r.bits,a=e[1];if(!ye.areEqual(a.dims,[r.n,o,n]))throw new Error("The second inputs must be 3D tensor with shape N X nBlocksPerCol X blobSize");let i=e[2].dims;if(ye.size(i)!==r.n*o)throw new Error("scales input size error.");if(e.length===4){let l=e[3].dims,c=r.bits>4?r.n*o:r.n*Math.floor((o+1)/2);if(ye.size(l)!==c)throw new Error("zeroPoints input size error.")}},Mf=(e,r)=>{let t=e[0].dims,s=t.length,o=t[s-2],n=r.k,a=r.n,i=t.slice(0,s-2),l=ye.size(i),c=e[1].dims[2]/4,p=e[0].dataType,d=lr(r.k),u=lr(c),f=lr(a),_=i.concat([o,a]),b=o>1&&a/f%2===0?2:1,k=ye.size(_)/f/b,w=64,y=[],$=[l,o,n/d],T=ye.convertShape(e[1].dims).slice();T.splice(-1,1,c/u),y.push(...dt($)),y.push(...dt(T)),y.push(...dt(e[2].dims)),e.length===4&&y.push(...dt(ye.convertShape(e[3].dims)));let M=[l,o,a/f];y.push(...dt(M));let x=v=>{let C=$.length,F=Ie("a",e[0].dataType,C,d),D=Ie("b",12,T.length,u),K=Ie("scales",e[2].dataType,e[2].dims.length),U=[F,D,K],j=e.length===4?Ie("zero_points",12,e[3].dims.length):void 0;j&&U.push(j);let se=M.length,q=nt("output",e[0].dataType,se,f),re=Ir(e[0].dataType),Z=(()=>{switch(d){case 1:return`array<${re}, 8>`;case 2:return`mat4x2<${re}>`;case 4:return`mat2x4<${re}>`;default:throw new Error(`${d}-component is not supported.`)}})(),ae=()=>{let oe=` - // reuse a data - var input_offset = ${F.indicesToOffset(`${F.type.indices}(batch, row, word_offset)`)}; - var a_data: ${Z}; - for (var j: u32 = 0; j < ${8/d}; j++) { - a_data[j] = ${F.getByOffset("input_offset")}; - input_offset++; - } - `;for(let G=0;G> 4) & b_mask); - b_quantized_values = ${Z}(${Array.from({length:4},(B,Q)=>`${re}(b_value_lower[${Q}]), ${re}(b_value_upper[${Q}])`).join(", ")}); - b_dequantized_values = ${d===1?`${Z}(${Array.from({length:8},(B,Q)=>`(b_quantized_values[${Q}] - ${j?`zero_point${G}`:"zero_point"}) * scale${G}`).join(", ")});`:`(b_quantized_values - ${Z}(${Array(8).fill(`${j?`zero_point${G}`:"zero_point"}`).join(",")})) * scale${G};`}; - workgroup_shared[local_id.x * ${b} + ${Math.floor(G/f)}]${f>1?`[${G%f}]`:""} += ${Array.from({length:8/d},(B,Q)=>`${d===1?`a_data[${Q}] * b_dequantized_values[${Q}]`:`dot(a_data[${Q}], b_dequantized_values[${Q}])`}`).join(" + ")}; - `;return oe},_e=()=>{let oe=` - var col_index = col * ${f}; - ${j?` - let zero_point_bytes_per_col = (nBlocksPerCol + 1) / 2; - var zero_point_byte_count: u32; - var zero_point_word_index: u32; - var zero_point_byte_offset: u32; - let zero_point_nibble_offset: u32 = block & 0x1u; - var zero_point_bits_offset: u32; - var zero_point_word: u32;`:` - // The default zero point is 8 for unsigned 4-bit quantization. - let zero_point = ${re}(8);`} - `;for(let G=0;G> 0x1u); - zero_point_word_index = zero_point_byte_count >> 0x2u; - zero_point_byte_offset = zero_point_byte_count & 0x3u; - zero_point_bits_offset = (zero_point_byte_offset << 3) + (zero_point_nibble_offset << 2); - zero_point_word = ${j.getByOffset("zero_point_word_index")} >> zero_point_bits_offset; - let zero_point${G} = ${re}((zero_point_word) & 0xFu);`:""} - col_index += 1;`;return oe},pe=()=>{let oe=`col_index = col * ${f};`;for(let G=0;G; - var b_value_upper: vec4; - var b_quantized_values: ${Z}; - var b_dequantized_values: ${Z};`,oe};return` - var workgroup_shared: array<${q.type.value}, ${b*w}>; - ${v.declareVariables(...U,q)} - ${v.mainStart([w,1,1])} - let output_indices = ${q.offsetToIndices(`(global_idx / ${w}) * ${b}`)}; - let col = output_indices[2]; - let row = output_indices[1]; - let batch = output_indices[0]; - let nBlocksPerCol = uniforms.b_shape[1]; - - for (var block = local_id.x; block < nBlocksPerCol; block += ${w}) { - //process one block - var word_offset: u32 = block * ${r.blockSize/d}; - ${_e()} - for (var word: u32 = 0; word < ${c}; word += ${u}) { - ${pe()} - for (var i: u32 = 0; i < ${u}; i++) { - ${ae()} - word_offset += ${8/d}; - } - } - } - workgroupBarrier(); - - if (local_id.x < ${b}) { - var output_value: ${q.type.value} = ${q.type.value}(0); - var workgroup_shared_offset: u32 = local_id.x; - for (var b: u32 = 0u; b < ${w}u; b++) { - output_value += workgroup_shared[workgroup_shared_offset]; - workgroup_shared_offset += ${b}; - } - ${q.setByIndices(`${q.type.indices}(batch, row, col + local_id.x)`,"output_value")}; - } - }`};return{name:"MatMulNBits",shaderCache:{hint:`${r.blockSize};${r.bits};${d};${u};${f};${b};${w}`,inputDependencies:Array(e.length).fill("rank")},getRunData:()=>({outputs:[{dims:_,dataType:p}],dispatchGroup:{x:k},programUniforms:y}),getShaderSource:x}},bf=(e,r)=>{let t=e[0].dims,s=t.length,o=t[s-2],n=r.k,a=r.n,i=t.slice(0,s-2),l=ye.size(i),c=e[1].dims[2]/4,p=e[0].dataType,d=lr(r.k),u=lr(c),f=i.concat([o,a]),_=128,b=a%8===0?8:a%4===0?4:1,k=_/b,w=k*u*8,y=w/d,$=w/r.blockSize,T=ye.size(f)/b,M=[],x=[l,o,n/d],v=ye.convertShape(e[1].dims).slice();v.splice(-1,1,c/u),M.push(...dt(x)),M.push(...dt(v)),M.push(...dt(e[2].dims)),e.length===4&&M.push(...dt(ye.convertShape(e[3].dims)));let C=[l,o,a];M.push(...dt(C));let F=D=>{let K=x.length,U=Ie("a",e[0].dataType,K,d),j=Ie("b",12,v.length,u),se=Ie("scales",e[2].dataType,e[2].dims.length),q=[U,j,se],re=e.length===4?Ie("zero_points",12,e[3].dims.length):void 0;re&&q.push(re);let Z=C.length,ae=nt("output",e[0].dataType,Z),_e=Ir(e[0].dataType),pe=()=>{switch(d){case 1:return` - let a_data0 = vec4<${_e}>(sub_a[word_offset], sub_a[word_offset + 1], sub_a[word_offset + 2], sub_a[word_offset + 3]); - let a_data1 = vec4<${_e}>(sub_a[word_offset + 4], sub_a[word_offset + 5], sub_a[word_offset + 6], sub_a[word_offset + 7]);`;case 2:return` - let a_data0 = vec4<${_e}>(sub_a[word_offset], sub_a[word_offset + 1]); - let a_data1 = vec4<${_e}>(sub_a[word_offset + 2], sub_a[word_offset + 3]);`;case 4:return` - let a_data0 = sub_a[word_offset]; - let a_data1 = sub_a[word_offset + 1];`;default:throw new Error(`${d}-component is not supported.`)}};return` - var sub_a: array<${U.type.value}, ${y}>; - var inter_results: array, ${b}>; - ${D.declareVariables(...q,ae)} - ${D.mainStart([k,b,1])} - let output_indices = ${ae.offsetToIndices(`workgroup_index * ${b}`)}; - let col = output_indices[2]; - let row = output_indices[1]; - let batch = output_indices[0]; - let n_blocks_per_col = uniforms.b_shape[1]; - let num_tiles = (n_blocks_per_col - 1) / ${$} + 1; - - // Loop over shared dimension. - for (var tile: u32 = 0; tile < num_tiles; tile += 1) { - let a_col_start = tile * ${y}; - // load one tile A data into shared memory. - for (var a_offset = local_idx; a_offset < ${y}; a_offset += ${_}) - { - let a_col = a_col_start + a_offset; - if (a_col < uniforms.a_shape[2]) - { - sub_a[a_offset] = ${U.getByIndices(`${U.type.indices}(batch, row, a_col)`)}; - } else { - sub_a[a_offset] = ${U.type.value}(0); - } - } - workgroupBarrier(); - - // each thread process one block - let b_row = col + local_id.y; - let block = tile * ${$} + local_id.x; - ${re?` - let zero_point_bytes_per_col = (n_blocks_per_col + 1) / 2; - let zero_point_byte_count = b_row * zero_point_bytes_per_col + (block >> 0x1u); - let zero_point_word_index = zero_point_byte_count >> 0x2u; - let zero_point_byte_offset = zero_point_byte_count & 0x3u; - let zero_point_nibble_offset: u32 = block & 0x1u; - let zero_point_bits_offset = (zero_point_byte_offset << 3) + (zero_point_nibble_offset << 2); - let zero_point_word = ${re.getByOffset("zero_point_word_index")} >> zero_point_bits_offset; - let zero_point = ${_e}((zero_point_word) & 0xFu);`:` - // The default zero point is 8 for unsigned 4-bit quantization. - let zero_point = ${_e}(8);`} - let scale = ${se.getByOffset("b_row * n_blocks_per_col + block")}; - let b_data = ${j.getByIndices(`${j.type.indices}(b_row, block, 0)`)}; - var word_offset = local_id.x * ${r.blockSize/d}; - for (var i: u32 = 0; i < ${u}; i++) { - ${pe()} - let b_value = ${u===1?"b_data":"b_data[i]"}; - let b_value_lower = unpack4xU8(b_value & 0x0F0F0F0Fu); - let b_value_upper = unpack4xU8((b_value >> 4) & 0x0F0F0F0Fu); - let b_quantized_values = mat2x4<${_e}>(${Array.from({length:4},(oe,G)=>`${_e}(b_value_lower[${G}]), ${_e}(b_value_upper[${G}])`).join(", ")}); - let b_dequantized_values = (b_quantized_values - mat2x4<${_e}>(${Array(8).fill("zero_point").join(",")})) * scale; - inter_results[local_id.y][local_id.x] += ${Array.from({length:2},(oe,G)=>`${`dot(a_data${G}, b_dequantized_values[${G}])`}`).join(" + ")}; - word_offset += ${8/d}; - } - workgroupBarrier(); - } - - if (local_idx < ${b}) { - var output_value: ${ae.type.value} = ${ae.type.value}(0); - for (var b = 0u; b < ${k}; b++) { - output_value += inter_results[local_idx][b]; - } - if (col + local_idx < uniforms.output_shape[2]) - { - ${ae.setByIndices(`${ae.type.indices}(batch, row, col + local_idx)`,"output_value")} - } - } - }`};return{name:"BlockwiseMatMulNBits32",shaderCache:{hint:`${r.blockSize};${d};${u};${k};${b}`,inputDependencies:Array(e.length).fill("rank")},getRunData:()=>({outputs:[{dims:f,dataType:p}],dispatchGroup:{x:T},programUniforms:M}),getShaderSource:F}},yf=(e,r)=>{wf(e.inputs,r),r.blockSize===32&&e.adapterInfo.isVendor("intel")&&e.adapterInfo.isArchitecture("gen-12lp")?e.compute(bf(e.inputs,r)):e.compute(Mf(e.inputs,r))},vf=e=>Kt(e)}),xf,Tf,Ef,Pf,Cf,Sf,$f,kf,If,pT=Ue(()=>{Mt(),Pt(),Ct(),xf=e=>{if(!e||e.length<1)throw new Error("Too few inputs");if(e[0].dataType!==1&&e[0].dataType!==10)throw new Error("Input type must be float or float16.");if(e.length>=2){let r=e[0].dims.length*2===e[1].dims[0];if(e.length===4&&(r=e[3].dims[0]*2===e[1].dims[0]),!r)throw new Error("The pads should be a 1D tensor of shape [2 * input_rank] or [2 * num_axes].")}},Tf=(e,r,t)=>{let s="";for(let o=r-1;o>=0;--o)s+=` - k = i32(${e.indicesGet("indices",o)}) - ${ct("uniforms.pads",o,t)}; - if (k < 0) { - break; - } - if (k >= i32(${ct("uniforms.x_shape",o,r)})) { - break; - } - offset += k * i32(${ct("uniforms.x_strides",o,r)}); - `;return` - value = ${e.type.value}(uniforms.constant_value); - for (var i = 0; i < 1; i++) { - var offset = 0; - var k = 0; - ${s} - value = x[offset]; - } - `},Ef=(e,r,t)=>{let s="";for(let o=r-1;o>=0;--o)s+=` - k = i32(${e.indicesGet("indices",o)}) - ${ct("uniforms.pads",o,t)}; - if (k < 0) { - k = -k; - } - { - let _2n_1 = 2 * (i32(${ct("uniforms.x_shape",o,r)}) - 1); - k = k % _2n_1; - if(k >= i32(${ct("uniforms.x_shape",o,r)})) { - k = _2n_1 - k; - } - } - offset += k * i32(${ct("uniforms.x_strides",o,r)}); - `;return` - var offset = 0; - var k = 0; - ${s} - value = x[offset]; - `},Pf=(e,r,t)=>{let s="";for(let o=r-1;o>=0;--o)s+=` - k = i32(${e.indicesGet("indices",o)}) - ${ct("uniforms.pads",o,t)}; - if (k < 0) { - k = 0; - } - if (k >= i32(${ct("uniforms.x_shape",o,r)})) { - k = i32(${ct("uniforms.x_shape",o,r)}) - 1; - } - offset += k * i32(${ct("uniforms.x_strides",o,r)}); - `;return` - var offset = 0; - var k = 0; - ${s} - value = x[offset]; - `},Cf=(e,r,t)=>{let s="";for(let o=r-1;o>=0;--o)s+=` - k = i32(${e.indicesGet("indices",o)}) - ${ct("uniforms.pads",o,t)}; - if (k < 0) { - k += i32(${ct("uniforms.x_shape",o,r)}]); - } - if (k >= i32(${ct("uniforms.x_shape",o,r)})) { - k -= i32(${ct("uniforms.x_shape",o,r)}); - } - offset += k * i32(${ct("uniforms.x_strides",o,r)}); - `;return` - var offset = 0; - var k = 0; - ${s} - value = x[offset]; - `},Sf=(e,r,t)=>{switch(t.mode){case 0:return Tf(e,r,t.pads.length);case 1:return Ef(e,r,t.pads.length);case 2:return Pf(e,r,t.pads.length);case 3:return Cf(e,r,t.pads.length);default:throw new Error("Invalid mode")}},$f=(e,r)=>{let t=ye.padShape(e[0].dims.slice(),r.pads),s=e[0].dims,o=ye.size(t),n=[{type:12,data:o},{type:6,data:r.pads}],a=e.length>=3&&e[2].data;r.mode===0&&n.push({type:a?e[2].dataType:1,data:r.value}),n.push(...dt(e[0].dims,t));let i=["rank"],l=c=>{let p=nt("output",e[0].dataType,t.length),d=Ie("x",e[0].dataType,s.length),u=d.type.value,f=Sf(p,s.length,r),_=[{name:"output_size",type:"u32"},{name:"pads",type:"i32",length:r.pads.length}];return r.mode===0&&_.push({name:"constant_value",type:a?u:"f32"}),` - ${c.registerUniforms(_).declareVariables(d,p)} - ${c.mainStart()} - ${c.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} - - let indices = ${p.offsetToIndices("global_idx")}; - - var value = ${u}(0); - ${f} - output[global_idx] = value; - }`};return{name:"Pad",shaderCache:{hint:`${r.mode}${a}`,inputDependencies:i},getRunData:()=>({outputs:[{dims:t,dataType:e[0].dataType}],dispatchGroup:{x:Math.ceil(ye.size(t)/64)},programUniforms:n}),getShaderSource:l}},kf=(e,r)=>{if(e.length>1){let t=e[1].getBigInt64Array(),s=e.length>=3&&e[2].data?e[2].dataType===10?e[2].getUint16Array()[0]:e[2].getFloat32Array()[0]:0,o=e[0].dims.length,n=new Int32Array(2*o).fill(0);if(e.length>=4){let i=e[3].getBigInt64Array();for(let l=0;ln[Number(l)]=Number(i));let a=[];return n.forEach(i=>a.push(i)),{mode:r.mode,value:s,pads:a}}else return r},If=(e,r)=>{xf(e.inputs);let t=kf(e.inputs,r);e.compute($f(e.inputs,t),{inputs:[0]})}}),To,Vl,Ul,Wl,Gl,Af,Ff,Kl,Hl,Of,Df,ql,Lf,zf,Ql,Bf,Rf,jf,Nf,mT=Ue(()=>{fs(),Mt(),Pt(),Ct(),To=e=>{if(tr.webgpu.validateInputContent&&(!e||e.length!==1))throw new Error("Pool ops requires 1 input.")},Vl=(e,r,t)=>{let s=r.format==="NHWC",o=e.dims.slice();s&&o.splice(1,0,o.pop());let n=Object.hasOwnProperty.call(r,"dilations"),a=r.kernelShape.slice(),i=r.strides.slice(),l=n?r.dilations.slice():[],c=r.pads.slice();aa.adjustPoolAttributes(t,o,a,i,l,c);let p=aa.computePoolOutputShape(t,o,i,l,a,c,r.autoPad),d=Object.assign({},r);n?Object.assign(d,{kernelShape:a,strides:i,pads:c,dilations:l,cacheKey:r.cacheKey}):Object.assign(d,{kernelShape:a,strides:i,pads:c,cacheKey:r.cacheKey});let u=p.slice();return u.push(u.splice(1,1)[0]),[d,s?u:p]},Ul=(e,r)=>{let t=r.format==="NHWC",s=ye.size(e),o=ye.size(r.kernelShape),n=[{type:12,data:s},{type:12,data:o}],a=[{name:"outputSize",type:"u32"},{name:"kernelSize",type:"u32"}];if(r.kernelShape.length<=2){let i=r.kernelShape[r.kernelShape.length-1],l=r.strides[r.strides.length-1],c=r.pads[r.pads.length/2-1],p=r.pads[r.pads.length-1],d=!!(c+p);n.push({type:12,data:i},{type:12,data:l},{type:12,data:c},{type:12,data:p}),a.push({name:"kw",type:"u32"},{name:"sw",type:"u32"},{name:"pwStart",type:"u32"},{name:"pwEnd",type:"u32"});let u=!1;if(r.kernelShape.length===2){let f=r.kernelShape[r.kernelShape.length-2],_=r.strides[r.strides.length-2],b=r.pads[r.pads.length/2-2],k=r.pads[r.pads.length-2];u=!!(b+k),n.push({type:12,data:f},{type:12,data:_},{type:12,data:b},{type:12,data:k}),a.push({name:"kh",type:"u32"},{name:"sh",type:"u32"},{name:"phStart",type:"u32"},{name:"phEnd",type:"u32"})}return[n,a,!0,d,u]}else{if(t)throw new Error("Pooling with kernelShape.length > 2 is not supported for NHWC format.");let i=ye.computeStrides(r.kernelShape);n.push({type:12,data:i},{type:12,data:r.pads},{type:12,data:r.strides}),a.push({name:"kernelStrides",type:"u32",length:i.length},{name:"pads",type:"u32",length:r.pads.length},{name:"strides",type:"u32",length:r.strides.length});let l=r.pads.reduce((c,p)=>c+p);return[n,a,!!l,!1,!1]}},Wl=(e,r,t,s,o,n,a,i,l,c,p,d)=>{let u=o.format==="NHWC",f=r.type.value,_=nt("output",r.type.tensor,s);if(o.kernelShape.length<=2){let b="",k="",w="",y=t-(u?2:1);if(p?b=` - for (var i: u32 = 0u; i < uniforms.kw; i++) { - xIndices[${y}] = indices[${y}] * uniforms.sw - uniforms.pwStart + i; - if (xIndices[${y}] < 0 || xIndices[${y}] - >= uniforms.x_shape[${y}]) { - pad++; - continue; - } - let x_val = x[${r.indicesToOffset("xIndices")}]; - ${n} - }`:b=` - for (var i: u32 = 0u; i < uniforms.kw; i++) { - xIndices[${y}] = indices[${y}] * uniforms.sw - uniforms.pwStart + i; - let x_val = x[${r.indicesToOffset("xIndices")}]; - ${n} - }`,o.kernelShape.length===2){let $=t-(u?3:2);d?k=` - for (var j: u32 = 0u; j < uniforms.kh; j++) { - xIndices[${$}] = indices[${$}] * uniforms.sh - uniforms.phStart + j; - if (xIndices[${$}] < 0 || xIndices[${$}] >= uniforms.x_shape[${$}]) { - pad += i32(uniforms.kw); - continue; - } - `:k=` - for (var j: u32 = 0u; j < uniforms.kh; j++) { - xIndices[${$}] = indices[${$}] * uniforms.sh - uniforms.phStart + j; - `,w=` - } - `}return` - ${e.registerUniforms(l).declareVariables(r,_)} - - ${e.mainStart()} - ${e.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.outputSize")} - - let indices = ${_.offsetToIndices("global_idx")}; - var xIndices = ${_.offsetToIndices("global_idx")}; - - var value = ${f}(${i}); - var pad = 0; - ${k} - ${b} - ${w} - ${a} - - output[global_idx] = value; - }`}else{if(u)throw new Error("Pooling with kernelShape.length > 2 is not supported for NHWC format.");let b=o.kernelShape.length,k=o.pads.length,w="";return c?w=` - if (xIndices[j] >= uniforms.x_shape[j]) { - pad++; - isPad = true; - break; - } - } - if (!isPad) { - let x_val = x[${r.indicesToOffset("xIndices")}]; - ${n} - }`:w=` - } - let x_val = x[${r.indicesToOffset("xIndices")}]; - ${n} - `,` - ${e.registerUniforms(l).declareVariables(r,_)} - - ${e.mainStart()} - ${e.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.outputSize")} - let indices = ${_.offsetToIndices("global_idx")}; - var xIndices = ${_.offsetToIndices("global_idx")}; - - var offsets: array; - - var value = ${f}(${i}); - var pad = 0; - var isPad = false; - - for (var i: u32 = 0u; i < uniforms.kernelSize; i++) { - var offset = i; - for (var j = 0u; j < ${b-1}u; j++) { - offsets[j] = offset / ${ct("uniforms.kernelStrides","j",b)}; - offset -= offsets[j] * ${ct("uniforms.kernelStrides","j",b)}; - } - offsets[${b-1}] = offset; - - isPad = false; - for (var j = ${t-b}u; j < ${t}u; j++) { - xIndices[j] = indices[j] * ${ct("uniforms.strides",`j - ${t-b}u`,b)} - + offsets[j - ${t-b}u] - ${ct("uniforms.pads","j - 2u",k)}; - ${w} - } - ${a} - - output[global_idx] = value; - }`}},Gl=e=>`${e.format};${e.ceilMode};${e.autoPad};${e.kernelShape.length}`,Af=e=>`${Gl(e)};${e.countIncludePad}`,Ff=e=>`${Gl(e)};${e.storageOrder};${e.dilations}`,Kl=e=>({format:e.format,autoPad:["NOTSET","VALID","SAME_UPPER","SAME_LOWER"][e.auto_pad],ceilMode:e.ceil_mode,kernelShape:e.kernel_shape,strides:e.strides,pads:e.pads}),Hl=(e,r,t,s)=>{let[o,n]=Vl(r,s,t),a=Ie("x",r.dataType,r.dims.length),i=a.type.value,l="value += x_val;",c="";o.countIncludePad?c+=`value /= ${i}(uniforms.kernelSize);`:c+=`value /= ${i}(i32(uniforms.kernelSize) - pad);`;let[p,d,u,f,_]=Ul(n,o);p.push(...dt(r.dims,n));let b=["rank"];return{name:e,shaderCache:{hint:`${s.cacheKey};${u};${f};${_}`,inputDependencies:b},getRunData:()=>({outputs:[{dims:n,dataType:r.dataType}],dispatchGroup:{x:Math.ceil(ye.size(n)/64)},programUniforms:p}),getShaderSource:k=>Wl(k,a,r.dims.length,n.length,o,l,c,0,d,u,f,_)}},Of=e=>{let r=e.count_include_pad!==0,t=Kl(e);if(t.ceilMode!==0)throw new Error("using ceil() in shape computation is not yet supported for AveragePool");let s={countIncludePad:r,...t,cacheKey:""};return{...s,cacheKey:Af(s)}},Df=(e,r)=>{To(e.inputs),e.compute(Hl("AveragePool",e.inputs[0],!1,r))},ql={autoPad:"",ceilMode:0,countIncludePad:!1,kernelShape:[],strides:[],pads:[],storageOrder:0,dilations:[]},Lf=e=>{let r=e.format;return{format:r,...ql,cacheKey:r}},zf=(e,r)=>{To(e.inputs),e.compute(Hl("GlobalAveragePool",e.inputs[0],!0,r))},Ql=(e,r,t,s)=>{let[o,n]=Vl(r,s,t),a=` - value = max(x_val, value); - `,i="",l=Ie("x",r.dataType,r.dims.length),c=["rank"],[p,d,u,f,_]=Ul(n,o);return p.push(...dt(r.dims,n)),{name:e,shaderCache:{hint:`${s.cacheKey};${u};${f};${_}`,inputDependencies:c},getRunData:()=>({outputs:[{dims:n,dataType:r.dataType}],dispatchGroup:{x:Math.ceil(ye.size(n)/64)},programUniforms:p}),getShaderSource:b=>Wl(b,l,r.dims.length,n.length,o,a,i,r.dataType===10?-65504:-1e5,d,u,f,_)}},Bf=(e,r)=>{To(e.inputs),e.compute(Ql("MaxPool",e.inputs[0],!1,r))},Rf=e=>{let r=e.storage_order,t=e.dilations,s=Kl(e);if(r!==0)throw new Error("column major storage order is not yet supported for MaxPool");if(s.ceilMode!==0)throw new Error("using ceil() in shape computation is not yet supported for MaxPool");let o={storageOrder:r,dilations:t,...s,cacheKey:""};return{...o,cacheKey:Ff(o)}},jf=e=>{let r=e.format;return{format:r,...ql,cacheKey:r}},Nf=(e,r)=>{To(e.inputs),e.compute(Ql("GlobalMaxPool",e.inputs[0],!0,r))}}),Vf,Uf,Wf,Gf,hT=Ue(()=>{Mt(),Pt(),pr(),Ct(),Vf=(e,r)=>{if(e.length<2||e.length>3)throw new Error("DequantizeLinear requires 2 or 3 inputs.");if(e.length===3&&e[1].dims===e[2].dims)throw new Error("x-scale and x-zero-point must have the same shape.");if(e.length===3&&e[0].dataType!==e[2].dataType)throw new Error("x and x-zero-point must have the same data type.");if(e[0].dataType===6&&e.length>2)throw new Error("In the case of dequantizing int32 there is no zero point.");if(e[1].dims.length!==0&&e[1].dims.length!==1&&e[1].dims.length!==e[0].dims.length)throw new Error("scale input must be a scalar, a 1D tensor, or have the same rank as the input tensor.");if(e.length>2){if(e[0].dataType!==e[2].dataType)throw new Error("x and x-zero-point must have the same data type.");if(e[1].dims.length!==e[2].dims.length)throw new Error("scale and zero-point inputs must have the same rank.");if(!e[1].dims.map((t,s)=>t===e[2].dims[s]).reduce((t,s)=>t&&s,!0))throw new Error("scale and zero-point inputs must have the same shape.")}if(r.blockSize>0){if(e[1].dims.length===0||e[1].dims.length===1&&e[1].dims[0]===1)throw new Error("blockSize must be set only for block quantization.");if(!e[1].dims.map((o,n)=>n===r.axis||o===e[0].dims[n]).reduce((o,n)=>o&&n,!0))throw new Error("For block qunatization, scale input shape to match the input shape except for the axis");if(e[1].dims.length!==e[0].dims.length)throw new Error("For block qunatization the scale input rank must be the same as the x rank.");let t=e[0].dims[r.axis],s=e[1].dims[r.axis];if(r.blockSizeMath.ceil(t/(s-1)-1))throw new Error("blockSize must be with in the range [ceil(dI / Si), ceil(dI / (Si - 1) - 1)].")}},Uf=(e,r)=>{let t=ye.normalizeAxis(r.axis,e[0].dims.length),s=e[0].dataType,o=s===3,n=e[0].dims,a=e[1].dataType,i=ye.size(n),l=s===3||s===2,c=l?[Math.ceil(ye.size(e[0].dims)/4)]:e[0].dims,p=e[1].dims,d=e.length>2?e[2]:void 0,u=d?l?[Math.ceil(ye.size(d.dims)/4)]:d.dims:void 0,f=p.length===0||p.length===1&&p[0]===1,_=f===!1&&p.length===1,b=lr(i),k=f&&(!l||b===4),w=k?b:1,y=k&&!l?b:1,$=Ie("input",l?12:s,c.length,y),T=Ie("scale",a,p.length),M=d?Ie("zero_point",l?12:s,u.length):void 0,x=nt("output",a,n.length,w),v=[$,T];M&&v.push(M);let C=[c,p];d&&C.push(u);let F=[{type:12,data:i/w},{type:12,data:t},{type:12,data:r.blockSize},...dt(...C,n)],D=K=>{let U=[{name:"output_size",type:"u32"},{name:"axis",type:"u32"},{name:"block_size",type:"u32"}];return` - ${K.registerUniforms(U).declareVariables(...v,x)} - ${K.mainStart()} - ${K.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} - let output_indices = ${x.offsetToIndices("global_idx")}; - - // Set input x - ${l?` - let input = ${$.getByOffset("global_idx / 4")}; - let x_vec = ${o?"unpack4xI8(input)":"unpack4xU8(input)"}; - let x_value = ${w===1?"x_vec[global_idx % 4]":"x_vec"};`:`let x_value = ${$.getByOffset("global_idx")};`}; - - // Set scale input - ${f?`let scale_value= ${T.getByOffset("0")}`:_?` - let scale_index = ${x.indicesGet("output_indices","uniforms.axis")}; - let scale_value= ${T.getByOffset("scale_index")};`:` - var scale_indices: ${T.type.indices} = output_indices; - let index = ${T.indicesGet("scale_indices","uniforms.axis")} / uniforms.block_size; - ${T.indicesSet("scale_indices","uniforms.axis","index")}; - let scale_value= ${T.getByIndices("scale_indices")};`}; - - // Set zero-point input - ${M?f?l?` - let zero_point_input = ${M.getByOffset("0")}; - let zero_point_vec = ${o?"unpack4xI8(zero_point_input)":"unpack4xU8(zero_point_input)"}; - let zero_point_value= zero_point_vec[0]`:`let zero_point_value = ${M.getByOffset("0")}`:_?l?` - let zero_point_index = ${x.indicesGet("output_indices","uniforms.axis")}; - let zero_point_input = ${M.getByOffset("zero_point_index / 4")}; - let zero_point_vec = ${o?"unpack4xI8(zero_point_input)":"unpack4xU8(zero_point_input)"}; - let zero_point_value = zero_point_vec[zero_point_index % 4]`:` - let zero_point_index = ${x.indicesGet("output_indices","uniforms.axis")}; - let zero_point_value = ${M.getByOffset("zero_point_index")};`:l?` - let zero_point_offset = ${T.indicesToOffset("scale_indices")}; - let zero_point_input = ${M.getByOffset("zero_point_offset / 4")}; - let zero_point_vec = ${o?"unpack4xI8(zero_point_input)":"unpack4xU8(zero_point_input)"}; - let zero_point_value = zero_point_vec[zero_point_offset % 4];`:`let zero_point_value = ${M.getByIndices("scale_indices")};`:`let zero_point_value = ${l?o?"i32":"u32":$.type.value}(0);`}; - // Compute and write output - ${x.setByOffset("global_idx",`${x.type.value}(x_value - zero_point_value) * scale_value`)}; - }`};return{name:"DequantizeLinear",shaderCache:{hint:r.cacheKey,inputDependencies:M?["rank","rank","rank"]:["rank","rank"]},getShaderSource:D,getRunData:()=>({outputs:[{dims:n,dataType:a}],dispatchGroup:{x:Math.ceil(i/w/64),y:1,z:1},programUniforms:F})}},Wf=(e,r)=>{Vf(e.inputs,r),e.compute(Uf(e.inputs,r))},Gf=e=>Kt({axis:e.axis,blockSize:e.blockSize})}),Kf,Hf,qf,_T=Ue(()=>{fs(),Mt(),Ct(),Kf=(e,r,t)=>{let s=e===r,o=er&&t>0;if(s||o||n)throw new Error("Range these inputs' contents are invalid.")},Hf=(e,r,t,s)=>{let o=Math.abs(Math.ceil((r-e)/t)),n=[o],a=o,i=[{type:12,data:a},{type:s,data:e},{type:s,data:t},...dt(n)],l=c=>{let p=nt("output",s,n.length),d=p.type.value,u=[{name:"outputSize",type:"u32"},{name:"start",type:d},{name:"delta",type:d}];return` - ${c.registerUniforms(u).declareVariables(p)} - ${c.mainStart()} - ${c.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.outputSize")} - output[global_idx] = uniforms.start + ${d}(global_idx) * uniforms.delta; - }`};return{name:"Range",shaderCache:{hint:`${s}`},getShaderSource:l,getRunData:()=>({outputs:[{dims:n,dataType:s}],dispatchGroup:{x:Math.ceil(a/64)},programUniforms:i})}},qf=e=>{let r=0,t=0,s=0;e.inputs[0].dataType===6?(r=e.inputs[0].getInt32Array()[0],t=e.inputs[1].getInt32Array()[0],s=e.inputs[2].getInt32Array()[0]):e.inputs[0].dataType===1&&(r=e.inputs[0].getFloat32Array()[0],t=e.inputs[1].getFloat32Array()[0],s=e.inputs[2].getFloat32Array()[0]),tr.webgpu.validateInputContent&&Kf(r,t,s),e.compute(Hf(r,t,s,e.inputs[0].dataType),{inputs:[]})}}),Qf,Xl,Jl,Xf,Jf,Yf,fT=Ue(()=>{Mt(),Pt(),pr(),Ct(),Qf=(e,r,t,s)=>{if(e!=="none"&&s!=="i32"&&s!=="u32"&&s!=="f32")throw new Error(`Input ${s} is not supported with reduction ${e}.`);let o=`{ - var oldValue = 0; - loop { - let newValueF32 =`,n=`; - let newValue = bitcast(newValueF32); - let res = atomicCompareExchangeWeak(&${r}, oldValue, newValue); - if res.exchanged { - break; - } - oldValue = res.old_value; - } - }`;switch(e){case"none":return`${r}=${t};`;case"add":return s==="i32"||s==="u32"?`atomicAdd(&${r}, bitcast<${s}>(${t}));`:` - ${o}bitcast<${s}>(oldValue) + (${t})${n}`;case"max":return s==="i32"||s==="u32"?`atomicMax(&${r}, bitcast<${s}>(${t}));`:` - ${o}max(bitcast(oldValue), (${t}))${n}`;case"min":return s==="i32"||s==="u32"?`atomicMin(&${r}, bitcast<${s}>(${t}));`:`${o}min(bitcast<${s}>(oldValue), (${t}))${n}`;case"mul":return`${o}(bitcast<${s}>(oldValue) * (${t}))${n}`;default:throw new Error(`Reduction ${e} is not supported.`)}},Xl=(e,r)=>`${e===1?` - let element_count_dim = uniforms.output_strides; - let dim_value = uniforms.output_shape;`:` - let element_count_dim = uniforms.output_strides[${r?"i - indices_start":"i"}]; - let dim_value = uniforms.output_shape[${r?"i - indices_start":"i"} + uniforms.last_index_dimension];`} - - if (index >= 0) { - if (index >= i32(dim_value)) { - index = i32(dim_value - 1); - } - } else { - if (index < -i32(dim_value)) { - index = 0; - } else { - index += i32(dim_value); - } - } - data_offset += u32((u32(index) * element_count_dim));`,Jl=(e,r,t)=>`for (var i = 0u; i < uniforms.num_updates_elements; i++) { - let value = updates[uniforms.num_updates_elements * ${t?"global_idx":"idx"} + i]; - ${Qf(e.reduction,"output[data_offset + i]","value",r)} - }`,Xf=(e,r)=>{let t=e[0].dims,s=e[1].dims,o=t,n=1,a=Math.ceil(ye.size(s)/n),i=s[s.length-1],l=ye.sizeFromDimension(t,i),c=ye.sizeFromDimension(s,0)/i,p=[{type:12,data:a},{type:12,data:i},{type:12,data:l},...dt(e[1].dims,e[2].dims,o)],d=u=>{let f=Ie("indices",e[1].dataType,e[1].dims.length),_=Ie("updates",e[2].dataType,e[2].dims.length,n),b=r.reduction!=="none"&&r.reduction!==""?sp("output",e[0].dataType,o.length):nt("output",e[0].dataType,o.length,n);return` - ${u.registerUniform("output_size","u32").registerUniform("last_index_dimension","u32").registerUniform("num_updates_elements","u32").declareVariables(f,_,b)} - ${u.mainStart()} - ${u.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} - var hasDuplicates = false; - if (${r.reduction==="none"}) { - for (var i = 0; i < ${c}; i = i + 1) { - for (var j = i + 1; j < ${c}; j = j + 1) { - var index_i = i32(indices[i].x); - var index_j = i32(indices[j].x); - if (index_i == index_j) { - hasDuplicates = true; - break; - } - } - if (hasDuplicates) { - break; - } - } - } - - if (${r.reduction==="none"} && hasDuplicates) { - if (global_idx != 0u) { - return; - } - // Process each index-update pair individually when duplicates exist - for (var idx = 0u; idx < ${c}u; idx++) { - var data_offset = 0u; - for (var i = 0u; i < uniforms.last_index_dimension; i++) { - var index = i32(indices[idx * uniforms.last_index_dimension + i].x); - ${Xl(t.length,!1)} - } - ${Jl(r,b.type.value,!1)} - } - return; - } - - var data_offset = 0u; - var indices_start = uniforms.last_index_dimension * global_idx; - var indices_end = indices_start + uniforms.last_index_dimension; - for (var i = indices_start; i < indices_end; i++) { - var index = i32(indices[i].x); - ${Xl(t.length,!0)} - } - ${Jl(r,b.type.value,!0)} - }`};return{name:"ScatterND",shaderCache:{hint:`${r.cacheKey}_${r.reduction}`,inputDependencies:["rank","rank"]},getRunData:()=>({outputs:[{dims:o,dataType:e[0].dataType}],dispatchGroup:{x:Math.ceil(a/64)},programUniforms:p}),getShaderSource:d}},Jf=e=>Kt({reduction:e.reduction}),Yf=(e,r)=>{e.compute(Xf(e.inputs,r),{inputs:[e.inputs[1],e.inputs[2]],outputs:[]})}}),Zf,eg,tg,Yl,rg,sg,ng,og,ag,ig,lg,cg,Zl,ug,dg,pg,mg,hg,_g,fg,gT=Ue(()=>{Mt(),Pt(),pr(),Ct(),Zf=(e,r)=>{if(e.every(t=>t>0||(()=>{throw new Error("Resize requires scales input values to be positive")})),e.length>0){if(r.mode==="linear"){if(!(e.length===2||e.length===3||e.length===4&&e[0]===1&&e[1]===1||e.length===4&&e[0]===1&&e[3]===1||e.length===5&&e[0]===1&&e[1]===1))throw new Error(`For linear mode, Resize requires scales to be 2D, 3D, 4D with either two outermost or one innermost and - one outermost scale values equal to 1, or 5D with two outermost scale values equal to 1`)}else if(r.mode==="cubic"&&!(e.length===2||e.length===4&&e[0]===1&&e[1]===1||e.length===4&&e[0]===1&&e[3]===1))throw new Error("Resize requires scales input size to be 2 or 4 for cubic mode")}},eg=(e,r,t)=>{r.every(o=>o>=0&&o{throw new Error("Resize requires axes input values to be positive and less than rank")}));let s=new Array(t).fill(1);return r.forEach((o,n)=>s[o]=e[n]),s},tg=(e,r,t,s,o,n)=>{let[a,i,l]=t>10?[1,2,3]:[-1,e.length>1?1:-1,-1],c=e[0].dims.length;if(a>0&&e.length>a&&e[a].dims.length>0)e[a].getFloat32Array().forEach(p=>n.push(p));else if(r.coordinateTransformMode==="tf_crop_and_resize")throw new Error("Resize requires RoI input to be specified when coordinateTransformMode is tfCropAndResize");if(i>0&&e.length>i&&e[i].dims.length===1&&e[i].dims[0]>0){if(e[i].getFloat32Array().forEach(p=>s.push(p)),s.length!==0&&s.length!==c&&t>=18&&s.length!==r.axes.length)throw new Error("Resize requires scales input size to be same as input rank or axes size for opset 18 and up");Zf(s,r),r.axes.length>0&&eg(s,r.axes,c).forEach((p,d)=>s[d]=p)}if(l>0&&e.length>l&&e[l].dims.length===1&&e[l].dims[0]>0&&(e[l].getBigInt64Array().forEach(p=>o.push(Number(p))),o.length!==0&&o.length!==c&&t>=18&&o.length!==r.axes.length))throw new Error("Resize requires sizes input size to be same as input rank or axes size for opset 18 and up");if(r.axes.length>0){if(s.length!==0&&s.length!==r.axes.length)throw new Error('Resize requires "scales" input size to be of axes rank when axes attributes is specified');if(o.length!==0&&o.length!==r.axes.length)throw new Error('Resize requires "sizes" input size to be of rank axes rank when axes attributes is specified')}if(typeof s<"u"&&typeof o<"u"&&s.length>0&&o.length>c)throw new Error("Resize requires only of scales or sizes to be specified")},Yl=(e,r,t,s)=>` - // The whole part and the fractional part are calculated separately due to inaccuracy of floating - // point division. As an example, f32(21) / f32(7) may evaluate to 2.99... instead of 3, causing an - // offset-by-one error later in floor(). - let big = (${e}) * (${r}); - let whole = ${s}(big / (${t})); - let fract = ${s}(big % (${t})) / ${s}(${t}); - return whole + fract; -`,rg=(e,r)=>`fn getOriginalCoordinateFromResizedCoordinate(xResized: u32, xScale: f32, lengthResized: u32, - lengthOriginal: u32, roiStart: f32, roiEnd: f32) -> ${r} { `+(()=>{switch(e){case"asymmetric":return` - if (xScale < 1.0 || floor(xScale) != xScale) { - return ${r}(xResized) / ${r}(xScale); - } else { - ${Yl("xResized","lengthOriginal","lengthResized",r)} - } - `;case"pytorch_half_pixel":return`if (lengthResized > 1) { - return (${r}(xResized) + 0.5) / ${r}(xScale) - 0.5; - } else { - return 0.0; - }`;case"tf_half_pixel_for_nn":return`return (${r}(xResized) + 0.5) / ${r}(xScale);`;case"align_corners":return`if (lengthResized == 1) { - return 0.0; - } else { - ${Yl("xResized","lengthOriginal - 1","lengthResized - 1",r)} - }`;case"tf_crop_and_resize":return`if (lengthResized > 1) { - return ${r}(roiStart) * ${r}(lengthOriginal - 1) + - (${r}(xResized) * ${r}(roiEnd - roiStart) * ${r}(lengthOriginal - 1)) / - ${r}(lengthResized - 1); - } else { - return 0.5 * ${r}(roiStart + roiEnd) * ${r}(lengthOriginal - 1); - }`;case"half_pixel_symmetric":return`const outputWidth = ${r}xScale * ${r}(lengthResized); - const adjustment = ${r}(lengthResized) / outputWidth; - const center = ${r}(lengthOriginal) / 2; - const offset = center * (1 - adjustment); - return offset + ((${r}(xResized) + 0.5) / ${r}(xScale)) - 0.5;`;case"half_pixel":return`return ((${r}(xResized) + 0.5) / ${r}(xScale)) - 0.5;`;default:throw new Error(`Coordinate transform mode ${e} is not supported`)}})()+"}",sg=(e,r,t)=>`fn getNearestPixelFromOriginal(xOriginal: ${t}, isDownSample: bool) -> ${t} {`+(()=>{switch(e){case"round_prefer_ceil":return"if (fract(xOriginal) == 0.5) { return ceil(xOriginal); } else { return round(xOriginal); }";case"floor":return"return floor(xOriginal);";case"ceil":return"return ceil(xOriginal);";case"round_prefer_floor":return"if (fract(xOriginal) == 0.5) { return floor(xOriginal); } else { return round(xOriginal); }";case"simple":default:if(r<11)return"if (isDownSample) { return ceil(xOriginal); } else { return xOriginal; }";throw new Error(`Nearest mode ${e} is not supported`)}})()+"}",ng=(e,r,t)=>{let s=new Array(t).fill(0).concat(new Array(t).fill(1)),o=e.length===0?s:e.slice();return r.length>0?(r.forEach((n,a)=>{s[n]=o[a],s[a+t]=o[r.length+a]}),s):o},og=(e,r,t,s)=>{let o=[];if(t.length>0)if(s.length>0){if(e.forEach(n=>o.push(n)),Math.max(...s)>e.length)throw new Error("axes is out of bound");s.forEach((n,a)=>o[n]=t[a])}else t.forEach(n=>o.push(n));else{if(r.length===0)throw new Error("Resize requires either scales or sizes.");o=e.map((n,a)=>Math.round(n*r[a]))}return o},ag=(e,r,t)=>{let s=(()=>{switch(t.keepAspectRatioPolicy){case"not_larger":return t.axes.length>0?Math.min(...t.axes.map(n=>r[n]),Number.MAX_VALUE):Math.min(...r,Number.MAX_VALUE);case"not_smaller":return t.axes.length>0?Math.max(...t.axes.map(n=>r[n]),Number.MIN_VALUE):Math.max(...r,Number.MIN_VALUE);default:throw new Error(`Keep aspect ratio policy ${t.keepAspectRatioPolicy} is not supported`)}})();r.fill(1,0,r.length);let o=e.slice();return t.axes.length>0?(t.axes.forEach(n=>r[n]=s),t.axes.forEach(n=>o[n]=Math.round(e[n]*r[n]))):(r.fill(s,0,r.length),o.forEach((n,a)=>o[a]=Math.round(n*r[a]))),o},ig=(e,r,t,s,o)=>` - fn calculateOriginalIndicesFromOutputIndices(output_indices: ${e.type.indices}) -> array<${e.type.value}, ${t.length}> { - var original_indices: array<${e.type.value}, ${t.length}>; - for (var i:u32 = 0; i < ${t.length}; i++) { - var output_index = ${e.indicesGet("output_indices","i")}; - var scale = ${ct("uniforms.scales","i",s)}; - var roi_low = ${ct("uniforms.roi","i",o)}; - var roi_hi = ${ct("uniforms.roi",`i + ${r.length}`,o)}; - if (scale == 1.0) { - original_indices[i] = ${e.type.value}(output_index); - } else { - var input_shape_i = ${ct("uniforms.input_shape","i",r.length)}; - var output_shape_i = ${ct("uniforms.output_shape","i",t.length)}; - original_indices[i] = getOriginalCoordinateFromResizedCoordinate(output_index, scale, output_shape_i, - input_shape_i, roi_low, roi_hi); - } - } - return original_indices; - }`,lg=(e,r,t,s,o,n,a)=>` - fn calculateInputIndicesFromOutputIndices(output_indices: ${r.type.indices}) -> ${e.type.indices} { - var input_indices: ${e.type.indices}; - for (var i:u32 = 0; i < ${s.length}; i++) { - var output_index = ${r.indicesGet("output_indices","i")}; - var input_index: u32; - var scale = ${ct("uniforms.scales","i",o)}; - if (scale == 1.0) { - input_index = output_index; - } else { - var roi_low = ${ct("uniforms.roi","i",n)}; - var roi_hi = ${ct("uniforms.roi",`i + ${t.length}`,n)}; - var input_shape_i = ${ct("uniforms.input_shape","i",t.length)}; - var output_shape_i = ${ct("uniforms.output_shape","i",s.length)}; - var original_idx = getOriginalCoordinateFromResizedCoordinate(output_index, scale, output_shape_i, - input_shape_i, roi_low, roi_hi); - if (!${a} || (original_idx >= 0 && original_idx < ${r.type.value}(input_shape_i))) { - if (original_idx < 0) { - input_index = 0; - } else if (original_idx > ${r.type.value}(input_shape_i - 1)) { - input_index = input_shape_i - 1; - } else { - input_index = u32(getNearestPixelFromOriginal(original_idx, scale < 1)); - } - } else { - input_index = u32(original_idx); - } - } - ${e.indicesSet("input_indices","i","input_index")} - } - return input_indices; - }`,cg=(e,r)=>` - fn checkInputIndices(input_indices: ${e.type.indices}) -> bool { - for (var i:u32 = 0; i < ${r.length}; i++) { - var input_index = ${e.indicesGet("input_indices","i")}; - if (input_index < 0 || input_index >= ${ct("uniforms.input_shape","i",r.length)}) { - return false; - } - } - return true; - }`,Zl=(e,r,t,s)=>e.rank>s?` - ${e.indicesSet("input_indices",r,"channel")}; - ${e.indicesSet("input_indices",t,"batch")}; -`:"",ug=(e,r,t,s,o)=>{let[n,a,i,l]=t.length===2?[-1,0,1,-1]:[0,2,3,1],c=e.type.value;return` - fn getInputValue(batch: u32, channel: u32, row: u32, col: u32) -> ${c} { - var input_indices: ${e.type.indices}; - ${e.indicesSet("input_indices",a,`max(0, min(row, ${t[a]} - 1))`)}; - ${e.indicesSet("input_indices",i,`max(0, min(col, ${t[i]} - 1))`)}; - ${Zl(e,l,n,2)} - return ${e.getByIndices("input_indices")}; - } - - fn bilinearInterpolation(output_indices: ${r.type.indices}) -> ${c} { - var originalIndices = calculateOriginalIndicesFromOutputIndices(output_indices); - var row:${c} = originalIndices[${a}]; - var col:${c} = originalIndices[${i}]; - ${s?`if (row < 0 || row > (${t[a]} - 1) || col < 0 || col > (${t[i]} - 1)) { - return ${o}; - }`:""}; - row = max(0, min(row, ${t[a]} - 1)); - col = max(0, min(col, ${t[i]} - 1)); - var row1: u32 = u32(row); - var col1: u32 = u32(col); - var row2: u32 = u32(row + 1); - var col2: u32 = u32(col + 1); - var channel: u32 = ${t.length>2?`u32(originalIndices[${l}])`:"0"}; - var batch: u32 = ${t.length>2?`u32(originalIndices[${n}])`:"0"}; - var x11: ${c} = getInputValue(batch, channel, row1, col1); - var x12: ${c} = getInputValue(batch, channel, row1, col2); - var x21: ${c} = getInputValue(batch, channel, row2, col1); - var x22: ${c} = getInputValue(batch, channel, row2, col2); - var dx1: ${c} = abs(row - ${c}(row1)); - var dx2: ${c} = abs(${c}(row2) - row); - var dy1: ${c} = abs(col - ${c}(col1)); - var dy2: ${c} = abs(${c}(col2) - col); - if (row1 == row2) { - dx1 = 0.5; - dx2 = 0.5; - } - if (col1 == col2) { - dy1 = 0.5; - dy2 = 0.5; - } - return (x11 * dx2 * dy2 + x12 * dx2 * dy1 + x21 * dx1 * dy2 + x22 * dx1 * dy1); - }`},dg=(e,r,t,s,o,n,a,i,l,c)=>{let p=t.length===2,[d,u]=p?[0,1]:[2,3],f=e.type.value,_=b=>{let k=b===d?"row":"col";return` - fn ${k}CubicInterpolation(input_indices: ${e.type.indices}, output_indices: ${r.type.indices}) -> ${f} { - var output_index = ${r.indicesGet("output_indices",b)}; - var originalIdx: ${f} = getOriginalCoordinateFromResizedCoordinate(output_index, ${o[b]}, - ${s[b]}, ${t[b]}, ${n[b]}, ${n[b]} + ${t.length}); - var fractOriginalIdx: ${f} = originalIdx - floor(originalIdx); - var coefs = getCubicInterpolationCoefs(fractOriginalIdx); - - if (${i} && (originalIdx < 0 || originalIdx > (${t[b]} - 1))) { - return ${l}; - } - var data: array<${f}, 4> = array<${f}, 4>(0.0, 0.0, 0.0, 0.0); - for (var i: i32 = -1; i < 3; i++) { - var ${k}: ${f} = originalIdx + ${f}(i); - if (${k} < 0 || ${k} >= ${t[b]}) { - ${c?`coefs[i + 1] = 0.0; - continue;`:i?`return ${l};`:`${k} = max(0, min(${k}, ${t[b]} - 1));`}; - } - var input_indices_copy: ${e.type.indices} = input_indices; - ${e.indicesSet("input_indices_copy",b,`u32(${k})`)}; - data[i + 1] = ${b===d?e.getByIndices("input_indices_copy"):"rowCubicInterpolation(input_indices_copy, output_indices)"}; - } - return cubicInterpolation1D(data, coefs); - }`};return` - ${_(d)}; - ${_(u)}; - fn getCubicInterpolationCoefs(s: ${f}) -> array<${f}, 4> { - var absS = abs(s); - var coeffs: array<${f}, 4> = array<${f}, 4>(0.0, 0.0, 0.0, 0.0); - var oneMinusAbsS: ${f} = 1.0 - absS; - var twoMinusAbsS: ${f} = 2.0 - absS; - var onePlusAbsS: ${f} = 1.0 + absS; - coeffs[0] = ((${a} * onePlusAbsS - 5 * ${a}) * onePlusAbsS + 8 * ${a}) * onePlusAbsS - 4 * ${a}; - coeffs[1] = ((${a} + 2) * absS - (${a} + 3)) * absS * absS + 1; - coeffs[2] = ((${a} + 2) * oneMinusAbsS - (${a} + 3)) * oneMinusAbsS * oneMinusAbsS + 1; - coeffs[3] = ((${a} * twoMinusAbsS - 5 * ${a}) * twoMinusAbsS + 8 * ${a}) * twoMinusAbsS - 4 * ${a}; - return coeffs; - } - - fn cubicInterpolation1D(x: array<${f}, 4>, coefs: array<${f}, 4>) -> ${f} { - var coefsSum: ${f} = coefs[0] + coefs[1] + coefs[2] + coefs[3]; - return (x[0] * coefs[0] + x[1] * coefs[1]+ x[2] * coefs[2]+ x[3] * coefs[3]) / coefsSum; - } - - fn bicubicInterpolation(output_indices: ${r.type.indices}) -> ${f} { - var input_indices: ${e.type.indices} = output_indices; - return colCubicInterpolation(input_indices, output_indices); - } - `},pg=(e,r,t,s,o)=>{let[n,a,i,l,c]=t.length===3?[-1,0,1,2,-1]:[0,2,3,4,1],p=e.type.value;return` - fn getInputValue(batch: u32, channel: u32, depth:u32, height: u32, width: u32) -> ${p} { - var input_indices: ${e.type.indices}; - ${e.indicesSet("input_indices",a,`max(0, min(depth, ${t[a]} - 1))`)}; - ${e.indicesSet("input_indices",i,`max(0, min(height, ${t[i]} - 1))`)}; - ${e.indicesSet("input_indices",l,`max(0, min(width, ${t[l]} - 1))`)}; - ${Zl(e,c,n,3)} - return ${e.getByIndices("input_indices")}; - } - - fn trilinearInterpolation(output_indices: ${r.type.indices}) -> ${p} { - var originalIndices = calculateOriginalIndicesFromOutputIndices(output_indices); - var depth:${p} = originalIndices[${a}]; - var height:${p} = originalIndices[${i}]; - var width:${p} = originalIndices[${l}]; - ${s?`if (depth < 0 || depth > (${t[a]} - 1) || height < 0 || height > (${t[i]} - 1) || width < 0 || (width > ${t[l]} - 1)) { - return ${o}; - }`:""}; - - depth = max(0, min(depth, ${t[a]} - 1)); - height = max(0, min(height, ${t[i]} - 1)); - width = max(0, min(width, ${t[l]} - 1)); - var depth1: u32 = u32(depth); - var height1: u32 = u32(height); - var width1: u32 = u32(width); - var depth2: u32 = u32(depth + 1); - var height2: u32 = u32(height + 1); - var width2: u32 = u32(width + 1); - var channel: u32 = ${t.length>3?`u32(originalIndices[${c}])`:"0"}; - var batch: u32 = ${t.length>3?`u32(originalIndices[${n}])`:"0"}; - - var x111: ${p} = getInputValue(batch, channel, depth1, height1, width1); - var x112: ${p} = getInputValue(batch, channel, depth1, height1, width2); - var x121: ${p} = getInputValue(batch, channel, depth1, height2, width1); - var x122: ${p} = getInputValue(batch, channel, depth1, height2, width2); - var x211: ${p} = getInputValue(batch, channel, depth2, height1, width1); - var x212: ${p} = getInputValue(batch, channel, depth2, height1, width2); - var x221: ${p} = getInputValue(batch, channel, depth2, height2, width1); - var x222: ${p} = getInputValue(batch, channel, depth2, height2, width2); - var dx1: ${p} = abs(depth - ${p}(depth1)); - var dx2: ${p} = abs(${p}(depth2) - depth); - var dy1: ${p} = abs(height - ${p}(height1)); - var dy2: ${p} = abs(${p}(height2) - height); - var dz1: ${p} = abs(width - ${p}(width1)); - var dz2: ${p} = abs(${p}(width2) - width); - if (depth1 == depth2) { - dx1 = 0.5; - dx2 = 0.5; - } - if (height1 == height2) { - dy1 = 0.5; - dy2 = 0.5; - } - if (width1 == width2) { - dz1 = 0.5; - dz2 = 0.5; - } - return (x111 * dx2 * dy2 * dz2 + x112 * dx2 * dy2 * dz1 + x121 * dx2 * dy1 *dz2 + x122 * dx2 * dy1 * dz1 + - x211 * dx1 * dy2 * dz2 + x212 * dx1 * dy2 * dz1 + x221 * dx1 * dy1 *dz2 + x222 * dx1 * dy1 * dz1); - }`},mg=(e,r,t,s,o,n)=>{let a=e.dims,i=ng(n,r.axes,a.length),l=og(a,s,o,r.axes),c=s.slice();s.length===0&&(c=a.map((y,$)=>y===0?1:l[$]/y),r.keepAspectRatioPolicy!=="stretch"&&(l=ag(a,c,r)));let p=nt("output",e.dataType,l.length),d=Ie("input",e.dataType,a.length),u=ye.size(l),f=a.length===l.length&&a.every((y,$)=>y===l[$]),_=r.coordinateTransformMode==="tf_crop_and_resize",b=r.extrapolationValue,k=d.type.value,w=y=>` - ${f?"":` - ${rg(r.coordinateTransformMode,k)}; - ${(()=>{switch(r.mode){case"nearest":return` - ${cg(d,a)}; - ${sg(r.nearestMode,t,k)}; - ${lg(d,p,a,l,c.length,i.length,_)}; - `;case"linear":return` - ${ig(p,a,l,c.length,i.length)}; - ${(()=>{if(a.length===2||a.length===4)return`${ug(d,p,a,_,b)}`;if(a.length===3||a.length===5)return`${pg(d,p,a,_,b)}`;throw Error("Linear mode only supports input dims 2, 3, 4 and 5 are supported in linear mode.")})()}; - `;case"cubic":return` - ${(()=>{if(a.length===2||a.length===4)return`${dg(d,p,a,l,c,i,r.cubicCoeffA,_,r.extrapolationValue,r.excludeOutside)}`;throw Error("Cubic mode only supports input dims 2 and 4 are supported in linear mode.")})()}; - `;default:throw Error("Invalid resize mode")}})()}; - `} - ${y.registerUniform("output_size","u32").registerUniform("scales","f32",c.length).registerUniform("roi","f32",i.length).declareVariables(d,p)} - ${y.mainStart()} - ${y.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} - ${f?"output[global_idx] = input[global_idx];":` - let output_indices = ${p.offsetToIndices("global_idx")}; - var input_indices: ${d.type.indices}; - ${(()=>{switch(r.mode){case"nearest":return`input_indices = calculateInputIndicesFromOutputIndices(output_indices); - if (checkInputIndices(input_indices)) { - output[global_idx] = ${d.getByIndices("input_indices")}; - } else { - output[global_idx] = ${r.extrapolationValue}; - }`;case"linear":return`output[global_idx] = ${a.length===2||a.length===4?"bilinearInterpolation":"trilinearInterpolation"}(output_indices);`;case"cubic":return"output[global_idx] = bicubicInterpolation(output_indices);";default:throw Error(`Unsupported resize mode: ${r.mode}`)}})()}; -`} - }`;return{name:"Resize",shaderCache:{hint:`${r.cacheKey}|${t}|${c.length>0?r.mode==="cubic"?c:c.length:""}|${o.length>0?o:""}|${i.length>0?i:""}|${f}|${r.mode==="nearest"?a.length:a}`,inputDependencies:["rank"]},getShaderSource:w,getRunData:()=>({outputs:[{dims:l,dataType:e.dataType}],dispatchGroup:{x:Math.ceil(u/64)},programUniforms:[{type:12,data:u},{type:1,data:c},{type:1,data:i},...dt(a,l)]})}},hg=e=>{let r=e.customDataBuffer;return new Uint32Array(r,r.byteOffset,1)[0]},_g=(e,r)=>{let t=[],s=[],o=[],n=hg(e);if(r.antialias!==0)throw Error("Only default value (0) for Antialias attribute is supported");tg(e.inputs,r,n,t,s,o),e.compute(mg(e.inputs[0],r,n,t,s,o),{inputs:[0]})},fg=e=>{let r=e.antialias,t=e.axes,s=e.coordinateTransformMode,o=e.cubicCoeffA,n=e.excludeOutside!==0,a=e.extrapolationValue,i=e.keepAspectRatioPolicy,l=e.mode,c=e.nearestMode===""?"simple":e.nearestMode;return Kt({antialias:r,axes:t,coordinateTransformMode:s,cubicCoeffA:o,excludeOutside:n,extrapolationValue:a,keepAspectRatioPolicy:i,mode:l,nearestMode:c})}}),gg,wg,Mg,wT=Ue(()=>{Mt(),Pt(),Ct(),gg=e=>{if(!e||e.length<3)throw new Error("layerNorm requires at least 3 inputs.");let r=e[0],t=e[1],s=e[2];if(r.dataType!==t.dataType||r.dataType!==s.dataType)throw new Error("All inputs must have the same data type");if(r.dims.length!==3&&r.dims.length!==2)throw new Error("Input must be 2D or 3D");if(t.dims.length!==3&&t.dims.length!==2)throw new Error("Skip must be 2D or 3D");let o=r.dims[r.dims.length-1],n=r.dims[r.dims.length-2];if(t.dims[t.dims.length-1]!==o)throw new Error("Skip must have the same hidden size as input");if(t.dims[t.dims.length-2]!==n)throw new Error("Skip must have the same sequence length as input");if(s.dims.length!==1)throw new Error("Gamma must be 1D");if(s.dims[s.dims.length-1]!==o)throw new Error("Gamma must have the same hidden size as input");if(e.length>3){let a=e[3];if(a.dims.length!==1)throw new Error("Beta must be 1D");if(a.dims[a.dims.length-1]!==o)throw new Error("Beta must have the same hidden size as input")}if(e.length>4){let a=e[4];if(a.dims.length!==1)throw new Error("Bias must be 1D");if(a.dims[a.dims.length-1]!==o)throw new Error("Bias must have the same hidden size as input")}},wg=(e,r,t,s)=>{let o=r.simplified,n=e[0].dims,a=ye.size(n),i=n,l=a,c=n.slice(-1)[0],p=s?n.slice(0,-1).concat(1):[],d=!o&&e.length>3,u=e.length>4,f=s&&t>1,_=s&&t>2,b=t>3,k=64,w=lr(c),y=[{type:12,data:l},{type:12,data:w},{type:12,data:c},{type:1,data:r.epsilon}],$=M=>{let x=[{name:"output_size",type:"u32"},{name:"components",type:"u32"},{name:"hidden_size",type:"u32"},{name:"epsilon",type:"f32"}],v=[Ie("x",e[0].dataType,e[0].dims,w),Ie("skip",e[1].dataType,e[1].dims,w),Ie("gamma",e[2].dataType,e[2].dims,w)];d&&v.push(Ie("beta",e[3].dataType,e[3].dims,w)),u&&v.push(Ie("bias",e[4].dataType,e[4].dims,w)),v.push(nt("output",e[0].dataType,i,w)),f&&v.push(nt("mean_output",1,p)),_&&v.push(nt("inv_std_output",1,p)),b&&v.push(nt("input_skip_bias_sum",e[0].dataType,i,w));let C=Ir(e[0].dataType),F=Ir(1,w);return` - - ${M.registerUniforms(x).declareVariables(...v)} - var sum_shared : array<${F}, ${k}>; - var sum_squared_shared : array<${F}, ${k}>; - - ${M.mainStart([k,1,1])} - let ix = local_id.x; - let iy = global_id.x / ${k}; - - let hidden_size_vectorized: u32 = uniforms.hidden_size / uniforms.components; - var stride = hidden_size_vectorized / ${k}; - let offset = ix * stride + iy * hidden_size_vectorized; - let offset1d = stride * ix; - if (ix == ${k-1}) { - stride = hidden_size_vectorized - stride * ix; - } - for (var i: u32 = 0; i < stride; i++) { - let skip_value = skip[offset + i]; - let bias_value = ${u?"bias[offset1d + i]":C+"(0.0)"}; - let input_value = x[offset + i]; - let value = input_value + skip_value + bias_value; - ${b?"input_skip_bias_sum[offset + i] = value;":""} - output[offset + i] = value; - let f32_value = ${Hn(C,w,"value")}; - sum_shared[ix] += f32_value; - sum_squared_shared[ix] += f32_value * f32_value; - } - workgroupBarrier(); - - var reduce_size : u32 = ${k}; - for (var curr_size = reduce_size >> 1; curr_size > 0; curr_size = reduce_size >> 1) { - reduce_size = curr_size + (reduce_size & 1); - if (ix < curr_size) { - sum_shared[ix] += sum_shared[ix + reduce_size]; - sum_squared_shared[ix] += sum_squared_shared[ix + reduce_size]; - } - workgroupBarrier(); - } - - let sum = sum_shared[0]; - let square_sum = sum_squared_shared[0]; - let mean = ${en("sum",w)} / f32(uniforms.hidden_size); - let inv_std_dev = inverseSqrt(${en("square_sum",w)} / f32(uniforms.hidden_size) ${o?"":"- mean * mean"} + uniforms.epsilon); - ${f?"mean_output[global_idx] = mean;":""} - ${_?"inv_std_output[global_idx] = inv_std_dev;":""} - - for (var i: u32 = 0; i < stride; i++) { - output[offset + i] = (output[offset + i] ${o?"":`- ${C}(mean)`}) * - ${C}(inv_std_dev) * gamma[offset1d + i] - ${d?"+ beta[offset1d + i]":""}; - } - }`},T=[{dims:i,dataType:e[0].dataType}];return t>1&&T.push({dims:p,dataType:1}),t>2&&T.push({dims:p,dataType:1}),t>3&&T.push({dims:n,dataType:e[0].dataType}),{name:"SkipLayerNormalization",shaderCache:{hint:`${w};${f};${_};${b}`,inputDependencies:e.map((M,x)=>"type")},getShaderSource:$,getRunData:()=>({outputs:T,dispatchGroup:{x:Math.ceil(l/c)},programUniforms:y})}},Mg=(e,r)=>{gg(e.inputs);let t=[0];e.outputCount>1&&t.push(-3),e.outputCount>2&&t.push(-3),e.outputCount>3&&t.push(3),e.compute(wg(e.inputs,r,e.outputCount,!1),{outputs:t})}}),bg,Eo,yg,ec,vg,xg,Tg,Eg,MT=Ue(()=>{Mt(),Pt(),pr(),Ct(),bg=(e,r)=>{if(!e||e.length<1)throw new Error("too few inputs");if(r.axes.length!==0){if(r.axes.length!==r.starts.length||r.axes.length!==r.ends.length)throw new Error("axes, starts and ends must have the same length")}else if(r.starts.length!==r.ends.length)throw new Error("starts and ends must have the same length");e.slice(1).forEach((t,s)=>{if(e[s+1].dataType!==6&&e[s+1].dataType!==7)throw new Error(`Input ${s} must be an array of int32 or int64`)})},Eo=(e,r)=>{let t=[];if(e.length>r)if(e[r].dataType===7)e[r].getBigInt64Array().forEach(s=>t.push(Number(s)));else if(e[r].dataType===6)e[r].getInt32Array().forEach(s=>t.push(Number(s)));else throw new Error(`Input ${r} must be an array of int32 or int64`);return t},yg=(e,r)=>{if(e.length>1){let t=Eo(e,1),s=Eo(e,2),o=Eo(e,3);return o.length===0&&(o=[...Array(e[0].dims.length).keys()]),Kt({starts:t,ends:s,axes:o})}else return r},ec=(e,r,t,s,o)=>{let n=e;return e<0&&(n+=t[s[r]]),o[r]<0?Math.max(0,Math.min(n,t[s[r]]-1)):Math.max(0,Math.min(n,t[s[r]]))},vg=(e,r,t)=>`fn calculateInputIndices(output_indices: ${r.type.indices}) -> ${e.type.indices} { - var input_indices: ${e.type.indices}; - var carry = 0u; - for (var i = ${t.length}; i >= 0; i--) { - let input_shape_i = ${ct("uniforms.input_shape","i",t.length)}; - let steps_i = ${ct("uniforms.steps","i",t.length)}; - let signs_i = ${ct("uniforms.signs","i",t.length)}; - let starts_i = ${ct("uniforms.starts","i",t.length)}; - var output_index = ${r.indicesGet("output_indices","i")}; - var input_index = output_index * steps_i + starts_i + carry; - carry = input_index / input_shape_i; - input_index = input_index % input_shape_i; - if (signs_i < 0) { - input_index = input_shape_i - input_index - 1u + starts_i; - } - ${e.indicesSet("input_indices","i","input_index")}; - } - return input_indices; - }`,xg=(e,r)=>{let t=e[0].dims,s=ye.size(t),o=r.axes.length>0?ye.normalizeAxes(r.axes,t.length):[...Array(t.length).keys()],n=Eo(e,4);n.forEach(w=>w!==0||(()=>{throw new Error("step cannot be 0")})),n.length===0&&(n=Array(o.length).fill(1));let a=r.starts.map((w,y)=>ec(w,y,t,o,n)),i=r.ends.map((w,y)=>ec(w,y,t,o,n));if(o.length!==a.length||o.length!==i.length)throw new Error("start, ends and axes should have the same number of elements");if(o.length!==t.length)for(let w=0;wMath.sign(w));n.forEach((w,y,$)=>{if(w<0){let T=(i[y]-a[y])/w,M=a[y],x=M+T*n[y];a[y]=x,i[y]=M,$[y]=-w}});let c=t.slice(0);o.forEach((w,y)=>{c[w]=Math.ceil((i[w]-a[w])/n[w])});let p={dims:c,dataType:e[0].dataType},d=nt("output",e[0].dataType,c.length),u=Ie("input",e[0].dataType,e[0].dims.length),f=ye.size(c),_=[{name:"outputSize",type:"u32"},{name:"starts",type:"u32",length:a.length},{name:"signs",type:"i32",length:l.length},{name:"steps",type:"u32",length:n.length}],b=[{type:12,data:f},{type:12,data:a},{type:6,data:l},{type:12,data:n},...dt(e[0].dims,c)],k=w=>` - ${w.registerUniforms(_).declareVariables(u,d)} - ${vg(u,d,t)} - ${w.mainStart()} - ${w.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.outputSize")} - let output_indices = ${d.offsetToIndices("global_idx")}; - let input_indices = calculateInputIndices(output_indices); - ${d.setByOffset("global_idx",u.getByIndices("input_indices"))} - }`;return{name:"Slice",shaderCache:{hint:`${l.length}_${a.length}_${n.length}`,inputDependencies:["rank"]},getShaderSource:k,getRunData:()=>({outputs:[p],dispatchGroup:{x:Math.ceil(s/64)},programUniforms:b})}},Tg=(e,r)=>{bg(e.inputs,r);let t=yg(e.inputs,r);e.compute(xg(e.inputs,t),{inputs:[0]})},Eg=e=>{let r=e.starts,t=e.ends,s=e.axes;return Kt({starts:r,ends:t,axes:s})}}),Pg,Cg,Sg,$g,bT=Ue(()=>{Mt(),Pt(),pr(),tn(),Ct(),Pg=e=>{if(!e||e.length!==1)throw new Error("Softmax op requires 1 input.")},Cg=(e,r)=>{let t=e.inputs[0],s=t.dims,o=ye.size(s),n=s.length,a=ye.normalizeAxis(r.axis,n),i=aC),c[a]=n-1,c[n-1]=a,l=e.compute(rs(t,c),{inputs:[t],outputs:[-1]})[0]):l=t;let p=l.dims,d=p[n-1],u=o/d,f=lr(d),_=d/f,b=64;u===1&&(b=256);let k=(v,C)=>C===4?`max(max(${v}.x, ${v}.y), max(${v}.z, ${v}.w))`:C===2?`max(${v}.x, ${v}.y)`:C===3?`max(max(${v}.x, ${v}.y), ${v}.z)`:v,w=Ie("x",l.dataType,l.dims,f),y=nt("result",l.dataType,l.dims,f),$=w.type.value,T=Ir(l.dataType)==="f32"?`var threadMax = ${$}(-3.402823e+38f);`:`var threadMax = ${$}(-65504.0h);`,M=v=>` - var rowMaxShared : ${$}; - var rowSumShared : ${$}; - var threadShared : array<${$}, ${b}>; - - fn getValue(row: i32, col: i32, row_stride: i32) -> ${$} { - let index = row * row_stride + col; - return x[index]; - } - - fn setValue(row: i32, col: i32, row_stride: i32, value: ${$}) { - let index = row * row_stride + col; - result[index] = value; - } - ${v.registerUniform("packedCols","i32").declareVariables(w,y)} - ${v.mainStart(b)} - let gindex = i32(global_idx); - let lindex = i32(local_idx); - const wg = ${b}; - let row = gindex / wg; - let cols = uniforms.packedCols; - let row_stride : i32 = uniforms.packedCols; - - // find the rows max - ${T} - for (var col = lindex; col < cols; col += wg) { - let value = getValue(row, col, row_stride); - threadMax = max(threadMax, value); - } - if (lindex < cols) { - threadShared[lindex] = threadMax; - } - workgroupBarrier(); - - var reduceSize = min(cols, wg); - for (var currSize = reduceSize >> 1; currSize > 0; currSize = reduceSize >> 1) { - reduceSize = currSize + (reduceSize & 1); - if (lindex < currSize) { - threadShared[lindex] = max(threadShared[lindex], threadShared[lindex + reduceSize]); - } - workgroupBarrier(); - } - if (lindex == 0) { - rowMaxShared = ${$}(${k("threadShared[0]",f)}); - } - workgroupBarrier(); - - // find the rows sum - var threadSum = ${$}(0.0); - for (var col = lindex; col < cols; col += wg) { - let subExp = exp(getValue(row, col, row_stride) - rowMaxShared); - threadSum += subExp; - } - threadShared[lindex] = threadSum; - workgroupBarrier(); - - for (var currSize = wg >> 1; currSize > 0; currSize = currSize >> 1) { - if (lindex < currSize) { - threadShared[lindex] = threadShared[lindex] + threadShared[lindex + currSize]; - } - workgroupBarrier(); - } - if (lindex == 0) { - rowSumShared = ${$}(${en("threadShared[0]",f)}); - } - workgroupBarrier(); - - // calculate final value for each element in the row - for (var col = lindex; col < cols; col += wg) { - let value = exp(getValue(row, col, row_stride) - rowMaxShared) / rowSumShared; - setValue(row, col, row_stride, value); - } - }`,x=e.compute({name:"Softmax",shaderCache:{hint:`${f};${b}`,inputDependencies:["type"]},getRunData:()=>({outputs:[{dims:p,dataType:l.dataType}],dispatchGroup:{x:u},programUniforms:[{type:6,data:_}]}),getShaderSource:M},{inputs:[l],outputs:[i?-1:0]})[0];i&&e.compute(rs(x,c),{inputs:[x]})},Sg=(e,r)=>{Pg(e.inputs),Cg(e,r)},$g=e=>Kt({axis:e.axis})}),tc,kg,Ig,Ag,Fg,yT=Ue(()=>{Mt(),Pt(),Ct(),tc=e=>Array.from(e.getBigInt64Array(),Number),kg=e=>{if(!e||e.length!==2)throw new Error("Tile requires 2 inputs.");if(e[0].dataType!==1&&e[0].dataType!==10&&e[0].dataType!==6&&e[0].dataType!==12)throw new Error("Tile only support float, float16, int32, and uint32 data types");if(e[1].dataType!==7)throw new Error("Tile `repeats` input should be of int64 data type");if(e[1].dims.length!==1)throw new Error("Tile `repeats` input should be 1-D");if(tc(e[1]).length!==e[0].dims.length)throw new Error("Tile `repeats` input should have same number of elements as rank of input data tensor")},Ig=(e,r)=>{let t=[];for(let s=0;s{let t=e[0].dims,s=r??tc(e[1]),o=Ig(t,s),n=ye.size(o),a=e[0].dataType,i=Ie("input",a,t.length),l=nt("output",a,o.length),c=p=>` - const inputShape = ${i.indices(...t)}; - ${p.registerUniform("output_size","u32").declareVariables(i,l)} - ${p.mainStart()} - ${p.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.output_size")} - let output_indices = ${l.offsetToIndices("global_idx")}; - var input_indices: ${i.type.indices}; - for (var i = 0; i < ${t.length}; i++) { - let input_dim_i = ${i.indicesGet("uniforms.input_shape","i")}; - let input_dim_value = ${l.indicesGet("output_indices","i")} % input_dim_i; - - ${i.indicesSet("input_indices","i","input_dim_value")} - } - ${l.setByOffset("global_idx",i.getByIndices("input_indices"))} - }`;return{name:"Tile",shaderCache:{hint:`${s}`,inputDependencies:["rank"]},getRunData:()=>({outputs:[{dims:o,dataType:e[0].dataType}],dispatchGroup:{x:Math.ceil(n/64)},programUniforms:[{type:12,data:n},...dt(e[0].dims,o)]}),getShaderSource:c}},Fg=e=>{kg(e.inputs),e.compute(Ag(e.inputs),{inputs:[0]})}}),Og,Dg,Lg,vT=Ue(()=>{Mt(),Pt(),Ct(),Og=(e,r,t,s,o)=>{let n=nt("output_data",o,t.length,4),a=Ie("a_data",r[1].dataType,r[1].dims.length,4),i=Ie("b_data",r[2].dataType,r[2].dims.length,4),l=Ie("c_data",r[0].dataType,r[0].dims.length,4),c,p=(d,u,f)=>`select(${u}, ${d}, ${f})`;if(!s)c=n.setByOffset("global_idx",p(a.getByOffset("global_idx"),i.getByOffset("global_idx"),l.getByOffset("global_idx")));else{let d=(u,f,_="")=>{let b=`a_data[index_a${f}][component_a${f}]`,k=`b_data[index_b${f}][component_b${f}]`,w=`bool(c_data[index_c${f}] & (0xffu << (component_c${f} * 8)))`;return` - let output_indices${f} = ${n.offsetToIndices(`global_idx * 4u + ${f}u`)}; - let offset_a${f} = ${a.broadcastedIndicesToOffset(`output_indices${f}`,n)}; - let offset_b${f} = ${i.broadcastedIndicesToOffset(`output_indices${f}`,n)}; - let offset_c${f} = ${l.broadcastedIndicesToOffset(`output_indices${f}`,n)}; - let index_a${f} = offset_a${f} / 4u; - let index_b${f} = offset_b${f} / 4u; - let index_c${f} = offset_c${f} / 4u; - let component_a${f} = offset_a${f} % 4u; - let component_b${f} = offset_b${f} % 4u; - let component_c${f} = offset_c${f} % 4u; - ${u}[${f}] = ${_}(${p(b,k,w)}); - `};o===9?c=` - var data = vec4(0); - ${d("data",0,"u32")} - ${d("data",1,"u32")} - ${d("data",2,"u32")} - ${d("data",3,"u32")} - output_data[global_idx] = dot(vec4(0x1, 0x100, 0x10000, 0x1000000), vec4(data));`:c=` - ${d("output_data[global_idx]",0)} - ${d("output_data[global_idx]",1)} - ${d("output_data[global_idx]",2)} - ${d("output_data[global_idx]",3)} - `}return` - ${e.registerUniform("vec_size","u32").declareVariables(l,a,i,n)} - ${e.mainStart()} - ${e.guardAgainstOutOfBoundsWorkgroupSizes("uniforms.vec_size")} - ${c} - }`},Dg=e=>{let r=e[1].dims,t=e[2].dims,s=e[0].dims,o=e[1].dataType,n=!(ye.areEqual(r,t)&&ye.areEqual(t,s)),a=r,i=ye.size(r);if(n){let c=Gn.calcShape(Gn.calcShape(r,t,!1),s,!1);if(!c)throw new Error("Can't perform where op on the given tensors");a=c,i=ye.size(a)}let l=Math.ceil(i/4);return{name:"Where",shaderCache:{inputDependencies:["rank","rank","rank"]},getShaderSource:c=>Og(c,e,a,n,o),getRunData:()=>({outputs:[{dims:a,dataType:o}],dispatchGroup:{x:Math.ceil(i/64/4)},programUniforms:[{type:12,data:l},...dt(s,r,t,a)]})}},Lg=e=>{e.compute(Dg(e.inputs))}}),zg,xT=Ue(()=>{zx(),_l(),Bx(),Rx(),jx(),Nx(),Vx(),Hx(),Qx(),Xx(),Jx(),Yx(),Zx(),eT(),tT(),rT(),sT(),nT(),oT(),aT(),iT(),lT(),cT(),uT(),dT(),q_(),pT(),mT(),hT(),_T(),fT(),pl(),gT(),nf(),wT(),MT(),bT(),tf(),yT(),tn(),Ml(),vT(),zg=new Map([["Abs",[fm]],["Acos",[gm]],["Acosh",[wm]],["Add",[oh]],["ArgMax",[tm,hl]],["ArgMin",[em,hl]],["Asin",[Mm]],["Asinh",[bm]],["Atan",[ym]],["Atanh",[vm]],["Attention",[im]],["AveragePool",[Df,Of]],["BatchNormalization",[dm]],["BiasAdd",[hm]],["BiasSplitGelu",[rh]],["Cast",[Tm,xm]],["Ceil",[Cm]],["Clip",[Pm]],["Concat",[Mh,bh]],["Conv",[Al,kl]],["ConvTranspose",[Hh,Wh]],["Cos",[Sm]],["Cosh",[$m]],["CumSum",[Qh,Xh]],["DepthToSpace",[e_,t_]],["DequantizeLinear",[Wf,Gf]],["Div",[ah]],["Einsum",[i_,l_]],["Elu",[km,Mo]],["Equal",[ih]],["Erf",[Im]],["Exp",[Am]],["Expand",[p_]],["FastGelu",[h_]],["Floor",[Fm]],["FusedConv",[Al,kl]],["Gather",[w_,g_]],["GatherElements",[$_,S_]],["GatherBlockQuantized",[T_,E_]],["GatherND",[b_,y_]],["Gelu",[Om]],["Gemm",[F_,A_]],["GlobalAveragePool",[zf,Lf]],["GlobalMaxPool",[Nf,jf]],["Greater",[dh]],["GreaterOrEqual",[mh]],["GridSample",[V_,U_]],["GroupQueryAttention",[cf]],["HardSigmoid",[Vm,Nm]],["InstanceNormalization",[pf]],["LayerNormalization",[_f]],["LeakyRelu",[Dm,Mo]],["Less",[ph]],["LessOrEqual",[hh]],["Log",[Xm]],["MatMul",[gf]],["MatMulNBits",[yf,vf]],["MaxPool",[Bf,Rf]],["Mul",[lh]],["MultiHeadAttention",[H_,G_]],["Neg",[zm]],["Not",[Lm]],["Pad",[If]],["Pow",[ch]],["QuickGelu",[Zm,Mo]],["Range",[qf]],["Reciprocal",[Bm]],["ReduceMin",[Qp]],["ReduceMean",[Wp]],["ReduceMax",[qp]],["ReduceSum",[Jp]],["ReduceProd",[Xp]],["ReduceL1",[Gp]],["ReduceL2",[Kp]],["ReduceLogSum",[Zp]],["ReduceLogSumExp",[Hp]],["ReduceSumSquare",[Yp]],["Relu",[Rm]],["Resize",[_g,fg]],["RotaryEmbedding",[sf]],["ScatterND",[Yf,Jf]],["Sigmoid",[jm]],["Sin",[Um]],["Sinh",[Wm]],["Slice",[Tg,Eg]],["SkipLayerNormalization",[Mg]],["Split",[Z_,ef]],["Sqrt",[Gm]],["Softmax",[Sg,$g]],["Sub",[uh]],["Tan",[Km]],["Tanh",[Hm]],["ThresholdedRelu",[Qm,Mo]],["Tile",[Fg]],["Transpose",[dp,pp]],["Where",[Lg]]])}),Bg,TT=Ue(()=>{fs(),Ns(),Ct(),Bg=class{constructor(e){this.backend=e,this.repo=new Map,this.attributesBound=!1}getArtifact(e){return this.repo.get(e)}setArtifact(e,r){this.repo.set(e,r)}run(e,r,t,s,o){_s(e.programInfo.name);let n=this.backend.device,a=this.backend.getComputePassEncoder();this.backend.writeTimestamp(this.backend.pendingDispatchNumber*2);let i=[];for(let c of r)i.push({binding:i.length,resource:{buffer:c.buffer}});for(let c of t)i.push({binding:i.length,resource:{buffer:c.buffer}});o&&i.push({binding:i.length,resource:o});let l=n.createBindGroup({layout:e.computePipeline.getBindGroupLayout(0),entries:i,label:e.programInfo.name});if(this.backend.sessionStatus==="capturing"){let c={kernelId:this.backend.currentKernelId,computePipeline:e.computePipeline,bindGroup:l,dispatchGroup:s};this.backend.capturedCommandList.get(this.backend.currentSessionId).push(c)}a.setPipeline(e.computePipeline),a.setBindGroup(0,l),a.dispatchWorkgroups(...s),this.backend.writeTimestamp(this.backend.pendingDispatchNumber*2+1),this.backend.pendingDispatchNumber++,(this.backend.pendingDispatchNumber>=this.backend.maxDispatchNumber||this.backend.queryType==="at-passes")&&this.backend.endComputePass(),this.backend.pendingDispatchNumber>=this.backend.maxDispatchNumber&&this.backend.flush(),is(e.programInfo.name)}dispose(){}build(e,r){_s(e.name);let t=this.backend.device,s=[];[{feature:"shader-f16",extension:"f16"},{feature:"subgroups",extension:"subgroups"}].forEach(c=>{t.features.has(c.feature)&&s.push(`enable ${c.extension};`)});let o=op(r,this.backend.device.limits),n=e.getShaderSource(o),a=`${s.join(` -`)} -${o.additionalImplementations} -${n}`,i=t.createShaderModule({code:a,label:e.name});zt("verbose",()=>`[WebGPU] ${e.name} shader code: ${a}`);let l=t.createComputePipeline({compute:{module:i,entryPoint:"main"},layout:"auto",label:e.name});return is(e.name),{programInfo:e,computePipeline:l,uniformVariablesInfo:o.variablesInfo}}normalizeDispatchGroupSize(e){let r=typeof e=="number"?e:e.x,t=typeof e=="number"?1:e.y||1,s=typeof e=="number"?1:e.z||1,o=this.backend.device.limits.maxComputeWorkgroupsPerDimension;if(r<=o&&t<=o&&s<=o)return[r,t,s];let n=r*t*s,a=Math.ceil(Math.sqrt(n));if(a>o){if(a=Math.ceil(Math.cbrt(n)),a>o)throw new Error("Total dispatch size exceeds WebGPU maximum.");return[a,a,a]}else return[a,a,1]}}}),Rg={};Un(Rg,{WebGpuBackend:()=>Ug});var jg,Ng,Vg,Ug,ET=Ue(()=>{fs(),Mt(),Ns(),Gd(),Dx(),xT(),TT(),jg=(e,r)=>{if(r.length!==e.length)throw new Error(`inputDependencies length ${r.length} is not equal to inputTensors length ${e.length}.`);let t=[];for(let s=0;s{var o,n;let s=e.name;return(o=e.shaderCache)!=null&&o.hint&&(s+="["+e.shaderCache.hint+"]"),s+=":"+t+`:${jg(r,((n=e.shaderCache)==null?void 0:n.inputDependencies)??new Array(r.length).fill("dims"))}`,s},Vg=class{constructor(e){e&&(this.architecture=e.architecture,this.vendor=e.vendor)}isArchitecture(e){return this.architecture===e}isVendor(e){return this.vendor===e}},Ug=class{constructor(){this.currentSessionId=null,this.currentKernelId=null,this.commandEncoder=null,this.computePassEncoder=null,this.maxDispatchNumber=16,this.pendingDispatchNumber=0,this.pendingKernels=[],this.pendingQueries=new Map,this.sessionStatus="default",this.capturedCommandList=new Map,this.capturedPendingKernels=new Map,this.sessionExternalDataMapping=new Map}get currentKernelCustomData(){if(this.currentKernelId===null)throw new Error("currentKernelCustomData(): currentKernelId is null. (should not happen)");let e=this.kernelCustomData.get(this.currentKernelId);return e||(e={},this.kernelCustomData.set(this.currentKernelId,e)),e}async initialize(e,r){this.env=e;let t=[],s={requiredLimits:{maxComputeWorkgroupStorageSize:r.limits.maxComputeWorkgroupStorageSize,maxComputeWorkgroupsPerDimension:r.limits.maxComputeWorkgroupsPerDimension,maxStorageBufferBindingSize:r.limits.maxStorageBufferBindingSize,maxBufferSize:r.limits.maxBufferSize,maxComputeInvocationsPerWorkgroup:r.limits.maxComputeInvocationsPerWorkgroup,maxComputeWorkgroupSizeX:r.limits.maxComputeWorkgroupSizeX,maxComputeWorkgroupSizeY:r.limits.maxComputeWorkgroupSizeY,maxComputeWorkgroupSizeZ:r.limits.maxComputeWorkgroupSizeZ},requiredFeatures:t},o=n=>r.features.has(n)&&t.push(n)&&!0;o("chromium-experimental-timestamp-query-inside-passes")||o("timestamp-query"),o("shader-f16"),o("subgroups"),this.device=await r.requestDevice(s),this.adapterInfo=new Vg(r.info||await r.requestAdapterInfo()),this.gpuDataManager=tp(this),this.programManager=new Bg(this),this.kernels=new Map,this.kernelPersistentData=new Map,this.kernelCustomData=new Map,Xi(e.logLevel,!!e.debug),this.device.onuncapturederror=n=>{n.error instanceof GPUValidationError&&console.error(`An uncaught WebGPU validation error was raised: ${n.error.message}`)},Object.defineProperty(this.env.webgpu,"device",{value:this.device,writable:!1,enumerable:!0,configurable:!1}),Object.defineProperty(this.env.webgpu,"adapter",{value:r,writable:!1,enumerable:!0,configurable:!1}),this.setQueryType()}dispose(){typeof this.querySet<"u"&&this.querySet.destroy(),this.gpuDataManager.dispose()}getCommandEncoder(){return this.commandEncoder||(this.commandEncoder=this.device.createCommandEncoder()),this.commandEncoder}getComputePassEncoder(){if(!this.computePassEncoder){let e=this.getCommandEncoder(),r={};this.queryType==="at-passes"&&(r.timestampWrites={querySet:this.querySet,beginningOfPassWriteIndex:this.pendingDispatchNumber*2,endOfPassWriteIndex:this.pendingDispatchNumber*2+1}),this.computePassEncoder=e.beginComputePass(r)}return this.computePassEncoder}endComputePass(){this.computePassEncoder&&(this.computePassEncoder.end(),this.computePassEncoder=null)}flush(){if(!this.commandEncoder)return;_s(),this.endComputePass();let e;this.queryType!=="none"&&(this.commandEncoder.resolveQuerySet(this.querySet,0,this.pendingDispatchNumber*2,this.queryResolveBuffer,0),e=this.device.createBuffer({size:this.pendingDispatchNumber*2*8,usage:GPUBufferUsage.MAP_READ|GPUBufferUsage.COPY_DST}),this.pendingQueries.set(e,this.pendingKernels),this.pendingKernels=[],this.commandEncoder.copyBufferToBuffer(this.queryResolveBuffer,0,e,0,this.pendingDispatchNumber*2*8)),this.device.queue.submit([this.commandEncoder.finish()]),this.gpuDataManager.refreshPendingBuffers(),this.commandEncoder=null,this.pendingDispatchNumber=0,this.queryType!=="none"&&e.mapAsync(GPUMapMode.READ).then(()=>{var s;let r=new BigUint64Array(e.getMappedRange()),t=this.pendingQueries.get(e);for(let o=0;o"u"&&(this.queryTimeBase=f);let b=Number(f-this.queryTimeBase),k=Number(_-this.queryTimeBase);if(!Number.isSafeInteger(b)||!Number.isSafeInteger(k))throw new RangeError("incorrect timestamp range");if((s=this.env.webgpu.profiling)!=null&&s.ondata)this.env.webgpu.profiling.ondata({version:1,inputsMetadata:d.map(w=>({dims:w.dims,dataType:js(w.dataType)})),outputsMetadata:u.map(w=>({dims:w.dims,dataType:js(w.dataType)})),kernelId:a,kernelType:l,kernelName:c,programName:p,startTime:b,endTime:k});else{let w="";d.forEach(($,T)=>{w+=`input[${T}]: [${$.dims}] | ${js($.dataType)}, `});let y="";u.forEach(($,T)=>{y+=`output[${T}]: [${$.dims}] | ${js($.dataType)}, `}),console.log(`[profiling] kernel "${a}|${l}|${c}|${p}" ${w}${y}execution time: ${k-b} ns`)}ho("GPU",`${p}::${f}::${_}`)}e.unmap(),this.pendingQueries.delete(e)}),is()}run(e,r,t,s,o,n){_s(e.name);let a=[];for(let y=0;y$):t;if(p.length!==i.length)throw new Error(`Output size ${p.length} must be equal to ${i.length}.`);let d=[],u=[];for(let y=0;y=n)throw new Error(`Invalid output index: ${p[y]}`);if(p[y]===-3)continue;let $=p[y]===-1,T=p[y]===-2,M=$||T?o(i[y].dataType,i[y].dims):s(p[y],i[y].dataType,i[y].dims);if(d.push(M),M.data===0)continue;let x=this.gpuDataManager.get(M.data);if(!x)throw new Error(`no GPU data for output: ${M.data}`);if($&&this.temporaryData.push(x),T){let v=this.kernelPersistentData.get(this.currentKernelId);v||(v=[],this.kernelPersistentData.set(this.currentKernelId,v)),v.push(x)}u.push(x)}if(a.length!==r.length||u.length!==d.length){if(u.length===0)return is(e.name),d;throw new Error(`Program ${e.name} has zero-sized tensor(s) in inputs or outputs. This is not supported now.`)}let f;if(c){let y=0,$=[];c.forEach(v=>{let C=typeof v.data=="number"?[v.data]:v.data;if(C.length===0)return;let F=v.type===10?2:4,D,K;v.type===10?(K=C.length>4?16:C.length>2?8:C.length*F,D=C.length>4?16:F*C.length):(K=C.length<=2?C.length*F:16,D=16),y=Math.ceil(y/K)*K,$.push(y);let U=v.type===10?8:4;y+=C.length>4?Math.ceil(C.length/U)*D:C.length*F});let T=16;y=Math.ceil(y/T)*T;let M=new ArrayBuffer(y);c.forEach((v,C)=>{let F=$[C],D=typeof v.data=="number"?[v.data]:v.data;if(v.type===6)new Int32Array(M,F,D.length).set(D);else if(v.type===12)new Uint32Array(M,F,D.length).set(D);else if(v.type===10)new Uint16Array(M,F,D.length).set(D);else if(v.type===1)new Float32Array(M,F,D.length).set(D);else throw new Error(`Unsupported uniform type: ${js(v.type)}`)});let x=this.gpuDataManager.create(y,GPUBufferUsage.COPY_DST|GPUBufferUsage.UNIFORM);this.device.queue.writeBuffer(x.buffer,0,M,0,y),this.gpuDataManager.release(x.id),f={offset:0,size:y,buffer:x.buffer}}let _=this.programManager.normalizeDispatchGroupSize(l),b=_[1]===1&&_[2]===1,k=Ng(e,r,b),w=this.programManager.getArtifact(k);if(w||(w=this.programManager.build(e,_),this.programManager.setArtifact(k,w),zt("info",()=>`[artifact] key: ${k}, programName: ${e.name}`)),c&&w.uniformVariablesInfo){if(c.length!==w.uniformVariablesInfo.length)throw new Error(`Uniform variables count mismatch: expect ${w.uniformVariablesInfo.length}, got ${c.length} in program "${w.programInfo.name}".`);for(let y=0;y`[ProgramManager] run "${e.name}" (key=${k}) with ${_[0]}x${_[1]}x${_[2]}`),this.queryType!=="none"||this.sessionStatus==="capturing"){let y={kernelId:this.currentKernelId,programName:w.programInfo.name,inputTensorViews:r,outputTensorViews:d};this.pendingKernels.push(y),this.sessionStatus==="capturing"&&this.capturedPendingKernels.get(this.currentSessionId).push(y)}return this.programManager.run(w,a,u,_,f),is(e.name),d}upload(e,r){this.gpuDataManager.upload(e,r)}memcpy(e,r){this.gpuDataManager.memcpy(e,r)}async download(e,r){await this.gpuDataManager.download(e,r)}alloc(e){return this.gpuDataManager.create(e).id}free(e){return this.gpuDataManager.release(e)}createKernel(e,r,t,s){let o=zg.get(e);if(!o)throw new Error(`kernel not implemented: ${e}`);let n={kernelType:e,kernelName:s,kernelEntry:o[0],attributes:[o[1],t]};this.kernels.set(r,n)}releaseKernel(e){let r=this.kernelPersistentData.get(e);if(r){for(let t of r)this.gpuDataManager.release(t.id);this.kernelPersistentData.delete(e)}this.kernelCustomData.delete(e),this.kernels.delete(e)}computeKernel(e,r,t){let s=this.kernels.get(e);if(!s)throw new Error(`kernel not created: ${e}`);let o=s.kernelType,n=s.kernelName,a=s.kernelEntry,i=s.attributes;if(this.currentKernelId!==null)throw new Error(`kernel "[${o}] ${n}" is not allowed to be called recursively`);this.currentKernelId=e,i[0]&&(i[1]=i[0](i[1]),i[0]=void 0),zt("info",()=>`[WebGPU] Start to run kernel "[${o}] ${n}"...`);let l=this.env.debug;this.temporaryData=[];try{return l&&this.device.pushErrorScope("validation"),a(r,i[1]),0}catch(c){return t.push(Promise.resolve(`[WebGPU] Kernel "[${o}] ${n}" failed. ${c}`)),1}finally{l&&t.push(this.device.popErrorScope().then(c=>c?`GPU validation error for kernel "[${o}] ${n}": ${c.message}`:null));for(let c of this.temporaryData)this.gpuDataManager.release(c.id);this.temporaryData=[],this.currentKernelId=null}}registerBuffer(e,r,t,s){let o=this.sessionExternalDataMapping.get(e);o||(o=new Map,this.sessionExternalDataMapping.set(e,o));let n=o.get(r),a=this.gpuDataManager.registerExternalBuffer(t,s,n);return o.set(r,[a,t]),a}unregisterBuffers(e){let r=this.sessionExternalDataMapping.get(e);r&&(r.forEach(t=>this.gpuDataManager.unregisterExternalBuffer(t[0])),this.sessionExternalDataMapping.delete(e))}getBuffer(e){let r=this.gpuDataManager.get(e);if(!r)throw new Error(`no GPU data for buffer: ${e}`);return r.buffer}createDownloader(e,r,t){return async()=>{let s=await il(this,e,r);return Ji(s.buffer,t)}}writeTimestamp(e){this.queryType==="inside-passes"&&this.computePassEncoder.writeTimestamp(this.querySet,e)}setQueryType(){var e;this.queryType="none",(((e=this.env.webgpu.profiling)==null?void 0:e.mode)==="default"||(typeof this.env.trace>"u"?this.env.wasm.trace:this.env.trace))&&(this.device.features.has("chromium-experimental-timestamp-query-inside-passes")?this.queryType="inside-passes":this.device.features.has("timestamp-query")&&(this.queryType="at-passes"),this.queryType!=="none"&&typeof this.querySet>"u"&&(this.querySet=this.device.createQuerySet({type:"timestamp",count:this.maxDispatchNumber*2}),this.queryResolveBuffer=this.device.createBuffer({size:this.maxDispatchNumber*2*8,usage:GPUBufferUsage.COPY_SRC|GPUBufferUsage.QUERY_RESOLVE})))}captureBegin(){zt("info","captureBegin"),this.capturedCommandList.get(this.currentSessionId)||this.capturedCommandList.set(this.currentSessionId,[]),this.capturedPendingKernels.get(this.currentSessionId)||this.capturedPendingKernels.set(this.currentSessionId,[]),this.flush(),this.sessionStatus="capturing"}captureEnd(){zt("info","captureEnd"),this.flush(),this.sessionStatus="default"}replay(){zt("info","replay"),this.sessionStatus="replaying";let e=this.capturedCommandList.get(this.currentSessionId),r=this.capturedPendingKernels.get(this.currentSessionId),t=e.length;this.pendingKernels=[];for(let s=0;s=this.maxDispatchNumber||this.queryType==="at-passes")&&this.endComputePass(),this.pendingDispatchNumber>=this.maxDispatchNumber&&this.flush()}this.flush(),this.sessionStatus="default"}onCreateSession(){this.gpuDataManager.onCreateSession()}onReleaseSession(e){this.unregisterBuffers(e),this.capturedCommandList.has(e)&&this.capturedCommandList.delete(e),this.capturedPendingKernels.has(e)&&this.capturedPendingKernels.delete(e),this.gpuDataManager.onReleaseSession(e)}onRunStart(e){this.currentSessionId=e,this.setQueryType()}}}),Wg={};Un(Wg,{init:()=>Kg});var Ma,Gg,Kg,PT=Ue(()=>{Mt(),Ns(),Pt(),Ox(),Ma=class Qv{constructor(r,t,s,o){this.module=r,this.dataType=t,this.data=s,this.dims=o}getFloat32Array(){if(this.dataType!==1)throw new Error("Invalid data type");let r=ye.size(this.dims);return r===0?new Float32Array:new Float32Array(this.module.HEAP8.buffer,this.data,r)}getBigInt64Array(){if(this.dataType!==7)throw new Error("Invalid data type");let r=ye.size(this.dims);return r===0?new BigInt64Array:new BigInt64Array(this.module.HEAP8.buffer,this.data,r)}getInt32Array(){if(this.dataType!==6)throw new Error("Invalid data type");let r=ye.size(this.dims);return r===0?new Int32Array:new Int32Array(this.module.HEAP8.buffer,this.data,r)}getUint16Array(){if(this.dataType!==10&&this.dataType!==4)throw new Error("Invalid data type");let r=ye.size(this.dims);return r===0?new Uint16Array:new Uint16Array(this.module.HEAP8.buffer,this.data,r)}reshape(r){if(ye.size(r)!==ye.size(this.dims))throw new Error("Invalid new shape");return new Qv(this.module,this.dataType,this.data,r)}},Gg=class{constructor(e,r,t){this.module=e,this.backend=r,this.customDataOffset=0,this.customDataSize=0,this.adapterInfo=r.adapterInfo;let s=e.PTR_SIZE,o=t/e.PTR_SIZE,n=s===4?"i32":"i64";this.opKernelContext=Number(e.getValue(s*o++,n));let a=Number(e.getValue(s*o++,n));this.outputCount=Number(e.getValue(s*o++,n)),this.customDataOffset=Number(e.getValue(s*o++,"*")),this.customDataSize=Number(e.getValue(s*o++,n));let i=[];for(let l=0;ltypeof i=="number"?this.inputs[i]:i))??this.inputs,s=(r==null?void 0:r.outputs)??[],o=(i,l,c)=>new Ma(this.module,l,this.output(i,c),c),n=(i,l)=>{let c=fn(i,l);if(!c)throw new Error(`Unsupported data type: ${i}`);let p=c>0?this.backend.gpuDataManager.create(c).id:0;return new Ma(this.module,i,p,l)};return this.backend.run(e,t,s,o,n,this.outputCount)}output(e,r){let t=this.module.stackSave();try{let s=this.module.PTR_SIZE,o=s===4?"i32":"i64",n=this.module.stackAlloc((1+r.length)*s);this.module.setValue(n,r.length,o);for(let a=0;a{let o=r.jsepInit;if(!o)throw new Error("Failed to initialize JSEP. The WebAssembly module is not built with JSEP support.");if(e==="webgpu"){let n=(ET(),uo(Rg)).WebGpuBackend,a=new n;await a.initialize(t,s),o("webgpu",[a,i=>a.alloc(Number(i)),i=>a.free(i),(i,l,c,p=!1)=>{if(p)zt("verbose",()=>`[WebGPU] jsepCopyGpuToGpu: src=${Number(i)}, dst=${Number(l)}, size=${Number(c)}`),a.memcpy(Number(i),Number(l));else{zt("verbose",()=>`[WebGPU] jsepCopyCpuToGpu: dataOffset=${Number(i)}, gpuDataId=${Number(l)}, size=${Number(c)}`);let d=r.HEAPU8.subarray(Number(i>>>0),Number(i>>>0)+Number(c));a.upload(Number(l),d)}},async(i,l,c)=>{zt("verbose",()=>`[WebGPU] jsepCopyGpuToCpu: gpuDataId=${i}, dataOffset=${l}, size=${c}`),await a.download(Number(i),()=>r.HEAPU8.subarray(Number(l)>>>0,Number(l+c)>>>0))},(i,l,c)=>a.createKernel(i,Number(l),c,r.UTF8ToString(r._JsepGetNodeName(Number(l)))),i=>a.releaseKernel(i),(i,l,c,p)=>{zt("verbose",()=>`[WebGPU] jsepRun: sessionHandle=${c}, kernel=${i}, contextDataOffset=${l}`);let d=new Gg(r,a,Number(l));return a.computeKernel(Number(i),d,p)},()=>a.captureBegin(),()=>a.captureEnd(),()=>a.replay()])}else{let n=new Jd(t);o("webnn",[n,()=>n.reserveTensorId(),a=>n.releaseTensorId(a),async(a,i,l,c,p)=>n.ensureTensor(a,i,l,c,p),(a,i)=>{n.uploadTensor(a,i)},async(a,i)=>n.downloadTensor(a,i)])}}}),Hg,rc,sc,rn,qg,nc,ba,oc,ac,ic,lc,cc,uc,Qg=Ue(()=>{Ix(),Ax(),Mt(),_n(),Wi(),Dd(),Hg=(e,r)=>{Zt()._OrtInit(e,r)!==0&&Xt("Can't initialize onnxruntime.")},rc=async e=>{Hg(e.wasm.numThreads,oa(e.logLevel))},sc=async(e,r)=>{var t,s;(s=(t=Zt()).asyncInit)==null||s.call(t);{let o=(PT(),uo(Wg)).init;if(r==="webgpu"){if(typeof navigator>"u"||!navigator.gpu)throw new Error("WebGPU is not supported in current environment");let n=e.webgpu.adapter;if(n){if(typeof n.limits!="object"||typeof n.features!="object"||typeof n.requestDevice!="function")throw new Error("Invalid GPU adapter set in `env.webgpu.adapter`. It must be a GPUAdapter object.")}else{let a=e.webgpu.powerPreference;if(a!==void 0&&a!=="low-power"&&a!=="high-performance")throw new Error(`Invalid powerPreference setting: "${a}"`);let i=e.webgpu.forceFallbackAdapter;if(i!==void 0&&typeof i!="boolean")throw new Error(`Invalid forceFallbackAdapter setting: "${i}"`);if(n=await navigator.gpu.requestAdapter({powerPreference:a,forceFallbackAdapter:i}),!n)throw new Error('Failed to get GPU adapter. You may need to enable flag "--enable-unsafe-webgpu" if you are using Chrome.')}await o("webgpu",Zt(),e,n)}if(r==="webnn"){if(typeof navigator>"u"||!navigator.ml)throw new Error("WebNN is not supported in current environment");await o("webnn",Zt(),e)}}},rn=new Map,qg=e=>{let r=Zt(),t=r.stackSave();try{let s=r.PTR_SIZE,o=r.stackAlloc(2*s);r._OrtGetInputOutputCount(e,o,o+s)!==0&&Xt("Can't get session input/output count.");let n=s===4?"i32":"i64";return[Number(r.getValue(o,n)),Number(r.getValue(o+s,n))]}finally{r.stackRestore(t)}},nc=(e,r)=>{let t=Zt(),s=t.stackSave(),o=0;try{let n=t.PTR_SIZE,a=t.stackAlloc(2*n);t._OrtGetInputOutputMetadata(e,r,a,a+n)!==0&&Xt("Can't get session input/output metadata.");let i=Number(t.getValue(a,"*"));o=Number(t.getValue(a+n,"*"));let l=t.HEAP32[o/4];if(l===0)return[i,0];let c=t.HEAPU32[o/4+1],p=[];for(let d=0;d{let r=Zt(),t=r._malloc(e.byteLength);if(t===0)throw new Error(`Can't create a session. failed to allocate a buffer of size ${e.byteLength}.`);return r.HEAPU8.set(e,t),[t,e.byteLength]},oc=async(e,r)=>{var d,u,f,_;let t,s,o=Zt();Array.isArray(e)?[t,s]=e:e.buffer===o.HEAPU8.buffer?[t,s]=[e.byteOffset,e.byteLength]:[t,s]=ba(e);let n=0,a=0,i=0,l=[],c=[],p=[];try{if([a,l]=await Od(r),(r==null?void 0:r.externalData)&&o.mountExternalData){let C=[];for(let F of r.externalData){let D=typeof F=="string"?F:F.path;C.push(Qi(typeof F=="string"?F:F.data).then(K=>{o.mountExternalData(D,K)}))}await Promise.all(C)}for(let C of(r==null?void 0:r.executionProviders)??[])if((typeof C=="string"?C:C.name)==="webnn"){if(o.shouldTransferToMLTensor=!1,typeof C!="string"){let F=C,D=F==null?void 0:F.context,K=F==null?void 0:F.gpuDevice,U=F==null?void 0:F.deviceType,j=F==null?void 0:F.powerPreference;D?o.currentContext=D:K?o.currentContext=await o.webnnCreateMLContext(K):o.currentContext=await o.webnnCreateMLContext({deviceType:U,powerPreference:j})}else o.currentContext=await o.webnnCreateMLContext();break}n=await o._OrtCreateSession(t,s,a),(d=o.webgpuOnCreateSession)==null||d.call(o,n),n===0&&Xt("Can't create a session."),(u=o.jsepOnCreateSession)==null||u.call(o),o.currentContext&&(o.webnnRegisterMLContext(n,o.currentContext),o.currentContext=void 0,o.shouldTransferToMLTensor=!0);let[b,k]=qg(n),w=!!(r!=null&&r.enableGraphCapture),y=[],$=[],T=[],M=[],x=[];for(let C=0;CC==="gpu-buffer"||C==="ml-tensor")&&(i=o._OrtCreateBinding(n),i===0&&Xt("Can't create IO binding."),v={handle:i,outputPreferredLocations:x,outputPreferredLocationsEncoded:x.map(C=>qi(C))}),rn.set(n,[n,c,p,v,w,!1]),[n,y,$,T,M]}catch(b){throw c.forEach(k=>o._OrtFree(k)),p.forEach(k=>o._OrtFree(k)),i!==0&&o._OrtReleaseBinding(i)!==0&&Xt("Can't release IO binding."),n!==0&&o._OrtReleaseSession(n)!==0&&Xt("Can't release session."),b}finally{o._free(t),a!==0&&o._OrtReleaseSessionOptions(a)!==0&&Xt("Can't release session options."),l.forEach(b=>o._free(b)),(_=o.unmountExternalData)==null||_.call(o)}},ac=e=>{var l,c,p;let r=Zt(),t=rn.get(e);if(!t)throw new Error(`cannot release session. invalid session id: ${e}`);let[s,o,n,a,i]=t;a&&(i&&r._OrtClearBoundOutputs(a.handle)!==0&&Xt("Can't clear bound outputs."),r._OrtReleaseBinding(a.handle)!==0&&Xt("Can't release IO binding.")),(l=r.jsepOnReleaseSession)==null||l.call(r,e),(c=r.webnnOnReleaseSession)==null||c.call(r,e),(p=r.webgpuOnReleaseSession)==null||p.call(r,e),o.forEach(d=>r._OrtFree(d)),n.forEach(d=>r._OrtFree(d)),r._OrtReleaseSession(s)!==0&&Xt("Can't release session."),rn.delete(e)},ic=async(e,r,t,s,o,n,a=!1)=>{if(!e){r.push(0);return}let i=Zt(),l=i.PTR_SIZE,c=e[0],p=e[1],d=e[3],u=d,f,_;if(c==="string"&&(d==="gpu-buffer"||d==="ml-tensor"))throw new Error("String tensor is not supported on GPU.");if(a&&d!=="gpu-buffer")throw new Error(`External buffer must be provided for input/output index ${n} when enableGraphCapture is true.`);if(d==="gpu-buffer"){let w=e[2].gpuBuffer;_=fn(Wn(c),p);{let y=i.jsepRegisterBuffer;if(!y)throw new Error('Tensor location "gpu-buffer" is not supported without using WebGPU.');f=y(s,n,w,_)}}else if(d==="ml-tensor"){let w=e[2].mlTensor;_=fn(Wn(c),p);let y=i.webnnRegisterMLTensor;if(!y)throw new Error('Tensor location "ml-tensor" is not supported without using WebNN.');f=y(s,w,Wn(c),p)}else{let w=e[2];if(Array.isArray(w)){_=l*w.length,f=i._malloc(_),t.push(f);for(let y=0;yi.setValue(k+$*l,y,l===4?"i32":"i64"));let w=i._OrtCreateTensor(Wn(c),f,_,k,p.length,qi(u));w===0&&Xt(`Can't create tensor for input/output. session=${s}, index=${n}.`),r.push(w)}finally{i.stackRestore(b)}},lc=async(e,r,t,s,o,n)=>{var K,U,j,se;let a=Zt(),i=a.PTR_SIZE,l=rn.get(e);if(!l)throw new Error(`cannot run inference. invalid session id: ${e}`);let c=l[0],p=l[1],d=l[2],u=l[3],f=l[4],_=l[5],b=r.length,k=s.length,w=0,y=[],$=[],T=[],M=[],x=a.stackSave(),v=a.stackAlloc(b*i),C=a.stackAlloc(b*i),F=a.stackAlloc(k*i),D=a.stackAlloc(k*i);try{[w,y]=$d(n);for(let Z=0;Zte*O,1);G=js(le);let Ae=u==null?void 0:u.outputPreferredLocations[s[Z]];if(G==="string"){if(Ae==="gpu-buffer"||Ae==="ml-tensor")throw new Error("String tensor is not supported on GPU.");let te=[];for(let O=0;O0){let te=a.jsepGetBuffer;if(!te)throw new Error('preferredLocation "gpu-buffer" is not supported without using WebGPU.');let O=te(B),me=fn(le,Ne);if(me===void 0||!Ki(G))throw new Error(`Unsupported data type: ${G}`);oe=!0,re.push([G,De,{gpuBuffer:O,download:a.jsepCreateDownloader(O,me,G),dispose:()=>{a._OrtReleaseTensor(ae)!==0&&Xt("Can't release tensor.")}},"gpu-buffer"])}else if(Ae==="ml-tensor"&&Ne>0){let te=a.webnnEnsureTensor,O=a.webnnIsInt64Supported;if(!te||!O)throw new Error('preferredLocation "ml-tensor" is not supported without using WebNN.');if(fn(le,Ne)===void 0||!Hi(G))throw new Error(`Unsupported data type: ${G}`);if(G==="int64"&&!O(e))throw new Error('preferredLocation "ml-tensor" for int64 output is not supported by current WebNN Context.');let me=await te(e,B,le,De,!1);oe=!0,re.push([G,De,{mlTensor:me,download:a.webnnCreateMLTensorDownloader(B,G),dispose:()=>{a.webnnReleaseTensorId(B),a._OrtReleaseTensor(ae)}},"ml-tensor"])}else{let te=Gi(G),O=new te(Ne);new Uint8Array(O.buffer,O.byteOffset,O.byteLength).set(a.HEAPU8.subarray(B,B+O.byteLength)),re.push([G,De,O,"cpu"])}}finally{a.stackRestore(_e),G==="string"&&B&&a._free(B),oe||a._OrtReleaseTensor(ae),(se=a.webnnOnRunEnd)==null||se.call(a,c)}}return u&&!f&&(a._OrtClearBoundOutputs(u.handle)!==0&&Xt("Can't clear bound outputs."),rn.set(e,[c,p,d,u,f,!1])),re}finally{a.stackRestore(x),$.forEach(q=>a._OrtReleaseTensor(q)),T.forEach(q=>a._OrtReleaseTensor(q)),M.forEach(q=>a._free(q)),w!==0&&a._OrtReleaseRunOptions(w),y.forEach(q=>a._free(q))}},cc=e=>{let r=Zt(),t=rn.get(e);if(!t)throw new Error("invalid session id");let s=t[0],o=r._OrtEndProfiling(s);o===0&&Xt("Can't get an profile file name."),r._OrtFree(o)},uc=e=>{let r=[];for(let t of e){let s=t[2];!Array.isArray(s)&&"buffer"in s&&r.push(s.buffer)}return r}}),sn,Xr,qn,Po,Co,ya,dc,va,xn,Tn,Xg,Jg,Yg,Zg,ew,tw,rw,sw,nw=Ue(()=>{fs(),Qg(),_n(),ji(),sn=()=>!!tr.wasm.proxy&&typeof document<"u",qn=!1,Po=!1,Co=!1,va=new Map,xn=(e,r)=>{let t=va.get(e);t?t.push(r):va.set(e,[r])},Tn=()=>{if(qn||!Po||Co||!Xr)throw new Error("worker not ready")},Xg=e=>{switch(e.data.type){case"init-wasm":qn=!1,e.data.err?(Co=!0,dc[1](e.data.err)):(Po=!0,dc[0]()),ya&&(URL.revokeObjectURL(ya),ya=void 0);break;case"init-ep":case"copy-from":case"create":case"release":case"run":case"end-profiling":{let r=va.get(e.data.type);e.data.err?r.shift()[1](e.data.err):r.shift()[0](e.data.out);break}}},Jg=async()=>{if(!Po){if(qn)throw new Error("multiple calls to 'initWasm()' detected.");if(Co)throw new Error("previous call to 'initWasm()' failed.");if(qn=!0,sn())return new Promise((e,r)=>{Xr==null||Xr.terminate(),Td().then(([t,s])=>{try{Xr=s,Xr.onerror=n=>r(n),Xr.onmessage=Xg,dc=[e,r];let o={type:"init-wasm",in:tr};!o.in.wasm.wasmPaths&&(t||Li)&&(o.in.wasm.wasmPaths={wasm:new URL("/assets/ort-wasm-simd-threaded.jsep-B0T3yYHD.wasm",self.location.href).href}),Xr.postMessage(o),ya=t}catch(o){r(o)}},r)});try{await Ui(tr.wasm),await rc(tr),Po=!0}catch(e){throw Co=!0,e}finally{qn=!1}}},Yg=async e=>{if(sn())return Tn(),new Promise((r,t)=>{xn("init-ep",[r,t]);let s={type:"init-ep",in:{epName:e,env:tr}};Xr.postMessage(s)});await sc(tr,e)},Zg=async e=>sn()?(Tn(),new Promise((r,t)=>{xn("copy-from",[r,t]);let s={type:"copy-from",in:{buffer:e}};Xr.postMessage(s,[e.buffer])})):ba(e),ew=async(e,r)=>{if(sn()){if(r!=null&&r.preferredOutputLocation)throw new Error('session option "preferredOutputLocation" is not supported for proxy.');return Tn(),new Promise((t,s)=>{xn("create",[t,s]);let o={type:"create",in:{model:e,options:{...r}}},n=[];e instanceof Uint8Array&&n.push(e.buffer),Xr.postMessage(o,n)})}else return oc(e,r)},tw=async e=>{if(sn())return Tn(),new Promise((r,t)=>{xn("release",[r,t]);let s={type:"release",in:e};Xr.postMessage(s)});ac(e)},rw=async(e,r,t,s,o,n)=>{if(sn()){if(t.some(a=>a[3]!=="cpu"))throw new Error("input tensor on GPU is not supported for proxy.");if(o.some(a=>a))throw new Error("pre-allocated output tensor is not supported for proxy.");return Tn(),new Promise((a,i)=>{xn("run",[a,i]);let l=t,c={type:"run",in:{sessionId:e,inputIndices:r,inputs:l,outputIndices:s,options:n}};Xr.postMessage(c,uc(l))})}else return lc(e,r,t,s,o,n)},sw=async e=>{if(sn())return Tn(),new Promise((r,t)=>{xn("end-profiling",[r,t]);let s={type:"end-profiling",in:e};Xr.postMessage(s)});cc(e)}}),pc,ow,aw,CT=Ue(()=>{fs(),nw(),Mt(),ki(),Dd(),pc=(e,r)=>{switch(e.location){case"cpu":return[e.type,e.dims,e.data,"cpu"];case"gpu-buffer":return[e.type,e.dims,{gpuBuffer:e.gpuBuffer},"gpu-buffer"];case"ml-tensor":return[e.type,e.dims,{mlTensor:e.mlTensor},"ml-tensor"];default:throw new Error(`invalid data location: ${e.location} for ${r()}`)}},ow=e=>{switch(e[3]){case"cpu":return new hs(e[0],e[2],e[1]);case"gpu-buffer":{let r=e[0];if(!Ki(r))throw new Error(`not supported data type: ${r} for deserializing GPU tensor`);let{gpuBuffer:t,download:s,dispose:o}=e[2];return hs.fromGpuBuffer(t,{dataType:r,dims:e[1],download:s,dispose:o})}case"ml-tensor":{let r=e[0];if(!Hi(r))throw new Error(`not supported data type: ${r} for deserializing MLTensor tensor`);let{mlTensor:t,download:s,dispose:o}=e[2];return hs.fromMLTensor(t,{dataType:r,dims:e[1],download:s,dispose:o})}default:throw new Error(`invalid data location: ${e[3]}`)}},aw=class{async fetchModelAndCopyToWasmMemory(e){return Zg(await Qi(e))}async loadModel(e,r){_s();let t;typeof e=="string"?t=await this.fetchModelAndCopyToWasmMemory(e):t=e,[this.sessionId,this.inputNames,this.outputNames,this.inputMetadata,this.outputMetadata]=await ew(t,r),is()}async dispose(){return tw(this.sessionId)}async run(e,r,t){_s();let s=[],o=[];Object.entries(e).forEach(d=>{let u=d[0],f=d[1],_=this.inputNames.indexOf(u);if(_===-1)throw new Error(`invalid input '${u}'`);s.push(f),o.push(_)});let n=[],a=[];Object.entries(r).forEach(d=>{let u=d[0],f=d[1],_=this.outputNames.indexOf(u);if(_===-1)throw new Error(`invalid output '${u}'`);n.push(f),a.push(_)});let i=s.map((d,u)=>pc(d,()=>`input "${this.inputNames[o[u]]}"`)),l=n.map((d,u)=>d?pc(d,()=>`output "${this.outputNames[a[u]]}"`):null),c=await rw(this.sessionId,o,i,a,l,t),p={};for(let d=0;dhc,initializeFlags:()=>mc,wasmBackend:()=>lw});var mc,hc,lw,ST=Ue(()=>{fs(),nw(),CT(),mc=()=>{(typeof tr.wasm.initTimeout!="number"||tr.wasm.initTimeout<0)&&(tr.wasm.initTimeout=0);let e=tr.wasm.simd;if(typeof e!="boolean"&&e!==void 0&&e!=="fixed"&&e!=="relaxed"&&(console.warn(`Property "env.wasm.simd" is set to unknown value "${e}". Reset it to \`false\` and ignore SIMD feature checking.`),tr.wasm.simd=!1),typeof tr.wasm.proxy!="boolean"&&(tr.wasm.proxy=!1),typeof tr.wasm.trace!="boolean"&&(tr.wasm.trace=!1),typeof tr.wasm.numThreads!="number"||!Number.isInteger(tr.wasm.numThreads)||tr.wasm.numThreads<=0)if(typeof self<"u"&&!self.crossOriginIsolated)tr.wasm.numThreads=1;else{let r=typeof navigator>"u"?hx("node:os").cpus().length:navigator.hardwareConcurrency;tr.wasm.numThreads=Math.min(4,Math.ceil((r||1)/2))}},hc=class{async init(e){mc(),await Jg(),await Yg(e)}async createInferenceSessionHandler(e,r){let t=new aw;return await t.loadModel(e,r),t}},lw=new hc});fs(),fs(),fs();var $T="1.22.0-dev.20250409-89f8206ba4",kT=md;{let e=(ST(),uo(iw)).wasmBackend;mn("webgpu",e,5),mn("webnn",e,5),mn("cpu",e,10),mn("wasm",e,10)}Object.defineProperty(tr.versions,"web",{value:$T,enumerable:!0});/** -* @license -* Copyright 2021 Google LLC. All Rights Reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* ============================================================================= -*//** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - *//** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */var IT=Object.freeze({__proto__:null,get InferenceSession(){return $i},get TRACE(){return ho},get TRACE_FUNC_BEGIN(){return _s},get TRACE_FUNC_END(){return is},get Tensor(){return hs},default:kT,get env(){return tr},get registerBackend(){return mn}}),Us={},AT={"onnxruntime-common":e=>{e.exports=ux},"onnxruntime-web":e=>{e.exports=IT},"?2ce3":()=>{},"?7992":()=>{},"?5af5":()=>{},"?2b25":()=>{},"?db59":()=>{},"?383f":()=>{},"?fa4b":()=>{},"./node_modules/@huggingface/jinja/dist/index.js":(e,r,t)=>{t.r(r),t.d(r,{Environment:()=>pt,Interpreter:()=>Mr,Template:()=>Fs,parse:()=>Se,tokenize:()=>d});var s=Object.freeze({Text:"Text",NumericLiteral:"NumericLiteral",StringLiteral:"StringLiteral",Identifier:"Identifier",Equals:"Equals",OpenParen:"OpenParen",CloseParen:"CloseParen",OpenStatement:"OpenStatement",CloseStatement:"CloseStatement",OpenExpression:"OpenExpression",CloseExpression:"CloseExpression",OpenSquareBracket:"OpenSquareBracket",CloseSquareBracket:"CloseSquareBracket",OpenCurlyBracket:"OpenCurlyBracket",CloseCurlyBracket:"CloseCurlyBracket",Comma:"Comma",Dot:"Dot",Colon:"Colon",Pipe:"Pipe",CallOperator:"CallOperator",AdditiveBinaryOperator:"AdditiveBinaryOperator",MultiplicativeBinaryOperator:"MultiplicativeBinaryOperator",ComparisonBinaryOperator:"ComparisonBinaryOperator",UnaryOperator:"UnaryOperator",Comment:"Comment"}),o=class{constructor(S,H){this.value=S,this.type=H}};function n(S){return/\w/.test(S)}function a(S){return/[0-9]/.test(S)}function i(S){return/\s/.test(S)}var l=[["{%",s.OpenStatement],["%}",s.CloseStatement],["{{",s.OpenExpression],["}}",s.CloseExpression],["(",s.OpenParen],[")",s.CloseParen],["{",s.OpenCurlyBracket],["}",s.CloseCurlyBracket],["[",s.OpenSquareBracket],["]",s.CloseSquareBracket],[",",s.Comma],[".",s.Dot],[":",s.Colon],["|",s.Pipe],["<=",s.ComparisonBinaryOperator],[">=",s.ComparisonBinaryOperator],["==",s.ComparisonBinaryOperator],["!=",s.ComparisonBinaryOperator],["<",s.ComparisonBinaryOperator],[">",s.ComparisonBinaryOperator],["+",s.AdditiveBinaryOperator],["-",s.AdditiveBinaryOperator],["~",s.AdditiveBinaryOperator],["*",s.MultiplicativeBinaryOperator],["/",s.MultiplicativeBinaryOperator],["%",s.MultiplicativeBinaryOperator],["=",s.Equals]],c=new Map([["n",` -`],["t"," "],["r","\r"],["b","\b"],["f","\f"],["v","\v"],["'","'"],['"','"'],["\\","\\"]]);function p(S,H={}){return S.endsWith(` -`)&&(S=S.slice(0,-1)),H.lstrip_blocks&&(S=S.replace(/^[ \t]*({[#%-])/gm,"$1")),H.trim_blocks&&(S=S.replace(/([#%-]})\n/g,"$1")),S.replace(/{%\s*(end)?generation\s*%}/gs,"")}function d(S,H={}){var rt,St;const R=[],W=p(S,H);let X=0,ue=0;const Ee=lt=>{let Ot="";for(;lt(W[X]);){if(W[X]==="\\"){if(++X,X>=W.length)throw new SyntaxError("Unexpected end of input");const at=W[X++],Dt=c.get(at);if(Dt===void 0)throw new SyntaxError(`Unexpected escaped character: ${at}`);Ot+=Dt;continue}if(Ot+=W[X++],X>=W.length)throw new SyntaxError("Unexpected end of input")}return Ot},et=()=>{const lt=R.at(-1);lt&<.type===s.Text&&(lt.value=lt.value.trimEnd(),lt.value===""&&R.pop())},ot=()=>{for(;X0){R.push(new o(at,s.Text));continue}}if(W[X]==="{"&&W[X+1]==="#"){X+=2;const at=W[X]==="-";at&&++X;let Dt="";for(;W[X]!=="#"||W[X+1]!=="}";){if(X+2>=W.length)throw new SyntaxError("Missing end of comment tag");Dt+=W[X++]}const Wt=Dt.endsWith("-");Wt&&(Dt=Dt.slice(0,-1)),at&&et(),R.push(new o(Dt,s.Comment)),X+=2,Wt&&ot();continue}if(W.slice(X,X+3)==="{%-"){et(),R.push(new o("{%",s.OpenStatement)),X+=3;continue}if(W.slice(X,X+3)==="{{-"){et(),R.push(new o("{{",s.OpenExpression)),ue=0,X+=3;continue}if(Ee(i),W.slice(X,X+3)==="-%}"){R.push(new o("%}",s.CloseStatement)),X+=3,ot();continue}if(W.slice(X,X+3)==="-}}"){R.push(new o("}}",s.CloseExpression)),X+=3,ot();continue}const Ot=W[X];if(Ot==="-"||Ot==="+"){const at=(St=R.at(-1))==null?void 0:St.type;if(at===s.Text||at===void 0)throw new SyntaxError(`Unexpected character: ${Ot}`);switch(at){case s.Identifier:case s.NumericLiteral:case s.StringLiteral:case s.CloseParen:case s.CloseSquareBracket:break;default:{++X;const Dt=Ee(a);R.push(new o(`${Ot}${Dt}`,Dt.length>0?s.NumericLiteral:s.UnaryOperator));continue}}}for(const[at,Dt]of l){if(at==="}}"&&ue>0)continue;if(W.slice(X,X+at.length)===at){R.push(new o(at,Dt)),Dt===s.OpenExpression?ue=0:Dt===s.OpenCurlyBracket?++ue:Dt===s.CloseCurlyBracket&&--ue,X+=at.length;continue e}}if(Ot==="'"||Ot==='"'){++X;const at=Ee(Dt=>Dt!==Ot);R.push(new o(at,s.StringLiteral)),++X;continue}if(a(Ot)){let at=Ee(a);if(W[X]==="."&&a(W[X+1])){++X;const Dt=Ee(a);at=`${at}.${Dt}`}R.push(new o(at,s.NumericLiteral));continue}if(n(Ot)){const at=Ee(n);R.push(new o(at,s.Identifier));continue}throw new SyntaxError(`Unexpected character: ${Ot}`)}return R}var u=class{constructor(){J(this,"type","Statement")}},f=class extends u{constructor(H){super();J(this,"type","Program");this.body=H}},_=class extends u{constructor(H,R,W){super();J(this,"type","If");this.test=H,this.body=R,this.alternate=W}},b=class extends u{constructor(H,R,W,X){super();J(this,"type","For");this.loopvar=H,this.iterable=R,this.body=W,this.defaultBlock=X}},k=class extends u{constructor(){super(...arguments);J(this,"type","Break")}},w=class extends u{constructor(){super(...arguments);J(this,"type","Continue")}},y=class extends u{constructor(H,R,W){super();J(this,"type","Set");this.assignee=H,this.value=R,this.body=W}},$=class extends u{constructor(H,R,W){super();J(this,"type","Macro");this.name=H,this.args=R,this.body=W}},T=class extends u{constructor(H){super();J(this,"type","Comment");this.value=H}},M=class extends u{constructor(){super(...arguments);J(this,"type","Expression")}},x=class extends M{constructor(H,R,W){super();J(this,"type","MemberExpression");this.object=H,this.property=R,this.computed=W}},v=class extends M{constructor(H,R){super();J(this,"type","CallExpression");this.callee=H,this.args=R}},C=class extends M{constructor(H){super();J(this,"type","Identifier");this.value=H}},F=class extends M{constructor(H){super();J(this,"type","Literal");this.value=H}},D=class extends F{constructor(){super(...arguments);J(this,"type","IntegerLiteral")}},K=class extends F{constructor(){super(...arguments);J(this,"type","FloatLiteral")}},U=class extends F{constructor(){super(...arguments);J(this,"type","StringLiteral")}},j=class extends F{constructor(){super(...arguments);J(this,"type","ArrayLiteral")}},se=class extends F{constructor(){super(...arguments);J(this,"type","TupleLiteral")}},q=class extends F{constructor(){super(...arguments);J(this,"type","ObjectLiteral")}},re=class extends M{constructor(H,R,W){super();J(this,"type","BinaryExpression");this.operator=H,this.left=R,this.right=W}},Z=class extends M{constructor(H,R){super();J(this,"type","FilterExpression");this.operand=H,this.filter=R}},ae=class extends u{constructor(H,R){super();J(this,"type","FilterStatement");this.filter=H,this.body=R}},_e=class extends M{constructor(H,R){super();J(this,"type","SelectExpression");this.lhs=H,this.test=R}},pe=class extends M{constructor(H,R,W){super();J(this,"type","TestExpression");this.operand=H,this.negate=R,this.test=W}},oe=class extends M{constructor(H,R){super();J(this,"type","UnaryExpression");this.operator=H,this.argument=R}},G=class extends M{constructor(H=void 0,R=void 0,W=void 0){super();J(this,"type","SliceExpression");this.start=H,this.stop=R,this.step=W}},B=class extends M{constructor(H,R){super();J(this,"type","KeywordArgumentExpression");this.key=H,this.value=R}},Q=class extends M{constructor(H){super();J(this,"type","SpreadExpression");this.argument=H}},le=class extends u{constructor(H,R,W){super();J(this,"type","CallStatement");this.call=H,this.callerArgs=R,this.body=W}},ee=class extends M{constructor(H,R,W){super();J(this,"type","Ternary");this.condition=H,this.trueExpr=R,this.falseExpr=W}};function Se(S){const H=new f([]);let R=0;function W(je,Ve){const st=S[R++];if(!st||st.type!==je)throw new Error(`Parser Error: ${Ve}. ${st.type} !== ${je}.`);return st}function X(je){if(!ot(je))throw new SyntaxError(`Expected ${je}`);++R}function ue(){switch(S[R].type){case s.Comment:return new T(S[R++].value);case s.Text:return rt();case s.OpenStatement:return St();case s.OpenExpression:return lt();default:throw new SyntaxError(`Unexpected token type: ${S[R].type}`)}}function Ee(...je){return R+je.length<=S.length&&je.every((Ve,st)=>Ve===S[R+st].type)}function et(...je){var Ve,st,qt;return((Ve=S[R])==null?void 0:Ve.type)===s.OpenStatement&&((st=S[R+1])==null?void 0:st.type)===s.Identifier&&je.includes((qt=S[R+1])==null?void 0:qt.value)}function ot(...je){return R+je.length<=S.length&&je.every((Ve,st)=>S[R+st].type==="Identifier"&&Ve===S[R+st].value)}function rt(){return new U(W(s.Text,"Expected text token").value)}function St(){if(W(s.OpenStatement,"Expected opening statement token"),S[R].type!==s.Identifier)throw new SyntaxError(`Unknown statement, got ${S[R].type}`);const je=S[R].value;let Ve;switch(je){case"set":++R,Ve=Ot();break;case"if":++R,Ve=at(),W(s.OpenStatement,"Expected {% token"),X("endif"),W(s.CloseStatement,"Expected %} token");break;case"macro":++R,Ve=Dt(),W(s.OpenStatement,"Expected {% token"),X("endmacro"),W(s.CloseStatement,"Expected %} token");break;case"for":++R,Ve=Br(),W(s.OpenStatement,"Expected {% token"),X("endfor"),W(s.CloseStatement,"Expected %} token");break;case"call":{++R;let st=null;Ee(s.OpenParen)&&(st=ur());const qt=Wr();if(qt.type!=="Identifier")throw new SyntaxError("Expected identifier following call statement");const qs=ur();W(s.CloseStatement,"Expected closing statement token");const Bs=[];for(;!et("endcall");)Bs.push(ue());W(s.OpenStatement,"Expected '{%'"),X("endcall"),W(s.CloseStatement,"Expected closing statement token");const Qs=new v(qt,qs);Ve=new le(Qs,st,Bs);break}case"break":++R,W(s.CloseStatement,"Expected closing statement token"),Ve=new k;break;case"continue":++R,W(s.CloseStatement,"Expected closing statement token"),Ve=new w;break;case"filter":{++R;let st=Wr();st instanceof C&&Ee(s.OpenParen)&&(st=Hr(st)),W(s.CloseStatement,"Expected closing statement token");const qt=[];for(;!et("endfilter");)qt.push(ue());W(s.OpenStatement,"Expected '{%'"),X("endfilter"),W(s.CloseStatement,"Expected '%}'"),Ve=new ae(st,qt);break}default:throw new SyntaxError(`Unknown statement type: ${je}`)}return Ve}function lt(){W(s.OpenExpression,"Expected opening expression token");const je=br();return W(s.CloseExpression,"Expected closing expression token"),je}function Ot(){const je=Wt();let Ve=null;const st=[];if(Ee(s.Equals))++R,Ve=Wt();else{for(W(s.CloseStatement,"Expected %} token");!et("endset");)st.push(ue());W(s.OpenStatement,"Expected {% token"),X("endset")}return W(s.CloseStatement,"Expected closing statement token"),new y(je,Ve,st)}function at(){const je=br();W(s.CloseStatement,"Expected closing statement token");const Ve=[],st=[];for(;!et("elif","else","endif");)Ve.push(ue());if(et("elif")){++R,++R;const qt=at();st.push(qt)}else if(et("else"))for(++R,++R,W(s.CloseStatement,"Expected closing statement token");!et("endif");)st.push(ue());return new _(je,Ve,st)}function Dt(){const je=Wr();if(je.type!=="Identifier")throw new SyntaxError("Expected identifier following macro statement");const Ve=ur();W(s.CloseStatement,"Expected closing statement token");const st=[];for(;!et("endmacro");)st.push(ue());return new $(je,Ve,st)}function Wt(je=!1){const Ve=je?Wr:br,st=[Ve()],qt=Ee(s.Comma);for(;qt&&(++R,st.push(Ve()),!!Ee(s.Comma)););return qt?new se(st):st[0]}function Br(){const je=Wt(!0);if(!(je instanceof C||je instanceof se))throw new SyntaxError(`Expected identifier/tuple for the loop variable, got ${je.type} instead`);if(!ot("in"))throw new SyntaxError("Expected `in` keyword following loop variable");++R;const Ve=br();W(s.CloseStatement,"Expected closing statement token");const st=[];for(;!et("endfor","else");)st.push(ue());const qt=[];if(et("else"))for(++R,++R,W(s.CloseStatement,"Expected closing statement token");!et("endfor");)qt.push(ue());return new b(je,Ve,st,qt)}function br(){return Rr()}function Rr(){const je=Ts();if(ot("if")){++R;const Ve=Ts();if(ot("else")){++R;const st=Rr();return new ee(Ve,je,st)}else return new _e(je,Ve)}return je}function Ts(){let je=Os();for(;ot("or");){const Ve=S[R];++R;const st=Os();je=new re(Ve,je,st)}return je}function Os(){let je=gr();for(;ot("and");){const Ve=S[R];++R;const st=gr();je=new re(Ve,je,st)}return je}function gr(){let je;for(;ot("not");){const Ve=S[R];++R;const st=gr();je=new oe(Ve,st)}return je??Hs()}function Hs(){let je=cs();for(;;){let Ve;if(ot("not","in"))Ve=new o("not in",s.Identifier),R+=2;else if(ot("in"))Ve=S[R++];else if(Ee(s.ComparisonBinaryOperator))Ve=S[R++];else break;const st=cs();je=new re(Ve,je,st)}return je}function cs(){let je=Ls();for(;Ee(s.AdditiveBinaryOperator);){const Ve=S[R];++R;const st=Ls();je=new re(Ve,je,st)}return je}function jr(){const je=Ds(Wr());return Ee(s.OpenParen)?Hr(je):je}function Hr(je){let Ve=new v(je,ur());return Ve=Ds(Ve),Ee(s.OpenParen)&&(Ve=Hr(Ve)),Ve}function ur(){W(s.OpenParen,"Expected opening parenthesis for arguments list");const je=mr();return W(s.CloseParen,"Expected closing parenthesis for arguments list"),je}function mr(){const je=[];for(;!Ee(s.CloseParen);){let Ve;if(S[R].type===s.MultiplicativeBinaryOperator&&S[R].value==="*"){++R;const st=br();Ve=new Q(st)}else if(Ve=br(),Ee(s.Equals)){if(++R,!(Ve instanceof C))throw new SyntaxError("Expected identifier for keyword argument");const st=br();Ve=new B(Ve,st)}je.push(Ve),Ee(s.Comma)&&++R}return je}function Es(){const je=[];let Ve=!1;for(;!Ee(s.CloseSquareBracket);)Ee(s.Colon)?(je.push(void 0),++R,Ve=!0):(je.push(br()),Ee(s.Colon)&&(++R,Ve=!0));if(je.length===0)throw new SyntaxError("Expected at least one argument for member/slice expression");if(Ve){if(je.length>3)throw new SyntaxError("Expected 0-3 arguments for slice expression");return new G(...je)}return je[0]}function Ds(je){for(;Ee(s.Dot)||Ee(s.OpenSquareBracket);){const Ve=S[R];++R;let st;const qt=Ve.type===s.OpenSquareBracket;if(qt)st=Es(),W(s.CloseSquareBracket,"Expected closing square bracket");else if(st=Wr(),st.type!=="Identifier")throw new SyntaxError("Expected identifier following dot operator");je=new x(je,st,qt)}return je}function Ls(){let je=zs();for(;Ee(s.MultiplicativeBinaryOperator);){const Ve=S[R++],st=zs();je=new re(Ve,je,st)}return je}function zs(){let je=us();for(;ot("is");){++R;const Ve=ot("not");Ve&&++R;const st=Wr();if(!(st instanceof C))throw new SyntaxError("Expected identifier for the test");je=new pe(je,Ve,st)}return je}function us(){let je=jr();for(;Ee(s.Pipe);){++R;let Ve=Wr();if(!(Ve instanceof C))throw new SyntaxError("Expected identifier for the filter");Ee(s.OpenParen)&&(Ve=Hr(Ve)),je=new Z(je,Ve)}return je}function Wr(){const je=S[R++];switch(je.type){case s.NumericLiteral:{const Ve=je.value;return Ve.includes(".")?new K(Number(Ve)):new D(Number(Ve))}case s.StringLiteral:{let Ve=je.value;for(;Ee(s.StringLiteral);)Ve+=S[R++].value;return new U(Ve)}case s.Identifier:return new C(je.value);case s.OpenParen:{const Ve=Wt();return W(s.CloseParen,"Expected closing parenthesis, got ${tokens[current].type} instead."),Ve}case s.OpenSquareBracket:{const Ve=[];for(;!Ee(s.CloseSquareBracket);)Ve.push(br()),Ee(s.Comma)&&++R;return++R,new j(Ve)}case s.OpenCurlyBracket:{const Ve=new Map;for(;!Ee(s.CloseCurlyBracket);){const st=br();W(s.Colon,"Expected colon between key and value in object literal");const qt=br();Ve.set(st,qt),Ee(s.Comma)&&++R}return++R,new q(Ve)}default:throw new SyntaxError(`Unexpected token: ${je.type}`)}}for(;R=0?(H=(H??(H=0))<0?Math.max(S.length+H,0):Math.min(H,S.length),R=(R??(R=S.length))<0?Math.max(S.length+R,0):Math.min(R,S.length)):(H=(H??(H=S.length-1))<0?Math.max(S.length+H,-1):Math.min(H,S.length-1),R=(R??(R=-1))<-1?Math.max(S.length+R,-1):Math.min(R,S.length-1));const ue=[];for(let Ee=H;X*EeH.toUpperCase())}function te(S){return O(new Date,S)}function O(S,H){const R=new Intl.DateTimeFormat(void 0,{month:"long"}),W=new Intl.DateTimeFormat(void 0,{month:"short"}),X=ue=>ue<10?"0"+ue:ue.toString();return H.replace(/%[YmdbBHM%]/g,ue=>{switch(ue){case"%Y":return S.getFullYear().toString();case"%m":return X(S.getMonth()+1);case"%d":return X(S.getDate());case"%b":return W.format(S);case"%B":return R.format(S);case"%H":return X(S.getHours());case"%M":return X(S.getMinutes());case"%%":return"%";default:return ue}})}function me(S){return S.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function xe(S,H,R,W){if(W===0)return S;let X=W==null||W<0?1/0:W;const ue=H.length===0?new RegExp("(?=)","gu"):new RegExp(me(H),"gu");return S.replaceAll(ue,Ee=>X>0?(--X,R):Ee)}var be=class extends Error{},Ce=class extends Error{},$e=class{constructor(S=void 0){J(this,"type","RuntimeValue");J(this,"value");J(this,"builtins",new Map);this.value=S}__bool__(){return new ke(!!this.value)}toString(){return String(this.value)}},Me=class extends $e{constructor(){super(...arguments);J(this,"type","IntegerValue")}},Le=class extends $e{constructor(){super(...arguments);J(this,"type","FloatValue")}toString(){return this.value%1===0?this.value.toFixed(1):this.value.toString()}},we=class extends $e{constructor(){super(...arguments);J(this,"type","StringValue");J(this,"builtins",new Map([["upper",new Qe(()=>new we(this.value.toUpperCase()))],["lower",new Qe(()=>new we(this.value.toLowerCase()))],["strip",new Qe(()=>new we(this.value.trim()))],["title",new Qe(()=>new we(Ae(this.value)))],["capitalize",new Qe(()=>new we(this.value.charAt(0).toUpperCase()+this.value.slice(1)))],["length",new Me(this.value.length)],["rstrip",new Qe(()=>new we(this.value.trimEnd()))],["lstrip",new Qe(()=>new we(this.value.trimStart()))],["startswith",new Qe(H=>{if(H.length===0)throw new Error("startswith() requires at least one argument");const R=H[0];if(R instanceof we)return new ke(this.value.startsWith(R.value));if(R instanceof We){for(const W of R.value){if(!(W instanceof we))throw new Error("startswith() tuple elements must be strings");if(this.value.startsWith(W.value))return new ke(!0)}return new ke(!1)}throw new Error("startswith() argument must be a string or tuple of strings")})],["endswith",new Qe(H=>{if(H.length===0)throw new Error("endswith() requires at least one argument");const R=H[0];if(R instanceof we)return new ke(this.value.endsWith(R.value));if(R instanceof We){for(const W of R.value){if(!(W instanceof we))throw new Error("endswith() tuple elements must be strings");if(this.value.endsWith(W.value))return new ke(!0)}return new ke(!1)}throw new Error("endswith() argument must be a string or tuple of strings")})],["split",new Qe(H=>{const R=H[0]??new Oe;if(!(R instanceof we||R instanceof Oe))throw new Error("sep argument must be a string or null");const W=H[1]??new Me(-1);if(!(W instanceof Me))throw new Error("maxsplit argument must be a number");let X=[];if(R instanceof Oe){const ue=this.value.trimStart();for(const{0:Ee,index:et}of ue.matchAll(/\S+/g)){if(W.value!==-1&&X.length>=W.value&&et!==void 0){X.push(Ee+ue.slice(et+Ee.length));break}X.push(Ee)}}else{if(R.value==="")throw new Error("empty separator");X=this.value.split(R.value),W.value!==-1&&X.length>W.value&&X.push(X.splice(W.value).join(R.value))}return new We(X.map(ue=>new we(ue)))})],["replace",new Qe(H=>{if(H.length<2)throw new Error("replace() requires at least two arguments");const R=H[0],W=H[1];if(!(R instanceof we&&W instanceof we))throw new Error("replace() arguments must be strings");let X;if(H.length>2?H[2].type==="KeywordArgumentsValue"?X=H[2].value.get("count")??new Oe:X=H[2]:X=new Oe,!(X instanceof Me||X instanceof Oe))throw new Error("replace() count argument must be a number or null");return new we(xe(this.value,R.value,W.value,X.value))})]]))}},ke=class extends $e{constructor(){super(...arguments);J(this,"type","BooleanValue")}};function He(S,H,R,W=!0){const X=R??0;switch(S.type){case"NullValue":return"null";case"UndefinedValue":return W?"null":"undefined";case"IntegerValue":case"FloatValue":case"StringValue":case"BooleanValue":return JSON.stringify(S.value);case"ArrayValue":case"ObjectValue":{const ue=H?" ".repeat(H):"",Ee=` -`+ue.repeat(X),et=Ee+ue;if(S.type==="ArrayValue"){const ot=S.value.map(rt=>He(rt,H,X+1,W));return H?`[${et}${ot.join(`,${et}`)}${Ee}]`:`[${ot.join(", ")}]`}else{const ot=Array.from(S.value.entries()).map(([rt,St])=>{const lt=`"${rt}": ${He(St,H,X+1,W)}`;return H?`${et}${lt}`:lt});return H?`{${ot.join(",")}${Ee}}`:`{${ot.join(", ")}}`}}default:throw new Error(`Cannot convert to JSON: ${S.type}`)}}var Fe=class extends $e{constructor(){super(...arguments);J(this,"type","ObjectValue");J(this,"builtins",new Map([["get",new Qe(([H,R])=>{if(!(H instanceof we))throw new Error(`Object key must be a string: got ${H.type}`);return this.value.get(H.value)??R??new Oe})],["items",new Qe(()=>this.items())],["keys",new Qe(()=>this.keys())],["values",new Qe(()=>this.values())],["dictsort",new Qe(H=>{let R=new Map;const W=H.filter(ot=>ot instanceof Ze?(R=ot.value,!1):!0),X=W.at(0)??R.get("case_sensitive")??new ke(!1);if(!(X instanceof ke))throw new Error("case_sensitive must be a boolean");const ue=W.at(1)??R.get("by")??new we("key");if(!(ue instanceof we))throw new Error("by must be a string");if(!["key","value"].includes(ue.value))throw new Error("by must be either 'key' or 'value'");const Ee=W.at(2)??R.get("reverse")??new ke(!1);if(!(Ee instanceof ke))throw new Error("reverse must be a boolean");const et=Array.from(this.value.entries()).map(([ot,rt])=>new We([new we(ot),rt])).sort((ot,rt)=>{const St=ue.value==="key"?0:1,lt=ot.value[St],Ot=rt.value[St],at=kt(lt,Ot,X.value);return Ee.value?-at:at});return new We(et)})]]))}__bool__(){return new ke(this.value.size>0)}items(){return new We(Array.from(this.value.entries()).map(([H,R])=>new We([new we(H),R])))}keys(){return new We(Array.from(this.value.keys()).map(H=>new we(H)))}values(){return new We(Array.from(this.value.values()))}toString(){return He(this,null,0,!1)}},Ze=class extends Fe{constructor(){super(...arguments);J(this,"type","KeywordArgumentsValue")}},We=class extends $e{constructor(){super(...arguments);J(this,"type","ArrayValue");J(this,"builtins",new Map([["length",new Me(this.value.length)]]))}__bool__(){return new ke(this.value.length>0)}toString(){return He(this,null,0,!1)}},yt=class extends We{constructor(){super(...arguments);J(this,"type","TupleValue")}},Qe=class extends $e{constructor(){super(...arguments);J(this,"type","FunctionValue")}},Oe=class extends $e{constructor(){super(...arguments);J(this,"type","NullValue")}},ze=class extends $e{constructor(){super(...arguments);J(this,"type","UndefinedValue")}},pt=class{constructor(S){J(this,"variables",new Map([["namespace",new Qe(S=>{if(S.length===0)return new Fe(new Map);if(S.length!==1||!(S[0]instanceof Fe))throw new Error("`namespace` expects either zero arguments or a single object argument");return S[0]})]]));J(this,"tests",new Map([["boolean",S=>S.type==="BooleanValue"],["callable",S=>S instanceof Qe],["odd",S=>{if(!(S instanceof Me))throw new Error(`cannot odd on ${S.type}`);return S.value%2!==0}],["even",S=>{if(!(S instanceof Me))throw new Error(`cannot even on ${S.type}`);return S.value%2===0}],["false",S=>S.type==="BooleanValue"&&!S.value],["true",S=>S.type==="BooleanValue"&&S.value],["none",S=>S.type==="NullValue"],["string",S=>S.type==="StringValue"],["number",S=>S instanceof Me||S instanceof Le],["integer",S=>S instanceof Me],["iterable",S=>S.type==="ArrayValue"||S.type==="StringValue"],["mapping",S=>S.type==="ObjectValue"],["lower",S=>{const H=S.value;return S.type==="StringValue"&&H===H.toLowerCase()}],["upper",S=>{const H=S.value;return S.type==="StringValue"&&H===H.toUpperCase()}],["none",S=>S.type==="NullValue"],["defined",S=>S.type!=="UndefinedValue"],["undefined",S=>S.type==="UndefinedValue"],["equalto",(S,H)=>S.value===H.value],["eq",(S,H)=>S.value===H.value]]));this.parent=S}set(S,H){return this.declareVariable(S,fr(H))}declareVariable(S,H){if(this.variables.has(S))throw new SyntaxError(`Variable already declared: ${S}`);return this.variables.set(S,H),H}setVariable(S,H){return this.variables.set(S,H),H}resolve(S){if(this.variables.has(S))return this;if(this.parent)return this.parent.resolve(S);throw new Error(`Unknown variable: ${S}`)}lookupVariable(S){try{return this.resolve(S).variables.get(S)??new ze}catch{return new ze}}};function ft(S){S.set("false",!1),S.set("true",!0),S.set("none",null),S.set("raise_exception",H=>{throw new Error(H)}),S.set("range",De),S.set("strftime_now",te),S.set("True",!0),S.set("False",!1),S.set("None",null)}function Lt(S,H){const R=H.split(".");let W=S;for(const X of R)if(W instanceof Fe)W=W.value.get(X)??new ze;else if(W instanceof We){const ue=parseInt(X,10);if(!isNaN(ue)&&ue>=0&&ueue instanceof Me||ue instanceof Le||ue instanceof ke,X=ue=>ue instanceof ke?ue.value?1:0:ue.value;if(W(S)&&W(H)){const ue=X(S),Ee=X(H);return ueEe?1:0}if(S.type!==H.type)throw new Error(`Cannot compare different types: ${S.type} and ${H.type}`);switch(S.type){case"StringValue":{let ue=S.value,Ee=H.value;return R||(ue=ue.toLowerCase(),Ee=Ee.toLowerCase()),ueEe?1:0}default:throw new Error(`Cannot compare type: ${S.type}`)}}var Mr=class{constructor(S){J(this,"global");this.global=S??new pt}run(S){return this.evaluate(S,this.global)}evaluateBinaryExpression(S,H){const R=this.evaluate(S.left,H);switch(S.operator.value){case"and":return R.__bool__().value?this.evaluate(S.right,H):R;case"or":return R.__bool__().value?R:this.evaluate(S.right,H)}const W=this.evaluate(S.right,H);switch(S.operator.value){case"==":return new ke(R.value==W.value);case"!=":return new ke(R.value!=W.value)}if(R instanceof ze||W instanceof ze){if(W instanceof ze&&["in","not in"].includes(S.operator.value))return new ke(S.operator.value==="not in");throw new Error(`Cannot perform operation ${S.operator.value} on undefined values`)}else{if(R instanceof Oe||W instanceof Oe)throw new Error("Cannot perform operation on null values");if(S.operator.value==="~")return new we(R.value.toString()+W.value.toString());if((R instanceof Me||R instanceof Le)&&(W instanceof Me||W instanceof Le)){const X=R.value,ue=W.value;switch(S.operator.value){case"+":case"-":case"*":{const Ee=S.operator.value==="+"?X+ue:S.operator.value==="-"?X-ue:X*ue;return R instanceof Le||W instanceof Le?new Le(Ee):new Me(Ee)}case"/":return new Le(X/ue);case"%":{const Ee=X%ue;return R instanceof Le||W instanceof Le?new Le(Ee):new Me(Ee)}case"<":return new ke(X":return new ke(X>ue);case">=":return new ke(X>=ue);case"<=":return new ke(X<=ue)}}else if(R instanceof We&&W instanceof We)switch(S.operator.value){case"+":return new We(R.value.concat(W.value))}else if(W instanceof We){const X=W.value.find(ue=>ue.value===R.value)!==void 0;switch(S.operator.value){case"in":return new ke(X);case"not in":return new ke(!X)}}}if(R instanceof we||W instanceof we)switch(S.operator.value){case"+":return new we(R.value.toString()+W.value.toString())}if(R instanceof we&&W instanceof we)switch(S.operator.value){case"in":return new ke(W.value.includes(R.value));case"not in":return new ke(!W.value.includes(R.value))}if(R instanceof we&&W instanceof Fe)switch(S.operator.value){case"in":return new ke(W.value.has(R.value));case"not in":return new ke(!W.value.has(R.value))}throw new SyntaxError(`Unknown operator "${S.operator.value}" between ${R.type} and ${W.type}`)}evaluateArguments(S,H){const R=[],W=new Map;for(const X of S)if(X.type==="SpreadExpression"){const ue=X,Ee=this.evaluate(ue.argument,H);if(!(Ee instanceof We))throw new Error(`Cannot unpack non-iterable type: ${Ee.type}`);for(const et of Ee.value)R.push(et)}else if(X.type==="KeywordArgumentExpression"){const ue=X;W.set(ue.key.value,this.evaluate(ue.value,H))}else{if(W.size>0)throw new Error("Positional arguments must come before keyword arguments");R.push(this.evaluate(X,H))}return[R,W]}applyFilter(S,H,R){if(H.type==="Identifier"){const W=H;if(W.value==="tojson")return new we(He(S));if(S instanceof We)switch(W.value){case"list":return S;case"first":return S.value[0];case"last":return S.value[S.value.length-1];case"length":return new Me(S.value.length);case"reverse":return new We(S.value.slice().reverse());case"sort":return new We(S.value.slice().sort((X,ue)=>kt(X,ue,!1)));case"join":return new we(S.value.map(X=>X.value).join(""));case"string":return new we(He(S,null,0,!1));case"unique":{const X=new Set,ue=[];for(const Ee of S.value)X.has(Ee.value)||(X.add(Ee.value),ue.push(Ee));return new We(ue)}default:throw new Error(`Unknown ArrayValue filter: ${W.value}`)}else if(S instanceof we)switch(W.value){case"length":case"upper":case"lower":case"title":case"capitalize":{const X=S.builtins.get(W.value);if(X instanceof Qe)return X.value([],R);if(X instanceof Me)return X;throw new Error(`Unknown StringValue filter: ${W.value}`)}case"trim":return new we(S.value.trim());case"indent":return new we(S.value.split(` -`).map((X,ue)=>ue===0||X.length===0?X:" "+X).join(` -`));case"join":case"string":return S;case"int":{const X=parseInt(S.value,10);return new Me(isNaN(X)?0:X)}case"float":{const X=parseFloat(S.value);return new Le(isNaN(X)?0:X)}default:throw new Error(`Unknown StringValue filter: ${W.value}`)}else if(S instanceof Me||S instanceof Le)switch(W.value){case"abs":return S instanceof Me?new Me(Math.abs(S.value)):new Le(Math.abs(S.value));case"int":return new Me(Math.floor(S.value));case"float":return new Le(S.value);default:throw new Error(`Unknown NumericValue filter: ${W.value}`)}else if(S instanceof Fe)switch(W.value){case"items":return new We(Array.from(S.value.entries()).map(([X,ue])=>new We([new we(X),ue])));case"length":return new Me(S.value.size);default:{const X=S.builtins.get(W.value);if(X)return X instanceof Qe?X.value([],R):X;throw new Error(`Unknown ObjectValue filter: ${W.value}`)}}else if(S instanceof ke)switch(W.value){case"bool":return new ke(S.value);case"int":return new Me(S.value?1:0);case"float":return new Le(S.value?1:0);case"string":return new we(S.value?"true":"false");default:throw new Error(`Unknown BooleanValue filter: ${W.value}`)}throw new Error(`Cannot apply filter "${W.value}" to type: ${S.type}`)}else if(H.type==="CallExpression"){const W=H;if(W.callee.type!=="Identifier")throw new Error(`Unknown filter: ${W.callee.type}`);const X=W.callee.value;if(X==="tojson"){const[,ue]=this.evaluateArguments(W.args,R),Ee=ue.get("indent")??new Oe;if(!(Ee instanceof Me||Ee instanceof Oe))throw new Error("If set, indent must be a number");return new we(He(S,Ee.value))}else if(X==="join"){let ue;if(S instanceof we)ue=Array.from(S.value);else if(S instanceof We)ue=S.value.map(rt=>rt.value);else throw new Error(`Cannot apply filter "${X}" to type: ${S.type}`);const[Ee,et]=this.evaluateArguments(W.args,R),ot=Ee.at(0)??et.get("separator")??new we("");if(!(ot instanceof we))throw new Error("separator must be a string");return new we(ue.join(ot.value))}else if(X==="int"||X==="float"){const[ue,Ee]=this.evaluateArguments(W.args,R),et=ue.at(0)??Ee.get("default")??(X==="int"?new Me(0):new Le(0));if(S instanceof we){const ot=X==="int"?parseInt(S.value,10):parseFloat(S.value);return isNaN(ot)?et:X==="int"?new Me(ot):new Le(ot)}else{if(S instanceof Me||S instanceof Le)return S;if(S instanceof ke)return X==="int"?new Me(S.value?1:0):new Le(S.value?1:0);throw new Error(`Cannot apply filter "${X}" to type: ${S.type}`)}}else if(X==="default"){const[ue,Ee]=this.evaluateArguments(W.args,R),et=ue[0]??new we(""),ot=ue[1]??Ee.get("boolean")??new ke(!1);if(!(ot instanceof ke))throw new Error("`default` filter flag must be a boolean");return S instanceof ze||ot.value&&!S.__bool__().value?et:S}if(S instanceof We){switch(X){case"sort":{const[ue,Ee]=this.evaluateArguments(W.args,R),et=ue.at(0)??Ee.get("reverse")??new ke(!1);if(!(et instanceof ke))throw new Error("reverse must be a boolean");const ot=ue.at(1)??Ee.get("case_sensitive")??new ke(!1);if(!(ot instanceof ke))throw new Error("case_sensitive must be a boolean");const rt=ue.at(2)??Ee.get("attribute")??new Oe;if(!(rt instanceof we||rt instanceof Me||rt instanceof Oe))throw new Error("attribute must be a string, integer, or null");const St=lt=>{if(rt instanceof Oe)return lt;const Ot=rt instanceof Me?String(rt.value):rt.value;return Lt(lt,Ot)};return new We(S.value.slice().sort((lt,Ot)=>{const at=St(lt),Dt=St(Ot),Wt=kt(at,Dt,ot.value);return et.value?-Wt:Wt}))}case"selectattr":case"rejectattr":{const ue=X==="selectattr";if(S.value.some(lt=>!(lt instanceof Fe)))throw new Error(`\`${X}\` can only be applied to array of objects`);if(W.args.some(lt=>lt.type!=="StringLiteral"))throw new Error(`arguments of \`${X}\` must be strings`);const[Ee,et,ot]=W.args.map(lt=>this.evaluate(lt,R));let rt;if(et){const lt=R.tests.get(et.value);if(!lt)throw new Error(`Unknown test: ${et.value}`);rt=lt}else rt=(...lt)=>lt[0].__bool__().value;const St=S.value.filter(lt=>{const Ot=lt.value.get(Ee.value),at=Ot?rt(Ot,ot):!1;return ue?at:!at});return new We(St)}case"map":{const[,ue]=this.evaluateArguments(W.args,R);if(ue.has("attribute")){const Ee=ue.get("attribute");if(!(Ee instanceof we))throw new Error("attribute must be a string");const et=ue.get("default"),ot=S.value.map(rt=>{if(!(rt instanceof Fe))throw new Error("items in map must be an object");const St=Lt(rt,Ee.value);return St instanceof ze?et??new ze:St});return new We(ot)}else throw new Error("`map` expressions without `attribute` set are not currently supported.")}}throw new Error(`Unknown ArrayValue filter: ${X}`)}else if(S instanceof we){switch(X){case"indent":{const[ue,Ee]=this.evaluateArguments(W.args,R),et=ue.at(0)??Ee.get("width")??new Me(4);if(!(et instanceof Me))throw new Error("width must be a number");const ot=ue.at(1)??Ee.get("first")??new ke(!1),rt=ue.at(2)??Ee.get("blank")??new ke(!1),St=S.value.split(` -`),lt=" ".repeat(et.value),Ot=St.map((at,Dt)=>!ot.value&&Dt===0||!rt.value&&at.length===0?at:lt+at);return new we(Ot.join(` -`))}case"replace":{const ue=S.builtins.get("replace");if(!(ue instanceof Qe))throw new Error("replace filter not available");const[Ee,et]=this.evaluateArguments(W.args,R);return ue.value([...Ee,new Ze(et)],R)}}throw new Error(`Unknown StringValue filter: ${X}`)}else if(S instanceof Fe){const ue=S.builtins.get(X);if(ue&&ue instanceof Qe){const[Ee,et]=this.evaluateArguments(W.args,R);return et.size>0&&Ee.push(new Ze(et)),ue.value(Ee,R)}throw new Error(`Unknown ObjectValue filter: ${X}`)}else throw new Error(`Cannot apply filter "${X}" to type: ${S.type}`)}throw new Error(`Unknown filter: ${H.type}`)}evaluateFilterExpression(S,H){const R=this.evaluate(S.operand,H);return this.applyFilter(R,S.filter,H)}evaluateTestExpression(S,H){const R=this.evaluate(S.operand,H),W=H.tests.get(S.test.value);if(!W)throw new Error(`Unknown test: ${S.test.value}`);const X=W(R);return new ke(S.negate?!X:X)}evaluateSelectExpression(S,H){return this.evaluate(S.test,H).__bool__().value?this.evaluate(S.lhs,H):new ze}evaluateUnaryExpression(S,H){const R=this.evaluate(S.argument,H);switch(S.operator.value){case"not":return new ke(!R.value);default:throw new SyntaxError(`Unknown operator: ${S.operator.value}`)}}evaluateTernaryExpression(S,H){return this.evaluate(S.condition,H).__bool__().value?this.evaluate(S.trueExpr,H):this.evaluate(S.falseExpr,H)}evalProgram(S,H){return this.evaluateBlock(S.body,H)}evaluateBlock(S,H){let R="";for(const W of S){const X=this.evaluate(W,H);X.type!=="NullValue"&&X.type!=="UndefinedValue"&&(R+=X.toString())}return new we(R)}evaluateIdentifier(S,H){return H.lookupVariable(S.value)}evaluateCallExpression(S,H){const[R,W]=this.evaluateArguments(S.args,H);W.size>0&&R.push(new Ze(W));const X=this.evaluate(S.callee,H);if(X.type!=="FunctionValue")throw new Error(`Cannot call something that is not a function: got ${X.type}`);return X.value(R,H)}evaluateSliceExpression(S,H,R){if(!(S instanceof We||S instanceof we))throw new Error("Slice object must be an array or string");const W=this.evaluate(H.start,R),X=this.evaluate(H.stop,R),ue=this.evaluate(H.step,R);if(!(W instanceof Me||W instanceof ze))throw new Error("Slice start must be numeric or undefined");if(!(X instanceof Me||X instanceof ze))throw new Error("Slice stop must be numeric or undefined");if(!(ue instanceof Me||ue instanceof ze))throw new Error("Slice step must be numeric or undefined");return S instanceof We?new We(Ne(S.value,W.value,X.value,ue.value)):new we(Ne(Array.from(S.value),W.value,X.value,ue.value).join(""))}evaluateMemberExpression(S,H){const R=this.evaluate(S.object,H);let W;if(S.computed){if(S.property.type==="SliceExpression")return this.evaluateSliceExpression(R,S.property,H);W=this.evaluate(S.property,H)}else W=new we(S.property.value);let X;if(R instanceof Fe){if(!(W instanceof we))throw new Error(`Cannot access property with non-string: got ${W.type}`);X=R.value.get(W.value)??R.builtins.get(W.value)}else if(R instanceof We||R instanceof we)if(W instanceof Me)X=R.value.at(W.value),R instanceof we&&(X=new we(R.value.at(W.value)));else if(W instanceof we)X=R.builtins.get(W.value);else throw new Error(`Cannot access property with non-string/non-number: got ${W.type}`);else{if(!(W instanceof we))throw new Error(`Cannot access property with non-string: got ${W.type}`);X=R.builtins.get(W.value)}return X instanceof $e?X:new ze}evaluateSet(S,H){const R=S.value?this.evaluate(S.value,H):this.evaluateBlock(S.body,H);if(S.assignee.type==="Identifier"){const W=S.assignee.value;H.setVariable(W,R)}else if(S.assignee.type==="TupleLiteral"){const W=S.assignee;if(!(R instanceof We))throw new Error(`Cannot unpack non-iterable type in set: ${R.type}`);const X=R.value;if(X.length!==W.value.length)throw new Error(`Too ${W.value.length>X.length?"few":"many"} items to unpack in set`);for(let ue=0;ueat.setVariable(S.loopvar.value,lt);else if(S.loopvar.type==="TupleLiteral"){const at=S.loopvar;if(lt.type!=="ArrayValue")throw new Error(`Cannot unpack non-iterable type: ${lt.type}`);const Dt=lt;if(at.value.length!==Dt.value.length)throw new Error(`Too ${at.value.length>Dt.value.length?"few":"many"} items to unpack`);Ot=Wt=>{for(let Br=0;Br0?ue[rt-1]:new ze],["nextitem",rt{var Ee;const X=new pt(W);R=R.slice();let ue;((Ee=R.at(-1))==null?void 0:Ee.type)==="KeywordArgumentsValue"&&(ue=R.pop());for(let et=0;et{const rt=new pt(ot);if(S.callerArgs)for(let St=0;Stthis.evaluate(R,H)));case"TupleLiteral":return new yt(S.value.map(R=>this.evaluate(R,H)));case"ObjectLiteral":{const R=new Map;for(const[W,X]of S.value){const ue=this.evaluate(W,H);if(!(ue instanceof we))throw new Error(`Object keys must be strings: got ${ue.type}`);R.set(ue.value,this.evaluate(X,H))}return new Fe(R)}case"Identifier":return this.evaluateIdentifier(S,H);case"CallExpression":return this.evaluateCallExpression(S,H);case"MemberExpression":return this.evaluateMemberExpression(S,H);case"UnaryExpression":return this.evaluateUnaryExpression(S,H);case"BinaryExpression":return this.evaluateBinaryExpression(S,H);case"FilterExpression":return this.evaluateFilterExpression(S,H);case"FilterStatement":return this.evaluateFilterStatement(S,H);case"TestExpression":return this.evaluateTestExpression(S,H);case"SelectExpression":return this.evaluateSelectExpression(S,H);case"Ternary":return this.evaluateTernaryExpression(S,H);case"Comment":return new Oe;default:throw new SyntaxError(`Unknown node type: ${S.type}`)}}};function fr(S){switch(typeof S){case"number":return Number.isInteger(S)?new Me(S):new Le(S);case"string":return new we(S);case"boolean":return new ke(S);case"undefined":return new ze;case"object":return S===null?new Oe:Array.isArray(S)?new We(S.map(fr)):new Fe(new Map(Object.entries(S).map(([H,R])=>[H,fr(R)])));case"function":return new Qe((H,R)=>{const W=S(...H.map(X=>X.value))??null;return fr(W)});default:throw new Error(`Cannot convert to runtime value: ${S}`)}}var Ut=` -`,Ur="{%- ",Ws=" -%}";function Gs(S){switch(S.operator.type){case"MultiplicativeBinaryOperator":return 4;case"AdditiveBinaryOperator":return 3;case"ComparisonBinaryOperator":return 2;case"Identifier":return S.operator.value==="and"?1:S.operator.value==="in"||S.operator.value==="not in"?2:0}return 0}function nn(S,H=" "){const R=typeof H=="number"?" ".repeat(H):H;return zr(S.body,0,R).replace(/\n$/,"")}function cr(...S){return Ur+S.join(" ")+Ws}function zr(S,H,R){return S.map(W=>ls(W,H,R)).join(Ut)}function ls(S,H,R){const W=R.repeat(H);switch(S.type){case"Program":return zr(S.body,H,R);case"If":return Ks(S,H,R);case"For":return gt(S,H,R);case"Set":return Is(S,H,R);case"Macro":return As(S,H,R);case"Break":return W+cr("break");case"Continue":return W+cr("continue");case"CallStatement":return Yt(S,H,R);case"FilterStatement":return Jr(S,H,R);case"Comment":return W+"{# "+S.value+" #}";default:return W+"{{- "+$t(S)+" -}}"}}function Ks(S,H,R){const W=R.repeat(H),X=[];let ue=S;for(;ue&&(X.push({test:ue.test,body:ue.body}),ue.alternate.length===1&&ue.alternate[0].type==="If");)ue=ue.alternate[0];let Ee=W+cr("if",$t(X[0].test))+Ut+zr(X[0].body,H+1,R);for(let et=1;et0&&(Ee+=Ut+W+cr("else")+Ut+zr(ue.alternate,H+1,R)),Ee+=Ut+W+cr("endif"),Ee}function gt(S,H,R){const W=R.repeat(H);let X="";if(S.iterable.type==="SelectExpression"){const Ee=S.iterable;X=`${$t(Ee.lhs)} if ${$t(Ee.test)}`}else X=$t(S.iterable);let ue=W+cr("for",$t(S.loopvar),"in",X)+Ut+zr(S.body,H+1,R);return S.defaultBlock.length>0&&(ue+=Ut+W+cr("else")+Ut+zr(S.defaultBlock,H+1,R)),ue+=Ut+W+cr("endfor"),ue}function Is(S,H,R){const W=R.repeat(H),X=$t(S.assignee),ue=S.value?$t(S.value):"",Ee=W+cr("set",`${X}${S.value?" = "+ue:""}`);return S.body.length===0?Ee:Ee+Ut+zr(S.body,H+1,R)+Ut+W+cr("endset")}function As(S,H,R){const W=R.repeat(H),X=S.args.map($t).join(", ");return W+cr("macro",`${S.name.value}(${X})`)+Ut+zr(S.body,H+1,R)+Ut+W+cr("endmacro")}function Yt(S,H,R){const W=R.repeat(H),X=S.callerArgs&&S.callerArgs.length>0?`(${S.callerArgs.map($t).join(", ")})`:"",ue=$t(S.call);let Ee=W+cr(`call${X}`,ue)+Ut;return Ee+=zr(S.body,H+1,R)+Ut,Ee+=W+cr("endcall"),Ee}function Jr(S,H,R){const W=R.repeat(H),X=S.filter.type==="Identifier"?S.filter.value:$t(S.filter);let ue=W+cr("filter",X)+Ut;return ue+=zr(S.body,H+1,R)+Ut,ue+=W+cr("endfilter"),ue}function $t(S,H=-1){switch(S.type){case"SpreadExpression":return`*${$t(S.argument)}`;case"Identifier":return S.value;case"IntegerLiteral":return`${S.value}`;case"FloatLiteral":return`${S.value}`;case"StringLiteral":return JSON.stringify(S.value);case"BinaryExpression":{const R=S,W=Gs(R),X=$t(R.left,W),ue=$t(R.right,W+1),Ee=`${X} ${R.operator.value} ${ue}`;return W`${$t(W)}: ${$t(X)}`).join(", ")}}`;case"SliceExpression":{const R=S,W=R.start?$t(R.start):"",X=R.stop?$t(R.stop):"",ue=R.step?`:${$t(R.step)}`:"";return`${W}:${X}${ue}`}case"KeywordArgumentExpression":{const R=S;return`${R.key.value}=${$t(R.value)}`}case"Ternary":{const R=S,W=`${$t(R.trueExpr)} if ${$t(R.condition,0)} else ${$t(R.falseExpr)}`;return H>-1?`(${W})`:W}default:throw new Error(`Unknown expression type: ${S.type}`)}}var Fs=class{constructor(S){J(this,"parsed");const H=d(S,{lstrip_blocks:!0,trim_blocks:!0});this.parsed=Se(H)}render(S){const H=new pt;if(ft(H),S)for(const[X,ue]of Object.entries(S))H.set(X,ue);return new Mr(H).run(this.parsed).value}format(S){return nn(this.parsed,(S==null?void 0:S.indent)||" ")}}},"./src/backends/onnx.js":(e,r,t)=>{var s;t.r(r),t.d(r,{Tensor:()=>i.Tensor,createInferenceSession:()=>k,deviceToExecutionProviders:()=>_,isONNXProxy:()=>x,isONNXTensor:()=>T,runInferenceSession:()=>$});var o=t("./src/env.js"),n=t("?2ce3"),a=t("onnxruntime-web"),i=t("onnxruntime-common");const l=Object.freeze({auto:null,gpu:null,cpu:"cpu",wasm:"wasm",webgpu:"webgpu",cuda:"cuda",dml:"dml",webnn:{name:"webnn",deviceType:"cpu"},"webnn-npu":{name:"webnn",deviceType:"npu"},"webnn-gpu":{name:"webnn",deviceType:"gpu"},"webnn-cpu":{name:"webnn",deviceType:"cpu"}}),c=[];let p,d;const u=Symbol.for("onnxruntime");if(u in globalThis)d=globalThis[u];else if(o.apis.IS_NODE_ENV){switch(d=n??(s||(s=t.t(n,2))),process.platform){case"win32":c.push("dml");break;case"linux":process.arch==="x64"&&c.push("cuda");break}c.push("cpu"),p=["cpu"]}else d=a,o.apis.IS_WEBNN_AVAILABLE&&c.push("webnn-npu","webnn-gpu","webnn-cpu","webnn"),o.apis.IS_WEBGPU_AVAILABLE&&c.push("webgpu"),c.push("wasm"),p=["wasm"];const f=d.InferenceSession;function _(v=null){if(!v)return p;switch(v){case"auto":return c;case"gpu":return c.filter(C=>["webgpu","cuda","dml","webnn-gpu"].includes(C))}if(c.includes(v))return[l[v]??v];throw new Error(`Unsupported device: "${v}". Should be one of: ${c.join(", ")}.`)}let b=null;async function k(v,C,F){b&&await b;const D=f.create(v,C);b??(b=D);const K=await D;return K.config=F,K}let w=Promise.resolve();const y=o.apis.IS_BROWSER_ENV||o.apis.IS_WEBWORKER_ENV;async function $(v,C){const F=()=>v.run(C);return await(y?w=w.then(F):F())}function T(v){return v instanceof d.Tensor}const M=d==null?void 0:d.env;M!=null&&M.wasm&&(!(typeof ServiceWorkerGlobalScope<"u"&&self instanceof ServiceWorkerGlobalScope)&&!M.wasm.wasmPaths&&(M.wasm.wasmPaths=`https://cdn.jsdelivr.net/npm/@huggingface/transformers@${o.env.version}/dist/`),M.wasm.proxy=!1),M!=null&&M.webgpu&&(M.webgpu.powerPreference="high-performance");function x(){var v;return(v=M==null?void 0:M.wasm)==null?void 0:v.proxy}o.env.backends.onnx=M},"./src/base/feature_extraction_utils.js":(e,r,t)=>{t.r(r),t.d(r,{FeatureExtractor:()=>a,validate_audio_inputs:()=>i});var s=t("./src/utils/constants.js"),o=t("./src/utils/generic.js"),n=t("./src/utils/hub.js");class a extends o.Callable{constructor(c){super(),this.config=c}static async from_pretrained(c,p={}){const d=await(0,n.getModelJSON)(c,s.FEATURE_EXTRACTOR_NAME,!0,p);return new this(d)}}function i(l,c){var p;if(!(l instanceof Float32Array||l instanceof Float64Array))throw new Error(`${c} expects input to be a Float32Array or a Float64Array, but got ${((p=l==null?void 0:l.constructor)==null?void 0:p.name)??typeof l} instead. If using the feature extractor directly, remember to use \`read_audio(url, sampling_rate)\` to obtain the raw audio data of the file/url.`)}},"./src/base/image_processors_utils.js":(e,r,t)=>{t.r(r),t.d(r,{ImageProcessor:()=>T,center_to_corners_format:()=>d,post_process_instance_segmentation:()=>$,post_process_object_detection:()=>u,post_process_panoptic_segmentation:()=>y,post_process_semantic_segmentation:()=>f});var s=t("./src/utils/generic.js"),o=t("./src/utils/tensor.js"),n=t("./src/utils/maths.js");t("./src/utils/image.js");var a=t("./src/utils/core.js"),i=t("./src/utils/hub.js"),l=t("./src/utils/constants.js");function c(M,x,v=0,C=null){const F=M/x;let D=(0,n.bankers_round)(F)*x;return C!==null&&D>C&&(D=Math.floor(F)*x),Dx&&G.push(Q)}else{let Q=(0,n.max)(oe.data)[1];if(Q===j-1||(B=(0,n.softmax)(oe.data),B[Q]ee*re[(Se+1)%2])),Z.boxes.push(le),Z.classes.push(Q),Z.scores.push(B[Q])}}se.push(Z)}return se}function f(M,x=null){const v=M.logits,C=v.dims[0];if(x!==null&&x.length!==C)throw Error("Make sure that you pass in as many target sizes as the batch dimension of the logits");const F=[];for(let D=0;Dre[G]&&(re[G]=oe[G],Z[G]=pe)}const ae=new Array(U.dims[0]);for(let pe=0;pepe!==void 0);F.push({segmentation:q,labels:_e})}return F}function _(M,x,v,C){const F=[],D=[],K=[];for(let U=0;Uv&&(F.push(se),D.push(Z),K.push(q))}return[F,D,K]}function b(M,x,v,C=.5,F=.8){const D=[];let K=0,U=0;const j=x[v].data;for(let q=0;q=C&&++U;let se=K>0&&U>0;return se&&(se=K/U>F),[se,D]}function k(M,x,v,C,F,D=null,K=null){const[U,j]=K??M[0].dims,se=new o.Tensor("int32",new Int32Array(U*j),[U,j]),q=[];if(K!==null)for(let pe=0;peZ[B]&&(re[B]=pe,Z[B]=G[B])}let ae=0;const _e=se.data;for(let pe=0;pe200)throw new Error(`absolute aspect ratio must be smaller than 200, got ${Math.max(M,x)/Math.min(M,x)}`);let D=Math.round(M/v)*v,K=Math.round(x/v)*v;if(D*K>F){const U=Math.sqrt(M*x/F);D=Math.floor(M/U/v)*v,K=Math.floor(x/U/v)*v}else if(D*KD?se=Math.floor(D*j/F):D>F&&(j=Math.floor(F*se/D)),await x.resize(se,j,{resample:C}))}async crop_margin(x,v=200){const C=x.clone().grayscale(),F=(0,n.min)(C.data)[0],K=(0,n.max)(C.data)[0]-F;if(K===0)return x;const U=v/255;let j=C.width,se=C.height,q=0,re=0;const Z=C.data;for(let ae=0;aethis.preprocess(D)));return{pixel_values:(0,o.stack)(C.map(D=>D.pixel_values),0),original_sizes:C.map(D=>D.original_size),reshaped_input_sizes:C.map(D=>D.reshaped_input_size)}}static async from_pretrained(x,v={}){const C=await(0,i.getModelJSON)(x,l.IMAGE_PROCESSOR_NAME,!0,v);return new this(C)}}},"./src/base/processing_utils.js":(e,r,t)=>{t.r(r),t.d(r,{Processor:()=>a});var s=t("./src/utils/constants.js"),o=t("./src/utils/generic.js"),n=t("./src/utils/hub.js");class a extends o.Callable{constructor(l,c,p){super(),this.config=l,this.components=c,this.chat_template=p}get image_processor(){return this.components.image_processor}get tokenizer(){return this.components.tokenizer}get feature_extractor(){return this.components.feature_extractor}apply_chat_template(l,c={}){if(!this.tokenizer)throw new Error("Unable to apply chat template without a tokenizer.");return this.tokenizer.apply_chat_template(l,{tokenize:!1,chat_template:this.chat_template??void 0,...c})}batch_decode(...l){if(!this.tokenizer)throw new Error("Unable to decode without a tokenizer.");return this.tokenizer.batch_decode(...l)}decode(...l){if(!this.tokenizer)throw new Error("Unable to decode without a tokenizer.");return this.tokenizer.decode(...l)}async _call(l,...c){for(const p of[this.image_processor,this.feature_extractor,this.tokenizer])if(p)return p(l,...c);throw new Error("No image processor, feature extractor, or tokenizer found.")}static async from_pretrained(l,c={}){const[p,d,u]=await Promise.all([this.uses_processor_config?(0,n.getModelJSON)(l,s.PROCESSOR_NAME,!0,c):{},Promise.all(this.classes.filter(f=>f in this).map(async f=>{const _=await this[f].from_pretrained(l,c);return[f.replace(/_class$/,""),_]})).then(Object.fromEntries),this.uses_chat_template_file?(0,n.getModelText)(l,s.CHAT_TEMPLATE_NAME,!0,c):null]);return new this(p,d,u)}}J(a,"classes",["image_processor_class","tokenizer_class","feature_extractor_class"]),J(a,"uses_processor_config",!1),J(a,"uses_chat_template_file",!1)},"./src/configs.js":(e,r,t)=>{t.r(r),t.d(r,{AutoConfig:()=>p,PretrainedConfig:()=>c,getCacheShapes:()=>i});var s=t("./src/utils/core.js"),o=t("./src/utils/hub.js");async function n(d,u){return await(0,o.getModelJSON)(d,"config.json",!0,u)}function a(d){const u={};let f={};switch(d.model_type){case"llava":case"paligemma":case"gemma3":case"florence2":case"llava_onevision":case"idefics3":case"ultravox":case"voxtral":case"smolvlm":case"gemma3n":case"mistral3":f=a(d.text_config);break;case"moondream1":f=a(d.phi_config);break;case"musicgen":f=a(d.decoder);break;case"multi_modality":f=a(d.language_config);break;case"gpt2":case"gptj":case"jais":case"codegen":case"gpt_bigcode":u.num_heads="n_head",u.num_layers="n_layer",u.hidden_size="n_embd";break;case"gpt_neox":case"stablelm":case"opt":case"falcon":case"modernbert-decoder":u.num_heads="num_attention_heads",u.num_layers="num_hidden_layers",u.hidden_size="hidden_size";break;case"llama":case"llama4_text":case"nanochat":case"arcee":case"lfm2":case"smollm3":case"olmo":case"olmo2":case"mobilellm":case"granite":case"granitemoehybrid":case"cohere":case"mistral":case"starcoder2":case"qwen2":case"qwen2_vl":case"phi":case"phi3":case"phi3_v":case"llava_qwen2":u.num_heads="num_key_value_heads",u.num_layers="num_hidden_layers",u.hidden_size="hidden_size",u.num_attention_heads="num_attention_heads",u.dim_kv="head_dim";break;case"qwen3":case"gemma":case"gemma2":case"vaultgemma":case"gemma3_text":case"gemma3n_text":case"glm":case"helium":case"ernie4_5":case"ministral":case"ministral3":u.num_heads="num_key_value_heads",u.num_layers="num_hidden_layers",u.dim_kv="head_dim";break;case"openelm":u.num_heads="num_kv_heads",u.num_layers="num_transformer_layers",u.dim_kv="head_dim";break;case"gpt_neo":case"donut-swin":u.num_heads="num_heads",u.num_layers="num_layers",u.hidden_size="hidden_size";break;case"bloom":u.num_heads="n_head",u.num_layers="n_layer",u.hidden_size="hidden_size";break;case"mpt":u.num_heads="n_heads",u.num_layers="n_layers",u.hidden_size="d_model";break;case"exaone":u.num_heads="num_key_value_heads",u.num_layers="num_layers",u.dim_kv="head_dim",u.num_attention_heads="num_attention_heads";break;case"t5":case"mt5":case"longt5":u.num_decoder_layers="num_decoder_layers",u.num_decoder_heads="num_heads",u.decoder_dim_kv="d_kv",u.num_encoder_layers="num_layers",u.num_encoder_heads="num_heads",u.encoder_dim_kv="d_kv";break;case"bart":case"mbart":case"marian":case"whisper":case"lite-whisper":case"m2m_100":case"blenderbot":case"blenderbot-small":case"florence2_language":u.num_decoder_layers="decoder_layers",u.num_decoder_heads="decoder_attention_heads",u.decoder_hidden_size="d_model",u.num_encoder_layers="encoder_layers",u.num_encoder_heads="encoder_attention_heads",u.encoder_hidden_size="d_model";break;case"speecht5":u.num_decoder_layers="decoder_layers",u.num_decoder_heads="decoder_attention_heads",u.decoder_hidden_size="hidden_size",u.num_encoder_layers="encoder_layers",u.num_encoder_heads="encoder_attention_heads",u.encoder_hidden_size="hidden_size";break;case"trocr":u.num_encoder_layers=u.num_decoder_layers="decoder_layers",u.num_encoder_heads=u.num_decoder_heads="decoder_attention_heads",u.encoder_hidden_size=u.decoder_hidden_size="d_model";break;case"musicgen_decoder":u.num_encoder_layers=u.num_decoder_layers="num_hidden_layers",u.num_encoder_heads=u.num_decoder_heads="num_attention_heads",u.encoder_hidden_size=u.decoder_hidden_size="hidden_size";break;case"moonshine":u.num_decoder_layers="decoder_num_hidden_layers",u.num_decoder_heads="decoder_num_key_value_heads",u.num_encoder_layers="encoder_num_hidden_layers",u.num_encoder_heads="encoder_num_key_value_heads",u.encoder_hidden_size=u.decoder_hidden_size="hidden_size";break;case"vision-encoder-decoder":const b=a(d.decoder),k="num_decoder_layers"in b,w=(0,s.pick)(d,["model_type","is_encoder_decoder"]);return k?(w.num_decoder_layers=b.num_decoder_layers,w.num_decoder_heads=b.num_decoder_heads,w.decoder_hidden_size=b.decoder_hidden_size,w.num_encoder_layers=b.num_encoder_layers,w.num_encoder_heads=b.num_encoder_heads,w.encoder_hidden_size=b.encoder_hidden_size):(w.num_layers=b.num_layers,w.num_heads=b.num_heads,w.hidden_size=b.hidden_size),w}const _={...f,...(0,s.pick)(d,["model_type","multi_query","is_encoder_decoder"])};for(const b in u)_[b]=d[u[b]];return _}function i(d,u){if(d.model_type==="lfm2"){const f=(u==null?void 0:u.prefix)??"past_key_values",_=f==="present"?"present":"past",b={},{layer_types:k,num_attention_heads:w,num_key_value_heads:y,hidden_size:$,conv_L_cache:T}=d,M=$/w,x=(u==null?void 0:u.batch_size)??1;for(let v=0;v{var F,D;t.r(r),t.d(r,{apis:()=>w,env:()=>v});var s=t("?db59"),o=t("?383f"),n=t("?fa4b");const a="3.8.1",i=typeof window<"u"&&typeof window.document<"u",l=typeof self<"u"&&["DedicatedWorkerGlobalScope","ServiceWorkerGlobalScope","SharedWorkerGlobalScope"].includes((F=self.constructor)==null?void 0:F.name),c=typeof self<"u"&&"caches"in self,p=typeof navigator<"u"&&"gpu"in navigator,d=typeof navigator<"u"&&"ml"in navigator,u=typeof process<"u",f=u&&((D=process==null?void 0:process.release)==null?void 0:D.name)==="node",_=!C(s),b=!C(o),k=typeof globalThis.Deno<"u",w=Object.freeze({IS_BROWSER_ENV:i,IS_WEBWORKER_ENV:l,IS_WEB_CACHE_AVAILABLE:c,IS_WEBGPU_AVAILABLE:p,IS_WEBNN_AVAILABLE:d,IS_PROCESS_AVAILABLE:u,IS_NODE_ENV:f,IS_FS_AVAILABLE:_,IS_PATH_AVAILABLE:b}),y=_&&b;let $="./";if(y){const K=Object({url:self.location.href}).url;K?$=o.dirname(o.dirname(n.fileURLToPath(K))):typeof __dirname<"u"&&($=o.dirname(__dirname))}const T=y?o.join($,"/.cache/"):null,M="/models/",x=y?o.join($,M):M,v={version:a,backends:{onnx:{}},allowRemoteModels:!0,remoteHost:"https://huggingface.co/",remotePathTemplate:"{model}/resolve/{revision}/",allowLocalModels:!(i||l),localModelPath:x,useFS:_,useBrowserCache:c&&!k,useFSCache:_,cacheDir:T,useCustomCache:!1,customCache:null};function C(K){return Object.keys(K).length===0}},"./src/generation/configuration_utils.js":(e,r,t)=>{t.r(r),t.d(r,{GenerationConfig:()=>o});var s=t("./src/utils/core.js");class o{constructor(a){J(this,"max_length",20);J(this,"max_new_tokens",null);J(this,"min_length",0);J(this,"min_new_tokens",null);J(this,"early_stopping",!1);J(this,"max_time",null);J(this,"do_sample",!1);J(this,"num_beams",1);J(this,"num_beam_groups",1);J(this,"penalty_alpha",null);J(this,"use_cache",!0);J(this,"temperature",1);J(this,"top_k",50);J(this,"top_p",1);J(this,"typical_p",1);J(this,"epsilon_cutoff",0);J(this,"eta_cutoff",0);J(this,"diversity_penalty",0);J(this,"repetition_penalty",1);J(this,"encoder_repetition_penalty",1);J(this,"length_penalty",1);J(this,"no_repeat_ngram_size",0);J(this,"bad_words_ids",null);J(this,"force_words_ids",null);J(this,"renormalize_logits",!1);J(this,"constraints",null);J(this,"forced_bos_token_id",null);J(this,"forced_eos_token_id",null);J(this,"remove_invalid_values",!1);J(this,"exponential_decay_length_penalty",null);J(this,"suppress_tokens",null);J(this,"streamer",null);J(this,"begin_suppress_tokens",null);J(this,"forced_decoder_ids",null);J(this,"guidance_scale",null);J(this,"num_return_sequences",1);J(this,"output_attentions",!1);J(this,"output_hidden_states",!1);J(this,"output_scores",!1);J(this,"return_dict_in_generate",!1);J(this,"pad_token_id",null);J(this,"bos_token_id",null);J(this,"eos_token_id",null);J(this,"encoder_no_repeat_ngram_size",0);J(this,"decoder_start_token_id",null);J(this,"generation_kwargs",{});Object.assign(this,(0,s.pick)(a,Object.getOwnPropertyNames(this)))}}},"./src/generation/logits_process.js":(e,r,t)=>{t.r(r),t.d(r,{ClassifierFreeGuidanceLogitsProcessor:()=>w,ForcedBOSTokenLogitsProcessor:()=>l,ForcedEOSTokenLogitsProcessor:()=>c,LogitsProcessor:()=>n,LogitsProcessorList:()=>i,LogitsWarper:()=>a,MinLengthLogitsProcessor:()=>_,MinNewTokensLengthLogitsProcessor:()=>b,NoBadWordsLogitsProcessor:()=>k,NoRepeatNGramLogitsProcessor:()=>u,RepetitionPenaltyLogitsProcessor:()=>f,SuppressTokensAtBeginLogitsProcessor:()=>p,TemperatureLogitsWarper:()=>y,TopKLogitsWarper:()=>T,TopPLogitsWarper:()=>$,WhisperTimeStampLogitsProcessor:()=>d});var s=t("./src/utils/generic.js");t("./src/utils/tensor.js");var o=t("./src/utils/maths.js");class n extends s.Callable{_call(x,v){throw Error("`_call` should be implemented in a subclass")}}class a extends s.Callable{_call(x,v){throw Error("`_call` should be implemented in a subclass")}}class i extends s.Callable{constructor(){super(),this.processors=[]}push(x){this.processors.push(x)}extend(x){this.processors.push(...x)}_call(x,v){let C=v;for(const F of this.processors)C=F(x,C);return C}[Symbol.iterator](){return this.processors.values()}}class l extends n{constructor(x){super(),this.bos_token_id=x}_call(x,v){for(let C=0;C=1&&D[D.length-1]>=this.timestamp_begin,U=D.length<2||D[D.length-2]>=this.timestamp_begin;if(K&&(U?F.subarray(this.timestamp_begin).fill(-1/0):F.subarray(0,this.eos_token_id).fill(-1/0)),x[C].length===this.begin_index&&this.max_initial_timestamp_index!==null){const re=this.timestamp_begin+this.max_initial_timestamp_index;F.subarray(re+1).fill(-1/0)}const j=(0,o.log_softmax)(F),se=Math.log(j.subarray(this.timestamp_begin).map(Math.exp).reduce((re,Z)=>re+Z)),q=(0,o.max)(j.subarray(0,this.timestamp_begin))[0];se>q&&F.subarray(0,this.timestamp_begin).fill(-1/0)}return v}}class u extends n{constructor(x){super(),this.no_repeat_ngram_size=x}getNgrams(x){const v=x.length,C=[];for(let D=0;D1 to use the classifier free guidance processor, got guidance scale ${x}.`);this.guidance_scale=x}_call(x,v){if(v.dims[0]!==2*x.length)throw new Error(`Logits should have twice the batch size of the input ids, the first half of batches corresponding to the conditional inputs, and the second half of batches corresponding to the unconditional inputs. Got batch size ${v.dims[0]} for the logits and ${x.length} for the input ids.`);const C=x.length,F=v.slice([0,C],null),D=v.slice([C,v.dims[0]],null);for(let K=0;K1)throw new Error(`\`top_p\` must be a float > 0 and < 1, but is ${x}`);if(!Number.isInteger(C)||C<1)throw new Error(`\`min_tokens_to_keep\` must be a positive integer, but is ${C}`);this.top_p=x,this.filter_value=v,this.min_tokens_to_keep=C}}class T extends a{constructor(x,{filter_value:v=-1/0,min_tokens_to_keep:C=1}={}){if(super(),!Number.isInteger(x)||x<0)throw new Error(`\`top_k\` must be a positive integer, but is ${x}`);this.top_k=Math.max(x,C),this.filter_value=v}}},"./src/generation/logits_sampler.js":(e,r,t)=>{t.r(r),t.d(r,{LogitsSampler:()=>a});var s=t("./src/utils/generic.js"),o=t("./src/utils/tensor.js"),n=t("./src/utils/maths.js");t("./src/generation/configuration_utils.js");class a extends s.Callable{constructor(d){super(),this.generation_config=d}async _call(d){return this.sample(d)}async sample(d){throw Error("sample should be implemented in subclasses.")}getLogits(d,u){let f=d.dims.at(-1),_=d.data;if(u===-1)_=_.slice(-f);else{let b=u*f;_=_.slice(b,b+f)}return _}randomSelect(d){let u=0;for(let _=0;_1)return new c(d);if(d.num_return_sequences>1)throw Error(`num_return_sequences has to be 1 when doing greedy search, but is ${d.num_return_sequences}.`);return new i(d)}}class i extends a{async sample(d){const u=(0,n.max)(d.data)[1];return[[BigInt(u),0]]}}class l extends a{async sample(d){let u=d.dims.at(-1);this.generation_config.top_k>0&&(u=Math.min(this.generation_config.top_k,u));const[f,_]=await(0,o.topk)(d,u),b=(0,n.softmax)(f.data);return Array.from({length:this.generation_config.num_beams},()=>{const k=this.randomSelect(b);return[_.data[k],Math.log(b[k])]})}}class c extends a{async sample(d){let u=d.dims.at(-1);this.generation_config.top_k>0&&(u=Math.min(this.generation_config.top_k,u));const[f,_]=await(0,o.topk)(d,u),b=(0,n.softmax)(f.data);return Array.from({length:this.generation_config.num_beams},(k,w)=>[_.data[w],Math.log(b[w])])}}},"./src/generation/stopping_criteria.js":(e,r,t)=>{t.r(r),t.d(r,{EosTokenCriteria:()=>i,InterruptableStoppingCriteria:()=>l,MaxLengthCriteria:()=>a,StoppingCriteria:()=>o,StoppingCriteriaList:()=>n});var s=t("./src/utils/generic.js");class o extends s.Callable{_call(p,d){throw Error("StoppingCriteria needs to be subclassed")}}class n extends s.Callable{constructor(){super(),this.criteria=[]}push(p){this.criteria.push(p)}extend(p){p instanceof n?p=p.criteria:p instanceof o&&(p=[p]),this.criteria.push(...p)}_call(p,d){const u=new Array(p.length).fill(!1);for(const f of this.criteria){const _=f(p,d);for(let b=0;bd.length>=this.max_length)}}class i extends o{constructor(p){super(),Array.isArray(p)||(p=[p]),this.eos_token_id=p}_call(p,d){return p.map(u=>{const f=u.at(-1);return this.eos_token_id.some(_=>f==_)})}}class l extends o{constructor(){super(),this.interrupted=!1}interrupt(){this.interrupted=!0}reset(){this.interrupted=!1}_call(p,d){return new Array(p.length).fill(this.interrupted)}}},"./src/generation/streamers.js":(e,r,t)=>{t.r(r),t.d(r,{BaseStreamer:()=>a,TextStreamer:()=>l,WhisperTextStreamer:()=>c});var s=t("./src/utils/core.js"),o=t("./src/tokenizers.js"),n=t("./src/env.js");class a{put(d){throw Error("Not implemented")}end(){throw Error("Not implemented")}}const i=n.apis.IS_PROCESS_AVAILABLE?p=>process.stdout.write(p):p=>console.log(p);class l extends a{constructor(d,{skip_prompt:u=!1,callback_function:f=null,token_callback_function:_=null,skip_special_tokens:b=!0,decode_kwargs:k={},...w}={}){super(),this.tokenizer=d,this.skip_prompt=u,this.callback_function=f??i,this.token_callback_function=_,this.decode_kwargs={skip_special_tokens:b,...k,...w},this.token_cache=[],this.print_len=0,this.next_tokens_are_prompt=!0}put(d){var k;if(d.length>1)throw Error("TextStreamer only supports batch size of 1");const u=this.next_tokens_are_prompt;if(u&&(this.next_tokens_are_prompt=!1,this.skip_prompt))return;const f=d[0];(k=this.token_callback_function)==null||k.call(this,f),this.token_cache=(0,s.mergeArrays)(this.token_cache,f);const _=this.tokenizer.decode(this.token_cache,this.decode_kwargs);let b;u||_.endsWith(` -`)?(b=_.slice(this.print_len),this.token_cache=[],this.print_len=0):_.length>0&&(0,o.is_chinese_char)(_.charCodeAt(_.length-1))?(b=_.slice(this.print_len),this.print_len+=b.length):(b=_.slice(this.print_len,_.lastIndexOf(" ")+1),this.print_len+=b.length),this.on_finalized_text(b,!1)}end(){let d;this.token_cache.length>0?(d=this.tokenizer.decode(this.token_cache,this.decode_kwargs).slice(this.print_len),this.token_cache=[],this.print_len=0):d="",this.next_tokens_are_prompt=!0,this.on_finalized_text(d,!0)}on_finalized_text(d,u){var f,_;d.length>0&&((f=this.callback_function)==null||f.call(this,d)),u&&this.callback_function===i&&n.apis.IS_PROCESS_AVAILABLE&&((_=this.callback_function)==null||_.call(this,` -`))}}class c extends l{constructor(d,{skip_prompt:u=!1,callback_function:f=null,token_callback_function:_=null,on_chunk_start:b=null,on_chunk_end:k=null,on_finalize:w=null,time_precision:y=.02,skip_special_tokens:$=!0,decode_kwargs:T={}}={}){super(d,{skip_prompt:u,skip_special_tokens:$,callback_function:f,token_callback_function:_,decode_kwargs:T}),this.timestamp_begin=d.timestamp_begin,this.on_chunk_start=b,this.on_chunk_end=k,this.on_finalize=w,this.time_precision=y,this.waiting_for_timestamp=!1}put(d){var f,_,b;if(d.length>1)throw Error("WhisperTextStreamer only supports batch size of 1");const u=d[0];if(u.length===1){const k=Number(u[0])-this.timestamp_begin;if(k>=0){const w=k*this.time_precision;this.waiting_for_timestamp?(f=this.on_chunk_end)==null||f.call(this,w):(_=this.on_chunk_start)==null||_.call(this,w),this.waiting_for_timestamp=!this.waiting_for_timestamp,(b=this.token_callback_function)==null||b.call(this,u);return}}return super.put(d)}end(){var d;super.end(),(d=this.on_finalize)==null||d.call(this)}}},"./src/models.js":(e,r,t)=>{t.r(r),t.d(r,{ASTForAudioClassification:()=>La,ASTModel:()=>Da,ASTPreTrainedModel:()=>Xn,AlbertForMaskedLM:()=>tt,AlbertForQuestionAnswering:()=>qe,AlbertForSequenceClassification:()=>Xe,AlbertModel:()=>Ge,AlbertPreTrainedModel:()=>Te,ArceeForCausalLM:()=>Ja,ArceeModel:()=>Ys,ArceePreTrainedModel:()=>Er,AutoModel:()=>Bu,AutoModelForAudioClassification:()=>Iv,AutoModelForAudioFrameClassification:()=>Fv,AutoModelForAudioTextToText:()=>Vv,AutoModelForCTC:()=>kv,AutoModelForCausalLM:()=>Mv,AutoModelForDepthEstimation:()=>zv,AutoModelForDocumentQuestionAnswering:()=>Ov,AutoModelForImageClassification:()=>xv,AutoModelForImageFeatureExtraction:()=>jv,AutoModelForImageMatting:()=>Dv,AutoModelForImageSegmentation:()=>Tv,AutoModelForImageTextToText:()=>Nv,AutoModelForImageToImage:()=>Lv,AutoModelForMaskGeneration:()=>$v,AutoModelForMaskedLM:()=>bv,AutoModelForNormalEstimation:()=>Bv,AutoModelForObjectDetection:()=>Cv,AutoModelForPoseEstimation:()=>Rv,AutoModelForQuestionAnswering:()=>yv,AutoModelForSemanticSegmentation:()=>Ev,AutoModelForSeq2SeqLM:()=>_v,AutoModelForSequenceClassification:()=>mv,AutoModelForSpeechSeq2Seq:()=>fv,AutoModelForTextToSpectrogram:()=>gv,AutoModelForTextToWaveform:()=>wv,AutoModelForTokenClassification:()=>hv,AutoModelForUniversalSegmentation:()=>Pv,AutoModelForVision2Seq:()=>vv,AutoModelForXVector:()=>Av,AutoModelForZeroShotObjectDetection:()=>Sv,BartForConditionalGeneration:()=>rr,BartForSequenceClassification:()=>Tr,BartModel:()=>ss,BartPretrainedModel:()=>Cr,BaseModelOutput:()=>xe,BeitForImageClassification:()=>AM,BeitModel:()=>IM,BeitPreTrainedModel:()=>Xc,BertForMaskedLM:()=>$e,BertForQuestionAnswering:()=>we,BertForSequenceClassification:()=>Me,BertForTokenClassification:()=>Le,BertModel:()=>Ce,BertPreTrainedModel:()=>be,BlenderbotForConditionalGeneration:()=>wr,BlenderbotModel:()=>_r,BlenderbotPreTrainedModel:()=>dr,BlenderbotSmallForConditionalGeneration:()=>Xs,BlenderbotSmallModel:()=>qr,BlenderbotSmallPreTrainedModel:()=>or,BloomForCausalLM:()=>eM,BloomModel:()=>Zw,BloomPreTrainedModel:()=>Bc,CLIPModel:()=>Lo,CLIPPreTrainedModel:()=>Cs,CLIPSegForImageSegmentation:()=>to,CLIPSegModel:()=>An,CLIPSegPreTrainedModel:()=>Zr,CLIPTextModel:()=>qa,CLIPTextModelWithProjection:()=>zo,CLIPVisionModel:()=>Qa,CLIPVisionModelWithProjection:()=>Bo,CamembertForMaskedLM:()=>ue,CamembertForQuestionAnswering:()=>ot,CamembertForSequenceClassification:()=>Ee,CamembertForTokenClassification:()=>et,CamembertModel:()=>X,CamembertPreTrainedModel:()=>W,CausalLMOutput:()=>dn,CausalLMOutputWithPast:()=>ZT,ChineseCLIPModel:()=>mt,ChineseCLIPPreTrainedModel:()=>kn,ClapAudioModelWithProjection:()=>Qy,ClapModel:()=>Hy,ClapPreTrainedModel:()=>oi,ClapTextModelWithProjection:()=>qy,CodeGenForCausalLM:()=>V,CodeGenModel:()=>z,CodeGenPreTrainedModel:()=>A,CohereForCausalLM:()=>Aw,CohereModel:()=>Iw,CoherePreTrainedModel:()=>Sc,ConvBertForMaskedLM:()=>gt,ConvBertForQuestionAnswering:()=>Yt,ConvBertForSequenceClassification:()=>Is,ConvBertForTokenClassification:()=>As,ConvBertModel:()=>Ks,ConvBertPreTrainedModel:()=>ls,ConvNextForImageClassification:()=>Pb,ConvNextModel:()=>Eb,ConvNextPreTrainedModel:()=>du,ConvNextV2ForImageClassification:()=>Sb,ConvNextV2Model:()=>Cb,ConvNextV2PreTrainedModel:()=>pu,DFineForObjectDetection:()=>GM,DFineModel:()=>WM,DFinePreTrainedModel:()=>ru,DINOv3ConvNextModel:()=>Lb,DINOv3ConvNextPreTrainedModel:()=>Db,DINOv3ViTModel:()=>Ob,DINOv3ViTPreTrainedModel:()=>Fb,DPTForDepthEstimation:()=>ib,DPTModel:()=>ab,DPTPreTrainedModel:()=>lu,DacDecoderModel:()=>z0,DacDecoderOutput:()=>O0,DacEncoderModel:()=>L0,DacEncoderOutput:()=>F0,DacModel:()=>D0,DacPreTrainedModel:()=>pi,DebertaForMaskedLM:()=>lt,DebertaForQuestionAnswering:()=>Dt,DebertaForSequenceClassification:()=>Ot,DebertaForTokenClassification:()=>at,DebertaModel:()=>St,DebertaPreTrainedModel:()=>rt,DebertaV2ForMaskedLM:()=>br,DebertaV2ForQuestionAnswering:()=>Os,DebertaV2ForSequenceClassification:()=>Rr,DebertaV2ForTokenClassification:()=>Ts,DebertaV2Model:()=>Br,DebertaV2PreTrainedModel:()=>Wt,DecisionTransformerModel:()=>f0,DecisionTransformerPreTrainedModel:()=>_0,DeiTForImageClassification:()=>XM,DeiTModel:()=>QM,DeiTPreTrainedModel:()=>nu,DepthAnythingForDepthEstimation:()=>cb,DepthAnythingPreTrainedModel:()=>lb,DepthProForDepthEstimation:()=>hb,DepthProPreTrainedModel:()=>mb,DetrForObjectDetection:()=>OM,DetrForSegmentation:()=>Jc,DetrModel:()=>FM,DetrObjectDetectionOutput:()=>Yc,DetrPreTrainedModel:()=>Ya,DetrSegmentationOutput:()=>DM,Dinov2ForImageClassification:()=>kb,Dinov2Model:()=>$b,Dinov2PreTrainedModel:()=>mu,Dinov2WithRegistersForImageClassification:()=>Ab,Dinov2WithRegistersModel:()=>Ib,Dinov2WithRegistersPreTrainedModel:()=>hu,DistilBertForMaskedLM:()=>ur,DistilBertForQuestionAnswering:()=>Hr,DistilBertForSequenceClassification:()=>cs,DistilBertForTokenClassification:()=>jr,DistilBertModel:()=>Hs,DistilBertPreTrainedModel:()=>gr,DonutSwinModel:()=>Tb,DonutSwinPreTrainedModel:()=>xb,EdgeTamModel:()=>Hb,EfficientNetForImageClassification:()=>r0,EfficientNetModel:()=>t0,EfficientNetPreTrainedModel:()=>Su,ElectraForMaskedLM:()=>Fs,ElectraForQuestionAnswering:()=>R,ElectraForSequenceClassification:()=>S,ElectraForTokenClassification:()=>H,ElectraModel:()=>$t,ElectraPreTrainedModel:()=>Jr,Ernie4_5ForCausalLM:()=>Vy,Ernie4_5Model:()=>Ny,Ernie4_5PreTrainedModel:()=>xu,EsmForMaskedLM:()=>Ds,EsmForSequenceClassification:()=>Ls,EsmForTokenClassification:()=>zs,EsmModel:()=>Es,EsmPreTrainedModel:()=>mr,ExaoneForCausalLM:()=>bw,ExaoneModel:()=>Mw,ExaonePreTrainedModel:()=>vc,FalconForCausalLM:()=>Ky,FalconModel:()=>Gy,FalconPreTrainedModel:()=>Eu,FastViTForImageClassification:()=>bM,FastViTModel:()=>MM,FastViTPreTrainedModel:()=>Gc,Florence2ForConditionalGeneration:()=>Va,Florence2PreTrainedModel:()=>Na,GLPNForDepthEstimation:()=>vb,GLPNModel:()=>yb,GLPNPreTrainedModel:()=>uu,GPT2LMHeadModel:()=>Wo,GPT2Model:()=>Uo,GPT2PreTrainedModel:()=>ro,GPTBigCodeForCausalLM:()=>E,GPTBigCodeModel:()=>h,GPTBigCodePreTrainedModel:()=>ao,GPTJForCausalLM:()=>Xo,GPTJModel:()=>Qo,GPTJPreTrainedModel:()=>oo,GPTNeoForCausalLM:()=>no,GPTNeoModel:()=>On,GPTNeoPreTrainedModel:()=>so,GPTNeoXForCausalLM:()=>qo,GPTNeoXModel:()=>Ho,GPTNeoXPreTrainedModel:()=>Dn,Gemma2ForCausalLM:()=>Lw,Gemma2Model:()=>Dw,Gemma2PreTrainedModel:()=>kc,Gemma3ForCausalLM:()=>jw,Gemma3Model:()=>Rw,Gemma3PreTrainedModel:()=>Ac,Gemma3nForConditionalGeneration:()=>ln,Gemma3nPreTrainedModel:()=>Ka,GemmaForCausalLM:()=>Ow,GemmaModel:()=>Fw,GemmaPreTrainedModel:()=>$c,GlmForCausalLM:()=>ww,GlmModel:()=>gw,GlmPreTrainedModel:()=>yc,GraniteForCausalLM:()=>Sw,GraniteModel:()=>Cw,GraniteMoeHybridForCausalLM:()=>kw,GraniteMoeHybridModel:()=>$w,GraniteMoeHybridPreTrainedModel:()=>Cc,GranitePreTrainedModel:()=>Pc,GroundingDinoForObjectDetection:()=>Bb,GroundingDinoPreTrainedModel:()=>zb,GroupViTModel:()=>wM,GroupViTPreTrainedModel:()=>gM,HeliumForCausalLM:()=>fw,HeliumModel:()=>_w,HeliumPreTrainedModel:()=>bc,HieraForImageClassification:()=>YM,HieraModel:()=>JM,HieraPreTrainedModel:()=>ou,HubertForCTC:()=>by,HubertForSequenceClassification:()=>yy,HubertModel:()=>My,HubertPreTrainedModel:()=>RT,IJepaForImageClassification:()=>lM,IJepaModel:()=>iM,IJepaPreTrainedModel:()=>Vc,Idefics3ForConditionalGeneration:()=>Sn,Idefics3PreTrainedModel:()=>cn,ImageMattingOutput:()=>Wv,JAISLMHeadModel:()=>Ko,JAISModel:()=>Go,JAISPreTrainedModel:()=>Fn,JinaCLIPModel:()=>No,JinaCLIPPreTrainedModel:()=>eo,JinaCLIPTextModel:()=>Vo,JinaCLIPVisionModel:()=>In,Lfm2ForCausalLM:()=>pw,Lfm2Model:()=>dw,Lfm2PreTrainedModel:()=>wc,LiteWhisperForConditionalGeneration:()=>za,Llama4ForCausalLM:()=>it,Llama4PreTrainedModel:()=>Je,LlamaForCausalLM:()=>Re,LlamaModel:()=>Pe,LlamaPreTrainedModel:()=>ce,LlavaForConditionalGeneration:()=>Cn,LlavaOnevisionForConditionalGeneration:()=>Ra,LlavaPreTrainedModel:()=>Pn,LlavaQwen2ForCausalLM:()=>Oo,LongT5ForConditionalGeneration:()=>yr,LongT5Model:()=>Jt,LongT5PreTrainedModel:()=>nr,M2M100ForConditionalGeneration:()=>Yb,M2M100Model:()=>Jb,M2M100PreTrainedModel:()=>gu,MBartForCausalLM:()=>ds,MBartForConditionalGeneration:()=>Ps,MBartForSequenceClassification:()=>Fr,MBartModel:()=>Yr,MBartPreTrainedModel:()=>Ar,MPNetForMaskedLM:()=>Bs,MPNetForQuestionAnswering:()=>he,MPNetForSequenceClassification:()=>Qs,MPNetForTokenClassification:()=>En,MPNetModel:()=>qs,MPNetPreTrainedModel:()=>qt,MT5ForConditionalGeneration:()=>xr,MT5Model:()=>hr,MT5PreTrainedModel:()=>vr,MarianMTModel:()=>Xb,MarianModel:()=>Qb,MarianPreTrainedModel:()=>fu,MaskFormerForInstanceSegmentation:()=>bb,MaskFormerModel:()=>Mb,MaskFormerPreTrainedModel:()=>cu,MaskedLMOutput:()=>Or,Metric3DForDepthEstimation:()=>fb,Metric3DPreTrainedModel:()=>_b,Metric3Dv2ForDepthEstimation:()=>wb,Metric3Dv2PreTrainedModel:()=>gb,MgpstrForSceneTextRecognition:()=>y0,MgpstrModelOutput:()=>M0,MgpstrPreTrainedModel:()=>b0,MimiDecoderModel:()=>A0,MimiDecoderOutput:()=>$0,MimiEncoderModel:()=>I0,MimiEncoderOutput:()=>S0,MimiModel:()=>k0,MimiPreTrainedModel:()=>di,Ministral3ForCausalLM:()=>jy,Ministral3Model:()=>Ry,Ministral3PreTrainedModel:()=>vu,MinistralForCausalLM:()=>By,MinistralModel:()=>zy,MinistralPreTrainedModel:()=>yu,Mistral3ForConditionalGeneration:()=>Ga,MistralForCausalLM:()=>Ly,MistralModel:()=>Dy,MistralPreTrainedModel:()=>bu,MobileBertForMaskedLM:()=>je,MobileBertForQuestionAnswering:()=>st,MobileBertForSequenceClassification:()=>Ve,MobileBertModel:()=>Wr,MobileBertPreTrainedModel:()=>us,MobileLLMForCausalLM:()=>vw,MobileLLMModel:()=>yw,MobileLLMPreTrainedModel:()=>xc,MobileNetV1ForImageClassification:()=>n0,MobileNetV1ForSemanticSegmentation:()=>o0,MobileNetV1Model:()=>s0,MobileNetV1PreTrainedModel:()=>ii,MobileNetV2ForImageClassification:()=>i0,MobileNetV2ForSemanticSegmentation:()=>l0,MobileNetV2Model:()=>a0,MobileNetV2PreTrainedModel:()=>li,MobileNetV3ForImageClassification:()=>u0,MobileNetV3ForSemanticSegmentation:()=>d0,MobileNetV3Model:()=>c0,MobileNetV3PreTrainedModel:()=>ci,MobileNetV4ForImageClassification:()=>m0,MobileNetV4ForSemanticSegmentation:()=>h0,MobileNetV4Model:()=>p0,MobileNetV4PreTrainedModel:()=>ui,MobileViTForImageClassification:()=>TM,MobileViTModel:()=>xM,MobileViTPreTrainedModel:()=>Kc,MobileViTV2ForImageClassification:()=>PM,MobileViTV2Model:()=>EM,MobileViTV2PreTrainedModel:()=>Hc,ModelOutput:()=>me,ModernBertDecoderForCausalLM:()=>Mr,ModernBertDecoderModel:()=>kt,ModernBertDecoderPreTrainedModel:()=>Lt,ModernBertForMaskedLM:()=>ze,ModernBertForSequenceClassification:()=>pt,ModernBertForTokenClassification:()=>ft,ModernBertModel:()=>Oe,ModernBertPreTrainedModel:()=>Qe,Moondream1ForConditionalGeneration:()=>ja,MoonshineForConditionalGeneration:()=>Ba,MoonshineModel:()=>gc,MoonshinePreTrainedModel:()=>Yn,MptForCausalLM:()=>rM,MptModel:()=>tM,MptPreTrainedModel:()=>Rc,MultiModalityCausalLM:()=>w0,MultiModalityPreTrainedModel:()=>g0,MusicgenForCausalLM:()=>UT,MusicgenForConditionalGeneration:()=>ku,MusicgenModel:()=>VT,MusicgenPreTrainedModel:()=>$u,NanoChatForCausalLM:()=>Qt,NanoChatModel:()=>Rt,NanoChatPreTrainedModel:()=>xt,NeoBertForMaskedLM:()=>Fe,NeoBertForQuestionAnswering:()=>yt,NeoBertForSequenceClassification:()=>Ze,NeoBertForTokenClassification:()=>We,NeoBertModel:()=>He,NeoBertPreTrainedModel:()=>ke,NomicBertModel:()=>Ut,NomicBertPreTrainedModel:()=>fr,OPTForCausalLM:()=>nM,OPTModel:()=>sM,OPTPreTrainedModel:()=>jc,Olmo2ForCausalLM:()=>Pw,Olmo2Model:()=>Ew,Olmo2PreTrainedModel:()=>Ec,OlmoForCausalLM:()=>Tw,OlmoModel:()=>xw,OlmoPreTrainedModel:()=>Tc,OpenELMForCausalLM:()=>Vw,OpenELMModel:()=>Nw,OpenELMPreTrainedModel:()=>Fc,OwlViTForObjectDetection:()=>SM,OwlViTModel:()=>CM,OwlViTPreTrainedModel:()=>qc,Owlv2ForObjectDetection:()=>kM,Owlv2Model:()=>$M,Owlv2PreTrainedModel:()=>Qc,PaliGemmaForConditionalGeneration:()=>Wa,PaliGemmaPreTrainedModel:()=>Ua,ParakeetForCTC:()=>ny,ParakeetPreTrainedModel:()=>sy,PatchTSMixerForPrediction:()=>E0,PatchTSMixerModel:()=>T0,PatchTSMixerPreTrainedModel:()=>Au,PatchTSTForPrediction:()=>x0,PatchTSTModel:()=>v0,PatchTSTPreTrainedModel:()=>Iu,Phi3ForCausalLM:()=>Yw,Phi3Model:()=>Jw,Phi3PreTrainedModel:()=>zc,Phi3VForCausalLM:()=>$n,Phi3VPreTrainedModel:()=>Ha,PhiForCausalLM:()=>Xw,PhiModel:()=>Qw,PhiPreTrainedModel:()=>Lc,PreTrainedModel:()=>O,PretrainedMixin:()=>Gt,PvtForImageClassification:()=>pM,PvtModel:()=>dM,PvtPreTrainedModel:()=>Uc,PyAnnoteForAudioFrameClassification:()=>ay,PyAnnoteModel:()=>oy,PyAnnotePreTrainedModel:()=>wu,QuestionAnsweringModelOutput:()=>Nr,Qwen2ForCausalLM:()=>Ww,Qwen2Model:()=>Uw,Qwen2PreTrainedModel:()=>Oc,Qwen2VLForConditionalGeneration:()=>qw,Qwen2VLPreTrainedModel:()=>Hw,Qwen3ForCausalLM:()=>Kw,Qwen3Model:()=>Gw,Qwen3PreTrainedModel:()=>Dc,RFDetrForObjectDetection:()=>VM,RFDetrModel:()=>NM,RFDetrObjectDetectionOutput:()=>UM,RFDetrPreTrainedModel:()=>tu,RTDetrForObjectDetection:()=>zM,RTDetrModel:()=>LM,RTDetrObjectDetectionOutput:()=>Jo,RTDetrPreTrainedModel:()=>Zc,RTDetrV2ForObjectDetection:()=>RM,RTDetrV2Model:()=>BM,RTDetrV2ObjectDetectionOutput:()=>jM,RTDetrV2PreTrainedModel:()=>eu,ResNetForImageClassification:()=>eb,ResNetModel:()=>ZM,ResNetPreTrainedModel:()=>au,RoFormerForMaskedLM:()=>Gs,RoFormerForQuestionAnswering:()=>zr,RoFormerForSequenceClassification:()=>nn,RoFormerForTokenClassification:()=>cr,RoFormerModel:()=>Ws,RoFormerPreTrainedModel:()=>Ur,RobertaForMaskedLM:()=>Ta,RobertaForQuestionAnswering:()=>Pa,RobertaForSequenceClassification:()=>$o,RobertaForTokenClassification:()=>Ea,RobertaModel:()=>xa,RobertaPreTrainedModel:()=>Rs,Sam2ImageSegmentationOutput:()=>Gb,Sam2Model:()=>ti,Sam2PreTrainedModel:()=>Kb,Sam3TrackerModel:()=>qb,SamImageSegmentationOutput:()=>Wb,SamModel:()=>Ub,SamPreTrainedModel:()=>Vb,SapiensForDepthEstimation:()=>db,SapiensForNormalEstimation:()=>pb,SapiensForSemanticSegmentation:()=>ub,SapiensPreTrainedModel:()=>ei,SegformerForImageClassification:()=>Jy,SegformerForSemanticSegmentation:()=>Yy,SegformerModel:()=>NT,SegformerPreTrainedModel:()=>ai,Seq2SeqLMOutput:()=>YT,SequenceClassifierOutput:()=>Et,SiglipModel:()=>Xa,SiglipPreTrainedModel:()=>Zn,SiglipTextModel:()=>Ro,SiglipVisionModel:()=>jo,SmolLM3ForCausalLM:()=>hw,SmolLM3Model:()=>mw,SmolLM3PreTrainedModel:()=>Mc,SmolVLMForConditionalGeneration:()=>Do,SnacDecoderModel:()=>j0,SnacEncoderModel:()=>R0,SnacModel:()=>B0,SnacPreTrainedModel:()=>mi,SpeechT5ForSpeechToText:()=>$y,SpeechT5ForTextToSpeech:()=>ky,SpeechT5HifiGan:()=>Iy,SpeechT5Model:()=>jT,SpeechT5PreTrainedModel:()=>ni,SqueezeBertForMaskedLM:()=>Y,SqueezeBertForQuestionAnswering:()=>de,SqueezeBertForSequenceClassification:()=>ie,SqueezeBertModel:()=>N,SqueezeBertPreTrainedModel:()=>I,StableLmForCausalLM:()=>e0,StableLmModel:()=>Zy,StableLmPreTrainedModel:()=>Cu,Starcoder2ForCausalLM:()=>Wy,Starcoder2Model:()=>Uy,Starcoder2PreTrainedModel:()=>Tu,StyleTextToSpeech2Model:()=>Sy,StyleTextToSpeech2PreTrainedModel:()=>Cy,SupertonicForConditionalGeneration:()=>Mu,SupertonicPreTrainedModel:()=>Ay,Swin2SRForImageSuperResolution:()=>ob,Swin2SRModel:()=>nb,Swin2SRPreTrainedModel:()=>iu,SwinForImageClassification:()=>rb,SwinForSemanticSegmentation:()=>sb,SwinModel:()=>tb,SwinPreTrainedModel:()=>Za,T5ForConditionalGeneration:()=>Bt,T5Model:()=>jt,T5PreTrainedModel:()=>bt,TableTransformerForObjectDetection:()=>HM,TableTransformerModel:()=>KM,TableTransformerObjectDetectionOutput:()=>qM,TableTransformerPreTrainedModel:()=>su,TokenClassifierOutput:()=>Sr,TrOCRForCausalLM:()=>Oy,TrOCRPreTrainedModel:()=>Fy,UltravoxModel:()=>Fu,UltravoxPreTrainedModel:()=>P0,UniSpeechForCTC:()=>uy,UniSpeechForSequenceClassification:()=>dy,UniSpeechModel:()=>cy,UniSpeechPreTrainedModel:()=>ri,UniSpeechSatForAudioFrameClassification:()=>_y,UniSpeechSatForCTC:()=>my,UniSpeechSatForSequenceClassification:()=>hy,UniSpeechSatModel:()=>py,UniSpeechSatPreTrainedModel:()=>Yo,VaultGemmaForCausalLM:()=>Bw,VaultGemmaModel:()=>zw,VaultGemmaPreTrainedModel:()=>Ic,ViTForImageClassification:()=>aM,ViTMAEModel:()=>hM,ViTMAEPreTrainedModel:()=>mM,ViTMSNForImageClassification:()=>fM,ViTMSNModel:()=>_M,ViTMSNPreTrainedModel:()=>Wc,ViTModel:()=>oM,ViTPreTrainedModel:()=>Nc,VisionEncoderDecoderModel:()=>Fo,VitMatteForImageMatting:()=>vM,VitMattePreTrainedModel:()=>yM,VitPoseForPoseEstimation:()=>uM,VitPosePreTrainedModel:()=>cM,VitsModel:()=>Pu,VitsModelOutput:()=>Gv,VitsPreTrainedModel:()=>Xy,VoxtralForConditionalGeneration:()=>C0,Wav2Vec2BertForCTC:()=>gy,Wav2Vec2BertForSequenceClassification:()=>wy,Wav2Vec2BertModel:()=>fy,Wav2Vec2BertPreTrainedModel:()=>si,Wav2Vec2ForAudioFrameClassification:()=>ry,Wav2Vec2ForCTC:()=>ey,Wav2Vec2ForSequenceClassification:()=>ty,Wav2Vec2Model:()=>Zb,Wav2Vec2PreTrainedModel:()=>un,WavLMForAudioFrameClassification:()=>Py,WavLMForCTC:()=>xy,WavLMForSequenceClassification:()=>Ty,WavLMForXVector:()=>Ey,WavLMModel:()=>vy,WavLMPreTrainedModel:()=>io,WeSpeakerResNetModel:()=>ly,WeSpeakerResNetPreTrainedModel:()=>iy,WhisperForConditionalGeneration:()=>Js,WhisperModel:()=>Ao,WhisperPreTrainedModel:()=>Jn,XLMForQuestionAnswering:()=>Ia,XLMForSequenceClassification:()=>$a,XLMForTokenClassification:()=>ka,XLMModel:()=>Ca,XLMPreTrainedModel:()=>on,XLMRobertaForMaskedLM:()=>Fa,XLMRobertaForQuestionAnswering:()=>Io,XLMRobertaForSequenceClassification:()=>Oa,XLMRobertaForTokenClassification:()=>ko,XLMRobertaModel:()=>Aa,XLMRobertaPreTrainedModel:()=>an,XLMWithLMHeadModel:()=>Sa,XVectorOutput:()=>Uv,YolosForObjectDetection:()=>jb,YolosModel:()=>Rb,YolosObjectDetectionOutput:()=>Nb,YolosPreTrainedModel:()=>_u});var s=t("./src/configs.js"),o=t("./src/backends/onnx.js"),n=t("./src/utils/dtypes.js"),a=t("./src/utils/generic.js"),i=t("./src/utils/core.js"),l=t("./src/utils/hub.js"),c=t("./src/utils/constants.js"),p=t("./src/generation/logits_process.js"),d=t("./src/generation/configuration_utils.js"),u=t("./src/utils/tensor.js"),f=t("./src/utils/image.js"),_=t("./src/utils/maths.js"),b=t("./src/generation/stopping_criteria.js"),k=t("./src/generation/logits_sampler.js"),w=t("./src/env.js"),y=t("./src/models/whisper/generation_whisper.js"),$=t("./src/models/whisper/common_whisper.js");const T={EncoderOnly:0,EncoderDecoder:1,Seq2Seq:2,Vision2Seq:3,DecoderOnly:4,MaskGeneration:5,ImageTextToText:6,Musicgen:7,MultiModality:8,Phi3V:9,AudioTextToText:10,AutoEncoder:11,ImageAudioTextToText:12,Supertonic:13},M=new Map,x=new Map,v=new Map;async function C(g,P,L){var Dr;let ne=((Dr=L.config)==null?void 0:Dr["transformers.js_config"])??{},ge=L.device??ne.device;ge&&typeof ge!="string"&&(ge.hasOwnProperty(P)?ge=ge[P]:(console.warn(`device not specified for "${P}". Using the default device.`),ge=null));const fe=ge??(w.apis.IS_NODE_ENV?"cpu":"wasm"),ve=(0,o.deviceToExecutionProviders)(fe),Be=ne.device_config??{};Be.hasOwnProperty(fe)&&(ne={...ne,...Be[fe]});let Ke=L.dtype??ne.dtype;if(typeof Ke!="string"&&(Ke&&Ke.hasOwnProperty(P)?Ke=Ke[P]:(Ke=n.DEFAULT_DEVICE_DTYPE_MAPPING[fe]??n.DATA_TYPES.fp32,console.warn(`dtype not specified for "${P}". Using the default dtype (${Ke}) for this device (${fe}).`))),Ke===n.DATA_TYPES.auto){let At=ne.dtype;typeof At!="string"&&(At=At==null?void 0:At[P]),At&&At!==n.DATA_TYPES.auto&&n.DATA_TYPES.hasOwnProperty(At)?Ke=At:Ke=n.DEFAULT_DEVICE_DTYPE_MAPPING[fe]??n.DATA_TYPES.fp32}const Ye=Ke;if(n.DEFAULT_DTYPE_SUFFIX_MAPPING.hasOwnProperty(Ye)){if(Ye===n.DATA_TYPES.fp16&&fe==="webgpu"&&!await(0,n.isWebGpuFp16Supported)())throw new Error(`The device (${fe}) does not support fp16.`)}else throw new Error(`Invalid dtype: ${Ye}. Should be one of: ${Object.keys(n.DATA_TYPES).join(", ")}`);const ht=ne.kv_cache_dtype,wt=ht?typeof ht=="string"?ht:ht[Ye]??"float32":void 0;if(wt&&!["float32","float16"].includes(wt))throw new Error(`Invalid kv_cache_dtype: ${wt}. Should be one of: float32, float16`);const vt={dtype:Ye,kv_cache_dtype:wt,device:fe},Ft=n.DEFAULT_DTYPE_SUFFIX_MAPPING[Ye],_t=`${P}${Ft}.onnx`,Tt=`${L.subfolder??""}/${_t}`,ut={...L.session_options};ut.executionProviders??(ut.executionProviders=ve);const It=ne.free_dimension_overrides;It?ut.freeDimensionOverrides??(ut.freeDimensionOverrides=It):fe.startsWith("webnn")&&!ut.freeDimensionOverrides&&console.warn(`WebNN does not currently support dynamic shapes and requires 'free_dimension_overrides' to be set in config.json, preferably as a field within config["transformers.js_config"]["device_config"]["${fe}"]. When 'free_dimension_overrides' is not set, you may experience significant performance degradation.`);const Nt=w.apis.IS_NODE_ENV&&w.env.useFSCache,er=(0,l.getModelFile)(g,Tt,!0,L,Nt),sr=L.use_external_data_format??ne.use_external_data_format;let ar=[];if(sr){let At;typeof sr=="object"?sr.hasOwnProperty(_t)?At=sr[_t]:sr.hasOwnProperty(P)?At=sr[P]:At=!1:At=sr;const $r=+At;if($r>l.MAX_EXTERNAL_DATA_CHUNKS)throw new Error(`The number of external data chunks (${$r}) exceeds the maximum allowed value (${l.MAX_EXTERNAL_DATA_CHUNKS}).`);for(let ns=0;ns<$r;++ns){const Ln=`${_t}_data${ns===0?"":"_"+ns}`,Qr=`${L.subfolder??""}/${Ln}`;ar.push(new Promise(async(ps,hi)=>{const zn=await(0,l.getModelFile)(g,Qr,!0,L,Nt);ps(zn instanceof Uint8Array?{path:Ln,data:zn}:Ln)}))}}else ut.externalData!==void 0&&(ar=ut.externalData.map(async At=>{if(typeof At.data=="string"){const $r=await(0,l.getModelFile)(g,At.data,!0,L);return{...At,data:$r}}return At}));if(ar.length>0){const At=await Promise.all(ar);w.apis.IS_NODE_ENV||(ut.externalData=At)}if(fe==="webgpu"){const At=(0,s.getCacheShapes)(L.config,{prefix:"present"});if(Object.keys(At).length>0&&!(0,o.isONNXProxy)()){const $r={};for(const ns in At)$r[ns]="gpu-buffer";ut.preferredOutputLocation=$r}}return{buffer_or_path:await er,session_options:ut,session_config:vt}}async function F(g,P,L){return Object.fromEntries(await Promise.all(Object.keys(P).map(async ne=>{const{buffer_or_path:ge,session_options:fe,session_config:ve}=await C(g,P[ne],L),Be=await(0,o.createInferenceSession)(ge,fe,ve);return[ne,Be]})))}async function D(g,P,L){return Object.fromEntries(await Promise.all(Object.keys(P).map(async ne=>{const ge=await(0,l.getModelJSON)(g,P[ne],!1,L);return[ne,ge]})))}function K(g,P){const L=Object.create(null),ne=[];for(const ve of g.inputNames){const Be=P[ve];if(!(Be instanceof u.Tensor)){ne.push(ve);continue}L[ve]=(0,o.isONNXProxy)()?Be.clone():Be}if(ne.length>0)throw new Error(`An error occurred during model execution: "Missing the following inputs: ${ne.join(", ")}.`);const ge=Object.keys(P).length,fe=g.inputNames.length;if(ge>fe){let ve=Object.keys(P).filter(Be=>!g.inputNames.includes(Be));console.warn(`WARNING: Too many inputs were provided (${ge} > ${fe}). The following inputs will be ignored: "${ve.join(", ")}".`)}return L}async function U(g,P){const L=K(g,P);try{const ne=Object.fromEntries(Object.entries(L).map(([fe,ve])=>[fe,ve.ort_tensor])),ge=await(0,o.runInferenceSession)(g,ne);return j(ge)}catch(ne){const ge=Object.fromEntries(Object.entries(L).map(([fe,ve])=>{const Be={type:ve.type,dims:ve.dims,location:ve.location};return Be.location!=="gpu-buffer"&&(Be.data=ve.data),[fe,Be]}));throw console.error(`An error occurred during model execution: "${ne}".`),console.error("Inputs given to model:",ge),ne}}function j(g){for(let P in g)(0,o.isONNXTensor)(g[P])?g[P]=new u.Tensor(g[P]):typeof g[P]=="object"&&j(g[P]);return g}function se(g){if(g instanceof u.Tensor)return g;if(g.length===0)throw Error("items must be non-empty");if(Array.isArray(g[0])){if(g.some(P=>P.length!==g[0].length))throw Error("Unable to create tensor, you should probably activate truncation and/or padding with 'padding=True' and/or 'truncation=True' to have batched tensors with the same length.");return new u.Tensor("int64",BigInt64Array.from(g.flat().map(P=>BigInt(P))),[g.length,g[0].length])}else return new u.Tensor("int64",BigInt64Array.from(g.map(P=>BigInt(P))),[1,g.length])}function q(g){return new u.Tensor("bool",[g],[1])}async function re(g,P){let{encoder_outputs:L,input_ids:ne,decoder_input_ids:ge,...fe}=P;if(!L){const Be=(0,i.pick)(P,g.sessions.model.inputNames);L=(await Z(g,Be)).last_hidden_state}return fe.input_ids=ge,fe.encoder_hidden_states=L,g.sessions.decoder_model_merged.inputNames.includes("encoder_attention_mask")&&(fe.encoder_attention_mask=P.attention_mask),await _e(g,fe,!0)}async function Z(g,P){const L=g.sessions.model,ne=(0,i.pick)(P,L.inputNames);if(L.inputNames.includes("inputs_embeds")&&!ne.inputs_embeds){if(!P.input_ids)throw new Error("Both `input_ids` and `inputs_embeds` are missing in the model inputs.");ne.inputs_embeds=await g.encode_text({input_ids:P.input_ids})}if(L.inputNames.includes("token_type_ids")&&!ne.token_type_ids){if(!ne.input_ids)throw new Error("Both `input_ids` and `token_type_ids` are missing in the model inputs.");ne.token_type_ids=(0,u.zeros_like)(ne.input_ids)}if(L.inputNames.includes("pixel_mask")&&!ne.pixel_mask){if(!ne.pixel_values)throw new Error("Both `pixel_values` and `pixel_mask` are missing in the model inputs.");const ge=ne.pixel_values.dims;ne.pixel_mask=(0,u.ones)([ge[0],ge[2],ge[3]])}return await U(L,ne)}async function ae(g,P){const L=await g.encode(P);return await g.decode(L)}async function _e(g,P,L=!1){const ne=g.sessions[L?"decoder_model_merged":"model"],{past_key_values:ge,...fe}=P;if(ne.inputNames.includes("use_cache_branch")&&(fe.use_cache_branch=q(!!ge)),ne.inputNames.includes("position_ids")&&fe.attention_mask&&!fe.position_ids){const Be=["paligemma","gemma3_text","gemma3"].includes(g.config.model_type)?1:0;fe.position_ids=Se(fe,ge,Be)}g.addPastKeyValues(fe,ge);const ve=(0,i.pick)(fe,ne.inputNames);return await U(ne,ve)}function pe({modality_token_id:g,inputs_embeds:P,modality_features:L,input_ids:ne,attention_mask:ge}){const fe=ne.tolist().map(Ye=>Ye.reduce((ht,wt,vt)=>(wt==g&&ht.push(vt),ht),[])),ve=fe.reduce((Ye,ht)=>Ye+ht.length,0),Be=L.dims[0];if(ve!==Be)throw new Error(`Number of tokens and features do not match: tokens: ${ve}, features ${Be}`);let Ke=0;for(let Ye=0;Yefe.dims[1]||ge[ge.at(-1)])),{...L,decoder_input_ids:se(P)}}function Ae(g,...P){return g.config.is_encoder_decoder?Ne(g,...P):De(g,...P)}function te(g,P,L,ne){const ge=!!L.past_key_values;return ne.guidance_scale!==null&&ne.guidance_scale>1&&(ge?L.input_ids=(0,u.cat)([L.input_ids,L.input_ids],0):(L.input_ids=(0,u.cat)([L.input_ids,(0,u.full_like)(L.input_ids,BigInt(ne.pad_token_id))],0),L.attention_mask=(0,u.cat)([L.attention_mask,(0,u.full_like)(L.attention_mask,0n)],0))),(ge||!L.pixel_values)&&(L.pixel_values=(0,u.full)([0,0,3,384,384],1)),ge&&(L.images_seq_mask=new u.Tensor("bool",new Array(1).fill(!0).fill(!1,0,1),[1,1]),L.images_emb_mask=new u.Tensor("bool",new Array(0).fill(!1),[1,1,0])),L}class O extends a.Callable{constructor(L,ne,ge){super();J(this,"main_input_name","input_ids");J(this,"forward_params",["input_ids","attention_mask"]);this.config=L,this.sessions=ne,this.configs=ge;const fe=v.get(this.constructor),ve=M.get(fe);switch(this.can_generate=!1,this._forward=null,this._prepare_inputs_for_generation=null,ve){case T.DecoderOnly:this.can_generate=!0,this._forward=_e,this._prepare_inputs_for_generation=De;break;case T.Seq2Seq:case T.Vision2Seq:case T.Musicgen:this.can_generate=!0,this._forward=re,this._prepare_inputs_for_generation=Ne;break;case T.EncoderDecoder:this._forward=re;break;case T.ImageTextToText:this.can_generate=!0,this._forward=le,this._prepare_inputs_for_generation=Ae;break;case T.AudioTextToText:this.can_generate=!0,this._forward=Q,this._prepare_inputs_for_generation=Ae;break;case T.Phi3V:case T.ImageAudioTextToText:this.can_generate=!0,this._prepare_inputs_for_generation=Ae;break;case T.MultiModality:this.can_generate=!0,this._prepare_inputs_for_generation=te;break;case T.AutoEncoder:this._forward=ae;break;default:this._forward=Z;break}this.can_generate&&this.forward_params.push("past_key_values"),this.custom_config=this.config["transformers.js_config"]??{}}async dispose(){var ne;const L=[];for(const ge of Object.values(this.sessions))(ne=ge==null?void 0:ge.handler)!=null&&ne.dispose&&L.push(ge.handler.dispose());return await Promise.all(L)}static async from_pretrained(L,{progress_callback:ne=null,config:ge=null,cache_dir:fe=null,local_files_only:ve=!1,revision:Be="main",model_file_name:Ke=null,subfolder:Ye="onnx",device:ht=null,dtype:wt=null,use_external_data_format:vt=null,session_options:Ft={}}={}){let _t={progress_callback:ne,config:ge,cache_dir:fe,local_files_only:ve,revision:Be,model_file_name:Ke,subfolder:Ye,device:ht,dtype:wt,use_external_data_format:vt,session_options:Ft};const Tt=v.get(this),ut=M.get(Tt);ge=_t.config=await s.AutoConfig.from_pretrained(L,_t);let It;if(ut===T.DecoderOnly)It=await Promise.all([F(L,{model:_t.model_file_name??"model"},_t),D(L,{generation_config:"generation_config.json"},_t)]);else if(ut===T.Seq2Seq||ut===T.Vision2Seq)It=await Promise.all([F(L,{model:"encoder_model",decoder_model_merged:"decoder_model_merged"},_t),D(L,{generation_config:"generation_config.json"},_t)]);else if(ut===T.MaskGeneration)It=await Promise.all([F(L,{model:"vision_encoder",prompt_encoder_mask_decoder:"prompt_encoder_mask_decoder"},_t)]);else if(ut===T.EncoderDecoder)It=await Promise.all([F(L,{model:"encoder_model",decoder_model_merged:"decoder_model_merged"},_t)]);else if(ut===T.ImageTextToText){const Nt={embed_tokens:"embed_tokens",vision_encoder:"vision_encoder",decoder_model_merged:"decoder_model_merged"};ge.is_encoder_decoder&&(Nt.model="encoder_model"),It=await Promise.all([F(L,Nt,_t),D(L,{generation_config:"generation_config.json"},_t)])}else if(ut===T.AudioTextToText){const Nt={embed_tokens:"embed_tokens",audio_encoder:"audio_encoder",decoder_model_merged:"decoder_model_merged"};It=await Promise.all([F(L,Nt,_t),D(L,{generation_config:"generation_config.json"},_t)])}else if(ut===T.ImageAudioTextToText){const Nt={embed_tokens:"embed_tokens",audio_encoder:"audio_encoder",vision_encoder:"vision_encoder",decoder_model_merged:"decoder_model_merged"};It=await Promise.all([F(L,Nt,_t),D(L,{generation_config:"generation_config.json"},_t)])}else if(ut===T.Musicgen)It=await Promise.all([F(L,{model:"text_encoder",decoder_model_merged:"decoder_model_merged",encodec_decode:"encodec_decode"},_t),D(L,{generation_config:"generation_config.json"},_t)]);else if(ut===T.MultiModality)It=await Promise.all([F(L,{prepare_inputs_embeds:"prepare_inputs_embeds",model:"language_model",lm_head:"lm_head",gen_head:"gen_head",gen_img_embeds:"gen_img_embeds",image_decode:"image_decode"},_t),D(L,{generation_config:"generation_config.json"},_t)]);else if(ut===T.Phi3V)It=await Promise.all([F(L,{prepare_inputs_embeds:"prepare_inputs_embeds",model:"model",vision_encoder:"vision_encoder"},_t),D(L,{generation_config:"generation_config.json"},_t)]);else if(ut===T.AutoEncoder)It=await Promise.all([F(L,{encoder_model:"encoder_model",decoder_model:"decoder_model"},_t)]);else if(ut===T.Supertonic)It=await Promise.all([F(L,{text_encoder:"text_encoder",latent_denoiser:"latent_denoiser",voice_decoder:"voice_decoder"},_t)]);else{if(ut!==T.EncoderOnly){const Nt=Tt??(ge==null?void 0:ge.model_type);Nt!=="custom"&&console.warn(`Model type for '${Nt}' not found, assuming encoder-only architecture. Please report this at ${c.GITHUB_ISSUE_URL}.`)}It=await Promise.all([F(L,{model:_t.model_file_name??"model"},_t)])}return new this(ge,...It)}async _call(L){return await this.forward(L)}async forward(L){return await this._forward(this,L)}get generation_config(){var L;return((L=this.configs)==null?void 0:L.generation_config)??null}_get_logits_processor(L,ne,ge=null){const fe=new p.LogitsProcessorList;if(L.repetition_penalty!==null&&L.repetition_penalty!==1&&fe.push(new p.RepetitionPenaltyLogitsProcessor(L.repetition_penalty)),L.no_repeat_ngram_size!==null&&L.no_repeat_ngram_size>0&&fe.push(new p.NoRepeatNGramLogitsProcessor(L.no_repeat_ngram_size)),L.bad_words_ids!==null&&fe.push(new p.NoBadWordsLogitsProcessor(L.bad_words_ids,L.eos_token_id)),L.min_length!==null&&L.eos_token_id!==null&&L.min_length>0&&fe.push(new p.MinLengthLogitsProcessor(L.min_length,L.eos_token_id)),L.min_new_tokens!==null&&L.eos_token_id!==null&&L.min_new_tokens>0&&fe.push(new p.MinNewTokensLengthLogitsProcessor(ne,L.min_new_tokens,L.eos_token_id)),L.forced_bos_token_id!==null&&fe.push(new p.ForcedBOSTokenLogitsProcessor(L.forced_bos_token_id)),L.forced_eos_token_id!==null&&fe.push(new p.ForcedEOSTokenLogitsProcessor(L.max_length,L.forced_eos_token_id)),L.begin_suppress_tokens!==null){const ve=ne>1||L.forced_bos_token_id===null?ne:ne+1;fe.push(new p.SuppressTokensAtBeginLogitsProcessor(L.begin_suppress_tokens,ve))}return L.guidance_scale!==null&&L.guidance_scale>1&&fe.push(new p.ClassifierFreeGuidanceLogitsProcessor(L.guidance_scale)),L.temperature===0&&L.do_sample&&(console.warn("`do_sample` changed to false because `temperature: 0` implies greedy sampling (always selecting the most likely token), which is incompatible with `do_sample: true`."),L.do_sample=!1),L.do_sample&&L.temperature!==null&&L.temperature!==1&&fe.push(new p.TemperatureLogitsWarper(L.temperature)),ge!==null&&fe.extend(ge),fe}_prepare_generation_config(L,ne,ge=d.GenerationConfig){const fe={...this.config};for(const Be of["decoder","generator","text_config"])Be in fe&&Object.assign(fe,fe[Be]);const ve=new ge(fe);return Object.assign(ve,this.generation_config??{}),L&&Object.assign(ve,L),ne&&Object.assign(ve,(0,i.pick)(ne,Object.getOwnPropertyNames(ve))),ve}_get_stopping_criteria(L,ne=null){const ge=new b.StoppingCriteriaList;return L.max_length!==null&&ge.push(new b.MaxLengthCriteria(L.max_length,this.config.max_position_embeddings??null)),L.eos_token_id!==null&&ge.push(new b.EosTokenCriteria(L.eos_token_id)),ne&&ge.extend(ne),ge}_validate_model_class(){if(!this.can_generate){const L=[Lu,zu,Du,Ou],ne=v.get(this.constructor),ge=new Set,fe=this.config.model_type;for(const Be of L){const Ke=Be.get(fe);Ke&&ge.add(Ke[0])}let ve=`The current model class (${ne}) is not compatible with \`.generate()\`, as it doesn't have a language model head.`;throw ge.size>0&&(ve+=` Please use the following class instead: ${[...ge].join(", ")}`),Error(ve)}}prepare_inputs_for_generation(...L){return this._prepare_inputs_for_generation(this,...L)}_update_model_kwargs_for_generation({generated_input_ids:L,outputs:ne,model_inputs:ge,is_encoder_decoder:fe}){return ge.past_key_values=this.getPastKeyValues(ne,ge.past_key_values),ge.input_ids=new u.Tensor("int64",L.flat(),[L.length,1]),fe||(ge.attention_mask=(0,u.cat)([ge.attention_mask,(0,u.ones)([ge.attention_mask.dims[0],1])],1)),ge.position_ids=null,ge}_prepare_model_inputs({inputs:L,bos_token_id:ne,model_kwargs:ge}){const fe=(0,i.pick)(ge,this.forward_params),ve=this.main_input_name;if(ve in fe){if(L)throw new Error("`inputs`: {inputs}` were passed alongside {input_name} which is not allowed. Make sure to either pass {inputs} or {input_name}=...")}else fe[ve]=L;return{inputs_tensor:fe[ve],model_inputs:fe,model_input_name:ve}}async _prepare_encoder_decoder_kwargs_for_generation({inputs_tensor:L,model_inputs:ne,model_input_name:ge,generation_config:fe}){if(this.sessions.model.inputNames.includes("inputs_embeds")&&!ne.inputs_embeds&&"_prepare_inputs_embeds"in this){const{input_ids:Be,pixel_values:Ke,attention_mask:Ye,...ht}=ne,wt=await this._prepare_inputs_embeds(ne);ne={...ht,...(0,i.pick)(wt,["inputs_embeds","attention_mask"])}}let{last_hidden_state:ve}=await Z(this,ne);if(fe.guidance_scale!==null&&fe.guidance_scale>1)ve=(0,u.cat)([ve,(0,u.full_like)(ve,0)],0),"attention_mask"in ne&&(ne.attention_mask=(0,u.cat)([ne.attention_mask,(0,u.zeros_like)(ne.attention_mask)],0));else if(ne.decoder_input_ids){const Be=se(ne.decoder_input_ids).dims[0];if(Be!==ve.dims[0]){if(ve.dims[0]!==1)throw new Error(`The encoder outputs have a different batch size (${ve.dims[0]}) than the decoder inputs (${Be}).`);ve=(0,u.cat)(Array.from({length:Be},()=>ve),0)}}return ne.encoder_outputs=ve,ne}_prepare_decoder_input_ids_for_generation({batch_size:L,model_input_name:ne,model_kwargs:ge,decoder_start_token_id:fe,bos_token_id:ve,generation_config:Be}){let{decoder_input_ids:Ke,...Ye}=ge;if(!(Ke instanceof u.Tensor)){if(Ke)Array.isArray(Ke[0])||(Ke=Array.from({length:L},()=>Ke));else if(fe??(fe=ve),this.config.model_type==="musicgen")Ke=Array.from({length:L*this.config.decoder.num_codebooks},()=>[fe]);else if(Array.isArray(fe)){if(fe.length!==L)throw new Error(`\`decoder_start_token_id\` expcted to have length ${L} but got ${fe.length}`);Ke=fe}else Ke=Array.from({length:L},()=>[fe]);Ke=se(Ke)}return ge.decoder_attention_mask=(0,u.ones_like)(Ke),{input_ids:Ke,model_inputs:Ye}}async generate({inputs:L=null,generation_config:ne=null,logits_processor:ge=null,stopping_criteria:fe=null,streamer:ve=null,...Be}){this._validate_model_class(),ne=this._prepare_generation_config(ne,Be);let{inputs_tensor:Ke,model_inputs:Ye,model_input_name:ht}=this._prepare_model_inputs({inputs:L,model_kwargs:Be});const wt=this.config.is_encoder_decoder;wt&&("encoder_outputs"in Ye||(Ye=await this._prepare_encoder_decoder_kwargs_for_generation({inputs_tensor:Ke,model_inputs:Ye,model_input_name:ht,generation_config:ne})));let vt;wt?{input_ids:vt,model_inputs:Ye}=this._prepare_decoder_input_ids_for_generation({batch_size:Ye[ht].dims.at(0),model_input_name:ht,model_kwargs:Ye,decoder_start_token_id:ne.decoder_start_token_id,bos_token_id:ne.bos_token_id,generation_config:ne}):vt=Ye[ht];let Ft=vt.dims.at(-1);ne.max_new_tokens!==null&&(ne.max_length=Ft+ne.max_new_tokens);const _t=this._get_logits_processor(ne,Ft,ge),Tt=this._get_stopping_criteria(ne,fe),ut=Ye[ht].dims.at(0),It=k.LogitsSampler.getSampler(ne),Nt=new Array(ut).fill(0),er=vt.tolist();ve&&ve.put(er);let sr,ar={};for(;;){if(Ye=this.prepare_inputs_for_generation(er,Ye,ne),sr=await this.forward(Ye),ne.output_attentions&&ne.return_dict_in_generate){const Qr=this.getAttentions(sr);for(const ps in Qr)ps in ar||(ar[ps]=[]),ar[ps].push(Qr[ps])}const At=sr.logits.slice(null,-1,null),$r=_t(er,At),ns=[];for(let Qr=0;Qr<$r.dims.at(0);++Qr){const ps=$r[Qr],hi=await It(ps);for(const[zn,_i]of hi){const fi=BigInt(zn);Nt[Qr]+=_i,er[Qr].push(fi),ns.push([fi]);break}}if(ve&&ve.put(ns),Tt(er).every(Qr=>Qr))break;Ye=this._update_model_kwargs_for_generation({generated_input_ids:ns,outputs:sr,model_inputs:Ye,is_encoder_decoder:wt})}ve&&ve.end();const Pr=this.getPastKeyValues(sr,Ye.past_key_values,!0),Dr=new u.Tensor("int64",er.flat(),[er.length,er[0].length]);if(ne.return_dict_in_generate)return{sequences:Dr,past_key_values:Pr,...ar};for(const At of Object.values(sr))At.location==="gpu-buffer"&&At.dispose();return Dr}getPastKeyValues(L,ne,ge=!1){const fe=Object.create(null);for(const ve in L)if(ve.startsWith("present")){const Be=ve.replace("present_conv","past_conv").replace("present","past_key_values"),Ke=ve.includes("encoder");if(Ke&&ne?fe[Be]=ne[Be]:fe[Be]=L[ve],ne&&(!Ke||ge)){const Ye=ne[Be];Ye.location==="gpu-buffer"&&Ye.dispose()}}return fe}getAttentions(L){const ne={};for(const ge of["cross_attentions","encoder_attentions","decoder_attentions"])for(const fe in L)fe.startsWith(ge)&&(ge in ne||(ne[ge]=[]),ne[ge].push(L[fe]));return ne}addPastKeyValues(L,ne){var ge,fe,ve;if(ne)Object.assign(L,ne);else{const Be=this.sessions.decoder_model_merged??this.sessions.model,Ke=((fe=(ge=L[this.main_input_name]??L.attention_mask)==null?void 0:ge.dims)==null?void 0:fe[0])??1,Ye=((ve=Be==null?void 0:Be.config)==null?void 0:ve.kv_cache_dtype)??"float32",ht=Ye==="float16"?u.DataTypeMap.float16:u.DataTypeMap.float32,wt=(0,s.getCacheShapes)(this.config,{batch_size:Ke});for(const vt in wt){const Ft=wt[vt].reduce((_t,Tt)=>_t*Tt,1);L[vt]=new u.Tensor(Ye,new ht(Ft),wt[vt])}}}async encode_image({pixel_values:L}){return(await U(this.sessions.vision_encoder,{pixel_values:L})).image_features}async encode_text({input_ids:L}){return(await U(this.sessions.embed_tokens,{input_ids:L})).inputs_embeds}async encode_audio({audio_values:L}){return(await U(this.sessions.audio_encoder,{audio_values:L})).audio_features}}class me{}class xe extends me{constructor({last_hidden_state:P,hidden_states:L=null,attentions:ne=null}){super(),this.last_hidden_state=P,this.hidden_states=L,this.attentions=ne}}class be extends O{}class Ce extends be{}class $e extends be{async _call(P){return new Or(await super._call(P))}}class Me extends be{async _call(P){return new Et(await super._call(P))}}class Le extends be{async _call(P){return new Sr(await super._call(P))}}class we extends be{async _call(P){return new Nr(await super._call(P))}}class ke extends O{}class He extends ke{}class Fe extends ke{async _call(P){return new Or(await super._call(P))}}class Ze extends ke{async _call(P){return new Et(await super._call(P))}}class We extends ke{async _call(P){return new Sr(await super._call(P))}}class yt extends ke{async _call(P){return new Nr(await super._call(P))}}class Qe extends O{}class Oe extends Qe{}class ze extends Qe{async _call(P){return new Or(await super._call(P))}}class pt extends Qe{async _call(P){return new Et(await super._call(P))}}class ft extends Qe{async _call(P){return new Sr(await super._call(P))}}class Lt extends O{}class kt extends Lt{}class Mr extends Lt{}class fr extends O{}class Ut extends fr{}class Ur extends O{}class Ws extends Ur{}class Gs extends Ur{async _call(P){return new Or(await super._call(P))}}class nn extends Ur{async _call(P){return new Et(await super._call(P))}}class cr extends Ur{async _call(P){return new Sr(await super._call(P))}}class zr extends Ur{async _call(P){return new Nr(await super._call(P))}}class ls extends O{}class Ks extends ls{}class gt extends ls{async _call(P){return new Or(await super._call(P))}}class Is extends ls{async _call(P){return new Et(await super._call(P))}}class As extends ls{async _call(P){return new Sr(await super._call(P))}}class Yt extends ls{async _call(P){return new Nr(await super._call(P))}}class Jr extends O{}class $t extends Jr{}class Fs extends Jr{async _call(P){return new Or(await super._call(P))}}class S extends Jr{async _call(P){return new Et(await super._call(P))}}class H extends Jr{async _call(P){return new Sr(await super._call(P))}}class R extends Jr{async _call(P){return new Nr(await super._call(P))}}class W extends O{}class X extends W{}class ue extends W{async _call(P){return new Or(await super._call(P))}}class Ee extends W{async _call(P){return new Et(await super._call(P))}}class et extends W{async _call(P){return new Sr(await super._call(P))}}class ot extends W{async _call(P){return new Nr(await super._call(P))}}class rt extends O{}class St extends rt{}class lt extends rt{async _call(P){return new Or(await super._call(P))}}class Ot extends rt{async _call(P){return new Et(await super._call(P))}}class at extends rt{async _call(P){return new Sr(await super._call(P))}}class Dt extends rt{async _call(P){return new Nr(await super._call(P))}}class Wt extends O{}class Br extends Wt{}class br extends Wt{async _call(P){return new Or(await super._call(P))}}class Rr extends Wt{async _call(P){return new Et(await super._call(P))}}class Ts extends Wt{async _call(P){return new Sr(await super._call(P))}}class Os extends Wt{async _call(P){return new Nr(await super._call(P))}}class gr extends O{}class Hs extends gr{}class cs extends gr{async _call(P){return new Et(await super._call(P))}}class jr extends gr{async _call(P){return new Sr(await super._call(P))}}class Hr extends gr{async _call(P){return new Nr(await super._call(P))}}class ur extends gr{async _call(P){return new Or(await super._call(P))}}class mr extends O{}class Es extends mr{}class Ds extends mr{async _call(P){return new Or(await super._call(P))}}class Ls extends mr{async _call(P){return new Et(await super._call(P))}}class zs extends mr{async _call(P){return new Sr(await super._call(P))}}class us extends O{}class Wr extends us{}class je extends us{async _call(P){return new Or(await super._call(P))}}class Ve extends us{async _call(P){return new Et(await super._call(P))}}class st extends us{async _call(P){return new Nr(await super._call(P))}}class qt extends O{}class qs extends qt{}class Bs extends qt{async _call(P){return new Or(await super._call(P))}}class Qs extends qt{async _call(P){return new Et(await super._call(P))}}class En extends qt{async _call(P){return new Sr(await super._call(P))}}class he extends qt{async _call(P){return new Nr(await super._call(P))}}class I extends O{}class N extends I{}class Y extends I{async _call(P){return new Or(await super._call(P))}}class ie extends I{async _call(P){return new Et(await super._call(P))}}class de extends I{async _call(P){return new Nr(await super._call(P))}}class Te extends O{}class Ge extends Te{}class Xe extends Te{async _call(P){return new Et(await super._call(P))}}class qe extends Te{async _call(P){return new Nr(await super._call(P))}}class tt extends Te{async _call(P){return new Or(await super._call(P))}}class bt extends O{constructor(){super(...arguments);J(this,"forward_params",["input_ids","attention_mask","encoder_outputs","decoder_input_ids","decoder_attention_mask","past_key_values"])}}class jt extends bt{}class Bt extends bt{}class nr extends O{}class Jt extends nr{}class yr extends nr{}class vr extends O{}class hr extends vr{}class xr extends vr{}class Cr extends O{}class ss extends Cr{}class rr extends Cr{}class Tr extends Cr{async _call(P){return new Et(await super._call(P))}}class Ar extends O{}class Yr extends Ar{}class Ps extends Ar{}class Fr extends Ar{async _call(P){return new Et(await super._call(P))}}class ds extends Ar{}class dr extends O{}class _r extends dr{}class wr extends dr{}class or extends O{}class qr extends or{}class Xs extends or{}class Rs extends O{}class xa extends Rs{}class Ta extends Rs{async _call(P){return new Or(await super._call(P))}}class $o extends Rs{async _call(P){return new Et(await super._call(P))}}class Ea extends Rs{async _call(P){return new Sr(await super._call(P))}}class Pa extends Rs{async _call(P){return new Nr(await super._call(P))}}class on extends O{}class Ca extends on{}class Sa extends on{async _call(P){return new Or(await super._call(P))}}class $a extends on{async _call(P){return new Et(await super._call(P))}}class ka extends on{async _call(P){return new Sr(await super._call(P))}}class Ia extends on{async _call(P){return new Nr(await super._call(P))}}class an extends O{}class Aa extends an{}class Fa extends an{async _call(P){return new Or(await super._call(P))}}class Oa extends an{async _call(P){return new Et(await super._call(P))}}class ko extends an{async _call(P){return new Sr(await super._call(P))}}class Io extends an{async _call(P){return new Nr(await super._call(P))}}class Xn extends O{}class Da extends Xn{}class La extends Xn{}class Jn extends O{constructor(){super(...arguments);J(this,"requires_attention_mask",!1);J(this,"main_input_name","input_features");J(this,"forward_params",["input_features","attention_mask","decoder_input_ids","decoder_attention_mask","past_key_values"])}}class Ao extends Jn{}class Js extends Jn{_prepare_generation_config(P,L){return super._prepare_generation_config(P,L,y.WhisperGenerationConfig)}_retrieve_init_tokens(P){const L=[P.decoder_start_token_id];let ne=P.language;const ge=P.task;if(P.is_multilingual){ne||(console.warn("No language specified - defaulting to English (en)."),ne="en");const ve=`<|${(0,$.whisper_language_to_code)(ne)}|>`;L.push(P.lang_to_id[ve]),L.push(P.task_to_id[ge??"transcribe"])}else if(ne||ge)throw new Error("Cannot specify `task` or `language` for an English-only model. If the model is intended to be multilingual, pass `is_multilingual=true` to generate, or update the generation config.");return!P.return_timestamps&&P.no_timestamps_token_id&&L.at(-1)!==P.no_timestamps_token_id?L.push(P.no_timestamps_token_id):P.return_timestamps&&L.at(-1)===P.no_timestamps_token_id&&(console.warn("<|notimestamps|> prompt token is removed from generation_config since `return_timestamps` is set to `true`."),L.pop()),L.filter(fe=>fe!=null)}async generate({inputs:P=null,generation_config:L=null,logits_processor:ne=null,stopping_criteria:ge=null,...fe}){L=this._prepare_generation_config(L,fe);const ve=fe.decoder_input_ids??this._retrieve_init_tokens(L);if(L.return_timestamps&&(ne??(ne=new p.LogitsProcessorList),ne.push(new p.WhisperTimeStampLogitsProcessor(L,ve))),L.begin_suppress_tokens&&(ne??(ne=new p.LogitsProcessorList),ne.push(new p.SuppressTokensAtBeginLogitsProcessor(L.begin_suppress_tokens,ve.length))),L.return_token_timestamps){if(!L.alignment_heads)throw new Error("Model generation config has no `alignment_heads`, token-level timestamps not available. See https://gist.github.com/hollance/42e32852f24243b748ae6bc1f985b13a on how to add this property to the generation config.");L.task==="translate"&&console.warn("Token-level timestamps may not be reliable for task 'translate'."),L.output_attentions=!0,L.return_dict_in_generate=!0}const Be=await super.generate({inputs:P,generation_config:L,logits_processor:ne,decoder_input_ids:ve,...fe});return L.return_token_timestamps&&(Be.token_timestamps=this._extract_token_timestamps(Be,L.alignment_heads,L.num_frames)),Be}_extract_token_timestamps(P,L,ne=null,ge=.02){if(!P.cross_attentions)throw new Error("Model outputs must contain cross attentions to extract timestamps. This is most likely because the model was not exported with `output_attentions=True`.");ne==null&&console.warn("`num_frames` has not been set, meaning the entire audio will be analyzed. This may lead to inaccurate token-level timestamps for short audios (< 30 seconds).");let fe=this.config.median_filter_width;fe===void 0&&(console.warn("Model config has no `median_filter_width`, using default value of 7."),fe=7);const ve=P.cross_attentions,Be=Array.from({length:this.config.decoder_layers},(Tt,ut)=>(0,u.cat)(ve.map(It=>It[ut]),2)),Ke=(0,u.stack)(L.map(([Tt,ut])=>{if(Tt>=Be.length)throw new Error(`Layer index ${Tt} is out of bounds for cross attentions (length ${Be.length}).`);return ne?Be[Tt].slice(null,ut,null,[0,ne]):Be[Tt].slice(null,ut)})).transpose(1,0,2,3),[Ye,ht]=(0,u.std_mean)(Ke,-2,0,!0),wt=Ke.clone();for(let Tt=0;TtIt[Dr+1]-It[Dr]),sr=(0,i.mergeArrays)([1],er).map(Pr=>!!Pr),ar=[];for(let Pr=0;PrArray.from({length:P.dims[0]},er=>Array.from({length:P.dims[1]},sr=>1))),_t=L?L.tolist():[],Tt=ne?ne.tolist():[];let ut=0,It=0;for(let Nt=0;Ntvt[Nt][kr]==1),ar=er.reduce((ir,kr,pn)=>(kr==Ke&&ir.push(pn),ir),[]).map(ir=>er[ir+1]),Pr=ar.filter(ir=>ir==ve).length,Dr=ar.filter(ir=>ir==Be).length;let At=[],$r=0,ns=Pr,Ln=Dr;for(let ir=0;irSs>$r&&Rn==ve),pn=er.findIndex((Rn,Ss)=>Ss>$r&&Rn==Be),Bn=ns>0&&kr!==-1?kr:er.length+1,co=Ln>0&&pn!==-1?pn:er.length+1;let gi,Ru,ju,Nu;Bn0?(0,_.max)(At.at(-1))[0]+1:0;At.push(Array.from({length:3*Uu},(Rn,Ss)=>Kv+Ss%Uu));const Wu=Uu+Kv,Mi=e1*Vu*wi,t1=Array.from({length:Mi},(Rn,Ss)=>Wu+Math.floor(Ss/(Vu*wi))),r1=Array.from({length:Mi},(Rn,Ss)=>Wu+Math.floor(Ss/wi)%Vu),s1=Array.from({length:Mi},(Rn,Ss)=>Wu+Ss%wi);At.push([t1,r1,s1].flat()),$r=gi+Mi}if($r0?(0,_.max)(At.at(-1))[0]+1:0,kr=er.length-$r;At.push(Array.from({length:3*kr},(pn,Bn)=>ir+Bn%kr))}const Qr=At.reduce((ir,kr)=>ir+kr.length,0),ps=new Array(Qr);let hi=0;for(let ir=0;ir<3;++ir)for(let kr=0;krwt[ut%wt.length]),_t=Array.from({length:vt[0]},(Tt,ut)=>(0,_.max)(wt.subarray(vt[1]*ut,vt[1]*(ut+1)))[0]+1n+BigInt(vt[1]));return[new u.Tensor("int64",Ft,[3,...vt]),new u.Tensor("int64",_t,[_t.length,1])]}else{const[wt,vt]=P.dims,Ft=BigInt64Array.from({length:3*wt*vt},(_t,Tt)=>BigInt(Math.floor(Tt%vt/wt)));return[new u.Tensor("int64",Ft,[3,...P.dims]),(0,u.zeros)([wt,1])]}}async encode_image({pixel_values:P,image_grid_thw:L}){return(await U(this.sessions.vision_encoder,{pixel_values:P,grid_thw:L})).image_features}_merge_input_ids_with_image_features(P){return oe({image_token_id:this.config.image_token_id,...P})}prepare_inputs_for_generation(P,L,ne){if(L.attention_mask&&!L.position_ids)if(!L.past_key_values)[L.position_ids,L.rope_deltas]=this.get_rope_index(L.input_ids,L.image_grid_thw,L.video_grid_thw,L.attention_mask);else{L.pixel_values=null;const ge=BigInt(Object.values(L.past_key_values)[0].dims.at(-2)),fe=L.rope_deltas.map(ve=>ge+ve);L.position_ids=(0,u.stack)([fe,fe,fe],0)}return L}}class Lc extends O{}class Qw extends Lc{}class Xw extends Lc{}class zc extends O{}class Jw extends zc{}class Yw extends zc{}class Bc extends O{}class Zw extends Bc{}class eM extends Bc{}class Rc extends O{}class tM extends Rc{}class rM extends Rc{}class jc extends O{}class sM extends jc{}class nM extends jc{}class Nc extends O{}class oM extends Nc{}class aM extends Nc{async _call(P){return new Et(await super._call(P))}}class Vc extends O{}class iM extends Vc{}class lM extends Vc{async _call(P){return new Et(await super._call(P))}}class cM extends O{}class uM extends cM{}class Uc extends O{}class dM extends Uc{}class pM extends Uc{async _call(P){return new Et(await super._call(P))}}class mM extends O{}class hM extends mM{}class Wc extends O{}class _M extends Wc{}class fM extends Wc{async _call(P){return new Et(await super._call(P))}}class gM extends O{}class wM extends gM{}class Gc extends O{}class MM extends Gc{}class bM extends Gc{async _call(P){return new Et(await super._call(P))}}class yM extends O{}class vM extends yM{async _call(P){return new Wv(await super._call(P))}}class Kc extends O{}class xM extends Kc{}class TM extends Kc{async _call(P){return new Et(await super._call(P))}}class Hc extends O{}class EM extends Hc{}class PM extends Hc{async _call(P){return new Et(await super._call(P))}}class qc extends O{}class CM extends qc{}class SM extends qc{}class Qc extends O{}class $M extends Qc{}class kM extends Qc{}class Xc extends O{}class IM extends Xc{}class AM extends Xc{async _call(P){return new Et(await super._call(P))}}class Ya extends O{}class FM extends Ya{}class OM extends Ya{async _call(P){return new Yc(await super._call(P))}}class Jc extends Ya{async _call(P){return new DM(await super._call(P))}}class Yc extends me{constructor({logits:P,pred_boxes:L}){super(),this.logits=P,this.pred_boxes=L}}class DM extends me{constructor({logits:P,pred_boxes:L,pred_masks:ne}){super(),this.logits=P,this.pred_boxes=L,this.pred_masks=ne}}class Zc extends O{}class LM extends Zc{}class zM extends Zc{async _call(P){return new Jo(await super._call(P))}}class Jo extends me{constructor({logits:P,pred_boxes:L}){super(),this.logits=P,this.pred_boxes=L}}class eu extends O{}class BM extends eu{}class RM extends eu{async _call(P){return new jM(await super._call(P))}}class jM extends Jo{}class tu extends O{}class NM extends tu{}class VM extends tu{async _call(P){return new UM(await super._call(P))}}class UM extends Jo{}class ru extends O{}class WM extends ru{}class GM extends ru{async _call(P){return new Jo(await super._call(P))}}class su extends O{}class KM extends su{}class HM extends su{async _call(P){return new qM(await super._call(P))}}class qM extends Yc{}class nu extends O{}class QM extends nu{}class XM extends nu{async _call(P){return new Et(await super._call(P))}}class ou extends O{}class JM extends ou{}class YM extends ou{async _call(P){return new Et(await super._call(P))}}class au extends O{}class ZM extends au{}class eb extends au{async _call(P){return new Et(await super._call(P))}}class Za extends O{}class tb extends Za{}class rb extends Za{async _call(P){return new Et(await super._call(P))}}class sb extends Za{}class iu extends O{}class nb extends iu{}class ob extends iu{}class lu extends O{}class ab extends lu{}class ib extends lu{}class lb extends O{}class cb extends lb{}class ei extends O{}class ub extends ei{}class db extends ei{}class pb extends ei{}class mb extends O{}class hb extends mb{}class _b extends O{}class fb extends _b{}class gb extends O{}class wb extends gb{}class cu extends O{}class Mb extends cu{}class bb extends cu{}class uu extends O{}class yb extends uu{}class vb extends uu{}class xb extends O{}class Tb extends xb{}class du extends O{}class Eb extends du{}class Pb extends du{async _call(P){return new Et(await super._call(P))}}class pu extends O{}class Cb extends pu{}class Sb extends pu{async _call(P){return new Et(await super._call(P))}}class mu extends O{}class $b extends mu{}class kb extends mu{async _call(P){return new Et(await super._call(P))}}class hu extends O{}class Ib extends hu{}class Ab extends hu{async _call(P){return new Et(await super._call(P))}}class Fb extends O{}class Ob extends Fb{}class Db extends O{}class Lb extends Db{}class zb extends O{}class Bb extends zb{}class _u extends O{}class Rb extends _u{}class jb extends _u{async _call(P){return new Nb(await super._call(P))}}class Nb extends me{constructor({logits:P,pred_boxes:L}){super(),this.logits=P,this.pred_boxes=L}}class Vb extends O{}class Ub extends Vb{async get_image_embeddings({pixel_values:P}){return await Z(this,{pixel_values:P})}async forward(P){!P.image_embeddings||!P.image_positional_embeddings?P={...P,...await this.get_image_embeddings(P)}:P={...P},P.input_labels??(P.input_labels=(0,u.ones)(P.input_points.dims.slice(0,-1)));const L={image_embeddings:P.image_embeddings,image_positional_embeddings:P.image_positional_embeddings};return P.input_points&&(L.input_points=P.input_points),P.input_labels&&(L.input_labels=P.input_labels),P.input_boxes&&(L.input_boxes=P.input_boxes),await U(this.sessions.prompt_encoder_mask_decoder,L)}async _call(P){return new Wb(await super._call(P))}}class Wb extends me{constructor({iou_scores:P,pred_masks:L}){super(),this.iou_scores=P,this.pred_masks=L}}class Gb extends me{constructor({iou_scores:P,pred_masks:L,object_score_logits:ne}){super(),this.iou_scores=P,this.pred_masks=L,this.object_score_logits=ne}}class Kb extends O{}class ti extends Kb{async get_image_embeddings({pixel_values:P}){return await Z(this,{pixel_values:P})}async forward(P){const{num_feature_levels:L}=this.config.vision_config;if(Array.from({length:L},(ve,Be)=>`image_embeddings.${Be}`).some(ve=>!P[ve])?P={...P,...await this.get_image_embeddings(P)}:P={...P},P.input_points){if(P.input_boxes&&P.input_boxes.dims[1]!==1)throw new Error("When both `input_points` and `input_boxes` are provided, the number of boxes per image must be 1.");const ve=P.input_points.dims;P.input_labels??(P.input_labels=(0,u.ones)(ve.slice(0,-1))),P.input_boxes??(P.input_boxes=(0,u.full)([ve[0],0,4],0))}else if(P.input_boxes){const ve=P.input_boxes.dims;P.input_labels=(0,u.full)([ve[0],ve[1],0],-1n),P.input_points=(0,u.full)([ve[0],1,0,2],0)}else throw new Error("At least one of `input_points` or `input_boxes` must be provided.");const ge=this.sessions.prompt_encoder_mask_decoder,fe=(0,i.pick)(P,ge.inputNames);return await U(ge,fe)}async _call(P){return new Gb(await super._call(P))}}class Hb extends ti{}class qb extends ti{}class fu extends O{}class Qb extends fu{}class Xb extends fu{}class gu extends O{}class Jb extends gu{}class Yb extends gu{}class un extends O{}class Zb extends un{}class ey extends un{async _call(P){return new dn(await super._call(P))}}class ty extends un{async _call(P){return new Et(await super._call(P))}}class ry extends un{async _call(P){return new Sr(await super._call(P))}}class sy extends O{}class ny extends sy{async _call(P){return new dn(await super._call(P))}}class wu extends O{}class oy extends wu{}class ay extends wu{async _call(P){return new Sr(await super._call(P))}}class iy extends O{}class ly extends iy{}class ri extends O{}class cy extends ri{}class uy extends ri{async _call(P){return new dn(await super._call(P))}}class dy extends ri{async _call(P){return new Et(await super._call(P))}}class Yo extends O{}class py extends Yo{}class my extends Yo{async _call(P){return new dn(await super._call(P))}}class hy extends Yo{async _call(P){return new Et(await super._call(P))}}class _y extends Yo{async _call(P){return new Sr(await super._call(P))}}class si extends O{}class fy extends si{}class gy extends si{async _call(P){return new dn(await super._call(P))}}class wy extends si{async _call(P){return new Et(await super._call(P))}}class RT extends O{}class My extends un{}class by extends un{async _call(P){return new dn(await super._call(P))}}class yy extends un{async _call(P){return new Et(await super._call(P))}}class io extends O{}class vy extends io{}class xy extends io{async _call(P){return new dn(await super._call(P))}}class Ty extends io{async _call(P){return new Et(await super._call(P))}}class Ey extends io{async _call(P){return new Uv(await super._call(P))}}class Py extends io{async _call(P){return new Sr(await super._call(P))}}class Cy extends O{}class Sy extends Cy{}class ni extends O{}class jT extends ni{}class $y extends ni{}class ky extends ni{async generate_speech(P,L,{threshold:ne=.5,minlenratio:ge=0,maxlenratio:fe=20,vocoder:ve=null}={}){const Be={input_ids:P},{encoder_outputs:Ke,encoder_attention_mask:Ye}=await Z(this,Be),ht=Ke.dims[1]/this.config.reduction_factor,wt=Math.floor(ht*fe),vt=Math.floor(ht*ge),Ft=this.config.num_mel_bins;let _t=[],Tt=null,ut=null,It=0;for(;;){++It;const sr=q(!!ut);let ar;ut?ar=ut.output_sequence_out:ar=new u.Tensor("float32",new Float32Array(Ft),[1,1,Ft]);let Pr={use_cache_branch:sr,output_sequence:ar,encoder_attention_mask:Ye,speaker_embeddings:L,encoder_hidden_states:Ke};this.addPastKeyValues(Pr,Tt),ut=await U(this.sessions.decoder_model_merged,Pr),Tt=this.getPastKeyValues(ut,Tt);const{prob:Dr,spectrum:At}=ut;if(_t.push(At),It>=vt&&(Array.from(Dr.data).filter($r=>$r>=ne).length>0||It>=wt))break}const Nt=(0,u.cat)(_t),{waveform:er}=await U(ve.sessions.model,{spectrogram:Nt});return{spectrogram:Nt,waveform:er}}}class Iy extends O{constructor(){super(...arguments);J(this,"main_input_name","spectrogram")}}class Ay extends O{}class Mu extends Ay{async generate_speech({input_ids:P,attention_mask:L,style:ne,num_inference_steps:ge=5,speed:fe=1.05}){const{sampling_rate:ve,chunk_compress_factor:Be,base_chunk_size:Ke,latent_dim:Ye}=this.config,{last_hidden_state:ht,durations:wt}=await U(this.sessions.text_encoder,{input_ids:P,attention_mask:L,style:ne});wt.div_(fe);const vt=wt.max().item()*ve,Ft=Ke*Be,_t=Math.floor((vt+Ft-1)/Ft),Tt=P.dims[0],ut=(0,u.ones)([Tt,_t]),It=(0,u.full)([Tt],ge);let Nt=(0,u.randn)([Tt,Ye*Be,_t]);for(let sr=0;sr0&&Ft<=ve&&(L.data[Be++]=L.data[ht])}const Ke=Math.floor(ne/fe),Ye=Be/(Ke*fe);return new u.Tensor(L.type,L.data.slice(0,Be),[Ke,fe,Ye])}prepare_inputs_for_generation(L,ne,ge){let fe=structuredClone(L);for(let Be=0;Be=Ke&&(fe[Be][Ke]=BigInt(this.config.decoder.pad_token_id));return ge.guidance_scale!==null&&ge.guidance_scale>1&&(fe=fe.concat(fe)),super.prepare_inputs_for_generation(fe,ne,ge)}async generate(L){const ne=await super.generate(L),ge=this._apply_and_filter_by_delay_pattern_mask(ne).unsqueeze_(0),{audio_values:fe}=await U(this.sessions.encodec_decode,{audio_codes:ge});return fe}}class ii extends O{}class s0 extends ii{}class n0 extends ii{async _call(P){return new Et(await super._call(P))}}class o0 extends ii{}class li extends O{}class a0 extends li{}class i0 extends li{async _call(P){return new Et(await super._call(P))}}class l0 extends li{}class ci extends O{}class c0 extends ci{}class u0 extends ci{async _call(P){return new Et(await super._call(P))}}class d0 extends ci{}class ui extends O{}class p0 extends ui{}class m0 extends ui{async _call(P){return new Et(await super._call(P))}}class h0 extends ui{}class _0 extends O{}class f0 extends _0{}class g0 extends O{}class w0 extends g0{constructor(...L){super(...L);J(this,"forward_params",["input_ids","pixel_values","images_seq_mask","images_emb_mask","attention_mask","position_ids","past_key_values"]);this._generation_mode="text"}async forward(L){const ne=this._generation_mode??"text";let ge;if(ne==="text"||!L.past_key_values){const Ye=this.sessions.prepare_inputs_embeds,ht=(0,i.pick)(L,Ye.inputNames);ge=await U(Ye,ht)}else{const Ye=this.sessions.gen_img_embeds,ht=(0,i.pick)({image_ids:L.input_ids},Ye.inputNames);ge=await U(Ye,ht)}const fe={...L,...ge},ve=await _e(this,fe),Be=this.sessions[ne==="text"?"lm_head":"gen_head"];if(!Be)throw new Error(`Unable to find "${Be}" generation head`);const Ke=await U(Be,(0,i.pick)(ve,Be.inputNames));return{...ge,...ve,...Ke}}async generate(L){return this._generation_mode="text",super.generate(L)}async generate_images(L){this._generation_mode="image";const ne=(L.inputs??L[this.main_input_name]).dims[1],fe=(await super.generate(L)).slice(null,[ne,null]),ve=this.sessions.image_decode,{decoded_image:Be}=await U(ve,{generated_tokens:fe}),Ke=Be.add_(1).mul_(255/2).clamp_(0,255).to("uint8"),Ye=[];for(const ht of Ke){const wt=f.RawImage.fromTensor(ht);Ye.push(wt)}return Ye}}class M0 extends me{constructor({char_logits:P,bpe_logits:L,wp_logits:ne}){super(),this.char_logits=P,this.bpe_logits=L,this.wp_logits=ne}get logits(){return[this.char_logits,this.bpe_logits,this.wp_logits]}}class b0 extends O{}class y0 extends b0{async _call(P){return new M0(await super._call(P))}}class Iu extends O{}class v0 extends Iu{}class x0 extends Iu{}class Au extends O{}class T0 extends Au{}class E0 extends Au{}class P0 extends O{constructor(){super(...arguments);J(this,"forward_params",["input_ids","attention_mask","position_ids","audio_values","past_key_values"])}}class Fu extends P0{_merge_input_ids_with_audio_features(P){const L=P.audio_features.dims.at(-1),ne=P.audio_features.view(-1,L);return G({audio_token_id:this.config.ignore_index??this.config.audio_token_id,...P,audio_features:ne})}}class C0 extends Fu{}class di extends O{constructor(){super(...arguments);J(this,"main_input_name","input_values");J(this,"forward_params",["input_values"])}}class S0 extends me{constructor({audio_codes:P}){super(),this.audio_codes=P}}class $0 extends me{constructor({audio_values:P}){super(),this.audio_values=P}}class k0 extends di{async encode(P){return new S0(await U(this.sessions.encoder_model,P))}async decode(P){return new $0(await U(this.sessions.decoder_model,P))}}class I0 extends di{static async from_pretrained(P,L={}){return super.from_pretrained(P,{...L,model_file_name:L.model_file_name??"encoder_model"})}}class A0 extends di{static async from_pretrained(P,L={}){return super.from_pretrained(P,{...L,model_file_name:L.model_file_name??"decoder_model"})}}class pi extends O{constructor(){super(...arguments);J(this,"main_input_name","input_values");J(this,"forward_params",["input_values"])}}class F0 extends me{constructor({audio_codes:P}){super(),this.audio_codes=P}}class O0 extends me{constructor({audio_values:P}){super(),this.audio_values=P}}class D0 extends pi{async encode(P){return new F0(await U(this.sessions.encoder_model,P))}async decode(P){return new O0(await U(this.sessions.decoder_model,P))}}class L0 extends pi{static async from_pretrained(P,L={}){return super.from_pretrained(P,{...L,model_file_name:L.model_file_name??"encoder_model"})}}class z0 extends pi{static async from_pretrained(P,L={}){return super.from_pretrained(P,{...L,model_file_name:L.model_file_name??"decoder_model"})}}class mi extends O{constructor(){super(...arguments);J(this,"main_input_name","input_values");J(this,"forward_params",["input_values"])}}class B0 extends mi{async encode(P){return await U(this.sessions.encoder_model,P)}async decode(P){return await U(this.sessions.decoder_model,P)}}class R0 extends mi{static async from_pretrained(P,L={}){return super.from_pretrained(P,{...L,model_file_name:L.model_file_name??"encoder_model"})}}class j0 extends mi{static async from_pretrained(P,L={}){return super.from_pretrained(P,{...L,model_file_name:L.model_file_name??"decoder_model"})}}class Gt{static async from_pretrained(P,{progress_callback:L=null,config:ne=null,cache_dir:ge=null,local_files_only:fe=!1,revision:ve="main",model_file_name:Be=null,subfolder:Ke="onnx",device:Ye=null,dtype:ht=null,use_external_data_format:wt=null,session_options:vt={}}={}){const Ft={progress_callback:L,config:ne,cache_dir:ge,local_files_only:fe,revision:ve,model_file_name:Be,subfolder:Ke,device:Ye,dtype:ht,use_external_data_format:wt,session_options:vt};if(Ft.config=await s.AutoConfig.from_pretrained(P,Ft),!this.MODEL_CLASS_MAPPINGS)throw new Error("`MODEL_CLASS_MAPPINGS` not implemented for this type of `AutoClass`: "+this.name);const _t=Ft.config.model_type;for(const Tt of this.MODEL_CLASS_MAPPINGS){let ut=Tt.get(_t);if(!ut){for(const It of Tt.values())if(It[0]===_t){ut=It;break}if(!ut)continue}return await ut[1].from_pretrained(P,Ft)}if(this.BASE_IF_FAIL)return pv.has(_t)||console.warn(`Unknown model class "${_t}", attempting to construct from base class.`),await O.from_pretrained(P,Ft);throw Error(`Unsupported model type: ${_t}`)}}J(Gt,"MODEL_CLASS_MAPPINGS",null),J(Gt,"BASE_IF_FAIL",!1);const WT=new Map([["bert",["BertModel",Ce]],["neobert",["NeoBertModel",He]],["modernbert",["ModernBertModel",Oe]],["nomic_bert",["NomicBertModel",Ut]],["roformer",["RoFormerModel",Ws]],["electra",["ElectraModel",$t]],["esm",["EsmModel",Es]],["convbert",["ConvBertModel",Ks]],["camembert",["CamembertModel",X]],["deberta",["DebertaModel",St]],["deberta-v2",["DebertaV2Model",Br]],["mpnet",["MPNetModel",qs]],["albert",["AlbertModel",Ge]],["distilbert",["DistilBertModel",Hs]],["roberta",["RobertaModel",xa]],["xlm",["XLMModel",Ca]],["xlm-roberta",["XLMRobertaModel",Aa]],["clap",["ClapModel",Hy]],["clip",["CLIPModel",Lo]],["clipseg",["CLIPSegModel",An]],["chinese_clip",["ChineseCLIPModel",mt]],["siglip",["SiglipModel",Xa]],["jina_clip",["JinaCLIPModel",No]],["mobilebert",["MobileBertModel",Wr]],["squeezebert",["SqueezeBertModel",N]],["wav2vec2",["Wav2Vec2Model",Zb]],["wav2vec2-bert",["Wav2Vec2BertModel",fy]],["unispeech",["UniSpeechModel",cy]],["unispeech-sat",["UniSpeechSatModel",py]],["hubert",["HubertModel",My]],["wavlm",["WavLMModel",vy]],["audio-spectrogram-transformer",["ASTModel",Da]],["vits",["VitsModel",Pu]],["pyannote",["PyAnnoteModel",oy]],["wespeaker-resnet",["WeSpeakerResNetModel",ly]],["detr",["DetrModel",FM]],["rt_detr",["RTDetrModel",LM]],["rt_detr_v2",["RTDetrV2Model",BM]],["rf_detr",["RFDetrModel",NM]],["d_fine",["DFineModel",WM]],["table-transformer",["TableTransformerModel",KM]],["vit",["ViTModel",oM]],["ijepa",["IJepaModel",iM]],["pvt",["PvtModel",dM]],["vit_msn",["ViTMSNModel",_M]],["vit_mae",["ViTMAEModel",hM]],["groupvit",["GroupViTModel",wM]],["fastvit",["FastViTModel",MM]],["mobilevit",["MobileViTModel",xM]],["mobilevitv2",["MobileViTV2Model",EM]],["owlvit",["OwlViTModel",CM]],["owlv2",["Owlv2Model",$M]],["beit",["BeitModel",IM]],["deit",["DeiTModel",QM]],["hiera",["HieraModel",JM]],["convnext",["ConvNextModel",Eb]],["convnextv2",["ConvNextV2Model",Cb]],["dinov2",["Dinov2Model",$b]],["dinov2_with_registers",["Dinov2WithRegistersModel",Ib]],["dinov3_vit",["DINOv3ViTModel",Ob]],["dinov3_convnext",["DINOv3ConvNextModel",Lb]],["resnet",["ResNetModel",ZM]],["swin",["SwinModel",tb]],["swin2sr",["Swin2SRModel",nb]],["donut-swin",["DonutSwinModel",Tb]],["yolos",["YolosModel",Rb]],["dpt",["DPTModel",ab]],["glpn",["GLPNModel",yb]],["hifigan",["SpeechT5HifiGan",Iy]],["efficientnet",["EfficientNetModel",t0]],["decision_transformer",["DecisionTransformerModel",f0]],["patchtst",["PatchTSTForPrediction",v0]],["patchtsmixer",["PatchTSMixerForPrediction",T0]],["mobilenet_v1",["MobileNetV1Model",s0]],["mobilenet_v2",["MobileNetV2Model",a0]],["mobilenet_v3",["MobileNetV3Model",c0]],["mobilenet_v4",["MobileNetV4Model",p0]],["maskformer",["MaskFormerModel",Mb]],["mgp-str",["MgpstrForSceneTextRecognition",y0]],["style_text_to_speech_2",["StyleTextToSpeech2Model",Sy]]]),GT=new Map([["t5",["T5Model",jt]],["longt5",["LongT5Model",Jt]],["mt5",["MT5Model",hr]],["bart",["BartModel",ss]],["mbart",["MBartModel",Yr]],["marian",["MarianModel",Qb]],["whisper",["WhisperModel",Ao]],["m2m_100",["M2M100Model",Jb]],["blenderbot",["BlenderbotModel",_r]],["blenderbot-small",["BlenderbotSmallModel",qr]]]),KT=new Map([["mimi",["MimiModel",k0]],["dac",["DacModel",D0]],["snac",["SnacModel",B0]]]),HT=new Map([["bloom",["BloomModel",Zw]],["jais",["JAISModel",Go]],["gpt2",["GPT2Model",Uo]],["gptj",["GPTJModel",Qo]],["gpt_bigcode",["GPTBigCodeModel",h]],["gpt_neo",["GPTNeoModel",On]],["gpt_neox",["GPTNeoXModel",Ho]],["codegen",["CodeGenModel",z]],["llama",["LlamaModel",Pe]],["nanochat",["NanoChatModel",Rt]],["arcee",["ArceeModel",Ys]],["lfm2",["Lfm2Model",dw]],["smollm3",["SmolLM3Model",mw]],["exaone",["ExaoneModel",Mw]],["olmo",["OlmoModel",xw]],["olmo2",["Olmo2Model",Ew]],["mobilellm",["MobileLLMModel",yw]],["granite",["GraniteModel",Cw]],["granitemoehybrid",["GraniteMoeHybridModel",$w]],["cohere",["CohereModel",Iw]],["gemma",["GemmaModel",Fw]],["gemma2",["Gemma2Model",Dw]],["vaultgemma",["VaultGemmaModel",zw]],["gemma3_text",["Gemma3Model",Rw]],["helium",["HeliumModel",_w]],["glm",["GlmModel",gw]],["openelm",["OpenELMModel",Nw]],["qwen2",["Qwen2Model",Uw]],["qwen3",["Qwen3Model",Gw]],["phi",["PhiModel",Qw]],["phi3",["Phi3Model",Jw]],["mpt",["MptModel",tM]],["opt",["OPTModel",sM]],["mistral",["MistralModel",Dy]],["ministral",["MinistralModel",zy]],["ministral3",["Ministral3Model",Ry]],["ernie4_5",["Ernie4_5Model",Ny]],["starcoder2",["Starcoder2Model",Uy]],["falcon",["FalconModel",Gy]],["stablelm",["StableLmModel",Zy]],["modernbert-decoder",["ModernBertDecoderModel",kt]]]),Ou=new Map([["speecht5",["SpeechT5ForSpeechToText",$y]],["whisper",["WhisperForConditionalGeneration",Js]],["lite-whisper",["LiteWhisperForConditionalGeneration",za]],["moonshine",["MoonshineForConditionalGeneration",Ba]]]),N0=new Map([["speecht5",["SpeechT5ForTextToSpeech",ky]]]),V0=new Map([["vits",["VitsModel",Pu]],["musicgen",["MusicgenForConditionalGeneration",ku]],["supertonic",["SupertonicForConditionalGeneration",Mu]]]),U0=new Map([["bert",["BertForSequenceClassification",Me]],["neobert",["NeoBertForSequenceClassification",Ze]],["modernbert",["ModernBertForSequenceClassification",pt]],["roformer",["RoFormerForSequenceClassification",nn]],["electra",["ElectraForSequenceClassification",S]],["esm",["EsmForSequenceClassification",Ls]],["convbert",["ConvBertForSequenceClassification",Is]],["camembert",["CamembertForSequenceClassification",Ee]],["deberta",["DebertaForSequenceClassification",Ot]],["deberta-v2",["DebertaV2ForSequenceClassification",Rr]],["mpnet",["MPNetForSequenceClassification",Qs]],["albert",["AlbertForSequenceClassification",Xe]],["distilbert",["DistilBertForSequenceClassification",cs]],["roberta",["RobertaForSequenceClassification",$o]],["xlm",["XLMForSequenceClassification",$a]],["xlm-roberta",["XLMRobertaForSequenceClassification",Oa]],["bart",["BartForSequenceClassification",Tr]],["mbart",["MBartForSequenceClassification",Fr]],["mobilebert",["MobileBertForSequenceClassification",Ve]],["squeezebert",["SqueezeBertForSequenceClassification",ie]]]),W0=new Map([["bert",["BertForTokenClassification",Le]],["neobert",["NeoBertForTokenClassification",We]],["modernbert",["ModernBertForTokenClassification",ft]],["roformer",["RoFormerForTokenClassification",cr]],["electra",["ElectraForTokenClassification",H]],["esm",["EsmForTokenClassification",zs]],["convbert",["ConvBertForTokenClassification",As]],["camembert",["CamembertForTokenClassification",et]],["deberta",["DebertaForTokenClassification",at]],["deberta-v2",["DebertaV2ForTokenClassification",Ts]],["mpnet",["MPNetForTokenClassification",En]],["distilbert",["DistilBertForTokenClassification",jr]],["roberta",["RobertaForTokenClassification",Ea]],["xlm",["XLMForTokenClassification",ka]],["xlm-roberta",["XLMRobertaForTokenClassification",ko]]]),Du=new Map([["t5",["T5ForConditionalGeneration",Bt]],["longt5",["LongT5ForConditionalGeneration",yr]],["mt5",["MT5ForConditionalGeneration",xr]],["bart",["BartForConditionalGeneration",rr]],["mbart",["MBartForConditionalGeneration",Ps]],["marian",["MarianMTModel",Xb]],["m2m_100",["M2M100ForConditionalGeneration",Yb]],["blenderbot",["BlenderbotForConditionalGeneration",wr]],["blenderbot-small",["BlenderbotSmallForConditionalGeneration",Xs]]]),Lu=new Map([["bloom",["BloomForCausalLM",eM]],["gpt2",["GPT2LMHeadModel",Wo]],["jais",["JAISLMHeadModel",Ko]],["gptj",["GPTJForCausalLM",Xo]],["gpt_bigcode",["GPTBigCodeForCausalLM",E]],["gpt_neo",["GPTNeoForCausalLM",no]],["gpt_neox",["GPTNeoXForCausalLM",qo]],["codegen",["CodeGenForCausalLM",V]],["llama",["LlamaForCausalLM",Re]],["nanochat",["NanoChatForCausalLM",Qt]],["llama4_text",["Llama4ForCausalLM",it]],["arcee",["ArceeForCausalLM",Ja]],["lfm2",["Lfm2ForCausalLM",pw]],["smollm3",["SmolLM3ForCausalLM",hw]],["exaone",["ExaoneForCausalLM",bw]],["olmo",["OlmoForCausalLM",Tw]],["olmo2",["Olmo2ForCausalLM",Pw]],["mobilellm",["MobileLLMForCausalLM",vw]],["granite",["GraniteForCausalLM",Sw]],["granitemoehybrid",["GraniteMoeHybridForCausalLM",kw]],["cohere",["CohereForCausalLM",Aw]],["gemma",["GemmaForCausalLM",Ow]],["gemma2",["Gemma2ForCausalLM",Lw]],["vaultgemma",["VaultGemmaForCausalLM",Bw]],["gemma3_text",["Gemma3ForCausalLM",jw]],["helium",["HeliumForCausalLM",fw]],["glm",["GlmForCausalLM",ww]],["openelm",["OpenELMForCausalLM",Vw]],["qwen2",["Qwen2ForCausalLM",Ww]],["qwen3",["Qwen3ForCausalLM",Kw]],["phi",["PhiForCausalLM",Xw]],["phi3",["Phi3ForCausalLM",Yw]],["mpt",["MptForCausalLM",rM]],["opt",["OPTForCausalLM",nM]],["mbart",["MBartForCausalLM",ds]],["mistral",["MistralForCausalLM",Ly]],["ministral",["MinistralForCausalLM",By]],["ministral3",["Ministral3ForCausalLM",jy]],["ernie4_5",["Ernie4_5ForCausalLM",Vy]],["starcoder2",["Starcoder2ForCausalLM",Wy]],["falcon",["FalconForCausalLM",Ky]],["trocr",["TrOCRForCausalLM",Oy]],["stablelm",["StableLmForCausalLM",e0]],["modernbert-decoder",["ModernBertDecoderForCausalLM",Mr]],["phi3_v",["Phi3VForCausalLM",$n]]]),qT=new Map([["multi_modality",["MultiModalityCausalLM",w0]]]),G0=new Map([["bert",["BertForMaskedLM",$e]],["neobert",["NeoBertForMaskedLM",Fe]],["modernbert",["ModernBertForMaskedLM",ze]],["roformer",["RoFormerForMaskedLM",Gs]],["electra",["ElectraForMaskedLM",Fs]],["esm",["EsmForMaskedLM",Ds]],["convbert",["ConvBertForMaskedLM",gt]],["camembert",["CamembertForMaskedLM",ue]],["deberta",["DebertaForMaskedLM",lt]],["deberta-v2",["DebertaV2ForMaskedLM",br]],["mpnet",["MPNetForMaskedLM",Bs]],["albert",["AlbertForMaskedLM",tt]],["distilbert",["DistilBertForMaskedLM",ur]],["roberta",["RobertaForMaskedLM",Ta]],["xlm",["XLMWithLMHeadModel",Sa]],["xlm-roberta",["XLMRobertaForMaskedLM",Fa]],["mobilebert",["MobileBertForMaskedLM",je]],["squeezebert",["SqueezeBertForMaskedLM",Y]]]),K0=new Map([["bert",["BertForQuestionAnswering",we]],["neobert",["NeoBertForQuestionAnswering",yt]],["roformer",["RoFormerForQuestionAnswering",zr]],["electra",["ElectraForQuestionAnswering",R]],["convbert",["ConvBertForQuestionAnswering",Yt]],["camembert",["CamembertForQuestionAnswering",ot]],["deberta",["DebertaForQuestionAnswering",Dt]],["deberta-v2",["DebertaV2ForQuestionAnswering",Os]],["mpnet",["MPNetForQuestionAnswering",he]],["albert",["AlbertForQuestionAnswering",qe]],["distilbert",["DistilBertForQuestionAnswering",Hr]],["roberta",["RobertaForQuestionAnswering",Pa]],["xlm",["XLMForQuestionAnswering",Ia]],["xlm-roberta",["XLMRobertaForQuestionAnswering",Io]],["mobilebert",["MobileBertForQuestionAnswering",st]],["squeezebert",["SqueezeBertForQuestionAnswering",de]]]),zu=new Map([["vision-encoder-decoder",["VisionEncoderDecoderModel",Fo]],["idefics3",["Idefics3ForConditionalGeneration",Sn]],["smolvlm",["SmolVLMForConditionalGeneration",Do]]]),H0=new Map([["llava",["LlavaForConditionalGeneration",Cn]],["llava_onevision",["LlavaOnevisionForConditionalGeneration",Ra]],["moondream1",["Moondream1ForConditionalGeneration",ja]],["florence2",["Florence2ForConditionalGeneration",Va]],["qwen2-vl",["Qwen2VLForConditionalGeneration",qw]],["idefics3",["Idefics3ForConditionalGeneration",Sn]],["smolvlm",["SmolVLMForConditionalGeneration",Do]],["paligemma",["PaliGemmaForConditionalGeneration",Wa]],["llava_qwen2",["LlavaQwen2ForCausalLM",Oo]],["gemma3n",["Gemma3nForConditionalGeneration",ln]],["mistral3",["Mistral3ForConditionalGeneration",Ga]]]),q0=new Map([["ultravox",["UltravoxModel",Fu]],["voxtral",["VoxtralForConditionalGeneration",C0]]]),QT=new Map([["vision-encoder-decoder",["VisionEncoderDecoderModel",Fo]]]),Q0=new Map([["vit",["ViTForImageClassification",aM]],["ijepa",["IJepaForImageClassification",lM]],["pvt",["PvtForImageClassification",pM]],["vit_msn",["ViTMSNForImageClassification",fM]],["fastvit",["FastViTForImageClassification",bM]],["mobilevit",["MobileViTForImageClassification",TM]],["mobilevitv2",["MobileViTV2ForImageClassification",PM]],["beit",["BeitForImageClassification",AM]],["deit",["DeiTForImageClassification",XM]],["hiera",["HieraForImageClassification",YM]],["convnext",["ConvNextForImageClassification",Pb]],["convnextv2",["ConvNextV2ForImageClassification",Sb]],["dinov2",["Dinov2ForImageClassification",kb]],["dinov2_with_registers",["Dinov2WithRegistersForImageClassification",Ab]],["resnet",["ResNetForImageClassification",eb]],["swin",["SwinForImageClassification",rb]],["segformer",["SegformerForImageClassification",Jy]],["efficientnet",["EfficientNetForImageClassification",r0]],["mobilenet_v1",["MobileNetV1ForImageClassification",n0]],["mobilenet_v2",["MobileNetV2ForImageClassification",i0]],["mobilenet_v3",["MobileNetV3ForImageClassification",u0]],["mobilenet_v4",["MobileNetV4ForImageClassification",m0]]]),X0=new Map([["detr",["DetrForObjectDetection",OM]],["rt_detr",["RTDetrForObjectDetection",zM]],["rt_detr_v2",["RTDetrV2ForObjectDetection",RM]],["rf_detr",["RFDetrForObjectDetection",VM]],["d_fine",["DFineForObjectDetection",GM]],["table-transformer",["TableTransformerForObjectDetection",HM]],["yolos",["YolosForObjectDetection",jb]]]),J0=new Map([["owlvit",["OwlViTForObjectDetection",SM]],["owlv2",["Owlv2ForObjectDetection",kM]],["grounding-dino",["GroundingDinoForObjectDetection",Bb]]]),lo=new Map([["detr",["DetrForSegmentation",Jc]],["clipseg",["CLIPSegForImageSegmentation",to]]]),Y0=new Map([["segformer",["SegformerForSemanticSegmentation",Yy]],["sapiens",["SapiensForSemanticSegmentation",ub]],["swin",["SwinForSemanticSegmentation",sb]],["mobilenet_v1",["MobileNetV1ForSemanticSegmentation",o0]],["mobilenet_v2",["MobileNetV2ForSemanticSegmentation",l0]],["mobilenet_v3",["MobileNetV3ForSemanticSegmentation",d0]],["mobilenet_v4",["MobileNetV4ForSemanticSegmentation",h0]]]),Z0=new Map([["detr",["DetrForSegmentation",Jc]],["maskformer",["MaskFormerForInstanceSegmentation",bb]]]),ev=new Map([["sam",["SamModel",Ub]],["sam2",["Sam2Model",ti]],["edgetam",["EdgeTamModel",Hb]],["sam3_tracker",["Sam3TrackerModel",qb]]]),tv=new Map([["wav2vec2",["Wav2Vec2ForCTC",ey]],["wav2vec2-bert",["Wav2Vec2BertForCTC",gy]],["unispeech",["UniSpeechForCTC",uy]],["unispeech-sat",["UniSpeechSatForCTC",my]],["wavlm",["WavLMForCTC",xy]],["hubert",["HubertForCTC",by]],["parakeet_ctc",["ParakeetForCTC",ny]]]),rv=new Map([["wav2vec2",["Wav2Vec2ForSequenceClassification",ty]],["wav2vec2-bert",["Wav2Vec2BertForSequenceClassification",wy]],["unispeech",["UniSpeechForSequenceClassification",dy]],["unispeech-sat",["UniSpeechSatForSequenceClassification",hy]],["wavlm",["WavLMForSequenceClassification",Ty]],["hubert",["HubertForSequenceClassification",yy]],["audio-spectrogram-transformer",["ASTForAudioClassification",La]]]),sv=new Map([["wavlm",["WavLMForXVector",Ey]]]),nv=new Map([["unispeech-sat",["UniSpeechSatForAudioFrameClassification",_y]],["wavlm",["WavLMForAudioFrameClassification",Py]],["wav2vec2",["Wav2Vec2ForAudioFrameClassification",ry]],["pyannote",["PyAnnoteForAudioFrameClassification",ay]]]),ov=new Map([["vitmatte",["VitMatteForImageMatting",vM]]]),XT=new Map([["patchtst",["PatchTSTForPrediction",x0]],["patchtsmixer",["PatchTSMixerForPrediction",E0]]]),av=new Map([["swin2sr",["Swin2SRForImageSuperResolution",ob]]]),iv=new Map([["dpt",["DPTForDepthEstimation",ib]],["depth_anything",["DepthAnythingForDepthEstimation",cb]],["glpn",["GLPNForDepthEstimation",vb]],["sapiens",["SapiensForDepthEstimation",db]],["depth_pro",["DepthProForDepthEstimation",hb]],["metric3d",["Metric3DForDepthEstimation",fb]],["metric3dv2",["Metric3Dv2ForDepthEstimation",wb]]]),lv=new Map([["sapiens",["SapiensForNormalEstimation",pb]]]),cv=new Map([["vitpose",["VitPoseForPoseEstimation",uM]]]),uv=new Map([["clip",["CLIPVisionModelWithProjection",Bo]],["siglip",["SiglipVisionModel",jo]],["jina_clip",["JinaCLIPVisionModel",In]]]),dv=[[WT,T.EncoderOnly],[GT,T.EncoderDecoder],[HT,T.DecoderOnly],[KT,T.AutoEncoder],[U0,T.EncoderOnly],[W0,T.EncoderOnly],[Du,T.Seq2Seq],[Ou,T.Seq2Seq],[Lu,T.DecoderOnly],[qT,T.MultiModality],[G0,T.EncoderOnly],[K0,T.EncoderOnly],[zu,T.Vision2Seq],[H0,T.ImageTextToText],[q0,T.AudioTextToText],[Q0,T.EncoderOnly],[lo,T.EncoderOnly],[Z0,T.EncoderOnly],[Y0,T.EncoderOnly],[ov,T.EncoderOnly],[XT,T.EncoderOnly],[av,T.EncoderOnly],[iv,T.EncoderOnly],[lv,T.EncoderOnly],[cv,T.EncoderOnly],[X0,T.EncoderOnly],[J0,T.EncoderOnly],[ev,T.MaskGeneration],[tv,T.EncoderOnly],[rv,T.EncoderOnly],[N0,T.Seq2Seq],[V0,T.EncoderOnly],[sv,T.EncoderOnly],[nv,T.EncoderOnly],[uv,T.EncoderOnly]];for(const[g,P]of dv)for(const[L,ne]of g.values())M.set(L,P),v.set(ne,L),x.set(L,ne);const JT=[["MusicgenForConditionalGeneration",ku,T.Musicgen],["Phi3VForCausalLM",$n,T.Phi3V],["CLIPTextModelWithProjection",zo,T.EncoderOnly],["SiglipTextModel",Ro,T.EncoderOnly],["JinaCLIPTextModel",Vo,T.EncoderOnly],["ClapTextModelWithProjection",qy,T.EncoderOnly],["ClapAudioModelWithProjection",Qy,T.EncoderOnly],["DacEncoderModel",L0,T.EncoderOnly],["DacDecoderModel",z0,T.EncoderOnly],["MimiEncoderModel",I0,T.EncoderOnly],["MimiDecoderModel",A0,T.EncoderOnly],["SnacEncoderModel",R0,T.EncoderOnly],["SnacDecoderModel",j0,T.EncoderOnly],["Gemma3nForConditionalGeneration",ln,T.ImageAudioTextToText],["SupertonicForConditionalGeneration",Mu,T.Supertonic]];for(const[g,P,L]of JT)M.set(g,L),v.set(P,g),x.set(g,P);const pv=new Map([["modnet",lo],["birefnet",lo],["isnet",lo],["ben",lo]]);for(const[g,P]of pv.entries())P.set(g,["PreTrainedModel",O]),M.set(g,T.EncoderOnly),v.set(O,g),x.set(g,O);class Bu extends Gt{}J(Bu,"MODEL_CLASS_MAPPINGS",dv.map(P=>P[0])),J(Bu,"BASE_IF_FAIL",!0);class mv extends Gt{}J(mv,"MODEL_CLASS_MAPPINGS",[U0]);class hv extends Gt{}J(hv,"MODEL_CLASS_MAPPINGS",[W0]);class _v extends Gt{}J(_v,"MODEL_CLASS_MAPPINGS",[Du]);class fv extends Gt{}J(fv,"MODEL_CLASS_MAPPINGS",[Ou]);class gv extends Gt{}J(gv,"MODEL_CLASS_MAPPINGS",[N0]);class wv extends Gt{}J(wv,"MODEL_CLASS_MAPPINGS",[V0]);class Mv extends Gt{}J(Mv,"MODEL_CLASS_MAPPINGS",[Lu]);class bv extends Gt{}J(bv,"MODEL_CLASS_MAPPINGS",[G0]);class yv extends Gt{}J(yv,"MODEL_CLASS_MAPPINGS",[K0]);class vv extends Gt{}J(vv,"MODEL_CLASS_MAPPINGS",[zu]);class xv extends Gt{}J(xv,"MODEL_CLASS_MAPPINGS",[Q0]);class Tv extends Gt{}J(Tv,"MODEL_CLASS_MAPPINGS",[lo]);class Ev extends Gt{}J(Ev,"MODEL_CLASS_MAPPINGS",[Y0]);class Pv extends Gt{}J(Pv,"MODEL_CLASS_MAPPINGS",[Z0]);class Cv extends Gt{}J(Cv,"MODEL_CLASS_MAPPINGS",[X0]);class Sv extends Gt{}J(Sv,"MODEL_CLASS_MAPPINGS",[J0]);class $v extends Gt{}J($v,"MODEL_CLASS_MAPPINGS",[ev]);class kv extends Gt{}J(kv,"MODEL_CLASS_MAPPINGS",[tv]);class Iv extends Gt{}J(Iv,"MODEL_CLASS_MAPPINGS",[rv]);class Av extends Gt{}J(Av,"MODEL_CLASS_MAPPINGS",[sv]);class Fv extends Gt{}J(Fv,"MODEL_CLASS_MAPPINGS",[nv]);class Ov extends Gt{}J(Ov,"MODEL_CLASS_MAPPINGS",[QT]);class Dv extends Gt{}J(Dv,"MODEL_CLASS_MAPPINGS",[ov]);class Lv extends Gt{}J(Lv,"MODEL_CLASS_MAPPINGS",[av]);class zv extends Gt{}J(zv,"MODEL_CLASS_MAPPINGS",[iv]);class Bv extends Gt{}J(Bv,"MODEL_CLASS_MAPPINGS",[lv]);class Rv extends Gt{}J(Rv,"MODEL_CLASS_MAPPINGS",[cv]);class jv extends Gt{}J(jv,"MODEL_CLASS_MAPPINGS",[uv]);class Nv extends Gt{}J(Nv,"MODEL_CLASS_MAPPINGS",[H0]);class Vv extends Gt{}J(Vv,"MODEL_CLASS_MAPPINGS",[q0]);class YT extends me{constructor({logits:P,past_key_values:L,encoder_outputs:ne,decoder_attentions:ge=null,cross_attentions:fe=null}){super(),this.logits=P,this.past_key_values=L,this.encoder_outputs=ne,this.decoder_attentions=ge,this.cross_attentions=fe}}class Et extends me{constructor({logits:P,...L}){super(),this.logits=P;const ne=Object.values(L);ne.length>0&&(this.attentions=ne)}}class Uv extends me{constructor({logits:P,embeddings:L}){super(),this.logits=P,this.embeddings=L}}class Sr extends me{constructor({logits:P}){super(),this.logits=P}}class Or extends me{constructor({logits:P}){super(),this.logits=P}}class Nr extends me{constructor({start_logits:P,end_logits:L}){super(),this.start_logits=P,this.end_logits=L}}class dn extends me{constructor({logits:P}){super(),this.logits=P}}class ZT extends me{constructor({logits:P,past_key_values:L}){super(),this.logits=P,this.past_key_values=L}}class Wv extends me{constructor({alphas:P}){super(),this.alphas=P}}class Gv extends me{constructor({waveform:P,spectrogram:L}){super(),this.waveform=P,this.spectrogram=L}}},"./src/models/audio_spectrogram_transformer/feature_extraction_audio_spectrogram_transformer.js":(e,r,t)=>{t.r(r),t.d(r,{ASTFeatureExtractor:()=>n});var s=t("./src/base/feature_extraction_utils.js");t("./src/utils/tensor.js");var o=t("./src/utils/audio.js");class n extends s.FeatureExtractor{constructor(i){super(i);const l=this.config.sampling_rate,c=(0,o.mel_filter_bank)(257,this.config.num_mel_bins,20,Math.floor(l/2),l,null,"kaldi",!0);this.mel_filters=c,this.window=(0,o.window_function)(400,"hann",{periodic:!1}),this.mean=this.config.mean,this.std=this.config.std}async _extract_fbank_features(i,l){return(0,o.spectrogram)(i,this.window,400,160,{fft_length:512,power:2,center:!1,preemphasis:.97,mel_filters:this.mel_filters,log_mel:"log",mel_floor:1192092955078125e-22,remove_dc_offset:!0,max_num_frames:l,transpose:!0})}async _call(i){(0,s.validate_audio_inputs)(i,"ASTFeatureExtractor");const l=await this._extract_fbank_features(i,this.config.max_length);if(this.config.do_normalize){const c=this.std*2,p=l.data;for(let d=0;d{t.r(r),t.d(r,{AutoFeatureExtractor:()=>a});var s=t("./src/utils/constants.js"),o=t("./src/utils/hub.js");t("./src/base/feature_extraction_utils.js");var n=t("./src/models/feature_extractors.js");class a{static async from_pretrained(l,c={}){const p=await(0,o.getModelJSON)(l,s.FEATURE_EXTRACTOR_NAME,!0,c),d=p.feature_extractor_type,u=n[d];if(!u)throw new Error(`Unknown feature_extractor_type: '${d}'. Please report this at ${s.GITHUB_ISSUE_URL}.`);return new u(p)}}},"./src/models/auto/image_processing_auto.js":(e,r,t)=>{t.r(r),t.d(r,{AutoImageProcessor:()=>i});var s=t("./src/utils/constants.js"),o=t("./src/utils/hub.js"),n=t("./src/base/image_processors_utils.js"),a=t("./src/models/image_processors.js");class i{static async from_pretrained(c,p={}){const d=await(0,o.getModelJSON)(c,s.IMAGE_PROCESSOR_NAME,!0,p),u=d.image_processor_type??d.feature_extractor_type;let f=a[u==null?void 0:u.replace(/Fast$/,"")];return f||(u!==void 0&&console.warn(`Image processor type '${u}' not found, assuming base ImageProcessor. Please report this at ${s.GITHUB_ISSUE_URL}.`),f=n.ImageProcessor),new f(d)}}},"./src/models/auto/processing_auto.js":(e,r,t)=>{t.r(r),t.d(r,{AutoProcessor:()=>c});var s=t("./src/utils/constants.js"),o=t("./src/utils/hub.js"),n=t("./src/base/processing_utils.js"),a=t("./src/models/processors.js"),i=t("./src/models/image_processors.js"),l=t("./src/models/feature_extractors.js");class c{static async from_pretrained(d,u={}){const f=await(0,o.getModelJSON)(d,s.IMAGE_PROCESSOR_NAME,!0,u),{image_processor_type:_,feature_extractor_type:b,processor_class:k}=f;if(k&&a[k])return a[k].from_pretrained(d,u);if(!_&&!b)throw new Error("No `image_processor_type` or `feature_extractor_type` found in the config.");const w={};if(_){const $=i[_.replace(/Fast$/,"")];if(!$)throw new Error(`Unknown image_processor_type: '${_}'.`);w.image_processor=new $(f)}if(b){const $=i[b];if($)w.image_processor=new $(f);else{const T=l[b];if(!T)throw new Error(`Unknown feature_extractor_type: '${b}'.`);w.feature_extractor=new T(f)}}const y={};return new n.Processor(y,w,null)}}},"./src/models/beit/image_processing_beit.js":(e,r,t)=>{t.r(r),t.d(r,{BeitFeatureExtractor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{}},"./src/models/bit/image_processing_bit.js":(e,r,t)=>{t.r(r),t.d(r,{BitImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{}},"./src/models/chinese_clip/image_processing_chinese_clip.js":(e,r,t)=>{t.r(r),t.d(r,{ChineseCLIPFeatureExtractor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{}},"./src/models/clap/feature_extraction_clap.js":(e,r,t)=>{t.r(r),t.d(r,{ClapFeatureExtractor:()=>n});var s=t("./src/base/feature_extraction_utils.js");t("./src/utils/tensor.js");var o=t("./src/utils/audio.js");class n extends s.FeatureExtractor{constructor(i){super(i),this.mel_filters=(0,o.mel_filter_bank)(this.config.nb_frequency_bins,this.config.feature_size,this.config.frequency_min,this.config.frequency_max,this.config.sampling_rate,null,"htk"),this.mel_filters_slaney=(0,o.mel_filter_bank)(this.config.nb_frequency_bins,this.config.feature_size,this.config.frequency_min,this.config.frequency_max,this.config.sampling_rate,"slaney","slaney"),this.window=(0,o.window_function)(this.config.fft_window_size,"hann")}async _get_input_mel(i,l,c,p){let d;const u=i.length-l;if(u>0)if(c==="rand_trunc"){const f=Math.floor(Math.random()*(u+1));i=i.subarray(f,f+l),d=await this._extract_fbank_features(i,this.mel_filters_slaney,this.config.nb_max_samples)}else throw new Error(`Truncation strategy "${c}" not implemented`);else{if(u<0){let f=new Float64Array(l);if(f.set(i),p==="repeat")for(let _=i.length;_{t.r(r),t.d(r,{CLIPFeatureExtractor:()=>n,CLIPImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{}class n extends o{}},"./src/models/convnext/image_processing_convnext.js":(e,r,t)=>{t.r(r),t.d(r,{ConvNextFeatureExtractor:()=>n,ConvNextImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{constructor(i){super(i),this.crop_pct=this.config.crop_pct??224/256}async resize(i){var c;const l=(c=this.size)==null?void 0:c.shortest_edge;if(l===void 0)throw new Error("Size dictionary must contain 'shortest_edge' key.");if(l<384){const p=Math.floor(l/this.crop_pct),[d,u]=this.get_resize_output_image_size(i,{shortest_edge:p});i=await i.resize(d,u,{resample:this.resample}),i=await i.center_crop(l,l)}else i=await i.resize(l,l,{resample:this.resample});return i}}class n extends o{}},"./src/models/dac/feature_extraction_dac.js":(e,r,t)=>{t.r(r),t.d(r,{DacFeatureExtractor:()=>o});var s=t("./src/models/encodec/feature_extraction_encodec.js");class o extends s.EncodecFeatureExtractor{}},"./src/models/deit/image_processing_deit.js":(e,r,t)=>{t.r(r),t.d(r,{DeiTFeatureExtractor:()=>n,DeiTImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{}class n extends o{}},"./src/models/detr/image_processing_detr.js":(e,r,t)=>{t.r(r),t.d(r,{DetrFeatureExtractor:()=>a,DetrImageProcessor:()=>n});var s=t("./src/base/image_processors_utils.js"),o=t("./src/utils/tensor.js");class n extends s.ImageProcessor{async _call(l){const c=await super._call(l),p=[c.pixel_values.dims[0],64,64],d=(0,o.full)(p,1n);return{...c,pixel_mask:d}}post_process_object_detection(...l){return(0,s.post_process_object_detection)(...l)}post_process_panoptic_segmentation(...l){return(0,s.post_process_panoptic_segmentation)(...l)}post_process_instance_segmentation(...l){return(0,s.post_process_instance_segmentation)(...l)}}class a extends n{}},"./src/models/dinov3_vit/image_processing_dinov3_vit.js":(e,r,t)=>{t.r(r),t.d(r,{DINOv3ViTImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{}},"./src/models/donut/image_processing_donut.js":(e,r,t)=>{t.r(r),t.d(r,{DonutFeatureExtractor:()=>n,DonutImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{pad_image(i,l,c,p={}){const[d,u,f]=l;let _=this.image_mean;Array.isArray(this.image_mean)||(_=new Array(f).fill(_));let b=this.image_std;Array.isArray(b)||(b=new Array(f).fill(_));const k=_.map((w,y)=>-w/b[y]);return super.pad_image(i,l,c,{center:!0,constant_values:k,...p})}}class n extends o{}},"./src/models/dpt/image_processing_dpt.js":(e,r,t)=>{t.r(r),t.d(r,{DPTFeatureExtractor:()=>n,DPTImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{}class n extends o{}},"./src/models/efficientnet/image_processing_efficientnet.js":(e,r,t)=>{t.r(r),t.d(r,{EfficientNetImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{constructor(a){super(a),this.include_top=this.config.include_top??!0,this.include_top&&(this.image_std=this.image_std.map(i=>i*i))}}},"./src/models/encodec/feature_extraction_encodec.js":(e,r,t)=>{t.r(r),t.d(r,{EncodecFeatureExtractor:()=>n});var s=t("./src/base/feature_extraction_utils.js"),o=t("./src/utils/tensor.js");class n extends s.FeatureExtractor{async _call(i){(0,s.validate_audio_inputs)(i,"EncodecFeatureExtractor"),i instanceof Float64Array&&(i=new Float32Array(i));const l=this.config.feature_size;if(i.length%l!==0)throw new Error(`The length of the audio data must be a multiple of the number of channels (${l}).`);const c=[1,l,i.length/l];return{input_values:new o.Tensor("float32",i,c)}}}},"./src/models/feature_extractors.js":(e,r,t)=>{t.r(r),t.d(r,{ASTFeatureExtractor:()=>s.ASTFeatureExtractor,ClapFeatureExtractor:()=>n.ClapFeatureExtractor,DacFeatureExtractor:()=>a.DacFeatureExtractor,EncodecFeatureExtractor:()=>o.EncodecFeatureExtractor,Gemma3nAudioFeatureExtractor:()=>i.Gemma3nAudioFeatureExtractor,ImageFeatureExtractor:()=>w.ImageProcessor,MoonshineFeatureExtractor:()=>l.MoonshineFeatureExtractor,ParakeetFeatureExtractor:()=>c.ParakeetFeatureExtractor,PyAnnoteFeatureExtractor:()=>p.PyAnnoteFeatureExtractor,SeamlessM4TFeatureExtractor:()=>d.SeamlessM4TFeatureExtractor,SnacFeatureExtractor:()=>u.SnacFeatureExtractor,SpeechT5FeatureExtractor:()=>f.SpeechT5FeatureExtractor,Wav2Vec2FeatureExtractor:()=>_.Wav2Vec2FeatureExtractor,WeSpeakerFeatureExtractor:()=>b.WeSpeakerFeatureExtractor,WhisperFeatureExtractor:()=>k.WhisperFeatureExtractor});var s=t("./src/models/audio_spectrogram_transformer/feature_extraction_audio_spectrogram_transformer.js"),o=t("./src/models/encodec/feature_extraction_encodec.js"),n=t("./src/models/clap/feature_extraction_clap.js"),a=t("./src/models/dac/feature_extraction_dac.js"),i=t("./src/models/gemma3n/feature_extraction_gemma3n.js"),l=t("./src/models/moonshine/feature_extraction_moonshine.js"),c=t("./src/models/parakeet/feature_extraction_parakeet.js"),p=t("./src/models/pyannote/feature_extraction_pyannote.js"),d=t("./src/models/seamless_m4t/feature_extraction_seamless_m4t.js"),u=t("./src/models/snac/feature_extraction_snac.js"),f=t("./src/models/speecht5/feature_extraction_speecht5.js"),_=t("./src/models/wav2vec2/feature_extraction_wav2vec2.js"),b=t("./src/models/wespeaker/feature_extraction_wespeaker.js"),k=t("./src/models/whisper/feature_extraction_whisper.js"),w=t("./src/base/image_processors_utils.js")},"./src/models/florence2/processing_florence2.js":(e,r,t)=>{t.r(r),t.d(r,{Florence2Processor:()=>a});var s=t("./src/base/processing_utils.js"),o=t("./src/models/auto/image_processing_auto.js"),n=t("./src/tokenizers.js");class a extends s.Processor{constructor(l,c,p){super(l,c,p);const{tasks_answer_post_processing_type:d,task_prompts_without_inputs:u,task_prompts_with_input:f}=this.image_processor.config;this.tasks_answer_post_processing_type=new Map(Object.entries(d??{})),this.task_prompts_without_inputs=new Map(Object.entries(u??{})),this.task_prompts_with_input=new Map(Object.entries(f??{})),this.regexes={quad_boxes:/(.+?)/gm,bboxes:/([^<]+)?/gm},this.size_per_bin=1e3}construct_prompts(l){typeof l=="string"&&(l=[l]);const c=[];for(const p of l)if(this.task_prompts_without_inputs.has(p))c.push(this.task_prompts_without_inputs.get(p));else{for(const[d,u]of this.task_prompts_with_input)if(p.includes(d)){c.push(u.replaceAll("{input}",p).replaceAll(d,""));break}c.length!==l.length&&c.push(p)}return c}post_process_generation(l,c,p){const d=this.tasks_answer_post_processing_type.get(c)??"pure_text";l=l.replaceAll("","").replaceAll("","");let u;switch(d){case"pure_text":u=l;break;case"description_with_bboxes":case"bboxes":case"phrase_grounding":case"ocr":const f=d==="ocr"?"quad_boxes":"bboxes",_=l.matchAll(this.regexes[f]),b=[],k=[];for(const[w,y,...$]of _)b.push(y?y.trim():b.at(-1)??""),k.push($.map((T,M)=>(Number(T)+.5)/this.size_per_bin*p[M%2]));u={labels:b,[f]:k};break;default:throw new Error(`Task "${c}" (of type "${d}") not yet implemented.`)}return{[c]:u}}async _call(l,c=null,p={}){if(!l&&!c)throw new Error("Either text or images must be provided");const d=await this.image_processor(l,p),u=c?this.tokenizer(this.construct_prompts(c),p):{};return{...d,...u}}}J(a,"tokenizer_class",n.AutoTokenizer),J(a,"image_processor_class",o.AutoImageProcessor)},"./src/models/gemma3n/feature_extraction_gemma3n.js":(e,r,t)=>{t.r(r),t.d(r,{Gemma3nAudioFeatureExtractor:()=>a});var s=t("./src/base/feature_extraction_utils.js"),o=t("./src/utils/tensor.js"),n=t("./src/utils/audio.js");class a extends s.FeatureExtractor{constructor(l){super(l);const{fft_length:c,feature_size:p,min_frequency:d,max_frequency:u,sampling_rate:f,frame_length:_}=this.config,b=(0,n.mel_filter_bank)(Math.floor(1+c/2),p,d,u,f,null,"htk",!1);this.mel_filters=b,this.window=(0,n.window_function)(_,"hann")}async _extract_fbank_features(l,c){return(0,n.spectrogram)(l,this.window,this.config.frame_length,this.config.hop_length,{fft_length:this.config.fft_length,center:!1,onesided:!0,preemphasis:this.config.preemphasis,preemphasis_htk_flavor:this.config.preemphasis_htk_flavor,mel_filters:this.mel_filters,log_mel:"log",mel_floor:this.config.mel_floor,remove_dc_offset:!1,transpose:!0})}async _call(l,{max_length:c=48e4,truncation:p=!0,padding:d=!0,pad_to_multiple_of:u=128}={}){if((0,s.validate_audio_inputs)(l,"Gemma3nAudioFeatureExtractor"),p&&l.length>c&&(l=l.slice(0,c)),d&&l.length%u!==0){const b=u-l.length%u,k=new Float64Array(l.length+b);k.set(l),this.config.padding_value!==0&&k.fill(this.config.padding_value,l.length),l=k}const f=await this._extract_fbank_features(l,this.config.max_length),_=(0,o.full)([1,f.dims[0]],!0);return{input_features:f.unsqueeze_(0),input_features_mask:_}}}},"./src/models/gemma3n/processing_gemma3n.js":(e,r,t)=>{t.r(r),t.d(r,{Gemma3nProcessor:()=>i});var s=t("./src/base/processing_utils.js"),o=t("./src/models/auto/image_processing_auto.js"),n=t("./src/models/auto/feature_extraction_auto.js"),a=t("./src/tokenizers.js");t("./src/utils/image.js"),t("./src/utils/audio.js");class i extends s.Processor{constructor(c,p,d){super(c,p,d),this.audio_seq_length=this.config.audio_seq_length,this.image_seq_length=this.config.image_seq_length;const{audio_token_id:u,boa_token:f,audio_token:_,eoa_token:b,image_token_id:k,boi_token:w,image_token:y,eoi_token:$}=this.tokenizer.config;this.audio_token_id=u,this.boa_token=f,this.audio_token=_;const T=_.repeat(this.audio_seq_length);this.full_audio_sequence=` - -${f}${T}${b} - -`,this.image_token_id=k,this.boi_token=w,this.image_token=y;const M=y.repeat(this.image_seq_length);this.full_image_sequence=` - -${w}${M}${$} - -`}async _call(c,p=null,d=null,u={}){typeof c=="string"&&(c=[c]);let f;d&&(f=await this.feature_extractor(d,u),c=c.map(k=>k.replaceAll(this.audio_token,this.full_audio_sequence)));let _;return p&&(_=await this.image_processor(p,u),c=c.map(k=>k.replaceAll(this.image_token,this.full_image_sequence))),{...this.tokenizer(c,u),..._,...f}}}J(i,"image_processor_class",o.AutoImageProcessor),J(i,"feature_extractor_class",n.AutoFeatureExtractor),J(i,"tokenizer_class",a.AutoTokenizer),J(i,"uses_processor_config",!0),J(i,"uses_chat_template_file",!0)},"./src/models/glpn/image_processing_glpn.js":(e,r,t)=>{t.r(r),t.d(r,{GLPNFeatureExtractor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{}},"./src/models/grounding_dino/image_processing_grounding_dino.js":(e,r,t)=>{t.r(r),t.d(r,{GroundingDinoImageProcessor:()=>n});var s=t("./src/base/image_processors_utils.js"),o=t("./src/utils/tensor.js");class n extends s.ImageProcessor{async _call(i){const l=await super._call(i),c=l.pixel_values.dims,p=(0,o.ones)([c[0],c[2],c[3]]);return{...l,pixel_mask:p}}}},"./src/models/grounding_dino/processing_grounding_dino.js":(e,r,t)=>{t.r(r),t.d(r,{GroundingDinoProcessor:()=>l});var s=t("./src/base/processing_utils.js"),o=t("./src/models/auto/image_processing_auto.js"),n=t("./src/tokenizers.js"),a=t("./src/base/image_processors_utils.js");function i(c,p){const u=c.dims.at(-1)-1,f=c.tolist();f.fill(!1,0,1),f.fill(!1,u);const _=p.tolist();return f.map((b,k)=>b?k:null).filter(b=>b!==null).map(b=>_[b])}class l extends s.Processor{async _call(p,d,u={}){const f=p?await this.image_processor(p,u):{};return{...d?this.tokenizer(d,u):{},...f}}post_process_grounded_object_detection(p,d,{box_threshold:u=.25,text_threshold:f=.25,target_sizes:_=null}={}){const{logits:b,pred_boxes:k}=p,w=b.dims[0];if(_!==null&&_.length!==w)throw Error("Make sure that you pass in as many target sizes as the batch dimension of the logits");const y=b.dims.at(1),$=b.sigmoid(),T=$.max(-1).tolist(),M=k.tolist().map(v=>v.map(C=>(0,a.center_to_corners_format)(C))),x=[];for(let v=0;vj.map((se,q)=>se*C[(q+1)%2])));const F=T[v],D=[],K=[],U=[];for(let j=0;j{t.r(r),t.d(r,{Idefics3ImageProcessor:()=>n});var s=t("./src/base/image_processors_utils.js"),o=t("./src/utils/tensor.js");class n extends s.ImageProcessor{constructor(i){super(i),this.do_image_splitting=i.do_image_splitting??!0,this.max_image_size=i.max_image_size}get_resize_for_vision_encoder(i,l){let[c,p]=i.dims.slice(-2);const d=p/c;return p>=c?(p=Math.ceil(p/l)*l,c=Math.floor(p/d),c=Math.ceil(c/l)*l):(c=Math.ceil(c/l)*l,p=Math.floor(c*d),p=Math.ceil(p/l)*l),{height:c,width:p}}async _call(i,{do_image_splitting:l=null,return_row_col_info:c=!1}={}){let p;if(!Array.isArray(i))p=[[i]];else{if(i.length===0||!i[0])throw new Error("No images provided.");Array.isArray(i[0])?p=i:p=[i]}let d=[],u=[],f=[];const _=[],b=[];for(const v of p){let C=await Promise.all(v.map(K=>this.preprocess(K)));_.push(...C.map(K=>K.original_size)),b.push(...C.map(K=>K.reshaped_input_size)),C.forEach(K=>K.pixel_values.unsqueeze_(0));const{longest_edge:F}=this.max_image_size;let D;if(l??this.do_image_splitting){let K=new Array(C.length),U=new Array(C.length);D=await Promise.all(C.map(async(j,se)=>{const q=this.get_resize_for_vision_encoder(j.pixel_values,F),re=await(0,o.interpolate_4d)(j.pixel_values,{size:[q.height,q.width]}),{frames:Z,num_splits_h:ae,num_splits_w:_e}=await this.split_image(re,this.max_image_size);return K[se]=ae,U[se]=_e,(0,o.cat)(Z,0)})),u.push(K),f.push(U)}else{const K=[F,F];D=await Promise.all(C.map(U=>(0,o.interpolate_4d)(U.pixel_values,{size:K}))),u.push(new Array(C.length).fill(0)),f.push(new Array(C.length).fill(0))}d.push((0,o.cat)(D,0))}const k=d.length,[w,y,$,T]=d[0].dims;let M,x;if(k===1)M=d[0].unsqueeze_(0),x=(0,o.full)([k,w,$,T],!0);else{const v=Math.max(...d.map(D=>D.dims.at(0)));x=(0,o.full)([k,v,$,T],!0);const C=x.data,F=v*$*T;for(let D=0;Dc||f>p){_=Math.ceil(u/c),b=Math.ceil(f/p);const k=Math.ceil(u/_),w=Math.ceil(f/b);for(let T=0;T<_;++T)for(let M=0;M{t.r(r),t.d(r,{Idefics3Processor:()=>p});var s=t("./src/base/processing_utils.js"),o=t("./src/models/auto/image_processing_auto.js"),n=t("./src/tokenizers.js");t("./src/utils/image.js");var a=t("./src/utils/core.js");function i(d,u,f,_,b,k){let w="";for(let y=0;y`+b.repeat(d);w+=` -`}return w+=` -${_}${k}`+b.repeat(d)+`${_}`,w}function l(d,u,f,_){return`${u}${_}`+f.repeat(d)+`${u}`}function c(d,u,f,_,b,k){return d===0&&u===0?l(f,_,b,k):i(f,d,u,_,b,k)}class p extends s.Processor{constructor(){super(...arguments);J(this,"fake_image_token","");J(this,"image_token","");J(this,"global_img_token","")}async _call(f,_=null,b={}){b.return_row_col_info??(b.return_row_col_info=!0);let k;_&&(k=await this.image_processor(_,b)),Array.isArray(f)||(f=[f]);const w=k.rows??[new Array(f.length).fill(0)],y=k.cols??[new Array(f.length).fill(0)],$=this.config.image_seq_len,T=[],M=[];for(let v=0;vc(se,D[q],$,this.fake_image_token,this.image_token,this.global_img_token)),U=C.split(this.image_token);if(U.length===0)throw new Error("The image token should be present in the text.");let j=U[0];for(let se=0;se{t.r(r),t.d(r,{BeitFeatureExtractor:()=>s.BeitFeatureExtractor,BitImageProcessor:()=>o.BitImageProcessor,CLIPFeatureExtractor:()=>a.CLIPFeatureExtractor,CLIPImageProcessor:()=>a.CLIPImageProcessor,ChineseCLIPFeatureExtractor:()=>n.ChineseCLIPFeatureExtractor,ConvNextFeatureExtractor:()=>i.ConvNextFeatureExtractor,ConvNextImageProcessor:()=>i.ConvNextImageProcessor,DINOv3ViTImageProcessor:()=>p.DINOv3ViTImageProcessor,DPTFeatureExtractor:()=>u.DPTFeatureExtractor,DPTImageProcessor:()=>u.DPTImageProcessor,DeiTFeatureExtractor:()=>l.DeiTFeatureExtractor,DeiTImageProcessor:()=>l.DeiTImageProcessor,DetrFeatureExtractor:()=>c.DetrFeatureExtractor,DetrImageProcessor:()=>c.DetrImageProcessor,DonutFeatureExtractor:()=>d.DonutFeatureExtractor,DonutImageProcessor:()=>d.DonutImageProcessor,EfficientNetImageProcessor:()=>f.EfficientNetImageProcessor,GLPNFeatureExtractor:()=>_.GLPNFeatureExtractor,GroundingDinoImageProcessor:()=>b.GroundingDinoImageProcessor,Idefics3ImageProcessor:()=>k.Idefics3ImageProcessor,JinaCLIPImageProcessor:()=>y.JinaCLIPImageProcessor,LlavaOnevisionImageProcessor:()=>$.LlavaOnevisionImageProcessor,Mask2FormerImageProcessor:()=>T.Mask2FormerImageProcessor,MaskFormerFeatureExtractor:()=>M.MaskFormerFeatureExtractor,MaskFormerImageProcessor:()=>M.MaskFormerImageProcessor,MobileNetV1FeatureExtractor:()=>x.MobileNetV1FeatureExtractor,MobileNetV1ImageProcessor:()=>x.MobileNetV1ImageProcessor,MobileNetV2FeatureExtractor:()=>v.MobileNetV2FeatureExtractor,MobileNetV2ImageProcessor:()=>v.MobileNetV2ImageProcessor,MobileNetV3FeatureExtractor:()=>C.MobileNetV3FeatureExtractor,MobileNetV3ImageProcessor:()=>C.MobileNetV3ImageProcessor,MobileNetV4FeatureExtractor:()=>F.MobileNetV4FeatureExtractor,MobileNetV4ImageProcessor:()=>F.MobileNetV4ImageProcessor,MobileViTFeatureExtractor:()=>D.MobileViTFeatureExtractor,MobileViTImageProcessor:()=>D.MobileViTImageProcessor,NougatImageProcessor:()=>K.NougatImageProcessor,OwlViTFeatureExtractor:()=>j.OwlViTFeatureExtractor,OwlViTImageProcessor:()=>j.OwlViTImageProcessor,Owlv2ImageProcessor:()=>U.Owlv2ImageProcessor,Phi3VImageProcessor:()=>se.Phi3VImageProcessor,PixtralImageProcessor:()=>q.PixtralImageProcessor,PvtImageProcessor:()=>re.PvtImageProcessor,Qwen2VLImageProcessor:()=>Z.Qwen2VLImageProcessor,RTDetrImageProcessor:()=>ae.RTDetrImageProcessor,Sam2ImageProcessor:()=>pe.Sam2ImageProcessor,Sam3ImageProcessor:()=>oe.Sam3ImageProcessor,SamImageProcessor:()=>_e.SamImageProcessor,SegformerFeatureExtractor:()=>G.SegformerFeatureExtractor,SegformerImageProcessor:()=>G.SegformerImageProcessor,SiglipImageProcessor:()=>B.SiglipImageProcessor,SmolVLMImageProcessor:()=>Q.SmolVLMImageProcessor,Swin2SRImageProcessor:()=>le.Swin2SRImageProcessor,VLMImageProcessor:()=>w.VLMImageProcessor,ViTFeatureExtractor:()=>ee.ViTFeatureExtractor,ViTImageProcessor:()=>ee.ViTImageProcessor,VitMatteImageProcessor:()=>Se.VitMatteImageProcessor,VitPoseImageProcessor:()=>De.VitPoseImageProcessor,YolosFeatureExtractor:()=>Ne.YolosFeatureExtractor,YolosImageProcessor:()=>Ne.YolosImageProcessor});var s=t("./src/models/beit/image_processing_beit.js"),o=t("./src/models/bit/image_processing_bit.js"),n=t("./src/models/chinese_clip/image_processing_chinese_clip.js"),a=t("./src/models/clip/image_processing_clip.js"),i=t("./src/models/convnext/image_processing_convnext.js"),l=t("./src/models/deit/image_processing_deit.js"),c=t("./src/models/detr/image_processing_detr.js"),p=t("./src/models/dinov3_vit/image_processing_dinov3_vit.js"),d=t("./src/models/donut/image_processing_donut.js"),u=t("./src/models/dpt/image_processing_dpt.js"),f=t("./src/models/efficientnet/image_processing_efficientnet.js"),_=t("./src/models/glpn/image_processing_glpn.js"),b=t("./src/models/grounding_dino/image_processing_grounding_dino.js"),k=t("./src/models/idefics3/image_processing_idefics3.js"),w=t("./src/models/janus/image_processing_janus.js"),y=t("./src/models/jina_clip/image_processing_jina_clip.js"),$=t("./src/models/llava_onevision/image_processing_llava_onevision.js"),T=t("./src/models/mask2former/image_processing_mask2former.js"),M=t("./src/models/maskformer/image_processing_maskformer.js"),x=t("./src/models/mobilenet_v1/image_processing_mobilenet_v1.js"),v=t("./src/models/mobilenet_v2/image_processing_mobilenet_v2.js"),C=t("./src/models/mobilenet_v3/image_processing_mobilenet_v3.js"),F=t("./src/models/mobilenet_v4/image_processing_mobilenet_v4.js"),D=t("./src/models/mobilevit/image_processing_mobilevit.js"),K=t("./src/models/nougat/image_processing_nougat.js"),U=t("./src/models/owlv2/image_processing_owlv2.js"),j=t("./src/models/owlvit/image_processing_owlvit.js"),se=t("./src/models/phi3_v/image_processing_phi3_v.js"),q=t("./src/models/pixtral/image_processing_pixtral.js"),re=t("./src/models/pvt/image_processing_pvt.js"),Z=t("./src/models/qwen2_vl/image_processing_qwen2_vl.js"),ae=t("./src/models/rt_detr/image_processing_rt_detr.js"),_e=t("./src/models/sam/image_processing_sam.js"),pe=t("./src/models/sam2/image_processing_sam2.js"),oe=t("./src/models/sam3/image_processing_sam3.js"),G=t("./src/models/segformer/image_processing_segformer.js"),B=t("./src/models/siglip/image_processing_siglip.js"),Q=t("./src/models/smolvlm/image_processing_smolvlm.js"),le=t("./src/models/swin2sr/image_processing_swin2sr.js"),ee=t("./src/models/vit/image_processing_vit.js"),Se=t("./src/models/vitmatte/image_processing_vitmatte.js"),De=t("./src/models/vitpose/image_processing_vitpose.js"),Ne=t("./src/models/yolos/image_processing_yolos.js")},"./src/models/janus/image_processing_janus.js":(e,r,t)=>{t.r(r),t.d(r,{VLMImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{constructor(a){super({do_pad:!0,pad_size:{width:a.image_size,height:a.image_size},...a}),this.constant_values=this.config.background_color.map(i=>i*this.rescale_factor)}pad_image(a,i,l,c){return super.pad_image(a,i,l,{constant_values:this.constant_values,center:!0,...c})}}},"./src/models/janus/processing_janus.js":(e,r,t)=>{t.r(r),t.d(r,{VLChatProcessor:()=>c});var s=t("./src/base/processing_utils.js"),o=t("./src/models/auto/image_processing_auto.js"),n=t("./src/tokenizers.js"),a=t("./src/utils/core.js"),i=t("./src/utils/tensor.js"),l=t("./src/utils/image.js");class c extends s.Processor{constructor(d,u,f){super(d,u,f),this.image_tag=this.config.image_tag,this.image_start_tag=this.config.image_start_tag,this.image_end_tag=this.config.image_end_tag,this.num_image_tokens=this.config.num_image_tokens}async _call(d,{images:u=null,chat_template:f="default"}={}){u?Array.isArray(u)||(u=[u]):u=await Promise.all(d.filter(D=>D.images).flatMap(D=>D.images).map(D=>l.RawImage.read(D)));const _=this.tokenizer,b=_.apply_chat_template(d,{tokenize:!1,add_generation_prompt:!0,chat_template:f}),k=D=>_.encode(D,{add_special_tokens:!1}),w=b.split(this.image_tag),y=w.length-1;if(u.length!==y)throw new Error(`Number of images provided (${u.length}) does not match number of "${this.image_tag}" image tags (${y})`);const[$,T,M]=_.model.convert_tokens_to_ids([this.image_tag,this.image_start_tag,this.image_end_tag]);let x=k(w[0]),v=new Array(x.length).fill(!1);for(let D=1;D0){const D=await this.image_processor(u);return D.pixel_values.unsqueeze_(0),{...F,...D}}return F}}J(c,"image_processor_class",o.AutoImageProcessor),J(c,"tokenizer_class",n.AutoTokenizer),J(c,"uses_processor_config",!0)},"./src/models/jina_clip/image_processing_jina_clip.js":(e,r,t)=>{t.r(r),t.d(r,{JinaCLIPImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{constructor(a){const{resize_mode:i,fill_color:l,interpolation:c,size:p,...d}=a,u=i==="squash"?{width:p,height:p}:i==="shortest"?{shortest_edge:p}:{longest_edge:p},f=c==="bicubic"?3:2;super({...d,size:u,resample:f,do_center_crop:!0,crop_size:p,do_normalize:!0})}}},"./src/models/jina_clip/processing_jina_clip.js":(e,r,t)=>{t.r(r),t.d(r,{JinaCLIPProcessor:()=>a});var s=t("./src/base/processing_utils.js"),o=t("./src/models/auto/image_processing_auto.js"),n=t("./src/tokenizers.js");class a extends s.Processor{async _call(l=null,c=null,p={}){if(!l&&!c)throw new Error("Either text or images must be provided");const d=l?this.tokenizer(l,p):{},u=c?await this.image_processor(c,p):{};return{...d,...u}}}J(a,"tokenizer_class",n.AutoTokenizer),J(a,"image_processor_class",o.AutoImageProcessor)},"./src/models/llava/processing_llava.js":(e,r,t)=>{t.r(r),t.d(r,{LlavaProcessor:()=>a});var s=t("./src/base/processing_utils.js"),o=t("./src/models/auto/image_processing_auto.js"),n=t("./src/tokenizers.js");class a extends s.Processor{async _call(l,c=null,p={}){const d=await this.image_processor(l,p);if(c){const[f,_]=d.pixel_values.dims.slice(-2),{image_token:b,patch_size:k,num_additional_image_tokens:w}=this.config,y=Math.floor(f/k)*Math.floor(_/k)+w;c=structuredClone(c),Array.isArray(c)||(c=[c]);for(let $=0;${t.r(r),t.d(r,{LlavaOnevisionImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{}},"./src/models/mask2former/image_processing_mask2former.js":(e,r,t)=>{t.r(r),t.d(r,{Mask2FormerImageProcessor:()=>o});var s=t("./src/models/maskformer/image_processing_maskformer.js");class o extends s.MaskFormerImageProcessor{}},"./src/models/maskformer/image_processing_maskformer.js":(e,r,t)=>{t.r(r),t.d(r,{MaskFormerFeatureExtractor:()=>n,MaskFormerImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{post_process_panoptic_segmentation(...i){return(0,s.post_process_panoptic_segmentation)(...i)}post_process_instance_segmentation(...i){return(0,s.post_process_instance_segmentation)(...i)}}class n extends o{}},"./src/models/mgp_str/processing_mgp_str.js":(e,r,t)=>{t.r(r),t.d(r,{MgpstrProcessor:()=>l});var s=t("./src/base/processing_utils.js"),o=t("./src/models/auto/image_processing_auto.js"),n=t("./src/tokenizers.js"),a=t("./src/utils/maths.js");const i={char:["char_decode",1],bpe:["bpe_decode",2],wp:["wp_decode",102]};class l extends s.Processor{get char_tokenizer(){return this.components.char_tokenizer}get bpe_tokenizer(){return this.components.bpe_tokenizer}get wp_tokenizer(){return this.components.wp_tokenizer}_decode_helper(p,d){if(!i.hasOwnProperty(d))throw new Error(`Format ${d} is not supported.`);const[u,f]=i[d],_=this[u].bind(this),[b,k]=p.dims,w=[],y=[],$=p.tolist();for(let M=0;M0?C.reduce((D,K)=>D*K,1):0;y.push(v),w.push(F)}return[_(y),w]}char_decode(p){return this.char_tokenizer.batch_decode(p).map(d=>d.replaceAll(" ",""))}bpe_decode(p){return this.bpe_tokenizer.batch_decode(p)}wp_decode(p){return this.wp_tokenizer.batch_decode(p).map(d=>d.replaceAll(" ",""))}batch_decode([p,d,u]){const[f,_]=this._decode_helper(p,"char"),[b,k]=this._decode_helper(d,"bpe"),[w,y]=this._decode_helper(u,"wp"),$=[],T=[];for(let M=0;M{t.r(r),t.d(r,{MobileNetV1FeatureExtractor:()=>n,MobileNetV1ImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{}class n extends o{}},"./src/models/mobilenet_v2/image_processing_mobilenet_v2.js":(e,r,t)=>{t.r(r),t.d(r,{MobileNetV2FeatureExtractor:()=>n,MobileNetV2ImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{}class n extends o{}},"./src/models/mobilenet_v3/image_processing_mobilenet_v3.js":(e,r,t)=>{t.r(r),t.d(r,{MobileNetV3FeatureExtractor:()=>n,MobileNetV3ImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{}class n extends o{}},"./src/models/mobilenet_v4/image_processing_mobilenet_v4.js":(e,r,t)=>{t.r(r),t.d(r,{MobileNetV4FeatureExtractor:()=>n,MobileNetV4ImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{}class n extends o{}},"./src/models/mobilevit/image_processing_mobilevit.js":(e,r,t)=>{t.r(r),t.d(r,{MobileViTFeatureExtractor:()=>n,MobileViTImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{}class n extends o{}},"./src/models/moonshine/feature_extraction_moonshine.js":(e,r,t)=>{t.r(r),t.d(r,{MoonshineFeatureExtractor:()=>n});var s=t("./src/base/feature_extraction_utils.js"),o=t("./src/utils/tensor.js");class n extends s.FeatureExtractor{async _call(i){(0,s.validate_audio_inputs)(i,"MoonshineFeatureExtractor"),i instanceof Float64Array&&(i=new Float32Array(i));const l=[1,i.length];return{input_values:new o.Tensor("float32",i,l)}}}},"./src/models/moonshine/processing_moonshine.js":(e,r,t)=>{t.r(r),t.d(r,{MoonshineProcessor:()=>a});var s=t("./src/models/auto/feature_extraction_auto.js"),o=t("./src/tokenizers.js"),n=t("./src/base/processing_utils.js");class a extends n.Processor{async _call(l){return await this.feature_extractor(l)}}J(a,"tokenizer_class",o.AutoTokenizer),J(a,"feature_extractor_class",s.AutoFeatureExtractor)},"./src/models/nougat/image_processing_nougat.js":(e,r,t)=>{t.r(r),t.d(r,{NougatImageProcessor:()=>o});var s=t("./src/models/donut/image_processing_donut.js");class o extends s.DonutImageProcessor{}},"./src/models/owlv2/image_processing_owlv2.js":(e,r,t)=>{t.r(r),t.d(r,{Owlv2ImageProcessor:()=>o});var s=t("./src/models/owlvit/image_processing_owlvit.js");class o extends s.OwlViTImageProcessor{}},"./src/models/owlvit/image_processing_owlvit.js":(e,r,t)=>{t.r(r),t.d(r,{OwlViTFeatureExtractor:()=>n,OwlViTImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{post_process_object_detection(...i){return(0,s.post_process_object_detection)(...i)}}class n extends o{}},"./src/models/owlvit/processing_owlvit.js":(e,r,t)=>{t.r(r),t.d(r,{OwlViTProcessor:()=>a});var s=t("./src/base/processing_utils.js"),o=t("./src/models/auto/image_processing_auto.js"),n=t("./src/tokenizers.js");class a extends s.Processor{}J(a,"tokenizer_class",n.AutoTokenizer),J(a,"image_processor_class",o.AutoImageProcessor)},"./src/models/paligemma/processing_paligemma.js":(e,r,t)=>{t.r(r),t.d(r,{PaliGemmaProcessor:()=>l});var s=t("./src/base/processing_utils.js"),o=t("./src/models/auto/image_processing_auto.js"),n=t("./src/tokenizers.js");const a="";function i(c,p,d,u,f){return`${u.repeat(d*f)}${p}${c} -`}class l extends s.Processor{async _call(p,d=null,u={}){d||(console.warn("You are using PaliGemma without a text prefix. It will perform as a picture-captioning model."),d=""),Array.isArray(p)||(p=[p]),Array.isArray(d)||(d=[d]);const f=this.tokenizer.bos_token,_=this.image_processor.config.image_seq_length;let b;d.some(y=>y.includes(a))?b=d.map(y=>{const $=y.replaceAll(a,a.repeat(_)),T=$.lastIndexOf(a),M=T===-1?0:T+a.length;return $.slice(0,M)+f+$.slice(M)+` -`}):(console.warn("You are passing both `text` and `images` to `PaliGemmaProcessor`. The processor expects special image tokens in the text, as many tokens as there are images per each text. It is recommended to add `` tokens in the very beginning of your text. For this call, we will infer how many images each text has and add special tokens."),b=d.map(y=>i(y,f,_,a,p.length)));const k=this.tokenizer(b,u);return{...await this.image_processor(p,u),...k}}}J(l,"tokenizer_class",n.AutoTokenizer),J(l,"image_processor_class",o.AutoImageProcessor),J(l,"uses_processor_config",!1)},"./src/models/parakeet/feature_extraction_parakeet.js":(e,r,t)=>{t.r(r),t.d(r,{ParakeetFeatureExtractor:()=>i});var s=t("./src/base/feature_extraction_utils.js"),o=t("./src/utils/tensor.js"),n=t("./src/utils/audio.js");const a=1e-5;class i extends s.FeatureExtractor{constructor(c){var u;super(c),(u=this.config).mel_filters??(u.mel_filters=(0,n.mel_filter_bank)(Math.floor(1+this.config.n_fft/2),this.config.feature_size,0,this.config.sampling_rate/2,this.config.sampling_rate,"slaney","slaney"));const p=(0,n.window_function)(this.config.win_length,"hann",{periodic:!1});this.window=new Float64Array(this.config.n_fft);const d=Math.floor((this.config.n_fft-this.config.win_length)/2);this.window.set(p,d)}async _extract_fbank_features(c){const p=this.config.preemphasis;c=new Float64Array(c);for(let u=c.length-1;u>=1;--u)c[u]-=p*c[u-1];return await(0,n.spectrogram)(c,this.window,this.window.length,this.config.hop_length,{fft_length:this.config.n_fft,power:2,mel_filters:this.config.mel_filters,log_mel:"log",mel_floor:-1/0,pad_mode:"constant",center:!0,transpose:!0,mel_offset:2**-24})}async _call(c){(0,s.validate_audio_inputs)(c,"ParakeetFeatureExtractor");const p=await this._extract_fbank_features(c),d=Math.floor((c.length+Math.floor(this.config.n_fft/2)*2-this.config.n_fft)/this.config.hop_length),u=p.data;u.fill(0,d*p.dims[1]);const[f,_]=p.dims,b=new Float64Array(_),k=new Float64Array(_);for(let $=0;$1?d-1:1;for(let $=0;$<_;++$){const T=b[$]/d,M=(k[$]-d*T*T)/w,v=1/(Math.sqrt(M)+a);for(let C=0;C{t.r(r),t.d(r,{Phi3VImageProcessor:()=>p});var s=t("./src/base/image_processors_utils.js"),o=t("./src/utils/tensor.js");const n=336,a=[2,3],{ceil:i,floor:l,sqrt:c}=Math;class p extends s.ImageProcessor{constructor(u){super({...u,do_normalize:!0,do_pad:!0,pad_size:"custom",do_convert_rgb:!0,do_resize:!0}),this._num_crops=u.num_crops}calc_num_image_tokens_from_image_size(u,f){const{num_img_tokens:_}=this.config;return l((l(f/n)*l(u/n)+1)*_+1+(l(f/n)+1)*c(_))}get_resize_output_image_size(u,f){const _=this._num_crops,[b,k]=u.size;let w=b/k,y=1;for(;y*Math.ceil(y/w)<=_;)y+=1;y-=1;const $=Math.floor(y*336),T=Math.floor($/w);return[$,T]}pad_image(u,f,_,b={}){const[k,w]=f,y=n*i(k/n),$=n*i(w/n),T=[1,1,1].map((M,x)=>(M-this.image_mean[x])/this.image_std[x]);return super.pad_image(u,f,{width:$,height:y},{center:!0,constant_values:T,...b})}async _call(u,{num_crops:f=null}={}){if(this._num_crops=f??(f=this.config.num_crops),f<4||c(f)%1!==0)throw new Error("num_crops must be a square number >= 4");Array.isArray(u)||(u=[u]);const _=u.length,b=await Promise.all(u.map(v=>this.preprocess(v))),k=b.map(v=>v.original_size),w=b.map(v=>v.reshaped_input_size),y=[];for(const{pixel_values:v}of b){v.unsqueeze_(0);const[C,F]=v.dims.slice(-2),D=await(0,o.interpolate_4d)(v,{size:[n,n],mode:"bicubic"});if(f>0){const K=[],U=c(f),j=l(F/U),se=l(C/U);for(let re=0;rev.map(C=>n*i(C/n))),M=new o.Tensor("int64",T.flat(),[_,2]),x=T.map(([v,C])=>this.calc_num_image_tokens_from_image_size(C,v));return{pixel_values:$,original_sizes:k,reshaped_input_sizes:w,image_sizes:M,num_img_tokens:x}}}},"./src/models/phi3_v/processing_phi3_v.js":(e,r,t)=>{t.r(r),t.d(r,{Phi3VProcessor:()=>l});var s=t("./src/base/processing_utils.js"),o=t("./src/models/auto/image_processing_auto.js"),n=t("./src/tokenizers.js");t("./src/utils/image.js");const a="<|image|>",i=/<\|image_\d+\|>/g;class l extends s.Processor{async _call(p,d=null,{padding:u=!0,truncation:f=!0,num_crops:_=null}={}){Array.isArray(p)||(p=[p]);let b,k;if(d){k=await this.image_processor(d,{num_crops:_});const{num_img_tokens:w}=k,y=p.map((T,M)=>T.split(i).join(a.repeat(w[M])));b=this.tokenizer(y,{padding:u,truncation:f});const $=this.tokenizer.model.convert_tokens_to_ids([a])[0];b.input_ids.map_(T=>T==$?-T:T)}else b=this.tokenizer(p);return{...b,...k}}}J(l,"image_processor_class",o.AutoImageProcessor),J(l,"tokenizer_class",n.AutoTokenizer)},"./src/models/pixtral/image_processing_pixtral.js":(e,r,t)=>{t.r(r),t.d(r,{PixtralImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{get_resize_output_image_size(a,i){const{longest_edge:l}=i;if(l===void 0)throw new Error("size must contain 'longest_edge'");const[c,p]=a.size,d=Math.max(c,p)/l;let u=c,f=p;d>1&&(u=Math.floor(c/d),f=Math.floor(p/d));const{patch_size:_,spatial_merge_size:b}=this.config;if(!b)throw new Error("config must contain 'spatial_merge_size'");const k=_*b,w=Math.floor((u-1)/k)+1,y=Math.floor((f-1)/k)+1;return[w*k,y*k]}}},"./src/models/pixtral/processing_pixtral.js":(e,r,t)=>{t.r(r),t.d(r,{PixtralProcessor:()=>a});var s=t("./src/base/processing_utils.js"),o=t("./src/models/auto/image_processing_auto.js"),n=t("./src/tokenizers.js");class a extends s.Processor{async _call(l,c=null,p={}){const d=await this.image_processor(l,p);if(c){const[f,_]=d.pixel_values.dims.slice(-2),{image_token:b,image_break_token:k,image_end_token:w,patch_size:y,spatial_merge_size:$}=this.config,T=y*$,M=Math.floor(f/T),x=Math.floor(_/T);c=structuredClone(c),Array.isArray(c)||(c=[c]);for(let v=0;v{t.r(r),t.d(r,{Florence2Processor:()=>s.Florence2Processor,Gemma3nProcessor:()=>o.Gemma3nProcessor,GroundingDinoProcessor:()=>n.GroundingDinoProcessor,Idefics3Processor:()=>a.Idefics3Processor,JinaCLIPProcessor:()=>l.JinaCLIPProcessor,LlavaProcessor:()=>c.LlavaProcessor,MgpstrProcessor:()=>p.MgpstrProcessor,MoonshineProcessor:()=>d.MoonshineProcessor,OwlViTProcessor:()=>u.OwlViTProcessor,PaliGemmaProcessor:()=>f.PaliGemmaProcessor,Phi3VProcessor:()=>_.Phi3VProcessor,PixtralProcessor:()=>b.PixtralProcessor,PyAnnoteProcessor:()=>k.PyAnnoteProcessor,Qwen2VLProcessor:()=>w.Qwen2VLProcessor,Sam2Processor:()=>$.Sam2Processor,Sam2VideoProcessor:()=>$.Sam2VideoProcessor,SamProcessor:()=>y.SamProcessor,SmolVLMProcessor:()=>T.SmolVLMProcessor,SpeechT5Processor:()=>M.SpeechT5Processor,UltravoxProcessor:()=>x.UltravoxProcessor,VLChatProcessor:()=>i.VLChatProcessor,VoxtralProcessor:()=>v.VoxtralProcessor,Wav2Vec2Processor:()=>C.Wav2Vec2Processor,Wav2Vec2ProcessorWithLM:()=>F.Wav2Vec2ProcessorWithLM,WhisperProcessor:()=>D.WhisperProcessor});var s=t("./src/models/florence2/processing_florence2.js"),o=t("./src/models/gemma3n/processing_gemma3n.js"),n=t("./src/models/grounding_dino/processing_grounding_dino.js"),a=t("./src/models/idefics3/processing_idefics3.js"),i=t("./src/models/janus/processing_janus.js"),l=t("./src/models/jina_clip/processing_jina_clip.js"),c=t("./src/models/llava/processing_llava.js"),p=t("./src/models/mgp_str/processing_mgp_str.js"),d=t("./src/models/moonshine/processing_moonshine.js"),u=t("./src/models/owlvit/processing_owlvit.js"),f=t("./src/models/paligemma/processing_paligemma.js"),_=t("./src/models/phi3_v/processing_phi3_v.js"),b=t("./src/models/pixtral/processing_pixtral.js"),k=t("./src/models/pyannote/processing_pyannote.js"),w=t("./src/models/qwen2_vl/processing_qwen2_vl.js"),y=t("./src/models/sam/processing_sam.js"),$=t("./src/models/sam2/processing_sam2.js"),T=t("./src/models/smolvlm/processing_smolvlm.js"),M=t("./src/models/speecht5/processing_speecht5.js"),x=t("./src/models/ultravox/processing_ultravox.js"),v=t("./src/models/voxtral/processing_voxtral.js"),C=t("./src/models/wav2vec2/processing_wav2vec2.js"),F=t("./src/models/wav2vec2_with_lm/processing_wav2vec2_with_lm.js"),D=t("./src/models/whisper/processing_whisper.js")},"./src/models/pvt/image_processing_pvt.js":(e,r,t)=>{t.r(r),t.d(r,{PvtImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{}},"./src/models/pyannote/feature_extraction_pyannote.js":(e,r,t)=>{t.r(r),t.d(r,{PyAnnoteFeatureExtractor:()=>a});var s=t("./src/base/feature_extraction_utils.js"),o=t("./src/utils/tensor.js"),n=t("./src/utils/maths.js");class a extends s.FeatureExtractor{async _call(l){(0,s.validate_audio_inputs)(l,"PyAnnoteFeatureExtractor"),l instanceof Float64Array&&(l=new Float32Array(l));const c=[1,1,l.length];return{input_values:new o.Tensor("float32",l,c)}}samples_to_frames(l){return(l-this.config.offset)/this.config.step}post_process_speaker_diarization(l,c){const p=c/this.samples_to_frames(c)/this.config.sampling_rate,d=[];for(const u of l.tolist()){const f=[];let _=-1;for(let b=0;b({id:b,start:k*p,end:w*p,confidence:y/(w-k)})))}return d}}},"./src/models/pyannote/processing_pyannote.js":(e,r,t)=>{t.r(r),t.d(r,{PyAnnoteProcessor:()=>n});var s=t("./src/base/processing_utils.js"),o=t("./src/models/pyannote/feature_extraction_pyannote.js");class n extends s.Processor{async _call(i){return await this.feature_extractor(i)}post_process_speaker_diarization(...i){return this.feature_extractor.post_process_speaker_diarization(...i)}get sampling_rate(){return this.feature_extractor.config.sampling_rate}}J(n,"feature_extractor_class",o.PyAnnoteFeatureExtractor)},"./src/models/qwen2_vl/image_processing_qwen2_vl.js":(e,r,t)=>{t.r(r),t.d(r,{Qwen2VLImageProcessor:()=>n});var s=t("./src/base/image_processors_utils.js"),o=t("./src/utils/tensor.js");class n extends s.ImageProcessor{async _call(i,...l){const{pixel_values:c,original_sizes:p,reshaped_input_sizes:d}=await super._call(i,...l);let u=c;const{temporal_patch_size:f,merge_size:_,patch_size:b}=this.config;u.dims[0]===1&&(u=(0,o.cat)(Array.from({length:f},()=>u),0));const k=u.dims[0]/f,w=u.dims[1],y=Math.floor(u.dims[2]/b),$=Math.floor(u.dims[3]/b),T=u.view(k,f,w,Math.floor(y/_),_,b,Math.floor($/_),_,b).permute(0,3,6,4,7,2,1,5,8).view(k*y*$,w*f*b*b),M=new o.Tensor("int64",[k,y,$],[1,3]);return{pixel_values:T,image_grid_thw:M,original_sizes:p,reshaped_input_sizes:d}}}},"./src/models/qwen2_vl/processing_qwen2_vl.js":(e,r,t)=>{t.r(r),t.d(r,{Qwen2VLProcessor:()=>a});var s=t("./src/base/processing_utils.js"),o=t("./src/models/auto/image_processing_auto.js"),n=t("./src/tokenizers.js");t("./src/utils/image.js");class a extends s.Processor{async _call(l,c=null,...p){Array.isArray(l)||(l=[l]);let d,u;if(c&&(d=await this.image_processor(c),u=d.image_grid_thw),u){let _=this.image_processor.config.merge_size**2,b=0;const k=u.tolist();l=l.map(w=>{for(;w.includes("<|image_pad|>");){const y=Number(k[b++].reduce(($,T)=>$*T,1n));w=w.replace("<|image_pad|>","<|placeholder|>".repeat(Math.floor(y/_)))}return w.replaceAll("<|placeholder|>","<|image_pad|>")})}return{...this.tokenizer(l),...d}}}J(a,"image_processor_class",o.AutoImageProcessor),J(a,"tokenizer_class",n.AutoTokenizer)},"./src/models/rt_detr/image_processing_rt_detr.js":(e,r,t)=>{t.r(r),t.d(r,{RTDetrImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{post_process_object_detection(...a){return(0,s.post_process_object_detection)(...a)}}},"./src/models/sam/image_processing_sam.js":(e,r,t)=>{t.r(r),t.d(r,{SamImageProcessor:()=>a});var s=t("./src/base/image_processors_utils.js"),o=t("./src/utils/core.js"),n=t("./src/utils/tensor.js");class a extends s.ImageProcessor{reshape_input_points(l,c,p,d=!1){l=structuredClone(l);let u=(0,o.calculateDimensions)(l);if(u.length===3)d||(u=[1,...u]),l=[l];else if(u.length!==4)throw Error("The input_points must be a 4D tensor of shape `batch_size`, `point_batch_size`, `nb_points_per_image`, `2`.");for(let f=0;fd!==c.dims[u]))throw Error(`The first ${p.length} dimensions of 'input_points' and 'input_labels' must be the same.`);return new n.Tensor("int64",l.flat(1/0).map(BigInt),p)}async _call(l,{input_points:c=null,input_labels:p=null,input_boxes:d=null}={}){const u=await super._call(l);if(c&&(u.input_points=this.reshape_input_points(c,u.original_sizes,u.reshaped_input_sizes)),p){if(!u.input_points)throw Error("`input_points` must be provided if `input_labels` are provided.");u.input_labels=this.add_input_labels(p,u.input_points)}return d&&(u.input_boxes=this.reshape_input_points(d,u.original_sizes,u.reshaped_input_sizes,!0)),u}async post_process_masks(l,c,p,{mask_threshold:d=0,binarize:u=!0,pad_size:f=null}={}){const _=[];f=f??this.pad_size??this.size;const b=[f.height,f.width];for(let k=0;kd&&(M[x]=1);$=new n.Tensor("bool",M,$.dims)}_.push($)}return _}generate_crop_boxes(l,c,{crop_n_layers:p=0,overlap_ratio:d=512/1500,points_per_crop:u=32,crop_n_points_downscale_factor:f=1}={}){}}},"./src/models/sam/processing_sam.js":(e,r,t)=>{t.r(r),t.d(r,{SamProcessor:()=>n});var s=t("./src/base/processing_utils.js"),o=t("./src/models/auto/image_processing_auto.js");class n extends s.Processor{async _call(...i){return await this.image_processor(...i)}post_process_masks(...i){return this.image_processor.post_process_masks(...i)}reshape_input_points(...i){return this.image_processor.reshape_input_points(...i)}}J(n,"image_processor_class",o.AutoImageProcessor)},"./src/models/sam2/image_processing_sam2.js":(e,r,t)=>{t.r(r),t.d(r,{Sam2ImageProcessor:()=>s.SamImageProcessor});var s=t("./src/models/sam/image_processing_sam.js")},"./src/models/sam2/processing_sam2.js":(e,r,t)=>{t.r(r),t.d(r,{Sam2Processor:()=>o,Sam2VideoProcessor:()=>n});var s=t("./src/models/sam/processing_sam.js");class o extends s.SamProcessor{}class n extends o{}},"./src/models/sam3/image_processing_sam3.js":(e,r,t)=>{t.r(r),t.d(r,{Sam3ImageProcessor:()=>s.Sam2ImageProcessor});var s=t("./src/models/sam2/image_processing_sam2.js")},"./src/models/seamless_m4t/feature_extraction_seamless_m4t.js":(e,r,t)=>{t.r(r),t.d(r,{SeamlessM4TFeatureExtractor:()=>a});var s=t("./src/base/feature_extraction_utils.js"),o=t("./src/utils/tensor.js"),n=t("./src/utils/audio.js");class a extends s.FeatureExtractor{constructor(l){super(l);const c=this.config.sampling_rate,p=(0,n.mel_filter_bank)(257,this.config.num_mel_bins,20,Math.floor(c/2),c,null,"kaldi",!0);this.mel_filters=p,this.window=(0,n.window_function)(400,"povey",{periodic:!1})}async _extract_fbank_features(l,c){return l=l.map(p=>p*32768),(0,n.spectrogram)(l,this.window,400,160,{fft_length:512,power:2,center:!1,preemphasis:.97,mel_filters:this.mel_filters,log_mel:"log",mel_floor:1192092955078125e-22,remove_dc_offset:!0,max_num_frames:c,transpose:!0})}async _call(l,{padding:c=!0,pad_to_multiple_of:p=2,do_normalize_per_mel_bins:d=!0,return_attention_mask:u=!0}={}){(0,s.validate_audio_inputs)(l,"SeamlessM4TFeatureExtractor");let f=await this._extract_fbank_features(l,this.config.max_length);if(d){const[M,x]=f.dims,v=f.data;for(let C=0;C0){const F=new Float32Array(x*(M+C));F.set(v),F.fill(this.config.padding_value,v.length);const D=M+C;f=new o.Tensor(f.type,F,[D,x]),u&&(_=new o.Tensor("int64",new BigInt64Array(D),[1,D]),_.data.fill(1n,0,M))}}const[b,k]=f.dims,w=this.config.stride;if(b%w!==0)throw new Error(`The number of frames (${b}) must be a multiple of the stride (${w}).`);const $=f.view(1,Math.floor(b/w),k*w),T={input_features:$};if(u){const M=$.dims[1],x=new BigInt64Array(M);if(_){const v=_.data;for(let C=1,F=0;C{t.r(r),t.d(r,{SegformerFeatureExtractor:()=>n,SegformerImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{post_process_semantic_segmentation(...i){return(0,s.post_process_semantic_segmentation)(...i)}}class n extends o{}},"./src/models/siglip/image_processing_siglip.js":(e,r,t)=>{t.r(r),t.d(r,{SiglipImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{}},"./src/models/smolvlm/image_processing_smolvlm.js":(e,r,t)=>{t.r(r),t.d(r,{SmolVLMImageProcessor:()=>s.Idefics3ImageProcessor});var s=t("./src/models/idefics3/image_processing_idefics3.js")},"./src/models/smolvlm/processing_smolvlm.js":(e,r,t)=>{t.r(r),t.d(r,{SmolVLMProcessor:()=>s.Idefics3Processor});var s=t("./src/models/idefics3/processing_idefics3.js")},"./src/models/snac/feature_extraction_snac.js":(e,r,t)=>{t.r(r),t.d(r,{SnacFeatureExtractor:()=>o});var s=t("./src/models/dac/feature_extraction_dac.js");class o extends s.DacFeatureExtractor{}},"./src/models/speecht5/feature_extraction_speecht5.js":(e,r,t)=>{t.r(r),t.d(r,{SpeechT5FeatureExtractor:()=>o});var s=t("./src/base/feature_extraction_utils.js");class o extends s.FeatureExtractor{}},"./src/models/speecht5/processing_speecht5.js":(e,r,t)=>{t.r(r),t.d(r,{SpeechT5Processor:()=>a});var s=t("./src/base/processing_utils.js"),o=t("./src/tokenizers.js"),n=t("./src/models/auto/feature_extraction_auto.js");class a extends s.Processor{async _call(l){return await this.feature_extractor(l)}}J(a,"tokenizer_class",o.AutoTokenizer),J(a,"feature_extractor_class",n.AutoFeatureExtractor)},"./src/models/swin2sr/image_processing_swin2sr.js":(e,r,t)=>{t.r(r),t.d(r,{Swin2SRImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{pad_image(a,i,l,c={}){const[p,d,u]=i;return super.pad_image(a,i,{width:d+(l-d%l)%l,height:p+(l-p%l)%l},{mode:"symmetric",center:!1,constant_values:-1,...c})}}},"./src/models/ultravox/processing_ultravox.js":(e,r,t)=>{t.r(r),t.d(r,{UltravoxProcessor:()=>a});var s=t("./src/models/auto/feature_extraction_auto.js"),o=t("./src/tokenizers.js"),n=t("./src/base/processing_utils.js");class a extends n.Processor{async _call(l,c=null,p={}){if(Array.isArray(l))throw new Error("Batched inputs are not supported yet.");let d={};if(c){const f=c.length,{input_features:_}=await this.feature_extractor(c,{...p,max_length:f}),b=Math.round(f/this.config.encoder_ds_factor+1e-4),k=1+Math.ceil(b/this.config.stack_factor);d.audio_token_len=[k],d.audio_values=_;const w=this.config.audio_placeholder;if(!l.includes(w))throw new Error(`The input text does not contain the image token ${w}.`);l=l.replaceAll(w,w.repeat(k))}return{...this.tokenizer(l,{add_special_tokens:!1,...p}),...d}}}J(a,"tokenizer_class",o.AutoTokenizer),J(a,"feature_extractor_class",s.AutoFeatureExtractor),J(a,"uses_processor_config",!0)},"./src/models/vit/image_processing_vit.js":(e,r,t)=>{t.r(r),t.d(r,{ViTFeatureExtractor:()=>n,ViTImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{}class n extends o{}},"./src/models/vitmatte/image_processing_vitmatte.js":(e,r,t)=>{t.r(r),t.d(r,{VitMatteImageProcessor:()=>n});var s=t("./src/base/image_processors_utils.js"),o=t("./src/utils/tensor.js");class n extends s.ImageProcessor{async _call(i,l){Array.isArray(i)||(i=[i]),Array.isArray(l)||(l=[l]);const c=await Promise.all(i.map(u=>this.preprocess(u))),p=await Promise.all(l.map(u=>this.preprocess(u,{do_normalize:!1,do_convert_rgb:!1,do_convert_grayscale:!0})));return{pixel_values:(0,o.stack)(c.map((u,f)=>(0,o.cat)([u.pixel_values,p[f].pixel_values],0)),0),original_sizes:c.map(u=>u.original_size),reshaped_input_sizes:c.map(u=>u.reshaped_input_size)}}}},"./src/models/vitpose/image_processing_vitpose.js":(e,r,t)=>{t.r(r),t.d(r,{VitPoseImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{post_process_pose_estimation(a,i,{threshold:l=null}={}){const c=a.tolist(),[p,d,u,f]=a.dims,_=[];for(let b=0;b{t.r(r),t.d(r,{VoxtralProcessor:()=>d});var s=t("./src/models/auto/feature_extraction_auto.js"),o=t("./src/tokenizers.js"),n=t("./src/base/processing_utils.js"),a=t("./src/utils/tensor.js");const i="[AUDIO]",l="[BEGIN_AUDIO]",c=375;function p(u,f){const _=[];for(let b=0;bp(D,T)),x=M.map(D=>D.length),v=M.flat(),C=(await Promise.all(v.map(D=>this.feature_extractor(D,b)))).map(D=>D.input_features);k.audio_values=C.length>1?(0,a.cat)(C,0):C[0];let F=y[0];for(let D=0;D{t.r(r),t.d(r,{Wav2Vec2FeatureExtractor:()=>n});var s=t("./src/base/feature_extraction_utils.js"),o=t("./src/utils/tensor.js");class n extends s.FeatureExtractor{_zero_mean_unit_var_norm(i){const c=i.reduce((d,u)=>d+u,0)/i.length,p=i.reduce((d,u)=>d+(u-c)**2,0)/i.length;return i.map(d=>(d-c)/Math.sqrt(p+1e-7))}async _call(i){(0,s.validate_audio_inputs)(i,"Wav2Vec2FeatureExtractor"),i instanceof Float64Array&&(i=new Float32Array(i));let l=i;this.config.do_normalize&&(l=this._zero_mean_unit_var_norm(l));const c=[1,l.length];return{input_values:new o.Tensor("float32",l,c),attention_mask:new o.Tensor("int64",new BigInt64Array(l.length).fill(1n),c)}}}},"./src/models/wav2vec2/processing_wav2vec2.js":(e,r,t)=>{t.r(r),t.d(r,{Wav2Vec2Processor:()=>a});var s=t("./src/tokenizers.js"),o=t("./src/models/auto/feature_extraction_auto.js"),n=t("./src/base/processing_utils.js");class a extends n.Processor{async _call(l){return await this.feature_extractor(l)}}J(a,"tokenizer_class",s.AutoTokenizer),J(a,"feature_extractor_class",o.AutoFeatureExtractor)},"./src/models/wav2vec2_with_lm/processing_wav2vec2_with_lm.js":(e,r,t)=>{t.r(r),t.d(r,{Wav2Vec2ProcessorWithLM:()=>a});var s=t("./src/tokenizers.js"),o=t("./src/models/auto/feature_extraction_auto.js"),n=t("./src/base/processing_utils.js");class a extends n.Processor{async _call(l){return await this.feature_extractor(l)}}J(a,"tokenizer_class",s.AutoTokenizer),J(a,"feature_extractor_class",o.AutoFeatureExtractor)},"./src/models/wespeaker/feature_extraction_wespeaker.js":(e,r,t)=>{t.r(r),t.d(r,{WeSpeakerFeatureExtractor:()=>n});var s=t("./src/base/feature_extraction_utils.js");t("./src/utils/tensor.js");var o=t("./src/utils/audio.js");class n extends s.FeatureExtractor{constructor(i){super(i);const l=this.config.sampling_rate,c=(0,o.mel_filter_bank)(257,this.config.num_mel_bins,20,Math.floor(l/2),l,null,"kaldi",!0);this.mel_filters=c,this.window=(0,o.window_function)(400,"hamming",{periodic:!1}),this.min_num_frames=this.config.min_num_frames}async _extract_fbank_features(i){return i=i.map(l=>l*32768),(0,o.spectrogram)(i,this.window,400,160,{fft_length:512,power:2,center:!1,preemphasis:.97,mel_filters:this.mel_filters,log_mel:"log",mel_floor:1192092955078125e-22,remove_dc_offset:!0,transpose:!0,min_num_frames:this.min_num_frames})}async _call(i){(0,s.validate_audio_inputs)(i,"WeSpeakerFeatureExtractor");const l=(await this._extract_fbank_features(i)).unsqueeze_(0);if(this.config.fbank_centering_span===null){const c=l.mean(1).data,p=l.data,[d,u,f]=l.dims;for(let _=0;_{t.r(r),t.d(r,{WHISPER_LANGUAGE_MAPPING:()=>o,WHISPER_TO_LANGUAGE_CODE_MAPPING:()=>n,whisper_language_to_code:()=>a});const s=[["en","english"],["zh","chinese"],["de","german"],["es","spanish"],["ru","russian"],["ko","korean"],["fr","french"],["ja","japanese"],["pt","portuguese"],["tr","turkish"],["pl","polish"],["ca","catalan"],["nl","dutch"],["ar","arabic"],["sv","swedish"],["it","italian"],["id","indonesian"],["hi","hindi"],["fi","finnish"],["vi","vietnamese"],["he","hebrew"],["uk","ukrainian"],["el","greek"],["ms","malay"],["cs","czech"],["ro","romanian"],["da","danish"],["hu","hungarian"],["ta","tamil"],["no","norwegian"],["th","thai"],["ur","urdu"],["hr","croatian"],["bg","bulgarian"],["lt","lithuanian"],["la","latin"],["mi","maori"],["ml","malayalam"],["cy","welsh"],["sk","slovak"],["te","telugu"],["fa","persian"],["lv","latvian"],["bn","bengali"],["sr","serbian"],["az","azerbaijani"],["sl","slovenian"],["kn","kannada"],["et","estonian"],["mk","macedonian"],["br","breton"],["eu","basque"],["is","icelandic"],["hy","armenian"],["ne","nepali"],["mn","mongolian"],["bs","bosnian"],["kk","kazakh"],["sq","albanian"],["sw","swahili"],["gl","galician"],["mr","marathi"],["pa","punjabi"],["si","sinhala"],["km","khmer"],["sn","shona"],["yo","yoruba"],["so","somali"],["af","afrikaans"],["oc","occitan"],["ka","georgian"],["be","belarusian"],["tg","tajik"],["sd","sindhi"],["gu","gujarati"],["am","amharic"],["yi","yiddish"],["lo","lao"],["uz","uzbek"],["fo","faroese"],["ht","haitian creole"],["ps","pashto"],["tk","turkmen"],["nn","nynorsk"],["mt","maltese"],["sa","sanskrit"],["lb","luxembourgish"],["my","myanmar"],["bo","tibetan"],["tl","tagalog"],["mg","malagasy"],["as","assamese"],["tt","tatar"],["haw","hawaiian"],["ln","lingala"],["ha","hausa"],["ba","bashkir"],["jw","javanese"],["su","sundanese"]],o=new Map(s),n=new Map([...s.map(([i,l])=>[l,i]),["burmese","my"],["valencian","ca"],["flemish","nl"],["haitian","ht"],["letzeburgesch","lb"],["pushto","ps"],["panjabi","pa"],["moldavian","ro"],["moldovan","ro"],["sinhalese","si"],["castilian","es"]]);function a(i){i=i.toLowerCase();let l=n.get(i);if(l===void 0){const c=i.match(/^<\|([a-z]{2})\|>$/);if(c&&(i=c[1]),o.has(i))l=i;else{const d=i.length===2?o.keys():o.values();throw new Error(`Language "${i}" is not supported. Must be one of: ${JSON.stringify(Array.from(d))}`)}}return l}},"./src/models/whisper/feature_extraction_whisper.js":(e,r,t)=>{t.r(r),t.d(r,{WhisperFeatureExtractor:()=>a});var s=t("./src/base/feature_extraction_utils.js");t("./src/utils/tensor.js");var o=t("./src/utils/audio.js"),n=t("./src/utils/maths.js");class a extends s.FeatureExtractor{constructor(l){var c;super(l),(c=this.config).mel_filters??(c.mel_filters=(0,o.mel_filter_bank)(Math.floor(1+this.config.n_fft/2),this.config.feature_size,0,8e3,this.config.sampling_rate,"slaney","slaney")),this.window=(0,o.window_function)(this.config.n_fft,"hann")}async _extract_fbank_features(l){const c=await(0,o.spectrogram)(l,this.window,this.config.n_fft,this.config.hop_length,{power:2,mel_filters:this.config.mel_filters,log_mel:"log10",max_num_frames:Math.min(Math.floor(l.length/this.config.hop_length),this.config.nb_max_frames)}),p=c.data,d=(0,n.max)(p)[0];for(let u=0;ud?(l.length>this.config.n_samples&&console.warn("Attempting to extract features for audio longer than 30 seconds. If using a pipeline to extract transcript from a long audio clip, remember to specify `chunk_length_s` and/or `stride_length_s`."),p=l.slice(0,d)):(p=new Float32Array(d),p.set(l)),{input_features:(await this._extract_fbank_features(p)).unsqueeze_(0)}}}},"./src/models/whisper/generation_whisper.js":(e,r,t)=>{t.r(r),t.d(r,{WhisperGenerationConfig:()=>o});var s=t("./src/generation/configuration_utils.js");class o extends s.GenerationConfig{constructor(){super(...arguments);J(this,"return_timestamps",null);J(this,"return_token_timestamps",null);J(this,"num_frames",null);J(this,"alignment_heads",null);J(this,"task",null);J(this,"language",null);J(this,"no_timestamps_token_id",null);J(this,"prompt_ids",null);J(this,"is_multilingual",null);J(this,"lang_to_id",null);J(this,"task_to_id",null);J(this,"max_initial_timestamp_index",1)}}},"./src/models/whisper/processing_whisper.js":(e,r,t)=>{t.r(r),t.d(r,{WhisperProcessor:()=>a});var s=t("./src/models/auto/feature_extraction_auto.js"),o=t("./src/tokenizers.js"),n=t("./src/base/processing_utils.js");class a extends n.Processor{async _call(l){return await this.feature_extractor(l)}}J(a,"tokenizer_class",o.AutoTokenizer),J(a,"feature_extractor_class",s.AutoFeatureExtractor)},"./src/models/yolos/image_processing_yolos.js":(e,r,t)=>{t.r(r),t.d(r,{YolosFeatureExtractor:()=>n,YolosImageProcessor:()=>o});var s=t("./src/base/image_processors_utils.js");class o extends s.ImageProcessor{post_process_object_detection(...i){return(0,s.post_process_object_detection)(...i)}}class n extends o{}},"./src/ops/registry.js":(e,r,t)=>{t.r(r),t.d(r,{TensorOpRegistry:()=>a});var s=t("./src/backends/onnx.js"),o=t("./src/utils/tensor.js");const n=async(i,l,c)=>{const p=await(0,s.createInferenceSession)(new Uint8Array(i),l);return async d=>{const u=(0,s.isONNXProxy)(),f=Object.fromEntries(Object.entries(d).map(([b,k])=>[b,(u?k.clone():k).ort_tensor])),_=await(0,s.runInferenceSession)(p,f);return Array.isArray(c)?c.map(b=>new o.Tensor(_[b])):new o.Tensor(_[c])}};class a{static get nearest_interpolate_4d(){return this._nearest_interpolate_4d||(this._nearest_interpolate_4d=n([8,10,18,0,58,129,1,10,41,10,1,120,10,0,10,0,10,1,115,18,1,121,34,6,82,101,115,105,122,101,42,18,10,4,109,111,100,101,34,7,110,101,97,114,101,115,116,160,1,3,18,1,114,90,31,10,1,120,18,26,10,24,8,1,18,20,10,3,18,1,98,10,3,18,1,99,10,3,18,1,104,10,3,18,1,119,90,15,10,1,115,18,10,10,8,8,7,18,4,10,2,8,4,98,31,10,1,121,18,26,10,24,8,1,18,20,10,3,18,1,98,10,3,18,1,99,10,3,18,1,104,10,3,18,1,119,66,2,16,21],this.session_options,"y")),this._nearest_interpolate_4d}static get bilinear_interpolate_4d(){return this._bilinear_interpolate_4d||(this._bilinear_interpolate_4d=n([8,9,18,0,58,128,1,10,40,10,1,120,10,0,10,0,10,1,115,18,1,121,34,6,82,101,115,105,122,101,42,17,10,4,109,111,100,101,34,6,108,105,110,101,97,114,160,1,3,18,1,114,90,31,10,1,120,18,26,10,24,8,1,18,20,10,3,18,1,98,10,3,18,1,99,10,3,18,1,104,10,3,18,1,119,90,15,10,1,115,18,10,10,8,8,7,18,4,10,2,8,4,98,31,10,1,121,18,26,10,24,8,1,18,20,10,3,18,1,98,10,3,18,1,99,10,3,18,1,104,10,3,18,1,119,66,2,16,20],this.session_options,"y")),this._bilinear_interpolate_4d}static get bicubic_interpolate_4d(){return this._bicubic_interpolate_4d||(this._bicubic_interpolate_4d=n([8,9,18,0,58,127,10,39,10,1,120,10,0,10,0,10,1,115,18,1,121,34,6,82,101,115,105,122,101,42,16,10,4,109,111,100,101,34,5,99,117,98,105,99,160,1,3,18,1,114,90,31,10,1,120,18,26,10,24,8,1,18,20,10,3,18,1,98,10,3,18,1,99,10,3,18,1,104,10,3,18,1,119,90,15,10,1,115,18,10,10,8,8,7,18,4,10,2,8,4,98,31,10,1,121,18,26,10,24,8,1,18,20,10,3,18,1,98,10,3,18,1,99,10,3,18,1,104,10,3,18,1,119,66,2,16,20],this.session_options,"y")),this._bicubic_interpolate_4d}static get matmul(){return this._matmul||(this._matmul=n([8,9,18,0,58,55,10,17,10,1,97,10,1,98,18,1,99,34,6,77,97,116,77,117,108,18,1,114,90,9,10,1,97,18,4,10,2,8,1,90,9,10,1,98,18,4,10,2,8,1,98,9,10,1,99,18,4,10,2,8,1,66,2,16,20],this.session_options,"c")),this._matmul}static get stft(){return this._stft||(this._stft=n([8,7,18,0,58,148,1,10,38,10,1,115,10,1,106,10,1,119,10,1,108,18,1,111,34,4,83,84,70,84,42,15,10,8,111,110,101,115,105,100,101,100,24,1,160,1,2,18,1,115,90,26,10,1,115,18,21,10,19,8,1,18,15,10,3,18,1,98,10,3,18,1,115,10,3,18,1,99,90,11,10,1,106,18,6,10,4,8,7,18,0,90,16,10,1,119,18,11,10,9,8,1,18,5,10,3,18,1,119,90,11,10,1,108,18,6,10,4,8,7,18,0,98,31,10,1,111,18,26,10,24,8,1,18,20,10,3,18,1,98,10,3,18,1,102,10,3,18,1,100,10,3,18,1,99,66,2,16,17],this.session_options,"o")),this._stft}static get rfft(){return this._rfft||(this._rfft=n([8,9,18,0,58,97,10,33,10,1,120,10,0,10,1,97,18,1,121,34,3,68,70,84,42,15,10,8,111,110,101,115,105,100,101,100,24,1,160,1,2,18,1,100,90,21,10,1,120,18,16,10,14,8,1,18,10,10,3,18,1,115,10,3,18,1,99,90,11,10,1,97,18,6,10,4,8,7,18,0,98,21,10,1,121,18,16,10,14,8,1,18,10,10,3,18,1,115,10,3,18,1,99,66,2,16,20],this.session_options,"y")),this._rfft}static get top_k(){return this._top_k||(this._top_k=n([8,10,18,0,58,73,10,18,10,1,120,10,1,107,18,1,118,18,1,105,34,4,84,111,112,75,18,1,116,90,9,10,1,120,18,4,10,2,8,1,90,15,10,1,107,18,10,10,8,8,7,18,4,10,2,8,1,98,9,10,1,118,18,4,10,2,8,1,98,9,10,1,105,18,4,10,2,8,7,66,2,16,21],this.session_options,["v","i"])),this._top_k}static get slice(){return this._slice||(this._slice=n([8,7,18,0,58,96,10,25,10,1,120,10,1,115,10,1,101,10,1,97,10,1,116,18,1,121,34,5,83,108,105,99,101,18,1,114,90,9,10,1,120,18,4,10,2,8,1,90,9,10,1,115,18,4,10,2,8,7,90,9,10,1,101,18,4,10,2,8,7,90,9,10,1,97,18,4,10,2,8,7,90,9,10,1,116,18,4,10,2,8,7,98,9,10,1,121,18,4,10,2,8,1,66,2,16,13],this.session_options,"y")),this._slice}}J(a,"session_options",{})},"./src/pipelines.js":(e,r,t)=>{t.r(r),t.d(r,{AudioClassificationPipeline:()=>U,AutomaticSpeechRecognitionPipeline:()=>se,BackgroundRemovalPipeline:()=>ae,DepthEstimationPipeline:()=>le,DocumentQuestionAnsweringPipeline:()=>G,FeatureExtractionPipeline:()=>D,FillMaskPipeline:()=>$,ImageClassificationPipeline:()=>re,ImageFeatureExtractionPipeline:()=>K,ImageSegmentationPipeline:()=>Z,ImageToImagePipeline:()=>Q,ImageToTextPipeline:()=>q,ObjectDetectionPipeline:()=>pe,Pipeline:()=>b,QuestionAnsweringPipeline:()=>y,SummarizationPipeline:()=>M,Text2TextGenerationPipeline:()=>T,TextClassificationPipeline:()=>k,TextGenerationPipeline:()=>C,TextToAudioPipeline:()=>B,TokenClassificationPipeline:()=>w,TranslationPipeline:()=>x,ZeroShotAudioClassificationPipeline:()=>j,ZeroShotClassificationPipeline:()=>F,ZeroShotImageClassificationPipeline:()=>_e,ZeroShotObjectDetectionPipeline:()=>oe,pipeline:()=>De});var s=t("./src/tokenizers.js"),o=t("./src/models.js"),n=t("./src/models/auto/processing_auto.js");t("./src/base/processing_utils.js");var a=t("./src/utils/generic.js"),i=t("./src/utils/core.js"),l=t("./src/utils/maths.js"),c=t("./src/utils/audio.js"),p=t("./src/utils/tensor.js"),d=t("./src/utils/image.js");async function u(Ae){return Array.isArray(Ae)||(Ae=[Ae]),await Promise.all(Ae.map(te=>d.RawImage.read(te)))}async function f(Ae,te){return Array.isArray(Ae)||(Ae=[Ae]),await Promise.all(Ae.map(O=>typeof O=="string"||O instanceof URL?(0,c.read_audio)(O,te):O instanceof Float64Array?new Float32Array(O):O))}function _(Ae,te){te&&(Ae=Ae.map(Ce=>Ce|0));const[O,me,xe,be]=Ae;return{xmin:O,ymin:me,xmax:xe,ymax:be}}class b extends a.Callable{constructor({task:te,model:O,tokenizer:me=null,processor:xe=null}){super(),this.task=te,this.model=O,this.tokenizer=me,this.processor=xe}async dispose(){await this.model.dispose()}}class k extends b{constructor(te){super(te)}async _call(te,{top_k:O=1}={}){const me=this.tokenizer(te,{padding:!0,truncation:!0}),xe=await this.model(me),be=this.model.config.problem_type==="multi_label_classification"?Me=>Me.sigmoid():Me=>new p.Tensor("float32",(0,l.softmax)(Me.data),Me.dims),Ce=this.model.config.id2label,$e=[];for(const Me of xe.logits){const Le=be(Me),we=await(0,p.topk)(Le,O),ke=we[0].tolist(),Fe=we[1].tolist().map((Ze,We)=>({label:Ce?Ce[Ze]:`LABEL_${Ze}`,score:ke[We]}));O===1?$e.push(...Fe):$e.push(Fe)}return Array.isArray(te)||O===1?$e:$e[0]}}class w extends b{constructor(te){super(te)}async _call(te,{ignore_labels:O=["O"]}={}){const me=Array.isArray(te),xe=this.tokenizer(me?te:[te],{padding:!0,truncation:!0}),Ce=(await this.model(xe)).logits,$e=this.model.config.id2label,Me=[];for(let Le=0;Leze==this.tokenizer.sep_token_id);Me[ke].map((ze,pt)=>ze==1&&(pt===0||pt>Fe&&Le.findIndex(ft=>ft==He[pt])===-1));const Ze=be[ke].tolist(),We=Ce[ke].tolist();for(let ze=1;zept==He[ze])!==-1)&&(Ze[ze]=-1/0,We[ze]=-1/0);const yt=(0,l.softmax)(Ze).map((ze,pt)=>[ze,pt]),Qe=(0,l.softmax)(We).map((ze,pt)=>[ze,pt]);yt[0][0]=0,Qe[0][0]=0;const Oe=(0,i.product)(yt,Qe).filter(ze=>ze[0][1]<=ze[1][1]).map(ze=>[ze[0][1],ze[1][1],ze[0][0]*ze[1][0]]).sort((ze,pt)=>pt[2]-ze[2]);for(let ze=0;zeZe==this.tokenizer.mask_token_id);if(Le===-1)throw Error(`Mask token (${this.tokenizer.mask_token}) not found in text.`);const we=xe[$e][Le],ke=await(0,p.topk)(new p.Tensor("float32",(0,l.softmax)(we.data),we.dims),O),He=ke[0].tolist(),Fe=ke[1].tolist();be.push(Fe.map((Ze,We)=>{const yt=Me.slice();return yt[Le]=Ze,{score:He[We],token:Number(Ze),token_str:this.tokenizer.decode([Ze]),sequence:this.tokenizer.decode(yt,{skip_special_tokens:!0})}}))}return Array.isArray(te)?be:be[0]}}class T extends b{constructor(O){super(O);J(this,"_key","generated_text")}async _call(O,me={}){Array.isArray(O)||(O=[O]),this.model.config.prefix&&(O=O.map(Le=>this.model.config.prefix+Le));const xe=this.model.config.task_specific_params;xe&&xe[this.task]&&xe[this.task].prefix&&(O=O.map(Le=>xe[this.task].prefix+Le));const be=this.tokenizer,Ce={padding:!0,truncation:!0};let $e;this instanceof x&&"_build_translation_inputs"in be?$e=be._build_translation_inputs(O,Ce,me):$e=be(O,Ce);const Me=await this.model.generate({...$e,...me});return be.batch_decode(Me,{skip_special_tokens:!0}).map(Le=>({[this._key]:Le}))}}class M extends T{constructor(O){super(O);J(this,"_key","summary_text")}}class x extends T{constructor(O){super(O);J(this,"_key","translation_text")}}function v(Ae){return Array.isArray(Ae)&&Ae.every(te=>"role"in te&&"content"in te)}class C extends b{constructor(te){super(te)}async _call(te,O={}){let me=!1,xe=!1,be=O.add_special_tokens??(this.tokenizer.add_bos_token||this.tokenizer.add_eos_token)??!1,Ce;if(typeof te=="string")Ce=te=[te];else if(Array.isArray(te)&&te.every(Fe=>typeof Fe=="string"))me=!0,Ce=te;else{if(v(te))te=[te];else if(Array.isArray(te)&&te.every(v))me=!0;else throw new Error("Input must be a string, an array of strings, a Chat, or an array of Chats");xe=!0,Ce=te.map(Fe=>this.tokenizer.apply_chat_template(Fe,{tokenize:!1,add_generation_prompt:!0})),be=!1}const $e=xe?!1:O.return_full_text??!0;this.tokenizer.padding_side="left";const Me=this.tokenizer(Ce,{add_special_tokens:be,padding:!0,truncation:!0}),Le=await this.model.generate({...Me,...O}),we=this.tokenizer.batch_decode(Le,{skip_special_tokens:!0});let ke;!$e&&Me.input_ids.dims.at(-1)>0&&(ke=this.tokenizer.batch_decode(Me.input_ids,{skip_special_tokens:!0}).map(Fe=>Fe.length));const He=Array.from({length:te.length},Fe=>[]);for(let Fe=0;Fe[O.toLowerCase(),me])),this.entailment_id=this.label2id.entailment,this.entailment_id===void 0&&(console.warn("Could not find 'entailment' in label2id mapping. Using 2 as entailment_id."),this.entailment_id=2),this.contradiction_id=this.label2id.contradiction??this.label2id.not_entailment,this.contradiction_id===void 0&&(console.warn("Could not find 'contradiction' in label2id mapping. Using 0 as contradiction_id."),this.contradiction_id=0)}async _call(te,O,{hypothesis_template:me="This example is {}.",multi_label:xe=!1}={}){const be=Array.isArray(te);be||(te=[te]),Array.isArray(O)||(O=[O]);const Ce=O.map(Le=>me.replace("{}",Le)),$e=xe||O.length===1,Me=[];for(const Le of te){const we=[];for(const Fe of Ce){const Ze=this.tokenizer(Le,{text_pair:Fe,padding:!0,truncation:!0}),We=await this.model(Ze);$e?we.push([We.logits.data[this.contradiction_id],We.logits.data[this.entailment_id]]):we.push(We.logits.data[this.entailment_id])}const He=($e?we.map(Fe=>(0,l.softmax)(Fe)[1]):(0,l.softmax)(we)).map((Fe,Ze)=>[Fe,Ze]).sort((Fe,Ze)=>Ze[0]-Fe[0]);Me.push({sequence:Le,labels:He.map(Fe=>O[Fe[1]]),scores:He.map(Fe=>Fe[0])})}return be?Me:Me[0]}}class D extends b{constructor(te){super(te)}async _call(te,{pooling:O="none",normalize:me=!1,quantize:xe=!1,precision:be="binary"}={}){const Ce=this.tokenizer(te,{padding:!0,truncation:!0}),$e=await this.model(Ce);let Me=$e.last_hidden_state??$e.logits??$e.token_embeddings;switch(O){case"none":break;case"mean":Me=(0,p.mean_pooling)(Me,Ce.attention_mask);break;case"first_token":case"cls":Me=Me.slice(null,0);break;case"last_token":case"eos":Me=Me.slice(null,-1);break;default:throw Error(`Pooling method '${O}' not supported.`)}return me&&(Me=Me.normalize(2,-1)),xe&&(Me=(0,p.quantize_embeddings)(Me,be)),Me}}class K extends b{constructor(te){super(te)}async _call(te,{pool:O=null}={}){const me=await u(te),{pixel_values:xe}=await this.processor(me),be=await this.model({pixel_values:xe});let Ce;if(O){if(!("pooler_output"in be))throw Error("No pooled output was returned. Make sure the model has a 'pooler' layer when using the 'pool' option.");Ce=be.pooler_output}else Ce=be.last_hidden_state??be.logits??be.image_embeds;return Ce}}class U extends b{constructor(te){super(te)}async _call(te,{top_k:O=5}={}){const me=this.processor.feature_extractor.config.sampling_rate,xe=await f(te,me),be=this.model.config.id2label,Ce=[];for(const $e of xe){const Me=await this.processor($e),we=(await this.model(Me)).logits[0],ke=await(0,p.topk)(new p.Tensor("float32",(0,l.softmax)(we.data),we.dims),O),He=ke[0].tolist(),Ze=ke[1].tolist().map((We,yt)=>({label:be?be[We]:`LABEL_${We}`,score:He[yt]}));Ce.push(Ze)}return Array.isArray(te)?Ce:Ce[0]}}class j extends b{constructor(te){super(te)}async _call(te,O,{hypothesis_template:me="This is a sound of {}."}={}){const xe=!Array.isArray(te);xe&&(te=[te]);const be=O.map(we=>me.replace("{}",we)),Ce=this.tokenizer(be,{padding:!0,truncation:!0}),$e=this.processor.feature_extractor.config.sampling_rate,Me=await f(te,$e),Le=[];for(const we of Me){const ke=await this.processor(we),He=await this.model({...Ce,...ke}),Fe=(0,l.softmax)(He.logits_per_audio.data);Le.push([...Fe].map((Ze,We)=>({score:Ze,label:O[We]})))}return xe?Le[0]:Le}}class se extends b{constructor(te){super(te)}async _call(te,O={}){switch(this.model.config.model_type){case"whisper":case"lite-whisper":return this._call_whisper(te,O);case"wav2vec2":case"wav2vec2-bert":case"unispeech":case"unispeech-sat":case"hubert":case"parakeet_ctc":return this._call_wav2vec2(te,O);case"moonshine":return this._call_moonshine(te,O);default:throw new Error(`AutomaticSpeechRecognitionPipeline does not support model type '${this.model.config.model_type}'.`)}}async _call_wav2vec2(te,O){O.language&&console.warn('`language` parameter is not yet supported for `wav2vec2` models, defaulting to "English".'),O.task&&console.warn('`task` parameter is not yet supported for `wav2vec2` models, defaulting to "transcribe".');const me=!Array.isArray(te);me&&(te=[te]);const xe=this.processor.feature_extractor.config.sampling_rate,be=await f(te,xe),Ce=[];for(const $e of be){const Me=await this.processor($e),we=(await this.model(Me)).logits[0],ke=[];for(const Fe of we)ke.push((0,l.max)(Fe.data)[1]);const He=this.tokenizer.decode(ke,{skip_special_tokens:!0}).trim();Ce.push({text:He})}return me?Ce[0]:Ce}async _call_whisper(te,O){const me=O.return_timestamps??!1,xe=O.chunk_length_s??0,be=O.force_full_sequences??!1;let Ce=O.stride_length_s??null;const $e={...O};me==="word"&&($e.return_token_timestamps=!0,$e.return_timestamps=!1);const Me=!Array.isArray(te);Me&&(te=[te]);const Le=this.processor.feature_extractor.config.chunk_length/this.model.config.max_source_positions,we=this.processor.feature_extractor.config.hop_length,ke=this.processor.feature_extractor.config.sampling_rate,He=await f(te,ke),Fe=[];for(const Ze of He){let We=[];if(xe>0){if(Ce===null)Ce=xe/6;else if(xe<=Ce)throw Error("`chunk_length_s` must be larger than `stride_length_s`.");const Oe=ke*xe,ze=ke*Ce,pt=Oe-2*ze;let ft=0;for(;;){const Lt=ft+Oe,kt=Ze.subarray(ft,Lt),Mr=await this.processor(kt),fr=ft===0,Ut=Lt>=Ze.length;if(We.push({stride:[kt.length,fr?0:ze,Ut?0:ze],input_features:Mr.input_features,is_last:Ut}),Ut)break;ft+=pt}}else We=[{stride:[Ze.length,0,0],input_features:(await this.processor(Ze)).input_features,is_last:!0}];for(const Oe of We){$e.num_frames=Math.floor(Oe.stride[0]/we);const ze=await this.model.generate({inputs:Oe.input_features,...$e});me==="word"?(Oe.tokens=ze.sequences.tolist()[0],Oe.token_timestamps=ze.token_timestamps.tolist()[0].map(pt=>(0,l.round)(pt,2))):Oe.tokens=ze[0].tolist(),Oe.stride=Oe.stride.map(pt=>pt/ke)}const[yt,Qe]=this.tokenizer._decode_asr(We,{time_precision:Le,return_timestamps:me,force_full_sequences:be});Fe.push({text:yt,...Qe})}return Me?Fe[0]:Fe}async _call_moonshine(te,O){const me=!Array.isArray(te);me&&(te=[te]);const xe=this.processor.feature_extractor.config.sampling_rate,be=await f(te,xe),Ce=[];for(const $e of be){const Me=await this.processor($e),Le=Math.floor($e.length/xe)*6,we=await this.model.generate({max_new_tokens:Le,...O,...Me}),ke=this.processor.batch_decode(we,{skip_special_tokens:!0})[0];Ce.push({text:ke})}return me?Ce[0]:Ce}}class q extends b{constructor(te){super(te)}async _call(te,O={}){const me=Array.isArray(te),xe=await u(te),{pixel_values:be}=await this.processor(xe),Ce=[];for(const $e of be){$e.dims=[1,...$e.dims];const Me=await this.model.generate({inputs:$e,...O}),Le=this.tokenizer.batch_decode(Me,{skip_special_tokens:!0}).map(we=>({generated_text:we.trim()}));Ce.push(Le)}return me?Ce:Ce[0]}}class re extends b{constructor(te){super(te)}async _call(te,{top_k:O=5}={}){const me=await u(te),{pixel_values:xe}=await this.processor(me),be=await this.model({pixel_values:xe}),Ce=this.model.config.id2label,$e=[];for(const Me of be.logits){const Le=await(0,p.topk)(new p.Tensor("float32",(0,l.softmax)(Me.data),Me.dims),O),we=Le[0].tolist(),He=Le[1].tolist().map((Fe,Ze)=>({label:Ce?Ce[Fe]:`LABEL_${Fe}`,score:we[Ze]}));$e.push(He)}return Array.isArray(te)?$e:$e[0]}}class Z extends b{constructor(te){super(te),this.subtasks_mapping={panoptic:"post_process_panoptic_segmentation",instance:"post_process_instance_segmentation",semantic:"post_process_semantic_segmentation"}}async _call(te,{threshold:O=.5,mask_threshold:me=.5,overlap_mask_area_threshold:xe=.8,label_ids_to_fuse:be=null,target_sizes:Ce=null,subtask:$e=null}={}){if(Array.isArray(te)&&te.length!==1)throw Error("Image segmentation pipeline currently only supports a batch size of 1.");const Le=await u(te),we=Le.map(Oe=>[Oe.height,Oe.width]),ke=await this.processor(Le),{inputNames:He,outputNames:Fe}=this.model.sessions.model;if(!He.includes("pixel_values")){if(He.length!==1)throw Error(`Expected a single input name, but got ${He.length} inputs: ${He}.`);const Oe=He[0];if(Oe in ke)throw Error(`Input name ${Oe} already exists in the inputs.`);ke[Oe]=ke.pixel_values}const Ze=await this.model(ke);let We=null;if($e!==null)We=this.subtasks_mapping[$e];else if(this.processor.image_processor){for(const[Oe,ze]of Object.entries(this.subtasks_mapping))if(ze in this.processor.image_processor){We=this.processor.image_processor[ze].bind(this.processor.image_processor),$e=Oe;break}}const yt=this.model.config.id2label,Qe=[];if($e)if($e==="panoptic"||$e==="instance"){const Oe=We(Ze,O,me,xe,be,Ce??we)[0],ze=Oe.segmentation;for(const pt of Oe.segments_info){const ft=new Uint8ClampedArray(ze.data.length);for(let kt=0;ktMr<-1e-5||Mr>1+1e-5)&&Lt.sigmoid_();const kt=await d.RawImage.fromTensor(Lt.mul_(255).to("uint8")).resize(ft[1],ft[0]);Qe.push({label:null,score:null,mask:kt})}}return Qe}}class ae extends Z{constructor(te){super(te)}async _call(te,O={}){if(Array.isArray(te)&&te.length!==1)throw Error("Background removal pipeline currently only supports a batch size of 1.");const xe=await u(te),be=await super._call(te,O);return xe.map(($e,Me)=>{const Le=$e.clone();return Le.putAlpha(be[Me].mask),Le})}}class _e extends b{constructor(te){super(te)}async _call(te,O,{hypothesis_template:me="This is a photo of {}"}={}){const xe=Array.isArray(te),be=await u(te),Ce=O.map(He=>me.replace("{}",He)),$e=this.tokenizer(Ce,{padding:this.model.config.model_type==="siglip"?"max_length":!0,truncation:!0}),{pixel_values:Me}=await this.processor(be),Le=await this.model({...$e,pixel_values:Me}),we=this.model.config.model_type==="siglip"?He=>He.sigmoid().data:He=>(0,l.softmax)(He.data),ke=[];for(const He of Le.logits_per_image){const Ze=[...we(He)].map((We,yt)=>({score:We,label:O[yt]}));Ze.sort((We,yt)=>yt.score-We.score),ke.push(Ze)}return xe?ke:ke[0]}}class pe extends b{constructor(te){super(te)}async _call(te,{threshold:O=.9,percentage:me=!1}={}){const xe=Array.isArray(te);if(xe&&te.length!==1)throw Error("Object detection pipeline currently only supports a batch size of 1.");const be=await u(te),Ce=me?null:be.map(Fe=>[Fe.height,Fe.width]),{pixel_values:$e,pixel_mask:Me}=await this.processor(be),Le=await this.model({pixel_values:$e,pixel_mask:Me}),we=this.processor.image_processor.post_process_object_detection(Le,O,Ce),ke=this.model.config.id2label,He=we.map(Fe=>Fe.boxes.map((Ze,We)=>({score:Fe.scores[We],label:ke[Fe.classes[We]],box:_(Ze,!me)})));return xe?He:He[0]}}class oe extends b{constructor(te){super(te)}async _call(te,O,{threshold:me=.1,top_k:xe=null,percentage:be=!1}={}){const Ce=Array.isArray(te),$e=await u(te),Me=this.tokenizer(O,{padding:!0,truncation:!0}),Le=await this.processor($e),we=[];for(let ke=0;ke<$e.length;++ke){const He=$e[ke],Fe=be?null:[[He.height,He.width]],Ze=Le.pixel_values[ke].unsqueeze_(0),We=await this.model({...Me,pixel_values:Ze});let yt;if("post_process_grounded_object_detection"in this.processor){const Qe=this.processor.post_process_grounded_object_detection(We,Me.input_ids,{box_threshold:me,text_threshold:me,target_sizes:Fe})[0];yt=Qe.boxes.map((Oe,ze)=>({score:Qe.scores[ze],label:Qe.labels[ze],box:_(Oe,!be)}))}else{const Qe=this.processor.image_processor.post_process_object_detection(We,me,Fe,!0)[0];yt=Qe.boxes.map((Oe,ze)=>({score:Qe.scores[ze],label:O[Qe.classes[ze]],box:_(Oe,!be)}))}yt.sort((Qe,Oe)=>Oe.score-Qe.score),xe!==null&&(yt=yt.slice(0,xe)),we.push(yt)}return Ce?we:we[0]}}class G extends b{constructor(te){super(te)}async _call(te,O,me={}){const xe=(await u(te))[0],{pixel_values:be}=await this.processor(xe),Ce=`${O}`,$e=this.tokenizer(Ce,{add_special_tokens:!1,padding:!0,truncation:!0}).input_ids,Me=await this.model.generate({inputs:be,max_length:this.model.config.decoder.max_position_embeddings,decoder_input_ids:$e,...me}),we=this.tokenizer.batch_decode(Me)[0].match(/(.*?)<\/s_answer>/);let ke=null;return we&&we.length>=2&&(ke=we[1].trim()),[{answer:ke}]}}class B extends b{constructor(O){super(O);J(this,"DEFAULT_VOCODER_ID","Xenova/speecht5_hifigan");this.vocoder=O.vocoder??null}async _prepare_speaker_embeddings(O){if((typeof O=="string"||O instanceof URL)&&(O=new Float32Array(await(await fetch(O)).arrayBuffer())),O instanceof Float32Array)O=new p.Tensor("float32",O,[O.length]);else if(!(O instanceof p.Tensor))throw new Error("Speaker embeddings must be a `Tensor`, `Float32Array`, `string`, or `URL`.");return O}async _call(O,{speaker_embeddings:me=null,num_inference_steps:xe,speed:be}={}){return this.processor?this._call_text_to_spectrogram(O,{speaker_embeddings:me}):this.model.config.model_type==="supertonic"?this._call_supertonic(O,{speaker_embeddings:me,num_inference_steps:xe,speed:be}):this._call_text_to_waveform(O)}async _call_supertonic(O,{speaker_embeddings:me,num_inference_steps:xe,speed:be}){if(!me)throw new Error("Speaker embeddings must be provided for Supertonic models.");me=await this._prepare_speaker_embeddings(me);const{sampling_rate:Ce,style_dim:$e}=this.model.config;me=me.view(1,-1,$e);const Me=this.tokenizer(O,{padding:!0,truncation:!0}),{waveform:Le}=await this.model.generate_speech({...Me,style:me,num_inference_steps:xe,speed:be});return new c.RawAudio(Le.data,Ce)}async _call_text_to_waveform(O){const me=this.tokenizer(O,{padding:!0,truncation:!0}),{waveform:xe}=await this.model(me),be=this.model.config.sampling_rate;return new c.RawAudio(xe.data,be)}async _call_text_to_spectrogram(O,{speaker_embeddings:me}){this.vocoder||(console.log("No vocoder specified, using default HifiGan vocoder."),this.vocoder=await o.AutoModel.from_pretrained(this.DEFAULT_VOCODER_ID,{dtype:"fp32"}));const{input_ids:xe}=this.tokenizer(O,{padding:!0,truncation:!0});me=await this._prepare_speaker_embeddings(me),me=me.view(1,-1);const{waveform:be}=await this.model.generate_speech(xe,me,{vocoder:this.vocoder}),Ce=this.processor.feature_extractor.config.sampling_rate;return new c.RawAudio(be.data,Ce)}}class Q extends b{constructor(te){super(te)}async _call(te){const O=await u(te),me=await this.processor(O),xe=await this.model(me),be=[];for(const Ce of xe.reconstruction){const $e=Ce.squeeze().clamp_(0,1).mul_(255).round_().to("uint8");be.push(d.RawImage.fromTensor($e))}return be.length>1?be:be[0]}}class le extends b{constructor(te){super(te)}async _call(te){const O=await u(te),me=await this.processor(O),{predicted_depth:xe}=await this.model(me),be=[];for(let Ce=0;Ce1?be:be[0]}}const ee=Object.freeze({"text-classification":{tokenizer:s.AutoTokenizer,pipeline:k,model:o.AutoModelForSequenceClassification,default:{model:"Xenova/distilbert-base-uncased-finetuned-sst-2-english"},type:"text"},"token-classification":{tokenizer:s.AutoTokenizer,pipeline:w,model:o.AutoModelForTokenClassification,default:{model:"Xenova/bert-base-multilingual-cased-ner-hrl"},type:"text"},"question-answering":{tokenizer:s.AutoTokenizer,pipeline:y,model:o.AutoModelForQuestionAnswering,default:{model:"Xenova/distilbert-base-cased-distilled-squad"},type:"text"},"fill-mask":{tokenizer:s.AutoTokenizer,pipeline:$,model:o.AutoModelForMaskedLM,default:{model:"Xenova/bert-base-uncased"},type:"text"},summarization:{tokenizer:s.AutoTokenizer,pipeline:M,model:o.AutoModelForSeq2SeqLM,default:{model:"Xenova/distilbart-cnn-6-6"},type:"text"},translation:{tokenizer:s.AutoTokenizer,pipeline:x,model:o.AutoModelForSeq2SeqLM,default:{model:"Xenova/t5-small"},type:"text"},"text2text-generation":{tokenizer:s.AutoTokenizer,pipeline:T,model:o.AutoModelForSeq2SeqLM,default:{model:"Xenova/flan-t5-small"},type:"text"},"text-generation":{tokenizer:s.AutoTokenizer,pipeline:C,model:o.AutoModelForCausalLM,default:{model:"Xenova/gpt2"},type:"text"},"zero-shot-classification":{tokenizer:s.AutoTokenizer,pipeline:F,model:o.AutoModelForSequenceClassification,default:{model:"Xenova/distilbert-base-uncased-mnli"},type:"text"},"audio-classification":{pipeline:U,model:o.AutoModelForAudioClassification,processor:n.AutoProcessor,default:{model:"Xenova/wav2vec2-base-superb-ks"},type:"audio"},"zero-shot-audio-classification":{tokenizer:s.AutoTokenizer,pipeline:j,model:o.AutoModel,processor:n.AutoProcessor,default:{model:"Xenova/clap-htsat-unfused"},type:"multimodal"},"automatic-speech-recognition":{tokenizer:s.AutoTokenizer,pipeline:se,model:[o.AutoModelForSpeechSeq2Seq,o.AutoModelForCTC],processor:n.AutoProcessor,default:{model:"Xenova/whisper-tiny.en"},type:"multimodal"},"text-to-audio":{tokenizer:s.AutoTokenizer,pipeline:B,model:[o.AutoModelForTextToWaveform,o.AutoModelForTextToSpectrogram],processor:[n.AutoProcessor,null],default:{model:"Xenova/speecht5_tts"},type:"text"},"image-to-text":{tokenizer:s.AutoTokenizer,pipeline:q,model:o.AutoModelForVision2Seq,processor:n.AutoProcessor,default:{model:"Xenova/vit-gpt2-image-captioning"},type:"multimodal"},"image-classification":{pipeline:re,model:o.AutoModelForImageClassification,processor:n.AutoProcessor,default:{model:"Xenova/vit-base-patch16-224"},type:"multimodal"},"image-segmentation":{pipeline:Z,model:[o.AutoModelForImageSegmentation,o.AutoModelForSemanticSegmentation,o.AutoModelForUniversalSegmentation],processor:n.AutoProcessor,default:{model:"Xenova/detr-resnet-50-panoptic"},type:"multimodal"},"background-removal":{pipeline:ae,model:[o.AutoModelForImageSegmentation,o.AutoModelForSemanticSegmentation,o.AutoModelForUniversalSegmentation],processor:n.AutoProcessor,default:{model:"Xenova/modnet"},type:"image"},"zero-shot-image-classification":{tokenizer:s.AutoTokenizer,pipeline:_e,model:o.AutoModel,processor:n.AutoProcessor,default:{model:"Xenova/clip-vit-base-patch32"},type:"multimodal"},"object-detection":{pipeline:pe,model:o.AutoModelForObjectDetection,processor:n.AutoProcessor,default:{model:"Xenova/detr-resnet-50"},type:"multimodal"},"zero-shot-object-detection":{tokenizer:s.AutoTokenizer,pipeline:oe,model:o.AutoModelForZeroShotObjectDetection,processor:n.AutoProcessor,default:{model:"Xenova/owlvit-base-patch32"},type:"multimodal"},"document-question-answering":{tokenizer:s.AutoTokenizer,pipeline:G,model:o.AutoModelForDocumentQuestionAnswering,processor:n.AutoProcessor,default:{model:"Xenova/donut-base-finetuned-docvqa"},type:"multimodal"},"image-to-image":{pipeline:Q,model:o.AutoModelForImageToImage,processor:n.AutoProcessor,default:{model:"Xenova/swin2SR-classical-sr-x2-64"},type:"image"},"depth-estimation":{pipeline:le,model:o.AutoModelForDepthEstimation,processor:n.AutoProcessor,default:{model:"Xenova/dpt-large"},type:"image"},"feature-extraction":{tokenizer:s.AutoTokenizer,pipeline:D,model:o.AutoModel,default:{model:"Xenova/all-MiniLM-L6-v2"},type:"text"},"image-feature-extraction":{processor:n.AutoProcessor,pipeline:K,model:[o.AutoModelForImageFeatureExtraction,o.AutoModel],default:{model:"Xenova/vit-base-patch16-224-in21k"},type:"image"}}),Se=Object.freeze({"sentiment-analysis":"text-classification",ner:"token-classification",asr:"automatic-speech-recognition","text-to-speech":"text-to-audio",embeddings:"feature-extraction"});async function De(Ae,te=null,{progress_callback:O=null,config:me=null,cache_dir:xe=null,local_files_only:be=!1,revision:Ce="main",device:$e=null,dtype:Me=null,subfolder:Le="onnx",use_external_data_format:we=null,model_file_name:ke=null,session_options:He={}}={}){Ae=Se[Ae]??Ae;const Fe=ee[Ae.split("_",1)[0]];if(!Fe)throw Error(`Unsupported pipeline: ${Ae}. Must be one of [${Object.keys(ee)}]`);te||(te=Fe.default.model,console.log(`No model specified. Using default model: "${te}".`));const Ze={progress_callback:O,config:me,cache_dir:xe,local_files_only:be,revision:Ce,device:$e,dtype:Me,subfolder:Le,use_external_data_format:we,model_file_name:ke,session_options:He},We=new Map([["tokenizer",Fe.tokenizer],["model",Fe.model],["processor",Fe.processor]]),yt=await Ne(We,te,Ze);yt.task=Ae,(0,i.dispatchCallback)(O,{status:"ready",task:Ae,model:te});const Qe=Fe.pipeline;return new Qe(yt)}async function Ne(Ae,te,O){const me=Object.create(null),xe=[];for(const[be,Ce]of Ae.entries()){if(!Ce)continue;let $e;Array.isArray(Ce)?$e=new Promise(async(Me,Le)=>{var ke,He;let we;for(const Fe of Ce){if(Fe===null){Me(null);return}try{Me(await Fe.from_pretrained(te,O));return}catch(Ze){if((ke=Ze.message)!=null&&ke.includes("Unsupported model type"))we=Ze;else if((He=Ze.message)!=null&&He.includes("Could not locate file"))we=Ze;else{Le(Ze);return}}}Le(we)}):$e=Ce.from_pretrained(te,O),me[be]=$e,xe.push($e)}await Promise.all(xe);for(const[be,Ce]of Object.entries(me))me[be]=await Ce;return me}},"./src/tokenizers.js":(e,r,t)=>{t.r(r),t.d(r,{AlbertTokenizer:()=>As,AutoTokenizer:()=>En,BartTokenizer:()=>rt,BertTokenizer:()=>Is,BlenderbotSmallTokenizer:()=>Ve,BlenderbotTokenizer:()=>je,BloomTokenizer:()=>at,CLIPTokenizer:()=>Ls,CamembertTokenizer:()=>X,CodeGenTokenizer:()=>Ds,CodeLlamaTokenizer:()=>Br,CohereTokenizer:()=>Bs,ConvBertTokenizer:()=>H,DebertaTokenizer:()=>$t,DebertaV2Tokenizer:()=>Fs,DistilBertTokenizer:()=>W,ElectraTokenizer:()=>Ee,EsmTokenizer:()=>gr,FalconTokenizer:()=>Ts,GPT2Tokenizer:()=>ot,GPTNeoXTokenizer:()=>Os,GemmaTokenizer:()=>cs,Grok1Tokenizer:()=>jr,HerbertTokenizer:()=>S,LlamaTokenizer:()=>Wt,M2M100Tokenizer:()=>mr,MBart50Tokenizer:()=>lt,MBartTokenizer:()=>St,MPNetTokenizer:()=>Rr,MarianTokenizer:()=>us,MgpstrTokenizer:()=>Qs,MobileBertTokenizer:()=>Yt,NllbTokenizer:()=>ur,NougatTokenizer:()=>qt,PreTrainedTokenizer:()=>gt,Qwen2Tokenizer:()=>Hs,RoFormerTokenizer:()=>R,RobertaTokenizer:()=>Ot,SiglipTokenizer:()=>zs,SpeechT5Tokenizer:()=>st,SqueezeBertTokenizer:()=>Jr,T5Tokenizer:()=>et,TokenizerModel:()=>K,VitsTokenizer:()=>qs,Wav2Vec2CTCTokenizer:()=>Wr,WhisperTokenizer:()=>Es,XLMRobertaTokenizer:()=>br,XLMTokenizer:()=>ue,is_chinese_char:()=>$});var s=t("./src/utils/generic.js"),o=t("./src/utils/core.js"),n=t("./src/utils/hub.js"),a=t("./src/utils/maths.js"),i=t("./src/utils/tensor.js"),l=t("./src/utils/data-structures.js"),c=t("./node_modules/@huggingface/jinja/dist/index.js"),p=t("./src/models/whisper/common_whisper.js");async function d(he,I){const N=await Promise.all([(0,n.getModelJSON)(he,"tokenizer.json",!0,I),(0,n.getModelJSON)(he,"tokenizer_config.json",!0,I)]);return I.legacy!==null&&(N[1].legacy=I.legacy),N}function u(he,I){const N=[];let Y=0;for(const ie of he.matchAll(I)){const de=ie[0];Y0&&N.push(de),Y=ie.index+de.length}return Y=19968&&he<=40959||he>=13312&&he<=19903||he>=131072&&he<=173791||he>=173824&&he<=177983||he>=177984&&he<=178207||he>=178208&&he<=183983||he>=63744&&he<=64255||he>=194560&&he<=195103}function T(he,I,N){const Y=[];let ie=0;for(;iethis.tokens_to_ids.get(N)??this.unk_token_id)}convert_ids_to_tokens(I){return I.map(N=>this.vocab[N]??this.unk_token)}}class U extends K{constructor(I){super(I),this.tokens_to_ids=_(I.vocab),this.unk_token_id=this.tokens_to_ids.get(I.unk_token),this.unk_token=I.unk_token,this.max_input_chars_per_word=I.max_input_chars_per_word??100,this.vocab=new Array(this.tokens_to_ids.size);for(const[N,Y]of this.tokens_to_ids)this.vocab[Y]=N}encode(I){const N=[];for(const Y of I){const ie=[...Y];if(ie.length>this.max_input_chars_per_word){N.push(this.unk_token);continue}let de=!1,Te=0;const Ge=[];for(;Te0&&(tt=this.config.continuing_subword_prefix+tt),this.tokens_to_ids.has(tt)){qe=tt;break}--Xe}if(qe===null){de=!0;break}Ge.push(qe),Te=Xe}de?N.push(this.unk_token):N.push(...Ge)}return N}}class j extends K{constructor(I,N){super(I);const Y=I.vocab.length;this.vocab=new Array(Y),this.scores=new Array(Y);for(let ie=0;ie[ie,de])),this.bos_token=" ",this.bos_token_id=this.tokens_to_ids.get(this.bos_token),this.eos_token=N.eos_token,this.eos_token_id=this.tokens_to_ids.get(this.eos_token),this.unk_token=this.vocab[this.unk_token_id],this.minScore=(0,a.min)(this.scores)[0],this.unk_score=this.minScore-10,this.scores[this.unk_token_id]=this.unk_score,this.trie=new l.CharTrie,this.trie.extend(this.vocab),this.fuse_unk=!0}populateNodes(I){const N=I.chars,Y=1;let ie=0;for(;ie{const he=[...Array.from({length:94},(ie,de)=>de+33),...Array.from({length:12},(ie,de)=>de+161),...Array.from({length:82},(ie,de)=>de+174)],I=he.slice();let N=0;for(let ie=0;ie<256;++ie)he.includes(ie)||(he.push(ie),I.push(256+N),N+=1);const Y=I.map(ie=>String.fromCharCode(ie));return Object.fromEntries(he.map((ie,de)=>[ie,Y[de]]))})(),q=(0,o.reverseDictionary)(se);class re extends K{constructor(I){super(I),this.tokens_to_ids=_(I.vocab),this.unk_token_id=this.tokens_to_ids.get(I.unk_token),this.unk_token=I.unk_token,this.vocab=new Array(this.tokens_to_ids.size);for(const[Y,ie]of this.tokens_to_ids)this.vocab[ie]=Y;const N=Array.isArray(I.merges[0]);this.merges=N?I.merges:I.merges.map(Y=>Y.split(" ",2)),this.bpe_ranks=new Map(this.merges.map((Y,ie)=>[JSON.stringify(Y),ie])),this.end_of_word_suffix=I.end_of_word_suffix,this.continuing_subword_suffix=I.continuing_subword_suffix??null,this.byte_fallback=this.config.byte_fallback??!1,this.byte_fallback&&(this.text_encoder=new TextEncoder),this.ignore_merges=this.config.ignore_merges??!1,this.max_length_to_cache=256,this.cache_capacity=1e4,this.cache=new l.LRUCache(this.cache_capacity)}clear_cache(){this.cache.clear()}bpe(I){if(I.length===0)return[];const N=this.cache.get(I);if(N!==void 0)return N;const Y=Array.from(I);this.end_of_word_suffix&&(Y[Y.length-1]+=this.end_of_word_suffix);let ie=[];if(Y.length>1){const de=new l.PriorityQueue((Xe,qe)=>Xe.score`<0x${Ge.toString(16).toUpperCase().padStart(2,"0")}>`);Te.every(Ge=>this.tokens_to_ids.has(Ge))?N.push(...Te):N.push(this.unk_token)}else N.push(this.unk_token)}return N}}class Z extends K{constructor(I,N){super(I),this.tokens_to_ids=_(N.target_lang?I.vocab[N.target_lang]:I.vocab),this.bos_token=N.bos_token,this.bos_token_id=this.tokens_to_ids.get(this.bos_token),this.eos_token=N.eos_token,this.eos_token_id=this.tokens_to_ids.get(this.eos_token),this.pad_token=N.pad_token,this.pad_token_id=this.tokens_to_ids.get(this.pad_token),this.unk_token=N.unk_token,this.unk_token_id=this.tokens_to_ids.get(this.unk_token),this.vocab=new Array(this.tokens_to_ids.size);for(const[Y,ie]of this.tokens_to_ids)this.vocab[ie]=Y}encode(I){return I}}class ae extends s.Callable{constructor(I){super(),this.config=I}static fromConfig(I){if(I===null)return null;switch(I.type){case"BertNormalizer":return new Ae(I);case"Precompiled":return new Ut(I);case"Sequence":return new Ne(I);case"Replace":return new _e(I);case"NFC":return new oe(I);case"NFD":return new G(I);case"NFKC":return new B(I);case"NFKD":return new Q(I);case"Strip":return new le(I);case"StripAccents":return new ee(I);case"Lowercase":return new Se(I);case"Prepend":return new De(I);default:throw new Error(`Unknown Normalizer type: ${I.type}`)}}normalize(I){throw Error("normalize should be implemented in subclass.")}_call(I){return this.normalize(I)}}class _e extends ae{normalize(I){const N=f(this.config.pattern);return N===null?I:I.replaceAll(N,this.config.content)}}class pe extends ae{constructor(){super(...arguments);J(this,"form")}normalize(N){return N=N.normalize(this.form),N}}class oe extends pe{constructor(){super(...arguments);J(this,"form","NFC")}}class G extends pe{constructor(){super(...arguments);J(this,"form","NFD")}}class B extends pe{constructor(){super(...arguments);J(this,"form","NFKC")}}class Q extends pe{constructor(){super(...arguments);J(this,"form","NFKD")}}class le extends ae{normalize(I){return this.config.strip_left&&this.config.strip_right?I=I.trim():(this.config.strip_left&&(I=I.trimStart()),this.config.strip_right&&(I=I.trimEnd())),I}}class ee extends ae{normalize(I){return I=w(I),I}}class Se extends ae{normalize(I){return I=I.toLowerCase(),I}}class De extends ae{normalize(I){return I=this.config.prepend+I,I}}class Ne extends ae{constructor(I){super(I),this.normalizers=I.normalizers.map(N=>ae.fromConfig(N))}normalize(I){return this.normalizers.reduce((N,Y)=>Y.normalize(N),I)}}class Ae extends ae{_tokenize_chinese_chars(I){const N=[];for(let Y=0;Ythis.pre_tokenize_text(Y,N)):this.pre_tokenize_text(I,N)).flat()}_call(I,N){return this.pre_tokenize(I,N)}}class O extends te{constructor(I){super(),this.pattern=new RegExp(`[^\\s${x}]+|[${x}]`,"gu")}pre_tokenize_text(I,N){return I.trim().match(this.pattern)||[]}}class me extends te{constructor(I){super(),this.config=I,this.add_prefix_space=this.config.add_prefix_space,this.trim_offsets=this.config.trim_offsets,this.use_regex=this.config.use_regex??!0,this.pattern=new RegExp("'s|'t|'re|'ve|'m|'ll|'d| ?\\p{L}+| ?\\p{N}+| ?[^\\s\\p{L}\\p{N}]+|\\s+(?!\\S)|\\s+","gu"),this.byte_encoder=se,this.text_encoder=new TextEncoder}pre_tokenize_text(I,N){return this.add_prefix_space&&!I.startsWith(" ")&&(I=" "+I),(this.use_regex?I.match(this.pattern)||[]:[I]).map(ie=>Array.from(this.text_encoder.encode(ie),de=>this.byte_encoder[de]).join(""))}}class xe extends te{constructor(I){super(),this.config=I,this.pattern=f(this.config.pattern,this.config.invert)}pre_tokenize_text(I,N){var Y;return this.pattern===null?[]:this.config.invert?I.match(this.pattern)||[]:((Y=this.config.behavior)==null?void 0:Y.toLowerCase())==="removed"?I.split(this.pattern).filter(ie=>ie):u(I,this.pattern)}}class be extends te{constructor(I){super(),this.config=I,this.pattern=new RegExp(`[^${x}]+|[${x}]+`,"gu")}pre_tokenize_text(I,N){return I.match(this.pattern)||[]}}class Ce extends te{constructor(I){super(),this.config=I;const N=`[^\\d]+|\\d${this.config.individual_digits?"":"+"}`;this.pattern=new RegExp(N,"gu")}pre_tokenize_text(I,N){return I.match(this.pattern)||[]}}class $e extends s.Callable{constructor(I){super(),this.config=I}static fromConfig(I){if(I===null)return null;switch(I.type){case"TemplateProcessing":return new we(I);case"ByteLevel":return new ke(I);case"RobertaProcessing":return new Le(I);case"BertProcessing":return new Me(I);case"Sequence":return new He(I);default:throw new Error(`Unknown PostProcessor type: ${I.type}`)}}post_process(I,...N){throw Error("post_process should be implemented in subclass.")}_call(I,...N){return this.post_process(I,...N)}}class Me extends $e{constructor(I){super(I),this.cls=I.cls[0],this.sep=I.sep[0]}post_process(I,N=null,{add_special_tokens:Y=!0}={}){Y&&(I=(0,o.mergeArrays)([this.cls],I,[this.sep]));let ie=new Array(I.length).fill(0);if(N!==null){const de=Y&&this instanceof Le?[this.sep]:[],Te=Y?[this.sep]:[];I=(0,o.mergeArrays)(I,de,N,Te),ie=(0,o.mergeArrays)(ie,new Array(N.length+de.length+Te.length).fill(1))}return{tokens:I,token_type_ids:ie}}}class Le extends Me{}class we extends $e{constructor(I){super(I),this.single=I.single,this.pair=I.pair}post_process(I,N=null,{add_special_tokens:Y=!0}={}){const ie=N===null?this.single:this.pair;let de=[],Te=[];for(const Ge of ie)"SpecialToken"in Ge?Y&&(de.push(Ge.SpecialToken.id),Te.push(Ge.SpecialToken.type_id)):"Sequence"in Ge&&(Ge.Sequence.id==="A"?(de=(0,o.mergeArrays)(de,I),Te=(0,o.mergeArrays)(Te,new Array(I.length).fill(Ge.Sequence.type_id))):Ge.Sequence.id==="B"&&(de=(0,o.mergeArrays)(de,N),Te=(0,o.mergeArrays)(Te,new Array(N.length).fill(Ge.Sequence.type_id))));return{tokens:de,token_type_ids:Te}}}class ke extends $e{post_process(I,N=null){return N&&(I=(0,o.mergeArrays)(I,N)),{tokens:I}}}class He extends $e{constructor(I){super(I),this.processors=I.processors.map(N=>$e.fromConfig(N))}post_process(I,N=null,Y={}){let ie;for(const de of this.processors)if(de instanceof ke)I=de.post_process(I).tokens,N&&(N=de.post_process(N).tokens);else{const Te=de.post_process(I,N,Y);I=Te.tokens,ie=Te.token_type_ids}return{tokens:I,token_type_ids:ie}}}class Fe extends s.Callable{constructor(I){super(),this.config=I,this.added_tokens=[],this.end_of_word_suffix=null,this.trim_offsets=I.trim_offsets}static fromConfig(I){if(I===null)return null;switch(I.type){case"WordPiece":return new Oe(I);case"Metaspace":return new fr(I);case"ByteLevel":return new ze(I);case"Replace":return new Ze(I);case"ByteFallback":return new We(I);case"Fuse":return new yt(I);case"Strip":return new Qe(I);case"Sequence":return new ft(I);case"CTC":return new pt(I);case"BPEDecoder":return new Lt(I);default:throw new Error(`Unknown Decoder type: ${I.type}`)}}_call(I){return this.decode(I)}decode(I){return this.decode_chain(I).join("")}decode_chain(I){throw Error("`decode_chain` should be implemented in subclass.")}}class Ze extends Fe{decode_chain(I){const N=f(this.config.pattern);return N===null?I:I.map(Y=>Y.replaceAll(N,this.config.content))}}class We extends Fe{constructor(I){super(I),this.text_decoder=new TextDecoder}decode_chain(I){const N=[];let Y=[];for(const ie of I){let de=null;if(ie.length===6&&ie.startsWith("<0x")&&ie.endsWith(">")){const Te=parseInt(ie.slice(3,5),16);isNaN(Te)||(de=Te)}if(de!==null)Y.push(de);else{if(Y.length>0){const Te=this.text_decoder.decode(Uint8Array.from(Y));N.push(Te),Y=[]}N.push(ie)}}if(Y.length>0){const ie=this.text_decoder.decode(Uint8Array.from(Y));N.push(ie),Y=[]}return N}}class yt extends Fe{decode_chain(I){return[I.join("")]}}class Qe extends Fe{constructor(I){super(I),this.content=this.config.content,this.start=this.config.start,this.stop=this.config.stop}decode_chain(I){return I.map(N=>{let Y=0;for(let de=0;de(Y!==0&&(N.startsWith(this.config.prefix)?N=N.replace(this.config.prefix,""):N=" "+N),this.cleanup&&(N=k(N)),N))}}class ze extends Fe{constructor(I){super(I),this.byte_decoder=q,this.text_decoder=new TextDecoder("utf-8",{fatal:!1,ignoreBOM:!0}),this.end_of_word_suffix=null}convert_tokens_to_string(I){const N=I.join(""),Y=new Uint8Array([...N].map(de=>this.byte_decoder[de]));return this.text_decoder.decode(Y)}decode_chain(I){const N=[];let Y=[];for(const ie of I)this.added_tokens.find(de=>de.content===ie)!==void 0?(Y.length>0&&(N.push(this.convert_tokens_to_string(Y)),Y=[]),N.push(ie)):Y.push(ie);return Y.length>0&&N.push(this.convert_tokens_to_string(Y)),N}}class pt extends Fe{constructor(I){super(I),this.pad_token=this.config.pad_token,this.word_delimiter_token=this.config.word_delimiter_token,this.cleanup=this.config.cleanup}convert_tokens_to_string(I){if(I.length===0)return"";const N=[I[0]];for(let de=1;dede!==this.pad_token).join("");return this.cleanup&&(ie=k(ie).replaceAll(this.word_delimiter_token," ").trim()),ie}decode_chain(I){return[this.convert_tokens_to_string(I)]}}class ft extends Fe{constructor(I){super(I),this.decoders=I.decoders.map(N=>Fe.fromConfig(N))}decode_chain(I){return this.decoders.reduce((N,Y)=>Y.decode_chain(N),I)}}class Lt extends Fe{constructor(I){super(I),this.suffix=this.config.suffix}decode_chain(I){return I.map((N,Y)=>N.replaceAll(this.suffix,Y===I.length-1?"":" "))}}class kt extends Fe{decode_chain(I){let N="";for(let Y=1;YY.normalize("NFKC")).join("~"):I=I.normalize("NFKC"),I}}class Ur extends te{constructor(I){super(),this.tokenizers=I.pretokenizers.map(N=>te.fromConfig(N))}pre_tokenize_text(I,N){return this.tokenizers.reduce((Y,ie)=>ie.pre_tokenize(Y,N),[I])}}class Ws extends te{constructor(I){super()}pre_tokenize_text(I,N){return I.match(/\w+|[^\w\s]+/g)||[]}}class Gs extends te{constructor(I){super()}pre_tokenize_text(I,N){return M(I)}}class nn extends te{constructor(I){super(),this.config=I,this.pattern=f(this.config.pattern),this.content=this.config.content}pre_tokenize_text(I,N){return this.pattern===null?[I]:[I.replaceAll(this.pattern,this.config.content)]}}class cr extends te{constructor(I){super(),this._length=I.length}pre_tokenize_text(I,N){const Y=[];for(let ie=0;ieie.content)),this.added_tokens_map=new Map(this.added_tokens.map(ie=>[ie.content,ie])),this.mask_token=this.getToken("mask_token"),this.mask_token_id=this.model.tokens_to_ids.get(this.mask_token),this.pad_token=this.getToken("pad_token","eos_token"),this.pad_token_id=this.model.tokens_to_ids.get(this.pad_token),this.sep_token=this.getToken("sep_token"),this.sep_token_id=this.model.tokens_to_ids.get(this.sep_token),this.unk_token=this.getToken("unk_token"),this.unk_token_id=this.model.tokens_to_ids.get(this.unk_token),this.bos_token=this.getToken("bos_token"),this.bos_token_id=this.model.tokens_to_ids.get(this.bos_token),this.eos_token=this.getToken("eos_token"),this.eos_token_id=this.model.tokens_to_ids.get(this.eos_token),this.model_max_length=Y.model_max_length,this.remove_space=Y.remove_space,this.clean_up_tokenization_spaces=Y.clean_up_tokenization_spaces??!0,this.do_lowercase_and_remove_accent=Y.do_lowercase_and_remove_accent??!1,Y.padding_side&&(this.padding_side=Y.padding_side),this.add_bos_token=Y.add_bos_token,this.add_eos_token=Y.add_eos_token,this.legacy=!1,this.chat_template=Y.chat_template??null,Array.isArray(this.chat_template)){const ie=Object.create(null);for(const{name:de,template:Te}of this.chat_template){if(typeof de!="string"||typeof Te!="string")throw new Error('Chat template must be a list of objects with "name" and "template" properties');ie[de]=Te}this.chat_template=ie}this._compiled_template_cache=new Map}getToken(...N){for(const Y of N){const ie=this.config[Y];if(ie)if(typeof ie=="object"){if(ie.__type==="AddedToken")return ie.content;throw Error(`Unknown token: ${ie}`)}else return ie}return null}static async from_pretrained(N,{progress_callback:Y=null,config:ie=null,cache_dir:de=null,local_files_only:Te=!1,revision:Ge="main",legacy:Xe=null}={}){const qe=await d(N,{progress_callback:Y,config:ie,cache_dir:de,local_files_only:Te,revision:Ge,legacy:Xe});return new this(...qe)}_call(N,{text_pair:Y=null,add_special_tokens:ie=!0,padding:de=!1,truncation:Te=null,max_length:Ge=null,return_tensor:Xe=!0,return_token_type_ids:qe=null}={}){const tt=Array.isArray(N);let bt;if(tt){if(N.length===0)throw Error("text array must be non-empty");if(Y!==null){if(Array.isArray(Y)){if(N.length!==Y.length)throw Error("text and text_pair must have the same length")}else throw Error("text_pair must also be an array");bt=N.map((Bt,nr)=>this._encode_plus(Bt,{text_pair:Y[nr],add_special_tokens:ie,return_token_type_ids:qe}))}else bt=N.map(Bt=>this._encode_plus(Bt,{add_special_tokens:ie,return_token_type_ids:qe}))}else{if(N==null)throw Error("text may not be null or undefined");if(Array.isArray(Y))throw Error("When specifying `text_pair`, since `text` is a string, `text_pair` must also be a string (i.e., not an array).");bt=[this._encode_plus(N,{text_pair:Y,add_special_tokens:ie,return_token_type_ids:qe})]}if(Ge===null?Ge=this.model_max_length:Te===null&&(de===!0?(console.warn("`max_length` is ignored when `padding: true` and there is no truncation strategy. To pad to max length, use `padding: 'max_length'`."),Ge=this.model_max_length):de===!1&&(console.warn("Truncation was not explicitly activated but `max_length` is provided a specific value, please use `truncation: true` to explicitly truncate examples to max length."),Te=!0)),de===!0&&(Ge=Math.min((0,a.max)(bt.map(Bt=>Bt.input_ids.length))[0],Ge??1/0)),Ge=Math.min(Ge,this.model_max_length??1/0),de||Te)for(let Bt=0;BtGe?Te&&Ks(bt[Bt],Ge):de&&ls(bt[Bt],Ge,nr=>nr==="input_ids"?this.pad_token_id:0,this.padding_side));const jt={};if(Xe){if(!(de&&Te)&&bt.some(nr=>{var Jt;for(const yr of Object.keys(nr))if(nr[yr].length!==((Jt=bt[0][yr])==null?void 0:Jt.length))return!0;return!1}))throw Error("Unable to create tensor, you should probably activate truncation and/or padding with 'padding=true' and 'truncation=true' to have batched tensors with the same length.");const Bt=[bt.length,bt[0].input_ids.length];for(const nr of Object.keys(bt[0]))jt[nr]=new i.Tensor("int64",BigInt64Array.from(bt.flatMap(Jt=>Jt[nr]).map(BigInt)),Bt)}else{for(const Bt of Object.keys(bt[0]))jt[Bt]=bt.map(nr=>nr[Bt]);if(!tt)for(const Bt of Object.keys(jt))jt[Bt]=jt[Bt][0]}return jt}_encode_text(N){if(N===null)return null;const Y=this.added_tokens_splitter.split(N);for(let de=0;de0&&(Y[de-1]=Y[de-1].trimEnd()),Te.rstrip&&de{if(de.length===0)return[];if(this.added_tokens_map.has(de))return[de];if(this.remove_space===!0&&(de=de.trim().split(/\s+/).join(" ")),this.do_lowercase_and_remove_accent&&(de=y(de)),this.normalizer!==null&&(de=this.normalizer(de)),de.length===0)return[];const Ge=this.pre_tokenizer!==null?this.pre_tokenizer(de,{section_index:Te}):[de];return this.model(Ge)})}_encode_plus(N,{text_pair:Y=null,add_special_tokens:ie=!0,return_token_type_ids:de=null}={}){const{tokens:Te,token_type_ids:Ge}=this._tokenize_helper(N,{pair:Y,add_special_tokens:ie}),Xe=this.model.convert_tokens_to_ids(Te),qe={input_ids:Xe,attention_mask:new Array(Xe.length).fill(1)};return(de??this.return_token_type_ids)&&Ge&&(qe.token_type_ids=Ge),qe}_tokenize_helper(N,{pair:Y=null,add_special_tokens:ie=!1}={}){const de=this._encode_text(N),Te=this._encode_text(Y);return this.post_processor?this.post_processor(de,Te,{add_special_tokens:ie}):{tokens:(0,o.mergeArrays)(de??[],Te??[])}}tokenize(N,{pair:Y=null,add_special_tokens:ie=!1}={}){return this._tokenize_helper(N,{pair:Y,add_special_tokens:ie}).tokens}encode(N,{text_pair:Y=null,add_special_tokens:ie=!0,return_token_type_ids:de=null}={}){return this._encode_plus(N,{text_pair:Y,add_special_tokens:ie,return_token_type_ids:de}).input_ids}batch_decode(N,Y={}){return N instanceof i.Tensor&&(N=N.tolist()),N.map(ie=>this.decode(ie,Y))}decode(N,Y={}){if(N instanceof i.Tensor&&(N=b(N)),!Array.isArray(N)||N.length===0||!(0,o.isIntegralNumber)(N[0]))throw Error("token_ids must be a non-empty array of integers.");return this.decode_single(N,Y)}decode_single(N,{skip_special_tokens:Y=!1,clean_up_tokenization_spaces:ie=null}){let de=this.model.convert_ids_to_tokens(N);Y&&(de=de.filter(Ge=>!this.special_tokens.includes(Ge)));let Te=this.decoder?this.decoder(de):de.join(" ");return this.decoder&&this.decoder.end_of_word_suffix&&(Te=Te.replaceAll(this.decoder.end_of_word_suffix," "),Y&&(Te=Te.trim())),(ie??this.clean_up_tokenization_spaces)&&(Te=k(Te)),Te}get_chat_template({chat_template:N=null,tools:Y=null}={}){if(this.chat_template&&typeof this.chat_template=="object"){const ie=this.chat_template;if(N!==null&&Object.hasOwn(ie,N))N=ie[N];else if(N===null)if(Y!==null&&"tool_use"in ie)N=ie.tool_use;else if("default"in ie)N=ie.default;else throw Error(`This model has multiple chat templates with no default specified! Please either pass a chat template or the name of the template you wish to use to the 'chat_template' argument. Available template names are ${Object.keys(ie).sort()}.`)}else if(N===null)if(this.chat_template)N=this.chat_template;else throw Error("Cannot use apply_chat_template() because tokenizer.chat_template is not set and no template argument was passed! For information about writing templates and setting the tokenizer.chat_template attribute, please see the documentation at https://huggingface.co/docs/transformers/main/en/chat_templating");return N}apply_chat_template(N,{tools:Y=null,documents:ie=null,chat_template:de=null,add_generation_prompt:Te=!1,tokenize:Ge=!0,padding:Xe=!1,truncation:qe=!1,max_length:tt=null,return_tensor:bt=!0,return_dict:jt=!1,tokenizer_kwargs:Bt={},...nr}={}){if(de=this.get_chat_template({chat_template:de,tools:Y}),typeof de!="string")throw Error(`chat_template must be a string, but got ${typeof de}`);let Jt=this._compiled_template_cache.get(de);Jt===void 0&&(Jt=new c.Template(de),this._compiled_template_cache.set(de,Jt));const yr=Object.create(null);for(const hr of zr){const xr=this.getToken(hr);xr&&(yr[hr]=xr)}const vr=Jt.render({messages:N,add_generation_prompt:Te,tools:Y,documents:ie,...yr,...nr});if(Ge){const hr=this._call(vr,{add_special_tokens:!1,padding:Xe,truncation:qe,max_length:tt,return_tensor:bt,...Bt});return jt?hr:hr.input_ids}return vr}}class Is extends gt{constructor(){super(...arguments);J(this,"return_token_type_ids",!0)}}class As extends gt{constructor(){super(...arguments);J(this,"return_token_type_ids",!0)}}class Yt extends gt{constructor(){super(...arguments);J(this,"return_token_type_ids",!0)}}class Jr extends gt{constructor(){super(...arguments);J(this,"return_token_type_ids",!0)}}class $t extends gt{constructor(){super(...arguments);J(this,"return_token_type_ids",!0)}}class Fs extends gt{constructor(){super(...arguments);J(this,"return_token_type_ids",!0)}}class S extends gt{constructor(){super(...arguments);J(this,"return_token_type_ids",!0)}}class H extends gt{constructor(){super(...arguments);J(this,"return_token_type_ids",!0)}}class R extends gt{constructor(){super(...arguments);J(this,"return_token_type_ids",!0)}}class W extends gt{}class X extends gt{}class ue extends gt{constructor(N,Y){super(N,Y);J(this,"return_token_type_ids",!0);console.warn('WARNING: `XLMTokenizer` is not yet supported by Hugging Face\'s "fast" tokenizers library. Therefore, you may experience slightly inaccurate results.')}}class Ee extends gt{constructor(){super(...arguments);J(this,"return_token_type_ids",!0)}}class et extends gt{}class ot extends gt{}class rt extends gt{}class St extends gt{constructor(I,N){super(I,N),this.languageRegex=/^[a-z]{2}_[A-Z]{2}$/,this.language_codes=this.special_tokens.filter(Y=>this.languageRegex.test(Y)),this.lang_to_token=Y=>Y}_build_translation_inputs(I,N,Y){return Hr(this,I,N,Y)}}class lt extends St{}class Ot extends gt{}class at extends gt{}const Dt="▁";class Wt extends gt{constructor(N,Y){super(N,Y);J(this,"padding_side","left");this.legacy=Y.legacy??!0,this.legacy||(this.normalizer=null,this.pre_tokenizer=new Mr({replacement:Dt,prepend_scheme:"first"}))}_encode_text(N){if(N===null)return null;if(this.legacy||N.length===0)return super._encode_text(N);let Y=super._encode_text(Dt+N.replaceAll(Dt," "));return Y.length>1&&Y[0]===Dt&&this.special_tokens.includes(Y[1])&&(Y=Y.slice(1)),Y}}class Br extends gt{}class br extends gt{}class Rr extends gt{}class Ts extends gt{}class Os extends gt{}class gr extends gt{}class Hs extends gt{}class cs extends gt{}class jr extends gt{}function Hr(he,I,N,Y){if(!("language_codes"in he)||!Array.isArray(he.language_codes))throw new Error("Tokenizer must have `language_codes` attribute set and it should be an array of language ids.");if(!("languageRegex"in he)||!(he.languageRegex instanceof RegExp))throw new Error("Tokenizer must have `languageRegex` attribute set and it should be a regular expression.");if(!("lang_to_token"in he)||typeof he.lang_to_token!="function")throw new Error("Tokenizer must have `lang_to_token` attribute set and it should be a function.");const ie=Y.src_lang,de=Y.tgt_lang;if(!he.language_codes.includes(de))throw new Error(`Target language code "${de}" is not valid. Must be one of: {${he.language_codes.join(", ")}}`);if(ie!==void 0){if(!he.language_codes.includes(ie))throw new Error(`Source language code "${ie}" is not valid. Must be one of: {${he.language_codes.join(", ")}}`);for(const Te of he.post_processor.config.single)if("SpecialToken"in Te&&he.languageRegex.test(Te.SpecialToken.id)){Te.SpecialToken.id=he.lang_to_token(ie);break}}return Y.forced_bos_token_id=he.model.convert_tokens_to_ids([he.lang_to_token(de)])[0],he._call(I,N)}class ur extends gt{constructor(I,N){super(I,N),this.languageRegex=/^[a-z]{3}_[A-Z][a-z]{3}$/,this.language_codes=this.special_tokens.filter(Y=>this.languageRegex.test(Y)),this.lang_to_token=Y=>Y}_build_translation_inputs(I,N,Y){return Hr(this,I,N,Y)}}class mr extends gt{constructor(I,N){super(I,N),this.languageRegex=/^__[a-z]{2,3}__$/,this.language_codes=this.special_tokens.filter(Y=>this.languageRegex.test(Y)).map(Y=>Y.slice(2,-2)),this.lang_to_token=Y=>`__${Y}__`}_build_translation_inputs(I,N,Y){return Hr(this,I,N,Y)}}class Es extends gt{get timestamp_begin(){return this.model.convert_tokens_to_ids(["<|notimestamps|>"])[0]+1}_decode_asr(I,{return_timestamps:N=!1,return_language:Y=!1,time_precision:ie=null,force_full_sequences:de=!0}={}){if(ie===null)throw Error("Must specify time_precision");let Te=null;const Ge=N==="word";function Xe(){return{language:Te,timestamp:[null,null],text:""}}const qe=[];let tt=Xe(),bt=0;const jt=this.timestamp_begin,nr=jt+1500;let Jt=[],yr=[],vr=!1,hr=null;const xr=new Set(this.all_special_ids);for(const rr of I){const Tr=rr.tokens,Ar=Ge?rr.token_timestamps:null;let Yr=null,Ps=jt;if("stride"in rr){const[dr,_r,wr]=rr.stride;if(bt-=_r,hr=dr-wr,_r&&(Ps=_r/ie+jt),wr)for(let or=Tr.length-1;or>=0;--or){const qr=Number(Tr[or]);if(qr>=jt){if(Yr!==null&&(qr-jt)*ie=jt&&_r<=nr){const wr=(_r-jt)*ie+bt,or=(0,a.round)(wr,2);if(Yr!==null&&_r>=Yr)vr=!0;else if(vr||Jt.length>0&&_r0?(Jt.push(Fr),Ge&&yr.push(ds)):Jt.every(dr=>dr.length===0)&&(tt=Xe(),Jt=[],Fr=[],yr=[],ds=[])}if(Jt.length>0){if(de&&N)throw new Error("Whisper did not predict an ending timestamp, which can happen if audio is cut off in the middle of a word. Also make sure WhisperTimeStampLogitsProcessor was used during generation.");const[rr,Tr]=this.findLongestCommonSequence(Jt,yr),Ar=this.decode(rr);tt.text=Ar,Ge&&(tt.words=this.collateWordTimestamps(rr,Tr,Te)),qe.push(tt)}let Cr=Object.create(null);const ss=qe.map(rr=>rr.text).join("");if(N||Y){for(let rr=0;rr0;let Ge=Te?[]:null,Xe=Te?N[0]:null;for(let qe=1;qe_r===Ps[wr]&&Xe[ss+wr]<=N[qe][Ar+wr]).length:Fr=Tr.filter((_r,wr)=>_r===Ps[wr]).length;const ds=Cr/1e4,dr=Fr/Cr+ds;Fr>1&&dr>bt&&(bt=dr,jt=[ss,rr,Ar,Yr])}const[nr,Jt,yr,vr]=jt,hr=Math.floor((Jt+nr)/2),xr=Math.floor((vr+yr)/2);de.push(...Y.slice(0,hr)),Y=tt.slice(xr),ie=Y.length,Te&&(Ge.push(...Xe.slice(0,hr)),Xe=N[qe].slice(xr))}return de.push(...Y),Te?(Ge.push(...Xe),[de,Ge]):[de,[]]}collateWordTimestamps(I,N,Y){const[ie,de,Te]=this.combineTokensIntoWords(I,Y),Ge=[];for(let Xe=0;Xe=ie){const Ge=((Te-ie)*Y).toFixed(2);de.push(`<|${Ge}|>`),de.push([])}else de[de.length-1].push(Te);return de=de.map(Te=>typeof Te=="string"?Te:super.decode(Te,N)),de.join("")}splitTokensOnUnicode(I){const N=this.decode(I,{decode_with_timestamps:!0}),Y="�",ie=[],de=[],Te=[];let Ge=[],Xe=[],qe=0;for(let tt=0;tt=this.model.tokens_to_ids.get("<|endoftext|>"),nr=tt.startsWith(" "),Jt=tt.trim(),yr=Xe.test(Jt);if(Bt||nr||yr||de.length===0)de.push(tt),Te.push(bt),Ge.push(jt);else{const vr=de.length-1;de[vr]+=tt,Te[vr].push(...bt),Ge[vr].push(...jt)}}return[de,Te,Ge]}mergePunctuations(I,N,Y,ie,de){const Te=structuredClone(I),Ge=structuredClone(N),Xe=structuredClone(Y);let qe=Te.length-2,tt=Te.length-1;for(;qe>=0;)Te[qe].startsWith(" ")&&ie.includes(Te[qe].trim())?(Te[tt]=Te[qe]+Te[tt],Ge[tt]=(0,o.mergeArrays)(Ge[qe],Ge[tt]),Xe[tt]=(0,o.mergeArrays)(Xe[qe],Xe[tt]),Te[qe]="",Ge[qe]=[],Xe[qe]=[]):tt=qe,--qe;for(qe=0,tt=1;ttbt),Ge.filter(bt=>bt.length>0),Xe.filter(bt=>bt.length>0)]}}class Ds extends gt{}class Ls extends gt{}class zs extends gt{}class us extends gt{constructor(I,N){super(I,N),this.languageRegex=/^(>>\w+<<)\s*/g,this.supported_language_codes=this.model.vocab.filter(Y=>this.languageRegex.test(Y)),console.warn('WARNING: `MarianTokenizer` is not yet supported by Hugging Face\'s "fast" tokenizers library. Therefore, you may experience slightly inaccurate results.')}_encode_text(I){if(I===null)return null;const[N,...Y]=I.trim().split(this.languageRegex);if(Y.length===0)return super._encode_text(N);if(Y.length===2){const[ie,de]=Y;return this.supported_language_codes.includes(ie)||console.warn(`Unsupported language code "${ie}" detected, which may lead to unexpected behavior. Should be one of: ${JSON.stringify(this.supported_language_codes)}`),(0,o.mergeArrays)([ie],super._encode_text(de))}}}class Wr extends gt{}class je extends gt{}class Ve extends gt{}class st extends gt{}class qt extends gt{}class qs extends gt{constructor(I,N){super(I,N),this.decoder=new kt({})}}class Bs extends gt{}class Qs extends gt{}class En{static async from_pretrained(I,{progress_callback:N=null,config:Y=null,cache_dir:ie=null,local_files_only:de=!1,revision:Te="main",legacy:Ge=null}={}){var jt;const[Xe,qe]=await d(I,{progress_callback:N,config:Y,cache_dir:ie,local_files_only:de,revision:Te,legacy:Ge}),tt=((jt=qe.tokenizer_class)==null?void 0:jt.replace(/Fast$/,""))??"PreTrainedTokenizer";let bt=this.TOKENIZER_CLASS_MAPPING[tt];return bt||(console.warn(`Unknown tokenizer class "${tt}", attempting to construct from base class.`),bt=gt),new bt(Xe,qe)}}J(En,"TOKENIZER_CLASS_MAPPING",{T5Tokenizer:et,DistilBertTokenizer:W,CamembertTokenizer:X,DebertaTokenizer:$t,DebertaV2Tokenizer:Fs,BertTokenizer:Is,HerbertTokenizer:S,ConvBertTokenizer:H,RoFormerTokenizer:R,XLMTokenizer:ue,ElectraTokenizer:Ee,MobileBertTokenizer:Yt,SqueezeBertTokenizer:Jr,AlbertTokenizer:As,GPT2Tokenizer:ot,BartTokenizer:rt,MBartTokenizer:St,MBart50Tokenizer:lt,RobertaTokenizer:Ot,WhisperTokenizer:Es,CodeGenTokenizer:Ds,CLIPTokenizer:Ls,SiglipTokenizer:zs,MarianTokenizer:us,BloomTokenizer:at,NllbTokenizer:ur,M2M100Tokenizer:mr,LlamaTokenizer:Wt,CodeLlamaTokenizer:Br,XLMRobertaTokenizer:br,MPNetTokenizer:Rr,FalconTokenizer:Ts,GPTNeoXTokenizer:Os,EsmTokenizer:gr,Wav2Vec2CTCTokenizer:Wr,BlenderbotTokenizer:je,BlenderbotSmallTokenizer:Ve,SpeechT5Tokenizer:st,NougatTokenizer:qt,VitsTokenizer:qs,Qwen2Tokenizer:Hs,GemmaTokenizer:cs,Grok1Tokenizer:jr,CohereTokenizer:Bs,MgpstrTokenizer:Qs,PreTrainedTokenizer:gt})},"./src/utils/audio.js":(e,r,t)=>{t.r(r),t.d(r,{RawAudio:()=>U,hamming:()=>u,hanning:()=>d,mel_filter_bank:()=>$,read_audio:()=>c,spectrogram:()=>C,window_function:()=>F});var s=t("./src/utils/hub.js"),o=t("./src/utils/maths.js"),n=t("./src/utils/core.js"),a=t("./src/env.js"),i=t("./src/utils/tensor.js"),l=t("?7992");async function c(j,se){if(typeof AudioContext>"u")throw Error("Unable to load audio from path/URL since `AudioContext` is not available in your environment. Instead, audio data should be passed directly to the pipeline/processor. For more information and some example code, see https://huggingface.co/docs/transformers.js/guides/node-audio-processing.");const q=await(await(0,s.getFile)(j)).arrayBuffer(),re=new AudioContext({sampleRate:se});typeof se>"u"&&console.warn(`No sampling rate provided, using default of ${re.sampleRate}Hz.`);const Z=await re.decodeAudioData(q);let ae;if(Z.numberOfChannels===2){const _e=Math.sqrt(2),pe=Z.getChannelData(0),oe=Z.getChannelData(1);ae=new Float32Array(pe.length);for(let G=0;G2595*Math.log10(1+j/700),kaldi:j=>1127*Math.log(1+j/700),slaney:(j,se=1e3,q=15,re=27/Math.log(6.4))=>j>=se?q+Math.log(j/se)*re:3*j/200};function _(j,se="htk"){const q=f[se];if(!q)throw new Error('mel_scale should be one of "htk", "slaney" or "kaldi".');return typeof j=="number"?q(j):j.map(re=>q(re))}const b={htk:j=>700*(10**(j/2595)-1),kaldi:j=>700*(Math.exp(j/1127)-1),slaney:(j,se=1e3,q=15,re=Math.log(6.4)/27)=>j>=q?se*Math.exp(re*(j-q)):200*j/3};function k(j,se="htk"){const q=b[se];if(!q)throw new Error('mel_scale should be one of "htk", "slaney" or "kaldi".');return typeof j=="number"?q(j):j.map(re=>q(re))}function w(j,se){const q=Float64Array.from({length:se.length-1},(_e,pe)=>se[pe+1]-se[pe]),re=Array.from({length:j.length},()=>new Array(se.length));for(let _e=0;_enew Array(j.length));for(let _e=0;_ej+re*ae)}function $(j,se,q,re,Z,ae=null,_e="htk",pe=!1){if(ae!==null&&ae!=="slaney")throw new Error('norm must be one of null or "slaney"');if(j<2)throw new Error(`Require num_frequency_bins: ${j} >= 2`);if(q>re)throw new Error(`Require min_frequency: ${q} <= max_frequency: ${re}`);const oe=_(q,_e),G=_(re,_e),B=y(oe,G,se+2);let Q=k(B,_e),le;if(pe){const Se=Z/((j-1)*2);le=_(Float64Array.from({length:j},(De,Ne)=>Ne*Se),_e),Q=B}else le=y(0,Math.floor(Z/2),j);const ee=w(le,Q);if(ae!==null&&ae==="slaney")for(let Se=0;SeZ)throw Error(`frame_length (${q}) may not be larger than fft_length (${Z})`);if(Ce!==q)throw new Error(`Length of the window (${Ce}) must equal frame_length (${q})`);if(re<=0)throw new Error("hop_length must be greater than zero");if(ae===null&&Q!==null)throw new Error("You have provided `mel_filters` but `power` is `None`. Mel spectrogram computation is not yet supported for complex-valued spectrogram. Specify `power` to fix this issue.");if(!B)throw new Error("`preemphasis_htk_flavor=false` is not currently supported.");if(_e)switch(pe){case"reflect":{const Oe=Math.floor((Z-1)/2)+1;j=T(j,Oe,Oe);break}case"constant":{const Oe=Math.floor(Z/2),ze=new j.constructor(j.length+2*Oe);ze.set(j,Oe),j=ze;break}default:throw new Error(`pad_mode="${pe}" not implemented yet.`)}let $e=Math.floor(1+Math.floor((j.length-q)/re));te!==null&&$e$e?me&&(we=O):we=Le=O);const ke=new o.FFT(Z),He=new Float64Array(Z),Fe=new Float64Array(ke.outputBufferSize),Ze=new Float32Array(Me*we);for(let Oe=0;Oe=1;--ft)He[ft]-=G*He[ft-1];He[0]*=1-G}for(let ft=0;ftMath.pow(pe,.85));break;default:throw new Error(`Unknown window type ${se}.`)}if(q&&(_e=_e.subarray(0,j)),re===null)return _e;if(j>re)throw new Error(`Length of the window (${j}) may not be larger than frame_length (${re})`);return _e}function D(j,se){let q=44;const re=new ArrayBuffer(q+j.length*4),Z=new DataView(re);K(Z,0,"RIFF"),Z.setUint32(4,36+j.length*4,!0),K(Z,8,"WAVE"),K(Z,12,"fmt "),Z.setUint32(16,16,!0),Z.setUint16(20,3,!0),Z.setUint16(22,1,!0),Z.setUint32(24,se,!0),Z.setUint32(28,se*4,!0),Z.setUint16(32,4,!0),Z.setUint16(34,32,!0),K(Z,36,"data"),Z.setUint32(40,j.length*4,!0);for(let ae=0;ae{let ae=await Z.arrayBuffer();l.writeFileSync(re,Buffer.from(ae))};else throw new Error("Unable to save because filesystem is disabled in this environment.");await q(se,this.toBlob())}}},"./src/utils/constants.js":(e,r,t)=>{t.r(r),t.d(r,{CHAT_TEMPLATE_NAME:()=>l,CONFIG_NAME:()=>o,FEATURE_EXTRACTOR_NAME:()=>n,GENERATION_CONFIG_NAME:()=>c,GITHUB_ISSUE_URL:()=>s,IMAGE_PROCESSOR_NAME:()=>a,PROCESSOR_NAME:()=>i});const s="https://github.com/huggingface/transformers.js/issues/new/choose",o="config.json",n="preprocessor_config.json",a=n,i="processor_config.json",l="chat_template.jinja",c="generation_config.json"},"./src/utils/core.js":(e,r,t)=>{t.r(r),t.d(r,{calculateDimensions:()=>c,calculateReflectOffset:()=>f,count:()=>w,dispatchCallback:()=>s,escapeRegExp:()=>n,isIntegralNumber:()=>i,isNullishDimension:()=>l,isTypedArray:()=>a,len:()=>k,mergeArrays:()=>d,pick:()=>b,pop:()=>p,product:()=>u,reverseDictionary:()=>o,saveBlob:()=>_});function s(y,$){y&&y($)}function o(y){return Object.fromEntries(Object.entries(y).map(([$,T])=>[T,$]))}function n(y){return y.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function a(y){var $,T,M;return((M=(T=($=y==null?void 0:y.prototype)==null?void 0:$.__proto__)==null?void 0:T.constructor)==null?void 0:M.name)==="TypedArray"}function i(y){return Number.isInteger(y)||typeof y=="bigint"}function l(y){return y==null||y===-1}function c(y){const $=[];let T=y;for(;Array.isArray(T);)$.push(T.length),T=T[0];return $}function p(y,$,T=void 0){const M=y[$];if(M!==void 0)return delete y[$],M;if(T===void 0)throw Error(`Key ${$} does not exist in object.`);return T}function d(...y){return Array.prototype.concat.apply([],y)}function u(...y){return y.reduce(($,T)=>$.flatMap(M=>T.map(x=>[M,x])))}function f(y,$){return Math.abs((y+$)%(2*$)-$)}function _(y,$){const T=URL.createObjectURL($),M=document.createElement("a");M.href=T,M.download=y,M.click(),M.remove(),URL.revokeObjectURL(T)}function b(y,$){return Object.assign({},...$.map(T=>{if(y[T]!==void 0)return{[T]:y[T]}}))}function k(y){let $=0;for(const T of y)++$;return $}function w(y,$){let T=0;for(const M of y)M===$&&++T;return T}},"./src/utils/data-structures.js":(e,r,t)=>{t.r(r),t.d(r,{CharTrie:()=>o,DictionarySplitter:()=>l,LRUCache:()=>c,PriorityQueue:()=>s,TokenLattice:()=>a});class s{constructor(d=(f,_)=>f>_,u=1/0){this._heap=[],this._comparator=d,this._maxSize=u}get size(){return this._heap.length}isEmpty(){return this.size===0}peek(){return this._heap[0]}push(...d){return this.extend(d)}extend(d){for(const u of d)if(this.size0&&this._swap(0,u),this._heap.pop(),this._siftDown(),d}replace(d){const u=this.peek();return this._heap[0]=d,this._siftDown(),u}_parent(d){return(d+1>>>1)-1}_left(d){return(d<<1)+1}_right(d){return d+1<<1}_greater(d,u){return this._comparator(this._heap[d],this._heap[u])}_swap(d,u){const f=this._heap[d];this._heap[d]=this._heap[u],this._heap[u]=f}_siftUp(){this._siftUpFrom(this.size-1)}_siftUpFrom(d){for(;d>0&&this._greater(d,this._parent(d));)this._swap(d,this._parent(d)),d=this._parent(d)}_siftDown(){let d=0;for(;this._left(d)[]),this.endNodes=Array.from({length:this.len+1},()=>[]);const _=new i(this.bosTokenId,0,0,0,0),b=new i(this.eosTokenId,1,this.len,0,0);this.nodes.push(_.clone()),this.nodes.push(b.clone()),this.beginNodes[this.len].push(b),this.endNodes[0].push(_)}insert(d,u,f,_){const b=this.nodes.length,k=new i(_,b,d,u,f);this.beginNodes[d].push(k),this.endNodes[d+u].push(k),this.nodes.push(k)}viterbi(){const d=this.len;let u=0;for(;u<=d;){if(this.beginNodes[u].length==0)return[];for(let w of this.beginNodes[u]){w.prev=null;let y=0,$=null;for(let T of this.endNodes[u]){const M=T.backtraceScore+w.score;($===null||M>y)&&($=T.clone(),y=M)}if($!==null)w.prev=$,w.backtraceScore=y;else return[]}++u}const f=[],b=this.beginNodes[d][0].prev;if(b===null)return[];let k=b.clone();for(;k.prev!==null;)f.push(k.clone()),k=k.clone().prev.clone();return f.reverse(),f}piece(d){return this.chars.slice(d.pos,d.pos+d.length).join("")}tokens(){return this.viterbi().map(u=>this.piece(u))}tokenIds(){return this.viterbi().map(u=>u.tokenId)}}class i{constructor(d,u,f,_,b){this.tokenId=d,this.nodeId=u,this.pos=f,this.length=_,this.score=b,this.prev=null,this.backtraceScore=0}clone(){const d=new i(this.tokenId,this.nodeId,this.pos,this.length,this.score);return d.prev=this.prev,d.backtraceScore=this.backtraceScore,d}}class l{constructor(d){this.trie=this._buildTrie(d)}_buildTrie(d){var f;const u=Object.create(null);for(const _ of d){let b=u;for(let k=0;k<_.length;++k)b=b[f=_[k]]??(b[f]=Object.create(null));b.end=_}return u}split(d){const u=[],f=d.length;let _=0,b=0;for(;b_&&u.push(d.slice(_,b)),u.push(w),b+=w.length,_=b):++b}return _this.capacity&&this.cache.delete(this.cache.keys().next().value)}clear(){this.cache.clear()}}},"./src/utils/devices.js":(e,r,t)=>{t.r(r),t.d(r,{DEVICE_TYPES:()=>s});const s=Object.freeze({auto:"auto",gpu:"gpu",cpu:"cpu",wasm:"wasm",webgpu:"webgpu",cuda:"cuda",dml:"dml",webnn:"webnn","webnn-npu":"webnn-npu","webnn-gpu":"webnn-gpu","webnn-cpu":"webnn-cpu"})},"./src/utils/dtypes.js":(e,r,t)=>{t.r(r),t.d(r,{DATA_TYPES:()=>a,DEFAULT_DEVICE_DTYPE_MAPPING:()=>i,DEFAULT_DTYPE_SUFFIX_MAPPING:()=>l,isWebGpuFp16Supported:()=>n});var s=t("./src/env.js"),o=t("./src/utils/devices.js");const n=function(){let c;return async function(){if(c===void 0)if(!s.apis.IS_WEBGPU_AVAILABLE)c=!1;else try{c=(await navigator.gpu.requestAdapter()).features.has("shader-f16")}catch{c=!1}return c}}(),a=Object.freeze({auto:"auto",fp32:"fp32",fp16:"fp16",q8:"q8",int8:"int8",uint8:"uint8",q4:"q4",bnb4:"bnb4",q4f16:"q4f16"}),i=Object.freeze({[o.DEVICE_TYPES.wasm]:a.q8}),l=Object.freeze({[a.fp32]:"",[a.fp16]:"_fp16",[a.int8]:"_int8",[a.uint8]:"_uint8",[a.q8]:"_quantized",[a.q4]:"_q4",[a.q4f16]:"_q4f16",[a.bnb4]:"_bnb4"})},"./src/utils/generic.js":(e,r,t)=>{t.r(r),t.d(r,{Callable:()=>s});const s=class{constructor(){let o=function(...n){return o._call(...n)};return Object.setPrototypeOf(o,new.target.prototype)}_call(...o){throw Error("Must implement _call method in subclass")}}},"./src/utils/hub.js":(e,r,t)=>{t.r(r),t.d(r,{MAX_EXTERNAL_DATA_CHUNKS:()=>i,getFile:()=>f,getModelFile:()=>y,getModelJSON:()=>T,getModelText:()=>$});var s=t("?7992"),o=t("?5af5"),n=t("./src/env.js"),a=t("./src/utils/core.js");const i=100,l={txt:"text/plain",html:"text/html",css:"text/css",js:"text/javascript",json:"application/json",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif"};class c{constructor(C){if(this.filePath=C,this.headers=new Headers,this.exists=s.existsSync(C),this.exists){this.status=200,this.statusText="OK";let F=s.statSync(C);this.headers.set("content-length",F.size.toString()),this.updateContentType();const D=s.createReadStream(C);this.body=new ReadableStream({start(K){D.on("data",U=>K.enqueue(U)),D.on("end",()=>K.close()),D.on("error",U=>K.error(U))},cancel(){D.destroy()}})}else this.status=404,this.statusText="Not Found",this.body=null}updateContentType(){const C=this.filePath.toString().split(".").pop().toLowerCase();this.headers.set("content-type",l[C]??"application/octet-stream")}clone(){let C=new c(this.filePath);return C.exists=this.exists,C.status=this.status,C.statusText=this.statusText,C.headers=new Headers(this.headers),C}async arrayBuffer(){return(await s.promises.readFile(this.filePath)).buffer}async blob(){const C=await s.promises.readFile(this.filePath);return new Blob([C],{type:this.headers.get("content-type")})}async text(){return await s.promises.readFile(this.filePath,"utf8")}async json(){return JSON.parse(await this.text())}}function p(v,C=null,F=null){let D;try{D=new URL(v)}catch{return!1}return!(C&&!C.includes(D.protocol)||F&&!F.includes(D.hostname))}const d=/^(\b[\w\-.]+\b\/)?\b[\w\-.]{1,96}\b$/;function u(v){return!(!d.test(v)||v.includes("..")||v.includes("--")||v.endsWith(".git")||v.endsWith(".ipynb"))}async function f(v){var C;if(n.env.useFS&&!p(v,["http:","https:","blob:"]))return new c(v instanceof URL?v.protocol==="file:"?v.pathname:v.toString():v);if(typeof process<"u"&&((C=process==null?void 0:process.release)==null?void 0:C.name)==="node"){const F=!!(Us!=null&&Us.TESTING_REMOTELY),D=n.env.version,K=new Headers;if(K.set("User-Agent",`transformers.js/${D}; is_ci/${F};`),p(v,["http:","https:"],["huggingface.co","hf.co"])){const j=(Us==null?void 0:Us.HF_TOKEN)??(Us==null?void 0:Us.HF_ACCESS_TOKEN);j&&K.set("Authorization",`Bearer ${j}`)}return fetch(v,{headers:K})}else return fetch(v)}const _={400:"Bad request error occurred while trying to load file",401:"Unauthorized access to file",403:"Forbidden access to file",404:"Could not locate file",408:"Request timeout error occurred while trying to load file",500:"Internal server error error occurred while trying to load file",502:"Bad gateway error occurred while trying to load file",503:"Service unavailable error occurred while trying to load file",504:"Gateway timeout error occurred while trying to load file"};function b(v,C,F){if(!F)return null;const D=_[v]??`Error (${v}) occurred while trying to load file`;throw Error(`${D}: "${C}".`)}class k{constructor(C){this.path=C}async match(C){let F=o.join(this.path,C),D=new c(F);if(D.exists)return D}async put(C,F,D=void 0){let K=o.join(this.path,C);try{const U=F.headers.get("Content-Length"),j=parseInt(U??"0");let se=0;await s.promises.mkdir(o.dirname(K),{recursive:!0});const q=s.createWriteStream(K),re=F.body.getReader();for(;;){const{done:Z,value:ae}=await re.read();if(Z)break;await new Promise((pe,oe)=>{q.write(ae,G=>{if(G){oe(G);return}pe()})}),se+=ae.length;const _e=j?se/j*100:0;D==null||D({progress:_e,loaded:se,total:j})}q.close()}catch(U){try{await s.promises.unlink(K)}catch{}throw U}}}async function w(v,...C){for(let F of C)try{let D=await v.match(F);if(D)return D}catch{continue}}async function y(v,C,F=!0,D={},K=!1){if(!n.env.allowLocalModels){if(D.local_files_only)throw Error("Invalid configuration detected: local models are disabled (`env.allowLocalModels=false`) but you have requested to only use local models (`local_files_only=true`).");if(!n.env.allowRemoteModels)throw Error("Invalid configuration detected: both local and remote models are disabled. Fix by setting `env.allowLocalModels` or `env.allowRemoteModels` to `true`.")}(0,a.dispatchCallback)(D.progress_callback,{status:"initiate",name:v,file:C});let U;if(!U&&n.env.useCustomCache){if(!n.env.customCache)throw Error("`env.useCustomCache=true`, but `env.customCache` is not defined.");if(!n.env.customCache.match||!n.env.customCache.put)throw new Error("`env.customCache` must be an object which implements the `match` and `put` functions of the Web Cache API. For more information, see https://developer.mozilla.org/en-US/docs/Web/API/Cache");U=n.env.customCache}if(!U&&n.env.useBrowserCache){if(typeof caches>"u")throw Error("Browser cache is not available in this environment.");try{U=await caches.open("transformers-cache")}catch(le){console.warn("An error occurred while opening the browser cache:",le)}}if(!U&&n.env.useFSCache){if(!n.apis.IS_FS_AVAILABLE)throw Error("File System Cache is not available in this environment.");U=new k(D.cache_dir??n.env.cacheDir)}const j=D.revision??"main",se=x(v,C),q=u(v),re=q?x(n.env.localModelPath,se):se,Z=x(n.env.remoteHost,n.env.remotePathTemplate.replaceAll("{model}",v).replaceAll("{revision}",encodeURIComponent(j)),C);let ae;const _e=U instanceof k?j==="main"?se:x(v,j,C):Z;let pe=!1,oe;U&&(oe=await w(U,re,_e));const G=oe!==void 0;if(oe===void 0){if(n.env.allowLocalModels)if(p(se,["http:","https:"])){if(D.local_files_only)throw new Error(`\`local_files_only=true\`, but attempted to load a remote file from: ${se}.`);if(!n.env.allowRemoteModels)throw new Error(`\`env.allowRemoteModels=false\`, but attempted to load a remote file from: ${se}.`)}else try{oe=await f(re),ae=re}catch(ee){console.warn(`Unable to load from local path "${re}": "${ee}"`)}if(oe===void 0||oe.status===404){if(D.local_files_only||!n.env.allowRemoteModels){if(F)throw Error(`\`local_files_only=true\` or \`env.allowRemoteModels=false\` and file was not found locally at "${re}".`);return null}if(!q)throw Error(`Local file missing at "${re}" and download aborted due to invalid model ID "${v}".`);if(oe=await f(Z),oe.status!==200)return b(oe.status,Z,F);ae=_e}pe=U&&typeof Response<"u"&&oe instanceof Response&&oe.status===200}(0,a.dispatchCallback)(D.progress_callback,{status:"download",name:v,file:C});let B;if(!(n.apis.IS_NODE_ENV&&K)){let le;D.progress_callback?G&&typeof navigator<"u"&&/firefox/i.test(navigator.userAgent)?(le=new Uint8Array(await oe.arrayBuffer()),(0,a.dispatchCallback)(D.progress_callback,{status:"progress",name:v,file:C,progress:100,loaded:le.length,total:le.length})):le=await M(oe,ee=>{(0,a.dispatchCallback)(D.progress_callback,{status:"progress",name:v,file:C,...ee})}):le=new Uint8Array(await oe.arrayBuffer()),B=le}if(pe&&ae&&await U.match(ae)===void 0)if(B)await U.put(ae,new Response(B,{headers:oe.headers})).catch(le=>{console.warn(`Unable to add response to browser cache: ${le}.`)});else{const le=D.progress_callback?ee=>(0,a.dispatchCallback)(D.progress_callback,{status:"progress",name:v,file:C,...ee}):void 0;await U.put(ae,oe,le)}if((0,a.dispatchCallback)(D.progress_callback,{status:"done",name:v,file:C}),B){if(!n.apis.IS_NODE_ENV&&K)throw new Error("Cannot return path in a browser environment.");return B}if(oe instanceof c)return oe.filePath;const Q=await(U==null?void 0:U.match(ae));if(Q instanceof c)return Q.filePath;if(Q instanceof Response)return new Uint8Array(await Q.arrayBuffer());if(typeof Q=="string")return Q;throw new Error("Unable to get model file path or buffer.")}async function $(v,C,F=!0,D={}){const K=await y(v,C,F,D,!1);return K===null?null:new TextDecoder("utf-8").decode(K)}async function T(v,C,F=!0,D={}){const K=await $(v,C,F,D);return K===null?{}:JSON.parse(K)}async function M(v,C){const F=v.headers.get("Content-Length");F===null&&console.warn("Unable to determine content-length from response headers. Will expand buffer when needed.");let D=parseInt(F??"0"),K=new Uint8Array(D),U=0;const j=v.body.getReader();async function se(){const{done:q,value:re}=await j.read();if(q)return;const Z=U+re.length;if(Z>D){D=Z;const _e=new Uint8Array(D);_e.set(K),K=_e}K.set(re,U),U=Z;const ae=U/D*100;return C({progress:ae,loaded:U,total:D}),se()}return await se(),K}function x(...v){return v=v.map((C,F)=>(F&&(C=C.replace(new RegExp("^/"),"")),F!==v.length-1&&(C=C.replace(new RegExp("/$"),"")),C)),v.join("/")}},"./src/utils/image.js":(e,r,t)=>{t.r(r),t.d(r,{RawImage:()=>_,load_image:()=>b});var s=t("./src/utils/core.js"),o=t("./src/utils/hub.js"),n=t("./src/env.js"),a=t("./src/utils/tensor.js"),i=t("?2b25");let l,c,p;const d=n.apis.IS_BROWSER_ENV||n.apis.IS_WEBWORKER_ENV;if(d)l=(k,w)=>{if(!self.OffscreenCanvas)throw new Error("OffscreenCanvas not supported by this browser.");return new self.OffscreenCanvas(k,w)},p=self.createImageBitmap,c=self.ImageData;else if(i)p=async k=>{const y=(await k.metadata()).channels,{data:$,info:T}=await k.rotate().raw().toBuffer({resolveWithObject:!0}),M=new _(new Uint8ClampedArray($),T.width,T.height,T.channels);return y!==void 0&&y!==T.channels&&M.convert(y),M};else throw new Error("Unable to load image processing library.");const u={0:"nearest",1:"lanczos",2:"bilinear",3:"bicubic",4:"box",5:"hamming"},f=new Map([["png","image/png"],["jpg","image/jpeg"],["jpeg","image/jpeg"],["gif","image/gif"]]);class _{constructor(w,y,$,T){this.data=w,this.width=y,this.height=$,this.channels=T}get size(){return[this.width,this.height]}static async read(w){if(w instanceof _)return w;if(typeof w=="string"||w instanceof URL)return await this.fromURL(w);if(w instanceof Blob)return await this.fromBlob(w);if(typeof HTMLCanvasElement<"u"&&w instanceof HTMLCanvasElement||typeof OffscreenCanvas<"u"&&w instanceof OffscreenCanvas)return this.fromCanvas(w);throw new Error(`Unsupported input type: ${typeof w}`)}static fromCanvas(w){if(!d)throw new Error("fromCanvas() is only supported in browser environments.");const $=w.getContext("2d").getImageData(0,0,w.width,w.height).data;return new _($,w.width,w.height,4)}static async fromURL(w){const y=await(0,o.getFile)(w);if(y.status!==200)throw new Error(`Unable to read image from "${w}" (${y.status} ${y.statusText})`);const $=await y.blob();return this.fromBlob($)}static async fromBlob(w){if(d){const y=await p(w),$=l(y.width,y.height).getContext("2d");return $.drawImage(y,0,0),new this($.getImageData(0,0,y.width,y.height).data,y.width,y.height,4)}else{const y=i(await w.arrayBuffer());return await p(y)}}static fromTensor(w,y="CHW"){if(w.dims.length!==3)throw new Error(`Tensor should have 3 dimensions, but has ${w.dims.length} dimensions.`);if(y==="CHW")w=w.transpose(1,2,0);else if(y!=="HWC")throw new Error(`Unsupported channel format: ${y}`);if(!(w.data instanceof Uint8ClampedArray||w.data instanceof Uint8Array))throw new Error(`Unsupported tensor type: ${w.type}`);switch(w.dims[2]){case 1:case 2:case 3:case 4:return new _(w.data,w.dims[1],w.dims[0],w.dims[2]);default:throw new Error(`Unsupported number of channels: ${w.dims[2]}`)}}grayscale(){if(this.channels===1)return this;const w=new Uint8ClampedArray(this.width*this.height*1);switch(this.channels){case 3:case 4:for(let y=0,$=0;y=0?C=$:D=-$,T>=0?F=T:K=-T,v.drawImage(x,C,F,w,y,D,K,w,y),new _(v.getImageData(0,0,w,y).data,w,y,4).convert(M)}else{let M=this.toSharp();if($>=0&&T>=0)M=M.extract({left:Math.floor($),top:Math.floor(T),width:w,height:y});else if($<=0&&T<=0){const x=Math.floor(-T),v=Math.floor(-$);M=M.extend({top:x,left:v,right:w-this.width-v,bottom:y-this.height-x})}else{let x=[0,0],v=0;T<0?(x[0]=Math.floor(-T),x[1]=y-this.height-x[0]):v=Math.floor(T);let C=[0,0],F=0;$<0?(C[0]=Math.floor(-$),C[1]=w-this.width-C[0]):F=Math.floor($),M=M.extend({top:x[0],bottom:x[1],left:C[0],right:C[1]}).extract({left:F,top:v,width:w,height:y})}return await p(M)}}async toBlob(w="image/png",y=1){if(!d)throw new Error("toBlob() is only supported in browser environments.");return await this.toCanvas().convertToBlob({type:w,quality:y})}toTensor(w="CHW"){let y=new a.Tensor("uint8",new Uint8Array(this.data),[this.height,this.width,this.channels]);if(w!=="HWC")if(w==="CHW")y=y.permute(2,0,1);else throw new Error(`Unsupported channel format: ${w}`);return y}toCanvas(){if(!d)throw new Error("toCanvas() is only supported in browser environments.");const w=this.clone().rgba(),y=l(w.width,w.height),$=new c(w.data,w.width,w.height);return y.getContext("2d").putImageData($,0,0),y}split(){const{data:w,width:y,height:$,channels:T}=this,M=w.constructor,x=w.length/T,v=Array.from({length:T},()=>new M(x));for(let C=0;Cnew _(C,y,$,1))}_update(w,y,$,T=null){return this.data=w,this.width=y,this.height=$,T!==null&&(this.channels=T),this}clone(){return new _(this.data.slice(),this.width,this.height,this.channels)}convert(w){if(this.channels===w)return this;switch(w){case 1:this.grayscale();break;case 3:this.rgb();break;case 4:this.rgba();break;default:throw new Error(`Conversion failed due to unsupported number of channels: ${this.channels}`)}return this}async save(w){if(d){if(n.apis.IS_WEBWORKER_ENV)throw new Error("Unable to save an image from a Web Worker.");const y=w.split(".").pop().toLowerCase(),$=f.get(y)??"image/png",T=await this.toBlob($);(0,s.saveBlob)(w,T)}else{if(n.apis.IS_FS_AVAILABLE)return await this.toSharp().toFile(w);throw new Error("Unable to save the image because filesystem is disabled in this environment.")}}toSharp(){if(d)throw new Error("toSharp() is only supported in server-side environments.");return i(this.data,{raw:{width:this.width,height:this.height,channels:this.channels}})}}const b=_.read.bind(_)},"./src/utils/maths.js":(e,r,t)=>{t.r(r),t.d(r,{FFT:()=>b,bankers_round:()=>y,cos_sim:()=>l,dot:()=>i,dynamic_time_warping:()=>$,interpolate_data:()=>s,log_softmax:()=>a,magnitude:()=>c,max:()=>d,medianFilter:()=>k,min:()=>p,permute_data:()=>o,round:()=>w,softmax:()=>n});function s(T,[M,x,v],[C,F],D="bilinear",K=!1){const U=F/v,j=C/x,se=new T.constructor(C*F*M),q=x*v,re=C*F;for(let Z=0;Z=0;--K)C[K]=U,v[K]=M[x[K]],U*=v[K];const F=x.map((K,U)=>C[x.indexOf(U)]),D=new T.constructor(T.length);for(let K=0;K=0;--j)U+=se%M[j]*F[j],se=Math.floor(se/M[j]);D[U]=T[K]}return[D,v]}function n(T){const M=d(T)[0],x=T.map(F=>Math.exp(F-M)),v=x.reduce((F,D)=>F+D,0);return x.map(F=>F/v)}function a(T){const M=d(T)[0];let x=0;for(let F=0;FF-M-v)}function i(T,M){let x=0;for(let v=0;vM+x*x,0))}function p(T){if(T.length===0)throw Error("Array must not be empty");let M=T[0],x=0;for(let v=1;vM&&(M=T[v],x=v);return[M,x]}function u(T){return T>0&&(T&T-1)===0}class f{constructor(M){if(this.size=M|0,this.size<=1||!u(this.size))throw new Error("FFT size must be a power of two larger than 1");this._csize=M<<1,this.table=new Float64Array(this.size*2);for(let v=0;vv;v<<=1)++x;this._width=x%2===0?x-1:x,this._bitrev=new Int32Array(1<>>C&3)<>>1);for(let C=0;C>>1]=M[C];return v}toComplexArray(M,x){const v=x||this.createComplexArray();for(let C=0;C>>1],v[C+1]=0;return v}transform(M,x){if(M===x)throw new Error("Input and output buffers must be different");this._transform4(M,x,1)}realTransform(M,x){if(M===x)throw new Error("Input and output buffers must be different");this._realTransform4(M,x,1)}inverseTransform(M,x){if(M===x)throw new Error("Input and output buffers must be different");this._transform4(M,x,-1);for(let v=0;v>=2;D>=2;D>>=2){K=C/D<<1;const re=K>>>2;for(U=0;U>>1,D>>>1)}else for(U=0,j=0;U>>1,D>>>1,v)}const q=this.table;for(D>>=2;D>=2;D>>=2){K=C/D<<1;const Z=K>>>1,ae=Z>>>1,_e=ae>>>1;for(U=0;U>>1;for(let Z=2;Z>1;++se){const q=(se+1-M)**2/2,re=Math.sqrt(U**2+j**2)**q,Z=q*Math.atan2(j,U),ae=2*se;F[ae]=re*Math.cos(Z),F[ae+1]=re*Math.sin(Z),D[ae]=F[ae],D[ae+1]=-F[ae+1]}this._slicedChirpBuffer=F.subarray(x,v),this._f=new f(C>>1),this._f.transform(this._chirpBuffer,D)}_transform(M,x,v){const C=this._buffer1,F=this._buffer2,D=this._outBuffer1,K=this._outBuffer2,U=this._chirpBuffer,j=this._slicedChirpBuffer,se=this._a;if(v)for(let q=0;q>1,ae=x[Z];C[q]=ae*j[q],C[re]=ae*j[re]}else for(let q=0;q=T.length&&(U=2*(T.length-1)-U),v[D++]=T[U]}v.sort(),x[F]=v[C]}return x}function w(T,M){const x=Math.pow(10,M);return Math.round(T*x)/x}function y(T){const M=Math.round(T);return Math.abs(T)%1===.5?M%2===0?M:M-1:M}function $(T){const M=T.length,x=T[0].length,v=[M+1,x+1],C=Array.from({length:v[0]},()=>Array(v[1]).fill(1/0));C[0][0]=0;const F=Array.from({length:v[0]},()=>Array(v[1]).fill(-1));for(let se=1;se0||K>0;)switch(U.push(D-1),j.push(K-1),F[D][K]){case 0:--D,--K;break;case 1:--D;break;case 2:--K;break;default:throw new Error(`Internal error in dynamic time warping. Unexpected trace[${D}, ${K}]. Please file a bug report.`)}return U.reverse(),j.reverse(),[U,j]}},"./src/utils/tensor.js":(e,r,t)=>{t.r(r),t.d(r,{DataTypeMap:()=>a,Tensor:()=>i,cat:()=>x,full:()=>j,full_like:()=>se,interpolate:()=>p,interpolate_4d:()=>d,layer_norm:()=>y,matmul:()=>u,mean:()=>D,mean_pooling:()=>w,ones:()=>q,ones_like:()=>re,permute:()=>c,quantize_embeddings:()=>oe,rand:()=>_e,randn:()=>pe,rfft:()=>f,slice:()=>k,stack:()=>v,std_mean:()=>F,topk:()=>_,zeros:()=>Z,zeros_like:()=>ae});var s=t("./src/utils/maths.js"),o=t("./src/backends/onnx.js"),n=t("./src/ops/registry.js");const a=Object.freeze({float32:Float32Array,float16:typeof Float16Array<"u"?Float16Array:Uint16Array,float64:Float64Array,string:Array,int8:Int8Array,uint8:Uint8Array,int16:Int16Array,uint16:Uint16Array,int32:Int32Array,uint32:Uint32Array,int64:BigInt64Array,uint64:BigUint64Array,bool:Uint8Array,uint4:Uint8Array,int4:Int8Array});class i{constructor(...B){J(this,"ort_tensor");return(0,o.isONNXTensor)(B[0])?this.ort_tensor=B[0]:this.ort_tensor=new o.Tensor(B[0],B[1],B[2]),new Proxy(this,{get:(Q,le)=>{if(typeof le=="string"){let ee=Number(le);if(Number.isInteger(ee))return Q._getitem(ee)}return Q[le]},set:(Q,le,ee)=>Q[le]=ee})}get dims(){return this.ort_tensor.dims}set dims(B){this.ort_tensor.dims=B}get type(){return this.ort_tensor.type}get data(){return this.ort_tensor.data}get size(){return this.ort_tensor.size}get location(){return this.ort_tensor.location}dispose(){this.ort_tensor.dispose()}*[Symbol.iterator](){const[B,...Q]=this.dims;if(Q.length>0){const le=Q.reduce((ee,Se)=>ee*Se);for(let ee=0;ee0){const ee=le.reduce((Se,De)=>Se*De);return this._subarray(B,ee,le)}else return new i(this.type,[this.data[B]],le)}indexOf(B){const Q=this.data;for(let le=0;lebe)throw new Error(`Invalid slice: ${me}`);const Ce=[Math.max(xe,0),Math.min(be,this.dims[O])];le.push(Ce),Q.push(Ce[1]-Ce[0])}else throw new Error(`Invalid slice: ${me}`)}const ee=le.map(([O,me])=>me-O),Se=ee.reduce((O,me)=>O*me),De=this.data,Ne=new De.constructor(Se),Ae=this.stride();let te=!0;for(let O=1;O=0;--xe){const Ce=ee[xe];me+=(be%Ce+le[xe][0])*Ae[xe],be=Math.floor(be/Ce)}Ne[O]=De[me]}return new i(this.type,Ne,Q)}permute(...B){return c(this,B)}transpose(...B){return this.permute(...B)}sum(B=null,Q=!1){return this.norm(1,B,Q)}norm(B="fro",Q=null,le=!1){if(B==="fro")B=2;else if(typeof B=="string")throw Error(`Unsupported norm: ${B}`);const ee=this.data,Se=(te,O)=>te+O**B;if(Q===null){const te=ee.reduce(Se,0)**(1/B);return new i(this.type,[te],[])}const[De,Ne,Ae]=C(Se,this,Q,le);if(B!==1)for(let te=0;te=0;--Ae){const me=this.dims[Ae];if(Ae!==Q){const xe=te%me;Ne+=xe*O,O*=this.dims[Ae]}te=Math.floor(te/me)}ee[De]/=Se[Ne]}return this}normalize(B=2,Q=1){return this.clone().normalize_(B,Q)}stride(){return K(this.dims)}squeeze(B=null){return new i(this.type,this.data,$(this.dims,B))}squeeze_(B=null){return this.dims=$(this.dims,B),this}unsqueeze(B=null){return new i(this.type,this.data,T(this.dims,B))}unsqueeze_(B=null){return this.dims=T(this.dims,B),this}flatten_(B=0,Q=-1){Q=(Q+this.dims.length)%this.dims.length;let le=this.dims.slice(0,B),ee=this.dims.slice(B,Q+1),Se=this.dims.slice(Q+1);return this.dims=[...le,ee.reduce((De,Ne)=>De*Ne,1),...Se],this}flatten(B=0,Q=-1){return this.clone().flatten_(B,Q)}view(...B){let Q=-1;for(let ee=0;eeNe!==Q?Se*De:Se,1);B[Q]=le.length/ee}return new i(this.type,le,B)}neg_(){const B=this.data;for(let Q=0;QB?1:0;return new i("bool",Q,this.dims)}lt(B){const Q=new Uint8Array(this.data.length),le=this.data;for(let ee=0;eeMath.min(De,Ne),this,B,Q,1/0);return new i(le,ee,Se)}max(B=null,Q=!1){if(B===null){const De=(0,s.max)(this.data)[0];return new i(this.type,[De],[])}const[le,ee,Se]=C((De,Ne)=>Math.max(De,Ne),this,B,Q,-1/0);return new i(le,ee,Se)}argmin(B=null,Q=!1){if(B!==null)throw new Error("`dim !== null` not yet implemented.");const le=(0,s.min)(this.data)[1];return new i("int64",[BigInt(le)],[])}argmax(B=null,Q=!1){if(B!==null)throw new Error("`dim !== null` not yet implemented.");const le=(0,s.max)(this.data)[1];return new i("int64",[BigInt(le)],[])}to(B){if(this.type===B)return this;if(!a.hasOwnProperty(B))throw new Error(`Unsupported type: ${B}`);let Q;const le=["int64","uint64"].includes(this.type),ee=["int64","uint64"].includes(B);return le&&!ee?Q=Number:!le&&ee&&(["float16","float32","float64"].includes(this.type)?Q=Se=>BigInt(Math.floor(Se)):Q=BigInt),new i(B,a[B].from(this.data,Q),this.dims)}}function l(G,B){const Q=G.length,le=B.reduce((Se,De)=>Se*De);if(Q!==le)throw Error(`cannot reshape array of size ${Q} into shape (${B})`);let ee=G;for(let Se=B.length-1;Se>=0;Se--)ee=ee.reduce((De,Ne)=>{let Ae=De[De.length-1];return Ae.lengthnew i("int64",G,[G.length]);async function k(G,B,Q,le,ee){return await(await n.TensorOpRegistry.slice)({x:G,s:b(B),e:b(Q),a:b(le),t:b(ee??new Array(le.length).fill(1))})}function w(G,B){const Q=G.data,le=B.data,ee=[G.dims[0],G.dims[2]],Se=new Q.constructor(ee[0]*ee[1]),[De,Ne,Ae]=G.dims;let te=0;for(let O=0;OQ!==1):typeof B=="number"?G[B]===1&&G.splice(B,1):Array.isArray(B)&&(G=G.filter((Q,le)=>Q!==1||!B.includes(le))),G}function T(G,B){return B=M(B,G.length+1),G=G.slice(),G.splice(B,0,1),G}function M(G,B,Q=null,le=!0){if(G<-B||G>=B){if(le)throw new Error(`IndexError: index ${G} is out of bounds for dimension${Q===null?"":" "+Q} with size ${B}`);return G<-B?0:B}return G<0&&(G=(G%B+B)%B),G}function x(G,B=0){B=M(B,G[0].dims.length);const Q=G[0].dims.slice();Q[B]=G.reduce((De,Ne)=>De+Ne.dims[B],0);const le=Q.reduce((De,Ne)=>De*Ne,1),ee=new G[0].data.constructor(le),Se=G[0].type;if(B===0){let De=0;for(const Ne of G){const Ae=Ne.data;ee.set(Ae,De),De+=Ae.length}}else{let De=0;for(let Ne=0;Ne=0;--xe){const $e=te[xe];let Me=be%$e;xe===B&&(Me+=De),me+=Me*Ce,Ce*=Q[xe],be=Math.floor(be/$e)}ee[me]=Ae[O]}De+=te[B]}}return new i(Se,ee,Q)}function v(G,B=0){return x(G.map(Q=>Q.unsqueeze(B)),B)}function C(G,B,Q=null,le=!1,ee=null){const Se=B.data,De=B.dims;Q=M(Q,De.length);const Ne=De.slice();Ne[Q]=1;const Ae=new Se.constructor(Se.length/De[Q]);ee!==null&&Ae.fill(ee);for(let te=0;te=0;--me){const Ce=De[me];if(me!==Q){const $e=xe%Ce;O+=$e*be,be*=Ne[me]}xe=Math.floor(xe/Ce)}Ae[O]=G(Ae[O],Se[te],te,O)}return le||Ne.splice(Q,1),[B.type,Ae,Ne]}function F(G,B=null,Q=1,le=!1){const ee=G.data,Se=G.dims;if(B===null){const be=ee.reduce((Le,we)=>Le+we,0)/ee.length,Ce=Math.sqrt(ee.reduce((Le,we)=>Le+(we-be)**2,0)/(ee.length-Q)),$e=new i(G.type,[be],[]);return[new i(G.type,[Ce],[]),$e]}B=M(B,Se.length);const De=D(G,B,le),Ne=De.data,[Ae,te,O]=C((xe,be,Ce,$e)=>xe+(be-Ne[$e])**2,G,B,le);for(let xe=0;xete+O,0);return new i(G.type,[Ae/ee.length],[])}B=M(B,le.length);const[Se,De,Ne]=C((Ae,te)=>Ae+te,G,B,Q);if(le[B]!==1)for(let Ae=0;Ae=0;--Q)B[Q]=le,le*=G[Q];return B}function U(G,B,Q,le){const ee=G.reduce((Se,De)=>Se*De,1);return new i(Q,new le(ee).fill(B),G)}function j(G,B){let Q,le;if(typeof B=="number")Q="float32",le=Float32Array;else if(typeof B=="bigint")Q="int64",le=BigInt64Array;else if(typeof B=="boolean")Q="bool",le=Uint8Array;else throw new Error(`Unsupported data type: ${typeof B}`);return U(G,B,Q,le)}function se(G,B){return j(G.dims,B)}function q(G){return U(G,1n,"int64",BigInt64Array)}function re(G){return q(G.dims)}function Z(G){return U(G,0n,"int64",BigInt64Array)}function ae(G){return Z(G.dims)}function _e(G){const B=G.reduce((Q,le)=>Q*le,1);return new i("float32",Float32Array.from({length:B},()=>Math.random()),G)}function pe(G){const B=G.reduce((le,ee)=>le*ee,1);function Q(){const le=1-Math.random(),ee=1-Math.random();return Math.sqrt(-2*Math.log(le))*Math.cos(2*Math.PI*ee)}return new i("float32",Float32Array.from({length:B},()=>Q()),G)}function oe(G,B){if(G.dims.length!==2)throw new Error("The tensor must have 2 dimensions");if(G.dims.at(-1)%8!==0)throw new Error("The last dimension of the tensor must be a multiple of 8");if(!["binary","ubinary"].includes(B))throw new Error("The precision must be either 'binary' or 'ubinary'");const Q=B==="binary",le=Q?"int8":"uint8",ee=Q?Int8Array:Uint8Array,Se=G.data,De=new ee(Se.length/8);for(let Ne=0;Ne0?1:0,te=Math.floor(Ne/8),O=Ne%8;De[te]|=Ae<<7-O,Q&&O===0&&(De[te]-=128)}return new i(le,De,[G.dims[0],G.dims[1]/8])}},"./src/utils/video.js":(e,r,t)=>{t.r(r),t.d(r,{RawVideo:()=>a,RawVideoFrame:()=>n,load_video:()=>i});var s=t("./src/utils/image.js"),o=t("./src/env.js");class n{constructor(c,p){this.image=c,this.timestamp=p}}class a{constructor(c,p){c.length>0&&c[0]instanceof s.RawImage&&(c=c.map((d,u)=>new n(d,(u+1)/(c.length+1)*p))),this.frames=c,this.duration=p}get width(){return this.frames[0].image.width}get height(){return this.frames[0].image.height}get fps(){return this.frames.length/this.duration}}async function i(l,{num_frames:c=null,fps:p=null}={}){if(!o.apis.IS_BROWSER_ENV)throw new Error("`load_video` is currently only supported in browser environments.");if(c==null&&p==null)throw new Error("Either num_frames or fps must be provided.");const d=[],u=document.createElement("video");if(u.crossOrigin="anonymous",u.muted=!0,typeof l=="string")u.src=l;else if(l instanceof Blob)u.src=URL.createObjectURL(l);else if(l instanceof HTMLVideoElement)u.src=l.src;else throw new Error("Invalid URL or video element provided.");if(await new Promise($=>u.onloadedmetadata=$),u.seekable.start(0)===u.seekable.end(0)){const T=await(await fetch(u.src)).blob();u.src=URL.createObjectURL(T),await new Promise(M=>u.onloadedmetadata=M)}const f=u.duration;let _,b;c!=null?(_=c,b=c===1?0:f/(c-1)):(b=1/p,_=Math.floor(f/b));let k=[];for(let $=0;$<_;++$)k.push(c===1?f/2:$*b);const w=document.createElement("canvas");w.width=u.videoWidth,w.height=u.videoHeight;const y=w.getContext("2d",{willReadFrequently:!0});for(const $ of k){u.currentTime=$,await new Promise(v=>{u.onseeked=v}),y.drawImage(u,0,0,w.width,w.height);const T=y.getImageData(0,0,w.width,w.height),M=new s.RawImage(T.data,w.width,w.height,4),x=new n(M,$);d.push(x)}return u.remove(),new a(d,f)}}},cw={};function Ht(e){var r=cw[e];if(r!==void 0)return r.exports;var t=cw[e]={exports:{}};return AT[e](t,t.exports,Ht),t.exports}(()=>{var e=Object.getPrototypeOf?t=>Object.getPrototypeOf(t):t=>t.__proto__,r;Ht.t=function(t,s){if(s&1&&(t=this(t)),s&8||typeof t=="object"&&t&&(s&4&&t.__esModule||s&16&&typeof t.then=="function"))return t;var o=Object.create(null);Ht.r(o);var n={};r=r||[null,e({}),e([]),e(e)];for(var a=s&2&&t;typeof a=="object"&&!~r.indexOf(a);a=e(a))Object.getOwnPropertyNames(a).forEach(i=>n[i]=()=>t[i]);return n.default=()=>t,Ht.d(o,n),o}})(),Ht.d=(e,r)=>{for(var t in r)Ht.o(r,t)&&!Ht.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},Ht.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),Ht.r=e=>{typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var m={};(()=>{/*!*****************************!*\ - !*** ./src/transformers.js ***! - \*****************************/Ht.r(m),Ht.d(m,{ASTFeatureExtractor:()=>d.ASTFeatureExtractor,ASTForAudioClassification:()=>t.ASTForAudioClassification,ASTModel:()=>t.ASTModel,ASTPreTrainedModel:()=>t.ASTPreTrainedModel,AlbertForMaskedLM:()=>t.AlbertForMaskedLM,AlbertForQuestionAnswering:()=>t.AlbertForQuestionAnswering,AlbertForSequenceClassification:()=>t.AlbertForSequenceClassification,AlbertModel:()=>t.AlbertModel,AlbertPreTrainedModel:()=>t.AlbertPreTrainedModel,AlbertTokenizer:()=>s.AlbertTokenizer,ArceeForCausalLM:()=>t.ArceeForCausalLM,ArceeModel:()=>t.ArceeModel,ArceePreTrainedModel:()=>t.ArceePreTrainedModel,AudioClassificationPipeline:()=>r.AudioClassificationPipeline,AutoConfig:()=>o.AutoConfig,AutoFeatureExtractor:()=>u.AutoFeatureExtractor,AutoImageProcessor:()=>b.AutoImageProcessor,AutoModel:()=>t.AutoModel,AutoModelForAudioClassification:()=>t.AutoModelForAudioClassification,AutoModelForAudioFrameClassification:()=>t.AutoModelForAudioFrameClassification,AutoModelForAudioTextToText:()=>t.AutoModelForAudioTextToText,AutoModelForCTC:()=>t.AutoModelForCTC,AutoModelForCausalLM:()=>t.AutoModelForCausalLM,AutoModelForDepthEstimation:()=>t.AutoModelForDepthEstimation,AutoModelForDocumentQuestionAnswering:()=>t.AutoModelForDocumentQuestionAnswering,AutoModelForImageClassification:()=>t.AutoModelForImageClassification,AutoModelForImageFeatureExtraction:()=>t.AutoModelForImageFeatureExtraction,AutoModelForImageMatting:()=>t.AutoModelForImageMatting,AutoModelForImageSegmentation:()=>t.AutoModelForImageSegmentation,AutoModelForImageTextToText:()=>t.AutoModelForImageTextToText,AutoModelForImageToImage:()=>t.AutoModelForImageToImage,AutoModelForMaskGeneration:()=>t.AutoModelForMaskGeneration,AutoModelForMaskedLM:()=>t.AutoModelForMaskedLM,AutoModelForNormalEstimation:()=>t.AutoModelForNormalEstimation,AutoModelForObjectDetection:()=>t.AutoModelForObjectDetection,AutoModelForPoseEstimation:()=>t.AutoModelForPoseEstimation,AutoModelForQuestionAnswering:()=>t.AutoModelForQuestionAnswering,AutoModelForSemanticSegmentation:()=>t.AutoModelForSemanticSegmentation,AutoModelForSeq2SeqLM:()=>t.AutoModelForSeq2SeqLM,AutoModelForSequenceClassification:()=>t.AutoModelForSequenceClassification,AutoModelForSpeechSeq2Seq:()=>t.AutoModelForSpeechSeq2Seq,AutoModelForTextToSpectrogram:()=>t.AutoModelForTextToSpectrogram,AutoModelForTextToWaveform:()=>t.AutoModelForTextToWaveform,AutoModelForTokenClassification:()=>t.AutoModelForTokenClassification,AutoModelForUniversalSegmentation:()=>t.AutoModelForUniversalSegmentation,AutoModelForVision2Seq:()=>t.AutoModelForVision2Seq,AutoModelForXVector:()=>t.AutoModelForXVector,AutoModelForZeroShotObjectDetection:()=>t.AutoModelForZeroShotObjectDetection,AutoProcessor:()=>y.AutoProcessor,AutoTokenizer:()=>s.AutoTokenizer,AutomaticSpeechRecognitionPipeline:()=>r.AutomaticSpeechRecognitionPipeline,BackgroundRemovalPipeline:()=>r.BackgroundRemovalPipeline,BartForConditionalGeneration:()=>t.BartForConditionalGeneration,BartForSequenceClassification:()=>t.BartForSequenceClassification,BartModel:()=>t.BartModel,BartPretrainedModel:()=>t.BartPretrainedModel,BartTokenizer:()=>s.BartTokenizer,BaseModelOutput:()=>t.BaseModelOutput,BaseStreamer:()=>$.BaseStreamer,BeitFeatureExtractor:()=>_.BeitFeatureExtractor,BeitForImageClassification:()=>t.BeitForImageClassification,BeitModel:()=>t.BeitModel,BeitPreTrainedModel:()=>t.BeitPreTrainedModel,BertForMaskedLM:()=>t.BertForMaskedLM,BertForQuestionAnswering:()=>t.BertForQuestionAnswering,BertForSequenceClassification:()=>t.BertForSequenceClassification,BertForTokenClassification:()=>t.BertForTokenClassification,BertModel:()=>t.BertModel,BertPreTrainedModel:()=>t.BertPreTrainedModel,BertTokenizer:()=>s.BertTokenizer,BitImageProcessor:()=>_.BitImageProcessor,BlenderbotForConditionalGeneration:()=>t.BlenderbotForConditionalGeneration,BlenderbotModel:()=>t.BlenderbotModel,BlenderbotPreTrainedModel:()=>t.BlenderbotPreTrainedModel,BlenderbotSmallForConditionalGeneration:()=>t.BlenderbotSmallForConditionalGeneration,BlenderbotSmallModel:()=>t.BlenderbotSmallModel,BlenderbotSmallPreTrainedModel:()=>t.BlenderbotSmallPreTrainedModel,BlenderbotSmallTokenizer:()=>s.BlenderbotSmallTokenizer,BlenderbotTokenizer:()=>s.BlenderbotTokenizer,BloomForCausalLM:()=>t.BloomForCausalLM,BloomModel:()=>t.BloomModel,BloomPreTrainedModel:()=>t.BloomPreTrainedModel,BloomTokenizer:()=>s.BloomTokenizer,CLIPFeatureExtractor:()=>_.CLIPFeatureExtractor,CLIPImageProcessor:()=>_.CLIPImageProcessor,CLIPModel:()=>t.CLIPModel,CLIPPreTrainedModel:()=>t.CLIPPreTrainedModel,CLIPSegForImageSegmentation:()=>t.CLIPSegForImageSegmentation,CLIPSegModel:()=>t.CLIPSegModel,CLIPSegPreTrainedModel:()=>t.CLIPSegPreTrainedModel,CLIPTextModel:()=>t.CLIPTextModel,CLIPTextModelWithProjection:()=>t.CLIPTextModelWithProjection,CLIPTokenizer:()=>s.CLIPTokenizer,CLIPVisionModel:()=>t.CLIPVisionModel,CLIPVisionModelWithProjection:()=>t.CLIPVisionModelWithProjection,CamembertForMaskedLM:()=>t.CamembertForMaskedLM,CamembertForQuestionAnswering:()=>t.CamembertForQuestionAnswering,CamembertForSequenceClassification:()=>t.CamembertForSequenceClassification,CamembertForTokenClassification:()=>t.CamembertForTokenClassification,CamembertModel:()=>t.CamembertModel,CamembertPreTrainedModel:()=>t.CamembertPreTrainedModel,CamembertTokenizer:()=>s.CamembertTokenizer,CausalLMOutput:()=>t.CausalLMOutput,CausalLMOutputWithPast:()=>t.CausalLMOutputWithPast,ChineseCLIPFeatureExtractor:()=>_.ChineseCLIPFeatureExtractor,ChineseCLIPModel:()=>t.ChineseCLIPModel,ChineseCLIPPreTrainedModel:()=>t.ChineseCLIPPreTrainedModel,ClapAudioModelWithProjection:()=>t.ClapAudioModelWithProjection,ClapFeatureExtractor:()=>d.ClapFeatureExtractor,ClapModel:()=>t.ClapModel,ClapPreTrainedModel:()=>t.ClapPreTrainedModel,ClapTextModelWithProjection:()=>t.ClapTextModelWithProjection,ClassifierFreeGuidanceLogitsProcessor:()=>M.ClassifierFreeGuidanceLogitsProcessor,CodeGenForCausalLM:()=>t.CodeGenForCausalLM,CodeGenModel:()=>t.CodeGenModel,CodeGenPreTrainedModel:()=>t.CodeGenPreTrainedModel,CodeGenTokenizer:()=>s.CodeGenTokenizer,CodeLlamaTokenizer:()=>s.CodeLlamaTokenizer,CohereForCausalLM:()=>t.CohereForCausalLM,CohereModel:()=>t.CohereModel,CoherePreTrainedModel:()=>t.CoherePreTrainedModel,CohereTokenizer:()=>s.CohereTokenizer,ConvBertForMaskedLM:()=>t.ConvBertForMaskedLM,ConvBertForQuestionAnswering:()=>t.ConvBertForQuestionAnswering,ConvBertForSequenceClassification:()=>t.ConvBertForSequenceClassification,ConvBertForTokenClassification:()=>t.ConvBertForTokenClassification,ConvBertModel:()=>t.ConvBertModel,ConvBertPreTrainedModel:()=>t.ConvBertPreTrainedModel,ConvBertTokenizer:()=>s.ConvBertTokenizer,ConvNextFeatureExtractor:()=>_.ConvNextFeatureExtractor,ConvNextForImageClassification:()=>t.ConvNextForImageClassification,ConvNextImageProcessor:()=>_.ConvNextImageProcessor,ConvNextModel:()=>t.ConvNextModel,ConvNextPreTrainedModel:()=>t.ConvNextPreTrainedModel,ConvNextV2ForImageClassification:()=>t.ConvNextV2ForImageClassification,ConvNextV2Model:()=>t.ConvNextV2Model,ConvNextV2PreTrainedModel:()=>t.ConvNextV2PreTrainedModel,DFineForObjectDetection:()=>t.DFineForObjectDetection,DFineModel:()=>t.DFineModel,DFinePreTrainedModel:()=>t.DFinePreTrainedModel,DINOv3ConvNextModel:()=>t.DINOv3ConvNextModel,DINOv3ConvNextPreTrainedModel:()=>t.DINOv3ConvNextPreTrainedModel,DINOv3ViTImageProcessor:()=>_.DINOv3ViTImageProcessor,DINOv3ViTModel:()=>t.DINOv3ViTModel,DINOv3ViTPreTrainedModel:()=>t.DINOv3ViTPreTrainedModel,DPTFeatureExtractor:()=>_.DPTFeatureExtractor,DPTForDepthEstimation:()=>t.DPTForDepthEstimation,DPTImageProcessor:()=>_.DPTImageProcessor,DPTModel:()=>t.DPTModel,DPTPreTrainedModel:()=>t.DPTPreTrainedModel,DacDecoderModel:()=>t.DacDecoderModel,DacDecoderOutput:()=>t.DacDecoderOutput,DacEncoderModel:()=>t.DacEncoderModel,DacEncoderOutput:()=>t.DacEncoderOutput,DacFeatureExtractor:()=>d.DacFeatureExtractor,DacModel:()=>t.DacModel,DacPreTrainedModel:()=>t.DacPreTrainedModel,DataTypeMap:()=>l.DataTypeMap,DebertaForMaskedLM:()=>t.DebertaForMaskedLM,DebertaForQuestionAnswering:()=>t.DebertaForQuestionAnswering,DebertaForSequenceClassification:()=>t.DebertaForSequenceClassification,DebertaForTokenClassification:()=>t.DebertaForTokenClassification,DebertaModel:()=>t.DebertaModel,DebertaPreTrainedModel:()=>t.DebertaPreTrainedModel,DebertaTokenizer:()=>s.DebertaTokenizer,DebertaV2ForMaskedLM:()=>t.DebertaV2ForMaskedLM,DebertaV2ForQuestionAnswering:()=>t.DebertaV2ForQuestionAnswering,DebertaV2ForSequenceClassification:()=>t.DebertaV2ForSequenceClassification,DebertaV2ForTokenClassification:()=>t.DebertaV2ForTokenClassification,DebertaV2Model:()=>t.DebertaV2Model,DebertaV2PreTrainedModel:()=>t.DebertaV2PreTrainedModel,DebertaV2Tokenizer:()=>s.DebertaV2Tokenizer,DecisionTransformerModel:()=>t.DecisionTransformerModel,DecisionTransformerPreTrainedModel:()=>t.DecisionTransformerPreTrainedModel,DeiTFeatureExtractor:()=>_.DeiTFeatureExtractor,DeiTForImageClassification:()=>t.DeiTForImageClassification,DeiTImageProcessor:()=>_.DeiTImageProcessor,DeiTModel:()=>t.DeiTModel,DeiTPreTrainedModel:()=>t.DeiTPreTrainedModel,DepthAnythingForDepthEstimation:()=>t.DepthAnythingForDepthEstimation,DepthAnythingPreTrainedModel:()=>t.DepthAnythingPreTrainedModel,DepthEstimationPipeline:()=>r.DepthEstimationPipeline,DepthProForDepthEstimation:()=>t.DepthProForDepthEstimation,DepthProPreTrainedModel:()=>t.DepthProPreTrainedModel,DetrFeatureExtractor:()=>_.DetrFeatureExtractor,DetrForObjectDetection:()=>t.DetrForObjectDetection,DetrForSegmentation:()=>t.DetrForSegmentation,DetrImageProcessor:()=>_.DetrImageProcessor,DetrModel:()=>t.DetrModel,DetrObjectDetectionOutput:()=>t.DetrObjectDetectionOutput,DetrPreTrainedModel:()=>t.DetrPreTrainedModel,DetrSegmentationOutput:()=>t.DetrSegmentationOutput,Dinov2ForImageClassification:()=>t.Dinov2ForImageClassification,Dinov2Model:()=>t.Dinov2Model,Dinov2PreTrainedModel:()=>t.Dinov2PreTrainedModel,Dinov2WithRegistersForImageClassification:()=>t.Dinov2WithRegistersForImageClassification,Dinov2WithRegistersModel:()=>t.Dinov2WithRegistersModel,Dinov2WithRegistersPreTrainedModel:()=>t.Dinov2WithRegistersPreTrainedModel,DistilBertForMaskedLM:()=>t.DistilBertForMaskedLM,DistilBertForQuestionAnswering:()=>t.DistilBertForQuestionAnswering,DistilBertForSequenceClassification:()=>t.DistilBertForSequenceClassification,DistilBertForTokenClassification:()=>t.DistilBertForTokenClassification,DistilBertModel:()=>t.DistilBertModel,DistilBertPreTrainedModel:()=>t.DistilBertPreTrainedModel,DistilBertTokenizer:()=>s.DistilBertTokenizer,DocumentQuestionAnsweringPipeline:()=>r.DocumentQuestionAnsweringPipeline,DonutFeatureExtractor:()=>_.DonutFeatureExtractor,DonutImageProcessor:()=>_.DonutImageProcessor,DonutSwinModel:()=>t.DonutSwinModel,DonutSwinPreTrainedModel:()=>t.DonutSwinPreTrainedModel,EdgeTamModel:()=>t.EdgeTamModel,EfficientNetForImageClassification:()=>t.EfficientNetForImageClassification,EfficientNetImageProcessor:()=>_.EfficientNetImageProcessor,EfficientNetModel:()=>t.EfficientNetModel,EfficientNetPreTrainedModel:()=>t.EfficientNetPreTrainedModel,ElectraForMaskedLM:()=>t.ElectraForMaskedLM,ElectraForQuestionAnswering:()=>t.ElectraForQuestionAnswering,ElectraForSequenceClassification:()=>t.ElectraForSequenceClassification,ElectraForTokenClassification:()=>t.ElectraForTokenClassification,ElectraModel:()=>t.ElectraModel,ElectraPreTrainedModel:()=>t.ElectraPreTrainedModel,ElectraTokenizer:()=>s.ElectraTokenizer,EncodecFeatureExtractor:()=>d.EncodecFeatureExtractor,EosTokenCriteria:()=>T.EosTokenCriteria,Ernie4_5ForCausalLM:()=>t.Ernie4_5ForCausalLM,Ernie4_5Model:()=>t.Ernie4_5Model,Ernie4_5PreTrainedModel:()=>t.Ernie4_5PreTrainedModel,EsmForMaskedLM:()=>t.EsmForMaskedLM,EsmForSequenceClassification:()=>t.EsmForSequenceClassification,EsmForTokenClassification:()=>t.EsmForTokenClassification,EsmModel:()=>t.EsmModel,EsmPreTrainedModel:()=>t.EsmPreTrainedModel,EsmTokenizer:()=>s.EsmTokenizer,ExaoneForCausalLM:()=>t.ExaoneForCausalLM,ExaoneModel:()=>t.ExaoneModel,ExaonePreTrainedModel:()=>t.ExaonePreTrainedModel,FFT:()=>c.FFT,FalconForCausalLM:()=>t.FalconForCausalLM,FalconModel:()=>t.FalconModel,FalconPreTrainedModel:()=>t.FalconPreTrainedModel,FalconTokenizer:()=>s.FalconTokenizer,FastViTForImageClassification:()=>t.FastViTForImageClassification,FastViTModel:()=>t.FastViTModel,FastViTPreTrainedModel:()=>t.FastViTPreTrainedModel,FeatureExtractionPipeline:()=>r.FeatureExtractionPipeline,FeatureExtractor:()=>p.FeatureExtractor,FillMaskPipeline:()=>r.FillMaskPipeline,Florence2ForConditionalGeneration:()=>t.Florence2ForConditionalGeneration,Florence2PreTrainedModel:()=>t.Florence2PreTrainedModel,Florence2Processor:()=>w.Florence2Processor,ForcedBOSTokenLogitsProcessor:()=>M.ForcedBOSTokenLogitsProcessor,ForcedEOSTokenLogitsProcessor:()=>M.ForcedEOSTokenLogitsProcessor,GLPNFeatureExtractor:()=>_.GLPNFeatureExtractor,GLPNForDepthEstimation:()=>t.GLPNForDepthEstimation,GLPNModel:()=>t.GLPNModel,GLPNPreTrainedModel:()=>t.GLPNPreTrainedModel,GPT2LMHeadModel:()=>t.GPT2LMHeadModel,GPT2Model:()=>t.GPT2Model,GPT2PreTrainedModel:()=>t.GPT2PreTrainedModel,GPT2Tokenizer:()=>s.GPT2Tokenizer,GPTBigCodeForCausalLM:()=>t.GPTBigCodeForCausalLM,GPTBigCodeModel:()=>t.GPTBigCodeModel,GPTBigCodePreTrainedModel:()=>t.GPTBigCodePreTrainedModel,GPTJForCausalLM:()=>t.GPTJForCausalLM,GPTJModel:()=>t.GPTJModel,GPTJPreTrainedModel:()=>t.GPTJPreTrainedModel,GPTNeoForCausalLM:()=>t.GPTNeoForCausalLM,GPTNeoModel:()=>t.GPTNeoModel,GPTNeoPreTrainedModel:()=>t.GPTNeoPreTrainedModel,GPTNeoXForCausalLM:()=>t.GPTNeoXForCausalLM,GPTNeoXModel:()=>t.GPTNeoXModel,GPTNeoXPreTrainedModel:()=>t.GPTNeoXPreTrainedModel,GPTNeoXTokenizer:()=>s.GPTNeoXTokenizer,Gemma2ForCausalLM:()=>t.Gemma2ForCausalLM,Gemma2Model:()=>t.Gemma2Model,Gemma2PreTrainedModel:()=>t.Gemma2PreTrainedModel,Gemma3ForCausalLM:()=>t.Gemma3ForCausalLM,Gemma3Model:()=>t.Gemma3Model,Gemma3PreTrainedModel:()=>t.Gemma3PreTrainedModel,Gemma3nAudioFeatureExtractor:()=>d.Gemma3nAudioFeatureExtractor,Gemma3nForConditionalGeneration:()=>t.Gemma3nForConditionalGeneration,Gemma3nPreTrainedModel:()=>t.Gemma3nPreTrainedModel,Gemma3nProcessor:()=>w.Gemma3nProcessor,GemmaForCausalLM:()=>t.GemmaForCausalLM,GemmaModel:()=>t.GemmaModel,GemmaPreTrainedModel:()=>t.GemmaPreTrainedModel,GemmaTokenizer:()=>s.GemmaTokenizer,GlmForCausalLM:()=>t.GlmForCausalLM,GlmModel:()=>t.GlmModel,GlmPreTrainedModel:()=>t.GlmPreTrainedModel,GraniteForCausalLM:()=>t.GraniteForCausalLM,GraniteModel:()=>t.GraniteModel,GraniteMoeHybridForCausalLM:()=>t.GraniteMoeHybridForCausalLM,GraniteMoeHybridModel:()=>t.GraniteMoeHybridModel,GraniteMoeHybridPreTrainedModel:()=>t.GraniteMoeHybridPreTrainedModel,GranitePreTrainedModel:()=>t.GranitePreTrainedModel,Grok1Tokenizer:()=>s.Grok1Tokenizer,GroundingDinoForObjectDetection:()=>t.GroundingDinoForObjectDetection,GroundingDinoImageProcessor:()=>_.GroundingDinoImageProcessor,GroundingDinoPreTrainedModel:()=>t.GroundingDinoPreTrainedModel,GroundingDinoProcessor:()=>w.GroundingDinoProcessor,GroupViTModel:()=>t.GroupViTModel,GroupViTPreTrainedModel:()=>t.GroupViTPreTrainedModel,HeliumForCausalLM:()=>t.HeliumForCausalLM,HeliumModel:()=>t.HeliumModel,HeliumPreTrainedModel:()=>t.HeliumPreTrainedModel,HerbertTokenizer:()=>s.HerbertTokenizer,HieraForImageClassification:()=>t.HieraForImageClassification,HieraModel:()=>t.HieraModel,HieraPreTrainedModel:()=>t.HieraPreTrainedModel,HubertForCTC:()=>t.HubertForCTC,HubertForSequenceClassification:()=>t.HubertForSequenceClassification,HubertModel:()=>t.HubertModel,HubertPreTrainedModel:()=>t.HubertPreTrainedModel,IJepaForImageClassification:()=>t.IJepaForImageClassification,IJepaModel:()=>t.IJepaModel,IJepaPreTrainedModel:()=>t.IJepaPreTrainedModel,Idefics3ForConditionalGeneration:()=>t.Idefics3ForConditionalGeneration,Idefics3ImageProcessor:()=>_.Idefics3ImageProcessor,Idefics3PreTrainedModel:()=>t.Idefics3PreTrainedModel,Idefics3Processor:()=>w.Idefics3Processor,ImageClassificationPipeline:()=>r.ImageClassificationPipeline,ImageFeatureExtractionPipeline:()=>r.ImageFeatureExtractionPipeline,ImageFeatureExtractor:()=>d.ImageFeatureExtractor,ImageMattingOutput:()=>t.ImageMattingOutput,ImageProcessor:()=>f.ImageProcessor,ImageSegmentationPipeline:()=>r.ImageSegmentationPipeline,ImageToImagePipeline:()=>r.ImageToImagePipeline,ImageToTextPipeline:()=>r.ImageToTextPipeline,InterruptableStoppingCriteria:()=>T.InterruptableStoppingCriteria,JAISLMHeadModel:()=>t.JAISLMHeadModel,JAISModel:()=>t.JAISModel,JAISPreTrainedModel:()=>t.JAISPreTrainedModel,JinaCLIPImageProcessor:()=>_.JinaCLIPImageProcessor,JinaCLIPModel:()=>t.JinaCLIPModel,JinaCLIPPreTrainedModel:()=>t.JinaCLIPPreTrainedModel,JinaCLIPProcessor:()=>w.JinaCLIPProcessor,JinaCLIPTextModel:()=>t.JinaCLIPTextModel,JinaCLIPVisionModel:()=>t.JinaCLIPVisionModel,Lfm2ForCausalLM:()=>t.Lfm2ForCausalLM,Lfm2Model:()=>t.Lfm2Model,Lfm2PreTrainedModel:()=>t.Lfm2PreTrainedModel,LiteWhisperForConditionalGeneration:()=>t.LiteWhisperForConditionalGeneration,Llama4ForCausalLM:()=>t.Llama4ForCausalLM,Llama4PreTrainedModel:()=>t.Llama4PreTrainedModel,LlamaForCausalLM:()=>t.LlamaForCausalLM,LlamaModel:()=>t.LlamaModel,LlamaPreTrainedModel:()=>t.LlamaPreTrainedModel,LlamaTokenizer:()=>s.LlamaTokenizer,LlavaForConditionalGeneration:()=>t.LlavaForConditionalGeneration,LlavaOnevisionForConditionalGeneration:()=>t.LlavaOnevisionForConditionalGeneration,LlavaOnevisionImageProcessor:()=>_.LlavaOnevisionImageProcessor,LlavaPreTrainedModel:()=>t.LlavaPreTrainedModel,LlavaProcessor:()=>w.LlavaProcessor,LlavaQwen2ForCausalLM:()=>t.LlavaQwen2ForCausalLM,LogitsProcessor:()=>M.LogitsProcessor,LogitsProcessorList:()=>M.LogitsProcessorList,LogitsWarper:()=>M.LogitsWarper,LongT5ForConditionalGeneration:()=>t.LongT5ForConditionalGeneration,LongT5Model:()=>t.LongT5Model,LongT5PreTrainedModel:()=>t.LongT5PreTrainedModel,M2M100ForConditionalGeneration:()=>t.M2M100ForConditionalGeneration,M2M100Model:()=>t.M2M100Model,M2M100PreTrainedModel:()=>t.M2M100PreTrainedModel,M2M100Tokenizer:()=>s.M2M100Tokenizer,MBart50Tokenizer:()=>s.MBart50Tokenizer,MBartForCausalLM:()=>t.MBartForCausalLM,MBartForConditionalGeneration:()=>t.MBartForConditionalGeneration,MBartForSequenceClassification:()=>t.MBartForSequenceClassification,MBartModel:()=>t.MBartModel,MBartPreTrainedModel:()=>t.MBartPreTrainedModel,MBartTokenizer:()=>s.MBartTokenizer,MPNetForMaskedLM:()=>t.MPNetForMaskedLM,MPNetForQuestionAnswering:()=>t.MPNetForQuestionAnswering,MPNetForSequenceClassification:()=>t.MPNetForSequenceClassification,MPNetForTokenClassification:()=>t.MPNetForTokenClassification,MPNetModel:()=>t.MPNetModel,MPNetPreTrainedModel:()=>t.MPNetPreTrainedModel,MPNetTokenizer:()=>s.MPNetTokenizer,MT5ForConditionalGeneration:()=>t.MT5ForConditionalGeneration,MT5Model:()=>t.MT5Model,MT5PreTrainedModel:()=>t.MT5PreTrainedModel,MarianMTModel:()=>t.MarianMTModel,MarianModel:()=>t.MarianModel,MarianPreTrainedModel:()=>t.MarianPreTrainedModel,MarianTokenizer:()=>s.MarianTokenizer,Mask2FormerImageProcessor:()=>_.Mask2FormerImageProcessor,MaskFormerFeatureExtractor:()=>_.MaskFormerFeatureExtractor,MaskFormerForInstanceSegmentation:()=>t.MaskFormerForInstanceSegmentation,MaskFormerImageProcessor:()=>_.MaskFormerImageProcessor,MaskFormerModel:()=>t.MaskFormerModel,MaskFormerPreTrainedModel:()=>t.MaskFormerPreTrainedModel,MaskedLMOutput:()=>t.MaskedLMOutput,MaxLengthCriteria:()=>T.MaxLengthCriteria,Metric3DForDepthEstimation:()=>t.Metric3DForDepthEstimation,Metric3DPreTrainedModel:()=>t.Metric3DPreTrainedModel,Metric3Dv2ForDepthEstimation:()=>t.Metric3Dv2ForDepthEstimation,Metric3Dv2PreTrainedModel:()=>t.Metric3Dv2PreTrainedModel,MgpstrForSceneTextRecognition:()=>t.MgpstrForSceneTextRecognition,MgpstrModelOutput:()=>t.MgpstrModelOutput,MgpstrPreTrainedModel:()=>t.MgpstrPreTrainedModel,MgpstrProcessor:()=>w.MgpstrProcessor,MgpstrTokenizer:()=>s.MgpstrTokenizer,MimiDecoderModel:()=>t.MimiDecoderModel,MimiDecoderOutput:()=>t.MimiDecoderOutput,MimiEncoderModel:()=>t.MimiEncoderModel,MimiEncoderOutput:()=>t.MimiEncoderOutput,MimiModel:()=>t.MimiModel,MimiPreTrainedModel:()=>t.MimiPreTrainedModel,MinLengthLogitsProcessor:()=>M.MinLengthLogitsProcessor,MinNewTokensLengthLogitsProcessor:()=>M.MinNewTokensLengthLogitsProcessor,Ministral3ForCausalLM:()=>t.Ministral3ForCausalLM,Ministral3Model:()=>t.Ministral3Model,Ministral3PreTrainedModel:()=>t.Ministral3PreTrainedModel,MinistralForCausalLM:()=>t.MinistralForCausalLM,MinistralModel:()=>t.MinistralModel,MinistralPreTrainedModel:()=>t.MinistralPreTrainedModel,Mistral3ForConditionalGeneration:()=>t.Mistral3ForConditionalGeneration,MistralForCausalLM:()=>t.MistralForCausalLM,MistralModel:()=>t.MistralModel,MistralPreTrainedModel:()=>t.MistralPreTrainedModel,MobileBertForMaskedLM:()=>t.MobileBertForMaskedLM,MobileBertForQuestionAnswering:()=>t.MobileBertForQuestionAnswering,MobileBertForSequenceClassification:()=>t.MobileBertForSequenceClassification,MobileBertModel:()=>t.MobileBertModel,MobileBertPreTrainedModel:()=>t.MobileBertPreTrainedModel,MobileBertTokenizer:()=>s.MobileBertTokenizer,MobileLLMForCausalLM:()=>t.MobileLLMForCausalLM,MobileLLMModel:()=>t.MobileLLMModel,MobileLLMPreTrainedModel:()=>t.MobileLLMPreTrainedModel,MobileNetV1FeatureExtractor:()=>_.MobileNetV1FeatureExtractor,MobileNetV1ForImageClassification:()=>t.MobileNetV1ForImageClassification,MobileNetV1ForSemanticSegmentation:()=>t.MobileNetV1ForSemanticSegmentation,MobileNetV1ImageProcessor:()=>_.MobileNetV1ImageProcessor,MobileNetV1Model:()=>t.MobileNetV1Model,MobileNetV1PreTrainedModel:()=>t.MobileNetV1PreTrainedModel,MobileNetV2FeatureExtractor:()=>_.MobileNetV2FeatureExtractor,MobileNetV2ForImageClassification:()=>t.MobileNetV2ForImageClassification,MobileNetV2ForSemanticSegmentation:()=>t.MobileNetV2ForSemanticSegmentation,MobileNetV2ImageProcessor:()=>_.MobileNetV2ImageProcessor,MobileNetV2Model:()=>t.MobileNetV2Model,MobileNetV2PreTrainedModel:()=>t.MobileNetV2PreTrainedModel,MobileNetV3FeatureExtractor:()=>_.MobileNetV3FeatureExtractor,MobileNetV3ForImageClassification:()=>t.MobileNetV3ForImageClassification,MobileNetV3ForSemanticSegmentation:()=>t.MobileNetV3ForSemanticSegmentation,MobileNetV3ImageProcessor:()=>_.MobileNetV3ImageProcessor,MobileNetV3Model:()=>t.MobileNetV3Model,MobileNetV3PreTrainedModel:()=>t.MobileNetV3PreTrainedModel,MobileNetV4FeatureExtractor:()=>_.MobileNetV4FeatureExtractor,MobileNetV4ForImageClassification:()=>t.MobileNetV4ForImageClassification,MobileNetV4ForSemanticSegmentation:()=>t.MobileNetV4ForSemanticSegmentation,MobileNetV4ImageProcessor:()=>_.MobileNetV4ImageProcessor,MobileNetV4Model:()=>t.MobileNetV4Model,MobileNetV4PreTrainedModel:()=>t.MobileNetV4PreTrainedModel,MobileViTFeatureExtractor:()=>_.MobileViTFeatureExtractor,MobileViTForImageClassification:()=>t.MobileViTForImageClassification,MobileViTImageProcessor:()=>_.MobileViTImageProcessor,MobileViTModel:()=>t.MobileViTModel,MobileViTPreTrainedModel:()=>t.MobileViTPreTrainedModel,MobileViTV2ForImageClassification:()=>t.MobileViTV2ForImageClassification,MobileViTV2Model:()=>t.MobileViTV2Model,MobileViTV2PreTrainedModel:()=>t.MobileViTV2PreTrainedModel,ModelOutput:()=>t.ModelOutput,ModernBertDecoderForCausalLM:()=>t.ModernBertDecoderForCausalLM,ModernBertDecoderModel:()=>t.ModernBertDecoderModel,ModernBertDecoderPreTrainedModel:()=>t.ModernBertDecoderPreTrainedModel,ModernBertForMaskedLM:()=>t.ModernBertForMaskedLM,ModernBertForSequenceClassification:()=>t.ModernBertForSequenceClassification,ModernBertForTokenClassification:()=>t.ModernBertForTokenClassification,ModernBertModel:()=>t.ModernBertModel,ModernBertPreTrainedModel:()=>t.ModernBertPreTrainedModel,Moondream1ForConditionalGeneration:()=>t.Moondream1ForConditionalGeneration,MoonshineFeatureExtractor:()=>d.MoonshineFeatureExtractor,MoonshineForConditionalGeneration:()=>t.MoonshineForConditionalGeneration,MoonshineModel:()=>t.MoonshineModel,MoonshinePreTrainedModel:()=>t.MoonshinePreTrainedModel,MoonshineProcessor:()=>w.MoonshineProcessor,MptForCausalLM:()=>t.MptForCausalLM,MptModel:()=>t.MptModel,MptPreTrainedModel:()=>t.MptPreTrainedModel,MultiModalityCausalLM:()=>t.MultiModalityCausalLM,MultiModalityPreTrainedModel:()=>t.MultiModalityPreTrainedModel,MusicgenForCausalLM:()=>t.MusicgenForCausalLM,MusicgenForConditionalGeneration:()=>t.MusicgenForConditionalGeneration,MusicgenModel:()=>t.MusicgenModel,MusicgenPreTrainedModel:()=>t.MusicgenPreTrainedModel,NanoChatForCausalLM:()=>t.NanoChatForCausalLM,NanoChatModel:()=>t.NanoChatModel,NanoChatPreTrainedModel:()=>t.NanoChatPreTrainedModel,NeoBertForMaskedLM:()=>t.NeoBertForMaskedLM,NeoBertForQuestionAnswering:()=>t.NeoBertForQuestionAnswering,NeoBertForSequenceClassification:()=>t.NeoBertForSequenceClassification,NeoBertForTokenClassification:()=>t.NeoBertForTokenClassification,NeoBertModel:()=>t.NeoBertModel,NeoBertPreTrainedModel:()=>t.NeoBertPreTrainedModel,NllbTokenizer:()=>s.NllbTokenizer,NoBadWordsLogitsProcessor:()=>M.NoBadWordsLogitsProcessor,NoRepeatNGramLogitsProcessor:()=>M.NoRepeatNGramLogitsProcessor,NomicBertModel:()=>t.NomicBertModel,NomicBertPreTrainedModel:()=>t.NomicBertPreTrainedModel,NougatImageProcessor:()=>_.NougatImageProcessor,NougatTokenizer:()=>s.NougatTokenizer,OPTForCausalLM:()=>t.OPTForCausalLM,OPTModel:()=>t.OPTModel,OPTPreTrainedModel:()=>t.OPTPreTrainedModel,ObjectDetectionPipeline:()=>r.ObjectDetectionPipeline,Olmo2ForCausalLM:()=>t.Olmo2ForCausalLM,Olmo2Model:()=>t.Olmo2Model,Olmo2PreTrainedModel:()=>t.Olmo2PreTrainedModel,OlmoForCausalLM:()=>t.OlmoForCausalLM,OlmoModel:()=>t.OlmoModel,OlmoPreTrainedModel:()=>t.OlmoPreTrainedModel,OpenELMForCausalLM:()=>t.OpenELMForCausalLM,OpenELMModel:()=>t.OpenELMModel,OpenELMPreTrainedModel:()=>t.OpenELMPreTrainedModel,OwlViTFeatureExtractor:()=>_.OwlViTFeatureExtractor,OwlViTForObjectDetection:()=>t.OwlViTForObjectDetection,OwlViTImageProcessor:()=>_.OwlViTImageProcessor,OwlViTModel:()=>t.OwlViTModel,OwlViTPreTrainedModel:()=>t.OwlViTPreTrainedModel,OwlViTProcessor:()=>w.OwlViTProcessor,Owlv2ForObjectDetection:()=>t.Owlv2ForObjectDetection,Owlv2ImageProcessor:()=>_.Owlv2ImageProcessor,Owlv2Model:()=>t.Owlv2Model,Owlv2PreTrainedModel:()=>t.Owlv2PreTrainedModel,PaliGemmaForConditionalGeneration:()=>t.PaliGemmaForConditionalGeneration,PaliGemmaPreTrainedModel:()=>t.PaliGemmaPreTrainedModel,PaliGemmaProcessor:()=>w.PaliGemmaProcessor,ParakeetFeatureExtractor:()=>d.ParakeetFeatureExtractor,ParakeetForCTC:()=>t.ParakeetForCTC,ParakeetPreTrainedModel:()=>t.ParakeetPreTrainedModel,PatchTSMixerForPrediction:()=>t.PatchTSMixerForPrediction,PatchTSMixerModel:()=>t.PatchTSMixerModel,PatchTSMixerPreTrainedModel:()=>t.PatchTSMixerPreTrainedModel,PatchTSTForPrediction:()=>t.PatchTSTForPrediction,PatchTSTModel:()=>t.PatchTSTModel,PatchTSTPreTrainedModel:()=>t.PatchTSTPreTrainedModel,Phi3ForCausalLM:()=>t.Phi3ForCausalLM,Phi3Model:()=>t.Phi3Model,Phi3PreTrainedModel:()=>t.Phi3PreTrainedModel,Phi3VForCausalLM:()=>t.Phi3VForCausalLM,Phi3VImageProcessor:()=>_.Phi3VImageProcessor,Phi3VPreTrainedModel:()=>t.Phi3VPreTrainedModel,Phi3VProcessor:()=>w.Phi3VProcessor,PhiForCausalLM:()=>t.PhiForCausalLM,PhiModel:()=>t.PhiModel,PhiPreTrainedModel:()=>t.PhiPreTrainedModel,Pipeline:()=>r.Pipeline,PixtralImageProcessor:()=>_.PixtralImageProcessor,PixtralProcessor:()=>w.PixtralProcessor,PreTrainedModel:()=>t.PreTrainedModel,PreTrainedTokenizer:()=>s.PreTrainedTokenizer,PretrainedConfig:()=>o.PretrainedConfig,PretrainedMixin:()=>t.PretrainedMixin,Processor:()=>k.Processor,PvtForImageClassification:()=>t.PvtForImageClassification,PvtImageProcessor:()=>_.PvtImageProcessor,PvtModel:()=>t.PvtModel,PvtPreTrainedModel:()=>t.PvtPreTrainedModel,PyAnnoteFeatureExtractor:()=>d.PyAnnoteFeatureExtractor,PyAnnoteForAudioFrameClassification:()=>t.PyAnnoteForAudioFrameClassification,PyAnnoteModel:()=>t.PyAnnoteModel,PyAnnotePreTrainedModel:()=>t.PyAnnotePreTrainedModel,PyAnnoteProcessor:()=>w.PyAnnoteProcessor,QuestionAnsweringModelOutput:()=>t.QuestionAnsweringModelOutput,QuestionAnsweringPipeline:()=>r.QuestionAnsweringPipeline,Qwen2ForCausalLM:()=>t.Qwen2ForCausalLM,Qwen2Model:()=>t.Qwen2Model,Qwen2PreTrainedModel:()=>t.Qwen2PreTrainedModel,Qwen2Tokenizer:()=>s.Qwen2Tokenizer,Qwen2VLForConditionalGeneration:()=>t.Qwen2VLForConditionalGeneration,Qwen2VLImageProcessor:()=>_.Qwen2VLImageProcessor,Qwen2VLPreTrainedModel:()=>t.Qwen2VLPreTrainedModel,Qwen2VLProcessor:()=>w.Qwen2VLProcessor,Qwen3ForCausalLM:()=>t.Qwen3ForCausalLM,Qwen3Model:()=>t.Qwen3Model,Qwen3PreTrainedModel:()=>t.Qwen3PreTrainedModel,RFDetrForObjectDetection:()=>t.RFDetrForObjectDetection,RFDetrModel:()=>t.RFDetrModel,RFDetrObjectDetectionOutput:()=>t.RFDetrObjectDetectionOutput,RFDetrPreTrainedModel:()=>t.RFDetrPreTrainedModel,RTDetrForObjectDetection:()=>t.RTDetrForObjectDetection,RTDetrImageProcessor:()=>_.RTDetrImageProcessor,RTDetrModel:()=>t.RTDetrModel,RTDetrObjectDetectionOutput:()=>t.RTDetrObjectDetectionOutput,RTDetrPreTrainedModel:()=>t.RTDetrPreTrainedModel,RTDetrV2ForObjectDetection:()=>t.RTDetrV2ForObjectDetection,RTDetrV2Model:()=>t.RTDetrV2Model,RTDetrV2ObjectDetectionOutput:()=>t.RTDetrV2ObjectDetectionOutput,RTDetrV2PreTrainedModel:()=>t.RTDetrV2PreTrainedModel,RawAudio:()=>n.RawAudio,RawImage:()=>a.RawImage,RawVideo:()=>i.RawVideo,RawVideoFrame:()=>i.RawVideoFrame,RepetitionPenaltyLogitsProcessor:()=>M.RepetitionPenaltyLogitsProcessor,ResNetForImageClassification:()=>t.ResNetForImageClassification,ResNetModel:()=>t.ResNetModel,ResNetPreTrainedModel:()=>t.ResNetPreTrainedModel,RoFormerForMaskedLM:()=>t.RoFormerForMaskedLM,RoFormerForQuestionAnswering:()=>t.RoFormerForQuestionAnswering,RoFormerForSequenceClassification:()=>t.RoFormerForSequenceClassification,RoFormerForTokenClassification:()=>t.RoFormerForTokenClassification,RoFormerModel:()=>t.RoFormerModel,RoFormerPreTrainedModel:()=>t.RoFormerPreTrainedModel,RoFormerTokenizer:()=>s.RoFormerTokenizer,RobertaForMaskedLM:()=>t.RobertaForMaskedLM,RobertaForQuestionAnswering:()=>t.RobertaForQuestionAnswering,RobertaForSequenceClassification:()=>t.RobertaForSequenceClassification,RobertaForTokenClassification:()=>t.RobertaForTokenClassification,RobertaModel:()=>t.RobertaModel,RobertaPreTrainedModel:()=>t.RobertaPreTrainedModel,RobertaTokenizer:()=>s.RobertaTokenizer,Sam2ImageProcessor:()=>_.Sam2ImageProcessor,Sam2ImageSegmentationOutput:()=>t.Sam2ImageSegmentationOutput,Sam2Model:()=>t.Sam2Model,Sam2PreTrainedModel:()=>t.Sam2PreTrainedModel,Sam2Processor:()=>w.Sam2Processor,Sam2VideoProcessor:()=>w.Sam2VideoProcessor,Sam3ImageProcessor:()=>_.Sam3ImageProcessor,Sam3TrackerModel:()=>t.Sam3TrackerModel,SamImageProcessor:()=>_.SamImageProcessor,SamImageSegmentationOutput:()=>t.SamImageSegmentationOutput,SamModel:()=>t.SamModel,SamPreTrainedModel:()=>t.SamPreTrainedModel,SamProcessor:()=>w.SamProcessor,SapiensForDepthEstimation:()=>t.SapiensForDepthEstimation,SapiensForNormalEstimation:()=>t.SapiensForNormalEstimation,SapiensForSemanticSegmentation:()=>t.SapiensForSemanticSegmentation,SapiensPreTrainedModel:()=>t.SapiensPreTrainedModel,SeamlessM4TFeatureExtractor:()=>d.SeamlessM4TFeatureExtractor,SegformerFeatureExtractor:()=>_.SegformerFeatureExtractor,SegformerForImageClassification:()=>t.SegformerForImageClassification,SegformerForSemanticSegmentation:()=>t.SegformerForSemanticSegmentation,SegformerImageProcessor:()=>_.SegformerImageProcessor,SegformerModel:()=>t.SegformerModel,SegformerPreTrainedModel:()=>t.SegformerPreTrainedModel,Seq2SeqLMOutput:()=>t.Seq2SeqLMOutput,SequenceClassifierOutput:()=>t.SequenceClassifierOutput,SiglipImageProcessor:()=>_.SiglipImageProcessor,SiglipModel:()=>t.SiglipModel,SiglipPreTrainedModel:()=>t.SiglipPreTrainedModel,SiglipTextModel:()=>t.SiglipTextModel,SiglipTokenizer:()=>s.SiglipTokenizer,SiglipVisionModel:()=>t.SiglipVisionModel,SmolLM3ForCausalLM:()=>t.SmolLM3ForCausalLM,SmolLM3Model:()=>t.SmolLM3Model,SmolLM3PreTrainedModel:()=>t.SmolLM3PreTrainedModel,SmolVLMForConditionalGeneration:()=>t.SmolVLMForConditionalGeneration,SmolVLMImageProcessor:()=>_.SmolVLMImageProcessor,SmolVLMProcessor:()=>w.SmolVLMProcessor,SnacDecoderModel:()=>t.SnacDecoderModel,SnacEncoderModel:()=>t.SnacEncoderModel,SnacFeatureExtractor:()=>d.SnacFeatureExtractor,SnacModel:()=>t.SnacModel,SnacPreTrainedModel:()=>t.SnacPreTrainedModel,SpeechT5FeatureExtractor:()=>d.SpeechT5FeatureExtractor,SpeechT5ForSpeechToText:()=>t.SpeechT5ForSpeechToText,SpeechT5ForTextToSpeech:()=>t.SpeechT5ForTextToSpeech,SpeechT5HifiGan:()=>t.SpeechT5HifiGan,SpeechT5Model:()=>t.SpeechT5Model,SpeechT5PreTrainedModel:()=>t.SpeechT5PreTrainedModel,SpeechT5Processor:()=>w.SpeechT5Processor,SpeechT5Tokenizer:()=>s.SpeechT5Tokenizer,SqueezeBertForMaskedLM:()=>t.SqueezeBertForMaskedLM,SqueezeBertForQuestionAnswering:()=>t.SqueezeBertForQuestionAnswering,SqueezeBertForSequenceClassification:()=>t.SqueezeBertForSequenceClassification,SqueezeBertModel:()=>t.SqueezeBertModel,SqueezeBertPreTrainedModel:()=>t.SqueezeBertPreTrainedModel,SqueezeBertTokenizer:()=>s.SqueezeBertTokenizer,StableLmForCausalLM:()=>t.StableLmForCausalLM,StableLmModel:()=>t.StableLmModel,StableLmPreTrainedModel:()=>t.StableLmPreTrainedModel,Starcoder2ForCausalLM:()=>t.Starcoder2ForCausalLM,Starcoder2Model:()=>t.Starcoder2Model,Starcoder2PreTrainedModel:()=>t.Starcoder2PreTrainedModel,StoppingCriteria:()=>T.StoppingCriteria,StoppingCriteriaList:()=>T.StoppingCriteriaList,StyleTextToSpeech2Model:()=>t.StyleTextToSpeech2Model,StyleTextToSpeech2PreTrainedModel:()=>t.StyleTextToSpeech2PreTrainedModel,SummarizationPipeline:()=>r.SummarizationPipeline,SupertonicForConditionalGeneration:()=>t.SupertonicForConditionalGeneration,SupertonicPreTrainedModel:()=>t.SupertonicPreTrainedModel,SuppressTokensAtBeginLogitsProcessor:()=>M.SuppressTokensAtBeginLogitsProcessor,Swin2SRForImageSuperResolution:()=>t.Swin2SRForImageSuperResolution,Swin2SRImageProcessor:()=>_.Swin2SRImageProcessor,Swin2SRModel:()=>t.Swin2SRModel,Swin2SRPreTrainedModel:()=>t.Swin2SRPreTrainedModel,SwinForImageClassification:()=>t.SwinForImageClassification,SwinForSemanticSegmentation:()=>t.SwinForSemanticSegmentation,SwinModel:()=>t.SwinModel,SwinPreTrainedModel:()=>t.SwinPreTrainedModel,T5ForConditionalGeneration:()=>t.T5ForConditionalGeneration,T5Model:()=>t.T5Model,T5PreTrainedModel:()=>t.T5PreTrainedModel,T5Tokenizer:()=>s.T5Tokenizer,TableTransformerForObjectDetection:()=>t.TableTransformerForObjectDetection,TableTransformerModel:()=>t.TableTransformerModel,TableTransformerObjectDetectionOutput:()=>t.TableTransformerObjectDetectionOutput,TableTransformerPreTrainedModel:()=>t.TableTransformerPreTrainedModel,TemperatureLogitsWarper:()=>M.TemperatureLogitsWarper,Tensor:()=>l.Tensor,Text2TextGenerationPipeline:()=>r.Text2TextGenerationPipeline,TextClassificationPipeline:()=>r.TextClassificationPipeline,TextGenerationPipeline:()=>r.TextGenerationPipeline,TextStreamer:()=>$.TextStreamer,TextToAudioPipeline:()=>r.TextToAudioPipeline,TokenClassificationPipeline:()=>r.TokenClassificationPipeline,TokenClassifierOutput:()=>t.TokenClassifierOutput,TokenizerModel:()=>s.TokenizerModel,TopKLogitsWarper:()=>M.TopKLogitsWarper,TopPLogitsWarper:()=>M.TopPLogitsWarper,TrOCRForCausalLM:()=>t.TrOCRForCausalLM,TrOCRPreTrainedModel:()=>t.TrOCRPreTrainedModel,TranslationPipeline:()=>r.TranslationPipeline,UltravoxModel:()=>t.UltravoxModel,UltravoxPreTrainedModel:()=>t.UltravoxPreTrainedModel,UltravoxProcessor:()=>w.UltravoxProcessor,UniSpeechForCTC:()=>t.UniSpeechForCTC,UniSpeechForSequenceClassification:()=>t.UniSpeechForSequenceClassification,UniSpeechModel:()=>t.UniSpeechModel,UniSpeechPreTrainedModel:()=>t.UniSpeechPreTrainedModel,UniSpeechSatForAudioFrameClassification:()=>t.UniSpeechSatForAudioFrameClassification,UniSpeechSatForCTC:()=>t.UniSpeechSatForCTC,UniSpeechSatForSequenceClassification:()=>t.UniSpeechSatForSequenceClassification,UniSpeechSatModel:()=>t.UniSpeechSatModel,UniSpeechSatPreTrainedModel:()=>t.UniSpeechSatPreTrainedModel,VLChatProcessor:()=>w.VLChatProcessor,VLMImageProcessor:()=>_.VLMImageProcessor,VaultGemmaForCausalLM:()=>t.VaultGemmaForCausalLM,VaultGemmaModel:()=>t.VaultGemmaModel,VaultGemmaPreTrainedModel:()=>t.VaultGemmaPreTrainedModel,ViTFeatureExtractor:()=>_.ViTFeatureExtractor,ViTForImageClassification:()=>t.ViTForImageClassification,ViTImageProcessor:()=>_.ViTImageProcessor,ViTMAEModel:()=>t.ViTMAEModel,ViTMAEPreTrainedModel:()=>t.ViTMAEPreTrainedModel,ViTMSNForImageClassification:()=>t.ViTMSNForImageClassification,ViTMSNModel:()=>t.ViTMSNModel,ViTMSNPreTrainedModel:()=>t.ViTMSNPreTrainedModel,ViTModel:()=>t.ViTModel,ViTPreTrainedModel:()=>t.ViTPreTrainedModel,VisionEncoderDecoderModel:()=>t.VisionEncoderDecoderModel,VitMatteForImageMatting:()=>t.VitMatteForImageMatting,VitMatteImageProcessor:()=>_.VitMatteImageProcessor,VitMattePreTrainedModel:()=>t.VitMattePreTrainedModel,VitPoseForPoseEstimation:()=>t.VitPoseForPoseEstimation,VitPoseImageProcessor:()=>_.VitPoseImageProcessor,VitPosePreTrainedModel:()=>t.VitPosePreTrainedModel,VitsModel:()=>t.VitsModel,VitsModelOutput:()=>t.VitsModelOutput,VitsPreTrainedModel:()=>t.VitsPreTrainedModel,VitsTokenizer:()=>s.VitsTokenizer,VoxtralForConditionalGeneration:()=>t.VoxtralForConditionalGeneration,VoxtralProcessor:()=>w.VoxtralProcessor,Wav2Vec2BertForCTC:()=>t.Wav2Vec2BertForCTC,Wav2Vec2BertForSequenceClassification:()=>t.Wav2Vec2BertForSequenceClassification,Wav2Vec2BertModel:()=>t.Wav2Vec2BertModel,Wav2Vec2BertPreTrainedModel:()=>t.Wav2Vec2BertPreTrainedModel,Wav2Vec2CTCTokenizer:()=>s.Wav2Vec2CTCTokenizer,Wav2Vec2FeatureExtractor:()=>d.Wav2Vec2FeatureExtractor,Wav2Vec2ForAudioFrameClassification:()=>t.Wav2Vec2ForAudioFrameClassification,Wav2Vec2ForCTC:()=>t.Wav2Vec2ForCTC,Wav2Vec2ForSequenceClassification:()=>t.Wav2Vec2ForSequenceClassification,Wav2Vec2Model:()=>t.Wav2Vec2Model,Wav2Vec2PreTrainedModel:()=>t.Wav2Vec2PreTrainedModel,Wav2Vec2Processor:()=>w.Wav2Vec2Processor,Wav2Vec2ProcessorWithLM:()=>w.Wav2Vec2ProcessorWithLM,WavLMForAudioFrameClassification:()=>t.WavLMForAudioFrameClassification,WavLMForCTC:()=>t.WavLMForCTC,WavLMForSequenceClassification:()=>t.WavLMForSequenceClassification,WavLMForXVector:()=>t.WavLMForXVector,WavLMModel:()=>t.WavLMModel,WavLMPreTrainedModel:()=>t.WavLMPreTrainedModel,WeSpeakerFeatureExtractor:()=>d.WeSpeakerFeatureExtractor,WeSpeakerResNetModel:()=>t.WeSpeakerResNetModel,WeSpeakerResNetPreTrainedModel:()=>t.WeSpeakerResNetPreTrainedModel,WhisperFeatureExtractor:()=>d.WhisperFeatureExtractor,WhisperForConditionalGeneration:()=>t.WhisperForConditionalGeneration,WhisperModel:()=>t.WhisperModel,WhisperPreTrainedModel:()=>t.WhisperPreTrainedModel,WhisperProcessor:()=>w.WhisperProcessor,WhisperTextStreamer:()=>$.WhisperTextStreamer,WhisperTimeStampLogitsProcessor:()=>M.WhisperTimeStampLogitsProcessor,WhisperTokenizer:()=>s.WhisperTokenizer,XLMForQuestionAnswering:()=>t.XLMForQuestionAnswering,XLMForSequenceClassification:()=>t.XLMForSequenceClassification,XLMForTokenClassification:()=>t.XLMForTokenClassification,XLMModel:()=>t.XLMModel,XLMPreTrainedModel:()=>t.XLMPreTrainedModel,XLMRobertaForMaskedLM:()=>t.XLMRobertaForMaskedLM,XLMRobertaForQuestionAnswering:()=>t.XLMRobertaForQuestionAnswering,XLMRobertaForSequenceClassification:()=>t.XLMRobertaForSequenceClassification,XLMRobertaForTokenClassification:()=>t.XLMRobertaForTokenClassification,XLMRobertaModel:()=>t.XLMRobertaModel,XLMRobertaPreTrainedModel:()=>t.XLMRobertaPreTrainedModel,XLMRobertaTokenizer:()=>s.XLMRobertaTokenizer,XLMTokenizer:()=>s.XLMTokenizer,XLMWithLMHeadModel:()=>t.XLMWithLMHeadModel,XVectorOutput:()=>t.XVectorOutput,YolosFeatureExtractor:()=>_.YolosFeatureExtractor,YolosForObjectDetection:()=>t.YolosForObjectDetection,YolosImageProcessor:()=>_.YolosImageProcessor,YolosModel:()=>t.YolosModel,YolosObjectDetectionOutput:()=>t.YolosObjectDetectionOutput,YolosPreTrainedModel:()=>t.YolosPreTrainedModel,ZeroShotAudioClassificationPipeline:()=>r.ZeroShotAudioClassificationPipeline,ZeroShotClassificationPipeline:()=>r.ZeroShotClassificationPipeline,ZeroShotImageClassificationPipeline:()=>r.ZeroShotImageClassificationPipeline,ZeroShotObjectDetectionPipeline:()=>r.ZeroShotObjectDetectionPipeline,bankers_round:()=>c.bankers_round,cat:()=>l.cat,cos_sim:()=>c.cos_sim,dot:()=>c.dot,dynamic_time_warping:()=>c.dynamic_time_warping,env:()=>e.env,full:()=>l.full,full_like:()=>l.full_like,getCacheShapes:()=>o.getCacheShapes,hamming:()=>n.hamming,hanning:()=>n.hanning,interpolate:()=>l.interpolate,interpolate_4d:()=>l.interpolate_4d,interpolate_data:()=>c.interpolate_data,is_chinese_char:()=>s.is_chinese_char,layer_norm:()=>l.layer_norm,load_image:()=>a.load_image,load_video:()=>i.load_video,log_softmax:()=>c.log_softmax,magnitude:()=>c.magnitude,matmul:()=>l.matmul,max:()=>c.max,mean:()=>l.mean,mean_pooling:()=>l.mean_pooling,medianFilter:()=>c.medianFilter,mel_filter_bank:()=>n.mel_filter_bank,min:()=>c.min,ones:()=>l.ones,ones_like:()=>l.ones_like,permute:()=>l.permute,permute_data:()=>c.permute_data,pipeline:()=>r.pipeline,quantize_embeddings:()=>l.quantize_embeddings,rand:()=>l.rand,randn:()=>l.randn,read_audio:()=>n.read_audio,rfft:()=>l.rfft,round:()=>c.round,slice:()=>l.slice,softmax:()=>c.softmax,spectrogram:()=>n.spectrogram,stack:()=>l.stack,std_mean:()=>l.std_mean,topk:()=>l.topk,window_function:()=>n.window_function,zeros:()=>l.zeros,zeros_like:()=>l.zeros_like});var e=Ht("./src/env.js"),r=Ht("./src/pipelines.js"),t=Ht("./src/models.js"),s=Ht("./src/tokenizers.js"),o=Ht("./src/configs.js"),n=Ht("./src/utils/audio.js"),a=Ht("./src/utils/image.js"),i=Ht("./src/utils/video.js"),l=Ht("./src/utils/tensor.js"),c=Ht("./src/utils/maths.js"),p=Ht("./src/base/feature_extraction_utils.js"),d=Ht("./src/models/feature_extractors.js"),u=Ht("./src/models/auto/feature_extraction_auto.js"),f=Ht("./src/base/image_processors_utils.js"),_=Ht("./src/models/image_processors.js"),b=Ht("./src/models/auto/image_processing_auto.js"),k=Ht("./src/base/processing_utils.js"),w=Ht("./src/models/processors.js"),y=Ht("./src/models/auto/processing_auto.js"),$=Ht("./src/generation/streamers.js"),T=Ht("./src/generation/stopping_criteria.js"),M=Ht("./src/generation/logits_process.js")})(),m.ASTFeatureExtractor,m.ASTForAudioClassification,m.ASTModel,m.ASTPreTrainedModel,m.AlbertForMaskedLM,m.AlbertForQuestionAnswering,m.AlbertForSequenceClassification,m.AlbertModel,m.AlbertPreTrainedModel,m.AlbertTokenizer,m.ArceeForCausalLM,m.ArceeModel,m.ArceePreTrainedModel,m.AudioClassificationPipeline,m.AutoConfig,m.AutoFeatureExtractor,m.AutoImageProcessor,m.AutoModel,m.AutoModelForAudioClassification,m.AutoModelForAudioFrameClassification,m.AutoModelForAudioTextToText,m.AutoModelForCTC,m.AutoModelForCausalLM,m.AutoModelForDepthEstimation,m.AutoModelForDocumentQuestionAnswering,m.AutoModelForImageClassification,m.AutoModelForImageFeatureExtraction,m.AutoModelForImageMatting,m.AutoModelForImageSegmentation,m.AutoModelForImageTextToText,m.AutoModelForImageToImage,m.AutoModelForMaskGeneration,m.AutoModelForMaskedLM,m.AutoModelForNormalEstimation,m.AutoModelForObjectDetection,m.AutoModelForPoseEstimation,m.AutoModelForQuestionAnswering,m.AutoModelForSemanticSegmentation,m.AutoModelForSeq2SeqLM,m.AutoModelForSequenceClassification,m.AutoModelForSpeechSeq2Seq,m.AutoModelForTextToSpectrogram,m.AutoModelForTextToWaveform,m.AutoModelForTokenClassification,m.AutoModelForUniversalSegmentation,m.AutoModelForVision2Seq,m.AutoModelForXVector,m.AutoModelForZeroShotObjectDetection,m.AutoProcessor,m.AutoTokenizer,m.AutomaticSpeechRecognitionPipeline,m.BackgroundRemovalPipeline,m.BartForConditionalGeneration,m.BartForSequenceClassification,m.BartModel,m.BartPretrainedModel,m.BartTokenizer,m.BaseModelOutput,m.BaseStreamer,m.BeitFeatureExtractor,m.BeitForImageClassification,m.BeitModel,m.BeitPreTrainedModel,m.BertForMaskedLM,m.BertForQuestionAnswering,m.BertForSequenceClassification,m.BertForTokenClassification,m.BertModel,m.BertPreTrainedModel,m.BertTokenizer,m.BitImageProcessor,m.BlenderbotForConditionalGeneration,m.BlenderbotModel,m.BlenderbotPreTrainedModel,m.BlenderbotSmallForConditionalGeneration,m.BlenderbotSmallModel,m.BlenderbotSmallPreTrainedModel,m.BlenderbotSmallTokenizer,m.BlenderbotTokenizer,m.BloomForCausalLM,m.BloomModel,m.BloomPreTrainedModel,m.BloomTokenizer,m.CLIPFeatureExtractor,m.CLIPImageProcessor,m.CLIPModel,m.CLIPPreTrainedModel,m.CLIPSegForImageSegmentation,m.CLIPSegModel,m.CLIPSegPreTrainedModel,m.CLIPTextModel,m.CLIPTextModelWithProjection,m.CLIPTokenizer,m.CLIPVisionModel,m.CLIPVisionModelWithProjection,m.CamembertForMaskedLM,m.CamembertForQuestionAnswering,m.CamembertForSequenceClassification,m.CamembertForTokenClassification,m.CamembertModel,m.CamembertPreTrainedModel,m.CamembertTokenizer,m.CausalLMOutput,m.CausalLMOutputWithPast,m.ChineseCLIPFeatureExtractor,m.ChineseCLIPModel,m.ChineseCLIPPreTrainedModel,m.ClapAudioModelWithProjection,m.ClapFeatureExtractor,m.ClapModel,m.ClapPreTrainedModel,m.ClapTextModelWithProjection,m.ClassifierFreeGuidanceLogitsProcessor,m.CodeGenForCausalLM,m.CodeGenModel,m.CodeGenPreTrainedModel,m.CodeGenTokenizer,m.CodeLlamaTokenizer,m.CohereForCausalLM,m.CohereModel,m.CoherePreTrainedModel,m.CohereTokenizer,m.ConvBertForMaskedLM,m.ConvBertForQuestionAnswering,m.ConvBertForSequenceClassification,m.ConvBertForTokenClassification,m.ConvBertModel,m.ConvBertPreTrainedModel,m.ConvBertTokenizer,m.ConvNextFeatureExtractor,m.ConvNextForImageClassification,m.ConvNextImageProcessor,m.ConvNextModel,m.ConvNextPreTrainedModel,m.ConvNextV2ForImageClassification,m.ConvNextV2Model,m.ConvNextV2PreTrainedModel,m.DFineForObjectDetection,m.DFineModel,m.DFinePreTrainedModel,m.DINOv3ConvNextModel,m.DINOv3ConvNextPreTrainedModel,m.DINOv3ViTImageProcessor,m.DINOv3ViTModel,m.DINOv3ViTPreTrainedModel,m.DPTFeatureExtractor,m.DPTForDepthEstimation,m.DPTImageProcessor,m.DPTModel,m.DPTPreTrainedModel,m.DacDecoderModel,m.DacDecoderOutput,m.DacEncoderModel,m.DacEncoderOutput,m.DacFeatureExtractor,m.DacModel,m.DacPreTrainedModel,m.DataTypeMap,m.DebertaForMaskedLM,m.DebertaForQuestionAnswering,m.DebertaForSequenceClassification,m.DebertaForTokenClassification,m.DebertaModel,m.DebertaPreTrainedModel,m.DebertaTokenizer,m.DebertaV2ForMaskedLM,m.DebertaV2ForQuestionAnswering,m.DebertaV2ForSequenceClassification,m.DebertaV2ForTokenClassification,m.DebertaV2Model,m.DebertaV2PreTrainedModel,m.DebertaV2Tokenizer,m.DecisionTransformerModel,m.DecisionTransformerPreTrainedModel,m.DeiTFeatureExtractor,m.DeiTForImageClassification,m.DeiTImageProcessor,m.DeiTModel,m.DeiTPreTrainedModel,m.DepthAnythingForDepthEstimation,m.DepthAnythingPreTrainedModel,m.DepthEstimationPipeline,m.DepthProForDepthEstimation,m.DepthProPreTrainedModel,m.DetrFeatureExtractor,m.DetrForObjectDetection,m.DetrForSegmentation,m.DetrImageProcessor,m.DetrModel,m.DetrObjectDetectionOutput,m.DetrPreTrainedModel,m.DetrSegmentationOutput,m.Dinov2ForImageClassification,m.Dinov2Model,m.Dinov2PreTrainedModel,m.Dinov2WithRegistersForImageClassification,m.Dinov2WithRegistersModel,m.Dinov2WithRegistersPreTrainedModel,m.DistilBertForMaskedLM,m.DistilBertForQuestionAnswering,m.DistilBertForSequenceClassification,m.DistilBertForTokenClassification,m.DistilBertModel,m.DistilBertPreTrainedModel,m.DistilBertTokenizer,m.DocumentQuestionAnsweringPipeline,m.DonutFeatureExtractor,m.DonutImageProcessor,m.DonutSwinModel,m.DonutSwinPreTrainedModel,m.EdgeTamModel,m.EfficientNetForImageClassification,m.EfficientNetImageProcessor,m.EfficientNetModel,m.EfficientNetPreTrainedModel,m.ElectraForMaskedLM,m.ElectraForQuestionAnswering,m.ElectraForSequenceClassification,m.ElectraForTokenClassification,m.ElectraModel,m.ElectraPreTrainedModel,m.ElectraTokenizer,m.EncodecFeatureExtractor,m.EosTokenCriteria,m.Ernie4_5ForCausalLM,m.Ernie4_5Model,m.Ernie4_5PreTrainedModel,m.EsmForMaskedLM,m.EsmForSequenceClassification,m.EsmForTokenClassification,m.EsmModel,m.EsmPreTrainedModel,m.EsmTokenizer,m.ExaoneForCausalLM,m.ExaoneModel,m.ExaonePreTrainedModel,m.FFT,m.FalconForCausalLM,m.FalconModel,m.FalconPreTrainedModel,m.FalconTokenizer,m.FastViTForImageClassification,m.FastViTModel,m.FastViTPreTrainedModel,m.FeatureExtractionPipeline,m.FeatureExtractor,m.FillMaskPipeline,m.Florence2ForConditionalGeneration,m.Florence2PreTrainedModel,m.Florence2Processor,m.ForcedBOSTokenLogitsProcessor,m.ForcedEOSTokenLogitsProcessor,m.GLPNFeatureExtractor,m.GLPNForDepthEstimation,m.GLPNModel,m.GLPNPreTrainedModel,m.GPT2LMHeadModel,m.GPT2Model,m.GPT2PreTrainedModel,m.GPT2Tokenizer,m.GPTBigCodeForCausalLM,m.GPTBigCodeModel,m.GPTBigCodePreTrainedModel,m.GPTJForCausalLM,m.GPTJModel,m.GPTJPreTrainedModel,m.GPTNeoForCausalLM,m.GPTNeoModel,m.GPTNeoPreTrainedModel,m.GPTNeoXForCausalLM,m.GPTNeoXModel,m.GPTNeoXPreTrainedModel,m.GPTNeoXTokenizer,m.Gemma2ForCausalLM,m.Gemma2Model,m.Gemma2PreTrainedModel,m.Gemma3ForCausalLM,m.Gemma3Model,m.Gemma3PreTrainedModel,m.Gemma3nAudioFeatureExtractor,m.Gemma3nForConditionalGeneration,m.Gemma3nPreTrainedModel,m.Gemma3nProcessor,m.GemmaForCausalLM,m.GemmaModel,m.GemmaPreTrainedModel,m.GemmaTokenizer,m.GlmForCausalLM,m.GlmModel,m.GlmPreTrainedModel,m.GraniteForCausalLM,m.GraniteModel,m.GraniteMoeHybridForCausalLM,m.GraniteMoeHybridModel,m.GraniteMoeHybridPreTrainedModel,m.GranitePreTrainedModel,m.Grok1Tokenizer,m.GroundingDinoForObjectDetection,m.GroundingDinoImageProcessor,m.GroundingDinoPreTrainedModel,m.GroundingDinoProcessor,m.GroupViTModel,m.GroupViTPreTrainedModel,m.HeliumForCausalLM,m.HeliumModel,m.HeliumPreTrainedModel,m.HerbertTokenizer,m.HieraForImageClassification,m.HieraModel,m.HieraPreTrainedModel,m.HubertForCTC,m.HubertForSequenceClassification,m.HubertModel,m.HubertPreTrainedModel,m.IJepaForImageClassification,m.IJepaModel,m.IJepaPreTrainedModel,m.Idefics3ForConditionalGeneration,m.Idefics3ImageProcessor,m.Idefics3PreTrainedModel,m.Idefics3Processor,m.ImageClassificationPipeline,m.ImageFeatureExtractionPipeline,m.ImageFeatureExtractor,m.ImageMattingOutput,m.ImageProcessor,m.ImageSegmentationPipeline,m.ImageToImagePipeline,m.ImageToTextPipeline,m.InterruptableStoppingCriteria,m.JAISLMHeadModel,m.JAISModel,m.JAISPreTrainedModel,m.JinaCLIPImageProcessor,m.JinaCLIPModel,m.JinaCLIPPreTrainedModel,m.JinaCLIPProcessor,m.JinaCLIPTextModel,m.JinaCLIPVisionModel,m.Lfm2ForCausalLM,m.Lfm2Model,m.Lfm2PreTrainedModel,m.LiteWhisperForConditionalGeneration,m.Llama4ForCausalLM,m.Llama4PreTrainedModel,m.LlamaForCausalLM,m.LlamaModel,m.LlamaPreTrainedModel,m.LlamaTokenizer,m.LlavaForConditionalGeneration,m.LlavaOnevisionForConditionalGeneration,m.LlavaOnevisionImageProcessor,m.LlavaPreTrainedModel,m.LlavaProcessor,m.LlavaQwen2ForCausalLM,m.LogitsProcessor,m.LogitsProcessorList,m.LogitsWarper,m.LongT5ForConditionalGeneration,m.LongT5Model,m.LongT5PreTrainedModel,m.M2M100ForConditionalGeneration,m.M2M100Model,m.M2M100PreTrainedModel,m.M2M100Tokenizer,m.MBart50Tokenizer,m.MBartForCausalLM,m.MBartForConditionalGeneration,m.MBartForSequenceClassification,m.MBartModel,m.MBartPreTrainedModel,m.MBartTokenizer,m.MPNetForMaskedLM,m.MPNetForQuestionAnswering,m.MPNetForSequenceClassification,m.MPNetForTokenClassification,m.MPNetModel,m.MPNetPreTrainedModel,m.MPNetTokenizer,m.MT5ForConditionalGeneration,m.MT5Model,m.MT5PreTrainedModel,m.MarianMTModel,m.MarianModel,m.MarianPreTrainedModel,m.MarianTokenizer,m.Mask2FormerImageProcessor,m.MaskFormerFeatureExtractor,m.MaskFormerForInstanceSegmentation,m.MaskFormerImageProcessor,m.MaskFormerModel,m.MaskFormerPreTrainedModel,m.MaskedLMOutput,m.MaxLengthCriteria,m.Metric3DForDepthEstimation,m.Metric3DPreTrainedModel,m.Metric3Dv2ForDepthEstimation,m.Metric3Dv2PreTrainedModel,m.MgpstrForSceneTextRecognition,m.MgpstrModelOutput,m.MgpstrPreTrainedModel,m.MgpstrProcessor,m.MgpstrTokenizer,m.MimiDecoderModel,m.MimiDecoderOutput,m.MimiEncoderModel,m.MimiEncoderOutput,m.MimiModel,m.MimiPreTrainedModel,m.MinLengthLogitsProcessor,m.MinNewTokensLengthLogitsProcessor,m.Ministral3ForCausalLM,m.Ministral3Model,m.Ministral3PreTrainedModel,m.MinistralForCausalLM,m.MinistralModel,m.MinistralPreTrainedModel,m.Mistral3ForConditionalGeneration,m.MistralForCausalLM,m.MistralModel,m.MistralPreTrainedModel,m.MobileBertForMaskedLM,m.MobileBertForQuestionAnswering,m.MobileBertForSequenceClassification,m.MobileBertModel,m.MobileBertPreTrainedModel,m.MobileBertTokenizer,m.MobileLLMForCausalLM,m.MobileLLMModel,m.MobileLLMPreTrainedModel,m.MobileNetV1FeatureExtractor,m.MobileNetV1ForImageClassification,m.MobileNetV1ForSemanticSegmentation,m.MobileNetV1ImageProcessor,m.MobileNetV1Model,m.MobileNetV1PreTrainedModel,m.MobileNetV2FeatureExtractor,m.MobileNetV2ForImageClassification,m.MobileNetV2ForSemanticSegmentation,m.MobileNetV2ImageProcessor,m.MobileNetV2Model,m.MobileNetV2PreTrainedModel,m.MobileNetV3FeatureExtractor,m.MobileNetV3ForImageClassification,m.MobileNetV3ForSemanticSegmentation,m.MobileNetV3ImageProcessor,m.MobileNetV3Model,m.MobileNetV3PreTrainedModel,m.MobileNetV4FeatureExtractor,m.MobileNetV4ForImageClassification,m.MobileNetV4ForSemanticSegmentation,m.MobileNetV4ImageProcessor,m.MobileNetV4Model,m.MobileNetV4PreTrainedModel,m.MobileViTFeatureExtractor,m.MobileViTForImageClassification,m.MobileViTImageProcessor,m.MobileViTModel,m.MobileViTPreTrainedModel,m.MobileViTV2ForImageClassification,m.MobileViTV2Model,m.MobileViTV2PreTrainedModel,m.ModelOutput,m.ModernBertDecoderForCausalLM,m.ModernBertDecoderModel,m.ModernBertDecoderPreTrainedModel,m.ModernBertForMaskedLM,m.ModernBertForSequenceClassification,m.ModernBertForTokenClassification,m.ModernBertModel,m.ModernBertPreTrainedModel,m.Moondream1ForConditionalGeneration,m.MoonshineFeatureExtractor,m.MoonshineForConditionalGeneration,m.MoonshineModel,m.MoonshinePreTrainedModel,m.MoonshineProcessor,m.MptForCausalLM,m.MptModel,m.MptPreTrainedModel,m.MultiModalityCausalLM,m.MultiModalityPreTrainedModel,m.MusicgenForCausalLM,m.MusicgenForConditionalGeneration,m.MusicgenModel,m.MusicgenPreTrainedModel,m.NanoChatForCausalLM,m.NanoChatModel,m.NanoChatPreTrainedModel,m.NeoBertForMaskedLM,m.NeoBertForQuestionAnswering,m.NeoBertForSequenceClassification,m.NeoBertForTokenClassification,m.NeoBertModel,m.NeoBertPreTrainedModel,m.NllbTokenizer,m.NoBadWordsLogitsProcessor,m.NoRepeatNGramLogitsProcessor,m.NomicBertModel,m.NomicBertPreTrainedModel,m.NougatImageProcessor,m.NougatTokenizer,m.OPTForCausalLM,m.OPTModel,m.OPTPreTrainedModel,m.ObjectDetectionPipeline,m.Olmo2ForCausalLM,m.Olmo2Model,m.Olmo2PreTrainedModel,m.OlmoForCausalLM,m.OlmoModel,m.OlmoPreTrainedModel,m.OpenELMForCausalLM,m.OpenELMModel,m.OpenELMPreTrainedModel,m.OwlViTFeatureExtractor,m.OwlViTForObjectDetection,m.OwlViTImageProcessor,m.OwlViTModel,m.OwlViTPreTrainedModel,m.OwlViTProcessor,m.Owlv2ForObjectDetection,m.Owlv2ImageProcessor,m.Owlv2Model,m.Owlv2PreTrainedModel,m.PaliGemmaForConditionalGeneration,m.PaliGemmaPreTrainedModel,m.PaliGemmaProcessor,m.ParakeetFeatureExtractor,m.ParakeetForCTC,m.ParakeetPreTrainedModel,m.PatchTSMixerForPrediction,m.PatchTSMixerModel,m.PatchTSMixerPreTrainedModel,m.PatchTSTForPrediction,m.PatchTSTModel,m.PatchTSTPreTrainedModel,m.Phi3ForCausalLM,m.Phi3Model,m.Phi3PreTrainedModel,m.Phi3VForCausalLM,m.Phi3VImageProcessor,m.Phi3VPreTrainedModel,m.Phi3VProcessor,m.PhiForCausalLM,m.PhiModel,m.PhiPreTrainedModel,m.Pipeline,m.PixtralImageProcessor,m.PixtralProcessor,m.PreTrainedModel,m.PreTrainedTokenizer,m.PretrainedConfig,m.PretrainedMixin,m.Processor,m.PvtForImageClassification,m.PvtImageProcessor,m.PvtModel,m.PvtPreTrainedModel,m.PyAnnoteFeatureExtractor,m.PyAnnoteForAudioFrameClassification,m.PyAnnoteModel,m.PyAnnotePreTrainedModel,m.PyAnnoteProcessor,m.QuestionAnsweringModelOutput,m.QuestionAnsweringPipeline,m.Qwen2ForCausalLM,m.Qwen2Model,m.Qwen2PreTrainedModel,m.Qwen2Tokenizer,m.Qwen2VLForConditionalGeneration,m.Qwen2VLImageProcessor,m.Qwen2VLPreTrainedModel,m.Qwen2VLProcessor,m.Qwen3ForCausalLM,m.Qwen3Model,m.Qwen3PreTrainedModel,m.RFDetrForObjectDetection,m.RFDetrModel,m.RFDetrObjectDetectionOutput,m.RFDetrPreTrainedModel,m.RTDetrForObjectDetection,m.RTDetrImageProcessor,m.RTDetrModel,m.RTDetrObjectDetectionOutput,m.RTDetrPreTrainedModel,m.RTDetrV2ForObjectDetection,m.RTDetrV2Model,m.RTDetrV2ObjectDetectionOutput,m.RTDetrV2PreTrainedModel,m.RawAudio,m.RawImage,m.RawVideo,m.RawVideoFrame,m.RepetitionPenaltyLogitsProcessor,m.ResNetForImageClassification,m.ResNetModel,m.ResNetPreTrainedModel,m.RoFormerForMaskedLM,m.RoFormerForQuestionAnswering,m.RoFormerForSequenceClassification,m.RoFormerForTokenClassification,m.RoFormerModel,m.RoFormerPreTrainedModel,m.RoFormerTokenizer,m.RobertaForMaskedLM,m.RobertaForQuestionAnswering,m.RobertaForSequenceClassification,m.RobertaForTokenClassification,m.RobertaModel,m.RobertaPreTrainedModel,m.RobertaTokenizer,m.Sam2ImageProcessor,m.Sam2ImageSegmentationOutput,m.Sam2Model,m.Sam2PreTrainedModel,m.Sam2Processor,m.Sam2VideoProcessor,m.Sam3ImageProcessor,m.Sam3TrackerModel,m.SamImageProcessor,m.SamImageSegmentationOutput,m.SamModel,m.SamPreTrainedModel,m.SamProcessor,m.SapiensForDepthEstimation,m.SapiensForNormalEstimation,m.SapiensForSemanticSegmentation,m.SapiensPreTrainedModel,m.SeamlessM4TFeatureExtractor,m.SegformerFeatureExtractor,m.SegformerForImageClassification,m.SegformerForSemanticSegmentation,m.SegformerImageProcessor,m.SegformerModel,m.SegformerPreTrainedModel,m.Seq2SeqLMOutput,m.SequenceClassifierOutput,m.SiglipImageProcessor,m.SiglipModel,m.SiglipPreTrainedModel,m.SiglipTextModel,m.SiglipTokenizer,m.SiglipVisionModel,m.SmolLM3ForCausalLM,m.SmolLM3Model,m.SmolLM3PreTrainedModel,m.SmolVLMForConditionalGeneration,m.SmolVLMImageProcessor,m.SmolVLMProcessor,m.SnacDecoderModel,m.SnacEncoderModel,m.SnacFeatureExtractor,m.SnacModel,m.SnacPreTrainedModel,m.SpeechT5FeatureExtractor,m.SpeechT5ForSpeechToText,m.SpeechT5ForTextToSpeech,m.SpeechT5HifiGan,m.SpeechT5Model,m.SpeechT5PreTrainedModel,m.SpeechT5Processor,m.SpeechT5Tokenizer,m.SqueezeBertForMaskedLM,m.SqueezeBertForQuestionAnswering,m.SqueezeBertForSequenceClassification,m.SqueezeBertModel,m.SqueezeBertPreTrainedModel,m.SqueezeBertTokenizer,m.StableLmForCausalLM,m.StableLmModel,m.StableLmPreTrainedModel,m.Starcoder2ForCausalLM,m.Starcoder2Model,m.Starcoder2PreTrainedModel,m.StoppingCriteria,m.StoppingCriteriaList,m.StyleTextToSpeech2Model,m.StyleTextToSpeech2PreTrainedModel,m.SummarizationPipeline,m.SupertonicForConditionalGeneration,m.SupertonicPreTrainedModel,m.SuppressTokensAtBeginLogitsProcessor,m.Swin2SRForImageSuperResolution,m.Swin2SRImageProcessor,m.Swin2SRModel,m.Swin2SRPreTrainedModel,m.SwinForImageClassification,m.SwinForSemanticSegmentation,m.SwinModel,m.SwinPreTrainedModel,m.T5ForConditionalGeneration,m.T5Model,m.T5PreTrainedModel,m.T5Tokenizer,m.TableTransformerForObjectDetection,m.TableTransformerModel,m.TableTransformerObjectDetectionOutput,m.TableTransformerPreTrainedModel,m.TemperatureLogitsWarper,m.Tensor,m.Text2TextGenerationPipeline,m.TextClassificationPipeline,m.TextGenerationPipeline,m.TextStreamer,m.TextToAudioPipeline,m.TokenClassificationPipeline,m.TokenClassifierOutput,m.TokenizerModel,m.TopKLogitsWarper,m.TopPLogitsWarper,m.TrOCRForCausalLM,m.TrOCRPreTrainedModel,m.TranslationPipeline,m.UltravoxModel,m.UltravoxPreTrainedModel,m.UltravoxProcessor,m.UniSpeechForCTC,m.UniSpeechForSequenceClassification,m.UniSpeechModel,m.UniSpeechPreTrainedModel,m.UniSpeechSatForAudioFrameClassification,m.UniSpeechSatForCTC,m.UniSpeechSatForSequenceClassification,m.UniSpeechSatModel,m.UniSpeechSatPreTrainedModel,m.VLChatProcessor,m.VLMImageProcessor,m.VaultGemmaForCausalLM,m.VaultGemmaModel,m.VaultGemmaPreTrainedModel,m.ViTFeatureExtractor,m.ViTForImageClassification,m.ViTImageProcessor,m.ViTMAEModel,m.ViTMAEPreTrainedModel,m.ViTMSNForImageClassification,m.ViTMSNModel,m.ViTMSNPreTrainedModel,m.ViTModel,m.ViTPreTrainedModel,m.VisionEncoderDecoderModel,m.VitMatteForImageMatting,m.VitMatteImageProcessor,m.VitMattePreTrainedModel,m.VitPoseForPoseEstimation,m.VitPoseImageProcessor,m.VitPosePreTrainedModel,m.VitsModel,m.VitsModelOutput,m.VitsPreTrainedModel,m.VitsTokenizer,m.VoxtralForConditionalGeneration,m.VoxtralProcessor,m.Wav2Vec2BertForCTC,m.Wav2Vec2BertForSequenceClassification,m.Wav2Vec2BertModel,m.Wav2Vec2BertPreTrainedModel,m.Wav2Vec2CTCTokenizer,m.Wav2Vec2FeatureExtractor,m.Wav2Vec2ForAudioFrameClassification,m.Wav2Vec2ForCTC,m.Wav2Vec2ForSequenceClassification,m.Wav2Vec2Model,m.Wav2Vec2PreTrainedModel,m.Wav2Vec2Processor,m.Wav2Vec2ProcessorWithLM,m.WavLMForAudioFrameClassification,m.WavLMForCTC,m.WavLMForSequenceClassification,m.WavLMForXVector,m.WavLMModel,m.WavLMPreTrainedModel,m.WeSpeakerFeatureExtractor,m.WeSpeakerResNetModel,m.WeSpeakerResNetPreTrainedModel,m.WhisperFeatureExtractor,m.WhisperForConditionalGeneration,m.WhisperModel,m.WhisperPreTrainedModel,m.WhisperProcessor,m.WhisperTextStreamer,m.WhisperTimeStampLogitsProcessor,m.WhisperTokenizer,m.XLMForQuestionAnswering,m.XLMForSequenceClassification,m.XLMForTokenClassification,m.XLMModel,m.XLMPreTrainedModel,m.XLMRobertaForMaskedLM,m.XLMRobertaForQuestionAnswering,m.XLMRobertaForSequenceClassification,m.XLMRobertaForTokenClassification,m.XLMRobertaModel,m.XLMRobertaPreTrainedModel,m.XLMRobertaTokenizer,m.XLMTokenizer,m.XLMWithLMHeadModel,m.XVectorOutput,m.YolosFeatureExtractor,m.YolosForObjectDetection,m.YolosImageProcessor,m.YolosModel,m.YolosObjectDetectionOutput,m.YolosPreTrainedModel,m.ZeroShotAudioClassificationPipeline,m.ZeroShotClassificationPipeline,m.ZeroShotImageClassificationPipeline,m.ZeroShotObjectDetectionPipeline,m.bankers_round,m.cat,m.cos_sim,m.dot,m.dynamic_time_warping,m.env,m.full,m.full_like,m.getCacheShapes,m.hamming,m.hanning,m.interpolate,m.interpolate_4d,m.interpolate_data,m.is_chinese_char,m.layer_norm,m.load_image,m.load_video,m.log_softmax,m.magnitude,m.matmul,m.max,m.mean,m.mean_pooling,m.medianFilter,m.mel_filter_bank,m.min,m.ones,m.ones_like,m.permute,m.permute_data;var FT=m.pipeline;m.quantize_embeddings,m.rand,m.randn,m.read_audio,m.rfft,m.round,m.slice,m.softmax,m.spectrogram,m.stack,m.std_mean,m.topk,m.window_function,m.zeros,m.zeros_like;const OT="onnx-community/depth-anything-v2-small-ONNX",DT=FT,uw=self;let xs=null,So=null;function _c(e,r=[]){uw.postMessage(e,r)}function Qn(e,r){_c({type:"status",id:e,message:r})}async function fc(e,r){return Qn(r,"AI 모델 준비 중…"),DT("depth-estimation",OT,{device:e,progress_callback:t=>{t.status==="progress"?Qn(r,`AI 모델 다운로드 중 · ${Math.round(t.progress??0)}%`):(t.status==="initiate"||t.status==="download")&&Qn(r,"AI 모델 다운로드 중…")}})}async function LT(e){if(xs)return xs;if("gpu"in navigator)try{return xs=await fc("webgpu",e),So="webgpu",xs}catch{xs&&await xs.dispose(),xs=null,Qn(e,"AI 모델을 준비하는 중입니다…")}return xs=await fc("wasm",e),So="wasm",xs}function zT(e){const{predicted_depth:r}=e,[t,s]=r.dims.slice(-2),o=r.data;if(!s||!t||o.length!==s*t)throw new Error("모델이 유효한 depth 크기를 반환하지 않았습니다.");let n=1/0,a=-1/0;for(let c=0;c{e.data.type==="infer"&&BT(e.data)})})(); diff --git a/dist/assets/cutout.worker-D417j0Nw.js b/dist/assets/cutout.worker-D417j0Nw.js new file mode 100644 index 0000000..2063bff --- /dev/null +++ b/dist/assets/cutout.worker-D417j0Nw.js @@ -0,0 +1,11 @@ +(function(){ +/*! +* ONNX Runtime Web v1.31.0-dev.20260914-8d85527a0 +* Copyright (c) Microsoft Corporation. All rights reserved. +* Licensed under the MIT License. +*/ +var e=Object.defineProperty,t=Object.getOwnPropertyDescriptor,n=Object.getOwnPropertyNames,r=Object.prototype.hasOwnProperty,i=(e=>typeof require<`u`?require:typeof Proxy<`u`?new Proxy(e,{get:(e,t)=>(typeof require<`u`?require:e)[t]}):e)(function(e){if(typeof require<`u`)return require.apply(this,arguments);throw Error(`Dynamic require of "`+e+`" is not supported`)}),a=(e,t,n)=>()=>{if(n)throw n[0];try{return e&&(t=e(e=0)),t}catch(e){throw n=[e],e}},o=(t,n)=>{for(var r in n)e(t,r,{get:n[r],enumerable:!0})},s=(i,a,o,s)=>{if(a&&typeof a==`object`||typeof a==`function`)for(let c of n(a))!r.call(i,c)&&c!==o&&e(i,c,{get:()=>a[c],enumerable:!(s=t(a,c))||s.enumerable});return i},c=t=>s(e({},`__esModule`,{value:!0}),t),l,u,d,f,p,m=a(()=>{"use strict";l=/* @__PURE__ */ new Map,u=[],d=(e,t,n)=>{if(t&&typeof t.init==`function`&&typeof t.createInferenceSessionHandler==`function`){let r=l.get(e);if(r===void 0)l.set(e,{backend:t,priority:n});else{if(r.priority>n)return;if(r.priority===n&&r.backend!==t)throw Error(`cannot register backend "${e}" using priority ${n}`)}if(n>=0){let t=u.indexOf(e);t!==-1&&u.splice(t,1);for(let t=0;t{let t=l.get(e);if(!t)return`backend not found.`;if(t.initialized)return t.backend;if(t.aborted)return t.error;{let n=!!t.initPromise;try{return n||(t.initPromise=t.backend.init(e)),await t.initPromise,t.initialized=!0,t.backend}catch(e){return n||(t.error=`${e}`,t.aborted=!0),t.error}finally{delete t.initPromise}}},p=async e=>{let t=e.executionProviders||[],n=t.map(e=>typeof e==`string`?e:e.name),r=n.length===0?u:n,i,a=[],o=/* @__PURE__ */ new Set;for(let e of r){let t=await f(e);typeof t==`string`?a.push({name:e,err:t}):(i||=t,i===t&&o.add(e))}if(!i)throw Error(`no available backend found. ERR: ${a.map(e=>`[${e.name}] ${e.err}`).join(`, `)}`);for(let{name:e,err:t}of a)n.includes(e)&&console.warn(`removing requested execution provider "${e}" from session options because it is not available: ${t}`);let s=t.filter(e=>o.has(typeof e==`string`?e:e.name));return[i,new Proxy(e,{get:(e,t)=>t===`executionProviders`?s:Reflect.get(e,t)})]}}),h=a(()=>{"use strict";m()}),g,_=a(()=>{"use strict";g=`1.31.0-dev.20260911-2a43ec07e`}),v,y,b=a(()=>{"use strict";_(),v=`warning`,y={wasm:{},webgl:{},webgpu:{},versions:{common:g},set logLevel(e){if(e!==void 0){if(typeof e!=`string`||[`verbose`,`info`,`warning`,`error`,`fatal`].indexOf(e)===-1)throw Error(`Unsupported logging level: ${e}`);v=e}},get logLevel(){return v}},Object.defineProperty(y,"logLevel",{enumerable:!0})}),x,ee=a(()=>{"use strict";b(),x=y}),S,te,ne=a(()=>{"use strict";S=(e,t)=>{let n=typeof document<`u`?document.createElement(`canvas`):new OffscreenCanvas(1,1);n.width=e.dims[3],n.height=e.dims[2];let r=n.getContext(`2d`);if(r!=null){let i,a;t?.tensorLayout!==void 0&&t.tensorLayout===`NHWC`?(i=e.dims[2],a=e.dims[3]):(i=e.dims[3],a=e.dims[2]);let o=t?.format===void 0?`RGB`:t.format,s=t?.norm,c,l;s===void 0||s.mean===void 0?c=[255,255,255,255]:typeof s.mean==`number`?c=[s.mean,s.mean,s.mean,s.mean]:(c=[s.mean[0],s.mean[1],s.mean[2],0],s.mean[3]!==void 0&&(c[3]=s.mean[3])),s===void 0||s.bias===void 0?l=[0,0,0,0]:typeof s.bias==`number`?l=[s.bias,s.bias,s.bias,s.bias]:(l=[s.bias[0],s.bias[1],s.bias[2],0],s.bias[3]!==void 0&&(l[3]=s.bias[3]));let u=a*i,d=0,f=u,p=u*2,m=-1;o===`RGBA`?(d=0,f=u,p=u*2,m=u*3):o===`RGB`?(d=0,f=u,p=u*2):o===`RBG`&&(d=0,p=u,f=u*2);for(let t=0;t{let n=typeof document<`u`?document.createElement(`canvas`).getContext(`2d`):new OffscreenCanvas(1,1).getContext(`2d`),r;if(n!=null){let i,a,o;t?.tensorLayout!==void 0&&t.tensorLayout===`NHWC`?(i=e.dims[2],a=e.dims[1],o=e.dims[3]):(i=e.dims[3],a=e.dims[2],o=e.dims[1]);let s=t!==void 0&&t.format!==void 0?t.format:`RGB`,c=t?.norm,l,u;c===void 0||c.mean===void 0?l=[255,255,255,255]:typeof c.mean==`number`?l=[c.mean,c.mean,c.mean,c.mean]:(l=[c.mean[0],c.mean[1],c.mean[2],255],c.mean[3]!==void 0&&(l[3]=c.mean[3])),c===void 0||c.bias===void 0?u=[0,0,0,0]:typeof c.bias==`number`?u=[c.bias,c.bias,c.bias,c.bias]:(u=[c.bias[0],c.bias[1],c.bias[2],0],c.bias[3]!==void 0&&(u[3]=c.bias[3]));let d=a*i;if(t!==void 0&&(t.format!==void 0&&o===4&&t.format!==`RGBA`||o===3&&t.format!==`RGB`&&t.format!==`BGR`))throw Error(`Tensor format doesn't match input tensor dims`);let f=0,p=1,m=2,h=3,g=0,_=d,v=d*2,y=-1;s===`RGBA`?(g=0,_=d,v=d*2,y=d*3):s===`RGB`?(g=0,_=d,v=d*2):s===`RBG`&&(g=0,v=d,_=d*2),r=n.createImageData(i,a);for(let t=0;t{"use strict";he(),C=(e,t)=>{if(e===void 0)throw Error(`Image buffer must be defined`);if(t.height===void 0||t.width===void 0)throw Error(`Image height and width must be defined`);if(t.tensorLayout===`NHWC`)throw Error(`NHWC Tensor layout is not supported yet`);let{height:n,width:r}=t,i=t.norm??{mean:255,bias:0},a,o;a=typeof i.mean==`number`?[i.mean,i.mean,i.mean,i.mean]:[i.mean[0],i.mean[1],i.mean[2],i.mean[3]??255],o=typeof i.bias==`number`?[i.bias,i.bias,i.bias,i.bias]:[i.bias[0],i.bias[1],i.bias[2],i.bias[3]??0];let s=t.format===void 0?`RGBA`:t.format,c=t.tensorFormat!==void 0&&t.tensorFormat!==void 0?t.tensorFormat:`RGB`,l=n*r,u=c===`RGBA`?new Float32Array(l*4):new Float32Array(l*3),d=4,f=0,p=1,m=2,h=3,g=0,_=l,v=l*2,y=-1;s===`RGB`&&(d=3,f=0,p=1,m=2,h=-1),c===`RGBA`?y=l*3:c===`RBG`?(g=0,v=l,_=l*2):c===`BGR`&&(v=0,_=l,g=l*2);for(let t=0;t{let n=typeof HTMLImageElement<`u`&&e instanceof HTMLImageElement,r=typeof ImageData<`u`&&e instanceof ImageData,i=typeof ImageBitmap<`u`&&e instanceof ImageBitmap,a=typeof e==`string`,o,s=t??{},c=()=>{if(typeof document<`u`)return document.createElement(`canvas`);if(typeof OffscreenCanvas<`u`)return new OffscreenCanvas(1,1);throw Error(`Canvas is not supported`)},l=e=>typeof HTMLCanvasElement<`u`&&e instanceof HTMLCanvasElement||e instanceof OffscreenCanvas?e.getContext(`2d`):null;if(n){let n=c();n.width=e.width,n.height=e.height;let r=l(n);if(r!=null){let n=e.height,i=e.width;if(t!==void 0&&t.resizedHeight!==void 0&&t.resizedWidth!==void 0&&(n=t.resizedHeight,i=t.resizedWidth),t!==void 0){if(s=t,t.tensorFormat!==void 0)throw Error(`Image input config format must be RGBA for HTMLImageElement`);s.tensorFormat=`RGBA`,s.height=n,s.width=i}else s.tensorFormat=`RGBA`,s.height=n,s.width=i;r.drawImage(e,0,0),o=r.getImageData(0,0,i,n).data}else throw Error(`Can not access image data`)}else if(r){let n,r;if(t!==void 0&&t.resizedWidth!==void 0&&t.resizedHeight!==void 0?(n=t.resizedHeight,r=t.resizedWidth):(n=e.height,r=e.width),t!==void 0&&(s=t),s.format=`RGBA`,s.height=n,s.width=r,t!==void 0){let t=c();t.width=r,t.height=n;let i=l(t);if(i!=null)i.putImageData(e,0,0),o=i.getImageData(0,0,r,n).data;else throw Error(`Can not access image data`)}else o=e.data}else if(i){if(t===void 0)throw Error(`Please provide image config with format for Imagebitmap`);let n=c();n.width=e.width,n.height=e.height;let r=l(n);if(r!=null){let t=e.height,n=e.width;return r.drawImage(e,0,0,n,t),o=r.getImageData(0,0,n,t).data,s.height=t,s.width=n,C(o,s)}throw Error(`Can not access image data`)}else{if(a)return new Promise((t,n)=>{let r=c(),i=l(r);if(!e||!i)return n();let a=new Image;a.crossOrigin=`Anonymous`,a.src=e,a.onload=()=>{r.width=a.width,r.height=a.height,i.drawImage(a,0,0,r.width,r.height);let e=i.getImageData(0,0,r.width,r.height);s.height=r.height,s.width=r.width,t(C(e.data,s))}});throw Error(`Input data provided is not supported - aborted tensor creation`)}if(o!==void 0)return C(o,s);throw Error(`Input data provided is not supported - aborted tensor creation`)},ie=(e,t)=>{let{width:n,height:r,download:i,dispose:a}=t;return new E({location:`texture`,type:`float32`,texture:e,dims:[1,r,n,4],download:i,dispose:a})},ae=(e,t)=>{let{dataType:n,dims:r,download:i,dispose:a}=t;return new E({location:`gpu-buffer`,type:n??`float32`,gpuBuffer:e,dims:r,download:i,dispose:a})},oe=(e,t)=>{let{dataType:n,dims:r,download:i,dispose:a}=t;return new E({location:`ml-tensor`,type:n??`float32`,mlTensor:e,dims:r,download:i,dispose:a})},se=(e,t,n)=>new E({location:`cpu-pinned`,type:e,data:t,dims:n??[t.length]})}),w,T,le,ue,de=a(()=>{"use strict";w=/* @__PURE__ */ new Map([[`float32`,Float32Array],[`uint8`,Uint8Array],[`int8`,Int8Array],[`uint16`,Uint16Array],[`int16`,Int16Array],[`int32`,Int32Array],[`bool`,Uint8Array],[`float64`,Float64Array],[`uint32`,Uint32Array],[`int4`,Uint8Array],[`uint4`,Uint8Array]]),T=/* @__PURE__ */ new Map([[Float32Array,`float32`],[Uint8Array,`uint8`],[Int8Array,`int8`],[Uint16Array,`uint16`],[Int16Array,`int16`],[Int32Array,`int32`],[Float64Array,`float64`],[Uint32Array,`uint32`]]),le=!1,ue=()=>{if(!le){le=!0;let e=typeof BigInt64Array<`u`&&BigInt64Array.from,t=typeof BigUint64Array<`u`&&BigUint64Array.from,n=globalThis.Float16Array,r=typeof n<`u`&&n.from;e&&(w.set(`int64`,BigInt64Array),T.set(BigInt64Array,`int64`)),t&&(w.set(`uint64`,BigUint64Array),T.set(BigUint64Array,`uint64`)),r?(w.set(`float16`,n),T.set(n,`float16`)):w.set(`float16`,Uint16Array)}}}),fe,pe,me=a(()=>{"use strict";he(),fe=e=>{let t=1;for(let n=0;n{switch(e.location){case`cpu`:return new E(e.type,e.data,t);case`cpu-pinned`:return new E({location:`cpu-pinned`,data:e.data,type:e.type,dims:t});case`texture`:return new E({location:`texture`,texture:e.texture,type:e.type,dims:t});case`gpu-buffer`:return new E({location:`gpu-buffer`,gpuBuffer:e.gpuBuffer,type:e.type,dims:t});case`ml-tensor`:return new E({location:`ml-tensor`,mlTensor:e.mlTensor,type:e.type,dims:t});default:throw Error(`tensorReshape: tensor location ${e.location} is not supported`)}}}),E,he=a(()=>{"use strict";ne(),ce(),de(),me(),E=class{constructor(e,t,n){ue();let r,i;if(typeof e==`object`&&`location`in e)switch(this.dataLocation=e.location,r=e.type,i=e.dims,e.location){case`cpu-pinned`:{let t=w.get(r);if(!t)throw TypeError(`unsupported type "${r}" to create tensor from pinned buffer`);if(!(e.data instanceof t))throw TypeError(`buffer should be of type ${t.name}`);this.cpuData=e.data;break}case`texture`:if(r!==`float32`)throw TypeError(`unsupported type "${r}" to create tensor from texture`);this.gpuTextureData=e.texture,this.downloader=e.download,this.disposer=e.dispose;break;case`gpu-buffer`:if(r!==`float32`&&r!==`float16`&&r!==`int32`&&r!==`int64`&&r!==`uint32`&&r!==`uint8`&&r!==`bool`&&r!==`uint4`&&r!==`int4`)throw TypeError(`unsupported type "${r}" to create tensor from gpu buffer`);this.gpuBufferData=e.gpuBuffer,this.downloader=e.download,this.disposer=e.dispose;break;case`ml-tensor`:if(r!==`float32`&&r!==`float16`&&r!==`int32`&&r!==`int64`&&r!==`uint32`&&r!==`uint64`&&r!==`int8`&&r!==`uint8`&&r!==`bool`&&r!==`uint4`&&r!==`int4`)throw TypeError(`unsupported type "${r}" to create tensor from MLTensor`);this.mlTensorData=e.mlTensor,this.downloader=e.download,this.disposer=e.dispose;break;default:throw Error(`Tensor constructor: unsupported location '${this.dataLocation}'`)}else{let a,o;if(typeof e==`string`){if(r=e,o=n,e===`string`){if(!Array.isArray(t))throw TypeError(`A string tensor's data must be a string array.`);a=t}else{let n=w.get(e);if(n===void 0)throw TypeError(`Unsupported tensor type: ${e}.`);if(Array.isArray(t)){if(e===`float16`&&n===Uint16Array||e===`uint4`||e===`int4`)throw TypeError(`Creating a ${e} tensor from number array is not supported. Please use ${n.name} as data.`);a=e===`uint64`||e===`int64`?n.from(t,BigInt):n.from(t)}else if(t instanceof n)a=t;else if(t instanceof Uint8ClampedArray){if(e===`uint8`)a=Uint8Array.from(t);else throw TypeError(`A Uint8ClampedArray tensor's data must be type of uint8`)}else if(e===`float16`&&t instanceof Uint16Array&&n!==Uint16Array)a=new globalThis.Float16Array(t.buffer,t.byteOffset,t.length);else throw TypeError(`A ${r} tensor's data must be type of ${n}`)}}else if(o=t,Array.isArray(e)){if(e.length===0)throw TypeError(`Tensor type cannot be inferred from an empty array.`);let t=typeof e[0];if(t===`string`)r=`string`,a=e;else if(t===`boolean`)r=`bool`,a=Uint8Array.from(e);else throw TypeError(`Invalid element type of data array: ${t}.`)}else if(e instanceof Uint8ClampedArray)r=`uint8`,a=Uint8Array.from(e);else{let t=T.get(e.constructor);if(t===void 0)throw TypeError(`Unsupported type for tensor data: ${e.constructor}.`);r=t,a=e}if(o===void 0)o=[a.length];else if(!Array.isArray(o))throw TypeError(`A tensor's dims must be a number array`);i=o,this.cpuData=a,this.dataLocation=`cpu`}let a=fe(i);if(this.cpuData&&a!==this.cpuData.length&&(r!==`uint4`&&r!==`int4`||Math.ceil(a/2)!==this.cpuData.length))throw Error(`Tensor's size(${a}) does not match data length(${this.cpuData.length}).`);this.type=r,this.dims=i,this.size=a}static async fromImage(e,t){return re(e,t)}static fromTexture(e,t){return ie(e,t)}static fromGpuBuffer(e,t){return ae(e,t)}static fromMLTensor(e,t){return oe(e,t)}static fromPinnedBuffer(e,t,n){return se(e,t,n)}toDataURL(e){return S(this,e)}toImageData(e){return te(this,e)}get data(){if(this.ensureValid(),!this.cpuData)throw Error("The data is not on CPU. Use `getData()` to download GPU data to CPU, or use `texture` or `gpuBuffer` property to access the GPU data directly.");return this.cpuData}get location(){return this.dataLocation}get texture(){if(this.ensureValid(),!this.gpuTextureData)throw Error(`The data is not stored as a WebGL texture.`);return this.gpuTextureData}get gpuBuffer(){if(this.ensureValid(),!this.gpuBufferData)throw Error(`The data is not stored as a WebGPU buffer.`);return this.gpuBufferData}get mlTensor(){if(this.ensureValid(),!this.mlTensorData)throw Error(`The data is not stored as a WebNN MLTensor.`);return this.mlTensorData}async getData(e){switch(this.ensureValid(),this.dataLocation){case`cpu`:case`cpu-pinned`:return this.data;case`texture`:case`gpu-buffer`:case`ml-tensor`:if(!this.downloader)throw Error(`The current tensor is not created with a specified data downloader.`);if(this.isDownloading)throw Error(`The current tensor is being downloaded.`);try{this.isDownloading=!0;let t=await this.downloader();return this.downloader=void 0,this.dataLocation=`cpu`,this.cpuData=t,e&&this.disposer&&(this.disposer(),this.disposer=void 0),t}finally{this.isDownloading=!1}default:throw Error(`cannot get data from location: ${this.dataLocation}`)}}dispose(){if(this.isDownloading)throw Error(`The current tensor is being downloaded.`);this.disposer&&=(this.disposer(),void 0),this.cpuData=void 0,this.gpuTextureData=void 0,this.gpuBufferData=void 0,this.mlTensorData=void 0,this.downloader=void 0,this.isDownloading=void 0,this.dataLocation=`none`}ensureValid(){if(this.dataLocation===`none`)throw Error(`The tensor is disposed.`)}reshape(e){if(this.ensureValid(),this.downloader||this.disposer)throw Error(`Cannot reshape a tensor that owns GPU resource.`);return pe(this,e)}}}),D,ge=a(()=>{"use strict";he(),D=E}),_e,ve,O,k,A,j,ye=a(()=>{"use strict";b(),_e=(e,t)=>{(typeof y.trace>`u`?!y.wasm.trace:!y.trace)||console.timeStamp(`${e}::ORT::${t}`)},ve=(e,t)=>{let n=(/* @__PURE__ */ Error()).stack?.split(/\r\n|\r|\n/g)||[],r=!1;for(let i=0;i{(typeof y.trace>`u`?!y.wasm.trace:!y.trace)||ve(`BEGIN`,e)},k=e=>{(typeof y.trace>`u`?!y.wasm.trace:!y.trace)||ve(`END`,e)},A=e=>{(typeof y.trace>`u`?!y.wasm.trace:!y.trace)||console.time(`ORT::${e}`)},j=e=>{(typeof y.trace>`u`?!y.wasm.trace:!y.trace)||console.timeEnd(`ORT::${e}`)}}),be,xe=a(()=>{"use strict";m(),ge(),ye(),be=class e{constructor(e){this.handler=e}async run(e,t,n){O(),A(`InferenceSession.run`);let r={},i={};if(typeof e!=`object`||!e||e instanceof D||Array.isArray(e))throw TypeError(`'feeds' must be an object that use input names as keys and OnnxValue as corresponding values.`);let a=!0;if(typeof t==`object`){if(t===null)throw TypeError(`Unexpected argument[1]: cannot be null.`);if(t instanceof D)throw TypeError(`'fetches' cannot be a Tensor`);if(Array.isArray(t)){if(t.length===0)throw TypeError(`'fetches' cannot be an empty array.`);a=!1;for(let e of t){if(typeof e!=`string`)throw TypeError(`'fetches' must be a string array or an object.`);if(this.outputNames.indexOf(e)===-1)throw RangeError(`'fetches' contains invalid output name: ${e}.`);r[e]=null}if(typeof n==`object`&&n)i=n;else if(typeof n<`u`)throw TypeError(`'options' must be an object.`)}else{let e=!1,o=Object.getOwnPropertyNames(t);for(let n of this.outputNames)if(o.indexOf(n)!==-1){let i=t[n];(i===null||i instanceof D)&&(e=!0,a=!1,r[n]=i)}if(e){if(typeof n==`object`&&n)i=n;else if(typeof n<`u`)throw TypeError(`'options' must be an object.`)}else i=t}}else if(typeof t<`u`)throw TypeError(`Unexpected argument[1]: must be 'fetches' or 'options'.`);for(let t of this.inputNames)if(typeof e[t]>`u`)throw Error(`input '${t}' is missing in 'feeds'.`);if(a)for(let e of this.outputNames)r[e]=null;let o=await this.handler.run(e,r,i),s={};for(let e in o)if(Object.hasOwnProperty.call(o,e)){let t=o[e];s[e]=t instanceof D?t:new D(t.type,t.data,t.dims)}return j(`InferenceSession.run`),k(),s}async release(){return this.handler.dispose()}static async create(t,n,r,i){O(),A(`InferenceSession.create`);let a,o={};if(typeof t==`string`){if(a=t,typeof n==`object`&&n)o=n;else if(typeof n<`u`)throw TypeError(`'options' must be an object.`)}else if(t instanceof Uint8Array){if(a=t,typeof n==`object`&&n)o=n;else if(typeof n<`u`)throw TypeError(`'options' must be an object.`)}else if(t instanceof ArrayBuffer||typeof SharedArrayBuffer<`u`&&t instanceof SharedArrayBuffer){let e=t,s=0,c=t.byteLength;if(typeof n==`object`&&n)o=n;else if(typeof n==`number`){if(s=n,!Number.isSafeInteger(s))throw RangeError(`'byteOffset' must be an integer.`);if(s<0||s>=e.byteLength)throw RangeError(`'byteOffset' is out of range [0, ${e.byteLength}).`);if(c=t.byteLength-s,typeof r==`number`){if(c=r,!Number.isSafeInteger(c))throw RangeError(`'byteLength' must be an integer.`);if(c<=0||s+c>e.byteLength)throw RangeError(`'byteLength' is out of range (0, ${e.byteLength-s}].`);if(typeof i==`object`&&i)o=i;else if(typeof i<`u`)throw TypeError(`'options' must be an object.`)}else if(typeof r<`u`)throw TypeError(`'byteLength' must be a number.`)}else if(typeof n<`u`)throw TypeError(`'options' must be an object.`);a=new Uint8Array(e,s,c)}else throw TypeError(`Unexpected argument[0]: must be 'path' or 'buffer'.`);let[s,c]=await p(o),l=await s.createInferenceSessionHandler(a,c);return j(`InferenceSession.create`),k(),new e(l)}startProfiling(){this.handler.startProfiling()}endProfiling(){this.handler.endProfiling()}get inputNames(){return this.handler.inputNames}get outputNames(){return this.handler.outputNames}get inputMetadata(){return this.handler.inputMetadata}get outputMetadata(){return this.handler.outputMetadata}}}),Se,Ce=a(()=>{"use strict";xe(),Se=be}),we=a(()=>{"use strict";}),Te=a(()=>{"use strict";}),Ee=a(()=>{"use strict";}),De=a(()=>{"use strict";});o({},{InferenceSession:()=>Se,TRACE:()=>_e,TRACE_EVENT_BEGIN:()=>A,TRACE_EVENT_END:()=>j,TRACE_FUNC_BEGIN:()=>O,TRACE_FUNC_END:()=>k,Tensor:()=>D,env:()=>x,registerBackend:()=>d});var M=a(()=>{"use strict";h(),ee(),Ce(),ge(),we(),Te(),ye(),Ee(),De()}),Oe=a(()=>{"use strict";}),ke={};o(ke,{default:()=>Me});var Ae,je,Me,Ne=a(()=>{"use strict";tn(),I(),qe(),Ae=`ort-wasm-proxy-worker`,je=globalThis.self?.name===Ae,je&&(self.onmessage=e=>{let{type:t,in:n}=e.data;try{switch(t){case`init-wasm`:et(n.wasm).then(()=>{Wt(n).then(()=>{postMessage({type:t})},e=>{postMessage({type:t,err:e})})},e=>{postMessage({type:t,err:e})});break;case`init-ep`:{let{epName:e,env:r}=n;Gt(r,e).then(()=>{postMessage({type:t})},e=>{postMessage({type:t,err:e})});break}case`copy-from`:{let{buffer:e}=n,r=Jt(e);postMessage({type:t,out:r});break}case`create`:{let{model:e,options:r}=n;Yt(e,r).then(e=>{postMessage({type:t,out:e})},e=>{postMessage({type:t,err:e})});break}case`release`:Xt(n),postMessage({type:t});break;case`run`:{let{sessionId:e,inputIndices:r,inputs:i,outputIndices:a,options:o}=n;Qt(e,r,i,a,Array(a.length).fill(null),o).then(e=>{e.some(e=>e[3]!==`cpu`)?postMessage({type:t,err:`Proxy does not support non-cpu tensor location.`}):postMessage({type:t,out:e},en([...i,...e]))},e=>{postMessage({type:t,err:e})});break}case`end-profiling`:$t(n),postMessage({type:t})}}catch(e){postMessage({type:t,err:e})}}),Me=je?null:e=>new Worker(e??N,{type:`module`,name:Ae})}),Pe,Fe,Ie,N,Le,Re,ze,Be,Ve,He,Ue,We,Ge,Ke,qe=a(()=>{"use strict";Oe(),Pe=typeof location>`u`?void 0:location.origin,Fe=self.location.href>`file:`&&self.location.href<`file;`,Ie=()=>Fe?new URL(new URL(`ort.webgpu.min.mjs`,self.location.href).href,Pe).href:self.location.href,N=Ie(),Le=()=>{if(N&&!N.startsWith(`blob:`))return N.substring(0,N.lastIndexOf(`/`)+1)},Re=(e,t)=>{try{let n=t??N;return(n?new URL(e,n):new URL(e)).origin===Pe}catch{return!1}},ze=(e,t)=>{let n=t??N;try{return(n?new URL(e,n):new URL(e)).href}catch{return}},Be=(e,t)=>`${t??`./`}${e}`,Ve=async e=>{let t=await(await fetch(e,{credentials:`same-origin`})).blob();return URL.createObjectURL(t)},He=async e=>(await import( +/*webpackIgnore:true*/ +/*@vite-ignore*/ +e)).default,Ue=(Ne(),c(ke)).default,We=async()=>{if(!N)throw Error(`Failed to load proxy worker: cannot determine the script source URL.`);if(Re(N))return[void 0,Ue()];let e=await Ve(N);return[e,Ue(e)]},Ge=void 0,Ke=async(e,t,n,r)=>{let i=Ge&&!(e||t);if(i){if(N)i=Re(N)||r&&!n;else if(r&&!n)i=!0;else throw Error(`cannot determine the script source URL.`)}if(i)return[void 0,Ge];{let r=`ort-wasm-simd-threaded.asyncify.mjs`,i=e??ze(r,t),a=n&&i&&!Re(i,t),o=a?await Ve(i):i??Be(r,t);return[a?o:void 0,await He(o)]}}}),Je,Ye,P,Xe,Ze,Qe,$e,et,F,I=a(()=>{"use strict";qe(),Ye=!1,P=!1,Xe=!1,Ze=()=>{if(typeof SharedArrayBuffer>`u`)return!1;try{return typeof MessageChannel<`u`&&new MessageChannel().port1.postMessage(new SharedArrayBuffer(1)),WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,5,4,1,3,1,1,10,11,1,9,0,65,0,254,16,2,0,26,11]))}catch{return!1}},Qe=()=>{try{return WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,10,30,1,28,0,65,0,253,15,253,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,253,186,1,26,11]))}catch{return!1}},$e=()=>{try{return WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,5,1,96,0,1,123,3,2,1,0,10,19,1,17,0,65,1,253,15,65,2,253,15,65,3,253,15,253,147,2,11]))}catch{return!1}},et=async e=>{if(Ye)return Promise.resolve();if(P)throw Error(`multiple calls to 'initializeWebAssembly()' detected.`);if(Xe)throw Error(`previous call to 'initializeWebAssembly()' failed.`);P=!0;let t=e.initTimeout,n=e.numThreads;if(e.simd!==!1){if(e.simd===`relaxed`){if(!$e())throw Error(`Relaxed WebAssembly SIMD is not supported in the current environment.`)}else if(!Qe())throw Error(`WebAssembly SIMD is not supported in the current environment.`)}let r=Ze();n>1&&!r&&(typeof self<`u`&&!self.crossOriginIsolated&&console.warn(`env.wasm.numThreads is set to `+n+`, but this will not work unless you enable crossOriginIsolated mode. See https://web.dev/cross-origin-isolation-guide/ for more info.`),console.warn(`WebAssembly multi-threading is not supported in the current environment. Falling back to single-threading.`),e.numThreads=n=1);let i=e.wasmPaths,a=typeof i==`string`?i:void 0,o=i?.mjs,s=o?.href??o,c=i?.wasm,l=c?.href??c,u=e.wasmBinary,[d,f]=await Ke(s,a,n>1,!!u||!!l),p=!1,m=[];if(t>0&&m.push(new Promise(e=>{setTimeout(()=>{p=!0,e()},t)})),m.push(new Promise((e,t)=>{let r={numThreads:n};if(u)r.wasmBinary=u,r.locateFile=e=>e;else if(l||a)r.locateFile=e=>l??a+e;else if(s&&s.indexOf(`blob:`)!==0)r.locateFile=e=>new URL(e,s).href;else if(d){let e=Le();e&&(r.locateFile=t=>e+t)}f(r).then(t=>{P=!1,Ye=!0,Je=t,e(),d&&URL.revokeObjectURL(d)},e=>{P=!1,Xe=!0,t(e)})})),await Promise.race(m),p)throw Error(`WebAssembly backend initializing failed due to timeout: ${t}ms`)},F=()=>{if(Ye&&Je)return Je;throw Error(`WebAssembly is not initialized yet.`)}}),L,tt,R,nt=a(()=>{"use strict";I(),L=(e,t)=>{let n=F(),r=n.lengthBytesUTF8(e)+1,i=n._malloc(r);return n.stringToUTF8(e,i,r),t.push(i),i},tt=(e,t,n,r)=>{if(typeof e==`object`&&e){if(n.has(e))throw Error(`Circular reference in options`);n.add(e)}Object.entries(e).forEach(([e,i])=>{let a=t?t+e:e;if(typeof i==`object`)tt(i,a+`.`,n,r);else if(typeof i==`string`||typeof i==`number`)r(a,i.toString());else if(typeof i==`boolean`)r(a,i?`1`:`0`);else throw Error(`Can't handle extra config type: ${typeof i}`)})},R=e=>{let t=F(),n=t.stackSave();try{let n=t.PTR_SIZE,r=t.stackAlloc(2*n);t._OrtGetLastError(r,r+n);let i=Number(t.getValue(r,n===4?`i32`:`i64`)),a=t.getValue(r+n,`*`),o=a?t.UTF8ToString(a):``;throw Error(`${e} ERROR_CODE: ${i}, ERROR_MESSAGE: ${o}`)}finally{t.stackRestore(n)}}}),rt,it=a(()=>{"use strict";I(),nt(),rt=e=>{let t=F(),n=0,r=[],i=e||{};try{if(e?.logSeverityLevel===void 0)i.logSeverityLevel=2;else if(typeof e.logSeverityLevel!=`number`||!Number.isInteger(e.logSeverityLevel)||e.logSeverityLevel<0||e.logSeverityLevel>4)throw Error(`log severity level is not valid: ${e.logSeverityLevel}`);if(e?.logVerbosityLevel===void 0)i.logVerbosityLevel=0;else if(typeof e.logVerbosityLevel!=`number`||!Number.isInteger(e.logVerbosityLevel))throw Error(`log verbosity level is not valid: ${e.logVerbosityLevel}`);e?.terminate===void 0&&(i.terminate=!1);let a=0;return e?.tag!==void 0&&(a=L(e.tag,r)),n=t._OrtCreateRunOptions(i.logSeverityLevel,i.logVerbosityLevel,!!i.terminate,a),n===0&&R(`Can't create run options.`),e?.extra!==void 0&&tt(e.extra,``,/* @__PURE__ */ new WeakSet,(e,i)=>{let a=L(e,r),o=L(i,r);t._OrtAddRunConfigEntry(n,a,o)!==0&&R(`Can't set a run config entry: ${e} - ${i}.`)}),[n,r]}catch(e){throw n!==0&&t._OrtReleaseRunOptions(n),r.forEach(e=>t._free(e)),e}}}),at,ot,st,z,B,ct,lt,ut=a(()=>{"use strict";I(),nt(),at=e=>{switch(e){case`disabled`:return 0;case`basic`:return 1;case`extended`:return 2;case`layout`:return 3;case`all`:return 99;default:throw Error(`unsupported graph optimization level: ${e}`)}},ot=e=>{switch(e){case`sequential`:return 0;case`parallel`:return 1;default:throw Error(`unsupported execution mode: ${e}`)}},st=e=>{e.extra||={},e.extra.session||(e.extra.session={});let t=e.extra.session;t.use_ort_model_bytes_directly||=`1`,e.executionProviders&&e.executionProviders.some(e=>(typeof e==`string`?e:e.name)===`webgpu`)&&(e.enableMemPattern=!1)},z=(e,t,n,r)=>{let i=L(t,r),a=L(n,r);F()._OrtAddSessionConfigEntry(e,i,a)!==0&&R(`Can't set a session config entry: ${t} - ${n}.`)},B=(e,t,n,r)=>{let i=L(t,r),a=L(n,r);e.push([i,a])},ct=async(e,t,n)=>{let r=t.executionProviders;for(let i of r){let r=typeof i==`string`?i:i.name,a=[];switch(r){case`webnn`:if(r=`WEBNN`,z(e,`session.disable_quant_qdq`,`1`,n),z(e,`session.disable_qdq_constant_folding`,`1`,n),typeof i!=`string`){let t=i?.deviceType;t&&z(e,`deviceType`,t,n)}break;case`webgpu`:{r=`WebGPU`;let e;if(typeof i!=`string`){let r=i;if(r.device){if(typeof GPUDevice<`u`&&r.device instanceof GPUDevice)e=r.device;else throw Error(`Invalid GPU device set in WebGPU EP options.`)}let{enableGraphCapture:o}=t;if(typeof o==`boolean`&&o&&B(a,`enableGraphCapture`,`1`,n),typeof r.preferredLayout==`string`&&B(a,`preferredLayout`,r.preferredLayout,n),r.forceCpuNodeNames){let e=Array.isArray(r.forceCpuNodeNames)?r.forceCpuNodeNames:[r.forceCpuNodeNames];B(a,`forceCpuNodeNames`,e.join(` +`),n)}r.validationMode&&B(a,`validationMode`,r.validationMode,n),typeof r.enableMatmulFp32Accumulation==`boolean`&&B(a,`enableMatmulFp32Accumulation`,r.enableMatmulFp32Accumulation?`1`:`0`,n);for(let e of[`storageBufferCacheMode`,`uniformBufferCacheMode`,`queryResolveBufferCacheMode`,`defaultBufferCacheMode`]){let t=r[e];if(t){if(t!==`disabled`&&t!==`lazyRelease`&&t!==`simple`&&t!==`bucket`)throw Error(`${e} must be one of 'disabled', 'lazyRelease', 'simple' or 'bucket': ${t}`);B(a,e,t,n)}}}let o=F().webgpuRegisterDevice(e);if(o){let[e,t,r]=o;B(a,`deviceId`,e.toString(),n),B(a,`webgpuInstance`,t.toString(),n),B(a,`webgpuDevice`,r.toString(),n)}}break;case`wasm`:case`cpu`:continue;default:throw Error(`not supported execution provider: ${r}`)}let o=L(r,n),s=a.length,c=0,l=0;if(s>0){c=F()._malloc(s*F().PTR_SIZE),n.push(c),l=F()._malloc(s*F().PTR_SIZE),n.push(l);for(let e=0;e{let t=F(),n=0,r=[],i=e||{};st(i);try{let e=at(i.graphOptimizationLevel??`all`),a=ot(i.executionMode??`sequential`),o=typeof i.logId==`string`?L(i.logId,r):0,s=i.logSeverityLevel??2;if(!Number.isInteger(s)||s<0||s>4)throw Error(`log severity level is not valid: ${s}`);let c=i.logVerbosityLevel??0;if(!Number.isInteger(c)||c<0||c>4)throw Error(`log verbosity level is not valid: ${c}`);let l=typeof i.optimizedModelFilePath==`string`?L(i.optimizedModelFilePath,r):0;if(n=t._OrtCreateSessionOptions(e,!!i.enableCpuMemArena,!!i.enableMemPattern,a,!!i.enableProfiling,0,o,s,c,l),n===0&&R(`Can't create session options.`),i.executionProviders&&await ct(n,i,r),i.enableGraphCapture!==void 0){if(typeof i.enableGraphCapture!=`boolean`)throw Error(`enableGraphCapture must be a boolean value: ${i.enableGraphCapture}`);z(n,`enableGraphCapture`,i.enableGraphCapture.toString(),r)}if(i.freeDimensionOverrides)for(let[e,a]of Object.entries(i.freeDimensionOverrides)){if(typeof e!=`string`)throw Error(`free dimension override name must be a string: ${e}`);if(typeof a!=`number`||!Number.isInteger(a)||a<0)throw Error(`free dimension override value must be a non-negative integer: ${a}`);let i=L(e,r);t._OrtAddFreeDimensionOverride(n,i,a)!==0&&R(`Can't set a free dimension override: ${e} - ${a}.`)}return i.extra!==void 0&&tt(i.extra,``,/* @__PURE__ */ new WeakSet,(e,t)=>{z(n,e,t,r)}),[n,r]}catch(e){throw n!==0&&t._OrtReleaseSessionOptions(n)!==0&&R(`Can't release session options.`),r.forEach(e=>t._free(e)),e}}}),V,dt,H,U,ft,pt,mt,ht,W=a(()=>{"use strict";V=e=>{switch(e){case`int8`:return 3;case`uint8`:return 2;case`bool`:return 9;case`int16`:return 5;case`uint16`:return 4;case`int32`:return 6;case`uint32`:return 12;case`float16`:return 10;case`float32`:return 1;case`float64`:return 11;case`string`:return 8;case`int64`:return 7;case`uint64`:return 13;case`int4`:return 22;case`uint4`:return 21;default:throw Error(`unsupported data type: ${e}`)}},dt=e=>{switch(e){case 3:return`int8`;case 2:return`uint8`;case 9:return`bool`;case 5:return`int16`;case 4:return`uint16`;case 6:return`int32`;case 12:return`uint32`;case 10:return`float16`;case 1:return`float32`;case 11:return`float64`;case 8:return`string`;case 7:return`int64`;case 13:return`uint64`;case 22:return`int4`;case 21:return`uint4`;default:throw Error(`unsupported data type: ${e}`)}},H=(e,t)=>{let n=[-1,4,1,1,2,2,4,8,-1,1,2,8,4,8,-1,-1,-1,-1,-1,-1,-1,.5,.5][e],r=typeof t==`number`?t:t.reduce((e,t)=>e*t,1);return n>0?Math.ceil(r*n):void 0},U=e=>{switch(e){case`float16`:return typeof Float16Array<`u`?Float16Array:Uint16Array;case`float32`:return Float32Array;case`uint8`:return Uint8Array;case`int8`:return Int8Array;case`uint16`:return Uint16Array;case`int16`:return Int16Array;case`int32`:return Int32Array;case`bool`:return Uint8Array;case`float64`:return Float64Array;case`uint32`:return Uint32Array;case`int64`:return BigInt64Array;case`uint64`:return BigUint64Array;default:throw Error(`unsupported type: ${e}`)}},ft=e=>{switch(e){case`verbose`:return 0;case`info`:return 1;case`warning`:return 2;case`error`:return 3;case`fatal`:return 4;default:throw Error(`unsupported logging level: ${e}`)}},pt=e=>e===`float32`||e===`float16`||e===`int32`||e===`int64`||e===`uint32`||e===`uint8`||e===`bool`||e===`uint4`||e===`int4`,mt=e=>e===`float32`||e===`float16`||e===`int32`||e===`int64`||e===`uint32`||e===`uint64`||e===`int8`||e===`uint8`||e===`bool`||e===`uint4`||e===`int4`,ht=e=>{switch(e){case`none`:return 0;case`cpu`:return 1;case`cpu-pinned`:return 2;case`texture`:return 3;case`gpu-buffer`:return 4;case`ml-tensor`:return 5;default:throw Error(`unsupported data location: ${e}`)}}}),gt,_t=a(()=>{"use strict";Oe(),gt=async e=>{if(typeof e==`string`){let t=await fetch(e);if(!t.ok)throw Error(`failed to load external data file: ${e}`);let n=t.headers.get(`Content-Length`),r=n?parseInt(n,10):0;if(r<1073741824)return new Uint8Array(await t.arrayBuffer());{if(!t.body)throw Error(`failed to load external data file: ${e}, no response body.`);let n=t.body.getReader(),i;try{i=new ArrayBuffer(r)}catch(e){if(e instanceof RangeError){let e=Math.ceil(r/65536);i=new WebAssembly.Memory({initial:e,maximum:e}).buffer}else throw e}let a=0;for(;;){let{done:e,value:t}=await n.read();if(e)break;let r=t.byteLength;new Uint8Array(i,a,r).set(t),a+=r}return new Uint8Array(i,0,r)}}return e instanceof Blob?new Uint8Array(await e.arrayBuffer()):e instanceof Uint8Array?e:new Uint8Array(e)}}),vt,yt=a(()=>{"use strict";W(),vt=(e,t)=>new(U(t))(e)}),bt,xt,St,Ct,wt,Tt,G,Et=a(()=>{"use strict";W(),bt=[`V`,`I`,`W`,`E`,`F`],xt=(e,t)=>{console.log(`[${bt[e]},${(/* @__PURE__ */ new Date()).toISOString()}]${t}`)},wt=(e,t)=>{St=e,Ct=t},Tt=(e,t)=>{let n=ft(e);n>=ft(St)&&xt(n,typeof t==`function`?t():t)},G=(...e)=>{Ct&&Tt(...e)}}),Dt,Ot,kt,At,jt,Mt,Nt,Pt,Ft,It,Lt,Rt=a(()=>{"use strict";W(),Et(),Dt=/* @__PURE__ */ new Map([[`float32`,32],[`float16`,16],[`int32`,32],[`uint32`,32],[`int64`,64],[`uint64`,64],[`int8`,8],[`uint8`,8],[`int4`,4],[`uint4`,4]]),Ot=(e,t)=>{if(t===`int32`)return e;let n=Dt.get(t);if(!n)throw Error(`WebNN backend does not support data type: ${t}`);let r=n/8;if(e.byteLength%r!==0)throw Error(`Invalid Uint8Array length - must be a multiple of ${r}.`);let i=e.byteLength/r,a=new(U(t))(e.buffer,e.byteOffset,i);switch(t){case`int64`:case`uint64`:{let e=new Int32Array(i);for(let t=0;t2147483647n||n<-2147483648n)throw Error(`Can not convert int64 data to int32 - value out of range.`);e[t]=Number(n)}return new Uint8Array(e.buffer)}case`int8`:case`uint8`:case`uint32`:{if(t===`uint32`&&a.some(e=>e>2147483647))throw Error(`Can not convert uint32 data to int32 - value out of range.`);let e=Int32Array.from(a,Number);return new Uint8Array(e.buffer)}default:throw Error(`Unsupported data conversion from ${t} to 'int32'`)}},kt=(e,t)=>{if(t===`int32`)return e;if(e.byteLength%4!=0)throw Error(`Invalid Uint8Array length - must be a multiple of 4 (int32).`);let n=e.byteLength/4,r=new Int32Array(e.buffer,e.byteOffset,n);switch(t){case`int64`:{let e=BigInt64Array.from(r,BigInt);return new Uint8Array(e.buffer)}case`uint64`:{if(r.some(e=>e<0))throw Error(`Can not convert int32 data to uin64 - negative value found.`);let e=BigUint64Array.from(r,BigInt);return new Uint8Array(e.buffer)}case`int8`:{if(r.some(e=>e<-128||e>127))throw Error(`Can not convert int32 data to int8 - value out of range.`);let e=Int8Array.from(r,Number);return new Uint8Array(e.buffer)}case`uint8`:if(r.some(e=>e<0||e>255))throw Error(`Can not convert int32 data to uint8 - value out of range.`);return Uint8Array.from(r,Number);case`uint32`:{if(r.some(e=>e<0))throw Error(`Can not convert int32 data to uint32 - negative value found.`);let e=Uint32Array.from(r,Number);return new Uint8Array(e.buffer)}default:throw Error(`Unsupported data conversion from 'int32' to ${t}`)}},At=1,jt=()=>At++,Mt=/* @__PURE__ */ new Map([[`int8`,`int32`],[`uint8`,`int32`],[`uint32`,`int32`],[`int64`,`int32`]]),Nt=(e,t)=>{let n=Dt.get(e);if(!n)throw Error(`WebNN backend does not support data type: ${e}`);return t.length>0?Math.ceil(t.reduce((e,t)=>e*t)*n/8):0},Pt=class{constructor(e){this.isDataConverted=!1;let{sessionId:t,context:n,tensor:r,dataType:i,shape:a,fallbackDataType:o}=e;this.sessionId=t,this.mlContext=n,this.mlTensor=r,this.dataType=i,this.tensorShape=a,this.fallbackDataType=o}get tensor(){return this.mlTensor}get type(){return this.dataType}get fallbackType(){return this.fallbackDataType}get shape(){return this.tensorShape}get byteLength(){return Nt(this.dataType,this.tensorShape)}destroy(){G(`verbose`,()=>`[WebNN] TensorWrapper.destroy`),this.mlTensor.destroy()}write(e){this.mlContext.writeTensor(this.mlTensor,e)}async read(e){if(this.fallbackDataType){let t=await this.mlContext.readTensor(this.mlTensor),n=kt(new Uint8Array(t),this.dataType);if(e){(e instanceof ArrayBuffer?new Uint8Array(e):new Uint8Array(e.buffer,e.byteOffset,e.byteLength)).set(n);return}return new Uint8Array(n).buffer}return e?this.mlContext.readTensor(this.mlTensor,e):this.mlContext.readTensor(this.mlTensor)}canReuseTensor(e,t,n){return this.mlContext===e&&this.dataType===t&&this.tensorShape.length===n.length&&this.tensorShape.every((e,t)=>e===n[t])}setIsDataConverted(e){this.isDataConverted=e}},Ft=class{constructor(e,t){this.tensorManager=e,this.wrapper=t}get tensorWrapper(){return this.wrapper}releaseTensor(){this.tensorWrapper&&(this.tensorManager.releaseTensor(this.tensorWrapper),this.wrapper=void 0)}async ensureTensor(e,t,n,r){let i=this.tensorManager.getMLContext(e),a=this.tensorManager.getMLOpSupportLimits(e),o;if(!a?.input.dataTypes.includes(t)){if(o=Mt.get(t),!o||!a?.input.dataTypes.includes(o))throw Error(`WebNN backend does not support data type: ${t}`);G(`verbose`,()=>`[WebNN] TensorIdTracker.ensureTensor: fallback dataType from ${t} to ${o}`)}if(this.wrapper){if(this.wrapper.canReuseTensor(i,t,n))return this.wrapper.tensor;if(r){if(this.wrapper.byteLength!==Nt(t,n))throw Error(`Unable to copy data to tensor with different size.`);this.activeUpload=new Uint8Array(await this.wrapper.read())}this.tensorManager.releaseTensor(this.wrapper)}let s=typeof MLTensorUsage>`u`?void 0:MLTensorUsage.READ|MLTensorUsage.WRITE;return this.wrapper=await this.tensorManager.getCachedTensor(e,t,n,s,!0,!0,o),r&&this.activeUpload&&(this.wrapper.write(this.activeUpload),this.activeUpload=void 0),this.wrapper.tensor}upload(e){let t=e;if(this.wrapper){if(this.wrapper.fallbackType){if(this.wrapper.fallbackType===`int32`)t=Ot(e,this.wrapper.type),this.wrapper.setIsDataConverted(!0);else throw Error(`Unsupported fallback data type: ${this.wrapper.fallbackType}`)}if(e.byteLength===this.wrapper.byteLength){this.wrapper.write(t);return}G(`verbose`,()=>`Data size does not match tensor size. Releasing tensor.`),this.releaseTensor()}this.activeUpload?this.activeUpload.set(t):this.activeUpload=new Uint8Array(t)}async download(e){if(this.activeUpload){let t=this.wrapper?.isDataConverted?kt(this.activeUpload,this.wrapper?.type):this.activeUpload;if(e){e instanceof ArrayBuffer?new Uint8Array(e).set(t):new Uint8Array(e.buffer,e.byteOffset,e.byteLength).set(t);return}return t.buffer}if(!this.wrapper)throw Error(`Tensor has not been created.`);return e?this.wrapper.read(e):this.wrapper.read()}},It=class{constructor(e){this.backend=e,this.tensorTrackersById=/* @__PURE__ */ new Map,this.freeTensors=[],this.externalTensors=/* @__PURE__ */ new Set}getMLContext(e){let t=this.backend.getMLContext(e);if(!t)throw Error(`MLContext not found for session.`);return t}getMLOpSupportLimits(e){return this.backend.getMLOpSupportLimits(e)}reserveTensorId(){let e=jt();return this.tensorTrackersById.set(e,new Ft(this)),e}releaseTensorId(e){let t=this.tensorTrackersById.get(e);t&&(this.tensorTrackersById.delete(e),t.tensorWrapper&&this.releaseTensor(t.tensorWrapper))}async ensureTensor(e,t,n,r,i){G(`verbose`,()=>`[WebNN] TensorManager.ensureTensor {tensorId: ${t}, dataType: ${n}, shape: ${r}, copyOld: ${i}}`);let a=this.tensorTrackersById.get(t);if(!a)throw Error(`Tensor not found.`);return a.ensureTensor(e,n,r,i)}upload(e,t){let n=this.tensorTrackersById.get(e);if(!n)throw Error(`Tensor not found.`);n.upload(t)}async download(e,t){G(`verbose`,()=>`[WebNN] TensorManager.download {tensorId: ${e}, dstBuffer: ${t?.byteLength}}`);let n=this.tensorTrackersById.get(e);if(!n)throw Error(`Tensor not found.`);return n.download(t)}releaseTensorsForSession(e){for(let t of this.freeTensors)t.sessionId===e&&t.destroy();this.freeTensors=this.freeTensors.filter(t=>t.sessionId!==e)}registerTensor(e,t,n,r){let i=this.getMLContext(e),a=jt(),o=new Pt({sessionId:e,context:i,tensor:t,dataType:n,shape:r});return this.tensorTrackersById.set(a,new Ft(this,o)),this.externalTensors.add(o),a}async getCachedTensor(e,t,n,r,i,a,o){let s=this.getMLContext(e);for(let[r,i]of this.freeTensors.entries())if(i.canReuseTensor(s,t,n)){G(`verbose`,()=>`[WebNN] Reusing tensor {dataType: ${t}, ${o?`fallbackDataType: ${o},`:``} shape: ${n}`);let i=this.freeTensors.splice(r,1)[0];return i.sessionId=e,i}G(`verbose`,()=>`[WebNN] MLContext.createTensor {dataType: ${t}, ${o?`fallbackDataType: ${o},`:``} shape: ${n}}`);let c=await s.createTensor({dataType:o??t,shape:n,dimensions:n,usage:r,writable:i,readable:a});return new Pt({sessionId:e,context:s,tensor:c,dataType:t,shape:n,fallbackDataType:o})}releaseTensor(e){this.externalTensors.has(e)&&this.externalTensors.delete(e),this.freeTensors.push(e)}},Lt=(...e)=>new It(...e)}),zt={};o(zt,{WebNNBackend:()=>Vt});var K,Bt,Vt,Ht=a(()=>{"use strict";W(),I(),yt(),Rt(),Et(),K=/* @__PURE__ */ new Map([[1,`float32`],[10,`float16`],[6,`int32`],[12,`uint32`],[7,`int64`],[13,`uint64`],[22,`int4`],[21,`uint4`],[3,`int8`],[2,`uint8`],[9,`uint8`]]),Bt=(e,t)=>{if(e===t)return!0;if(e===void 0||t===void 0)return!1;let n=Object.keys(e).sort(),r=Object.keys(t).sort();return n.length===r.length&&n.every((n,i)=>n===r[i]&&e[n]===t[n])},Vt=class{constructor(e){this.tensorManager=Lt(this),this.mlContextBySessionId=/* @__PURE__ */ new Map,this.sessionIdsByMLContext=/* @__PURE__ */ new Map,this.mlContextCache=[],this.sessionGraphInputs=/* @__PURE__ */ new Map,this.sessionGraphOutputs=/* @__PURE__ */ new Map,this.temporaryGraphInputs=[],this.temporaryGraphOutputs=[],this.temporarySessionTensorIds=/* @__PURE__ */ new Map,this.mlOpSupportLimitsBySessionId=/* @__PURE__ */ new Map,wt(e.logLevel,!!e.debug)}get currentSessionId(){if(this.activeSessionId===void 0)throw Error(`No active session`);return this.activeSessionId}onRunStart(e){G(`verbose`,()=>`[WebNN] onRunStart {sessionId: ${e}}`),this.activeSessionId=e}onRunEnd(e){G(`verbose`,()=>`[WebNN] onRunEnd {sessionId: ${e}}`);let t=this.temporarySessionTensorIds.get(e);if(t){for(let e of t)G(`verbose`,()=>`[WebNN] releasing temporary tensor {tensorId: ${e}}`),this.tensorManager.releaseTensorId(e);this.temporarySessionTensorIds.delete(e),this.activeSessionId=void 0}}async createMLContext(e){if(e instanceof GPUDevice){let t=this.mlContextCache.findIndex(t=>t.gpuDevice===e);if(t!==-1)return this.mlContextCache[t].mlContext;{let t=await navigator.ml.createContext(e);return this.mlContextCache.push({gpuDevice:e,mlContext:t}),t}}if(e===void 0){let e=this.mlContextCache.findIndex(e=>e.options===void 0&&e.gpuDevice===void 0);if(e!==-1)return this.mlContextCache[e].mlContext;{let e=await navigator.ml.createContext();return this.mlContextCache.push({mlContext:e}),e}}let t=this.mlContextCache.findIndex(t=>Bt(t.options,e));if(t!==-1)return this.mlContextCache[t].mlContext;{let t=await navigator.ml.createContext(e);return this.mlContextCache.push({options:e,mlContext:t}),t}}registerMLContext(e,t){this.mlContextBySessionId.set(e,t);let n=this.sessionIdsByMLContext.get(t);n||(n=/* @__PURE__ */ new Set,this.sessionIdsByMLContext.set(t,n)),n.add(e),this.mlOpSupportLimitsBySessionId.has(e)||this.mlOpSupportLimitsBySessionId.set(e,t.opSupportLimits()),this.temporaryGraphInputs.length>0&&(this.sessionGraphInputs.set(e,this.temporaryGraphInputs),this.temporaryGraphInputs=[]),this.temporaryGraphOutputs.length>0&&(this.sessionGraphOutputs.set(e,this.temporaryGraphOutputs),this.temporaryGraphOutputs=[])}onReleaseSession(e){this.sessionGraphInputs.delete(e),this.sessionGraphOutputs.delete(e);let t=this.mlContextBySessionId.get(e);if(!t)return;this.tensorManager.releaseTensorsForSession(e),this.mlContextBySessionId.delete(e),this.mlOpSupportLimitsBySessionId.delete(e);let n=this.sessionIdsByMLContext.get(t);if(n.delete(e),n.size===0){this.sessionIdsByMLContext.delete(t);let e=this.mlContextCache.findIndex(e=>e.mlContext===t);e!==-1&&this.mlContextCache.splice(e,1)}}getMLContext(e){return this.mlContextBySessionId.get(e)}getMLOpSupportLimits(e){return this.mlOpSupportLimitsBySessionId.get(e)}reserveTensorId(){return this.tensorManager.reserveTensorId()}releaseTensorId(e){G(`verbose`,()=>`[WebNN] releaseTensorId {tensorId: ${e}}`),this.tensorManager.releaseTensorId(e)}async ensureTensor(e,t,n,r,i){let a=K.get(n);if(!a)throw Error(`Unsupported ONNX data type: ${n}`);return this.tensorManager.ensureTensor(e??this.currentSessionId,t,a,r,i)}async createTemporaryTensor(e,t,n){G(`verbose`,()=>`[WebNN] createTemporaryTensor {onnxDataType: ${t}, shape: ${n}}`);let r=K.get(t);if(!r)throw Error(`Unsupported ONNX data type: ${t}`);let i=this.tensorManager.reserveTensorId();await this.tensorManager.ensureTensor(e,i,r,n,!1);let a=this.temporarySessionTensorIds.get(e);return a?a.push(i):this.temporarySessionTensorIds.set(e,[i]),i}uploadTensor(e,t){if(!F().shouldTransferToMLTensor)throw Error(`Trying to upload to a MLTensor while shouldTransferToMLTensor is false`);G(`verbose`,()=>`[WebNN] uploadTensor {tensorId: ${e}, data: ${t.byteLength}}`),this.tensorManager.upload(e,t)}async downloadTensor(e,t){return this.tensorManager.download(e,t)}createMLTensorDownloader(e,t){return async()=>{let n=await this.tensorManager.download(e);return vt(n,t)}}registerMLTensor(e,t,n,r){let i=K.get(n);if(!i)throw Error(`Unsupported ONNX data type: ${n}`);let a=this.tensorManager.registerTensor(e,t,i,r);return G(`verbose`,()=>`[WebNN] registerMLTensor {tensor: ${t}, dataType: ${i}, dimensions: ${r}} -> {tensorId: ${a}}`),a}registerGraphInput(e){this.temporaryGraphInputs.push(e)}registerGraphOutput(e){this.temporaryGraphOutputs.push(e)}isGraphInput(e,t){let n=this.sessionGraphInputs.get(e);return n?n.includes(t):!1}isGraphOutput(e,t){let n=this.sessionGraphOutputs.get(e);return n?n.includes(t):!1}isGraphInputOutputTypeSupported(e,t,n=!0){let r=K.get(V(t)),i=this.mlOpSupportLimitsBySessionId.get(e);return typeof r>`u`?!1:n?!!i?.input.dataTypes.includes(r):!!i?.output.dataTypes.includes(r)}flush(){}}}),Ut,Wt,Gt,q,Kt,qt,Jt,Yt,Xt,Zt,Qt,$t,en,tn=a(()=>{"use strict";M(),it(),ut(),W(),I(),nt(),_t(),Ut=(e,t)=>{F()._OrtInit(e,t)!==0&&R(`Can't initialize onnxruntime.`)},Wt=async e=>{Ut(e.wasm.numThreads,ft(e.logLevel))},Gt=async(e,t)=>{F().asyncInit?.();let n=e.webgpu.adapter;if(t===`webgpu`){if(typeof navigator>`u`||!navigator.gpu)throw Error(`WebGPU is not supported in current environment`);if(n){if(typeof n.limits!=`object`||typeof n.features!=`object`||typeof n.requestDevice!=`function`)throw Error("Invalid GPU adapter set in `env.webgpu.adapter`. It must be a GPUAdapter object.")}else{let t=e.webgpu.powerPreference;if(t!==void 0&&t!==`low-power`&&t!==`high-performance`)throw Error(`Invalid powerPreference setting: "${t}"`);let r=e.webgpu.forceFallbackAdapter;if(r!==void 0&&typeof r!=`boolean`)throw Error(`Invalid forceFallbackAdapter setting: "${r}"`);if(n=await navigator.gpu.requestAdapter({powerPreference:t,forceFallbackAdapter:r}),!n)throw Error(`Failed to get GPU adapter. You may need to enable flag "--enable-unsafe-webgpu" if you are using Chrome.`)}}if(t===`webnn`&&(typeof navigator>`u`||!navigator.ml))throw Error(`WebNN is not supported in current environment`);if(t===`webgpu`&&F().webgpuInit(t=>{e.webgpu.device=t}),t===`webnn`){let t=new(Ht(),c(zt)).WebNNBackend(e);F().webnnInit([t,()=>t.reserveTensorId(),e=>t.releaseTensorId(e),async(e,n,r,i,a)=>t.ensureTensor(e,n,r,i,a),(e,n)=>{t.uploadTensor(e,n)},async(e,n)=>t.downloadTensor(e,n),(e,n)=>t.registerMLContext(e,n),!!e.trace])}},q=/* @__PURE__ */ new Map,Kt=e=>{let t=F(),n=t.stackSave();try{let n=t.PTR_SIZE,r=t.stackAlloc(2*n);t._OrtGetInputOutputCount(e,r,r+n)!==0&&R(`Can't get session input/output count.`);let i=n===4?`i32`:`i64`;return[Number(t.getValue(r,i)),Number(t.getValue(r+n,i))]}finally{t.stackRestore(n)}},qt=(e,t)=>{let n=F(),r=n.stackSave(),i=0;try{let r=n.PTR_SIZE,a=n.stackAlloc(2*r);n._OrtGetInputOutputMetadata(e,t,a,a+r)!==0&&R(`Can't get session input/output metadata.`);let o=Number(n.getValue(a,`*`));i=Number(n.getValue(a+r,`*`));let s=n.HEAP32[i/4];if(s===0)return[o,0];let c=n.HEAPU32[i/4+1],l=[];for(let e=0;e{let t=F(),n=t._malloc(e.byteLength);if(n===0)throw Error(`Can't create a session. failed to allocate a buffer of size ${e.byteLength}.`);return t.HEAPU8.set(e,n),[n,e.byteLength]},Yt=async(e,t)=>{let n,r,i=F();Array.isArray(e)?[n,r]=e:e.buffer===i.HEAPU8.buffer?[n,r]=[e.byteOffset,e.byteLength]:[n,r]=Jt(e);let a=0,o=0,s=0,c=[],l=[],u=[];try{if([o,c]=await lt(t),t?.externalData&&i.mountExternalData){let e=[];for(let n of t.externalData){let t=typeof n==`string`?n:n.path,r=typeof n==`string`?n:n.data;e.push(gt(r).then(e=>{i.mountExternalData(t,e)}))}await Promise.all(e)}for(let e of t?.executionProviders??[])if((typeof e==`string`?e:e.name)===`webnn`){if(i.shouldTransferToMLTensor=!1,typeof e!=`string`){let t=e,n=t?.context,r=t?.gpuDevice,a=t?.deviceType,o=t?.powerPreference;i.currentContext=n||(r?await i.webnnCreateMLContext(r):await i.webnnCreateMLContext({deviceType:a,powerPreference:o}))}else i.currentContext=await i.webnnCreateMLContext();break}a=await i._OrtCreateSession(n,r,o),i.webgpuOnCreateSession?.(a),a===0&&R(`Can't create a session.`),i.jsepOnCreateSession?.(),i.currentContext&&(i.webnnRegisterMLContext(a,i.currentContext),i.currentContext=void 0,i.shouldTransferToMLTensor=!0);let[e,d]=Kt(a),f=!!t?.enableGraphCapture,p=[],m=[],h=[],g=[],_=[];for(let t=0;te===`gpu-buffer`||e===`ml-tensor`||e===`ml-tensor-cpu-output`)&&(s=i._OrtCreateBinding(a),s===0&&R(`Can't create IO binding.`),v={handle:s,outputPreferredLocations:_,outputPreferredLocationsEncoded:_.map(e=>e===`ml-tensor-cpu-output`?`ml-tensor`:e).map(e=>ht(e))}),q.set(a,[a,l,u,v,f,!1]),[a,p,m,h,g]}catch(e){throw l.forEach(e=>i._OrtFree(e)),u.forEach(e=>i._OrtFree(e)),s!==0&&i._OrtReleaseBinding(s)!==0&&R(`Can't release IO binding.`),a!==0&&i._OrtReleaseSession(a)!==0&&R(`Can't release session.`),e}finally{i._free(n),o!==0&&i._OrtReleaseSessionOptions(o)!==0&&R(`Can't release session options.`),c.forEach(e=>i._free(e)),i.unmountExternalData?.()}},Xt=e=>{let t=F(),n=q.get(e);if(!n)throw Error(`cannot release session. invalid session id: ${e}`);let[r,i,a,o,s]=n;o&&(s&&t._OrtClearBoundOutputs(o.handle)!==0&&R(`Can't clear bound outputs.`),t._OrtReleaseBinding(o.handle)!==0&&R(`Can't release IO binding.`)),t.jsepOnReleaseSession?.(e),t.webnnOnReleaseSession?.(e),t.webgpuOnReleaseSession?.(e),i.forEach(e=>t._OrtFree(e)),a.forEach(e=>t._OrtFree(e)),t._OrtReleaseSession(r)!==0&&R(`Can't release session.`),q.delete(e)},Zt=async(e,t,n,r,i,a,o=!1)=>{if(!e){t.push(0);return}let s=F(),c=s.PTR_SIZE,l=e[0],u=e[1],d=e[3],f=d,p,m;if(l===`string`&&(d===`gpu-buffer`||d===`ml-tensor`))throw Error(`String tensor is not supported on GPU.`);if(o&&d!==`gpu-buffer`)throw Error(`External buffer must be provided for input/output index ${a} when enableGraphCapture is true.`);if(d===`gpu-buffer`){let t=e[2].gpuBuffer;m=H(V(l),u);{let e=s.webgpuRegisterBuffer;if(!e)throw Error(`Tensor location "gpu-buffer" is not supported without using WebGPU.`);p=e(t,r)}}else if(d===`ml-tensor`){let t=e[2].mlTensor;m=H(V(l),u);let n=s.webnnRegisterMLTensor;if(!n)throw Error(`Tensor location "ml-tensor" is not supported without using WebNN.`);p=n(r,t,V(l),u)}else{let t=e[2];if(Array.isArray(t)){m=c*t.length,p=s._malloc(m),n.push(p);for(let e=0;es.setValue(g+t*c,e,c===4?`i32`:`i64`));let e=s._OrtCreateTensor(V(l),p,m,g,u.length,ht(f));e===0&&R(`Can't create tensor for input/output. session=${r}, index=${a}.`),t.push(e)}finally{s.stackRestore(h)}},Qt=async(e,t,n,r,i,a)=>{let o=F(),s=o.PTR_SIZE,c=q.get(e);if(!c)throw Error(`cannot run inference. invalid session id: ${e}`);let l=c[0],u=c[1],d=c[2],f=c[3],p=c[4],m=c[5],h=t.length,g=r.length,_=0,v=[],y=[],b=[],x=[],ee=[],S=o.stackSave(),te=o.stackAlloc(h*s),ne=o.stackAlloc(h*s),C=o.stackAlloc(g*s),re=o.stackAlloc(g*s);try{[_,v]=rt(a),A(`wasm prepareInputOutputTensor`);for(let r=0;re*t,1);u=dt(a);let _=f?.outputPreferredLocations[r[t]];if(u===`string`){if(_===`gpu-buffer`||_===`ml-tensor`)throw Error(`String tensor is not supported on GPU.`);let e=[];for(let t=0;t0){let t=o.webgpuGetBuffer;if(!t)throw Error(`preferredLocation "gpu-buffer" is not supported without using WebGPU.`);let r=t(d),i=H(a,g);if(i===void 0||!pt(u))throw Error(`Unsupported data type: ${u}`);l=!0;{o.webgpuRegisterBuffer(r,e,d);let t=o.webgpuCreateDownloader(r,i,e);S.push([u,h,{gpuBuffer:r,download:async()=>{let e=await t();return new(U(u))(e)},dispose:()=>{o._OrtReleaseTensor(n)!==0&&R(`Can't release tensor.`)}},`gpu-buffer`])}}else if(_===`ml-tensor`&&g>0){let t=o.webnnEnsureTensor,r=o.webnnIsGraphInputOutputTypeSupported;if(!t||!r)throw Error(`preferredLocation "ml-tensor" is not supported without using WebNN.`);if(H(a,g)===void 0||!mt(u))throw Error(`Unsupported data type: ${u}`);if(!r(e,u,!1))throw Error(`preferredLocation "ml-tensor" for ${u} output is not supported by current WebNN Context.`);let i=await t(e,d,a,h,!1);l=!0,S.push([u,h,{mlTensor:i,download:o.webnnCreateMLTensorDownloader(d,u),dispose:()=>{o.webnnReleaseTensorId(d),o._OrtReleaseTensor(n)}},`ml-tensor`])}else if(_===`ml-tensor-cpu-output`&&g>0){let e=o.webnnCreateMLTensorDownloader(d,u)(),t=S.length;l=!0,ie.push((async()=>{let r=[t,await e];return o.webnnReleaseTensorId(d),o._OrtReleaseTensor(n),r})()),S.push([u,h,[],`cpu`])}else{let e=new(U(u))(g);new Uint8Array(e.buffer,e.byteOffset,e.byteLength).set(o.HEAPU8.subarray(d,d+e.byteLength)),S.push([u,h,e,`cpu`])}}finally{o.stackRestore(a),u===`string`&&d&&o._free(d),l||o._OrtReleaseTensor(n)}}f&&!p&&(o._OrtClearBoundOutputs(f.handle)!==0&&R(`Can't clear bound outputs.`),q.set(e,[l,u,d,f,p,!1]));for(let[e,t]of await Promise.all(ie))S[e][2]=t;return j(`wasm ProcessOutputTensor`),S}finally{o.webnnOnRunEnd?.(l),o.stackRestore(S),n.forEach(e=>{e&&e[3]===`gpu-buffer`&&o.webgpuUnregisterBuffer(e[2].gpuBuffer)}),i.forEach(e=>{e&&e[3]===`gpu-buffer`&&o.webgpuUnregisterBuffer(e[2].gpuBuffer)}),y.forEach(e=>o._OrtReleaseTensor(e)),b.forEach(e=>o._OrtReleaseTensor(e)),x.forEach(e=>o._free(e)),_!==0&&o._OrtReleaseRunOptions(_),v.forEach(e=>o._free(e))}},$t=e=>{let t=F(),n=q.get(e);if(!n)throw Error(`invalid session id`);let r=n[0],i=t._OrtEndProfiling(r);i===0&&R(`Can't get an profile file name.`),t._OrtFree(i)},en=e=>{let t=[];for(let n of e){let e=n[2];!Array.isArray(e)&&`buffer`in e&&t.push(e.buffer)}return t}}),J,Y,X,nn,rn,an,on,sn,Z,Q,cn,ln,un,dn,fn,pn,mn,hn,gn=a(()=>{"use strict";M(),tn(),I(),qe(),J=()=>!!x.wasm.proxy&&typeof document<`u`,X=!1,nn=!1,rn=!1,sn=/* @__PURE__ */ new Map,Z=(e,t)=>{let n=sn.get(e);n?n.push(t):sn.set(e,[t])},Q=()=>{if(X||!nn||rn||!Y)throw Error(`worker not ready`)},cn=e=>{switch(e.data.type){case`init-wasm`:X=!1,e.data.err?(rn=!0,on[1](e.data.err)):(nn=!0,on[0]()),an&&=(URL.revokeObjectURL(an),void 0);break;case`init-ep`:case`copy-from`:case`create`:case`release`:case`run`:case`end-profiling`:{let t=sn.get(e.data.type);e.data.err?t.shift()[1](e.data.err):t.shift()[0](e.data.out);break}}},ln=async()=>{if(!nn){if(X)throw Error(`multiple calls to 'initWasm()' detected.`);if(rn)throw Error(`previous call to 'initWasm()' failed.`);if(X=!0,J())return new Promise((e,t)=>{Y?.terminate(),We().then(([n,r])=>{try{Y=r,Y.onerror=e=>t(e),Y.onmessage=cn,on=[e,t];let i={type:`init-wasm`,in:x};if(!i.in.wasm.wasmPaths&&n){let e=Le();e&&(i.in.wasm.wasmPaths=e)}Y.postMessage(i),an=n}catch(e){t(e)}},t)});try{await et(x.wasm),await Wt(x),nn=!0}catch(e){throw rn=!0,e}finally{X=!1}}},un=async e=>{if(J())return Q(),new Promise((t,n)=>{Z(`init-ep`,[t,n]);let r={type:`init-ep`,in:{epName:e,env:x}};Y.postMessage(r)});await Gt(x,e)},dn=async e=>J()?(Q(),new Promise((t,n)=>{Z(`copy-from`,[t,n]);let r={type:`copy-from`,in:{buffer:e}};Y.postMessage(r,[e.buffer])})):Jt(e),fn=async(e,t)=>{if(J()){if(t?.preferredOutputLocation)throw Error(`session option "preferredOutputLocation" is not supported for proxy.`);return Q(),new Promise((n,r)=>{Z(`create`,[n,r]);let i={type:`create`,in:{model:e,options:{...t}}},a=[];e instanceof Uint8Array&&a.push(e.buffer),Y.postMessage(i,a)})}return Yt(e,t)},pn=async e=>{if(J())return Q(),new Promise((t,n)=>{Z(`release`,[t,n]);let r={type:`release`,in:e};Y.postMessage(r)});Xt(e)},mn=async(e,t,n,r,i,a)=>{if(J()){if(n.some(e=>e[3]!==`cpu`))throw Error(`input tensor on GPU is not supported for proxy.`);if(i.some(e=>e))throw Error(`pre-allocated output tensor is not supported for proxy.`);return Q(),new Promise((i,o)=>{Z(`run`,[i,o]);let s=n,c={type:`run`,in:{sessionId:e,inputIndices:t,inputs:s,outputIndices:r,options:a}};Y.postMessage(c,en(s))})}return Qt(e,t,n,r,i,a)},hn=async e=>{if(J())return Q(),new Promise((t,n)=>{Z(`end-profiling`,[t,n]);let r={type:`end-profiling`,in:e};Y.postMessage(r)});$t(e)}}),_n,vn,yn,bn=a(()=>{"use strict";M(),gn(),W(),Oe(),_t(),_n=(e,t)=>{switch(e.location){case`cpu`:return[e.type,e.dims,e.data,`cpu`];case`gpu-buffer`:return[e.type,e.dims,{gpuBuffer:e.gpuBuffer},`gpu-buffer`];case`ml-tensor`:return[e.type,e.dims,{mlTensor:e.mlTensor},`ml-tensor`];default:throw Error(`invalid data location: ${e.location} for ${t()}`)}},vn=e=>{switch(e[3]){case`cpu`:return new D(e[0],e[2],e[1]);case`gpu-buffer`:{let t=e[0];if(!pt(t))throw Error(`not supported data type: ${t} for deserializing GPU tensor`);let{gpuBuffer:n,download:r,dispose:i}=e[2];return D.fromGpuBuffer(n,{dataType:t,dims:e[1],download:r,dispose:i})}case`ml-tensor`:{let t=e[0];if(!mt(t))throw Error(`not supported data type: ${t} for deserializing MLTensor tensor`);let{mlTensor:n,download:r,dispose:i}=e[2];return D.fromMLTensor(n,{dataType:t,dims:e[1],download:r,dispose:i})}default:throw Error(`invalid data location: ${e[3]}`)}},yn=class{async fetchModelAndCopyToWasmMemory(e){return dn(await gt(e))}async loadModel(e,t){O();let n;n=typeof e==`string`?await this.fetchModelAndCopyToWasmMemory(e):e,[this.sessionId,this.inputNames,this.outputNames,this.inputMetadata,this.outputMetadata]=await fn(n,t),k()}async dispose(){return pn(this.sessionId)}async run(e,t,n){O();let r=[],i=[];Object.entries(e).forEach(e=>{let t=e[0],n=e[1],a=this.inputNames.indexOf(t);if(a===-1)throw Error(`invalid input '${t}'`);r.push(n),i.push(a)});let a=[],o=[];Object.entries(t).forEach(e=>{let t=e[0],n=e[1],r=this.outputNames.indexOf(t);if(r===-1)throw Error(`invalid output '${t}'`);a.push(n),o.push(r)});let s=r.map((e,t)=>_n(e,()=>`input "${this.inputNames[i[t]]}"`)),c=a.map((e,t)=>e?_n(e,()=>`output "${this.outputNames[o[t]]}"`):null),l=await mn(this.sessionId,i,s,o,c,n),u={};for(let e=0;eCn,initializeFlags:()=>Sn,wasmBackend:()=>wn});var Sn,Cn,wn,Tn=a(()=>{"use strict";M(),gn(),bn(),Sn=()=>{(typeof x.wasm.initTimeout!=`number`||x.wasm.initTimeout<0)&&(x.wasm.initTimeout=0);let e=x.wasm.simd;if(typeof e!=`boolean`&&e!==void 0&&e!==`fixed`&&e!==`relaxed`&&(console.warn(`Property "env.wasm.simd" is set to unknown value "${e}". Reset it to \`false\` and ignore SIMD feature checking.`),x.wasm.simd=!1),typeof x.wasm.proxy!=`boolean`&&(x.wasm.proxy=!1),typeof x.wasm.trace!=`boolean`&&(x.wasm.trace=!1),typeof x.wasm.numThreads!=`number`||!Number.isInteger(x.wasm.numThreads)||x.wasm.numThreads<=0){if(typeof self<`u`&&!self.crossOriginIsolated)x.wasm.numThreads=1;else{let e=typeof navigator>`u`?i(`node:os`).cpus().length:navigator.hardwareConcurrency;x.wasm.numThreads=Math.min(4,Math.ceil((e||1)/2))}}},Cn=class{async init(e){Sn(),await ln(),await un(e)}async createInferenceSessionHandler(e,t){let n=new yn;return await n.loadModel(e,t),n}},wn=new Cn});M(),M(),M();var En=`1.31.0-dev.20260914-8d85527a0`;{let e=(Tn(),c(xn)).wasmBackend;d(`webgpu`,e,5),d(`webnn`,e,5),d(`cpu`,e,10),d(`wasm`,e,10)}Object.defineProperty(x.versions,"web",{value:En,enumerable:!0});function Dn(e,t,n){let r=t*n;if(e.length!==r*4||r<1)throw Error(`Invalid U2Net RGB dimensions`);let i=0;for(let t=0;tMath.round(255*Math.max(0,Math.min(1,(e-a)/(o-a)))))}let An=`309c8469258dda742793dce0ebea8e6dd393174f89934733ecc8b14c76f4ddd8`;x.wasm.wasmPaths=`https://cdn.jsdelivr.net/npm/onnxruntime-web@1.31.0-dev.20260914-8d85527a0/dist/`,x.wasm.numThreads=1;let $=self;$.addEventListener(`message`,e=>{e.data.type===`infer`&&jn(e.data)});async function jn({id:e,image:t,forceWasm:n}){let r=performance.now(),i=null,a=null,o=null,s=`wasm`;try{let c=t.width,l=t.height;$.postMessage({type:`status`,id:e,message:`실험용 누끼 모델을 준비하는 중…`});let u=await fetch(`/models/u2netp/model.onnx`,{cache:`force-cache`});if(!u.ok)throw Error(`누끼 모델을 불러오지 못했어요. 다시 시도해 주세요.`);let d=await u.arrayBuffer();if(Array.from(new Uint8Array(await crypto.subtle.digest(`SHA-256`,d)),e=>e.toString(16).padStart(2,`0`)).join(``)!==An)throw Error(`누끼 모델 파일을 확인하지 못했어요.`);if(!n)try{await navigator.gpu?.requestAdapter()&&(s=`webgpu`)}catch{}let f=new OffscreenCanvas(320,320).getContext(`2d`);if(!f)throw Error(`이 브라우저에서 사진을 읽지 못했어요.`);f.drawImage(t,0,0,320,320),a=new D(`float32`,Dn(f.getImageData(0,0,320,320).data,320,320),[1,3,320,320]);let p=0,m=0;try{i=await Se.create(d,{executionProviders:[s],graphOptimizationLevel:`all`}),p=performance.now()-r,$.postMessage({type:`status`,id:e,message:`강아지만 남기는 중… 결과는 다음 화면에서 꼭 확인해 주세요.`});let t=performance.now();o=await i.run({[i.inputNames[0]]:a}),m=performance.now()-t}catch(t){if(s===`webgpu`){await i?.release().catch(()=>{}),i=null,$.postMessage({type:`fallback`,id:e});return}throw t}let h=o[i.outputNames[0]];if(h.type!==`float32`)throw Error(`누끼 모델의 결과 형식이 맞지 않아요.`);let g=h.dims.slice(-2),_=kn(h.data,g[1],g[0],c,l);Object.values(o).forEach(e=>e.dispose()),o=null,a.dispose(),a=null,await i.release(),i=null;let v={model:`U2Netp · experimental foreground`,revision:An,backend:s,downloadBytes:d.byteLength,preparationMs:p,inferenceMs:m,totalMs:performance.now()-r};$.postMessage({type:`result`,id:e,width:c,height:l,alpha:_.buffer,run:v},[_.buffer])}catch(t){$.postMessage({type:`error`,id:e,message:t instanceof Error?t.message:`누끼를 만들지 못했어요. 다른 사진이나 기존 방식을 선택해 주세요.`})}finally{t.close(),a?.dispose(),o&&Object.values(o).forEach(e=>e.dispose()),await i?.release().catch(()=>{})}}})(); \ No newline at end of file diff --git a/dist/assets/index-BYcEjj7E.js b/dist/assets/index-BYcEjj7E.js new file mode 100644 index 0000000..2364e86 --- /dev/null +++ b/dist/assets/index-BYcEjj7E.js @@ -0,0 +1,4173 @@ +(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var e=[`pointerdown`,`mousedown`,`pointerup`,`mouseup`,`click`],t=new WeakMap;function n(n,i,a){r(n);let o=e=>{let t=e.target;n.contains(t)&&((!a||a(t))&&(e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation()),e.type===`click`&&i?.(e))};for(let t of e)document.addEventListener(t,o,!0);t.set(n,o)}function r(n){let r=t.get(n);if(r){for(let t of e)document.removeEventListener(t,r,!0);t.delete(n)}}function i(e,t){let n=e.wrapper.getBoundingClientRect();return{width:n.width+t,height:n.height+t,realWidth:n.width,realHeight:n.height}}function a(e,t){let{elementDimensions:n,popoverDimensions:r,popoverPadding:i,popoverArrowDimensions:a}=t;return e===`start`?Math.max(Math.min(n.top-i,window.innerHeight-r.realHeight-a.width),a.width):e===`end`?Math.max(Math.min(n.top-r?.realHeight+n.height+i,window.innerHeight-r?.realHeight-a.width),a.width):e===`center`?Math.max(Math.min(n.top+n.height/2-r?.realHeight/2,window.innerHeight-r?.realHeight-a.width),a.width):0}function o(e,t){let{elementDimensions:n,popoverDimensions:r,popoverPadding:i,popoverArrowDimensions:a}=t;return e===`start`?Math.max(Math.min(n.left-i,window.innerWidth-r.realWidth-a.width),a.width):e===`end`?Math.max(Math.min(n.left-r?.realWidth+n.width+i,window.innerWidth-r?.realWidth-a.width),a.width):e===`center`?Math.max(Math.min(n.left+n.width/2-r?.realWidth/2,window.innerWidth-r?.realWidth-a.width),a.width):0}function s(e,t,n){let{align:r,side:s}=n,c=n.centered?`over`:s,l=n.padding,u=i(e,n.offset),f=e.arrow.getBoundingClientRect(),p=t.getBoundingClientRect(),m=p.top-u.height,h=m>=0,g=window.innerHeight-(p.bottom+u.height),_=g>=0,v=p.left-u.width,y=v>=0,b=window.innerWidth-(p.right+u.width),x=b>=0,S=!h&&!_&&!y&&!x,C=c;if(c===`top`&&h?x=y=_=!1:c===`bottom`&&_?x=y=h=!1:c===`left`&&y?x=h=_=!1:c===`right`&&x&&(y=h=_=!1),c===`over`){let t=window.innerWidth/2-u.realWidth/2,n=window.innerHeight/2-u.realHeight/2;e.wrapper.style.left=`${t}px`,e.wrapper.style.right=`auto`,e.wrapper.style.top=`${n}px`,e.wrapper.style.bottom=`auto`}else if(S){let t=window.innerWidth/2-u?.realWidth/2;e.wrapper.style.left=`${t}px`,e.wrapper.style.right=`auto`,e.wrapper.style.bottom=`10px`,e.wrapper.style.top=`auto`}else if(y){let t=Math.min(v,window.innerWidth-u?.realWidth-f.width),n=a(r,{elementDimensions:p,popoverDimensions:u,popoverPadding:l,popoverArrowDimensions:f});e.wrapper.style.left=`${t}px`,e.wrapper.style.top=`${n}px`,e.wrapper.style.bottom=`auto`,e.wrapper.style.right=`auto`,C=`left`}else if(x){let t=Math.min(b,window.innerWidth-u?.realWidth-f.width),n=a(r,{elementDimensions:p,popoverDimensions:u,popoverPadding:l,popoverArrowDimensions:f});e.wrapper.style.right=`${t}px`,e.wrapper.style.top=`${n}px`,e.wrapper.style.bottom=`auto`,e.wrapper.style.left=`auto`,C=`right`}else if(h){let t=Math.min(m,window.innerHeight-u.realHeight-f.width),n=o(r,{elementDimensions:p,popoverDimensions:u,popoverPadding:l,popoverArrowDimensions:f});e.wrapper.style.top=`${t}px`,e.wrapper.style.left=`${n}px`,e.wrapper.style.bottom=`auto`,e.wrapper.style.right=`auto`,C=`top`}else if(_){let t=Math.min(g,window.innerHeight-u?.realHeight-f.width),n=o(r,{elementDimensions:p,popoverDimensions:u,popoverPadding:l,popoverArrowDimensions:f});e.wrapper.style.left=`${n}px`,e.wrapper.style.bottom=`${t}px`,e.wrapper.style.top=`auto`,e.wrapper.style.right=`auto`,C=`bottom`}d(e,S?`over`:C,r,t),[...e.wrapper.classList].filter(e=>e.startsWith(`driver-popover-side-`)||e.startsWith(`driver-popover-align-`)).forEach(t=>e.wrapper.classList.remove(t)),e.wrapper.classList.add(`driver-popover-side-${C}`),e.wrapper.classList.add(`driver-popover-align-${r}`)}function c(e,t,n,r,i,a=10){let o=r-n;return e<=n&&t>=r?i===`start`?15+a/2:i===`end`?o-15-a/2:o/2:(Math.min(Math.max(e,n),r)+Math.min(Math.max(t,n),r))/2-n}function l(e,t,n=10){let r=t-15-n;if(r<15)return Math.max(0,(t-n)/2);let i=e-n/2;return Math.min(Math.max(i,15),r)}function u(e,t,n){return e===`left`||e===`right`?t.bottom>n.top&&t.topn.left&&t.lefte===`auto`||e===`scroll`)}function m(e,t,n,r){return(e/=r/2)<1?n/2*e*e+t:-n/2*(--e*(e-2)-1)+t}function h(e){let t=`a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled])`;return e.flatMap(e=>{let n=e.matches(t),r=Array.from(e.querySelectorAll(t));return[...n?[e]:[],...r]}).filter(e=>getComputedStyle(e).pointerEvents!==`none`&&y(e))}function g(e,t){if(!e||v(e))return;let n=e.offsetHeight>window.innerHeight;e.scrollIntoView({behavior:!t||_(e)?`auto`:`smooth`,inline:`center`,block:n?`start`:`center`})}function _(e){if(!e||!e.parentElement)return;let t=e.parentElement;return t.scrollHeight>t.clientHeight}function v(e){let t=e.getBoundingClientRect();return t.top>=0&&t.left>=0&&t.bottom<=(window.innerHeight||document.documentElement.clientHeight)&&t.right<=(window.innerWidth||document.documentElement.clientWidth)}function y(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)}function b(e){e&&(e.wrapper.style.display=`none`)}function x(e,t){let r=C();document.body.appendChild(r.wrapper);let{title:i,description:a,showButtons:o,disableButtons:c,showProgress:l,nextBtnText:u,prevBtnText:d,progressText:f}=t;r.nextButton.innerHTML=u,r.previousButton.innerHTML=d,r.progress.innerHTML=f,r.closeButton.setAttribute(`aria-label`,t.closeBtnLabel),t.doneButton&&r.nextButton.classList.add(`driver-popover-done-btn`),i?(r.title.innerHTML=i,r.title.style.display=`block`):r.title.style.display=`none`,a?(r.description.innerHTML=a,r.description.style.display=`block`):r.description.style.display=`none`;let p=o.includes(`next`)||o.includes(`previous`)||l;r.closeButton.style.display=o.includes(`close`)?`block`:`none`,p?(r.footer.style.display=`flex`,r.progress.style.display=l?`block`:`none`,r.nextButton.style.display=o.includes(`next`)?`block`:`none`,r.previousButton.style.display=o.includes(`previous`)?`block`:`none`):r.footer.style.display=`none`,c.includes(`next`)&&(r.nextButton.disabled=!0,r.nextButton.classList.add(`driver-popover-btn-disabled`)),c.includes(`previous`)&&(r.previousButton.disabled=!0,r.previousButton.classList.add(`driver-popover-btn-disabled`)),c.includes(`close`)&&(r.closeButton.disabled=!0,r.closeButton.classList.add(`driver-popover-btn-disabled`));let m=r.wrapper;m.style.display=`block`,m.style.left=``,m.style.top=``,m.style.bottom=``,m.style.right=``,m.id=`driver-popover-content`,m.setAttribute(`role`,`dialog`),m.setAttribute(`aria-labelledby`,`driver-popover-title`),m.setAttribute(`aria-describedby`,`driver-popover-description`);let _=r.arrow;_.className=`driver-popover-arrow`,m.className=`driver-popover ${t.popoverClass||``}`.trim(),n(r.wrapper,e=>{let n=e.target;if(n.closest(`.driver-popover-next-btn`))return t.onNextClick?.();if(n.closest(`.driver-popover-prev-btn`))return t.onPrevClick?.();if(n.closest(`.driver-popover-close-btn`))return t.onCloseClick?.()},e=>r.description.contains(e)||r.title.contains(e)?!1:!!e.closest(`.driver-popover-prev-btn, .driver-popover-next-btn, .driver-popover-close-btn`)),t.onRender?.(r),s(r,e,t.position),S(r,e,t.position),g(m,t.smoothScroll);let v=h([m,e]);return v.length>0&&v[0].focus(),r}function S(e,t,n){e.wrapper.querySelectorAll(`img`).forEach(r=>{if(r.complete)return;let i=()=>s(e,t,n);r.addEventListener(`load`,i,{once:!0}),r.addEventListener(`error`,i,{once:!0})})}function C(){let e=document.createElement(`div`);e.classList.add(`driver-popover`);let t=document.createElement(`div`);t.classList.add(`driver-popover-arrow`);let n=document.createElement(`header`);n.id=`driver-popover-title`,n.classList.add(`driver-popover-title`),n.style.display=`none`,n.innerText=`Popover Title`;let r=document.createElement(`div`);r.id=`driver-popover-description`,r.classList.add(`driver-popover-description`),r.style.display=`none`,r.innerText=`Popover description is here`;let i=document.createElement(`button`);i.type=`button`,i.classList.add(`driver-popover-close-btn`),i.innerHTML=`×`;let a=document.createElement(`footer`);a.classList.add(`driver-popover-footer`);let o=document.createElement(`span`);o.classList.add(`driver-popover-progress-text`),o.innerText=``;let s=document.createElement(`span`);s.classList.add(`driver-popover-navigation-btns`);let c=document.createElement(`button`);c.type=`button`,c.classList.add(`driver-popover-prev-btn`,`driver-popover-footer-btn`),c.innerHTML=`Previous`;let l=document.createElement(`button`);return l.type=`button`,l.classList.add(`driver-popover-next-btn`,`driver-popover-footer-btn`),l.innerHTML=`Next`,s.appendChild(c),s.appendChild(l),a.appendChild(o),a.appendChild(s),e.appendChild(i),e.appendChild(t),e.appendChild(n),e.appendChild(r),e.appendChild(a),{wrapper:e,arrow:t,title:n,description:r,footer:a,previousButton:c,nextButton:l,closeButton:i,footerButtons:s,progress:o}}function w(e){e&&(r(e.wrapper),e.wrapper.parentElement?.removeChild(e.wrapper))}function T(e,t){let n=window.innerWidth,r=window.innerHeight,i=t.padding,a=t.radius,o=e.width+i*2,s=e.height+i*2,c=Math.min(a,o/2,s/2),l=Math.floor(Math.max(c,0)),u=e.x-i+l,d=e.y-i,f=o-l*2,p=s-l*2;return`M${n},0L0,0L0,${r}L${n},${r}L${n},0Z + M${u},${d} h${f} a${l},${l} 0 0 1 ${l},${l} v${p} a${l},${l} 0 0 1 -${l},${l} h-${f} a${l},${l} 0 0 1 -${l},-${l} v-${p} a${l},${l} 0 0 1 ${l},-${l} z`}function E(e,t,n,r,i){let a=e.getState(`__activeStagePosition`),o=a||r.getBoundingClientRect(),s=i.getBoundingClientRect();a={x:m(t,o.x,s.x-o.x,n),y:m(t,o.y,s.y-o.y,n),width:m(t,o.width,s.width-o.width,n),height:m(t,o.height,s.height-o.height,n)},A(e,a),e.setState(`__activeStagePosition`,a)}function D(e,t){if(!t)return;let n=t.getBoundingClientRect(),r={x:n.x,y:n.y,width:n.width,height:n.height};e.setState(`__activeStagePosition`,r),A(e,r)}function O(e){let t=e.getState(`__activeStagePosition`),n=e.getState(`__overlaySvg`);if(!t)return;if(!n){console.warn(`No stage svg found.`);return}let r=window.innerWidth,i=window.innerHeight;n.setAttribute(`viewBox`,`0 0 ${r} ${i}`)}function k(e,t){let r=M(e,t);document.body.appendChild(r),n(r,t=>{t.target.tagName===`path`&&e.emit(`overlayClick`)}),e.setState(`__overlaySvg`,r)}function A(e,t){let n=e.getState(`__overlaySvg`);if(!n){k(e,t);return}let r=n.firstElementChild;if(r?.tagName!==`path`)throw Error(`no path element found in stage svg`);r.setAttribute(`d`,T(t,j(e)))}function j(e){return e.getState(`activeElement`)?.id===`driver-dummy-element`?{padding:0,radius:0}:{padding:e.getConfig(`stagePadding`)||0,radius:e.getConfig(`stageRadius`)||0}}function M(e,t){let n=window.innerWidth,r=window.innerHeight,i=document.createElementNS(`http://www.w3.org/2000/svg`,`svg`);i.classList.add(`driver-overlay`,`driver-overlay-animated`),i.setAttribute(`viewBox`,`0 0 ${n} ${r}`),i.setAttribute(`xmlSpace`,`preserve`),i.setAttribute(`xmlnsXlink`,`http://www.w3.org/1999/xlink`),i.setAttribute(`version`,`1.1`),i.setAttribute(`preserveAspectRatio`,`xMinYMin slice`),i.style.fillRule=`evenodd`,i.style.clipRule=`evenodd`,i.style.strokeLinejoin=`round`,i.style.strokeMiterlimit=`2`,i.style.zIndex=`10000`,i.style.position=`fixed`,i.style.top=`0`,i.style.left=`0`,i.style.width=`100%`,i.style.height=`100%`;let a=document.createElementNS(`http://www.w3.org/2000/svg`,`path`);return a.setAttribute(`d`,T(t,j(e))),a.style.fill=e.getConfig(`overlayColor`)||`rgb(0,0,0)`,a.style.opacity=`${e.getConfig(`overlayOpacity`)}`,a.style.pointerEvents=`auto`,a.style.cursor=`auto`,i.appendChild(a),i}function N(e){let t=e.getState(`__overlaySvg`);t&&(r(t),t.remove())}var P=`{{current}} of {{total}}`;function F(e,t){return!(t.skipMissingElement??e.getConfig(`skipMissingElement`))||!t.element?!1:!f(t.element)}function I(e,t,n){let r=e.getConfig(`steps`)||[];for(let i=t;i>=0&&i!f?.length||f.includes(e)),m=a.onNextClick||e.getConfig(`onNextClick`),h=a.onPrevClick||e.getConfig(`onPrevClick`),g=a.onCloseClick||e.getConfig(`onCloseClick`);return{...i,popover:{showButtons:p,nextBtnText:o?void 0:c,disableButtons:[...e.getConfig(`disableButtons`)||[],...s?[]:[`previous`]],showProgress:u,onNextClick:m||n.onNextClick,onPrevClick:h||n.onPrevClick,onCloseClick:g||n.onCloseClick,...a,progressText:d}}}function ie(e,t){return{showButtons:t?.popover?.showButtons||e.getConfig(`showButtons`)||[],disableButtons:t?.popover?.disableButtons||e.getConfig(`disableButtons`)||[]}}function ae(e,t,n){let r=e.getConfig(`stagePadding`)||0;return{side:n.popover?.side||`bottom`,align:n.popover?.align||`start`,offset:r+(e.getConfig(`popoverOffset`)||0),padding:r,centered:t.id===`driver-dummy-element`}}function oe(e,t,n){let r=n.popover||{},i=e.getState(`activeIndex`),a=i!==void 0&&I(e,i+1,1)===void 0;return{title:r.title,description:r.description,...ie(e,n),showProgress:r.showProgress||e.getConfig(`showProgress`)||!1,progressText:r.progressText??(e.getConfig(`progressText`)||P),nextBtnText:r.nextBtnText??(e.getConfig(`nextBtnText`)||`Next`),prevBtnText:r.prevBtnText??(e.getConfig(`prevBtnText`)||`Previous`),closeBtnLabel:r.closeBtnLabel??(e.getConfig(`closeBtnLabel`)||`Close`),doneButton:a,popoverClass:r.popoverClass||e.getConfig(`popoverClass`)||``,smoothScroll:e.getConfig(`smoothScroll`),onNextClick:()=>{let r=ee(e,n);return r?r(t,n,e.getHookOpts()):e.emit(`nextClick`)},onPrevClick:()=>{let r=te(e,n);return r?r(t,n,e.getHookOpts()):e.emit(`prevClick`)},onCloseClick:()=>{let r=ne(e,n);return r?r(t,n,e.getHookOpts()):e.emit(`closeClick`)},onRender:t=>{e.setState(`popover`,t),(r.onPopoverRender||e.getConfig(`onPopoverRender`))?.(t,e.getHookOpts())},position:ae(e,t,n)}}function se(e,t,n){w(e.getState(`popover`)),x(t,oe(e,t,n))}function ce(e,t,n){let r=e.getState(`popover`);r&&s(r,t,ae(e,t,n))}var le={"aria-haspopup":`dialog`,"aria-expanded":`true`,"aria-controls":`driver-popover-content`},ue=new WeakMap;function L(e){if(!ue.has(e)){let t=Object.fromEntries(Object.keys(le).map(t=>[t,e.getAttribute(t)]));ue.set(e,t)}for(let[t,n]of Object.entries(le))e.setAttribute(t,n)}function de(e){let t=ue.get(e);if(t){for(let[n,r]of Object.entries(t))r===null?e.removeAttribute(n):e.setAttribute(n,r);ue.delete(e)}}function fe(){let e=document.getElementById(`driver-dummy-element`);if(e)return e;let t=document.createElement(`div`);return t.id=`driver-dummy-element`,t.style.width=`0`,t.style.height=`0`,t.style.pointerEvents=`none`,t.style.opacity=`0`,t.style.position=`fixed`,t.style.top=`50%`,t.style.left=`50%`,document.body.appendChild(t),t}function pe(e,t){let n=f(t.element);n||=fe(),me(e,n,t)}function R(e){let t=e.getState(`__activeElement`),n=e.getState(`__activeStep`);t&&(D(e,t),O(e),ce(e,t,n))}function me(e,t,n){let r=e.getConfig(`duration`)||400,i=Date.now(),a=e.getState(`__activeStep`),o=e.getState(`__activeElement`)||t,s=!o||o===t,c=t.id===`driver-dummy-element`,l=o.id===`driver-dummy-element`,u=e.getConfig(`animate`),d=n.onHighlightStarted||e.getConfig(`onHighlightStarted`),f=n?.onHighlighted||e.getConfig(`onHighlighted`),m=a?.onDeselected||e.getConfig(`onDeselected`),h=e.getHookOpts();a&&a!==n&&m&&m(l?void 0:o,a,h),d&&d(c?void 0:t,n,h);let _=!s&&u,v=!1;b(e.getState(`popover`)),e.setState(`previousStep`,a),e.setState(`previousElement`,o),e.setState(`activeStep`,n),e.setState(`activeElement`,t);let y=()=>{if(e.getState(`__transitionCallback`)!==y)return;let s=Date.now()-i,l=r-s<=r/2;n.popover&&l&&!v&&_&&(se(e,t,n),v=!0),e.getConfig(`animate`)&&s{e.classList.remove(`driver-active-element-parent`,`driver-active-element-parent-no-scroll`)}),document.querySelectorAll(`.driver-active-element`).forEach(e=>{e.classList.remove(`driver-active-element`,`driver-no-interaction`),de(e)}),(n.disableActiveInteraction??e.getConfig(`disableActiveInteraction`))&&t.classList.add(`driver-no-interaction`);let x=t.parentElement;x&&x!==document.body&&(x.classList.add(`driver-active-element-parent`),p(x)&&x.classList.add(`driver-active-element-parent-no-scroll`)),t.classList.add(`driver-active-element`),L(t)}function z(){document.getElementById(`driver-dummy-element`)?.remove(),document.querySelectorAll(`.driver-active-element`).forEach(e=>{let t=e.parentElement;t&&t!==document.body&&t.classList.remove(`driver-active-element-parent`,`driver-active-element-parent-no-scroll`),e.classList.remove(`driver-active-element`,`driver-no-interaction`),de(e)})}function B(e){let t=e.getState(`__resizeTimeout`);t&&window.cancelAnimationFrame(t),e.setState(`__resizeTimeout`,window.requestAnimationFrame(()=>R(e)))}function he(e,t){if(!e.getState(`isInitialized`)||t.key!==`Tab`&&t.keyCode!==9)return;let n=e.getState(`__activeElement`),r=e.getState(`popover`)?.wrapper,i=h([...r?[r]:[],...n?[n]:[]]),a=i[0],o=i[i.length-1];t.preventDefault(),t.shiftKey?(i[i.indexOf(document.activeElement)-1]||o)?.focus():(i[i.indexOf(document.activeElement)+1]||a)?.focus()}function ge(e,t){(e.getConfig(`allowKeyboardControl`)??!0)&&(t.key===`Escape`?e.emit(`escapePress`):t.key===`ArrowRight`?e.emit(`arrowRightPress`):t.key===`ArrowLeft`&&e.emit(`arrowLeftPress`))}function _e(e,t){let n=e.getState(`__activeElement`),r=t.target;!n||!r||!n.contains(r)||e.emit(`activeElementClick`)}function ve(e){let t=t=>ge(e,t),n=t=>he(e,t),r=()=>B(e),i=()=>B(e),a=t=>_e(e,t);e.setState(`__events`,{onKeyup:t,onKeydown:n,onResize:r,onScroll:i,onClick:a}),window.addEventListener(`keyup`,t,!1),window.addEventListener(`keydown`,n,!1),window.addEventListener(`resize`,r),window.addEventListener(`scroll`,i),document.addEventListener(`click`,a,!1)}function ye(e){let t=e.getState(`__events`);t&&(window.removeEventListener(`keyup`,t.onKeyup),window.removeEventListener(`keydown`,t.onKeydown),window.removeEventListener(`resize`,t.onResize),window.removeEventListener(`scroll`,t.onScroll),document.removeEventListener(`click`,t.onClick,!1))}function be(){let e={};function t(t={}){e={animate:!0,duration:400,allowClose:!0,allowScroll:!0,overlayClickBehavior:`close`,overlayOpacity:.7,smoothScroll:!1,disableActiveInteraction:!1,advanceOnClick:!1,skipMissingElement:!1,waitForElement:0,showProgress:!1,stagePadding:10,stageRadius:5,popoverOffset:10,showButtons:[`next`,`previous`,`close`],disableButtons:[],overlayColor:`#000`,...t}}return t(),{getConfig:(t=>t?e[t]:e),configure:t}}function xe(){let e={},t=(t=>t?e[t]:e),n=(t,n)=>{e[t]=n};function r(){e={}}return{getState:t,setState:n,resetState:r}}function Se(){let e={};function t(t,n){e[t]=n}function n(t){e[t]?.()}function r(){e={}}return{listen:t,emit:n,reset:r}}function Ce(e={}){let t=be();t.configure(e);let n=xe(),r=Se(),i;return{getConfig:t.getConfig,setConfig:t.configure,getState:n.getState,setState:n.setState,resetState:n.resetState,listen:r.listen,emit:r.emit,resetEmitter:r.reset,getDriver:()=>i,setDriver:e=>{i=e},getHookOpts:e=>{let r=e||n.getState();return{config:t.getConfig(),state:r,driver:i,index:r.activeIndex}}}}var we;function Te(e={}){let t=Ce(e),n=()=>v(!1);function r(){t.getConfig(`allowClose`)&&v()}function i(){let{disableButtons:e}=ie(t,t.getState(`__activeStep`));e.includes(`close`)||r()}function a(e){let{showButtons:n,disableButtons:r}=ie(t,t.getState(`__activeStep`));return n.includes(e)&&!r.includes(e)}function o(){let e=t.getConfig(`overlayClickBehavior`);if(t.getConfig(`allowClose`)&&e===`close`){v();return}if(typeof e==`function`){let n=t.getState(`__activeStep`);e(t.getState(`__activeElement`),n,t.getHookOpts());return}if(e===`nextStep`){let e=t.getState(`activeStep`),n=t.getState(`activeElement`),r=ee(t,e);if(r){r(n,e,t.getHookOpts());return}s()}}function s(){let e=t.getState(`activeIndex`),n=t.getConfig(`steps`)||[];if(e===void 0)return;let r=e+1;n[r]?_(r):v()}function c(){let e=t.getState(`activeIndex`),n=t.getConfig(`steps`)||[];if(e===void 0)return;let r=e-1;n[r]?_(r):v()}function l(e){(t.getConfig(`steps`)||[])[e]?_(e):v()}function u(){if(t.getState(`__transitionCallback`))return;let e=t.getState(`__activeStep`);if(!e||!(e.advanceOnClick??t.getConfig(`advanceOnClick`)))return;let n=t.getState(`__activeElement`),r=ee(t,e);if(r){r(n,e,t.getHookOpts());return}s()}function d(){if(t.getState(`__transitionCallback`))return;let e=t.getState(`activeIndex`),n=t.getState(`__activeStep`),r=t.getState(`__activeElement`);if(e===void 0||n===void 0||!(t.getConfig(`steps`)||[])[e-1]||!a(`previous`))return;let i=te(t,n);if(i)return i(r,n,t.getHookOpts());c()}function p(){if(t.getState(`__transitionCallback`))return;let e=t.getState(`activeIndex`),n=t.getState(`__activeStep`),r=t.getState(`__activeElement`);if(e===void 0||n===void 0||!a(`next`))return;let i=ee(t,n);if(i)return i(r,n,t.getHookOpts());s()}function m(){t.getState(`isInitialized`)||(we&&we!==n&&we(),we=n,t.setState(`isInitialized`,!0),document.body.classList.add(`driver-active`,t.getConfig(`animate`)?`driver-fade`:`driver-simple`),t.getConfig(`allowScroll`)||document.body.classList.add(`driver-no-scroll`),document.body.style.setProperty(`--driver-animation-duration`,`${t.getConfig(`duration`)||400}ms`),ve(t),t.listen(`overlayClick`,o),t.listen(`activeElementClick`,u),t.listen(`escapePress`,i),t.listen(`closeClick`,r),t.listen(`arrowLeftPress`,d),t.listen(`arrowRightPress`,p))}function h(){let e=t.getState(`__pendingWaitCancel`);e&&(t.setState(`__pendingWaitCancel`,void 0),e())}function g(e,n,r){let i=()=>{a.disconnect(),window.clearTimeout(o),t.setState(`__pendingWaitCancel`,void 0),r()},a=new MutationObserver(()=>{f(e.element)&&i()}),o=window.setTimeout(i,n);t.setState(`__pendingWaitCancel`,()=>{a.disconnect(),window.clearTimeout(o)}),a.observe(document.documentElement,{childList:!0,subtree:!0,attributes:!0})}function _(e=0,n=!1){h();let r=t.getConfig(`steps`);if(!r){console.error(`No steps to drive through`),v();return}if(!r[e]){v();return}let i=r[e],a=i.waitForElement??t.getConfig(`waitForElement`)??0;if(!n&&a>0&&i.element&&!f(i.element)){b(t.getState(`popover`)),g(i,a,()=>_(e,!0));return}if(F(t,i)){let n=t.getState(`activeIndex`),i=typeof n==`number`&&e{o?_(e+1):v()},onPrevClick:()=>{_(e-1)},onCloseClick:()=>{v()}}))}function v(e=!0){if(!t.getState(`isInitialized`))return;let r=t.getState(`__activeElement`),i=t.getState(`__activeStep`),a=t.getState(`__activeOnDestroyed`),o=t.getConfig(`onDestroyStarted`);if(e&&o){o(!r||r?.id===`driver-dummy-element`?void 0:r,i,t.getHookOpts());return}we===n&&(we=void 0);let s=i?.onDeselected||t.getConfig(`onDeselected`),c=t.getConfig(`onDestroyed`);document.body.classList.remove(`driver-active`,`driver-fade`,`driver-simple`,`driver-no-scroll`),document.body.style.removeProperty(`--driver-animation-duration`),h(),ye(t),w(t.getState(`popover`)),z(),N(t),t.resetEmitter();let l=t.getState();if(t.resetState(),r&&i){let e=r.id===`driver-dummy-element`;s&&s(e?void 0:r,i,t.getHookOpts(l)),c&&c(e?void 0:r,i,t.getHookOpts(l))}a&&a.focus()}let y={isActive:()=>t.getState(`isInitialized`)||!1,refresh:()=>B(t),drive:(e=0)=>{m(),_(e)},setConfig:t.setConfig,setSteps:e=>{h(),t.resetState(),t.setConfig({...t.getConfig(),steps:e})},getConfig:t.getConfig,getState:t.getState,getActiveIndex:()=>t.getState(`activeIndex`),isFirstStep:()=>{let e=t.getState(`activeIndex`);return e!==void 0&&I(t,e-1,-1)===void 0},isLastStep:()=>{let e=t.getState(`activeIndex`);return e!==void 0&&I(t,e+1,1)===void 0},getActiveStep:()=>t.getState(`activeStep`),getActiveElement:()=>t.getState(`activeElement`),getPreviousElement:()=>t.getState(`previousElement`),getPreviousStep:()=>t.getState(`previousStep`),getNextStep:()=>{let e=t.getConfig(`steps`)||[],n=t.getState(`activeIndex`);if(n===void 0)return;let r=I(t,n+1,1);return r===void 0?void 0:e[r]},moveNext:s,movePrevious:c,moveTo:l,hasNextStep:()=>{let e=t.getState(`activeIndex`);return e!==void 0&&I(t,e+1,1)!==void 0},hasPreviousStep:()=>{let e=t.getState(`activeIndex`);return e!==void 0&&I(t,e-1,-1)!==void 0},highlight:e=>{m(),pe(t,{...e,popover:e.popover?{showButtons:[],showProgress:!1,progressText:``,...e.popover}:void 0})},destroy:()=>{v(!1)}};return t.setDriver(y),y}var Ee=`behind-glass.first-guide.v1`,De=`behind-glass.recenter-guide.v1`;function Oe(e,t,n,r,i,a=Te){let o=t=>e.querySelector(`#${t}`),s=o(`first-guide`),c=o(`experience`),l=e.defaultView,u=!1,d=!1,f=null,p=!1,m=!1,h=!1,g=`main`;try{u=l?.localStorage.getItem(Ee)===`1`,d=l?.localStorage.getItem(De)===`1`}catch{}let _=t=>{let n=e.querySelector(`#${t}`);if(!n||n.closest(`[hidden]`))return;let r=n.getBoundingClientRect(),i=l?.getComputedStyle?.(n);return r.width>0&&r.height>0&&i?.visibility!==`hidden`&&i?.display!==`none`?n:void 0},v=()=>{p&&(p=!1,f=null,c.inert=h,s.open&&s.close(),i())},y=(e=!1)=>{if(!p&&!f)return;if(m=!0,e){g===`main`?u=!0:d=!0;try{l?.localStorage.setItem(g===`main`?Ee:De,`1`)}catch{}}let t=f;f=null;try{t?.destroy()}finally{v(),m=!1,i()}},b=(n,o)=>{if(!(t.aborted||p||m||!r())){g=o,h=c.inert,p=!0,s.show(),c.inert=!0,i();try{f=a({steps:n,animate:!l?.matchMedia?.(`(prefers-reduced-motion: reduce)`).matches,overlayColor:`#201a13`,overlayOpacity:.62,stagePadding:9,stageRadius:9,popoverOffset:12,allowScroll:!1,smoothScroll:!1,disableActiveInteraction:!0,skipMissingElement:!0,overlayClickBehavior:`none`,allowClose:!0,showProgress:o===`main`,progressText:`{{current}} / {{total}}`,nextBtnText:`다음`,prevBtnText:`이전`,doneBtnText:o===`main`?`시작하기`:`알겠어요`,closeBtnLabel:`안내 건너뛰기`,popoverClass:`behind-glass-tour`,onNextClick:()=>{f?.isLastStep()?y(!0):f?.moveNext()},onDoneClick:()=>y(!0),onCloseClick:()=>y(!0),onDestroyStarted:()=>y(!0),onDestroyed:v,onPopoverRender:t=>{t.closeButton.textContent=`건너뛰기`;let n=e.createElement(`div`);n.className=`guide-popover-content`,n.append(t.closeButton,t.title,t.description,t.footer),t.wrapper.append(n)}}),f.drive()}catch{y(!1)}}};s.addEventListener(`close`,()=>{s.open||y(!1)},{signal:t}),s.addEventListener(`cancel`,e=>{e.preventDefault(),y(!0)},{signal:t});let x=()=>{if(!p)return;let e=f?.getActiveElement?.();if(e&&e.id&&!_(e.id)){y(!1);return}f?.refresh()};return l?.visualViewport?.addEventListener(`resize`,x,{signal:t}),l?.visualViewport?.addEventListener(`scroll`,x,{signal:t}),t.addEventListener(`abort`,()=>y(!1),{once:!0}),{start(e=!1){if(u&&!e||t.aborted)return;let r=[{element:()=>_(`guide-scene-target`),popover:{title:`유리 너머를 둘러보세요`,description:n?`손가락으로 드래그해서 시점을 바꾸고, 두 손가락으로 확대해 보세요.`:`드래그해서 시점을 바꾸고, 마우스 휠로 확대해 보세요.`,side:`bottom`,align:`center`}},{element:()=>_(`door-toggle`),popover:{title:`문도 열어볼까요?`,description:`이 버튼으로 문을 열고 닫을 수 있어요. 문 손잡이를 좌우로 밀어도 돼요.`,side:`top`,align:`start`}},...n?[{element:()=>_(`gyro`),popover:{title:`휴대폰을 기울여 보세요`,description:`안내를 마친 뒤 이 버튼을 눌러 연결해 주세요. 기울기를 쓰지 않아도 드래그로 둘러볼 수 있어요.`,side:`bottom`,align:`end`}}]:[]];b(r,`main`)},recenter(){n&&u&&!d&&_(`gyro-recenter`)&&b([{element:()=>_(`gyro-recenter`),popover:{title:`편한 자세로 중앙 맞추기`,description:`휴대폰을 편하게 든 뒤 이 버튼을 누르면 지금 자세가 새로운 기준이 돼요. 확대 정도는 그대로 유지돼요.`,side:`top`,align:`end`}}],`recenter`)}}}var ke=`attached`,Ae=1e3,je=1001,Me=1002,Ne=1003,Pe=1004,Fe=1005,Ie=1006,Le=1007,Re=1008,ze=1009,Be=1010,Ve=1011,He=1012,Ue=1013,We=1014,Ge=1015,Ke=1016,qe=1017,Je=1018,Ye=1020,Xe=35902,Ze=1021,Qe=1022,$e=1023,et=1024,tt=1025,nt=1026,rt=1027,it=1028,at=1029,ot=1030,st=1031,ct=1033,lt=33776,ut=33777,dt=33778,ft=33779,pt=35840,mt=35841,ht=35842,gt=35843,_t=36196,vt=37492,yt=37496,bt=37808,xt=37809,St=37810,Ct=37811,wt=37812,Tt=37813,Et=37814,Dt=37815,Ot=37816,kt=37817,At=37818,jt=37819,Mt=37820,Nt=37821,Pt=36492,Ft=36494,It=36495,Lt=36283,Rt=36284,zt=36285,Bt=36286,Vt=2300,Ht=2301,Ut=2302,Wt=2400,Gt=2401,Kt=2402,qt=2500,Jt=3200,Yt=3201,Xt=`srgb`,Zt=`srgb-linear`,Qt=`display-p3`,$t=`display-p3-linear`,en=`linear`,tn=`srgb`,nn=`rec709`,rn=7680,an=35044,on=2e3,sn=class{addEventListener(e,t){this._listeners===void 0&&(this._listeners={});let n=this._listeners;n[e]===void 0&&(n[e]=[]),n[e].indexOf(t)===-1&&n[e].push(t)}hasEventListener(e,t){if(this._listeners===void 0)return!1;let n=this._listeners;return n[e]!==void 0&&n[e].indexOf(t)!==-1}removeEventListener(e,t){if(this._listeners===void 0)return;let n=this._listeners[e];if(n!==void 0){let e=n.indexOf(t);e!==-1&&n.splice(e,1)}}dispatchEvent(e){if(this._listeners===void 0)return;let t=this._listeners[e.type];if(t!==void 0){e.target=this;let n=t.slice(0);for(let t=0,r=n.length;t>8&255]+cn[e>>16&255]+cn[e>>24&255]+`-`+cn[t&255]+cn[t>>8&255]+`-`+cn[t>>16&15|64]+cn[t>>24&255]+`-`+cn[n&63|128]+cn[n>>8&255]+`-`+cn[n>>16&255]+cn[n>>24&255]+cn[r&255]+cn[r>>8&255]+cn[r>>16&255]+cn[r>>24&255]).toLowerCase()}function pn(e,t,n){return Math.max(t,Math.min(n,e))}function mn(e,t){return(e%t+t)%t}function hn(e,t,n,r,i){return r+(e-t)*(i-r)/(n-t)}function gn(e,t,n){return e===t?0:(n-e)/(t-e)}function _n(e,t,n){return(1-n)*e+n*t}function vn(e,t,n,r){return _n(e,t,1-Math.exp(-n*r))}function yn(e,t=1){return t-Math.abs(mn(e,t*2)-t)}function bn(e,t,n){return e<=t?0:e>=n?1:(e=(e-t)/(n-t),e*e*(3-2*e))}function xn(e,t,n){return e<=t?0:e>=n?1:(e=(e-t)/(n-t),e*e*e*(e*(e*6-15)+10))}function Sn(e,t){return e+Math.floor(Math.random()*(t-e+1))}function Cn(e,t){return e+Math.random()*(t-e)}function wn(e){return e*(.5-Math.random())}function Tn(e){e!==void 0&&(ln=e);let t=ln+=1831565813;return t=Math.imul(t^t>>>15,t|1),t^=t+Math.imul(t^t>>>7,t|61),((t^t>>>14)>>>0)/4294967296}function En(e){return e*un}function Dn(e){return e*dn}function On(e){return!(e&e-1)&&e!==0}function kn(e){return 2**Math.ceil(Math.log(e)/Math.LN2)}function An(e){return 2**Math.floor(Math.log(e)/Math.LN2)}function jn(e,t,n,r,i){let a=Math.cos,o=Math.sin,s=a(n/2),c=o(n/2),l=a((t+r)/2),u=o((t+r)/2),d=a((t-r)/2),f=o((t-r)/2),p=a((r-t)/2),m=o((r-t)/2);switch(i){case`XYX`:e.set(s*u,c*d,c*f,s*l);break;case`YZY`:e.set(c*f,s*u,c*d,s*l);break;case`ZXZ`:e.set(c*d,c*f,s*u,s*l);break;case`XZX`:e.set(s*u,c*m,c*p,s*l);break;case`YXY`:e.set(c*p,s*u,c*m,s*l);break;case`ZYZ`:e.set(c*m,c*p,s*u,s*l);break;default:console.warn(`THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: `+i)}}function Mn(e,t){switch(t.constructor){case Float32Array:return e;case Uint32Array:return e/4294967295;case Uint16Array:return e/65535;case Uint8Array:return e/255;case Int32Array:return Math.max(e/2147483647,-1);case Int16Array:return Math.max(e/32767,-1);case Int8Array:return Math.max(e/127,-1);default:throw Error(`Invalid component type.`)}}function Nn(e,t){switch(t.constructor){case Float32Array:return e;case Uint32Array:return Math.round(e*4294967295);case Uint16Array:return Math.round(e*65535);case Uint8Array:return Math.round(e*255);case Int32Array:return Math.round(e*2147483647);case Int16Array:return Math.round(e*32767);case Int8Array:return Math.round(e*127);default:throw Error(`Invalid component type.`)}}var V={DEG2RAD:un,RAD2DEG:dn,generateUUID:fn,clamp:pn,euclideanModulo:mn,mapLinear:hn,inverseLerp:gn,lerp:_n,damp:vn,pingpong:yn,smoothstep:bn,smootherstep:xn,randInt:Sn,randFloat:Cn,randFloatSpread:wn,seededRandom:Tn,degToRad:En,radToDeg:Dn,isPowerOfTwo:On,ceilPowerOfTwo:kn,floorPowerOfTwo:An,setQuaternionFromProperEuler:jn,normalize:Nn,denormalize:Mn},H=class e{constructor(t=0,n=0){e.prototype.isVector2=!0,this.x=t,this.y=n}get width(){return this.x}set width(e){this.x=e}get height(){return this.y}set height(e){this.y=e}set(e,t){return this.x=e,this.y=t,this}setScalar(e){return this.x=e,this.y=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;default:throw Error(`index is out of range: `+e)}return this}getComponent(e){switch(e){case 0:return this.x;case 1:return this.y;default:throw Error(`index is out of range: `+e)}}clone(){return new this.constructor(this.x,this.y)}copy(e){return this.x=e.x,this.y=e.y,this}add(e){return this.x+=e.x,this.y+=e.y,this}addScalar(e){return this.x+=e,this.y+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this}subScalar(e){return this.x-=e,this.y-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this}multiply(e){return this.x*=e.x,this.y*=e.y,this}multiplyScalar(e){return this.x*=e,this.y*=e,this}divide(e){return this.x/=e.x,this.y/=e.y,this}divideScalar(e){return this.multiplyScalar(1/e)}applyMatrix3(e){let t=this.x,n=this.y,r=e.elements;return this.x=r[0]*t+r[3]*n+r[6],this.y=r[1]*t+r[4]*n+r[7],this}min(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this}max(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this}clamp(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this}clampScalar(e,t){return this.x=Math.max(e,Math.min(t,this.x)),this.y=Math.max(e,Math.min(t,this.y)),this}clampLength(e,t){let n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(e,Math.min(t,n)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this}negate(){return this.x=-this.x,this.y=-this.y,this}dot(e){return this.x*e.x+this.y*e.y}cross(e){return this.x*e.y-this.y*e.x}lengthSq(){return this.x*this.x+this.y*this.y}length(){return Math.sqrt(this.x*this.x+this.y*this.y)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)}normalize(){return this.divideScalar(this.length()||1)}angle(){return Math.atan2(-this.y,-this.x)+Math.PI}angleTo(e){let t=Math.sqrt(this.lengthSq()*e.lengthSq());if(t===0)return Math.PI/2;let n=this.dot(e)/t;return Math.acos(pn(n,-1,1))}distanceTo(e){return Math.sqrt(this.distanceToSquared(e))}distanceToSquared(e){let t=this.x-e.x,n=this.y-e.y;return t*t+n*n}manhattanDistanceTo(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)}setLength(e){return this.normalize().multiplyScalar(e)}lerp(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this}lerpVectors(e,t,n){return this.x=e.x+(t.x-e.x)*n,this.y=e.y+(t.y-e.y)*n,this}equals(e){return e.x===this.x&&e.y===this.y}fromArray(e,t=0){return this.x=e[t],this.y=e[t+1],this}toArray(e=[],t=0){return e[t]=this.x,e[t+1]=this.y,e}fromBufferAttribute(e,t){return this.x=e.getX(t),this.y=e.getY(t),this}rotateAround(e,t){let n=Math.cos(t),r=Math.sin(t),i=this.x-e.x,a=this.y-e.y;return this.x=i*n-a*r+e.x,this.y=i*r+a*n+e.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}},U=class e{constructor(t,n,r,i,a,o,s,c,l){e.prototype.isMatrix3=!0,this.elements=[1,0,0,0,1,0,0,0,1],t!==void 0&&this.set(t,n,r,i,a,o,s,c,l)}set(e,t,n,r,i,a,o,s,c){let l=this.elements;return l[0]=e,l[1]=r,l[2]=o,l[3]=t,l[4]=i,l[5]=s,l[6]=n,l[7]=a,l[8]=c,this}identity(){return this.set(1,0,0,0,1,0,0,0,1),this}copy(e){let t=this.elements,n=e.elements;return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],this}extractBasis(e,t,n){return e.setFromMatrix3Column(this,0),t.setFromMatrix3Column(this,1),n.setFromMatrix3Column(this,2),this}setFromMatrix4(e){let t=e.elements;return this.set(t[0],t[4],t[8],t[1],t[5],t[9],t[2],t[6],t[10]),this}multiply(e){return this.multiplyMatrices(this,e)}premultiply(e){return this.multiplyMatrices(e,this)}multiplyMatrices(e,t){let n=e.elements,r=t.elements,i=this.elements,a=n[0],o=n[3],s=n[6],c=n[1],l=n[4],u=n[7],d=n[2],f=n[5],p=n[8],m=r[0],h=r[3],g=r[6],_=r[1],v=r[4],y=r[7],b=r[2],x=r[5],S=r[8];return i[0]=a*m+o*_+s*b,i[3]=a*h+o*v+s*x,i[6]=a*g+o*y+s*S,i[1]=c*m+l*_+u*b,i[4]=c*h+l*v+u*x,i[7]=c*g+l*y+u*S,i[2]=d*m+f*_+p*b,i[5]=d*h+f*v+p*x,i[8]=d*g+f*y+p*S,this}multiplyScalar(e){let t=this.elements;return t[0]*=e,t[3]*=e,t[6]*=e,t[1]*=e,t[4]*=e,t[7]*=e,t[2]*=e,t[5]*=e,t[8]*=e,this}determinant(){let e=this.elements,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];return t*a*l-t*o*c-n*i*l+n*o*s+r*i*c-r*a*s}invert(){let e=this.elements,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=l*a-o*c,d=o*s-l*i,f=c*i-a*s,p=t*u+n*d+r*f;if(p===0)return this.set(0,0,0,0,0,0,0,0,0);let m=1/p;return e[0]=u*m,e[1]=(r*c-l*n)*m,e[2]=(o*n-r*a)*m,e[3]=d*m,e[4]=(l*t-r*s)*m,e[5]=(r*i-o*t)*m,e[6]=f*m,e[7]=(n*s-c*t)*m,e[8]=(a*t-n*i)*m,this}transpose(){let e,t=this.elements;return e=t[1],t[1]=t[3],t[3]=e,e=t[2],t[2]=t[6],t[6]=e,e=t[5],t[5]=t[7],t[7]=e,this}getNormalMatrix(e){return this.setFromMatrix4(e).invert().transpose()}transposeIntoArray(e){let t=this.elements;return e[0]=t[0],e[1]=t[3],e[2]=t[6],e[3]=t[1],e[4]=t[4],e[5]=t[7],e[6]=t[2],e[7]=t[5],e[8]=t[8],this}setUvTransform(e,t,n,r,i,a,o){let s=Math.cos(i),c=Math.sin(i);return this.set(n*s,n*c,-n*(s*a+c*o)+a+e,-r*c,r*s,-r*(-c*a+s*o)+o+t,0,0,1),this}scale(e,t){return this.premultiply(Pn.makeScale(e,t)),this}rotate(e){return this.premultiply(Pn.makeRotation(-e)),this}translate(e,t){return this.premultiply(Pn.makeTranslation(e,t)),this}makeTranslation(e,t){return e.isVector2?this.set(1,0,e.x,0,1,e.y,0,0,1):this.set(1,0,e,0,1,t,0,0,1),this}makeRotation(e){let t=Math.cos(e),n=Math.sin(e);return this.set(t,-n,0,n,t,0,0,0,1),this}makeScale(e,t){return this.set(e,0,0,0,t,0,0,0,1),this}equals(e){let t=this.elements,n=e.elements;for(let e=0;e<9;e++)if(t[e]!==n[e])return!1;return!0}fromArray(e,t=0){for(let n=0;n<9;n++)this.elements[n]=e[n+t];return this}toArray(e=[],t=0){let n=this.elements;return e[t]=n[0],e[t+1]=n[1],e[t+2]=n[2],e[t+3]=n[3],e[t+4]=n[4],e[t+5]=n[5],e[t+6]=n[6],e[t+7]=n[7],e[t+8]=n[8],e}clone(){return new this.constructor().fromArray(this.elements)}},Pn=new U;function Fn(e){for(let t=e.length-1;t>=0;--t)if(e[t]>=65535)return!0;return!1}function In(e){return document.createElementNS(`http://www.w3.org/1999/xhtml`,e)}function Ln(){let e=In(`canvas`);return e.style.display=`block`,e}var Rn={};function zn(e){e in Rn||(Rn[e]=!0,console.warn(e))}function Bn(e,t,n){return new Promise(function(r,i){function a(){switch(e.clientWaitSync(t,e.SYNC_FLUSH_COMMANDS_BIT,0)){case e.WAIT_FAILED:i();break;case e.TIMEOUT_EXPIRED:setTimeout(a,n);break;default:r()}}setTimeout(a,n)})}function Vn(e){let t=e.elements;t[2]=.5*t[2]+.5*t[3],t[6]=.5*t[6]+.5*t[7],t[10]=.5*t[10]+.5*t[11],t[14]=.5*t[14]+.5*t[15]}function Hn(e){let t=e.elements;t[11]===-1?(t[10]=-t[10]-1,t[14]=-t[14]):(t[10]=-t[10],t[14]=-t[14]+1)}var Un=new U().set(.8224621,.177538,0,.0331941,.9668058,0,.0170827,.0723974,.9105199),Wn=new U().set(1.2249401,-.2249404,0,-.0420569,1.0420571,0,-.0196376,-.0786361,1.0982735),Gn={[Zt]:{transfer:en,primaries:nn,luminanceCoefficients:[.2126,.7152,.0722],toReference:e=>e,fromReference:e=>e},[Xt]:{transfer:tn,primaries:nn,luminanceCoefficients:[.2126,.7152,.0722],toReference:e=>e.convertSRGBToLinear(),fromReference:e=>e.convertLinearToSRGB()},[$t]:{transfer:en,primaries:`p3`,luminanceCoefficients:[.2289,.6917,.0793],toReference:e=>e.applyMatrix3(Wn),fromReference:e=>e.applyMatrix3(Un)},[Qt]:{transfer:tn,primaries:`p3`,luminanceCoefficients:[.2289,.6917,.0793],toReference:e=>e.convertSRGBToLinear().applyMatrix3(Wn),fromReference:e=>e.applyMatrix3(Un).convertLinearToSRGB()}},Kn=new Set([Zt,$t]),qn={enabled:!0,_workingColorSpace:Zt,get workingColorSpace(){return this._workingColorSpace},set workingColorSpace(e){if(!Kn.has(e))throw Error(`Unsupported working color space, "${e}".`);this._workingColorSpace=e},convert:function(e,t,n){if(this.enabled===!1||t===n||!t||!n)return e;let r=Gn[t].toReference,i=Gn[n].fromReference;return i(r(e))},fromWorkingColorSpace:function(e,t){return this.convert(e,this._workingColorSpace,t)},toWorkingColorSpace:function(e,t){return this.convert(e,t,this._workingColorSpace)},getPrimaries:function(e){return Gn[e].primaries},getTransfer:function(e){return e===``?en:Gn[e].transfer},getLuminanceCoefficients:function(e,t=this._workingColorSpace){return e.fromArray(Gn[t].luminanceCoefficients)}};function Jn(e){return e<.04045?e*.0773993808:(e*.9478672986+.0521327014)**2.4}function Yn(e){return e<.0031308?e*12.92:1.055*e**.41666-.055}var Xn,Zn=class{static getDataURL(e){if(/^data:/i.test(e.src)||typeof HTMLCanvasElement>`u`)return e.src;let t;if(e instanceof HTMLCanvasElement)t=e;else{Xn===void 0&&(Xn=In(`canvas`)),Xn.width=e.width,Xn.height=e.height;let n=Xn.getContext(`2d`);e instanceof ImageData?n.putImageData(e,0,0):n.drawImage(e,0,0,e.width,e.height),t=Xn}return t.width>2048||t.height>2048?(console.warn(`THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons`,e),t.toDataURL(`image/jpeg`,.6)):t.toDataURL(`image/png`)}static sRGBToLinear(e){if(typeof HTMLImageElement<`u`&&e instanceof HTMLImageElement||typeof HTMLCanvasElement<`u`&&e instanceof HTMLCanvasElement||typeof ImageBitmap<`u`&&e instanceof ImageBitmap){let t=In(`canvas`);t.width=e.width,t.height=e.height;let n=t.getContext(`2d`);n.drawImage(e,0,0,e.width,e.height);let r=n.getImageData(0,0,e.width,e.height),i=r.data;for(let e=0;e0&&(n.userData=this.userData),t||(e.textures[this.uuid]=n),n}dispose(){this.dispatchEvent({type:`dispose`})}transformUv(e){if(this.mapping!==300)return e;if(e.applyMatrix3(this.matrix),e.x<0||e.x>1)switch(this.wrapS){case Ae:e.x-=Math.floor(e.x);break;case je:e.x=e.x<0?0:1;break;case Me:Math.abs(Math.floor(e.x)%2)===1?e.x=Math.ceil(e.x)-e.x:e.x-=Math.floor(e.x)}if(e.y<0||e.y>1)switch(this.wrapT){case Ae:e.y-=Math.floor(e.y);break;case je:e.y=e.y<0?0:1;break;case Me:Math.abs(Math.floor(e.y)%2)===1?e.y=Math.ceil(e.y)-e.y:e.y-=Math.floor(e.y)}return this.flipY&&(e.y=1-e.y),e}set needsUpdate(e){e===!0&&(this.version++,this.source.needsUpdate=!0)}set needsPMREMUpdate(e){e===!0&&this.pmremVersion++}};nr.DEFAULT_IMAGE=null,nr.DEFAULT_MAPPING=300,nr.DEFAULT_ANISOTROPY=1;var rr=class e{constructor(t=0,n=0,r=0,i=1){e.prototype.isVector4=!0,this.x=t,this.y=n,this.z=r,this.w=i}get width(){return this.z}set width(e){this.z=e}get height(){return this.w}set height(e){this.w=e}set(e,t,n,r){return this.x=e,this.y=t,this.z=n,this.w=r,this}setScalar(e){return this.x=e,this.y=e,this.z=e,this.w=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setZ(e){return this.z=e,this}setW(e){return this.w=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;case 3:this.w=t;break;default:throw Error(`index is out of range: `+e)}return this}getComponent(e){switch(e){case 0:return this.x;case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw Error(`index is out of range: `+e)}}clone(){return new this.constructor(this.x,this.y,this.z,this.w)}copy(e){return this.x=e.x,this.y=e.y,this.z=e.z,this.w=e.w===void 0?1:e.w,this}add(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this.w+=e.w,this}addScalar(e){return this.x+=e,this.y+=e,this.z+=e,this.w+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this.w=e.w+t.w,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this.w+=e.w*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this.z-=e.z,this.w-=e.w,this}subScalar(e){return this.x-=e,this.y-=e,this.z-=e,this.w-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this.w=e.w-t.w,this}multiply(e){return this.x*=e.x,this.y*=e.y,this.z*=e.z,this.w*=e.w,this}multiplyScalar(e){return this.x*=e,this.y*=e,this.z*=e,this.w*=e,this}applyMatrix4(e){let t=this.x,n=this.y,r=this.z,i=this.w,a=e.elements;return this.x=a[0]*t+a[4]*n+a[8]*r+a[12]*i,this.y=a[1]*t+a[5]*n+a[9]*r+a[13]*i,this.z=a[2]*t+a[6]*n+a[10]*r+a[14]*i,this.w=a[3]*t+a[7]*n+a[11]*r+a[15]*i,this}divideScalar(e){return this.multiplyScalar(1/e)}setAxisAngleFromQuaternion(e){this.w=2*Math.acos(e.w);let t=Math.sqrt(1-e.w*e.w);return t<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=e.x/t,this.y=e.y/t,this.z=e.z/t),this}setAxisAngleFromRotationMatrix(e){let t,n,r,i,a=.01,o=.1,s=e.elements,c=s[0],l=s[4],u=s[8],d=s[1],f=s[5],p=s[9],m=s[2],h=s[6],g=s[10];if(Math.abs(l-d)s&&e>_?e_?s=0?1:-1,r=1-t*t;if(r>2**-52){let i=Math.sqrt(r),a=Math.atan2(i,t*n);e=Math.sin(e*a)/i,o=Math.sin(o*a)/i}let i=o*n;if(s=s*e+d*i,c=c*e+f*i,l=l*e+p*i,u=u*e+m*i,e===1-o){let e=1/Math.sqrt(s*s+c*c+l*l+u*u);s*=e,c*=e,l*=e,u*=e}}e[t]=s,e[t+1]=c,e[t+2]=l,e[t+3]=u}static multiplyQuaternionsFlat(e,t,n,r,i,a){let o=n[r],s=n[r+1],c=n[r+2],l=n[r+3],u=i[a],d=i[a+1],f=i[a+2],p=i[a+3];return e[t]=o*p+l*u+s*f-c*d,e[t+1]=s*p+l*d+c*u-o*f,e[t+2]=c*p+l*f+o*d-s*u,e[t+3]=l*p-o*u-s*d-c*f,e}get x(){return this._x}set x(e){this._x=e,this._onChangeCallback()}get y(){return this._y}set y(e){this._y=e,this._onChangeCallback()}get z(){return this._z}set z(e){this._z=e,this._onChangeCallback()}get w(){return this._w}set w(e){this._w=e,this._onChangeCallback()}set(e,t,n,r){return this._x=e,this._y=t,this._z=n,this._w=r,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._w)}copy(e){return this._x=e.x,this._y=e.y,this._z=e.z,this._w=e.w,this._onChangeCallback(),this}setFromEuler(e,t=!0){let n=e._x,r=e._y,i=e._z,a=e._order,o=Math.cos,s=Math.sin,c=o(n/2),l=o(r/2),u=o(i/2),d=s(n/2),f=s(r/2),p=s(i/2);switch(a){case`XYZ`:this._x=d*l*u+c*f*p,this._y=c*f*u-d*l*p,this._z=c*l*p+d*f*u,this._w=c*l*u-d*f*p;break;case`YXZ`:this._x=d*l*u+c*f*p,this._y=c*f*u-d*l*p,this._z=c*l*p-d*f*u,this._w=c*l*u+d*f*p;break;case`ZXY`:this._x=d*l*u-c*f*p,this._y=c*f*u+d*l*p,this._z=c*l*p+d*f*u,this._w=c*l*u-d*f*p;break;case`ZYX`:this._x=d*l*u-c*f*p,this._y=c*f*u+d*l*p,this._z=c*l*p-d*f*u,this._w=c*l*u+d*f*p;break;case`YZX`:this._x=d*l*u+c*f*p,this._y=c*f*u+d*l*p,this._z=c*l*p-d*f*u,this._w=c*l*u-d*f*p;break;case`XZY`:this._x=d*l*u-c*f*p,this._y=c*f*u-d*l*p,this._z=c*l*p+d*f*u,this._w=c*l*u+d*f*p;break;default:console.warn(`THREE.Quaternion: .setFromEuler() encountered an unknown order: `+a)}return t===!0&&this._onChangeCallback(),this}setFromAxisAngle(e,t){let n=t/2,r=Math.sin(n);return this._x=e.x*r,this._y=e.y*r,this._z=e.z*r,this._w=Math.cos(n),this._onChangeCallback(),this}setFromRotationMatrix(e){let t=e.elements,n=t[0],r=t[4],i=t[8],a=t[1],o=t[5],s=t[9],c=t[2],l=t[6],u=t[10],d=n+o+u;if(d>0){let e=.5/Math.sqrt(d+1);this._w=.25/e,this._x=(l-s)*e,this._y=(i-c)*e,this._z=(a-r)*e}else if(n>o&&n>u){let e=2*Math.sqrt(1+n-o-u);this._w=(l-s)/e,this._x=.25*e,this._y=(r+a)/e,this._z=(i+c)/e}else if(o>u){let e=2*Math.sqrt(1+o-n-u);this._w=(i-c)/e,this._x=(r+a)/e,this._y=.25*e,this._z=(s+l)/e}else{let e=2*Math.sqrt(1+u-n-o);this._w=(a-r)/e,this._x=(i+c)/e,this._y=(s+l)/e,this._z=.25*e}return this._onChangeCallback(),this}setFromUnitVectors(e,t){let n=e.dot(t)+1;return n<2**-52?(n=0,Math.abs(e.x)>Math.abs(e.z)?(this._x=-e.y,this._y=e.x,this._z=0,this._w=n):(this._x=0,this._y=-e.z,this._z=e.y,this._w=n)):(this._x=e.y*t.z-e.z*t.y,this._y=e.z*t.x-e.x*t.z,this._z=e.x*t.y-e.y*t.x,this._w=n),this.normalize()}angleTo(e){return 2*Math.acos(Math.abs(pn(this.dot(e),-1,1)))}rotateTowards(e,t){let n=this.angleTo(e);if(n===0)return this;let r=Math.min(1,t/n);return this.slerp(e,r),this}identity(){return this.set(0,0,0,1)}invert(){return this.conjugate()}conjugate(){return this._x*=-1,this._y*=-1,this._z*=-1,this._onChangeCallback(),this}dot(e){return this._x*e._x+this._y*e._y+this._z*e._z+this._w*e._w}lengthSq(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w}length(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)}normalize(){let e=this.length();return e===0?(this._x=0,this._y=0,this._z=0,this._w=1):(e=1/e,this._x*=e,this._y*=e,this._z*=e,this._w*=e),this._onChangeCallback(),this}multiply(e){return this.multiplyQuaternions(this,e)}premultiply(e){return this.multiplyQuaternions(e,this)}multiplyQuaternions(e,t){let n=e._x,r=e._y,i=e._z,a=e._w,o=t._x,s=t._y,c=t._z,l=t._w;return this._x=n*l+a*o+r*c-i*s,this._y=r*l+a*s+i*o-n*c,this._z=i*l+a*c+n*s-r*o,this._w=a*l-n*o-r*s-i*c,this._onChangeCallback(),this}slerp(e,t){if(t===0)return this;if(t===1)return this.copy(e);let n=this._x,r=this._y,i=this._z,a=this._w,o=a*e._w+n*e._x+r*e._y+i*e._z;if(o<0?(this._w=-e._w,this._x=-e._x,this._y=-e._y,this._z=-e._z,o=-o):this.copy(e),o>=1)return this._w=a,this._x=n,this._y=r,this._z=i,this;let s=1-o*o;if(s<=2**-52){let e=1-t;return this._w=e*a+t*this._w,this._x=e*n+t*this._x,this._y=e*r+t*this._y,this._z=e*i+t*this._z,this.normalize(),this}let c=Math.sqrt(s),l=Math.atan2(c,o),u=Math.sin((1-t)*l)/c,d=Math.sin(t*l)/c;return this._w=a*u+this._w*d,this._x=n*u+this._x*d,this._y=r*u+this._y*d,this._z=i*u+this._z*d,this._onChangeCallback(),this}slerpQuaternions(e,t,n){return this.copy(e).slerp(t,n)}random(){let e=2*Math.PI*Math.random(),t=2*Math.PI*Math.random(),n=Math.random(),r=Math.sqrt(1-n),i=Math.sqrt(n);return this.set(r*Math.sin(e),r*Math.cos(e),i*Math.sin(t),i*Math.cos(t))}equals(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._w===this._w}fromArray(e,t=0){return this._x=e[t],this._y=e[t+1],this._z=e[t+2],this._w=e[t+3],this._onChangeCallback(),this}toArray(e=[],t=0){return e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._w,e}fromBufferAttribute(e,t){return this._x=e.getX(t),this._y=e.getY(t),this._z=e.getZ(t),this._w=e.getW(t),this._onChangeCallback(),this}toJSON(){return this.toArray()}_onChange(e){return this._onChangeCallback=e,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._w}},W=class e{constructor(t=0,n=0,r=0){e.prototype.isVector3=!0,this.x=t,this.y=n,this.z=r}set(e,t,n){return n===void 0&&(n=this.z),this.x=e,this.y=t,this.z=n,this}setScalar(e){return this.x=e,this.y=e,this.z=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setZ(e){return this.z=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;default:throw Error(`index is out of range: `+e)}return this}getComponent(e){switch(e){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw Error(`index is out of range: `+e)}}clone(){return new this.constructor(this.x,this.y,this.z)}copy(e){return this.x=e.x,this.y=e.y,this.z=e.z,this}add(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this}addScalar(e){return this.x+=e,this.y+=e,this.z+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this.z-=e.z,this}subScalar(e){return this.x-=e,this.y-=e,this.z-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this}multiply(e){return this.x*=e.x,this.y*=e.y,this.z*=e.z,this}multiplyScalar(e){return this.x*=e,this.y*=e,this.z*=e,this}multiplyVectors(e,t){return this.x=e.x*t.x,this.y=e.y*t.y,this.z=e.z*t.z,this}applyEuler(e){return this.applyQuaternion(ur.setFromEuler(e))}applyAxisAngle(e,t){return this.applyQuaternion(ur.setFromAxisAngle(e,t))}applyMatrix3(e){let t=this.x,n=this.y,r=this.z,i=e.elements;return this.x=i[0]*t+i[3]*n+i[6]*r,this.y=i[1]*t+i[4]*n+i[7]*r,this.z=i[2]*t+i[5]*n+i[8]*r,this}applyNormalMatrix(e){return this.applyMatrix3(e).normalize()}applyMatrix4(e){let t=this.x,n=this.y,r=this.z,i=e.elements,a=1/(i[3]*t+i[7]*n+i[11]*r+i[15]);return this.x=(i[0]*t+i[4]*n+i[8]*r+i[12])*a,this.y=(i[1]*t+i[5]*n+i[9]*r+i[13])*a,this.z=(i[2]*t+i[6]*n+i[10]*r+i[14])*a,this}applyQuaternion(e){let t=this.x,n=this.y,r=this.z,i=e.x,a=e.y,o=e.z,s=e.w,c=2*(a*r-o*n),l=2*(o*t-i*r),u=2*(i*n-a*t);return this.x=t+s*c+a*u-o*l,this.y=n+s*l+o*c-i*u,this.z=r+s*u+i*l-a*c,this}project(e){return this.applyMatrix4(e.matrixWorldInverse).applyMatrix4(e.projectionMatrix)}unproject(e){return this.applyMatrix4(e.projectionMatrixInverse).applyMatrix4(e.matrixWorld)}transformDirection(e){let t=this.x,n=this.y,r=this.z,i=e.elements;return this.x=i[0]*t+i[4]*n+i[8]*r,this.y=i[1]*t+i[5]*n+i[9]*r,this.z=i[2]*t+i[6]*n+i[10]*r,this.normalize()}divide(e){return this.x/=e.x,this.y/=e.y,this.z/=e.z,this}divideScalar(e){return this.multiplyScalar(1/e)}min(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this.z=Math.min(this.z,e.z),this}max(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this.z=Math.max(this.z,e.z),this}clamp(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this.z=Math.max(e.z,Math.min(t.z,this.z)),this}clampScalar(e,t){return this.x=Math.max(e,Math.min(t,this.x)),this.y=Math.max(e,Math.min(t,this.y)),this.z=Math.max(e,Math.min(t,this.z)),this}clampLength(e,t){let n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(e,Math.min(t,n)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this.z=Math.trunc(this.z),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this}dot(e){return this.x*e.x+this.y*e.y+this.z*e.z}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)}normalize(){return this.divideScalar(this.length()||1)}setLength(e){return this.normalize().multiplyScalar(e)}lerp(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this.z+=(e.z-this.z)*t,this}lerpVectors(e,t,n){return this.x=e.x+(t.x-e.x)*n,this.y=e.y+(t.y-e.y)*n,this.z=e.z+(t.z-e.z)*n,this}cross(e){return this.crossVectors(this,e)}crossVectors(e,t){let n=e.x,r=e.y,i=e.z,a=t.x,o=t.y,s=t.z;return this.x=r*s-i*o,this.y=i*a-n*s,this.z=n*o-r*a,this}projectOnVector(e){let t=e.lengthSq();if(t===0)return this.set(0,0,0);let n=e.dot(this)/t;return this.copy(e).multiplyScalar(n)}projectOnPlane(e){return lr.copy(this).projectOnVector(e),this.sub(lr)}reflect(e){return this.sub(lr.copy(e).multiplyScalar(2*this.dot(e)))}angleTo(e){let t=Math.sqrt(this.lengthSq()*e.lengthSq());if(t===0)return Math.PI/2;let n=this.dot(e)/t;return Math.acos(pn(n,-1,1))}distanceTo(e){return Math.sqrt(this.distanceToSquared(e))}distanceToSquared(e){let t=this.x-e.x,n=this.y-e.y,r=this.z-e.z;return t*t+n*n+r*r}manhattanDistanceTo(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)+Math.abs(this.z-e.z)}setFromSpherical(e){return this.setFromSphericalCoords(e.radius,e.phi,e.theta)}setFromSphericalCoords(e,t,n){let r=Math.sin(t)*e;return this.x=r*Math.sin(n),this.y=Math.cos(t)*e,this.z=r*Math.cos(n),this}setFromCylindrical(e){return this.setFromCylindricalCoords(e.radius,e.theta,e.y)}setFromCylindricalCoords(e,t,n){return this.x=e*Math.sin(t),this.y=n,this.z=e*Math.cos(t),this}setFromMatrixPosition(e){let t=e.elements;return this.x=t[12],this.y=t[13],this.z=t[14],this}setFromMatrixScale(e){let t=this.setFromMatrixColumn(e,0).length(),n=this.setFromMatrixColumn(e,1).length(),r=this.setFromMatrixColumn(e,2).length();return this.x=t,this.y=n,this.z=r,this}setFromMatrixColumn(e,t){return this.fromArray(e.elements,t*4)}setFromMatrix3Column(e,t){return this.fromArray(e.elements,t*3)}setFromEuler(e){return this.x=e._x,this.y=e._y,this.z=e._z,this}setFromColor(e){return this.x=e.r,this.y=e.g,this.z=e.b,this}equals(e){return e.x===this.x&&e.y===this.y&&e.z===this.z}fromArray(e,t=0){return this.x=e[t],this.y=e[t+1],this.z=e[t+2],this}toArray(e=[],t=0){return e[t]=this.x,e[t+1]=this.y,e[t+2]=this.z,e}fromBufferAttribute(e,t){return this.x=e.getX(t),this.y=e.getY(t),this.z=e.getZ(t),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}randomDirection(){let e=Math.random()*Math.PI*2,t=Math.random()*2-1,n=Math.sqrt(1-t*t);return this.x=n*Math.cos(e),this.y=t,this.z=n*Math.sin(e),this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}},lr=new W,ur=new cr,dr=class{constructor(e=new W(1/0,1/0,1/0),t=new W(-1/0,-1/0,-1/0)){this.isBox3=!0,this.min=e,this.max=t}set(e,t){return this.min.copy(e),this.max.copy(t),this}setFromArray(e){this.makeEmpty();for(let t=0,n=e.length;t=this.min.x&&e.x<=this.max.x&&e.y>=this.min.y&&e.y<=this.max.y&&e.z>=this.min.z&&e.z<=this.max.z}containsBox(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y&&this.min.z<=e.min.z&&e.max.z<=this.max.z}getParameter(e,t){return t.set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y),(e.z-this.min.z)/(this.max.z-this.min.z))}intersectsBox(e){return e.max.x>=this.min.x&&e.min.x<=this.max.x&&e.max.y>=this.min.y&&e.min.y<=this.max.y&&e.max.z>=this.min.z&&e.min.z<=this.max.z}intersectsSphere(e){return this.clampPoint(e.center,pr),pr.distanceToSquared(e.center)<=e.radius*e.radius}intersectsPlane(e){let t,n;return e.normal.x>0?(t=e.normal.x*this.min.x,n=e.normal.x*this.max.x):(t=e.normal.x*this.max.x,n=e.normal.x*this.min.x),e.normal.y>0?(t+=e.normal.y*this.min.y,n+=e.normal.y*this.max.y):(t+=e.normal.y*this.max.y,n+=e.normal.y*this.min.y),e.normal.z>0?(t+=e.normal.z*this.min.z,n+=e.normal.z*this.max.z):(t+=e.normal.z*this.max.z,n+=e.normal.z*this.min.z),t<=-e.constant&&n>=-e.constant}intersectsTriangle(e){if(this.isEmpty())return!1;this.getCenter(xr),Sr.subVectors(this.max,xr),hr.subVectors(e.a,xr),gr.subVectors(e.b,xr),_r.subVectors(e.c,xr),vr.subVectors(gr,hr),yr.subVectors(_r,gr),br.subVectors(hr,_r);let t=[0,-vr.z,vr.y,0,-yr.z,yr.y,0,-br.z,br.y,vr.z,0,-vr.x,yr.z,0,-yr.x,br.z,0,-br.x,-vr.y,vr.x,0,-yr.y,yr.x,0,-br.y,br.x,0];return!Tr(t,hr,gr,_r,Sr)||(t=[1,0,0,0,1,0,0,0,1],!Tr(t,hr,gr,_r,Sr))?!1:(Cr.crossVectors(vr,yr),t=[Cr.x,Cr.y,Cr.z],Tr(t,hr,gr,_r,Sr))}clampPoint(e,t){return t.copy(e).clamp(this.min,this.max)}distanceToPoint(e){return this.clampPoint(e,pr).distanceTo(e)}getBoundingSphere(e){return this.isEmpty()?e.makeEmpty():(this.getCenter(e.center),e.radius=this.getSize(pr).length()*.5),e}intersect(e){return this.min.max(e.min),this.max.min(e.max),this.isEmpty()&&this.makeEmpty(),this}union(e){return this.min.min(e.min),this.max.max(e.max),this}applyMatrix4(e){return this.isEmpty()?this:(fr[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(e),fr[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(e),fr[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(e),fr[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(e),fr[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(e),fr[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(e),fr[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(e),fr[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(e),this.setFromPoints(fr),this)}translate(e){return this.min.add(e),this.max.add(e),this}equals(e){return e.min.equals(this.min)&&e.max.equals(this.max)}},fr=[new W,new W,new W,new W,new W,new W,new W,new W],pr=new W,mr=new dr,hr=new W,gr=new W,_r=new W,vr=new W,yr=new W,br=new W,xr=new W,Sr=new W,Cr=new W,wr=new W;function Tr(e,t,n,r,i){for(let a=0,o=e.length-3;a<=o;a+=3){wr.fromArray(e,a);let o=i.x*Math.abs(wr.x)+i.y*Math.abs(wr.y)+i.z*Math.abs(wr.z),s=t.dot(wr),c=n.dot(wr),l=r.dot(wr);if(Math.max(-Math.max(s,c,l),Math.min(s,c,l))>o)return!1}return!0}var Er=new dr,Dr=new W,Or=new W,kr=class{constructor(e=new W,t=-1){this.isSphere=!0,this.center=e,this.radius=t}set(e,t){return this.center.copy(e),this.radius=t,this}setFromPoints(e,t){let n=this.center;t===void 0?Er.setFromPoints(e).getCenter(n):n.copy(t);let r=0;for(let t=0,i=e.length;tthis.radius*this.radius&&(t.sub(this.center).normalize(),t.multiplyScalar(this.radius).add(this.center)),t}getBoundingBox(e){return this.isEmpty()?(e.makeEmpty(),e):(e.set(this.center,this.center),e.expandByScalar(this.radius),e)}applyMatrix4(e){return this.center.applyMatrix4(e),this.radius*=e.getMaxScaleOnAxis(),this}translate(e){return this.center.add(e),this}expandByPoint(e){if(this.isEmpty())return this.center.copy(e),this.radius=0,this;Dr.subVectors(e,this.center);let t=Dr.lengthSq();if(t>this.radius*this.radius){let e=Math.sqrt(t),n=(e-this.radius)*.5;this.center.addScaledVector(Dr,n/e),this.radius+=n}return this}union(e){return e.isEmpty()?this:this.isEmpty()?(this.copy(e),this):(this.center.equals(e.center)===!0?this.radius=Math.max(this.radius,e.radius):(Or.subVectors(e.center,this.center).setLength(e.radius),this.expandByPoint(Dr.copy(e.center).add(Or)),this.expandByPoint(Dr.copy(e.center).sub(Or))),this)}equals(e){return e.center.equals(this.center)&&e.radius===this.radius}clone(){return new this.constructor().copy(this)}},Ar=new W,jr=new W,Mr=new W,Nr=new W,Pr=new W,Fr=new W,Ir=new W,Lr=class{constructor(e=new W,t=new W(0,0,-1)){this.origin=e,this.direction=t}set(e,t){return this.origin.copy(e),this.direction.copy(t),this}copy(e){return this.origin.copy(e.origin),this.direction.copy(e.direction),this}at(e,t){return t.copy(this.origin).addScaledVector(this.direction,e)}lookAt(e){return this.direction.copy(e).sub(this.origin).normalize(),this}recast(e){return this.origin.copy(this.at(e,Ar)),this}closestPointToPoint(e,t){t.subVectors(e,this.origin);let n=t.dot(this.direction);return n<0?t.copy(this.origin):t.copy(this.origin).addScaledVector(this.direction,n)}distanceToPoint(e){return Math.sqrt(this.distanceSqToPoint(e))}distanceSqToPoint(e){let t=Ar.subVectors(e,this.origin).dot(this.direction);return t<0?this.origin.distanceToSquared(e):(Ar.copy(this.origin).addScaledVector(this.direction,t),Ar.distanceToSquared(e))}distanceSqToSegment(e,t,n,r){jr.copy(e).add(t).multiplyScalar(.5),Mr.copy(t).sub(e).normalize(),Nr.copy(this.origin).sub(jr);let i=e.distanceTo(t)*.5,a=-this.direction.dot(Mr),o=Nr.dot(this.direction),s=-Nr.dot(Mr),c=Nr.lengthSq(),l=Math.abs(1-a*a),u,d,f,p;if(l>0){if(u=a*s-o,d=a*o-s,p=i*l,u>=0){if(d>=-p){if(d<=p){let e=1/l;u*=e,d*=e,f=u*(u+a*d+2*o)+d*(a*u+d+2*s)+c}else d=i,u=Math.max(0,-(a*d+o)),f=-u*u+d*(d+2*s)+c}else d=-i,u=Math.max(0,-(a*d+o)),f=-u*u+d*(d+2*s)+c}else d<=-p?(u=Math.max(0,-(-a*i+o)),d=u>0?-i:Math.min(Math.max(-i,-s),i),f=-u*u+d*(d+2*s)+c):d<=p?(u=0,d=Math.min(Math.max(-i,-s),i),f=d*(d+2*s)+c):(u=Math.max(0,-(a*i+o)),d=u>0?i:Math.min(Math.max(-i,-s),i),f=-u*u+d*(d+2*s)+c)}else d=a>0?-i:i,u=Math.max(0,-(a*d+o)),f=-u*u+d*(d+2*s)+c;return n&&n.copy(this.origin).addScaledVector(this.direction,u),r&&r.copy(jr).addScaledVector(Mr,d),f}intersectSphere(e,t){Ar.subVectors(e.center,this.origin);let n=Ar.dot(this.direction),r=Ar.dot(Ar)-n*n,i=e.radius*e.radius;if(r>i)return null;let a=Math.sqrt(i-r),o=n-a,s=n+a;return s<0?null:o<0?this.at(s,t):this.at(o,t)}intersectsSphere(e){return this.distanceSqToPoint(e.center)<=e.radius*e.radius}distanceToPlane(e){let t=e.normal.dot(this.direction);if(t===0)return e.distanceToPoint(this.origin)===0?0:null;let n=-(this.origin.dot(e.normal)+e.constant)/t;return n>=0?n:null}intersectPlane(e,t){let n=this.distanceToPlane(e);return n===null?null:this.at(n,t)}intersectsPlane(e){let t=e.distanceToPoint(this.origin);return t===0||e.normal.dot(this.direction)*t<0}intersectBox(e,t){let n,r,i,a,o,s,c=1/this.direction.x,l=1/this.direction.y,u=1/this.direction.z,d=this.origin;return c>=0?(n=(e.min.x-d.x)*c,r=(e.max.x-d.x)*c):(n=(e.max.x-d.x)*c,r=(e.min.x-d.x)*c),l>=0?(i=(e.min.y-d.y)*l,a=(e.max.y-d.y)*l):(i=(e.max.y-d.y)*l,a=(e.min.y-d.y)*l),n>a||i>r||((i>n||isNaN(n))&&(n=i),(a=0?(o=(e.min.z-d.z)*u,s=(e.max.z-d.z)*u):(o=(e.max.z-d.z)*u,s=(e.min.z-d.z)*u),n>s||o>r)||((o>n||n!==n)&&(n=o),(s=0?n:r,t)}intersectsBox(e){return this.intersectBox(e,Ar)!==null}intersectTriangle(e,t,n,r,i){Pr.subVectors(t,e),Fr.subVectors(n,e),Ir.crossVectors(Pr,Fr);let a=this.direction.dot(Ir),o;if(a>0){if(r)return null;o=1}else if(a<0)o=-1,a=-a;else return null;Nr.subVectors(this.origin,e);let s=o*this.direction.dot(Fr.crossVectors(Nr,Fr));if(s<0)return null;let c=o*this.direction.dot(Pr.cross(Nr));if(c<0||s+c>a)return null;let l=-o*Nr.dot(Ir);return l<0?null:this.at(l/a,i)}applyMatrix4(e){return this.origin.applyMatrix4(e),this.direction.transformDirection(e),this}equals(e){return e.origin.equals(this.origin)&&e.direction.equals(this.direction)}clone(){return new this.constructor().copy(this)}},G=class e{constructor(t,n,r,i,a,o,s,c,l,u,d,f,p,m,h,g){e.prototype.isMatrix4=!0,this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],t!==void 0&&this.set(t,n,r,i,a,o,s,c,l,u,d,f,p,m,h,g)}set(e,t,n,r,i,a,o,s,c,l,u,d,f,p,m,h){let g=this.elements;return g[0]=e,g[4]=t,g[8]=n,g[12]=r,g[1]=i,g[5]=a,g[9]=o,g[13]=s,g[2]=c,g[6]=l,g[10]=u,g[14]=d,g[3]=f,g[7]=p,g[11]=m,g[15]=h,this}identity(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this}clone(){return new e().fromArray(this.elements)}copy(e){let t=this.elements,n=e.elements;return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t[9]=n[9],t[10]=n[10],t[11]=n[11],t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15],this}copyPosition(e){let t=this.elements,n=e.elements;return t[12]=n[12],t[13]=n[13],t[14]=n[14],this}setFromMatrix3(e){let t=e.elements;return this.set(t[0],t[3],t[6],0,t[1],t[4],t[7],0,t[2],t[5],t[8],0,0,0,0,1),this}extractBasis(e,t,n){return e.setFromMatrixColumn(this,0),t.setFromMatrixColumn(this,1),n.setFromMatrixColumn(this,2),this}makeBasis(e,t,n){return this.set(e.x,t.x,n.x,0,e.y,t.y,n.y,0,e.z,t.z,n.z,0,0,0,0,1),this}extractRotation(e){let t=this.elements,n=e.elements,r=1/Rr.setFromMatrixColumn(e,0).length(),i=1/Rr.setFromMatrixColumn(e,1).length(),a=1/Rr.setFromMatrixColumn(e,2).length();return t[0]=n[0]*r,t[1]=n[1]*r,t[2]=n[2]*r,t[3]=0,t[4]=n[4]*i,t[5]=n[5]*i,t[6]=n[6]*i,t[7]=0,t[8]=n[8]*a,t[9]=n[9]*a,t[10]=n[10]*a,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this}makeRotationFromEuler(e){let t=this.elements,n=e.x,r=e.y,i=e.z,a=Math.cos(n),o=Math.sin(n),s=Math.cos(r),c=Math.sin(r),l=Math.cos(i),u=Math.sin(i);if(e.order===`XYZ`){let e=a*l,n=a*u,r=o*l,i=o*u;t[0]=s*l,t[4]=-s*u,t[8]=c,t[1]=n+r*c,t[5]=e-i*c,t[9]=-o*s,t[2]=i-e*c,t[6]=r+n*c,t[10]=a*s}else if(e.order===`YXZ`){let e=s*l,n=s*u,r=c*l,i=c*u;t[0]=e+i*o,t[4]=r*o-n,t[8]=a*c,t[1]=a*u,t[5]=a*l,t[9]=-o,t[2]=n*o-r,t[6]=i+e*o,t[10]=a*s}else if(e.order===`ZXY`){let e=s*l,n=s*u,r=c*l,i=c*u;t[0]=e-i*o,t[4]=-a*u,t[8]=r+n*o,t[1]=n+r*o,t[5]=a*l,t[9]=i-e*o,t[2]=-a*c,t[6]=o,t[10]=a*s}else if(e.order===`ZYX`){let e=a*l,n=a*u,r=o*l,i=o*u;t[0]=s*l,t[4]=r*c-n,t[8]=e*c+i,t[1]=s*u,t[5]=i*c+e,t[9]=n*c-r,t[2]=-c,t[6]=o*s,t[10]=a*s}else if(e.order===`YZX`){let e=a*s,n=a*c,r=o*s,i=o*c;t[0]=s*l,t[4]=i-e*u,t[8]=r*u+n,t[1]=u,t[5]=a*l,t[9]=-o*l,t[2]=-c*l,t[6]=n*u+r,t[10]=e-i*u}else if(e.order===`XZY`){let e=a*s,n=a*c,r=o*s,i=o*c;t[0]=s*l,t[4]=-u,t[8]=c*l,t[1]=e*u+i,t[5]=a*l,t[9]=n*u-r,t[2]=r*u-n,t[6]=o*l,t[10]=i*u+e}return t[3]=0,t[7]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this}makeRotationFromQuaternion(e){return this.compose(Br,e,Vr)}lookAt(e,t,n){let r=this.elements;return Wr.subVectors(e,t),Wr.lengthSq()===0&&(Wr.z=1),Wr.normalize(),Hr.crossVectors(n,Wr),Hr.lengthSq()===0&&(Math.abs(n.z)===1?Wr.x+=1e-4:Wr.z+=1e-4,Wr.normalize(),Hr.crossVectors(n,Wr)),Hr.normalize(),Ur.crossVectors(Wr,Hr),r[0]=Hr.x,r[4]=Ur.x,r[8]=Wr.x,r[1]=Hr.y,r[5]=Ur.y,r[9]=Wr.y,r[2]=Hr.z,r[6]=Ur.z,r[10]=Wr.z,this}multiply(e){return this.multiplyMatrices(this,e)}premultiply(e){return this.multiplyMatrices(e,this)}multiplyMatrices(e,t){let n=e.elements,r=t.elements,i=this.elements,a=n[0],o=n[4],s=n[8],c=n[12],l=n[1],u=n[5],d=n[9],f=n[13],p=n[2],m=n[6],h=n[10],g=n[14],_=n[3],v=n[7],y=n[11],b=n[15],x=r[0],S=r[4],C=r[8],w=r[12],T=r[1],E=r[5],D=r[9],O=r[13],k=r[2],A=r[6],j=r[10],M=r[14],N=r[3],P=r[7],F=r[11],I=r[15];return i[0]=a*x+o*T+s*k+c*N,i[4]=a*S+o*E+s*A+c*P,i[8]=a*C+o*D+s*j+c*F,i[12]=a*w+o*O+s*M+c*I,i[1]=l*x+u*T+d*k+f*N,i[5]=l*S+u*E+d*A+f*P,i[9]=l*C+u*D+d*j+f*F,i[13]=l*w+u*O+d*M+f*I,i[2]=p*x+m*T+h*k+g*N,i[6]=p*S+m*E+h*A+g*P,i[10]=p*C+m*D+h*j+g*F,i[14]=p*w+m*O+h*M+g*I,i[3]=_*x+v*T+y*k+b*N,i[7]=_*S+v*E+y*A+b*P,i[11]=_*C+v*D+y*j+b*F,i[15]=_*w+v*O+y*M+b*I,this}multiplyScalar(e){let t=this.elements;return t[0]*=e,t[4]*=e,t[8]*=e,t[12]*=e,t[1]*=e,t[5]*=e,t[9]*=e,t[13]*=e,t[2]*=e,t[6]*=e,t[10]*=e,t[14]*=e,t[3]*=e,t[7]*=e,t[11]*=e,t[15]*=e,this}determinant(){let e=this.elements,t=e[0],n=e[4],r=e[8],i=e[12],a=e[1],o=e[5],s=e[9],c=e[13],l=e[2],u=e[6],d=e[10],f=e[14],p=e[3],m=e[7],h=e[11],g=e[15];return p*(+i*s*u-r*c*u-i*o*d+n*c*d+r*o*f-n*s*f)+m*(+t*s*f-t*c*d+i*a*d-r*a*f+r*c*l-i*s*l)+h*(+t*c*u-t*o*f-i*a*u+n*a*f+i*o*l-n*c*l)+g*(-r*o*l-t*s*u+t*o*d+r*a*u-n*a*d+n*s*l)}transpose(){let e=this.elements,t;return t=e[1],e[1]=e[4],e[4]=t,t=e[2],e[2]=e[8],e[8]=t,t=e[6],e[6]=e[9],e[9]=t,t=e[3],e[3]=e[12],e[12]=t,t=e[7],e[7]=e[13],e[13]=t,t=e[11],e[11]=e[14],e[14]=t,this}setPosition(e,t,n){let r=this.elements;return e.isVector3?(r[12]=e.x,r[13]=e.y,r[14]=e.z):(r[12]=e,r[13]=t,r[14]=n),this}invert(){let e=this.elements,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;if(x===0)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);let S=1/x;return e[0]=_*S,e[1]=(m*d*i-u*h*i-m*r*f+n*h*f+u*r*g-n*d*g)*S,e[2]=(o*h*i-m*s*i+m*r*c-n*h*c-o*r*g+n*s*g)*S,e[3]=(u*s*i-o*d*i-u*r*c+n*d*c+o*r*f-n*s*f)*S,e[4]=v*S,e[5]=(l*h*i-p*d*i+p*r*f-t*h*f-l*r*g+t*d*g)*S,e[6]=(p*s*i-a*h*i-p*r*c+t*h*c+a*r*g-t*s*g)*S,e[7]=(a*d*i-l*s*i+l*r*c-t*d*c-a*r*f+t*s*f)*S,e[8]=y*S,e[9]=(p*u*i-l*m*i-p*n*f+t*m*f+l*n*g-t*u*g)*S,e[10]=(a*m*i-p*o*i+p*n*c-t*m*c-a*n*g+t*o*g)*S,e[11]=(l*o*i-a*u*i-l*n*c+t*u*c+a*n*f-t*o*f)*S,e[12]=b*S,e[13]=(l*m*r-p*u*r+p*n*d-t*m*d-l*n*h+t*u*h)*S,e[14]=(p*o*r-a*m*r-p*n*s+t*m*s+a*n*h-t*o*h)*S,e[15]=(a*u*r-l*o*r+l*n*s-t*u*s-a*n*d+t*o*d)*S,this}scale(e){let t=this.elements,n=e.x,r=e.y,i=e.z;return t[0]*=n,t[4]*=r,t[8]*=i,t[1]*=n,t[5]*=r,t[9]*=i,t[2]*=n,t[6]*=r,t[10]*=i,t[3]*=n,t[7]*=r,t[11]*=i,this}getMaxScaleOnAxis(){let e=this.elements,t=e[0]*e[0]+e[1]*e[1]+e[2]*e[2],n=e[4]*e[4]+e[5]*e[5]+e[6]*e[6],r=e[8]*e[8]+e[9]*e[9]+e[10]*e[10];return Math.sqrt(Math.max(t,n,r))}makeTranslation(e,t,n){return e.isVector3?this.set(1,0,0,e.x,0,1,0,e.y,0,0,1,e.z,0,0,0,1):this.set(1,0,0,e,0,1,0,t,0,0,1,n,0,0,0,1),this}makeRotationX(e){let t=Math.cos(e),n=Math.sin(e);return this.set(1,0,0,0,0,t,-n,0,0,n,t,0,0,0,0,1),this}makeRotationY(e){let t=Math.cos(e),n=Math.sin(e);return this.set(t,0,n,0,0,1,0,0,-n,0,t,0,0,0,0,1),this}makeRotationZ(e){let t=Math.cos(e),n=Math.sin(e);return this.set(t,-n,0,0,n,t,0,0,0,0,1,0,0,0,0,1),this}makeRotationAxis(e,t){let n=Math.cos(t),r=Math.sin(t),i=1-n,a=e.x,o=e.y,s=e.z,c=i*a,l=i*o;return this.set(c*a+n,c*o-r*s,c*s+r*o,0,c*o+r*s,l*o+n,l*s-r*a,0,c*s-r*o,l*s+r*a,i*s*s+n,0,0,0,0,1),this}makeScale(e,t,n){return this.set(e,0,0,0,0,t,0,0,0,0,n,0,0,0,0,1),this}makeShear(e,t,n,r,i,a){return this.set(1,n,i,0,e,1,a,0,t,r,1,0,0,0,0,1),this}compose(e,t,n){let r=this.elements,i=t._x,a=t._y,o=t._z,s=t._w,c=i+i,l=a+a,u=o+o,d=i*c,f=i*l,p=i*u,m=a*l,h=a*u,g=o*u,_=s*c,v=s*l,y=s*u,b=n.x,x=n.y,S=n.z;return r[0]=(1-(m+g))*b,r[1]=(f+y)*b,r[2]=(p-v)*b,r[3]=0,r[4]=(f-y)*x,r[5]=(1-(d+g))*x,r[6]=(h+_)*x,r[7]=0,r[8]=(p+v)*S,r[9]=(h-_)*S,r[10]=(1-(d+m))*S,r[11]=0,r[12]=e.x,r[13]=e.y,r[14]=e.z,r[15]=1,this}decompose(e,t,n){let r=this.elements,i=Rr.set(r[0],r[1],r[2]).length(),a=Rr.set(r[4],r[5],r[6]).length(),o=Rr.set(r[8],r[9],r[10]).length();this.determinant()<0&&(i=-i),e.x=r[12],e.y=r[13],e.z=r[14],zr.copy(this);let s=1/i,c=1/a,l=1/o;return zr.elements[0]*=s,zr.elements[1]*=s,zr.elements[2]*=s,zr.elements[4]*=c,zr.elements[5]*=c,zr.elements[6]*=c,zr.elements[8]*=l,zr.elements[9]*=l,zr.elements[10]*=l,t.setFromRotationMatrix(zr),n.x=i,n.y=a,n.z=o,this}makePerspective(e,t,n,r,i,a,o=on){let s=this.elements,c=2*i/(t-e),l=2*i/(n-r),u=(t+e)/(t-e),d=(n+r)/(n-r),f,p;if(o===2e3)f=-(a+i)/(a-i),p=-2*a*i/(a-i);else if(o===2001)f=-a/(a-i),p=-a*i/(a-i);else throw Error(`THREE.Matrix4.makePerspective(): Invalid coordinate system: `+o);return s[0]=c,s[4]=0,s[8]=u,s[12]=0,s[1]=0,s[5]=l,s[9]=d,s[13]=0,s[2]=0,s[6]=0,s[10]=f,s[14]=p,s[3]=0,s[7]=0,s[11]=-1,s[15]=0,this}makeOrthographic(e,t,n,r,i,a,o=on){let s=this.elements,c=1/(t-e),l=1/(n-r),u=1/(a-i),d=(t+e)*c,f=(n+r)*l,p,m;if(o===2e3)p=(a+i)*u,m=-2*u;else if(o===2001)p=i*u,m=-1*u;else throw Error(`THREE.Matrix4.makeOrthographic(): Invalid coordinate system: `+o);return s[0]=2*c,s[4]=0,s[8]=0,s[12]=-d,s[1]=0,s[5]=2*l,s[9]=0,s[13]=-f,s[2]=0,s[6]=0,s[10]=m,s[14]=-p,s[3]=0,s[7]=0,s[11]=0,s[15]=1,this}equals(e){let t=this.elements,n=e.elements;for(let e=0;e<16;e++)if(t[e]!==n[e])return!1;return!0}fromArray(e,t=0){for(let n=0;n<16;n++)this.elements[n]=e[n+t];return this}toArray(e=[],t=0){let n=this.elements;return e[t]=n[0],e[t+1]=n[1],e[t+2]=n[2],e[t+3]=n[3],e[t+4]=n[4],e[t+5]=n[5],e[t+6]=n[6],e[t+7]=n[7],e[t+8]=n[8],e[t+9]=n[9],e[t+10]=n[10],e[t+11]=n[11],e[t+12]=n[12],e[t+13]=n[13],e[t+14]=n[14],e[t+15]=n[15],e}},Rr=new W,zr=new G,Br=new W(0,0,0),Vr=new W(1,1,1),Hr=new W,Ur=new W,Wr=new W,Gr=new G,Kr=new cr,qr=class e{constructor(t=0,n=0,r=0,i=e.DEFAULT_ORDER){this.isEuler=!0,this._x=t,this._y=n,this._z=r,this._order=i}get x(){return this._x}set x(e){this._x=e,this._onChangeCallback()}get y(){return this._y}set y(e){this._y=e,this._onChangeCallback()}get z(){return this._z}set z(e){this._z=e,this._onChangeCallback()}get order(){return this._order}set order(e){this._order=e,this._onChangeCallback()}set(e,t,n,r=this._order){return this._x=e,this._y=t,this._z=n,this._order=r,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._order)}copy(e){return this._x=e._x,this._y=e._y,this._z=e._z,this._order=e._order,this._onChangeCallback(),this}setFromRotationMatrix(e,t=this._order,n=!0){let r=e.elements,i=r[0],a=r[4],o=r[8],s=r[1],c=r[5],l=r[9],u=r[2],d=r[6],f=r[10];switch(t){case`XYZ`:this._y=Math.asin(pn(o,-1,1)),Math.abs(o)<.9999999?(this._x=Math.atan2(-l,f),this._z=Math.atan2(-a,i)):(this._x=Math.atan2(d,c),this._z=0);break;case`YXZ`:this._x=Math.asin(-pn(l,-1,1)),Math.abs(l)<.9999999?(this._y=Math.atan2(o,f),this._z=Math.atan2(s,c)):(this._y=Math.atan2(-u,i),this._z=0);break;case`ZXY`:this._x=Math.asin(pn(d,-1,1)),Math.abs(d)<.9999999?(this._y=Math.atan2(-u,f),this._z=Math.atan2(-a,c)):(this._y=0,this._z=Math.atan2(s,i));break;case`ZYX`:this._y=Math.asin(-pn(u,-1,1)),Math.abs(u)<.9999999?(this._x=Math.atan2(d,f),this._z=Math.atan2(s,i)):(this._x=0,this._z=Math.atan2(-a,c));break;case`YZX`:this._z=Math.asin(pn(s,-1,1)),Math.abs(s)<.9999999?(this._x=Math.atan2(-l,c),this._y=Math.atan2(-u,i)):(this._x=0,this._y=Math.atan2(o,f));break;case`XZY`:this._z=Math.asin(-pn(a,-1,1)),Math.abs(a)<.9999999?(this._x=Math.atan2(d,c),this._y=Math.atan2(o,i)):(this._x=Math.atan2(-l,f),this._y=0);break;default:console.warn(`THREE.Euler: .setFromRotationMatrix() encountered an unknown order: `+t)}return this._order=t,n===!0&&this._onChangeCallback(),this}setFromQuaternion(e,t,n){return Gr.makeRotationFromQuaternion(e),this.setFromRotationMatrix(Gr,t,n)}setFromVector3(e,t=this._order){return this.set(e.x,e.y,e.z,t)}reorder(e){return Kr.setFromEuler(this),this.setFromQuaternion(Kr,e)}equals(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._order===this._order}fromArray(e){return this._x=e[0],this._y=e[1],this._z=e[2],e[3]!==void 0&&(this._order=e[3]),this._onChangeCallback(),this}toArray(e=[],t=0){return e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._order,e}_onChange(e){return this._onChangeCallback=e,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._order}};qr.DEFAULT_ORDER=`XYZ`;var Jr=class{constructor(){this.mask=1}set(e){this.mask=(1<>>0}enable(e){this.mask|=1<1){for(let e=0;e1){for(let e=0;e0&&(r.userData=this.userData),r.layers=this.layers.mask,r.matrix=this.matrix.toArray(),r.up=this.up.toArray(),this.matrixAutoUpdate===!1&&(r.matrixAutoUpdate=!1),this.isInstancedMesh&&(r.type=`InstancedMesh`,r.count=this.count,r.instanceMatrix=this.instanceMatrix.toJSON(),this.instanceColor!==null&&(r.instanceColor=this.instanceColor.toJSON())),this.isBatchedMesh&&(r.type=`BatchedMesh`,r.perObjectFrustumCulled=this.perObjectFrustumCulled,r.sortObjects=this.sortObjects,r.drawRanges=this._drawRanges,r.reservedRanges=this._reservedRanges,r.visibility=this._visibility,r.active=this._active,r.bounds=this._bounds.map(e=>({boxInitialized:e.boxInitialized,boxMin:e.box.min.toArray(),boxMax:e.box.max.toArray(),sphereInitialized:e.sphereInitialized,sphereRadius:e.sphere.radius,sphereCenter:e.sphere.center.toArray()})),r.maxInstanceCount=this._maxInstanceCount,r.maxVertexCount=this._maxVertexCount,r.maxIndexCount=this._maxIndexCount,r.geometryInitialized=this._geometryInitialized,r.geometryCount=this._geometryCount,r.matricesTexture=this._matricesTexture.toJSON(e),this._colorsTexture!==null&&(r.colorsTexture=this._colorsTexture.toJSON(e)),this.boundingSphere!==null&&(r.boundingSphere={center:r.boundingSphere.center.toArray(),radius:r.boundingSphere.radius}),this.boundingBox!==null&&(r.boundingBox={min:r.boundingBox.min.toArray(),max:r.boundingBox.max.toArray()}));function i(t,n){return t[n.uuid]===void 0&&(t[n.uuid]=n.toJSON(e)),n.uuid}if(this.isScene)this.background&&(this.background.isColor?r.background=this.background.toJSON():this.background.isTexture&&(r.background=this.background.toJSON(e).uuid)),this.environment&&this.environment.isTexture&&this.environment.isRenderTargetTexture!==!0&&(r.environment=this.environment.toJSON(e).uuid);else if(this.isMesh||this.isLine||this.isPoints){r.geometry=i(e.geometries,this.geometry);let t=this.geometry.parameters;if(t!==void 0&&t.shapes!==void 0){let n=t.shapes;if(Array.isArray(n))for(let t=0,r=n.length;t0){r.children=[];for(let t=0;t0){r.animations=[];for(let t=0;t0&&(n.geometries=t),r.length>0&&(n.materials=r),i.length>0&&(n.textures=i),o.length>0&&(n.images=o),s.length>0&&(n.shapes=s),c.length>0&&(n.skeletons=c),l.length>0&&(n.animations=l),u.length>0&&(n.nodes=u)}return n.object=r,n;function a(e){let t=[];for(let n in e){let r=e[n];delete r.metadata,t.push(r)}return t}}clone(e){return new this.constructor().copy(this,e)}copy(e,t=!0){if(this.name=e.name,this.up.copy(e.up),this.position.copy(e.position),this.rotation.order=e.rotation.order,this.quaternion.copy(e.quaternion),this.scale.copy(e.scale),this.matrix.copy(e.matrix),this.matrixWorld.copy(e.matrixWorld),this.matrixAutoUpdate=e.matrixAutoUpdate,this.matrixWorldAutoUpdate=e.matrixWorldAutoUpdate,this.matrixWorldNeedsUpdate=e.matrixWorldNeedsUpdate,this.layers.mask=e.layers.mask,this.visible=e.visible,this.castShadow=e.castShadow,this.receiveShadow=e.receiveShadow,this.frustumCulled=e.frustumCulled,this.renderOrder=e.renderOrder,this.animations=e.animations.slice(),this.userData=JSON.parse(JSON.stringify(e.userData)),t===!0)for(let t=0;t0?r.multiplyScalar(1/Math.sqrt(i)):r.set(0,0,0)}static getBarycoord(e,t,n,r,i){di.subVectors(r,t),fi.subVectors(n,t),pi.subVectors(e,t);let a=di.dot(di),o=di.dot(fi),s=di.dot(pi),c=fi.dot(fi),l=fi.dot(pi),u=a*c-o*o;if(u===0)return i.set(0,0,0),null;let d=1/u,f=(c*s-o*l)*d,p=(a*l-o*s)*d;return i.set(1-f-p,p,f)}static containsPoint(e,t,n,r){return this.getBarycoord(e,t,n,r,mi)!==null&&mi.x>=0&&mi.y>=0&&mi.x+mi.y<=1}static getInterpolation(e,t,n,r,i,a,o,s){return this.getBarycoord(e,t,n,r,mi)===null?(s.x=0,s.y=0,`z`in s&&(s.z=0),`w`in s&&(s.w=0),null):(s.setScalar(0),s.addScaledVector(i,mi.x),s.addScaledVector(a,mi.y),s.addScaledVector(o,mi.z),s)}static getInterpolatedAttribute(e,t,n,r,i,a){return xi.setScalar(0),Si.setScalar(0),Ci.setScalar(0),xi.fromBufferAttribute(e,t),Si.fromBufferAttribute(e,n),Ci.fromBufferAttribute(e,r),a.setScalar(0),a.addScaledVector(xi,i.x),a.addScaledVector(Si,i.y),a.addScaledVector(Ci,i.z),a}static isFrontFacing(e,t,n,r){return di.subVectors(n,t),fi.subVectors(e,t),di.cross(fi).dot(r)<0}set(e,t,n){return this.a.copy(e),this.b.copy(t),this.c.copy(n),this}setFromPointsAndIndices(e,t,n,r){return this.a.copy(e[t]),this.b.copy(e[n]),this.c.copy(e[r]),this}setFromAttributeAndIndices(e,t,n,r){return this.a.fromBufferAttribute(e,t),this.b.fromBufferAttribute(e,n),this.c.fromBufferAttribute(e,r),this}clone(){return new this.constructor().copy(this)}copy(e){return this.a.copy(e.a),this.b.copy(e.b),this.c.copy(e.c),this}getArea(){return di.subVectors(this.c,this.b),fi.subVectors(this.a,this.b),di.cross(fi).length()*.5}getMidpoint(e){return e.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(t){return e.getNormal(this.a,this.b,this.c,t)}getPlane(e){return e.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(t,n){return e.getBarycoord(t,this.a,this.b,this.c,n)}getInterpolation(t,n,r,i,a){return e.getInterpolation(t,this.a,this.b,this.c,n,r,i,a)}containsPoint(t){return e.containsPoint(t,this.a,this.b,this.c)}isFrontFacing(t){return e.isFrontFacing(this.a,this.b,this.c,t)}intersectsBox(e){return e.intersectsTriangle(this)}closestPointToPoint(e,t){let n=this.a,r=this.b,i=this.c,a,o;hi.subVectors(r,n),gi.subVectors(i,n),vi.subVectors(e,n);let s=hi.dot(vi),c=gi.dot(vi);if(s<=0&&c<=0)return t.copy(n);yi.subVectors(e,r);let l=hi.dot(yi),u=gi.dot(yi);if(l>=0&&u<=l)return t.copy(r);let d=s*u-l*c;if(d<=0&&s>=0&&l<=0)return a=s/(s-l),t.copy(n).addScaledVector(hi,a);bi.subVectors(e,i);let f=hi.dot(bi),p=gi.dot(bi);if(p>=0&&f<=p)return t.copy(i);let m=f*c-s*p;if(m<=0&&c>=0&&p<=0)return o=c/(c-p),t.copy(n).addScaledVector(gi,o);let h=l*p-f*u;if(h<=0&&u-l>=0&&f-p>=0)return _i.subVectors(i,r),o=(u-l)/(u-l+(f-p)),t.copy(r).addScaledVector(_i,o);let g=1/(h+m+d);return a=m*g,o=d*g,t.copy(n).addScaledVector(hi,a).addScaledVector(gi,o)}equals(e){return e.a.equals(this.a)&&e.b.equals(this.b)&&e.c.equals(this.c)}},Ti={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074},Ei={h:0,s:0,l:0},Di={h:0,s:0,l:0};function Oi(e,t,n){return n<0&&(n+=1),n>1&&--n,n<1/6?e+(t-e)*6*n:n<1/2?t:n<2/3?e+(t-e)*6*(2/3-n):e}var K=class{constructor(e,t,n){return this.isColor=!0,this.r=1,this.g=1,this.b=1,this.set(e,t,n)}set(e,t,n){if(t===void 0&&n===void 0){let t=e;t&&t.isColor?this.copy(t):typeof t==`number`?this.setHex(t):typeof t==`string`&&this.setStyle(t)}else this.setRGB(e,t,n);return this}setScalar(e){return this.r=e,this.g=e,this.b=e,this}setHex(e,t=Xt){return e=Math.floor(e),this.r=(e>>16&255)/255,this.g=(e>>8&255)/255,this.b=(e&255)/255,qn.toWorkingColorSpace(this,t),this}setRGB(e,t,n,r=qn.workingColorSpace){return this.r=e,this.g=t,this.b=n,qn.toWorkingColorSpace(this,r),this}setHSL(e,t,n,r=qn.workingColorSpace){if(e=mn(e,1),t=pn(t,0,1),n=pn(n,0,1),t===0)this.r=this.g=this.b=n;else{let r=n<=.5?n*(1+t):n+t-n*t,i=2*n-r;this.r=Oi(i,r,e+1/3),this.g=Oi(i,r,e),this.b=Oi(i,r,e-1/3)}return qn.toWorkingColorSpace(this,r),this}setStyle(e,t=Xt){function n(t){t!==void 0&&parseFloat(t)<1&&console.warn(`THREE.Color: Alpha component of `+e+` will be ignored.`)}let r;if(r=/^(\w+)\(([^\)]*)\)/.exec(e)){let i,a=r[1],o=r[2];switch(a){case`rgb`:case`rgba`:if(i=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return n(i[4]),this.setRGB(Math.min(255,parseInt(i[1],10))/255,Math.min(255,parseInt(i[2],10))/255,Math.min(255,parseInt(i[3],10))/255,t);if(i=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return n(i[4]),this.setRGB(Math.min(100,parseInt(i[1],10))/100,Math.min(100,parseInt(i[2],10))/100,Math.min(100,parseInt(i[3],10))/100,t);break;case`hsl`:case`hsla`:if(i=/^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return n(i[4]),this.setHSL(parseFloat(i[1])/360,parseFloat(i[2])/100,parseFloat(i[3])/100,t);break;default:console.warn(`THREE.Color: Unknown color model `+e)}}else if(r=/^\#([A-Fa-f\d]+)$/.exec(e)){let n=r[1],i=n.length;if(i===3)return this.setRGB(parseInt(n.charAt(0),16)/15,parseInt(n.charAt(1),16)/15,parseInt(n.charAt(2),16)/15,t);if(i===6)return this.setHex(parseInt(n,16),t);console.warn(`THREE.Color: Invalid hex color `+e)}else if(e&&e.length>0)return this.setColorName(e,t);return this}setColorName(e,t=Xt){let n=Ti[e.toLowerCase()];return n===void 0?console.warn(`THREE.Color: Unknown color `+e):this.setHex(n,t),this}clone(){return new this.constructor(this.r,this.g,this.b)}copy(e){return this.r=e.r,this.g=e.g,this.b=e.b,this}copySRGBToLinear(e){return this.r=Jn(e.r),this.g=Jn(e.g),this.b=Jn(e.b),this}copyLinearToSRGB(e){return this.r=Yn(e.r),this.g=Yn(e.g),this.b=Yn(e.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(e=Xt){return qn.fromWorkingColorSpace(ki.copy(this),e),Math.round(pn(ki.r*255,0,255))*65536+Math.round(pn(ki.g*255,0,255))*256+Math.round(pn(ki.b*255,0,255))}getHexString(e=Xt){return(`000000`+this.getHex(e).toString(16)).slice(-6)}getHSL(e,t=qn.workingColorSpace){qn.fromWorkingColorSpace(ki.copy(this),t);let n=ki.r,r=ki.g,i=ki.b,a=Math.max(n,r,i),o=Math.min(n,r,i),s,c,l=(o+a)/2;if(o===a)s=0,c=0;else{let e=a-o;switch(c=l<=.5?e/(a+o):e/(2-a-o),a){case n:s=(r-i)/e+(r0!=e>0&&this.version++,this._alphaTest=e}onBeforeRender(){}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(e){if(e!==void 0)for(let t in e){let n=e[t];if(n===void 0){console.warn(`THREE.Material: parameter '${t}' has value of undefined.`);continue}let r=this[t];if(r===void 0){console.warn(`THREE.Material: '${t}' is not a property of THREE.${this.type}.`);continue}r&&r.isColor?r.set(n):r&&r.isVector3&&n&&n.isVector3?r.copy(n):this[t]=n}}toJSON(e){let t=e===void 0||typeof e==`string`;t&&(e={textures:{},images:{}});let n={metadata:{version:4.6,type:`Material`,generator:`Material.toJSON`}};n.uuid=this.uuid,n.type=this.type,this.name!==``&&(n.name=this.name),this.color&&this.color.isColor&&(n.color=this.color.getHex()),this.roughness!==void 0&&(n.roughness=this.roughness),this.metalness!==void 0&&(n.metalness=this.metalness),this.sheen!==void 0&&(n.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(n.sheenColor=this.sheenColor.getHex()),this.sheenRoughness!==void 0&&(n.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(n.emissive=this.emissive.getHex()),this.emissiveIntensity!==void 0&&this.emissiveIntensity!==1&&(n.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(n.specular=this.specular.getHex()),this.specularIntensity!==void 0&&(n.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(n.specularColor=this.specularColor.getHex()),this.shininess!==void 0&&(n.shininess=this.shininess),this.clearcoat!==void 0&&(n.clearcoat=this.clearcoat),this.clearcoatRoughness!==void 0&&(n.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(n.clearcoatMap=this.clearcoatMap.toJSON(e).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(n.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(e).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(n.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(e).uuid,n.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),this.dispersion!==void 0&&(n.dispersion=this.dispersion),this.iridescence!==void 0&&(n.iridescence=this.iridescence),this.iridescenceIOR!==void 0&&(n.iridescenceIOR=this.iridescenceIOR),this.iridescenceThicknessRange!==void 0&&(n.iridescenceThicknessRange=this.iridescenceThicknessRange),this.iridescenceMap&&this.iridescenceMap.isTexture&&(n.iridescenceMap=this.iridescenceMap.toJSON(e).uuid),this.iridescenceThicknessMap&&this.iridescenceThicknessMap.isTexture&&(n.iridescenceThicknessMap=this.iridescenceThicknessMap.toJSON(e).uuid),this.anisotropy!==void 0&&(n.anisotropy=this.anisotropy),this.anisotropyRotation!==void 0&&(n.anisotropyRotation=this.anisotropyRotation),this.anisotropyMap&&this.anisotropyMap.isTexture&&(n.anisotropyMap=this.anisotropyMap.toJSON(e).uuid),this.map&&this.map.isTexture&&(n.map=this.map.toJSON(e).uuid),this.matcap&&this.matcap.isTexture&&(n.matcap=this.matcap.toJSON(e).uuid),this.alphaMap&&this.alphaMap.isTexture&&(n.alphaMap=this.alphaMap.toJSON(e).uuid),this.lightMap&&this.lightMap.isTexture&&(n.lightMap=this.lightMap.toJSON(e).uuid,n.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(n.aoMap=this.aoMap.toJSON(e).uuid,n.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(n.bumpMap=this.bumpMap.toJSON(e).uuid,n.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(n.normalMap=this.normalMap.toJSON(e).uuid,n.normalMapType=this.normalMapType,n.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(n.displacementMap=this.displacementMap.toJSON(e).uuid,n.displacementScale=this.displacementScale,n.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(n.roughnessMap=this.roughnessMap.toJSON(e).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(n.metalnessMap=this.metalnessMap.toJSON(e).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(n.emissiveMap=this.emissiveMap.toJSON(e).uuid),this.specularMap&&this.specularMap.isTexture&&(n.specularMap=this.specularMap.toJSON(e).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(n.specularIntensityMap=this.specularIntensityMap.toJSON(e).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(n.specularColorMap=this.specularColorMap.toJSON(e).uuid),this.envMap&&this.envMap.isTexture&&(n.envMap=this.envMap.toJSON(e).uuid,this.combine!==void 0&&(n.combine=this.combine)),this.envMapRotation!==void 0&&(n.envMapRotation=this.envMapRotation.toArray()),this.envMapIntensity!==void 0&&(n.envMapIntensity=this.envMapIntensity),this.reflectivity!==void 0&&(n.reflectivity=this.reflectivity),this.refractionRatio!==void 0&&(n.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(n.gradientMap=this.gradientMap.toJSON(e).uuid),this.transmission!==void 0&&(n.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(n.transmissionMap=this.transmissionMap.toJSON(e).uuid),this.thickness!==void 0&&(n.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(n.thicknessMap=this.thicknessMap.toJSON(e).uuid),this.attenuationDistance!==void 0&&this.attenuationDistance!==1/0&&(n.attenuationDistance=this.attenuationDistance),this.attenuationColor!==void 0&&(n.attenuationColor=this.attenuationColor.getHex()),this.size!==void 0&&(n.size=this.size),this.shadowSide!==null&&(n.shadowSide=this.shadowSide),this.sizeAttenuation!==void 0&&(n.sizeAttenuation=this.sizeAttenuation),this.blending!==1&&(n.blending=this.blending),this.side!==0&&(n.side=this.side),this.vertexColors===!0&&(n.vertexColors=!0),this.opacity<1&&(n.opacity=this.opacity),this.transparent===!0&&(n.transparent=!0),this.blendSrc!==204&&(n.blendSrc=this.blendSrc),this.blendDst!==205&&(n.blendDst=this.blendDst),this.blendEquation!==100&&(n.blendEquation=this.blendEquation),this.blendSrcAlpha!==null&&(n.blendSrcAlpha=this.blendSrcAlpha),this.blendDstAlpha!==null&&(n.blendDstAlpha=this.blendDstAlpha),this.blendEquationAlpha!==null&&(n.blendEquationAlpha=this.blendEquationAlpha),this.blendColor&&this.blendColor.isColor&&(n.blendColor=this.blendColor.getHex()),this.blendAlpha!==0&&(n.blendAlpha=this.blendAlpha),this.depthFunc!==3&&(n.depthFunc=this.depthFunc),this.depthTest===!1&&(n.depthTest=this.depthTest),this.depthWrite===!1&&(n.depthWrite=this.depthWrite),this.colorWrite===!1&&(n.colorWrite=this.colorWrite),this.stencilWriteMask!==255&&(n.stencilWriteMask=this.stencilWriteMask),this.stencilFunc!==519&&(n.stencilFunc=this.stencilFunc),this.stencilRef!==0&&(n.stencilRef=this.stencilRef),this.stencilFuncMask!==255&&(n.stencilFuncMask=this.stencilFuncMask),this.stencilFail!==7680&&(n.stencilFail=this.stencilFail),this.stencilZFail!==7680&&(n.stencilZFail=this.stencilZFail),this.stencilZPass!==7680&&(n.stencilZPass=this.stencilZPass),this.stencilWrite===!0&&(n.stencilWrite=this.stencilWrite),this.rotation!==void 0&&this.rotation!==0&&(n.rotation=this.rotation),this.polygonOffset===!0&&(n.polygonOffset=!0),this.polygonOffsetFactor!==0&&(n.polygonOffsetFactor=this.polygonOffsetFactor),this.polygonOffsetUnits!==0&&(n.polygonOffsetUnits=this.polygonOffsetUnits),this.linewidth!==void 0&&this.linewidth!==1&&(n.linewidth=this.linewidth),this.dashSize!==void 0&&(n.dashSize=this.dashSize),this.gapSize!==void 0&&(n.gapSize=this.gapSize),this.scale!==void 0&&(n.scale=this.scale),this.dithering===!0&&(n.dithering=!0),this.alphaTest>0&&(n.alphaTest=this.alphaTest),this.alphaHash===!0&&(n.alphaHash=!0),this.alphaToCoverage===!0&&(n.alphaToCoverage=!0),this.premultipliedAlpha===!0&&(n.premultipliedAlpha=!0),this.forceSinglePass===!0&&(n.forceSinglePass=!0),this.wireframe===!0&&(n.wireframe=!0),this.wireframeLinewidth>1&&(n.wireframeLinewidth=this.wireframeLinewidth),this.wireframeLinecap!==`round`&&(n.wireframeLinecap=this.wireframeLinecap),this.wireframeLinejoin!==`round`&&(n.wireframeLinejoin=this.wireframeLinejoin),this.flatShading===!0&&(n.flatShading=!0),this.visible===!1&&(n.visible=!1),this.toneMapped===!1&&(n.toneMapped=!1),this.fog===!1&&(n.fog=!1),Object.keys(this.userData).length>0&&(n.userData=this.userData);function r(e){let t=[];for(let n in e){let r=e[n];delete r.metadata,t.push(r)}return t}if(t){let t=r(e.textures),i=r(e.images);t.length>0&&(n.textures=t),i.length>0&&(n.images=i)}return n}clone(){return new this.constructor().copy(this)}copy(e){this.name=e.name,this.blending=e.blending,this.side=e.side,this.vertexColors=e.vertexColors,this.opacity=e.opacity,this.transparent=e.transparent,this.blendSrc=e.blendSrc,this.blendDst=e.blendDst,this.blendEquation=e.blendEquation,this.blendSrcAlpha=e.blendSrcAlpha,this.blendDstAlpha=e.blendDstAlpha,this.blendEquationAlpha=e.blendEquationAlpha,this.blendColor.copy(e.blendColor),this.blendAlpha=e.blendAlpha,this.depthFunc=e.depthFunc,this.depthTest=e.depthTest,this.depthWrite=e.depthWrite,this.stencilWriteMask=e.stencilWriteMask,this.stencilFunc=e.stencilFunc,this.stencilRef=e.stencilRef,this.stencilFuncMask=e.stencilFuncMask,this.stencilFail=e.stencilFail,this.stencilZFail=e.stencilZFail,this.stencilZPass=e.stencilZPass,this.stencilWrite=e.stencilWrite;let t=e.clippingPlanes,n=null;if(t!==null){let e=t.length;n=Array(e);for(let r=0;r!==e;++r)n[r]=t[r].clone()}return this.clippingPlanes=n,this.clipIntersection=e.clipIntersection,this.clipShadows=e.clipShadows,this.shadowSide=e.shadowSide,this.colorWrite=e.colorWrite,this.precision=e.precision,this.polygonOffset=e.polygonOffset,this.polygonOffsetFactor=e.polygonOffsetFactor,this.polygonOffsetUnits=e.polygonOffsetUnits,this.dithering=e.dithering,this.alphaTest=e.alphaTest,this.alphaHash=e.alphaHash,this.alphaToCoverage=e.alphaToCoverage,this.premultipliedAlpha=e.premultipliedAlpha,this.forceSinglePass=e.forceSinglePass,this.visible=e.visible,this.toneMapped=e.toneMapped,this.userData=JSON.parse(JSON.stringify(e.userData)),this}dispose(){this.dispatchEvent({type:`dispose`})}set needsUpdate(e){e===!0&&this.version++}onBuild(){console.warn(`Material: onBuild() has been removed.`)}},Mi=class extends ji{constructor(e){super(),this.isMeshBasicMaterial=!0,this.type=`MeshBasicMaterial`,this.color=new K(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new qr,this.combine=0,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap=`round`,this.wireframeLinejoin=`round`,this.fog=!0,this.setValues(e)}copy(e){return super.copy(e),this.color.copy(e.color),this.map=e.map,this.lightMap=e.lightMap,this.lightMapIntensity=e.lightMapIntensity,this.aoMap=e.aoMap,this.aoMapIntensity=e.aoMapIntensity,this.specularMap=e.specularMap,this.alphaMap=e.alphaMap,this.envMap=e.envMap,this.envMapRotation.copy(e.envMapRotation),this.combine=e.combine,this.reflectivity=e.reflectivity,this.refractionRatio=e.refractionRatio,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.fog=e.fog,this}},Ni=Pi();function Pi(){let e=new ArrayBuffer(4),t=new Float32Array(e),n=new Uint32Array(e),r=new Uint32Array(512),i=new Uint32Array(512);for(let e=0;e<256;++e){let t=e-127;t<-27?(r[e]=0,r[e|256]=32768,i[e]=24,i[e|256]=24):t<-14?(r[e]=1024>>-t-14,r[e|256]=1024>>-t-14|32768,i[e]=-t-1,i[e|256]=-t-1):t<=15?(r[e]=t+15<<10,r[e|256]=t+15<<10|32768,i[e]=13,i[e|256]=13):t<128?(r[e]=31744,r[e|256]=64512,i[e]=24,i[e|256]=24):(r[e]=31744,r[e|256]=64512,i[e]=13,i[e|256]=13)}let a=new Uint32Array(2048),o=new Uint32Array(64),s=new Uint32Array(64);for(let e=1;e<1024;++e){let t=e<<13,n=0;for(;!(t&8388608);)t<<=1,n-=8388608;t&=-8388609,n+=947912704,a[e]=t|n}for(let e=1024;e<2048;++e)a[e]=939524096+(e-1024<<13);for(let e=1;e<31;++e)o[e]=e<<23;o[31]=1199570944,o[32]=2147483648;for(let e=33;e<63;++e)o[e]=2147483648+(e-32<<23);o[63]=3347054592;for(let e=1;e<64;++e)e!==32&&(s[e]=1024);return{floatView:t,uint32View:n,baseTable:r,shiftTable:i,mantissaTable:a,exponentTable:o,offsetTable:s}}function Fi(e){Math.abs(e)>65504&&console.warn(`THREE.DataUtils.toHalfFloat(): Value out of range.`),e=pn(e,-65504,65504),Ni.floatView[0]=e;let t=Ni.uint32View[0],n=t>>23&511;return Ni.baseTable[n]+((t&8388607)>>Ni.shiftTable[n])}function Ii(e){let t=e>>10;return Ni.uint32View[0]=Ni.mantissaTable[Ni.offsetTable[t]+(e&1023)]+Ni.exponentTable[t],Ni.floatView[0]}var Li={toHalfFloat:Fi,fromHalfFloat:Ii},Ri=new W,zi=new H,Bi=class{constructor(e,t,n=!1){if(Array.isArray(e))throw TypeError(`THREE.BufferAttribute: array should be a Typed Array.`);this.isBufferAttribute=!0,this.name=``,this.array=e,this.itemSize=t,this.count=e===void 0?0:e.length/t,this.normalized=n,this.usage=an,this.updateRanges=[],this.gpuType=Ge,this.version=0}onUploadCallback(){}set needsUpdate(e){e===!0&&this.version++}setUsage(e){return this.usage=e,this}addUpdateRange(e,t){this.updateRanges.push({start:e,count:t})}clearUpdateRanges(){this.updateRanges.length=0}copy(e){return this.name=e.name,this.array=new e.array.constructor(e.array),this.itemSize=e.itemSize,this.count=e.count,this.normalized=e.normalized,this.usage=e.usage,this.gpuType=e.gpuType,this}copyAt(e,t,n){e*=this.itemSize,n*=t.itemSize;for(let r=0,i=this.itemSize;r0&&(e.userData=this.userData),this.parameters!==void 0){let t=this.parameters;for(let n in t)t[n]!==void 0&&(e[n]=t[n]);return e}e.data={attributes:{}};let t=this.index;t!==null&&(e.data.index={type:t.array.constructor.name,array:Array.prototype.slice.call(t.array)});let n=this.attributes;for(let t in n){let r=n[t];e.data.attributes[t]=r.toJSON(e.data)}let r={},i=!1;for(let t in this.morphAttributes){let n=this.morphAttributes[t],a=[];for(let t=0,r=n.length;t0&&(r[t]=a,i=!0)}i&&(e.data.morphAttributes=r,e.data.morphTargetsRelative=this.morphTargetsRelative);let a=this.groups;a.length>0&&(e.data.groups=JSON.parse(JSON.stringify(a)));let o=this.boundingSphere;return o!==null&&(e.data.boundingSphere={center:o.center.toArray(),radius:o.radius}),e}clone(){return new this.constructor().copy(this)}copy(e){this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null;let t={};this.name=e.name;let n=e.index;n!==null&&this.setIndex(n.clone(t));let r=e.attributes;for(let e in r){let n=r[e];this.setAttribute(e,n.clone(t))}let i=e.morphAttributes;for(let e in i){let n=[],r=i[e];for(let e=0,i=r.length;e0){let n=e[t[0]];if(n!==void 0){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,t=n.length;e(e.far-e.near)**2))&&(Qi.copy(i).invert(),$i.copy(e.ray).applyMatrix4(Qi),(n.boundingBox===null||$i.intersectsBox(n.boundingBox)!==!1)&&this._computeIntersections(e,t,$i)))}_computeIntersections(e,t,n){let r,i=this.geometry,a=this.material,o=i.index,s=i.attributes.position,c=i.attributes.uv,l=i.attributes.uv1,u=i.attributes.normal,d=i.groups,f=i.drawRange;if(o!==null){if(Array.isArray(a))for(let i=0,s=d.length;in.far?null:{distance:l,point:ca.clone(),object:e}}function ua(e,t,n,r,i,a,o,s,c,l){e.getVertexPosition(s,na),e.getVertexPosition(c,ra),e.getVertexPosition(l,ia);let u=la(e,t,n,r,na,ra,ia,sa);if(u){let e=new W;wi.getBarycoord(sa,na,ra,ia,e),i&&(u.uv=wi.getInterpolatedAttribute(i,s,c,l,e,new H)),a&&(u.uv1=wi.getInterpolatedAttribute(a,s,c,l,e,new H)),o&&(u.normal=wi.getInterpolatedAttribute(o,s,c,l,e,new W),u.normal.dot(r.direction)>0&&u.normal.multiplyScalar(-1));let t={a:s,b:c,c:l,normal:new W,materialIndex:0};wi.getNormal(na,ra,ia,t.normal),u.face=t,u.barycoord=e}return u}var da=class e extends Zi{constructor(e=1,t=1,n=1,r=1,i=1,a=1){super(),this.type=`BoxGeometry`,this.parameters={width:e,height:t,depth:n,widthSegments:r,heightSegments:i,depthSegments:a};let o=this;r=Math.floor(r),i=Math.floor(i),a=Math.floor(a);let s=[],c=[],l=[],u=[],d=0,f=0;p(`z`,`y`,`x`,-1,-1,n,t,e,a,i,0),p(`z`,`y`,`x`,1,-1,n,t,-e,a,i,1),p(`x`,`z`,`y`,1,1,e,n,t,r,a,2),p(`x`,`z`,`y`,1,-1,e,n,-t,r,a,3),p(`x`,`y`,`z`,1,-1,e,t,n,r,i,4),p(`x`,`y`,`z`,-1,-1,e,t,-n,r,i,5),this.setIndex(s),this.setAttribute(`position`,new Ui(c,3)),this.setAttribute(`normal`,new Ui(l,3)),this.setAttribute(`uv`,new Ui(u,2));function p(e,t,n,r,i,a,p,m,h,g,_){let v=a/h,y=p/g,b=a/2,x=p/2,S=m/2,C=h+1,w=g+1,T=0,E=0,D=new W;for(let a=0;a0?1:-1,l.push(D.x,D.y,D.z),u.push(s/h),u.push(1-a/g),T+=1}for(let e=0;e0&&(t.defines=this.defines),t.vertexShader=this.vertexShader,t.fragmentShader=this.fragmentShader,t.lights=this.lights,t.clipping=this.clipping;let n={};for(let e in this.extensions)this.extensions[e]===!0&&(n[e]=!0);return Object.keys(n).length>0&&(t.extensions=n),t}},ba=class extends ui{constructor(){super(),this.isCamera=!0,this.type=`Camera`,this.matrixWorldInverse=new G,this.projectionMatrix=new G,this.projectionMatrixInverse=new G,this.coordinateSystem=on}copy(e,t){return super.copy(e,t),this.matrixWorldInverse.copy(e.matrixWorldInverse),this.projectionMatrix.copy(e.projectionMatrix),this.projectionMatrixInverse.copy(e.projectionMatrixInverse),this.coordinateSystem=e.coordinateSystem,this}getWorldDirection(e){return super.getWorldDirection(e).negate()}updateMatrixWorld(e){super.updateMatrixWorld(e),this.matrixWorldInverse.copy(this.matrixWorld).invert()}updateWorldMatrix(e,t){super.updateWorldMatrix(e,t),this.matrixWorldInverse.copy(this.matrixWorld).invert()}clone(){return new this.constructor().copy(this)}},xa=new W,Sa=new H,Ca=new H,wa=class extends ba{constructor(e=50,t=1,n=.1,r=2e3){super(),this.isPerspectiveCamera=!0,this.type=`PerspectiveCamera`,this.fov=e,this.zoom=1,this.near=n,this.far=r,this.focus=10,this.aspect=t,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}copy(e,t){return super.copy(e,t),this.fov=e.fov,this.zoom=e.zoom,this.near=e.near,this.far=e.far,this.focus=e.focus,this.aspect=e.aspect,this.view=e.view===null?null:Object.assign({},e.view),this.filmGauge=e.filmGauge,this.filmOffset=e.filmOffset,this}setFocalLength(e){let t=.5*this.getFilmHeight()/e;this.fov=dn*2*Math.atan(t),this.updateProjectionMatrix()}getFocalLength(){let e=Math.tan(un*.5*this.fov);return .5*this.getFilmHeight()/e}getEffectiveFOV(){return dn*2*Math.atan(Math.tan(un*.5*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}getViewBounds(e,t,n){xa.set(-1,-1,.5).applyMatrix4(this.projectionMatrixInverse),t.set(xa.x,xa.y).multiplyScalar(-e/xa.z),xa.set(1,1,.5).applyMatrix4(this.projectionMatrixInverse),n.set(xa.x,xa.y).multiplyScalar(-e/xa.z)}getViewSize(e,t){return this.getViewBounds(e,Sa,Ca),t.subVectors(Ca,Sa)}setViewOffset(e,t,n,r,i,a){this.aspect=e/t,this.view===null&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=e,this.view.fullHeight=t,this.view.offsetX=n,this.view.offsetY=r,this.view.width=i,this.view.height=a,this.updateProjectionMatrix()}clearViewOffset(){this.view!==null&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){let e=this.near,t=e*Math.tan(un*.5*this.fov)/this.zoom,n=2*t,r=this.aspect*n,i=-.5*r,a=this.view;if(this.view!==null&&this.view.enabled){let e=a.fullWidth,o=a.fullHeight;i+=a.offsetX*r/e,t-=a.offsetY*n/o,r*=a.width/e,n*=a.height/o}let o=this.filmOffset;o!==0&&(i+=e*o/this.getFilmWidth()),this.projectionMatrix.makePerspective(i,i+r,t,t-n,e,this.far,this.coordinateSystem),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(e){let t=super.toJSON(e);return t.object.fov=this.fov,t.object.zoom=this.zoom,t.object.near=this.near,t.object.far=this.far,t.object.focus=this.focus,t.object.aspect=this.aspect,this.view!==null&&(t.object.view=Object.assign({},this.view)),t.object.filmGauge=this.filmGauge,t.object.filmOffset=this.filmOffset,t}},Ta=-90,Ea=1,Da=class extends ui{constructor(e,t,n){super(),this.type=`CubeCamera`,this.renderTarget=n,this.coordinateSystem=null,this.activeMipmapLevel=0;let r=new wa(Ta,Ea,e,t);r.layers=this.layers,this.add(r);let i=new wa(Ta,Ea,e,t);i.layers=this.layers,this.add(i);let a=new wa(Ta,Ea,e,t);a.layers=this.layers,this.add(a);let o=new wa(Ta,Ea,e,t);o.layers=this.layers,this.add(o);let s=new wa(Ta,Ea,e,t);s.layers=this.layers,this.add(s);let c=new wa(Ta,Ea,e,t);c.layers=this.layers,this.add(c)}updateCoordinateSystem(){let e=this.coordinateSystem,t=this.children.concat(),[n,r,i,a,o,s]=t;for(let e of t)this.remove(e);if(e===2e3)n.up.set(0,1,0),n.lookAt(1,0,0),r.up.set(0,1,0),r.lookAt(-1,0,0),i.up.set(0,0,-1),i.lookAt(0,1,0),a.up.set(0,0,1),a.lookAt(0,-1,0),o.up.set(0,1,0),o.lookAt(0,0,1),s.up.set(0,1,0),s.lookAt(0,0,-1);else if(e===2001)n.up.set(0,-1,0),n.lookAt(-1,0,0),r.up.set(0,-1,0),r.lookAt(1,0,0),i.up.set(0,0,1),i.lookAt(0,1,0),a.up.set(0,0,-1),a.lookAt(0,-1,0),o.up.set(0,-1,0),o.lookAt(0,0,1),s.up.set(0,-1,0),s.lookAt(0,0,-1);else throw Error(`THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: `+e);for(let e of t)this.add(e),e.updateMatrixWorld()}update(e,t){this.parent===null&&this.updateMatrixWorld();let{renderTarget:n,activeMipmapLevel:r}=this;this.coordinateSystem!==e.coordinateSystem&&(this.coordinateSystem=e.coordinateSystem,this.updateCoordinateSystem());let[i,a,o,s,c,l]=this.children,u=e.getRenderTarget(),d=e.getActiveCubeFace(),f=e.getActiveMipmapLevel(),p=e.xr.enabled;e.xr.enabled=!1;let m=n.texture.generateMipmaps;n.texture.generateMipmaps=!1,e.setRenderTarget(n,0,r),e.render(t,i),e.setRenderTarget(n,1,r),e.render(t,a),e.setRenderTarget(n,2,r),e.render(t,o),e.setRenderTarget(n,3,r),e.render(t,s),e.setRenderTarget(n,4,r),e.render(t,c),n.texture.generateMipmaps=m,e.setRenderTarget(n,5,r),e.render(t,l),e.setRenderTarget(u,d,f),e.xr.enabled=p,n.texture.needsPMREMUpdate=!0}},Oa=class extends nr{constructor(e,t,n,r,i,a,o,s,c,l){e=e===void 0?[]:e,t=t===void 0?301:t,super(e,t,n,r,i,a,o,s,c,l),this.isCubeTexture=!0,this.flipY=!1}get images(){return this.image}set images(e){this.image=e}},ka=class extends ar{constructor(e=1,t={}){super(e,e,t),this.isWebGLCubeRenderTarget=!0;let n={width:e,height:e,depth:1},r=[n,n,n,n,n,n];this.texture=new Oa(r,t.mapping,t.wrapS,t.wrapT,t.magFilter,t.minFilter,t.format,t.type,t.anisotropy,t.colorSpace),this.texture.isRenderTargetTexture=!0,this.texture.generateMipmaps=t.generateMipmaps!==void 0&&t.generateMipmaps,this.texture.minFilter=t.minFilter===void 0?Ie:t.minFilter}fromEquirectangularTexture(e,t){this.texture.type=t.type,this.texture.colorSpace=t.colorSpace,this.texture.generateMipmaps=t.generateMipmaps,this.texture.minFilter=t.minFilter,this.texture.magFilter=t.magFilter;let n={uniforms:{tEquirect:{value:null}},vertexShader:` + + varying vec3 vWorldDirection; + + vec3 transformDirection( in vec3 dir, in mat4 matrix ) { + + return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz ); + + } + + void main() { + + vWorldDirection = transformDirection( position, modelMatrix ); + + #include + #include + + } + `,fragmentShader:` + + uniform sampler2D tEquirect; + + varying vec3 vWorldDirection; + + #include + + void main() { + + vec3 direction = normalize( vWorldDirection ); + + vec2 sampleUV = equirectUv( direction ); + + gl_FragColor = texture2D( tEquirect, sampleUV ); + + } + `},r=new da(5,5,5),i=new ya({name:`CubemapFromEquirect`,uniforms:fa(n.uniforms),vertexShader:n.vertexShader,fragmentShader:n.fragmentShader,side:1,blending:0});i.uniforms.tEquirect.value=t;let a=new q(r,i),o=t.minFilter;return t.minFilter===1008&&(t.minFilter=Ie),new Da(1,10,this).update(e,a),t.minFilter=o,a.geometry.dispose(),a.material.dispose(),this}clear(e,t,n,r){let i=e.getRenderTarget();for(let i=0;i<6;i++)e.setRenderTarget(this,i),e.clear(t,n,r);e.setRenderTarget(i)}},Aa=new W,ja=new W,Ma=new U,Na=class{constructor(e=new W(1,0,0),t=0){this.isPlane=!0,this.normal=e,this.constant=t}set(e,t){return this.normal.copy(e),this.constant=t,this}setComponents(e,t,n,r){return this.normal.set(e,t,n),this.constant=r,this}setFromNormalAndCoplanarPoint(e,t){return this.normal.copy(e),this.constant=-t.dot(this.normal),this}setFromCoplanarPoints(e,t,n){let r=Aa.subVectors(n,t).cross(ja.subVectors(e,t)).normalize();return this.setFromNormalAndCoplanarPoint(r,e),this}copy(e){return this.normal.copy(e.normal),this.constant=e.constant,this}normalize(){let e=1/this.normal.length();return this.normal.multiplyScalar(e),this.constant*=e,this}negate(){return this.constant*=-1,this.normal.negate(),this}distanceToPoint(e){return this.normal.dot(e)+this.constant}distanceToSphere(e){return this.distanceToPoint(e.center)-e.radius}projectPoint(e,t){return t.copy(e).addScaledVector(this.normal,-this.distanceToPoint(e))}intersectLine(e,t){let n=e.delta(Aa),r=this.normal.dot(n);if(r===0)return this.distanceToPoint(e.start)===0?t.copy(e.start):null;let i=-(e.start.dot(this.normal)+this.constant)/r;return i<0||i>1?null:t.copy(e.start).addScaledVector(n,i)}intersectsLine(e){let t=this.distanceToPoint(e.start),n=this.distanceToPoint(e.end);return t<0&&n>0||n<0&&t>0}intersectsBox(e){return e.intersectsPlane(this)}intersectsSphere(e){return e.intersectsPlane(this)}coplanarPoint(e){return e.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(e,t){let n=t||Ma.getNormalMatrix(e),r=this.coplanarPoint(Aa).applyMatrix4(e),i=this.normal.applyMatrix3(n).normalize();return this.constant=-r.dot(i),this}translate(e){return this.constant-=e.dot(this.normal),this}equals(e){return e.normal.equals(this.normal)&&e.constant===this.constant}clone(){return new this.constructor().copy(this)}},Pa=new kr,Fa=new W,Ia=class{constructor(e=new Na,t=new Na,n=new Na,r=new Na,i=new Na,a=new Na){this.planes=[e,t,n,r,i,a]}set(e,t,n,r,i,a){let o=this.planes;return o[0].copy(e),o[1].copy(t),o[2].copy(n),o[3].copy(r),o[4].copy(i),o[5].copy(a),this}copy(e){let t=this.planes;for(let n=0;n<6;n++)t[n].copy(e.planes[n]);return this}setFromProjectionMatrix(e,t=on){let n=this.planes,r=e.elements,i=r[0],a=r[1],o=r[2],s=r[3],c=r[4],l=r[5],u=r[6],d=r[7],f=r[8],p=r[9],m=r[10],h=r[11],g=r[12],_=r[13],v=r[14],y=r[15];if(n[0].setComponents(s-i,d-c,h-f,y-g).normalize(),n[1].setComponents(s+i,d+c,h+f,y+g).normalize(),n[2].setComponents(s+a,d+l,h+p,y+_).normalize(),n[3].setComponents(s-a,d-l,h-p,y-_).normalize(),n[4].setComponents(s-o,d-u,h-m,y-v).normalize(),t===2e3)n[5].setComponents(s+o,d+u,h+m,y+v).normalize();else if(t===2001)n[5].setComponents(o,u,m,v).normalize();else throw Error(`THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: `+t);return this}intersectsObject(e){if(e.boundingSphere!==void 0)e.boundingSphere===null&&e.computeBoundingSphere(),Pa.copy(e.boundingSphere).applyMatrix4(e.matrixWorld);else{let t=e.geometry;t.boundingSphere===null&&t.computeBoundingSphere(),Pa.copy(t.boundingSphere).applyMatrix4(e.matrixWorld)}return this.intersectsSphere(Pa)}intersectsSprite(e){return Pa.center.set(0,0,0),Pa.radius=.7071067811865476,Pa.applyMatrix4(e.matrixWorld),this.intersectsSphere(Pa)}intersectsSphere(e){let t=this.planes,n=e.center,r=-e.radius;for(let e=0;e<6;e++)if(t[e].distanceToPoint(n)0?e.max.x:e.min.x,Fa.y=r.normal.y>0?e.max.y:e.min.y,Fa.z=r.normal.z>0?e.max.z:e.min.z,r.distanceToPoint(Fa)<0)return!1}return!0}containsPoint(e){let t=this.planes;for(let n=0;n<6;n++)if(t[n].distanceToPoint(e)<0)return!1;return!0}clone(){return new this.constructor().copy(this)}};function La(){let e=null,t=!1,n=null,r=null;function i(t,a){n(t,a),r=e.requestAnimationFrame(i)}return{start:function(){t!==!0&&n!==null&&(r=e.requestAnimationFrame(i),t=!0)},stop:function(){e.cancelAnimationFrame(r),t=!1},setAnimationLoop:function(e){n=e},setContext:function(t){e=t}}}function Ra(e){let t=new WeakMap;function n(t,n){let r=t.array,i=t.usage,a=r.byteLength,o=e.createBuffer();e.bindBuffer(n,o),e.bufferData(n,r,i),t.onUploadCallback();let s;if(r instanceof Float32Array)s=e.FLOAT;else if(r instanceof Uint16Array)s=t.isFloat16BufferAttribute?e.HALF_FLOAT:e.UNSIGNED_SHORT;else if(r instanceof Int16Array)s=e.SHORT;else if(r instanceof Uint32Array)s=e.UNSIGNED_INT;else if(r instanceof Int32Array)s=e.INT;else if(r instanceof Int8Array)s=e.BYTE;else if(r instanceof Uint8Array)s=e.UNSIGNED_BYTE;else if(r instanceof Uint8ClampedArray)s=e.UNSIGNED_BYTE;else throw Error(`THREE.WebGLAttributes: Unsupported buffer data format: `+r);return{buffer:o,type:s,bytesPerElement:r.BYTES_PER_ELEMENT,version:t.version,size:a}}function r(t,n,r){let i=n.array,a=n.updateRanges;if(e.bindBuffer(r,t),a.length===0)e.bufferSubData(r,0,i);else{a.sort((e,t)=>e.start-t.start);let t=0;for(let e=1;e 0 + vec4 plane; + #ifdef ALPHA_TO_COVERAGE + float distanceToPlane, distanceGradient; + float clipOpacity = 1.0; + #pragma unroll_loop_start + for ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) { + plane = clippingPlanes[ i ]; + distanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w; + distanceGradient = fwidth( distanceToPlane ) / 2.0; + clipOpacity *= smoothstep( - distanceGradient, distanceGradient, distanceToPlane ); + if ( clipOpacity == 0.0 ) discard; + } + #pragma unroll_loop_end + #if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES + float unionClipOpacity = 1.0; + #pragma unroll_loop_start + for ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) { + plane = clippingPlanes[ i ]; + distanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w; + distanceGradient = fwidth( distanceToPlane ) / 2.0; + unionClipOpacity *= 1.0 - smoothstep( - distanceGradient, distanceGradient, distanceToPlane ); + } + #pragma unroll_loop_end + clipOpacity *= 1.0 - unionClipOpacity; + #endif + diffuseColor.a *= clipOpacity; + if ( diffuseColor.a == 0.0 ) discard; + #else + #pragma unroll_loop_start + for ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) { + plane = clippingPlanes[ i ]; + if ( dot( vClipPosition, plane.xyz ) > plane.w ) discard; + } + #pragma unroll_loop_end + #if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES + bool clipped = true; + #pragma unroll_loop_start + for ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) { + plane = clippingPlanes[ i ]; + clipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped; + } + #pragma unroll_loop_end + if ( clipped ) discard; + #endif + #endif +#endif`,clipping_planes_pars_fragment:`#if NUM_CLIPPING_PLANES > 0 + varying vec3 vClipPosition; + uniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ]; +#endif`,clipping_planes_pars_vertex:`#if NUM_CLIPPING_PLANES > 0 + varying vec3 vClipPosition; +#endif`,clipping_planes_vertex:`#if NUM_CLIPPING_PLANES > 0 + vClipPosition = - mvPosition.xyz; +#endif`,color_fragment:`#if defined( USE_COLOR_ALPHA ) + diffuseColor *= vColor; +#elif defined( USE_COLOR ) + diffuseColor.rgb *= vColor; +#endif`,color_pars_fragment:`#if defined( USE_COLOR_ALPHA ) + varying vec4 vColor; +#elif defined( USE_COLOR ) + varying vec3 vColor; +#endif`,color_pars_vertex:`#if defined( USE_COLOR_ALPHA ) + varying vec4 vColor; +#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR ) + varying vec3 vColor; +#endif`,color_vertex:`#if defined( USE_COLOR_ALPHA ) + vColor = vec4( 1.0 ); +#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR ) + vColor = vec3( 1.0 ); +#endif +#ifdef USE_COLOR + vColor *= color; +#endif +#ifdef USE_INSTANCING_COLOR + vColor.xyz *= instanceColor.xyz; +#endif +#ifdef USE_BATCHING_COLOR + vec3 batchingColor = getBatchingColor( getIndirectIndex( gl_DrawID ) ); + vColor.xyz *= batchingColor.xyz; +#endif`,common:`#define PI 3.141592653589793 +#define PI2 6.283185307179586 +#define PI_HALF 1.5707963267948966 +#define RECIPROCAL_PI 0.3183098861837907 +#define RECIPROCAL_PI2 0.15915494309189535 +#define EPSILON 1e-6 +#ifndef saturate +#define saturate( a ) clamp( a, 0.0, 1.0 ) +#endif +#define whiteComplement( a ) ( 1.0 - saturate( a ) ) +float pow2( const in float x ) { return x*x; } +vec3 pow2( const in vec3 x ) { return x*x; } +float pow3( const in float x ) { return x*x*x; } +float pow4( const in float x ) { float x2 = x*x; return x2*x2; } +float max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); } +float average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); } +highp float rand( const in vec2 uv ) { + const highp float a = 12.9898, b = 78.233, c = 43758.5453; + highp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI ); + return fract( sin( sn ) * c ); +} +#ifdef HIGH_PRECISION + float precisionSafeLength( vec3 v ) { return length( v ); } +#else + float precisionSafeLength( vec3 v ) { + float maxComponent = max3( abs( v ) ); + return length( v / maxComponent ) * maxComponent; + } +#endif +struct IncidentLight { + vec3 color; + vec3 direction; + bool visible; +}; +struct ReflectedLight { + vec3 directDiffuse; + vec3 directSpecular; + vec3 indirectDiffuse; + vec3 indirectSpecular; +}; +#ifdef USE_ALPHAHASH + varying vec3 vPosition; +#endif +vec3 transformDirection( in vec3 dir, in mat4 matrix ) { + return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz ); +} +vec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) { + return normalize( ( vec4( dir, 0.0 ) * matrix ).xyz ); +} +mat3 transposeMat3( const in mat3 m ) { + mat3 tmp; + tmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x ); + tmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y ); + tmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z ); + return tmp; +} +bool isPerspectiveMatrix( mat4 m ) { + return m[ 2 ][ 3 ] == - 1.0; +} +vec2 equirectUv( in vec3 dir ) { + float u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5; + float v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5; + return vec2( u, v ); +} +vec3 BRDF_Lambert( const in vec3 diffuseColor ) { + return RECIPROCAL_PI * diffuseColor; +} +vec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) { + float fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH ); + return f0 * ( 1.0 - fresnel ) + ( f90 * fresnel ); +} +float F_Schlick( const in float f0, const in float f90, const in float dotVH ) { + float fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH ); + return f0 * ( 1.0 - fresnel ) + ( f90 * fresnel ); +} // validated`,cube_uv_reflection_fragment:`#ifdef ENVMAP_TYPE_CUBE_UV + #define cubeUV_minMipLevel 4.0 + #define cubeUV_minTileSize 16.0 + float getFace( vec3 direction ) { + vec3 absDirection = abs( direction ); + float face = - 1.0; + if ( absDirection.x > absDirection.z ) { + if ( absDirection.x > absDirection.y ) + face = direction.x > 0.0 ? 0.0 : 3.0; + else + face = direction.y > 0.0 ? 1.0 : 4.0; + } else { + if ( absDirection.z > absDirection.y ) + face = direction.z > 0.0 ? 2.0 : 5.0; + else + face = direction.y > 0.0 ? 1.0 : 4.0; + } + return face; + } + vec2 getUV( vec3 direction, float face ) { + vec2 uv; + if ( face == 0.0 ) { + uv = vec2( direction.z, direction.y ) / abs( direction.x ); + } else if ( face == 1.0 ) { + uv = vec2( - direction.x, - direction.z ) / abs( direction.y ); + } else if ( face == 2.0 ) { + uv = vec2( - direction.x, direction.y ) / abs( direction.z ); + } else if ( face == 3.0 ) { + uv = vec2( - direction.z, direction.y ) / abs( direction.x ); + } else if ( face == 4.0 ) { + uv = vec2( - direction.x, direction.z ) / abs( direction.y ); + } else { + uv = vec2( direction.x, direction.y ) / abs( direction.z ); + } + return 0.5 * ( uv + 1.0 ); + } + vec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) { + float face = getFace( direction ); + float filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 ); + mipInt = max( mipInt, cubeUV_minMipLevel ); + float faceSize = exp2( mipInt ); + highp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0; + if ( face > 2.0 ) { + uv.y += faceSize; + face -= 3.0; + } + uv.x += face * faceSize; + uv.x += filterInt * 3.0 * cubeUV_minTileSize; + uv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize ); + uv.x *= CUBEUV_TEXEL_WIDTH; + uv.y *= CUBEUV_TEXEL_HEIGHT; + #ifdef texture2DGradEXT + return texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb; + #else + return texture2D( envMap, uv ).rgb; + #endif + } + #define cubeUV_r0 1.0 + #define cubeUV_m0 - 2.0 + #define cubeUV_r1 0.8 + #define cubeUV_m1 - 1.0 + #define cubeUV_r4 0.4 + #define cubeUV_m4 2.0 + #define cubeUV_r5 0.305 + #define cubeUV_m5 3.0 + #define cubeUV_r6 0.21 + #define cubeUV_m6 4.0 + float roughnessToMip( float roughness ) { + float mip = 0.0; + if ( roughness >= cubeUV_r1 ) { + mip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0; + } else if ( roughness >= cubeUV_r4 ) { + mip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1; + } else if ( roughness >= cubeUV_r5 ) { + mip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4; + } else if ( roughness >= cubeUV_r6 ) { + mip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5; + } else { + mip = - 2.0 * log2( 1.16 * roughness ); } + return mip; + } + vec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) { + float mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP ); + float mipF = fract( mip ); + float mipInt = floor( mip ); + vec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt ); + if ( mipF == 0.0 ) { + return vec4( color0, 1.0 ); + } else { + vec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 ); + return vec4( mix( color0, color1, mipF ), 1.0 ); + } + } +#endif`,defaultnormal_vertex:`vec3 transformedNormal = objectNormal; +#ifdef USE_TANGENT + vec3 transformedTangent = objectTangent; +#endif +#ifdef USE_BATCHING + mat3 bm = mat3( batchingMatrix ); + transformedNormal /= vec3( dot( bm[ 0 ], bm[ 0 ] ), dot( bm[ 1 ], bm[ 1 ] ), dot( bm[ 2 ], bm[ 2 ] ) ); + transformedNormal = bm * transformedNormal; + #ifdef USE_TANGENT + transformedTangent = bm * transformedTangent; + #endif +#endif +#ifdef USE_INSTANCING + mat3 im = mat3( instanceMatrix ); + transformedNormal /= vec3( dot( im[ 0 ], im[ 0 ] ), dot( im[ 1 ], im[ 1 ] ), dot( im[ 2 ], im[ 2 ] ) ); + transformedNormal = im * transformedNormal; + #ifdef USE_TANGENT + transformedTangent = im * transformedTangent; + #endif +#endif +transformedNormal = normalMatrix * transformedNormal; +#ifdef FLIP_SIDED + transformedNormal = - transformedNormal; +#endif +#ifdef USE_TANGENT + transformedTangent = ( modelViewMatrix * vec4( transformedTangent, 0.0 ) ).xyz; + #ifdef FLIP_SIDED + transformedTangent = - transformedTangent; + #endif +#endif`,displacementmap_pars_vertex:`#ifdef USE_DISPLACEMENTMAP + uniform sampler2D displacementMap; + uniform float displacementScale; + uniform float displacementBias; +#endif`,displacementmap_vertex:`#ifdef USE_DISPLACEMENTMAP + transformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias ); +#endif`,emissivemap_fragment:`#ifdef USE_EMISSIVEMAP + vec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv ); + totalEmissiveRadiance *= emissiveColor.rgb; +#endif`,emissivemap_pars_fragment:`#ifdef USE_EMISSIVEMAP + uniform sampler2D emissiveMap; +#endif`,colorspace_fragment:`gl_FragColor = linearToOutputTexel( gl_FragColor );`,colorspace_pars_fragment:` +const mat3 LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = mat3( + vec3( 0.8224621, 0.177538, 0.0 ), + vec3( 0.0331941, 0.9668058, 0.0 ), + vec3( 0.0170827, 0.0723974, 0.9105199 ) +); +const mat3 LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = mat3( + vec3( 1.2249401, - 0.2249404, 0.0 ), + vec3( - 0.0420569, 1.0420571, 0.0 ), + vec3( - 0.0196376, - 0.0786361, 1.0982735 ) +); +vec4 LinearSRGBToLinearDisplayP3( in vec4 value ) { + return vec4( value.rgb * LINEAR_SRGB_TO_LINEAR_DISPLAY_P3, value.a ); +} +vec4 LinearDisplayP3ToLinearSRGB( in vec4 value ) { + return vec4( value.rgb * LINEAR_DISPLAY_P3_TO_LINEAR_SRGB, value.a ); +} +vec4 LinearTransferOETF( in vec4 value ) { + return value; +} +vec4 sRGBTransferOETF( in vec4 value ) { + return vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a ); +}`,envmap_fragment:`#ifdef USE_ENVMAP + #ifdef ENV_WORLDPOS + vec3 cameraToFrag; + if ( isOrthographic ) { + cameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) ); + } else { + cameraToFrag = normalize( vWorldPosition - cameraPosition ); + } + vec3 worldNormal = inverseTransformDirection( normal, viewMatrix ); + #ifdef ENVMAP_MODE_REFLECTION + vec3 reflectVec = reflect( cameraToFrag, worldNormal ); + #else + vec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio ); + #endif + #else + vec3 reflectVec = vReflect; + #endif + #ifdef ENVMAP_TYPE_CUBE + vec4 envColor = textureCube( envMap, envMapRotation * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) ); + #else + vec4 envColor = vec4( 0.0 ); + #endif + #ifdef ENVMAP_BLENDING_MULTIPLY + outgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity ); + #elif defined( ENVMAP_BLENDING_MIX ) + outgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity ); + #elif defined( ENVMAP_BLENDING_ADD ) + outgoingLight += envColor.xyz * specularStrength * reflectivity; + #endif +#endif`,envmap_common_pars_fragment:`#ifdef USE_ENVMAP + uniform float envMapIntensity; + uniform float flipEnvMap; + uniform mat3 envMapRotation; + #ifdef ENVMAP_TYPE_CUBE + uniform samplerCube envMap; + #else + uniform sampler2D envMap; + #endif + +#endif`,envmap_pars_fragment:`#ifdef USE_ENVMAP + uniform float reflectivity; + #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT ) + #define ENV_WORLDPOS + #endif + #ifdef ENV_WORLDPOS + varying vec3 vWorldPosition; + uniform float refractionRatio; + #else + varying vec3 vReflect; + #endif +#endif`,envmap_pars_vertex:`#ifdef USE_ENVMAP + #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT ) + #define ENV_WORLDPOS + #endif + #ifdef ENV_WORLDPOS + + varying vec3 vWorldPosition; + #else + varying vec3 vReflect; + uniform float refractionRatio; + #endif +#endif`,envmap_physical_pars_fragment:`#ifdef USE_ENVMAP + vec3 getIBLIrradiance( const in vec3 normal ) { + #ifdef ENVMAP_TYPE_CUBE_UV + vec3 worldNormal = inverseTransformDirection( normal, viewMatrix ); + vec4 envMapColor = textureCubeUV( envMap, envMapRotation * worldNormal, 1.0 ); + return PI * envMapColor.rgb * envMapIntensity; + #else + return vec3( 0.0 ); + #endif + } + vec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) { + #ifdef ENVMAP_TYPE_CUBE_UV + vec3 reflectVec = reflect( - viewDir, normal ); + reflectVec = normalize( mix( reflectVec, normal, roughness * roughness) ); + reflectVec = inverseTransformDirection( reflectVec, viewMatrix ); + vec4 envMapColor = textureCubeUV( envMap, envMapRotation * reflectVec, roughness ); + return envMapColor.rgb * envMapIntensity; + #else + return vec3( 0.0 ); + #endif + } + #ifdef USE_ANISOTROPY + vec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) { + #ifdef ENVMAP_TYPE_CUBE_UV + vec3 bentNormal = cross( bitangent, viewDir ); + bentNormal = normalize( cross( bentNormal, bitangent ) ); + bentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) ); + return getIBLRadiance( viewDir, bentNormal, roughness ); + #else + return vec3( 0.0 ); + #endif + } + #endif +#endif`,envmap_vertex:`#ifdef USE_ENVMAP + #ifdef ENV_WORLDPOS + vWorldPosition = worldPosition.xyz; + #else + vec3 cameraToVertex; + if ( isOrthographic ) { + cameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) ); + } else { + cameraToVertex = normalize( worldPosition.xyz - cameraPosition ); + } + vec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix ); + #ifdef ENVMAP_MODE_REFLECTION + vReflect = reflect( cameraToVertex, worldNormal ); + #else + vReflect = refract( cameraToVertex, worldNormal, refractionRatio ); + #endif + #endif +#endif`,fog_vertex:`#ifdef USE_FOG + vFogDepth = - mvPosition.z; +#endif`,fog_pars_vertex:`#ifdef USE_FOG + varying float vFogDepth; +#endif`,fog_fragment:`#ifdef USE_FOG + #ifdef FOG_EXP2 + float fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth ); + #else + float fogFactor = smoothstep( fogNear, fogFar, vFogDepth ); + #endif + gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor ); +#endif`,fog_pars_fragment:`#ifdef USE_FOG + uniform vec3 fogColor; + varying float vFogDepth; + #ifdef FOG_EXP2 + uniform float fogDensity; + #else + uniform float fogNear; + uniform float fogFar; + #endif +#endif`,gradientmap_pars_fragment:`#ifdef USE_GRADIENTMAP + uniform sampler2D gradientMap; +#endif +vec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) { + float dotNL = dot( normal, lightDirection ); + vec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 ); + #ifdef USE_GRADIENTMAP + return vec3( texture2D( gradientMap, coord ).r ); + #else + vec2 fw = fwidth( coord ) * 0.5; + return mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) ); + #endif +}`,lightmap_pars_fragment:`#ifdef USE_LIGHTMAP + uniform sampler2D lightMap; + uniform float lightMapIntensity; +#endif`,lights_lambert_fragment:`LambertMaterial material; +material.diffuseColor = diffuseColor.rgb; +material.specularStrength = specularStrength;`,lights_lambert_pars_fragment:`varying vec3 vViewPosition; +struct LambertMaterial { + vec3 diffuseColor; + float specularStrength; +}; +void RE_Direct_Lambert( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) { + float dotNL = saturate( dot( geometryNormal, directLight.direction ) ); + vec3 irradiance = dotNL * directLight.color; + reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); +} +void RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) { + reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); +} +#define RE_Direct RE_Direct_Lambert +#define RE_IndirectDiffuse RE_IndirectDiffuse_Lambert`,lights_pars_begin:`uniform bool receiveShadow; +uniform vec3 ambientLightColor; +#if defined( USE_LIGHT_PROBES ) + uniform vec3 lightProbe[ 9 ]; +#endif +vec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) { + float x = normal.x, y = normal.y, z = normal.z; + vec3 result = shCoefficients[ 0 ] * 0.886227; + result += shCoefficients[ 1 ] * 2.0 * 0.511664 * y; + result += shCoefficients[ 2 ] * 2.0 * 0.511664 * z; + result += shCoefficients[ 3 ] * 2.0 * 0.511664 * x; + result += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y; + result += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z; + result += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 ); + result += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z; + result += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y ); + return result; +} +vec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) { + vec3 worldNormal = inverseTransformDirection( normal, viewMatrix ); + vec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe ); + return irradiance; +} +vec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) { + vec3 irradiance = ambientLightColor; + return irradiance; +} +float getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) { + float distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 ); + if ( cutoffDistance > 0.0 ) { + distanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) ); + } + return distanceFalloff; +} +float getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) { + return smoothstep( coneCosine, penumbraCosine, angleCosine ); +} +#if NUM_DIR_LIGHTS > 0 + struct DirectionalLight { + vec3 direction; + vec3 color; + }; + uniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ]; + void getDirectionalLightInfo( const in DirectionalLight directionalLight, out IncidentLight light ) { + light.color = directionalLight.color; + light.direction = directionalLight.direction; + light.visible = true; + } +#endif +#if NUM_POINT_LIGHTS > 0 + struct PointLight { + vec3 position; + vec3 color; + float distance; + float decay; + }; + uniform PointLight pointLights[ NUM_POINT_LIGHTS ]; + void getPointLightInfo( const in PointLight pointLight, const in vec3 geometryPosition, out IncidentLight light ) { + vec3 lVector = pointLight.position - geometryPosition; + light.direction = normalize( lVector ); + float lightDistance = length( lVector ); + light.color = pointLight.color; + light.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay ); + light.visible = ( light.color != vec3( 0.0 ) ); + } +#endif +#if NUM_SPOT_LIGHTS > 0 + struct SpotLight { + vec3 position; + vec3 direction; + vec3 color; + float distance; + float decay; + float coneCos; + float penumbraCos; + }; + uniform SpotLight spotLights[ NUM_SPOT_LIGHTS ]; + void getSpotLightInfo( const in SpotLight spotLight, const in vec3 geometryPosition, out IncidentLight light ) { + vec3 lVector = spotLight.position - geometryPosition; + light.direction = normalize( lVector ); + float angleCos = dot( light.direction, spotLight.direction ); + float spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos ); + if ( spotAttenuation > 0.0 ) { + float lightDistance = length( lVector ); + light.color = spotLight.color * spotAttenuation; + light.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay ); + light.visible = ( light.color != vec3( 0.0 ) ); + } else { + light.color = vec3( 0.0 ); + light.visible = false; + } + } +#endif +#if NUM_RECT_AREA_LIGHTS > 0 + struct RectAreaLight { + vec3 color; + vec3 position; + vec3 halfWidth; + vec3 halfHeight; + }; + uniform sampler2D ltc_1; uniform sampler2D ltc_2; + uniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ]; +#endif +#if NUM_HEMI_LIGHTS > 0 + struct HemisphereLight { + vec3 direction; + vec3 skyColor; + vec3 groundColor; + }; + uniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ]; + vec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) { + float dotNL = dot( normal, hemiLight.direction ); + float hemiDiffuseWeight = 0.5 * dotNL + 0.5; + vec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight ); + return irradiance; + } +#endif`,lights_toon_fragment:`ToonMaterial material; +material.diffuseColor = diffuseColor.rgb;`,lights_toon_pars_fragment:`varying vec3 vViewPosition; +struct ToonMaterial { + vec3 diffuseColor; +}; +void RE_Direct_Toon( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) { + vec3 irradiance = getGradientIrradiance( geometryNormal, directLight.direction ) * directLight.color; + reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); +} +void RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) { + reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); +} +#define RE_Direct RE_Direct_Toon +#define RE_IndirectDiffuse RE_IndirectDiffuse_Toon`,lights_phong_fragment:`BlinnPhongMaterial material; +material.diffuseColor = diffuseColor.rgb; +material.specularColor = specular; +material.specularShininess = shininess; +material.specularStrength = specularStrength;`,lights_phong_pars_fragment:`varying vec3 vViewPosition; +struct BlinnPhongMaterial { + vec3 diffuseColor; + vec3 specularColor; + float specularShininess; + float specularStrength; +}; +void RE_Direct_BlinnPhong( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) { + float dotNL = saturate( dot( geometryNormal, directLight.direction ) ); + vec3 irradiance = dotNL * directLight.color; + reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); + reflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometryViewDir, geometryNormal, material.specularColor, material.specularShininess ) * material.specularStrength; +} +void RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) { + reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); +} +#define RE_Direct RE_Direct_BlinnPhong +#define RE_IndirectDiffuse RE_IndirectDiffuse_BlinnPhong`,lights_physical_fragment:`PhysicalMaterial material; +material.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor ); +vec3 dxy = max( abs( dFdx( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) ); +float geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z ); +material.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness; +material.roughness = min( material.roughness, 1.0 ); +#ifdef IOR + material.ior = ior; + #ifdef USE_SPECULAR + float specularIntensityFactor = specularIntensity; + vec3 specularColorFactor = specularColor; + #ifdef USE_SPECULAR_COLORMAP + specularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb; + #endif + #ifdef USE_SPECULAR_INTENSITYMAP + specularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a; + #endif + material.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor ); + #else + float specularIntensityFactor = 1.0; + vec3 specularColorFactor = vec3( 1.0 ); + material.specularF90 = 1.0; + #endif + material.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor ); +#else + material.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor ); + material.specularF90 = 1.0; +#endif +#ifdef USE_CLEARCOAT + material.clearcoat = clearcoat; + material.clearcoatRoughness = clearcoatRoughness; + material.clearcoatF0 = vec3( 0.04 ); + material.clearcoatF90 = 1.0; + #ifdef USE_CLEARCOATMAP + material.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x; + #endif + #ifdef USE_CLEARCOAT_ROUGHNESSMAP + material.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y; + #endif + material.clearcoat = saturate( material.clearcoat ); material.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 ); + material.clearcoatRoughness += geometryRoughness; + material.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 ); +#endif +#ifdef USE_DISPERSION + material.dispersion = dispersion; +#endif +#ifdef USE_IRIDESCENCE + material.iridescence = iridescence; + material.iridescenceIOR = iridescenceIOR; + #ifdef USE_IRIDESCENCEMAP + material.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r; + #endif + #ifdef USE_IRIDESCENCE_THICKNESSMAP + material.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum; + #else + material.iridescenceThickness = iridescenceThicknessMaximum; + #endif +#endif +#ifdef USE_SHEEN + material.sheenColor = sheenColor; + #ifdef USE_SHEEN_COLORMAP + material.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb; + #endif + material.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 ); + #ifdef USE_SHEEN_ROUGHNESSMAP + material.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a; + #endif +#endif +#ifdef USE_ANISOTROPY + #ifdef USE_ANISOTROPYMAP + mat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x ); + vec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb; + vec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b; + #else + vec2 anisotropyV = anisotropyVector; + #endif + material.anisotropy = length( anisotropyV ); + if( material.anisotropy == 0.0 ) { + anisotropyV = vec2( 1.0, 0.0 ); + } else { + anisotropyV /= material.anisotropy; + material.anisotropy = saturate( material.anisotropy ); + } + material.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) ); + material.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y; + material.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y; +#endif`,lights_physical_pars_fragment:`struct PhysicalMaterial { + vec3 diffuseColor; + float roughness; + vec3 specularColor; + float specularF90; + float dispersion; + #ifdef USE_CLEARCOAT + float clearcoat; + float clearcoatRoughness; + vec3 clearcoatF0; + float clearcoatF90; + #endif + #ifdef USE_IRIDESCENCE + float iridescence; + float iridescenceIOR; + float iridescenceThickness; + vec3 iridescenceFresnel; + vec3 iridescenceF0; + #endif + #ifdef USE_SHEEN + vec3 sheenColor; + float sheenRoughness; + #endif + #ifdef IOR + float ior; + #endif + #ifdef USE_TRANSMISSION + float transmission; + float transmissionAlpha; + float thickness; + float attenuationDistance; + vec3 attenuationColor; + #endif + #ifdef USE_ANISOTROPY + float anisotropy; + float alphaT; + vec3 anisotropyT; + vec3 anisotropyB; + #endif +}; +vec3 clearcoatSpecularDirect = vec3( 0.0 ); +vec3 clearcoatSpecularIndirect = vec3( 0.0 ); +vec3 sheenSpecularDirect = vec3( 0.0 ); +vec3 sheenSpecularIndirect = vec3(0.0 ); +vec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) { + float x = clamp( 1.0 - dotVH, 0.0, 1.0 ); + float x2 = x * x; + float x5 = clamp( x * x2 * x2, 0.0, 0.9999 ); + return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 ); +} +float V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) { + float a2 = pow2( alpha ); + float gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) ); + float gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) ); + return 0.5 / max( gv + gl, EPSILON ); +} +float D_GGX( const in float alpha, const in float dotNH ) { + float a2 = pow2( alpha ); + float denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0; + return RECIPROCAL_PI * a2 / pow2( denom ); +} +#ifdef USE_ANISOTROPY + float V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) { + float gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) ); + float gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) ); + float v = 0.5 / ( gv + gl ); + return saturate(v); + } + float D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) { + float a2 = alphaT * alphaB; + highp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH ); + highp float v2 = dot( v, v ); + float w2 = a2 / v2; + return RECIPROCAL_PI * a2 * pow2 ( w2 ); + } +#endif +#ifdef USE_CLEARCOAT + vec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) { + vec3 f0 = material.clearcoatF0; + float f90 = material.clearcoatF90; + float roughness = material.clearcoatRoughness; + float alpha = pow2( roughness ); + vec3 halfDir = normalize( lightDir + viewDir ); + float dotNL = saturate( dot( normal, lightDir ) ); + float dotNV = saturate( dot( normal, viewDir ) ); + float dotNH = saturate( dot( normal, halfDir ) ); + float dotVH = saturate( dot( viewDir, halfDir ) ); + vec3 F = F_Schlick( f0, f90, dotVH ); + float V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV ); + float D = D_GGX( alpha, dotNH ); + return F * ( V * D ); + } +#endif +vec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) { + vec3 f0 = material.specularColor; + float f90 = material.specularF90; + float roughness = material.roughness; + float alpha = pow2( roughness ); + vec3 halfDir = normalize( lightDir + viewDir ); + float dotNL = saturate( dot( normal, lightDir ) ); + float dotNV = saturate( dot( normal, viewDir ) ); + float dotNH = saturate( dot( normal, halfDir ) ); + float dotVH = saturate( dot( viewDir, halfDir ) ); + vec3 F = F_Schlick( f0, f90, dotVH ); + #ifdef USE_IRIDESCENCE + F = mix( F, material.iridescenceFresnel, material.iridescence ); + #endif + #ifdef USE_ANISOTROPY + float dotTL = dot( material.anisotropyT, lightDir ); + float dotTV = dot( material.anisotropyT, viewDir ); + float dotTH = dot( material.anisotropyT, halfDir ); + float dotBL = dot( material.anisotropyB, lightDir ); + float dotBV = dot( material.anisotropyB, viewDir ); + float dotBH = dot( material.anisotropyB, halfDir ); + float V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL ); + float D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH ); + #else + float V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV ); + float D = D_GGX( alpha, dotNH ); + #endif + return F * ( V * D ); +} +vec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) { + const float LUT_SIZE = 64.0; + const float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE; + const float LUT_BIAS = 0.5 / LUT_SIZE; + float dotNV = saturate( dot( N, V ) ); + vec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) ); + uv = uv * LUT_SCALE + LUT_BIAS; + return uv; +} +float LTC_ClippedSphereFormFactor( const in vec3 f ) { + float l = length( f ); + return max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 ); +} +vec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) { + float x = dot( v1, v2 ); + float y = abs( x ); + float a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y; + float b = 3.4175940 + ( 4.1616724 + y ) * y; + float v = a / b; + float theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v; + return cross( v1, v2 ) * theta_sintheta; +} +vec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) { + vec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ]; + vec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ]; + vec3 lightNormal = cross( v1, v2 ); + if( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 ); + vec3 T1, T2; + T1 = normalize( V - N * dot( V, N ) ); + T2 = - cross( N, T1 ); + mat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) ); + vec3 coords[ 4 ]; + coords[ 0 ] = mat * ( rectCoords[ 0 ] - P ); + coords[ 1 ] = mat * ( rectCoords[ 1 ] - P ); + coords[ 2 ] = mat * ( rectCoords[ 2 ] - P ); + coords[ 3 ] = mat * ( rectCoords[ 3 ] - P ); + coords[ 0 ] = normalize( coords[ 0 ] ); + coords[ 1 ] = normalize( coords[ 1 ] ); + coords[ 2 ] = normalize( coords[ 2 ] ); + coords[ 3 ] = normalize( coords[ 3 ] ); + vec3 vectorFormFactor = vec3( 0.0 ); + vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] ); + vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] ); + vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] ); + vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] ); + float result = LTC_ClippedSphereFormFactor( vectorFormFactor ); + return vec3( result ); +} +#if defined( USE_SHEEN ) +float D_Charlie( float roughness, float dotNH ) { + float alpha = pow2( roughness ); + float invAlpha = 1.0 / alpha; + float cos2h = dotNH * dotNH; + float sin2h = max( 1.0 - cos2h, 0.0078125 ); + return ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI ); +} +float V_Neubelt( float dotNV, float dotNL ) { + return saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) ); +} +vec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) { + vec3 halfDir = normalize( lightDir + viewDir ); + float dotNL = saturate( dot( normal, lightDir ) ); + float dotNV = saturate( dot( normal, viewDir ) ); + float dotNH = saturate( dot( normal, halfDir ) ); + float D = D_Charlie( sheenRoughness, dotNH ); + float V = V_Neubelt( dotNV, dotNL ); + return sheenColor * ( D * V ); +} +#endif +float IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) { + float dotNV = saturate( dot( normal, viewDir ) ); + float r2 = roughness * roughness; + float a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95; + float b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72; + float DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) ); + return saturate( DG * RECIPROCAL_PI ); +} +vec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) { + float dotNV = saturate( dot( normal, viewDir ) ); + const vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 ); + const vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 ); + vec4 r = roughness * c0 + c1; + float a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y; + vec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw; + return fab; +} +vec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) { + vec2 fab = DFGApprox( normal, viewDir, roughness ); + return specularColor * fab.x + specularF90 * fab.y; +} +#ifdef USE_IRIDESCENCE +void computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) { +#else +void computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) { +#endif + vec2 fab = DFGApprox( normal, viewDir, roughness ); + #ifdef USE_IRIDESCENCE + vec3 Fr = mix( specularColor, iridescenceF0, iridescence ); + #else + vec3 Fr = specularColor; + #endif + vec3 FssEss = Fr * fab.x + specularF90 * fab.y; + float Ess = fab.x + fab.y; + float Ems = 1.0 - Ess; + vec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619; vec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg ); + singleScatter += FssEss; + multiScatter += Fms * Ems; +} +#if NUM_RECT_AREA_LIGHTS > 0 + void RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) { + vec3 normal = geometryNormal; + vec3 viewDir = geometryViewDir; + vec3 position = geometryPosition; + vec3 lightPos = rectAreaLight.position; + vec3 halfWidth = rectAreaLight.halfWidth; + vec3 halfHeight = rectAreaLight.halfHeight; + vec3 lightColor = rectAreaLight.color; + float roughness = material.roughness; + vec3 rectCoords[ 4 ]; + rectCoords[ 0 ] = lightPos + halfWidth - halfHeight; rectCoords[ 1 ] = lightPos - halfWidth - halfHeight; + rectCoords[ 2 ] = lightPos - halfWidth + halfHeight; + rectCoords[ 3 ] = lightPos + halfWidth + halfHeight; + vec2 uv = LTC_Uv( normal, viewDir, roughness ); + vec4 t1 = texture2D( ltc_1, uv ); + vec4 t2 = texture2D( ltc_2, uv ); + mat3 mInv = mat3( + vec3( t1.x, 0, t1.y ), + vec3( 0, 1, 0 ), + vec3( t1.z, 0, t1.w ) + ); + vec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y ); + reflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords ); + reflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords ); + } +#endif +void RE_Direct_Physical( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) { + float dotNL = saturate( dot( geometryNormal, directLight.direction ) ); + vec3 irradiance = dotNL * directLight.color; + #ifdef USE_CLEARCOAT + float dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) ); + vec3 ccIrradiance = dotNLcc * directLight.color; + clearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material ); + #endif + #ifdef USE_SHEEN + sheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness ); + #endif + reflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometryViewDir, geometryNormal, material ); + reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); +} +void RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) { + reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); +} +void RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) { + #ifdef USE_CLEARCOAT + clearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness ); + #endif + #ifdef USE_SHEEN + sheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness ); + #endif + vec3 singleScattering = vec3( 0.0 ); + vec3 multiScattering = vec3( 0.0 ); + vec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI; + #ifdef USE_IRIDESCENCE + computeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering ); + #else + computeMultiscattering( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering ); + #endif + vec3 totalScattering = singleScattering + multiScattering; + vec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) ); + reflectedLight.indirectSpecular += radiance * singleScattering; + reflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance; + reflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance; +} +#define RE_Direct RE_Direct_Physical +#define RE_Direct_RectArea RE_Direct_RectArea_Physical +#define RE_IndirectDiffuse RE_IndirectDiffuse_Physical +#define RE_IndirectSpecular RE_IndirectSpecular_Physical +float computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) { + return saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion ); +}`,lights_fragment_begin:` +vec3 geometryPosition = - vViewPosition; +vec3 geometryNormal = normal; +vec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition ); +vec3 geometryClearcoatNormal = vec3( 0.0 ); +#ifdef USE_CLEARCOAT + geometryClearcoatNormal = clearcoatNormal; +#endif +#ifdef USE_IRIDESCENCE + float dotNVi = saturate( dot( normal, geometryViewDir ) ); + if ( material.iridescenceThickness == 0.0 ) { + material.iridescence = 0.0; + } else { + material.iridescence = saturate( material.iridescence ); + } + if ( material.iridescence > 0.0 ) { + material.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor ); + material.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi ); + } +#endif +IncidentLight directLight; +#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct ) + PointLight pointLight; + #if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0 + PointLightShadow pointLightShadow; + #endif + #pragma unroll_loop_start + for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) { + pointLight = pointLights[ i ]; + getPointLightInfo( pointLight, geometryPosition, directLight ); + #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS ) + pointLightShadow = pointLightShadows[ i ]; + directLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowIntensity, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0; + #endif + RE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); + } + #pragma unroll_loop_end +#endif +#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct ) + SpotLight spotLight; + vec4 spotColor; + vec3 spotLightCoord; + bool inSpotLightMap; + #if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0 + SpotLightShadow spotLightShadow; + #endif + #pragma unroll_loop_start + for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) { + spotLight = spotLights[ i ]; + getSpotLightInfo( spotLight, geometryPosition, directLight ); + #if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS ) + #define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX + #elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS ) + #define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS + #else + #define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS ) + #endif + #if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS ) + spotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w; + inSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) ); + spotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy ); + directLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color; + #endif + #undef SPOT_LIGHT_MAP_INDEX + #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS ) + spotLightShadow = spotLightShadows[ i ]; + directLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowIntensity, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0; + #endif + RE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); + } + #pragma unroll_loop_end +#endif +#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct ) + DirectionalLight directionalLight; + #if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0 + DirectionalLightShadow directionalLightShadow; + #endif + #pragma unroll_loop_start + for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) { + directionalLight = directionalLights[ i ]; + getDirectionalLightInfo( directionalLight, directLight ); + #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS ) + directionalLightShadow = directionalLightShadows[ i ]; + directLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowIntensity, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0; + #endif + RE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); + } + #pragma unroll_loop_end +#endif +#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea ) + RectAreaLight rectAreaLight; + #pragma unroll_loop_start + for ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) { + rectAreaLight = rectAreaLights[ i ]; + RE_Direct_RectArea( rectAreaLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); + } + #pragma unroll_loop_end +#endif +#if defined( RE_IndirectDiffuse ) + vec3 iblIrradiance = vec3( 0.0 ); + vec3 irradiance = getAmbientLightIrradiance( ambientLightColor ); + #if defined( USE_LIGHT_PROBES ) + irradiance += getLightProbeIrradiance( lightProbe, geometryNormal ); + #endif + #if ( NUM_HEMI_LIGHTS > 0 ) + #pragma unroll_loop_start + for ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) { + irradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometryNormal ); + } + #pragma unroll_loop_end + #endif +#endif +#if defined( RE_IndirectSpecular ) + vec3 radiance = vec3( 0.0 ); + vec3 clearcoatRadiance = vec3( 0.0 ); +#endif`,lights_fragment_maps:`#if defined( RE_IndirectDiffuse ) + #ifdef USE_LIGHTMAP + vec4 lightMapTexel = texture2D( lightMap, vLightMapUv ); + vec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity; + irradiance += lightMapIrradiance; + #endif + #if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV ) + iblIrradiance += getIBLIrradiance( geometryNormal ); + #endif +#endif +#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular ) + #ifdef USE_ANISOTROPY + radiance += getIBLAnisotropyRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy ); + #else + radiance += getIBLRadiance( geometryViewDir, geometryNormal, material.roughness ); + #endif + #ifdef USE_CLEARCOAT + clearcoatRadiance += getIBLRadiance( geometryViewDir, geometryClearcoatNormal, material.clearcoatRoughness ); + #endif +#endif`,lights_fragment_end:`#if defined( RE_IndirectDiffuse ) + RE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); +#endif +#if defined( RE_IndirectSpecular ) + RE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); +#endif`,logdepthbuf_fragment:`#if defined( USE_LOGDEPTHBUF ) + gl_FragDepth = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5; +#endif`,logdepthbuf_pars_fragment:`#if defined( USE_LOGDEPTHBUF ) + uniform float logDepthBufFC; + varying float vFragDepth; + varying float vIsPerspective; +#endif`,logdepthbuf_pars_vertex:`#ifdef USE_LOGDEPTHBUF + varying float vFragDepth; + varying float vIsPerspective; +#endif`,logdepthbuf_vertex:`#ifdef USE_LOGDEPTHBUF + vFragDepth = 1.0 + gl_Position.w; + vIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) ); +#endif`,map_fragment:`#ifdef USE_MAP + vec4 sampledDiffuseColor = texture2D( map, vMapUv ); + #ifdef DECODE_VIDEO_TEXTURE + sampledDiffuseColor = vec4( mix( pow( sampledDiffuseColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), sampledDiffuseColor.rgb * 0.0773993808, vec3( lessThanEqual( sampledDiffuseColor.rgb, vec3( 0.04045 ) ) ) ), sampledDiffuseColor.w ); + + #endif + diffuseColor *= sampledDiffuseColor; +#endif`,map_pars_fragment:`#ifdef USE_MAP + uniform sampler2D map; +#endif`,map_particle_fragment:`#if defined( USE_MAP ) || defined( USE_ALPHAMAP ) + #if defined( USE_POINTS_UV ) + vec2 uv = vUv; + #else + vec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy; + #endif +#endif +#ifdef USE_MAP + diffuseColor *= texture2D( map, uv ); +#endif +#ifdef USE_ALPHAMAP + diffuseColor.a *= texture2D( alphaMap, uv ).g; +#endif`,map_particle_pars_fragment:`#if defined( USE_POINTS_UV ) + varying vec2 vUv; +#else + #if defined( USE_MAP ) || defined( USE_ALPHAMAP ) + uniform mat3 uvTransform; + #endif +#endif +#ifdef USE_MAP + uniform sampler2D map; +#endif +#ifdef USE_ALPHAMAP + uniform sampler2D alphaMap; +#endif`,metalnessmap_fragment:`float metalnessFactor = metalness; +#ifdef USE_METALNESSMAP + vec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv ); + metalnessFactor *= texelMetalness.b; +#endif`,metalnessmap_pars_fragment:`#ifdef USE_METALNESSMAP + uniform sampler2D metalnessMap; +#endif`,morphinstance_vertex:`#ifdef USE_INSTANCING_MORPH + float morphTargetInfluences[ MORPHTARGETS_COUNT ]; + float morphTargetBaseInfluence = texelFetch( morphTexture, ivec2( 0, gl_InstanceID ), 0 ).r; + for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) { + morphTargetInfluences[i] = texelFetch( morphTexture, ivec2( i + 1, gl_InstanceID ), 0 ).r; + } +#endif`,morphcolor_vertex:`#if defined( USE_MORPHCOLORS ) + vColor *= morphTargetBaseInfluence; + for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) { + #if defined( USE_COLOR_ALPHA ) + if ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ]; + #elif defined( USE_COLOR ) + if ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ]; + #endif + } +#endif`,morphnormal_vertex:`#ifdef USE_MORPHNORMALS + objectNormal *= morphTargetBaseInfluence; + for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) { + if ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ]; + } +#endif`,morphtarget_pars_vertex:`#ifdef USE_MORPHTARGETS + #ifndef USE_INSTANCING_MORPH + uniform float morphTargetBaseInfluence; + uniform float morphTargetInfluences[ MORPHTARGETS_COUNT ]; + #endif + uniform sampler2DArray morphTargetsTexture; + uniform ivec2 morphTargetsTextureSize; + vec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) { + int texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset; + int y = texelIndex / morphTargetsTextureSize.x; + int x = texelIndex - y * morphTargetsTextureSize.x; + ivec3 morphUV = ivec3( x, y, morphTargetIndex ); + return texelFetch( morphTargetsTexture, morphUV, 0 ); + } +#endif`,morphtarget_vertex:`#ifdef USE_MORPHTARGETS + transformed *= morphTargetBaseInfluence; + for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) { + if ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ]; + } +#endif`,normal_fragment_begin:`float faceDirection = gl_FrontFacing ? 1.0 : - 1.0; +#ifdef FLAT_SHADED + vec3 fdx = dFdx( vViewPosition ); + vec3 fdy = dFdy( vViewPosition ); + vec3 normal = normalize( cross( fdx, fdy ) ); +#else + vec3 normal = normalize( vNormal ); + #ifdef DOUBLE_SIDED + normal *= faceDirection; + #endif +#endif +#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) + #ifdef USE_TANGENT + mat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal ); + #else + mat3 tbn = getTangentFrame( - vViewPosition, normal, + #if defined( USE_NORMALMAP ) + vNormalMapUv + #elif defined( USE_CLEARCOAT_NORMALMAP ) + vClearcoatNormalMapUv + #else + vUv + #endif + ); + #endif + #if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED ) + tbn[0] *= faceDirection; + tbn[1] *= faceDirection; + #endif +#endif +#ifdef USE_CLEARCOAT_NORMALMAP + #ifdef USE_TANGENT + mat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal ); + #else + mat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv ); + #endif + #if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED ) + tbn2[0] *= faceDirection; + tbn2[1] *= faceDirection; + #endif +#endif +vec3 nonPerturbedNormal = normal;`,normal_fragment_maps:`#ifdef USE_NORMALMAP_OBJECTSPACE + normal = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0; + #ifdef FLIP_SIDED + normal = - normal; + #endif + #ifdef DOUBLE_SIDED + normal = normal * faceDirection; + #endif + normal = normalize( normalMatrix * normal ); +#elif defined( USE_NORMALMAP_TANGENTSPACE ) + vec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0; + mapN.xy *= normalScale; + normal = normalize( tbn * mapN ); +#elif defined( USE_BUMPMAP ) + normal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection ); +#endif`,normal_pars_fragment:`#ifndef FLAT_SHADED + varying vec3 vNormal; + #ifdef USE_TANGENT + varying vec3 vTangent; + varying vec3 vBitangent; + #endif +#endif`,normal_pars_vertex:`#ifndef FLAT_SHADED + varying vec3 vNormal; + #ifdef USE_TANGENT + varying vec3 vTangent; + varying vec3 vBitangent; + #endif +#endif`,normal_vertex:`#ifndef FLAT_SHADED + vNormal = normalize( transformedNormal ); + #ifdef USE_TANGENT + vTangent = normalize( transformedTangent ); + vBitangent = normalize( cross( vNormal, vTangent ) * tangent.w ); + #endif +#endif`,normalmap_pars_fragment:`#ifdef USE_NORMALMAP + uniform sampler2D normalMap; + uniform vec2 normalScale; +#endif +#ifdef USE_NORMALMAP_OBJECTSPACE + uniform mat3 normalMatrix; +#endif +#if ! defined ( USE_TANGENT ) && ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) ) + mat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) { + vec3 q0 = dFdx( eye_pos.xyz ); + vec3 q1 = dFdy( eye_pos.xyz ); + vec2 st0 = dFdx( uv.st ); + vec2 st1 = dFdy( uv.st ); + vec3 N = surf_norm; + vec3 q1perp = cross( q1, N ); + vec3 q0perp = cross( N, q0 ); + vec3 T = q1perp * st0.x + q0perp * st1.x; + vec3 B = q1perp * st0.y + q0perp * st1.y; + float det = max( dot( T, T ), dot( B, B ) ); + float scale = ( det == 0.0 ) ? 0.0 : inversesqrt( det ); + return mat3( T * scale, B * scale, N ); + } +#endif`,clearcoat_normal_fragment_begin:`#ifdef USE_CLEARCOAT + vec3 clearcoatNormal = nonPerturbedNormal; +#endif`,clearcoat_normal_fragment_maps:`#ifdef USE_CLEARCOAT_NORMALMAP + vec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0; + clearcoatMapN.xy *= clearcoatNormalScale; + clearcoatNormal = normalize( tbn2 * clearcoatMapN ); +#endif`,clearcoat_pars_fragment:`#ifdef USE_CLEARCOATMAP + uniform sampler2D clearcoatMap; +#endif +#ifdef USE_CLEARCOAT_NORMALMAP + uniform sampler2D clearcoatNormalMap; + uniform vec2 clearcoatNormalScale; +#endif +#ifdef USE_CLEARCOAT_ROUGHNESSMAP + uniform sampler2D clearcoatRoughnessMap; +#endif`,iridescence_pars_fragment:`#ifdef USE_IRIDESCENCEMAP + uniform sampler2D iridescenceMap; +#endif +#ifdef USE_IRIDESCENCE_THICKNESSMAP + uniform sampler2D iridescenceThicknessMap; +#endif`,opaque_fragment:`#ifdef OPAQUE +diffuseColor.a = 1.0; +#endif +#ifdef USE_TRANSMISSION +diffuseColor.a *= material.transmissionAlpha; +#endif +gl_FragColor = vec4( outgoingLight, diffuseColor.a );`,packing:`vec3 packNormalToRGB( const in vec3 normal ) { + return normalize( normal ) * 0.5 + 0.5; +} +vec3 unpackRGBToNormal( const in vec3 rgb ) { + return 2.0 * rgb.xyz - 1.0; +} +const float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;const float ShiftRight8 = 1. / 256.; +const float Inv255 = 1. / 255.; +const vec4 PackFactors = vec4( 1.0, 256.0, 256.0 * 256.0, 256.0 * 256.0 * 256.0 ); +const vec2 UnpackFactors2 = vec2( UnpackDownscale, 1.0 / PackFactors.g ); +const vec3 UnpackFactors3 = vec3( UnpackDownscale / PackFactors.rg, 1.0 / PackFactors.b ); +const vec4 UnpackFactors4 = vec4( UnpackDownscale / PackFactors.rgb, 1.0 / PackFactors.a ); +vec4 packDepthToRGBA( const in float v ) { + if( v <= 0.0 ) + return vec4( 0., 0., 0., 0. ); + if( v >= 1.0 ) + return vec4( 1., 1., 1., 1. ); + float vuf; + float af = modf( v * PackFactors.a, vuf ); + float bf = modf( vuf * ShiftRight8, vuf ); + float gf = modf( vuf * ShiftRight8, vuf ); + return vec4( vuf * Inv255, gf * PackUpscale, bf * PackUpscale, af ); +} +vec3 packDepthToRGB( const in float v ) { + if( v <= 0.0 ) + return vec3( 0., 0., 0. ); + if( v >= 1.0 ) + return vec3( 1., 1., 1. ); + float vuf; + float bf = modf( v * PackFactors.b, vuf ); + float gf = modf( vuf * ShiftRight8, vuf ); + return vec3( vuf * Inv255, gf * PackUpscale, bf ); +} +vec2 packDepthToRG( const in float v ) { + if( v <= 0.0 ) + return vec2( 0., 0. ); + if( v >= 1.0 ) + return vec2( 1., 1. ); + float vuf; + float gf = modf( v * 256., vuf ); + return vec2( vuf * Inv255, gf ); +} +float unpackRGBAToDepth( const in vec4 v ) { + return dot( v, UnpackFactors4 ); +} +float unpackRGBToDepth( const in vec3 v ) { + return dot( v, UnpackFactors3 ); +} +float unpackRGToDepth( const in vec2 v ) { + return v.r * UnpackFactors2.r + v.g * UnpackFactors2.g; +} +vec4 pack2HalfToRGBA( const in vec2 v ) { + vec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) ); + return vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w ); +} +vec2 unpackRGBATo2Half( const in vec4 v ) { + return vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) ); +} +float viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) { + return ( viewZ + near ) / ( near - far ); +} +float orthographicDepthToViewZ( const in float depth, const in float near, const in float far ) { + return depth * ( near - far ) - near; +} +float viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) { + return ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ ); +} +float perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) { + return ( near * far ) / ( ( far - near ) * depth - far ); +}`,premultiplied_alpha_fragment:`#ifdef PREMULTIPLIED_ALPHA + gl_FragColor.rgb *= gl_FragColor.a; +#endif`,project_vertex:`vec4 mvPosition = vec4( transformed, 1.0 ); +#ifdef USE_BATCHING + mvPosition = batchingMatrix * mvPosition; +#endif +#ifdef USE_INSTANCING + mvPosition = instanceMatrix * mvPosition; +#endif +mvPosition = modelViewMatrix * mvPosition; +gl_Position = projectionMatrix * mvPosition;`,dithering_fragment:`#ifdef DITHERING + gl_FragColor.rgb = dithering( gl_FragColor.rgb ); +#endif`,dithering_pars_fragment:`#ifdef DITHERING + vec3 dithering( vec3 color ) { + float grid_position = rand( gl_FragCoord.xy ); + vec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 ); + dither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position ); + return color + dither_shift_RGB; + } +#endif`,roughnessmap_fragment:`float roughnessFactor = roughness; +#ifdef USE_ROUGHNESSMAP + vec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv ); + roughnessFactor *= texelRoughness.g; +#endif`,roughnessmap_pars_fragment:`#ifdef USE_ROUGHNESSMAP + uniform sampler2D roughnessMap; +#endif`,shadowmap_pars_fragment:`#if NUM_SPOT_LIGHT_COORDS > 0 + varying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ]; +#endif +#if NUM_SPOT_LIGHT_MAPS > 0 + uniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ]; +#endif +#ifdef USE_SHADOWMAP + #if NUM_DIR_LIGHT_SHADOWS > 0 + uniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ]; + varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ]; + struct DirectionalLightShadow { + float shadowIntensity; + float shadowBias; + float shadowNormalBias; + float shadowRadius; + vec2 shadowMapSize; + }; + uniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ]; + #endif + #if NUM_SPOT_LIGHT_SHADOWS > 0 + uniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ]; + struct SpotLightShadow { + float shadowIntensity; + float shadowBias; + float shadowNormalBias; + float shadowRadius; + vec2 shadowMapSize; + }; + uniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ]; + #endif + #if NUM_POINT_LIGHT_SHADOWS > 0 + uniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ]; + varying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ]; + struct PointLightShadow { + float shadowIntensity; + float shadowBias; + float shadowNormalBias; + float shadowRadius; + vec2 shadowMapSize; + float shadowCameraNear; + float shadowCameraFar; + }; + uniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ]; + #endif + float texture2DCompare( sampler2D depths, vec2 uv, float compare ) { + return step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) ); + } + vec2 texture2DDistribution( sampler2D shadow, vec2 uv ) { + return unpackRGBATo2Half( texture2D( shadow, uv ) ); + } + float VSMShadow (sampler2D shadow, vec2 uv, float compare ){ + float occlusion = 1.0; + vec2 distribution = texture2DDistribution( shadow, uv ); + float hard_shadow = step( compare , distribution.x ); + if (hard_shadow != 1.0 ) { + float distance = compare - distribution.x ; + float variance = max( 0.00000, distribution.y * distribution.y ); + float softness_probability = variance / (variance + distance * distance ); softness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 ); occlusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 ); + } + return occlusion; + } + float getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) { + float shadow = 1.0; + shadowCoord.xyz /= shadowCoord.w; + shadowCoord.z += shadowBias; + bool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0; + bool frustumTest = inFrustum && shadowCoord.z <= 1.0; + if ( frustumTest ) { + #if defined( SHADOWMAP_TYPE_PCF ) + vec2 texelSize = vec2( 1.0 ) / shadowMapSize; + float dx0 = - texelSize.x * shadowRadius; + float dy0 = - texelSize.y * shadowRadius; + float dx1 = + texelSize.x * shadowRadius; + float dy1 = + texelSize.y * shadowRadius; + float dx2 = dx0 / 2.0; + float dy2 = dy0 / 2.0; + float dx3 = dx1 / 2.0; + float dy3 = dy1 / 2.0; + shadow = ( + texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) + + texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z ) + ) * ( 1.0 / 17.0 ); + #elif defined( SHADOWMAP_TYPE_PCF_SOFT ) + vec2 texelSize = vec2( 1.0 ) / shadowMapSize; + float dx = texelSize.x; + float dy = texelSize.y; + vec2 uv = shadowCoord.xy; + vec2 f = fract( uv * shadowMapSize + 0.5 ); + uv -= f * texelSize; + shadow = ( + texture2DCompare( shadowMap, uv, shadowCoord.z ) + + texture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) + + texture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) + + texture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) + + mix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ), + texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ), + f.x ) + + mix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ), + texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ), + f.x ) + + mix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ), + texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ), + f.y ) + + mix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ), + texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ), + f.y ) + + mix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ), + texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ), + f.x ), + mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ), + texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ), + f.x ), + f.y ) + ) * ( 1.0 / 9.0 ); + #elif defined( SHADOWMAP_TYPE_VSM ) + shadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z ); + #else + shadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ); + #endif + } + return mix( 1.0, shadow, shadowIntensity ); + } + vec2 cubeToUV( vec3 v, float texelSizeY ) { + vec3 absV = abs( v ); + float scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) ); + absV *= scaleToCube; + v *= scaleToCube * ( 1.0 - 2.0 * texelSizeY ); + vec2 planar = v.xy; + float almostATexel = 1.5 * texelSizeY; + float almostOne = 1.0 - almostATexel; + if ( absV.z >= almostOne ) { + if ( v.z > 0.0 ) + planar.x = 4.0 - v.x; + } else if ( absV.x >= almostOne ) { + float signX = sign( v.x ); + planar.x = v.z * signX + 2.0 * signX; + } else if ( absV.y >= almostOne ) { + float signY = sign( v.y ); + planar.x = v.x + 2.0 * signY + 2.0; + planar.y = v.z * signY - 2.0; + } + return vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 ); + } + float getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) { + float shadow = 1.0; + vec3 lightToPosition = shadowCoord.xyz; + + float lightToPositionLength = length( lightToPosition ); + if ( lightToPositionLength - shadowCameraFar <= 0.0 && lightToPositionLength - shadowCameraNear >= 0.0 ) { + float dp = ( lightToPositionLength - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear ); dp += shadowBias; + vec3 bd3D = normalize( lightToPosition ); + vec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) ); + #if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM ) + vec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y; + shadow = ( + texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) + + texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) + + texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) + + texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) + + texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) + + texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) + + texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) + + texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) + + texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp ) + ) * ( 1.0 / 9.0 ); + #else + shadow = texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ); + #endif + } + return mix( 1.0, shadow, shadowIntensity ); + } +#endif`,shadowmap_pars_vertex:`#if NUM_SPOT_LIGHT_COORDS > 0 + uniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ]; + varying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ]; +#endif +#ifdef USE_SHADOWMAP + #if NUM_DIR_LIGHT_SHADOWS > 0 + uniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ]; + varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ]; + struct DirectionalLightShadow { + float shadowIntensity; + float shadowBias; + float shadowNormalBias; + float shadowRadius; + vec2 shadowMapSize; + }; + uniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ]; + #endif + #if NUM_SPOT_LIGHT_SHADOWS > 0 + struct SpotLightShadow { + float shadowIntensity; + float shadowBias; + float shadowNormalBias; + float shadowRadius; + vec2 shadowMapSize; + }; + uniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ]; + #endif + #if NUM_POINT_LIGHT_SHADOWS > 0 + uniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ]; + varying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ]; + struct PointLightShadow { + float shadowIntensity; + float shadowBias; + float shadowNormalBias; + float shadowRadius; + vec2 shadowMapSize; + float shadowCameraNear; + float shadowCameraFar; + }; + uniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ]; + #endif +#endif`,shadowmap_vertex:`#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 ) + vec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix ); + vec4 shadowWorldPosition; +#endif +#if defined( USE_SHADOWMAP ) + #if NUM_DIR_LIGHT_SHADOWS > 0 + #pragma unroll_loop_start + for ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) { + shadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 ); + vDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition; + } + #pragma unroll_loop_end + #endif + #if NUM_POINT_LIGHT_SHADOWS > 0 + #pragma unroll_loop_start + for ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) { + shadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 ); + vPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition; + } + #pragma unroll_loop_end + #endif +#endif +#if NUM_SPOT_LIGHT_COORDS > 0 + #pragma unroll_loop_start + for ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) { + shadowWorldPosition = worldPosition; + #if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS ) + shadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias; + #endif + vSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition; + } + #pragma unroll_loop_end +#endif`,shadowmask_pars_fragment:`float getShadowMask() { + float shadow = 1.0; + #ifdef USE_SHADOWMAP + #if NUM_DIR_LIGHT_SHADOWS > 0 + DirectionalLightShadow directionalLight; + #pragma unroll_loop_start + for ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) { + directionalLight = directionalLightShadows[ i ]; + shadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowIntensity, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0; + } + #pragma unroll_loop_end + #endif + #if NUM_SPOT_LIGHT_SHADOWS > 0 + SpotLightShadow spotLight; + #pragma unroll_loop_start + for ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) { + spotLight = spotLightShadows[ i ]; + shadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowIntensity, spotLight.shadowBias, spotLight.shadowRadius, vSpotLightCoord[ i ] ) : 1.0; + } + #pragma unroll_loop_end + #endif + #if NUM_POINT_LIGHT_SHADOWS > 0 + PointLightShadow pointLight; + #pragma unroll_loop_start + for ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) { + pointLight = pointLightShadows[ i ]; + shadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowIntensity, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0; + } + #pragma unroll_loop_end + #endif + #endif + return shadow; +}`,skinbase_vertex:`#ifdef USE_SKINNING + mat4 boneMatX = getBoneMatrix( skinIndex.x ); + mat4 boneMatY = getBoneMatrix( skinIndex.y ); + mat4 boneMatZ = getBoneMatrix( skinIndex.z ); + mat4 boneMatW = getBoneMatrix( skinIndex.w ); +#endif`,skinning_pars_vertex:`#ifdef USE_SKINNING + uniform mat4 bindMatrix; + uniform mat4 bindMatrixInverse; + uniform highp sampler2D boneTexture; + mat4 getBoneMatrix( const in float i ) { + int size = textureSize( boneTexture, 0 ).x; + int j = int( i ) * 4; + int x = j % size; + int y = j / size; + vec4 v1 = texelFetch( boneTexture, ivec2( x, y ), 0 ); + vec4 v2 = texelFetch( boneTexture, ivec2( x + 1, y ), 0 ); + vec4 v3 = texelFetch( boneTexture, ivec2( x + 2, y ), 0 ); + vec4 v4 = texelFetch( boneTexture, ivec2( x + 3, y ), 0 ); + return mat4( v1, v2, v3, v4 ); + } +#endif`,skinning_vertex:`#ifdef USE_SKINNING + vec4 skinVertex = bindMatrix * vec4( transformed, 1.0 ); + vec4 skinned = vec4( 0.0 ); + skinned += boneMatX * skinVertex * skinWeight.x; + skinned += boneMatY * skinVertex * skinWeight.y; + skinned += boneMatZ * skinVertex * skinWeight.z; + skinned += boneMatW * skinVertex * skinWeight.w; + transformed = ( bindMatrixInverse * skinned ).xyz; +#endif`,skinnormal_vertex:`#ifdef USE_SKINNING + mat4 skinMatrix = mat4( 0.0 ); + skinMatrix += skinWeight.x * boneMatX; + skinMatrix += skinWeight.y * boneMatY; + skinMatrix += skinWeight.z * boneMatZ; + skinMatrix += skinWeight.w * boneMatW; + skinMatrix = bindMatrixInverse * skinMatrix * bindMatrix; + objectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz; + #ifdef USE_TANGENT + objectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz; + #endif +#endif`,specularmap_fragment:`float specularStrength; +#ifdef USE_SPECULARMAP + vec4 texelSpecular = texture2D( specularMap, vSpecularMapUv ); + specularStrength = texelSpecular.r; +#else + specularStrength = 1.0; +#endif`,specularmap_pars_fragment:`#ifdef USE_SPECULARMAP + uniform sampler2D specularMap; +#endif`,tonemapping_fragment:`#if defined( TONE_MAPPING ) + gl_FragColor.rgb = toneMapping( gl_FragColor.rgb ); +#endif`,tonemapping_pars_fragment:`#ifndef saturate +#define saturate( a ) clamp( a, 0.0, 1.0 ) +#endif +uniform float toneMappingExposure; +vec3 LinearToneMapping( vec3 color ) { + return saturate( toneMappingExposure * color ); +} +vec3 ReinhardToneMapping( vec3 color ) { + color *= toneMappingExposure; + return saturate( color / ( vec3( 1.0 ) + color ) ); +} +vec3 CineonToneMapping( vec3 color ) { + color *= toneMappingExposure; + color = max( vec3( 0.0 ), color - 0.004 ); + return pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) ); +} +vec3 RRTAndODTFit( vec3 v ) { + vec3 a = v * ( v + 0.0245786 ) - 0.000090537; + vec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081; + return a / b; +} +vec3 ACESFilmicToneMapping( vec3 color ) { + const mat3 ACESInputMat = mat3( + vec3( 0.59719, 0.07600, 0.02840 ), vec3( 0.35458, 0.90834, 0.13383 ), + vec3( 0.04823, 0.01566, 0.83777 ) + ); + const mat3 ACESOutputMat = mat3( + vec3( 1.60475, -0.10208, -0.00327 ), vec3( -0.53108, 1.10813, -0.07276 ), + vec3( -0.07367, -0.00605, 1.07602 ) + ); + color *= toneMappingExposure / 0.6; + color = ACESInputMat * color; + color = RRTAndODTFit( color ); + color = ACESOutputMat * color; + return saturate( color ); +} +const mat3 LINEAR_REC2020_TO_LINEAR_SRGB = mat3( + vec3( 1.6605, - 0.1246, - 0.0182 ), + vec3( - 0.5876, 1.1329, - 0.1006 ), + vec3( - 0.0728, - 0.0083, 1.1187 ) +); +const mat3 LINEAR_SRGB_TO_LINEAR_REC2020 = mat3( + vec3( 0.6274, 0.0691, 0.0164 ), + vec3( 0.3293, 0.9195, 0.0880 ), + vec3( 0.0433, 0.0113, 0.8956 ) +); +vec3 agxDefaultContrastApprox( vec3 x ) { + vec3 x2 = x * x; + vec3 x4 = x2 * x2; + return + 15.5 * x4 * x2 + - 40.14 * x4 * x + + 31.96 * x4 + - 6.868 * x2 * x + + 0.4298 * x2 + + 0.1191 * x + - 0.00232; +} +vec3 AgXToneMapping( vec3 color ) { + const mat3 AgXInsetMatrix = mat3( + vec3( 0.856627153315983, 0.137318972929847, 0.11189821299995 ), + vec3( 0.0951212405381588, 0.761241990602591, 0.0767994186031903 ), + vec3( 0.0482516061458583, 0.101439036467562, 0.811302368396859 ) + ); + const mat3 AgXOutsetMatrix = mat3( + vec3( 1.1271005818144368, - 0.1413297634984383, - 0.14132976349843826 ), + vec3( - 0.11060664309660323, 1.157823702216272, - 0.11060664309660294 ), + vec3( - 0.016493938717834573, - 0.016493938717834257, 1.2519364065950405 ) + ); + const float AgxMinEv = - 12.47393; const float AgxMaxEv = 4.026069; + color *= toneMappingExposure; + color = LINEAR_SRGB_TO_LINEAR_REC2020 * color; + color = AgXInsetMatrix * color; + color = max( color, 1e-10 ); color = log2( color ); + color = ( color - AgxMinEv ) / ( AgxMaxEv - AgxMinEv ); + color = clamp( color, 0.0, 1.0 ); + color = agxDefaultContrastApprox( color ); + color = AgXOutsetMatrix * color; + color = pow( max( vec3( 0.0 ), color ), vec3( 2.2 ) ); + color = LINEAR_REC2020_TO_LINEAR_SRGB * color; + color = clamp( color, 0.0, 1.0 ); + return color; +} +vec3 NeutralToneMapping( vec3 color ) { + const float StartCompression = 0.8 - 0.04; + const float Desaturation = 0.15; + color *= toneMappingExposure; + float x = min( color.r, min( color.g, color.b ) ); + float offset = x < 0.08 ? x - 6.25 * x * x : 0.04; + color -= offset; + float peak = max( color.r, max( color.g, color.b ) ); + if ( peak < StartCompression ) return color; + float d = 1. - StartCompression; + float newPeak = 1. - d * d / ( peak + d - StartCompression ); + color *= newPeak / peak; + float g = 1. - 1. / ( Desaturation * ( peak - newPeak ) + 1. ); + return mix( color, vec3( newPeak ), g ); +} +vec3 CustomToneMapping( vec3 color ) { return color; }`,transmission_fragment:`#ifdef USE_TRANSMISSION + material.transmission = transmission; + material.transmissionAlpha = 1.0; + material.thickness = thickness; + material.attenuationDistance = attenuationDistance; + material.attenuationColor = attenuationColor; + #ifdef USE_TRANSMISSIONMAP + material.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r; + #endif + #ifdef USE_THICKNESSMAP + material.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g; + #endif + vec3 pos = vWorldPosition; + vec3 v = normalize( cameraPosition - pos ); + vec3 n = inverseTransformDirection( normal, viewMatrix ); + vec4 transmitted = getIBLVolumeRefraction( + n, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90, + pos, modelMatrix, viewMatrix, projectionMatrix, material.dispersion, material.ior, material.thickness, + material.attenuationColor, material.attenuationDistance ); + material.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission ); + totalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission ); +#endif`,transmission_pars_fragment:`#ifdef USE_TRANSMISSION + uniform float transmission; + uniform float thickness; + uniform float attenuationDistance; + uniform vec3 attenuationColor; + #ifdef USE_TRANSMISSIONMAP + uniform sampler2D transmissionMap; + #endif + #ifdef USE_THICKNESSMAP + uniform sampler2D thicknessMap; + #endif + uniform vec2 transmissionSamplerSize; + uniform sampler2D transmissionSamplerMap; + uniform mat4 modelMatrix; + uniform mat4 projectionMatrix; + varying vec3 vWorldPosition; + float w0( float a ) { + return ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 ); + } + float w1( float a ) { + return ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 ); + } + float w2( float a ){ + return ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 ); + } + float w3( float a ) { + return ( 1.0 / 6.0 ) * ( a * a * a ); + } + float g0( float a ) { + return w0( a ) + w1( a ); + } + float g1( float a ) { + return w2( a ) + w3( a ); + } + float h0( float a ) { + return - 1.0 + w1( a ) / ( w0( a ) + w1( a ) ); + } + float h1( float a ) { + return 1.0 + w3( a ) / ( w2( a ) + w3( a ) ); + } + vec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) { + uv = uv * texelSize.zw + 0.5; + vec2 iuv = floor( uv ); + vec2 fuv = fract( uv ); + float g0x = g0( fuv.x ); + float g1x = g1( fuv.x ); + float h0x = h0( fuv.x ); + float h1x = h1( fuv.x ); + float h0y = h0( fuv.y ); + float h1y = h1( fuv.y ); + vec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy; + vec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy; + vec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy; + vec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy; + return g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) + + g1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) ); + } + vec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) { + vec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) ); + vec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) ); + vec2 fLodSizeInv = 1.0 / fLodSize; + vec2 cLodSizeInv = 1.0 / cLodSize; + vec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) ); + vec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) ); + return mix( fSample, cSample, fract( lod ) ); + } + vec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) { + vec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior ); + vec3 modelScale; + modelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) ); + modelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) ); + modelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) ); + return normalize( refractionVector ) * thickness * modelScale; + } + float applyIorToRoughness( const in float roughness, const in float ior ) { + return roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 ); + } + vec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) { + float lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior ); + return textureBicubic( transmissionSamplerMap, fragCoord.xy, lod ); + } + vec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) { + if ( isinf( attenuationDistance ) ) { + return vec3( 1.0 ); + } else { + vec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance; + vec3 transmittance = exp( - attenuationCoefficient * transmissionDistance ); return transmittance; + } + } + vec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor, + const in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix, + const in mat4 viewMatrix, const in mat4 projMatrix, const in float dispersion, const in float ior, const in float thickness, + const in vec3 attenuationColor, const in float attenuationDistance ) { + vec4 transmittedLight; + vec3 transmittance; + #ifdef USE_DISPERSION + float halfSpread = ( ior - 1.0 ) * 0.025 * dispersion; + vec3 iors = vec3( ior - halfSpread, ior, ior + halfSpread ); + for ( int i = 0; i < 3; i ++ ) { + vec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, iors[ i ], modelMatrix ); + vec3 refractedRayExit = position + transmissionRay; + + vec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 ); + vec2 refractionCoords = ndcPos.xy / ndcPos.w; + refractionCoords += 1.0; + refractionCoords /= 2.0; + + vec4 transmissionSample = getTransmissionSample( refractionCoords, roughness, iors[ i ] ); + transmittedLight[ i ] = transmissionSample[ i ]; + transmittedLight.a += transmissionSample.a; + transmittance[ i ] = diffuseColor[ i ] * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance )[ i ]; + } + transmittedLight.a /= 3.0; + + #else + + vec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix ); + vec3 refractedRayExit = position + transmissionRay; + vec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 ); + vec2 refractionCoords = ndcPos.xy / ndcPos.w; + refractionCoords += 1.0; + refractionCoords /= 2.0; + transmittedLight = getTransmissionSample( refractionCoords, roughness, ior ); + transmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance ); + + #endif + vec3 attenuatedColor = transmittance * transmittedLight.rgb; + vec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness ); + float transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0; + return vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor ); + } +#endif`,uv_pars_fragment:`#if defined( USE_UV ) || defined( USE_ANISOTROPY ) + varying vec2 vUv; +#endif +#ifdef USE_MAP + varying vec2 vMapUv; +#endif +#ifdef USE_ALPHAMAP + varying vec2 vAlphaMapUv; +#endif +#ifdef USE_LIGHTMAP + varying vec2 vLightMapUv; +#endif +#ifdef USE_AOMAP + varying vec2 vAoMapUv; +#endif +#ifdef USE_BUMPMAP + varying vec2 vBumpMapUv; +#endif +#ifdef USE_NORMALMAP + varying vec2 vNormalMapUv; +#endif +#ifdef USE_EMISSIVEMAP + varying vec2 vEmissiveMapUv; +#endif +#ifdef USE_METALNESSMAP + varying vec2 vMetalnessMapUv; +#endif +#ifdef USE_ROUGHNESSMAP + varying vec2 vRoughnessMapUv; +#endif +#ifdef USE_ANISOTROPYMAP + varying vec2 vAnisotropyMapUv; +#endif +#ifdef USE_CLEARCOATMAP + varying vec2 vClearcoatMapUv; +#endif +#ifdef USE_CLEARCOAT_NORMALMAP + varying vec2 vClearcoatNormalMapUv; +#endif +#ifdef USE_CLEARCOAT_ROUGHNESSMAP + varying vec2 vClearcoatRoughnessMapUv; +#endif +#ifdef USE_IRIDESCENCEMAP + varying vec2 vIridescenceMapUv; +#endif +#ifdef USE_IRIDESCENCE_THICKNESSMAP + varying vec2 vIridescenceThicknessMapUv; +#endif +#ifdef USE_SHEEN_COLORMAP + varying vec2 vSheenColorMapUv; +#endif +#ifdef USE_SHEEN_ROUGHNESSMAP + varying vec2 vSheenRoughnessMapUv; +#endif +#ifdef USE_SPECULARMAP + varying vec2 vSpecularMapUv; +#endif +#ifdef USE_SPECULAR_COLORMAP + varying vec2 vSpecularColorMapUv; +#endif +#ifdef USE_SPECULAR_INTENSITYMAP + varying vec2 vSpecularIntensityMapUv; +#endif +#ifdef USE_TRANSMISSIONMAP + uniform mat3 transmissionMapTransform; + varying vec2 vTransmissionMapUv; +#endif +#ifdef USE_THICKNESSMAP + uniform mat3 thicknessMapTransform; + varying vec2 vThicknessMapUv; +#endif`,uv_pars_vertex:`#if defined( USE_UV ) || defined( USE_ANISOTROPY ) + varying vec2 vUv; +#endif +#ifdef USE_MAP + uniform mat3 mapTransform; + varying vec2 vMapUv; +#endif +#ifdef USE_ALPHAMAP + uniform mat3 alphaMapTransform; + varying vec2 vAlphaMapUv; +#endif +#ifdef USE_LIGHTMAP + uniform mat3 lightMapTransform; + varying vec2 vLightMapUv; +#endif +#ifdef USE_AOMAP + uniform mat3 aoMapTransform; + varying vec2 vAoMapUv; +#endif +#ifdef USE_BUMPMAP + uniform mat3 bumpMapTransform; + varying vec2 vBumpMapUv; +#endif +#ifdef USE_NORMALMAP + uniform mat3 normalMapTransform; + varying vec2 vNormalMapUv; +#endif +#ifdef USE_DISPLACEMENTMAP + uniform mat3 displacementMapTransform; + varying vec2 vDisplacementMapUv; +#endif +#ifdef USE_EMISSIVEMAP + uniform mat3 emissiveMapTransform; + varying vec2 vEmissiveMapUv; +#endif +#ifdef USE_METALNESSMAP + uniform mat3 metalnessMapTransform; + varying vec2 vMetalnessMapUv; +#endif +#ifdef USE_ROUGHNESSMAP + uniform mat3 roughnessMapTransform; + varying vec2 vRoughnessMapUv; +#endif +#ifdef USE_ANISOTROPYMAP + uniform mat3 anisotropyMapTransform; + varying vec2 vAnisotropyMapUv; +#endif +#ifdef USE_CLEARCOATMAP + uniform mat3 clearcoatMapTransform; + varying vec2 vClearcoatMapUv; +#endif +#ifdef USE_CLEARCOAT_NORMALMAP + uniform mat3 clearcoatNormalMapTransform; + varying vec2 vClearcoatNormalMapUv; +#endif +#ifdef USE_CLEARCOAT_ROUGHNESSMAP + uniform mat3 clearcoatRoughnessMapTransform; + varying vec2 vClearcoatRoughnessMapUv; +#endif +#ifdef USE_SHEEN_COLORMAP + uniform mat3 sheenColorMapTransform; + varying vec2 vSheenColorMapUv; +#endif +#ifdef USE_SHEEN_ROUGHNESSMAP + uniform mat3 sheenRoughnessMapTransform; + varying vec2 vSheenRoughnessMapUv; +#endif +#ifdef USE_IRIDESCENCEMAP + uniform mat3 iridescenceMapTransform; + varying vec2 vIridescenceMapUv; +#endif +#ifdef USE_IRIDESCENCE_THICKNESSMAP + uniform mat3 iridescenceThicknessMapTransform; + varying vec2 vIridescenceThicknessMapUv; +#endif +#ifdef USE_SPECULARMAP + uniform mat3 specularMapTransform; + varying vec2 vSpecularMapUv; +#endif +#ifdef USE_SPECULAR_COLORMAP + uniform mat3 specularColorMapTransform; + varying vec2 vSpecularColorMapUv; +#endif +#ifdef USE_SPECULAR_INTENSITYMAP + uniform mat3 specularIntensityMapTransform; + varying vec2 vSpecularIntensityMapUv; +#endif +#ifdef USE_TRANSMISSIONMAP + uniform mat3 transmissionMapTransform; + varying vec2 vTransmissionMapUv; +#endif +#ifdef USE_THICKNESSMAP + uniform mat3 thicknessMapTransform; + varying vec2 vThicknessMapUv; +#endif`,uv_vertex:`#if defined( USE_UV ) || defined( USE_ANISOTROPY ) + vUv = vec3( uv, 1 ).xy; +#endif +#ifdef USE_MAP + vMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy; +#endif +#ifdef USE_ALPHAMAP + vAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_LIGHTMAP + vLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_AOMAP + vAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_BUMPMAP + vBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_NORMALMAP + vNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_DISPLACEMENTMAP + vDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_EMISSIVEMAP + vEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_METALNESSMAP + vMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_ROUGHNESSMAP + vRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_ANISOTROPYMAP + vAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_CLEARCOATMAP + vClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_CLEARCOAT_NORMALMAP + vClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_CLEARCOAT_ROUGHNESSMAP + vClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_IRIDESCENCEMAP + vIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_IRIDESCENCE_THICKNESSMAP + vIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_SHEEN_COLORMAP + vSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_SHEEN_ROUGHNESSMAP + vSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_SPECULARMAP + vSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_SPECULAR_COLORMAP + vSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_SPECULAR_INTENSITYMAP + vSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_TRANSMISSIONMAP + vTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy; +#endif +#ifdef USE_THICKNESSMAP + vThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy; +#endif`,worldpos_vertex:`#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0 + vec4 worldPosition = vec4( transformed, 1.0 ); + #ifdef USE_BATCHING + worldPosition = batchingMatrix * worldPosition; + #endif + #ifdef USE_INSTANCING + worldPosition = instanceMatrix * worldPosition; + #endif + worldPosition = modelMatrix * worldPosition; +#endif`,background_vert:`varying vec2 vUv; +uniform mat3 uvTransform; +void main() { + vUv = ( uvTransform * vec3( uv, 1 ) ).xy; + gl_Position = vec4( position.xy, 1.0, 1.0 ); +}`,background_frag:`uniform sampler2D t2D; +uniform float backgroundIntensity; +varying vec2 vUv; +void main() { + vec4 texColor = texture2D( t2D, vUv ); + #ifdef DECODE_VIDEO_TEXTURE + texColor = vec4( mix( pow( texColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), texColor.rgb * 0.0773993808, vec3( lessThanEqual( texColor.rgb, vec3( 0.04045 ) ) ) ), texColor.w ); + #endif + texColor.rgb *= backgroundIntensity; + gl_FragColor = texColor; + #include + #include +}`,backgroundCube_vert:`varying vec3 vWorldDirection; +#include +void main() { + vWorldDirection = transformDirection( position, modelMatrix ); + #include + #include + gl_Position.z = gl_Position.w; +}`,backgroundCube_frag:`#ifdef ENVMAP_TYPE_CUBE + uniform samplerCube envMap; +#elif defined( ENVMAP_TYPE_CUBE_UV ) + uniform sampler2D envMap; +#endif +uniform float flipEnvMap; +uniform float backgroundBlurriness; +uniform float backgroundIntensity; +uniform mat3 backgroundRotation; +varying vec3 vWorldDirection; +#include +void main() { + #ifdef ENVMAP_TYPE_CUBE + vec4 texColor = textureCube( envMap, backgroundRotation * vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) ); + #elif defined( ENVMAP_TYPE_CUBE_UV ) + vec4 texColor = textureCubeUV( envMap, backgroundRotation * vWorldDirection, backgroundBlurriness ); + #else + vec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 ); + #endif + texColor.rgb *= backgroundIntensity; + gl_FragColor = texColor; + #include + #include +}`,cube_vert:`varying vec3 vWorldDirection; +#include +void main() { + vWorldDirection = transformDirection( position, modelMatrix ); + #include + #include + gl_Position.z = gl_Position.w; +}`,cube_frag:`uniform samplerCube tCube; +uniform float tFlip; +uniform float opacity; +varying vec3 vWorldDirection; +void main() { + vec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) ); + gl_FragColor = texColor; + gl_FragColor.a *= opacity; + #include + #include +}`,depth_vert:`#include +#include +#include +#include +#include +#include +#include +#include +varying vec2 vHighPrecisionZW; +void main() { + #include + #include + #include + #include + #ifdef USE_DISPLACEMENTMAP + #include + #include + #include + #endif + #include + #include + #include + #include + #include + #include + #include + vHighPrecisionZW = gl_Position.zw; +}`,depth_frag:`#if DEPTH_PACKING == 3200 + uniform float opacity; +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +varying vec2 vHighPrecisionZW; +void main() { + vec4 diffuseColor = vec4( 1.0 ); + #include + #if DEPTH_PACKING == 3200 + diffuseColor.a = opacity; + #endif + #include + #include + #include + #include + #include + float fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5; + #if DEPTH_PACKING == 3200 + gl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity ); + #elif DEPTH_PACKING == 3201 + gl_FragColor = packDepthToRGBA( fragCoordZ ); + #elif DEPTH_PACKING == 3202 + gl_FragColor = vec4( packDepthToRGB( fragCoordZ ), 1.0 ); + #elif DEPTH_PACKING == 3203 + gl_FragColor = vec4( packDepthToRG( fragCoordZ ), 0.0, 1.0 ); + #endif +}`,distanceRGBA_vert:`#define DISTANCE +varying vec3 vWorldPosition; +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #ifdef USE_DISPLACEMENTMAP + #include + #include + #include + #endif + #include + #include + #include + #include + #include + #include + #include + vWorldPosition = worldPosition.xyz; +}`,distanceRGBA_frag:`#define DISTANCE +uniform vec3 referencePosition; +uniform float nearDistance; +uniform float farDistance; +varying vec3 vWorldPosition; +#include +#include +#include +#include +#include +#include +#include +#include +void main () { + vec4 diffuseColor = vec4( 1.0 ); + #include + #include + #include + #include + #include + float dist = length( vWorldPosition - referencePosition ); + dist = ( dist - nearDistance ) / ( farDistance - nearDistance ); + dist = saturate( dist ); + gl_FragColor = packDepthToRGBA( dist ); +}`,equirect_vert:`varying vec3 vWorldDirection; +#include +void main() { + vWorldDirection = transformDirection( position, modelMatrix ); + #include + #include +}`,equirect_frag:`uniform sampler2D tEquirect; +varying vec3 vWorldDirection; +#include +void main() { + vec3 direction = normalize( vWorldDirection ); + vec2 sampleUV = equirectUv( direction ); + gl_FragColor = texture2D( tEquirect, sampleUV ); + #include + #include +}`,linedashed_vert:`uniform float scale; +attribute float lineDistance; +varying float vLineDistance; +#include +#include +#include +#include +#include +#include +#include +void main() { + vLineDistance = scale * lineDistance; + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include +}`,linedashed_frag:`uniform vec3 diffuse; +uniform float opacity; +uniform float dashSize; +uniform float totalSize; +varying float vLineDistance; +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + if ( mod( vLineDistance, totalSize ) > dashSize ) { + discard; + } + vec3 outgoingLight = vec3( 0.0 ); + #include + #include + #include + outgoingLight = diffuseColor.rgb; + #include + #include + #include + #include + #include +}`,meshbasic_vert:`#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #include + #if defined ( USE_ENVMAP ) || defined ( USE_SKINNING ) + #include + #include + #include + #include + #include + #endif + #include + #include + #include + #include + #include + #include + #include + #include + #include +}`,meshbasic_frag:`uniform vec3 diffuse; +uniform float opacity; +#ifndef FLAT_SHADED + varying vec3 vNormal; +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + #include + #include + #include + #include + #include + #include + #include + ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) ); + #ifdef USE_LIGHTMAP + vec4 lightMapTexel = texture2D( lightMap, vLightMapUv ); + reflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI; + #else + reflectedLight.indirectDiffuse += vec3( 1.0 ); + #endif + #include + reflectedLight.indirectDiffuse *= diffuseColor.rgb; + vec3 outgoingLight = reflectedLight.indirectDiffuse; + #include + #include + #include + #include + #include + #include + #include +}`,meshlambert_vert:`#define LAMBERT +varying vec3 vViewPosition; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vViewPosition = - mvPosition.xyz; + #include + #include + #include + #include +}`,meshlambert_frag:`#define LAMBERT +uniform vec3 diffuse; +uniform vec3 emissive; +uniform float opacity; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) ); + vec3 totalEmissiveRadiance = emissive; + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance; + #include + #include + #include + #include + #include + #include + #include +}`,meshmatcap_vert:`#define MATCAP +varying vec3 vViewPosition; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vViewPosition = - mvPosition.xyz; +}`,meshmatcap_frag:`#define MATCAP +uniform vec3 diffuse; +uniform float opacity; +uniform sampler2D matcap; +varying vec3 vViewPosition; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + #include + #include + #include + #include + #include + #include + #include + #include + vec3 viewDir = normalize( vViewPosition ); + vec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) ); + vec3 y = cross( viewDir, x ); + vec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5; + #ifdef USE_MATCAP + vec4 matcapColor = texture2D( matcap, uv ); + #else + vec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 ); + #endif + vec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb; + #include + #include + #include + #include + #include + #include +}`,meshnormal_vert:`#define NORMAL +#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE ) + varying vec3 vViewPosition; +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include +#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE ) + vViewPosition = - mvPosition.xyz; +#endif +}`,meshnormal_frag:`#define NORMAL +uniform float opacity; +#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE ) + varying vec3 vViewPosition; +#endif +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( 0.0, 0.0, 0.0, opacity ); + #include + #include + #include + #include + gl_FragColor = vec4( packNormalToRGB( normal ), diffuseColor.a ); + #ifdef OPAQUE + gl_FragColor.a = 1.0; + #endif +}`,meshphong_vert:`#define PHONG +varying vec3 vViewPosition; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vViewPosition = - mvPosition.xyz; + #include + #include + #include + #include +}`,meshphong_frag:`#define PHONG +uniform vec3 diffuse; +uniform vec3 emissive; +uniform vec3 specular; +uniform float shininess; +uniform float opacity; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) ); + vec3 totalEmissiveRadiance = emissive; + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance; + #include + #include + #include + #include + #include + #include + #include +}`,meshphysical_vert:`#define STANDARD +varying vec3 vViewPosition; +#ifdef USE_TRANSMISSION + varying vec3 vWorldPosition; +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vViewPosition = - mvPosition.xyz; + #include + #include + #include +#ifdef USE_TRANSMISSION + vWorldPosition = worldPosition.xyz; +#endif +}`,meshphysical_frag:`#define STANDARD +#ifdef PHYSICAL + #define IOR + #define USE_SPECULAR +#endif +uniform vec3 diffuse; +uniform vec3 emissive; +uniform float roughness; +uniform float metalness; +uniform float opacity; +#ifdef IOR + uniform float ior; +#endif +#ifdef USE_SPECULAR + uniform float specularIntensity; + uniform vec3 specularColor; + #ifdef USE_SPECULAR_COLORMAP + uniform sampler2D specularColorMap; + #endif + #ifdef USE_SPECULAR_INTENSITYMAP + uniform sampler2D specularIntensityMap; + #endif +#endif +#ifdef USE_CLEARCOAT + uniform float clearcoat; + uniform float clearcoatRoughness; +#endif +#ifdef USE_DISPERSION + uniform float dispersion; +#endif +#ifdef USE_IRIDESCENCE + uniform float iridescence; + uniform float iridescenceIOR; + uniform float iridescenceThicknessMinimum; + uniform float iridescenceThicknessMaximum; +#endif +#ifdef USE_SHEEN + uniform vec3 sheenColor; + uniform float sheenRoughness; + #ifdef USE_SHEEN_COLORMAP + uniform sampler2D sheenColorMap; + #endif + #ifdef USE_SHEEN_ROUGHNESSMAP + uniform sampler2D sheenRoughnessMap; + #endif +#endif +#ifdef USE_ANISOTROPY + uniform vec2 anisotropyVector; + #ifdef USE_ANISOTROPYMAP + uniform sampler2D anisotropyMap; + #endif +#endif +varying vec3 vViewPosition; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) ); + vec3 totalEmissiveRadiance = emissive; + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse; + vec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular; + #include + vec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance; + #ifdef USE_SHEEN + float sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor ); + outgoingLight = outgoingLight * sheenEnergyComp + sheenSpecularDirect + sheenSpecularIndirect; + #endif + #ifdef USE_CLEARCOAT + float dotNVcc = saturate( dot( geometryClearcoatNormal, geometryViewDir ) ); + vec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc ); + outgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + ( clearcoatSpecularDirect + clearcoatSpecularIndirect ) * material.clearcoat; + #endif + #include + #include + #include + #include + #include + #include +}`,meshtoon_vert:`#define TOON +varying vec3 vViewPosition; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vViewPosition = - mvPosition.xyz; + #include + #include + #include +}`,meshtoon_frag:`#define TOON +uniform vec3 diffuse; +uniform vec3 emissive; +uniform float opacity; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) ); + vec3 totalEmissiveRadiance = emissive; + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance; + #include + #include + #include + #include + #include + #include +}`,points_vert:`uniform float size; +uniform float scale; +#include +#include +#include +#include +#include +#include +#ifdef USE_POINTS_UV + varying vec2 vUv; + uniform mat3 uvTransform; +#endif +void main() { + #ifdef USE_POINTS_UV + vUv = ( uvTransform * vec3( uv, 1 ) ).xy; + #endif + #include + #include + #include + #include + #include + #include + gl_PointSize = size; + #ifdef USE_SIZEATTENUATION + bool isPerspective = isPerspectiveMatrix( projectionMatrix ); + if ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z ); + #endif + #include + #include + #include + #include +}`,points_frag:`uniform vec3 diffuse; +uniform float opacity; +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + vec3 outgoingLight = vec3( 0.0 ); + #include + #include + #include + #include + #include + outgoingLight = diffuseColor.rgb; + #include + #include + #include + #include + #include +}`,shadow_vert:`#include +#include +#include +#include +#include +#include +#include +void main() { + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include +}`,shadow_frag:`uniform vec3 color; +uniform float opacity; +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + #include + gl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) ); + #include + #include + #include +}`,sprite_vert:`uniform float rotation; +uniform vec2 center; +#include +#include +#include +#include +#include +void main() { + #include + vec4 mvPosition = modelViewMatrix[ 3 ]; + vec2 scale = vec2( length( modelMatrix[ 0 ].xyz ), length( modelMatrix[ 1 ].xyz ) ); + #ifndef USE_SIZEATTENUATION + bool isPerspective = isPerspectiveMatrix( projectionMatrix ); + if ( isPerspective ) scale *= - mvPosition.z; + #endif + vec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale; + vec2 rotatedPosition; + rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y; + rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y; + mvPosition.xy += rotatedPosition; + gl_Position = projectionMatrix * mvPosition; + #include + #include + #include +}`,sprite_frag:`uniform vec3 diffuse; +uniform float opacity; +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main() { + vec4 diffuseColor = vec4( diffuse, opacity ); + #include + vec3 outgoingLight = vec3( 0.0 ); + #include + #include + #include + #include + #include + outgoingLight = diffuseColor.rgb; + #include + #include + #include + #include +}`},Y={common:{diffuse:{value:new K(16777215)},opacity:{value:1},map:{value:null},mapTransform:{value:new U},alphaMap:{value:null},alphaMapTransform:{value:new U},alphaTest:{value:0}},specularmap:{specularMap:{value:null},specularMapTransform:{value:new U}},envmap:{envMap:{value:null},envMapRotation:{value:new U},flipEnvMap:{value:-1},reflectivity:{value:1},ior:{value:1.5},refractionRatio:{value:.98}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1},aoMapTransform:{value:new U}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1},lightMapTransform:{value:new U}},bumpmap:{bumpMap:{value:null},bumpMapTransform:{value:new U},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalMapTransform:{value:new U},normalScale:{value:new H(1,1)}},displacementmap:{displacementMap:{value:null},displacementMapTransform:{value:new U},displacementScale:{value:1},displacementBias:{value:0}},emissivemap:{emissiveMap:{value:null},emissiveMapTransform:{value:new U}},metalnessmap:{metalnessMap:{value:null},metalnessMapTransform:{value:new U}},roughnessmap:{roughnessMap:{value:null},roughnessMapTransform:{value:new U}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new K(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},spotLightMap:{value:[]},spotShadowMap:{value:[]},spotLightMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{},shadowCameraNear:{},shadowCameraFar:{}}},pointShadowMap:{value:[]},pointShadowMatrix:{value:[]},hemisphereLights:{value:[],properties:{direction:{},skyColor:{},groundColor:{}}},rectAreaLights:{value:[],properties:{color:{},position:{},width:{},height:{}}},ltc_1:{value:null},ltc_2:{value:null}},points:{diffuse:{value:new K(16777215)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},alphaMapTransform:{value:new U},alphaTest:{value:0},uvTransform:{value:new U}},sprite:{diffuse:{value:new K(16777215)},opacity:{value:1},center:{value:new H(.5,.5)},rotation:{value:0},map:{value:null},mapTransform:{value:new U},alphaMap:{value:null},alphaMapTransform:{value:new U},alphaTest:{value:0}}},Ba={basic:{uniforms:pa([Y.common,Y.specularmap,Y.envmap,Y.aomap,Y.lightmap,Y.fog]),vertexShader:J.meshbasic_vert,fragmentShader:J.meshbasic_frag},lambert:{uniforms:pa([Y.common,Y.specularmap,Y.envmap,Y.aomap,Y.lightmap,Y.emissivemap,Y.bumpmap,Y.normalmap,Y.displacementmap,Y.fog,Y.lights,{emissive:{value:new K(0)}}]),vertexShader:J.meshlambert_vert,fragmentShader:J.meshlambert_frag},phong:{uniforms:pa([Y.common,Y.specularmap,Y.envmap,Y.aomap,Y.lightmap,Y.emissivemap,Y.bumpmap,Y.normalmap,Y.displacementmap,Y.fog,Y.lights,{emissive:{value:new K(0)},specular:{value:new K(1118481)},shininess:{value:30}}]),vertexShader:J.meshphong_vert,fragmentShader:J.meshphong_frag},standard:{uniforms:pa([Y.common,Y.envmap,Y.aomap,Y.lightmap,Y.emissivemap,Y.bumpmap,Y.normalmap,Y.displacementmap,Y.roughnessmap,Y.metalnessmap,Y.fog,Y.lights,{emissive:{value:new K(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:J.meshphysical_vert,fragmentShader:J.meshphysical_frag},toon:{uniforms:pa([Y.common,Y.aomap,Y.lightmap,Y.emissivemap,Y.bumpmap,Y.normalmap,Y.displacementmap,Y.gradientmap,Y.fog,Y.lights,{emissive:{value:new K(0)}}]),vertexShader:J.meshtoon_vert,fragmentShader:J.meshtoon_frag},matcap:{uniforms:pa([Y.common,Y.bumpmap,Y.normalmap,Y.displacementmap,Y.fog,{matcap:{value:null}}]),vertexShader:J.meshmatcap_vert,fragmentShader:J.meshmatcap_frag},points:{uniforms:pa([Y.points,Y.fog]),vertexShader:J.points_vert,fragmentShader:J.points_frag},dashed:{uniforms:pa([Y.common,Y.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:J.linedashed_vert,fragmentShader:J.linedashed_frag},depth:{uniforms:pa([Y.common,Y.displacementmap]),vertexShader:J.depth_vert,fragmentShader:J.depth_frag},normal:{uniforms:pa([Y.common,Y.bumpmap,Y.normalmap,Y.displacementmap,{opacity:{value:1}}]),vertexShader:J.meshnormal_vert,fragmentShader:J.meshnormal_frag},sprite:{uniforms:pa([Y.sprite,Y.fog]),vertexShader:J.sprite_vert,fragmentShader:J.sprite_frag},background:{uniforms:{uvTransform:{value:new U},t2D:{value:null},backgroundIntensity:{value:1}},vertexShader:J.background_vert,fragmentShader:J.background_frag},backgroundCube:{uniforms:{envMap:{value:null},flipEnvMap:{value:-1},backgroundBlurriness:{value:0},backgroundIntensity:{value:1},backgroundRotation:{value:new U}},vertexShader:J.backgroundCube_vert,fragmentShader:J.backgroundCube_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:J.cube_vert,fragmentShader:J.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:J.equirect_vert,fragmentShader:J.equirect_frag},distanceRGBA:{uniforms:pa([Y.common,Y.displacementmap,{referencePosition:{value:new W},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:J.distanceRGBA_vert,fragmentShader:J.distanceRGBA_frag},shadow:{uniforms:pa([Y.lights,Y.fog,{color:{value:new K(0)},opacity:{value:1}}]),vertexShader:J.shadow_vert,fragmentShader:J.shadow_frag}};Ba.physical={uniforms:pa([Ba.standard.uniforms,{clearcoat:{value:0},clearcoatMap:{value:null},clearcoatMapTransform:{value:new U},clearcoatNormalMap:{value:null},clearcoatNormalMapTransform:{value:new U},clearcoatNormalScale:{value:new H(1,1)},clearcoatRoughness:{value:0},clearcoatRoughnessMap:{value:null},clearcoatRoughnessMapTransform:{value:new U},dispersion:{value:0},iridescence:{value:0},iridescenceMap:{value:null},iridescenceMapTransform:{value:new U},iridescenceIOR:{value:1.3},iridescenceThicknessMinimum:{value:100},iridescenceThicknessMaximum:{value:400},iridescenceThicknessMap:{value:null},iridescenceThicknessMapTransform:{value:new U},sheen:{value:0},sheenColor:{value:new K(0)},sheenColorMap:{value:null},sheenColorMapTransform:{value:new U},sheenRoughness:{value:1},sheenRoughnessMap:{value:null},sheenRoughnessMapTransform:{value:new U},transmission:{value:0},transmissionMap:{value:null},transmissionMapTransform:{value:new U},transmissionSamplerSize:{value:new H},transmissionSamplerMap:{value:null},thickness:{value:0},thicknessMap:{value:null},thicknessMapTransform:{value:new U},attenuationDistance:{value:0},attenuationColor:{value:new K(0)},specularColor:{value:new K(1,1,1)},specularColorMap:{value:null},specularColorMapTransform:{value:new U},specularIntensity:{value:1},specularIntensityMap:{value:null},specularIntensityMapTransform:{value:new U},anisotropyVector:{value:new H},anisotropyMap:{value:null},anisotropyMapTransform:{value:new U}}]),vertexShader:J.meshphysical_vert,fragmentShader:J.meshphysical_frag};var Va={r:0,b:0,g:0},Ha=new qr,Ua=new G;function Wa(e,t,n,r,i,a,o){let s=new K(0),c=a===!0?0:1,l,u,d=null,f=0,p=null;function m(e){let r=e.isScene===!0?e.background:null;return r&&r.isTexture&&(r=(e.backgroundBlurriness>0?n:t).get(r)),r}function h(t){let n=!1,i=m(t);i===null?_(s,c):i&&i.isColor&&(_(i,1),n=!0);let a=e.xr.getEnvironmentBlendMode();a===`additive`?r.buffers.color.setClear(0,0,0,1,o):a===`alpha-blend`&&r.buffers.color.setClear(0,0,0,0,o),(e.autoClear||n)&&(r.buffers.depth.setTest(!0),r.buffers.depth.setMask(!0),r.buffers.color.setMask(!0),e.clear(e.autoClearColor,e.autoClearDepth,e.autoClearStencil))}function g(t,n){let r=m(n);r&&(r.isCubeTexture||r.mapping===306)?(u===void 0&&(u=new q(new da(1,1,1),new ya({name:`BackgroundCubeMaterial`,uniforms:fa(Ba.backgroundCube.uniforms),vertexShader:Ba.backgroundCube.vertexShader,fragmentShader:Ba.backgroundCube.fragmentShader,side:1,depthTest:!1,depthWrite:!1,fog:!1})),u.geometry.deleteAttribute(`normal`),u.geometry.deleteAttribute(`uv`),u.onBeforeRender=function(e,t,n){this.matrixWorld.copyPosition(n.matrixWorld)},Object.defineProperty(u.material,"envMap",{get:function(){return this.uniforms.envMap.value}}),i.update(u)),Ha.copy(n.backgroundRotation),Ha.x*=-1,Ha.y*=-1,Ha.z*=-1,r.isCubeTexture&&r.isRenderTargetTexture===!1&&(Ha.y*=-1,Ha.z*=-1),u.material.uniforms.envMap.value=r,u.material.uniforms.flipEnvMap.value=r.isCubeTexture&&r.isRenderTargetTexture===!1?-1:1,u.material.uniforms.backgroundBlurriness.value=n.backgroundBlurriness,u.material.uniforms.backgroundIntensity.value=n.backgroundIntensity,u.material.uniforms.backgroundRotation.value.setFromMatrix4(Ua.makeRotationFromEuler(Ha)),u.material.toneMapped=qn.getTransfer(r.colorSpace)!==tn,(d!==r||f!==r.version||p!==e.toneMapping)&&(u.material.needsUpdate=!0,d=r,f=r.version,p=e.toneMapping),u.layers.enableAll(),t.unshift(u,u.geometry,u.material,0,0,null)):r&&r.isTexture&&(l===void 0&&(l=new q(new za(2,2),new ya({name:`BackgroundMaterial`,uniforms:fa(Ba.background.uniforms),vertexShader:Ba.background.vertexShader,fragmentShader:Ba.background.fragmentShader,side:0,depthTest:!1,depthWrite:!1,fog:!1})),l.geometry.deleteAttribute(`normal`),Object.defineProperty(l.material,"map",{get:function(){return this.uniforms.t2D.value}}),i.update(l)),l.material.uniforms.t2D.value=r,l.material.uniforms.backgroundIntensity.value=n.backgroundIntensity,l.material.toneMapped=qn.getTransfer(r.colorSpace)!==tn,r.matrixAutoUpdate===!0&&r.updateMatrix(),l.material.uniforms.uvTransform.value.copy(r.matrix),(d!==r||f!==r.version||p!==e.toneMapping)&&(l.material.needsUpdate=!0,d=r,f=r.version,p=e.toneMapping),l.layers.enableAll(),t.unshift(l,l.geometry,l.material,0,0,null))}function _(t,n){t.getRGB(Va,ha(e)),r.buffers.color.setClear(Va.r,Va.g,Va.b,n,o)}return{getClearColor:function(){return s},setClearColor:function(e,t=1){s.set(e),c=t,_(s,c)},getClearAlpha:function(){return c},setClearAlpha:function(e){c=e,_(s,c)},render:h,addToRenderList:g}}function Ga(e,t){let n=e.getParameter(e.MAX_VERTEX_ATTRIBS),r={},i=f(null),a=i,o=!1;function s(n,r,i,s,c){let u=!1,f=d(s,i,r);a!==f&&(a=f,l(a.object)),u=p(n,s,i,c),u&&m(n,s,i,c),c!==null&&t.update(c,e.ELEMENT_ARRAY_BUFFER),(u||o)&&(o=!1,b(n,r,i,s),c!==null&&e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,t.get(c).buffer))}function c(){return e.createVertexArray()}function l(t){return e.bindVertexArray(t)}function u(t){return e.deleteVertexArray(t)}function d(e,t,n){let i=n.wireframe===!0,a=r[e.id];a===void 0&&(a={},r[e.id]=a);let o=a[t.id];o===void 0&&(o={},a[t.id]=o);let s=o[i];return s===void 0&&(s=f(c()),o[i]=s),s}function f(e){let t=[],r=[],i=[];for(let e=0;e=0){let n=i[t],r=o[t];if(r===void 0&&(t===`instanceMatrix`&&e.instanceMatrix&&(r=e.instanceMatrix),t===`instanceColor`&&e.instanceColor&&(r=e.instanceColor)),n===void 0||n.attribute!==r||r&&n.data!==r.data)return!0;s++}return a.attributesNum!==s||a.index!==r}function m(e,t,n,r){let i={},o=t.attributes,s=0,c=n.getAttributes();for(let t in c)if(c[t].location>=0){let n=o[t];n===void 0&&(t===`instanceMatrix`&&e.instanceMatrix&&(n=e.instanceMatrix),t===`instanceColor`&&e.instanceColor&&(n=e.instanceColor));let r={};r.attribute=n,n&&n.data&&(r.data=n.data),i[t]=r,s++}a.attributes=i,a.attributesNum=s,a.index=r}function h(){let e=a.newAttributes;for(let t=0,n=e.length;t=0){let s=o[r];if(s===void 0&&(r===`instanceMatrix`&&n.instanceMatrix&&(s=n.instanceMatrix),r===`instanceColor`&&n.instanceColor&&(s=n.instanceColor)),s!==void 0){let r=s.normalized,o=s.itemSize,c=t.get(s);if(c===void 0)continue;let l=c.buffer,u=c.type,d=c.bytesPerElement,f=u===e.INT||u===e.UNSIGNED_INT||s.gpuType===1013;if(s.isInterleavedBufferAttribute){let t=s.data,c=t.stride,p=s.offset;if(t.isInstancedInterleavedBuffer){for(let e=0;e0&&e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT).precision>0)return`highp`;t=`mediump`}return t===`mediump`&&e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.MEDIUM_FLOAT).precision>0&&e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_FLOAT).precision>0?`mediump`:`lowp`}let l=n.precision===void 0?`highp`:n.precision,u=c(l);u!==l&&(console.warn(`THREE.WebGLRenderer:`,l,`not supported, using`,u,`instead.`),l=u);let d=n.logarithmicDepthBuffer===!0,f=n.reverseDepthBuffer===!0&&t.has(`EXT_clip_control`);if(f===!0){let e=t.get(`EXT_clip_control`);e.clipControlEXT(e.LOWER_LEFT_EXT,e.ZERO_TO_ONE_EXT)}let p=e.getParameter(e.MAX_TEXTURE_IMAGE_UNITS),m=e.getParameter(e.MAX_VERTEX_TEXTURE_IMAGE_UNITS),h=e.getParameter(e.MAX_TEXTURE_SIZE),g=e.getParameter(e.MAX_CUBE_MAP_TEXTURE_SIZE),_=e.getParameter(e.MAX_VERTEX_ATTRIBS),v=e.getParameter(e.MAX_VERTEX_UNIFORM_VECTORS),y=e.getParameter(e.MAX_VARYING_VECTORS),b=e.getParameter(e.MAX_FRAGMENT_UNIFORM_VECTORS),x=m>0,S=e.getParameter(e.MAX_SAMPLES);return{isWebGL2:!0,getMaxAnisotropy:a,getMaxPrecision:c,textureFormatReadable:o,textureTypeReadable:s,precision:l,logarithmicDepthBuffer:d,reverseDepthBuffer:f,maxTextures:p,maxVertexTextures:m,maxTextureSize:h,maxCubemapSize:g,maxAttributes:_,maxVertexUniforms:v,maxVaryings:y,maxFragmentUniforms:b,vertexTextures:x,maxSamples:S}}function Ja(e){let t=this,n=null,r=0,i=!1,a=!1,o=new Na,s=new U,c={value:null,needsUpdate:!1};this.uniform=c,this.numPlanes=0,this.numIntersection=0,this.init=function(e,t){let n=e.length!==0||t||r!==0||i;return i=t,r=e.length,n},this.beginShadows=function(){a=!0,u(null)},this.endShadows=function(){a=!1},this.setGlobalState=function(e,t){n=u(e,t,0)},this.setState=function(t,o,s){let d=t.clippingPlanes,f=t.clipIntersection,p=t.clipShadows,m=e.get(t);if(!i||d===null||d.length===0||a&&!p)a?u(null):l();else{let e=a?0:r,t=e*4,i=m.clippingState||null;c.value=i,i=u(d,o,t,s);for(let e=0;e!==t;++e)i[e]=n[e];m.clippingState=i,this.numIntersection=f?this.numPlanes:0,this.numPlanes+=e}};function l(){c.value!==n&&(c.value=n,c.needsUpdate=r>0),t.numPlanes=r,t.numIntersection=0}function u(e,n,r,i){let a=e===null?0:e.length,l=null;if(a!==0){if(l=c.value,i!==!0||l===null){let t=r+a*4,i=n.matrixWorldInverse;s.getNormalMatrix(i),(l===null||l.length0){let o=new ka(a.height);return o.fromEquirectangularTexture(e,r),t.set(r,o),r.addEventListener(`dispose`,i),n(o.texture,r.mapping)}return null}}}return r}function i(e){let n=e.target;n.removeEventListener(`dispose`,i);let r=t.get(n);r!==void 0&&(t.delete(n),r.dispose())}function a(){t=new WeakMap}return{get:r,dispose:a}}var Xa=class extends ba{constructor(e=-1,t=1,n=1,r=-1,i=.1,a=2e3){super(),this.isOrthographicCamera=!0,this.type=`OrthographicCamera`,this.zoom=1,this.view=null,this.left=e,this.right=t,this.top=n,this.bottom=r,this.near=i,this.far=a,this.updateProjectionMatrix()}copy(e,t){return super.copy(e,t),this.left=e.left,this.right=e.right,this.top=e.top,this.bottom=e.bottom,this.near=e.near,this.far=e.far,this.zoom=e.zoom,this.view=e.view===null?null:Object.assign({},e.view),this}setViewOffset(e,t,n,r,i,a){this.view===null&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=e,this.view.fullHeight=t,this.view.offsetX=n,this.view.offsetY=r,this.view.width=i,this.view.height=a,this.updateProjectionMatrix()}clearViewOffset(){this.view!==null&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){let e=(this.right-this.left)/(2*this.zoom),t=(this.top-this.bottom)/(2*this.zoom),n=(this.right+this.left)/2,r=(this.top+this.bottom)/2,i=n-e,a=n+e,o=r+t,s=r-t;if(this.view!==null&&this.view.enabled){let e=(this.right-this.left)/this.view.fullWidth/this.zoom,t=(this.top-this.bottom)/this.view.fullHeight/this.zoom;i+=e*this.view.offsetX,a=i+e*this.view.width,o-=t*this.view.offsetY,s=o-t*this.view.height}this.projectionMatrix.makeOrthographic(i,a,o,s,this.near,this.far,this.coordinateSystem),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(e){let t=super.toJSON(e);return t.object.zoom=this.zoom,t.object.left=this.left,t.object.right=this.right,t.object.top=this.top,t.object.bottom=this.bottom,t.object.near=this.near,t.object.far=this.far,this.view!==null&&(t.object.view=Object.assign({},this.view)),t}},Za=4,Qa=[.125,.215,.35,.446,.526,.582],$a=20,eo=new Xa,to=new K,no=null,ro=0,io=0,ao=!1,oo=(1+Math.sqrt(5))/2,so=1/oo,co=[new W(-oo,so,0),new W(oo,so,0),new W(-so,0,oo),new W(so,0,oo),new W(0,oo,-so),new W(0,oo,so),new W(-1,1,-1),new W(1,1,-1),new W(-1,1,1),new W(1,1,1)],lo=class{constructor(e){this._renderer=e,this._pingPongRenderTarget=null,this._lodMax=0,this._cubeSize=0,this._lodPlanes=[],this._sizeLods=[],this._sigmas=[],this._blurMaterial=null,this._cubemapMaterial=null,this._equirectMaterial=null,this._compileMaterial(this._blurMaterial)}fromScene(e,t=0,n=.1,r=100){no=this._renderer.getRenderTarget(),ro=this._renderer.getActiveCubeFace(),io=this._renderer.getActiveMipmapLevel(),ao=this._renderer.xr.enabled,this._renderer.xr.enabled=!1,this._setSize(256);let i=this._allocateTargets();return i.depthBuffer=!0,this._sceneToCubeUV(e,n,r,i),t>0&&this._blur(i,0,0,t),this._applyPMREM(i),this._cleanup(i),i}fromEquirectangular(e,t=null){return this._fromTexture(e,t)}fromCubemap(e,t=null){return this._fromTexture(e,t)}compileCubemapShader(){this._cubemapMaterial===null&&(this._cubemapMaterial=go(),this._compileMaterial(this._cubemapMaterial))}compileEquirectangularShader(){this._equirectMaterial===null&&(this._equirectMaterial=ho(),this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),this._cubemapMaterial!==null&&this._cubemapMaterial.dispose(),this._equirectMaterial!==null&&this._equirectMaterial.dispose()}_setSize(e){this._lodMax=Math.floor(Math.log2(e)),this._cubeSize=2**this._lodMax}_dispose(){this._blurMaterial!==null&&this._blurMaterial.dispose(),this._pingPongRenderTarget!==null&&this._pingPongRenderTarget.dispose();for(let e=0;e2?c:0,c,c),s.setRenderTarget(r),f&&s.render(d,i),s.render(e,i)}d.geometry.dispose(),d.material.dispose(),s.toneMapping=l,s.autoClear=c,e.background=p}_textureToCubeUV(e,t){let n=this._renderer,r=e.mapping===301||e.mapping===302;r?(this._cubemapMaterial===null&&(this._cubemapMaterial=go()),this._cubemapMaterial.uniforms.flipEnvMap.value=e.isRenderTargetTexture===!1?-1:1):this._equirectMaterial===null&&(this._equirectMaterial=ho());let i=r?this._cubemapMaterial:this._equirectMaterial,a=new q(this._lodPlanes[0],i),o=i.uniforms;o.envMap.value=e;let s=this._cubeSize;po(t,0,0,3*s,2*s),n.setRenderTarget(t),n.render(a,eo)}_applyPMREM(e){let t=this._renderer,n=t.autoClear;t.autoClear=!1;let r=this._lodPlanes.length;for(let t=1;t$a&&console.warn(`sigmaRadians, ${i}, is too large and will clip, as it requested ${m} samples when the maximum is set to ${$a}`);let h=[],g=0;for(let e=0;e<$a;++e){let t=e/p,n=Math.exp(-t*t/2);h.push(n),e===0?g+=n:e_-Za?r-_+Za:0),4*(this._cubeSize-v),3*v,2*v),s.setRenderTarget(t),s.render(l,eo)}};function uo(e){let t=[],n=[],r=[],i=e,a=e-Za+1+Qa.length;for(let o=0;oe-Za?s=Qa[o-e+Za-1]:o===0&&(s=0),r.push(s);let c=1/(a-2),l=-c,u=1+c,d=[l,l,u,l,u,u,l,l,u,u,l,u],f=new Float32Array(108),p=new Float32Array(72),m=new Float32Array(36);for(let e=0;e<6;e++){let t=e%3*2/3-1,n=e>2?0:-1,r=[t,n,0,t+2/3,n,0,t+2/3,n+1,0,t,n,0,t+2/3,n+1,0,t,n+1,0];f.set(r,18*e),p.set(d,12*e);let i=[e,e,e,e,e,e];m.set(i,6*e)}let h=new Zi;h.setAttribute(`position`,new Bi(f,3)),h.setAttribute(`uv`,new Bi(p,2)),h.setAttribute(`faceIndex`,new Bi(m,1)),t.push(h),i>Za&&i--}return{lodPlanes:t,sizeLods:n,sigmas:r}}function fo(e,t,n){let r=new ar(e,t,n);return r.texture.mapping=306,r.texture.name=`PMREM.cubeUv`,r.scissorTest=!0,r}function po(e,t,n,r,i){e.viewport.set(t,n,r,i),e.scissor.set(t,n,r,i)}function mo(e,t,n){let r=new Float32Array($a),i=new W(0,1,0);return new ya({name:`SphericalGaussianBlur`,defines:{n:$a,CUBEUV_TEXEL_WIDTH:1/t,CUBEUV_TEXEL_HEIGHT:1/n,CUBEUV_MAX_MIP:`${e}.0`},uniforms:{envMap:{value:null},samples:{value:1},weights:{value:r},latitudinal:{value:!1},dTheta:{value:0},mipInt:{value:0},poleAxis:{value:i}},vertexShader:_o(),fragmentShader:` + + precision mediump float; + precision mediump int; + + varying vec3 vOutputDirection; + + uniform sampler2D envMap; + uniform int samples; + uniform float weights[ n ]; + uniform bool latitudinal; + uniform float dTheta; + uniform float mipInt; + uniform vec3 poleAxis; + + #define ENVMAP_TYPE_CUBE_UV + #include + + vec3 getSample( float theta, vec3 axis ) { + + float cosTheta = cos( theta ); + // Rodrigues' axis-angle rotation + vec3 sampleDirection = vOutputDirection * cosTheta + + cross( axis, vOutputDirection ) * sin( theta ) + + axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta ); + + return bilinearCubeUV( envMap, sampleDirection, mipInt ); + + } + + void main() { + + vec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection ); + + if ( all( equal( axis, vec3( 0.0 ) ) ) ) { + + axis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x ); + + } + + axis = normalize( axis ); + + gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 ); + gl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis ); + + for ( int i = 1; i < n; i++ ) { + + if ( i >= samples ) { + + break; + + } + + float theta = dTheta * float( i ); + gl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis ); + gl_FragColor.rgb += weights[ i ] * getSample( theta, axis ); + + } + + } + `,blending:0,depthTest:!1,depthWrite:!1})}function ho(){return new ya({name:`EquirectangularToCubeUV`,uniforms:{envMap:{value:null}},vertexShader:_o(),fragmentShader:` + + precision mediump float; + precision mediump int; + + varying vec3 vOutputDirection; + + uniform sampler2D envMap; + + #include + + void main() { + + vec3 outputDirection = normalize( vOutputDirection ); + vec2 uv = equirectUv( outputDirection ); + + gl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 ); + + } + `,blending:0,depthTest:!1,depthWrite:!1})}function go(){return new ya({name:`CubemapToCubeUV`,uniforms:{envMap:{value:null},flipEnvMap:{value:-1}},vertexShader:_o(),fragmentShader:` + + precision mediump float; + precision mediump int; + + uniform float flipEnvMap; + + varying vec3 vOutputDirection; + + uniform samplerCube envMap; + + void main() { + + gl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) ); + + } + `,blending:0,depthTest:!1,depthWrite:!1})}function _o(){return` + + precision mediump float; + precision mediump int; + + attribute float faceIndex; + + varying vec3 vOutputDirection; + + // RH coordinate system; PMREM face-indexing convention + vec3 getDirection( vec2 uv, float face ) { + + uv = 2.0 * uv - 1.0; + + vec3 direction = vec3( uv, 1.0 ); + + if ( face == 0.0 ) { + + direction = direction.zyx; // ( 1, v, u ) pos x + + } else if ( face == 1.0 ) { + + direction = direction.xzy; + direction.xz *= -1.0; // ( -u, 1, -v ) pos y + + } else if ( face == 2.0 ) { + + direction.x *= -1.0; // ( -u, v, 1 ) pos z + + } else if ( face == 3.0 ) { + + direction = direction.zyx; + direction.xz *= -1.0; // ( -1, v, -u ) neg x + + } else if ( face == 4.0 ) { + + direction = direction.xzy; + direction.xy *= -1.0; // ( -u, -1, v ) neg y + + } else if ( face == 5.0 ) { + + direction.z *= -1.0; // ( u, v, -1 ) neg z + + } + + return direction; + + } + + void main() { + + vOutputDirection = getDirection( uv, faceIndex ); + gl_Position = vec4( position, 1.0 ); + + } + `}function vo(e){let t=new WeakMap,n=null;function r(r){if(r&&r.isTexture){let o=r.mapping,s=o===303||o===304,c=o===301||o===302;if(s||c){let o=t.get(r),l=o===void 0?0:o.texture.pmremVersion;if(r.isRenderTargetTexture&&r.pmremVersion!==l)return n===null&&(n=new lo(e)),o=s?n.fromEquirectangular(r,o):n.fromCubemap(r,o),o.texture.pmremVersion=r.pmremVersion,t.set(r,o),o.texture;if(o!==void 0)return o.texture;{let l=r.image;return s&&l&&l.height>0||c&&l&&i(l)?(n===null&&(n=new lo(e)),o=s?n.fromEquirectangular(r):n.fromCubemap(r),o.texture.pmremVersion=r.pmremVersion,t.set(r,o),r.addEventListener(`dispose`,a),o.texture):null}}}return r}function i(e){let t=0;for(let n=0;n<6;n++)e[n]!==void 0&&t++;return t===6}function a(e){let n=e.target;n.removeEventListener(`dispose`,a);let r=t.get(n);r!==void 0&&(t.delete(n),r.dispose())}function o(){t=new WeakMap,n!==null&&(n.dispose(),n=null)}return{get:r,dispose:o}}function yo(e){let t={};function n(n){if(t[n]!==void 0)return t[n];let r;switch(n){case`WEBGL_depth_texture`:r=e.getExtension(`WEBGL_depth_texture`)||e.getExtension(`MOZ_WEBGL_depth_texture`)||e.getExtension(`WEBKIT_WEBGL_depth_texture`);break;case`EXT_texture_filter_anisotropic`:r=e.getExtension(`EXT_texture_filter_anisotropic`)||e.getExtension(`MOZ_EXT_texture_filter_anisotropic`)||e.getExtension(`WEBKIT_EXT_texture_filter_anisotropic`);break;case`WEBGL_compressed_texture_s3tc`:r=e.getExtension(`WEBGL_compressed_texture_s3tc`)||e.getExtension(`MOZ_WEBGL_compressed_texture_s3tc`)||e.getExtension(`WEBKIT_WEBGL_compressed_texture_s3tc`);break;case`WEBGL_compressed_texture_pvrtc`:r=e.getExtension(`WEBGL_compressed_texture_pvrtc`)||e.getExtension(`WEBKIT_WEBGL_compressed_texture_pvrtc`);break;default:r=e.getExtension(n)}return t[n]=r,r}return{has:function(e){return n(e)!==null},init:function(){n(`EXT_color_buffer_float`),n(`WEBGL_clip_cull_distance`),n(`OES_texture_float_linear`),n(`EXT_color_buffer_half_float`),n(`WEBGL_multisampled_render_to_texture`),n(`WEBGL_render_shared_exponent`)},get:function(e){let t=n(e);return t===null&&zn(`THREE.WebGLRenderer: `+e+` extension not supported.`),t}}}function bo(e,t,n,r){let i={},a=new WeakMap;function o(e){let s=e.target;s.index!==null&&t.remove(s.index);for(let e in s.attributes)t.remove(s.attributes[e]);for(let e in s.morphAttributes){let n=s.morphAttributes[e];for(let e=0,r=n.length;et.maxTextureSize&&(m=Math.ceil(p/t.maxTextureSize),p=t.maxTextureSize);let h=new Float32Array(p*m*4*u),g=new or(h,p,m,u);g.type=Ge,g.needsUpdate=!0;let _=f*4;for(let t=0;t0)return e;let i=t*n,a=jo[i];if(a===void 0&&(a=new Float32Array(i),jo[i]=a),t!==0){r.toArray(a,0);for(let r=1,i=0;r!==t;++r)i+=n,e[r].toArray(a,i)}return a}function Lo(e,t){if(e.length!==t.length)return!1;for(let n=0,r=e.length;n`:` `} ${i}: ${n[e]}`)}return r.join(` +`)}function Ls(e){let t=qn.getPrimaries(qn.workingColorSpace),n=qn.getPrimaries(e),r;switch(t===n?r=``:t===`p3`&&n===`rec709`?r=`LinearDisplayP3ToLinearSRGB`:t===`rec709`&&n===`p3`&&(r=`LinearSRGBToLinearDisplayP3`),e){case Zt:case $t:return[r,`LinearTransferOETF`];case Xt:case Qt:return[r,`sRGBTransferOETF`];default:return console.warn(`THREE.WebGLProgram: Unsupported color space:`,e),[r,`LinearTransferOETF`]}}function Rs(e,t,n){let r=e.getShaderParameter(t,e.COMPILE_STATUS),i=e.getShaderInfoLog(t).trim();if(r&&i===``)return``;let a=/ERROR: 0:(\d+)/.exec(i);if(a){let r=parseInt(a[1]);return n.toUpperCase()+` + +`+i+` + +`+Is(e.getShaderSource(t),r)}return i}function zs(e,t){let n=Ls(t);return`vec4 ${e}( vec4 value ) { return ${n[0]}( ${n[1]}( value ) ); }`}function Bs(e,t){let n;switch(t){case 1:n=`Linear`;break;case 2:n=`Reinhard`;break;case 3:n=`Cineon`;break;case 4:n=`ACESFilmic`;break;case 6:n=`AgX`;break;case 7:n=`Neutral`;break;case 5:n=`Custom`;break;default:console.warn(`THREE.WebGLProgram: Unsupported toneMapping:`,t),n=`Linear`}return`vec3 `+e+`( vec3 color ) { return `+n+`ToneMapping( color ); }`}var Vs=new W;function Hs(){return qn.getLuminanceCoefficients(Vs),[`float luminance( const in vec3 rgb ) {`,` const vec3 weights = vec3( ${Vs.x.toFixed(4)}, ${Vs.y.toFixed(4)}, ${Vs.z.toFixed(4)} );`,` return dot( weights, rgb );`,`}`].join(` +`)}function Us(e){return[e.extensionClipCullDistance?`#extension GL_ANGLE_clip_cull_distance : require`:``,e.extensionMultiDraw?`#extension GL_ANGLE_multi_draw : require`:``].filter(Ks).join(` +`)}function Ws(e){let t=[];for(let n in e){let r=e[n];r!==!1&&t.push(`#define `+n+` `+r)}return t.join(` +`)}function Gs(e,t){let n={},r=e.getProgramParameter(t,e.ACTIVE_ATTRIBUTES);for(let i=0;i/gm;function Xs(e){return e.replace(Ys,Qs)}var Zs=new Map;function Qs(e,t){let n=J[t];if(n===void 0){let e=Zs.get(t);if(e!==void 0)n=J[e],console.warn(`THREE.WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.`,t,e);else throw Error(`Can not resolve #include <`+t+`>`)}return Xs(n)}var $s=/#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g;function ec(e){return e.replace($s,tc)}function tc(e,t,n,r){let i=``;for(let e=parseInt(t);e0&&(g+=` +`),_=[`#define SHADER_TYPE `+n.shaderType,`#define SHADER_NAME `+n.shaderName,m].filter(Ks).join(` +`),_.length>0&&(_+=` +`)):(g=[nc(n),`#define SHADER_TYPE `+n.shaderType,`#define SHADER_NAME `+n.shaderName,m,n.extensionClipCullDistance?`#define USE_CLIP_DISTANCE`:``,n.batching?`#define USE_BATCHING`:``,n.batchingColor?`#define USE_BATCHING_COLOR`:``,n.instancing?`#define USE_INSTANCING`:``,n.instancingColor?`#define USE_INSTANCING_COLOR`:``,n.instancingMorph?`#define USE_INSTANCING_MORPH`:``,n.useFog&&n.fog?`#define USE_FOG`:``,n.useFog&&n.fogExp2?`#define FOG_EXP2`:``,n.map?`#define USE_MAP`:``,n.envMap?`#define USE_ENVMAP`:``,n.envMap?`#define `+u:``,n.lightMap?`#define USE_LIGHTMAP`:``,n.aoMap?`#define USE_AOMAP`:``,n.bumpMap?`#define USE_BUMPMAP`:``,n.normalMap?`#define USE_NORMALMAP`:``,n.normalMapObjectSpace?`#define USE_NORMALMAP_OBJECTSPACE`:``,n.normalMapTangentSpace?`#define USE_NORMALMAP_TANGENTSPACE`:``,n.displacementMap?`#define USE_DISPLACEMENTMAP`:``,n.emissiveMap?`#define USE_EMISSIVEMAP`:``,n.anisotropy?`#define USE_ANISOTROPY`:``,n.anisotropyMap?`#define USE_ANISOTROPYMAP`:``,n.clearcoatMap?`#define USE_CLEARCOATMAP`:``,n.clearcoatRoughnessMap?`#define USE_CLEARCOAT_ROUGHNESSMAP`:``,n.clearcoatNormalMap?`#define USE_CLEARCOAT_NORMALMAP`:``,n.iridescenceMap?`#define USE_IRIDESCENCEMAP`:``,n.iridescenceThicknessMap?`#define USE_IRIDESCENCE_THICKNESSMAP`:``,n.specularMap?`#define USE_SPECULARMAP`:``,n.specularColorMap?`#define USE_SPECULAR_COLORMAP`:``,n.specularIntensityMap?`#define USE_SPECULAR_INTENSITYMAP`:``,n.roughnessMap?`#define USE_ROUGHNESSMAP`:``,n.metalnessMap?`#define USE_METALNESSMAP`:``,n.alphaMap?`#define USE_ALPHAMAP`:``,n.alphaHash?`#define USE_ALPHAHASH`:``,n.transmission?`#define USE_TRANSMISSION`:``,n.transmissionMap?`#define USE_TRANSMISSIONMAP`:``,n.thicknessMap?`#define USE_THICKNESSMAP`:``,n.sheenColorMap?`#define USE_SHEEN_COLORMAP`:``,n.sheenRoughnessMap?`#define USE_SHEEN_ROUGHNESSMAP`:``,n.mapUv?`#define MAP_UV `+n.mapUv:``,n.alphaMapUv?`#define ALPHAMAP_UV `+n.alphaMapUv:``,n.lightMapUv?`#define LIGHTMAP_UV `+n.lightMapUv:``,n.aoMapUv?`#define AOMAP_UV `+n.aoMapUv:``,n.emissiveMapUv?`#define EMISSIVEMAP_UV `+n.emissiveMapUv:``,n.bumpMapUv?`#define BUMPMAP_UV `+n.bumpMapUv:``,n.normalMapUv?`#define NORMALMAP_UV `+n.normalMapUv:``,n.displacementMapUv?`#define DISPLACEMENTMAP_UV `+n.displacementMapUv:``,n.metalnessMapUv?`#define METALNESSMAP_UV `+n.metalnessMapUv:``,n.roughnessMapUv?`#define ROUGHNESSMAP_UV `+n.roughnessMapUv:``,n.anisotropyMapUv?`#define ANISOTROPYMAP_UV `+n.anisotropyMapUv:``,n.clearcoatMapUv?`#define CLEARCOATMAP_UV `+n.clearcoatMapUv:``,n.clearcoatNormalMapUv?`#define CLEARCOAT_NORMALMAP_UV `+n.clearcoatNormalMapUv:``,n.clearcoatRoughnessMapUv?`#define CLEARCOAT_ROUGHNESSMAP_UV `+n.clearcoatRoughnessMapUv:``,n.iridescenceMapUv?`#define IRIDESCENCEMAP_UV `+n.iridescenceMapUv:``,n.iridescenceThicknessMapUv?`#define IRIDESCENCE_THICKNESSMAP_UV `+n.iridescenceThicknessMapUv:``,n.sheenColorMapUv?`#define SHEEN_COLORMAP_UV `+n.sheenColorMapUv:``,n.sheenRoughnessMapUv?`#define SHEEN_ROUGHNESSMAP_UV `+n.sheenRoughnessMapUv:``,n.specularMapUv?`#define SPECULARMAP_UV `+n.specularMapUv:``,n.specularColorMapUv?`#define SPECULAR_COLORMAP_UV `+n.specularColorMapUv:``,n.specularIntensityMapUv?`#define SPECULAR_INTENSITYMAP_UV `+n.specularIntensityMapUv:``,n.transmissionMapUv?`#define TRANSMISSIONMAP_UV `+n.transmissionMapUv:``,n.thicknessMapUv?`#define THICKNESSMAP_UV `+n.thicknessMapUv:``,n.vertexTangents&&n.flatShading===!1?`#define USE_TANGENT`:``,n.vertexColors?`#define USE_COLOR`:``,n.vertexAlphas?`#define USE_COLOR_ALPHA`:``,n.vertexUv1s?`#define USE_UV1`:``,n.vertexUv2s?`#define USE_UV2`:``,n.vertexUv3s?`#define USE_UV3`:``,n.pointsUvs?`#define USE_POINTS_UV`:``,n.flatShading?`#define FLAT_SHADED`:``,n.skinning?`#define USE_SKINNING`:``,n.morphTargets?`#define USE_MORPHTARGETS`:``,n.morphNormals&&n.flatShading===!1?`#define USE_MORPHNORMALS`:``,n.morphColors?`#define USE_MORPHCOLORS`:``,n.morphTargetsCount>0?`#define MORPHTARGETS_TEXTURE_STRIDE `+n.morphTextureStride:``,n.morphTargetsCount>0?`#define MORPHTARGETS_COUNT `+n.morphTargetsCount:``,n.doubleSided?`#define DOUBLE_SIDED`:``,n.flipSided?`#define FLIP_SIDED`:``,n.shadowMapEnabled?`#define USE_SHADOWMAP`:``,n.shadowMapEnabled?`#define `+c:``,n.sizeAttenuation?`#define USE_SIZEATTENUATION`:``,n.numLightProbes>0?`#define USE_LIGHT_PROBES`:``,n.logarithmicDepthBuffer?`#define USE_LOGDEPTHBUF`:``,n.reverseDepthBuffer?`#define USE_REVERSEDEPTHBUF`:``,`uniform mat4 modelMatrix;`,`uniform mat4 modelViewMatrix;`,`uniform mat4 projectionMatrix;`,`uniform mat4 viewMatrix;`,`uniform mat3 normalMatrix;`,`uniform vec3 cameraPosition;`,`uniform bool isOrthographic;`,`#ifdef USE_INSTANCING`,` attribute mat4 instanceMatrix;`,`#endif`,`#ifdef USE_INSTANCING_COLOR`,` attribute vec3 instanceColor;`,`#endif`,`#ifdef USE_INSTANCING_MORPH`,` uniform sampler2D morphTexture;`,`#endif`,`attribute vec3 position;`,`attribute vec3 normal;`,`attribute vec2 uv;`,`#ifdef USE_UV1`,` attribute vec2 uv1;`,`#endif`,`#ifdef USE_UV2`,` attribute vec2 uv2;`,`#endif`,`#ifdef USE_UV3`,` attribute vec2 uv3;`,`#endif`,`#ifdef USE_TANGENT`,` attribute vec4 tangent;`,`#endif`,`#if defined( USE_COLOR_ALPHA )`,` attribute vec4 color;`,`#elif defined( USE_COLOR )`,` attribute vec3 color;`,`#endif`,`#ifdef USE_SKINNING`,` attribute vec4 skinIndex;`,` attribute vec4 skinWeight;`,`#endif`,` +`].filter(Ks).join(` +`),_=[nc(n),`#define SHADER_TYPE `+n.shaderType,`#define SHADER_NAME `+n.shaderName,m,n.useFog&&n.fog?`#define USE_FOG`:``,n.useFog&&n.fogExp2?`#define FOG_EXP2`:``,n.alphaToCoverage?`#define ALPHA_TO_COVERAGE`:``,n.map?`#define USE_MAP`:``,n.matcap?`#define USE_MATCAP`:``,n.envMap?`#define USE_ENVMAP`:``,n.envMap?`#define `+l:``,n.envMap?`#define `+u:``,n.envMap?`#define `+d:``,f?`#define CUBEUV_TEXEL_WIDTH `+f.texelWidth:``,f?`#define CUBEUV_TEXEL_HEIGHT `+f.texelHeight:``,f?`#define CUBEUV_MAX_MIP `+f.maxMip+`.0`:``,n.lightMap?`#define USE_LIGHTMAP`:``,n.aoMap?`#define USE_AOMAP`:``,n.bumpMap?`#define USE_BUMPMAP`:``,n.normalMap?`#define USE_NORMALMAP`:``,n.normalMapObjectSpace?`#define USE_NORMALMAP_OBJECTSPACE`:``,n.normalMapTangentSpace?`#define USE_NORMALMAP_TANGENTSPACE`:``,n.emissiveMap?`#define USE_EMISSIVEMAP`:``,n.anisotropy?`#define USE_ANISOTROPY`:``,n.anisotropyMap?`#define USE_ANISOTROPYMAP`:``,n.clearcoat?`#define USE_CLEARCOAT`:``,n.clearcoatMap?`#define USE_CLEARCOATMAP`:``,n.clearcoatRoughnessMap?`#define USE_CLEARCOAT_ROUGHNESSMAP`:``,n.clearcoatNormalMap?`#define USE_CLEARCOAT_NORMALMAP`:``,n.dispersion?`#define USE_DISPERSION`:``,n.iridescence?`#define USE_IRIDESCENCE`:``,n.iridescenceMap?`#define USE_IRIDESCENCEMAP`:``,n.iridescenceThicknessMap?`#define USE_IRIDESCENCE_THICKNESSMAP`:``,n.specularMap?`#define USE_SPECULARMAP`:``,n.specularColorMap?`#define USE_SPECULAR_COLORMAP`:``,n.specularIntensityMap?`#define USE_SPECULAR_INTENSITYMAP`:``,n.roughnessMap?`#define USE_ROUGHNESSMAP`:``,n.metalnessMap?`#define USE_METALNESSMAP`:``,n.alphaMap?`#define USE_ALPHAMAP`:``,n.alphaTest?`#define USE_ALPHATEST`:``,n.alphaHash?`#define USE_ALPHAHASH`:``,n.sheen?`#define USE_SHEEN`:``,n.sheenColorMap?`#define USE_SHEEN_COLORMAP`:``,n.sheenRoughnessMap?`#define USE_SHEEN_ROUGHNESSMAP`:``,n.transmission?`#define USE_TRANSMISSION`:``,n.transmissionMap?`#define USE_TRANSMISSIONMAP`:``,n.thicknessMap?`#define USE_THICKNESSMAP`:``,n.vertexTangents&&n.flatShading===!1?`#define USE_TANGENT`:``,n.vertexColors||n.instancingColor||n.batchingColor?`#define USE_COLOR`:``,n.vertexAlphas?`#define USE_COLOR_ALPHA`:``,n.vertexUv1s?`#define USE_UV1`:``,n.vertexUv2s?`#define USE_UV2`:``,n.vertexUv3s?`#define USE_UV3`:``,n.pointsUvs?`#define USE_POINTS_UV`:``,n.gradientMap?`#define USE_GRADIENTMAP`:``,n.flatShading?`#define FLAT_SHADED`:``,n.doubleSided?`#define DOUBLE_SIDED`:``,n.flipSided?`#define FLIP_SIDED`:``,n.shadowMapEnabled?`#define USE_SHADOWMAP`:``,n.shadowMapEnabled?`#define `+c:``,n.premultipliedAlpha?`#define PREMULTIPLIED_ALPHA`:``,n.numLightProbes>0?`#define USE_LIGHT_PROBES`:``,n.decodeVideoTexture?`#define DECODE_VIDEO_TEXTURE`:``,n.logarithmicDepthBuffer?`#define USE_LOGDEPTHBUF`:``,n.reverseDepthBuffer?`#define USE_REVERSEDEPTHBUF`:``,`uniform mat4 viewMatrix;`,`uniform vec3 cameraPosition;`,`uniform bool isOrthographic;`,n.toneMapping===0?``:`#define TONE_MAPPING`,n.toneMapping===0?``:J.tonemapping_pars_fragment,n.toneMapping===0?``:Bs(`toneMapping`,n.toneMapping),n.dithering?`#define DITHERING`:``,n.opaque?`#define OPAQUE`:``,J.colorspace_pars_fragment,zs(`linearToOutputTexel`,n.outputColorSpace),Hs(),n.useDepthPacking?`#define DEPTH_PACKING `+n.depthPacking:``,` +`].filter(Ks).join(` +`)),o=Xs(o),o=qs(o,n),o=Js(o,n),s=Xs(s),s=qs(s,n),s=Js(s,n),o=ec(o),s=ec(s),n.isRawShaderMaterial!==!0&&(v=`#version 300 es +`,g=[p,`#define attribute in`,`#define varying out`,`#define texture2D texture`].join(` +`)+` +`+g,_=[`#define varying in`,n.glslVersion===`300 es`?``:`layout(location = 0) out highp vec4 pc_fragColor;`,n.glslVersion===`300 es`?``:`#define gl_FragColor pc_fragColor`,`#define gl_FragDepthEXT gl_FragDepth`,`#define texture2D texture`,`#define textureCube texture`,`#define texture2DProj textureProj`,`#define texture2DLodEXT textureLod`,`#define texture2DProjLodEXT textureProjLod`,`#define textureCubeLodEXT textureLod`,`#define texture2DGradEXT textureGrad`,`#define texture2DProjGradEXT textureProjGrad`,`#define textureCubeGradEXT textureGrad`].join(` +`)+` +`+_);let y=v+g+o,b=v+_+s,x=Ns(i,i.VERTEX_SHADER,y),S=Ns(i,i.FRAGMENT_SHADER,b);i.attachShader(h,x),i.attachShader(h,S),n.index0AttributeName===void 0?n.morphTargets===!0&&i.bindAttribLocation(h,0,`position`):i.bindAttribLocation(h,0,n.index0AttributeName),i.linkProgram(h);function C(t){if(e.debug.checkShaderErrors){let n=i.getProgramInfoLog(h).trim(),r=i.getShaderInfoLog(x).trim(),a=i.getShaderInfoLog(S).trim(),o=!0,s=!0;if(i.getProgramParameter(h,i.LINK_STATUS)===!1){if(o=!1,typeof e.debug.onShaderError==`function`)e.debug.onShaderError(i,h,x,S);else{let e=Rs(i,x,`vertex`),r=Rs(i,S,`fragment`);console.error(`THREE.WebGLProgram: Shader Error `+i.getError()+` - VALIDATE_STATUS `+i.getProgramParameter(h,i.VALIDATE_STATUS)+` + +Material Name: `+t.name+` +Material Type: `+t.type+` + +Program Info Log: `+n+` +`+e+` +`+r)}}else n===``?(r===``||a===``)&&(s=!1):console.warn(`THREE.WebGLProgram: Program Info Log:`,n);s&&(t.diagnostics={runnable:o,programLog:n,vertexShader:{log:r,prefix:g},fragmentShader:{log:a,prefix:_}})}i.deleteShader(x),i.deleteShader(S),w=new Ms(i,h),T=Gs(i,h)}let w;this.getUniforms=function(){return w===void 0&&C(this),w};let T;this.getAttributes=function(){return T===void 0&&C(this),T};let E=n.rendererExtensionParallelShaderCompile===!1;return this.isReady=function(){return E===!1&&(E=i.getProgramParameter(h,Ps)),E},this.destroy=function(){r.releaseStatesOfProgram(this),i.deleteProgram(h),this.program=void 0},this.type=n.shaderType,this.name=n.shaderName,this.id=Fs++,this.cacheKey=t,this.usedTimes=1,this.program=h,this.vertexShader=x,this.fragmentShader=S,this}var lc=0,uc=class{constructor(){this.shaderCache=new Map,this.materialCache=new Map}update(e){let t=e.vertexShader,n=e.fragmentShader,r=this._getShaderStage(t),i=this._getShaderStage(n),a=this._getShaderCacheForMaterial(e);return a.has(r)===!1&&(a.add(r),r.usedTimes++),a.has(i)===!1&&(a.add(i),i.usedTimes++),this}remove(e){let t=this.materialCache.get(e);for(let e of t)e.usedTimes--,e.usedTimes===0&&this.shaderCache.delete(e.code);return this.materialCache.delete(e),this}getVertexShaderID(e){return this._getShaderStage(e.vertexShader).id}getFragmentShaderID(e){return this._getShaderStage(e.fragmentShader).id}dispose(){this.shaderCache.clear(),this.materialCache.clear()}_getShaderCacheForMaterial(e){let t=this.materialCache,n=t.get(e);return n===void 0&&(n=new Set,t.set(e,n)),n}_getShaderStage(e){let t=this.shaderCache,n=t.get(e);return n===void 0&&(n=new dc(e),t.set(e,n)),n}},dc=class{constructor(e){this.id=lc++,this.code=e,this.usedTimes=0}};function fc(e,t,n,r,i,a,o){let s=new Jr,c=new uc,l=new Set,u=[],d=i.logarithmicDepthBuffer,f=i.reverseDepthBuffer,p=i.vertexTextures,m=i.precision,h={MeshDepthMaterial:`depth`,MeshDistanceMaterial:`distanceRGBA`,MeshNormalMaterial:`normal`,MeshBasicMaterial:`basic`,MeshLambertMaterial:`lambert`,MeshPhongMaterial:`phong`,MeshToonMaterial:`toon`,MeshStandardMaterial:`physical`,MeshPhysicalMaterial:`physical`,MeshMatcapMaterial:`matcap`,LineBasicMaterial:`basic`,LineDashedMaterial:`dashed`,PointsMaterial:`points`,ShadowMaterial:`shadow`,SpriteMaterial:`sprite`};function g(e){return l.add(e),e===0?`uv`:`uv${e}`}function _(a,s,u,_,v){let y=_.fog,b=v.geometry,x=a.isMeshStandardMaterial?_.environment:null,S=(a.isMeshStandardMaterial?n:t).get(a.envMap||x),C=S&&S.mapping===306?S.image.height:null,w=h[a.type];a.precision!==null&&(m=i.getMaxPrecision(a.precision),m!==a.precision&&console.warn(`THREE.WebGLProgram.getParameters:`,a.precision,`not supported, using`,m,`instead.`));let T=b.morphAttributes.position||b.morphAttributes.normal||b.morphAttributes.color,E=T===void 0?0:T.length,D=0;b.morphAttributes.position!==void 0&&(D=1),b.morphAttributes.normal!==void 0&&(D=2),b.morphAttributes.color!==void 0&&(D=3);let O,k,A,j;if(w){let e=Ba[w];O=e.vertexShader,k=e.fragmentShader}else O=a.vertexShader,k=a.fragmentShader,c.update(a),A=c.getVertexShaderID(a),j=c.getFragmentShaderID(a);let M=e.getRenderTarget(),N=v.isInstancedMesh===!0,P=v.isBatchedMesh===!0,F=!!a.map,I=!!a.matcap,ee=!!S,te=!!a.aoMap,ne=!!a.lightMap,re=!!a.bumpMap,ie=!!a.normalMap,ae=!!a.displacementMap,oe=!!a.emissiveMap,se=!!a.metalnessMap,ce=!!a.roughnessMap,le=a.anisotropy>0,ue=a.clearcoat>0,L=a.dispersion>0,de=a.iridescence>0,fe=a.sheen>0,pe=a.transmission>0,R=le&&!!a.anisotropyMap,me=ue&&!!a.clearcoatMap,z=ue&&!!a.clearcoatNormalMap,B=ue&&!!a.clearcoatRoughnessMap,he=de&&!!a.iridescenceMap,ge=de&&!!a.iridescenceThicknessMap,_e=fe&&!!a.sheenColorMap,ve=fe&&!!a.sheenRoughnessMap,ye=!!a.specularMap,be=!!a.specularColorMap,xe=!!a.specularIntensityMap,Se=pe&&!!a.transmissionMap,Ce=pe&&!!a.thicknessMap,we=!!a.gradientMap,Te=!!a.alphaMap,Ee=a.alphaTest>0,De=!!a.alphaHash,Oe=!!a.extensions,ke=0;a.toneMapped&&(M===null||M.isXRRenderTarget===!0)&&(ke=e.toneMapping);let Ae={shaderID:w,shaderType:a.type,shaderName:a.name,vertexShader:O,fragmentShader:k,defines:a.defines,customVertexShaderID:A,customFragmentShaderID:j,isRawShaderMaterial:a.isRawShaderMaterial===!0,glslVersion:a.glslVersion,precision:m,batching:P,batchingColor:P&&v._colorsTexture!==null,instancing:N,instancingColor:N&&v.instanceColor!==null,instancingMorph:N&&v.morphTexture!==null,supportsVertexTextures:p,outputColorSpace:M===null?e.outputColorSpace:M.isXRRenderTarget===!0?M.texture.colorSpace:Zt,alphaToCoverage:!!a.alphaToCoverage,map:F,matcap:I,envMap:ee,envMapMode:ee&&S.mapping,envMapCubeUVHeight:C,aoMap:te,lightMap:ne,bumpMap:re,normalMap:ie,displacementMap:p&&ae,emissiveMap:oe,normalMapObjectSpace:ie&&a.normalMapType===1,normalMapTangentSpace:ie&&a.normalMapType===0,metalnessMap:se,roughnessMap:ce,anisotropy:le,anisotropyMap:R,clearcoat:ue,clearcoatMap:me,clearcoatNormalMap:z,clearcoatRoughnessMap:B,dispersion:L,iridescence:de,iridescenceMap:he,iridescenceThicknessMap:ge,sheen:fe,sheenColorMap:_e,sheenRoughnessMap:ve,specularMap:ye,specularColorMap:be,specularIntensityMap:xe,transmission:pe,transmissionMap:Se,thicknessMap:Ce,gradientMap:we,opaque:a.transparent===!1&&a.blending===1&&a.alphaToCoverage===!1,alphaMap:Te,alphaTest:Ee,alphaHash:De,combine:a.combine,mapUv:F&&g(a.map.channel),aoMapUv:te&&g(a.aoMap.channel),lightMapUv:ne&&g(a.lightMap.channel),bumpMapUv:re&&g(a.bumpMap.channel),normalMapUv:ie&&g(a.normalMap.channel),displacementMapUv:ae&&g(a.displacementMap.channel),emissiveMapUv:oe&&g(a.emissiveMap.channel),metalnessMapUv:se&&g(a.metalnessMap.channel),roughnessMapUv:ce&&g(a.roughnessMap.channel),anisotropyMapUv:R&&g(a.anisotropyMap.channel),clearcoatMapUv:me&&g(a.clearcoatMap.channel),clearcoatNormalMapUv:z&&g(a.clearcoatNormalMap.channel),clearcoatRoughnessMapUv:B&&g(a.clearcoatRoughnessMap.channel),iridescenceMapUv:he&&g(a.iridescenceMap.channel),iridescenceThicknessMapUv:ge&&g(a.iridescenceThicknessMap.channel),sheenColorMapUv:_e&&g(a.sheenColorMap.channel),sheenRoughnessMapUv:ve&&g(a.sheenRoughnessMap.channel),specularMapUv:ye&&g(a.specularMap.channel),specularColorMapUv:be&&g(a.specularColorMap.channel),specularIntensityMapUv:xe&&g(a.specularIntensityMap.channel),transmissionMapUv:Se&&g(a.transmissionMap.channel),thicknessMapUv:Ce&&g(a.thicknessMap.channel),alphaMapUv:Te&&g(a.alphaMap.channel),vertexTangents:!!b.attributes.tangent&&(ie||le),vertexColors:a.vertexColors,vertexAlphas:a.vertexColors===!0&&!!b.attributes.color&&b.attributes.color.itemSize===4,pointsUvs:v.isPoints===!0&&!!b.attributes.uv&&(F||Te),fog:!!y,useFog:a.fog===!0,fogExp2:!!y&&y.isFogExp2,flatShading:a.flatShading===!0,sizeAttenuation:a.sizeAttenuation===!0,logarithmicDepthBuffer:d,reverseDepthBuffer:f,skinning:v.isSkinnedMesh===!0,morphTargets:b.morphAttributes.position!==void 0,morphNormals:b.morphAttributes.normal!==void 0,morphColors:b.morphAttributes.color!==void 0,morphTargetsCount:E,morphTextureStride:D,numDirLights:s.directional.length,numPointLights:s.point.length,numSpotLights:s.spot.length,numSpotLightMaps:s.spotLightMap.length,numRectAreaLights:s.rectArea.length,numHemiLights:s.hemi.length,numDirLightShadows:s.directionalShadowMap.length,numPointLightShadows:s.pointShadowMap.length,numSpotLightShadows:s.spotShadowMap.length,numSpotLightShadowsWithMaps:s.numSpotLightShadowsWithMaps,numLightProbes:s.numLightProbes,numClippingPlanes:o.numPlanes,numClipIntersection:o.numIntersection,dithering:a.dithering,shadowMapEnabled:e.shadowMap.enabled&&u.length>0,shadowMapType:e.shadowMap.type,toneMapping:ke,decodeVideoTexture:F&&a.map.isVideoTexture===!0&&qn.getTransfer(a.map.colorSpace)===`srgb`,premultipliedAlpha:a.premultipliedAlpha,doubleSided:a.side===2,flipSided:a.side===1,useDepthPacking:a.depthPacking>=0,depthPacking:a.depthPacking||0,index0AttributeName:a.index0AttributeName,extensionClipCullDistance:Oe&&a.extensions.clipCullDistance===!0&&r.has(`WEBGL_clip_cull_distance`),extensionMultiDraw:(Oe&&a.extensions.multiDraw===!0||P)&&r.has(`WEBGL_multi_draw`),rendererExtensionParallelShaderCompile:r.has(`KHR_parallel_shader_compile`),customProgramCacheKey:a.customProgramCacheKey()};return Ae.vertexUv1s=l.has(1),Ae.vertexUv2s=l.has(2),Ae.vertexUv3s=l.has(3),l.clear(),Ae}function v(t){let n=[];if(t.shaderID?n.push(t.shaderID):(n.push(t.customVertexShaderID),n.push(t.customFragmentShaderID)),t.defines!==void 0)for(let e in t.defines)n.push(e),n.push(t.defines[e]);return t.isRawShaderMaterial===!1&&(y(n,t),b(n,t),n.push(e.outputColorSpace)),n.push(t.customProgramCacheKey),n.join()}function y(e,t){e.push(t.precision),e.push(t.outputColorSpace),e.push(t.envMapMode),e.push(t.envMapCubeUVHeight),e.push(t.mapUv),e.push(t.alphaMapUv),e.push(t.lightMapUv),e.push(t.aoMapUv),e.push(t.bumpMapUv),e.push(t.normalMapUv),e.push(t.displacementMapUv),e.push(t.emissiveMapUv),e.push(t.metalnessMapUv),e.push(t.roughnessMapUv),e.push(t.anisotropyMapUv),e.push(t.clearcoatMapUv),e.push(t.clearcoatNormalMapUv),e.push(t.clearcoatRoughnessMapUv),e.push(t.iridescenceMapUv),e.push(t.iridescenceThicknessMapUv),e.push(t.sheenColorMapUv),e.push(t.sheenRoughnessMapUv),e.push(t.specularMapUv),e.push(t.specularColorMapUv),e.push(t.specularIntensityMapUv),e.push(t.transmissionMapUv),e.push(t.thicknessMapUv),e.push(t.combine),e.push(t.fogExp2),e.push(t.sizeAttenuation),e.push(t.morphTargetsCount),e.push(t.morphAttributeCount),e.push(t.numDirLights),e.push(t.numPointLights),e.push(t.numSpotLights),e.push(t.numSpotLightMaps),e.push(t.numHemiLights),e.push(t.numRectAreaLights),e.push(t.numDirLightShadows),e.push(t.numPointLightShadows),e.push(t.numSpotLightShadows),e.push(t.numSpotLightShadowsWithMaps),e.push(t.numLightProbes),e.push(t.shadowMapType),e.push(t.toneMapping),e.push(t.numClippingPlanes),e.push(t.numClipIntersection),e.push(t.depthPacking)}function b(e,t){s.disableAll(),t.supportsVertexTextures&&s.enable(0),t.instancing&&s.enable(1),t.instancingColor&&s.enable(2),t.instancingMorph&&s.enable(3),t.matcap&&s.enable(4),t.envMap&&s.enable(5),t.normalMapObjectSpace&&s.enable(6),t.normalMapTangentSpace&&s.enable(7),t.clearcoat&&s.enable(8),t.iridescence&&s.enable(9),t.alphaTest&&s.enable(10),t.vertexColors&&s.enable(11),t.vertexAlphas&&s.enable(12),t.vertexUv1s&&s.enable(13),t.vertexUv2s&&s.enable(14),t.vertexUv3s&&s.enable(15),t.vertexTangents&&s.enable(16),t.anisotropy&&s.enable(17),t.alphaHash&&s.enable(18),t.batching&&s.enable(19),t.dispersion&&s.enable(20),t.batchingColor&&s.enable(21),e.push(s.mask),s.disableAll(),t.fog&&s.enable(0),t.useFog&&s.enable(1),t.flatShading&&s.enable(2),t.logarithmicDepthBuffer&&s.enable(3),t.reverseDepthBuffer&&s.enable(4),t.skinning&&s.enable(5),t.morphTargets&&s.enable(6),t.morphNormals&&s.enable(7),t.morphColors&&s.enable(8),t.premultipliedAlpha&&s.enable(9),t.shadowMapEnabled&&s.enable(10),t.doubleSided&&s.enable(11),t.flipSided&&s.enable(12),t.useDepthPacking&&s.enable(13),t.dithering&&s.enable(14),t.transmission&&s.enable(15),t.sheen&&s.enable(16),t.opaque&&s.enable(17),t.pointsUvs&&s.enable(18),t.decodeVideoTexture&&s.enable(19),t.alphaToCoverage&&s.enable(20),e.push(s.mask)}function x(e){let t=h[e.type],n;if(t){let e=Ba[t];n=ga.clone(e.uniforms)}else n=e.uniforms;return n}function S(t,n){let r;for(let e=0,t=u.length;e0?r.push(u):a.transparent===!0?i.push(u):n.push(u)}function c(e,t,a,s,c,l){let u=o(e,t,a,s,c,l);a.transmission>0?r.unshift(u):a.transparent===!0?i.unshift(u):n.unshift(u)}function l(e,t){n.length>1&&n.sort(e||mc),r.length>1&&r.sort(t||hc),i.length>1&&i.sort(t||hc)}function u(){for(let n=t,r=e.length;n=r.length?(i=new gc,r.push(i)):i=r[n],i}function n(){e=new WeakMap}return{get:t,dispose:n}}function vc(){let e={};return{get:function(t){if(e[t.id]!==void 0)return e[t.id];let n;switch(t.type){case`DirectionalLight`:n={direction:new W,color:new K};break;case`SpotLight`:n={position:new W,direction:new W,color:new K,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case`PointLight`:n={position:new W,color:new K,distance:0,decay:0};break;case`HemisphereLight`:n={direction:new W,skyColor:new K,groundColor:new K};break;case`RectAreaLight`:n={color:new K,position:new W,halfWidth:new W,halfHeight:new W}}return e[t.id]=n,n}}}function yc(){let e={};return{get:function(t){if(e[t.id]!==void 0)return e[t.id];let n;switch(t.type){case`DirectionalLight`:n={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new H};break;case`SpotLight`:n={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new H};break;case`PointLight`:n={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new H,shadowCameraNear:1,shadowCameraFar:1e3}}return e[t.id]=n,n}}}var bc=0;function xc(e,t){return(t.castShadow?2:0)-(e.castShadow?2:0)+ +!!t.map-!!e.map}function Sc(e){let t=new vc,n=yc(),r={version:0,hash:{directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1,numSpotMaps:-1,numLightProbes:-1},ambient:[0,0,0],probe:[],directional:[],directionalShadow:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotLightMap:[],spotShadow:[],spotShadowMap:[],spotLightMatrix:[],rectArea:[],rectAreaLTC1:null,rectAreaLTC2:null,point:[],pointShadow:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[],numSpotLightShadowsWithMaps:0,numLightProbes:0};for(let e=0;e<9;e++)r.probe.push(new W);let i=new W,a=new G,o=new G;function s(i){let a=0,o=0,s=0;for(let e=0;e<9;e++)r.probe[e].set(0,0,0);let c=0,l=0,u=0,d=0,f=0,p=0,m=0,h=0,g=0,_=0,v=0;i.sort(xc);for(let e=0,y=i.length;e0&&(e.has(`OES_texture_float_linear`)===!0?(r.rectAreaLTC1=Y.LTC_FLOAT_1,r.rectAreaLTC2=Y.LTC_FLOAT_2):(r.rectAreaLTC1=Y.LTC_HALF_1,r.rectAreaLTC2=Y.LTC_HALF_2)),r.ambient[0]=a,r.ambient[1]=o,r.ambient[2]=s;let y=r.hash;(y.directionalLength!==c||y.pointLength!==l||y.spotLength!==u||y.rectAreaLength!==d||y.hemiLength!==f||y.numDirectionalShadows!==p||y.numPointShadows!==m||y.numSpotShadows!==h||y.numSpotMaps!==g||y.numLightProbes!==v)&&(r.directional.length=c,r.spot.length=u,r.rectArea.length=d,r.point.length=l,r.hemi.length=f,r.directionalShadow.length=p,r.directionalShadowMap.length=p,r.pointShadow.length=m,r.pointShadowMap.length=m,r.spotShadow.length=h,r.spotShadowMap.length=h,r.directionalShadowMatrix.length=p,r.pointShadowMatrix.length=m,r.spotLightMatrix.length=h+g-_,r.spotLightMap.length=g,r.numSpotLightShadowsWithMaps=_,r.numLightProbes=v,y.directionalLength=c,y.pointLength=l,y.spotLength=u,y.rectAreaLength=d,y.hemiLength=f,y.numDirectionalShadows=p,y.numPointShadows=m,y.numSpotShadows=h,y.numSpotMaps=g,y.numLightProbes=v,r.version=bc++)}function c(e,t){let n=0,s=0,c=0,l=0,u=0,d=t.matrixWorldInverse;for(let t=0,f=e.length;t=i.length?(a=new Cc(e),i.push(a)):a=i[r],a}function r(){t=new WeakMap}return{get:n,dispose:r}}var Tc=class extends ji{constructor(e){super(),this.isMeshDepthMaterial=!0,this.type=`MeshDepthMaterial`,this.depthPacking=Jt,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.setValues(e)}copy(e){return super.copy(e),this.depthPacking=e.depthPacking,this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this}},Ec=class extends ji{constructor(e){super(),this.isMeshDistanceMaterial=!0,this.type=`MeshDistanceMaterial`,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.setValues(e)}copy(e){return super.copy(e),this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this}},Dc=`void main() { + gl_Position = vec4( position, 1.0 ); +}`,Oc=`uniform sampler2D shadow_pass; +uniform vec2 resolution; +uniform float radius; +#include +void main() { + const float samples = float( VSM_SAMPLES ); + float mean = 0.0; + float squared_mean = 0.0; + float uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 ); + float uvStart = samples <= 1.0 ? 0.0 : - 1.0; + for ( float i = 0.0; i < samples; i ++ ) { + float uvOffset = uvStart + i * uvStride; + #ifdef HORIZONTAL_PASS + vec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) ); + mean += distribution.x; + squared_mean += distribution.y * distribution.y + distribution.x * distribution.x; + #else + float depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) ); + mean += depth; + squared_mean += depth * depth; + #endif + } + mean = mean / samples; + squared_mean = squared_mean / samples; + float std_dev = sqrt( squared_mean - mean * mean ); + gl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) ); +}`;function kc(e,t,n){let r=new Ia,i=new H,a=new H,o=new rr,s=new Tc({depthPacking:Yt}),c=new Ec,l={},u=n.maxTextureSize,d={0:1,1:0,2:2},f=new ya({defines:{VSM_SAMPLES:8},uniforms:{shadow_pass:{value:null},resolution:{value:new H},radius:{value:4}},vertexShader:Dc,fragmentShader:Oc}),p=f.clone();p.defines.HORIZONTAL_PASS=1;let m=new Zi;m.setAttribute(`position`,new Bi(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));let h=new q(m,f),g=this;this.enabled=!1,this.autoUpdate=!0,this.needsUpdate=!1,this.type=1;let _=this.type;this.render=function(t,n,s){if(g.enabled===!1||g.autoUpdate===!1&&g.needsUpdate===!1||t.length===0)return;let c=e.getRenderTarget(),l=e.getActiveCubeFace(),d=e.getActiveMipmapLevel(),f=e.state;f.setBlending(0),f.buffers.color.setClear(1,1,1,1),f.buffers.depth.setTest(!0),f.setScissorTest(!1);let p=_!==3&&this.type===3,m=_===3&&this.type!==3;for(let c=0,l=t.length;cu||i.y>u)&&(i.x>u&&(a.x=Math.floor(u/h.x),i.x=a.x*h.x,d.mapSize.x=a.x),i.y>u&&(a.y=Math.floor(u/h.y),i.y=a.y*h.y,d.mapSize.y=a.y)),d.map===null||p===!0||m===!0){let e=this.type===3?{}:{minFilter:Ne,magFilter:Ne};d.map!==null&&d.map.dispose(),d.map=new ar(i.x,i.y,e),d.map.texture.name=l.name+`.shadowMap`,d.camera.updateProjectionMatrix()}e.setRenderTarget(d.map),e.clear();let g=d.getViewportCount();for(let e=0;e0||n.map&&n.alphaTest>0){let e=a.uuid,t=n.uuid,r=l[e];r===void 0&&(r={},l[e]=r);let i=r[t];i===void 0&&(i=a.clone(),r[t]=i,n.addEventListener(`dispose`,x)),a=i}if(a.visible=n.visible,a.wireframe=n.wireframe,i===3?a.side=n.shadowSide===null?n.side:n.shadowSide:a.side=n.shadowSide===null?d[n.side]:n.shadowSide,a.alphaMap=n.alphaMap,a.alphaTest=n.alphaTest,a.map=n.map,a.clipShadows=n.clipShadows,a.clippingPlanes=n.clippingPlanes,a.clipIntersection=n.clipIntersection,a.displacementMap=n.displacementMap,a.displacementScale=n.displacementScale,a.displacementBias=n.displacementBias,a.wireframeLinewidth=n.wireframeLinewidth,a.linewidth=n.linewidth,r.isPointLight===!0&&a.isMeshDistanceMaterial===!0){let t=e.properties.get(a);t.light=r}return a}function b(n,i,a,o,s){if(n.visible===!1)return;if(n.layers.test(i.layers)&&(n.isMesh||n.isLine||n.isPoints)&&(n.castShadow||n.receiveShadow&&s===3)&&(!n.frustumCulled||r.intersectsObject(n))){n.modelViewMatrix.multiplyMatrices(a.matrixWorldInverse,n.matrixWorld);let r=t.update(n),c=n.material;if(Array.isArray(c)){let t=r.groups;for(let l=0,u=t.length;l=2):(M=parseFloat(/^WebGL (\d)/.exec(N)[1]),j=M>=1);let P=null,F={},I=e.getParameter(e.SCISSOR_BOX),ee=e.getParameter(e.VIEWPORT),te=new rr().fromArray(I),ne=new rr().fromArray(ee);function re(t,n,r,i){let a=new Uint8Array(4),o=e.createTexture();e.bindTexture(t,o),e.texParameteri(t,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(t,e.TEXTURE_MAG_FILTER,e.NEAREST);for(let o=0;o`u`?!1:/OculusBrowser/g.test(navigator.userAgent),l=new H,u=new WeakMap,d,f=new WeakMap,p=!1;try{p=typeof OffscreenCanvas<`u`&&new OffscreenCanvas(1,1).getContext(`2d`)!==null}catch{}function m(e,t){return p?new OffscreenCanvas(e,t):In(`canvas`)}function h(e,t,n){let r=1,i=B(e);if((i.width>n||i.height>n)&&(r=n/Math.max(i.width,i.height)),r<1){if(typeof HTMLImageElement<`u`&&e instanceof HTMLImageElement||typeof HTMLCanvasElement<`u`&&e instanceof HTMLCanvasElement||typeof ImageBitmap<`u`&&e instanceof ImageBitmap||typeof VideoFrame<`u`&&e instanceof VideoFrame){let n=Math.floor(r*i.width),a=Math.floor(r*i.height);d===void 0&&(d=m(n,a));let o=t?m(n,a):d;return o.width=n,o.height=a,o.getContext(`2d`).drawImage(e,0,0,n,a),console.warn(`THREE.WebGLRenderer: Texture has been resized from (`+i.width+`x`+i.height+`) to (`+n+`x`+a+`).`),o}return`data`in e&&console.warn(`THREE.WebGLRenderer: Image in DataTexture is too big (`+i.width+`x`+i.height+`).`),e}return e}function g(e){return e.generateMipmaps&&e.minFilter!==1003&&e.minFilter!==1006}function _(t){e.generateMipmap(t)}function v(n,r,i,a,o=!1){if(n!==null){if(e[n]!==void 0)return e[n];console.warn(`THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '`+n+`'`)}let s=r;if(r===e.RED&&(i===e.FLOAT&&(s=e.R32F),i===e.HALF_FLOAT&&(s=e.R16F),i===e.UNSIGNED_BYTE&&(s=e.R8)),r===e.RED_INTEGER&&(i===e.UNSIGNED_BYTE&&(s=e.R8UI),i===e.UNSIGNED_SHORT&&(s=e.R16UI),i===e.UNSIGNED_INT&&(s=e.R32UI),i===e.BYTE&&(s=e.R8I),i===e.SHORT&&(s=e.R16I),i===e.INT&&(s=e.R32I)),r===e.RG&&(i===e.FLOAT&&(s=e.RG32F),i===e.HALF_FLOAT&&(s=e.RG16F),i===e.UNSIGNED_BYTE&&(s=e.RG8)),r===e.RG_INTEGER&&(i===e.UNSIGNED_BYTE&&(s=e.RG8UI),i===e.UNSIGNED_SHORT&&(s=e.RG16UI),i===e.UNSIGNED_INT&&(s=e.RG32UI),i===e.BYTE&&(s=e.RG8I),i===e.SHORT&&(s=e.RG16I),i===e.INT&&(s=e.RG32I)),r===e.RGB_INTEGER&&(i===e.UNSIGNED_BYTE&&(s=e.RGB8UI),i===e.UNSIGNED_SHORT&&(s=e.RGB16UI),i===e.UNSIGNED_INT&&(s=e.RGB32UI),i===e.BYTE&&(s=e.RGB8I),i===e.SHORT&&(s=e.RGB16I),i===e.INT&&(s=e.RGB32I)),r===e.RGBA_INTEGER&&(i===e.UNSIGNED_BYTE&&(s=e.RGBA8UI),i===e.UNSIGNED_SHORT&&(s=e.RGBA16UI),i===e.UNSIGNED_INT&&(s=e.RGBA32UI),i===e.BYTE&&(s=e.RGBA8I),i===e.SHORT&&(s=e.RGBA16I),i===e.INT&&(s=e.RGBA32I)),r===e.RGB&&i===e.UNSIGNED_INT_5_9_9_9_REV&&(s=e.RGB9_E5),r===e.RGBA){let t=o?en:qn.getTransfer(a);i===e.FLOAT&&(s=e.RGBA32F),i===e.HALF_FLOAT&&(s=e.RGBA16F),i===e.UNSIGNED_BYTE&&(s=t===`srgb`?e.SRGB8_ALPHA8:e.RGBA8),i===e.UNSIGNED_SHORT_4_4_4_4&&(s=e.RGBA4),i===e.UNSIGNED_SHORT_5_5_5_1&&(s=e.RGB5_A1)}return(s===e.R16F||s===e.R32F||s===e.RG16F||s===e.RG32F||s===e.RGBA16F||s===e.RGBA32F)&&t.get(`EXT_color_buffer_float`),s}function y(t,n){let r;return t?n===null||n===1014||n===1020?r=e.DEPTH24_STENCIL8:n===1015?r=e.DEPTH32F_STENCIL8:n===1012&&(r=e.DEPTH24_STENCIL8,console.warn(`DepthTexture: 16 bit depth attachment is not supported with stencil. Using 24-bit attachment.`)):n===null||n===1014||n===1020?r=e.DEPTH_COMPONENT24:n===1015?r=e.DEPTH_COMPONENT32F:n===1012&&(r=e.DEPTH_COMPONENT16),r}function b(e,t){return g(e)===!0||e.isFramebufferTexture&&e.minFilter!==1003&&e.minFilter!==1006?Math.log2(Math.max(t.width,t.height))+1:e.mipmaps!==void 0&&e.mipmaps.length>0?e.mipmaps.length:e.isCompressedTexture&&Array.isArray(e.image)?t.mipmaps.length:1}function x(e){let t=e.target;t.removeEventListener(`dispose`,x),C(t),t.isVideoTexture&&u.delete(t)}function S(e){let t=e.target;t.removeEventListener(`dispose`,S),T(t)}function C(e){let t=r.get(e);if(t.__webglInit===void 0)return;let n=e.source,i=f.get(n);if(i){let r=i[t.__cacheKey];r.usedTimes--,r.usedTimes===0&&w(e),Object.keys(i).length===0&&f.delete(n)}r.remove(e)}function w(t){let n=r.get(t);e.deleteTexture(n.__webglTexture);let i=t.source,a=f.get(i);delete a[n.__cacheKey],o.memory.textures--}function T(t){let n=r.get(t);if(t.depthTexture&&t.depthTexture.dispose(),t.isWebGLCubeRenderTarget)for(let t=0;t<6;t++){if(Array.isArray(n.__webglFramebuffer[t]))for(let r=0;r=i.maxTextures&&console.warn(`THREE.WebGLTextures: Trying to use `+e+` texture units while this GPU supports only `+i.maxTextures),E+=1,e}function k(e){let t=[];return t.push(e.wrapS),t.push(e.wrapT),t.push(e.wrapR||0),t.push(e.magFilter),t.push(e.minFilter),t.push(e.anisotropy),t.push(e.internalFormat),t.push(e.format),t.push(e.type),t.push(e.generateMipmaps),t.push(e.premultiplyAlpha),t.push(e.flipY),t.push(e.unpackAlignment),t.push(e.colorSpace),t.join()}function A(t,i){let a=r.get(t);if(t.isVideoTexture&&me(t),t.isRenderTargetTexture===!1&&t.version>0&&a.__version!==t.version){let e=t.image;if(e===null)console.warn(`THREE.WebGLRenderer: Texture marked for update but no image data found.`);else if(e.complete===!1)console.warn(`THREE.WebGLRenderer: Texture marked for update but image is incomplete`);else{ne(a,t,i);return}}n.bindTexture(e.TEXTURE_2D,a.__webglTexture,e.TEXTURE0+i)}function j(t,i){let a=r.get(t);if(t.version>0&&a.__version!==t.version){ne(a,t,i);return}n.bindTexture(e.TEXTURE_2D_ARRAY,a.__webglTexture,e.TEXTURE0+i)}function M(t,i){let a=r.get(t);if(t.version>0&&a.__version!==t.version){ne(a,t,i);return}n.bindTexture(e.TEXTURE_3D,a.__webglTexture,e.TEXTURE0+i)}function N(t,i){let a=r.get(t);if(t.version>0&&a.__version!==t.version){re(a,t,i);return}n.bindTexture(e.TEXTURE_CUBE_MAP,a.__webglTexture,e.TEXTURE0+i)}let P={[Ae]:e.REPEAT,[je]:e.CLAMP_TO_EDGE,[Me]:e.MIRRORED_REPEAT},F={[Ne]:e.NEAREST,[Pe]:e.NEAREST_MIPMAP_NEAREST,[Fe]:e.NEAREST_MIPMAP_LINEAR,[Ie]:e.LINEAR,[Le]:e.LINEAR_MIPMAP_NEAREST,[Re]:e.LINEAR_MIPMAP_LINEAR},I={512:e.NEVER,519:e.ALWAYS,513:e.LESS,515:e.LEQUAL,514:e.EQUAL,518:e.GEQUAL,516:e.GREATER,517:e.NOTEQUAL};function ee(n,a){if(a.type===1015&&t.has(`OES_texture_float_linear`)===!1&&(a.magFilter===1006||a.magFilter===1007||a.magFilter===1005||a.magFilter===1008||a.minFilter===1006||a.minFilter===1007||a.minFilter===1005||a.minFilter===1008)&&console.warn(`THREE.WebGLRenderer: Unable to use linear filtering with floating point textures. OES_texture_float_linear not supported on this device.`),e.texParameteri(n,e.TEXTURE_WRAP_S,P[a.wrapS]),e.texParameteri(n,e.TEXTURE_WRAP_T,P[a.wrapT]),(n===e.TEXTURE_3D||n===e.TEXTURE_2D_ARRAY)&&e.texParameteri(n,e.TEXTURE_WRAP_R,P[a.wrapR]),e.texParameteri(n,e.TEXTURE_MAG_FILTER,F[a.magFilter]),e.texParameteri(n,e.TEXTURE_MIN_FILTER,F[a.minFilter]),a.compareFunction&&(e.texParameteri(n,e.TEXTURE_COMPARE_MODE,e.COMPARE_REF_TO_TEXTURE),e.texParameteri(n,e.TEXTURE_COMPARE_FUNC,I[a.compareFunction])),t.has(`EXT_texture_filter_anisotropic`)===!0){if(a.magFilter===1003||a.minFilter!==1005&&a.minFilter!==1008||a.type===1015&&t.has(`OES_texture_float_linear`)===!1)return;if(a.anisotropy>1||r.get(a).__currentAnisotropy){let o=t.get(`EXT_texture_filter_anisotropic`);e.texParameterf(n,o.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(a.anisotropy,i.getMaxAnisotropy())),r.get(a).__currentAnisotropy=a.anisotropy}}}function te(t,n){let r=!1;t.__webglInit===void 0&&(t.__webglInit=!0,n.addEventListener(`dispose`,x));let i=n.source,a=f.get(i);a===void 0&&(a={},f.set(i,a));let s=k(n);if(s!==t.__cacheKey){a[s]===void 0&&(a[s]={texture:e.createTexture(),usedTimes:0},o.memory.textures++,r=!0),a[s].usedTimes++;let i=a[t.__cacheKey];i!==void 0&&(a[t.__cacheKey].usedTimes--,i.usedTimes===0&&w(n)),t.__cacheKey=s,t.__webglTexture=a[s].texture}return r}function ne(t,o,s){let c=e.TEXTURE_2D;(o.isDataArrayTexture||o.isCompressedArrayTexture)&&(c=e.TEXTURE_2D_ARRAY),o.isData3DTexture&&(c=e.TEXTURE_3D);let l=te(t,o),u=o.source;n.bindTexture(c,t.__webglTexture,e.TEXTURE0+s);let d=r.get(u);if(u.version!==d.__version||l===!0){n.activeTexture(e.TEXTURE0+s);let t=qn.getPrimaries(qn.workingColorSpace),r=o.colorSpace===``?null:qn.getPrimaries(o.colorSpace),f=o.colorSpace===``||t===r?e.NONE:e.BROWSER_DEFAULT_WEBGL;e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,o.flipY),e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL,o.premultiplyAlpha),e.pixelStorei(e.UNPACK_ALIGNMENT,o.unpackAlignment),e.pixelStorei(e.UNPACK_COLORSPACE_CONVERSION_WEBGL,f);let p=h(o.image,!1,i.maxTextureSize);p=z(o,p);let m=a.convert(o.format,o.colorSpace),x=a.convert(o.type),S=v(o.internalFormat,m,x,o.colorSpace,o.isVideoTexture);ee(c,o);let C,w=o.mipmaps,T=o.isVideoTexture!==!0,E=d.__version===void 0||l===!0,D=u.dataReady,O=b(o,p);if(o.isDepthTexture)S=y(o.format===rt,o.type),E&&(T?n.texStorage2D(e.TEXTURE_2D,1,S,p.width,p.height):n.texImage2D(e.TEXTURE_2D,0,S,p.width,p.height,0,m,x,null));else if(o.isDataTexture){if(w.length>0){T&&E&&n.texStorage2D(e.TEXTURE_2D,O,S,w[0].width,w[0].height);for(let t=0,r=w.length;t0){let r=Mc(C.width,C.height,o.format,o.type);for(let i of o.layerUpdates){let a=C.data.subarray(i*r/C.data.BYTES_PER_ELEMENT,(i+1)*r/C.data.BYTES_PER_ELEMENT);n.compressedTexSubImage3D(e.TEXTURE_2D_ARRAY,t,0,0,i,C.width,C.height,1,m,a,0,0)}o.clearLayerUpdates()}else n.compressedTexSubImage3D(e.TEXTURE_2D_ARRAY,t,0,0,0,C.width,C.height,p.depth,m,C.data,0,0)}}else n.compressedTexImage3D(e.TEXTURE_2D_ARRAY,t,S,C.width,C.height,p.depth,0,C.data,0,0)}else console.warn(`THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()`)}else T?D&&n.texSubImage3D(e.TEXTURE_2D_ARRAY,t,0,0,0,C.width,C.height,p.depth,m,x,C.data):n.texImage3D(e.TEXTURE_2D_ARRAY,t,S,C.width,C.height,p.depth,0,m,x,C.data)}else{T&&E&&n.texStorage2D(e.TEXTURE_2D,O,S,w[0].width,w[0].height);for(let t=0,r=w.length;t0){let t=Mc(p.width,p.height,o.format,o.type);for(let r of o.layerUpdates){let i=p.data.subarray(r*t/p.data.BYTES_PER_ELEMENT,(r+1)*t/p.data.BYTES_PER_ELEMENT);n.texSubImage3D(e.TEXTURE_2D_ARRAY,0,0,0,r,p.width,p.height,1,m,x,i)}o.clearLayerUpdates()}else n.texSubImage3D(e.TEXTURE_2D_ARRAY,0,0,0,0,p.width,p.height,p.depth,m,x,p.data)}}else n.texImage3D(e.TEXTURE_2D_ARRAY,0,S,p.width,p.height,p.depth,0,m,x,p.data)}else if(o.isData3DTexture)T?(E&&n.texStorage3D(e.TEXTURE_3D,O,S,p.width,p.height,p.depth),D&&n.texSubImage3D(e.TEXTURE_3D,0,0,0,0,p.width,p.height,p.depth,m,x,p.data)):n.texImage3D(e.TEXTURE_3D,0,S,p.width,p.height,p.depth,0,m,x,p.data);else if(o.isFramebufferTexture){if(E){if(T)n.texStorage2D(e.TEXTURE_2D,O,S,p.width,p.height);else{let t=p.width,r=p.height;for(let i=0;i>=1,r>>=1}}}else if(w.length>0){if(T&&E){let t=B(w[0]);n.texStorage2D(e.TEXTURE_2D,O,S,t.width,t.height)}for(let t=0,r=w.length;t0&&D++;let t=B(m[0]);n.texStorage2D(e.TEXTURE_CUBE_MAP,D,C,t.width,t.height)}for(let t=0;t<6;t++)if(p){w?E&&n.texSubImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+t,0,0,0,m[t].width,m[t].height,x,S,m[t].data):n.texImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+t,0,C,m[t].width,m[t].height,0,x,S,m[t].data);for(let r=0;r>u),r=Math.max(1,i.height>>u);l===e.TEXTURE_3D||l===e.TEXTURE_2D_ARRAY?n.texImage3D(l,u,p,t,r,i.depth,0,d,f,null):n.texImage2D(l,u,p,t,r,0,d,f,null)}n.bindFramebuffer(e.FRAMEBUFFER,t),R(i)?s.framebufferTexture2DMultisampleEXT(e.FRAMEBUFFER,c,l,r.get(o).__webglTexture,0,pe(i)):(l===e.TEXTURE_2D||l>=e.TEXTURE_CUBE_MAP_POSITIVE_X&&l<=e.TEXTURE_CUBE_MAP_NEGATIVE_Z)&&e.framebufferTexture2D(e.FRAMEBUFFER,c,l,r.get(o).__webglTexture,u),n.bindFramebuffer(e.FRAMEBUFFER,null)}function ae(t,n,r){if(e.bindRenderbuffer(e.RENDERBUFFER,t),n.depthBuffer){let i=n.depthTexture,a=i&&i.isDepthTexture?i.type:null,o=y(n.stencilBuffer,a),c=n.stencilBuffer?e.DEPTH_STENCIL_ATTACHMENT:e.DEPTH_ATTACHMENT,l=pe(n);R(n)?s.renderbufferStorageMultisampleEXT(e.RENDERBUFFER,l,o,n.width,n.height):r?e.renderbufferStorageMultisample(e.RENDERBUFFER,l,o,n.width,n.height):e.renderbufferStorage(e.RENDERBUFFER,o,n.width,n.height),e.framebufferRenderbuffer(e.FRAMEBUFFER,c,e.RENDERBUFFER,t)}else{let t=n.textures;for(let i=0;i{delete i.__boundDepthTexture,delete i.__depthDisposeCallback,e.removeEventListener(`dispose`,t)};e.addEventListener(`dispose`,t),i.__depthDisposeCallback=t}i.__boundDepthTexture=e}if(t.depthTexture&&!i.__autoAllocateDepthBuffer){if(a)throw Error(`target.depthTexture not supported in Cube render targets`);oe(i.__webglFramebuffer,t)}else if(a){i.__webglDepthbuffer=[];for(let r=0;r<6;r++)if(n.bindFramebuffer(e.FRAMEBUFFER,i.__webglFramebuffer[r]),i.__webglDepthbuffer[r]===void 0)i.__webglDepthbuffer[r]=e.createRenderbuffer(),ae(i.__webglDepthbuffer[r],t,!1);else{let n=t.stencilBuffer?e.DEPTH_STENCIL_ATTACHMENT:e.DEPTH_ATTACHMENT,a=i.__webglDepthbuffer[r];e.bindRenderbuffer(e.RENDERBUFFER,a),e.framebufferRenderbuffer(e.FRAMEBUFFER,n,e.RENDERBUFFER,a)}}else if(n.bindFramebuffer(e.FRAMEBUFFER,i.__webglFramebuffer),i.__webglDepthbuffer===void 0)i.__webglDepthbuffer=e.createRenderbuffer(),ae(i.__webglDepthbuffer,t,!1);else{let n=t.stencilBuffer?e.DEPTH_STENCIL_ATTACHMENT:e.DEPTH_ATTACHMENT,r=i.__webglDepthbuffer;e.bindRenderbuffer(e.RENDERBUFFER,r),e.framebufferRenderbuffer(e.FRAMEBUFFER,n,e.RENDERBUFFER,r)}n.bindFramebuffer(e.FRAMEBUFFER,null)}function ce(t,n,i){let a=r.get(t);n!==void 0&&ie(a.__webglFramebuffer,t,t.texture,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,0),i!==void 0&&se(t)}function le(t){let i=t.texture,s=r.get(t),c=r.get(i);t.addEventListener(`dispose`,S);let l=t.textures,u=t.isWebGLCubeRenderTarget===!0,d=l.length>1;if(d||(c.__webglTexture===void 0&&(c.__webglTexture=e.createTexture()),c.__version=i.version,o.memory.textures++),u){s.__webglFramebuffer=[];for(let t=0;t<6;t++)if(i.mipmaps&&i.mipmaps.length>0){s.__webglFramebuffer[t]=[];for(let n=0;n0){s.__webglFramebuffer=[];for(let t=0;t0&&R(t)===!1){s.__webglMultisampledFramebuffer=e.createFramebuffer(),s.__webglColorRenderbuffer=[],n.bindFramebuffer(e.FRAMEBUFFER,s.__webglMultisampledFramebuffer);for(let n=0;n0)for(let r=0;r0)for(let n=0;n0){if(R(t)===!1){let i=t.textures,a=t.width,o=t.height,s=e.COLOR_BUFFER_BIT,l=t.stencilBuffer?e.DEPTH_STENCIL_ATTACHMENT:e.DEPTH_ATTACHMENT,u=r.get(t),d=i.length>1;if(d)for(let t=0;t0&&t.has(`WEBGL_multisampled_render_to_texture`)===!0&&n.__useRenderToTexture!==!1}function me(e){let t=o.render.frame;u.get(e)!==t&&(u.set(e,t),e.update())}function z(e,t){let n=e.colorSpace,r=e.format,i=e.type;return e.isCompressedTexture===!0||e.isVideoTexture===!0||n!==`srgb-linear`&&n!==``&&(qn.getTransfer(n)===`srgb`?(r!==1023||i!==1009)&&console.warn(`THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType.`):console.error(`THREE.WebGLTextures: Unsupported texture color space:`,n)),t}function B(e){return typeof HTMLImageElement<`u`&&e instanceof HTMLImageElement?(l.width=e.naturalWidth||e.width,l.height=e.naturalHeight||e.height):typeof VideoFrame<`u`&&e instanceof VideoFrame?(l.width=e.displayWidth,l.height=e.displayHeight):(l.width=e.width,l.height=e.height),l}this.allocateTextureUnit=O,this.resetTextureUnits=D,this.setTexture2D=A,this.setTexture2DArray=j,this.setTexture3D=M,this.setTextureCube=N,this.rebindTextures=ce,this.setupRenderTarget=le,this.updateRenderTargetMipmap=ue,this.updateMultisampleRenderTarget=fe,this.setupDepthRenderbuffer=se,this.setupFrameBufferTexture=ie,this.useMultisampledRTT=R}function Fc(e,t){function n(n,r=``){let i,a=qn.getTransfer(r);if(n===1009)return e.UNSIGNED_BYTE;if(n===1017)return e.UNSIGNED_SHORT_4_4_4_4;if(n===1018)return e.UNSIGNED_SHORT_5_5_5_1;if(n===35902)return e.UNSIGNED_INT_5_9_9_9_REV;if(n===1010)return e.BYTE;if(n===1011)return e.SHORT;if(n===1012)return e.UNSIGNED_SHORT;if(n===1013)return e.INT;if(n===1014)return e.UNSIGNED_INT;if(n===1015)return e.FLOAT;if(n===1016)return e.HALF_FLOAT;if(n===1021)return e.ALPHA;if(n===1022)return e.RGB;if(n===1023)return e.RGBA;if(n===1024)return e.LUMINANCE;if(n===1025)return e.LUMINANCE_ALPHA;if(n===1026)return e.DEPTH_COMPONENT;if(n===1027)return e.DEPTH_STENCIL;if(n===1028)return e.RED;if(n===1029)return e.RED_INTEGER;if(n===1030)return e.RG;if(n===1031)return e.RG_INTEGER;if(n===1033)return e.RGBA_INTEGER;if(n===33776||n===33777||n===33778||n===33779){if(a===`srgb`){if(i=t.get(`WEBGL_compressed_texture_s3tc_srgb`),i!==null){if(n===33776)return i.COMPRESSED_SRGB_S3TC_DXT1_EXT;if(n===33777)return i.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;if(n===33778)return i.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;if(n===33779)return i.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT}else return null}else if(i=t.get(`WEBGL_compressed_texture_s3tc`),i!==null){if(n===33776)return i.COMPRESSED_RGB_S3TC_DXT1_EXT;if(n===33777)return i.COMPRESSED_RGBA_S3TC_DXT1_EXT;if(n===33778)return i.COMPRESSED_RGBA_S3TC_DXT3_EXT;if(n===33779)return i.COMPRESSED_RGBA_S3TC_DXT5_EXT}else return null}if(n===35840||n===35841||n===35842||n===35843){if(i=t.get(`WEBGL_compressed_texture_pvrtc`),i!==null){if(n===35840)return i.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;if(n===35841)return i.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;if(n===35842)return i.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;if(n===35843)return i.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG}else return null}if(n===36196||n===37492||n===37496){if(i=t.get(`WEBGL_compressed_texture_etc`),i!==null){if(n===36196||n===37492)return a===`srgb`?i.COMPRESSED_SRGB8_ETC2:i.COMPRESSED_RGB8_ETC2;if(n===37496)return a===`srgb`?i.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:i.COMPRESSED_RGBA8_ETC2_EAC}else return null}if(n===37808||n===37809||n===37810||n===37811||n===37812||n===37813||n===37814||n===37815||n===37816||n===37817||n===37818||n===37819||n===37820||n===37821){if(i=t.get(`WEBGL_compressed_texture_astc`),i!==null){if(n===37808)return a===`srgb`?i.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:i.COMPRESSED_RGBA_ASTC_4x4_KHR;if(n===37809)return a===`srgb`?i.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:i.COMPRESSED_RGBA_ASTC_5x4_KHR;if(n===37810)return a===`srgb`?i.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:i.COMPRESSED_RGBA_ASTC_5x5_KHR;if(n===37811)return a===`srgb`?i.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:i.COMPRESSED_RGBA_ASTC_6x5_KHR;if(n===37812)return a===`srgb`?i.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:i.COMPRESSED_RGBA_ASTC_6x6_KHR;if(n===37813)return a===`srgb`?i.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:i.COMPRESSED_RGBA_ASTC_8x5_KHR;if(n===37814)return a===`srgb`?i.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:i.COMPRESSED_RGBA_ASTC_8x6_KHR;if(n===37815)return a===`srgb`?i.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:i.COMPRESSED_RGBA_ASTC_8x8_KHR;if(n===37816)return a===`srgb`?i.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:i.COMPRESSED_RGBA_ASTC_10x5_KHR;if(n===37817)return a===`srgb`?i.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:i.COMPRESSED_RGBA_ASTC_10x6_KHR;if(n===37818)return a===`srgb`?i.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:i.COMPRESSED_RGBA_ASTC_10x8_KHR;if(n===37819)return a===`srgb`?i.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:i.COMPRESSED_RGBA_ASTC_10x10_KHR;if(n===37820)return a===`srgb`?i.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:i.COMPRESSED_RGBA_ASTC_12x10_KHR;if(n===37821)return a===`srgb`?i.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:i.COMPRESSED_RGBA_ASTC_12x12_KHR}else return null}if(n===36492||n===36494||n===36495){if(i=t.get(`EXT_texture_compression_bptc`),i!==null){if(n===36492)return a===`srgb`?i.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:i.COMPRESSED_RGBA_BPTC_UNORM_EXT;if(n===36494)return i.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT;if(n===36495)return i.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT}else return null}if(n===36283||n===36284||n===36285||n===36286){if(i=t.get(`EXT_texture_compression_rgtc`),i!==null){if(n===36492)return i.COMPRESSED_RED_RGTC1_EXT;if(n===36284)return i.COMPRESSED_SIGNED_RED_RGTC1_EXT;if(n===36285)return i.COMPRESSED_RED_GREEN_RGTC2_EXT;if(n===36286)return i.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT}else return null}return n===1020?e.UNSIGNED_INT_24_8:e[n]===void 0?null:e[n]}return{convert:n}}var Ic=class extends wa{constructor(e=[]){super(),this.isArrayCamera=!0,this.cameras=e}},Lc=class extends ui{constructor(){super(),this.isGroup=!0,this.type=`Group`}},Rc={type:`move`},zc=class{constructor(){this._targetRay=null,this._grip=null,this._hand=null}getHandSpace(){return this._hand===null&&(this._hand=new Lc,this._hand.matrixAutoUpdate=!1,this._hand.visible=!1,this._hand.joints={},this._hand.inputState={pinching:!1}),this._hand}getTargetRaySpace(){return this._targetRay===null&&(this._targetRay=new Lc,this._targetRay.matrixAutoUpdate=!1,this._targetRay.visible=!1,this._targetRay.hasLinearVelocity=!1,this._targetRay.linearVelocity=new W,this._targetRay.hasAngularVelocity=!1,this._targetRay.angularVelocity=new W),this._targetRay}getGripSpace(){return this._grip===null&&(this._grip=new Lc,this._grip.matrixAutoUpdate=!1,this._grip.visible=!1,this._grip.hasLinearVelocity=!1,this._grip.linearVelocity=new W,this._grip.hasAngularVelocity=!1,this._grip.angularVelocity=new W),this._grip}dispatchEvent(e){return this._targetRay!==null&&this._targetRay.dispatchEvent(e),this._grip!==null&&this._grip.dispatchEvent(e),this._hand!==null&&this._hand.dispatchEvent(e),this}connect(e){if(e&&e.hand){let t=this._hand;if(t)for(let n of e.hand.values())this._getHandJoint(t,n)}return this.dispatchEvent({type:`connected`,data:e}),this}disconnect(e){return this.dispatchEvent({type:`disconnected`,data:e}),this._targetRay!==null&&(this._targetRay.visible=!1),this._grip!==null&&(this._grip.visible=!1),this._hand!==null&&(this._hand.visible=!1),this}update(e,t,n){let r=null,i=null,a=null,o=this._targetRay,s=this._grip,c=this._hand;if(e&&t.session.visibilityState!==`visible-blurred`){if(c&&e.hand){a=!0;for(let r of e.hand.values()){let e=t.getJointPose(r,n),i=this._getHandJoint(c,r);e!==null&&(i.matrix.fromArray(e.transform.matrix),i.matrix.decompose(i.position,i.rotation,i.scale),i.matrixWorldNeedsUpdate=!0,i.jointRadius=e.radius),i.visible=e!==null}let r=c.joints[`index-finger-tip`],i=c.joints[`thumb-tip`],o=r.position.distanceTo(i.position);c.inputState.pinching&&o>.025?(c.inputState.pinching=!1,this.dispatchEvent({type:`pinchend`,handedness:e.handedness,target:this})):!c.inputState.pinching&&o<=.015&&(c.inputState.pinching=!0,this.dispatchEvent({type:`pinchstart`,handedness:e.handedness,target:this}))}else s!==null&&e.gripSpace&&(i=t.getPose(e.gripSpace,n),i!==null&&(s.matrix.fromArray(i.transform.matrix),s.matrix.decompose(s.position,s.rotation,s.scale),s.matrixWorldNeedsUpdate=!0,i.linearVelocity?(s.hasLinearVelocity=!0,s.linearVelocity.copy(i.linearVelocity)):s.hasLinearVelocity=!1,i.angularVelocity?(s.hasAngularVelocity=!0,s.angularVelocity.copy(i.angularVelocity)):s.hasAngularVelocity=!1));o!==null&&(r=t.getPose(e.targetRaySpace,n),r===null&&i!==null&&(r=i),r!==null&&(o.matrix.fromArray(r.transform.matrix),o.matrix.decompose(o.position,o.rotation,o.scale),o.matrixWorldNeedsUpdate=!0,r.linearVelocity?(o.hasLinearVelocity=!0,o.linearVelocity.copy(r.linearVelocity)):o.hasLinearVelocity=!1,r.angularVelocity?(o.hasAngularVelocity=!0,o.angularVelocity.copy(r.angularVelocity)):o.hasAngularVelocity=!1,this.dispatchEvent(Rc)))}return o!==null&&(o.visible=r!==null),s!==null&&(s.visible=i!==null),c!==null&&(c.visible=a!==null),this}_getHandJoint(e,t){if(e.joints[t.jointName]===void 0){let n=new Lc;n.matrixAutoUpdate=!1,n.visible=!1,e.joints[t.jointName]=n,e.add(n)}return e.joints[t.jointName]}},Bc=` +void main() { + + gl_Position = vec4( position, 1.0 ); + +}`,Vc=` +uniform sampler2DArray depthColor; +uniform float depthWidth; +uniform float depthHeight; + +void main() { + + vec2 coord = vec2( gl_FragCoord.x / depthWidth, gl_FragCoord.y / depthHeight ); + + if ( coord.x >= 1.0 ) { + + gl_FragDepth = texture( depthColor, vec3( coord.x - 1.0, coord.y, 1 ) ).r; + + } else { + + gl_FragDepth = texture( depthColor, vec3( coord.x, coord.y, 0 ) ).r; + + } + +}`,Hc=class{constructor(){this.texture=null,this.mesh=null,this.depthNear=0,this.depthFar=0}init(e,t,n){if(this.texture===null){let r=new nr,i=e.properties.get(r);i.__webglTexture=t.texture,(t.depthNear!=n.depthNear||t.depthFar!=n.depthFar)&&(this.depthNear=t.depthNear,this.depthFar=t.depthFar),this.texture=r}}getMesh(e){if(this.texture!==null&&this.mesh===null){let t=e.cameras[0].viewport,n=new ya({vertexShader:Bc,fragmentShader:Vc,uniforms:{depthColor:{value:this.texture},depthWidth:{value:t.z},depthHeight:{value:t.w}}});this.mesh=new q(new za(20,20),n)}return this.mesh}reset(){this.texture=null,this.mesh=null}getDepthTexture(){return this.texture}},Uc=class extends sn{constructor(e,t){super();let n=this,r=null,i=1,a=null,o=`local-floor`,s=1,c=null,l=null,u=null,d=null,f=null,p=null,m=new Hc,h=t.getContextAttributes(),g=null,_=null,v=[],y=[],b=new H,x=null,S=new wa;S.layers.enable(1),S.viewport=new rr;let C=new wa;C.layers.enable(2),C.viewport=new rr;let w=[S,C],T=new Ic;T.layers.enable(1),T.layers.enable(2);let E=null,D=null;this.cameraAutoUpdate=!0,this.enabled=!1,this.isPresenting=!1,this.getController=function(e){let t=v[e];return t===void 0&&(t=new zc,v[e]=t),t.getTargetRaySpace()},this.getControllerGrip=function(e){let t=v[e];return t===void 0&&(t=new zc,v[e]=t),t.getGripSpace()},this.getHand=function(e){let t=v[e];return t===void 0&&(t=new zc,v[e]=t),t.getHandSpace()};function O(e){let t=y.indexOf(e.inputSource);if(t===-1)return;let n=v[t];n!==void 0&&(n.update(e.inputSource,e.frame,c||a),n.dispatchEvent({type:e.type,data:e.inputSource}))}function k(){r.removeEventListener(`select`,O),r.removeEventListener(`selectstart`,O),r.removeEventListener(`selectend`,O),r.removeEventListener(`squeeze`,O),r.removeEventListener(`squeezestart`,O),r.removeEventListener(`squeezeend`,O),r.removeEventListener(`end`,k),r.removeEventListener(`inputsourceschange`,A);for(let e=0;e=0&&(y[r]=null,v[r].disconnect(n))}for(let t=0;t=y.length){y.push(n),r=e;break}else if(y[e]===null){y[e]=n,r=e;break}if(r===-1)break}let i=v[r];i&&i.connect(n)}}let j=new W,M=new W;function N(e,t,n){j.setFromMatrixPosition(t.matrixWorld),M.setFromMatrixPosition(n.matrixWorld);let r=j.distanceTo(M),i=t.projectionMatrix.elements,a=n.projectionMatrix.elements,o=i[14]/(i[10]-1),s=i[14]/(i[10]+1),c=(i[9]+1)/i[5],l=(i[9]-1)/i[5],u=(i[8]-1)/i[0],d=(a[8]+1)/a[0],f=o*u,p=o*d,m=r/(-u+d),h=m*-u;if(t.matrixWorld.decompose(e.position,e.quaternion,e.scale),e.translateX(h),e.translateZ(m),e.matrixWorld.compose(e.position,e.quaternion,e.scale),e.matrixWorldInverse.copy(e.matrixWorld).invert(),i[10]===-1)e.projectionMatrix.copy(t.projectionMatrix),e.projectionMatrixInverse.copy(t.projectionMatrixInverse);else{let t=o+m,n=s+m,i=f-h,a=p+(r-h),u=c*s/n*t,d=l*s/n*t;e.projectionMatrix.makePerspective(i,a,u,d,t,n),e.projectionMatrixInverse.copy(e.projectionMatrix).invert()}}function P(e,t){t===null?e.matrixWorld.copy(e.matrix):e.matrixWorld.multiplyMatrices(t.matrixWorld,e.matrix),e.matrixWorldInverse.copy(e.matrixWorld).invert()}this.updateCamera=function(e){if(r===null)return;let t=e.near,n=e.far;m.texture!==null&&(m.depthNear>0&&(t=m.depthNear),m.depthFar>0&&(n=m.depthFar)),T.near=C.near=S.near=t,T.far=C.far=S.far=n,(E!==T.near||D!==T.far)&&(r.updateRenderState({depthNear:T.near,depthFar:T.far}),E=T.near,D=T.far);let i=e.parent,a=T.cameras;P(T,i);for(let e=0;e0&&(e.alphaTest.value=r.alphaTest);let i=t.get(r),a=i.envMap,o=i.envMapRotation;a&&(e.envMap.value=a,Wc.copy(o),Wc.x*=-1,Wc.y*=-1,Wc.z*=-1,a.isCubeTexture&&a.isRenderTargetTexture===!1&&(Wc.y*=-1,Wc.z*=-1),e.envMapRotation.value.setFromMatrix4(Gc.makeRotationFromEuler(Wc)),e.flipEnvMap.value=a.isCubeTexture&&a.isRenderTargetTexture===!1?-1:1,e.reflectivity.value=r.reflectivity,e.ior.value=r.ior,e.refractionRatio.value=r.refractionRatio),r.lightMap&&(e.lightMap.value=r.lightMap,e.lightMapIntensity.value=r.lightMapIntensity,n(r.lightMap,e.lightMapTransform)),r.aoMap&&(e.aoMap.value=r.aoMap,e.aoMapIntensity.value=r.aoMapIntensity,n(r.aoMap,e.aoMapTransform))}function o(e,t){e.diffuse.value.copy(t.color),e.opacity.value=t.opacity,t.map&&(e.map.value=t.map,n(t.map,e.mapTransform))}function s(e,t){e.dashSize.value=t.dashSize,e.totalSize.value=t.dashSize+t.gapSize,e.scale.value=t.scale}function c(e,t,r,i){e.diffuse.value.copy(t.color),e.opacity.value=t.opacity,e.size.value=t.size*r,e.scale.value=i*.5,t.map&&(e.map.value=t.map,n(t.map,e.uvTransform)),t.alphaMap&&(e.alphaMap.value=t.alphaMap,n(t.alphaMap,e.alphaMapTransform)),t.alphaTest>0&&(e.alphaTest.value=t.alphaTest)}function l(e,t){e.diffuse.value.copy(t.color),e.opacity.value=t.opacity,e.rotation.value=t.rotation,t.map&&(e.map.value=t.map,n(t.map,e.mapTransform)),t.alphaMap&&(e.alphaMap.value=t.alphaMap,n(t.alphaMap,e.alphaMapTransform)),t.alphaTest>0&&(e.alphaTest.value=t.alphaTest)}function u(e,t){e.specular.value.copy(t.specular),e.shininess.value=Math.max(t.shininess,1e-4)}function d(e,t){t.gradientMap&&(e.gradientMap.value=t.gradientMap)}function f(e,t){e.metalness.value=t.metalness,t.metalnessMap&&(e.metalnessMap.value=t.metalnessMap,n(t.metalnessMap,e.metalnessMapTransform)),e.roughness.value=t.roughness,t.roughnessMap&&(e.roughnessMap.value=t.roughnessMap,n(t.roughnessMap,e.roughnessMapTransform)),t.envMap&&(e.envMapIntensity.value=t.envMapIntensity)}function p(e,t,r){e.ior.value=t.ior,t.sheen>0&&(e.sheenColor.value.copy(t.sheenColor).multiplyScalar(t.sheen),e.sheenRoughness.value=t.sheenRoughness,t.sheenColorMap&&(e.sheenColorMap.value=t.sheenColorMap,n(t.sheenColorMap,e.sheenColorMapTransform)),t.sheenRoughnessMap&&(e.sheenRoughnessMap.value=t.sheenRoughnessMap,n(t.sheenRoughnessMap,e.sheenRoughnessMapTransform))),t.clearcoat>0&&(e.clearcoat.value=t.clearcoat,e.clearcoatRoughness.value=t.clearcoatRoughness,t.clearcoatMap&&(e.clearcoatMap.value=t.clearcoatMap,n(t.clearcoatMap,e.clearcoatMapTransform)),t.clearcoatRoughnessMap&&(e.clearcoatRoughnessMap.value=t.clearcoatRoughnessMap,n(t.clearcoatRoughnessMap,e.clearcoatRoughnessMapTransform)),t.clearcoatNormalMap&&(e.clearcoatNormalMap.value=t.clearcoatNormalMap,n(t.clearcoatNormalMap,e.clearcoatNormalMapTransform),e.clearcoatNormalScale.value.copy(t.clearcoatNormalScale),t.side===1&&e.clearcoatNormalScale.value.negate())),t.dispersion>0&&(e.dispersion.value=t.dispersion),t.iridescence>0&&(e.iridescence.value=t.iridescence,e.iridescenceIOR.value=t.iridescenceIOR,e.iridescenceThicknessMinimum.value=t.iridescenceThicknessRange[0],e.iridescenceThicknessMaximum.value=t.iridescenceThicknessRange[1],t.iridescenceMap&&(e.iridescenceMap.value=t.iridescenceMap,n(t.iridescenceMap,e.iridescenceMapTransform)),t.iridescenceThicknessMap&&(e.iridescenceThicknessMap.value=t.iridescenceThicknessMap,n(t.iridescenceThicknessMap,e.iridescenceThicknessMapTransform))),t.transmission>0&&(e.transmission.value=t.transmission,e.transmissionSamplerMap.value=r.texture,e.transmissionSamplerSize.value.set(r.width,r.height),t.transmissionMap&&(e.transmissionMap.value=t.transmissionMap,n(t.transmissionMap,e.transmissionMapTransform)),e.thickness.value=t.thickness,t.thicknessMap&&(e.thicknessMap.value=t.thicknessMap,n(t.thicknessMap,e.thicknessMapTransform)),e.attenuationDistance.value=t.attenuationDistance,e.attenuationColor.value.copy(t.attenuationColor)),t.anisotropy>0&&(e.anisotropyVector.value.set(t.anisotropy*Math.cos(t.anisotropyRotation),t.anisotropy*Math.sin(t.anisotropyRotation)),t.anisotropyMap&&(e.anisotropyMap.value=t.anisotropyMap,n(t.anisotropyMap,e.anisotropyMapTransform))),e.specularIntensity.value=t.specularIntensity,e.specularColor.value.copy(t.specularColor),t.specularColorMap&&(e.specularColorMap.value=t.specularColorMap,n(t.specularColorMap,e.specularColorMapTransform)),t.specularIntensityMap&&(e.specularIntensityMap.value=t.specularIntensityMap,n(t.specularIntensityMap,e.specularIntensityMapTransform))}function m(e,t){t.matcap&&(e.matcap.value=t.matcap)}function h(e,n){let r=t.get(n).light;e.referencePosition.value.setFromMatrixPosition(r.matrixWorld),e.nearDistance.value=r.shadow.camera.near,e.farDistance.value=r.shadow.camera.far}return{refreshFogUniforms:r,refreshMaterialUniforms:i}}function qc(e,t,n,r){let i={},a={},o=[],s=e.getParameter(e.MAX_UNIFORM_BUFFER_BINDINGS);function c(e,t){let n=t.program;r.uniformBlockBinding(e,n)}function l(e,n){let o=i[e.id];o===void 0&&(m(e),o=u(e),i[e.id]=o,e.addEventListener(`dispose`,g));let s=n.program;r.updateUBOMapping(e,s);let c=t.render.frame;a[e.id]!==c&&(f(e),a[e.id]=c)}function u(t){let n=d();t.__bindingPointIndex=n;let r=e.createBuffer(),i=t.__size,a=t.usage;return e.bindBuffer(e.UNIFORM_BUFFER,r),e.bufferData(e.UNIFORM_BUFFER,i,a),e.bindBuffer(e.UNIFORM_BUFFER,null),e.bindBufferBase(e.UNIFORM_BUFFER,n,r),r}function d(){for(let e=0;e0&&(n+=16-r),e.__size=n,e.__cache={},this}function h(e){let t={boundary:0,storage:0};return typeof e==`number`||typeof e==`boolean`?(t.boundary=4,t.storage=4):e.isVector2?(t.boundary=8,t.storage=8):e.isVector3||e.isColor?(t.boundary=16,t.storage=12):e.isVector4?(t.boundary=16,t.storage=16):e.isMatrix3?(t.boundary=48,t.storage=48):e.isMatrix4?(t.boundary=64,t.storage=64):e.isTexture?console.warn(`THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group.`):console.warn(`THREE.WebGLRenderer: Unsupported uniform value type.`,e),t}function g(t){let n=t.target;n.removeEventListener(`dispose`,g);let r=o.indexOf(n.__bindingPointIndex);o.splice(r,1),e.deleteBuffer(i[n.id]),delete i[n.id],delete a[n.id]}function _(){for(let t in i)e.deleteBuffer(i[t]);o=[],i={},a={}}return{bind:c,update:l,dispose:_}}var Jc=class{constructor(e={}){let{canvas:t=Ln(),context:n=null,depth:r=!0,stencil:i=!1,alpha:a=!1,antialias:o=!1,premultipliedAlpha:s=!0,preserveDrawingBuffer:c=!1,powerPreference:l=`default`,failIfMajorPerformanceCaveat:u=!1}=e;this.isWebGLRenderer=!0;let d;if(n!==null){if(typeof WebGLRenderingContext<`u`&&n instanceof WebGLRenderingContext)throw Error(`THREE.WebGLRenderer: WebGL 1 is not supported since r163.`);d=n.getContextAttributes().alpha}else d=a;let f=new Uint32Array(4),p=new Int32Array(4),m=null,h=null,g=[],_=[];this.domElement=t,this.debug={checkShaderErrors:!0,onShaderError:null},this.autoClear=!0,this.autoClearColor=!0,this.autoClearDepth=!0,this.autoClearStencil=!0,this.sortObjects=!0,this.clippingPlanes=[],this.localClippingEnabled=!1,this._outputColorSpace=Xt,this.toneMapping=0,this.toneMappingExposure=1;let v=this,y=!1,b=0,x=0,S=null,C=-1,w=null,T=new rr,E=new rr,D=null,O=new K(0),k=0,A=t.width,j=t.height,M=1,N=null,P=null,F=new rr(0,0,A,j),I=new rr(0,0,A,j),ee=!1,te=new Ia,ne=!1,re=!1,ie=new G,ae=new G,oe=new W,se=new rr,ce={background:null,fog:null,environment:null,overrideMaterial:null,isScene:!0},le=!1;function ue(){return S===null?M:1}let L=n;function de(e,n){return t.getContext(e,n)}try{let e={alpha:!0,depth:r,stencil:i,antialias:o,premultipliedAlpha:s,preserveDrawingBuffer:c,powerPreference:l,failIfMajorPerformanceCaveat:u};if(`setAttribute`in t&&t.setAttribute(`data-engine`,`three.js r169`),t.addEventListener(`webglcontextlost`,Fe,!1),t.addEventListener(`webglcontextrestored`,Ie,!1),t.addEventListener(`webglcontextcreationerror`,Le,!1),L===null){let t=`webgl2`;if(L=de(t,e),L===null)throw de(t)?Error(`Error creating WebGL context with your selected attributes.`):Error(`Error creating WebGL context.`)}}catch(e){throw console.error(`THREE.WebGLRenderer: `+e.message),e}let fe,pe,R,me,z,B,he,ge,_e,ve,ye,be,xe,Se,Ce,we,Te,Ee,De,Oe,ke,Ae,je,Me;function Ne(){fe=new yo(L),fe.init(),Ae=new Fc(L,fe),pe=new qa(L,fe,e,Ae),R=new jc(L),pe.reverseDepthBuffer&&R.buffers.depth.setReversed(!0),me=new So(L),z=new pc,B=new Pc(L,fe,R,z,pe,Ae,me),he=new Ya(v),ge=new vo(v),_e=new Ra(L),je=new Ga(L,_e),ve=new bo(L,_e,me,je),ye=new wo(L,ve,_e,me),De=new Co(L,pe,B),we=new Ja(z),be=new fc(v,he,ge,fe,pe,je,we),xe=new Kc(v,z),Se=new _c,Ce=new wc(fe),Ee=new Wa(v,he,ge,R,ye,d,s),Te=new kc(v,ye,pe),Me=new qc(L,me,pe,R),Oe=new Ka(L,fe,me),ke=new xo(L,fe,me),me.programs=be.programs,v.capabilities=pe,v.extensions=fe,v.properties=z,v.renderLists=Se,v.shadowMap=Te,v.state=R,v.info=me}Ne();let Pe=new Uc(v,L);this.xr=Pe,this.getContext=function(){return L},this.getContextAttributes=function(){return L.getContextAttributes()},this.forceContextLoss=function(){let e=fe.get(`WEBGL_lose_context`);e&&e.loseContext()},this.forceContextRestore=function(){let e=fe.get(`WEBGL_lose_context`);e&&e.restoreContext()},this.getPixelRatio=function(){return M},this.setPixelRatio=function(e){e!==void 0&&(M=e,this.setSize(A,j,!1))},this.getSize=function(e){return e.set(A,j)},this.setSize=function(e,n,r=!0){if(Pe.isPresenting){console.warn(`THREE.WebGLRenderer: Can't change size while VR device is presenting.`);return}A=e,j=n,t.width=Math.floor(e*M),t.height=Math.floor(n*M),r===!0&&(t.style.width=e+`px`,t.style.height=n+`px`),this.setViewport(0,0,e,n)},this.getDrawingBufferSize=function(e){return e.set(A*M,j*M).floor()},this.setDrawingBufferSize=function(e,n,r){A=e,j=n,M=r,t.width=Math.floor(e*r),t.height=Math.floor(n*r),this.setViewport(0,0,e,n)},this.getCurrentViewport=function(e){return e.copy(T)},this.getViewport=function(e){return e.copy(F)},this.setViewport=function(e,t,n,r){e.isVector4?F.set(e.x,e.y,e.z,e.w):F.set(e,t,n,r),R.viewport(T.copy(F).multiplyScalar(M).round())},this.getScissor=function(e){return e.copy(I)},this.setScissor=function(e,t,n,r){e.isVector4?I.set(e.x,e.y,e.z,e.w):I.set(e,t,n,r),R.scissor(E.copy(I).multiplyScalar(M).round())},this.getScissorTest=function(){return ee},this.setScissorTest=function(e){R.setScissorTest(ee=e)},this.setOpaqueSort=function(e){N=e},this.setTransparentSort=function(e){P=e},this.getClearColor=function(e){return e.copy(Ee.getClearColor())},this.setClearColor=function(){Ee.setClearColor.apply(Ee,arguments)},this.getClearAlpha=function(){return Ee.getClearAlpha()},this.setClearAlpha=function(){Ee.setClearAlpha.apply(Ee,arguments)},this.clear=function(e=!0,t=!0,n=!0){let r=0;if(e){let e=!1;if(S!==null){let t=S.texture.format;e=t===1033||t===1031||t===1029}if(e){let e=S.texture.type,t=e===1009||e===1014||e===1012||e===1020||e===1017||e===1018,n=Ee.getClearColor(),r=Ee.getClearAlpha(),i=n.r,a=n.g,o=n.b;t?(f[0]=i,f[1]=a,f[2]=o,f[3]=r,L.clearBufferuiv(L.COLOR,0,f)):(p[0]=i,p[1]=a,p[2]=o,p[3]=r,L.clearBufferiv(L.COLOR,0,p))}else r|=L.COLOR_BUFFER_BIT}t&&(r|=L.DEPTH_BUFFER_BIT,L.clearDepth(+!this.capabilities.reverseDepthBuffer)),n&&(r|=L.STENCIL_BUFFER_BIT,this.state.buffers.stencil.setMask(4294967295)),L.clear(r)},this.clearColor=function(){this.clear(!0,!1,!1)},this.clearDepth=function(){this.clear(!1,!0,!1)},this.clearStencil=function(){this.clear(!1,!1,!0)},this.dispose=function(){t.removeEventListener(`webglcontextlost`,Fe,!1),t.removeEventListener(`webglcontextrestored`,Ie,!1),t.removeEventListener(`webglcontextcreationerror`,Le,!1),Se.dispose(),Ce.dispose(),z.dispose(),he.dispose(),ge.dispose(),ye.dispose(),je.dispose(),Me.dispose(),be.dispose(),Pe.dispose(),Pe.removeEventListener(`sessionstart`,qe),Pe.removeEventListener(`sessionend`,Je),Ye.stop()};function Fe(e){e.preventDefault(),console.log(`THREE.WebGLRenderer: Context Lost.`),y=!0}function Ie(){console.log(`THREE.WebGLRenderer: Context Restored.`),y=!1;let e=me.autoReset,t=Te.enabled,n=Te.autoUpdate,r=Te.needsUpdate,i=Te.type;Ne(),me.autoReset=e,Te.enabled=t,Te.autoUpdate=n,Te.needsUpdate=r,Te.type=i}function Le(e){console.error(`THREE.WebGLRenderer: A WebGL context could not be created. Reason: `,e.statusMessage)}function Be(e){let t=e.target;t.removeEventListener(`dispose`,Be),Ve(t)}function Ve(e){He(e),z.remove(e)}function He(e){let t=z.get(e).programs;t!==void 0&&(t.forEach(function(e){be.releaseProgram(e)}),e.isShaderMaterial&&be.releaseShaderCache(e))}this.renderBufferDirect=function(e,t,n,r,i,a){t===null&&(t=ce);let o=i.isMesh&&i.matrixWorld.determinant()<0,s=it(e,t,n,r,i);R.setMaterial(r,o);let c=n.index,l=1;if(r.wireframe===!0){if(c=ve.getWireframeAttribute(n),c===void 0)return;l=2}let u=n.drawRange,d=n.attributes.position,f=u.start*l,p=(u.start+u.count)*l;a!==null&&(f=Math.max(f,a.start*l),p=Math.min(p,(a.start+a.count)*l)),c===null?d!=null&&(f=Math.max(f,0),p=Math.min(p,d.count)):(f=Math.max(f,0),p=Math.min(p,c.count));let m=p-f;if(m<0||m===1/0)return;je.setup(i,r,s,n,c);let h,g=Oe;if(c!==null&&(h=_e.get(c),g=ke,g.setIndex(h)),i.isMesh)r.wireframe===!0?(R.setLineWidth(r.wireframeLinewidth*ue()),g.setMode(L.LINES)):g.setMode(L.TRIANGLES);else if(i.isLine){let e=r.linewidth;e===void 0&&(e=1),R.setLineWidth(e*ue()),i.isLineSegments?g.setMode(L.LINES):i.isLineLoop?g.setMode(L.LINE_LOOP):g.setMode(L.LINE_STRIP)}else i.isPoints?g.setMode(L.POINTS):i.isSprite&&g.setMode(L.TRIANGLES);if(i.isBatchedMesh){if(i._multiDrawInstances!==null)g.renderMultiDrawInstances(i._multiDrawStarts,i._multiDrawCounts,i._multiDrawCount,i._multiDrawInstances);else if(fe.get(`WEBGL_multi_draw`))g.renderMultiDraw(i._multiDrawStarts,i._multiDrawCounts,i._multiDrawCount);else{let e=i._multiDrawStarts,t=i._multiDrawCounts,n=i._multiDrawCount,a=c?_e.get(c).bytesPerElement:1,o=z.get(r).currentProgram.getUniforms();for(let r=0;r{function n(){if(r.forEach(function(e){z.get(e).currentProgram.isReady()&&r.delete(e)}),r.size===0){t(e);return}setTimeout(n,10)}fe.get(`KHR_parallel_shader_compile`)===null?setTimeout(n,10):n()})};let We=null;function Ge(e){We&&We(e)}function qe(){Ye.stop()}function Je(){Ye.start()}let Ye=new La;Ye.setAnimationLoop(Ge),typeof self<`u`&&Ye.setContext(self),this.setAnimationLoop=function(e){We=e,Pe.setAnimationLoop(e),e===null?Ye.stop():Ye.start()},Pe.addEventListener(`sessionstart`,qe),Pe.addEventListener(`sessionend`,Je),this.render=function(e,t){if(t!==void 0&&t.isCamera!==!0){console.error(`THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.`);return}if(y===!0)return;if(e.matrixWorldAutoUpdate===!0&&e.updateMatrixWorld(),t.parent===null&&t.matrixWorldAutoUpdate===!0&&t.updateMatrixWorld(),Pe.enabled===!0&&Pe.isPresenting===!0&&(Pe.cameraAutoUpdate===!0&&Pe.updateCamera(t),t=Pe.getCamera()),e.isScene===!0&&e.onBeforeRender(v,e,t,S),h=Ce.get(e,_.length),h.init(t),_.push(h),ae.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),te.setFromProjectionMatrix(ae),re=this.localClippingEnabled,ne=we.init(this.clippingPlanes,re),m=Se.get(e,g.length),m.init(),g.push(m),Pe.enabled===!0&&Pe.isPresenting===!0){let e=v.xr.getDepthSensingMesh();e!==null&&Xe(e,t,-1/0,v.sortObjects)}Xe(e,t,0,v.sortObjects),m.finish(),v.sortObjects===!0&&m.sort(N,P),le=Pe.enabled===!1||Pe.isPresenting===!1||Pe.hasDepthSensing()===!1,le&&Ee.addToRenderList(m,e),this.info.render.frame++,ne===!0&&we.beginShadows();let n=h.state.shadowsArray;Te.render(n,e,t),ne===!0&&we.endShadows(),this.info.autoReset===!0&&this.info.reset();let r=m.opaque,i=m.transmissive;if(h.setupLights(),t.isArrayCamera){let n=t.cameras;if(i.length>0)for(let t=0,a=n.length;t0&&Qe(r,i,e,t),le&&Ee.render(e),Ze(m,e,t);S!==null&&(B.updateMultisampleRenderTarget(S),B.updateRenderTargetMipmap(S)),e.isScene===!0&&e.onAfterRender(v,e,t),je.resetDefaultState(),C=-1,w=null,_.pop(),_.length>0?(h=_[_.length-1],ne===!0&&we.setGlobalState(v.clippingPlanes,h.state.camera)):h=null,g.pop(),m=g.length>0?g[g.length-1]:null};function Xe(e,t,n,r){if(e.visible===!1)return;if(e.layers.test(t.layers)){if(e.isGroup)n=e.renderOrder;else if(e.isLOD)e.autoUpdate===!0&&e.update(t);else if(e.isLight)h.pushLight(e),e.castShadow&&h.pushShadow(e);else if(e.isSprite){if(!e.frustumCulled||te.intersectsSprite(e)){r&&se.setFromMatrixPosition(e.matrixWorld).applyMatrix4(ae);let t=ye.update(e),i=e.material;i.visible&&m.push(e,t,i,n,se.z,null)}}else if((e.isMesh||e.isLine||e.isPoints)&&(!e.frustumCulled||te.intersectsObject(e))){let t=ye.update(e),i=e.material;if(r&&(e.boundingSphere===void 0?(t.boundingSphere===null&&t.computeBoundingSphere(),se.copy(t.boundingSphere.center)):(e.boundingSphere===null&&e.computeBoundingSphere(),se.copy(e.boundingSphere.center)),se.applyMatrix4(e.matrixWorld).applyMatrix4(ae)),Array.isArray(i)){let r=t.groups;for(let a=0,o=r.length;a0&&$e(i,t,n),a.length>0&&$e(a,t,n),o.length>0&&$e(o,t,n),R.buffers.depth.setTest(!0),R.buffers.depth.setMask(!0),R.buffers.color.setMask(!0),R.setPolygonOffset(!1)}function Qe(e,t,n,r){if((n.isScene===!0?n.overrideMaterial:null)!==null)return;h.state.transmissionRenderTarget[r.id]===void 0&&(h.state.transmissionRenderTarget[r.id]=new ar(1,1,{generateMipmaps:!0,type:fe.has(`EXT_color_buffer_half_float`)||fe.has(`EXT_color_buffer_float`)?Ke:ze,minFilter:Re,samples:4,stencilBuffer:i,resolveDepthBuffer:!1,resolveStencilBuffer:!1,colorSpace:qn.workingColorSpace}));let a=h.state.transmissionRenderTarget[r.id],o=r.viewport||T;a.setSize(o.z,o.w);let s=v.getRenderTarget();v.setRenderTarget(a),v.getClearColor(O),k=v.getClearAlpha(),k<1&&v.setClearColor(16777215,.5),v.clear(),le&&Ee.render(n);let c=v.toneMapping;v.toneMapping=0;let l=r.viewport;if(r.viewport!==void 0&&(r.viewport=void 0),h.setupLightsView(r),ne===!0&&we.setGlobalState(v.clippingPlanes,r),$e(e,n,r),B.updateMultisampleRenderTarget(a),B.updateRenderTargetMipmap(a),fe.has(`WEBGL_multisampled_render_to_texture`)===!1){let e=!1;for(let i=0,a=t.length;i0),d=!!n.morphAttributes.position,f=!!n.morphAttributes.normal,p=!!n.morphAttributes.color,m=0;r.toneMapped&&(S===null||S.isXRRenderTarget===!0)&&(m=v.toneMapping);let g=n.morphAttributes.position||n.morphAttributes.normal||n.morphAttributes.color,_=g===void 0?0:g.length,y=z.get(r),b=h.state.lights;if(ne===!0&&(re===!0||e!==w)){let t=e===w&&r.id===C;we.setState(r,e,t)}let x=!1;r.version===y.__version?y.needsLights&&y.lightsStateVersion!==b.state.version?x=!0:y.outputColorSpace===s?i.isBatchedMesh&&y.batching===!1||!i.isBatchedMesh&&y.batching===!0||i.isBatchedMesh&&y.batchingColor===!0&&i.colorTexture===null||i.isBatchedMesh&&y.batchingColor===!1&&i.colorTexture!==null||i.isInstancedMesh&&y.instancing===!1||!i.isInstancedMesh&&y.instancing===!0||i.isSkinnedMesh&&y.skinning===!1||!i.isSkinnedMesh&&y.skinning===!0||i.isInstancedMesh&&y.instancingColor===!0&&i.instanceColor===null||i.isInstancedMesh&&y.instancingColor===!1&&i.instanceColor!==null||i.isInstancedMesh&&y.instancingMorph===!0&&i.morphTexture===null||i.isInstancedMesh&&y.instancingMorph===!1&&i.morphTexture!==null?x=!0:y.envMap===c?r.fog===!0&&y.fog!==a||y.numClippingPlanes!==void 0&&(y.numClippingPlanes!==we.numPlanes||y.numIntersection!==we.numIntersection)?x=!0:y.vertexAlphas===l&&y.vertexTangents===u&&y.morphTargets===d&&y.morphNormals===f&&y.morphColors===p&&y.toneMapping===m?y.morphTargetsCount!==_&&(x=!0):x=!0:x=!0:x=!0:(x=!0,y.__version=r.version);let T=y.currentProgram;x===!0&&(T=tt(r,t,i));let E=!1,D=!1,O=!1,k=T.getUniforms(),A=y.uniforms;if(R.useProgram(T.program)&&(E=!0,D=!0,O=!0),r.id!==C&&(C=r.id,D=!0),E||w!==e){pe.reverseDepthBuffer?(ie.copy(e.projectionMatrix),Vn(ie),Hn(ie),k.setValue(L,`projectionMatrix`,ie)):k.setValue(L,`projectionMatrix`,e.projectionMatrix),k.setValue(L,`viewMatrix`,e.matrixWorldInverse);let t=k.map.cameraPosition;t!==void 0&&t.setValue(L,oe.setFromMatrixPosition(e.matrixWorld)),pe.logarithmicDepthBuffer&&k.setValue(L,`logDepthBufFC`,2/(Math.log(e.far+1)/Math.LN2)),(r.isMeshPhongMaterial||r.isMeshToonMaterial||r.isMeshLambertMaterial||r.isMeshBasicMaterial||r.isMeshStandardMaterial||r.isShaderMaterial)&&k.setValue(L,`isOrthographic`,e.isOrthographicCamera===!0),w!==e&&(w=e,D=!0,O=!0)}if(i.isSkinnedMesh){k.setOptional(L,i,`bindMatrix`),k.setOptional(L,i,`bindMatrixInverse`);let e=i.skeleton;e&&(e.boneTexture===null&&e.computeBoneTexture(),k.setValue(L,`boneTexture`,e.boneTexture,B))}i.isBatchedMesh&&(k.setOptional(L,i,`batchingTexture`),k.setValue(L,`batchingTexture`,i._matricesTexture,B),k.setOptional(L,i,`batchingIdTexture`),k.setValue(L,`batchingIdTexture`,i._indirectTexture,B),k.setOptional(L,i,`batchingColorTexture`),i._colorsTexture!==null&&k.setValue(L,`batchingColorTexture`,i._colorsTexture,B));let N=n.morphAttributes;if((N.position!==void 0||N.normal!==void 0||N.color!==void 0)&&De.update(i,n,T),(D||y.receiveShadow!==i.receiveShadow)&&(y.receiveShadow=i.receiveShadow,k.setValue(L,`receiveShadow`,i.receiveShadow)),r.isMeshGouraudMaterial&&r.envMap!==null&&(A.envMap.value=c,A.flipEnvMap.value=c.isCubeTexture&&c.isRenderTargetTexture===!1?-1:1),r.isMeshStandardMaterial&&r.envMap===null&&t.environment!==null&&(A.envMapIntensity.value=t.environmentIntensity),D&&(k.setValue(L,`toneMappingExposure`,v.toneMappingExposure),y.needsLights&&at(A,O),a&&r.fog===!0&&xe.refreshFogUniforms(A,a),xe.refreshMaterialUniforms(A,r,M,j,h.state.transmissionRenderTarget[e.id]),Ms.upload(L,nt(y),A,B)),r.isShaderMaterial&&r.uniformsNeedUpdate===!0&&(Ms.upload(L,nt(y),A,B),r.uniformsNeedUpdate=!1),r.isSpriteMaterial&&k.setValue(L,`center`,i.center),k.setValue(L,`modelViewMatrix`,i.modelViewMatrix),k.setValue(L,`normalMatrix`,i.normalMatrix),k.setValue(L,`modelMatrix`,i.matrixWorld),r.isShaderMaterial||r.isRawShaderMaterial){let e=r.uniformsGroups;for(let t=0,n=e.length;t0&&B.useMultisampledRTT(e)===!1?z.get(e).__webglMultisampledFramebuffer:Array.isArray(l)?l[n]:l,T.copy(e.viewport),E.copy(e.scissor),D=e.scissorTest}else T.copy(F).multiplyScalar(M).floor(),E.copy(I).multiplyScalar(M).floor(),D=ee;if(R.bindFramebuffer(L.FRAMEBUFFER,i)&&r&&R.drawBuffers(e,i),R.viewport(T),R.scissor(E),R.setScissorTest(D),a){let r=z.get(e.texture);L.framebufferTexture2D(L.FRAMEBUFFER,L.COLOR_ATTACHMENT0,L.TEXTURE_CUBE_MAP_POSITIVE_X+t,r.__webglTexture,n)}else if(o){let r=z.get(e.texture),i=t||0;L.framebufferTextureLayer(L.FRAMEBUFFER,L.COLOR_ATTACHMENT0,r.__webglTexture,n||0,i)}C=-1},this.readRenderTargetPixels=function(e,t,n,r,i,a,o){if(!(e&&e.isWebGLRenderTarget)){console.error(`THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.`);return}let s=z.get(e).__webglFramebuffer;if(e.isWebGLCubeRenderTarget&&o!==void 0&&(s=s[o]),s){R.bindFramebuffer(L.FRAMEBUFFER,s);try{let o=e.texture,s=o.format,c=o.type;if(!pe.textureFormatReadable(s)){console.error(`THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.`);return}if(!pe.textureTypeReadable(c)){console.error(`THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.`);return}t>=0&&t<=e.width-r&&n>=0&&n<=e.height-i&&L.readPixels(t,n,r,i,Ae.convert(s),Ae.convert(c),a)}finally{let e=S===null?null:z.get(S).__webglFramebuffer;R.bindFramebuffer(L.FRAMEBUFFER,e)}}},this.readRenderTargetPixelsAsync=async function(e,t,n,r,i,a,o){if(!(e&&e.isWebGLRenderTarget))throw Error(`THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.`);let s=z.get(e).__webglFramebuffer;if(e.isWebGLCubeRenderTarget&&o!==void 0&&(s=s[o]),s){let o=e.texture,c=o.format,l=o.type;if(!pe.textureFormatReadable(c))throw Error(`THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in RGBA or implementation defined format.`);if(!pe.textureTypeReadable(l))throw Error(`THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in UnsignedByteType or implementation defined type.`);if(t>=0&&t<=e.width-r&&n>=0&&n<=e.height-i){R.bindFramebuffer(L.FRAMEBUFFER,s);let e=L.createBuffer();L.bindBuffer(L.PIXEL_PACK_BUFFER,e),L.bufferData(L.PIXEL_PACK_BUFFER,a.byteLength,L.STREAM_READ),L.readPixels(t,n,r,i,Ae.convert(c),Ae.convert(l),0);let o=S===null?null:z.get(S).__webglFramebuffer;R.bindFramebuffer(L.FRAMEBUFFER,o);let u=L.fenceSync(L.SYNC_GPU_COMMANDS_COMPLETE,0);return L.flush(),await Bn(L,u,4),L.bindBuffer(L.PIXEL_PACK_BUFFER,e),L.getBufferSubData(L.PIXEL_PACK_BUFFER,0,a),L.deleteBuffer(e),L.deleteSync(u),a}throw Error(`THREE.WebGLRenderer.readRenderTargetPixelsAsync: requested read bounds are out of range.`)}},this.copyFramebufferToTexture=function(e,t=null,n=0){e.isTexture!==!0&&(zn(`WebGLRenderer: copyFramebufferToTexture function signature has changed.`),t=arguments[0]||null,e=arguments[1]);let r=2**-n,i=Math.floor(e.image.width*r),a=Math.floor(e.image.height*r),o=t===null?0:t.x,s=t===null?0:t.y;B.setTexture2D(e,0),L.copyTexSubImage2D(L.TEXTURE_2D,n,0,0,o,s,i,a),R.unbindTexture()},this.copyTextureToTexture=function(e,t,n=null,r=null,i=0){e.isTexture!==!0&&(zn(`WebGLRenderer: copyTextureToTexture function signature has changed.`),r=arguments[0]||null,e=arguments[1],t=arguments[2],i=arguments[3]||0,n=null);let a,o,s,c,l,u;n===null?(a=e.image.width,o=e.image.height,s=0,c=0):(a=n.max.x-n.min.x,o=n.max.y-n.min.y,s=n.min.x,c=n.min.y),r===null?(l=0,u=0):(l=r.x,u=r.y);let d=Ae.convert(t.format),f=Ae.convert(t.type);B.setTexture2D(t,0),L.pixelStorei(L.UNPACK_FLIP_Y_WEBGL,t.flipY),L.pixelStorei(L.UNPACK_PREMULTIPLY_ALPHA_WEBGL,t.premultiplyAlpha),L.pixelStorei(L.UNPACK_ALIGNMENT,t.unpackAlignment);let p=L.getParameter(L.UNPACK_ROW_LENGTH),m=L.getParameter(L.UNPACK_IMAGE_HEIGHT),h=L.getParameter(L.UNPACK_SKIP_PIXELS),g=L.getParameter(L.UNPACK_SKIP_ROWS),_=L.getParameter(L.UNPACK_SKIP_IMAGES),v=e.isCompressedTexture?e.mipmaps[i]:e.image;L.pixelStorei(L.UNPACK_ROW_LENGTH,v.width),L.pixelStorei(L.UNPACK_IMAGE_HEIGHT,v.height),L.pixelStorei(L.UNPACK_SKIP_PIXELS,s),L.pixelStorei(L.UNPACK_SKIP_ROWS,c),e.isDataTexture?L.texSubImage2D(L.TEXTURE_2D,i,l,u,a,o,d,f,v.data):e.isCompressedTexture?L.compressedTexSubImage2D(L.TEXTURE_2D,i,l,u,v.width,v.height,d,v.data):L.texSubImage2D(L.TEXTURE_2D,i,l,u,a,o,d,f,v),L.pixelStorei(L.UNPACK_ROW_LENGTH,p),L.pixelStorei(L.UNPACK_IMAGE_HEIGHT,m),L.pixelStorei(L.UNPACK_SKIP_PIXELS,h),L.pixelStorei(L.UNPACK_SKIP_ROWS,g),L.pixelStorei(L.UNPACK_SKIP_IMAGES,_),i===0&&t.generateMipmaps&&L.generateMipmap(L.TEXTURE_2D),R.unbindTexture()},this.copyTextureToTexture3D=function(e,t,n=null,r=null,i=0){e.isTexture!==!0&&(zn(`WebGLRenderer: copyTextureToTexture3D function signature has changed.`),n=arguments[0]||null,r=arguments[1]||null,e=arguments[2],t=arguments[3],i=arguments[4]||0);let a,o,s,c,l,u,d,f,p,m=e.isCompressedTexture?e.mipmaps[i]:e.image;n===null?(a=m.width,o=m.height,s=m.depth,c=0,l=0,u=0):(a=n.max.x-n.min.x,o=n.max.y-n.min.y,s=n.max.z-n.min.z,c=n.min.x,l=n.min.y,u=n.min.z),r===null?(d=0,f=0,p=0):(d=r.x,f=r.y,p=r.z);let h=Ae.convert(t.format),g=Ae.convert(t.type),_;if(t.isData3DTexture)B.setTexture3D(t,0),_=L.TEXTURE_3D;else if(t.isDataArrayTexture||t.isCompressedArrayTexture)B.setTexture2DArray(t,0),_=L.TEXTURE_2D_ARRAY;else{console.warn(`THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.`);return}L.pixelStorei(L.UNPACK_FLIP_Y_WEBGL,t.flipY),L.pixelStorei(L.UNPACK_PREMULTIPLY_ALPHA_WEBGL,t.premultiplyAlpha),L.pixelStorei(L.UNPACK_ALIGNMENT,t.unpackAlignment);let v=L.getParameter(L.UNPACK_ROW_LENGTH),y=L.getParameter(L.UNPACK_IMAGE_HEIGHT),b=L.getParameter(L.UNPACK_SKIP_PIXELS),x=L.getParameter(L.UNPACK_SKIP_ROWS),S=L.getParameter(L.UNPACK_SKIP_IMAGES);L.pixelStorei(L.UNPACK_ROW_LENGTH,m.width),L.pixelStorei(L.UNPACK_IMAGE_HEIGHT,m.height),L.pixelStorei(L.UNPACK_SKIP_PIXELS,c),L.pixelStorei(L.UNPACK_SKIP_ROWS,l),L.pixelStorei(L.UNPACK_SKIP_IMAGES,u),e.isDataTexture||e.isData3DTexture?L.texSubImage3D(_,i,d,f,p,a,o,s,h,g,m.data):t.isCompressedArrayTexture?L.compressedTexSubImage3D(_,i,d,f,p,a,o,s,h,m.data):L.texSubImage3D(_,i,d,f,p,a,o,s,h,g,m),L.pixelStorei(L.UNPACK_ROW_LENGTH,v),L.pixelStorei(L.UNPACK_IMAGE_HEIGHT,y),L.pixelStorei(L.UNPACK_SKIP_PIXELS,b),L.pixelStorei(L.UNPACK_SKIP_ROWS,x),L.pixelStorei(L.UNPACK_SKIP_IMAGES,S),i===0&&t.generateMipmaps&&L.generateMipmap(_),R.unbindTexture()},this.initRenderTarget=function(e){z.get(e).__webglFramebuffer===void 0&&B.setupRenderTarget(e)},this.initTexture=function(e){e.isCubeTexture?B.setTextureCube(e,0):e.isData3DTexture?B.setTexture3D(e,0):e.isDataArrayTexture||e.isCompressedArrayTexture?B.setTexture2DArray(e,0):B.setTexture2D(e,0),R.unbindTexture()},this.resetState=function(){b=0,x=0,S=null,R.reset(),je.reset()},typeof __THREE_DEVTOOLS__<`u`&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent(`observe`,{detail:this}))}get coordinateSystem(){return on}get outputColorSpace(){return this._outputColorSpace}set outputColorSpace(e){this._outputColorSpace=e;let t=this.getContext();t.drawingBufferColorSpace=e===`display-p3`?`display-p3`:`srgb`,t.unpackColorSpace=qn.workingColorSpace===`display-p3-linear`?`display-p3`:`srgb`}},Yc=class extends ui{constructor(){super(),this.isScene=!0,this.type=`Scene`,this.background=null,this.environment=null,this.fog=null,this.backgroundBlurriness=0,this.backgroundIntensity=1,this.backgroundRotation=new qr,this.environmentIntensity=1,this.environmentRotation=new qr,this.overrideMaterial=null,typeof __THREE_DEVTOOLS__<`u`&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent(`observe`,{detail:this}))}copy(e,t){return super.copy(e,t),e.background!==null&&(this.background=e.background.clone()),e.environment!==null&&(this.environment=e.environment.clone()),e.fog!==null&&(this.fog=e.fog.clone()),this.backgroundBlurriness=e.backgroundBlurriness,this.backgroundIntensity=e.backgroundIntensity,this.backgroundRotation.copy(e.backgroundRotation),this.environmentIntensity=e.environmentIntensity,this.environmentRotation.copy(e.environmentRotation),e.overrideMaterial!==null&&(this.overrideMaterial=e.overrideMaterial.clone()),this.matrixAutoUpdate=e.matrixAutoUpdate,this}toJSON(e){let t=super.toJSON(e);return this.fog!==null&&(t.object.fog=this.fog.toJSON()),this.backgroundBlurriness>0&&(t.object.backgroundBlurriness=this.backgroundBlurriness),this.backgroundIntensity!==1&&(t.object.backgroundIntensity=this.backgroundIntensity),t.object.backgroundRotation=this.backgroundRotation.toArray(),this.environmentIntensity!==1&&(t.object.environmentIntensity=this.environmentIntensity),t.object.environmentRotation=this.environmentRotation.toArray(),t}},Xc=class{constructor(e,t){this.isInterleavedBuffer=!0,this.array=e,this.stride=t,this.count=e===void 0?0:e.length/t,this.usage=an,this.updateRanges=[],this.version=0,this.uuid=fn()}onUploadCallback(){}set needsUpdate(e){e===!0&&this.version++}setUsage(e){return this.usage=e,this}addUpdateRange(e,t){this.updateRanges.push({start:e,count:t})}clearUpdateRanges(){this.updateRanges.length=0}copy(e){return this.array=new e.array.constructor(e.array),this.count=e.count,this.stride=e.stride,this.usage=e.usage,this}copyAt(e,t,n){e*=this.stride,n*=t.stride;for(let r=0,i=this.stride;r0){let n=e[t[0]];if(n!==void 0){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,t=n.length;er)return;kl.applyMatrix4(e.matrixWorld);let s=t.ray.origin.distanceTo(kl);if(!(st.far))return{distance:s,point:Al.clone().applyMatrix4(e.matrixWorld),index:i,face:null,faceIndex:null,barycoord:null,object:e}}var Nl=new W,Pl=new W,Fl=class extends jl{constructor(e,t){super(e,t),this.isLineSegments=!0,this.type=`LineSegments`}computeLineDistances(){let e=this.geometry;if(e.index===null){let t=e.attributes.position,n=[];for(let e=0,r=t.count;e0){let n=e[t[0]];if(n!==void 0){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,t=n.length;ei.far)return;a.push({distance:c,distanceToRay:Math.sqrt(s),point:n,index:t,face:null,faceIndex:null,barycoord:null,object:o})}}var Wl=class extends nr{constructor(e,t,n,r,i,a,o,s,c){super(e,t,n,r,i,a,o,s,c),this.isVideoTexture=!0,this.minFilter=a===void 0?Ie:a,this.magFilter=i===void 0?Ie:i,this.generateMipmaps=!1;let l=this;function u(){l.needsUpdate=!0,e.requestVideoFrameCallback(u)}`requestVideoFrameCallback`in e&&e.requestVideoFrameCallback(u)}clone(){return new this.constructor(this.image).copy(this)}update(){let e=this.image;!(`requestVideoFrameCallback`in e)&&e.readyState>=e.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}},Gl=class extends nr{constructor(e,t,n,r,i,a,o,s,c){super(e,t,n,r,i,a,o,s,c),this.isCanvasTexture=!0,this.needsUpdate=!0}},Kl=class{constructor(){this.type=`Curve`,this.arcLengthDivisions=200}getPoint(){return console.warn(`THREE.Curve: .getPoint() not implemented.`),null}getPointAt(e,t){let n=this.getUtoTmapping(e);return this.getPoint(n,t)}getPoints(e=5){let t=[];for(let n=0;n<=e;n++)t.push(this.getPoint(n/e));return t}getSpacedPoints(e=5){let t=[];for(let n=0;n<=e;n++)t.push(this.getPointAt(n/e));return t}getLength(){let e=this.getLengths();return e[e.length-1]}getLengths(e=this.arcLengthDivisions){if(this.cacheArcLengths&&this.cacheArcLengths.length===e+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;let t=[],n,r=this.getPoint(0),i=0;t.push(0);for(let a=1;a<=e;a++)n=this.getPoint(a/e),i+=n.distanceTo(r),t.push(i),r=n;return this.cacheArcLengths=t,t}updateArcLengths(){this.needsUpdate=!0,this.getLengths()}getUtoTmapping(e,t){let n=this.getLengths(),r=0,i=n.length,a;a=t||e*n[i-1];let o=0,s=i-1,c;for(;o<=s;)if(r=Math.floor(o+(s-o)/2),c=n[r]-a,c<0)o=r+1;else if(c>0)s=r-1;else{s=r;break}if(r=s,n[r]===a)return r/(i-1);let l=n[r],u=n[r+1]-l,d=(a-l)/u;return(r+d)/(i-1)}getTangent(e,t){let n=1e-4,r=e-n,i=e+n;r<0&&(r=0),i>1&&(i=1);let a=this.getPoint(r),o=this.getPoint(i),s=t||(a.isVector2?new H:new W);return s.copy(o).sub(a).normalize(),s}getTangentAt(e,t){let n=this.getUtoTmapping(e);return this.getTangent(n,t)}computeFrenetFrames(e,t){let n=new W,r=[],i=[],a=[],o=new W,s=new G;for(let t=0;t<=e;t++){let n=t/e;r[t]=this.getTangentAt(n,new W)}i[0]=new W,a[0]=new W;let c=Number.MAX_VALUE,l=Math.abs(r[0].x),u=Math.abs(r[0].y),d=Math.abs(r[0].z);l<=c&&(c=l,n.set(1,0,0)),u<=c&&(c=u,n.set(0,1,0)),d<=c&&n.set(0,0,1),o.crossVectors(r[0],n).normalize(),i[0].crossVectors(r[0],o),a[0].crossVectors(r[0],i[0]);for(let t=1;t<=e;t++){if(i[t]=i[t-1].clone(),a[t]=a[t-1].clone(),o.crossVectors(r[t-1],r[t]),o.length()>2**-52){o.normalize();let e=Math.acos(pn(r[t-1].dot(r[t]),-1,1));i[t].applyMatrix4(s.makeRotationAxis(o,e))}a[t].crossVectors(r[t],i[t])}if(t===!0){let t=Math.acos(pn(i[0].dot(i[e]),-1,1));t/=e,r[0].dot(o.crossVectors(i[0],i[e]))>0&&(t=-t);for(let n=1;n<=e;n++)i[n].applyMatrix4(s.makeRotationAxis(r[n],t*n)),a[n].crossVectors(r[n],i[n])}return{tangents:r,normals:i,binormals:a}}clone(){return new this.constructor().copy(this)}copy(e){return this.arcLengthDivisions=e.arcLengthDivisions,this}toJSON(){let e={metadata:{version:4.6,type:`Curve`,generator:`Curve.toJSON`}};return e.arcLengthDivisions=this.arcLengthDivisions,e.type=this.type,e}fromJSON(e){return this.arcLengthDivisions=e.arcLengthDivisions,this}},ql=class extends Kl{constructor(e=0,t=0,n=1,r=1,i=0,a=Math.PI*2,o=!1,s=0){super(),this.isEllipseCurve=!0,this.type=`EllipseCurve`,this.aX=e,this.aY=t,this.xRadius=n,this.yRadius=r,this.aStartAngle=i,this.aEndAngle=a,this.aClockwise=o,this.aRotation=s}getPoint(e,t=new H){let n=t,r=Math.PI*2,i=this.aEndAngle-this.aStartAngle,a=Math.abs(i)<2**-52;for(;i<0;)i+=r;for(;i>r;)i-=r;i<2**-52&&(i=a?0:r),this.aClockwise===!0&&!a&&(i===r?i=-r:i-=r);let o=this.aStartAngle+e*i,s=this.aX+this.xRadius*Math.cos(o),c=this.aY+this.yRadius*Math.sin(o);if(this.aRotation!==0){let e=Math.cos(this.aRotation),t=Math.sin(this.aRotation),n=s-this.aX,r=c-this.aY;s=n*e-r*t+this.aX,c=n*t+r*e+this.aY}return n.set(s,c)}copy(e){return super.copy(e),this.aX=e.aX,this.aY=e.aY,this.xRadius=e.xRadius,this.yRadius=e.yRadius,this.aStartAngle=e.aStartAngle,this.aEndAngle=e.aEndAngle,this.aClockwise=e.aClockwise,this.aRotation=e.aRotation,this}toJSON(){let e=super.toJSON();return e.aX=this.aX,e.aY=this.aY,e.xRadius=this.xRadius,e.yRadius=this.yRadius,e.aStartAngle=this.aStartAngle,e.aEndAngle=this.aEndAngle,e.aClockwise=this.aClockwise,e.aRotation=this.aRotation,e}fromJSON(e){return super.fromJSON(e),this.aX=e.aX,this.aY=e.aY,this.xRadius=e.xRadius,this.yRadius=e.yRadius,this.aStartAngle=e.aStartAngle,this.aEndAngle=e.aEndAngle,this.aClockwise=e.aClockwise,this.aRotation=e.aRotation,this}},Jl=class extends ql{constructor(e,t,n,r,i,a){super(e,t,n,n,r,i,a),this.isArcCurve=!0,this.type=`ArcCurve`}};function Yl(){let e=0,t=0,n=0,r=0;function i(i,a,o,s){e=i,t=o,n=-3*i+3*a-2*o-s,r=2*i-2*a+o+s}return{initCatmullRom:function(e,t,n,r,a){i(t,n,a*(n-e),a*(r-t))},initNonuniformCatmullRom:function(e,t,n,r,a,o,s){let c=(t-e)/a-(n-e)/(a+o)+(n-t)/o,l=(n-t)/o-(r-t)/(o+s)+(r-n)/s;c*=o,l*=o,i(t,n,c,l)},calc:function(i){let a=i*i,o=a*i;return e+t*i+n*a+r*o}}}var Xl=new W,Zl=new Yl,Ql=new Yl,$l=new Yl,eu=class extends Kl{constructor(e=[],t=!1,n=`centripetal`,r=.5){super(),this.isCatmullRomCurve3=!0,this.type=`CatmullRomCurve3`,this.points=e,this.closed=t,this.curveType=n,this.tension=r}getPoint(e,t=new W){let n=t,r=this.points,i=r.length,a=(i-+!this.closed)*e,o=Math.floor(a),s=a-o;this.closed?o+=o>0?0:(Math.floor(Math.abs(o)/i)+1)*i:s===0&&o===i-1&&(o=i-2,s=1);let c,l;this.closed||o>0?c=r[(o-1)%i]:(Xl.subVectors(r[0],r[1]).add(r[0]),c=Xl);let u=r[o%i],d=r[(o+1)%i];if(this.closed||o+2r.length-2?r.length-1:a+1],u=r[a>r.length-3?r.length-1:a+2];return n.set(tu(o,s.x,c.x,l.x,u.x),tu(o,s.y,c.y,l.y,u.y)),n}copy(e){super.copy(e),this.points=[];for(let t=0,n=e.points.length;t=n){let e=r[i]-n,a=this.curves[i],o=a.getLength(),s=o===0?0:1-e/o;return a.getPointAt(s,t)}i++}return null}getLength(){let e=this.getCurveLengths();return e[e.length-1]}updateArcLengths(){this.needsUpdate=!0,this.cacheLengths=null,this.getCurveLengths()}getCurveLengths(){if(this.cacheLengths&&this.cacheLengths.length===this.curves.length)return this.cacheLengths;let e=[],t=0;for(let n=0,r=this.curves.length;n1&&!t[t.length-1].equals(t[0])&&t.push(t[0]),t}copy(e){super.copy(e),this.curves=[];for(let t=0,n=e.curves.length;t0){let e=c.getPoint(0);e.equals(this.currentPoint)||this.lineTo(e.x,e.y)}this.curves.push(c);let l=c.getPoint(1);return this.currentPoint.copy(l),this}copy(e){return super.copy(e),this.currentPoint.copy(e.currentPoint),this}toJSON(){let e=super.toJSON();return e.currentPoint=this.currentPoint.toArray(),e}fromJSON(e){return super.fromJSON(e),this.currentPoint.fromArray(e.currentPoint),this}},xu=class e extends Zi{constructor(e=1,t=32,n=0,r=Math.PI*2){super(),this.type=`CircleGeometry`,this.parameters={radius:e,segments:t,thetaStart:n,thetaLength:r},t=Math.max(3,t);let i=[],a=[],o=[],s=[],c=new W,l=new H;a.push(0,0,0),o.push(0,0,1),s.push(.5,.5);for(let i=0,u=3;i<=t;i++,u+=3){let d=n+i/t*r;c.x=e*Math.cos(d),c.y=e*Math.sin(d),a.push(c.x,c.y,c.z),o.push(0,0,1),l.x=(a[u]/e+1)/2,l.y=(a[u+1]/e+1)/2,s.push(l.x,l.y)}for(let e=1;e<=t;e++)i.push(e,e+1,0);this.setIndex(i),this.setAttribute(`position`,new Ui(a,3)),this.setAttribute(`normal`,new Ui(o,3)),this.setAttribute(`uv`,new Ui(s,2))}copy(e){return super.copy(e),this.parameters=Object.assign({},e.parameters),this}static fromJSON(t){return new e(t.radius,t.segments,t.thetaStart,t.thetaLength)}},Su=class e extends Zi{constructor(e=1,t=1,n=1,r=32,i=1,a=!1,o=0,s=Math.PI*2){super(),this.type=`CylinderGeometry`,this.parameters={radiusTop:e,radiusBottom:t,height:n,radialSegments:r,heightSegments:i,openEnded:a,thetaStart:o,thetaLength:s};let c=this;r=Math.floor(r),i=Math.floor(i);let l=[],u=[],d=[],f=[],p=0,m=[],h=n/2,g=0;_(),a===!1&&(e>0&&v(!0),t>0&&v(!1)),this.setIndex(l),this.setAttribute(`position`,new Ui(u,3)),this.setAttribute(`normal`,new Ui(d,3)),this.setAttribute(`uv`,new Ui(f,2));function _(){let a=new W,_=new W,v=0,y=(t-e)/n;for(let c=0;c<=i;c++){let l=[],g=c/i,v=g*(t-e)+e;for(let e=0;e<=r;e++){let t=e/r,i=t*s+o,c=Math.sin(i),m=Math.cos(i);_.x=v*c,_.y=-g*n+h,_.z=v*m,u.push(_.x,_.y,_.z),a.set(c,y,m).normalize(),d.push(a.x,a.y,a.z),f.push(t,1-g),l.push(p++)}m.push(l)}for(let n=0;n0&&(l.push(i,a,s),v+=3),t>0&&(l.push(a,o,s),v+=3)}c.addGroup(g,v,0),g+=v}function v(n){let i=p,a=new H,m=new W,_=0,v=n===!0?e:t,y=n===!0?1:-1;for(let e=1;e<=r;e++)u.push(0,h*y,0),d.push(0,y,0),f.push(.5,.5),p++;let b=p;for(let e=0;e<=r;e++){let t=e/r*s+o,n=Math.cos(t),i=Math.sin(t);m.x=v*i,m.y=h*y,m.z=v*n,u.push(m.x,m.y,m.z),d.push(0,y,0),a.x=n*.5+.5,a.y=i*.5*y+.5,f.push(a.x,a.y),p++}for(let e=0;e80*n){s=l=e[0],c=u=e[1];for(let t=n;tl&&(l=d),f>u&&(u=f);p=Math.max(l-s,u-c),p=p===0?0:32767/p}return Du(a,o,n,s,c,p,0),o}};function Tu(e,t,n,r,i){let a,o;if(i===td(e,t,n,r)>0)for(a=t;a=t;a-=r)o=Qu(a,e[a],e[a+1],o);return o&&Wu(o,o.next)&&($u(o),o=o.next),o}function Eu(e,t){if(!e)return e;t||=e;let n=e,r;do if(r=!1,!n.steiner&&(Wu(n,n.next)||Uu(n.prev,n,n.next)===0)){if($u(n),n=t=n.prev,n===n.next)break;r=!0}else n=n.next;while(r||n!==t);return t}function Du(e,t,n,r,i,a,o){if(!e)return;!o&&a&&Lu(e,r,i,a);let s=e,c,l;for(;e.prev!==e.next;){if(c=e.prev,l=e.next,a?ku(e,r,i,a):Ou(e)){t.push(c.i/n|0),t.push(e.i/n|0),t.push(l.i/n|0),$u(e),e=l.next,s=l.next;continue}if(e=l,e===s){o?o===1?(e=Au(Eu(e),t,n),Du(e,t,n,r,i,a,2)):o===2&&ju(e,t,n,r,i,a):Du(Eu(e),t,n,r,i,a,1);break}}}function Ou(e){let t=e.prev,n=e,r=e.next;if(Uu(t,n,r)>=0)return!1;let i=t.x,a=n.x,o=r.x,s=t.y,c=n.y,l=r.y,u=ia?i>o?i:o:a>o?a:o,p=s>c?s>l?s:l:c>l?c:l,m=r.next;for(;m!==t;){if(m.x>=u&&m.x<=f&&m.y>=d&&m.y<=p&&Vu(i,s,a,c,o,l,m.x,m.y)&&Uu(m.prev,m,m.next)>=0)return!1;m=m.next}return!0}function ku(e,t,n,r){let i=e.prev,a=e,o=e.next;if(Uu(i,a,o)>=0)return!1;let s=i.x,c=a.x,l=o.x,u=i.y,d=a.y,f=o.y,p=sc?s>l?s:l:c>l?c:l,g=u>d?u>f?u:f:d>f?d:f,_=zu(p,m,t,n,r),v=zu(h,g,t,n,r),y=e.prevZ,b=e.nextZ;for(;y&&y.z>=_&&b&&b.z<=v;){if(y.x>=p&&y.x<=h&&y.y>=m&&y.y<=g&&y!==i&&y!==o&&Vu(s,u,c,d,l,f,y.x,y.y)&&Uu(y.prev,y,y.next)>=0||(y=y.prevZ,b.x>=p&&b.x<=h&&b.y>=m&&b.y<=g&&b!==i&&b!==o&&Vu(s,u,c,d,l,f,b.x,b.y)&&Uu(b.prev,b,b.next)>=0))return!1;b=b.nextZ}for(;y&&y.z>=_;){if(y.x>=p&&y.x<=h&&y.y>=m&&y.y<=g&&y!==i&&y!==o&&Vu(s,u,c,d,l,f,y.x,y.y)&&Uu(y.prev,y,y.next)>=0)return!1;y=y.prevZ}for(;b&&b.z<=v;){if(b.x>=p&&b.x<=h&&b.y>=m&&b.y<=g&&b!==i&&b!==o&&Vu(s,u,c,d,l,f,b.x,b.y)&&Uu(b.prev,b,b.next)>=0)return!1;b=b.nextZ}return!0}function Au(e,t,n){let r=e;do{let i=r.prev,a=r.next.next;!Wu(i,a)&&Gu(i,r,r.next,a)&&Yu(i,a)&&Yu(a,i)&&(t.push(i.i/n|0),t.push(r.i/n|0),t.push(a.i/n|0),$u(r),$u(r.next),r=e=a),r=r.next}while(r!==e);return Eu(r)}function ju(e,t,n,r,i,a){let o=e;do{let e=o.next.next;for(;e!==o.prev;){if(o.i!==e.i&&Hu(o,e)){let s=Zu(o,e);o=Eu(o,o.next),s=Eu(s,s.next),Du(o,t,n,r,i,a,0),Du(s,t,n,r,i,a,0);return}e=e.next}o=o.next}while(o!==e)}function Mu(e,t,n,r){let i=[],a,o,s,c,l;for(a=0,o=t.length;a=n.next.y&&n.next.y!==n.y){let e=n.x+(o-n.y)*(n.next.x-n.x)/(n.next.y-n.y);if(e<=a&&e>r&&(r=e,i=n.x=n.x&&n.x>=c&&a!==n.x&&Vu(oi.x||n.x===i.x&&Iu(i,n)))&&(i=n,u=d)),n=n.next;while(n!==s);return i}function Iu(e,t){return Uu(e.prev,e,t.prev)<0&&Uu(t.next,e,e.next)<0}function Lu(e,t,n,r){let i=e;do i.z===0&&(i.z=zu(i.x,i.y,t,n,r)),i.prevZ=i.prev,i.nextZ=i.next,i=i.next;while(i!==e);i.prevZ.nextZ=null,i.prevZ=null,Ru(i)}function Ru(e){let t,n,r,i,a,o,s,c,l=1;do{for(n=e,e=null,a=null,o=0;n;){for(o++,r=n,s=0,t=0;t0||c>0&&r;)s!==0&&(c===0||!r||n.z<=r.z)?(i=n,n=n.nextZ,s--):(i=r,r=r.nextZ,c--),a?a.nextZ=i:e=i,i.prevZ=a,a=i;n=r}a.nextZ=null,l*=2}while(o>1);return e}function zu(e,t,n,r,i){return e=(e-n)*i|0,t=(t-r)*i|0,e=(e|e<<8)&16711935,e=(e|e<<4)&252645135,e=(e|e<<2)&858993459,e=(e|e<<1)&1431655765,t=(t|t<<8)&16711935,t=(t|t<<4)&252645135,t=(t|t<<2)&858993459,t=(t|t<<1)&1431655765,e|t<<1}function Bu(e){let t=e,n=e;do(t.x=(e-o)*(a-s)&&(e-o)*(r-s)>=(n-o)*(t-s)&&(n-o)*(a-s)>=(i-o)*(r-s)}function Hu(e,t){return e.next.i!==t.i&&e.prev.i!==t.i&&!Ju(e,t)&&(Yu(e,t)&&Yu(t,e)&&Xu(e,t)&&(Uu(e.prev,e,t.prev)||Uu(e,t.prev,t))||Wu(e,t)&&Uu(e.prev,e,e.next)>0&&Uu(t.prev,t,t.next)>0)}function Uu(e,t,n){return(t.y-e.y)*(n.x-t.x)-(t.x-e.x)*(n.y-t.y)}function Wu(e,t){return e.x===t.x&&e.y===t.y}function Gu(e,t,n,r){let i=qu(Uu(e,t,n)),a=qu(Uu(e,t,r)),o=qu(Uu(n,r,e)),s=qu(Uu(n,r,t));return!!(i!==a&&o!==s||i===0&&Ku(e,n,t)||a===0&&Ku(e,r,t)||o===0&&Ku(n,e,r)||s===0&&Ku(n,t,r))}function Ku(e,t,n){return t.x<=Math.max(e.x,n.x)&&t.x>=Math.min(e.x,n.x)&&t.y<=Math.max(e.y,n.y)&&t.y>=Math.min(e.y,n.y)}function qu(e){return e>0?1:e<0?-1:0}function Ju(e,t){let n=e;do{if(n.i!==e.i&&n.next.i!==e.i&&n.i!==t.i&&n.next.i!==t.i&&Gu(n,n.next,e,t))return!0;n=n.next}while(n!==e);return!1}function Yu(e,t){return Uu(e.prev,e,e.next)<0?Uu(e,t,e.next)>=0&&Uu(e,e.prev,t)>=0:Uu(e,t,e.prev)<0||Uu(e,e.next,t)<0}function Xu(e,t){let n=e,r=!1,i=(e.x+t.x)/2,a=(e.y+t.y)/2;do n.y>a!=n.next.y>a&&n.next.y!==n.y&&i<(n.next.x-n.x)*(a-n.y)/(n.next.y-n.y)+n.x&&(r=!r),n=n.next;while(n!==e);return r}function Zu(e,t){let n=new ed(e.i,e.x,e.y),r=new ed(t.i,t.x,t.y),i=e.next,a=t.prev;return e.next=t,t.prev=e,n.next=i,i.prev=n,r.next=n,n.prev=r,a.next=r,r.prev=a,r}function Qu(e,t,n,r){let i=new ed(e,t,n);return r?(i.next=r.next,i.prev=r,r.next.prev=i,r.next=i):(i.prev=i,i.next=i),i}function $u(e){e.next.prev=e.prev,e.prev.next=e.next,e.prevZ&&(e.prevZ.nextZ=e.nextZ),e.nextZ&&(e.nextZ.prevZ=e.prevZ)}function ed(e,t,n){this.i=e,this.x=t,this.y=n,this.prev=null,this.next=null,this.z=0,this.prevZ=null,this.nextZ=null,this.steiner=!1}function td(e,t,n,r){let i=0;for(let a=t,o=n-r;a2&&e[t-1].equals(e[0])&&e.pop()}function id(e,t){for(let n=0;n2**-52){let d=Math.sqrt(u),f=Math.sqrt(c*c+l*l),p=t.x-s/d,m=t.y+o/d,h=n.x-l/f,g=n.y+c/f,_=((h-p)*l-(g-m)*c)/(o*l-s*c);r=p+o*_-e.x,i=m+s*_-e.y;let v=r*r+i*i;if(v<=2)return new H(r,i);a=Math.sqrt(v/2)}else{let e=!1;o>2**-52?c>2**-52&&(e=!0):o<-(2**-52)?c<-(2**-52)&&(e=!0):Math.sign(s)===Math.sign(l)&&(e=!0),e?(r=-s,i=o,a=Math.sqrt(u)):(r=o,i=s,a=Math.sqrt(u/2))}return new H(r/a,i/a)}let j=[];for(let e=0,t=E.length,n=t-1,r=e+1;e=0;e--){let t=e/p,n=u*Math.cos(t*Math.PI/2),r=d*Math.sin(t*Math.PI/2)+f;for(let e=0,t=E.length;e=0;){let r=n,i=n-1;i<0&&(i=e.length-1);for(let e=0,n=s+p*2;e0!=e>0&&this.version++,this._anisotropy=e}get clearcoat(){return this._clearcoat}set clearcoat(e){this._clearcoat>0!=e>0&&this.version++,this._clearcoat=e}get iridescence(){return this._iridescence}set iridescence(e){this._iridescence>0!=e>0&&this.version++,this._iridescence=e}get dispersion(){return this._dispersion}set dispersion(e){this._dispersion>0!=e>0&&this.version++,this._dispersion=e}get sheen(){return this._sheen}set sheen(e){this._sheen>0!=e>0&&this.version++,this._sheen=e}get transmission(){return this._transmission}set transmission(e){this._transmission>0!=e>0&&this.version++,this._transmission=e}copy(e){return super.copy(e),this.defines={STANDARD:``,PHYSICAL:``},this.anisotropy=e.anisotropy,this.anisotropyRotation=e.anisotropyRotation,this.anisotropyMap=e.anisotropyMap,this.clearcoat=e.clearcoat,this.clearcoatMap=e.clearcoatMap,this.clearcoatRoughness=e.clearcoatRoughness,this.clearcoatRoughnessMap=e.clearcoatRoughnessMap,this.clearcoatNormalMap=e.clearcoatNormalMap,this.clearcoatNormalScale.copy(e.clearcoatNormalScale),this.dispersion=e.dispersion,this.ior=e.ior,this.iridescence=e.iridescence,this.iridescenceMap=e.iridescenceMap,this.iridescenceIOR=e.iridescenceIOR,this.iridescenceThicknessRange=[...e.iridescenceThicknessRange],this.iridescenceThicknessMap=e.iridescenceThicknessMap,this.sheen=e.sheen,this.sheenColor.copy(e.sheenColor),this.sheenColorMap=e.sheenColorMap,this.sheenRoughness=e.sheenRoughness,this.sheenRoughnessMap=e.sheenRoughnessMap,this.transmission=e.transmission,this.transmissionMap=e.transmissionMap,this.thickness=e.thickness,this.thicknessMap=e.thicknessMap,this.attenuationDistance=e.attenuationDistance,this.attenuationColor.copy(e.attenuationColor),this.specularIntensity=e.specularIntensity,this.specularIntensityMap=e.specularIntensityMap,this.specularColor.copy(e.specularColor),this.specularColorMap=e.specularColorMap,this}};function fd(e,t,n){return!e||!n&&e.constructor===t?e:typeof t.BYTES_PER_ELEMENT==`number`?new t(e):Array.prototype.slice.call(e)}function pd(e){return ArrayBuffer.isView(e)&&!(e instanceof DataView)}function md(e){function t(t,n){return e[t]-e[n]}let n=e.length,r=Array(n);for(let e=0;e!==n;++e)r[e]=e;return r.sort(t),r}function hd(e,t,n){let r=e.length,i=new e.constructor(r);for(let a=0,o=0;o!==r;++a){let r=n[a]*t;for(let n=0;n!==t;++n)i[o++]=e[r+n]}return i}function gd(e,t,n,r){let i=1,a=e[0];for(;a!==void 0&&a[r]===void 0;)a=e[i++];if(a===void 0)return;let o=a[r];if(o!==void 0){if(Array.isArray(o))do o=a[r],o!==void 0&&(t.push(a.time),n.push.apply(n,o)),a=e[i++];while(a!==void 0);else if(o.toArray!==void 0)do o=a[r],o!==void 0&&(t.push(a.time),o.toArray(n,n.length)),a=e[i++];while(a!==void 0);else do o=a[r],o!==void 0&&(t.push(a.time),n.push(o)),a=e[i++];while(a!==void 0)}}var _d=class{constructor(e,t,n,r){this.parameterPositions=e,this._cachedIndex=0,this.resultBuffer=r===void 0?new t.constructor(n):r,this.sampleValues=t,this.valueSize=n,this.settings=null,this.DefaultSettings_={}}evaluate(e){let t=this.parameterPositions,n=this._cachedIndex,r=t[n],i=t[n-1];validate_interval:{seek:{let a;linear_scan:{forward_scan:if(!(e=i)){let o=t[1];e=i)break seek}a=n,n=0;break linear_scan}break validate_interval}for(;n>>1;et;)--a;if(++a,i!==0||a!==r){i>=a&&(a=Math.max(a,1),i=a-1);let e=this.getValueSize();this.times=n.slice(i,a),this.values=this.values.slice(i*e,a*e)}return this}validate(){let e=!0,t=this.getValueSize();t-Math.floor(t)!==0&&(console.error(`THREE.KeyframeTrack: Invalid value size in track.`,this),e=!1);let n=this.times,r=this.values,i=n.length;i===0&&(console.error(`THREE.KeyframeTrack: Track is empty.`,this),e=!1);let a=null;for(let t=0;t!==i;t++){let r=n[t];if(typeof r==`number`&&isNaN(r)){console.error(`THREE.KeyframeTrack: Time is not a valid number.`,this,t,r),e=!1;break}if(a!==null&&a>r){console.error(`THREE.KeyframeTrack: Out of order keys.`,this,t,r,a),e=!1;break}a=r}if(r!==void 0&&pd(r))for(let t=0,n=r.length;t!==n;++t){let n=r[t];if(isNaN(n)){console.error(`THREE.KeyframeTrack: Value is not a valid number.`,this,t,n),e=!1;break}}return e}optimize(){let e=this.times.slice(),t=this.values.slice(),n=this.getValueSize(),r=this.getInterpolation()===Ut,i=e.length-1,a=1;for(let o=1;o0){e[a]=e[i];for(let e=i*n,r=a*n,o=0;o!==n;++o)t[r+o]=t[e+o];++a}return a===e.length?(this.times=e,this.values=t):(this.times=e.slice(0,a),this.values=t.slice(0,a*n)),this}clone(){let e=this.times.slice(),t=this.values.slice(),n=this.constructor,r=new n(this.name,e,t);return r.createInterpolant=this.createInterpolant,r}};xd.prototype.TimeBufferType=Float32Array,xd.prototype.ValueBufferType=Float32Array,xd.prototype.DefaultInterpolation=Ht;var Sd=class extends xd{constructor(e,t,n){super(e,t,n)}};Sd.prototype.ValueTypeName=`bool`,Sd.prototype.ValueBufferType=Array,Sd.prototype.DefaultInterpolation=Vt,Sd.prototype.InterpolantFactoryMethodLinear=void 0,Sd.prototype.InterpolantFactoryMethodSmooth=void 0;var Cd=class extends xd{};Cd.prototype.ValueTypeName=`color`;var wd=class extends xd{};wd.prototype.ValueTypeName=`number`;var Td=class extends _d{constructor(e,t,n,r){super(e,t,n,r)}interpolate_(e,t,n,r){let i=this.resultBuffer,a=this.sampleValues,o=this.valueSize,s=(n-t)/(r-t),c=e*o;for(let e=c+o;c!==e;c+=4)cr.slerpFlat(i,0,a,c-o,a,c,s);return i}},Ed=class extends xd{InterpolantFactoryMethodLinear(e){return new Td(this.times,this.values,this.getValueSize(),e)}};Ed.prototype.ValueTypeName=`quaternion`,Ed.prototype.InterpolantFactoryMethodSmooth=void 0;var Dd=class extends xd{constructor(e,t,n){super(e,t,n)}};Dd.prototype.ValueTypeName=`string`,Dd.prototype.ValueBufferType=Array,Dd.prototype.DefaultInterpolation=Vt,Dd.prototype.InterpolantFactoryMethodLinear=void 0,Dd.prototype.InterpolantFactoryMethodSmooth=void 0;var Od=class extends xd{};Od.prototype.ValueTypeName=`vector`;var kd=class{constructor(e=``,t=-1,n=[],r=qt){this.name=e,this.tracks=n,this.duration=t,this.blendMode=r,this.uuid=fn(),this.duration<0&&this.resetDuration()}static parse(e){let t=[],n=e.tracks,r=1/(e.fps||1);for(let e=0,i=n.length;e!==i;++e)t.push(jd(n[e]).scale(r));let i=new this(e.name,e.duration,t,e.blendMode);return i.uuid=e.uuid,i}static toJSON(e){let t=[],n=e.tracks,r={name:e.name,duration:e.duration,tracks:t,uuid:e.uuid,blendMode:e.blendMode};for(let e=0,r=n.length;e!==r;++e)t.push(xd.toJSON(n[e]));return r}static CreateFromMorphTargetSequence(e,t,n,r){let i=t.length,a=[];for(let e=0;e1){let e=a[1],t=r[e];t||(r[e]=t=[]),t.push(n)}}let a=[];for(let e in r)a.push(this.CreateFromMorphTargetSequence(e,r[e],t,n));return a}static parseAnimation(e,t){if(!e)return console.error(`THREE.AnimationClip: No animation in JSONLoader data.`),null;let n=function(e,t,n,r,i){if(n.length!==0){let a=[],o=[];gd(n,a,o,r),a.length!==0&&i.push(new e(t,a,o))}},r=[],i=e.name||`default`,a=e.fps||30,o=e.blendMode,s=e.length||-1,c=e.hierarchy||[];for(let e=0;e{t&&t(i),this.manager.itemEnd(e)},0),i;if(Fd[e]!==void 0){Fd[e].push({onLoad:t,onProgress:n,onError:r});return}Fd[e]=[],Fd[e].push({onLoad:t,onProgress:n,onError:r});let a=new Request(e,{headers:new Headers(this.requestHeader),credentials:this.withCredentials?`include`:`same-origin`}),o=this.mimeType,s=this.responseType;fetch(a).then(t=>{if(t.status===200||t.status===0){if(t.status===0&&console.warn(`THREE.FileLoader: HTTP Status 0 received.`),typeof ReadableStream>`u`||t.body===void 0||t.body.getReader===void 0)return t;let n=Fd[e],r=t.body.getReader(),i=t.headers.get(`X-File-Size`)||t.headers.get(`Content-Length`),a=i?parseInt(i):0,o=a!==0,s=0,c=new ReadableStream({start(e){t();function t(){r.read().then(({done:r,value:i})=>{if(r)e.close();else{s+=i.byteLength;let r=new ProgressEvent(`progress`,{lengthComputable:o,loaded:s,total:a});for(let e=0,t=n.length;e{e.error(t)})}}});return new Response(c)}throw new Id(`fetch for "${t.url}" responded with ${t.status}: ${t.statusText}`,t)}).then(e=>{switch(s){case`arraybuffer`:return e.arrayBuffer();case`blob`:return e.blob();case`document`:return e.text().then(e=>new DOMParser().parseFromString(e,o));case`json`:return e.json();default:if(o===void 0)return e.text();{let t=/charset="?([^;"\s]*)"?/i.exec(o),n=t&&t[1]?t[1].toLowerCase():void 0,r=new TextDecoder(n);return e.arrayBuffer().then(e=>r.decode(e))}}}).then(t=>{Md.add(e,t);let n=Fd[e];delete Fd[e];for(let e=0,r=n.length;e{let n=Fd[e];if(n===void 0)throw this.manager.itemError(e),t;delete Fd[e];for(let e=0,r=n.length;e{this.manager.itemEnd(e)}),this.manager.itemStart(e)}setResponseType(e){return this.responseType=e,this}setMimeType(e){return this.mimeType=e,this}},Rd=class extends Pd{constructor(e){super(e)}load(e,t,n,r){this.path!==void 0&&(e=this.path+e),e=this.manager.resolveURL(e);let i=this,a=Md.get(e);if(a!==void 0)return i.manager.itemStart(e),setTimeout(function(){t&&t(a),i.manager.itemEnd(e)},0),a;let o=In(`img`);function s(){l(),Md.add(e,this),t&&t(this),i.manager.itemEnd(e)}function c(t){l(),r&&r(t),i.manager.itemError(e),i.manager.itemEnd(e)}function l(){o.removeEventListener(`load`,s,!1),o.removeEventListener(`error`,c,!1)}return o.addEventListener(`load`,s,!1),o.addEventListener(`error`,c,!1),e.slice(0,5)!==`data:`&&this.crossOrigin!==void 0&&(o.crossOrigin=this.crossOrigin),i.manager.itemStart(e),o.src=e,o}},zd=class extends Pd{constructor(e){super(e)}load(e,t,n,r){let i=new nr,a=new Rd(this.manager);return a.setCrossOrigin(this.crossOrigin),a.setPath(this.path),a.load(e,function(e){i.image=e,i.needsUpdate=!0,t!==void 0&&t(i)},n,r),i}},Bd=class extends ui{constructor(e,t=1){super(),this.isLight=!0,this.type=`Light`,this.color=new K(e),this.intensity=t}dispose(){}copy(e,t){return super.copy(e,t),this.color.copy(e.color),this.intensity=e.intensity,this}toJSON(e){let t=super.toJSON(e);return t.object.color=this.color.getHex(),t.object.intensity=this.intensity,this.groundColor!==void 0&&(t.object.groundColor=this.groundColor.getHex()),this.distance!==void 0&&(t.object.distance=this.distance),this.angle!==void 0&&(t.object.angle=this.angle),this.decay!==void 0&&(t.object.decay=this.decay),this.penumbra!==void 0&&(t.object.penumbra=this.penumbra),this.shadow!==void 0&&(t.object.shadow=this.shadow.toJSON()),this.target!==void 0&&(t.object.target=this.target.uuid),t}},Vd=new G,Hd=new W,Ud=new W,Wd=class{constructor(e){this.camera=e,this.intensity=1,this.bias=0,this.normalBias=0,this.radius=1,this.blurSamples=8,this.mapSize=new H(512,512),this.map=null,this.mapPass=null,this.matrix=new G,this.autoUpdate=!0,this.needsUpdate=!1,this._frustum=new Ia,this._frameExtents=new H(1,1),this._viewportCount=1,this._viewports=[new rr(0,0,1,1)]}getViewportCount(){return this._viewportCount}getFrustum(){return this._frustum}updateMatrices(e){let t=this.camera,n=this.matrix;Hd.setFromMatrixPosition(e.matrixWorld),t.position.copy(Hd),Ud.setFromMatrixPosition(e.target.matrixWorld),t.lookAt(Ud),t.updateMatrixWorld(),Vd.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),this._frustum.setFromProjectionMatrix(Vd),n.set(.5,0,0,.5,0,.5,0,.5,0,0,.5,.5,0,0,0,1),n.multiply(Vd)}getViewport(e){return this._viewports[e]}getFrameExtents(){return this._frameExtents}dispose(){this.map&&this.map.dispose(),this.mapPass&&this.mapPass.dispose()}copy(e){return this.camera=e.camera.clone(),this.intensity=e.intensity,this.bias=e.bias,this.radius=e.radius,this.mapSize.copy(e.mapSize),this}clone(){return new this.constructor().copy(this)}toJSON(){let e={};return this.intensity!==1&&(e.intensity=this.intensity),this.bias!==0&&(e.bias=this.bias),this.normalBias!==0&&(e.normalBias=this.normalBias),this.radius!==1&&(e.radius=this.radius),(this.mapSize.x!==512||this.mapSize.y!==512)&&(e.mapSize=this.mapSize.toArray()),e.camera=this.camera.toJSON(!1).object,delete e.camera.matrix,e}},Gd=class extends Wd{constructor(){super(new wa(50,1,.5,500)),this.isSpotLightShadow=!0,this.focus=1}updateMatrices(e){let t=this.camera,n=dn*2*e.angle*this.focus,r=this.mapSize.width/this.mapSize.height,i=e.distance||t.far;(n!==t.fov||r!==t.aspect||i!==t.far)&&(t.fov=n,t.aspect=r,t.far=i,t.updateProjectionMatrix()),super.updateMatrices(e)}copy(e){return super.copy(e),this.focus=e.focus,this}},Kd=class extends Bd{constructor(e,t,n=0,r=Math.PI/3,i=0,a=2){super(e,t),this.isSpotLight=!0,this.type=`SpotLight`,this.position.copy(ui.DEFAULT_UP),this.updateMatrix(),this.target=new ui,this.distance=n,this.angle=r,this.penumbra=i,this.decay=a,this.map=null,this.shadow=new Gd}get power(){return this.intensity*Math.PI}set power(e){this.intensity=e/Math.PI}dispose(){this.shadow.dispose()}copy(e,t){return super.copy(e,t),this.distance=e.distance,this.angle=e.angle,this.penumbra=e.penumbra,this.decay=e.decay,this.target=e.target.clone(),this.shadow=e.shadow.clone(),this}},qd=new G,Jd=new W,Yd=new W,Xd=class extends Wd{constructor(){super(new wa(90,1,.5,500)),this.isPointLightShadow=!0,this._frameExtents=new H(4,2),this._viewportCount=6,this._viewports=[new rr(2,1,1,1),new rr(0,1,1,1),new rr(3,1,1,1),new rr(1,1,1,1),new rr(3,0,1,1),new rr(1,0,1,1)],this._cubeDirections=[new W(1,0,0),new W(-1,0,0),new W(0,0,1),new W(0,0,-1),new W(0,1,0),new W(0,-1,0)],this._cubeUps=[new W(0,1,0),new W(0,1,0),new W(0,1,0),new W(0,1,0),new W(0,0,1),new W(0,0,-1)]}updateMatrices(e,t=0){let n=this.camera,r=this.matrix,i=e.distance||n.far;i!==n.far&&(n.far=i,n.updateProjectionMatrix()),Jd.setFromMatrixPosition(e.matrixWorld),n.position.copy(Jd),Yd.copy(n.position),Yd.add(this._cubeDirections[t]),n.up.copy(this._cubeUps[t]),n.lookAt(Yd),n.updateMatrixWorld(),r.makeTranslation(-Jd.x,-Jd.y,-Jd.z),qd.multiplyMatrices(n.projectionMatrix,n.matrixWorldInverse),this._frustum.setFromProjectionMatrix(qd)}},Zd=class extends Bd{constructor(e,t,n=0,r=2){super(e,t),this.isPointLight=!0,this.type=`PointLight`,this.distance=n,this.decay=r,this.shadow=new Xd}get power(){return this.intensity*4*Math.PI}set power(e){this.intensity=e/(4*Math.PI)}dispose(){this.shadow.dispose()}copy(e,t){return super.copy(e,t),this.distance=e.distance,this.decay=e.decay,this.shadow=e.shadow.clone(),this}},Qd=class extends Wd{constructor(){super(new Xa(-5,5,5,-5,.5,500)),this.isDirectionalLightShadow=!0}},$d=class extends Bd{constructor(e,t){super(e,t),this.isDirectionalLight=!0,this.type=`DirectionalLight`,this.position.copy(ui.DEFAULT_UP),this.updateMatrix(),this.target=new ui,this.shadow=new Qd}dispose(){this.shadow.dispose()}copy(e){return super.copy(e),this.target=e.target.clone(),this.shadow=e.shadow.clone(),this}},ef=class extends Bd{constructor(e,t){super(e,t),this.isAmbientLight=!0,this.type=`AmbientLight`}},tf=class extends Bd{constructor(e,t,n=10,r=10){super(e,t),this.isRectAreaLight=!0,this.type=`RectAreaLight`,this.width=n,this.height=r}get power(){return this.intensity*this.width*this.height*Math.PI}set power(e){this.intensity=e/(this.width*this.height*Math.PI)}copy(e){return super.copy(e),this.width=e.width,this.height=e.height,this}toJSON(e){let t=super.toJSON(e);return t.object.width=this.width,t.object.height=this.height,t}},nf=class{static decodeText(e){if(console.warn(`THREE.LoaderUtils: decodeText() has been deprecated with r165 and will be removed with r175. Use TextDecoder instead.`),typeof TextDecoder<`u`)return new TextDecoder().decode(e);let t=``;for(let n=0,r=e.length;n`u`&&console.warn(`THREE.ImageBitmapLoader: createImageBitmap() not supported.`),typeof fetch>`u`&&console.warn(`THREE.ImageBitmapLoader: fetch() not supported.`),this.options={premultiplyAlpha:`none`}}setOptions(e){return this.options=e,this}load(e,t,n,r){e===void 0&&(e=``),this.path!==void 0&&(e=this.path+e),e=this.manager.resolveURL(e);let i=this,a=Md.get(e);if(a!==void 0){if(i.manager.itemStart(e),a.then){a.then(n=>{t&&t(n),i.manager.itemEnd(e)}).catch(e=>{r&&r(e)});return}return setTimeout(function(){t&&t(a),i.manager.itemEnd(e)},0),a}let o={};o.credentials=this.crossOrigin===`anonymous`?`same-origin`:`include`,o.headers=this.requestHeader;let s=fetch(e,o).then(function(e){return e.blob()}).then(function(e){return createImageBitmap(e,Object.assign(i.options,{colorSpaceConversion:`none`}))}).then(function(n){return Md.add(e,n),t&&t(n),i.manager.itemEnd(e),n}).catch(function(t){r&&r(t),Md.remove(e),i.manager.itemError(e),i.manager.itemEnd(e)});Md.add(e,s),i.manager.itemStart(e)}},af=`\\[\\]\\.:\\/`,of=RegExp(`[\\[\\]\\.:\\/]`,`g`),sf=`[^\\[\\]\\.:\\/]`,cf=`[^`+af.replace(`\\.`,``)+`]`,lf=`((?:WC+[\\/:])*)`.replace(`WC`,sf),uf=`(WCOD+)?`.replace(`WCOD`,cf),df=`(?:\\.(WC+)(?:\\[(.+)\\])?)?`.replace(`WC`,sf),ff=`\\.(WC+)(?:\\[(.+)\\])?`.replace(`WC`,sf),pf=RegExp(`^`+lf+uf+df+ff+`$`),mf=[`material`,`materials`,`bones`,`map`],hf=class{constructor(e,t,n){let r=n||gf.parseTrackName(t);this._targetGroup=e,this._bindings=e.subscribe_(t,r)}getValue(e,t){this.bind();let n=this._targetGroup.nCachedObjects_,r=this._bindings[n];r!==void 0&&r.getValue(e,t)}setValue(e,t){let n=this._bindings;for(let r=this._targetGroup.nCachedObjects_,i=n.length;r!==i;++r)n[r].setValue(e,t)}bind(){let e=this._bindings;for(let t=this._targetGroup.nCachedObjects_,n=e.length;t!==n;++t)e[t].bind()}unbind(){let e=this._bindings;for(let t=this._targetGroup.nCachedObjects_,n=e.length;t!==n;++t)e[t].unbind()}},gf=class e{constructor(t,n,r){this.path=n,this.parsedPath=r||e.parseTrackName(n),this.node=e.findNode(t,this.parsedPath.nodeName),this.rootNode=t,this.getValue=this._getValue_unbound,this.setValue=this._setValue_unbound}static create(t,n,r){return t&&t.isAnimationObjectGroup?new e.Composite(t,n,r):new e(t,n,r)}static sanitizeNodeName(e){return e.replace(/\s/g,`_`).replace(of,``)}static parseTrackName(e){let t=pf.exec(e);if(t===null)throw Error(`PropertyBinding: Cannot parse trackName: `+e);let n={nodeName:t[2],objectName:t[3],objectIndex:t[4],propertyName:t[5],propertyIndex:t[6]},r=n.nodeName&&n.nodeName.lastIndexOf(`.`);if(r!==void 0&&r!==-1){let e=n.nodeName.substring(r+1);mf.indexOf(e)!==-1&&(n.nodeName=n.nodeName.substring(0,r),n.objectName=e)}if(n.propertyName===null||n.propertyName.length===0)throw Error(`PropertyBinding: can not parse propertyName from trackName: `+e);return n}static findNode(e,t){if(t===void 0||t===``||t===`.`||t===-1||t===e.name||t===e.uuid)return e;if(e.skeleton){let n=e.skeleton.getBoneByName(t);if(n!==void 0)return n}if(e.children){let n=function(e){for(let r=0;r0&&(i=Math.min(i,n),a=Math.max(a,n),o=Math.min(o,r),s=Math.max(s,r));if(a{if(r.aborted)throw new DOMException(`Cancelled`,`AbortError`);if(e.getContext().isContextLost())throw Error(`화면 연결이 복구된 뒤 다시 저장해 주세요.`)};a();let o=e.getDrawingBufferSize(new H),s=Math.min(1,(n===`photo`?1024:2048)/Math.max(o.x,o.y)),c=Math.max(1,Math.round(o.x*s)),l=Math.max(1,Math.round(o.y*s)),u=new ar(c,l,{type:ze,format:$e,colorSpace:Xt,depthBuffer:!0,samples:0}),d=e.getRenderTarget(),f=e.getViewport(new rr),p=e.getScissor(new rr),m=e.getScissorTest(),h=e.getClearColor(new K),g=e.getClearAlpha(),_=e.autoClear;try{let r=new Uint8Array(c*l*4);try{e.setClearColor(0,0),e.autoClear=!0,i(u)}finally{e.setRenderTarget(d),e.setViewport(f),e.setScissor(p),e.setScissorTest(m),e.setClearColor(h,g),e.autoClear=_}a(),await e.readRenderTargetPixelsAsync(u,0,0,c,l,r),a();let o=xf(r,c,l,n===`photo`),s=t.createElement(`canvas`);s.width=o.width,s.height=o.height;let v=s.getContext(`2d`);if(!v)throw Error(`이미지를 저장할 수 없어요. 다시 시도해 주세요.`);let y=v.createImageData(o.width,o.height);y.data.set(o.data),v.putImageData(y,0,0);let b=await new Promise((e,t)=>s.toBlob(n=>n?e(n):t(Error(`이미지 파일을 만들지 못했어요.`)),`image/png`));return a(),b}finally{u.dispose()}}function Cf(e,t,n,r,i){let a=t=>e.querySelector(`#${t}`),o=a(`export-dialog`),s=a(`export-open`),c=a(`export-photo`),l=a(`export-scene`),u=a(`export-preview`),d=a(`export-status`),f=a(`export-download`),p=a(`export-share`),m=e.defaultView.URL,h=e.defaultView.navigator,g=0,_=null,v=null,y=null,b=!1,x=()=>{v&&m.revokeObjectURL(v),v=null,y=null,u.removeAttribute(`src`),u.hidden=!0,f.removeAttribute(`href`),f.hidden=!0,p.hidden=!0,p.disabled=!1},S=()=>{g++,_?.abort(),_=null,b=!1,c.disabled=!1,l.disabled=!1,x()},C=()=>{o.open?o.close():S()};s.addEventListener(`click`,()=>{t.aborted||!n()||o.open||(S(),d.textContent=`마음에 드는 현재 구도를 저장해 보세요`,o.showModal(),i(),c.focus())},{signal:t});let w=async e=>{if(t.aborted||!o.open||b||!n())return;S(),b=!0,c.disabled=!0,l.disabled=!0;let i=g;_=new AbortController,d.textContent=`지금 모습을 사진으로 담는 중…`,o.setAttribute(`aria-busy`,`true`);try{let a=await r(e,_.signal);if(i!==g||t.aborted||!o.open||!n())return;y=new File([a],e===`photo`?`behind-glass-photo.png`:`behind-glass-scene.png`,{type:`image/png`}),v=m.createObjectURL(a),u.src=v,u.hidden=!1,u.alt=e===`photo`?`현재 구도의 굴절사진 저장 미리보기`:`방을 포함한 현재 화면 저장 미리보기`,f.href=v,f.download=y.name,f.hidden=!1;try{p.hidden=!(typeof h.share==`function`&&h.canShare?.({files:[y]}))}catch{p.hidden=!0}d.textContent=e===`photo`?`체크무늬 부분은 투명하게 저장돼요`:`버튼과 안내 문구 없이 저장돼요`}catch(e){i===g&&!t.aborted&&o.open&&(d.textContent=e instanceof Error?e.message:`사진을 만들지 못했어요. 다시 시도해 주세요.`)}finally{i===g&&(b=!1,c.disabled=!1,l.disabled=!1,o.setAttribute(`aria-busy`,`false`))}};return c.addEventListener(`click`,()=>{w(`photo`)},{signal:t}),l.addEventListener(`click`,()=>{w(`scene`)},{signal:t}),p.addEventListener(`click`,async()=>{if(!y||b||p.disabled||!o.open||t.aborted)return;let e=g;p.disabled=!0;try{await h.share({files:[y]})}catch(t){e===g&&t?.name!==`AbortError`&&(d.textContent=`공유를 열지 못했어요. 내려받기를 이용해 주세요.`)}finally{e===g&&(p.disabled=!1)}},{signal:t}),a(`export-close`).addEventListener(`click`,C,{signal:t}),o.addEventListener(`cancel`,e=>{e.preventDefault(),C()},{signal:t}),o.addEventListener(`click`,e=>{if(e.target!==o)return;let t=o.getBoundingClientRect();(e.clientXt.right||e.clientYt.bottom)&&C()},{signal:t}),o.addEventListener(`close`,()=>{S(),o.setAttribute(`aria-busy`,`false`),i(),!t.aborted&&n()&&!s.hidden&&(e.querySelector(`#scene-menu-open`)??s).focus()},{signal:t}),t.addEventListener(`abort`,()=>{S(),o.open&&o.close()},{once:!0}),x(),{cancel:C,setAvailable(e){s.disabled=!e}}}function wf(e){if(!e)return!1;if(e.userAgentData?.mobile===!0)return!0;let t=e.userAgent??``;return/Android|iPhone|iPad|iPod/i.test(t)||/Macintosh|MacIntel/i.test(t)&&(e.maxTouchPoints??0)>1}function Tf(e,t){let n=t=>e.querySelector(`#${t}`),r=n(`entry-notices`),i=[`photo-tip`,`privacy-tip`,`paste-tip`].map(n),a=e.defaultView?.matchMedia?.(`(hover: hover) and (pointer: fine)`),o=0,s=null,c=()=>a?.matches?3:2,l=(e=!1)=>{let t=c();o>=t&&(o=0),i.forEach((e,n)=>{e.hidden=n>=t,e.dataset.active=String(n===o),e.setAttribute(`aria-hidden`,String(n!==o))}),n(`notice-position`).textContent=`${o+1} / ${t}`,e&&(n(`notice-status`).textContent=`${o+1} / ${t}. ${i[o].textContent}`)},u=e=>{o=(o+e+c())%c(),l(!0)};n(`notice-prev`).addEventListener(`click`,()=>u(-1),{signal:t}),n(`notice-next`).addEventListener(`click`,()=>u(1),{signal:t}),a?.addEventListener(`change`,()=>{s=null,n(`notice-status`).textContent=``,l()},{signal:t}),r.addEventListener(`pointerdown`,e=>{if(!e.isPrimary){s=null;return}e.pointerType!==`touch`||e.target?.closest?.(`button`)||(s={id:e.pointerId,x:e.clientX,y:e.clientY})},{signal:t}),r.addEventListener(`pointerup`,e=>{let t=s;if(s=null,!t||t.id!==e.pointerId)return;let n=e.clientX-t.x,r=e.clientY-t.y;Math.abs(n)>=40&&Math.abs(n)>Math.abs(r)*1.5&&u(n<0?1:-1)},{signal:t}),r.addEventListener(`pointercancel`,()=>{s=null},{signal:t}),t.addEventListener(`abort`,()=>{s=null},{once:!0}),l()}function Ef(e,t,n,r){let i=e=>{let t=e;return!!(t?.isContentEditable||t?.closest?.(`input, textarea, select, [role="textbox"], [contenteditable]:not([contenteditable="false"])`))};e.addEventListener(`paste`,a=>{if(t.aborted||a.defaultPrevented||!n()||e.querySelector?.(`dialog[open]`)||i(a.target)||i(e.activeElement)||a.composedPath?.().some(i))return;let o=a.clipboardData;if(!o)return;let s=null;for(let e of Array.from(o.items??[])){if(e.kind!==`file`||!e.type.startsWith(`image/`))continue;let t=e.getAsFile();if(t?.type.startsWith(`image/`)){s=t;break}}s||=Array.from(o.files??[]).find(e=>e.type.startsWith(`image/`))??null,s&&r(s)&&a.preventDefault()},{signal:t})}var Df=`behind-glass.pet-name.v1`;function Of(e){return Array.from(e.normalize(`NFC`).trim()).slice(0,20).join(``)}function kf(e){let t=Of(e)||`멍멍이`,n=t.codePointAt(t.length-1)??0,r=n>=44032&&n<=55203&&(n-44032)%28!=0?`${t}이`:t;return{display:r,object:`${r}를`,subject:`${r}가`,possessive:`${r}의`}}function Af(e){let t=``,n,r=!1,i=new Set;try{n=e(),r=!n,t=Of(n?.getItem(`behind-glass.pet-name.v1`)??``)}catch{r=!0}return{get name(){return t},get storageUnavailable(){return r},setName(e){let a=Of(e);if(a!==t){t=a;try{n?.setItem(Df,t),r=!n}catch{r=!0}i.forEach(e=>e())}},subscribe(e,t){t.aborted||(i.add(e),t.addEventListener(`abort`,()=>i.delete(e),{once:!0}))}}}var jf=`behind-glass.visitor-id.v1`,Mf=/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/,Nf=new WeakMap;function Pf(e){if(Nf.has(e))return Nf.get(e);let t,n;try{t=e.getStorage();let r=t?.getItem(jf);r&&Mf.test(r)&&(n=r)}catch{}if(!n){try{let t=e.randomUUID?.();t&&Mf.test(t)&&(n=t)}catch{}if(n)try{t?.setItem(jf,n)}catch{}}return Nf.set(e,n),n}async function Ff(e,t,n){try{if(!n)return``;let r=Of(t)||`멍멍이`,i=new TextEncoder().encode(JSON.stringify([1,e,r])),a=new Uint8Array(await n(`SHA-256`,i));return a.length===32?Array.from(a,e=>e.toString(16).padStart(2,`0`)).join(``):``}catch{return``}}function If(e,t){let n;return new Promise((r,i)=>{if(n=()=>i(Error(`Telemetry cancelled`)),t.aborted){n();return}t.addEventListener(`abort`,n,{once:!0});try{Promise.resolve(e()).then(r,i)}catch(e){i(e)}}).finally(()=>t.removeEventListener(`abort`,n))}function Lf(e,t){return new Promise(n=>{let r=()=>{clearTimeout(i),t?.removeEventListener(`abort`,r),n()},i=setTimeout(r,e);t?.aborted?r():t?.addEventListener(`abort`,r,{once:!0})})}function Rf({fetch:e=(e,t)=>globalThis.fetch(e,t),sleep:t=Lf,timeoutMs:n=3e3,retryDelays:r=[500,1500]}={}){let i=r.slice(0,2);async function a(t,r,i){let a=new AbortController,o,s=()=>a.abort();i?.addEventListener(`abort`,s,{once:!0}),i?.aborted&&s();let c=setTimeout(s,n);try{return await If(async()=>{if(o=await e(t,{method:r===void 0?`GET`:`POST`,body:r,headers:r===void 0?void 0:{"Content-Type":`application/json`},signal:a.signal,credentials:`same-origin`,cache:`no-store`}),o.status===429||o.status>=500&&o.status<=599)return{result:{ok:!1},retry:!0};if(r!==void 0)return{result:{ok:o.status===204},retry:!1};if(o.status!==200)return{result:{ok:!1},retry:!1};let n;try{n=await o.json()}catch(e){if(e instanceof SyntaxError)return{result:{ok:!1},retry:!1};throw e}let i=n&&typeof n==`object`&&`count`in n?n.count:void 0;return{result:typeof i==`number`&&Number.isSafeInteger(i)&&i>=0?{ok:!0,count:i}:{ok:!1},retry:!1}},a.signal)}catch{return{result:{ok:!1},retry:!i?.aborted}}finally{if(o?.body&&!o.bodyUsed){a.abort();try{Promise.resolve(o.body.cancel()).catch(()=>{})}catch{}}clearTimeout(c),i?.removeEventListener(`abort`,s)}}return{async request(e,n,r){try{let o=n===void 0?void 0:JSON.stringify(n);for(let n=0;n<=i.length;n++){if(r?.aborted)return{ok:!1};let{result:s,retry:c}=await a(e,o,r);if(r?.aborted)return{ok:!1};if(!c||n===i.length)return s;r?await If(()=>t(i[n],r),r):await t(i[n])}}catch{}return{ok:!1}}}}function zf({visitorId:e,makeDogId:t,transport:n,onCount:r}){let i=new AbortController,a=!1,o=0,s,c=0,l=0;async function u(e,t,r){try{return await n.request(e,t,r)}catch{return{ok:!1}}}async function d(){let e=++c,t=await u(`/api/arrivals/count`,void 0,i.signal),n=t.count;if(!(i.signal.aborted||!t.ok||e<=l||typeof n!=`number`||!Number.isSafeInteger(n)||n<0)){l=e;try{r(n)}catch{}}}function f(){o++,s?.controller.abort(),s=void 0}function p(e){return!i.signal.aborted&&!e.controller.signal.aborted&&s===e&&o===e.token}async function m(e){if(!p(e))return;let t=await e.hash;p(e)&&/^[0-9a-f]{64}$/.test(t)&&(await u(`/api/arrivals`,{dog_id:t},e.controller.signal)).ok&&p(e)&&await d()}return{start(){a||i.signal.aborted||(a=!0,e&&u(`/api/visits`,{visitor_id:e},i.signal),d())},begin(n,r){f();let a=o;if(i.signal.aborted||n!==`personal`||!e)return a;let c;try{c=Promise.resolve(t(e,r)).catch(()=>``)}catch{c=Promise.resolve(``)}return s={token:a,controller:new AbortController,hash:c,scheduled:!1},a},invalidate:f,arrived(e){s&&s.token===e&&p(s)&&!s.scheduled&&(s.scheduled=!0,m(s).catch(()=>{}))},dispose(){f(),i.abort()}}}var Bf=new WeakSet;function Vf(e,t){let n=typeof t==`number`&&Number.isSafeInteger(t)&&t>=0;for(let r of e)n?(r.textContent=`지금까지 ${t.toLocaleString(`ko-KR`)}번 도착했어요`,r.hidden=!1,Bf.add(r)):Bf.has(r)||(r.hidden=!0)}var Hf=`behind-glass-camera-composition-v32`;function Uf(e){try{return e?.getItem(Hf)===`legacy`?`legacy`:`wall`}catch{return`wall`}}function Wf(e,t){try{return e?(e.setItem(Hf,t),!0):!1}catch{return!1}}var Gf={drag:`드래그해서 유리 너머를 둘러보세요`,tilt:`휴대폰을 살짝 기울여 둘러보세요`,"door-open":`손잡이를 왼쪽으로 밀면 열려요`,"door-close":`손잡이를 오른쪽으로 밀면 닫혀요`},Kf=class{learned=new Set;shown=new Map;sequence=0;ready=!1;due=1/0;active=null;interact(e,t){t&&this.learned.add(t),this.active=null,this.due=e+5e3}update(e,t){if(!t.enabled)return this.ready=!1,this.active=null,this.due=1/0,null;this.ready||(this.ready=!0,this.due=e+5e3);let n=[`drag`];t.tiltActive&&n.push(`tilt`),t.sliding&&n.push(t.doorOpen>.001?`door-close`:`door-open`);let r=n.filter(e=>!this.learned.has(e));if(this.active&&!r.includes(this.active.kind)&&(this.active=null,this.due=e+5e3),!r.length)return this.due=1/0,null;if(Number.isFinite(this.due)||(this.due=e+5e3),!this.active&&e>=this.due){let n=r.sort((e,t)=>(this.shown.get(e)??-1)-(this.shown.get(t)??-1))[0];this.shown.set(n,this.sequence++),this.active={kind:n,start:e,reduced:t.reducedMotion}}if(!this.active)return null;let i=e-this.active.start,a=t.reducedMotion||this.active.reduced;return i>=(a?3e3:4400)?(this.active=null,this.due=e+18e3,null):{kind:this.active.kind,text:Gf[this.active.kind],phase:a?`hold`:i<600?`in`:i<3600?`hold`:`out`}}};function qf(e,t,n){let r=e<720,i=r?38:16,a=Math.min(106,t*.22),o=Math.min(140,t*.28),s=Math.max(2,e-20),c=Math.max(2,t-a-o),l=r?s:(s-i)/2,u=r?(c-i)/2:c,d=Math.max(1,Math.min(l,u*n)),f=d/n,p=10+(l-d)/2,m=a+(u-f)/2;return{panes:[{x:p,y:m,width:d,height:f},{x:p+(r?0:l+i),y:m+(r?u+i:0),width:d,height:f}],stacked:r}}function Jf(e,t,n){return e.find(e=>t>=e.x&&t<=e.x+e.width&&n>=e.y&&n<=e.y+e.height)??null}var Yf=class{values={a:{cpuMs:0,calls:0,triangles:0},b:{cpuMs:0,calls:0,triangles:0}};previous=null;cadence=null;record(e,t,n){this.values[e]={cpuMs:t,calls:n.calls,triangles:n.triangles}}frame(e){if(this.previous!==null&&e>this.previous){let t=e-this.previous;this.cadence=this.cadence===null?t:this.cadence*.9+t*.1}this.previous=e}snapshot(){return{a:{...this.values.a},b:{...this.values.b},frameMs:this.cadence}}reset(){this.previous=null,this.cadence=null}},Xf=class{dirty=!0;signature=``;historySeconds=0;invalidate(){this.dirty=!0}shouldRender(e,t){let n=this.dirty||t.signature!==this.signature;if(t.temporal?(n||t.continuous)&&(this.historySeconds=.7):this.historySeconds=0,!(n||t.continuous||this.historySeconds>0))return!1;this.dirty=!1,this.signature=t.signature;let r=Number.isFinite(e)?Math.max(0,Math.min(e,.1)):0;return this.historySeconds=Math.max(0,this.historySeconds-r),!0}},Zf=class{static init(){let e=[1,0,0,2e-5,1,0,0,503905e-9,1,0,0,.00201562,1,0,0,.00453516,1,0,0,.00806253,1,0,0,.0125978,1,0,0,.018141,1,0,0,.0246924,1,0,0,.0322525,1,0,0,.0408213,1,0,0,.0503999,1,0,0,.0609894,1,0,0,.0725906,1,0,0,.0852058,1,0,0,.0988363,1,0,0,.113484,1,0,0,.129153,1,0,0,.145839,1,0,0,.163548,1,0,0,.182266,1,0,0,.201942,1,0,0,.222314,1,0,0,.241906,1,0,0,.262314,1,0,0,.285754,1,0,0,.310159,1,0,0,.335426,1,0,0,.361341,1,0,0,.387445,1,0,0,.412784,1,0,0,.438197,1,0,0,.466966,1,0,0,.49559,1,0,0,.523448,1,0,0,.549938,1,0,0,.57979,1,0,0,.608746,1,0,0,.636185,1,0,0,.664748,1,0,0,.69313,1,0,0,.71966,1,0,0,.747662,1,0,0,.774023,1,0,0,.799775,1,0,0,.825274,1,0,0,.849156,1,0,0,.873248,1,0,0,.89532,1,0,0,.917565,1,0,0,.937863,1,0,0,.958139,1,0,0,.976563,1,0,0,.994658,1,0,0,1.0112,1,0,0,1.02712,1,0,0,1.04189,1,0,0,1.05568,1,0,0,1.06877,1,0,0,1.08058,1,0,0,1.09194,1,0,0,1.10191,1,0,0,1.11161,1,0,0,1.1199,1,0,0,1.12813,.999547,-4.48815e-7,.0224417,199902e-10,.999495,-113079e-10,.0224406,503651e-9,.999496,-452317e-10,.0224406,.00201461,.999496,-101772e-9,.0224406,.00453287,.999495,-180928e-9,.0224406,.00805845,.999497,-282702e-9,.0224406,.0125914,.999496,-407096e-9,.0224406,.0181319,.999498,-554114e-9,.0224406,.02468,.999499,-723768e-9,.0224406,.0322363,.999495,-916058e-9,.0224405,.0408009,.999499,-.00113101,.0224408,.050375,.999494,-.00136863,.0224405,.0609586,.999489,-.00162896,.0224401,.0725537,.999489,-.00191201,.0224414,.0851619,.999498,-.00221787,.0224413,.0987867,.999492,-.00254642,.0224409,.113426,.999507,-.00289779,.0224417,.129088,.999494,-.0032716,.0224386,.145767,.999546,-.0036673,.0224424,.163472,.999543,-.00408166,.0224387,.182182,.999499,-.00450056,.0224338,.201843,.999503,-.00483661,.0224203,.222198,.999546,-.00452928,.022315,.241714,.999508,-.00587403,.0224329,.262184,.999509,-.00638806,.0224271,.285609,.999501,-.00691028,.0224166,.309998,.999539,-.00741979,.0223989,.335262,.999454,-.00786282,.0223675,.361154,.999529,-.00811928,.0222828,.387224,.999503,-.00799941,.0221063,.41252,.999561,-.00952753,.0223057,.438006,.999557,-.0099134,.0222065,.466735,.999541,-.0100935,.0220402,.495332,.999562,-.00996821,.0218067,.523197,.999556,-.0105031,.0217096,.550223,.999561,-.0114191,.0217215,.579498,.999588,-.0111818,.0213357,.608416,.999633,-.0107725,.0208689,.635965,.999527,-.0121671,.0210149,.664476,.999508,-.0116005,.020431,.692786,.999568,-.0115604,.0199791,.719709,.999671,-.0121117,.0197415,.74737,.999688,-.0110769,.0188846,.773692,.99962,-.0122368,.0188452,.799534,.999823,-.0110325,.0178001,.825046,.999599,-.0114923,.0174221,.849075,.999619,-.0105923,.0164345,.872999,.999613,-.0105988,.0158227,.895371,.99964,-.00979861,.0148131,.917364,.99977,-.00967238,.0140721,.938002,.999726,-.00869175,.0129543,.957917,.99973,-.00866872,.0122329,.976557,.999773,-.00731956,.0108958,.994459,.999811,-.00756027,.0102715,1.01118,.999862,-.00583732,.00878781,1.02701,.999835,-.00631438,.00827529,1.04186,.999871,-.00450785,.00674583,1.05569,.999867,-.00486079,.00621041,1.06861,.999939,-.00322072,.00478301,1.08064,.999918,-.00318199,.00406395,1.09181,1.00003,-.00193348,.00280682,1.10207,.999928,-.00153729,.00198741,1.11152,.999933,-623666e-9,917714e-9,1.12009,1,-102387e-11,9.07581e-7,1.12813,.997866,-8.96716e-7,.0448334,199584e-10,.997987,-225945e-10,.0448389,502891e-9,.997987,-903781e-10,.0448388,.00201156,.997985,-203351e-9,.0448388,.00452602,.997986,-361514e-9,.0448388,.00804629,.997987,-56487e-8,.0448389,.0125724,.997988,-813423e-9,.0448389,.0181045,.997984,-.00110718,.0448387,.0246427,.997985,-.00144616,.0448388,.0321875,.997987,-.00183038,.044839,.0407392,.997983,-.00225987,.0448387,.0502986,.997991,-.00273467,.0448389,.0608667,.997984,-.00325481,.0448384,.0724444,.998002,-.00382043,.044839,.0850348,.997997,-.00443145,.0448396,.0986372,.998007,-.00508796,.0448397,.113255,.998008,-.00578985,.04484,.128891,.998003,-.00653683,.0448384,.145548,.997983,-.00732713,.0448358,.163221,.997985,-.00815454,.0448358,.181899,.998005,-.00898985,.0448286,.201533,.998026,-.00964404,.0447934,.221821,.998055,-.00922677,.044611,.241282,.99804,-.0117361,.0448245,.261791,.998048,-.0127628,.0448159,.285181,.998088,-.0138055,.0447996,.30954,.998058,-.0148206,.0447669,.334751,.998099,-.0156998,.044697,.36061,.998116,-.0161976,.0445122,.386603,.998195,-.015945,.0441711,.411844,.998168,-.0183947,.0444255,.43773,.998184,-.0197913,.0443809,.466009,.998251,-.0201426,.0440689,.494574,.998305,-.0198847,.0435632,.522405,.998273,-.0210577,.043414,.549967,.998254,-.0227901,.0433943,.578655,.998349,-.0223108,.0426529,.60758,.99843,-.0223088,.042,.635524,.998373,-.0241141,.0418987,.663621,.998425,-.0231446,.0408118,.691906,.998504,-.0233684,.0400565,.719339,.998443,-.0241652,.0394634,.74643,.99848,-.0228715,.0380002,.773086,.998569,-.023519,.0372322,.798988,.998619,-.0223108,.0356468,.824249,.998594,-.0223105,.034523,.848808,.998622,-.0213426,.0328887,.87227,.998669,-.0207912,.0314374,.895157,.998705,-.0198416,.0296925,.916769,.998786,-.0189168,.0279634,.937773,.998888,-.0178811,.0261597,.957431,.99906,-.0166845,.0242159,.976495,.999038,-.0155464,.0222638,.994169,.999237,-.0141349,.0201967,1.01112,.999378,-.0129324,.0181744,1.02692,.999433,-.0113192,.0159898,1.04174,.999439,-.0101244,.0140385,1.05559,.999614,-.00837456,.0117826,1.06852,.999722,-.00721769,.00983745,1.08069,.999817,-.00554067,.00769002,1.09176,.99983,-.00426961,.005782,1.10211,.999964,-.00273904,.00374503,1.11152,1.00001,-.00136739,.00187176,1.12031,.999946,393227e-10,-28919e-9,1.12804,.995847,-13435e-10,.0671785,19916e-9,.995464,-338387e-10,.0671527,501622e-9,.99547,-135355e-9,.0671531,.00200649,.995471,-30455e-8,.0671532,.00451461,.99547,-541423e-9,.0671531,.008026,.995471,-84598e-8,.0671531,.0125407,.99547,-.00121823,.0671531,.0180589,.99547,-.00165817,.0671531,.0245806,.995463,-.00216583,.0671526,.0321062,.995468,-.00274127,.0671527,.0406366,.995474,-.00338447,.0671534,.0501717,.995473,-.00409554,.0671533,.0607131,.995478,-.00487451,.0671531,.0722618,.995476,-.00572148,.0671532,.0848191,.995477,-.00663658,.0671539,.0983882,.995498,-.00761986,.0671541,.112972,.995509,-.00867094,.0671542,.128568,.995509,-.00978951,.0671531,.145183,.995503,-.0109725,.0671491,.162808,.995501,-.012211,.0671465,.181441,.99553,-.0134565,.0671371,.201015,.99555,-.014391,.0670831,.221206,.99558,-.014351,.0668883,.240813,.995577,-.0173997,.0671055,.261257,.995602,-.0191111,.0671178,.284467,.995623,-.0206705,.0670946,.308765,.995658,-.022184,.0670472,.333905,.995705,-.0234832,.0669417,.359677,.995719,-.0241933,.0666714,.385554,.995786,-.0243539,.066266,.410951,.995887,-.0271866,.0664367,.437163,.995944,-.0296012,.0664931,.464842,.996004,-.0301045,.0660105,.49332,.996128,-.0298311,.0652694,.521131,.996253,-.0316426,.0650739,.549167,.996244,-.0339043,.0649433,.57737,.996309,-.033329,.0638926,.606073,.996417,-.0338935,.0630849,.634527,.996372,-.0353104,.0625083,.66256,.996542,-.0348942,.0611986,.690516,.996568,-.0351614,.060069,.718317,.996711,-.0354317,.0588522,.74528,.996671,-.0349513,.0571902,.772061,.996865,-.0345622,.0555321,.798089,.996802,-.0342566,.0537816,.823178,.996992,-.0330862,.0516095,.847949,.996944,-.0324666,.0495537,.871431,.997146,-.0309544,.0470302,.894357,.997189,-.0299372,.0446043,.916142,.997471,-.0281389,.0418812,.937193,.997515,-.0268702,.0391823,.957,.997812,-.0247166,.0361338,.975936,.998027,-.0233525,.0333945,.99391,.998233,-.0209839,.0301917,1.01075,.998481,-.0194309,.027271,1.02669,.998859,-.0169728,.0240162,1.04173,.99894,-.0152322,.0210517,1.05551,.999132,-.0127497,.0178632,1.06856,.999369,-.0108282,.014787,1.08054,.999549,-.00845886,.0116185,1.09185,.999805,-.0063937,.00867209,1.10207,.99985,-.00414582,.00566823,1.1117,.999912,-.00207443,.00277562,1.12022,1.00001,870226e-10,-53766e-9,1.12832,.991943,-178672e-11,.0893382,198384e-10,.991952,-450183e-10,.089339,499849e-9,.991956,-180074e-9,.0893394,.0019994,.991955,-405167e-9,.0893393,.00449867,.991953,-720298e-9,.0893391,.00799764,.991955,-.00112548,.0893393,.0124964,.991957,-.0016207,.0893395,.0179951,.991958,-.00220601,.0893396,.0244939,.991947,-.00288137,.0893385,.0319929,.991962,-.00364693,.0893399,.0404933,.991965,-.00450264,.0893399,.049995,.99198,-.00544862,.0893411,.0604995,.99197,-.00648491,.0893397,.0720074,.991976,-.00761164,.089341,.0845207,.99198,-.00882891,.0893405,.0980413,.991982,-.0101367,.0893396,.112571,.992008,-.011535,.0893415,.128115,.992026,-.0130228,.0893414,.144672,.992064,-.0145966,.0893418,.162241,.992041,-.0162421,.0893359,.180801,.992086,-.0178888,.0893214,.200302,.992157,-.0190368,.0892401,.220332,.992181,-.0195584,.0890525,.240144,.992175,-.0227257,.0892153,.260728,.99221,-.0254195,.089304,.283473,.99222,-.0274883,.0892703,.307673,.992317,-.0294905,.0892027,.332729,.992374,-.0311861,.0890577,.358387,.992505,-.0320656,.0886994,.384102,.992568,-.0329715,.0883198,.409767,.992675,-.036006,.0883602,.436145,.992746,-.0392897,.0884591,.463217,.992873,-.0399337,.0878287,.491557,.992934,-.040231,.0870108,.519516,.993091,-.0422013,.0865857,.547741,.993259,-.0443503,.0861937,.575792,.993455,-.0446368,.0851187,.604233,.993497,-.0454299,.0840576,.632925,.993694,-.0463296,.0829671,.660985,.993718,-.0470619,.0817185,.688714,.993973,-.0468838,.0800294,.716743,.994207,-.046705,.0781286,.74377,.994168,-.0469698,.0763337,.77042,.9945,-.0456816,.0738184,.796659,.994356,-.0455518,.0715545,.821868,.994747,-.0439488,.0686085,.846572,.994937,-.0430056,.065869,.870435,.995142,-.0413414,.0626446,.893272,.995451,-.0396521,.05929,.915376,.995445,-.0378453,.0558503,.936196,.995967,-.0355219,.0520949,.956376,.996094,-.0335146,.048377,.975327,.996622,-.030682,.0442575,.993471,.996938,-.0285504,.0404693,1.01052,.997383,-.0253399,.0360903,1.02637,.997714,-.0231651,.0322176,1.04139,.998249,-.0198138,.0278433,1.05542,.998596,-.0174337,.0238759,1.06846,.998946,-.0141349,.0195944,1.08056,.99928,-.0115603,.0156279,1.09181,.999507,-.00839065,.0114607,1.10213,.999697,-.005666,.00763325,1.11169,.999869,-.00269902,.00364946,1.12042,1.00001,623836e-10,-319288e-10,1.12832,.987221,-222675e-11,.111332,197456e-10,.98739,-561116e-10,.111351,497563e-9,.987448,-224453e-9,.111357,.00199031,.987441,-505019e-9,.111357,.0044782,.987442,-897816e-9,.111357,.00796129,.987442,-.00140284,.111357,.0124396,.987444,-.00202012,.111357,.0179132,.987442,-.00274964,.111357,.0243824,.987446,-.00359147,.111357,.0318474,.987435,-.00454562,.111356,.0403086,.987461,-.00561225,.111358,.0497678,.987458,-.00679125,.111358,.0602239,.987443,-.0080828,.111356,.0716792,.987476,-.0094872,.111358,.0841364,.98749,-.0110044,.111361,.097597,.987508,-.0126344,.111362,.112062,.987494,-.0143767,.111357,.127533,.987526,-.0162307,.111359,.144015,.987558,-.0181912,.111361,.161502,.987602,-.0202393,.111355,.179979,.987692,-.022273,.111346,.199386,.987702,-.0235306,.111215,.219183,.987789,-.0247628,.111061,.239202,.987776,-.0280668,.111171,.259957,.987856,-.0316751,.111327,.282198,.987912,-.0342468,.111282,.306294,.988,-.0367205,.111198,.331219,.988055,-.0387766,.110994,.356708,.988241,-.0397722,.110547,.382234,.988399,-.0416076,.110198,.408227,.988539,-.0448192,.110137,.434662,.988661,-.0483793,.110143,.461442,.988967,-.0495895,.109453,.489318,.989073,-.0506797,.108628,.517516,.989274,-.0526953,.108003,.545844,.989528,-.054578,.107255,.573823,.989709,-.0561503,.106294,.601944,.989991,-.056866,.104896,.630855,.990392,-.0572914,.103336,.658925,.990374,-.0586224,.10189,.686661,.990747,-.0584764,.099783,.714548,.991041,-.0582662,.0974309,.74186,.991236,-.0584118,.0951678,.768422,.991585,-.0573055,.0921581,.794817,.991984,-.0564241,.0891167,.820336,.9921,-.0553608,.085805,.84493,.992749,-.0533816,.0820354,.868961,.99288,-.0518661,.0782181,.891931,.993511,-.0492492,.0738935,.914186,.993617,-.0471956,.0696402,.93532,.99411,-.044216,.0649659,.95543,.994595,-.0416654,.0603177,.974685,.994976,-.0384314,.0553493,.992807,.995579,-.0353491,.0503942,1.00996,.996069,-.0319787,.0452123,1.02606,.996718,-.028472,.0400112,1.04114,.997173,-.0250789,.0349456,1.05517,.997818,-.0213326,.029653,1.0683,.998318,-.0178509,.024549,1.0805,.998853,-.0141118,.0194197,1.09177,.999218,-.0105914,.0143869,1.1022,.999594,-.00693474,.00943517,1.11175,.99975,-.00340478,.00464051,1.12056,1.00001,109172e-9,-112821e-9,1.12853,.983383,-266524e-11,.133358,196534e-10,.981942,-671009e-10,.133162,494804e-9,.981946,-268405e-9,.133163,.00197923,.981944,-603912e-9,.133163,.00445326,.981941,-.00107362,.133162,.00791693,.981946,-.00167755,.133163,.0123703,.981944,-.00241569,.133162,.0178135,.981945,-.00328807,.133163,.0242466,.981945,-.00429472,.133162,.03167,.981955,-.00543573,.133164,.0400846,.981951,-.00671105,.133163,.0494901,.981968,-.00812092,.133165,.0598886,.981979,-.00966541,.133166,.0712811,.981996,-.0113446,.133168,.083669,.982014,-.0131585,.133169,.0970533,.982011,-.0151073,.133167,.111438,.982062,-.0171906,.133172,.126826,.9821,-.0194067,.133175,.143215,.982149,-.0217502,.133176,.160609,.982163,-.0241945,.133173,.178981,.982247,-.0265907,.133148,.198249,.982291,-.027916,.132974,.217795,.982396,-.0299663,.132868,.238042,.982456,-.0334544,.132934,.258901,.982499,-.0378636,.133137,.280639,.982617,-.0409274,.133085,.304604,.98274,-.0438523,.132985,.329376,.982944,-.0462288,.132728,.354697,.98308,-.0475995,.132228,.380102,.983391,-.0501901,.131924,.406256,.983514,-.0535899,.131737,.432735,.98373,-.0571858,.131567,.459359,.984056,-.0592353,.130932,.486637,.984234,-.0610488,.130092,.51509,.984748,-.0630758,.12923,.543461,.985073,-.0647398,.128174,.571376,.985195,-.0671941,.127133,.599414,.985734,-.0681345,.125576,.628134,.986241,-.0686089,.123639,.656399,.986356,-.0698511,.121834,.684258,.986894,-.0700931,.119454,.711818,.987382,-.0698321,.116718,.739511,.988109,-.0693975,.113699,.766267,.988363,-.0689584,.110454,.792456,.989112,-.0672353,.106602,.81813,.989241,-.0662034,.10267,.842889,.990333,-.0638938,.0981381,.867204,.990591,-.0618534,.0935388,.89038,.991106,-.0593117,.088553,.912576,.991919,-.0562676,.0832187,.934118,.992111,-.0534085,.0778302,.954254,.992997,-.0495459,.0720453,.973722,.993317,-.0463707,.0663458,.991949,.994133,-.0421245,.0601883,1.00936,.994705,-.0384977,.0542501,1.02559,.995495,-.0340956,.0479862,1.04083,.996206,-.030105,.041887,1.05497,.996971,-.0256095,.0355355,1.06824,.997796,-.0213932,.0293655,1.08056,.998272,-.0169612,.0232926,1.09182,.998857,-.0126756,.0172786,1.10219,.99939,-.00832486,.0113156,1.11192,.999752,-.00410826,.00557892,1.12075,1,150957e-9,-119101e-9,1.12885,.975169,-309397e-11,.154669,195073e-10,.975439,-779608e-10,.154712,491534e-9,.975464,-311847e-9,.154716,.00196617,.975464,-701656e-9,.154716,.00442387,.975462,-.0012474,.154715,.0078647,.975461,-.00194906,.154715,.0122886,.975464,-.00280667,.154715,.0176959,.975468,-.00382025,.154716,.0240867,.975471,-.00498985,.154716,.0314612,.975472,-.00631541,.154717,.0398199,.975486,-.00779719,.154718,.0491639,.975489,-.00943505,.154718,.0594932,.975509,-.0112295,.154721,.0708113,.97554,-.0131802,.154724,.0831176,.975557,-.0152876,.154726,.096415,.975585,-.0175512,.154728,.110705,.975605,-.0199713,.154729,.125992,.975645,-.0225447,.154729,.142272,.975711,-.0252649,.154735,.159549,.975788,-.0280986,.154736,.177805,.975872,-.0308232,.154704,.196911,.975968,-.0324841,.154525,.216324,.976063,-.0351281,.154432,.236628,.976157,-.0388618,.15446,.257539,.976204,-.0437704,.154665,.278975,.976358,-.047514,.154652,.302606,.976571,-.0508638,.154535,.327204,.976725,-.0534995,.154221,.352276,.977013,-.0555547,.153737,.377696,.977294,-.0586728,.153403,.403855,.977602,-.0622715,.15312,.430333,.977932,-.0658166,.152755,.456855,.978241,-.0689877,.152233,.483668,.978602,-.0712805,.15132,.512097,.979234,-.0732775,.150235,.540455,.97977,-.075163,.148978,.568486,.979995,-.0778026,.147755,.596524,.98078,-.0791854,.146019,.624825,.981628,-.0799666,.143906,.653403,.982067,-.0808532,.141561,.681445,.98271,-.0816024,.139025,.708918,.983734,-.0812511,.135764,.736594,.98431,-.0806201,.132152,.763576,.985071,-.0801605,.12846,.789797,.98618,-.0784208,.124084,.815804,.986886,-.0766643,.1193,.840869,.987485,-.0747744,.114236,.864952,.988431,-.0716701,.108654,.888431,.988886,-.0691609,.102994,.910963,.990024,-.0654048,.0967278,.932629,.990401,-.0619765,.090384,.95313,.991093,-.0579296,.0837885,.972587,.992018,-.0536576,.0770171,.991184,.992536,-.0493719,.0701486,1.00863,.993421,-.0444813,.062953,1.02494,.993928,-.040008,.0560455,1.04017,.994994,-.0347982,.04856,1.05463,.995866,-.0301017,.0416152,1.06807,.996916,-.0248225,.0342597,1.08039,.997766,-.0199229,.0271668,1.09177,.998479,-.0147422,.0201387,1.10235,.99921,-.00980173,.0131944,1.11206,.999652,-.0047426,.00640712,1.12104,.999998,891673e-10,-10379e-8,1.12906,.967868,-351885e-11,.175947,193569e-10,.968001,-886733e-10,.175972,487782e-9,.96801,-354697e-9,.175973,.00195115,.968012,-798063e-9,.175974,.00439006,.968011,-.00141879,.175973,.00780461,.968011,-.00221686,.175973,.0121948,.968016,-.00319231,.175974,.0175607,.968019,-.00434515,.175974,.0239027,.968018,-.00567538,.175974,.0312208,.968033,-.00718308,.175977,.0395158,.968049,-.00886836,.175979,.0487885,.968047,-.0107312,.175978,.0590394,.968072,-.0127719,.175981,.0702705,.968108,-.0149905,.175986,.0824836,.968112,-.0173866,.175985,.0956783,.968173,-.0199611,.175993,.109862,.96827,-.0227128,.176008,.125033,.968292,-.025639,.17601,.141193,.968339,-.0287299,.176007,.158336,.968389,-.0319399,.176001,.176441,.968501,-.034941,.175962,.195359,.968646,-.0370812,.175793,.214686,.968789,-.0402329,.175708,.234973,.96886,-.0442601,.1757,.255871,.969013,-.049398,.175876,.277238,.969242,-.0539932,.17594,.300326,.969419,-.0577299,.175781,.324702,.969763,-.0605643,.175432,.349527,.970093,-.0634488,.174992,.374976,.970361,-.0670589,.174611,.401097,.970825,-.0708246,.174226,.427496,.971214,-.0742871,.173684,.453858,.971622,-.0782608,.173186,.480637,.972175,-.0813151,.172288,.508655,.972944,-.0832678,.170979,.536973,.973595,-.0855964,.169573,.565138,.974345,-.0882163,.168152,.593222,.975233,-.0901671,.166314,.621201,.976239,-.0912111,.163931,.649919,.977289,-.0916959,.161106,.678011,.978076,-.0927061,.158272,.705717,.979533,-.0925562,.15475,.733228,.980335,-.0918159,.150638,.760454,.981808,-.0908508,.146201,.786918,.983061,-.0896172,.141386,.812953,.984148,-.0871588,.135837,.838281,.985047,-.0850624,.130135,.862594,.986219,-.0818541,.123882,.88633,.987043,-.0784523,.117126,.908952,.988107,-.0749601,.110341,.930744,.988955,-.0703548,.102885,.951728,.989426,-.0662798,.0954167,.971166,.990421,-.0610834,.0876331,.989984,.991032,-.0562936,.0797785,1.00765,.992041,-.0508154,.0718166,1.02434,.992794,-.0454045,.0637125,1.03976,.993691,-.0398194,.0555338,1.05418,.994778,-.0341482,.0473388,1.06772,.995915,-.028428,.0391016,1.08028,.997109,-.022642,.0309953,1.09185,.998095,-.0168738,.0230288,1.10247,.998985,-.0111274,.0150722,1.11229,.999581,-.00543881,.00740605,1.12131,1.00003,162239e-9,-105549e-9,1.12946,.959505,-393734e-11,.196876,191893e-10,.959599,-992157e-10,.196895,483544e-9,.959641,-396868e-9,.196903,.0019342,.959599,-892948e-9,.196895,.00435193,.959603,-.00158747,.196896,.0077368,.959604,-.00248042,.196896,.0120888,.959605,-.00357184,.196896,.0174082,.959605,-.00486169,.196896,.0236949,.959613,-.00635008,.196897,.0309497,.959619,-.00803696,.196898,.0391725,.959636,-.00992255,.196901,.0483649,.959634,-.0120067,.1969,.0585266,.959675,-.0142898,.196906,.0696609,.959712,-.0167717,.196911,.0817678,.959752,-.0194524,.196918,.0948494,.959807,-.0223321,.196925,.10891,.959828,-.0254091,.196924,.123947,.959906,-.0286815,.196934,.139968,.960005,-.0321371,.196944,.156968,.960071,-.0357114,.196936,.17491,.960237,-.0389064,.196882,.193597,.960367,-.041623,.196731,.21285,.960562,-.0452655,.196654,.233075,.960735,-.0496207,.196643,.253941,.960913,-.0549379,.196774,.275278,.961121,-.0603414,.196893,.297733,.96139,-.0644244,.196717,.321877,.961818,-.067556,.196314,.346476,.962175,-.0712709,.195917,.371907,.96255,-.0752848,.1955,.397916,.963164,-.0792073,.195026,.424229,.963782,-.0828225,.194424,.450637,.964306,-.0873119,.193831,.477288,.964923,-.0911051,.192973,.504716,.966048,-.093251,.19151,.533053,.967024,-.0958983,.190013,.561366,.968038,-.09835,.188253,.589464,.969152,-.100754,.186257,.617433,.970557,-.102239,.183775,.645801,.972104,-.102767,.180645,.674278,.973203,-.103492,.177242,.702004,.975123,-.103793,.17345,.729529,.97641,-.102839,.168886,.756712,.978313,-.101687,.163892,.783801,.980036,-.100314,.158439,.809671,.981339,-.097836,.152211,.835402,.982794,-.0950006,.145679,.860081,.984123,-.0920994,.138949,.883757,.984918,-.0878641,.131283,.90685,.985999,-.083939,.123464,.928786,.987151,-.0791234,.115324,.94983,.987827,-.0739332,.106854,.96962,.988806,-.0688088,.0982691,.98861,.989588,-.0628962,.0893456,1.00667,.990438,-.0573146,.0805392,1.02344,.991506,-.0509433,.0713725,1.03933,.992492,-.0448724,.0623732,1.05378,.993663,-.0383497,.0530838,1.06747,.994956,-.0319593,.0439512,1.08007,.99634,-.025401,.0347803,1.09182,.99761,-.0189687,.0257954,1.1025,.99863,-.0124441,.0169893,1.11247,.99947,-.00614003,.00829498,1.12151,1.00008,216624e-9,-146107e-9,1.12993,.950129,-434955e-11,.217413,190081e-10,.950264,-10957e-8,.217444,47884e-8,.9503,-438299e-9,.217451,.00191543,.950246,-986124e-9,.21744,.00430951,.950246,-.00175311,.21744,.00766137,.950245,-.00273923,.21744,.011971,.950253,-.00394453,.217441,.0172385,.950258,-.00536897,.217442,.0234641,.950267,-.00701262,.217444,.030648,.950277,-.00887551,.217446,.038791,.950284,-.0109576,.217446,.0478931,.950312,-.0132591,.217451,.0579568,.950334,-.01578,.217454,.0689821,.950378,-.0185204,.217462,.0809714,.950417,-.0214803,.217467,.0939265,.950488,-.0246594,.217479,.10785,.950534,-.0280565,.217483,.122743,.950633,-.0316685,.217498,.138611,.950698,-.0354787,.217499,.155442,.950844,-.0394003,.217507,.173208,.950999,-.0426812,.217419,.191605,.951221,-.0461302,.217317,.21084,.951412,-.0502131,.217238,.230945,.951623,-.0549183,.21722,.251745,.951867,-.0604493,.217306,.273001,.952069,-.0665189,.217466,.294874,.952459,-.0709179,.217266,.318732,.952996,-.0746112,.216891,.34318,.953425,-.0789252,.216503,.36849,.953885,-.0833293,.216042,.394373,.954617,-.087371,.215469,.420505,.955429,-.0914054,.214802,.446907,.956068,-.0961671,.214146,.473522,.957094,-.10048,.213286,.50052,.958372,-.103248,.211796,.528715,.959654,-.106033,.21016,.557065,.961305,-.108384,.208149,.585286,.962785,-.111122,.206024,.613334,.964848,-.112981,.203442,.641334,.966498,-.113717,.19996,.669955,.968678,-.114121,.196105,.698094,.970489,-.114524,.191906,.725643,.972903,-.113792,.186963,.752856,.974701,-.112406,.181343,.780013,.976718,-.110685,.175185,.806268,.978905,-.108468,.168535,.832073,.980267,-.105061,.161106,.857149,.981967,-.101675,.153387,.881145,.983063,-.0974492,.145199,.904255,.984432,-.0925815,.136527,.926686,.985734,-.0877983,.127584,.947901,.986228,-.081884,.118125,.968111,.98719,-.0761208,.108594,.98719,.988228,-.0698196,.0989996,1.00559,.989046,-.0632739,.0890074,1.02246,.990242,-.056522,.0790832,1.03841,.991252,-.0495272,.0689182,1.05347,.992542,-.0425373,.0588592,1.06724,.994096,-.0353198,.0486833,1.08009,.995593,-.028235,.0385977,1.09177,.99711,-.0209511,.0286457,1.10274,.998263,-.0139289,.0188497,1.11262,.999254,-.0067359,.009208,1.12191,.999967,141846e-9,-657764e-10,1.13024,.935608,-474692e-11,.236466,187817e-10,.93996,-11971e-8,.237568,473646e-9,.939959,-478845e-9,.237567,.0018946,.939954,-.0010774,.237566,.00426284,.939956,-.00191538,.237566,.00757842,.939954,-.00299277,.237566,.0118413,.93996,-.00430961,.237567,.0170518,.939969,-.00586589,.237569,.02321,.939982,-.00766166,.237572,.0303164,.939987,-.00969686,.237572,.0383711,.939997,-.0119715,.237574,.0473751,.940031,-.0144858,.237581,.0573298,.940073,-.0172399,.237589,.0682366,.94012,-.0202335,.237598,.080097,.940162,-.0234663,.237604,.0929116,.940237,-.0269387,.237615,.106686,.940328,-.0306489,.237632,.121421,.940419,-.0345917,.237645,.137115,.940522,-.0387481,.237654,.153766,.940702,-.0429906,.237661,.17133,.940871,-.0465089,.237561,.189502,.941103,-.050531,.23748,.208616,.941369,-.0550657,.237423,.228595,.941641,-.0601337,.237399,.249287,.941903,-.0658804,.237443,.270467,.942224,-.0722674,.237597,.292024,.942633,-.0771788,.237419,.315272,.943172,-.0815623,.237068,.339579,.943691,-.0863973,.236682,.364717,.944382,-.0911536,.236213,.390435,.945392,-.0952967,.235562,.416425,.946185,-.0998948,.234832,.442772,.947212,-.104796,.234114,.469347,.948778,-.10928,.233222,.496162,.950149,-.113081,.231845,.523978,.951989,-.115893,.230005,.552295,.953921,-.11846,.227862,.580569,.955624,-.12115,.225439,.608698,.958234,-.123373,.222635,.636696,.960593,-.124519,.219093,.665208,.963201,-.124736,.214749,.693557,.965642,-.125012,.210059,.721334,.968765,-.124661,.204935,.748613,.971753,-.122996,.198661,.776224,.973751,-.120998,.191823,.802461,.976709,-.118583,.184359,.828399,.977956,-.115102,.176437,.853693,.979672,-.111077,.167681,.877962,.981816,-.10688,.158872,.901564,.98238,-.101469,.149398,.924057,.983964,-.0960013,.139436,.945751,.984933,-.0899626,.12943,.966272,.985694,-.0832973,.11894,.985741,.986822,-.0767082,.108349,1.00407,.987725,-.0693614,.0976026,1.02154,.98877,-.06211,.086652,1.03757,.990129,-.0544143,.0756182,1.05296,.991337,-.046744,.0645753,1.06683,.992978,-.0387931,.0534683,1.0798,.994676,-.030973,.0424137,1.09181,.99645,-.0230311,.0314035,1.10286,.997967,-.0152065,.0206869,1.11291,.99922,-.00744837,.010155,1.12237,1.00002,240209e-9,-752767e-10,1.13089,.922948,-515351e-11,.255626,186069e-10,.928785,-129623e-9,.257244,468009e-9,.928761,-51849e-8,.257237,.00187202,.928751,-.0011666,.257235,.00421204,.928751,-.00207395,.257234,.0074881,.928754,-.00324055,.257235,.0117002,.92876,-.00466639,.257236,.0168486,.928763,-.00635149,.257237,.0229334,.928774,-.00829584,.257239,.029955,.928791,-.0104995,.257243,.0379139,.928804,-.0129623,.257245,.0468108,.928847,-.0156846,.257255,.0566473,.92889,-.0186661,.257263,.0674246,.928924,-.0219067,.257268,.0791433,.928989,-.0254066,.257282,.0918076,.92909,-.0291651,.257301,.105419,.92918,-.0331801,.257316,.119978,.92929,-.0374469,.257332,.135491,.929453,-.041939,.257357,.151948,.929586,-.0464612,.257347,.169275,.929858,-.0503426,.257269,.187257,.930125,-.0548409,.257199,.206204,.930403,-.0598063,.257149,.22601,.930726,-.0652437,.257122,.246561,.931098,-.0712376,.257153,.267618,.931396,-.0777506,.257237,.288993,.931947,-.0832374,.257124,.311527,.932579,-.0883955,.25683,.335697,.933194,-.0937037,.256444,.360634,.934013,-.0987292,.255939,.386126,.935307,-.103215,.255282,.412018,.936374,-.108234,.254538,.438292,.93776,-.113234,.253728,.464805,.939599,-.118013,.25275,.491464,.941036,-.122661,.251404,.518751,.94337,-.125477,.249435,.547133,.945318,-.128374,.247113,.575456,.947995,-.130996,.244441,.60372,.950818,-.133438,.241352,.63174,.954378,-.135004,.237849,.659971,.957151,-.135313,.233188,.688478,.960743,-.13521,.228001,.716767,.964352,-.135007,.222249,.744349,.967273,-.133523,.21542,.771786,.969767,-.131155,.208039,.798639,.973195,-.128492,.200076,.824774,.975557,-.125094,.191451,.850222,.977692,-.120578,.18184,.874761,.98026,-.115882,.172102,.898497,.981394,-.110372,.161859,.921636,.982386,-.10415,.15108,.943467,.983783,-.0978128,.140407,.964045,.98422,-.0906171,.129058,.98398,.985447,-.0832921,.117614,1.00276,.986682,-.0754412,.10585,1.02047,.987326,-.0673885,.0940943,1.03678,.988707,-.0592565,.0822093,1.05218,.990185,-.050717,.070192,1.06652,.991866,-.0423486,.0582081,1.07965,.993897,-.0336118,.0460985,1.09188,.995841,-.0252178,.0342737,1.10307,.997605,-.0164893,.0224829,1.11324,.999037,-.00817112,.0110647,1.12262,1.00003,291686e-9,-168673e-9,1.13139,.915304,-552675e-11,.275999,183285e-10,.91668,-139285e-9,.276414,461914e-9,.916664,-55713e-8,.276409,.00184763,.916653,-.00125354,.276406,.00415715,.916651,-.00222851,.276405,.00739053,.916655,-.00348205,.276406,.0115478,.916653,-.00501414,.276405,.0166291,.916667,-.00682478,.276409,.0226346,.91668,-.00891398,.276412,.0295648,.91669,-.0112817,.276413,.0374199,.916727,-.013928,.276422,.0462016,.916759,-.0168528,.276429,.0559101,.916793,-.0200558,.276436,.0665466,.916849,-.0235373,.276448,.0781139,.916964,-.0272973,.276474,.0906156,.917047,-.0313344,.276491,.104051,.917152,-.0356465,.276511,.118424,.917286,-.0402271,.276533,.133736,.917469,-.0450408,.276564,.149978,.917686,-.0497872,.276563,.167057,.917953,-.0540937,.276493,.184846,.918228,-.0590709,.276437,.203614,.918572,-.0644277,.276398,.223212,.918918,-.0702326,.276362,.243584,.919356,-.076484,.276383,.264465,.919842,-.0830808,.276434,.285701,.920451,-.0892972,.276407,.307559,.921113,-.095016,.276128,.331501,.921881,-.100771,.275754,.356207,.923027,-.106029,.275254,.381477,.924364,-.111029,.274595,.40722,.925818,-.116345,.273841,.433385,.92746,-.121424,.272913,.459848,.929167,-.12657,.271837,.486493,.931426,-.131581,.270575,.513432,.934001,-.135038,.268512,.541502,.936296,-.138039,.266135,.569658,.939985,-.140687,.263271,.598375,.943516,-.143247,.260058,.626563,.94782,-.145135,.256138,.654711,.951023,-.145733,.251154,.683285,.955338,-.145554,.245562,.711831,.959629,-.145008,.239265,.739573,.963123,-.144003,.232064,.767027,.966742,-.141289,.224036,.794359,.969991,-.138247,.215305,.820361,.973403,-.134786,.206051,.846548,.975317,-.129966,.195914,.871541,.977647,-.12471,.185184,.895313,.980137,-.119086,.174161,.918398,.981031,-.112297,.162792,.940679,.982037,-.105372,.150952,.961991,.983164,-.097821,.138921,.981913,.983757,-.0897245,.126611,1.00109,.985036,-.0815974,.114228,1.01902,.986289,-.0727725,.101389,1.03604,.987329,-.0639323,.0886476,1.05149,.989193,-.0548109,.0756837,1.06619,.990716,-.045687,.0627581,1.07948,.992769,-.0364315,.0498337,1.09172,.99524,-.0271761,.0370305,1.1033,.997154,-.0179609,.0243959,1.11353,.998845,-.00878063,.0119567,1.12319,1.00002,259038e-9,-108146e-9,1.13177,.903945,-591681e-11,.295126,181226e-10,.903668,-148672e-9,.295037,455367e-9,.903677,-594683e-9,.29504,.00182145,.903673,-.00133805,.295039,.00409831,.903666,-.00237872,.295036,.00728584,.903668,-.00371676,.295037,.0113842,.903679,-.00535212,.29504,.0163936,.903684,-.00728479,.295041,.0223141,.903698,-.00951473,.295044,.0291462,.903718,-.0120419,.295049,.0368904,.903754,-.0148664,.295058,.0455477,.903801,-.017988,.29507,.0551194,.903851,-.0214064,.295082,.0656058,.903921,-.0251219,.295097,.0770109,.904002,-.0291337,.295116,.0893354,.904111,-.033441,.29514,.102583,.904246,-.0380415,.295169,.116755,.904408,-.0429258,.295202,.131853,.904637,-.0480468,.295245,.147869,.904821,-.0529208,.295214,.164658,.905163,-.0577748,.295185,.182274,.905469,-.0631763,.295143,.200828,.905851,-.068917,.295112,.2202,.906322,-.0750861,.295104,.240372,.906761,-.0815855,.295086,.261082,.90735,-.0882138,.295095,.282123,.908087,-.095082,.295139,.303563,.908826,-.101488,.29492,.327028,.909832,-.107577,.294577,.351464,.911393,-.113033,.294115,.376497,.912804,-.118629,.293446,.402115,.914081,-.124232,.292581,.428111,.91637,-.129399,.29166,.454442,.91814,-.134892,.290422,.481024,.921179,-.140069,.289194,.507924,.924544,-.144431,.287421,.535557,.927995,-.147498,.284867,.563984,.931556,-.150197,.281722,.5923,.935777,-.152711,.278207,.620832,.940869,-.154836,.274148,.649069,.945994,-.155912,.269057,.677746,.949634,-.155641,.262799,.706293,.955032,-.154809,.256097,.734278,.95917,-.153678,.248618,.761751,.962931,-.151253,.239794,.789032,.966045,-.147625,.230281,.815422,.96971,-.143964,.220382,.841787,.972747,-.139464,.209846,.867446,.975545,-.133459,.198189,.892004,.978381,-.127424,.186362,.915458,.979935,-.120506,.173964,.937948,.980948,-.11282,.161429,.959732,.982234,-.104941,.148557,.980118,.982767,-.0962905,.135508,.999463,.983544,-.0873625,.122338,1.01756,.984965,-.0783447,.108669,1.03492,.986233,-.0684798,.0949911,1.05087,.987796,-.0590867,.0811386,1.0656,.989885,-.0489145,.0673099,1.0794,.991821,-.0391,.0535665,1.09174,.99448,-.029087,.0397529,1.10341,.996769,-.019114,.0261463,1.11383,.998641,-.00947007,.0128731,1.1237,.999978,446316e-9,-169093e-9,1.13253,.888362,-627064e-11,.312578,178215e-10,.889988,-157791e-9,.313148,448451e-9,.889825,-631076e-9,.313092,.00179356,.88984,-.00141994,.313097,.00403554,.889828,-.0025243,.313092,.00717429,.889831,-.00394421,.313093,.0112099,.889831,-.00567962,.313093,.0161425,.889844,-.00773051,.313096,.0219724,.889858,-.0100968,.3131,.0286999,.889882,-.0127786,.313106,.0363256,.889918,-.0157757,.313116,.0448509,.889967,-.0190878,.313129,.0542758,.89003,-.022715,.313145,.0646032,.890108,-.0266566,.313165,.0758339,.890218,-.0309131,.313193,.0879729,.890351,-.0354819,.313226,.101019,.89051,-.0403613,.313263,.114979,.890672,-.0455385,.313294,.129848,.890882,-.0509444,.313333,.145616,.891189,-.0559657,.313324,.162122,.891457,-.0613123,.313281,.179524,.891856,-.0671488,.313281,.197855,.892312,-.0732732,.313268,.216991,.892819,-.0797865,.313263,.236924,.893369,-.0865269,.313247,.257433,.894045,-.0931592,.313205,.278215,.894884,-.100532,.313276,.299467,.895832,-.107716,.313205,.322276,.897043,-.114099,.312873,.34642,.898515,-.119941,.312331,.371187,.900191,-.126044,.311731,.396656,.90188,-.131808,.310859,.422488,.904359,-.137289,.309857,.448744,.906923,-.142991,.308714,.475239,.910634,-.148253,.307465,.501983,.914502,-.153332,.305774,.529254,.919046,-.156646,.303156,.557709,.923194,-.159612,.299928,.586267,.928858,-.162027,.296245,.614925,.934464,-.164203,.291832,.643187,.939824,-.165602,.286565,.671601,.944582,-.165383,.280073,.700213,.949257,-.164439,.272891,.728432,.954389,-.162953,.264771,.756082,.958595,-.161007,.255927,.78369,.962138,-.157243,.245769,.810769,.966979,-.152872,.235127,.836999,.969566,-.148209,.22347,.862684,.972372,-.142211,.211147,.887847,.975916,-.135458,.198606,.911843,.978026,-.128398,.185498,.934795,.979686,-.120313,.17171,.956787,.980748,-.11166,.158159,.978046,.981622,-.103035,.144399,.997693,.982356,-.0930328,.13001,1.01642,.983308,-.0834627,.115778,1.03366,.985037,-.0732249,.101327,1.05014,.986493,-.0628145,.086554,1.06507,.988484,-.0526556,.0720413,1.07907,.991051,-.0415744,.0571151,1.09189,.993523,-.0314275,.0426643,1.10369,.99628,-.0203603,.0279325,1.11423,.998344,-.0102446,.0138182,1.12421,.999997,42612e-8,-193628e-9,1.1333,.871555,-660007e-11,.329176,174749e-10,.875255,-166579e-9,.330571,441051e-9,.875644,-666394e-9,.330718,.00176441,.875159,-.00149903,.330536,.00396899,.87516,-.00266493,.330536,.007056,.875158,-.00416393,.330535,.0110251,.87516,-.00599598,.330535,.0158764,.875163,-.00816108,.330536,.0216101,.875174,-.0106591,.330538,.0282266,.875199,-.0134899,.330545,.0357266,.875257,-.0166538,.330563,.0441117,.875304,-.0201501,.330575,.0533821,.875373,-.0239785,.330595,.0635395,.875464,-.0281389,.330619,.0745872,.875565,-.0326301,.330645,.0865255,.875691,-.0374516,.330676,.0993599,.875897,-.0425993,.330733,.113093,.876091,-.0480576,.330776,.127722,.876353,-.0537216,.330826,.143227,.876649,-.0589807,.330809,.159462,.877034,-.0647865,.330819,.176642,.877443,-.0709789,.330817,.194702,.877956,-.0774782,.330832,.213577,.878499,-.0843175,.330822,.233246,.879144,-.0912714,.330804,.253512,.879982,-.0980824,.330766,.274137,.88097,-.105823,.330864,.295209,.882051,-.113671,.330896,.317226,.883397,-.120303,.330545,.341068,.884987,-.12667,.330068,.365613,.886789,-.133118,.329418,.390807,.889311,-.139024,.328683,.416494,.891995,-.144971,.327729,.442618,.895106,-.150747,.326521,.469131,.899527,-.156283,.325229,.495921,.90504,-.161707,.32378,.523162,.909875,-.165661,.32122,.55092,.91561,-.168755,.317942,.579928,.921225,-.171193,.313983,.608539,.927308,-.17319,.309636,.636854,.933077,-.174819,.304262,.66523,.938766,-.175002,.297563,.693609,.943667,-.173946,.289613,.722157,.949033,-.172221,.281227,.750021,.953765,-.169869,.271545,.777466,.95804,-.166578,.261034,.804853,.962302,-.161761,.249434,.831569,.966544,-.156636,.237484,.857779,.969372,-.150784,.224395,.883051,.972486,-.143672,.210786,.907864,.975853,-.135772,.196556,.931223,.977975,-.127942,.182307,.954061,.979122,-.118347,.167607,.97531,.980719,-.109112,.152739,.995666,.981223,-.0991789,.137932,1.01475,.98216,-.0883553,.122692,1.03253,.983379,-.0780825,.107493,1.04917,.985434,-.0665646,.0917791,1.06464,.987332,-.0557714,.0764949,1.07896,.990004,-.0442805,.060721,1.09199,.992975,-.0331676,.0452284,1.10393,.995811,-.0219547,.0297934,1.11476,.9982,-.0107613,.0146415,1.12484,1.00002,248678e-9,-14555e-8,1.13413,.859519,-693595e-11,.347264,171673e-10,.859843,-17503e-8,.347394,433219e-9,.859656,-700076e-9,.347319,.00173277,.859671,-.00157517,.347325,.00389875,.859669,-.00280028,.347324,.00693112,.85967,-.0043754,.347324,.01083,.859665,-.00630049,.347321,.0155954,.859685,-.0085755,.347328,.0212278,.859694,-.0112003,.347329,.0277273,.859718,-.0141747,.347336,.0350946,.85976,-.0174988,.347348,.0433314,.85982,-.0211722,.347366,.0524384,.859892,-.0251941,.347387,.0624168,.860006,-.0295649,.347422,.0732708,.860122,-.0342825,.347453,.0849999,.860282,-.0393462,.347499,.0976102,.860482,-.0447513,.347554,.111104,.860719,-.0504775,.347614,.125479,.860998,-.0563577,.347666,.140703,.861322,-.0619473,.347662,.156681,.861724,-.0681277,.347684,.173597,.862198,-.0746567,.347709,.191371,.862733,-.0815234,.347727,.209976,.863371,-.0886643,.347744,.229351,.86414,-.0957908,.347734,.24934,.865138,-.102912,.34772,.269797,.866182,-.110924,.3478,.290654,.867436,-.119223,.347911,.312074,.869087,-.126197,.347649,.335438,.870859,-.133145,.347222,.359732,.872997,-.139869,.346645,.38467,.875939,-.146089,.345935,.41019,.879012,-.152334,.345012,.436218,.883353,-.15821,.343924,.462641,.888362,-.164097,.342636,.489449,.895026,-.169528,.341351,.516629,.900753,-.174408,.339115,.544109,.906814,-.17751,.335809,.572857,.912855,-.180101,.331597,.601554,.919438,-.182116,.32698,.630198,.925962,-.183494,.321449,.658404,.931734,-.184159,.314595,.686625,.93762,-.18304,.306462,.71531,.943858,-.181323,.297514,.744272,.948662,-.178683,.287447,.771462,.953299,-.175379,.276166,.798593,.957346,-.170395,.263758,.8256,.962565,-.165042,.251019,.852575,.966075,-.158655,.237011,.878316,.969048,-.151707,.222518,.90329,.972423,-.143271,.207848,.927745,.975833,-.134824,.192463,.950859,.977629,-.125444,.1768,.972947,.978995,-.114949,.161033,.993263,.980533,-.104936,.145523,1.01337,.980745,-.0935577,.129799,1.03128,.981814,-.0822956,.113486,1.04825,.983943,-.0710082,.0972925,1.06405,.986141,-.0587931,.0808138,1.0785,.988878,-.0472755,.0644915,1.09204,.992132,-.0349128,.0478128,1.10413,.9953,-.0232407,.031621,1.11527,.998117,-.0112713,.0154935,1.12551,1.00003,339743e-9,-195763e-9,1.13504,.845441,-729126e-11,.364305,169208e-10,.843588,-183164e-9,.363506,425067e-9,.843412,-73253e-8,.36343,.00169999,.843401,-.00164818,.363426,.00382495,.843399,-.00293008,.363425,.00679993,.843401,-.00457822,.363425,.010625,.843394,-.00659249,.363421,.0153002,.843398,-.00897282,.363421,.0208258,.843415,-.0117191,.363426,.0272024,.843438,-.0148312,.363432,.0344305,.843483,-.018309,.363447,.0425116,.84356,-.0221521,.363472,.0514471,.843646,-.0263597,.363499,.061238,.843743,-.0309315,.363527,.0718873,.84388,-.0358658,.363569,.0833969,.844079,-.0411624,.363631,.0957742,.844279,-.0468128,.363688,.109015,.844549,-.0527923,.363761,.123124,.844858,-.0588204,.363817,.138044,.84522,-.0647573,.36383,.153755,.845669,-.0713181,.363879,.170394,.846155,-.0781697,.363908,.187861,.846789,-.0853913,.363969,.206176,.847502,-.0928086,.363999,.225244,.8484,-.10005,.363997,.244926,.849461,-.107615,.364008,.265188,.850562,-.115814,.364055,.28587,.851962,-.124334,.364179,.306926,.854326,-.131995,.364233,.329605,.856295,-.139338,.363856,.35359,.858857,-.146346,.363347,.37831,.862428,-.152994,.362807,.403722,.866203,-.159463,.361963,.429537,.871629,-.165623,.36112,.456,.877365,-.171649,.359917,.482773,.883744,-.177151,.35848,.509705,.890693,-.182381,.356523,.537215,.897278,-.186076,.3533,.565493,.903958,-.188602,.349095,.594293,.910908,-.190755,.344215,.623165,.918117,-.192063,.338606,.651573,.924644,-.192758,.331544,.679869,.931054,-.192238,.323163,.708668,.937303,-.190035,.313529,.737201,.943387,-.187162,.303152,.764977,.948494,-.183876,.29146,.792683,.952546,-.178901,.277917,.819228,.958077,-.173173,.264753,.846559,.962462,-.16645,.25002,.872962,.966569,-.159452,.234873,.898729,.969108,-.15074,.218752,.923126,.973072,-.141523,.202673,.947278,.975452,-.132075,.186326,.969938,.977784,-.121257,.169396,.991325,.97899,-.110182,.153044,1.01123,.979777,-.0989634,.136485,1.0299,.980865,-.0865894,.119343,1.04727,.982432,-.0746115,.102452,1.06341,.984935,-.0621822,.0852423,1.07834,.987776,-.0495694,.0678546,1.092,.99103,-.0372386,.0506917,1.1043,.99474,-.0244353,.0333316,1.11576,.997768,-.0121448,.0164348,1.12617,1.00003,31774e-8,-169504e-9,1.13598,.825551,-756799e-11,.378425,165099e-10,.82664,-190922e-9,.378923,416504e-9,.826323,-763495e-9,.378779,.0016656,.826359,-.00171789,.378795,.00374768,.82636,-.00305402,.378795,.00666259,.826368,-.00477185,.378798,.0104104,.826364,-.00687131,.378795,.0149912,.826368,-.00935232,.378795,.0204054,.826376,-.0122146,.378797,.0266532,.826399,-.0154581,.378803,.0337355,.82646,-.0190825,.378824,.0416537,.826525,-.0230873,.378846,.0504091,.826614,-.0274719,.378876,.0600032,.82674,-.0322355,.378917,.0704393,.826888,-.0373766,.378964,.0817195,.827078,-.0428936,.379024,.0938492,.827318,-.0487778,.379099,.106828,.82764,-.0549935,.379199,.120659,.827926,-.0611058,.379227,.13526,.828325,-.0675054,.379275,.150713,.828801,-.0743455,.379332,.167034,.8294,-.0815523,.379415,.184209,.830094,-.0890779,.379495,.202203,.8309,-.096736,.379555,.220945,.831943,-.104135,.379577,.240306,.833037,-.112106,.379604,.260317,.834278,-.120554,.379668,.2808,.836192,-.129128,.3799,.301654,.838671,-.137541,.380109,.323502,.840939,-.14523,.379809,.347176,.844575,-.15248,.379593,.371706,.848379,-.159607,.37909,.39688,.853616,-.166267,.378617,.422702,.858921,-.172698,.377746,.448919,.865324,-.178823,.376749,.475661,.872207,-.184542,.375363,.502599,.880018,-.189836,.373657,.529914,.88694,-.194294,.370673,.557683,.894779,-.197022,.36662,.586848,.902242,-.199108,.36138,.615831,.909914,-.200398,.355434,.644478,.917088,-.20094,.348173,.672905,.923888,-.200671,.339482,.701327,.930495,-.198773,.32956,.730101,.937247,-.195394,.318363,.758383,.943108,-.191956,.306323,.786539,.948296,-.187227,.292576,.813637,.953472,-.181165,.278234,.840793,.958485,-.174119,.263054,.867712,.962714,-.166564,.246756,.893635,.966185,-.158181,.229945,.919028,.970146,-.148275,.212633,.943413,.973491,-.138157,.195229,.966627,.975741,-.127574,.178048,.988817,.977238,-.11554,.160312,1.00924,.978411,-.10364,.142857,1.02845,.979811,-.0913122,.125317,1.04648,.98116,-.0782558,.107627,1.06284,.983543,-.0655957,.0895862,1.07798,.986789,-.0520411,.0713756,1.092,.990292,-.0389727,.053228,1.10484,.994187,-.025808,.0351945,1.11642,.997499,-.0126071,.0173198,1.12703,.999999,275604e-9,-148602e-9,1.13674,.81075,-78735e-10,.394456,161829e-10,.808692,-198293e-9,.393453,407564e-9,.80846,-792877e-9,.39334,.00162965,.808595,-.00178416,.393407,.00366711,.808597,-.00317182,.393408,.00651934,.808598,-.00495589,.393408,.0101866,.808591,-.00713627,.393403,.0146689,.808592,-.00971285,.393402,.0199667,.80861,-.0126855,.393407,.0260803,.808633,-.0160538,.393413,.0330107,.80868,-.0198175,.393429,.0407589,.808748,-.0239758,.393453,.0493264,.808854,-.0285286,.39349,.0587161,.808992,-.0334748,.39354,.0689304,.809141,-.0388116,.393588,.0799707,.809352,-.0445375,.39366,.0918432,.809608,-.0506427,.393742,.104549,.809915,-.0570708,.393834,.118085,.810253,-.0633526,.393885,.132377,.810687,-.0700966,.393953,.147537,.811233,-.0772274,.394047,.163543,.811865,-.0847629,.394148,.180394,.812648,-.0925663,.394265,.198051,.813583,-.100416,.394363,.216443,.814683,-.108119,.394402,.235502,.815948,-.11644,.394489,.255242,.817278,-.125036,.394542,.275441,.819605,-.133655,.39486,.296094,.822256,-.142682,.395248,.317309,.825349,-.150756,.395241,.340516,.829605,-.158392,.395285,.364819,.83391,-.165801,.394922,.389736,.839808,-.172677,.394691,.415409,.845708,-.179448,.394006,.441546,.853025,-.185746,.393279,.46832,.859666,-.191684,.391655,.495302,.86789,-.197146,.390068,.52262,.875845,-.201904,.38727,.550336,.882634,-.205023,.382688,.578825,.891076,-.207098,.377543,.608103,.900589,-.208474,.371752,.63723,.90791,-.209068,.364016,.665769,.915971,-.208655,.355593,.694428,.923455,-.20729,.345439,.723224,.931514,-.203821,.334099,.751925,.937885,-.19986,.321069,.780249,.943136,-.194993,.306571,.8077,.948818,-.189132,.291556,.83497,.954433,-.181617,.275745,.86188,.959078,-.173595,.258695,.888562,.962705,-.164855,.240825,.914008,.966753,-.155129,.22268,.939145,.970704,-.144241,.204542,.963393,.973367,-.133188,.185927,.985983,.975984,-.121146,.167743,1.00704,.976994,-.108366,.149218,1.02715,.978485,-.0956746,.13131,1.0455,.980074,-.0820733,.112513,1.06221,.98225,-.0684061,.0938323,1.07782,.98553,-.0549503,.0749508,1.09199,.989529,-.0407857,.055848,1.10508,.993536,-.0271978,.0368581,1.11684,.997247,-.0132716,.0181845,1.12789,1,431817e-9,-198809e-9,1.13792,.785886,-812608e-11,.405036,157669e-10,.790388,-205278e-9,.407355,398297e-9,.790145,-820824e-9,.407231,.00159263,.790135,-.00184681,.407226,.00358336,.790119,-.00328316,.407218,.00637039,.790126,-.00512988,.40722,.0099539,.79013,-.00738684,.407221,.0143339,.790135,-.0100538,.407221,.0195107,.790134,-.0131306,.407217,.0254848,.79016,-.0166169,.407224,.0322572,.790197,-.020512,.407236,.0398284,.790273,-.0248157,.407263,.0482014,.790381,-.029527,.407304,.0573777,.790521,-.0346446,.407355,.0673602,.790704,-.0401665,.40742,.0781522,.790925,-.0460896,.407499,.0897582,.791195,-.0524017,.407589,.10218,.791522,-.0590121,.407691,.11541,.791878,-.0654876,.407748,.12939,.792361,-.0725207,.407849,.144237,.792942,-.0799844,.407963,.159924,.79362,-.0877896,.408087,.176425,.794529,-.0958451,.408259,.193733,.795521,-.103827,.408362,.211756,.796778,-.111937,.408482,.230524,.798027,-.120521,.408547,.249967,.799813,-.129242,.408721,.269926,.802387,-.138048,.409148,.290338,.805279,-.147301,.409641,.311193,.809251,-.155895,.410154,.333611,.813733,-.163942,.410297,.357615,.819081,-.171666,.410373,.382339,.825427,-.178905,.410348,.407828,.83172,-.185812,.409486,.434034,.83877,-.192318,.408776,.460493,.845817,-.198249,.407176,.487346,.854664,-.204034,.405719,.514832,.863495,-.208908,.403282,.542401,.871883,-.212765,.399293,.570683,.88065,-.214911,.393803,.599947,.89004,-.216214,.387536,.62932,.898476,-.216745,.379846,.658319,.906738,-.216387,.370625,.687138,.914844,-.215053,.360139,.71601,.923877,-.212007,.348849,.745124,.931925,-.207481,.335639,.773366,.938054,-.202418,.320798,.801636,.943895,-.196507,.304772,.829055,.949468,-.189009,.288033,.856097,.955152,-.180539,.270532,.88301,.959403,-.171437,.251639,.909296,.963309,-.161661,.232563,.934868,.967399,-.150425,.213231,.959662,.972009,-.138659,.194247,.98302,.97433,-.126595,.174718,1.00517,.975823,-.113205,.155518,1.02566,.976371,-.0996096,.136709,1.04418,.978705,-.0860754,.117571,1.06146,.981477,-.0714438,.0980046,1.07777,.984263,-.0572304,.0782181,1.09214,.988423,-.0428875,.0584052,1.10553,.993,-.0282442,.038522,1.11758,.99704,-.0140183,.0190148,1.12864,.999913,369494e-9,-145203e-9,1.13901,.777662,-84153e-10,.423844,154403e-10,.770458,-211714e-9,.419915,38845e-8,.770716,-846888e-9,.420055,.00155386,.770982,-.00190567,.420202,.00349653,.770981,-.00338782,.420201,.00621606,.77098,-.00529338,.4202,.00971274,.770983,-.00762223,.4202,.0139867,.770985,-.0103741,.420198,.0190381,.770996,-.0135489,.4202,.0248677,.771029,-.0171461,.420212,.0314764,.771052,-.0211647,.420215,.0388648,.771131,-.0256048,.420245,.047036,.771235,-.0304647,.420284,.0559911,.771383,-.0357436,.420341,.0657346,.771591,-.0414392,.420423,.0762694,.771819,-.0475462,.420506,.0875984,.772123,-.0540506,.420617,.099727,.772464,-.060797,.42072,.112637,.772855,-.0675393,.420799,.126313,.773317,-.0748323,.420893,.140824,.773981,-.0825681,.421058,.15617,.774746,-.0906307,.421226,.172322,.77566,-.0988982,.421397,.189253,.776837,-.106994,.421569,.206912,.778097,-.115528,.421704,.225359,.779588,-.124317,.421849,.24447,.781574,-.133139,.422097,.264156,.784451,-.142179,.422615,.284318,.787682,-.15165,.423269,.304902,.792433,-.160771,.424396,.3265,.797359,-.169166,.424772,.35014,.803986,-.177149,.425475,.374768,.809504,-.184745,.424996,.399928,.815885,-.19173,.424247,.425796,.823513,-.198525,.423515,.452287,.832549,-.204709,.422787,.479321,.841653,-.210447,.421187,.506718,.850401,-.215501,.418519,.53432,.859854,-.219752,.414715,.56242,.869364,-.222305,.409462,.591558,.878837,-.223744,.402926,.621074,.888636,-.224065,.395043,.650538,.898132,-.223742,.38564,.679538,.907181,-.222308,.375378,.708674,.915621,-.219837,.363212,.737714,.9239,-.215233,.349313,.767014,.931644,-.209592,.334162,.795133,.938887,-.203644,.317943,.823228,.945282,-.196349,.300581,.850822,.950758,-.18742,.282195,.877594,.956146,-.177879,.262481,.904564,.960355,-.167643,.242487,.930741,.965256,-.156671,.222668,.955868,.968029,-.144123,.201907,.979869,.97251,-.131305,.18202,1.00291,.974925,-.118335,.161909,1.02392,.975402,-.103714,.142129,1.0433,.976987,-.089415,.122447,1.06089,.979677,-.0748858,.102248,1.07713,.983184,-.0596086,.0814851,1.09218,.987466,-.0447671,.0609484,1.10585,.992348,-.0295217,.0401835,1.11829,.996674,-.0143917,.0198163,1.12966,1.00003,321364e-9,-149983e-9,1.1402,.757901,-869074e-11,.436176,151011e-10,.751195,-217848e-9,.432317,378533e-9,.751178,-871373e-9,.432307,.0015141,.751195,-.00196061,.432317,.0034068,.751198,-.00348552,.432318,.00605659,.751195,-.00544599,.432315,.00946353,.751207,-.00784203,.43232,.013628,.751213,-.0106732,.43232,.0185499,.751221,-.0139393,.432319,.0242302,.751244,-.0176398,.432325,.0306694,.7513,-.0217743,.432348,.0378698,.751358,-.0263412,.432367,.0458321,.751458,-.0313396,.432404,.0545587,.751608,-.0367682,.432464,.0640543,.7518,-.0426246,.43254,.0743222,.752065,-.0489031,.432645,.0853668,.752376,-.0555828,.432762,.0971911,.752715,-.0623861,.432859,.109768,.753137,-.069415,.432958,.123126,.753676,-.0770039,.433099,.137308,.754345,-.084971,.433272,.15229,.755235,-.0932681,.433504,.168075,.756186,-.10171,.433693,.184625,.757363,-.110019,.433857,.201897,.75884,-.11887,.434102,.220014,.760467,-.127881,.434306,.238778,.762969,-.136766,.434751,.258172,.765823,-.14612,.43529,.278062,.769676,-.15566,.436236,.298437,.774909,-.165177,.437754,.319532,.77994,-.17402,.438343,.342505,.785757,-.182201,.438609,.366693,.792487,-.190104,.438762,.391668,.80038,-.197438,.438795,.417494,.808494,-.204365,.438226,.443933,.817695,-.210714,.437283,.470929,.828111,-.216651,.436087,.498569,.837901,-.221804,.433717,.526165,.847813,-.226318,.430133,.554155,.858314,-.229297,.425213,.582822,.868891,-.230999,.418576,.612847,.878941,-.231155,.410405,.642445,.888809,-.230935,.400544,.672024,.898089,-.229343,.389613,.701366,.908081,-.226886,.377197,.730763,.916819,-.222676,.363397,.759642,.924968,-.216835,.347437,.788775,.932906,-.210245,.32995,.817135,.940025,-.202992,.312262,.844912,.946101,-.19436,.293313,.872164,.952835,-.184125,.273638,.899443,.957347,-.173657,.252385,.926389,.961434,-.162204,.231038,.951947,.965522,-.14979,.209834,.976751,.969412,-.136307,.188821,1.00022,.973902,-.122527,.168013,1.02229,.974045,-.108213,.147634,1.04199,.975775,-.0927397,.12705,1.06019,.978383,-.0778212,.106309,1.07711,.98211,-.0621216,.0849279,1.09245,.986517,-.0463847,.0633519,1.10651,.991696,-.0309353,.0419698,1.11903,.996349,-.0150914,.0206272,1.13073,1.00003,442449e-9,-231396e-9,1.14146,.727498,-885074e-11,.441528,145832e-10,.730897,-223525e-9,.443589,368298e-9,.730796,-893996e-9,.443528,.00147303,.730805,-.00201149,.443533,.00331433,.730814,-.00357596,.443538,.00589222,.730815,-.00558734,.443538,.00920678,.730822,-.00804544,.44354,.0132582,.730836,-.0109501,.443545,.0180468,.730848,-.0143008,.443546,.0235732,.730871,-.0180969,.443552,.0298382,.730915,-.022338,.443567,.0368438,.730982,-.0270225,.443591,.044591,.731076,-.0321491,.443627,.0530831,.731245,-.0377166,.443699,.0623243,.73144,-.0437216,.443777,.0723181,.7317,-.0501576,.443881,.0830691,.732034,-.0569942,.444014,.0945809,.732388,-.0638756,.444113,.106825,.732853,-.071203,.444247,.119859,.733473,-.0790076,.444442,.13369,.734195,-.0871937,.444645,.148304,.735069,-.095696,.444877,.163702,.736169,-.10426,.445133,.179861,.73747,-.112853,.44537,.196778,.738991,-.12199,.445651,.214496,.740865,-.131153,.445958,.232913,.743637,-.140245,.446548,.251977,.746797,-.149722,.447246,.271551,.751517,-.159341,.448656,.291774,.756156,-.169106,.449866,.312455,.761519,-.178436,.450919,.334552,.768295,-.186904,.451776,.358491,.776613,-.195117,.452832,.383446,.783966,-.202695,.45249,.408945,.793542,-.20985,.452587,.435364,.803192,-.216403,.451852,.462336,.813892,-.22251,.450708,.48987,.824968,-.227676,.4486,.517697,.835859,-.232443,.445156,.545975,.846825,-.235775,.440351,.574483,.858085,-.237897,.433641,.604246,.868825,-.238074,.425354,.634101,.879638,-.237661,.415383,.664201,.889966,-.236186,.404136,.693918,.899479,-.233599,.390917,.723481,.908769,-.229737,.376352,.75258,.917966,-.223836,.360372,.781764,.926304,-.217067,.342551,.811139,.934626,-.209309,.324238,.839585,.941841,-.20071,.304484,.867044,.94789,-.190602,.283607,.894579,.954196,-.179253,.262205,.921743,.958383,-.167646,.239847,.948026,.963119,-.155073,.218078,.973296,.966941,-.141426,.195899,.998135,.970836,-.126849,.174121,1.02021,.973301,-.112296,.153052,1.04085,.97448,-.0964965,.131733,1.05946,.977045,-.080489,.10997,1.07693,.980751,-.064844,.0881657,1.09254,.985475,-.0481938,.0657987,1.10697,.991089,-.0319185,.0435215,1.12004,.996122,-.0158088,.0214779,1.13173,1.00001,372455e-9,-200295e-9,1.14291,.708622,-907597e-11,.45304,141962e-10,.711162,-228911e-9,.454662,358052e-9,.709812,-914446e-9,.453797,.00143034,.709865,-.00205819,.453834,.00321935,.709864,-.00365894,.453833,.00572331,.709855,-.00571692,.453826,.00894278,.709862,-.00823201,.453828,.012878,.709875,-.011204,.453832,.0175295,.709896,-.0146323,.453839,.0228978,.709925,-.0185163,.453847,.0289839,.709974,-.0228551,.453866,.0357894,.710045,-.0276473,.453892,.0433161,.710133,-.032891,.453924,.0515665,.710292,-.0385851,.453992,.0605458,.710485,-.0447254,.45407,.0702574,.710769,-.0513051,.454192,.0807077,.711106,-.0582733,.454329,.091896,.711516,-.0652866,.45446,.103814,.712071,-.0728426,.454653,.116508,.712676,-.0808307,.45484,.129968,.713476,-.0892216,.455096,.144206,.714377,-.0979047,.455346,.159212,.715579,-.106531,.455647,.174973,.716977,-.115492,.455961,.191504,.71862,-.124821,.456315,.208835,.72084,-.134079,.4568,.226869,.723786,-.143427,.457521,.245582,.727464,-.153061,.458475,.264957,.732771,-.162768,.460239,.284948,.736515,-.172627,.460899,.30522,.743519,-.182487,.463225,.326717,.750041,-.191295,.464027,.350113,.758589,-.199746,.465227,.374782,.767703,-.207584,.465877,.400226,.777484,-.214973,.465996,.426442,.788792,-.221796,.466019,.453688,.800194,-.228038,.465083,.481246,.811234,-.233346,.462506,.509086,.822859,-.238073,.459257,.537338,.835082,-.241764,.454863,.566108,.846332,-.244241,.448163,.595126,.858355,-.244736,.439709,.625574,.87034,-.244278,.429837,.65617,.881027,-.24255,.418002,.686029,.891007,-.239912,.404325,.716039,.900874,-.236133,.389222,.745518,.911072,-.230672,.373269,.775026,.920359,-.22356,.355083,.804521,.928604,-.215591,.335533,.834045,.937175,-.206503,.315278,.861612,.942825,-.196684,.293653,.889131,.949805,-.185116,.271503,.916853,.955535,-.172703,.248821,.943541,.959843,-.159978,.225591,.970132,.964393,-.146375,.202719,.994709,.968008,-.131269,.179928,1.0186,.971013,-.11569,.158007,1.03928,.973334,-.1003,.13624,1.05887,.975775,-.0833352,.1138,1.07652,.979579,-.0668981,.0913141,1.09297,.984323,-.0500902,.0683051,1.10734,.990351,-.0332377,.0451771,1.12084,.995823,-.0161491,.0221705,1.13296,1.0001,234083e-9,-108712e-9,1.14441,.683895,-924677e-11,.46015,137429e-10,.68833,-233383e-9,.463134,346865e-9,.688368,-933547e-9,.463159,.00138748,.688367,-.00210049,.463159,.00312187,.688369,-.00373415,.463159,.00555004,.688377,-.00583449,.463163,.00867216,.688386,-.00840128,.463166,.0124884,.688398,-.0114343,.463169,.0169993,.688418,-.0149329,.463175,.0222054,.688453,-.0188964,.463188,.028108,.688515,-.0233239,.463214,.0347085,.68857,-.0282136,.463231,.0420091,.688679,-.033564,.463276,.0500132,.688854,-.0393733,.463356,.0587255,.689038,-.0456354,.46343,.0681476,.689321,-.0523433,.463553,.0782897,.689662,-.059412,.463693,.0891501,.690188,-.0665736,.4639,.100735,.690755,-.0743106,.464107,.113074,.691405,-.0824722,.464329,.126161,.692198,-.0910484,.464585,.140007,.693196,-.0998778,.464893,.154612,.69454,-.108651,.465285,.169984,.695921,-.117855,.465596,.186106,.697749,-.12734,.466056,.203034,.700375,-.136714,.466771,.220703,.703395,-.146386,.467579,.239062,.707904,-.156096,.469067,.258188,.711673,-.165904,.469851,.277759,.717489,-.175812,.471815,.297935,.724051,-.185931,.47389,.318916,.731965,-.195238,.47587,.341591,.741151,-.204021,.477523,.366062,.751416,-.212113,.478881,.391396,.761848,-.21979,.479226,.417599,.771886,-.2267,.478495,.444401,.783998,-.232991,.477622,.472084,.796523,-.238645,.475833,.500193,.808851,-.243396,.472568,.52865,.821191,-.247226,.467857,.557362,.834261,-.250102,.461871,.586768,.846762,-.251056,.453543,.617085,.859867,-.250604,.443494,.647659,.871948,-.248783,.431711,.678119,.882967,-.245855,.417911,.708399,.892826,-.242168,.401993,.738256,.90332,-.237062,.385371,.767999,.913633,-.22997,.366837,.798191,.922774,-.221687,.346372,.827756,.931371,-.212345,.325682,.856425,.938929,-.20206,.303665,.884299,.944821,-.190981,.280786,.912023,.951792,-.178065,.2573,.939669,.957712,-.164634,.233448,.96655,.961912,-.150863,.209504,.992366,.966382,-.13577,.18597,1.01633,.969588,-.119593,.162905,1.03843,.971777,-.103203,.14053,1.05841,.97433,-.0865888,.117909,1.07632,.978686,-.0690829,.0944101,1.09326,.983281,-.0516568,.0705671,1.10796,.989562,-.034558,.0468592,1.12182,.995465,-.0167808,.0229846,1.1342,.999991,373016e-9,-235606e-9,1.1459,.662251,-939016e-11,.468575,132714e-10,.666634,-237624e-9,.471675,335842e-9,.666411,-950385e-9,.471516,.00134321,.666399,-.00213833,.471509,.00302221,.666386,-.0038014,.471499,.00537283,.666405,-.00593958,.471511,.00839533,.666406,-.00855253,.471508,.0120898,.666428,-.0116401,.471519,.0164569,.666444,-.0152015,.471522,.0214971,.66649,-.0192362,.471543,.027212,.666537,-.0237428,.471558,.033603,.666617,-.0287198,.471591,.0406728,.666718,-.0341647,.471631,.0484238,.666889,-.0400759,.47171,.0568621,.667104,-.0464479,.471805,.0659915,.667374,-.0532677,.471923,.0758178,.667772,-.0603805,.472098,.0863425,.668371,-.0677392,.472363,.0975917,.668971,-.0756028,.472596,.109567,.669696,-.0839293,.472869,.122272,.670481,-.0926683,.473126,.135718,.6715,-.1016,.473442,.149914,.672911,-.110566,.47389,.164882,.674512,-.119984,.474354,.180602,.67651,-.129574,.474922,.19711,.679292,-.139106,.475764,.214371,.682798,-.148993,.476886,.232405,.686955,-.158737,.478179,.251153,.691406,-.168754,.479432,.270436,.697438,-.178703,.481481,.290374,.704761,-.188955,.484143,.311044,.713599,-.198814,.487007,.333003,.723194,-.207869,.488962,.357144,.732601,-.216189,.489815,.382169,.744193,-.22398,.490888,.408227,.754907,-.231156,.490355,.434928,.767403,-.23747,.489548,.462599,.78107,-.243503,.488274,.490908,.793893,-.248114,.484843,.519421,.807296,-.25222,.4803,.548561,.820529,-.255265,.474097,.577772,.833716,-.256741,.466041,.607782,.848403,-.25637,.456547,.638807,.860755,-.254804,.443946,.670058,.874012,-.251834,.430852,.700749,.885619,-.247867,.414903,.731446,.896069,-.242634,.397276,.761191,.906266,-.236093,.378535,.791053,.916759,-.227543,.358038,.821298,.92523,-.21783,.335705,.850747,.93436,-.207534,.313797,.879258,.941631,-.195983,.289671,.907734,.947564,-.183567,.265319,.935206,.953681,-.169345,.240815,.962739,.960008,-.154909,.216119,.989227,.964145,-.140161,.192096,1.01465,.968171,-.123411,.167855,1.03737,.969859,-.106525,.144817,1.05767,.972666,-.0891023,.12149,1.0761,.977055,-.0718094,.0975306,1.09336,.982527,-.0534213,.0730217,1.10878,.989001,-.0355579,.0483366,1.12285,.99512,-.0176383,.023938,1.13548,1.00007,368831e-9,-211581e-9,1.14744,.651047,-960845e-11,.484101,12922e-9,.644145,-241347e-9,.478968,324578e-9,.64396,-965142e-9,.478831,.00129798,.64396,-.00217154,.47883,.00292046,.643968,-.00386049,.478835,.00519202,.643974,-.00603186,.478838,.0081128,.643977,-.0086854,.478836,.011683,.643982,-.0118207,.478834,.0159031,.644024,-.0154374,.478856,.0207743,.644059,-.0195343,.478868,.0262975,.644122,-.0241103,.478896,.0324747,.644207,-.0291638,.478933,.039309,.64432,-.0346919,.478981,.0468029,.644481,-.0406919,.479053,.0549614,.644722,-.047159,.479169,.0637909,.645013,-.0540748,.479302,.0732974,.645503,-.0612001,.479541,.0834898,.646117,-.0687303,.479829,.0943873,.646707,-.0767846,.480061,.105991,.647431,-.0852465,.480343,.11831,.64831,-.0940719,.48066,.131348,.649486,-.103056,.481083,.14514,.650864,-.112261,.481528,.159676,.652604,-.121852,.482102,.174979,.654825,-.131505,.482813,.191079,.657876,-.141189,.483876,.207927,.661339,-.151239,.48499,.225586,.665463,-.161091,.486279,.243947,.670542,-.171235,.487968,.262957,.677361,-.181347,.49053,.282781,.685672,-.191679,.493862,.303311,.694551,-.201781,.49699,.324607,.703753,-.211164,.498884,.347916,.713703,-.219675,.500086,.372628,.725911,-.227836,.501554,.398694,.73862,-.23533,.502193,.425529,.752118,-.241786,.501811,.453209,.76579,-.247865,.500185,.481381,.779568,-.252696,.497159,.51011,.793991,-.256802,.492765,.539322,.808182,-.259942,.486827,.569078,.821698,-.261703,.478386,.598818,.836009,-.262006,.468772,.629762,.849824,-.260333,.456352,.661366,.863888,-.257398,.442533,.69295,.876585,-.253264,.426573,.723608,.888665,-.248026,.408964,.754378,.899537,-.241487,.389677,.784761,.9094,-.233463,.368516,.814688,.920166,-.223397,.346624,.845009,.928899,-.21255,.322717,.874431,.937156,-.200869,.298698,.902922,.943861,-.188387,.273491,.931356,.949557,-.174341,.247866,.958854,.955862,-.158994,.222496,.986098,.961721,-.143664,.197522,1.01229,.965976,-.127412,.17302,1.03571,.968652,-.109798,.148954,1.05699,.971084,-.0916787,.125044,1.07587,.975584,-.0739634,.100577,1.09372,.98122,-.055322,.0753666,1.10948,.988253,-.0366825,.0498899,1.12394,.99482,-.0180389,.024611,1.13694,1.00001,229839e-9,-188283e-9,1.14919,.613867,-964198e-11,.479449,123452e-10,.621485,-244534e-9,.485399,313091e-9,.621429,-978202e-9,.485353,.00125245,.62112,-.00220004,.485114,.00281687,.621119,-.0039111,.485112,.00500783,.621122,-.00611091,.485112,.00782498,.621133,-.00879922,.485117,.0112687,.621152,-.0119756,.485125,.0153394,.621183,-.0156396,.485139,.0200382,.621227,-.0197898,.485158,.0253663,.621298,-.0244253,.485192,.0313261,.621388,-.0295441,.485233,.0379204,.621507,-.0351432,.485286,.0451523,.621693,-.0412198,.485378,.0530277,.621933,-.0477673,.485495,.0615522,.622232,-.0547574,.485635,.0707316,.622809,-.0619417,.485943,.0805883,.623407,-.069625,.486232,.0911267,.62406,-.077796,.486516,.102354,.624835,-.0863731,.486838,.114279,.625758,-.095251,.487188,.126902,.627043,-.104299,.487695,.140285,.628438,-.113724,.488163,.154397,.630325,-.123417,.488858,.169267,.632801,-.133137,.489754,.184941,.635784,-.143052,.490815,.20136,.639406,-.153132,.492048,.218643,.643872,-.163143,.49363,.236615,.6499,-.17333,.496009,.255449,.657201,-.183622,.498994,.275006,.666221,-.194019,.502888,.295354,.674419,-.204192,.505459,.316244,.683729,-.21406,.507771,.33849,.695584,-.222854,.510245,.363166,.708583,-.231315,.512293,.389071,.721233,-.238911,.512747,.415737,.735134,-.245657,.512482,.443331,.750179,-.251879,.511526,.471891,.765073,-.256911,.508935,.500892,.779794,-.261144,.504341,.530294,.794801,-.264316,.498515,.560144,.810339,-.266276,.491015,.590213,.824818,-.266981,.481126,.620865,.839375,-.265778,.468685,.652687,.853043,-.262748,.453925,.684759,.867335,-.258474,.437912,.716209,.88037,-.253187,.419648,.747508,.891711,-.246476,.39982,.77797,.902896,-.238735,.37879,.808586,.913601,-.22885,.355891,.838843,.923019,-.217656,.331773,.869014,.933432,-.205539,.307356,.898512,.939691,-.192595,.281321,.9269,.946938,-.178945,.255441,.955297,.952372,-.163587,.229013,.983231,.95909,-.147214,.203179,1.00971,.963675,-.13064,.17792,1.03438,.968247,-.113121,.152898,1.05625,.97001,-.0945824,.128712,1.07598,.974458,-.0755648,.103349,1.094,.980168,-.0571998,.0776731,1.1104,.987295,-.0377994,.0514445,1.12491,.994432,-.0186417,.025429,1.13851,.999975,542714e-9,-282356e-9,1.15108,.592656,-980249e-11,.486018,119532e-10,.598467,-247275e-9,.490781,301531e-9,.597934,-988317e-9,.490343,.00120517,.597903,-.00222366,.490319,.0027116,.597913,-.00395315,.490327,.00482077,.597919,-.00617653,.490329,.00753264,.597936,-.00889375,.490339,.0108478,.597956,-.0121043,.490347,.0147668,.597992,-.0158073,.490365,.0192905,.598032,-.0200017,.490382,.0244204,.598109,-.0246865,.49042,.0301593,.598215,-.0298594,.490474,.03651,.59833,-.0355167,.490524,.0434757,.598525,-.0416559,.490624,.0510629,.598778,-.0482692,.490753,.0592781,.599135,-.0553114,.49094,.0681304,.599802,-.062542,.491328,.0776467,.600361,-.0703638,.491598,.0878184,.60101,-.0786256,.491882,.0986573,.601811,-.0872962,.492232,.11018,.602861,-.0962284,.492684,.1224,.604167,-.10538,.493213,.135354,.605693,-.114896,.493799,.149034,.607682,-.124654,.494576,.163469,.610672,-.13456,.4959,.178747,.613313,-.144581,.496713,.194723,.617603,-.154703,.498499,.211617,.622174,-.16489,.500188,.229183,.628855,-.175164,.503072,.247786,.636963,-.185565,.506798,.267116,.644866,-.195911,.509719,.28702,.653741,-.206104,.512776,.307763,.664942,-.216447,.516812,.329631,.67633,-.22552,.519181,.353515,.690012,-.234316,.521681,.379226,.704243,-.242032,.523129,.405901,.719396,-.249172,.523768,.433585,.734471,-.255543,.522541,.462085,.750539,-.260697,.520217,.491233,.766365,-.26501,.516293,.521094,.781677,-.268409,.509708,.551014,.797132,-.270399,.501944,.581463,.812655,-.271247,.492025,.612402,.828592,-.270708,.480424,.643798,.844044,-.268085,.465955,.67682,.857305,-.263459,.448425,.708496,.87114,-.258151,.430243,.74046,.884936,-.251171,.410578,.771583,.895772,-.243305,.38862,.802234,.906961,-.234037,.365214,.833179,.917775,-.222714,.34116,.86353,.927883,-.210175,.31572,.893557,.936617,-.196925,.289159,.922976,.943384,-.182788,.261996,.951606,.949713,-.167965,.235324,.979958,.955818,-.151109,.208408,1.00765,.961344,-.133834,.182591,1.03329,.965469,-.115987,.156958,1.0557,.968693,-.09746,.132239,1.07583,.973165,-.0778514,.106195,1.09451,.979387,-.0585067,.0797669,1.11137,.98671,-.0390409,.0530263,1.12643,.994093,-.019408,.0263163,1.14016,1.00002,540029e-9,-194487e-9,1.15299,.574483,-989066e-11,.494533,114896e-10,.574478,-249127e-9,.494528,289403e-9,.574607,-996811e-9,.494637,.00115797,.574396,-.00224241,.494458,.00260498,.574377,-.00398632,.49444,.00463102,.574386,-.00622836,.494445,.00723623,.574401,-.0089683,.494453,.010421,.574419,-.0122056,.49446,.0141859,.574459,-.0159396,.494481,.0185322,.574525,-.0201692,.49452,.0234617,.574587,-.0248924,.494547,.0289762,.574697,-.0301074,.494604,.0350797,.574853,-.0358114,.494688,.0417767,.575027,-.041999,.494772,.0490718,.575294,-.0486618,.494915,.0569728,.575733,-.0557148,.495173,.0654955,.576356,-.0630489,.495537,.0746612,.576944,-.0709285,.495836,.0844615,.57765,-.0792723,.496177,.0949142,.578491,-.0880167,.496563,.10603,.579639,-.0969462,.497096,.117841,.580989,-.10622,.497684,.130367,.582587,-.115861,.498337,.143609,.584951,-.125605,.499414,.157625,.587602,-.135608,.500518,.172413,.59076,-.145742,.501767,.187999,.594992,-.155934,.503542,.20445,.600656,-.166303,.506135,.221764,.607816,-.176681,.509542,.24002,.61522,-.187071,.51263,.258992,.623702,-.197465,.516021,.278773,.634192,-.207816,.520422,.299377,.644936,-.218183,.524073,.320802,.657888,-.2278,.528049,.34384,.670666,-.236747,.52986,.36916,.685626,-.24484,.531892,.395867,.701304,-.252071,.532727,.423488,.717727,-.258714,.532146,.452201,.733914,-.264211,.529883,.481579,.750529,-.26859,.5259,.511558,.76747,-.272046,.51999,.542042,.785189,-.274225,.513083,.572799,.800954,-.275189,.502936,.603816,.816962,-.274946,.490921,.635461,.83336,-.272695,.47684,.6676,.848143,-.268223,.459405,.70051,.861818,-.262768,.440319,.732902,.876828,-.255872,.420123,.765084,.889312,-.247703,.398379,.796391,.900412,-.238381,.374496,.827333,.912251,-.227783,.349874,.858385,.921792,-.214832,.323181,.888652,.931273,-.200949,.296624,.917763,.940295,-.186537,.269211,.947878,.946812,-.171538,.241447,.977016,.953588,-.155254,.213829,1.00501,.958841,-.137156,.186807,1.03179,.963746,-.118699,.160706,1.05502,.966468,-.0998358,.135504,1.07568,.971178,-.0805186,.109131,1.09479,.97831,-.0599348,.0818293,1.1123,.985886,-.0399661,.0545872,1.12771,.994021,-.0198682,.0269405,1.14186,1.00009,271022e-9,-12989e-8,1.15514,.538716,-990918e-11,.486732,109675e-10,.550656,-250642e-9,.497518,277412e-9,.55057,-.00100265,.497441,.00110974,.550903,-.00225672,.497733,.00249779,.550568,-.00401046,.497438,.00443906,.550574,-.00626613,.49744,.00693637,.550591,-.0090226,.497449,.00998921,.550623,-.0122795,.497469,.0135984,.550667,-.0160361,.497495,.0177654,.550724,-.0202908,.497526,.0224915,.550792,-.0250421,.497557,.0277795,.550918,-.0302878,.49763,.0336334,.551058,-.0360241,.497701,.0400573,.551276,-.0422473,.497824,.0470585,.551551,-.0489441,.497977,.0546433,.552074,-.0559596,.498312,.0628367,.552681,-.0633978,.498679,.071646,.553324,-.0713176,.499031,.0810746,.554011,-.0797268,.499365,.091129,.55488,-.0885238,.499779,.101837,.556171,-.0974417,.500444,.113239,.557498,-.106841,.501025,.125316,.559299,-.116533,.501864,.138128,.561647,-.126298,.502967,.151695,.564347,-.136388,.504129,.16604,.567863,-.146576,.505713,.181207,.572569,-.156832,.507953,.197259,.578919,-.167323,.511186,.214258,.585387,-.177712,.514042,.232038,.593134,-.188184,.517484,.250733,.603295,-.198717,.522345,.270454,.613854,-.209177,.526751,.290807,.626092,-.219644,.531595,.312202,.637868,-.229494,.534721,.334435,.652458,-.238718,.538304,.359184,.666985,-.247061,.539875,.385637,.683301,-.254652,.541042,.41328,.69998,-.261376,.540735,.441903,.717824,-.267085,.539139,.471609,.734617,-.271465,.534958,.501446,.753663,-.27528,.53032,.532571,.770512,-.277617,.522134,.563641,.787356,-.278525,.51206,.595067,.806252,-.278512,.50119,.627226,.822061,-.277023,.486791,.659402,.838959,-.273175,.470467,.692874,.85379,-.267238,.450688,.725702,.868268,-.260327,.429741,.75832,.881994,-.251946,.407223,.790189,.893885,-.242432,.383214,.821625,.905118,-.231904,.357297,.853011,.916045,-.219545,.330733,.883773,.927614,-.205378,.303916,.914435,.936005,-.190388,.275941,.944502,.944533,-.1749,.247493,.974439,.950758,-.158588,.218996,1.00286,.957078,-.141027,.191559,1.0304,.962448,-.121507,.164457,1.05466,.964993,-.102068,.138636,1.0761,.970017,-.0822598,.111861,1.09541,.97661,-.062033,.0843438,1.11317,.985073,-.0409832,.0558496,1.12911,.993515,-.020146,.0275331,1.1438,1.00006,27329e-8,-107883e-9,1.15736,.525324,-999341e-11,.498153,105385e-10,.526513,-251605e-9,.499277,265329e-9,.526517,-.00100641,.499282,.0010613,.526588,-.00226466,.499337,.00238823,.526539,-.0040255,.499302,.00424535,.526547,-.00628954,.499306,.00663364,.526561,-.00905628,.499313,.00955337,.526593,-.0123253,.499334,.0130054,.526642,-.0160957,.499365,.0169911,.5267,-.0203661,.499396,.0215122,.526792,-.0251347,.499451,.0265718,.526904,-.0303985,.499511,.0321732,.527079,-.0361554,.499617,.0383231,.527285,-.0423982,.499731,.045026,.527602,-.0491121,.499924,.0522936,.528166,-.0561127,.500306,.0601528,.52879,-.0635988,.5007,.0686059,.529421,-.071581,.501048,.0776518,.530144,-.0799854,.501421,.0873148,.531062,-.0888032,.501884,.0976084,.532374,-.0977643,.50259,.108588,.533828,-.107197,.50329,.120234,.53581,-.116887,.504312,.132602,.538063,-.126755,.505365,.145721,.5409,-.136819,.506668,.159617,.544882,-.147117,.508731,.174369,.550238,-.157446,.511601,.190028,.556038,-.167988,.514431,.206587,.563031,-.178364,.517808,.224046,.571543,-.189007,.521937,.242503,.582255,-.199546,.527415,.261977,.59272,-.210084,.531682,.282162,.605648,-.220448,.537123,.303426,.61785,-.230593,.540664,.325323,.632223,-.240238,.544467,.348993,.648819,-.24887,.547594,.375462,.665825,-.256657,.54912,.403024,.683389,-.263711,.549294,.431773,.701495,-.269666,.547649,.461494,.719197,-.274169,.543786,.491623,.737906,-.278124,.538644,.522994,.756652,-.280632,.531057,.554775,.775279,-.281741,.521972,.586441,.792688,-.281652,.509613,.618596,.811894,-.280345,.496497,.651462,.827938,-.277128,.47968,.684023,.844837,-.271646,.460688,.718024,.859239,-.264397,.438872,.751207,.874088,-.256144,.41577,.784232,.887693,-.246311,.391369,.816191,.899402,-.235497,.365872,.847828,.910973,-.223631,.338618,.87934,.92204,-.209874,.310803,.910325,.930987,-.194265,.281802,.940695,.94,-.178125,.252836,.970958,.948018,-.161479,.224239,1.00078,.955141,-.144038,.195857,1.0288,.960513,-.124915,.168487,1.05371,.963964,-.104284,.141495,1.07596,.968713,-.0838732,.114437,1.09628,.975524,-.0635579,.0863105,1.11448,.98431,-.042291,.0574774,1.13069,.992916,-.0209131,.0284343,1.14568,.999926,743097e-9,-379265e-9,1.15955,.501042,-998428e-11,.498726,100306e-10,.502992,-252112e-9,.500665,253283e-9,.502417,-.00100791,.500092,.00101259,.502965,-.00226919,.500621,.00227978,.502318,-.00403109,.499994,.00405011,.502333,-.00629832,.500005,.00632868,.502362,-.00906907,.500027,.00911446,.502369,-.0123423,.500023,.0124078,.50243,-.0161178,.500066,.016211,.502493,-.0203937,.500103,.0205256,.502592,-.0251684,.500166,.0253548,.502707,-.0304389,.50023,.0307029,.502881,-.0362015,.500335,.0365753,.503124,-.0424507,.500488,.0429798,.503443,-.0491582,.500686,.0499268,.504083,-.0561476,.501155,.0574541,.504668,-.0636846,.501524,.0655408,.505319,-.0716834,.501904,.0742072,.50609,-.0800925,.502321,.0834699,.507122,-.0888425,.502896,.0933603,.508414,-.097855,.503603,.10391,.509955,-.107304,.504416,.115113,.512061,-.116921,.505565,.127054,.514419,-.12689,.506732,.139709,.517529,-.136934,.508338,.153173,.522085,-.147327,.510987,.167528,.526986,-.157612,.513527,.182708,.533122,-.168213,.516717,.198881,.540807,-.178688,.520832,.215986,.550687,-.189511,.52632,.234335,.560567,-.199998,.531009,.253375,.571698,-.210652,.535839,.273499,.584364,-.220917,.541091,.294355,.599066,-.23137,.546875,.316525,.614148,-.241206,.551306,.339671,.631157,-.250379,.555187,.36531,.647919,-.258397,.556595,.392767,.666112,-.265528,.556949,.421397,.686158,-.271827,.556617,.451433,.704838,-.27674,.552975,.482131,.723957,-.280733,.547814,.513458,.74262,-.283359,.53997,.545446,.762009,-.284541,.530422,.57775,.781314,-.284507,.518546,.610434,.799116,-.283309,.504178,.643178,.817604,-.280378,.48843,.676248,.83459,-.275619,.469457,.709698,.850974,-.26856,.447698,.744245,.866747,-.260094,.424791,.777695,.881412,-.249929,.399913,.810392,.8936,-.239137,.37308,.842872,.905943,-.226818,.345705,.874677,.916408,-.213699,.31706,.906257,.927215,-.198428,.288444,.936881,.935625,-.181643,.258329,.96795,.944076,-.164386,.228488,.998216,.951229,-.146339,.199763,1.02689,.958793,-.127709,.172153,1.0535,.963219,-.107244,.144989,1.07646,.967562,-.0857764,.11685,1.09675,.974866,-.0645377,.0880571,1.11576,.983353,-.0431732,.0587352,1.13227,.992503,-.0218356,.0294181,1.1478,1.00003,605203e-9,-231013e-9,1.16207,.482935,-101177e-10,.504695,968142e-11,.477554,-251521e-9,.499071,240676e-9,.477904,-.00100683,.499436,96342e-8,.478368,-.00226636,.499899,.0021687,.477977,-.00402719,.499513,.00385384,.477993,-.00629226,.499525,.0060221,.478011,-.00906011,.499536,.00867289,.478051,-.0123305,.499566,.0118074,.478089,-.016102,.499587,.0154269,.478171,-.0203736,.499645,.0195341,.478254,-.025143,.499692,.0241318,.47839,-.0304071,.499779,.0292247,.478588,-.0361631,.499911,.0348196,.478812,-.0424023,.500046,.0409231,.479208,-.0490724,.500326,.047552,.479841,-.0560722,.500805,.0547377,.480392,-.0636125,.501152,.0624607,.481068,-.0716134,.501561,.0707473,.481898,-.0800062,.502054,.0796118,.483022,-.0886568,.502728,.0890974,.484332,-.0977553,.503479,.0992099,.486126,-.107173,.504546,.10999,.488066,-.11677,.50557,.121476,.490521,-.126725,.506849,.133672,.494232,-.136793,.50911,.146731,.498302,-.147116,.511345,.160577,.503565,-.157446,.514344,.175335,.510902,-.168121,.518824,.191207,.519263,-.178799,.523666,.208058,.528204,-.189407,.528296,.225875,.538854,-.200145,.533724,.244782,.551278,-.210701,.539833,.264753,.565222,-.221303,.546131,.285745,.579403,-.231688,.551496,.307592,.595469,-.241718,.556809,.330582,.610929,-.250992,.559641,.354995,.629433,-.259602,.562379,.382471,.648504,-.267038,.563676,.411126,.66756,-.273388,.562092,.440924,.689143,-.278788,.560807,.472118,.709056,-.282783,.555701,.503774,.729855,-.285836,.548698,.536364,.748954,-.287078,.538544,.56895,.768373,-.287133,.526711,.601991,.78827,-.285839,.512511,.635403,.807465,-.283238,.496323,.668797,.825194,-.27906,.477638,.702584,.842203,-.272286,.456253,.736393,.857749,-.263854,.432412,.77096,.874799,-.253943,.407806,.80489,.887497,-.24237,.38033,.83771,.89966,-.230278,.352446,.870376,.911753,-.21646,.323268,.902256,.923011,-.202071,.294314,.933306,.932375,-.185519,.264104,.965177,.940537,-.167604,.234035,.996303,.948904,-.149068,.20412,1.0261,.955263,-.129539,.175431,1.05304,.960303,-.109932,.148116,1.07617,.965512,-.0880572,.119693,1.09742,.973466,-.0660548,.0901619,1.11721,.98284,-.0439228,.0599875,1.13436,.992216,-.0219588,.0298975,1.15006,.999946,119402e-9,-208547e-10,1.16471,.447827,-100414e-10,.491543,914833e-11,.454778,-251257e-9,.499172,22891e-8,.453519,-.00100342,.497787,914184e-9,.45357,-.00225776,.497847,.00205701,.453578,-.00401371,.497855,.00365705,.45357,-.00627107,.497841,.00571453,.453598,-.00902968,.497864,.00823019,.453627,-.0122888,.497882,.0112049,.453684,-.0160475,.497923,.0146405,.453764,-.0203044,.49798,.0185394,.453866,-.0250576,.498049,.0229054,.453996,-.0303028,.49813,.0277424,.454196,-.0360379,.498267,.0330587,.454457,-.0422521,.498445,.0388613,.454926,-.0488393,.498812,.0451767,.455525,-.0558653,.499272,.0520153,.456074,-.0633772,.499625,.0593754,.456752,-.0713606,.500049,.0672751,.457648,-.07971,.500615,.0757447,.458849,-.0883032,.501399,.0848231,.46029,-.0974095,.502293,.0945135,.462,-.106729,.503301,.104848,.464121,-.116354,.504533,.115884,.466889,-.126214,.506172,.127652,.470744,-.136324,.508667,.14024,.47488,-.146595,.510995,.153673,.480845,-.157027,.514832,.168053,.488262,-.167658,.519506,.183508,.496547,-.178343,.524347,.199948,.506254,-.188916,.52983,.217503,.517961,-.199975,.536357,.236272,.531484,-.210624,.543641,.256096,.545496,-.221227,.550048,.277085,.559497,-.231568,.555076,.298615,.575752,-.241698,.560541,.321547,.591999,-.251172,.564156,.345602,.610654,-.260178,.567607,.371851,.630484,-.268094,.56923,.40076,.651807,-.274661,.569779,.430801,.67239,-.280331,.566791,.461939,.693024,-.284501,.562007,.493854,.715473,-.287852,.555791,.526992,.736323,-.28929,.546345,.560102,.755771,-.289405,.534,.593543,.775424,-.2881,.519114,.627256,.795447,-.285562,.502543,.661464,.815319,-.281416,.484773,.695206,.831769,-.275523,.463445,.729044,.849464,-.267516,.440269,.764069,.866775,-.257584,.415049,.799089,.881252,-.245817,.388049,.831948,.894209,-.233127,.35889,.865526,.906922,-.219579,.329915,.89818,.919686,-.204491,.300441,.930013,.929044,-.188962,.269445,.962061,.938393,-.171079,.238402,.994214,.94661,-.15199,.208204,1.02533,.953095,-.131953,.178653,1.0529,.958644,-.111233,.150684,1.0771,.963925,-.0903098,.122359,1.09855,.971995,-.0680505,.0923342,1.11874,.981658,-.0448512,.0614195,1.13635,.991649,-.0221931,.0303582,1.15238,.999985,393403e-9,-111086e-9,1.16772,.396806,-971563e-11,.457671,842355e-11,.429186,-249421e-9,.495017,21625e-8,.429324,-998052e-9,.495173,865322e-9,.429175,-.00224487,.494999,.00194637,.429129,-.00399041,.494952,.00346004,.429153,-.00623476,.494974,.00540684,.429168,-.0089773,.494983,.00778714,.429207,-.0122175,.495012,.0106022,.429257,-.0159542,.495047,.0138535,.429338,-.0201864,.495106,.0175443,.429431,-.0249104,.495165,.0216774,.429587,-.0301252,.495279,.0262594,.429796,-.0358249,.495432,.0312968,.430065,-.0419972,.495621,.0367985,.430588,-.0485144,.496061,.042798,.43113,-.0555028,.496472,.0492914,.431743,-.0629852,.496904,.0562907,.432448,-.0709256,.497369,.0638056,.433414,-.0791942,.498032,.071885,.434638,-.0877346,.498854,.0805517,.43611,-.0968056,.499812,.0898047,.437859,-.106002,.500891,.0997142,.440017,-.115648,.502198,.110289,.443236,-.125427,.504389,.121644,.44697,-.135492,.506809,.133769,.451689,-.145746,.509858,.146787,.45811,-.156219,.514247,.160793,.465305,-.166834,.518816,.175791,.474085,-.177546,.524331,.191906,.484808,-.188262,.53104,.209199,.49732,-.199346,.538511,.227825,.509693,-.209951,.544554,.247269,.524367,-.220533,.551616,.267978,.539228,-.231082,.557368,.289672,.55644,-.241342,.563782,.31268,.574204,-.250964,.568851,.33651,.593388,-.260306,.57312,.362219,.613358,-.268667,.574916,.390322,.634512,-.275591,.575053,.420478,.65563,-.281328,.572404,.451614,.678265,-.285948,.568893,.484112,.70011,-.289408,.561878,.517348,.723005,-.291328,.55359,.551355,.743744,-.291418,.541099,.585109,.763949,-.290252,.526489,.619487,.784186,-.287648,.509496,.65404,.804304,-.283782,.491484,.688649,.823629,-.278067,.470517,.723133,.84094,-.270588,.44705,.757163,.857852,-.261188,.421252,.792816,.874934,-.249313,.394191,.827248,.888709,-.236492,.365359,.861074,.902589,-.222185,.336016,.894417,.914201,-.207314,.30527,.926825,.925978,-.191146,.274532,.9595,.93512,-.174135,.243393,.991583,.943656,-.155231,.212414,1.02356,.951719,-.134403,.182005,1.05239,.957164,-.113023,.153043,1.07754,.962656,-.0914493,.124186,1.09984,.970695,-.0694179,.0941654,1.12,.980749,-.0466199,.0629671,1.13849,.991205,-.0227032,.0311146,1.15494,.999884,632388e-9,-254483e-9,1.1706,.379821,-957289e-11,.460637,789337e-11,.405188,-247483e-9,.491396,204064e-9,.404796,-989434e-9,.490914,815853e-9,.40483,-.00222607,.490949,.00183559,.40473,-.00395723,.49084,.00326332,.404731,-.00618287,.490836,.00509945,.404768,-.00890258,.490871,.00734463,.404791,-.0121156,.490883,.00999992,.404857,-.0158214,.490938,.0130676,.404943,-.0200178,.491004,.0165503,.405059,-.0247027,.491093,.0204521,.405213,-.0298729,.491205,.0247788,.405399,-.0355226,.491333,.0295373,.405731,-.0416352,.491604,.034741,.406303,-.0480807,.492116,.0404255,.406814,-.0550458,.492506,.0465732,.407404,-.0624652,.492926,.0532058,.408149,-.0702958,.493442,.0603442,.409128,-.0784623,.494136,.0680297,.410408,-.087007,.495054,.0762786,.411813,-.0959639,.495962,.0851046,.413735,-.105075,.497257,.0945878,.416137,-.114646,.498882,.104725,.41934,-.124394,.501132,.11563,.423326,-.134328,.503883,.127325,.428419,-.14458,.50747,.139911,.43484,-.154979,.511964,.153481,.442641,-.165628,.517328,.168114,.452511,-.176365,.524258,.183995,.463473,-.187298,.531248,.200953,.475564,-.198244,.538367,.219176,.488664,-.208938,.545175,.238514,.504073,-.219599,.553227,.259129,.520832,-.230378,.560653,.280997,.538455,-.240703,.567523,.303821,.55709,-.250548,.573287,.327948,.576646,-.259964,.577795,.353362,.596705,-.268721,.580077,.380336,.618053,-.276054,.58018,.4101,.640303,-.282176,.578747,.44161,.662365,-.286931,.574294,.474106,.684542,-.290521,.567035,.507549,.707984,-.292672,.558687,.541853,.730913,-.293189,.547606,.576581,.752948,-.292199,.533471,.61172,.773452,-.289508,.516395,.646339,.794715,-.285716,.497873,.682131,.814251,-.280051,.476845,.716396,.833057,-.272873,.453449,.751503,.84959,-.263982,.427857,.786085,.867022,-.252745,.400335,.821355,.882277,-.239655,.371304,.85646,.895375,-.225386,.340397,.890828,.909347,-.209587,.310005,.923532,.921885,-.193433,.2796,.956419,.932127,-.176135,.247276,.989445,.941869,-.157872,.216186,1.02221,.949735,-.137577,.185602,1.05195,.956617,-.115285,.155767,1.07822,.961974,-.0928418,.126103,1.10149,.96972,-.0700592,.0956758,1.12207,.98012,-.0474671,.0643269,1.1408,.990825,-.0238113,.0320863,1.1577,.999876,381574e-9,-812203e-10,1.17403,.367636,-961342e-11,.469176,753287e-11,.380377,-244772e-9,.485434,191797e-9,.380416,-978857e-9,.485475,767015e-9,.380376,-.00220165,.485435,.00172522,.380419,-.00391408,.485487,.00306734,.380438,-.00611549,.485505,.00479332,.380462,-.00880558,.485525,.00690391,.380496,-.0119837,.485551,.00940039,.38056,-.0156487,.485605,.0122848,.38064,-.0197988,.485666,.0155601,.380767,-.0244324,.48577,.0192313,.380909,-.0295444,.485871,.0233032,.381142,-.0351321,.48606,.0277861,.381472,-.0411535,.486336,.0326939,.382015,-.0475408,.486833,.0380565,.382523,-.0544395,.487231,.0438615,.383129,-.061784,.487683,.0501332,.383952,-.0695085,.488313,.0568996,.38498,-.0775819,.489077,.0641952,.386331,-.0860443,.490113,.0720324,.387788,-.0948406,.491099,.0804379,.389808,-.103899,.492566,.0894899,.39252,-.113313,.494601,.0992098,.395493,-.123007,.496619,.109641,.399826,-.132859,.499912,.120919,.405341,-.143077,.504061,.133107,.411932,-.153465,.508905,.146263,.420591,-.164108,.515482,.160544,.43101,-.174893,.523191,.176123,.441881,-.185839,.53026,.192757,.453919,-.196633,.537295,.210535,.468715,-.207611,.546156,.229886,.485182,-.218517,.555173,.250543,.501926,-.229249,.562728,.27221,.51785,-.239481,.567494,.294892,.536947,-.249395,.573889,.318987,.557115,-.259,.578831,.344348,.577966,-.268075,.582055,.371223,.599489,-.276115,.583307,.399834,.62479,-.282523,.583902,.431415,.647504,-.287663,.57953,.464301,.670601,-.291538,.573103,.498123,.693539,-.293842,.563731,.532662,.717385,-.294681,.553169,.567925,.741533,-.293717,.539908,.603502,.762142,-.291156,.521902,.639074,.783014,-.28719,.502815,.674439,.805158,-.281773,.482598,.710497,.823646,-.274682,.458949,.7456,.841879,-.266184,.433129,.781085,.859515,-.255682,.406064,.816,.875335,-.242849,.376509,.851074,.890147,-.228329,.345502,.886473,.903144,-.212491,.31428,.920751,.916618,-.195695,.282994,.954606,.927953,-.178267,.251091,.988402,.937414,-.159549,.219107,1.02141,.946823,-.140022,.18896,1.05167,.954651,-.118154,.158667,1.07819,.959955,-.0946636,.128808,1.1025,.96858,-.0711792,.0973787,1.12391,.97938,-.0475046,.0650965,1.14322,.990498,-.024059,.0326267,1.16077,.999844,-512408e-10,112444e-9,1.17727,.316912,-934977e-11,.425996,695559e-11,.356423,-241372e-9,.479108,179562e-9,.356272,-965292e-9,.478897,71811e-8,.356262,-.00217182,.478894,.00161574,.356265,-.00386092,.478895,.00287261,.356278,-.0060324,.478905,.00448907,.356293,-.00868565,.478914,.00646572,.356346,-.0118207,.478965,.00880438,.356395,-.0154355,.479001,.0115066,.356484,-.019529,.479075,.0145762,.356609,-.0240991,.47918,.018018,.356766,-.0291413,.479305,.0218379,.357009,-.0346498,.479512,.0260454,.357424,-.0405462,.479909,.0306657,.357899,-.0468825,.480337,.0357054,.358424,-.0536887,.480771,.0411728,.359041,-.0609416,.481242,.0470841,.359903,-.0685239,.481943,.0534831,.360932,-.0764883,.482741,.0603795,.362196,-.0848364,.483688,.0678028,.363847,-.0935002,.484947,.0758086,.365972,-.102471,.486588,.0844173,.368741,-.111751,.488787,.0937199,.372146,-.121334,.491405,.103732,.377114,-.131147,.495604,.114608,.38226,-.141213,.499436,.126345,.389609,-.151632,.505334,.139116,.397925,-.162073,.51168,.152995,.407824,-.172819,.518876,.168071,.420014,-.183929,.527639,.184495,.434266,-.195032,.537588,.20232,.447352,-.205792,.544379,.221189,.463726,-.216704,.553422,.241616,.481406,-.227531,.562074,.263298,.498707,-.238017,.568227,.286116,.518039,-.247936,.574473,.3101,.538277,-.257437,.579191,.335401,.561166,-.266829,.584807,.362246,.583189,-.275329,.586476,.390609,.606024,-.28234,.585578,.420998,.632419,-.287924,.584496,.454357,.656128,-.291972,.577766,.488233,.679953,-.29456,.56875,.523248,.704654,-.295816,.558388,.559168,.729016,-.295157,.544826,.595326,.752062,-.292779,.528273,.631864,.773138,-.288681,.508482,.667793,.794869,-.283358,.487341,.704035,.815101,-.27608,.46354,.739925,.834212,-.26767,.438672,.775539,.852368,-.257397,.411239,.810895,.870207,-.245689,.3829,.846472,.884063,-.231452,.351496,.881788,.898284,-.215561,.31895,.917438,.912964,-.198208,.287367,.952422,.924666,-.180426,.254487,.987551,.934429,-.161525,.222226,1.02142,.943485,-.141197,.191143,1.05218,.9521,-.120085,.161112,1.07937,.957876,-.0975881,.130982,1.10403,.966943,-.0726842,.0990553,1.12616,.978313,-.0483705,.0662818,1.14619,.990048,-.0239072,.0329243,1.16413,.999984,461885e-9,-772859e-10,1.18099,.321287,-935049e-11,.455413,659662e-11,.332595,-237513e-9,.471437,167562e-9,.332729,-949964e-9,.471618,670192e-9,.332305,-.00213618,.471028,.00150712,.332326,-.00379765,.471055,.00267959,.332344,-.00593353,.471072,.00418751,.332356,-.00854349,.471077,.00603172,.332403,-.0116268,.471121,.00821362,.332461,-.0151824,.47117,.0107357,.332552,-.0192088,.471251,.0136014,.332657,-.0237024,.47133,.0168152,.332835,-.0286615,.471487,.0203853,.333083,-.0340765,.471708,.0243212,.333547,-.0398563,.47219,.0286518,.333989,-.0460916,.472587,.0333763,.334532,-.0527897,.473054,.0385084,.335167,-.0599284,.473568,.0440638,.33608,-.0673514,.474362,.0500962,.337146,-.0752237,.475231,.0566022,.338462,-.083418,.476282,.0636272,.34014,-.0919382,.477615,.0712153,.342341,-.100741,.479404,.079417,.345088,-.109905,.481618,.0882631,.349049,-.119369,.485081,.0978851,.353939,-.129033,.489317,.108336,.359893,-.139038,.494309,.119698,.366945,-.149411,.499983,.132024,.375814,-.159843,.507185,.145558,.387112,-.170664,.516392,.160433,.40023,-.181897,.526519,.176648,.412555,-.192785,.53423,.193922,.427023,-.203663,.542741,.212662,.443685,-.214695,.552066,.232944,.461499,-.225561,.560762,.254495,.480975,-.236257,.569421,.277531,.501,-.24639,.576101,.301724,.521691,-.256101,.581493,.327112,.543478,-.265289,.585221,.353917,.566094,-.273938,.587614,.381941,.589578,-.281679,.587991,.41172,.614583,-.287655,.585928,.444148,.641813,-.292228,.582092,.478617,.666189,-.295172,.57398,.51397,.690475,-.29648,.561676,.550118,.715543,-.296203,.548758,.586933,.740405,-.293999,.532792,.62384,.762183,-.28998,.512735,.660723,.786069,-.28478,.492402,.69807,.806812,-.277568,.469058,.734422,.826987,-.268951,.443017,.770946,.844588,-.259049,.415501,.80699,.863725,-.2471,.387328,.842107,.879137,-.234157,.356108,.878078,.894634,-.218719,.324315,.914058,.909162,-.201293,.291813,.949922,.92072,-.18267,.258474,.985337,.93158,-.163212,.225593,1.0205,.941238,-.142771,.193986,1.05273,.949293,-.120956,.163392,1.08075,.956226,-.0985743,.132934,1.10559,.96546,-.075118,.101255,1.12823,.977403,-.0497921,.0675441,1.149,.989648,-.0241574,.0334681,1.16765,1.00001,5762e-7,-184807e-9,1.18519,.303474,-916603e-11,.4542,61243e-10,.308894,-232869e-9,.462306,155592e-9,.309426,-931661e-9,.463093,622499e-9,.308643,-.0020949,.461933,.00139979,.308651,-.0037242,.461941,.00248874,.308662,-.00581873,.46195,.00388933,.308687,-.00837818,.461974,.00560247,.308728,-.0114016,.462011,.00762948,.308789,-.0148884,.462067,.00997326,.308882,-.0188369,.462151,.0126375,.309007,-.0232436,.462263,.0156271,.30918,-.0281054,.462417,.0189498,.309442,-.0334065,.462667,.0226167,.309901,-.0390589,.463162,.0266614,.310331,-.0452042,.463555,.0310715,.310858,-.0517735,.464019,.0358698,.311576,-.0587359,.464669,.0410848,.312436,-.0660383,.465406,.0467453,.313526,-.0737266,.466339,.0528718,.314903,-.0817574,.467504,.0595039,.316814,-.090167,.469226,.0666888,.318965,-.0987555,.470981,.0744658,.322077,-.107792,.473814,.082912,.325947,-.117098,.477241,.0920846,.331008,-.126602,.48184,.102137,.337893,-.136619,.488334,.113135,.345106,-.146838,.494415,.12511,.355111,-.157357,.503275,.138356,.365095,-.167955,.510966,.152686,.378344,-.179157,.521508,.16856,.391599,-.190143,.530455,.18561,.407786,-.20123,.541275,.204308,.425294,-.212456,.551784,.224623,.444021,-.223568,.561493,.246172,.463418,-.234154,.569886,.268979,.484077,-.244546,.577116,.293411,.505513,-.254301,.582914,.318936,.527672,-.263564,.587208,.345856,.550565,-.272332,.589277,.374054,.573656,-.280011,.588426,.403276,.59827,-.286924,.587504,.43474,.624731,-.291994,.583401,.468767,.652396,-.295159,.576997,.504411,.67732,-.296954,.565863,.54114,.703147,-.296877,.552316,.57816,.728715,-.295147,.536773,.616124,.752448,-.291275,.51771,.653885,.775169,-.285905,.496087,.691537,.799307,-.279064,.474232,.729251,.819482,-.270294,.447676,.766267,.837659,-.260032,.419656,.802616,.856903,-.248497,.391328,.838583,.873325,-.235252,.360285,.874711,.889788,-.221126,.329215,.91077,.904486,-.204304,.296392,.94653,.917711,-.185562,.262159,.983828,.928969,-.165635,.229142,1.01955,.939707,-.14442,.19673,1.05317,.948167,-.122147,.165095,1.0823,.955222,-.099098,.13451,1.10791,.964401,-.0755332,.102476,1.1312,.976605,-.0513817,.0689667,1.15218,.989085,-.0258499,.034506,1.17129,.999908,617773e-9,-271268e-9,1.18961,.285803,-905752e-11,.452348,572272e-11,.284689,-22732e-8,.450581,143626e-9,.285263,-910214e-9,.451482,575099e-9,.285302,-.00204784,.451553,.00129395,.285318,-.00364057,.451574,.0023006,.28533,-.00568813,.451585,.00359547,.285361,-.00819001,.451618,.00517934,.285397,-.0111458,.45165,.007054,.285447,-.0145536,.451688,.00922167,.285527,-.0184127,.451758,.0116869,.285688,-.0227207,.451929,.0144555,.28584,-.0274712,.452055,.0175341,.286136,-.0326278,.452369,.0209406,.286574,-.0381792,.452853,.0246965,.287012,-.0441879,.453272,.0287996,.287542,-.0506096,.453752,.033268,.288299,-.0573634,.454488,.0381504,.289186,-.0645458,.455294,.0434447,.290302,-.0720405,.456301,.0491973,.291776,-.0799046,.457648,.0554453,.29372,-.088117,.459483,.0622311,.296052,-.0965328,.461571,.0695992,.299563,-.105409,.465085,.077658,.30335,-.114553,.468506,.0864176,.309167,-.123917,.474423,.0961078,.31529,-.13381,.47995,.106643,.324163,-.144021,.488592,.118322,.333272,-.154382,.496461,.131133,.344224,-.165015,.50562,.145208,.357733,-.176168,.516719,.16073,.373046,-.187468,.528513,.177807,.38788,-.198488,.537713,.196072,.405133,-.209545,.547999,.21605,.423845,-.220724,.55759,.237484,.443777,-.231518,.566246,.26039,.464824,-.242035,.574326,.284835,.486635,-.251898,.58037,.310518,.51012,-.261304,.58568,.337678,.535301,-.270384,.590197,.366242,.559193,-.27841,.590569,.395873,.583544,-.285325,.588161,.426857,.608834,-.291113,.584249,.459477,.635753,-.294882,.57763,.494734,.664367,-.297088,.569479,.532023,.689688,-.297364,.555064,.569629,.715732,-.295949,.539522,.608124,.741307,-.292259,.521613,.646231,.764949,-.287063,.49969,.684938,.788599,-.28012,.476747,.723548,.81048,-.27153,.45116,.761135,.831372,-.261289,.424101,.798916,.850092,-.249559,.39443,.835952,.867777,-.236348,.363849,.871606,.884632,-.221569,.332477,.907843,.90047,-.20618,.300667,.944187,.914524,-.188771,.266552,.981371,.926892,-.168362,.232349,1.01841,.937951,-.146761,.199359,1.05308,.947236,-.123813,.1675,1.0839,.954367,-.099984,.136166,1.11047,.963907,-.0759278,.103808,1.13414,.976218,-.0511367,.0697061,1.15575,.988772,-.0267415,.0352529,1.17531,.999888,-520778e-9,289926e-9,1.19389,.263546,-883274e-11,.441896,526783e-11,.262352,-221849e-9,.439889,132311e-9,.262325,-886683e-9,.439848,528824e-9,.26228,-.00199476,.439765,.00118975,.262372,-.00354671,.439922,.00211568,.26239,-.00554141,.439941,.00330652,.262412,-.00797888,.439961,.00476346,.262453,-.0108584,.440002,.00648818,.262528,-.0141788,.440085,.0084835,.262615,-.017938,.440166,.0107533,.262744,-.0221346,.440291,.0133044,.262939,-.026762,.440493,.0161445,.263277,-.0317573,.440889,.0192974,.26368,-.0371832,.441338,.0227699,.264106,-.0430371,.441753,.0265698,.264624,-.0493035,.442227,.0307178,.265378,-.0558669,.442985,.0352616,.266253,-.0628718,.443795,.0401968,.267478,-.0701569,.445008,.04559,.269062,-.077845,.446599,.0514539,.270926,-.0857941,.448349,.0578382,.273693,-.0940773,.451221,.0648363,.276746,-.102704,.454097,.0724389,.281693,-.111735,.459517,.0808744,.287335,-.121004,.46531,.0901551,.29448,-.130734,.472605,.100371,.30257,-.140777,.480251,.111644,.312465,-.15111,.489444,.124111,.324856,-.16189,.500919,.137979,.33774,-.172946,.511317,.153163,.35255,-.184152,.522684,.169817,.367786,-.19522,.53248,.187886,.385474,-.20632,.543326,.207634,.404976,-.217744,.554109,.229165,.425203,-.228691,.563395,.252068,.446704,-.239299,.571565,.276471,.468951,-.249348,.577935,.302323,.493487,-.258933,.584309,.329882,.517861,-.268009,.58773,.358525,.543309,-.276238,.589612,.388585,.569704,-.28356,.589294,.419787,.594871,-.289497,.585137,.452114,.622555,-.294452,.580356,.486466,.651167,-.296918,.57185,.523079,.677332,-.297647,.558428,.5611,.703718,-.296321,.542232,.599592,.730262,-.293339,.524541,.639138,.754304,-.288036,.502691,.677978,.778051,-.281018,.479212,.716537,.801557,-.272414,.454071,.75586,.822559,-.262419,.425952,.794477,.843051,-.250702,.397313,.832664,.86232,-.237264,.366534,.869876,.879044,-.222716,.334816,.906973,.896362,-.206827,.303143,.943558,.910342,-.189659,.269699,.979759,.924119,-.171108,.236411,1.01718,.935374,-.149579,.202224,1.05289,.944295,-.126295,.16989,1.08496,.952227,-.101511,.138089,1.11256,.962041,-.0766392,.105053,1.1375,.97528,-.0511967,.070329,1.15983,.988476,-.025463,.0351268,1.17987,.999962,286808e-10,145564e-10,1.19901,.227089,-841413e-11,.404216,472707e-11,.239725,-215083e-9,.426708,120833e-9,.239904,-860718e-9,.427028,483555e-9,.239911,-.00193661,.427039,.00108806,.239914,-.00344276,.42704,.00193457,.239933,-.00537907,.427064,.00302363,.239944,-.00774482,.427065,.00435604,.239993,-.01054,.427122,.00593398,.240052,-.0137626,.427179,.00775987,.240148,-.0174115,.427279,.00983854,.240278,-.021484,.42741,.0121763,.240472,-.0259729,.427618,.0147827,.240839,-.0308131,.428086,.0176837,.241201,-.0360893,.428482,.0208775,.241626,-.0417723,.428907,.0243821,.242207,-.0478337,.42952,.0282228,.24298,-.0542199,.430332,.0324333,.243881,-.0610015,.431222,.0370252,.245123,-.0680874,.432512,.0420535,.24667,-.0755482,.434088,.0475414,.248779,-.0832873,.436323,.0535542,.251665,-.0913546,.439509,.0601716,.255305,-.0998489,.443478,.0674282,.260049,-.108576,.448713,.0754673,.266192,-.117754,.455524,.084339,.273158,-.127294,.4627,.0941683,.282131,-.137311,.472068,.10515,.293332,-.147736,.483565,.117402,.304667,-.158357,.493702,.130824,.317785,-.169274,.504708,.145724,.333245,-.180595,.517107,.16215,.349843,-.191892,.528849,.180149,.367944,-.203168,.540301,.199746,.387579,-.214443,.551514,.221047,.408247,-.225624,.560906,.243981,.43014,-.236422,.56959,.268513,.452669,-.24654,.576098,.294409,.476196,-.256157,.580925,.322002,.501157,-.265289,.584839,.351052,.527632,-.273671,.587614,.3812,.555754,-.281254,.589119,.412994,.581682,-.287448,.585204,.445498,.608196,-.292614,.579006,.479505,.635661,-.296068,.571297,.514643,.664999,-.297395,.560855,.552213,.691039,-.296645,.544525,.591365,.7179,-.293785,.526535,.630883,.744059,-.289089,.50545,.670932,.76863,-.282239,.482514,.710904,.793273,-.273688,.457246,.750259,.814731,-.26328,.428872,.78948,.835603,-.251526,.399384,.828597,.85489,-.238339,.368811,.866892,.872828,-.223607,.336617,.90563,.889462,-.207538,.303997,.943538,.904929,-.190297,.270812,.980591,.919101,-.172034,.237453,1.01935,.930536,-.152058,.204431,1.05498,.941223,-.129515,.172495,1.08717,.94982,-.104263,.140175,1.11551,.960592,-.0781944,.106465,1.14098,.974629,-.051688,.0711592,1.16418,.98811,-.0253929,.0354432,1.18465,1.00004,804378e-9,-330876e-9,1.20462,.214668,-821282e-11,.406619,433582e-11,.218053,-208144e-9,.413025,109887e-9,.217987,-832212e-9,.412901,439362e-9,.217971,-.00187246,.412876,988623e-9,.217968,-.00332855,.41286,.00175772,.217985,-.00520055,.412882,.00274729,.218014,-.00748814,.412916,.00395842,.218054,-.0101901,.412957,.00539274,.218106,-.0133057,.413005,.00705348,.218217,-.0168342,.413139,.00894581,.218338,-.0207707,.413258,.0110754,.21855,-.0251001,.413509,.0134551,.218913,-.0297861,.413992,.0161081,.219265,-.0348956,.414383,.0190307,.219696,-.0403909,.414839,.0222458,.220329,-.0462003,.415567,.025792,.220989,-.0524208,.41621,.0296637,.222027,-.058948,.417385,.0339323,.223301,-.0658208,.418779,.0386055,.224988,-.0730347,.420665,.0437355,.227211,-.0805274,.423198,.0493844,.230131,-.088395,.426566,.0556135,.233908,-.0966208,.43091,.0624829,.239092,-.105223,.437148,.0701636,.245315,-.11424,.444302,.0786949,.253166,-.12368,.453262,.0882382,.262374,-.133569,.463211,.0988682,.273145,-.143836,.474271,.110727,.285512,-.154577,.4863,.123945,.299512,-.165501,.498817,.138581,.314287,-.176698,.510341,.154676,.331083,-.188066,.522583,.172459,.349615,-.199597,.534879,.191979,.369318,-.210843,.546083,.21309,.390377,-.222068,.5562,.235998,.412411,-.233059,.564704,.260518,.435715,-.24357,.572314,.286795,.461196,-.253356,.579395,.314559,.485587,-.262362,.581985,.343581,.511908,-.270895,.584347,.374367,.539798,-.278452,.58505,.406015,.567974,-.284877,.583344,.439168,.594303,-.290124,.577348,.473005,.622951,-.294183,.570751,.508534,.652404,-.296389,.561541,.544764,.679291,-.296605,.546426,.582927,.706437,-.294095,.528599,.622681,.734485,-.28978,.508676,.663567,.758841,-.283363,.484768,.704092,.78537,-.275015,.460434,.745101,.807315,-.264689,.432166,.784712,.8271,-.252597,.401807,.824241,.849191,-.239154,.371458,.863803,.867046,-.224451,.338873,.903063,.8852,-.208342,.306175,.942763,.901771,-.190684,.272759,.981559,.915958,-.172105,.239306,1.02048,.928046,-.152214,.206071,1.05765,.939961,-.130247,.17367,1.08999,.948711,-.10672,.142201,1.11829,.959305,-.0808688,.108454,1.14467,.973009,-.0539145,.0728109,1.16839,.987631,-.0262947,.0360625,1.19004,.999978,.00132758,-559424e-9,1.21058,.193925,-793421e-11,.391974,392537e-11,.196746,-200315e-9,.397675,991033e-10,.19667,-801099e-9,.397521,396342e-9,.196633,-.00180246,.397445,891829e-9,.196654,-.00320443,.397482,.00158582,.196659,-.00500647,.39748,.00247867,.196683,-.0072086,.397506,.00357167,.196728,-.00981001,.397562,.00486675,.196792,-.0128096,.397633,.00636707,.19689,-.0162055,.397746,.00807752,.197017,-.0199943,.397884,.0100052,.19729,-.024139,.39827,.0121691,.197583,-.0286671,.398639,.0145755,.197927,-.0335858,.399034,.0172355,.198383,-.0388806,.399554,.0201718,.199002,-.0444736,.400289,.0234194,.199739,-.0504583,.401111,.026984,.200784,-.056729,.402349,.0309217,.202075,-.0633643,.403841,.0352496,.203898,-.0703247,.406076,.0400313,.206199,-.0775565,.408841,.0453282,.209252,-.085184,.41259,.0511794,.213638,-.0931994,.418288,.0577459,.21881,-.101617,.424681,.0650508,.225642,-.11052,.433429,.0732759,.233717,-.119772,.442897,.0824683,.242823,-.129505,.452888,.0927484,.254772,-.139906,.466407,.104417,.266603,-.150402,.477413,.117211,.28073,-.161395,.490519,.131598,.295399,-.172465,.50201,.147407,.312705,-.183982,.515311,.165031,.331335,-.195532,.52786,.184336,.351037,-.206971,.5392,.205361,.372175,-.218117,.54941,.228043,.394548,-.229327,.558642,.25267,.419598,-.240052,.567861,.279071,.443922,-.249937,.573332,.306882,.471495,-.259407,.58013,.33661,.496769,-.267749,.580564,.367328,.524951,-.275524,.581696,.399753,.55318,-.282148,.579885,.433134,.581577,-.287533,.575471,.467534,.609231,-.291612,.567445,.502943,.637478,-.293911,.557657,.53871,.667795,-.295096,.546535,.576568,.694272,-.294073,.529561,.614929,.722937,-.290386,.510561,.655909,.749682,-.284481,.487846,.697663,.774754,-.276188,.462487,.738515,.799301,-.266215,.43481,.779802,.820762,-.254116,.404879,.820045,.843231,-.240393,.374559,.860294,.861857,-.225503,.341582,.900965,.880815,-.209382,.308778,.941727,.89766,-.19155,.275232,.980916,.912926,-.172346,.240938,1.02162,.926391,-.151799,.207223,1.0597,.938429,-.129968,.17484,1.09291,.947834,-.10651,.142984,1.12248,.958432,-.0824098,.109902,1.149,.972402,-.0565242,.0744454,1.1733,.987191,-.028427,.0373794,1.19538,.999975,385685e-10,-4203e-8,1.21676,.178114,-766075e-11,.385418,354027e-11,.176074,-191966e-9,.381002,887135e-10,.17601,-767549e-9,.380861,354715e-9,.17598,-.00172696,.380798,798168e-9,.175994,-.00307012,.380824,.00141928,.176017,-.00479684,.380858,.00221859,.176019,-.00690648,.380839,.00319714,.176072,-.00939888,.380913,.0043572,.176131,-.0122726,.380979,.005702,.176239,-.0155264,.38112,.00723689,.176371,-.0191551,.381272,.00896907,.176638,-.023117,.381669,.0109194,.176912,-.0274633,.382015,.0130903,.177279,-.032173,.382476,.0154949,.17774,-.0372219,.383041,.0181669,.178344,-.0426132,.38378,.0211209,.179153,-.0483309,.384773,.0243899,.180197,-.0543447,.386076,.0280062,.181581,-.0607122,.387809,.032004,.18344,-.0673855,.390205,.036453,.186139,-.0743989,.393944,.0414162,.189432,-.0817731,.39832,.0469394,.193795,-.0895464,.404188,.0531442,.199641,-.0978264,.4121,.0601374,.206679,-.106499,.421425,.0680078,.214865,-.115654,.431504,.076919,.224406,-.125268,.442526,.0868835,.235876,-.135475,.455465,.0981875,.248335,-.146023,.4681,.110759,.262868,-.157016,.482069,.124885,.278962,-.168245,.496182,.140645,.295082,-.17958,.507401,.157838,.313738,-.191227,.520252,.17695,.333573,-.202718,.531708,.197817,.356433,-.214424,.544509,.220785,.378853,-.225492,.55373,.245306,.402717,-.236236,.561348,.271593,.428375,-.246568,.568538,.299776,.454724,-.255941,.573462,.329433,.482291,-.264511,.576356,.360598,.509706,-.272129,.576446,.393204,.538805,-.278979,.575298,.427227,.568919,-.284528,.572154,.462157,.596804,-.288801,.564691,.497997,.625987,-.291334,.555134,.534467,.656414,-.292722,.545051,.571736,.683916,-.292185,.528813,.610158,.711809,-.290043,.51106,.649061,.739547,-.285246,.490103,.690081,.766914,-.277647,.465523,.732554,.791375,-.267603,.437718,.773982,.814772,-.256109,.40882,.81609,.836691,-.242281,.377823,.856849,.856984,-.227155,.34496,.898363,.876332,-.210395,.311335,.939471,.894988,-.192612,.277703,.980799,.911113,-.173236,.243019,1.02215,.924092,-.152258,.209037,1.06139,.936828,-.129575,.175909,1.09635,.946869,-.10594,.143852,1.12707,.958284,-.081318,.110289,1.15419,.972325,-.0556133,.0747232,1.17909,.986878,-.0297899,.0383149,1.20163,.999936,-.00197169,912402e-9,1.22338,.151174,-720365e-11,.351531,309789e-11,.155594,-18279e-8,.361806,78608e-9,.156099,-731569e-9,.362982,314615e-9,.156053,-.00164578,.362869,707845e-9,.156093,-.0029261,.362961,.00125884,.156099,-.00457155,.362959,.00196783,.15612,-.00658224,.362982,.00283622,.156168,-.00895774,.363048,.00386625,.156221,-.0116962,.363101,.00506109,.156324,-.0147973,.363241,.00642675,.156476,-.0182503,.363448,.00797175,.156731,-.0220266,.36384,.00971484,.156994,-.026176,.364179,.0116575,.157341,-.0306701,.36462,.0138207,.157867,-.0354591,.365364,.0162356,.15846,-.0406141,.366111,.0189092,.159308,-.0460519,.367248,.021885,.160426,-.0518096,.368767,.0252004,.161877,-.0578906,.370745,.0288825,.163995,-.0642812,.373831,.0330139,.16655,-.0710067,.377366,.0376283,.170237,-.0781522,.382799,.0428493,.175096,-.0857172,.389915,.0487324,.181069,-.0938025,.398487,.0554214,.188487,-.102363,.408799,.0630189,.197029,-.111343,.419991,.071634,.206684,-.120812,.431455,.0812797,.218698,-.131033,.445746,.0923651,.230726,-.141373,.457471,.104545,.245516,-.152387,.472388,.118449,.261551,-.163628,.486671,.133923,.277437,-.174814,.49762,.150849,.296662,-.186713,.51162,.169924,.31795,-.198513,.525435,.190848,.339422,-.210119,.536267,.213504,.362143,-.221354,.545982,.237947,.387198,-.23224,.555364,.264427,.412349,-.24257,.561489,.292519,.439274,-.252284,.566903,.322561,.466779,-.261023,.569614,.353952,.496011,-.26899,.571589,.387278,.524964,-.275498,.570325,.421356,.556518,-.281449,.568792,.457314,.584363,-.285526,.560268,.493199,.614214,-.28844,.55205,.530276,.645684,-.289777,.541906,.56855,.673446,-.289722,.526464,.606927,.701924,-.287792,.509872,.645945,.73037,-.284315,.490649,.685564,.757405,-.278804,.467964,.726511,.784025,-.269543,.441468,.768601,.808255,-.258117,.41216,.811321,.830739,-.244728,.380606,.853496,.851914,-.229428,.348111,.895374,.872586,-.212508,.314732,.937674,.891581,-.194025,.280338,.979869,.907641,-.174711,.245203,1.02253,.922233,-.153509,.21077,1.06371,.935878,-.130418,.177399,1.09972,.946338,-.105558,.144507,1.13124,.957265,-.080059,.110508,1.15973,.971668,-.0539766,.0742311,1.18515,.9866,-.0277101,.0375224,1.20858,1.00021,-515531e-9,135226e-9,1.23135,.137468,-686011e-11,.345041,273315e-11,.13703,-173378e-9,.343936,690761e-10,.136986,-693048e-9,.34383,276126e-9,.136964,-.00155931,.343761,621337e-9,.137003,-.00277211,.343863,.00110494,.137012,-.00433103,.343868,.00172744,.137043,-.00623606,.343916,.00249022,.13709,-.0084868,.343986,.00339559,.137145,-.0110814,.344045,.00444687,.137242,-.0140187,.344177,.00565007,.137431,-.0172713,.344491,.00701868,.137644,-.0208605,.344805,.00856042,.13791,-.024792,.345172,.0102863,.138295,-.0290461,.345734,.0122185,.138764,-.0335957,.346371,.0143771,.139415,-.038467,.347298,.0167894,.140272,-.0436176,.348527,.0194895,.141457,-.0491016,.350276,.0225043,.14303,-.0548764,.352646,.0258962,.145289,-.0610096,.356206,.0297168,.148502,-.0674777,.361488,.0340562,.152188,-.074345,.367103,.0389534,.157359,-.0817442,.375247,.0445541,.16379,-.0896334,.385064,.0509535,.171376,-.098005,.396082,.0582611,.179901,-.106817,.407418,.06654,.189892,-.116239,.420031,.075994,.201838,-.12627,.434321,.0867239,.214311,-.136701,.447631,.0987517,.228902,-.147616,.462046,.112353,.245107,-.158871,.476942,.127605,.262292,-.170261,.490285,.144469,.281215,-.182017,.503783,.163282,.301058,-.193729,.515505,.183873,.322752,-.205512,.52682,.206466,.347547,-.217214,.539473,.231194,.370969,-.227966,.546625,.257288,.397533,-.238555,.55472,.285789,.42398,-.248278,.559468,.315746,.452928,-.257422,.564095,.347724,.482121,-.265306,.565426,.380922,.510438,-.272043,.563205,.415639,.541188,-.277614,.561087,.451702,.571667,-.281927,.554922,.48845,.602432,-.285015,.546838,.526442,.634126,-.286512,.537415,.564896,.662816,-.286388,.522906,.604037,.692411,-.284734,.507003,.643795,.720946,-.281297,.488398,.68298,.748293,-.276262,.466353,.723466,.776931,-.269978,.443573,.764565,.801065,-.260305,.415279,.805838,.825843,-.247426,.384773,.849985,.84807,-.232437,.352555,.893174,.869122,-.215806,.318642,.936564,.888963,-.197307,.28381,.980253,.905547,-.177203,.247888,1.02463,.918554,-.155542,.212904,1.06714,.931395,-.131948,.1787,1.10451,.941749,-.106723,.145902,1.13694,.954551,-.0804939,.111193,1.1666,.970279,-.0534239,.0744697,1.19249,.986117,-.0257452,.0368788,1.21665,.999938,.00190634,-.0010291,1.23981,.118493,-647439e-11,.32272,23772e-10,.118765,-163023e-9,.323456,598573e-10,.118772,-65212e-8,.323477,239447e-9,.118843,-.00146741,.323657,538881e-9,.118804,-.00260846,.323553,95826e-8,.118826,-.00407576,.323595,.00149845,.118846,-.00586826,.323617,.00216047,.118886,-.00798578,.32367,.00294679,.118947,-.0104273,.323753,.00386124,.119055,-.0131909,.323922,.00490999,.119241,-.0162444,.324251,.00610804,.11944,-.0196339,.324544,.00745805,.119739,-.0233378,.325026,.00897805,.12011,-.0273179,.325586,.0106895,.120571,-.0316143,.326231,.0126073,.12124,-.0361939,.327264,.0147654,.122162,-.0410511,.328733,.0172001,.123378,-.0462233,.330659,.0199375,.125183,-.0517109,.333754,.0230498,.127832,-.0575652,.338507,.026597,.130909,-.0637441,.343666,.0306345,.135221,-.0704302,.351063,.035273,.14082,-.0776364,.360604,.0406137,.146781,-.0852293,.369638,.0466788,.155121,-.0935351,.3827,.0537628,.16398,-.102234,.39522,.0617985,.173926,-.111465,.40793,.07097,.185137,-.121296,.42105,.0813426,.19826,-.13169,.435735,.0931596,.212938,-.142614,.450932,.106547,.229046,-.153884,.465726,.121575,.246246,-.165382,.479461,.138286,.264637,-.176806,.492106,.15666,.284959,-.188793,.504774,.17728,.308157,-.200763,.518805,.19988,.330951,-.21239,.528231,.224293,.3549,-.223521,.536376,.250541,.381502,-.234169,.544846,.278902,.409529,-.244077,.551717,.309227,.437523,-.253363,.55517,.341426,.467624,-.261659,.557772,.37518,.497268,-.268498,.556442,.41007,.528294,-.274018,.553915,.446445,.559053,-.278169,.549153,.483779,.589329,-.281229,.539878,.522249,.622503,-.282902,.53162,.561754,.652382,-.282815,.518119,.601544,.681847,-.281247,.502187,.641574,.712285,-.277986,.484824,.682633,.740094,-.273017,.463483,.723426,.768478,-.266692,.441299,.763747,.794556,-.258358,.415238,.805565,.819408,-.248807,.386912,.847254,.843411,-.236214,.356165,.891091,.862397,-.219794,.320562,.936174,.883113,-.201768,.285322,.982562,.90023,-.181672,.249713,1.02862,.915192,-.159279,.214546,1.07163,.928458,-.134725,.180285,1.10995,.94069,-.10913,.147119,1.14354,.953409,-.0821315,.112492,1.17372,.969537,-.0542677,.0752014,1.20043,.985612,-.0259096,.0370361,1.22528,.999835,.00298198,-.00151801,1.24959,.10097,-602574e-11,.300277,202619e-11,.101577,-152164e-9,.302077,511662e-10,.101572,-608889e-9,.302066,204751e-9,.101566,-.00136997,.302047,460753e-9,.101592,-.00243557,.302114,819497e-9,.101608,-.0038053,.30214,.00128154,.101627,-.00547906,.30216,.0018483,.101669,-.00745647,.302224,.00252223,.101732,-.00973615,.302318,.00330716,.101844,-.0123097,.302513,.00421061,.102025,-.0151681,.30285,.00524481,.102224,-.0183334,.303166,.0064154,.102515,-.0217819,.303654,.00774063,.102886,-.0255067,.304243,.0092398,.103395,-.029514,.305089,.0109339,.104109,-.0337912,.306301,.0128561,.105074,-.0383565,.30798,.0150338,.10654,-.0432132,.310726,.0175228,.108478,-.0484244,.314351,.0203648,.111015,-.0539339,.319032,.0236325,.114682,-.0598885,.32605,.0274188,.11911,-.0663375,.334109,.0317905,.124736,-.0733011,.344013,.0368502,.131479,-.0807744,.355358,.0427104,.139283,-.0888204,.367614,.0494788,.148054,-.0973394,.380072,.0572367,.159037,-.10665,.395678,.0662704,.169794,-.116221,.40795,.0763192,.18314,-.126632,.423546,.087956,.197515,-.137383,.438213,.101042,.213514,-.148641,.453248,.115827,.23065,-.160117,.46688,.132283,.249148,-.171807,.479962,.150644,.270219,-.183695,.494618,.171073,.292338,-.195574,.506937,.193378,.314999,-.207205,.516463,.217585,.340991,-.218955,.528123,.24428,.367982,-.229917,.537025,.272784,.39432,-.239737,.541627,.302742,.423364,-.249048,.546466,.335112,.453751,-.257329,.549466,.369032,.48416,-.264623,.549503,.404577,.515262,-.270411,.547008,.441337,.547036,-.274581,.542249,.479162,.576614,-.277266,.533015,.517904,.611143,-.279144,.525512,.558508,.640989,-.279001,.51154,.598995,.671182,-.277324,.495641,.639935,.700848,-.273908,.477526,.681017,.729862,-.269063,.457955,.722764,.758273,-.262282,.434846,.764349,.784121,-.254281,.409203,.806206,.809798,-.24505,.382694,.848617,.834953,-.233861,.354034,.892445,.856817,-.221308,.321764,.936263,.877609,-.205996,.288118,.982401,.897489,-.186702,.253277,1.02975,.913792,-.164618,.217963,1.07488,.92785,-.140023,.183221,1.11487,.940378,-.11328,.149385,1.14947,.95273,-.0853958,.114152,1.1807,.969059,-.0568698,.0769845,1.20912,.985574,-.0276502,.0381186,1.23498,.999943,.00239052,-.00126861,1.25987,.0852715,-560067e-11,.279021,171162e-11,.0854143,-140871e-9,.279483,430516e-10,.0854191,-563385e-9,.2795,172184e-9,.0854188,-.00126753,.279493,387464e-9,.0854229,-.00225337,.279501,68918e-8,.0854443,-.00352086,.279549,.00107803,.0854697,-.00506962,.279591,.00155536,.0855093,-.00689873,.279652,.00212354,.0855724,-.00900821,.279752,.00278703,.0856991,-.0113799,.280011,.0035551,.085855,-.0140314,.280297,.00443449,.0860682,-.016963,.280682,.00543636,.086344,-.0201438,.281159,.0065788,.0867426,-.0235999,.281886,.00787977,.087239,-.0273069,.282745,.0093606,.0879815,-.031269,.284139,.011056,.0891258,-.035531,.28647,.0130065,.0906909,-.0400947,.289708,.0152495,.0927624,-.0449638,.293904,.0178454,.0958376,-.0502427,.300471,.0208915,.0995827,-.0559514,.30806,.0244247,.104526,-.0622152,.317874,.0285721,.110532,-.0690046,.329332,.0334227,.117385,-.0763068,.341217,.0390466,.12522,-.084184,.353968,.0455786,.134037,-.0925248,.366797,.0530773,.144014,-.101487,.380209,.0617424,.156013,-.111273,.395956,.071777,.168872,-.121431,.41053,.0830905,.183089,-.132105,.425073,.0959341,.198763,-.143286,.439833,.110448,.216159,-.154841,.454507,.126769,.234859,-.166588,.468368,.14495,.255879,-.178626,.482846,.165233,.27677,-.190218,.493489,.187217,.301184,-.202227,.506549,.211659,.325852,-.213764,.5158,.237922,.352824,-.22487,.525442,.26632,.380882,-.235246,.532487,.296691,.410137,-.244847,.537703,.329179,.439787,-.253122,.540361,.363135,.472291,-.260517,.542734,.399222,.501856,-.266519,.538826,.436352,.534816,-.270905,.535152,.474505,.565069,-.273826,.525979,.513988,.597154,-.275333,.516394,.554852,.630473,-.275314,.506206,.596592,.660574,-.273323,.489769,.638117,.692015,-.270008,.472578,.680457,.720647,-.265001,.452134,.723008,.750528,-.258311,.430344,.765954,.777568,-.250046,.405624,.809012,.80387,-.240114,.378339,.852425,.828439,-.228737,.349877,.895346,.851472,-.216632,.318968,.940695,.873906,-.202782,.287489,.987235,.89467,-.187059,.254394,1.03348,.912281,-.168818,.221294,1.07812,.927358,-.146494,.18675,1.11928,.940385,-.120009,.152322,1.15609,.952672,-.0917183,.117514,1.18875,.968496,-.0620321,.0797405,1.21821,.985236,-.0314945,.0402383,1.24523,.99998,-575153e-9,110644e-9,1.27133,.0702429,-512222e-11,.255273,140947e-11,.0702981,-128826e-9,.255469,354488e-10,.0703691,-515562e-9,.255727,141874e-9,.0703805,-.00116,.255754,31929e-8,.0703961,-.00206224,.255813,567999e-9,.0704102,-.00322223,.255839,88871e-8,.0704298,-.00463928,.255863,.00128272,.0704759,-.00631375,.255953,.00175283,.0705434,-.00824317,.256079,.00230342,.0706693,-.010412,.25636,.0029443,.0708189,-.0128439,.256647,.00368031,.0710364,-.0155177,.257084,.00452614,.0713223,-.0184374,.257637,.00549706,.0717182,-.0216002,.258416,.00661246,.072321,-.0249966,.259699,.00790147,.0731446,-.0286566,.261475,.0093884,.0743352,-.0325888,.264132,.0111186,.0760676,-.036843,.26815,.013145,.078454,-.0414292,.273636,.0155251,.0818618,-.0464634,.281653,.0183525,.0857382,-.0519478,.289992,.0216642,.0908131,-.0579836,.30066,.0255956,.0967512,-.0645124,.312204,.0301954,.103717,-.0716505,.325001,.0356017,.111596,-.0793232,.338129,.041896,.120933,-.087645,.352853,.0492447,.130787,-.096492,.366192,.0576749,.142311,-.105973,.380864,.0673969,.155344,-.116182,.396575,.0785899,.169535,-.126815,.411443,.0912377,.185173,-.138015,.426256,.105607,.201755,-.149325,.439607,.121551,.221334,-.161207,.455467,.139608,.241461,-.173162,.469096,.159591,.26294,-.18504,.481014,.18156,.286776,-.196881,.493291,.205781,.311596,-.208311,.503556,.231819,.338667,-.219671,.513268,.260274,.366021,-.230451,.519414,.290862,.395875,-.240131,.526766,.323196,.425564,-.248566,.52905,.357071,.457094,-.256195,.530796,.393262,.488286,-.262331,.528703,.430797,.522291,-.267141,.52727,.470231,.554172,-.270411,.519848,.510477,.586427,-.271986,.510307,.551594,.619638,-.27192,.499158,.593849,.650656,-.269817,.483852,.636314,.68284,-.266267,.467515,.679679,.714356,-.26113,.44931,.723884,.742717,-.254067,.425789,.767245,.770894,-.245652,.401144,.811819,.797358,-.235554,.374224,.856315,.823377,-.223896,.346167,.901077,.847456,-.210865,.316056,.946502,.870697,-.196574,.284503,.993711,.891068,-.180814,.251628,1.04134,.909267,-.163314,.219065,1.08609,.925653,-.143304,.186446,1.12702,.940017,-.121322,.153416,1.16371,.952398,-.0973872,.120334,1.19712,.967568,-.0698785,.08352,1.22791,.984772,-.0390031,.0439209,1.25672,1.00026,-.0070087,.00315668,1.28428,.0556653,-459654e-11,.227325,112556e-11,.0565238,-116382e-9,.230826,284985e-10,.0565717,-465666e-9,.231026,114036e-9,.0565859,-.00104773,.231079,256656e-9,.0565761,-.00186255,.231025,45663e-8,.0565913,-.00291002,.231058,714664e-9,.0566108,-.00418998,.231085,.00103224,.0566532,-.00570206,.231169,.00141202,.0567473,-.00743666,.231417,.00186018,.0568567,-.00940298,.231661,.00238264,.0569859,-.0115991,.231895,.00298699,.0572221,-.0140096,.232456,.00368957,.057519,-.0166508,.233096,.00450303,.0579534,-.01951,.234094,.00544945,.0585922,-.0225991,.235629,.00655564,.0595647,-.0259416,.238106,.00785724,.0609109,-.0295661,.241557,.00939127,.0628751,-.0335126,.246652,.0112198,.0656908,-.0378604,.254091,.0134168,.0691347,-.0426543,.262666,.0160374,.0732165,-.0478967,.272029,.0191514,.0782863,-.0536716,.283007,.0228597,.0843973,-.0600683,.295732,.0272829,.0913598,-.0670095,.308779,.032484,.0994407,-.0745516,.322886,.0385886,.108189,-.082712,.336408,.0457133,.118574,-.0914927,.351692,.0539832,.129989,-.100854,.366502,.0635162,.142722,-.110837,.381675,.0744386,.156654,-.121353,.3963,.0868483,.172151,-.132414,.411477,.100963,.188712,-.143809,.42508,.116795,.208093,-.155765,.441328,.134715,.227936,-.167608,.454328,.154396,.249495,-.179579,.467235,.176179,.27362,-.191488,.480248,.200193,.296371,-.202618,.487886,.225775,.324234,-.214133,.499632,.25441,.353049,-.225212,.509532,.285077,.381785,-.234875,.514265,.317047,.414038,-.244205,.521282,.351874,.445251,-.252145,.522931,.388279,.476819,-.258433,.520947,.425825,.509209,-.263411,.517669,.465104,.542759,-.266732,.512841,.505741,.574822,-.268263,.503317,.547611,.609324,-.268489,.493035,.590953,.641772,-.266941,.478816,.63488,.674049,-.263297,.462863,.679072,.705071,-.257618,.442931,.723487,.734709,-.250625,.421299,.768708,.763704,-.24179,.397085,.814375,.791818,-.231115,.370577,.859907,.817439,-.21922,.34232,.906715,.843202,-.205658,.312627,.953943,.866639,-.190563,.280933,1.00185,.888129,-.173978,.248393,1.05105,.907239,-.155485,.216007,1.09704,.923893,-.134782,.183233,1.13857,.938882,-.11249,.150376,1.17539,.952464,-.0890706,.117177,1.20924,.968529,-.0646523,.0813095,1.24055,.984763,-.038606,.0439378,1.27018,1.00053,-.01238,.00598668,1.29873,.0437928,-409594e-11,.204012,8.79224e-7,.0440166,-103395e-9,.205049,221946e-10,.0440529,-413633e-9,.205225,887981e-10,.0440493,-930594e-9,.2052,199858e-9,.0439884,-.00165352,.204901,355495e-9,.0440716,-.0025849,.205255,556983e-9,.0440968,-.00372222,.205311,805326e-9,.0441359,-.00506478,.205391,.00110333,.0442231,-.00660384,.205638,.00145768,.0443254,-.00835246,.205877,.00187275,.0444832,-.0102992,.20627,.00235938,.0447001,-.0124449,.206796,.0029299,.0450168,-.0147935,.207593,.0036005,.0454816,-.017336,.208819,.00439246,.0462446,-.0201156,.211036,.00533864,.0473694,-.0231568,.214388,.00646984,.0490191,-.0264941,.219357,.00783856,.0512776,-.030184,.226061,.00950182,.0541279,-.0342661,.234094,.0115156,.0578989,-.0388539,.244297,.0139687,.0620835,-.0438735,.254457,.0169015,.0673497,-.04951,.266706,.0204554,.0731759,-.0556263,.278753,.0246606,.0803937,-.0624585,.29309,.0297126,.0879287,-.0697556,.305856,.0355868,.0970669,-.0778795,.321059,.0425768,.106508,-.0863541,.333873,.05056,.11776,-.0955935,.349008,.0598972,.130081,-.105438,.363776,.0706314,.144454,-.115899,.380112,.0828822,.1596,-.126827,.394843,.0967611,.176097,-.138161,.409033,.112381,.194726,-.149904,.424257,.129952,.213944,-.161675,.436945,.149333,.235516,-.173659,.450176,.170892,.260564,-.185963,.466305,.194984,.285183,-.197582,.477328,.220805,.311095,-.208697,.486566,.248694,.338924,-.219519,.494811,.279015,.369757,-.229766,.504065,.311725,.3996,-.238879,.507909,.345844,.430484,-.246802,.509805,.381749,.46413,-.253924,.511436,.420251,.497077,-.259319,.508787,.459957,.530434,-.263297,.50394,.501356,.565725,-.265619,.49804,.544252,.599254,-.265842,.487346,.587856,.631251,-.263978,.472975,.631969,.663972,-.26043,.457135,.677471,.697724,-.255358,.439844,.723744,.727725,-.248308,.417872,.770653,.756417,-.239181,.39273,.817357,.785419,-.22814,.367839,.864221,.81266,-.215681,.339449,.912701,.839391,-.201623,.309279,.962419,.86366,-.185624,.278029,1.0122,.885028,-.16797,.245294,1.06186,.904639,-.148336,.212689,1.10934,.922048,-.12637,.179616,1.15063,.936952,-.102928,.146749,1.18885,.951895,-.0785268,.112733,1.22352,.967198,-.0530153,.0760056,1.25681,.984405,-.02649,.0383183,1.28762,1.00021,70019e-8,-20039e-8,1.31656,.0325964,-355447e-11,.176706,6.55682e-7,.0329333,-899174e-10,.178527,165869e-10,.0329181,-359637e-9,.178453,663498e-10,.0329085,-808991e-9,.178383,149332e-9,.0329181,-.00143826,.178394,265873e-9,.0329425,-.00224678,.178517,416597e-9,.0329511,-.00323575,.17849,603299e-9,.033011,-.00439875,.178695,829422e-9,.0330733,-.00574059,.178843,.00109908,.0331857,-.00725896,.179176,.00141933,.0333445,-.00895289,.179618,.0017999,.0335674,-.0108219,.180238,.00225316,.033939,-.0128687,.181417,.00279765,.0345239,-.015114,.183395,.0034564,.0354458,-.017596,.186616,.00425864,.0368313,-.0203524,.191547,.00524936,.0386115,-.0234105,.197508,.00647033,.0410303,-.0268509,.205395,.00798121,.0442245,-.0307481,.215365,.0098557,.0478659,-.0350863,.225595,.0121417,.0522416,-.0399506,.236946,.0149385,.0574513,-.045357,.249442,.0183189,.0631208,-.0512863,.261222,.0223644,.0701124,-.0579273,.275418,.0272418,.0777331,-.0650652,.288989,.0329458,.0862709,-.0728813,.302546,.0396819,.096103,-.081363,.317164,.04757,.106976,-.0904463,.331733,.0567012,.119175,-.100105,.34661,.067202,.132919,-.110375,.362249,.0792588,.147727,-.121115,.376978,.0928672,.163618,-.132299,.390681,.108228,.182234,-.143887,.406571,.125502,.201809,-.155827,.42042,.144836,.225041,-.168357,.438411,.166706,.247621,-.18004,.450368,.189909,.27097,-.191536,.460083,.215251,.296658,-.203024,.469765,.243164,.325892,-.214056,.481837,.273388,.35406,-.224104,.487474,.305344,.384372,-.233489,.492773,.339741,.41749,-.241874,.498451,.376287,.45013,-.248834,.499632,.414195,.481285,-.254658,.495233,.454077,.519183,-.259367,.496401,.496352,.551544,-.261818,.487686,.538798,.587349,-.262964,.479453,.583626,.621679,-.262128,.467709,.629451,.654991,-.258998,.452123,.67566,.686873,-.254119,.433495,.723248,.719801,-.246946,.413657,.771156,.750355,-.237709,.390366,.81989,.780033,-.226549,.364947,.868601,.809254,-.214186,.337256,.920034,.836576,-.199639,.307395,.971706,.861774,-.183169,.275431,1.02479,.885707,-.165111,.243431,1.07837,.904742,-.144363,.210921,1.12783,.915604,-.121305,.17647,1.17254,.930959,-.0962119,.143106,1.21012,.948404,-.069969,.108112,1.24474,.967012,-.0427586,.0708478,1.27718,.984183,-.0147043,.032335,1.3083,.999577,.0142165,-.00726867,1.3382,.0229227,-299799e-11,.148623,4.62391e-7,.0232194,-758796e-10,.15054,117033e-10,.0232315,-303636e-9,.15063,468397e-10,.0232354,-683189e-9,.150624,105472e-9,.0232092,-.0012136,.150445,187744e-9,.0232523,-.00189765,.150679,294847e-9,.0232828,-.00273247,.150789,428013e-9,.0233371,-.00371287,.150995,591134e-9,.0234015,-.00484794,.15118,787642e-9,.023514,-.00612877,.151562,.00102547,.023679,-.00756125,.152116,.00131351,.0239559,-.00914651,.153162,.00166594,.0244334,-.010904,.155133,.00210182,.025139,-.0128615,.158035,.00264406,.0262598,-.0150628,.162751,.00332923,.0277875,-.0175532,.168944,.00419773,.0298472,-.0203981,.176835,.00530034,.0325444,-.023655,.186686,.00669777,.0355581,-.0272982,.196248,.00842661,.0392841,-.0314457,.207352,.0105854,.0436815,-.0361157,.219279,.0132458,.0485272,-.0412932,.230728,.0164736,.0541574,-.0470337,.242994,.0203715,.0609479,-.0535002,.257042,.0250953,.0685228,-.0605409,.27102,.0306856,.0768042,-.0680553,.28406,.037193,.0864844,-.0765011,.299186,.0449795,.0969415,-.0852674,.3132,.0538316,.108478,-.0947333,.327138,.0641149,.121705,-.10481,.342345,.0759185,.136743,-.115474,.358472,.0894116,.152986,-.126536,.374067,.104562,.170397,-.138061,.388267,.121632,.191392,-.150203,.406467,.140996,.211566,-.161751,.418641,.161696,.233567,-.173407,.430418,.184557,.257769,-.185397,.44277,.210092,.28531,-.197048,.457191,.237827,.311726,-.20784,.464712,.267253,.340537,-.218345,.472539,.299332,.372921,-.228306,.482331,.333988,.402924,-.236665,.484378,.369722,.434475,-.244097,.484717,.407836,.469736,-.250547,.487093,.448465,.505045,-.25511,.485575,.490263,.540262,-.258444,.481225,.534495,.576347,-.259903,.473481,.579451,.608656,-.259572,.4603,.625604,.646679,-.257908,.450341,.674511,.679902,-.253663,.431561,.723269,.714159,-.247419,.412684,.773263,.745345,-.239122,.389388,.824182,.778248,-.228837,.365361,.876634,.807208,-.216197,.337667,.92945,.835019,-.201772,.307197,.985261,.860261,-.185291,.274205,1.04299,.877601,-.165809,.240178,1.09816,.898211,-.143897,.207571,1.14694,.915789,-.119513,.174904,1.19008,.931831,-.0932919,.141423,1.2297,.949244,-.0656528,.105603,1.26553,.967527,-.0370262,.0679551,1.29986,.984139,-.00730117,.0283133,1.33252,.999713,.0234648,-.0121785,1.36397,.0152135,-245447e-11,.122795,3.04092e-7,.0151652,-615778e-10,.122399,76292e-10,.0151181,-245948e-9,.122023,304802e-10,.0151203,-553394e-9,.12203,686634e-10,.015125,-983841e-9,.122037,122463e-9,.0151427,-.00153774,.12214,192706e-9,.0151708,-.0022103,.122237,281219e-9,.0152115,-.00300741,.12238,390804e-9,.0152877,-.00392494,.1227,526317e-9,.015412,-.00496597,.123244,69443e-8,.0156201,-.00613314,.124228,90547e-8,.0159658,-.00744113,.125945,.0011732,.0165674,-.00892546,.129098,.00151888,.017487,-.010627,.133865,.00197007,.018839,-.0126043,.140682,.0025637,.020554,-.0148814,.148534,.00333637,.0226727,-.0175123,.157381,.00433738,.0251879,-.0205266,.166685,.00561664,.0283635,-.0240319,.177796,.00725563,.0318694,-.0279432,.188251,.00928811,.0361044,-.0324313,.200038,.011835,.0406656,-.0373527,.210685,.0149146,.0463846,-.0430132,.224182,.0187254,.0525696,-.0491013,.23634,.0232283,.0598083,-.0559175,.250013,.0286521,.0679437,-.0633657,.263981,.0350634,.0771181,-.0714602,.278072,.0425882,.0881273,-.0803502,.29511,.0514487,.0996628,-.0896903,.309976,.0615766,.112702,-.099644,.325611,.0732139,.126488,-.109829,.339321,.0862324,.142625,-.120859,.35574,.101275,.15953,-.131956,.369845,.117892,.176991,-.143145,.38146,.136205,.199715,-.155292,.40052,.157252,.220787,-.167066,.412055,.179966,.243697,-.178396,.423133,.204418,.272106,-.190433,.439524,.232141,.297637,-.201265,.447041,.261109,.325273,-.211834,.454488,.292627,.357219,-.221889,.465004,.326669,.387362,-.230729,.468527,.362426,.423131,-.23924,.475836,.401533,.45543,-.246067,.475017,.441902,.493393,-.251557,.478017,.484239,.526253,-.255571,.4709,.528586,.560554,-.257752,.463167,.574346,.599306,-.258076,.456452,.621655,.634541,-.256471,.443725,.670492,.668907,-.253283,.428719,.721943,.705619,-.247562,.411348,.772477,.739034,-.240626,.388939,.8264,.771408,-.231493,.36425,.881702,.803312,-.220125,.337321,.9385,.828457,-.206645,.305364,.997437,.854819,-.190664,.273715,1.05693,.878666,-.171429,.242218,1.11251,.898404,-.149235,.209556,1.16398,.917416,-.12435,.176863,1.21014,.933133,-.0972703,.142775,1.25178,.95066,-.0683607,.106735,1.29028,.968589,-.0378724,.0681609,1.32703,.984776,-.00605712,.0273966,1.36158,.99994,.0263276,-.0138124,1.3943,.00867437,-186005e-11,.0928979,1.73682e-7,.00864003,-466389e-10,.0925237,435505e-11,.00864593,-186594e-9,.0925806,174322e-10,.00864095,-419639e-9,.0924903,392862e-10,.00863851,-746272e-9,.0924589,702598e-10,.00868531,-.00116456,.0929,111188e-9,.00869667,-.00167711,.0928529,163867e-9,.00874332,-.00228051,.0930914,23104e-8,.00882709,-.00297864,.0935679,31741e-8,.00898874,-.00377557,.0946165,430186e-9,.00929346,-.00469247,.0967406,580383e-9,.00978271,-.00575491,.100084,783529e-9,.0105746,-.00701514,.105447,.00106304,.0116949,-.00851797,.112494,.00144685,.0130419,-.0102757,.119876,.00196439,.0148375,-.012381,.129034,.00266433,.0168725,-.01482,.137812,.00358364,.0193689,-.0176563,.147696,.00478132,.0222691,-.0209211,.157795,.00631721,.0256891,-.0246655,.168431,.00826346,.0294686,-.0288597,.178587,.0106714,.0340412,-.0336441,.190251,.0136629,.0393918,-.039033,.202999,.0173272,.0453947,-.0450087,.215655,.0217448,.0521936,-.0515461,.228686,.0269941,.0600279,-.058817,.242838,.033272,.0692398,-.0667228,.258145,.0406457,.0793832,-.0752401,.273565,.0492239,.0902297,-.0841851,.287735,.0590105,.102014,-.0936479,.301161,.0702021,.116054,-.103967,.317438,.0832001,.13191,-.114622,.334166,.0977951,.148239,-.125452,.348192,.113985,.165809,-.136453,.361094,.131928,.184616,-.147648,.373534,.151811,.207491,-.159607,.39101,.174476,.230106,-.171119,.402504,.198798,.257036,-.182906,.418032,.225796,.281172,-.193605,.425468,.254027,.312034,-.204771,.440379,.285713,.340402,-.214988,.445406,.319196,.370231,-.224711,.44968,.35537,.407105,-.233516,.460747,.393838,.439037,-.240801,.460624,.433747,.47781,-.24762,.465957,.477234,.510655,-.251823,.460054,.52044,.550584,-.255552,.459172,.567853,.585872,-.257036,.450311,.615943,.620466,-.257535,.437763,.667693,.660496,-.255248,.426639,.718988,.695578,-.251141,.409185,.772503,.732176,-.244718,.39015,.827023,.760782,-.236782,.362594,.885651,.79422,-.225923,.33711,.943756,.824521,-.213855,.308272,1.00874,.854964,-.197723,.278529,1.06764,.878065,-.179209,.246208,1.12836,.899834,-.157569,.21329,1.18318,.918815,-.133206,.181038,1.23161,.934934,-.106545,.146993,1.27644,.952115,-.0780574,.111175,1.31842,.96906,-.0478279,.0728553,1.35839,.985178,-.0160014,.032579,1.39697,1.00039,.0173126,-.0095256,1.43312,.00384146,-124311e-11,.0613583,7.78271e-8,.00390023,-314043e-10,.0622919,196626e-11,.00389971,-125622e-9,.0622632,787379e-11,.00389491,-282352e-9,.0620659,1778e-8,.00391618,-502512e-9,.0624687,320918e-10,.00392662,-784458e-9,.0625113,515573e-10,.00396053,-.00112907,.0628175,778668e-10,.00401911,-.00153821,.0633286,113811e-9,.00414994,-.0020208,.0646443,16445e-8,.00441223,-.00260007,.0673886,237734e-9,.00484427,-.0033097,.0716528,345929e-9,.00549109,-.00418966,.0774998,505987e-9,.00636293,-.00527331,.0844758,739208e-9,.00746566,-.00660428,.0921325,.00107347,.00876625,-.00818826,.0997067,.00153691,.0103125,-.0100811,.107433,.00217153,.0123309,-.0123643,.117088,.00303427,.0146274,-.0150007,.126438,.00416018,.0172295,-.0180531,.135672,.00561513,.0204248,-.0215962,.146244,.007478,.0241597,-.0256234,.157481,.00981046,.0284693,-.0302209,.169125,.0127148,.033445,-.0353333,.181659,.0162453,.0391251,-.0410845,.1944,.0205417,.0454721,-.0473451,.207082,.0256333,.0530983,-.0542858,.221656,.0317036,.0615356,-.0618384,.236036,.0388319,.0703363,-.0697631,.248398,.046974,.0810391,-.0784757,.263611,.0565246,.0920144,-.0873488,.275857,.0671724,.105584,-.0973652,.292555,.0798105,.119506,-.107271,.306333,.0935945,.134434,-.117608,.318888,.109106,.153399,-.128938,.337552,.127074,.171258,-.139944,.349955,.14643,.191059,-.151288,.361545,.168,.215069,-.163018,.378421,.192082,.237838,-.174226,.38879,.217838,.266965,-.186063,.405857,.246931,.292827,-.196909,.414146,.277505,.324352,-.207473,.426955,.310711,.354427,-.217713,.433429,.346794,.389854,-.227183,.443966,.385237,.420749,-.235131,.44471,.424955,.459597,-.242786,.451729,.468446,.495316,-.248767,.45072,.513422,.534903,-.253351,.450924,.560618,.572369,-.256277,.445266,.609677,.612383,-.2576,.438798,.660995,.644037,-.256931,.421693,.713807,.686749,-.254036,.4109,.767616,.719814,-.249785,.390151,.82533,.754719,-.244283,.367847,.888311,.792022,-.235076,.345013,.948177,.822404,-.225061,.316193,1.01661,.853084,-.211113,.287013,1.08075,.879871,-.19449,.255424,1.14501,.901655,-.174023,.222879,1.20203,.919957,-.1509,.18989,1.25698,.938412,-.124923,.15606,1.30588,.953471,-.0968139,.120512,1.3529,.970451,-.066734,.0828515,1.3986,.985522,-.034734,.0424458,1.44148,1.00099,-.00102222,678929e-9,1.48398,965494e-9,-6.27338e-7,.0306409,1.97672e-8,99168e-8,-158573e-10,.0314638,4.99803e-7,991068e-9,-634012e-10,.031363,200682e-11,974567e-9,-14144e-8,.03036,457312e-11,998079e-9,-252812e-9,.031496,860131e-11,.00102243,-396506e-9,.0319955,148288e-10,.00107877,-577593e-9,.0331376,249141e-10,.00121622,-816816e-9,.0359396,423011e-10,.0014455,-.00113761,.0399652,724613e-10,.00178791,-.00156959,.0450556,123929e-9,.00225668,-.00214064,.0508025,208531e-9,.00285627,-.00287655,.0568443,341969e-9,.0035991,-.00380271,.0630892,544158e-9,.00455524,-.00496264,.0702204,842423e-9,.00569143,-.0063793,.0773426,.00126704,.00716928,-.00813531,.0860839,.00186642,.00885307,-.0101946,.0944079,.00267014,.0109316,-.0126386,.103951,.00374033,.0133704,-.0154876,.113786,.0051304,.0161525,-.0187317,.123477,.00688858,.0194267,-.0224652,.133986,.00910557,.0230967,-.0265976,.143979,.0118074,.0273627,-.0312848,.154645,.0151266,.0323898,-.0365949,.166765,.0191791,.0379225,-.0422914,.177932,.0239236,.0447501,-.0487469,.19167,.0296568,.0519391,-.0556398,.203224,.0362924,.0599464,-.0631646,.215652,.0440585,.0702427,-.0714308,.232089,.0531619,.0806902,-.0800605,.245258,.0634564,.0923194,-.0892815,.258609,.0752481,.106938,-.09931,.276654,.0888914,.121238,-.109575,.289847,.104055,.138817,-.120461,.307566,.121266,.15595,-.131209,.320117,.139944,.178418,-.143049,.339677,.161591,.197875,-.154074,.349886,.184303,.224368,-.166307,.369352,.210669,.252213,-.178051,.386242,.238895,.277321,-.189335,.395294,.269182,.310332,-.200683,.412148,.302508,.338809,-.210856,.418266,.337264,.372678,-.220655,.428723,.374881,.405632,-.230053,.433887,.415656,.442293,-.237993,.439911,.457982,.477256,-.244897,.440175,.502831,.515592,-.250657,.441079,.550277,.550969,-.255459,.435219,.601102,.592883,-.257696,.432882,.651785,.629092,-.259894,.421054,.708961,.672033,-.258592,.41177,.763806,.709147,-.256525,.395267,.824249,.745367,-.254677,.375013,.8951,.784715,-.247892,.353906,.959317,.818107,-.240162,.327801,1.03153,.847895,-.229741,.298821,1.10601,.879603,-.213084,.269115,1.164,.902605,-.195242,.236606,1.22854,.922788,-.174505,.203442,1.29017,.944831,-.150169,.169594,1.34157,.959656,-.124099,.135909,1.3956,.972399,-.0960626,.0990563,1.45128,.986549,-.0657097,.0602348,1.50312,1.00013,-.0333558,.0186694,1.55364,619747e-11,-1e-7,.00778326,796756e-16,2.37499e-8,-9.99999e-8,282592e-10,114596e-15,100292e-11,-166369e-11,250354e-9,6.77492e-9,350752e-11,-637769e-11,357289e-9,6.31655e-8,826445e-11,-174689e-10,516179e-9,3.1851e-7,242481e-10,-450868e-10,.0010223,130577e-11,455631e-10,-89044e-9,.00144302,374587e-11,971222e-10,-178311e-9,.00241912,102584e-10,171403e-9,-313976e-9,.00354938,236481e-10,292747e-9,-520026e-9,.00513765,496014e-10,789827e-9,-.00118187,.0238621,139056e-9,.00114093,-.00171827,.0286691,244093e-9,.00176119,-.00249667,.0368565,420623e-9,.0022233,-.00333742,.0400469,65673e-8,.00343382,-.00481976,.0535751,.00109323,.00427602,-.00600755,.057099,.00155268,.00461435,-.00737637,.0551084,.00215031,.00695698,-.00971401,.0715767,.00316529,.00867619,-.0120943,.0793314,.00436995,.0106694,-.0148202,.0869391,.0058959,.0140351,-.0183501,.101572,.00798757,.0168939,-.022006,.11018,.0104233,.020197,-.0261568,.119041,.0134167,.0254702,-.0312778,.135404,.0173009,.0298384,-.0362469,.1437,.0215428,.035159,-.042237,.15512,.0268882,.0427685,-.0488711,.17128,.033235,.0494848,-.0557997,.181813,.0404443,.0592394,-.0635578,.198745,.0490043,.0681463,-.071838,.210497,.0588239,.0804753,-.0809297,.228864,.0702835,.0942205,-.0906488,.247008,.0834012,.106777,-.100216,.258812,.0975952,.124471,-.110827,.278617,.114162,.138389,-.121193,.287049,.131983,.159543,-.13253,.307151,.152541,.176432,-.143611,.31564,.174673,.201723,-.15548,.33538,.199842,.229721,-.167166,.355256,.227097,.250206,-.178238,.360047,.256014,.282118,-.189905,.378761,.28855,.312821,-.201033,.39181,.323348,.341482,-.211584,.397716,.360564,.377368,-.221314,.410141,.400004,.418229,-.230474,.423485,.442371,.444881,-.239443,.418874,.488796,.488899,-.245987,.427545,.535012,.520317,-.253948,.422147,.589678,.568566,-.256616,.42719,.637683,.599607,-.26376,.415114,.703363,.64222,-.268687,.408715,.771363,.685698,-.2694,.399722,.83574,.732327,-.266642,.388651,.897764,.769873,-.267712,.369198,.983312,.806733,-.263479,.346802,1.06222,.843466,-.254575,.321368,1.13477,.873008,-.242749,.29211,1.20712,.908438,-.22725,.262143,1.27465,.936321,-.207621,.228876,1.33203,.950353,-.187932,.19484,1.40439,.96442,-.165154,.163178,1.4732,.979856,-.139302,.127531,1.53574,.982561,-.11134,.0903457,1.59982,.996389,-.0808124,.0489007,1.6577],t=[1,0,0,0,1,791421e-36,0,0,1,104392e-29,0,0,1,349405e-26,0,0,1,109923e-23,0,0,1,947414e-22,0,0,1,359627e-20,0,0,1,772053e-19,0,0,1,108799e-17,0,0,1,110655e-16,0,0,1,865818e-16,0,0,.999998,545037e-15,0,0,.999994,2.85095e-9,0,0,.999989,1.26931e-8,0,0,.999973,4.89938e-8,0,0,.999947,1.66347e-7,0,0,.999894,5.02694e-7,0,0,.999798,136532e-11,0,0,.999617,335898e-11,0,0,.999234,752126e-11,0,0,.998258,152586e-10,0,0,.99504,266207e-10,0,0,.980816,236802e-10,0,0,.967553,207684e-11,0,0,.966877,403733e-11,0,0,.965752,741174e-11,0,0,.96382,127746e-10,0,0,.960306,202792e-10,0,0,.953619,280232e-10,0,0,.941103,278816e-10,0,0,.926619,160221e-10,0,0,.920983,235164e-10,0,0,.912293,311924e-10,0,.0158731,.899277,348118e-10,0,.0476191,.880884,26041e-9,0,.0793651,.870399,338726e-10,0,.111111,.856138,392906e-10,0,.142857,.837436,372874e-10,0,.174603,.820973,392558e-10,0,.206349,.803583,434658e-10,0,.238095,.782168,40256e-9,0,.269841,.764107,448159e-10,0,.301587,.743092,457627e-10,0,.333333,.721626,455314e-10,0,.365079,.700375,477335e-10,0,.396825,.677334,461072e-10,0,.428571,.655702,484393e-10,0,.460317,.632059,464583e-10,0,.492064,.610125,483923e-10,0,.52381,.58653,464342e-10,0,.555556,.564508,477033e-10,0,.587302,.541405,459263e-10,0,.619048,.519556,46412e-9,0,.650794,.497292,448913e-10,0,.68254,.475898,445789e-10,0,.714286,.454722,433496e-10,0,.746032,.434042,423054e-10,0,.777778,.414126,413737e-10,0,.809524,.394387,397265e-10,0,.84127,.375841,390709e-10,0,.873016,.357219,369938e-10,0,.904762,.340084,365618e-10,0,.936508,.322714,342533e-10,0,.968254,.306974,339596e-10,0,1,1,101524e-23,0,0,1,10292e-22,0,0,1,130908e-23,0,0,1,473331e-23,0,0,1,625319e-22,0,0,1,107932e-20,0,0,1,163779e-19,0,0,1,203198e-18,0,0,1,204717e-17,0,0,.999999,168995e-16,0,0,.999998,115855e-15,0,0,.999996,66947e-14,0,0,.999991,3.30863e-9,0,0,.999983,1.41737e-8,0,0,.999968,5.32626e-8,0,0,.99994,1.77431e-7,0,0,.999891,5.28835e-7,0,0,.999797,142169e-11,0,0,.999617,347057e-11,0,0,.999227,77231e-10,0,0,.998239,155753e-10,0,0,.994937,268495e-10,0,0,.980225,213742e-10,0,0,.967549,21631e-10,0,0,.966865,417989e-11,0,0,.965739,763341e-11,0,0,.963794,130892e-10,0,0,.960244,206456e-10,0,0,.953495,282016e-10,0,148105e-9,.940876,271581e-10,0,.002454,.926569,164159e-10,0,.00867491,.920905,239521e-10,0,.01956,.912169,315127e-10,0,.035433,.899095,346626e-10,0,.056294,.882209,290223e-10,0,.0818191,.870272,342992e-10,0,.111259,.855977,394164e-10,0,.142857,.837431,372343e-10,0,.174603,.820826,396691e-10,0,.206349,.803408,435395e-10,0,.238095,.782838,419579e-10,0,.269841,.763941,450953e-10,0,.301587,.742904,455847e-10,0,.333333,.721463,458833e-10,0,.365079,.700197,477159e-10,0,.396825,.677501,470641e-10,0,.428571,.655527,484732e-10,0,.460317,.6324,476834e-10,0,.492064,.609964,484213e-10,0,.52381,.586839,475541e-10,0,.555556,.564353,476951e-10,0,.587302,.541589,467611e-10,0,.619048,.519413,463493e-10,0,.650794,.497337,453994e-10,0,.68254,.475797,445308e-10,0,.714286,.454659,435787e-10,0,.746032,.434065,424839e-10,0,.777778,.414018,41436e-9,0,.809524,.39455,401902e-10,0,.84127,.375742,390813e-10,0,.873016,.357501,377116e-10,0,.904762,.339996,36535e-9,0,.936508,.323069,351265e-10,0,.968254,.306897,339112e-10,0,1,1,10396e-19,0,0,1,104326e-20,0,0,1,110153e-20,0,0,1,144668e-20,0,0,1,34528e-19,0,0,1,175958e-19,0,0,1,12627e-17,0,0,1,936074e-18,0,0,1,645742e-17,0,0,.999998,401228e-16,0,0,.999997,222338e-15,0,0,.999995,1.0967e-9,0,0,.999991,4.82132e-9,0,0,.999981,1.89434e-8,0,0,.999967,6.67716e-8,0,0,.999938,2.12066e-7,0,0,.999886,6.0977e-7,0,0,.999792,159504e-11,0,0,.999608,381191e-11,0,0,.999209,833727e-11,0,0,.998179,165288e-10,0,0,.994605,274387e-10,0,0,.979468,167316e-10,0,0,.967529,242877e-11,0,0,.966836,461696e-11,0,0,.96569,830977e-11,0,0,.963706,140427e-10,0,244659e-11,.960063,217353e-10,0,760774e-9,.953113,286606e-10,0,.00367261,.940192,247691e-10,0,.00940263,.927731,195814e-10,0,.018333,.920669,252531e-10,0,.0306825,.911799,324277e-10,0,.0465556,.89857,340982e-10,0,.0659521,.883283,319622e-10,0,.0887677,.86989,35548e-9,0,.114784,.855483,397143e-10,0,.143618,.837987,391665e-10,0,.174606,.820546,411306e-10,0,.206349,.802878,436753e-10,0,.238095,.783402,444e-7,0,.269841,.763439,458726e-10,0,.301587,.742925,467097e-10,0,.333333,.721633,478887e-10,0,.365079,.69985,481251e-10,0,.396825,.67783,491811e-10,0,.428571,.655126,488199e-10,0,.460318,.632697,496025e-10,0,.492064,.609613,48829e-9,0,.52381,.587098,492754e-10,0,.555556,.564119,482625e-10,0,.587302,.541813,482807e-10,0,.619048,.519342,471552e-10,0,.650794,.497514,466765e-10,0,.68254,.475879,455582e-10,0,.714286,.454789,446007e-10,0,.746032,.434217,435382e-10,0,.777778,.414086,421753e-10,0,.809524,.394744,412093e-10,0,.84127,.375782,396634e-10,0,.873016,.357707,386419e-10,0,.904762,.340038,370345e-10,0,.936508,.323284,359725e-10,0,.968254,.306954,3436e-8,0,1,1,599567e-19,0,0,1,600497e-19,0,0,1,614839e-19,0,0,1,686641e-19,0,0,1,972658e-19,0,0,1,221271e-18,0,0,1,833195e-18,0,0,1,403601e-17,0,0,.999999,206001e-16,0,0,.999998,101739e-15,0,0,.999997,470132e-15,0,0,.999993,2.00436e-9,0,0,.999988,7.83682e-9,0,0,.999979,2.80338e-8,0,0,.999962,9.17033e-8,0,0,.999933,2.74514e-7,0,0,.999881,7.53201e-7,0,0,.999783,189826e-11,0,0,.999594,440279e-11,0,0,.999178,93898e-10,0,0,.998073,181265e-10,0,0,.993993,280487e-10,0,0,.979982,149422e-10,0,0,.968145,378481e-11,0,0,.966786,53771e-10,0,0,.965611,947508e-11,0,388934e-10,.963557,156616e-10,0,9693e-7,.959752,235144e-10,0,.00370329,.952461,291568e-10,0,.00868428,.940193,240102e-10,0,.0161889,.929042,231235e-10,0,.0263948,.920266,273968e-10,0,.0394088,.911178,337915e-10,0,.0552818,.897873,333629e-10,0,.0740138,.884053,351405e-10,0,.0955539,.869455,378034e-10,0,.119795,.854655,399378e-10,0,.14656,.838347,419108e-10,0,.175573,.820693,440831e-10,0,.206388,.802277,445599e-10,0,.238095,.783634,472691e-10,0,.269841,.763159,476984e-10,0,.301587,.742914,491487e-10,0,.333333,.721662,502312e-10,0,.365079,.699668,502817e-10,0,.396825,.677839,51406e-9,0,.428571,.655091,511095e-10,0,.460317,.632665,516067e-10,0,.492064,.609734,512255e-10,0,.52381,.587043,510263e-10,0,.555556,.564298,50565e-9,0,.587302,.541769,497951e-10,0,.619048,.519529,492698e-10,0,.650794,.497574,482066e-10,0,.68254,.476028,473689e-10,0,.714286,.454961,461941e-10,0,.746032,.434341,450618e-10,0,.777778,.414364,438355e-10,0,.809524,.394832,424196e-10,0,.84127,.376109,412563e-10,0,.873016,.35779,396226e-10,0,.904762,.340379,384886e-10,0,.936508,.323385,368214e-10,0,.968254,.307295,356636e-10,0,1,1,106465e-17,0,0,1,106555e-17,0,0,1,107966e-17,0,0,1,114601e-17,0,0,1,137123e-17,0,0,1,21243e-16,0,0,.999999,489653e-17,0,0,.999999,160283e-16,0,0,.999998,62269e-15,0,0,.999997,251859e-15,0,0,.999996,996192e-15,0,0,.999992,3.74531e-9,0,0,.999986,1.32022e-8,0,0,.999975,4.33315e-8,0,0,.999959,1.31956e-7,0,0,.999927,3.72249e-7,0,0,.999871,9.72461e-7,0,0,.999771,235343e-11,0,0,.999572,52768e-10,0,0,.999133,109237e-10,0,0,.997912,203675e-10,0,0,.993008,279396e-10,0,0,.980645,139604e-10,0,0,.970057,646596e-11,0,0,.966717,65089e-10,0,474145e-10,.965497,111863e-10,0,89544e-8,.96334,179857e-10,0,.0032647,.959294,259045e-10,0,.0075144,.951519,292327e-10,0,.0138734,.940517,249769e-10,0,.0224952,.93014,26803e-9,0,.0334828,.91972,303656e-10,0,.0468973,.910294,353323e-10,0,.0627703,.897701,351002e-10,0,.0811019,.884522,388104e-10,0,.10186,.869489,412932e-10,0,.124985,.853983,415781e-10,0,.150372,.838425,454066e-10,0,.177868,.820656,471624e-10,0,.207245,.801875,475243e-10,0,.238143,.783521,505621e-10,0,.269841,.763131,50721e-9,0,.301587,.74261,523293e-10,0,.333333,.72148,528699e-10,0,.365079,.699696,538677e-10,0,.396825,.677592,539255e-10,0,.428571,.65525,546367e-10,0,.460317,.632452,541348e-10,0,.492064,.609903,544976e-10,0,.52381,.586928,536201e-10,0,.555556,.564464,535185e-10,0,.587302,.541801,524949e-10,0,.619048,.519681,51812e-9,0,.650794,.497685,507687e-10,0,.68254,.47622,496243e-10,0,.714286,.455135,485714e-10,0,.746032,.4346,471847e-10,0,.777778,.414564,459294e-10,0,.809524,.395165,444705e-10,0,.84127,.376333,430772e-10,0,.873016,.358197,416229e-10,0,.904762,.34064,401019e-10,0,.936508,.323816,386623e-10,0,.968254,.307581,370933e-10,0,1,1,991541e-17,0,0,1,992077e-17,0,0,1,100041e-16,0,0,1,10385e-15,0,0,1,115777e-16,0,0,1,150215e-16,0,0,.999999,254738e-16,0,0,.999999,598822e-16,0,0,.999998,179597e-15,0,0,.999997,602367e-15,0,0,.999994,2.06835e-9,0,0,.99999,6.94952e-9,0,0,.999984,2.23363e-8,0,0,.999972,6.78578e-8,0,0,.999952,1.93571e-7,0,0,.999919,5.16594e-7,0,0,.99986,128739e-11,0,0,.999753,299298e-11,0,0,.999546,648258e-11,0,0,.999074,129985e-10,0,0,.997671,232176e-10,0,0,.991504,256701e-10,0,0,.981148,131141e-10,0,0,.971965,869048e-11,0,280182e-10,.966624,808301e-11,0,695475e-9,.965344,135235e-10,0,.00265522,.963048,210592e-10,0,.00622975,.958673,287473e-10,0,.0116234,.950262,281379e-10,0,.018976,.940836,271089e-10,0,.0283844,.930996,30926e-9,0,.0399151,.919848,348359e-10,0,.0536063,.909136,366092e-10,0,.0694793,.897554,384162e-10,0,.0875342,.884691,430971e-10,0,.107749,.869414,447803e-10,0,.130087,.853462,452858e-10,0,.154481,.838187,495769e-10,0,.180833,.820381,502709e-10,0,.209005,.801844,522713e-10,0,.238791,.783061,541505e-10,0,.269869,.763205,553712e-10,0,.301587,.742362,564909e-10,0,.333333,.721393,572646e-10,0,.365079,.699676,581012e-10,0,.396825,.677395,58096e-9,0,.428571,.655208,585766e-10,0,.460317,.632451,583602e-10,0,.492064,.609839,580234e-10,0,.52381,.587093,577161e-10,0,.555556,.564467,568447e-10,0,.587302,.542043,563166e-10,0,.619048,.519826,55156e-9,0,.650794,.497952,541682e-10,0,.68254,.476477,528971e-10,0,.714286,.455412,514952e-10,0,.746032,.434926,502222e-10,0,.777778,.4149,485779e-10,0,.809524,.395552,472242e-10,0,.84127,.376712,454891e-10,0,.873016,.358622,440924e-10,0,.904762,.341048,422984e-10,0,.936508,.324262,408582e-10,0,.968254,.308013,390839e-10,0,1,1,613913e-16,0,0,1,614145e-16,0,0,1,617708e-16,0,0,1,633717e-16,0,0,1,681648e-16,0,0,1,808291e-16,0,0,1,114608e-15,0,0,.999998,210507e-15,0,0,.999997,499595e-15,0,0,.999995,1.39897e-9,0,0,.999994,4.19818e-9,0,0,.999988,1.27042e-8,0,0,.999979,3.75153e-8,0,0,.999965,1.06206e-7,0,0,.999945,2.85381e-7,0,0,.999908,7.23611e-7,0,0,.999846,17255e-10,0,0,.999733,386104e-11,0,0,.999511,808493e-11,0,0,.998993,156884e-10,0,0,.997326,265538e-10,0,0,.989706,206466e-10,0,0,.981713,130756e-10,0,70005e-10,.973636,106473e-10,0,464797e-9,.966509,10194e-9,0,.00201743,.965149,165881e-10,0,.00497549,.962669,249147e-10,0,.00953262,.95786,317449e-10,0,.0158211,.949334,281045e-10,0,.0239343,.941041,303263e-10,0,.0339372,.931575,356754e-10,0,.0458738,.920102,397075e-10,0,.059772,.908002,384886e-10,0,.075645,.897269,43027e-9,0,.0934929,.884559,479925e-10,0,.113302,.869161,48246e-9,0,.135045,.853342,509505e-10,0,.158678,.837633,542846e-10,0,.184136,.820252,554139e-10,0,.211325,.801872,581412e-10,0,.240113,.782418,585535e-10,0,.270306,.7631,610923e-10,0,.301594,.742183,613678e-10,0,.333333,.721098,627275e-10,0,.365079,.699512,629413e-10,0,.396825,.677372,636351e-10,0,.428571,.655059,633555e-10,0,.460317,.632567,636513e-10,0,.492064,.609784,628965e-10,0,.52381,.587237,625546e-10,0,.555556,.564525,615825e-10,0,.587302,.542181,605048e-10,0,.619048,.520017,596329e-10,0,.650794,.498204,581516e-10,0,.68254,.476742,569186e-10,0,.714286,.455803,553833e-10,0,.746032,.435251,537807e-10,0,.777778,.415374,522025e-10,0,.809524,.395921,503421e-10,0,.84127,.377253,488211e-10,0,.873016,.359021,468234e-10,0,.904762,.341637,453269e-10,0,.936508,.3247,433014e-10,0,.968254,.308625,418007e-10,0,1,1,286798e-15,0,0,1,286877e-15,0,0,1,288094e-15,0,0,1,293506e-15,0,0,1,309262e-15,0,0,.999999,348593e-15,0,0,.999999,444582e-15,0,0,.999998,688591e-15,0,0,.999996,1.34391e-9,0,0,.999993,3.17438e-9,0,0,.999989,8.35609e-9,0,0,.999983,2.28677e-8,0,0,.999974,6.23361e-8,0,0,.999959,1.65225e-7,0,0,.999936,4.19983e-7,0,0,.999896,101546e-11,0,0,.99983,232376e-11,0,0,.999709,50156e-10,0,0,.999469,10167e-9,0,0,.998886,190775e-10,0,0,.996819,300511e-10,0,0,.988837,185092e-10,0,1.68222e-7,.982178,134622e-10,0,259622e-9,.975017,125961e-10,0,.00142595,.967101,13507e-9,0,.00382273,.964905,205003e-10,0,.00764164,.96218,29546e-9,0,.0130121,.956821,343738e-10,0,.0200253,.948829,305063e-10,0,.0287452,.941092,346487e-10,0,.039218,.931883,412061e-10,0,.0514748,.920211,444651e-10,0,.0655351,.907307,431252e-10,0,.0814082,.89684,490382e-10,0,.0990939,.884119,53334e-9,0,.118583,.869148,54114e-9,0,.139856,.853377,578536e-10,0,.162882,.836753,592285e-10,0,.187615,.820063,622787e-10,0,.213991,.801694,645492e-10,0,.241918,.782116,65353e-9,0,.271267,.762673,674344e-10,0,.301847,.742133,682788e-10,0,.333333,.720779,691959e-10,0,.365079,.699386,696817e-10,0,.396826,.67732,699583e-10,0,.428572,.654888,698447e-10,0,.460318,.632499,694063e-10,0,.492064,.609825,691612e-10,0,.52381,.587287,681576e-10,0,.555556,.564743,674138e-10,0,.587302,.542409,661617e-10,0,.619048,.520282,647785e-10,0,.650794,.498506,633836e-10,0,.68254,.477102,615905e-10,0,.714286,.456167,601013e-10,0,.746032,.435728,581457e-10,0,.777778,.415809,564215e-10,0,.809524,.396517,544997e-10,0,.84127,.377737,525061e-10,0,.873016,.359698,506831e-10,0,.904762,.342164,48568e-9,0,.936508,.325417,467826e-10,0,.968254,.309186,446736e-10,0,1,1,1.09018e-9,0,0,1,1.0904e-9,0,0,1,1.09393e-9,0,0,1,1.1095e-9,0,0,1,1.154e-9,0,0,1,1.26089e-9,0,0,.999999,1.5059e-9,0,0,.999997,2.07899e-9,0,0,.999994,3.48164e-9,0,0,.999993,7.05728e-9,0,0,.999987,1.63692e-8,0,0,.999981,4.06033e-8,0,0,.999969,1.0245e-7,0,0,.999953,2.55023e-7,0,0,.999925,6.1511e-7,0,0,.999881,142218e-11,0,0,.99981,313086e-11,0,0,.99968,653119e-11,0,0,.999418,12832e-9,0,0,.998748,232497e-10,0,0,.996066,329522e-10,0,0,.988379,179613e-10,0,108799e-9,.982567,143715e-10,0,921302e-9,.976097,148096e-10,0,.00280738,.968475,178905e-10,0,.00596622,.964606,253921e-10,0,.0105284,.961564,348623e-10,0,.0165848,.955517,357612e-10,0,.0242,.948381,343493e-10,0,.03342,.941095,405849e-10,0,.0442777,.931923,475394e-10,0,.0567958,.91996,484328e-10,0,.0709879,.907419,502146e-10,0,.086861,.89618,561654e-10,0,.104415,.88337,587612e-10,0,.123643,.869046,618057e-10,0,.144531,.853278,657392e-10,0,.167057,.836091,66303e-9,0,.191188,.819644,704445e-10,0,.216878,.801246,714071e-10,0,.244062,.782031,740093e-10,0,.272649,.762066,74685e-9,0,.302509,.741964,766647e-10,0,.333442,.720554,766328e-10,0,.365079,.699098,777857e-10,0,.396826,.677189,774633e-10,0,.428572,.65484,776235e-10,0,.460318,.632496,770316e-10,0,.492064,.609908,762669e-10,0,.52381,.587312,753972e-10,0,.555556,.564938,739994e-10,0,.587302,.542577,728382e-10,0,.619048,.52062,71112e-9,0,.650794,.498819,694004e-10,0,.68254,.477555,675575e-10,0,.714286,.456568,653449e-10,0,.746032,.436278,636068e-10,0,.777778,.41637,613466e-10,0,.809524,.397144,594177e-10,0,.84127,.378412,570987e-10,0,.873016,.360376,550419e-10,0,.904762,.342906,527422e-10,0,.936508,.326136,506544e-10,0,.968254,.30997,484307e-10,0,1,1,3.54014e-9,0,0,1,3.54073e-9,0,0,1,3.54972e-9,0,0,1,3.58929e-9,0,0,1,3.70093e-9,0,0,.999999,3.96194e-9,0,0,.999998,4.53352e-9,0,0,.999997,5.78828e-9,0,0,.999994,8.63812e-9,0,0,.999991,1.53622e-8,0,0,.999985,3.16356e-8,0,0,.999977,7.12781e-8,0,0,.999964,1.66725e-7,0,0,.999945,3.90501e-7,0,0,.999912,8.95622e-7,0,0,.999866,198428e-11,0,0,.999786,421038e-11,0,0,.999647,850239e-11,0,0,.999356,162059e-10,0,0,.998563,282652e-10,0,0,.994928,336309e-10,0,244244e-10,.987999,178458e-10,0,523891e-9,.982893,159162e-10,0,.00194729,.977044,178056e-10,0,.00451099,.969972,230624e-10,0,.00835132,.964237,313922e-10,0,.013561,.960791,406145e-10,0,.0202056,.954292,372796e-10,0,.0283321,.948052,403199e-10,0,.0379739,.940938,479537e-10,0,.0491551,.931689,545292e-10,0,.0618918,.91987,54038e-9,0,.0761941,.907665,589909e-10,0,.0920672,.895281,642651e-10,0,.109511,.882621,659707e-10,0,.12852,.86873,709973e-10,0,.149085,.853008,742221e-10,0,.171189,.835944,761754e-10,0,.194809,.818949,797052e-10,0,.21991,.800951,812434e-10,0,.246447,.781847,838075e-10,0,.274352,.761649,84501e-9,0,.303535,.74152,860258e-10,0,.333857,.720495,866233e-10,0,.365104,.698742,868326e-10,0,.396826,.677096,87133e-9,0,.428572,.654782,863497e-10,0,.460318,.632335,860206e-10,0,.492064,.610031,849337e-10,0,.52381,.587457,838279e-10,0,.555556,.56513,82309e-9,0,.587302,.542877,803542e-10,0,.619048,.5209,786928e-10,0,.650794,.499291,765171e-10,0,.68254,.477971,744753e-10,0,.714286,.457221,72209e-9,0,.746032,.436803,697448e-10,0,.777778,.417083,675333e-10,0,.809524,.397749,648058e-10,0,.84127,.379177,625759e-10,0,.873016,.361061,598584e-10,0,.904762,.343713,575797e-10,0,.936508,.326894,549999e-10,0,.968254,.310816,527482e-10,0,1,1,1.0153e-8,0,0,1,1.01544e-8,0,0,1,1.01751e-8,0,0,1,1.02662e-8,0,0,1,1.0521e-8,0,0,.999999,1.11049e-8,0,0,.999999,1.23408e-8,0,0,.999996,1.4924e-8,0,0,.999992,2.04471e-8,0,0,.999989,3.26539e-8,0,0,.99998,6.03559e-8,0,0,.999971,1.23936e-7,0,0,.999955,2.69058e-7,0,0,.999933,5.93604e-7,0,0,.999901,129633e-11,0,0,.999847,275621e-11,0,0,.999761,564494e-11,0,0,.999607,110485e-10,0,0,.999282,204388e-10,0,0,.99831,341084e-10,0,2.2038e-7,.993288,294949e-10,0,242388e-9,.987855,192736e-10,0,.0012503,.983167,182383e-10,0,.0032745,.977908,218633e-10,0,.00646321,.971194,290662e-10,0,.0109133,.963867,386401e-10,0,.0166927,.95982,462827e-10,0,.0238494,.953497,420705e-10,0,.0324178,.947621,477743e-10,0,.0424225,.940611,568258e-10,0,.0538808,.931174,618061e-10,0,.0668047,.919919,627098e-10,0,.0812014,.907856,694714e-10,0,.0970745,.894509,735008e-10,0,.114424,.881954,763369e-10,0,.133246,.868309,821896e-10,0,.153534,.852511,83769e-9,0,.175275,.835821,881615e-10,0,.198453,.817981,896368e-10,0,.223042,.800504,930906e-10,0,.249009,.78141,945056e-10,0,.276304,.761427,963605e-10,0,.304862,.74094,968088e-10,0,.334584,.720233,981481e-10,0,.365322,.698592,979122e-10,0,.396826,.676763,981057e-10,0,.428571,.654808,973956e-10,0,.460318,.632326,962619e-10,0,.492064,.610049,952996e-10,0,.52381,.58763,933334e-10,0,.555556,.565261,917573e-10,0,.587302,.543244,896636e-10,0,.619048,.521273,873304e-10,0,.650794,.499818,852648e-10,0,.68254,.478536,823961e-10,0,.714286,.457826,79939e-9,0,.746032,.437549,77126e-9,0,.777778,.41776,743043e-10,0,.809524,.39863,716426e-10,0,.84127,.379954,686456e-10,0,.873016,.362025,660514e-10,0,.904762,.344581,630755e-10,0,.936508,.327909,605439e-10,0,.968254,.311736,576345e-10,0,1,1,2.63344e-8,0,0,1,2.63373e-8,0,0,1,2.63815e-8,0,0,1,2.65753e-8,0,0,1,2.71132e-8,0,0,.999999,2.83279e-8,0,0,.999997,3.0833e-8,0,0,.999995,3.58711e-8,0,0,.999992,4.61266e-8,0,0,.999985,6.7574e-8,0,0,.999977,1.1358e-7,0,0,.999966,2.13657e-7,0,0,.999948,4.31151e-7,0,0,.999923,8.96656e-7,0,0,.999884,186603e-11,0,0,.999826,381115e-11,0,0,.999732,754184e-11,0,0,.999561,143192e-10,0,0,.999191,257061e-10,0,0,.997955,405724e-10,0,744132e-10,.992228,276537e-10,0,716477e-9,.987638,208885e-10,0,.0022524,.983395,215226e-10,0,.00484816,.978614,270795e-10,0,.00860962,.972389,365282e-10,0,.0136083,.964392,474747e-10,0,.0198941,.95861,509141e-10,0,.0275023,.952806,48963e-9,0,.0364584,.94712,571119e-10,0,.04678,.940104,671704e-10,0,.0584799,.930398,687586e-10,0,.0715665,.919866,738161e-10,0,.086045,.907853,813235e-10,0,.101918,.894078,834582e-10,0,.119186,.881177,892093e-10,0,.137845,.867575,944548e-10,0,.157891,.852107,969607e-10,0,.179316,.835502,101456e-9,0,.202106,.81756,103256e-9,0,.226243,.79984,106954e-9,0,.251704,.780998,108066e-9,0,.278451,.761132,110111e-9,0,.306436,.740429,110459e-9,0,.335586,.719836,111219e-9,0,.365796,.698467,11145e-8,0,.3969,.676446,110393e-9,0,.428571,.654635,110035e-9,0,.460318,.632411,108548e-9,0,.492064,.609986,106963e-9,0,.52381,.587872,105238e-9,0,.555556,.565528,102665e-9,0,.587302,.543563,100543e-9,0,.619048,.52176,976182e-10,0,.650794,.500188,947099e-10,0,.68254,.479204,919929e-10,0,.714286,.458413,886139e-10,0,.746032,.438314,857839e-10,0,.777778,.418573,82411e-9,0,.809524,.39947,792211e-10,0,.84127,.380892,759546e-10,0,.873016,.362953,727571e-10,0,.904762,.345601,695738e-10,0,.936508,.328895,664907e-10,0,.968254,.312808,634277e-10,0,1,1,6.28647e-8,0,0,1,6.28705e-8,0,0,1,6.29587e-8,0,0,1,6.33441e-8,0,0,.999999,6.44087e-8,0,0,.999998,6.67856e-8,0,0,.999997,7.15889e-8,0,0,.999995,8.09577e-8,0,0,.999989,9.92764e-8,0,0,.999983,1.35834e-7,0,0,.999974,2.10482e-7,0,0,.999959,3.65215e-7,0,0,.999939,6.86693e-7,0,0,.999911,13472e-10,0,0,.999868,26731e-10,0,0,.999804,524756e-11,0,0,.9997,100403e-10,0,0,.99951,185019e-10,0,0,.999078,322036e-10,0,620676e-11,.997428,470002e-10,0,341552e-9,.99162,287123e-10,0,.00143727,.987479,234706e-10,0,.00349201,.983582,260083e-10,0,.0066242,.979186,337927e-10,0,.0109113,.97325,454689e-10,0,.0164064,.965221,573759e-10,0,.0231463,.957262,544114e-10,0,.0311571,.952211,587006e-10,0,.0404572,.946631,692256e-10,0,.0510592,.939391,787819e-10,0,.0629723,.929795,792368e-10,0,.0762025,.91965,875075e-10,0,.090753,.907737,950903e-10,0,.106626,.893899,972963e-10,0,.123822,.880239,10459e-8,0,.142337,.866562,107689e-9,0,.16217,.85164,113081e-9,0,.183314,.835021,116636e-9,0,.20576,.817311,120074e-9,0,.229496,.798845,121921e-9,0,.254502,.780479,12475e-8,0,.280753,.760694,125255e-9,0,.308212,.740142,126719e-9,0,.336825,.719248,12636e-8,0,.366517,.698209,126712e-9,0,.397167,.676398,125769e-9,0,.428578,.654378,124432e-9,0,.460318,.632484,123272e-9,0,.492064,.610113,12085e-8,0,.52381,.587931,118411e-9,0,.555556,.565872,11569e-8,0,.587302,.543814,112521e-9,0,.619048,.522265,109737e-9,0,.650794,.500835,106228e-9,0,.68254,.479818,102591e-9,0,.714286,.459258,991288e-10,0,.746032,.439061,952325e-10,0,.777778,.419552,91895e-9,0,.809524,.400399,879051e-10,0,.84127,.381976,844775e-10,0,.873016,.364009,806316e-10,0,.904762,.346761,771848e-10,0,.936508,.330049,735429e-10,0,.968254,.314018,702103e-10,0,1,1,1.39968e-7,0,0,1,1.39979e-7,0,0,1,1.40145e-7,0,0,1,1.4087e-7,0,0,.999999,1.42865e-7,0,0,.999998,1.47279e-7,0,0,.999997,1.56057e-7,0,0,.999992,1.7276e-7,0,0,.999989,2.04352e-7,0,0,.99998,2.6494e-7,0,0,.999969,3.83435e-7,0,0,.999953,6.18641e-7,0,0,.999929,108755e-11,0,0,.999898,201497e-11,0,0,.999849,381346e-11,0,0,.999778,719815e-11,0,0,.999661,133215e-10,0,0,.999451,238313e-10,0,0,.998936,401343e-10,0,113724e-9,.99662,517346e-10,0,820171e-9,.991094,304323e-10,0,.00238143,.987487,281757e-10,0,.00493527,.983731,320048e-10,0,.00856859,.979647,423905e-10,0,.0133393,.973837,562935e-10,0,.0192863,.96584,677442e-10,0,.0264369,.956309,623073e-10,0,.03481,.951523,704131e-10,0,.0444184,.946003,836594e-10,0,.0552713,.938454,911736e-10,0,.0673749,.929279,938264e-10,0,.0807329,.919239,103754e-9,0,.0953479,.907293,109928e-9,0,.111221,.893936,115257e-9,0,.128352,.879674,122265e-9,0,.14674,.865668,125733e-9,0,.166382,.850998,132305e-9,0,.187276,.834498,134844e-9,0,.209413,.816903,139276e-9,0,.232786,.798235,140984e-9,0,.257382,.779724,14378e-8,0,.283181,.760251,144623e-9,0,.310156,.739808,145228e-9,0,.338269,.718762,14539e-8,0,.367461,.697815,144432e-9,0,.397646,.67631,143893e-9,0,.428685,.654278,141846e-9,0,.460318,.632347,13935e-8,0,.492064,.610296,137138e-9,0,.52381,.588039,133806e-9,0,.555556,.566218,130755e-9,0,.587302,.544346,127128e-9,0,.619048,.522701,123002e-9,0,.650794,.501542,119443e-9,0,.68254,.480508,115055e-9,0,.714286,.460092,111032e-9,0,.746032,.440021,106635e-9,0,.777778,.420446,102162e-9,0,.809524,.401512,98184e-9,0,.84127,.38299,936497e-10,0,.873016,.365232,89813e-9,0,.904762,.347865,853073e-10,0,.936508,.331342,817068e-10,0,.968254,.315202,773818e-10,0,1,1,2.9368e-7,0,0,1,2.937e-7,0,0,1,2.93998e-7,0,0,1,2.95298e-7,0,0,.999999,2.98865e-7,0,0,.999998,3.067e-7,0,0,.999995,3.22082e-7,0,0,.999992,3.50767e-7,0,0,.999986,4.03538e-7,0,0,.999976,5.01372e-7,0,0,.999964,6.8562e-7,0,0,.999945,10374e-10,0,0,.999919,171269e-11,0,0,.999882,300175e-11,0,0,.999829,542144e-11,0,0,.999749,984182e-11,0,0,.99962,176213e-10,0,0,.999382,305995e-10,0,138418e-10,.998751,496686e-10,0,389844e-9,.995344,510733e-10,0,.00150343,.990768,345829e-10,0,.00352451,.987464,342841e-10,0,.00655379,.983846,399072e-10,0,.0106554,.980007,533219e-10,0,.0158723,.974494,696992e-10,0,.0222333,.96622,776754e-10,0,.029758,.956273,747718e-10,0,.0384596,.950952,864611e-10,0,.0483473,.945215,100464e-9,0,.0594266,.937287,103729e-9,0,.0717019,.928649,111665e-9,0,.0851752,.918791,12353e-8,0,.0998479,.906685,127115e-9,0,.115721,.893706,13628e-8,0,.132794,.879248,142427e-9,0,.151067,.864685,148091e-9,0,.170538,.850032,153517e-9,0,.191204,.833853,157322e-9,0,.213063,.816353,161086e-9,0,.236107,.797834,164111e-9,0,.260329,.778831,165446e-9,0,.285714,.759756,167492e-9,0,.312243,.739419,166928e-9,0,.339887,.718491,167e-6,0,.368604,.697392,165674e-9,0,.398329,.676102,163815e-9,0,.428961,.654243,162003e-9,0,.460331,.632176,158831e-9,0,.492064,.610407,155463e-9,0,.52381,.588394,152062e-9,0,.555556,.56645,147665e-9,0,.587302,.5449,14375e-8,0,.619048,.523276,138905e-9,0,.650794,.502179,134189e-9,0,.68254,.481359,129392e-9,0,.714286,.46092,124556e-9,0,.746032,.441084,11957e-8,0,.777778,.421517,114652e-9,0,.809524,.402721,109688e-9,0,.84127,.384222,104667e-9,0,.873016,.366534,999633e-10,0,.904762,.349205,950177e-10,0,.936508,.332702,907301e-10,0,.968254,.316599,859769e-10,0,1,1,5.85473e-7,0,0,1,5.85507e-7,0,0,1,5.8602e-7,0,0,.999999,5.88259e-7,0,0,.999999,5.94381e-7,0,0,.999998,6.07754e-7,0,0,.999995,6.33729e-7,0,0,.99999,6.8137e-7,0,0,.999984,7.67003e-7,0,0,.999973,9.21212e-7,0,0,.999959,120218e-11,0,0,.999936,172024e-11,0,0,.999907,268088e-11,0,0,.999866,445512e-11,0,0,.999806,768481e-11,0,0,.999716,1342e-8,0,0,.999576,232473e-10,0,0,.9993,391694e-10,0,129917e-9,.998498,608429e-10,0,845035e-9,.994132,489743e-10,0,.00237616,.99031,384644e-10,0,.00484456,.987409,421768e-10,0,.00832472,.983981,504854e-10,0,.0128643,.980268,671028e-10,0,.0184947,.974875,852749e-10,0,.025237,.966063,85531e-9,0,.0331046,.956779,900588e-10,0,.0421067,.950259,10577e-8,0,.0522487,.944239,119458e-9,0,.0635343,.936341,122164e-9,0,.0759654,.928047,134929e-9,0,.0895434,.918065,145544e-9,0,.104269,.906267,150531e-9,0,.120142,.893419,161652e-9,0,.137163,.878758,16593e-8,0,.15533,.863699,174014e-9,0,.174645,.848876,177877e-9,0,.195106,.833032,184049e-9,0,.21671,.815557,186088e-9,0,.239454,.797323,19054e-8,0,.263332,.778124,191765e-9,0,.288336,.758929,192535e-9,0,.314451,.738979,192688e-9,0,.341658,.718213,191522e-9,0,.369924,.696947,190491e-9,0,.399202,.675807,187913e-9,0,.429416,.654147,184451e-9,0,.460447,.63229,181442e-9,0,.492064,.610499,177139e-9,0,.523809,.588747,172596e-9,0,.555555,.566783,167457e-9,0,.587301,.545359,162518e-9,0,.619048,.523984,156818e-9,0,.650794,.502917,151884e-9,0,.68254,.482294,145514e-9,0,.714286,.461945,140199e-9,0,.746032,.442133,134101e-9,0,.777778,.422705,128374e-9,0,.809524,.403916,122996e-9,0,.84127,.38554,116808e-9,0,.873016,.367909,111973e-9,0,.904762,.350651,105938e-9,0,.936508,.334208,101355e-9,0,.968254,.318123,957629e-10,0,1,1,111633e-11,0,0,1,111639e-11,0,0,1,111725e-11,0,0,1,112096e-11,0,0,.999999,11311e-10,0,0,.999997,115315e-11,0,0,.999995,11956e-10,0,0,.999989,127239e-11,0,0,.999981,140772e-11,0,0,.999969,164541e-11,0,0,.999952,206607e-11,0,0,.999928,281783e-11,0,0,.999895,416835e-11,0,0,.999848,658728e-11,0,0,.999781,108648e-10,0,0,.999682,182579e-10,0,0,.999523,306003e-10,0,159122e-10,.999205,499862e-10,0,391184e-9,.998131,73306e-9,0,.00147534,.993334,513229e-10,0,.0034227,.99016,467783e-10,0,.00632232,.987321,523413e-10,0,.0102295,.984099,64267e-9,0,.0151794,.980432,843042e-10,0,.0211947,.974976,102819e-9,0,.0282899,.966429,996234e-10,0,.0364739,.957633,111074e-9,0,.0457522,.949422,128644e-9,0,.0561278,.943045,140076e-9,0,.0676023,.935448,146349e-9,0,.0801762,.927225,161854e-9,0,.0938499,.917033,169135e-9,0,.108623,.905762,179987e-9,0,.124496,.892879,189832e-9,0,.141469,.878435,195881e-9,0,.159541,.863114,20466e-8,0,.178713,.84776,209473e-9,0,.198985,.832084,214861e-9,0,.220355,.814915,217695e-9,0,.242823,.796711,220313e-9,0,.266385,.777603,22313e-8,0,.291036,.757991,222471e-9,0,.316767,.738371,222869e-9,0,.343563,.717872,221243e-9,0,.371402,.696619,218089e-9,0,.400248,.675379,21562e-8,0,.430047,.65411,21169e-8,0,.460709,.63241,206947e-9,0,.492079,.61046,201709e-9,0,.52381,.58903,196753e-9,0,.555556,.567267,189637e-9,0,.587302,.545886,184735e-9,0,.619048,.524714,177257e-9,0,.650794,.503789,171424e-9,0,.68254,.483204,164688e-9,0,.714286,.462976,157172e-9,0,.746032,.443294,151341e-9,0,.777778,.423988,143737e-9,0,.809524,.405325,138098e-9,0,.84127,.386981,130698e-9,0,.873016,.369436,125276e-9,0,.904762,.35219,118349e-9,0,.936508,.335804,11312e-8,0,.968254,.319749,106687e-9,0,1,1,204685e-11,0,0,1,204694e-11,0,0,1,204831e-11,0,0,.999999,205428e-11,0,0,.999999,207056e-11,0,0,.999997,210581e-11,0,0,.999993,21732e-10,0,0,.999987,229365e-11,0,0,.999979,250243e-11,0,0,.999965,286127e-11,0,0,.999947,348028e-11,0,0,.999918,455588e-11,0,0,.999881,643303e-11,0,0,.999828,970064e-11,0,0,.999753,153233e-10,0,0,.999642,24793e-9,0,0,.999464,402032e-10,0,122947e-9,.999089,635852e-10,0,807414e-9,.997567,857026e-10,0,.00227206,.992903,594912e-10,0,.00462812,.990011,578515e-10,0,.00794162,.987192,65399e-9,0,.0122534,.98418,819675e-10,0,.0175888,.980491,105514e-9,0,.0239635,.974779,121532e-9,0,.031387,.96675,119144e-9,0,.0398644,.958248,136125e-9,0,.0493982,.948884,155408e-9,0,.0599896,.941673,162281e-9,0,.0716382,.934521,176754e-9,0,.0843437,.926205,192873e-9,0,.0981056,.916089,200038e-9,0,.112923,.904963,213624e-9,0,.128796,.892089,221834e-9,0,.145725,.878028,232619e-9,0,.163709,.86249,238632e-9,0,.182749,.846587,247002e-9,0,.202847,.830988,250702e-9,0,.224001,.814165,255562e-9,0,.246214,.796135,257505e-9,0,.269482,.777052,258625e-9,0,.293805,.757201,258398e-9,0,.319176,.737655,256714e-9,0,.345587,.717477,255187e-9,0,.373021,.696433,251792e-9,0,.401454,.675084,247223e-9,0,.430844,.653907,242213e-9,0,.461125,.632561,237397e-9,0,.492187,.610658,229313e-9,0,.52381,.589322,224402e-9,0,.555556,.567857,216116e-9,0,.587302,.54652,209124e-9,0,.619048,.525433,201601e-9,0,.650794,.504679,192957e-9,0,.68254,.484203,186052e-9,0,.714286,.464203,177672e-9,0,.746032,.444549,170005e-9,0,.777778,.425346,162401e-9,0,.809524,.406706,1544e-7,0,.84127,.388576,147437e-9,0,.873016,.37094,139493e-9,0,.904762,.353996,133219e-9,0,.936508,.337391,125573e-9,0,.968254,.321648,119867e-9,0,1,1,362511e-11,0,0,1,362525e-11,0,0,1,362739e-11,0,0,.999999,363673e-11,0,0,.999998,366214e-11,0,0,.999996,371698e-11,0,0,.999992,382116e-11,0,0,.999986,400554e-11,0,0,.999976,432058e-11,0,0,.999961,485194e-11,0,0,.999938,574808e-11,0,0,.999908,726643e-11,0,0,.999865,984707e-11,0,0,.999807,142217e-10,0,0,.999723,215581e-10,0,0,.999602,336114e-10,0,119113e-10,.999398,527353e-10,0,355813e-9,.998946,805809e-10,0,.00137768,.996647,942908e-10,0,.00322469,.992298,668733e-10,0,.00597897,.989802,716564e-10,0,.00968903,.987019,821355e-10,0,.0143845,.984219,104555e-9,0,.0200831,.980425,131245e-9,0,.0267948,.974241,139613e-9,0,.034525,.967006,145931e-9,0,.0432757,.95893,167153e-9,0,.0530471,.949157,188146e-9,0,.0638386,.94062,194625e-9,0,.0756487,.933509,213721e-9,0,.0884762,.925088,229616e-9,0,.10232,.915178,239638e-9,0,.117178,.904093,254814e-9,0,.133051,.891337,263685e-9,0,.149939,.877326,274789e-9,0,.167841,.861794,280534e-9,0,.18676,.845758,289534e-9,0,.206696,.829792,294446e-9,0,.22765,.813037,296877e-9,0,.249625,.795285,300217e-9,0,.27262,.776323,299826e-9,0,.296636,.756673,299787e-9,0,.321671,.736856,297867e-9,0,.347718,.716883,294052e-9,0,.374768,.696089,289462e-9,0,.402804,.67505,285212e-9,0,.431796,.653509,27653e-8,0,.461695,.63258,271759e-9,0,.49242,.61104,262811e-9,0,.523822,.589567,255151e-9,0,.555556,.568322,246434e-9,0,.587302,.547235,237061e-9,0,.619048,.52616,228343e-9,0,.650794,.505716,219236e-9,0,.68254,.485274,209595e-9,0,.714286,.465411,201011e-9,0,.746032,.445854,19109e-8,0,.777778,.426911,182897e-9,0,.809524,.408222,173569e-9,0,.84127,.390307,165496e-9,0,.873016,.372624,156799e-9,0,.904762,.355804,14917e-8,0,.936508,.33924,140907e-9,0,.968254,.323534,134062e-9,0,1,1,622487e-11,0,0,1,62251e-10,0,0,1,622837e-11,0,0,.999999,624259e-11,0,0,.999998,628127e-11,0,0,.999996,636451e-11,0,0,.999991,65218e-10,0,0,.999984,679782e-11,0,0,.999973,726361e-11,0,0,.999955,803644e-11,0,0,.999931,931397e-11,0,0,.999896,114299e-10,0,0,.999847,149402e-10,0,0,.999784,207461e-10,0,0,.999692,302493e-10,0,0,.999554,454957e-10,0,997275e-10,.999326,690762e-10,0,724813e-9,.998757,101605e-9,0,.0020972,.995367,958745e-10,0,.00432324,.99209,832808e-10,0,.00746347,.989517,887601e-10,0,.0115534,.987008,10564e-8,0,.0166134,.98421,133179e-9,0,.0226552,.98021,161746e-9,0,.0296838,.973676,161821e-9,0,.0377016,.967052,178635e-9,0,.0467079,.959385,206765e-9,0,.0567013,.949461,22476e-8,0,.0676796,.939578,23574e-8,0,.0796403,.932416,25893e-8,0,.0925812,.923759,271228e-9,0,.106501,.914223,289165e-9,0,.121397,.902942,301156e-9,0,.13727,.890419,313852e-9,0,.15412,.876639,324408e-9,0,.171946,.861316,33249e-8,0,.190751,.84496,338497e-9,0,.210537,.828427,345861e-9,0,.231305,.811871,347863e-9,0,.253057,.794397,350225e-9,0,.275797,.775726,349915e-9,0,.299525,.75617,347297e-9,0,.324242,.736091,344232e-9,0,.349947,.716213,340835e-9,0,.376633,.695736,332369e-9,0,.404289,.674961,327943e-9,0,.432895,.653518,318533e-9,0,.462415,.632574,310391e-9,0,.492788,.61134,300755e-9,0,.523909,.590017,290506e-9,0,.555556,.568752,280446e-9,0,.587302,.548061,269902e-9,0,.619048,.52711,258815e-9,0,.650794,.506682,248481e-9,0,.68254,.486524,237141e-9,0,.714286,.466812,226872e-9,0,.746032,.44732,216037e-9,0,.777778,.428473,205629e-9,0,.809524,.409921,195691e-9,0,.84127,.392028,185457e-9,0,.873016,.374606,176436e-9,0,.904762,.357601,166508e-9,0,.936508,.341348,158385e-9,0,.968254,.32542,149203e-9,0,1,1,103967e-10,0,0,1,10397e-9,0,0,1,104019e-10,0,0,.999999,104231e-10,0,0,.999998,104806e-10,0,0,.999995,106042e-10,0,0,.999991,108366e-10,0,0,.999982,112415e-10,0,0,.999968,119174e-10,0,0,.99995,130227e-10,0,0,.999922,148176e-10,0,0,.999884,177303e-10,0,0,.99983,224564e-10,0,0,.999758,300966e-10,0,0,.999654,423193e-10,0,549083e-11,.999503,614848e-10,0,296087e-9,.999237,903576e-10,0,.00123144,.998491,1271e-7,0,.00295954,.994594,107754e-9,0,.00555829,.99178,103025e-9,0,.00907209,.989265,11154e-8,0,.0135257,.986998,136296e-9,0,.0189327,.984137,169154e-9,0,.0252993,.979798,196671e-9,0,.0326272,.97337,196678e-9,0,.0409157,.967239,223121e-9,0,.0501623,.959543,253809e-9,0,.0603638,.949466,265972e-9,0,.0715171,.939074,288372e-9,0,.0836187,.931118,310983e-9,0,.0966657,.922525,325561e-9,0,.110656,.912983,345725e-9,0,.125588,.901617,3556e-7,0,.141461,.889487,374012e-9,0,.158275,.875787,383445e-9,0,.176031,.860654,393972e-9,0,.19473,.844417,400311e-9,0,.214374,.82741,405004e-9,0,.234967,.810545,407378e-9,0,.256512,.793312,407351e-9,0,.279011,.774847,406563e-9,0,.302468,.755621,404903e-9,0,.326887,.735511,397486e-9,0,.352266,.715435,39357e-8,0,.378605,.695403,384739e-9,0,.405897,.674681,376108e-9,0,.43413,.65359,365997e-9,0,.463277,.632471,354957e-9,0,.493295,.61151,343593e-9,0,.524106,.59064,331841e-9,0,.555561,.569386,318891e-9,0,.587302,.548785,3072e-7,0,.619048,.528146,29361e-8,0,.650794,.507872,281709e-9,0,.68254,.487805,268627e-9,0,.714286,.468196,255887e-9,0,.746032,.448922,243997e-9,0,.777778,.430093,231662e-9,0,.809524,.411845,220339e-9,0,.84127,.393808,208694e-9,0,.873016,.376615,198045e-9,0,.904762,.359655,187375e-9,0,.936508,.343452,177371e-9,0,.968254,.32765,167525e-9,0,1,1,169351e-10,0,0,1,169356e-10,0,0,1,169427e-10,0,0,.999999,169736e-10,0,0,.999998,170575e-10,0,0,.999995,172372e-10,0,0,.99999,175739e-10,0,0,.999979,181568e-10,0,0,.999966,191206e-10,0,0,.999944,20677e-9,0,0,.999912,231644e-10,0,0,.999869,271268e-10,0,0,.999811,334272e-10,0,0,.99973,433979e-10,0,0,.999617,590083e-10,0,680315e-10,.999445,829497e-10,0,612796e-9,.999138,118019e-9,0,.00187408,.998095,156712e-9,0,.00395791,.993919,125054e-9,0,.00692144,.991333,126091e-9,0,.0107962,.989226,144912e-9,0,.0155986,.986954,175737e-9,0,.0213364,.983982,213883e-9,0,.0280114,.979128,234526e-9,0,.0356226,.973327,243725e-9,0,.0441668,.967416,2773e-7,0,.0536399,.959729,308799e-9,0,.0640376,.949758,322447e-9,0,.0753554,.939173,350021e-9,0,.0875893,.9296,370089e-9,0,.100736,.921181,391365e-9,0,.114793,.91164,413636e-9,0,.129759,.900435,427068e-9,0,.145632,.888183,441046e-9,0,.162412,.874772,454968e-9,0,.180101,.859566,461882e-9,0,.1987,.843579,471556e-9,0,.218213,.826453,474335e-9,0,.238641,.809164,477078e-9,0,.259989,.792179,47755e-8,0,.282262,.773866,472573e-9,0,.305464,.754944,469765e-9,0,.329599,.735133,462371e-9,0,.35467,.714858,453674e-9,0,.380678,.694829,443888e-9,0,.407622,.674453,432052e-9,0,.435493,.653685,420315e-9,0,.464275,.632666,406829e-9,0,.493938,.611676,392234e-9,0,.524422,.591193,379208e-9,0,.555624,.570145,36319e-8,0,.587302,.549566,349111e-9,0,.619048,.529278,334166e-9,0,.650794,.509026,318456e-9,0,.68254,.489186,30449e-8,0,.714286,.469662,289051e-9,0,.746032,.450691,275494e-9,0,.777778,.431841,261437e-9,0,.809524,.413752,247846e-9,0,.84127,.395951,235085e-9,0,.873016,.378633,222245e-9,0,.904762,.36194,210533e-9,0,.936508,.345599,198494e-9,0,.968254,.329999,188133e-9,0,1,1,269663e-10,0,0,1,26967e-9,0,0,1,269772e-10,0,0,.999999,270214e-10,0,0,.999998,271415e-10,0,0,.999994,27398e-9,0,0,.999988,278771e-10,0,0,.999977,287019e-10,0,0,.999961,300544e-10,0,0,.999937,322138e-10,0,0,.999904,356163e-10,0,0,.999854,409465e-10,0,0,.99979,492651e-10,0,0,.999699,621722e-10,0,8.8288e-7,.999572,819715e-10,0,223369e-9,.999381,111689e-9,0,.00105414,.999016,153862e-9,0,.0026493,.997437,187667e-9,0,.00508608,.993545,155672e-9,0,.00840554,.991135,161455e-9,0,.012629,.989157,188241e-9,0,.0177661,.986874,226229e-9,0,.0238198,.983714,268668e-9,0,.0307887,.978301,277109e-9,0,.0386688,.973227,303446e-9,0,.0474554,.967317,341851e-9,0,.0571428,.959477,370885e-9,0,.0677256,.950012,392753e-9,0,.0791988,.939484,42781e-8,0,.0915576,.928135,443866e-9,0,.104798,.919819,472959e-9,0,.118918,.910049,491551e-9,0,.133915,.899181,512616e-9,0,.149788,.886881,523563e-9,0,.166537,.87359,540183e-9,0,.184164,.858613,547386e-9,0,.202669,.842809,554809e-9,0,.222056,.825727,558316e-9,0,.242329,.808086,557824e-9,0,.263492,.790728,556346e-9,0,.285551,.772987,552672e-9,0,.30851,.7541,543738e-9,0,.332376,.734669,536107e-9,0,.357153,.714411,523342e-9,0,.382845,.694196,512238e-9,0,.409454,.674252,497465e-9,0,.436977,.65357,481096e-9,0,.465404,.632999,467054e-9,0,.494713,.611994,448771e-9,0,.524864,.591604,431889e-9,0,.555779,.571134,415238e-9,0,.587302,.550528,396369e-9,0,.619048,.530292,379477e-9,0,.650794,.510364,361488e-9,0,.68254,.490749,343787e-9,0,.714286,.471266,327822e-9,0,.746032,.452462,310626e-9,0,.777778,.433907,295352e-9,0,.809524,.415659,279179e-9,0,.84127,.398138,264685e-9,0,.873016,.380833,249905e-9,0,.904762,.364247,236282e-9,0,.936508,.348041,222905e-9,0,.968254,.332389,210522e-9,0,1,1,420604e-10,0,0,1,420614e-10,0,0,1,420757e-10,0,0,.999999,42138e-9,0,0,.999997,423067e-10,0,0,.999993,426668e-10,0,0,.999986,433372e-10,0,0,.999974,444857e-10,0,0,.999956,463554e-10,0,0,.99993,493105e-10,0,0,.999892,539077e-10,0,0,.999838,610005e-10,0,0,.999767,718822e-10,0,0,.999666,884581e-10,0,365471e-10,.999525,113398e-9,0,485623e-9,.999311,150043e-9,0,.00162096,.998865,200063e-9,0,.00355319,.996278,211014e-9,0,.00633818,.992956,189672e-9,0,.0100043,.991017,210262e-9,0,.0145648,.989055,244292e-9,0,.0200237,.986741,290481e-9,0,.0263798,.983288,334303e-9,0,.033629,.977784,340307e-9,0,.0417652,.973037,377864e-9,0,.0507821,.967181,4239e-7,0,.060673,.958971,443854e-9,0,.0714314,.950093,483039e-9,0,.0830518,.939552,517934e-9,0,.0955288,.927678,539449e-9,0,.108859,.918278,568604e-9,0,.123038,.908449,588505e-9,0,.138065,.897713,612473e-9,0,.153938,.885533,625575e-9,0,.170657,.872131,63854e-8,0,.188224,.857517,647034e-9,0,.20664,.841796,65209e-8,0,.225909,.824726,6544e-7,0,.246035,.807297,655744e-9,0,.267022,.789058,646716e-9,0,.288878,.77189,643898e-9,0,.311607,.753082,629973e-9,0,.335216,.7341,621564e-9,0,.359713,.714094,605171e-9,0,.385103,.693839,588752e-9,0,.41139,.673891,573294e-9,0,.438576,.653565,552682e-9,0,.466656,.633326,533446e-9,0,.495617,.612582,514635e-9,0,.525431,.59205,49303e-8,0,.556041,.571918,471842e-9,0,.587338,.551572,451713e-9,0,.619048,.531553,430049e-9,0,.650794,.51175,410445e-9,0,.68254,.49238,390098e-9,0,.714286,.473143,370033e-9,0,.746032,.45423,351205e-9,0,.777778,.435963,332049e-9,0,.809524,.41787,315021e-9,0,.84127,.400387,297315e-9,0,.873016,.383332,281385e-9,0,.904762,.366665,265397e-9,0,.936508,.350633,250601e-9,0,.968254,.334964,23589e-8,0,1,1,643736e-10,0,0,1,64375e-9,0,0,1,643947e-10,0,0,.999999,64481e-9,0,0,.999997,647143e-10,0,0,.999994,652119e-10,0,0,.999985,661359e-10,0,0,.999972,677116e-10,0,0,.999952,702599e-10,0,0,.999922,742517e-10,0,0,.99988,803906e-10,0,0,.99982,897315e-10,0,0,.999741,103838e-9,0,0,.999629,12496e-8,0,149024e-9,.999474,156161e-9,0,861027e-9,.999229,201034e-9,0,.00231198,.998662,259069e-9,0,.00458147,.995299,245439e-9,0,.00770895,.992732,24498e-8,0,.0117126,.990847,273211e-9,0,.0165989,.988911,316492e-9,0,.0223674,.98654,37161e-8,0,.0290135,.982636,410352e-9,0,.0365309,.977346,421756e-9,0,.0449117,.972909,475578e-9,0,.0541481,.966821,522482e-9,0,.0642326,.958686,545008e-9,0,.075158,.949754,589286e-9,0,.0869181,.939184,619995e-9,0,.0995074,.927505,654266e-9,0,.112922,.916606,682362e-9,0,.127157,.906707,704286e-9,0,.142212,.895937,725909e-9,0,.158085,.883913,743939e-9,0,.174776,.870642,755157e-9,0,.192287,.856241,764387e-9,0,.210619,.84069,771032e-9,0,.229775,.823728,765906e-9,0,.249761,.806481,767604e-9,0,.270582,.787924,754385e-9,0,.292243,.770588,749668e-9,0,.314753,.751991,731613e-9,0,.338118,.733407,717655e-9,0,.362347,.713688,700604e-9,0,.387447,.693595,678765e-9,0,.413424,.673426,657042e-9,0,.440284,.65359,635892e-9,0,.468027,.633576,611569e-9,0,.496645,.613144,586011e-9,0,.526122,.592711,563111e-9,0,.556417,.572722,537699e-9,0,.587451,.552762,512556e-9,0,.619048,.532985,489757e-9,0,.650794,.513219,464139e-9,0,.68254,.493992,442193e-9,0,.714286,.47509,418629e-9,0,.746032,.456287,397045e-9,0,.777778,.438152,375504e-9,0,.809524,.420294,35492e-8,0,.84127,.402749,335327e-9,0,.873016,.385879,316422e-9,0,.904762,.369352,298333e-9,0,.936508,.353301,281417e-9,0,.968254,.337781,265203e-9,0,1,1,968267e-10,0,0,1,968284e-10,0,0,1,968556e-10,0,0,.999999,969733e-10,0,0,.999997,972913e-10,0,0,.999993,979688e-10,0,0,.999984,992239e-10,0,0,.999969,101356e-9,0,0,.999946,104784e-9,0,0,.999913,110111e-9,0,0,.999868,118217e-9,0,0,.999801,130396e-9,0,0,.999712,148523e-9,0,124907e-10,.999589,175233e-9,0,355405e-9,.999416,213999e-9,0,.0013528,.999136,268529e-9,0,.00312557,.998367,333088e-9,0,.00573045,.994701,304757e-9,0,.00919397,.992497,318031e-9,0,.0135261,.990608,353863e-9,0,.0187278,.988715,409044e-9,0,.0247947,.986241,472967e-9,0,.0317196,.981696,495104e-9,0,.039494,.977097,532873e-9,0,.0481087,.972583,594447e-9,0,.0575549,.966142,636867e-9,0,.0678242,.95823,669899e-9,0,.0789089,.949677,719499e-9,0,.0908023,.939226,750584e-9,0,.103499,.927501,793183e-9,0,.116993,.915199,81995e-8,0,.131282,.90498,847654e-9,0,.146364,.894243,868929e-9,0,.162237,.882154,884278e-9,0,.178902,.869161,898108e-9,0,.196358,.854751,901254e-9,0,.21461,.839368,90679e-8,0,.23366,.822874,901541e-9,0,.253512,.805514,897297e-9,0,.274174,.78716,881856e-9,0,.29565,.769061,870032e-9,0,.31795,.751,851719e-9,0,.341081,.732614,830671e-9,0,.365053,.713171,806569e-9,0,.389874,.693472,78338e-8,0,.415553,.673528,756404e-9,0,.442098,.653397,726872e-9,0,.469512,.633781,700494e-9,0,.497794,.613877,67105e-8,0,.526935,.593506,640361e-9,0,.556908,.573667,613502e-9,0,.587657,.553932,583177e-9,0,.61906,.534345,554375e-9,0,.650794,.515042,527811e-9,0,.68254,.495674,499367e-9,0,.714286,.477132,47429e-8,0,.746032,.458609,447726e-9,0,.777778,.440354,424205e-9,0,.809524,.422765,399549e-9,0,.84127,.405472,378315e-9,0,.873016,.388482,355327e-9,0,.904762,.372191,336122e-9,0,.936508,.356099,315247e-9,0,.968254,.340737,29794e-8,0,1,1,143327e-9,0,0,1,14333e-8,0,0,1,143366e-9,0,0,.999999,143524e-9,0,0,.999996,143952e-9,0,0,.999991,144862e-9,0,0,.999981,146544e-9,0,0,.999966,149391e-9,0,0,.999941,153946e-9,0,0,.999905,160971e-9,0,0,.999852,171562e-9,0,0,.99978,18729e-8,0,0,.999681,210386e-9,0,826239e-10,.999546,243906e-9,0,664807e-9,.999352,291739e-9,0,.00196192,.999027,357419e-9,0,.00405941,.997886,422349e-9,0,.00699664,.99419,385008e-9,0,.0107896,.99214,409775e-9,0,.0154415,.990274,456418e-9,0,.0209488,.988455,527008e-9,0,.0273037,.985804,597685e-9,0,.0344969,.98103,613124e-9,0,.0425183,.976674,668321e-9,0,.0513575,.972021,736985e-9,0,.0610046,.965274,773789e-9,0,.0714508,.958046,830852e-9,0,.0826877,.949333,875766e-9,0,.0947085,.939135,917088e-9,0,.107507,.927119,952244e-9,0,.121078,.91469,990626e-9,0,.135419,.903006,.00101304,0,.150526,.892368,.00103834,0,.166399,.880231,.00105002,0,.183038,.867432,.00106331,0,.200443,.853208,.00106783,0,.218618,.837956,.00106458,0,.237566,.821772,.00105945,0,.257291,.804328,.00104685,0,.2778,.786465,.00103178,0,.2991,.768004,.00101077,0,.321199,.74972,985504e-9,0,.344106,.731682,962893e-9,0,.36783,.712813,932146e-9,0,.392383,.693139,89871e-8,0,.417774,.673566,869678e-9,0,.444013,.653483,835525e-9,0,.471107,.633891,799853e-9,0,.49906,.614433,766838e-9,0,.527869,.594586,732227e-9,0,.557517,.574769,696442e-9,0,.587966,.555149,663935e-9,0,.61913,.535898,629826e-9,0,.650794,.516753,596486e-9,0,.68254,.497816,567078e-9,0,.714286,.479034,534399e-9,0,.746032,.460975,507013e-9,0,.777778,.442935,477421e-9,0,.809524,.425263,451101e-9,0,.84127,.408248,424964e-9,0,.873016,.391339,39993e-8,0,.904762,.37513,377619e-9,0,.936508,.359172,354418e-9,0,.968254,.343876,334823e-9,0,1,1,209042e-9,0,0,1,209045e-9,0,0,1,209093e-9,0,0,.999999,209304e-9,0,0,.999996,209871e-9,0,0,.999991,211078e-9,0,0,.999979,213304e-9,0,0,.999963,217061e-9,0,0,.999933,223042e-9,0,0,.999894,232206e-9,0,0,.999837,245901e-9,0,0,.999756,266023e-9,0,102927e-11,.999648,295204e-9,0,233468e-9,.999499,336958e-9,0,.00108237,.999283,395563e-9,0,.00268832,.998896,473785e-9,0,.00511138,.997006,520008e-9,0,.00837705,.993819,497261e-9,0,.0124928,.991632,523722e-9,0,.0174561,.989875,587258e-9,0,.0232596,.988109,676329e-9,0,.0298932,.985155,747701e-9,0,.0373453,.980479,768803e-9,0,.0456045,.976271,841054e-9,0,.0546593,.971347,911469e-9,0,.0644994,.964528,953057e-9,0,.0751152,.957632,.00102221,0,.0864981,.948681,.00106122,0,.0986407,.938716,.00111857,0,.111537,.926629,.00114762,0,.125182,.914025,.00118995,0,.139571,.901026,.00121228,0,.154703,.890358,.00123946,0,.170576,.878283,.0012527,0,.18719,.865459,.00125536,0,.204547,.851407,.00126134,0,.222648,.836276,.00124759,0,.241498,.820436,.00124443,0,.261101,.803253,.00122071,0,.281465,.785562,.00120107,0,.302595,.76718,.00117762,0,.324501,.748551,.00114289,0,.347192,.730564,.00110872,0,.370679,.712253,.00107636,0,.394973,.692867,.00103646,0,.420085,.673695,996793e-9,0,.446027,.653912,95675e-8,0,.47281,.634129,916739e-9,0,.500441,.615004,874401e-9,0,.528921,.595587,833411e-9,0,.558244,.575965,794556e-9,0,.588384,.5566,75196e-8,0,.619281,.537428,716381e-9,0,.650795,.518623,676558e-9,0,.68254,.499964,64074e-8,0,.714286,.481356,605984e-9,0,.746032,.463279,570256e-9,0,.777778,.445673,540138e-9,0,.809524,.428032,507299e-9,0,.84127,.411112,479553e-9,0,.873016,.394444,450737e-9,0,.904762,.378247,424269e-9,0,.936508,.362415,399111e-9,0,.968254,.347103,375274e-9,0,1,1,300729e-9,0,0,1,300733e-9,0,0,1,300797e-9,0,0,.999998,301072e-9,0,0,.999996,301817e-9,0,0,.999989,303398e-9,0,0,.999977,306309e-9,0,0,.999958,311209e-9,0,0,.999927,318975e-9,0,0,.999884,330804e-9,0,0,.99982,34834e-8,0,0,.999733,373854e-9,0,326995e-10,.999613,410424e-9,0,477174e-9,.999447,462047e-9,0,.00161099,.999204,533322e-9,0,.00353153,.998725,624964e-9,0,.00627965,.995871,631786e-9,0,.0098693,.993194,632017e-9,0,.0143011,.991541,68923e-8,0,.019568,.989773,766892e-9,0,.0256593,.987647,863668e-9,0,.0325625,.984193,922089e-9,0,.0402647,.980016,970749e-9,0,.0487532,.975859,.00106027,0,.058016,.970514,.00112239,0,.0680419,.963625,.00117212,0,.0788208,.956959,.00125211,0,.0903439,.947956,.00129411,0,.102604,.93809,.00135879,0,.115594,.92659,.00139309,0,.129309,.913829,.00143253,0,.143745,.90005,.00145809,0,.158901,.888129,.0014748,0,.174774,.87607,.00148756,0,.191365,.863461,.00148714,0,.208674,.849594,.00148892,0,.226705,.834531,.00146496,0,.245461,.81903,.0014579,0,.264947,.802122,.00143039,0,.28517,.78445,.00139717,0,.306137,.766434,.00136312,0,.327857,.747816,.00132597,0,.350341,.729519,.00128323,0,.373598,.711454,.00123803,0,.397642,.692699,.00119097,0,.422485,.673723,.00114565,0,.448139,.654386,.00109552,0,.474619,.634673,.00104553,0,.501933,.615554,99985e-8,0,.530089,.596462,948207e-9,0,.559087,.577385,902299e-9,0,.588913,.558257,856448e-9,0,.619525,.5392,810395e-9,0,.650826,.520543,768558e-9,0,.68254,.502206,7239e-7,0,.714286,.48402,685794e-9,0,.746032,.465779,64471e-8,0,.777778,.448455,609583e-9,0,.809524,.431091,57227e-8,0,.84127,.414147,54042e-8,0,.873016,.39765,506545e-9,0,.904762,.381576,477635e-9,0,.936508,.365881,448446e-9,0,.968254,.350582,421424e-9,0,1,1,427144e-9,0,0,1,427151e-9,0,0,1,427232e-9,0,0,.999998,42759e-8,0,0,.999995,428555e-9,0,0,.999988,430603e-9,0,0,.999976,434368e-9,0,0,.999952,440688e-9,0,0,.999919,450667e-9,0,0,.999871,46578e-8,0,0,.999801,488024e-9,0,0,.999704,520092e-9,0,129791e-9,.999572,565553e-9,0,821056e-9,.999389,628906e-9,0,.00225241,.999114,714911e-9,0,.00449109,.998488,819218e-9,0,.00756249,.995234,80415e-8,0,.0114716,.993021,830181e-9,0,.0162131,.991407,902645e-9,0,.021776,.989625,996934e-9,0,.0281471,.987064,.00109707,0,.0353118,.983265,.00114353,0,.0432562,.979535,.0012272,0,.0519665,.975224,.00132642,0,.0614298,.969574,.00138092,0,.0716348,.963021,.00145896,0,.0825709,.956046,.00152834,0,.094229,.947136,.00158217,0,.106602,.937313,.0016347,0,.119682,.926073,.00168383,0,.133465,.913121,.00171627,0,.147947,.899165,.00174229,0,.163125,.885891,.00176137,0,.178998,.873783,.00176406,0,.195566,.861331,.00176156,0,.21283,.847569,.00175346,0,.230793,.832785,.00172753,0,.249459,.817442,.00170204,0,.268832,.800613,.00166576,0,.28892,.783597,.00162909,0,.30973,.76571,.0015826,0,.331271,.747021,.00153106,0,.353554,.728593,.00148036,0,.37659,.710661,.00142808,0,.400391,.692426,.00136906,0,.424973,.673623,.00131066,0,.450347,.65494,.00125569,0,.476531,.635448,.00119517,0,.503535,.616221,.00113828,0,.531372,.597531,.0010816,0,.560047,.578795,.00102673,0,.589554,.559892,970985e-9,0,.619869,.541307,919773e-9,0,.650923,.522608,868479e-9,0,.68254,.504484,82137e-8,0,.714286,.486603,772916e-9,0,.746032,.468802,730353e-9,0,.777778,.451172,684955e-9,0,.809524,.434348,647565e-9,0,.84127,.417445,605863e-9,0,.873016,.401077,571885e-9,0,.904762,.385039,536034e-9,0,.936508,.369483,504227e-9,0,.968254,.354272,473165e-9,0,1,1,599525e-9,0,0,1,599533e-9,0,0,1,599639e-9,0,0,.999998,600097e-9,0,0,.999994,601336e-9,0,0,.999987,603958e-9,0,0,.999972,608775e-9,0,0,.999949,616842e-9,0,0,.999912,629534e-9,0,0,.999857,648658e-9,0,0,.999781,676615e-9,0,538873e-11,.999674,716574e-9,0,308602e-9,.999528,772641e-9,0,.00127003,.999326,849806e-9,0,.00300783,.999009,952682e-9,0,.00556637,.998112,.00106394,0,.00895889,.994496,.00102228,0,.0131827,.992806,.00108586,0,.0182277,.991211,.0011759,0,.0240795,.989415,.00128955,0,.030723,.986499,.00139038,0,.0381418,.982679,.00144539,0,.046321,.978839,.00153954,0,.0552459,.974295,.00164417,0,.0649034,.968784,.00171517,0,.0752814,.962324,.00180282,0,.0863693,.954956,.00186387,0,.0981578,.94624,.00193817,0,.110639,.936517,.00198156,0,.123806,.925186,.00203042,0,.137655,.91252,.0020664,0,.15218,.898441,.00207822,0,.16738,.884394,.0020992,0,.183253,.871273,.00208748,0,.199799,.859057,.00208686,0,.21702,.845243,.00205519,0,.234918,.830723,.00202868,0,.253496,.815801,.00199501,0,.272761,.79914,.00194193,0,.292719,.782372,.00188824,0,.313377,.76482,.00183695,0,.334745,.746586,.00177418,0,.356833,.7281,.00170628,0,.379654,.709842,.00164063,0,.403221,.692019,.00157355,0,.427548,.67364,.00150262,0,.452651,.655277,.00143473,0,.478545,.636438,.00136371,0,.505246,.617364,.00129911,0,.532768,.598603,.00123014,0,.561122,.580195,.00116587,0,.590309,.561786,.00110398,0,.620318,.543377,.00104148,0,.651102,.525093,983984e-9,0,.682545,.506791,92667e-8,0,.714286,.489291,874326e-9,0,.746032,.471811,821734e-9,0,.777778,.454435,774698e-9,0,.809524,.437493,727302e-9,0,.84127,.420977,684039e-9,0,.873016,.404729,64373e-8,0,.904762,.388756,60285e-8,0,.936508,.373344,56765e-8,0,.968254,.358191,531929e-9,0,1,1,832169e-9,0,0,1,832178e-9,0,0,1,83231e-8,0,0,.999998,832893e-9,0,0,.999995,834465e-9,0,0,.999985,837791e-9,0,0,.999969,843893e-9,0,0,.999944,854086e-9,0,0,.999903,870071e-9,0,0,.999843,894042e-9,0,0,.999759,928865e-9,0,531805e-10,.999643,978242e-9,0,579365e-9,.99948,.00104684,0,.00182774,.999255,.00114012,0,.00387804,.998885,.00126188,0,.00675709,.997405,.00135888,0,.010468,.99424,.00133626,0,.0150018,.992458,.00140905,0,.0203443,.990929,.00152305,0,.0264786,.989116,.00165882,0,.0333875,.985624,.00174128,0,.0410536,.982003,.00182108,0,.0494609,.978336,.00194498,0,.0585941,.973184,.00202708,0,.0684396,.9678,.00212166,0,.0789851,.961348,.00221366,0,.0902199,.953841,.00228219,0,.102134,.94534,.00235662,0,.114721,.935552,.00240572,0,.127972,.924064,.00244405,0,.141884,.911827,.00247557,0,.156451,.897731,.00248374,0,.171672,.883409,.00249863,0,.187545,.868625,.00246688,0,.20407,.856529,.00246523,0,.221249,.842999,.00242368,0,.239083,.828505,.00237354,0,.257578,.813825,.00232588,0,.276738,.797813,.00226731,0,.296569,.781097,.00219704,0,.31708,.764038,.00212394,0,.338281,.746067,.00204786,0,.360181,.727687,.00196728,0,.382794,.709571,.00188779,0,.406133,.691503,.00180532,0,.430213,.673673,.00171849,0,.45505,.655732,.00164147,0,.480662,.637399,.00155858,0,.507065,.618616,.00147641,0,.534278,.60005,.00140125,0,.562313,.581713,.00132441,0,.59118,.563546,.00125014,0,.620875,.545605,.00118249,0,.651373,.527559,.0011116,0,.682593,.509764,.00104979,0,.714286,.49193,985977e-9,0,.746032,.475011,928592e-9,0,.777778,.457878,873466e-9,0,.809524,.440979,819585e-9,0,.84127,.424613,772365e-9,0,.873016,.408549,722195e-9,0,.904762,.392771,680014e-9,0,.936508,.377317,636797e-9,0,.968254,.362352,598318e-9,0,1,1,.00114313,0,0,1,.00114314,0,0,.999999,.00114331,0,0,.999998,.00114404,0,0,.999994,.00114601,0,0,.999984,.00115019,0,0,.999967,.00115784,0,0,.999937,.0011706,0,0,.999894,.00119054,0,0,.999828,.00122031,0,0,.999735,.00126331,0,169263e-9,.999606,.00132382,0,949167e-9,.999426,.0014071,0,.00249668,.999173,.00151895,0,.00486392,.99873,.00166102,0,.00806323,.996243,.0017023,0,.0120895,.993779,.00172782,0,.0169288,.9919,.0018108,0,.0225633,.990524,.00196028,0,.028974,.98868,.00212014,0,.036142,.984663,.00217598,0,.044049,.981457,.00230563,0,.0526781,.977608,.00243966,0,.0620137,.972215,.00251336,0,.0720418,.966798,.0026285,0,.0827499,.960241,.00271409,0,.0941271,.952489,.00278381,0,.106164,.944127,.00285399,0,.118852,.934282,.00290994,0,.132185,.923271,.00294558,0,.146157,.910803,.00296269,0,.160766,.896705,.00296803,0,.176007,.88238,.00296637,0,.19188,.867116,.00293163,0,.208385,.853636,.00289418,0,.225523,.840469,.00284663,0,.243296,.82639,.00278594,0,.261709,.811759,.00271618,0,.280767,.796113,.00263187,0,.300476,.779518,.00254589,0,.320845,.763142,.00246003,0,.341883,.745464,.00236529,0,.363601,.727491,.00226536,0,.386011,.709414,.00216375,0,.409128,.691396,.00207127,0,.432967,.67368,.00197106,0,.457545,.656049,.00187022,0,.482881,.638188,.00177605,0,.508992,.620177,.00168482,0,.535899,.601506,.00158909,0,.563619,.58362,.00150583,0,.592165,.565496,.00141791,0,.621544,.54789,.00133693,0,.651743,.530323,.00126038,0,.682709,.512795,.00118556,0,.714286,.495199,.00111527,0,.746032,.478101,.0010489,0,.777778,.461511,984264e-9,0,.809524,.444879,92591e-8,0,.84127,.428424,866582e-9,0,.873016,.412495,814463e-9,0,.904762,.396975,764498e-9,0,.936508,.381614,715967e-9,0,.968254,.366732,672483e-9,0,1,1,.00155501,0,0,1,.00155503,0,0,1,.00155524,0,0,.999998,.00155615,0,0,.999994,.0015586,0,0,.999983,.00156379,0,0,.999963,.0015733,0,0,.999932,.00158911,0,0,.999882,.00161376,0,0,.99981,.00165041,0,100875e-10,.999708,.00170304,0,367658e-9,.999565,.00177658,0,.0014234,.999368,.00187688,0,.00327939,.999081,.00200989,0,.00596629,.99852,.00217177,0,.0094852,.99549,.0021745,0,.013824,.993252,.00222357,0,.0189642,.991727,.00235022,0,.0248856,.989951,.00250561,0,.0315669,.988029,.00268829,0,.0389882,.984029,.0027496,0,.0471302,.980683,.00289793,0,.0559754,.976554,.00303315,0,.0655081,.97139,.00313257,0,.0757138,.965544,.00323656,0,.08658,.95912,.00333432,0,.0980954,.951183,.0034039,0,.110251,.942974,.00347515,0,.123038,.932642,.00350381,0,.13645,.922158,.00354519,0,.150482,.909404,.00353851,0,.165129,.896071,.0035435,0,.18039,.881206,.00349936,0,.196263,.866077,.00347256,0,.212748,.85093,.003415,0,.229847,.837703,.00333367,0,.247561,.823878,.003249,0,.265895,.809449,.00316347,0,.284854,.794379,.00306351,0,.304445,.778138,.0029499,0,.324675,.761997,.00284099,0,.345555,.744938,.00272104,0,.367095,.727212,.00260715,0,.389309,.709549,.00248855,0,.41221,.691704,.00236783,0,.435814,.673689,.00225178,0,.460138,.656453,.00213765,0,.485203,.639128,.00202178,0,.511028,.621512,.00191443,0,.537634,.603598,.00180977,0,.565041,.58559,.00170456,0,.593268,.567852,.00160927,0,.622327,.5503,.00151395,0,.652217,.533033,.00142499,0,.682907,.515942,.00133955,0,.714296,.498814,.0012602,0,.746032,.481595,.00118188,0,.777778,.465117,.00111171,0,.809524,.448865,.00104091,0,.84127,.432711,976618e-9,0,.873016,.416822,91859e-8,0,.904762,.401272,857704e-9,0,.936508,.386226,807172e-9,0,.968254,.371321,75464e-8,0,1,1,.00209596,0,0,1,.00209598,0,0,1,.00209624,0,0,.999997,.00209736,0,0,.999991,.00210039,0,0,.999979,.00210678,0,0,.999959,.00211847,0,0,.999925,.0021379,0,0,.99987,.00216809,0,0,.999791,.00221281,0,681487e-10,.999677,.00227669,0,658161e-9,.999521,.00236533,0,.00200635,.999301,.00248514,0,.0041779,.998977,.00264185,0,.00718648,.998191,.00281695,0,.0110239,.994801,.00278518,0,.015672,.993091,.00288774,0,.0211091,.991571,.00303931,0,.0273123,.9897,.00321643,0,.034259,.987023,.00337332,0,.0419282,.983289,.00346146,0,.0502998,.979892,.00363704,0,.0593562,.975111,.00373601,0,.069081,.970351,.0038842,0,.0794598,.964131,.00397053,0,.0904798,.957747,.00408078,0,.10213,.949536,.00413533,0,.1144,.941372,.00420305,0,.127284,.931049,.00422815,0,.140772,.920647,.00425048,0,.154862,.908033,.0042281,0,.169548,.895028,.00422026,0,.184828,.879968,.00415042,0,.200701,.864875,.00408821,0,.217167,.84918,.00400909,0,.234227,.834934,.00391178,0,.251884,.821397,.00380066,0,.270141,.807135,.00367974,0,.289004,.792363,.00355172,0,.308479,.776661,.003411,0,.328575,.760705,.00328123,0,.349301,.744408,.00314003,0,.370668,.726994,.0029906,0,.392689,.709598,.00285034,0,.415379,.692112,.00271179,0,.438754,.674435,.00257185,0,.46283,.65676,.00243425,0,.48763,.639982,.00230351,0,.513173,.622983,.0021777,0,.539482,.605471,.00204991,0,.566579,.58796,.00193759,0,.594488,.570463,.00181976,0,.623226,.553058,.00171497,0,.6528,.535894,.00161109,0,.683198,.519089,.00151394,0,.714354,.502454,.00142122,0,.746032,.485681,.00133488,0,.777778,.468935,.00124975,0,.809524,.452951,.00117309,0,.84127,.437139,.00110155,0,.873016,.421446,.00103124,0,.904762,.405951,966387e-9,0,.936508,.391003,908119e-9,0,.968254,.376198,848057e-9,0,1,1,.00280076,0,0,1,.00280078,0,0,.999999,.00280109,0,0,.999997,.00280246,0,0,.999992,.00280616,0,0,.999979,.00281396,0,0,.999956,.00282822,0,0,.999916,.00285186,0,0,.999857,.0028885,0,0,.999768,.00294259,0,196026e-9,.999645,.00301946,0,.00104842,.99947,.00312541,0,.00270199,.999229,.00326733,0,.00519449,.998852,.00344992,0,.00852602,.997558,.00361052,0,.0126804,.994417,.0035898,0,.017635,.992824,.00372393,0,.023365,.991344,.00390695,0,.0298456,.989337,.00410392,0,.0370529,.985811,.00420987,0,.0449651,.982772,.00437488,0,.0535615,.979001,.00455069,0,.0628243,.974102,.00464462,0,.0727368,.969197,.00480577,0,.0832844,.962759,.00487818,0,.0944545,.956207,.00498176,0,.106236,.947909,.00503392,0,.118619,.939596,.00507474,0,.131595,.929642,.00509798,0,.145159,.918807,.00508476,0,.159305,.906921,.00505634,0,.174028,.893312,.00498845,0,.189327,.878933,.0049133,0,.2052,.863986,.0048259,0,.221647,.847936,.00470848,0,.23867,.832253,.00456889,0,.25627,.818619,.00442726,0,.274453,.804788,.00427677,0,.293222,.790241,.00411906,0,.312585,.775162,.00394833,0,.33255,.759463,.00377366,0,.353126,.743598,.00361026,0,.374324,.72697,.00343627,0,.396158,.709646,.00326422,0,.418641,.69277,.00309717,0,.44179,.675371,.0029356,0,.465624,.657863,.00277712,0,.490163,.640772,.00261738,0,.515429,.624441,.0024737,0,.541445,.607497,.00233125,0,.568236,.590438,.00218994,0,.595828,.573224,.0020664,0,.624242,.556168,.00193526,0,.653496,.539232,.00182463,0,.683588,.522352,.00170735,0,.714482,.506172,.00160555,0,.746032,.489842,.00150451,0,.777778,.473463,.00140938,0,.809524,.457266,.00132568,0,.84127,.441609,.0012376,0,.873016,.426348,.00116265,0,.904762,.411002,.00108935,0,.936508,.396045,.00101946,0,.968254,.381448,955665e-9,0,1,1,.0037121,0,0,1,.00371213,0,0,1,.00371251,0,0,.999997,.00371417,0,0,.99999,.00371863,0,0,.999977,.00372807,0,0,.99995,.00374529,0,0,.999908,.0037738,0,0,.999843,.00381789,0,123596e-10,.999745,.00388273,0,407442e-9,.999608,.00397443,0,.0015447,.999415,.00409998,0,.00351385,.999143,.00426662,0,.0063316,.9987,.00447625,0,.00998679,.996363,.00455323,0,.0144569,.994021,.00461052,0,.0197151,.992372,.00476359,0,.0257344,.991007,.00499101,0,.0324882,.988767,.0051972,0,.0399517,.984872,.00528407,0,.0481022,.982004,.00548926,0,.0569191,.977714,.00564385,0,.0663839,.973076,.0057693,0,.0764801,.967565,.0058924,0,.0871928,.961384,.00599629,0,.0985095,.954435,.00605998,0,.110419,.946303,.0061133,0,.122912,.937662,.00612028,0,.13598,.927867,.00612209,0,.149617,.916475,.00604813,0,.163817,.90541,.00603088,0,.178577,.891591,.00592218,0,.193894,.877573,.00578854,0,.209767,.862511,.00566648,0,.226196,.846861,.00551481,0,.243182,.83068,.00533754,0,.260728,.815725,.00515487,0,.278837,.802321,.0049655,0,.297515,.787826,.00475421,0,.316768,.773454,.00456002,0,.336605,.758224,.00434727,0,.357034,.74265,.00414444,0,.378067,.726729,.00393738,0,.399717,.710155,.00373575,0,.421998,.693312,.00353736,0,.444928,.67653,.00334368,0,.468523,.659444,.00315981,0,.492806,.642051,.00297809,0,.517798,.625758,.00280592,0,.543525,.609615,.00264254,0,.570012,.592919,.00248459,0,.597288,.576298,.00233327,0,.625379,.559489,.00219519,0,.654307,.542891,.00205441,0,.684084,.526255,.00193385,0,.714693,.509853,.00180745,0,.746044,.494131,.00169817,0,.777778,.478114,.0015913,0,.809524,.462274,.00148981,0,.84127,.446412,.00139537,0,.873016,.431274,.00130984,0,.904762,.41635,.00122403,0,.936508,.401476,.00114809,0,.968254,.386993,.00107563,0,1,1,.00488216,0,0,1,.0048822,0,0,1,.00488265,0,0,.999997,.00488463,0,0,.999988,.00488999,0,0,.999974,.00490129,0,0,.999946,.00492191,0,0,.999897,.00495598,0,0,.999825,.00500855,0,744791e-10,.999718,.00508559,0,712744e-9,.999565,.005194,0,.00215249,.999352,.00534147,0,.00444576,.999046,.00553523,0,.00759218,.998492,.00577016,0,.0115714,.995564,.00578487,0,.0163557,.993339,.00586414,0,.021915,.991834,.00606002,0,.0282201,.990496,.00633312,0,.0352433,.987826,.00651941,0,.042959,.98383,.00660842,0,.0513439,.98109,.00685523,0,.0603772,.976131,.00695778,0,.0700402,.971922,.00714236,0,.0803163,.965901,.00721437,0,.0911908,.959606,.00732017,0,.102651,.952504,.00735788,0,.114686,.944365,.00738493,0,.127286,.935652,.00737969,0,.140443,.925813,.00733612,0,.154151,.914397,.00723094,0,.168405,.903257,.00714002,0,.183201,.890015,.00700149,0,.198536,.876014,.00682813,0,.214409,.861436,.00665567,0,.23082,.845752,.00644526,0,.24777,.829169,.00621635,0,.265263,.813435,.00597789,0,.283301,.799701,.00575694,0,.301889,.785726,.00549866,0,.321035,.77152,.0052503,0,.340746,.75683,.00499619,0,.361032,.741951,.0047543,0,.381904,.726367,.0045084,0,.403374,.710537,.00426784,0,.425457,.693965,.00403487,0,.448169,.677724,.0038075,0,.47153,.66117,.00359431,0,.495561,.644274,.00338354,0,.520284,.627449,.00318163,0,.545725,.611645,.00299672,0,.571911,.595614,.00281016,0,.598873,.579426,.00264252,0,.62664,.563016,.00247509,0,.655239,.546728,.00232647,0,.684692,.530539,.00217803,0,.714999,.514164,.00204216,0,.746106,.498344,.00191403,0,.777778,.482957,.00179203,0,.809524,.467336,.00167695,0,.84127,.451994,.00157567,0,.873016,.436514,.00147113,0,.904762,.42178,.00138034,0,.936508,.407271,.00129219,0,.968254,.392822,.0012098,0,1,1,.00637427,0,0,1,.00637431,0,0,.999999,.00637485,0,0,.999996,.00637721,0,0,.999987,.00638357,0,0,.999971,.006397,0,0,.999939,.00642142,0,0,.999888,.00646177,0,0,.999807,.00652387,0,207916e-9,.999689,.00661454,0,.00112051,.99952,.00674155,0,.00287719,.999283,.00691313,0,.00550145,.998936,.00713598,0,.00897928,.998165,.00738501,0,.0132829,.994847,.00734388,0,.01838,.993182,.00749991,0,.0242381,.991665,.0077246,0,.030826,.989708,.00797579,0,.0381152,.986663,.00813011,0,.0460794,.983288,.00830365,0,.0546951,.980104,.00853496,0,.0639411,.974855,.00861045,0,.0737988,.97045,.00879133,0,.0842516,.964509,.00886377,0,.0952848,.957594,.00890346,0,.106886,.950546,.00893289,0,.119044,.942225,.00890074,0,.131749,.933365,.00886826,0,.144994,.923202,.0087316,0,.158772,.912605,.00863082,0,.173078,.901099,.00847403,0,.187908,.888177,.00825838,0,.203261,.873955,.00801834,0,.219134,.860091,.00779026,0,.235527,.84434,.00752478,0,.252443,.828517,.00724074,0,.269883,.81239,.00693769,0,.287851,.79721,.00664817,0,.306352,.783489,.00634763,0,.325393,.769514,.00604221,0,.344981,.755419,.00573568,0,.365126,.741083,.00544359,0,.385839,.726059,.00515515,0,.407132,.710809,.00487139,0,.42902,.695052,.00459846,0,.45152,.678886,.00433412,0,.474651,.663042,.00407981,0,.498433,.646634,.00384264,0,.52289,.630117,.00360897,0,.548048,.613804,.00338863,0,.573936,.598338,.00318486,0,.600584,.582687,.00298377,0,.628027,.566809,.00280082,0,.656295,.550817,.00262255,0,.685417,.534937,.00245835,0,.715406,.519151,.00230574,0,.74624,.503118,.0021549,0,.777778,.487723,.00202008,0,.809524,.472725,.00189355,0,.84127,.457599,.00177108,0,.873016,.442558,.00165843,0,.904762,.427624,.00155494,0,.936508,.413171,.00145273,0,.968254,.399122,.00136454,0,1,1,.00826496,0,0,1,.00826499,0,0,1,.00826564,0,0,.999996,.00826842,0,0,.999987,.00827589,0,0,.999967,.00829167,0,0,.999933,.00832037,0,0,.999876,.00836768,0,109338e-10,.999786,.00844031,0,427145e-9,.999655,.00854603,0,.0016384,.999468,.00869337,0,.00372392,.999203,.008891,0,.00668513,.998803,.00914387,0,.0104968,.99748,.00935838,0,.015125,.994446,.00933309,0,.0205338,.99292,.00953084,0,.0266884,.991414,.0097893,0,.0335565,.989049,.0100228,0,.0411086,.98582,.0101664,0,.0493181,.982441,.0103582,0,.0581613,.978595,.0105292,0,.0676169,.973495,.0106274,0,.0776661,.968405,.0107261,0,.0882926,.962717,.0108234,0,.0994817,.955478,.0108102,0,.111221,.948275,.0107914,0,.123499,.940006,.0107161,0,.136308,.930831,.0106309,0,.149639,.920648,.0104083,0,.163485,.910205,.0102312,0,.177843,.898445,.0100051,0,.192707,.885986,.00971928,0,.208077,.872204,.00940747,0,.22395,.858436,.0091085,0,.240326,.843454,.00876595,0,.257208,.827437,.00839794,0,.274596,.811488,.00803692,0,.292496,.796039,.00767352,0,.310911,.781083,.0073097,0,.329849,.767642,.00694032,0,.349316,.753901,.00657476,0,.369323,.740131,.00622699,0,.38988,.725845,.0058838,0,.410999,.710991,.00555586,0,.432696,.696002,.00523089,0,.454987,.680461,.00492494,0,.47789,.664875,.00463464,0,.501426,.649273,.00435422,0,.52562,.63302,.0040875,0,.550498,.61705,.00384075,0,.576089,.601154,.00359557,0,.602427,.586008,.00337636,0,.629544,.570699,.00316019,0,.657479,.555166,.00296033,0,.686264,.539645,.00277552,0,.715924,.524159,.00259499,0,.746459,.508682,.00243257,0,.777789,.493163,.00227851,0,.809524,.478004,.00213083,0,.84127,.46347,.00199502,0,.873016,.448778,.00186967,0,.904762,.434105,.00174732,0,.936508,.419576,.00163861,0,.968254,.405541,.00153341,0,1,1,.0106462,0,0,1,.0106462,0,0,.999999,.010647,0,0,.999995,.0106502,0,0,.999985,.0106589,0,0,.999964,.0106773,0,0,.999925,.0107106,0,0,.999861,.0107655,0,712986e-10,.999763,.0108497,0,743959e-9,.999616,.0109716,0,.00227361,.999408,.0111408,0,.0046983,.999112,.0113659,0,.00800158,.998637,.0116475,0,.0121493,.996223,.0117231,0,.0171023,.994006,.0118064,0,.0228218,.992444,.0120254,0,.0292711,.991028,.0123314,0,.036417,.98803,.0124954,0,.0442295,.984816,.0126538,0,.0526815,.981399,.0128537,0,.0617492,.977085,.0129694,0,.0714114,.972154,.013091,0,.0816495,.966617,.0131166,0,.0924472,.960628,.0131583,0,.10379,.953295,.0131094,0,.115665,.94575,.0129966,0,.128062,.937654,.0128796,0,.140972,.927716,.0126477,0,.154387,.917932,.0123889,0,.168301,.907719,.012131,0,.182709,.89584,.0118013,0,.197608,.883526,.0114145,0,.212994,.870301,.0110075,0,.228867,.856272,.0106019,0,.245227,.842251,.0101938,0,.262074,.826466,.00973254,0,.279412,.810859,.0092846,0,.297244,.795051,.00883304,0,.315575,.780053,.00840272,0,.334412,.76575,.00796438,0,.35376,.752298,.00752526,0,.373631,.739153,.00711486,0,.394034,.725514,.00670361,0,.414983,.711473,.00632656,0,.436491,.696936,.00595206,0,.458575,.682126,.00559191,0,.481253,.667027,.00525362,0,.504547,.651875,.00493805,0,.528481,.636463,.00462848,0,.553081,.620641,.00433936,0,.578377,.604931,.00407,0,.604404,.589549,.00380864,0,.631197,.574712,.00357049,0,.658795,.559775,.00334466,0,.687238,.544514,.00312505,0,.716559,.529555,.00293199,0,.746776,.514402,.00274204,0,.777849,.499302,.00256647,0,.809524,.484114,.00239901,0,.84127,.469308,.00225148,0,.873016,.455133,.00210178,0,.904762,.440939,.0019727,0,.936508,.426627,.00184382,0,.968254,.412509,.00172548,0,1,1,.013628,0,0,1,.0136281,0,0,.999999,.0136289,0,0,.999995,.0136327,0,0,.999983,.0136427,0,0,.99996,.0136638,0,0,.999917,.0137022,0,0,.999846,.0137652,0,204597e-9,.999736,.0138615,0,.00116837,.999573,.0140007,0,.00303325,.99934,.0141927,0,.00580613,.999004,.0144457,0,.00945626,.998407,.0147489,0,.0139421,.995464,.014731,0,.0192202,.993328,.0148283,0,.0252495,.991799,.0150797,0,.0319921,.990397,.0154316,0,.0394138,.986835,.0155005,0,.0474843,.983938,.0157308,0,.0561763,.980154,.0158753,0,.0654661,.975659,.0159581,0,.0753326,.970171,.0159832,0,.0857571,.964803,.0160084,0,.0967236,.958366,.0159484,0,.108218,.950613,.0158001,0,.120227,.942874,.0155845,0,.132741,.935005,.0154292,0,.145751,.924991,.0150742,0,.159249,.914814,.0146757,0,.17323,.904743,.0143097,0,.187687,.893216,.0138695,0,.202619,.880769,.0133706,0,.218021,.868136,.0128606,0,.233894,.85469,.0123403,0,.250238,.840593,.0118091,0,.267052,.825808,.011253,0,.284341,.81009,.0107099,0,.302106,.79504,.0101636,0,.320354,.779757,.00964041,0,.33909,.764697,.00911896,0,.358322,.750913,.00859533,0,.378059,.738175,.00811592,0,.398311,.725242,.00764504,0,.41909,.711864,.00718885,0,.440412,.698009,.00675843,0,.462292,.683841,.00634984,0,.484748,.669391,.00595502,0,.507802,.654731,.00558671,0,.531477,.639805,.00523578,0,.555802,.624789,.00490834,0,.580805,.609325,.00459448,0,.606522,.593975,.00430342,0,.63299,.578983,.00403019,0,.66025,.564442,.0037707,0,.688346,.549835,.0035316,0,.717319,.535039,.00330255,0,.7472,.520403,.00308932,0,.777982,.505687,.00289335,0,.809524,.490939,.00270818,0,.84127,.476233,.0025343,0,.873016,.461624,.00237097,0,.904762,.447833,.00222065,0,.936508,.433992,.00207561,0,.968254,.420147,.00194955,0,1,1,.0173415,0,0,1,.0173416,0,0,.999999,.0173426,0,0,.999995,.0173468,0,0,.999983,.0173582,0,0,.999954,.0173822,0,0,.999908,.0174258,0,669501e-11,.999828,.0174973,0,427399e-9,.999705,.0176063,0,.00171019,.999524,.0177631,0,.0039248,.999263,.0179781,0,.00705382,.998878,.018258,0,.0110552,.998012,.0185551,0,.0158812,.994614,.0184264,0,.0214852,.993132,.0186385,0,.0278239,.991563,.0189067,0,.0348585,.989298,.0191577,0,.0425544,.986036,.0192522,0,.050881,.982558,.0194063,0,.059811,.978531,.019486,0,.0693209,.974198,.0195847,0,.0793895,.968148,.0194749,0,.0899984,.962565,.0194277,0,.101132,.956041,.0192991,0,.112775,.947749,.0189893,0,.124917,.94018,.018704,0,.137547,.93165,.0183458,0,.150655,.921798,.0178775,0,.164236,.911573,.0173618,0,.178281,.901569,.0168482,0,.192788,.890341,.016265,0,.207752,.877835,.0156199,0,.223171,.865472,.0149516,0,.239044,.852905,.0143274,0,.255371,.838906,.0136643,0,.272153,.824888,.0129903,0,.289393,.809977,.0123218,0,.307093,.794697,.0116572,0,.325259,.780028,.0110307,0,.343896,.765124,.0104236,0,.363012,.750411,.0098219,0,.382617,.737264,.00924397,0,.402719,.724799,.00868719,0,.423332,.712253,.00816476,0,.444469,.699267,.00767262,0,.466146,.685618,.00719746,0,.488383,.671736,.00673916,0,.511199,.657777,.00631937,0,.534618,.643497,.00592411,0,.558668,.62889,.00553928,0,.58338,.614299,.0051934,0,.608787,.599197,.00485985,0,.634929,.584175,.00454357,0,.661849,.569541,.00425787,0,.689594,.555193,.00397905,0,.718211,.540947,.00372364,0,.747742,.526593,.00348599,0,.778205,.512335,.00326103,0,.80953,.498017,.00305137,0,.84127,.483609,.00285485,0,.873016,.469368,.00267472,0,.904762,.455037,.00249945,0,.936508,.441493,.00234792,0,.968254,.428147,.00219936,0,1,1,.0219422,0,0,1,.0219423,0,0,.999998,.0219434,0,0,.999993,.0219481,0,0,.999981,.021961,0,0,.999949,.0219879,0,0,.999896,.0220367,0,593194e-10,.999808,.0221167,0,75364e-8,.99967,.0222383,0,.00237884,.999466,.0224125,0,.00495612,.999174,.0226495,0,.00844887,.998725,.0229525,0,.0128058,.996979,.0231123,0,.0179742,.994317,.0230742,0,.0239047,.992781,.0232895,0,.0305526,.991191,.0235734,0,.0378786,.987787,.0236152,0,.0458475,.985092,.0237994,0,.0544287,.981121,.0238553,0,.0635952,.976924,.0238706,0,.0733233,.97218,.0238704,0,.0835922,.965956,.0236598,0,.0943839,.959998,.0234735,0,.105682,.953245,.0232277,0,.117474,.944445,.0226973,0,.129747,.937087,.0223527,0,.142491,.928341,.0218144,0,.155697,.9184,.0211516,0,.169358,.907959,.0204553,0,.183469,.89808,.0197673,0,.198024,.887047,.0189915,0,.21302,.875221,.0182082,0,.228455,.86269,.0173584,0,.244329,.850735,.0165718,0,.260639,.837545,.0157524,0,.277389,.823639,.0149482,0,.29458,.809699,.0141431,0,.312216,.794797,.0133527,0,.3303,.780578,.0126193,0,.34884,.766019,.0118914,0,.367842,.751447,.0111839,0,.387315,.737275,.010514,0,.40727,.724545,.00987277,0,.427717,.712644,.00926569,0,.448671,.700432,.00869029,0,.470149,.687664,.00814691,0,.492167,.674288,.00763012,0,.514746,.660966,.00714437,0,.537911,.647264,.00668457,0,.561688,.633431,.00626581,0,.586108,.619133,.00585593,0,.611206,.604935,.00548188,0,.637022,.590236,.00513288,0,.663599,.575473,.0047906,0,.690989,.561228,.00448895,0,.719242,.547054,.00420233,0,.748411,.533175,.00392869,0,.778531,.519163,.00367445,0,.809583,.505328,.00344097,0,.84127,.491446,.00322003,0,.873016,.477356,.00301283,0,.904762,.46356,.00282592,0,.936508,.449623,.00264956,0,.968254,.436068,.00246956,0,1,1,.0276135,0,0,1,.0276136,0,0,.999998,.0276148,0,0,.999993,.0276201,0,0,.999976,.0276342,0,0,.999945,.027664,0,0,.999884,.0277179,0,18679e-8,.999784,.027806,0,.00119607,.99963,.0279394,0,.00318407,.999401,.0281295,0,.00613601,.999066,.0283858,0,.00999963,.998524,.0287027,0,.0147164,.995702,.0286256,0,.0202295,.993593,.0286733,0,.0264876,.992067,.0288989,0,.0334452,.990548,.0292135,0,.0410621,.986775,.0291296,0,.0493032,.984054,.0293099,0,.0581381,.979481,.0291881,0,.0675397,.975297,.0291598,0,.0774848,.96981,.028954,0,.0879528,.963524,.028628,0,.0989258,.957398,.0283135,0,.110388,.950088,.0278469,0,.122327,.941538,.0271798,0,.134729,.933332,.0265388,0,.147587,.924392,.0257776,0,.160889,.914581,.024916,0,.174631,.904347,.0240242,0,.188806,.894324,.0231229,0,.203409,.883724,.022153,0,.218437,.872207,.0211355,0,.233888,.859927,.0201048,0,.249761,.848373,.0191263,0,.266056,.836023,.0181306,0,.282774,.82289,.0171718,0,.299917,.809324,.0162196,0,.317488,.795361,.0152622,0,.335493,.781253,.01439,0,.353936,.767338,.013533,0,.372825,.753156,.0127244,0,.392168,.739122,.0119454,0,.411976,.725358,.0112054,0,.432259,.712949,.010487,0,.453032,.701621,.00984032,0,.47431,.689703,.00921495,0,.496111,.677216,.00862492,0,.518456,.664217,.00806882,0,.541367,.65137,.00755922,0,.564872,.638,.00705705,0,.589001,.62453,.00661266,0,.613789,.610601,.00618432,0,.639277,.59676,.00578033,0,.66551,.582433,.00540927,0,.692539,.568026,.00506104,0,.720422,.55414,.0047353,0,.749216,.540178,.00442889,0,.778974,.526513,.00414363,0,.809711,.512954,.00388237,0,.84127,.499403,.00362875,0,.873016,.486026,.00340827,0,.904762,.472345,.00318598,0,.936508,.458828,.00297635,0,.968254,.445379,.00279447,0,1,1,.0345716,0,0,1,.0345717,0,0,.999999,.034573,0,0,.999991,.0345787,0,0,.999974,.0345941,0,0,.999937,.0346263,0,188589e-11,.999869,.0346847,0,409238e-9,.999757,.0347798,0,.0017674,.999582,.0349233,0,.00413658,.999322,.0351265,0,.00747408,.998939,.0353967,0,.0117157,.998219,.0357018,0,.0167966,.994974,.0354726,0,.0226572,.993201,.0355621,0,.0292445,.991573,.0357641,0,.0365123,.989301,.0359252,0,.0444203,.985712,.0358017,0,.0529334,.982411,.0358353,0,.0620214,.977827,.035617,0,.0716574,.973278,.0354398,0,.0818186,.967397,.0350483,0,.0924846,.960696,.0344795,0,.103638,.954349,.0339861,0,.115263,.946066,.0331323,0,.127348,.938012,.032359,0,.13988,.929413,.0314413,0,.152849,.920355,.0304103,0,.166248,.910586,.0292785,0,.18007,.900609,.0281391,0,.194308,.890093,.0269103,0,.208958,.880013,.0257269,0,.224018,.869001,.0244671,0,.239485,.85751,.0232252,0,.255359,.84582,.0220117,0,.271638,.834383,.0208274,0,.288324,.822158,.0196628,0,.305419,.809056,.0185306,0,.322927,.795832,.0174174,0,.340851,.782547,.0163758,0,.359199,.7689,.015391,0,.377975,.755526,.0144488,0,.397189,.741681,.0135372,0,.416851,.728178,.0126957,0,.436971,.714642,.0118812,0,.457564,.702756,.0111165,0,.478644,.69175,.0104145,0,.500229,.680159,.00974439,0,.522339,.668073,.00911926,0,.544997,.655405,.00851393,0,.56823,.642921,.00797637,0,.592068,.629993,.00745119,0,.616546,.616828,.00696972,0,.641705,.603305,.00652425,0,.66759,.589833,.00610188,0,.694255,.575945,.00570834,0,.72176,.561745,.00533384,0,.750168,.548277,.00500001,0,.779545,.534467,.00467582,0,.809933,.521032,.00438092,0,.841272,.507877,.00410348,0,.873016,.494654,.00383618,0,.904762,.481592,.00358699,0,.936508,.468509,.00337281,0,.968254,.455293,.00316196,0,1,1,.0430698,0,0,1,.0430699,0,0,.999998,.0430713,0,0,.999991,.0430773,0,0,.99997,.0430936,0,0,.999928,.0431277,0,406396e-10,.999852,.0431893,0,744376e-9,.999724,.0432895,0,.0024806,.999527,.0434397,0,.00524779,.99923,.0436507,0,.00898164,.998783,.0439255,0,.0136083,.997507,.0441104,0,.0190582,.994418,.0438225,0,.0252694,.992864,.0439396,0,.0321879,.991127,.0440962,0,.039767,.987331,.0438408,0,.0479667,.984819,.0438991,0,.056752,.980384,.0435906,0,.0660929,.975846,.0432543,0,.075963,.970748,.0428293,0,.0863398,.964303,.042153,0,.0972035,.95772,.0414111,0,.108537,.950747,.0405893,0,.120325,.942533,.0394887,0,.132554,.934045,.0383544,0,.145215,.924942,.037057,0,.158296,.915811,.0356993,0,.17179,.90612,.0342401,0,.185691,.896434,.0328078,0,.199993,.886021,.031288,0,.214691,.876081,.0297776,0,.229782,.865608,.0282334,0,.245265,.854924,.026749,0,.261138,.843607,.02526,0,.277401,.832456,.0238214,0,.294056,.821342,.0224682,0,.311104,.809303,.0211297,0,.328548,.796468,.0198387,0,.346394,.784046,.0186227,0,.364645,.771262,.0174561,0,.38331,.758118,.0163806,0,.402396,.745075,.0153287,0,.421912,.731926,.0143647,0,.44187,.71863,.0134363,0,.462283,.705414,.0125603,0,.483165,.693792,.0117508,0,.504535,.683108,.0110016,0,.52641,.67183,.0102757,0,.548816,.66015,.00962044,0,.571776,.647907,.00898031,0,.595323,.635734,.00840811,0,.619489,.623208,.00786211,0,.644317,.610438,.00734953,0,.669852,.597345,.00687688,0,.696148,.584138,.00643469,0,.723267,.5707,.00602236,0,.75128,.556966,.0056324,0,.780258,.543607,.00528277,0,.810268,.530213,.00493999,0,.841311,.516912,.00462265,0,.873016,.503916,.0043307,0,.904762,.491146,.00406858,0,.936508,.478439,.00381436,0,.968254,.465834,.00358003,0,1,1,.0534039,0,0,1,.053404,0,0,.999998,.0534055,0,0,.999989,.0534116,0,0,.999968,.0534283,0,0,.999918,.0534633,0,155895e-9,.99983,.0535262,0,.00120914,.999685,.0536281,0,.00334944,.999461,.0537799,0,.00653077,.999119,.0539902,0,.0106718,.998582,.0542524,0,.0156907,.995919,.0540318,0,.0215147,.993735,.0538914,0,.0280801,.992126,.0539557,0,.0353323,.990266,.0540401,0,.0432247,.986317,.0536064,0,.0517172,.983213,.0534425,0,.0607754,.978303,.0528622,0,.0703698,.973665,.0523363,0,.0804742,.968091,.0516165,0,.0910667,.961026,.0505434,0,.102128,.954333,.049523,0,.113641,.946372,.0481698,0,.125591,.938254,.0467674,0,.137965,.929516,.0452341,0,.150754,.920106,.0435083,0,.163947,.910899,.0417399,0,.177537,.901532,.0399389,0,.191516,.891919,.0380901,0,.205881,.882006,.0362341,0,.220626,.871965,.0343444,0,.235749,.862145,.0324832,0,.251248,.852058,.0306681,0,.267121,.84161,.0289097,0,.283368,.830806,.0272079,0,.299992,.820476,.0256089,0,.316992,.809514,.0240394,0,.334374,.797865,.0225379,0,.35214,.785621,.0211235,0,.370296,.773765,.0197908,0,.388849,.761629,.0185235,0,.407807,.748891,.0173358,0,.427178,.736437,.0162305,0,.446974,.723707,.0151778,0,.467207,.710606,.0141791,0,.487892,.698019,.0132592,0,.509046,.686203,.0123887,0,.530687,.675692,.0115976,0,.552839,.664826,.0108325,0,.575527,.65349,.0101348,0,.59878,.641774,.00947756,0,.622634,.629794,.00886058,0,.647128,.617647,.00828526,0,.672308,.60534,.00775312,0,.698231,.592718,.00726033,0,.724958,.579746,.00679731,0,.752563,.566763,.00636111,0,.781127,.553515,.00595228,0,.810733,.540118,.00556876,0,.841426,.527325,.00523051,0,.873016,.514265,.00490712,0,.904762,.501406,.00460297,0,.936508,.488922,.00431247,0,.968254,.476541,.0040472,0,1,1,.0659184,0,0,1,.0659185,0,0,.999998,.06592,0,0,.999988,.0659259,0,0,.999963,.0659423,0,0,.999907,.0659764,0,374198e-9,.999806,.0660376,0,.00182071,.999639,.0661361,0,.0043894,.999378,.0662814,0,.00800055,.998985,.0664779,0,.0125594,.998285,.0666914,0,.0179786,.995071,.0661989,0,.0241822,.993172,.0660454,0,.031106,.991438,.0660105,0,.0386952,.988428,.0656875,0,.0469032,.985218,.0652913,0,.0556905,.981128,.0647107,0,.065023,.976015,.0638491,0,.0748717,.97097,.062993,0,.0852112,.964582,.0617927,0,.0960199,.957383,.0603626,0,.107279,.949969,.0588128,0,.118971,.941843,.0570274,0,.131084,.933624,.0551885,0,.143604,.924543,.053122,0,.156521,.914919,.0508897,0,.169825,.905773,.0486418,0,.18351,.896434,.0463364,0,.197569,.887195,.0440623,0,.211997,.877706,.0417799,0,.226789,.867719,.03945,0,.241944,.858587,.037243,0,.257458,.849317,.0350956,0,.273331,.839585,.0329852,0,.289563,.829856,.0310028,0,.306154,.819589,.0290953,0,.323108,.809714,.0272738,0,.340426,.79934,.0255631,0,.358113,.788224,.0239175,0,.376175,.776619,.0223831,0,.394616,.76521,.0209298,0,.413445,.753716,.0195786,0,.432671,.741564,.0183001,0,.452305,.729413,.0171259,0,.472358,.717146,.0159933,0,.492845,.70436,.0149495,0,.513783,.69219,.0139681,0,.535189,.680289,.0130577,0,.557087,.669611,.0122198,0,.5795,.659113,.0114174,0,.602459,.648148,.0106729,0,.625997,.636905,.00998997,0,.650154,.625154,.00934313,0,.674976,.613481,.00874839,0,.700518,.60154,.00818265,0,.726845,.58943,.00766889,0,.754032,.576828,.00717153,0,.782167,.564194,.00672696,0,.811344,.551501,.00630863,0,.841644,.538635,.00592177,0,.873016,.525724,.00554888,0,.904762,.513209,.00520225,0,.936508,.500457,.00488231,0,.968254,.48799,.00457153,0,1,1,.0810131,0,0,1,.0810133,0,0,.999997,.0810145,0,0,.999985,.08102,0,0,.999956,.0810347,0,195026e-10,.999893,.0810656,0,719316e-9,.999777,.0811205,0,.00259774,.999583,.081208,0,.00561807,.999281,.0813343,0,.00967472,.998813,.0814969,0,.0146627,.997597,.0815217,0,.0204902,.994379,.0808502,0,.0270802,.992744,.0806792,0,.0343674,.990745,.0804589,0,.0422974,.986646,.0796107,0,.0508242,.983611,.0790913,0,.0599087,.978869,.0780746,0,.0695175,.973475,.0768218,0,.0796223,.967845,.0754926,0,.0901983,.960778,.0737063,0,.101224,.953333,.0718052,0,.112682,.945274,.0695946,0,.124555,.936955,.0672492,0,.136831,.928319,.0647732,0,.149496,.919075,.0620947,0,.162542,.909114,.0591816,0,.175958,.900137,.0563917,0,.189739,.891069,.0535392,0,.203877,.882262,.0507642,0,.218368,.873232,.0479793,0,.233208,.864042,.045226,0,.248393,.855002,.0425413,0,.263923,.846569,.0400126,0,.279796,.837714,.0375269,0,.296012,.828918,.0352027,0,.312573,.819783,.0330011,0,.329479,.810129,.0308908,0,.346734,.800866,.0289112,0,.364342,.79093,.0270255,0,.382307,.780593,.0252758,0,.400637,.769511,.0236178,0,.419337,.758558,.0220652,0,.438418,.747632,.0206289,0,.457889,.736146,.0192873,0,.477761,.724093,.0180333,0,.49805,.71234,.0168264,0,.51877,.700201,.015746,0,.53994,.687949,.0147027,0,.561581,.676163,.0137512,0,.583718,.665001,.0128655,0,.60638,.65472,.0120366,0,.629599,.644213,.0112604,0,.653415,.633382,.0105413,0,.677874,.62212,.00986498,0,.70303,.610631,.00923308,0,.728948,.599078,.00864206,0,.755706,.587519,.00811784,0,.783396,.575505,.00761237,0,.812121,.563148,.00713949,0,.841989,.550828,.00668379,0,.873035,.538458,.00627715,0,.904762,.525905,.00588336,0,.936508,.513517,.00552687,0,.968254,.501395,.00519681,0,1,1,.0991506,0,0,1,.0991504,0,0,.999996,.0991515,0,0,.999984,.0991558,0,0,.999947,.0991672,0,114389e-9,.999874,.0991912,0,.00121503,.999739,.0992331,0,.00356108,.999514,.0992983,0,.00705578,.999159,.0993877,0,.011574,.998586,.0994837,0,.017003,.995731,.0988425,0,.0232484,.993384,.098276,0,.0302318,.991615,.0979269,0,.0378884,.989029,.0973432,0,.0461641,.985373,.0963539,0,.0550136,.981278,.0952306,0,.0643988,.975777,.0936233,0,.0742868,.970526,.0920219,0,.0846501,.963755,.0898912,0,.0954644,.956676,.0876064,0,.106709,.948099,.0847751,0,.118367,.939718,.0818638,0,.130423,.931305,.078857,0,.142862,.922342,.0756127,0,.155674,.912842,.0721473,0,.168849,.903304,.0686195,0,.182378,.89411,.0650589,0,.196255,.885512,.0616022,0,.210473,.877193,.0582434,0,.225027,.86877,.0548979,0,.239915,.860267,.0516095,0,.255132,.851915,.048468,0,.270678,.843912,.0454447,0,.286551,.83604,.0425612,0,.302751,.828245,.0398752,0,.31928,.820159,.0373198,0,.336138,.81167,.034916,0,.35333,.802659,.0326402,0,.370858,.793921,.0304901,0,.388728,.784713,.0284857,0,.406944,.774946,.0266186,0,.425515,.76448,.0248593,0,.444449,.753793,.0232114,0,.463756,.743506,.0217039,0,.483447,.732555,.0202841,0,.503535,.720965,.0189648,0,.524036,.709422,.0177189,0,.544968,.697756,.0165626,0,.56635,.685565,.015483,0,.588208,.673987,.0144892,0,.610569,.66244,.0135607,0,.633466,.651675,.0126956,0,.656936,.641598,.0118788,0,.681025,.63121,.0111261,0,.705788,.620514,.010437,0,.731289,.609366,.00978747,0,.757606,.598137,.00917257,0,.784834,.586966,.00859778,0,.813085,.575549,.00806803,0,.842485,.563797,.00757294,0,.87313,.551758,.00710592,0,.904762,.539894,.0066841,0,.936508,.527901,.00627901,0,.968254,.515819,.00590506,0,1,1,.120864,0,0,1,.120864,0,0,.999996,.120864,0,0,.99998,.120867,0,0,.99994,.120872,0,323781e-9,.999852,.120884,0,.00188693,.999693,.120903,0,.00473489,.999426,.120929,0,.00872704,.999002,.120955,0,.0137237,.998235,.120918,0,.0196068,.994608,.119764,0,.0262803,.992997,.119265,0,.0336657,.990968,.11863,0,.0416987,.987002,.117261,0,.0503261,.983524,.116009,0,.0595035,.97875,.114252,0,.0691935,.972652,.11193,0,.0793645,.966613,.109555,0,.0899894,.959275,.106612,0,.101045,.951272,.103375,0,.112512,.942323,.0996594,0,.124372,.933679,.0958841,0,.136611,.924822,.0919265,0,.149216,.915742,.0878061,0,.162176,.906348,.0834894,0,.175482,.896883,.079085,0,.189125,.88774,.0746745,0,.203098,.87986,.0705773,0,.217396,.871998,.0665005,0,.232015,.864325,.0625413,0,.24695,.856685,.0586781,0,.2622,.84925,.0550063,0,.277761,.841719,.0514727,0,.293634,.834755,.0481398,0,.309819,.827853,.0450172,0,.326315,.820888,.0420969,0,.343126,.813616,.0393702,0,.360254,.805767,.0367771,0,.377701,.797338,.0343274,0,.395474,.789122,.0320529,0,.413577,.780601,.0299485,0,.432018,.771424,.0279812,0,.450804,.761502,.0261054,0,.469944,.751166,.0243942,0,.489451,.741276,.0228087,0,.509337,.730898,.0213265,0,.529617,.719878,.0199307,0,.550307,.708379,.0186574,0,.571428,.697165,.0174446,0,.593003,.685554,.0163144,0,.615059,.673631,.015276,0,.637628,.662385,.0143003,0,.660746,.651059,.0134112,0,.68446,.640451,.0125794,0,.70882,.630536,.011793,0,.733893,.620316,.0110547,0,.759756,.609722,.0103668,0,.786505,.598804,.00973009,0,.814259,.587871,.00912812,0,.843157,.577121,.00858916,0,.87334,.566019,.00807333,0,.904762,.554664,.00759687,0,.936508,.543101,.00714759,0,.968254,.531558,.00673418,0,1,1,.146767,0,0,1,.146767,0,0,.999997,.146767,0,0,.999977,.146765,0,320658e-11,.999929,.146762,0,682576e-9,.999823,.146753,0,.00276402,.999633,.146735,0,.00614771,.999314,.146699,0,.0106613,.998796,.14662,0,.0161546,.997124,.146107,0,.0225063,.994062,.144857,0,.0296198,.992154,.144011,0,.037417,.989186,.142712,0,.0458348,.985279,.140926,0,.0548211,.980826,.13885,0,.0643326,.975056,.136168,0,.074333,.969005,.133217,0,.0847917,.961554,.12959,0,.0956828,.954206,.125886,0,.106984,.945046,.121335,0,.118675,.935678,.116492,0,.130741,.926748,.111635,0,.143166,.917764,.106625,0,.155939,.908358,.101325,0,.169049,.899219,.0960249,0,.182487,.890089,.0906527,0,.196245,.881488,.0853905,0,.210317,.874031,.0804177,0,.224697,.866932,.0756005,0,.23938,.859976,.0709019,0,.254364,.853375,.0664391,0,.269646,.846971,.0622012,0,.285223,.840483,.058129,0,.301096,.833969,.0542762,0,.317265,.82806,.0507042,0,.333729,.822128,.047368,0,.350491,.815989,.044272,0,.367554,.809336,.0413444,0,.38492,.802177,.038601,0,.402594,.79441,.0360227,0,.420582,.786573,.0336383,0,.438891,.778619,.0314321,0,.457527,.77,.029362,0,.476499,.760698,.0274102,0,.49582,.750932,.0256146,0,.5155,.740993,.023974,0,.535555,.731159,.0224182,0,.556,.720836,.0209889,0,.576855,.709913,.0196411,0,.598143,.698415,.0183824,0,.619888,.68745,.0172222,0,.642123,.676154,.0161509,0,.664883,.664383,.0151397,0,.688211,.6533,.0141873,0,.71216,.642072,.0133105,0,.736792,.631412,.0124932,0,.762186,.621622,.0117408,0,.788439,.611681,.0110358,0,.815672,.60142,.0103775,0,.844034,.59083,.00975623,0,.873699,.580254,.00918084,0,.904765,.569841,.00864721,0,.936508,.559224,.00815731,0,.968254,.548315,.00767924,0,1,1,.177563,0,0,1,.177563,0,0,.999994,.177562,0,0,.999972,.177555,0,664171e-10,.999914,.177536,0,.0012276,.999787,.177496,0,.00388025,.999556,.17742,0,.00783463,.999165,.177285,0,.0128953,.9985,.177037,0,.0189053,.995388,.175634,0,.025742,.993102,.174375,0,.033309,.990992,.173121,0,.0415298,.986932,.170896,0,.0503425,.982786,.16847,0,.0596964,.977592,.165455,0,.0695498,.971075,.161676,0,.0798676,.963967,.157458,0,.0906201,.956397,.152836,0,.101783,.947489,.147467,0,.113333,.937564,.14145,0,.125254,.928182,.135383,0,.137529,.919027,.129212,0,.150144,.909618,.12276,0,.163088,.900492,.116273,0,.176351,.891671,.1098,0,.189924,.883146,.103362,0,.203799,.875151,.0970799,0,.21797,.868338,.0911732,0,.232433,.862033,.0854966,0,.247182,.856107,.0800691,0,.262216,.850644,.0749618,0,.27753,.845261,.070079,0,.293124,.839885,.0654321,0,.308997,.834609,.0610975,0,.325149,.829083,.0569741,0,.341581,.82404,.0531736,0,.358294,.818968,.049665,0,.37529,.813496,.0463856,0,.392573,.807533,.0433217,0,.410148,.80099,.0404402,0,.428019,.793891,.0377578,0,.446192,.786281,.0352616,0,.464676,.778773,.0329577,0,.483478,.770737,.030808,0,.502608,.762094,.0287964,0,.522079,.752898,.0269254,0,.541905,.743306,.0251926,0,.5621,.733416,.023595,0,.582684,.723742,.0221155,0,.603677,.713542,.0207435,0,.625106,.702755,.019434,0,.646998,.691484,.0182046,0,.66939,.680531,.0170771,0,.692324,.66953,.0160339,0,.715849,.658126,.0150677,0,.740028,.646933,.0141551,0,.764937,.636107,.0133179,0,.790673,.625271,.0125284,0,.817358,.615225,.0117937,0,.84515,.605678,.0111181,0,.874244,.59583,.0104759,0,.904828,.585704,.00986672,0,.936508,.575413,.00929712,0,.968254,.565373,.00876713,0,1,1,.214058,0,0,.999999,.214058,0,0,.999994,.214055,0,0,.999966,.214039,0,259642e-9,.999893,.213998,0,.00200075,.999737,.21391,0,.00527775,.999449,.213745,0,.00983959,.99896,.213458,0,.0154755,.9979,.212855,0,.0220249,.994278,.210779,0,.0293654,.992254,.20926,0,.0374021,.98881,.206908,0,.0460604,.984715,.204009,0,.0552802,.979738,.200471,0,.0650127,.972884,.195813,0,.0752175,.965996,.190856,0,.0858612,.957974,.185077,0,.0969155,.949155,.17868,0,.108356,.939288,.171513,0,.120163,.928996,.163838,0,.132319,.919563,.156246,0,.144808,.910004,.148359,0,.157618,.900791,.140417,0,.170737,.892135,.132569,0,.184155,.883803,.124741,0,.197866,.876034,.117091,0,.211861,.869219,.109835,0,.226134,.863062,.102859,0,.240682,.857795,.0962928,0,.255499,.853009,.0900725,0,.270583,.848603,.0842101,0,.285931,.844335,.0786527,0,.301542,.840208,.0734397,0,.317415,.836035,.0685334,0,.33355,.83172,.0639275,0,.349948,.827135,.0595909,0,.36661,.822797,.0556204,0,.383539,.818387,.0519394,0,.400738,.813565,.0485317,0,.41821,.808142,.0453138,0,.435961,.802212,.0423354,0,.453997,.79573,.0395553,0,.472324,.788741,.036988,0,.490951,.781093,.0345688,0,.509887,.773597,.0323297,0,.529144,.765622,.0302719,0,.548735,.757083,.0283477,0,.568674,.747992,.0265562,0,.588979,.738591,.0248844,0,.609671,.728719,.0233342,0,.630773,.719146,.0219081,0,.652314,.709165,.0205711,0,.674328,.69875,.0193248,0,.696854,.687884,.0181582,0,.719942,.676818,.0170746,0,.743651,.666247,.0160718,0,.768057,.655284,.0151262,0,.793253,.64401,.0142561,0,.819363,.633353,.0134327,0,.846547,.622674,.012653,0,.875017,.612265,.0119354,0,.905021,.602455,.0112533,0,.936508,.593147,.0106234,0,.968254,.583592,.0100213,0,1,1,.25717,0,0,1,.25717,0,0,.999992,.257164,0,0,.999958,.257135,0,641715e-9,.999864,.25706,0,.00305314,.999666,.256897,0,.00700975,.999302,.256596,0,.0122194,.998663,.25607,0,.0184622,.995607,.254123,0,.0255773,.993094,.252081,0,.0334439,.9907,.249867,0,.0419696,.98594,.246118,0,.0510823,.981214,.242049,0,.0607242,.974966,.236869,0,.0708486,.967589,.230724,0,.081417,.95915,.223635,0,.0923974,.950257,.21596,0,.103763,.940165,.207296,0,.115491,.929396,.197901,0,.127562,.919288,.188437,0,.13996,.909428,.178762,0,.15267,.900105,.169072,0,.165679,.891418,.159478,0,.178979,.883347,.15002,0,.192558,.875992,.140813,0,.20641,.869466,.13196,0,.220529,.863699,.123501,0,.234907,.858553,.115436,0,.249542,.854379,.107901,0,.264428,.850894,.10088,0,.279564,.847632,.0942296,0,.294947,.844571,.0879861,0,.310575,.84163,.0821534,0,.326448,.838542,.0766409,0,.342566,.835412,.0715322,0,.358929,.831899,.0666883,0,.37554,.828177,.0622175,0,.392399,.82416,.0580452,0,.409511,.820393,.054267,0,.426878,.816068,.0507172,0,.444506,.811201,.0474041,0,.4624,.805785,.0443174,0,.480566,.799878,.0414562,0,.499013,.793469,.0388147,0,.517749,.786473,.0363453,0,.536785,.778874,.0340225,0,.556134,.771277,.0318599,0,.575809,.763426,.0298859,0,.595827,.755044,.0280357,0,.616207,.746161,.0262979,0,.636973,.737124,.0247295,0,.65815,.72761,.0232514,0,.679772,.717822,.0218755,0,.701876,.708279,.0205942,0,.724509,.698333,.0193947,0,.74773,.68802,.0182717,0,.771609,.677321,.0172044,0,.79624,.666504,.0162122,0,.821743,.656184,.0152924,0,.84828,.64556,.0144326,0,.876069,.634636,.0136157,0,.905404,.624124,.0128612,0,.936508,.613914,.0121435,0,.968254,.603589,.0114887,0,1,1,.307946,0,0,.999999,.307945,0,0,.999988,.307934,0,204479e-10,.999944,.307886,0,.00127833,.999824,.307756,0,.00445047,.999565,.30748,0,.00914673,.999085,.306966,0,.0150498,.998103,.306004,0,.0219367,.994249,.303028,0,.0296485,.991807,.300435,0,.038068,.987773,.296554,0,.0471062,.982673,.2916,0,.0566942,.976623,.285641,0,.0667768,.968757,.27815,0,.0773099,.959849,.269529,0,.088257,.950663,.260248,0,.0995879,.940129,.249704,0,.111277,.92895,.238291,0,.123304,.917996,.226501,0,.13565,.907813,.214669,0,.148299,.898305,.202835,0,.161237,.889626,.191158,0,.174455,.88175,.179695,0,.187941,.874715,.168548,0,.201687,.868746,.15792,0,.215687,.863703,.147807,0,.229933,.859315,.138149,0,.24442,.855538,.128993,0,.259145,.852428,.120414,0,.274103,.850168,.112498,0,.289293,.848132,.105054,0,.304711,.846291,.0981087,0,.320357,.844431,.0915942,0,.33623,.842493,.0855056,0,.35233,.840368,.0798204,0,.368658,.83798,.0745097,0,.385214,.83523,.0695424,0,.402002,.832091,.0649092,0,.419023,.828667,.0606291,0,.436282,.824805,.0566523,0,.453782,.820988,.0530229,0,.471529,.816635,.0496364,0,.489528,.811725,.0464658,0,.507788,.806316,.0435082,0,.526317,.800469,.0407873,0,.545124,.794107,.038255,0,.564221,.787218,.0358825,0,.583621,.779872,.0336785,0,.603341,.772097,.0316379,0,.623397,.764484,.0297379,0,.643812,.756428,.0279581,0,.664611,.748022,.0263153,0,.685824,.739268,.0247799,0,.707488,.73024,.0233385,0,.729646,.720893,.0220035,0,.752354,.71119,.0207555,0,.77568,.701791,.0195843,0,.799715,.692184,.0184891,0,.824574,.682258,.0174541,0,.850417,.67206,.0164873,0,.877466,.661717,.0155959,0,.90604,.651462,.0147519,0,.936528,.641467,.0139727,0,.968254,.631229,.0132363,0,1,1,.367573,0,0,.999999,.367571,0,0,.999984,.367553,0,183382e-9,.999925,.367473,0,.00225254,.999759,.367259,0,.00628165,.99941,.366801,0,.0117858,.998739,.365946,0,.0184359,.995529,.363191,0,.0260114,.992875,.360171,0,.0343581,.989135,.355981,0,.0433637,.984166,.350401,0,.0529438,.977871,.343348,0,.0630334,.96951,.334341,0,.0735805,.959964,.323862,0,.0845437,.950162,.312521,0,.095889,.938882,.299577,0,.107588,.926992,.285573,0,.119617,.915589,.271212,0,.131957,.904791,.256611,0,.144591,.895177,.242224,0,.157503,.886403,.227952,0,.170682,.878957,.214192,0,.184117,.872418,.200795,0,.197799,.867029,.188015,0,.21172,.862835,.175975,0,.225873,.859411,.164526,0,.240253,.856655,.153693,0,.254854,.854519,.14352,0,.269673,.852828,.13397,0,.284707,.851412,.124984,0,.299953,.850609,.116748,0,.315408,.849855,.10905,0,.331073,.849017,.101839,0,.346946,.848079,.0951359,0,.363028,.846911,.0888774,0,.379318,.845445,.0830375,0,.395818,.84362,.0775844,0,.41253,.841411,.0725054,0,.429457,.838768,.0677691,0,.446602,.835801,.0634016,0,.463968,.832341,.0593095,0,.481561,.828424,.0555121,0,.499386,.824312,.052024,0,.51745,.819918,.0487865,0,.535761,.815072,.0457801,0,.554328,.809863,.0430184,0,.573162,.804164,.0404245,0,.592275,.798034,.0380146,0,.611681,.791436,.0357436,0,.631398,.784498,.0336475,0,.651445,.777125,.0316666,0,.671845,.769365,.0298122,0,.692628,.761579,.0281001,0,.713827,.753746,.0265049,0,.735484,.745573,.0250067,0,.75765,.737083,.0236026,0,.78039,.728545,.0223302,0,.803789,.719691,.0211243,0,.82796,.710569,.0199983,0,.853056,.701216,.0189569,0,.879298,.692094,.0179702,0,.907014,.682909,.0170418,0,.936691,.673509,.0161732,0,.968254,.663863,.0153406,0,1,1,.437395,0,0,.999998,.437394,0,0,.99998,.437363,0,616704e-9,.999891,.437232,0,.00367925,.999656,.436877,0,.00867446,.999148,.436121,0,.0150679,.997959,.434564,0,.022531,.993464,.430134,0,.0308507,.990606,.426077,0,.0398805,.985027,.419397,0,.0495148,.978491,.41118,0,.0596749,.969643,.40048,0,.0703001,.959189,.38769,0,.0813427,.948223,.373575,0,.0927641,.935955,.357622,0,.104533,.923237,.34043,0,.116624,.911074,.322735,0,.129015,.899724,.30479,0,.141687,.890189,.287392,0,.154626,.881796,.270248,0,.167818,.874781,.253659,0,.181252,.869166,.237786,0,.194918,.864725,.222618,0,.208807,.861565,.208356,0,.222913,.859284,.194867,0,.237229,.857677,.18212,0,.25175,.856714,.17018,0,.266473,.856155,.158969,0,.281392,.8558,.148413,0,.296505,.855672,.138578,0,.311811,.855538,.129345,0,.327306,.855689,.120861,0,.342991,.855767,.112969,0,.358864,.855618,.105593,0,.374925,.85525,.0987451,0,.391176,.854583,.0923727,0,.407616,.853534,.0864143,0,.424249,.852061,.0808338,0,.441076,.850253,.0756771,0,.4581,.848004,.0708612,0,.475324,.845333,.0663784,0,.492754,.842376,.0622631,0,.510394,.838956,.0584112,0,.528251,.835121,.0548328,0,.546331,.830842,.0514838,0,.564644,.826212,.048355,0,.583198,.821522,.0454714,0,.602005,.816551,.0428263,0,.621078,.811211,.0403612,0,.640434,.805479,.038039,0,.660089,.799409,.0358739,0,.680066,.79306,.0338727,0,.70039,.786395,.0319985,0,.721094,.779416,.030241,0,.742215,.77214,.0285951,0,.7638,.764636,.0270747,0,.785912,.756836,.0256354,0,.808628,.749315,.0243027,0,.832055,.741561,.0230497,0,.856338,.733589,.0218801,0,.88169,.725479,.020784,0,.908441,.717255,.0197702,0,.937125,.708829,.0188168,0,.968254,.700191,.0179113,0,1,1,.518937,0,0,.999998,.518933,0,0,.999967,.518883,0,.00147741,.999832,.51866,0,.00573221,.999466,.518057,0,.011826,.998644,.516752,0,.0192116,.994458,.512347,0,.027573,.991223,.507675,0,.0367099,.985515,.500188,0,.046487,.978308,.490408,0,.0568071,.968359,.477357,0,.0675984,.95682,.461752,0,.0788059,.943929,.443796,0,.090386,.930224,.423893,0,.102304,.916514,.402682,0,.114532,.903653,.380914,0,.127047,.892315,.359212,0,.139828,.882942,.338102,0,.152861,.875438,.31773,0,.16613,.869642,.298186,0,.179624,.865304,.279491,0,.193332,.862382,.261804,0,.207247,.860666,.245146,0,.22136,.859788,.229406,0,.235666,.859608,.214605,0,.250158,.859912,.200691,0,.264832,.86053,.187623,0,.279684,.861368,.17539,0,.294711,.862237,.163901,0,.309911,.863127,.153175,0,.32528,.863923,.143147,0,.340819,.864567,.133781,0,.356524,.865013,.125042,0,.372397,.86539,.116952,0,.388438,.865591,.109476,0,.404645,.865517,.102542,0,.421022,.865084,.0960688,0,.437569,.864309,.0900499,0,.454287,.863151,.0844328,0,.471181,.861649,.0792218,0,.488253,.859742,.0743482,0,.505507,.857446,.0697963,0,.522947,.854757,.0655364,0,.54058,.851783,.061608,0,.558412,.848516,.0579701,0,.576449,.844897,.0545742,0,.594701,.840956,.0514167,0,.613178,.836676,.0484598,0,.631892,.832075,.0456934,0,.650856,.827191,.0431178,0,.670088,.822295,.0407718,0,.689606,.817294,.0386032,0,.709434,.812013,.0365675,0,.7296,.806465,.0346547,0,.750138,.800691,.0328717,0,.771093,.794709,.031211,0,.792519,.788493,.0296504,0,.814488,.782049,.0281782,0,.837097,.775403,.0267965,0,.860481,.76857,.0255002,0,.884842,.761536,.0242759,0,.910494,.754303,.0231142,0,.937985,.74692,.0220305,0,.968254,.739745,.0210192,0,1,1,.613914,0,0,.999996,.613907,0,963597e-10,.999942,.613814,0,.00301247,.999704,.613407,0,.00870385,.999046,.612302,0,.0160714,.995516,.608266,0,.0245899,.991726,.602863,0,.0339681,.985157,.593956,0,.0440254,.97642,.581748,0,.0546409,.964404,.565183,0,.0657284,.950601,.545273,0,.0772246,.935158,.522129,0,.0890812,.919364,.496782,0,.10126,.904754,.470571,0,.113731,.89176,.444037,0,.126469,.881492,.418322,0,.139454,.873656,.393522,0,.15267,.868053,.369795,0,.166101,.864336,.347171,0,.179736,.862259,.325737,0,.193565,.861556,.305532,0,.207578,.861776,.286416,0,.221769,.862661,.268355,0,.23613,.864015,.251334,0,.250656,.865711,.235352,0,.265343,.867519,.220302,0,.280187,.869351,.206161,0,.295183,.871144,.192908,0,.31033,.872839,.180505,0,.325624,.874307,.168848,0,.341065,.875667,.158021,0,.35665,.876758,.147877,0,.37238,.87764,.138441,0,.388253,.878237,.129627,0,.404269,.878563,.121415,0,.42043,.878572,.113741,0,.436735,.87842,.106652,0,.453187,.878057,.100097,0,.469786,.877413,.0940128,0,.486536,.87646,.0883462,0,.503439,.875233,.0830924,0,.520498,.8737,.0781975,0,.537717,.871873,.07364,0,.555102,.86978,.0694103,0,.572657,.867405,.0654696,0,.59039,.864751,.0617914,0,.608307,.861818,.0583491,0,.626419,.858645,.0551443,0,.644733,.855307,.0521894,0,.663264,.851736,.0494334,0,.682025,.847927,.0468504,0,.701032,.843888,.0444261,0,.720308,.839629,.0421497,0,.739875,.835158,.0400082,0,.759764,.830509,.0380076,0,.780014,.825714,.0361488,0,.800673,.820729,.0343956,0,.821803,.815751,.0327781,0,.843492,.810752,.031275,0,.86586,.805587,.0298542,0,.889087,.800317,.0285397,0,.913466,.79489,.0272948,0,.93952,.789314,.0261139,0,.96835,.783593,.0249938,0,1,1,.724258,0,0,.999992,.724243,0,726889e-9,.99987,.724044,0,.00569574,.999336,.72317,0,.0131702,.996271,.719432,0,.0220738,.991159,.712576,0,.0319405,.982465,.700927,0,.0425202,.97049,.684297,0,.0536599,.953973,.661244,0,.065258,.935546,.633804,0,.0772427,.916596,.603071,0,.0895616,.899353,.57105,0,.102175,.885216,.539206,0,.11505,.875076,.508714,0,.128164,.868334,.479571,0,.141495,.864414,.451796,0,.155026,.862678,.425328,0,.168745,.862835,.400352,0,.182639,.864067,.376532,0,.196699,.866086,.35391,0,.210915,.868557,.332424,0,.225282,.871271,.312053,0,.239792,.874058,.292764,0,.25444,.8768,.27453,0,.269223,.87939,.257297,0,.284135,.8819,.24114,0,.299174,.884187,.225934,0,.314337,.886262,.211669,0,.329622,.888119,.198311,0,.345026,.889709,.185783,0,.360549,.891054,.174063,0,.376189,.892196,.163143,0,.391946,.893101,.152952,0,.407819,.893803,.143475,0,.423808,.894277,.134647,0,.439914,.894532,.126434,0,.456137,.894576,.1188,0,.472479,.894393,.111694,0,.48894,.893976,.105069,0,.505523,.893346,.0989077,0,.52223,.892502,.0931724,0,.539064,.891441,.0878276,0,.556028,.890276,.082903,0,.573125,.888972,.0783505,0,.590361,.887469,.0741083,0,.607741,.885785,.0701633,0,.62527,.883914,.0664835,0,.642957,.881872,.0630567,0,.660809,.879651,.0598527,0,.678836,.877267,.0568615,0,.69705,.874717,.05406,0,.715465,.872012,.0514378,0,.734098,.869157,.0489805,0,.752968,.866155,.0466727,0,.772101,.863014,.0445056,0,.791529,.859748,.0424733,0,.81129,.856416,.0405957,0,.831438,.852958,.0388273,0,.852044,.849382,.0371619,0,.87321,.845694,.0355959,0,.89509,.841893,.0341155,0,.917932,.837981,.0327141,0,.942204,.833963,.0313856,0,.968981,.829847,.0301275,0,1,1,.85214,0,0,.999969,.852095,0,.00279627,.999483,.851408,0,.0107635,.994545,.84579,0,.0206454,.986188,.835231,0,.0315756,.969847,.814687,0,.0432021,.945951,.783735,0,.0553396,.91917,.746074,0,.0678766,.895488,.706938,0,.0807395,.878232,.669534,0,.0938767,.868252,.635168,0,.10725,.863873,.603069,0,.120832,.863369,.572514,0,.134598,.86545,.543169,0,.148533,.868803,.514578,0,.16262,.872794,.486762,0,.176849,.87702,.459811,0,.19121,.881054,.433654,0,.205694,.884974,.408574,0,.220294,.888587,.384525,0,.235005,.891877,.36156,0,.24982,.894793,.339661,0,.264737,.89743,.318913,0,.279751,.899796,.299302,0,.294859,.901943,.280843,0,.310058,.903858,.263481,0,.325346,.905574,.247197,0,.340721,.907069,.231915,0,.356181,.908379,.217614,0,.371725,.90952,.20425,0,.387353,.910483,.191758,0,.403063,.91128,.180092,0,.418854,.911936,.169222,0,.434727,.912454,.159098,0,.450682,.912835,.149668,0,.466718,.913078,.140884,0,.482837,.913192,.132709,0,.499038,.913175,.125095,0,.515324,.91304,.118012,0,.531695,.912781,.111417,0,.548153,.91241,.105281,0,.5647,.911924,.0995691,0,.581338,.911331,.0942531,0,.59807,.910637,.0893076,0,.6149,.90984,.0846998,0,.63183,.908941,.0804044,0,.648865,.907944,.0763984,0,.666011,.906857,.0726638,0,.683273,.90568,.0691783,0,.700659,.904416,.0659222,0,.718176,.903067,.0628782,0,.735834,.901637,.0600307,0,.753646,.900128,.0573647,0,.771625,.898544,.0548668,0,.78979,.89689,.052527,0,.808162,.895165,.0503306,0,.826771,.893371,.0482668,0,.845654,.891572,.0463605,0,.864863,.889763,.0445998,0,.884472,.887894,.0429451,0,.904592,.885967,.0413884,0,.925407,.883984,.0399225,0,.947271,.881945,.0385405,0,.97105,.879854,.0372362,0,1,.999804,.995833,0,0,.938155,.933611,0,.0158731,.864755,.854311,0,.0317461,.888594,.865264,0,.0476191,.905575,.863922,0,.0634921,.915125,.850558,0,.0793651,.920665,.829254,0,.0952381,.924073,.802578,0,.111111,.926304,.772211,0,.126984,.927829,.739366,0,.142857,.928924,.705033,0,.15873,.92973,.670019,0,.174603,.930339,.634993,0,.190476,.930811,.600485,0,.206349,.931191,.566897,0,.222222,.93149,.534485,0,.238095,.931737,.503429,0,.253968,.931939,.473811,0,.269841,.932108,.445668,0,.285714,.93225,.418993,0,.301587,.932371,.393762,0,.31746,.932474,.369939,0,.333333,.932562,.347479,0,.349206,.932638,.326336,0,.365079,.932703,.306462,0,.380952,.93276,.287805,0,.396825,.932809,.270313,0,.412698,.932851,.253933,0,.428571,.932887,.23861,0,.444444,.932917,.224289,0,.460317,.932943,.210917,0,.47619,.932965,.19844,0,.492063,.932982,.186807,0,.507937,.932995,.175966,0,.52381,.933005,.165869,0,.539683,.933011,.156468,0,.555556,.933013,.147719,0,.571429,.933013,.139579,0,.587302,.93301,.132007,0,.603175,.933004,.124965,0,.619048,.932994,.118416,0,.634921,.932982,.112326,0,.650794,.932968,.106663,0,.666667,.93295,.101397,0,.68254,.932931,.0964993,0,.698413,.932908,.0919438,0,.714286,.932883,.0877057,0,.730159,.932856,.0837623,0,.746032,.932827,.0800921,0,.761905,.932796,.0766754,0,.777778,.932762,.0734936,0,.793651,.932727,.0705296,0,.809524,.932689,.0677676,0,.825397,.93265,.0651929,0,.84127,.932609,.0627917,0,.857143,.932565,.0605515,0,.873016,.932521,.0584606,0,.888889,.932474,.0565082,0,.904762,.932427,.0546841,0,.920635,.932377,.0529793,0,.936508,.932326,.0513851,0,.952381,.932274,.0498936,0,.968254,.93222,.0484975,0,.984127,.932164,.0471899,0,1],n=new Float32Array(e),r=new Float32Array(t),i=new ul(n,64,64,$e,Ge,300,je,je,Ie,Ne,1),a=new ul(r,64,64,$e,Ge,300,je,je,Ie,Ne,1);i.needsUpdate=!0,a.needsUpdate=!0;let o=new Uint16Array(e.length);e.forEach(function(e,t){o[t]=Li.toHalfFloat(e)});let s=new Uint16Array(t.length);t.forEach(function(e,t){s[t]=Li.toHalfFloat(e)});let c=new ul(o,64,64,$e,Ke,300,je,je,Ie,Ne,1),l=new ul(s,64,64,$e,Ke,300,je,je,Ie,Ne,1);return c.needsUpdate=!0,l.needsUpdate=!0,this.LTC_HALF_1=c,this.LTC_HALF_1=l,this.LTC_FLOAT_1=i,this.LTC_FLOAT_2=a,this}};Zf.LTC_HALF_1=null,Zf.LTC_HALF_1=null,Zf.LTC_FLOAT_1=null,Zf.LTC_FLOAT_2=null;var Qf=class{static init(){Zf.init();let{LTC_FLOAT_1:e,LTC_FLOAT_2:t,LTC_HALF_1:n,LTC_HALF_2:r}=Zf;Y.LTC_FLOAT_1=e,Y.LTC_FLOAT_2=t,Y.LTC_HALF_1=n,Y.LTC_HALF_2=r}},$f=.12,ep={minGap:.04,maxGap:.6,defaultPercent:16},tp={grid:20,heightPerCell:.085,flatHalfWidth:.07,bevelRound:.1,refractiveIndex:1.5,thickness:.008,environmentStrength:.45};function np(e){let t=.5-tp.flatHalfWidth,n=tp.bevelRound,r=V.clamp((Math.abs(e)-tp.flatHalfWidth)/t,0,1),i=r-n*.5,a=1;return r1-n&&(i=1-n-(1-r)*(1-r)/(2*n),a=(1-r)/n),[1-i/(1-n),-a*Math.sign(e)/(t*(1-n))]}function rp(e,t,n){let r=n.grid,i=Math.max(1,r*n.height/n.width),a=Math.min(n.width/r,n.height/i),[o,s]=np((e*r%1+1)%1-.5),[c,l]=np((t*i%1+1)%1-.5),u=e*r*Math.PI*2,d=t*i*Math.PI*2,f=u*3+Math.sin(d),p=.008*Math.sin(f)*Math.sin(d),m=.008*Math.PI*2*3*Math.cos(f)*Math.sin(d),h=.008*Math.PI*2*(Math.cos(f)*Math.cos(d)*Math.sin(d)+Math.sin(f)*Math.cos(d)),g=tp.heightPerCell*a*V.clamp(n.curvature,-1,1);return{height:g*(.25*o+.55*c+.2*o*c+p),dx:g*((.25+.2*c)*s+m)/(n.width/r),dy:g*((.55+.2*o)*l+h)/(n.height/i)}}function ip(e,t){let n=[0,.043,.387,.43,.57,.613,.957];if(Math.ceil(e)*n.length>t)return Array.from({length:t+1},(e,n)=>n/t);let r=[];for(let t=0;t=0;e--)_.push((c.length-1)*l+e);for(let e=c.length-2;e>0;e--)_.push(e*l);let v=g(0,0,n,0,0,-1,.5,.5),y=_.map(e=>g(u[e*3],u[e*3+1],n,0,0,-1,f[e*2],f[e*2+1]));for(let e=0;e<_.length;e++){let t=(e+1)%_.length,r=_[e],i=_[t];p.push(v,y[t],y[e]);let a=u[r*3],o=u[r*3+1],s=u[i*3],c=u[i*3+1],l=new W(c-o,a-s,0).normalize(),d=g(a,o,u[r*3+2],l.x,l.y,0,f[r*2],f[r*2+1]),m=g(s,c,u[i*3+2],l.x,l.y,0,f[i*2],f[i*2+1]),h=g(a,o,n,l.x,l.y,0,f[r*2],f[r*2+1]),b=g(s,c,n,l.x,l.y,0,f[i*2],f[i*2+1]);p.push(d,h,b,d,b,m)}let b=new Zi;return b.setAttribute(`position`,new Ui(u,3)),b.setAttribute(`normal`,new Ui(d,3)),b.setAttribute(`uv`,new Ui(f,2)),b.setIndex(p),b.computeBoundingSphere(),{geometry:b,backZ:n,minThickness:m,maxThickness:h,frontSegments:[s.length-1,c.length-1],reducedSampling:Math.ceil(e.grid)*7>a||Math.ceil(r)*7>o}}var op=12;function sp(e,t,n){if(![e,t,n].every(Number.isFinite))throw RangeError(`Courtyard dimensions must be finite`);if(e<=0||t<=0)throw RangeError(`Courtyard width and height must be positive`);let r=Math.min(e,t),i=Math.max(e,t),a=-t/2-.1*r,o=n-3*t,s=-Math.max(e*1.5,t*.8),c=-.12*e,l=n-.55*t,u=n-1.4*t,d=a+.28*r,f=.075*r,p=Math.max(e*.66,t*.4),m=n-.95*t,h=[{name:`ground`,min:[-40*i,a-.14*r,n-80*i],max:[40*i,a,n-.015*r],kind:0},{name:`boundary-wall`,min:[-3*i,a,o-.13*r],max:[3*i,a+.69*t,o],kind:1},{name:`boundary-cap`,min:[-3*i,a+.69*t,o-.16*r],max:[3*i,a+.725*t,o+.025*r],kind:5},{name:`left-return`,min:[-2.5*i-.13*r,a,o],max:[-2.5*i,a+.69*t,n-.3*t],kind:1},{name:`side-building`,min:[p,a,o-1.8*t],max:[p+3*i,a+2.8*t,m],kind:3},{name:`blue-building-base`,min:[p-.016*r,a,o-1.8*t],max:[p+3*i,a+.33*t,m+.016*r],kind:4},{name:`building-eaves`,min:[p-.1*r,a+2.8*t,o-1.85*t],max:[p+3.1*i,a+2.86*t,m+.1*r],kind:5},{name:`wood-platform`,min:[s,d-.055*r,u],max:[c,d,l],kind:2}];for(let e of[s+.1*r,c-.1*r-f])for(let t of[u+.08*r,l-.08*r-f])h.push({name:`platform-leg-${h.length-8}`,min:[e,a,t],max:[e+f,d-.055*r,t+f],kind:2});return h}var cp=` +uniform float uYardEnabled; +uniform vec3 uYardDimensions; +uniform vec3 uYardSkyColor; +uniform vec4 uYardDogContact; +uniform vec3 uYardBoxMin[${op}]; +uniform vec3 uYardBoxMax[${op}]; +uniform float uYardBoxKind[${op}]; +`,lp=` +float bYardNoise(vec2 p) { + vec2 cell=floor(p), f=fract(p); + f=f*f*(3.0-2.0*f); + vec4 h=fract(sin(vec4(dot(cell,vec2(127.1,311.7)),dot(cell+vec2(1.0,0.0),vec2(127.1,311.7)), + dot(cell+vec2(0.0,1.0),vec2(127.1,311.7)),dot(cell+vec2(1.0),vec2(127.1,311.7))))*43758.5453); + return mix(mix(h.x,h.y,f.x),mix(h.z,h.w,f.x),f.y); +} +vec3 bYardSurfaceColor(vec3 point,vec3 normal,float kind) { + float scale=min(uYardDimensions.x,uYardDimensions.y); + vec3 p=(point-vec3(0.0,-uYardDimensions.y*.5-.1*scale,uYardDimensions.z))/scale; + vec2 face=abs(normal.y)>.5?p.xz:(abs(normal.x)>.5?p.zy:p.xy); + float broad=bYardNoise(face*3.7), fine=bYardNoise(face*65.0); + vec3 base=vec3(.30,.285,.245); + if(kind<.5) { + base*=.88+.16*broad+.07*fine; + // Fixed world-space shade under the deck and alongside the building, shared by both views. + vec2 lo=uYardBoxMin[7].xz/scale, hi=uYardBoxMax[7].xz/scale; + vec2 footprint=smoothstep(lo-vec2(.10),lo+vec2(.02),point.xz/scale) + *(1.0-smoothstep(hi-vec2(.02),hi+vec2(.10),point.xz/scale)); + float deckShade=footprint.x*footprint.y; + float sideShade=smoothstep(uYardBoxMin[4].x/scale-.7,uYardBoxMin[4].x/scale+.05,point.x/scale); + base*=1.0-.38*deckShade; + base*=1.0-.24*sideShade; + vec2 contact=(point.xz-uYardDogContact.xy)/max(.001,uYardDogContact.z); + base*=1.0-uYardDogContact.w*exp(-dot(contact,contact)*2.0); + } else if(kind<1.5) { + vec2 block=vec2(face.x*3.4+mod(floor(face.y*5.0),2.0)*.5,face.y*5.0); + vec2 edge=min(fract(block),1.0-fract(block)); + float joint=1.0-smoothstep(.018,.04,min(edge.x,edge.y)); + base=mix(vec3(.32,.335,.30)*(.89+.15*broad+.04*fine),vec3(.20,.215,.195),joint*.65); + base*=.80+.20*smoothstep(0.0,.5,p.y); + } else if(kind<2.5) { + float grain=sin(face.x*105.0+sin(face.y*4.2)*1.8)*.035+sin(face.x*291.0+face.y*1.4)*.017; + float plank=fract(p.x*7.0); + float seam=1.0-smoothstep(.014,.038,min(plank,1.0-plank)); + base=vec3(.39,.215,.095)*(.94+.12*broad+grain); + base*=1.0-.30*seam; + } else if(kind<3.5) { + base=vec3(.56,.575,.57)*(.96+.055*broad+.016*fine); + } else if(kind<4.5) { + base=vec3(.16,.36,.38)*(.85+.21*broad+.045*fine); + base*=.75+.25*smoothstep(0.0,.18,p.y); + } else { + base=vec3(.145,.17,.19)*(.92+.11*broad); + } + vec3 sun=normalize(vec3(-.48,.82,.30)); + float daylight=.62+.54*max(dot(normal,sun),0.0); + return base*daylight*vec3(1.035,1.015,.975); +} +`,up=cp+lp+` +bool bYardBoxHit(vec3 origin,vec3 ray,vec3 boxMin,vec3 boxMax,out float distance,out vec3 normal) { + float nearDistance=-1e19,farDistance=1e19; + vec3 nearNormal=vec3(0.0),farNormal=vec3(0.0); + for(int axis=0;axis<3;axis++) { + if(abs(ray[axis])<1e-8) { + if(origin[axis]boxMax[axis]) return false; + } else { + float a=(boxMin[axis]-origin[axis])/ray[axis],b=(boxMax[axis]-origin[axis])/ray[axis]; + float lo=min(a,b),hi=max(a,b); + if(lo>nearDistance) { + nearDistance=lo; nearNormal=vec3(0.0); nearNormal[axis]=-sign(ray[axis]); + } + if(hifarDistance||farDistance<1e-5) return false; + bool outside=nearDistance>=1e-5; + distance=outside?nearDistance:farDistance; + normal=outside?nearNormal:farNormal; + return true; +} +bool bCourtyardHit(vec3 origin,vec3 ray,out float distance,out vec3 color) { + distance=1e19; color=uYardSkyColor; + if(uYardEnabled<.5||dot(ray,ray)<1e-16) return false; + vec3 direction=normalize(ray),closestNormal=vec3(0.0); + float closestKind=-1.0; + for(int box=0;box<${op};box++) { + float candidateDistance; vec3 candidateNormal; + if(bYardBoxHit(origin,direction,uYardBoxMin[box],uYardBoxMax[box],candidateDistance,candidateNormal) + &&candidateDistance=0.0) color=bYardSurfaceColor(origin+direction*distance,closestNormal,closestKind); + return true; +} +`;function dp(e){let t=new da(1,1,1).toNonIndexed(),n=t.getAttribute(`position`),r=t.getAttribute(`normal`),i=n.count,a=new Float32Array(e.length*i*3),o=new Float32Array(a.length),s=new Float32Array(e.length*i);e.forEach((e,t)=>{for(let c=0;cnew W)},uYardBoxMax:{value:Array.from({length:op},()=>new W)},uYardBoxKind:{value:Array.from({length:op},()=>0)}}}var pp=class{group=new Lc;uniforms=fp();material;mesh;disposed=!1;constructor(){this.group.name=`experimental-courtyard`,this.group.visible=!1,this.material=new ya({name:`unified-courtyard-surfaces`,uniforms:this.uniforms,side:2,vertexShader:` + attribute float aYardKind; + varying vec3 vYardPoint; + varying vec3 vYardNormal; + varying float vYardKind; + void main() { + vec4 world=modelMatrix*vec4(position,1.0); + vYardPoint=world.xyz; vYardNormal=mat3(modelMatrix)*normal; vYardKind=aYardKind; + gl_Position=projectionMatrix*viewMatrix*world; + } + `,fragmentShader:cp+lp+` + varying vec3 vYardPoint; + varying vec3 vYardNormal; + varying float vYardKind; + void main() { + gl_FragColor=vec4(bYardSurfaceColor(vYardPoint,normalize(vYardNormal),vYardKind),1.0); + #include + #include + } + `}),this.mesh=new q(new Zi,this.material),this.mesh.name=`courtyard-merged-boxes`,this.group.add(this.mesh),this.resize(1,1,.6)}resize(e,t,n){if(this.disposed)return;let r=sp(e,t,n),i=dp(r);this.uniforms.uYardDimensions.value.set(e,t,n),r.forEach((e,t)=>{this.uniforms.uYardBoxMin.value[t].fromArray(e.min),this.uniforms.uYardBoxMax.value[t].fromArray(e.max),this.uniforms.uYardBoxKind.value[t]=e.kind}),this.mesh.geometry.dispose(),this.mesh.geometry=i}setDogContact(e,t,n,r){this.uniforms.uYardDogContact.value.set(e,t,Math.max(.001,n),V.clamp(r,0,1))}setEnabled(e){this.group.visible=e&&!this.disposed,this.uniforms.uYardEnabled.value=+!!this.group.visible}dispose(){this.disposed||(this.disposed=!0,this.setEnabled(!1),this.group.removeFromParent(),this.mesh.geometry.dispose(),this.material.dispose())}},mp=` +uniform sampler2D uBPhoto; +uniform sampler2D uBDepthMap; +uniform mat4 uBPhotoWorldToLocal; +uniform float uBDepthScale; +uniform float uBDepthBias; +uniform float uBPhotoSegments; +uniform float uBBackZ; +uniform vec2 uBPaneHalfSize; +uniform float uBPaneCenterX; +uniform vec3 uBBackground; +uniform bool uBIsVideo; +uniform bool uBUsePhotoAlpha; +${up} +uniform bool uBShowPhoto; +uniform bool uBPhotoExport; +uniform bool uBRevealEnabled; +uniform vec3 uBRevealVertices[16]; +uniform vec2 uBRevealUvs[16]; +uniform vec3 uBRevealColors[4]; +uniform float uBRevealUnlit[4]; +uniform float uBRevealHasMap[4]; +uniform sampler2D uBRevealMapVertical; +uniform sampler2D uBRevealMapHorizontal; +uniform mat3 uBRevealMapTransformVertical; +uniform mat3 uBRevealMapTransformHorizontal; +uniform vec3 uBRevealAmbient; +uniform vec3 uBRevealLightColor; +uniform vec3 uBRevealLightDirection; + +float bRevealTriangle(vec3 origin,vec3 ray,int a,int b,int c,out vec2 uv) { + vec3 e1=uBRevealVertices[b]-uBRevealVertices[a],e2=uBRevealVertices[c]-uBRevealVertices[a]; + vec3 p=cross(ray,e2);float det=dot(e1,p); + if(abs(det)<1e-9)return 1e20; // WindowReveal uses DoubleSide. + vec3 delta=origin-uBRevealVertices[a];float u=dot(delta,p)/det; + vec3 q=cross(delta,e1);float v=dot(ray,q)/det; + if(u<-.00001||v<-.00001||u+v>1.00001)return 1e20; + float t=dot(e2,q)/det;if(t<.000001)return 1e20; + uv=uBRevealUvs[a]*(1.-u-v)+uBRevealUvs[b]*u+uBRevealUvs[c]*v; + return t; +} +bool bRevealHit(vec3 origin,vec3 ray,out float distance,out vec3 color) { + distance=1e20;color=uBBackground;if(!uBRevealEnabled)return false; + for(int wall=0;wall<4;wall++) { + int i=wall*4;vec2 uv0,uv1; + float t0=bRevealTriangle(origin,ray,i,i+1,i+2,uv0),t1=bRevealTriangle(origin,ray,i,i+2,i+3,uv1); + float t=min(t0,t1);if(t>=distance)continue; + distance=t;vec2 uv=t0.5) { + if(wall<2)texel=textureLod(uBRevealMapVertical,(uBRevealMapTransformVertical*vec3(uv,1.)).xy,0.).rgb; + else texel=textureLod(uBRevealMapHorizontal,(uBRevealMapTransformHorizontal*vec3(uv,1.)).xy,0.).rgb; + } + vec3 n=normalize(cross(uBRevealVertices[i+1]-uBRevealVertices[i],uBRevealVertices[i+2]-uBRevealVertices[i])); + if(dot(n,ray)>0.)n=-n; + // Same diffuse map/tint and fixed room lights as the actual recess. This + // intentionally omits secondary glossy bounces; never invent photo pixels. + vec3 irradiance=uBRevealAmbient+uBRevealLightColor*max(0.,dot(n,uBRevealLightDirection)); + color=texel*uBRevealColors[wall]*mix(irradiance/3.14159265359,vec3(1.),uBRevealUnlit[wall]); + } + return distance<1e19; +} + +float bTriangle(vec3 origin, vec3 ray, vec3 a, vec3 b, vec3 c) { + vec3 e1=b-a,e2=c-a,p=cross(ray,e2); + float det=dot(e1,p); + // Match the photo's FrontSide material; no invented back surface. + if(det<=1e-9)return 1e20; + vec3 s=origin-a;float u=dot(s,p)/det; + if(u<-.00001||u>1.00001)return 1e20; + vec3 q=cross(s,e1);float v=dot(ray,q)/det; + if(v<-.00001||u+v>1.00001)return 1e20; + float t=dot(e2,q)/det;return t>=0.?t:1e20; +} +vec3 bPhotoVertex(vec2 grid) { + vec2 uv=grid/uBPhotoSegments; + // Explicit base LOD matches PetDepthMesh's vertex texture lookup. Implicit + // derivatives are undefined in divergent ray-traversal control flow. + float depth=textureLod(uBDepthMap,uv,0.).r; + return vec3(uv-.5,(depth-uBDepthBias)*uBDepthScale); +} +bool bSlab(float origin,float ray,float lo,float hi,inout float nearT,inout float farT) { + if(abs(ray)<1e-9)return origin>=lo&&origin<=hi; + float a=(lo-origin)/ray,b=(hi-origin)/ray; + nearT=max(nearT,min(a,b));farT=min(farT,max(a,b));return farT>=nearT; +} +float bPhotoCoverageWeight(float coverage,float alpha){return (1.-coverage)*alpha;} +bool bPhotoHit(vec3 worldOrigin,vec3 worldRay,out vec2 hitUv,out float hitDistance,out vec4 hitColor,float backgroundDistance) { + hitDistance=1e20;hitColor=vec4(0.);float lastDistance=-1.; + vec3 origin=(uBPhotoWorldToLocal*vec4(worldOrigin,1.)).xyz; + vec3 ray=(uBPhotoWorldToLocal*vec4(worldRay,0.)).xyz; + float nearT=0.,farT=1e20; + float lo=-uBDepthBias*uBDepthScale,hi=(1.-uBDepthBias)*uBDepthScale; + if(!bSlab(origin.x,ray.x,-.5,.5,nearT,farT)|| + !bSlab(origin.y,ray.y,-.5,.5,nearT,farT)|| + !bSlab(origin.z,ray.z,min(lo,hi),max(lo,hi),nearT,farT))return false; + vec2 point=(origin+ray*nearT).xy; + vec2 direction=sign(ray.xy); + vec2 cell=clamp(floor((point+.5)*uBPhotoSegments+direction*.00001),vec2(0.),vec2(uBPhotoSegments-1.)); + vec2 nextT=vec2(1e20),delta=vec2(1e20); + if(abs(ray.x)>=1e-9){nextT.x=((cell.x+step(0.,ray.x))/uBPhotoSegments-.5-origin.x)/ray.x;delta.x=1./(uBPhotoSegments*abs(ray.x));} + if(abs(ray.y)>=1e-9){nextT.y=((cell.y+step(0.,ray.y))/uBPhotoSegments-.5-origin.y)/ray.y;delta.y=1./(uBPhotoSegments*abs(ray.y));} + // A ray crosses at most 128+128+1 cells. This is exact triangle traversal, + // not fixed-distance ray marching that can skip a narrow foreground feature. + for(int iteration=0;iteration<257;iteration++) { + vec3 ll=bPhotoVertex(cell),lr=bPhotoVertex(cell+vec2(1.,0.)); + vec3 ul=bPhotoVertex(cell+vec2(0.,1.)),ur=bPhotoVertex(cell+vec2(1.,1.)); + // PlaneGeometry's diagonal is lower-left → upper-right. + float t0=bTriangle(origin,ray,ul,ll,ur),t1=bTriangle(origin,ray,ll,lr,ur); + float endT=min(farT,min(nextT.x,nextT.y)); + for(int sampleIndex=0;sampleIndex<2;sampleIndex++){ + float t=sampleIndex==0?min(t0,t1):max(t0,t1); + if(t>=nearT-.00001&&t<=endT+.00001&&tlastDistance+.00001){ + vec2 candidate=clamp((origin+ray*t).xy+.5,vec2(0.),vec2(1.)); + vec4 sampleColor=textureLod(uBPhoto,candidate,0.); + float alpha=uBUsePhotoAlpha?sampleColor.a:1.; + if(alpha>.003){ + if(uBIsVideo)sampleColor.rgb=mix(sampleColor.rgb/12.92,pow((sampleColor.rgb+.055)/1.055,vec3(2.4)),step(vec3(.04045),sampleColor.rgb)); + float weight=bPhotoCoverageWeight(hitColor.a,alpha); + hitColor.rgb+=sampleColor.rgb*weight;hitColor.a+=weight; + if(hitDistance>1e19){hitDistance=t;hitUv=candidate;} + if(hitColor.a>=.999)return true; + } + lastDistance=t; + } + } + if(endT>=farT-.000001||endT>=backgroundDistance)return hitColor.a>0.; + bool crossX=nextT.x<=nextT.y; + bool crossY=nextT.y<=nextT.x; + nearT=endT; + if(crossX){cell.x+=direction.x;nextT.x+=delta.x;} + if(crossY){cell.y+=direction.y;nextT.y+=delta.y;} + if(any(lessThan(cell,vec2(0.)))||any(greaterThanEqual(cell,vec2(uBPhotoSegments))))return hitColor.a>0.; + } + return hitColor.a>0.; +} +bool bExitGlass(vec3 entry,vec3 ray,out vec3 exitPoint,out vec3 inwardNormal) { + float distance=1e20;inwardNormal=vec3(0.,0.,1.); + if(ray.z< -1e-9){float t=(uBBackZ-entry.z)/ray.z;if(t>1e-7)distance=t;} + if(abs(ray.x)>1e-9){float side=sign(ray.x),t=(side*uBPaneHalfSize.x+uBPaneCenterX-entry.x)/ray.x;if(t>1e-7&&t1e-9){float side=sign(ray.y),t=(side*uBPaneHalfSize.y-entry.y)/ray.y;if(t>1e-7&&t=1e19)return false; + exitPoint=entry+ray*distance;return true; +} +vec4 bTracePhotoRay(vec3 entry,vec3 normal,vec3 viewDirection,float ior) { + if(!uBShowPhoto)return vec4(uBBackground,1.); + vec3 internalRay=refract(-viewDirection,normalize(normal),1./ior); + vec3 exitPoint,inwardNormal; + if(!bExitGlass(entry,internalRay,exitPoint,inwardNormal))return uBPhotoExport?vec4(0.):vec4(uBBackground,1.); + vec3 outgoing=refract(internalRay,inwardNormal,ior); + if(dot(outgoing,outgoing)<1e-8)return uBPhotoExport?vec4(0.):vec4(0.,0.,0.,-1.); + vec2 hitUv;float photoDistance,revealDistance;vec3 revealColor; + bool revealHit=bRevealHit(exitPoint,outgoing,revealDistance,revealColor); + float backgroundDistance=revealHit?revealDistance:1e20; + vec3 backgroundColor=revealHit?revealColor:uBBackground; + float yardDistance;vec3 yardColor; + if(bCourtyardHit(exitPoint,outgoing,yardDistance,yardColor) && yardDistancenew W)},uBRevealUvs:{value:Array.from({length:16},()=>new H)},uBRevealColors:{value:Array.from({length:4},()=>new K)},uBRevealUnlit:{value:[0,0,0,0]},uBRevealHasMap:{value:[0,0,0,0]},uBRevealMapVertical:{value:null},uBRevealMapHorizontal:{value:null},uBRevealMapTransformVertical:{value:new U},uBRevealMapTransformHorizontal:{value:new U},uBRevealAmbient:{value:new K(0,0,0)},uBRevealLightColor:{value:new K(0,0,0)},uBRevealLightDirection:{value:new W},uBPaneCenterX:{value:0},uBBackground:{value:new K},uBIsVideo:{value:!1},uBUsePhotoAlpha:{value:!1},uBShowPhoto:{value:!0},uBPhotoExport:{value:!1}};e.onBeforeCompile=e=>{if(Object.assign(e.uniforms,n),!e.fragmentShader.includes(`#include `)||!e.fragmentShader.includes(`#include `))throw Error(`Unsupported Three transmission shader`);e.fragmentShader=e.fragmentShader.replace(`#include `,`#include +`+mp).replace(`#include `,hp).replace(`#include `,`#include +#ifdef USE_TRANSMISSION +if(uBPhotoExport){gl_FragColor.a = clamp(bLight.a,0.,1.);if(gl_FragColor.a==0.)gl_FragColor.rgb=vec3(0.);} +#endif`)},e.customProgramCacheKey=()=>`mesh-exit-photo-reveal-courtyard-export-v5`;let r=new W,i=new W;return{uniforms:n,syncReveal(e,a){if(n.uBRevealEnabled.value=e.length===4&&e.every(e=>e.geometry?.getAttribute(`position`)?.count===4),n.uBRevealEnabled.value){for(let r=0;r<4;r++){let i=e[r],a=i.geometry.getAttribute(`position`),o=i.geometry.getAttribute(`uv`);i.updateWorldMatrix(!0,!1);for(let e=0;e<4;e++)n.uBRevealVertices.value[r*4+e].fromBufferAttribute(a,e).applyMatrix4(i.matrixWorld),n.uBRevealUvs.value[r*4+e].set(o.getX(e),o.getY(e));let s=i.material;if(n.uBRevealColors.value[r].copy(s.color),n.uBRevealUnlit.value[r]=+!!s.isMeshBasicMaterial,n.uBRevealHasMap.value[r]=+!!s.map,r===0||r===2){let e=s.map;e?.updateMatrix(),(r===0?n.uBRevealMapVertical:n.uBRevealMapHorizontal).value=e??t.material.uniforms.uTexture.value,(r===0?n.uBRevealMapTransformVertical:n.uBRevealMapTransformHorizontal).value.copy(e?.matrix??new U)}}n.uBRevealAmbient.value.setRGB(0,0,0),n.uBRevealLightColor.value.setRGB(0,0,0),a.traverseVisible(e=>{e instanceof ef&&n.uBRevealAmbient.value.setRGB(n.uBRevealAmbient.value.r+e.color.r*e.intensity,n.uBRevealAmbient.value.g+e.color.g*e.intensity,n.uBRevealAmbient.value.b+e.color.b*e.intensity),e instanceof $d&&(n.uBRevealLightColor.value.copy(e.color).multiplyScalar(e.intensity),e.getWorldPosition(r),e.target.getWorldPosition(i),n.uBRevealLightDirection.value.copy(r).sub(i).normalize())})}},sync(e,r,i,a=0){let o=t.material.uniforms;t.updateWorldMatrix(!0,!1),n.uBPhotoWorldToLocal.value.copy(t.matrixWorld).invert(),n.uBPhoto.value=o.uTexture.value,n.uBDepthMap.value=o.uDepthMap.value,n.uBDepthScale.value=o.uDepthScale.value,n.uBDepthBias.value=o.uDepthBias.value,n.uBIsVideo.value=o.uIsVideo?.value??!1,n.uBUsePhotoAlpha.value=o.uUsePhotoAlpha?.value??!1,n.uBPaneCenterX.value=a,n.uBBackZ.value=r,n.uBPaneHalfSize.value.set(e.width*.5,e.height*.5),n.uBBackground.value.copy(i)}}}var _p=null,vp=class{renderer;depthSource;scene=new Yc;material=new dd({color:16777215,metalness:0,roughness:.04,transmission:1,opacity:1,transparent:!1,ior:tp.refractiveIndex,thickness:tp.thickness,side:0,attenuationDistance:1/0,envMapIntensity:.45});glass=new q(new Zi,this.material);photo;courtyard=null;syncCourtyard(e){if(this.courtyard&&this.courtyard!==e&&(this.courtyard.group.visible=!1),this.courtyard=e,this.refraction.uniforms.uYardEnabled.value=+!!e,e){for(let[t,n]of Object.entries(e.uniforms)){let e=this.refraction.uniforms[t];e&&(e.value=n.value)}this.scene.add(e.group),e.group.visible=!0}}refraction;backLocalZ=0;pocketPlane=new Na(new W(1,0,0),1);setSlide(e){Number.isFinite(e)&&(this.glass.position.x=e===0?0:e)}output=null;photoExport=!1;internalTargets=new Set;light=new tf(15792127,3,1,1);environment;signature=``;thicknessMap=null;isDisposed=!1;failed=!1;environmentOnly;reducedSampling=!1;triangleCount=0;geometryBytes=0;thicknessRange=[0,0];constructor(e,t){if(this.renderer=e,this.depthSource=t,this.photo=new q(t.geometry,t.material),this.photo.frustumCulled=!1,this.refraction=gp(this.material,t),this.photo.onBeforeRender=()=>{let t=e.getRenderTarget();t&&t!==this.output&&this.internalTargets.add(t)},this.material.clippingPlanes=[this.pocketPlane],this.scene.add(this.photo,this.glass,this.light),!_p){Qf.init();let e=Y;_p=[e.LTC_FLOAT_1,e.LTC_FLOAT_2,e.LTC_HALF_1,e.LTC_HALF_2].filter(Boolean)}_p.forEach(e=>{e.needsUpdate=!0}),this.environmentOnly=!e.extensions.has(`OES_texture_float_linear`),this.light.visible=!this.environmentOnly,this.environment=yp(),this.scene.environment=this.environment}sync(e,t,n,r){this.scene.background=r,this.photo.position.copy(this.depthSource.position),this.photo.quaternion.copy(this.depthSource.quaternion),this.photo.scale.copy(this.depthSource.scale),this.photo.visible=!0,this.light.position.copy(n),this.light.lookAt(0,0,t),this.light.width=Math.min(e.width,e.height)*.76,this.light.height=Math.min(e.width,e.height)*1.04,this.glass.position.z=t,this.pocketPlane.constant=e.width/2+.05*Math.min(e.width,e.height);let i=[e.width,e.height,e.grid,e.curvature].join(`|`);if(i===this.signature){this.refraction.sync(e,t+this.backLocalZ,r,this.glass.position.x);return}let a=ap(e);this.backLocalZ=a.backZ,this.glass.geometry.dispose(),this.glass.geometry=a.geometry,this.triangleCount=a.geometry.index.count/3,this.reducedSampling=a.reducedSampling,this.geometryBytes=Object.values(a.geometry.attributes).reduce((e,t)=>e+t.array.byteLength,0)+a.geometry.index.array.byteLength,this.thicknessRange=[a.minThickness,a.maxThickness];let o=Math.min(e.width/e.grid,e.height/Math.max(1,e.grid*e.height/e.width)),s=tp.thickness+tp.heightPerCell*o*(1+1.008*Math.abs(e.curvature)),c=Math.min(256,Math.max(32,Math.ceil(e.grid*10))),l=Math.min(256,Math.max(32,Math.ceil(e.grid*e.height/e.width*10))),u=new Uint8Array(c*l*4);for(let t=0;t{c=!0,l?.(...e)};try{this.renderer.render(this.scene,e)}catch(e){throw this.failed=!0,e}finally{this.renderer.debug.onShaderError=l,a.colorWrite=o,a.depthWrite=s}if(c)throw this.failed=!0,Error(`Mesh exit/photo refraction shader compilation failed`);if(this.photoExport||!n&&!(this.courtyard&&i))return;let u=this.renderer.autoClear;try{this.renderer.autoClear=!1,this.renderer.render(t,e)}finally{this.renderer.autoClear=u}}renderForExport(e,t,n,r){let i=this.scene.background,a=this.output,o=this.photoExport,s=this.refraction.uniforms.uBPhotoExport.value,c=this.photo.material,l=c.alphaToCoverage,u=this.courtyard?.group.visible,d=this.renderer.autoClear,f=t.background,p=new Map;try{if(this.photoExport=r,this.refraction.uniforms.uBPhotoExport.value=r,r&&(this.scene.background=null),c.alphaToCoverage=!1,r){t.traverseVisible(e=>{let t=e.material;if(t)for(let e of Array.isArray(t)?t:[t])p.has(e)||(p.set(e,e.colorWrite),e.colorWrite=!1)});try{t.background=null,this.renderer.autoClear=!0,this.renderer.setScissorTest(!1),this.renderer.setRenderTarget(n),this.renderer.render(t,e)}finally{for(let[e,t]of p)e.colorWrite=t;t.background=f}this.renderer.autoClear=!1}this.render(e,t,!0,n,!0)}finally{for(let[e,t]of p)e.colorWrite=t;t.background=f,this.renderer.autoClear=d,this.scene.background=i,this.output=a,this.photoExport=o,this.refraction.uniforms.uBPhotoExport.value=s,c.alphaToCoverage=l,this.courtyard&&u!==void 0&&(this.courtyard.group.visible=u)}}restore(){this.failed=!1,this.internalTargets.forEach(e=>e.dispose()),this.internalTargets.clear(),this.material.needsUpdate=!0,this.environment.needsUpdate=!0,this.thicknessMap&&(this.thicknessMap.needsUpdate=!0),_p?.forEach(e=>{e.needsUpdate=!0})}dispose(){this.isDisposed||(this.isDisposed=!0,this.renderer.getContext().isContextLost()||(this.renderer.setRenderTarget(null),this.renderer.setScissorTest(!1)),this.internalTargets.forEach(e=>e.dispose()),this.internalTargets.clear(),this.glass.geometry.dispose(),this.material.dispose(),this.thicknessMap?.dispose(),this.environment.dispose(),_p?.forEach(e=>e.dispose()),this.photo.onBeforeRender=()=>{},this.scene.clear())}};function yp(){let e=new Float32Array(32768),t=new K().setRGB(.09,.13,.17),n=new K().setRGB(.78,.84,.86),r=new K().setRGB(.12,.16,.2),i=new K;for(let a=0;a<64;a++)for(let o=0;o<128;o++){let s=((a+.5)/64-.5)*Math.PI,c=((o+.5)/128-.5)*Math.PI*2,l=Math.sin(s),u=Math.cos(s)*Math.cos(c);i.copy(t).lerp(n,V.smoothstep(l,-.4,.65)),i.lerp(r,(1-V.smoothstep(Math.abs(u+.12),.015,.06))*.55);let d=(a*128+o)*4;e[d]=i.r,e[d+1]=i.g,e[d+2]=i.b,e[d+3]=1}let a=new ul(e,128,64,$e,Ge);return a.mapping=303,a.needsUpdate=!0,a}function bp(e,t){let n=[...e.querySelectorAll(`[data-tool]`)],r=[...e.querySelectorAll(`[data-panel]`)],i=[...e.querySelectorAll(`[data-pattern]`)],a=e.querySelector(`#mosaic-style`),o=e.querySelector(`#effect`),s=e.querySelector(`#pattern-cards`),c=e=>{n.forEach((t,n)=>{t.setAttribute(`aria-selected`,String(n===e)),t.tabIndex=n===e?0:-1}),r.forEach(t=>{t.hidden=t.dataset.panel!==n[e].dataset.tool})};n.forEach((e,r)=>{e.addEventListener(`click`,()=>c(r),{signal:t}),e.addEventListener(`keydown`,e=>{let t=e.key===`ArrowRight`?(r+1)%n.length:e.key===`ArrowLeft`?(r+n.length-1)%n.length:e.key===`Home`?0:e.key===`End`?n.length-1:-1;t<0||(e.preventDefault(),c(t),n[t].focus())},{signal:t})});let l=()=>{i.forEach(e=>e.setAttribute(`aria-pressed`,String(e.dataset.pattern===a.value))),s.hidden=o.value!==`mosaic`};i.forEach(e=>e.addEventListener(`click`,()=>{a.value!==e.dataset.pattern&&(a.value=e.dataset.pattern,a.dispatchEvent(new Event(`change`,{bubbles:!0})))},{signal:t})),a.addEventListener(`change`,l,{signal:t}),o.addEventListener(`change`,l,{signal:t}),c(0),l()}var xp=`behind-glass:theme`,Sp={wood:{name:`할머니집 창가`,background:`#e6dfcf`,room:[`#b5ac94`,`#8b8c73`,`#6e705d`],light:`#ddd8b8`,mullion:`#787b65`},booth:{name:`통통 포토부스`,background:`#f7f0e5`,room:[`#eadfed`,`#d2c2d8`,`#b4a2c1`],light:`#fff7e6`,mullion:`#af99ba`}};function Cp(e,t,n,r=()=>{},i=()=>{},a=Af(()=>e.defaultView?.localStorage),o=()=>{},s=()=>{}){let c=t=>e.querySelector(`#${t}`),l=c(`experience`),u=c(`welcome`),d=c(`flow-overlay`),f=c(`flow-title`),p=c(`flow-detail`),m=c(`flow-photo`),h=c(`journey`),g=c(`flow-actions`),_=c(`flow-retry`),v=c(`flow-flat`),y=c(`settings-dialog`),b=c(`sample-dialog`),x=c(`credits-dialog`),S=c(`export-dialog`),C=c(`scene-menu`),w=c(`scene-menu-open`),T=c(`home-dialog`),E=c(`photo-adjust-panel`),D=!1,O=c(`first-guide`),k=[...e.querySelectorAll(`[data-sample-choice]`)],A=`dog5`,j=`누렁이`,M=null,N=c(`theme-select`),P=c(`canvas-wrap`),F=`entry`,I=!1,ee=`wood`,te=`personal`,ne=null,re=e.defaultView,ie=re?.matchMedia?.(`(prefers-reduced-motion: reduce)`),ae=!1,oe=!1,se,ce=0,le=!1,ue;try{ue=e.defaultView?.localStorage;let t=ue?.getItem(xp);t===`booth`&&(ee=t)}catch{}let L=new Set,de=`behind-glass.entry-completed.v1`,fe=a.name?`photo`:`name`;try{ue?.getItem(de)===`1`&&(fe=`photo`)}catch{}let pe=()=>{u.dataset.step=fe,c(`entry-name-step`).hidden=fe!==`name`,c(`entry-photo-step`).hidden=fe!==`photo`,c(`entry-notices`).hidden=fe!==`photo`,c(`entry-name-edit`).hidden=fe!==`photo`},R=()=>{a.setName(c(`entry-pet-name`).value),fe=`photo`;try{ue?.setItem(de,`1`)}catch{}pe(),c(`entry-photo-button`).focus({preventScroll:!0})};c(`entry-name-next`).addEventListener(`click`,R,{signal:t}),c(`entry-name-skip`).addEventListener(`click`,()=>{c(`entry-pet-name`).value=``,R()},{signal:t}),c(`entry-name-edit`).addEventListener(`click`,()=>{fe=`name`,pe(),c(`entry-pet-name`).focus({preventScroll:!0})},{signal:t}),c(`entry-pet-name`).addEventListener(`keydown`,e=>{e.key===`Enter`&&!e.isComposing&&e.keyCode!==229&&!L.has(c(`entry-pet-name`))&&(e.preventDefault(),R())},{signal:t}),pe();let me=()=>I||F!==`ready`||le||y.open||b.open||x.open||S.open||O.open||C.open||T.open,z=()=>{P.inert=me(),c(`photo-adjust-open`).hidden=me()||D},B=()=>{D&&(D=!1,E.hidden=!0,delete l.dataset.photoAdjust,P.setAttribute(`aria-label`,`사진 미리보기. 드래그하거나 방향키로 시점을 움직이세요`),P.setAttribute(`aria-describedby`,`scene-instructions`),s(!1),z())},he=()=>{t.aborted||me()||D||(D=!0,E.hidden=!1,l.dataset.photoAdjust=`true`,P.setAttribute(`aria-label`,`사진 위치 조절. 드래그하거나 방향키로 사진을 옮기세요`),P.setAttribute(`aria-describedby`,`photo-adjust-help`),s(!0),z(),P.focus({preventScroll:!0}))};c(`photo-adjust-done`).addEventListener(`click`,()=>{B(),me()||c(`photo-adjust-open`).focus({preventScroll:!0})},{signal:t}),e.addEventListener(`keydown`,e=>{e.key===`Escape`&&D&&(e.preventDefault(),B(),me()||c(`photo-adjust-open`).focus({preventScroll:!0}))},{signal:t});let ge=(e=!1)=>{T.open&&(T.close(),z(),e&&!t.aborted&&!I&&F!==`entry`&&c(`sample-home`).focus({preventScroll:!0}))};c(`home-cancel`).addEventListener(`click`,()=>ge(!0),{signal:t}),T.addEventListener(`cancel`,e=>{e.preventDefault(),ge(!0)},{signal:t}),T.addEventListener(`click`,e=>{if(e.target!==T)return;let t=T.getBoundingClientRect();(e.clientXt.right||e.clientYt.bottom)&&ge(!0)},{signal:t}),T.addEventListener(`close`,()=>{T.open||z()},{signal:t});let _e=(e=!1)=>{C.open&&(C.close(),w.setAttribute(`aria-expanded`,`false`),z(),e&&!t.aborted&&!I&&F!==`entry`&&w.focus({preventScroll:!0}))};w.addEventListener(`click`,()=>{t.aborted||I||F===`entry`||C.open||y.open||b.open||x.open||S.open||O.open||T.open||(B(),le&&be(!1),C.showModal(),w.setAttribute(`aria-expanded`,`true`),z(),c(`scene-menu-close`).focus())},{signal:t}),c(`scene-menu-close`).addEventListener(`click`,()=>_e(!0),{signal:t}),C.addEventListener(`cancel`,e=>{e.preventDefault(),_e(!0)},{signal:t}),C.addEventListener(`click`,e=>{if(e.target!==C)return;let t=C.getBoundingClientRect();(e.clientXt.right||e.clientYt.bottom)&&_e(!0)},{signal:t}),C.addEventListener(`close`,()=>{C.open||(w.setAttribute(`aria-expanded`,`false`),z())},{signal:t});for(let e of[`export-open`,`scene-photo-change`,`settings-open`,`scene-zoom-reset`,`comparison-exit`,`scene-guide-replay`,`sample-home`])c(e).addEventListener(`click`,()=>_e(),{capture:!0,signal:t});let ve=()=>{ce+=1,le=!1,se!==void 0&&re?.clearTimeout(se),se=void 0},ye=()=>{d.dataset.motion=ie?.matches?`paused`:`running`},be=(e=!0)=>{let t=le;ve(),F===`ready`&&(d.hidden=!0),z(),t&&e&&!me()&&(P.focus({preventScroll:!0}),r())},xe=()=>{let e=te===`sample`&&F!==`entry`;c(`scene-photo-change`).hidden=e||F===`entry`,c(`settings-open`).hidden=e||F===`entry`,c(`credits-open`).hidden=F!==`entry`,c(`export-open`).hidden=e||F!==`ready`,c(`sample-home`).hidden=F===`entry`,w.hidden=F===`entry`,c(`scene-guide-replay`).hidden=e||F!==`ready`||ee!==`wood`},Se=()=>{let e=kf(a.name);c(`welcome-name`).textContent=`${e.subject} 왔어요`,c(`entry-photo-button`).textContent=`${e.display} 사진 고르기`,c(`image`).setAttribute(`aria-label`,`${e.display} 사진 선택`),c(`pet-stage`).setAttribute(`aria-label`,te===`sample`?`유리문 너머의 샘플 사진`:`유리문 너머의 ${e.display}`),m.alt=te===`sample`?`선택한 샘플 사진`:`선택한 ${e.display} 사진`;let t=kf(te===`sample`?j:a.name);F===`error`?f.textContent=`사진을 준비하지 못했어요`:d.dataset.journey===`unpacking`?f.textContent=`짐을 푸는 중…`:d.dataset.journey===`arrived`?f.textContent=ee===`wood`?`${t.subject} 할머니 집에 도착했어요`:`${t.possessive} 포토부스에 도착했어요`:f.textContent=ee===`wood`?`${t.object} 할머니 집으로 데려가는 중…`:`${t.possessive} 포토부스를 준비하는 중…`},Ce=[c(`entry-pet-name`),c(`settings-pet-name`)],we=()=>{c(`entry-name-skip`).hidden=!!c(`entry-pet-name`).value.trim()},Te=()=>{for(let t of Ce)e.activeElement!==t&&!L.has(t)&&(t.value=a.name);for(let e of[`entry`,`settings`])c(`${e}-name-notice`).hidden=!a.storageUnavailable,c(`${e}-pet-name`).setAttribute(`aria-describedby`,`${e}-name-help${a.storageUnavailable?` ${e}-name-notice`:``}`);Se(),we()};for(let e of Ce){e.value=a.name;let n=(t=!1)=>{L.has(e)||(a.setName(e.value),(t||Array.from(e.value.normalize(`NFC`).trim()).length>20)&&(e.value=Of(e.value)))};e.addEventListener(`compositionstart`,()=>L.add(e),{signal:t}),e.addEventListener(`compositionend`,()=>{L.delete(e),n(!0),we()},{signal:t}),e.addEventListener(`input`,e=>{e.isComposing||n(),we()},{signal:t}),e.addEventListener(`change`,()=>n(!0),{signal:t}),e.addEventListener(`blur`,()=>n(!0),{signal:t})}a.subscribe(Te,t),Te();let Ee=()=>{e.documentElement.dataset.theme=ee,N.value=ee,n(ee),Se(),xe(),e.querySelector(`meta[name="theme-color"]`)?.setAttribute(`content`,Sp[ee].background)},De=()=>{y.open&&y.close()},Oe=!1,ke=(e=!0)=>{e||(Oe=!1),x.open&&x.close()};c(`credits-open`).addEventListener(`click`,()=>{F!==`entry`||I||t.aborted||x.open||b.open||y.open||(Oe=!0,x.showModal(),z(),c(`credits-close`).focus())},{signal:t}),c(`credits-close`).addEventListener(`click`,()=>ke(),{signal:t}),x.addEventListener(`cancel`,e=>{e.preventDefault(),ke()},{signal:t}),x.addEventListener(`click`,e=>{if(e.target!==x)return;let t=x.getBoundingClientRect();(e.clientXt.right||e.clientYt.bottom)&&ke()},{signal:t}),x.addEventListener(`close`,()=>{z(),Oe&&F===`entry`&&!t.aborted&&c(`credits-open`).focus(),Oe=!1},{signal:t});let Ae=(e=!0)=>{e||(M=null),b.open&&b.close()},je=e=>{I||t.aborted||(le&&be(!1),B(),ge(),_e(),ke(!1),De(),M=e,b.showModal(),z(),(k.find(e=>e.dataset.sampleChoice===A)??c(`sample-close`)).focus())};k.forEach(e=>e.setAttribute(`aria-pressed`,String(e.dataset.sampleChoice===A))),k.forEach(e=>e.addEventListener(`click`,()=>{A=e.dataset.sampleChoice,k.forEach(t=>t.setAttribute(`aria-pressed`,String(t===e)))},{signal:t})),c(`sample-confirm`).addEventListener(`click`,()=>{!b.open||I||t.aborted||(Ae(!1),i(A))},{signal:t}),c(`sample-close`).addEventListener(`click`,()=>Ae(),{signal:t}),c(`flow-samples`).addEventListener(`click`,()=>je(c(`flow-samples`)),{signal:t}),b.addEventListener(`cancel`,e=>{e.preventDefault(),Ae()},{signal:t}),b.addEventListener(`click`,e=>{if(e.target!==b)return;let t=b.getBoundingClientRect();(e.clientXt.right||e.clientYt.bottom)&&Ae()},{signal:t}),b.addEventListener(`close`,()=>{z(),M?.isConnected&&M.focus(),M=null},{signal:t});let Me=e=>{F!==`entry`&&te!==`sample`&&(le&&be(!1),B(),ge(),Ae(!1),_e(),ne=e===c(`settings-open`)?w:e,y.showModal(),z(),c(`settings-close`).focus())};c(`settings-open`).addEventListener(`click`,()=>Me(c(`settings-open`)),{signal:t}),c(`settings-close`).addEventListener(`click`,De,{signal:t}),c(`entry-samples`).addEventListener(`click`,()=>je(c(`entry-samples`)),{signal:t}),y.addEventListener(`cancel`,e=>{e.preventDefault(),De()},{signal:t}),y.addEventListener(`click`,e=>{if(e.target!==y)return;let t=y.getBoundingClientRect();(e.clientXt.right||e.clientYt.bottom)&&De()},{signal:t}),y.addEventListener(`close`,()=>{z(),ne?.isConnected&&ne.focus()},{signal:t}),N.addEventListener(`change`,()=>{let e=N.value===`booth`?`booth`:`wood`;if(e!==ee){ee=e,Ee();try{ue?.setItem(xp,ee)}catch{}}},{signal:t}),ie?.addEventListener(`change`,()=>{ye(),ie.matches&&le&&be()},{signal:t});let Ne=(e,t=!1,n=!1)=>{let i=e===`ready`&&oe&&ae&&!I;if(ve(),oe=!1,F=e,B(),ge(),_e(),e!==`entry`&&ke(!1),S.open&&S.close(),O.open&&O.close(),(e===`loading`||e===`error`)&&(De(),Ae(!1)),l.dataset.flow=e,u.hidden=e!==`entry`,d.hidden=e===`entry`||e===`ready`,d.dataset.journey=i?`arrived`:`idle`,p.hidden=i,g.hidden=e!==`error`,c(`flow-samples`).hidden=e!==`error`,_.hidden=e!==`error`||!(t||n),_.textContent=n?`동영상 재생하기`:`다시 시도하기`,v.hidden=e!==`error`||!t,Se(),xe(),d.setAttribute(`aria-busy`,String(e===`loading`)),ye(),i&&!ie?.matches&&re?.setTimeout){le=!0,d.hidden=!1;let e=ce;se=re.setTimeout(()=>{e===ce&&(d.dataset.journey=`unpacking`,f.textContent=`짐을 푸는 중…`,se=re.setTimeout(()=>{e===ce&&be()},1500))},1350)}z(),i&&!me()&&(P.focus({preventScroll:!0}),r())};return c(`sample-home`).addEventListener(`click`,()=>{t.aborted||I||F===`entry`||T.open||y.open||b.open||S.open||O.open||(B(),_e(),T.showModal(),z(),c(`home-cancel`).focus())},{signal:t}),c(`home-confirm`).addEventListener(`click`,()=>{t.aborted||I||F===`entry`||!T.open||(ge(),o(),ne=null,M=null,S.open&&S.close(),O.open&&O.close(),De(),Ae(!1),ve(),oe=!1,ae=!1,m.src=``,m.hidden=!0,h.hidden=!0,te=`personal`,fe=`photo`,pe(),Ne(`entry`),c(`entry-photo-button`).focus({preventScroll:!0}))},{signal:t}),t.addEventListener(`abort`,()=>{B(),ge(),_e(),O.open&&O.close(),ke(!1),Ae(!1),ve(),oe=!1,d.dataset.journey=`idle`,d.hidden=!0},{once:!0}),Ee(),Ne(`entry`),{setState:Ne,isBlocked:me,startPhotoAdjust:he,stopPhotoAdjust:B,isPhotoAdjusting:()=>D,canAdjustPhoto(){return!t.aborted&&!I&&F===`ready`&&!le&&!y.open&&!b.open&&!O.open&&!T.open&&!S.open},isGuideOpen:()=>O.open,refreshBlocking:z,canShowFirstGuide(){return F===`ready`&&te===`personal`&&ee===`wood`&&!D&&!me()},canExportPhoto(){return!t.aborted&&!I&&F===`ready`&&te===`personal`&&!le&&!y.open&&!b.open&&!O.open&&!T.open&&!D},setSampleName(e){j=e,Se()},canAcceptPhotoPaste(){return!t.aborted&&!I&&!y.open&&!b.open&&!x.open&&!S.open&&!O.open&&!C.open&&!T.open&&!D&&(F===`entry`?fe===`photo`:te===`personal`)},setMediaOrigin(e){B(),te=e,Se(),xe()},startJourney(){Ne(`loading`),!(I||t.aborted)&&(oe=!0,d.dataset.journey=`driving`,ye())},setRenderLost(e){I=e,e&&(B(),ge(),_e(),O.open&&O.close(),S.open&&S.close(),ke(!1),De(),Ae(!1),ve(),oe=!1,d.dataset.journey=`idle`,F===`ready`&&(d.hidden=!0),ye()),z()},setDetail(e){p.textContent=e},setPhoto(e){B(),ve(),oe=!1,d.dataset.journey=`idle`,F===`ready`&&(d.hidden=!0),ae=!!e,m.src=e,m.hidden=!e,h.hidden=!e,ye(),z()}}}var wp=class{canvas;dialog;reloadButton;onLost;onRestored;reload;lost=!1;visibility;constructor(e,t,n,r,i,a){this.canvas=e,this.dialog=t,this.reloadButton=n,this.onLost=r,this.onRestored=i,this.reload=a,this.visibility=e.style.visibility,e.addEventListener(`webglcontextlost`,this.contextLost),e.addEventListener(`webglcontextrestored`,this.contextRestored),t.addEventListener(`cancel`,this.preventDismiss),n.addEventListener(`click`,this.reload)}preventDismiss=e=>{e.preventDefault()};contextLost=e=>{e.preventDefault(),!this.lost&&(this.lost=!0,this.canvas.style.visibility=`hidden`,this.onLost(),this.dialog.open||this.dialog.showModal(),this.reloadButton.focus())};contextRestored=()=>{if(this.lost){try{this.onRestored()}catch{return}this.lost=!1,this.canvas.style.visibility=this.visibility,this.dialog.open&&this.dialog.close()}};dispose(){this.canvas.removeEventListener(`webglcontextlost`,this.contextLost),this.canvas.removeEventListener(`webglcontextrestored`,this.contextRestored),this.dialog.removeEventListener(`cancel`,this.preventDismiss),this.reloadButton.removeEventListener(`click`,this.reload),this.dialog.open&&this.dialog.close()}};function Tp(e,t=!1){let n=e[0].index!==null,r=new Set(Object.keys(e[0].attributes)),i=new Set(Object.keys(e[0].morphAttributes)),a={},o={},s=e[0].morphTargetsRelative,c=new Zi,l=0;for(let u=0;u=2.0 are supported.`));return}let c=new wm(i,{path:t||this.resourcePath||``,crossOrigin:this.crossOrigin,requestHeader:this.requestHeader,manager:this.manager,ktx2Loader:this.ktx2Loader,meshoptDecoder:this.meshoptDecoder});c.fileLoader.setRequestHeader(this.requestHeader);for(let e=0;e=0&&o[t]===void 0&&console.warn(`THREE.GLTFLoader: Unknown extension "`+t+`".`)}}c.setExtensions(a),c.setPlugins(o),c.parse(n,r)}parseAsync(e,t){let n=this;return new Promise(function(r,i){n.parse(e,t,r,i)})}};function kp(){let e={};return{get:function(t){return e[t]},add:function(t,n){e[t]=n},remove:function(t){delete e[t]},removeAll:function(){e={}}}}var Ap={KHR_BINARY_GLTF:`KHR_binary_glTF`,KHR_DRACO_MESH_COMPRESSION:`KHR_draco_mesh_compression`,KHR_LIGHTS_PUNCTUAL:`KHR_lights_punctual`,KHR_MATERIALS_CLEARCOAT:`KHR_materials_clearcoat`,KHR_MATERIALS_DISPERSION:`KHR_materials_dispersion`,KHR_MATERIALS_IOR:`KHR_materials_ior`,KHR_MATERIALS_SHEEN:`KHR_materials_sheen`,KHR_MATERIALS_SPECULAR:`KHR_materials_specular`,KHR_MATERIALS_TRANSMISSION:`KHR_materials_transmission`,KHR_MATERIALS_IRIDESCENCE:`KHR_materials_iridescence`,KHR_MATERIALS_ANISOTROPY:`KHR_materials_anisotropy`,KHR_MATERIALS_UNLIT:`KHR_materials_unlit`,KHR_MATERIALS_VOLUME:`KHR_materials_volume`,KHR_TEXTURE_BASISU:`KHR_texture_basisu`,KHR_TEXTURE_TRANSFORM:`KHR_texture_transform`,KHR_MESH_QUANTIZATION:`KHR_mesh_quantization`,KHR_MATERIALS_EMISSIVE_STRENGTH:`KHR_materials_emissive_strength`,EXT_MATERIALS_BUMP:`EXT_materials_bump`,EXT_TEXTURE_WEBP:`EXT_texture_webp`,EXT_TEXTURE_AVIF:`EXT_texture_avif`,EXT_MESHOPT_COMPRESSION:`EXT_meshopt_compression`,EXT_MESH_GPU_INSTANCING:`EXT_mesh_gpu_instancing`},jp=class{constructor(e){this.parser=e,this.name=Ap.KHR_LIGHTS_PUNCTUAL,this.cache={refs:{},uses:{}}}_markDefs(){let e=this.parser,t=this.parser.json.nodes||[];for(let n=0,r=t.length;n=0)throw Error(`THREE.GLTFLoader: setKTX2Loader must be called before loading KTX2 textures`);return null}return t.loadTextureImage(e,i.source,a)}},Gp=class{constructor(e){this.parser=e,this.name=Ap.EXT_TEXTURE_WEBP,this.isSupported=null}loadTexture(e){let t=this.name,n=this.parser,r=n.json,i=r.textures[e];if(!i.extensions||!i.extensions[t])return null;let a=i.extensions[t],o=r.images[a.source],s=n.textureLoader;if(o.uri){let e=n.options.manager.getHandler(o.uri);e!==null&&(s=e)}return this.detectSupport().then(function(i){if(i)return n.loadTextureImage(e,a.source,s);if(r.extensionsRequired&&r.extensionsRequired.indexOf(t)>=0)throw Error(`THREE.GLTFLoader: WebP required by asset but unsupported.`);return n.loadTexture(e)})}detectSupport(){return this.isSupported||=new Promise(function(e){let t=new Image;t.src=`data:image/webp;base64,UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA`,t.onload=t.onerror=function(){e(t.height===1)}}),this.isSupported}},Kp=class{constructor(e){this.parser=e,this.name=Ap.EXT_TEXTURE_AVIF,this.isSupported=null}loadTexture(e){let t=this.name,n=this.parser,r=n.json,i=r.textures[e];if(!i.extensions||!i.extensions[t])return null;let a=i.extensions[t],o=r.images[a.source],s=n.textureLoader;if(o.uri){let e=n.options.manager.getHandler(o.uri);e!==null&&(s=e)}return this.detectSupport().then(function(i){if(i)return n.loadTextureImage(e,a.source,s);if(r.extensionsRequired&&r.extensionsRequired.indexOf(t)>=0)throw Error(`THREE.GLTFLoader: AVIF required by asset but unsupported.`);return n.loadTexture(e)})}detectSupport(){return this.isSupported||=new Promise(function(e){let t=new Image;t.src=`data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAABcAAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAEAAAABAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQAMAAAAABNjb2xybmNseAACAAIABoAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAAB9tZGF0EgAKCBgABogQEDQgMgkQAAAAB8dSLfI=`,t.onload=t.onerror=function(){e(t.height===1)}}),this.isSupported}},qp=class{constructor(e){this.name=Ap.EXT_MESHOPT_COMPRESSION,this.parser=e}loadBufferView(e){let t=this.parser.json,n=t.bufferViews[e];if(n.extensions&&n.extensions[this.name]){let e=n.extensions[this.name],r=this.parser.getDependency(`buffer`,e.buffer),i=this.parser.options.meshoptDecoder;if(!i||!i.supported){if(t.extensionsRequired&&t.extensionsRequired.indexOf(this.name)>=0)throw Error(`THREE.GLTFLoader: setMeshoptDecoder must be called before loading compressed files`);return null}return r.then(function(t){let n=e.byteOffset||0,r=e.byteLength||0,a=e.count,o=e.byteStride,s=new Uint8Array(t,n,r);return i.decodeGltfBufferAsync?i.decodeGltfBufferAsync(a,o,s,e.mode,e.filter).then(function(e){return e.buffer}):i.ready.then(function(){let t=new ArrayBuffer(a*o);return i.decodeGltfBuffer(new Uint8Array(t),a,o,s,e.mode,e.filter),t})})}return null}},Jp=class{constructor(e){this.name=Ap.EXT_MESH_GPU_INSTANCING,this.parser=e}createNodeMesh(e){let t=this.parser.json,n=t.nodes[e];if(!n.extensions||!n.extensions[this.name]||n.mesh===void 0)return null;let r=t.meshes[n.mesh];for(let e of r.primitives)if(e.mode!==am.TRIANGLES&&e.mode!==am.TRIANGLE_STRIP&&e.mode!==am.TRIANGLE_FAN&&e.mode!==void 0)return null;let i=n.extensions[this.name].attributes,a=[],o={};for(let e in i)a.push(this.parser.getDependency(`accessor`,i[e]).then(t=>(o[e]=t,o[e])));return a.length<1?null:(a.push(this.parser.createNodeMesh(e)),Promise.all(a).then(e=>{let t=e.pop(),n=t.isGroup?t.children:[t],r=e[0].count,i=[];for(let e of n){let t=new G,n=new W,a=new cr,s=new W(1,1,1),c=new Sl(e.geometry,e.material,r);for(let e=0;e0||e.search(/^data\:image\/jpeg/)===0?`image/jpeg`:e.search(/\.webp($|\?)/i)>0||e.search(/^data\:image\/webp/)===0?`image/webp`:`image/png`}var Cm=new G,wm=class{constructor(e={},t={}){this.json=e,this.extensions={},this.plugins={},this.options=t,this.cache=new kp,this.associations=new Map,this.primitiveCache={},this.nodeCache={},this.meshCache={refs:{},uses:{}},this.cameraCache={refs:{},uses:{}},this.lightCache={refs:{},uses:{}},this.sourceCache={},this.textureCache={},this.nodeNamesUsed={};let n=!1,r=-1,i=!1,a=-1;if(typeof navigator<`u`){let e=navigator.userAgent;n=/^((?!chrome|android).)*safari/i.test(e)===!0;let t=e.match(/Version\/(\d+)/);r=n&&t?parseInt(t[1],10):-1,i=e.indexOf(`Firefox`)>-1,a=i?e.match(/Firefox\/([0-9]+)\./)[1]:-1}this.textureLoader=typeof createImageBitmap>`u`||n&&r<17||i&&a<98?new zd(this.options.manager):new rf(this.options.manager),this.textureLoader.setCrossOrigin(this.options.crossOrigin),this.textureLoader.setRequestHeader(this.options.requestHeader),this.fileLoader=new Ld(this.options.manager),this.fileLoader.setResponseType(`arraybuffer`),this.options.crossOrigin===`use-credentials`&&this.fileLoader.setWithCredentials(!0)}setExtensions(e){this.extensions=e}setPlugins(e){this.plugins=e}parse(e,t){let n=this,r=this.json,i=this.extensions;this.cache.removeAll(),this.nodeCache={},this._invokeAll(function(e){return e._markDefs&&e._markDefs()}),Promise.all(this._invokeAll(function(e){return e.beforeRoot&&e.beforeRoot()})).then(function(){return Promise.all([n.getDependencies(`scene`),n.getDependencies(`animation`),n.getDependencies(`camera`)])}).then(function(t){let a={scene:t[0][r.scene||0],scenes:t[0],animations:t[1],cameras:t[2],asset:r.asset,parser:n,userData:{}};return hm(i,a,r),gm(a,r),Promise.all(n._invokeAll(function(e){return e.afterRoot&&e.afterRoot(a)})).then(function(){for(let e of a.scenes)e.updateMatrixWorld();e(a)})}).catch(t)}_markDefs(){let e=this.json.nodes||[],t=this.json.skins||[],n=this.json.meshes||[];for(let n=0,r=t.length;n{let n=this.associations.get(e);n!=null&&this.associations.set(t,n);for(let[n,r]of e.children.entries())i(r,t.children[n])};return i(n,r),r.name+=`_instance_`+e.uses[t]++,r}_invokeOne(e){let t=Object.values(this.plugins);t.push(this);for(let n=0;n=2&&p.setY(t,u[e*a+1]),a>=3&&p.setZ(t,u[e*a+2]),a>=4&&p.setW(t,u[e*a+3]),a>=5)throw Error(`THREE.GLTFLoader: Unsupported itemSize in sparse BufferAttribute.`)}p.normalized=d}return p})}loadTexture(e){let t=this.json,n=this.options,r=t.textures[e].source,i=t.images[r],a=this.textureLoader;if(i.uri){let e=n.manager.getHandler(i.uri);e!==null&&(a=e)}return this.loadTextureImage(e,r,a)}loadTextureImage(e,t,n){let r=this,i=this.json,a=i.textures[e],o=i.images[t],s=(o.uri||o.bufferView)+`:`+a.sampler;if(this.textureCache[s])return this.textureCache[s];let c=this.loadImageSource(t,n).then(function(t){t.flipY=!1,t.name=a.name||o.name||``,t.name===``&&typeof o.uri==`string`&&o.uri.startsWith(`data:image/`)===!1&&(t.name=o.uri);let n=(i.samplers||{})[a.sampler]||{};return t.magFilter=sm[n.magFilter]||1006,t.minFilter=sm[n.minFilter]||1008,t.wrapS=cm[n.wrapS]||1e3,t.wrapT=cm[n.wrapT]||1e3,r.associations.set(t,{textures:e}),t}).catch(function(){return null});return this.textureCache[s]=c,c}loadImageSource(e,t){let n=this,r=this.json,i=this.options;if(this.sourceCache[e]!==void 0)return this.sourceCache[e].then(e=>e.clone());let a=r.images[e],o=self.URL||self.webkitURL,s=a.uri||``,c=!1;if(a.bufferView!==void 0)s=n.getDependency(`bufferView`,a.bufferView).then(function(e){c=!0;let t=new Blob([e],{type:a.mimeType});return s=o.createObjectURL(t),s});else if(a.uri===void 0)throw Error(`THREE.GLTFLoader: Image `+e+` is missing URI and bufferView`);let l=Promise.resolve(s).then(function(e){return new Promise(function(n,r){let a=n;t.isImageBitmapLoader===!0&&(a=function(e){let t=new nr(e);t.needsUpdate=!0,n(t)}),t.load(nf.resolveURL(e,i.path),a,void 0,r)})}).then(function(e){return c===!0&&o.revokeObjectURL(s),gm(e,a),e.userData.mimeType=a.mimeType||Sm(a.uri),e}).catch(function(e){throw console.error(`THREE.GLTFLoader: Couldn't load texture`,s),e});return this.sourceCache[e]=l,l}assignTexture(e,t,n,r){let i=this;return this.getDependency(`texture`,n.index).then(function(a){if(!a)return null;if(n.texCoord!==void 0&&n.texCoord>0&&(a=a.clone(),a.channel=n.texCoord),i.extensions[Ap.KHR_TEXTURE_TRANSFORM]){let e=n.extensions===void 0?void 0:n.extensions[Ap.KHR_TEXTURE_TRANSFORM];if(e){let t=i.associations.get(a);a=i.extensions[Ap.KHR_TEXTURE_TRANSFORM].extendTexture(a,e),i.associations.set(a,t)}}return r!==void 0&&(a.colorSpace=r),e[t]=a,a})}assignFinalMaterial(e){let t=e.geometry,n=e.material,r=t.attributes.tangent===void 0,i=t.attributes.color!==void 0,a=t.attributes.normal===void 0;if(e.isPoints){let e=`PointsMaterial:`+n.uuid,t=this.cache.get(e);t||(t=new Ll,ji.prototype.copy.call(t,n),t.color.copy(n.color),t.map=n.map,t.sizeAttenuation=!1,this.cache.add(e,t)),n=t}else if(e.isLine){let e=`LineBasicMaterial:`+n.uuid,t=this.cache.get(e);t||(t=new Cl,ji.prototype.copy.call(t,n),t.color.copy(n.color),t.map=n.map,this.cache.add(e,t)),n=t}if(r||i||a){let e=`ClonedMaterial:`+n.uuid+`:`;r&&(e+=`derivative-tangents:`),i&&(e+=`vertex-colors:`),a&&(e+=`flat-shading:`);let t=this.cache.get(e);t||(t=n.clone(),i&&(t.vertexColors=!0),a&&(t.flatShading=!0),r&&(t.normalScale&&(t.normalScale.y*=-1),t.clearcoatNormalScale&&(t.clearcoatNormalScale.y*=-1)),this.cache.add(e,t),this.associations.set(t,this.associations.get(n))),n=t}e.material=n}getMaterialType(){return ud}loadMaterial(e){let t=this,n=this.json,r=this.extensions,i=n.materials[e],a,o={},s=i.extensions||{},c=[];if(s[Ap.KHR_MATERIALS_UNLIT]){let e=r[Ap.KHR_MATERIALS_UNLIT];a=e.getMaterialType(),c.push(e.extendParams(o,i,t))}else{let n=i.pbrMetallicRoughness||{};if(o.color=new K(1,1,1),o.opacity=1,Array.isArray(n.baseColorFactor)){let e=n.baseColorFactor;o.color.setRGB(e[0],e[1],e[2],Zt),o.opacity=e[3]}n.baseColorTexture!==void 0&&c.push(t.assignTexture(o,`map`,n.baseColorTexture,Xt)),o.metalness=n.metallicFactor===void 0?1:n.metallicFactor,o.roughness=n.roughnessFactor===void 0?1:n.roughnessFactor,n.metallicRoughnessTexture!==void 0&&(c.push(t.assignTexture(o,`metalnessMap`,n.metallicRoughnessTexture)),c.push(t.assignTexture(o,`roughnessMap`,n.metallicRoughnessTexture))),a=this._invokeOne(function(t){return t.getMaterialType&&t.getMaterialType(e)}),c.push(Promise.all(this._invokeAll(function(t){return t.extendMaterialParams&&t.extendMaterialParams(e,o)})))}i.doubleSided===!0&&(o.side=2);let l=i.alphaMode||pm.OPAQUE;if(l===pm.BLEND?(o.transparent=!0,o.depthWrite=!1):(o.transparent=!1,l===pm.MASK&&(o.alphaTest=i.alphaCutoff===void 0?.5:i.alphaCutoff)),i.normalTexture!==void 0&&a!==Mi&&(c.push(t.assignTexture(o,`normalMap`,i.normalTexture)),o.normalScale=new H(1,1),i.normalTexture.scale!==void 0)){let e=i.normalTexture.scale;o.normalScale.set(e,e)}if(i.occlusionTexture!==void 0&&a!==Mi&&(c.push(t.assignTexture(o,`aoMap`,i.occlusionTexture)),i.occlusionTexture.strength!==void 0&&(o.aoMapIntensity=i.occlusionTexture.strength)),i.emissiveFactor!==void 0&&a!==Mi){let e=i.emissiveFactor;o.emissive=new K().setRGB(e[0],e[1],e[2],Zt)}return i.emissiveTexture!==void 0&&a!==Mi&&c.push(t.assignTexture(o,`emissiveMap`,i.emissiveTexture,Xt)),Promise.all(c).then(function(){let n=new a(o);return i.name&&(n.name=i.name),gm(n,i),t.associations.set(n,{materials:e}),i.extensions&&hm(r,n,i),n})}createUniqueName(e){let t=gf.sanitizeNodeName(e||``);return t in this.nodeNamesUsed?t+`_`+ ++this.nodeNamesUsed[t]:(this.nodeNamesUsed[t]=0,t)}loadGeometries(e){let t=this,n=this.extensions,r=this.primitiveCache;function i(e){return n[Ap.KHR_DRACO_MESH_COMPRESSION].decodePrimitive(e,t).then(function(n){return Em(n,e,t)})}let a=[];for(let n=0,o=e.length;n0&&vm(d,i),d.name=t.createUniqueName(i.name||`mesh_`+e),gm(d,i),u.extensions&&hm(r,d,u),t.assignFinalMaterial(d),c.push(d)}for(let n=0,r=c.length;n1?new Lc:t.length===1?t[0]:new ui,o!==t[0])for(let e=0,n=t.length;e{let t=new Map;for(let[e,n]of r.associations)(e instanceof ji||e instanceof nr)&&t.set(e,n);return e.traverse(e=>{let n=r.associations.get(e);n!=null&&t.set(e,n)}),t})(i),i})}_createAnimationTracks(e,t,n,r,i){let a=[],o=e.name?e.name:e.uuid,s=[];dm[i.path]===dm.weights?e.traverse(function(e){e.morphTargetInfluences&&s.push(e.name?e.name:e.uuid)}):s.push(o);let c;switch(dm[i.path]){case dm.weights:c=wd;break;case dm.rotation:c=Ed;break;case dm.position:case dm.scale:c=Od;break;default:switch(n.itemSize){case 1:c=wd;break;default:c=Od}}let l=r.interpolation===void 0?Ht:fm[r.interpolation],u=this._getArrayFromAccessor(n);for(let e=0,n=s.length;e{let t=J.normal_fragment_maps.replace(`mapN.xy *= normalScale;`,`mapN.y *= 1.0 - 2.0 * mod(floor(vNormalMapUv.y), 2.0); + mapN.xy *= normalScale;`);e.fragmentShader=e.fragmentShader.replace(`#include `,t)},e.customProgramCacheKey=()=>`wood-mirrored-grain-r169-v1`}function Am(e){let t=new Set,n=new Set,r=new Set;e.traverse(e=>{if(e instanceof q){t.add(e.geometry);for(let t of Array.isArray(e.material)?e.material:[e.material])n.add(t)}}),n.forEach(e=>Object.values(e).forEach(e=>{e instanceof nr&&r.add(e)})),t.forEach(e=>e.dispose()),n.forEach(e=>e.dispose()),r.forEach(e=>e.dispose()),new Set([...r].map(e=>e.image)).forEach(e=>{typeof e?.close==`function`&&e.close()}),e.removeFromParent()}function jm(e){let t=e.geometry.getAttribute(`position`),n=e.geometry.index;if(!n)throw Error(`Window asset must have indexed triangles`);let r=Array.from({length:t.count},(e,t)=>t),i=new Map,a=e=>{for(;r[e]!==e;)r[e]=r[r[e]],e=r[e];return e},o=(e,t)=>{r[a(e)]=a(t)};for(let e=0;ee.toFixed(6)).join(`,`),r=i.get(n);r===void 0?i.set(n,e):o(e,r)}for(let e=0;e{let r=[1/0,1/0,1/0],i=[-1/0,-1/0,-1/0];n.forEach(e=>{for(let n=0;n<3;n++){let a=t.getComponent(e,n);r[n]=Math.min(r[n],a),i[n]=Math.max(i[n],a)}});let a=i[0]-r[0]>i[1]-r[1]?0:1,o=i[a]-r[a],s=(i[a]+r[a])/2,c=e.name===`MovableSash_Brass`||e.name===`MovableSash_Patina`&&r[2]>.05,l=o>.9;if(l&&n.some(e=>Math.min(Math.abs(t.getComponent(e,a)-r[a]),Math.abs(t.getComponent(e,a)-i[a]))>.00301))throw Error(`Unrecognized window beam topology`);return{ids:n,axis:a,center:s,length:o,beam:l,hardware:c}})}var Mm=(e,t,n,r)=>V.clamp(e,-t,t)*n/t+Math.sign(e)*Math.max(Math.abs(e)-t,0)*r;function Nm(e){if(!e.getObjectByName(`FixedSurround`)||!e.getObjectByName(`MovableSash`)||!e.getObjectByName(`BrassLatch`))throw Error(`Unrecognized window hierarchy`);e.updateMatrixWorld(!0);let t=new G().copy(e.matrixWorld).invert(),n=[];if(e.traverse(e=>{if(!(e instanceof q))return;e.geometry.applyMatrix4(new G().multiplyMatrices(t,e.matrixWorld)),e.position.set(0,0,0),e.quaternion.identity(),e.scale.set(1,1,1),e.updateMatrix();let r=jm(e);if(r.length!=={FixedSurround_Wood:10,MovableSash_Wood:12,MovableSash_Patina:7,MovableSash_Brass:5}[e.name])throw Error(`Unrecognized window components`);if(n.push({mesh:e,positions:new Float32Array(e.geometry.getAttribute(`position`).array),uvs:new Float32Array(e.geometry.getAttribute(`uv`).array),components:r}),e.name.endsWith(`_Wood`))for(let t of Array.isArray(e.material)?e.material:[e.material])km(t)}),n.length!==4||n.reduce((e,t)=>e+t.mesh.geometry.index.count/3,0)!==6988)throw Error(`Unrecognized window geometry`);let r=e.getObjectByName(`MovableSash`),i=new Na(new W(1,0,0),1),a=new Set;e.getObjectByName(`FixedSurround`).traverse(e=>{if(e instanceof q)for(let t of Array.isArray(e.material)?e.material:[e.material])a.add(t)});let o=new Map;r.traverse(e=>{if(!(e instanceof q))return;let t=t=>{let n=o.get(t);return n||(n=a.has(t)?t.clone():t,n.clippingPlanes=[i],e.name.endsWith(`_Wood`)&&km(n),o.set(t,n)),n};e.material=Array.isArray(e.material)?e.material.map(t):t(e.material)});let s=!1,c=0,l=1,u=()=>{r.position.x=c===0?0:-l*c,e.updateMatrixWorld(!0)};return{setOpen(e){Number.isFinite(e)&&(c=V.clamp(e,0,1),u())},handlePosition(t){return e.getObjectByName(`BrassLatch`).getWorldPosition(t)},resize(t,r,a){if(!Number.isFinite(t)||!Number.isFinite(r)||t<=0||r<=0)throw Error(`Invalid window aperture`);let o=Math.min(t,r);l=t,i.constant=t/2+.05*o;for(let e of n){let n=e.mesh.geometry.getAttribute(`position`),i=e.mesh.geometry.getAttribute(`uv`);for(let a of e.components)for(let s of a.ids){let c=[e.positions[s*3],e.positions[s*3+1],e.positions[s*3+2]],l=[Mm(c[0],.5,t/2,o),Mm(c[1],.66,r/2,o),c[2]*o],u=e.uvs[s*2+1];if(a.hardware)l[0]=t/2+.026*o+(c[0]-.526)*o,l[1]=-.235*r/1.32+(c[1]+.235)*o,l[2]=c[2]*o;else if(a.beam){let n=a.axis,i=n===0?1:1.32,s=n===0?t:r,d=c[n]{if(this.disposed){Am(e);return}try{this.asset=Nm(e),this.asset.resize(...this.size),this.asset.setOpen(this.openness)}catch(t){throw Am(e),this.asset=null,t}this.root=e,e.name=`blender-window-frame`,this.scene.add(e),this.state=`ready`,this.notify()}).catch(()=>{this.disposed||(this.state=`error`,this.notify())}).finally(()=>{this.pending=null}),this.pending)}dispose(){this.disposed||(this.disposed=!0,this.abort.abort(),this.asset?.dispose(),this.asset=null,this.root=null)}};function Im(e,t,n){let r=Math.min(e,t),i=Math.max(e/2+.95*r,t*.55),a=i/1.45;return{halfWidth:i,unit:a,floor:-t/2-.24*r,ceiling:Math.max(2.3,t/2+.73*r),front:n+.35*r,rear:Math.max(4.2,n+4.8*a)}}var Lm={grid:10,curvature:1},Rm=`/assets/window/grandma-house-surround.glb?v=2`,zm=e=>e===`wood`?.82:1,Bm=new Set([`HouseCurtain`,`HouseCurtainEmbroidery`,`HouseEntranceMat`,`HousePaintedTrim`,`HousePlaster`,`HouseSlippers`,`HouseThreshold`]),Vm=(e,t,n,r)=>V.clamp(e,-t,t)*n/t+Math.sign(e)*Math.max(Math.abs(e)-t,0)*r,Hm=Im;function Um(e,t,n,r,i){let{halfWidth:a,floor:o,ceiling:s,front:c,rear:l}=e,u=.12,d=s-o,f=l-c,p=[[-a-u/2,(o+s)/2,(c+l)/2,u,d,f],[a+u/2,(o+s)/2,(c+l)/2,u,d,f],[0,(o+s)/2,l+u/2,2*a+2*u,d,u],[0,s+u/2,(c+l)/2,2*a+2*u,u,f+u]],m=Math.min(n,r),h=n/2+.002*m,g=r/2+.002*m,_=n/2+.11*m,v=r/2+.12*m,y=Math.min(n/i.grid,r/Math.max(1,i.grid*r/n)),b=tp.heightPerCell*y*1.008*Math.abs(V.clamp(i.curvature,-1,1)),x=.002*m,S=t+b+.001*m+x/2;p.push([-(h+_)/2,0,S,_-h,2*v,x],[(h+_)/2,0,S,_-h,2*v,x],[0,(g+v)/2,t+.001*m,2*h,v-g,x],[0,-(g+v)/2,t+.001*m,2*h,v-g,x]);let C=p.map(([e,n,r,i,a,o])=>new da(i,a,o).translate(e,n,r-t)),w=Tp(C);C.forEach(e=>e.dispose());let T=w.getAttribute(`uv`);for(let e=0;e{let r=new K(n),i=new Float32Array(e.getAttribute(`position`).count*3);for(let e=0;ee.index?e.toNonIndexed():e),a=Tp(i);new Set([...t,...i]).forEach(e=>e.dispose());let o=new q(a,new ud({vertexColors:!0,roughness:.92}));return o.name=e,o}function Gm(e){let t=new Set,n=new Set,r=new Set;e.traverse(e=>{if(e instanceof q){t.add(e.geometry);for(let t of Array.isArray(e.material)?e.material:[e.material])n.add(t)}}),n.forEach(e=>Object.values(e).forEach(e=>{e instanceof nr&&r.add(e)})),t.forEach(e=>e.dispose()),n.forEach(e=>e.dispose()),r.forEach(e=>e.dispose()),new Set([...r].map(e=>e.image)).forEach(e=>{typeof e?.close==`function`&&e.close()}),e.removeFromParent()}function Km(e){if(!e.getObjectByName(`GrandmaHouseSurround`))throw Error(`Unrecognized house hierarchy`);e.updateMatrixWorld(!0);let t=new G().copy(e.matrixWorld).invert(),n=[];if(e.traverse(e=>{if(!(e instanceof q))return;if(!Bm.has(e.name))throw Error(`Unrecognized house component`);let r=new G().multiplyMatrices(t,e.matrixWorld);r.equals(new G)||e.geometry.applyMatrix4(r),e.position.set(0,0,0),e.quaternion.identity(),e.scale.set(1,1,1),e.updateMatrix(),e.geometry.computeBoundingBox(),n.push({mesh:e,positions:new Float32Array(e.geometry.getAttribute(`position`).array),normals:new Float32Array(e.geometry.getAttribute(`normal`).array),tangents:e.geometry.hasAttribute(`tangent`)?new Float32Array(e.geometry.getAttribute(`tangent`).array):null,center:e.geometry.boundingBox.getCenter(new W),rigid:e.name===`HouseSlippers`})}),n.length!==7||n.reduce((e,t)=>e+(t.mesh.geometry.index?.count??0)/3,0)!==20014)throw Error(`Unrecognized house geometry`);let r=n.find(e=>e.mesh.name===`HousePlaster`).mesh,i=new q(new Zi,r.material);i.name=`HouseRoomShell`,e.add(i);let a=[Wm(`RoomPictureLeft`),Wm(`RoomPictureRight`)];e.add(...a);let o=!1;return{resize(t,r,o,s=Math.min(t,r),c=!1,l=Lm){if(![t,r,o].every(Number.isFinite)||t<=0||r<=0)throw Error(`Invalid house aperture`);let u=Math.min(t,r),d=new W,f=new W,p=Hm(t,r,o),m=Math.min(c?.2*u:u,Math.max(.001,s));p.front=o+.35*m;let h=t/2+.8*u,g=r/2+.49*u,_=1.3*m,v=e=>Math.abs(e)<=1.3?Vm(e,.5,t/2,u):Math.sign(e)*(h+(Math.abs(e)-1.3)/.3*(p.halfWidth-h)),y=e=>e<=1.15?Vm(e,.66,r/2,u):g+(e-1.15)/.24*(p.ceiling-g),b=e=>e<=1.3?e*m:_+(e-1.3)/.67*(p.rear-o-_);for(let e of n){let n=e.mesh.geometry.getAttribute(`position`),i=e.mesh.geometry.getAttribute(`normal`),a=e.mesh.geometry.getAttribute(`tangent`),s=e.center,c=Vm(s.x,.5,t/2,u),l=Vm(s.y,.66,r/2,u);for(let x=0;x1.3?(p.halfWidth-h)/.3:Math.abs(S)>.5?u:t,E=e.rigid?u:C>1.15?(p.ceiling-g)/.24:Math.abs(C)>.66?u:r/1.32,D=w>1.3?(p.rear-o-_)/.67:m;d.fromArray(e.normals,x*3),(T!==u||E!==u||D!==u)&&d.set(d.x/T,d.y/E,d.z/D).normalize(),i.setXYZ(x,d.x,d.y,d.z),a&&e.tangents&&(f.fromArray(e.tangents,x*4),(T!==u||E!==u||D!==u)&&(f.set(f.x*T,f.y*E,f.z*D),f.addScaledVector(d,-f.dot(d)).normalize()),a.setXYZW(x,f.x,f.y,f.z,e.tangents[x*4+3]))}n.needsUpdate=!0,i.needsUpdate=!0,a&&(a.needsUpdate=!0),e.mesh.geometry.computeBoundingBox(),e.mesh.geometry.computeBoundingSphere()}i.geometry.dispose(),i.geometry=Um(p,o,t,r,l),a.forEach((e,t)=>{let n=t===0?-1:1;e.scale.setScalar(p.unit),e.rotation.y=-n*Math.PI/2,e.position.set(n*(p.halfWidth-.018*p.unit),Math.min(.08*r,p.floor+1.05*p.unit),p.front-o+.5*p.unit)}),e.position.z=o,e.updateMatrixWorld(!0)},dispose(){o||(o=!0,Gm(e))}}}async function qm(e){let t=await fetch(Rm,{signal:e});if(!t.ok)throw Error(`House surround load failed`);return(await new Op().parseAsync(await t.arrayBuffer(),``)).scene}var Jm=class{scene;onState;loader;root=null;asset=null;size=[1,1.32,.6,1];pane=Lm;theme=`wood`;composition=`legacy`;setCompositionMode(e){this.composition=e,this.asset?.resize(...this.size,e===`wall`,this.pane)}state=`idle`;pending=null;disposed=!1;abort=new AbortController;constructor(e,t,n=qm){this.scene=e,this.onState=t,this.loader=n}get isReady(){return this.state===`ready`}apply(e){this.theme=e,this.root&&(this.root.visible=e===`wood`)}resize(e,t,n,r=Math.min(e,t),i=Lm){this.size=[e,t,n,r],this.pane={...i},this.asset?.resize(...this.size,this.composition===`wall`,this.pane)}load(){return this.disposed||this.state===`ready`?Promise.resolve():this.pending?this.pending:(this.state=`loading`,this.onState(this.state),this.pending=this.loader(this.abort.signal).then(e=>{if(this.disposed){Gm(e);return}try{this.asset=Km(e),this.asset.resize(...this.size,this.composition===`wall`,this.pane)}catch(t){throw Gm(e),this.asset=null,t}this.root=e,e.name=`blender-house-surround`,this.scene.add(e),this.apply(this.theme),this.state=`ready`,this.onState(this.state)}).catch(()=>{this.disposed||(this.state=`error`,this.onState(this.state))}).finally(()=>{this.pending=null}),this.pending)}dispose(){this.disposed||(this.disposed=!0,this.abort.abort(),this.asset?.dispose(),this.asset=null,this.root=null)}};function Ym(e){let t=new ya({uniforms:e.material.uniforms,vertexShader:e.material.vertexShader,fragmentShader:`uniform sampler2D uTexture; uniform bool uUsePhotoAlpha; varying vec2 vUv; void main(){if(uUsePhotoAlpha && texture2D(uTexture,vUv).a < .5) discard; gl_FragColor=vec4(0.);}`,colorWrite:!1,depthWrite:!0,depthTest:!0}),n=new q(e.geometry,t);n.name=`house-photo-depth-occluder`,n.renderOrder=-1,n.frustumCulled=!1,n.matrixAutoUpdate=!1,n.visible=!1;let r=!1;return{mesh:n,sync(t){e.updateMatrixWorld(!0),n.matrix.copy(e.matrixWorld),n.matrixWorldNeedsUpdate=!0,n.visible=t},dispose(){r||(r=!0,n.removeFromParent(),t.dispose())}}}function Xm(e){let t=1024,n=new Uint8Array(128*t*4);for(let e=0;e[14074804,14797498,10983816,15785158,16777215,10257781].map(t=>new ud({color:t,map:e,bumpMap:e,bumpScale:.002,roughness:.43,metalness:0}))),this.reveals=this.textures.map(e=>new ud({color:12362123,map:e,roughness:.62,side:2}));let a=new Mi({color:3679510}),o=new Mi({color:3680025,transparent:!0,opacity:.18,depthWrite:!1}),s=new ud({color:10387783,roughness:.44,metalness:.65}),c=new ud({color:6444343,roughness:.58,metalness:.6});this.materials.push(...this.wood.flat(),...this.reveals,a,o,s,c);let l=new Cu;l.moveTo(-.46,-.46),l.lineTo(.46,-.46),l.lineTo(.46,.46),l.lineTo(-.46,.46),l.closePath(),this.geometry=new ad(l,{depth:.8,bevelEnabled:!0,bevelSize:.04,bevelThickness:.1,bevelSegments:3,steps:1}),this.geometry.translate(0,0,-.4);let u=this.geometry.getAttribute(`uv`);for(let e=0;enew q(this.geometry,this.wood[t<2?0:1][4])),this.grooves=Array.from({length:4},()=>new q(this.hardwareGeometry,a)),this.shadows=Array.from({length:4},()=>new q(this.hardwareGeometry,o)),this.panel=new q(this.geometry,this.wood[0][4]),this.panel.name=`lower-door-panel`,this.sill=new q(this.geometry,this.wood[1][4]),this.sill.name=`sill`,this.latch=new Lc,this.latch.name=`brass-latch`;let d=new q(this.geometry,s);d.scale.set(.025,.078,.007);let f=new q(this.geometry,s);f.scale.set(.016,.032,.013),f.position.z=.009;let p=new q(this.hardwareGeometry,a);p.scale.set(.003,.019,.002),p.position.set(0,.002,.017),this.latch.add(d,f,p);for(let e of[-.028,.028]){let t=new q(this.screwGeometry,c);t.rotation.x=Math.PI/2,t.scale.set(.005,.005,.005),t.position.set(0,e,.006),this.latch.add(t)}this.details.add(...this.shadows,this.panel,this.sill,...this.grooves,...this.beads,this.latch),this.light.position.set(3,4,5),e.add(this.details,this.ambient,this.light)}apply(e){this.theme=e;let t=e===`wood`;this.frames.forEach((e,n)=>{e.visible=!t||!this.assetActive,e.material=t?this.wood[n<2?0:1]:this.boothMaterials}),this.reveal.meshes.forEach((e,n)=>{e.material=t?this.reveals[n<2?0:1]:this.boothReveal}),this.details.visible=t&&!this.assetActive,this.ambient.visible=this.light.visible=t}setAssetActive(e){this.assetActive=e,this.apply(this.theme)}update(e,t,n,r,i){let a=n+i*.78,o=r*.3;this.beads.forEach((n,r)=>{n.position.set(r<2?(r===0?-1:1)*(e+o)/2:0,r<2?0:(r===2?1:-1)*(t+o)/2,a),n.scale.set(r<2?o:e+2*o,r<2?t:o,i*.23)}),this.grooves.forEach((n,a)=>{n.position.copy(this.beads[a].position),a<2?n.position.x+=(a===0?-1:1)*o*.63:n.position.y+=(a===2?1:-1)*o*.63,n.position.z-=i*.13,n.scale.set(a<2?r*.05:e+2*r,a<2?t:r*.05,.002)}),this.shadows.forEach((a,o)=>{a.position.copy(this.beads[o].position),o<2?a.position.x+=(o===0?-1:1)*r*.65:a.position.y+=(o===2?1:-1)*r*.65,a.position.z=n-i*.48,a.scale.set(o<2?r*1.65:e+2.7*r,o<2?t+r:r*1.65,.002)});let s=Math.min(.16,t*.12);this.panel.position.set(0,-(t/2+r+s/2),n+i*.05),this.panel.scale.set(e+r*2,s,i*.75),this.sill.position.set(0,-(t/2+r+s),n+i*.26),this.sill.scale.set(e+r*2.5,r*.75,i*1.35),this.latch.position.set((e+r)/2,-t*.17,a+i*.12),this.latch.scale.setScalar(Math.min(e,t)/1.1)}dispose(){this.details.removeFromParent(),this.ambient.removeFromParent(),this.light.removeFromParent(),this.geometry.dispose(),this.hardwareGeometry.dispose(),this.screwGeometry.dispose(),this.materials.forEach(e=>e.dispose()),this.textures.forEach(e=>e.dispose())}},Qm=262144;async function $m(e){if(typeof e.slice!=`function`)return null;try{let t=await e.slice(0,Qm).arrayBuffer(),n=new Uint8Array(t),r=new DataView(t),i=0,a=0,o=null;if(n.length>=24&&n[0]===137&&n[1]===80&&n[2]===78&&n[3]===71)i=r.getUint32(16),a=r.getUint32(20),o=await eh(e,n,!0);else if(n.length>=30&&String.fromCharCode(...n.slice(0,4))===`RIFF`&&String.fromCharCode(...n.slice(8,12))===`WEBP`){let t=String.fromCharCode(...n.slice(12,16));o=t!==`VP8X`||!(n[20]&8)?1:await eh(e,n,!1),t===`VP8X`?(i=1+n[24]+(n[25]<<8)+(n[26]<<16),a=1+n[27]+(n[28]<<8)+(n[29]<<16)):t===`VP8 `&&n[23]===157&&n[24]===1&&n[25]===42?(i=r.getUint16(26,!0)&16383,a=r.getUint16(28,!0)&16383):t===`VP8L`&&n[20]===47&&(i=1+((n[22]&63)<<8)+n[21],a=1+((n[24]&15)<<10)+(n[23]<<2)+(n[22]>>6))}else if(n.length>=4&&n[0]===255&&n[1]===216)for(let e=2;e+4<=n.length&&n[e]===255;){let t=n[e+1];if(t===217||t===218){o??=1;break}if(t===255){e++;continue}let s=r.getUint16(e+2),c=e+2+s;if(s<2||c>n.length)break;if(t===225&&s>=16&&String.fromCharCode(...n.slice(e+4,e+10))===`Exif\0\0`){let t=e+10,n=r.getUint16(t)===18761;if(r.getUint16(t+2,n)===42){let e=t+r.getUint32(t+4,n);if(e>=t&&e+2<=c){let t=r.getUint16(e,n);for(let i=0;ic)break;if(r.getUint16(t,n)===274&&r.getUint16(t+2,n)===3&&r.getUint32(t+4,n)===1){let e=r.getUint16(t+8,n);e>=1&&e<=8&&(o=e)}}}}}[192,193,194,195,197,198,199,201,202,203,205,206,207].includes(t)&&s>=7&&(a=r.getUint16(e+5),i=r.getUint16(e+7)),e=c}else if(n.length>=10&&String.fromCharCode(...n.slice(0,3))===`GIF`)i=r.getUint16(6,!0),a=r.getUint16(8,!0),o=1;else if(n.length>=26&&n[0]===66&&n[1]===77){let e=r.getUint32(14,!0);e===12?(i=r.getUint16(18,!0),a=r.getUint16(20,!0)):e>=40&&(i=r.getInt32(18,!0),a=Math.abs(r.getInt32(22,!0))),o=1}return i<1||a<1||!Number.isSafeInteger(i*a)?null:o!==null&&o>=5?{width:a,height:i,orientation:o}:{width:i,height:a,orientation:o}}catch{return null}}async function eh(e,t,n){let r=Qm,i=async(n,i)=>i>r||n<0||n+i>e.size?null:n+i<=t.length?t.subarray(n,n+i):(r-=i,new Uint8Array(await e.slice(n,n+i).arrayBuffer())),a=n?e.size:Math.min(e.size,new DataView(t.buffer,t.byteOffset,t.byteLength).getUint32(4,!0)+8),o=n?8:12;for(let e=0;e<512&&o+8<=a;e++){let e=await i(o,8);if(!e||e.length<8)return null;let t=new DataView(e.buffer,e.byteOffset,e.byteLength).getUint32(n?0:4,!n),r=String.fromCharCode(...e.subarray(n?4:0,n?8:4)),s=o+8+t+(n?4:t%2);if(s>a||s<=o)return null;if(r===(n?`eXIf`:`EXIF`)){let e=await i(o+8,t);return e?th(e):null}if(n&&r===`IEND`)return 1;o=s}return!n&&o===a?1:null}function th(e){let t=String.fromCharCode(...e.subarray(0,6))===`Exif\0\0`?6:0;if(e.lengthe.length)return null;let o=n.getUint16(a,i);for(let t=0;te.length)return null;if(n.getUint16(r,i)===274){if(n.getUint16(r+2,i)!==3||n.getUint32(r+4,i)!==1)return null;let e=n.getUint16(r+8,i);return e>=1&&e<=8?e:null}}return 1}var nh=1024;function rh(e,t){if(!Number.isInteger(e)||!Number.isInteger(t)||e<1||t<1)throw Error(`사진 크기를 확인할 수 없어요.`);if(e>32768||t>32768||e*t>64e6)throw Error(`사진이 너무 커요. 긴 변 8,000픽셀 이하로 줄인 사본을 선택해 주세요.`);let n=Math.min(1,nh/Math.max(e,t));return{width:Math.max(1,Math.round(e*n)),height:Math.max(1,Math.round(t*n))}}async function ih(e,t,n){n.throwIfAborted();let r=await $m(e);n.throwIfAborted();let i=r?rh(r.width,r.height):null;if(typeof createImageBitmap!=`function`)throw Error(`이 브라우저에서 사진 준비를 지원하지 않아요. 최신 브라우저에서 다시 열어 주세요.`);let a;try{a=await createImageBitmap(e,{imageOrientation:`from-image`,premultiplyAlpha:`none`,...i&&r?.orientation!==null?{resizeWidth:i.width,resizeHeight:i.height,resizeQuality:`high`}:{}})}catch{n.throwIfAborted(),a=await oh(e,n)}try{n.throwIfAborted();let e=rh(a.width,a.height);if(e.width!==a.width||e.height!==a.height){let t=a,r=null;try{r=await createImageBitmap(t,{resizeWidth:e.width,resizeHeight:e.height,resizeQuality:`high`,premultiplyAlpha:`none`})}catch{}r&&(r.width!==e.width||r.height!==e.height)&&(r!==t&&r.close(),r=null),r||=(n.throwIfAborted(),await ah(t,e.width,e.height)),a=r,a!==t&&t.close()}if(n.throwIfAborted(),Math.max(a.width,a.height)>1024)throw Error(`브라우저가 사진 크기를 줄이지 못했어요. 작은 사본을 선택해 주세요.`);return{requestId:t,width:a.width,height:a.height,bitmap:a}}catch(e){throw a.close(),e}}async function ah(e,t,n){let r=document.createElement(`canvas`);r.width=t,r.height=n;try{let i=r.getContext(`2d`);if(!i)throw Error(`사진을 준비할 수 없어요.`);return i.imageSmoothingEnabled=!0,i.imageSmoothingQuality=`high`,i.drawImage(e,0,0,t,n),await createImageBitmap(r,{premultiplyAlpha:`none`})}finally{r.width=r.height=1}}async function oh(e,t){let n=new Image,r=URL.createObjectURL(e);try{await new Promise((e,i)=>{let a=()=>{n.onload=n.onerror=null,t.removeEventListener(`abort`,o)},o=()=>{a(),i(new DOMException(`사진 준비를 취소했어요.`,`AbortError`))};n.onload=()=>{a(),e()},n.onerror=()=>{a(),i(Error(`사진을 읽지 못했어요. HEIC 등 지원되지 않는 형식은 JPEG 또는 PNG 사본으로 선택해 주세요.`))},t.addEventListener(`abort`,o,{once:!0}),t.aborted?o():n.src=r}),t.throwIfAborted();let e=rh(n.naturalWidth||n.width,n.naturalHeight||n.height),i=await ah(n,e.width,e.height);return t.aborted&&(i.close(),t.throwIfAborted()),i}finally{n.onload=n.onerror=null,n.removeAttribute(`src`),URL.revokeObjectURL(r)}}async function sh(e,t,n){let r=await ih(e,t,n),i=document.createElement(`canvas`);i.width=r.width,i.height=r.height;let a=``,o=new Image,s=!1,c=()=>{s||(s=!0,o.onload=o.onerror=null,o.removeAttribute(`src`),a&&URL.revokeObjectURL(a))};try{n.throwIfAborted();let e=i.getContext(`2d`);if(!e)throw Error(`사진을 준비할 수 없어요.`);e.drawImage(r.bitmap,0,0);let t=await new Promise((e,t)=>i.toBlob(n=>n?e(n):t(Error(`작업용 사진을 만들지 못했어요.`)),`image/png`));return n.throwIfAborted(),a=URL.createObjectURL(t),await new Promise((e,t)=>{let r=()=>{o.onload=o.onerror=null,n.removeEventListener(`abort`,i)},i=()=>{r(),t(new DOMException(`사진 준비를 취소했어요.`,`AbortError`))};o.onload=()=>{r(),e()},o.onerror=()=>{r(),t(Error(`작업용 사진을 읽지 못했어요.`))},n.addEventListener(`abort`,i,{once:!0}),n.aborted?i():o.src=a}),n.throwIfAborted(),{image:o,url:a,dispose:c}}catch(e){throw c(),e}finally{r.bitmap.close(),i.width=i.height=1}}var ch=class{onReady;onStatus;token=0;activeUrl=``;pendingPhoto=null;activePhoto=null;pendingUrl=``;pendingVideo=null;activeVideo=null;retryVideo=null;constructor(e,t){this.onReady=e,this.onStatus=t}cancelPending(e=!1){++this.token,this.clearPending(),this.retryVideo=e?this.activeVideo:null}load(e){let t=++this.token;if(this.clearPending(),this.retryVideo=null,e.type.startsWith(`image/`)){let n=new AbortController;this.pendingPhoto=n,sh(e,t,n.signal).then(e=>{if(t!==this.token||n.signal.aborted){e.dispose();return}this.pendingPhoto=null;let r=new nr(e.image);r.colorSpace=Xt,r.needsUpdate=!0;let i=this.replaceActive(``,null);this.activePhoto=e;try{this.onReady(r,e.image.width/e.image.height,null)}catch(t){throw r.dispose(),e.dispose(),this.activePhoto===e&&(this.activePhoto=null),t}finally{i?.dispose()}t===this.token&&this.onStatus(``)}).catch(e=>{t!==this.token||n.signal.aborted||(this.pendingPhoto=null,this.onStatus(e instanceof Error?e.message:`이미지를 읽지 못했습니다.`))});return}let n=URL.createObjectURL(e);this.pendingUrl=n;let r=document.createElement(`video`);this.pendingVideo=r,r.muted=!0,r.loop=!0,r.playsInline=!0,r.preload=`auto`,r.src=n;let i=()=>{r.onloadeddata=null,r.onerror=null,r.pause(),r.removeAttribute(`src`),r.load(),this.pendingVideo===r&&(this.pendingVideo=null),this.pendingUrl===n&&(this.pendingUrl=``),this.disposeUrl(n)};r.onerror=()=>{t===this.token&&this.onStatus(`동영상을 읽지 못했습니다.`),i()},r.onloadeddata=()=>{if(t!==this.token)return i();r.onloadeddata=null,r.onerror=null,this.pendingUrl===n&&(this.pendingUrl=``),this.pendingVideo===r&&(this.pendingVideo=null);let e=new Wl(r);e.colorSpace=Xt;let a=this.replaceActive(n,r);this.retryVideo=r;try{this.onReady(e,r.videoWidth/r.videoHeight,r)}finally{a?.dispose()}t===this.token&&this.activeVideo===r&&this.onStatus(``),r.play().catch(()=>{t===this.token&&r===this.activeVideo&&this.onStatus(`자동 재생이 차단되었습니다. 화면을 눌러 재생하세요.`)})},r.load()}retry(){let e=this.retryVideo,t=this.token;e?.play().then(()=>{t===this.token&&e===this.activeVideo&&this.onStatus(``)}).catch(()=>{t===this.token&&e===this.activeVideo&&this.onStatus(`재생할 수 없습니다.`)})}dispose(){++this.token,this.clearPending(),this.retryVideo=null,this.activeVideo&&=(this.activeVideo.pause(),this.activeVideo.removeAttribute(`src`),this.activeVideo.load(),null),this.disposeUrl(this.activeUrl),this.activeUrl=``,this.activePhoto?.dispose(),this.activePhoto=null}replaceActive(e,t){let n=this.activePhoto;return this.activePhoto=null,this.activeVideo&&this.activeVideo!==t&&(this.activeVideo.pause(),this.activeVideo.removeAttribute(`src`),this.activeVideo.load()),this.activeUrl&&this.activeUrl!==e&&this.disposeUrl(this.activeUrl),this.activeUrl=e,this.activeVideo=t,this.retryVideo=t,n}clearPending(){this.pendingPhoto?.abort(),this.pendingPhoto=null,this.pendingVideo&&=(this.pendingVideo.onloadeddata=null,this.pendingVideo.onerror=null,this.pendingVideo.pause(),this.pendingVideo.removeAttribute(`src`),this.pendingVideo.load(),null),this.pendingUrl&&this.disposeUrl(this.pendingUrl),this.pendingUrl=``}disposeUrl(e){e&&URL.revokeObjectURL(e)}},lh=class{element;setView;onDrag;zoom;pointers=new Map;pinchDistance=0;hasDragged=!1;draggingSubject=!1;suppressSinglePointer=!1;endSubject(e){this.draggingSubject&&(this.draggingSubject=!1,this.zoom?.subjectDrag?.end(e))}constructor(e,t,n,r){this.element=e,this.setView=t,this.onDrag=n,this.zoom=r,e.addEventListener(`pointerdown`,this.down),e.addEventListener(`pointermove`,this.move),e.addEventListener(`pointerup`,this.end),e.addEventListener(`pointercancel`,this.end),e.addEventListener(`lostpointercapture`,this.end),e.addEventListener(`wheel`,this.wheel,{passive:!1})}get isInteracting(){return this.pointers.size>0}syncGesture(){this.zoom?.onGestureChange?.(this.isInteracting,this.pointers.size===2)}isEnabled(){return this.zoom?.isEnabled?.()!==!1||(this.cancelGesture(),!1)}distance(){let[e,t]=this.pointers.values();return e&&t?Math.hypot(t.x-e.x,t.y-e.y):0}midpoint(){let[e,t]=this.pointers.values();return{x:(e.x+t.x)/2,y:(e.y+t.y)/2}}anchor(e){let t=this.zoom?.getBounds?this.zoom.getBounds(e):this.element.getBoundingClientRect();return!t||t.width<=0||t.height<=0||!Number.isFinite(e.x)||!Number.isFinite(e.y)?null:{x:(e.x-t.left)/t.width*2-1,y:1-(e.y-t.top)/t.height*2}}markDragged(){this.hasDragged||(this.hasDragged=!0,this.element.classList.add(`is-dragging`),this.onDrag?.())}zoomBy(e,t,n=t){if(!this.zoom||!Number.isFinite(e)||e<=0)return!1;let r=this.zoom.getZoom();if(!Number.isFinite(r))return!1;let i=Math.max(1,Math.min(3,r*e));return i===r&&t.x===n.x&&t.y===n.y?!1:(this.zoom.setZoom(i,t,n),!0)}down=e=>{if(e.pointerType!==`touch`&&e.button!==0||!this.isEnabled()||this.pointers.has(e.pointerId)||this.pointers.size>=2)return;if(this.zoom?.getBounds){let t=this.zoom.getBounds({x:e.clientX,y:e.clientY});if(!t||e.clientXt.left+t.width||e.clientYt.top+t.height)return}let t=this.pointers.values().next().value;if(!t||this.zoom&&t.type===`touch`&&e.pointerType===`touch`){this.pointers.set(e.pointerId,{x:e.clientX,y:e.clientY,type:e.pointerType});try{this.element.setPointerCapture(e.pointerId)}catch{this.pointers.delete(e.pointerId)}this.pointers.size===1&&this.pointers.has(e.pointerId)?(this.suppressSinglePointer=!1,this.draggingSubject=this.zoom?.subjectDrag?.begin({x:e.clientX,y:e.clientY})??!1):this.pointers.size===2&&this.draggingSubject&&(this.endSubject(!0),this.suppressSinglePointer=!0),this.pinchDistance=this.distance(),this.syncGesture()}};move=e=>{if(!this.isEnabled())return;let t=this.pointers.get(e.pointerId);if(!t)return;let n=this.pointers.size===2?this.midpoint():null,r=e.clientX-t.x,i=e.clientY-t.y;if(t.x=e.clientX,t.y=e.clientY,this.pointers.size===2){let e=this.distance(),t=n&&this.anchor(n),r=this.anchor(this.midpoint());t&&r&&this.pinchDistance>0&&e>0&&this.zoomBy(e/this.pinchDistance,t,r)&&this.markDragged(),this.pinchDistance=e;return}if(this.suppressSinglePointer||r===0&&i===0)return;if(this.draggingSubject){this.markDragged(),this.zoom?.subjectDrag?.move({x:e.clientX,y:e.clientY});return}let a=this.zoom?.getBounds?this.zoom.getBounds({x:e.clientX,y:e.clientY}):this.element.getBoundingClientRect();!a||a.width<=0||a.height<=0||(this.markDragged(),this.setView(r/a.width,-i/a.height))};wheel=e=>{if(!this.isEnabled()||!this.zoom||e.ctrlKey||!Number.isFinite(e.deltaY)||e.deltaY===0)return;let t=this.anchor({x:e.clientX,y:e.clientY});if(!t)return;let n=e.deltaMode===1?16:e.deltaMode===2?this.element.getBoundingClientRect().height:1,r=Math.max(-20,Math.min(20,-e.deltaY*n*.0015));e.preventDefault(),this.zoomBy(Math.exp(r),t)&&this.onDrag?.()};releaseCapture(e){try{this.element.hasPointerCapture(e)&&this.element.releasePointerCapture(e)}catch{}}end=e=>{this.pointers.delete(e.pointerId)&&(this.endSubject(e.type!==`pointerup`),this.pinchDistance=0,this.pointers.size===0&&(this.hasDragged=!1,this.element.classList.remove(`is-dragging`)),this.releaseCapture(e.pointerId),this.syncGesture())};cancelGesture(){this.endSubject(!0),this.suppressSinglePointer=!1;let e=[...this.pointers.keys()];this.pointers.clear(),this.pinchDistance=0,this.hasDragged=!1,this.element.classList.remove(`is-dragging`),e.forEach(e=>this.releaseCapture(e)),e.length&&this.syncGesture()}dispose(){this.element.removeEventListener(`pointerdown`,this.down),this.element.removeEventListener(`pointermove`,this.move),this.element.removeEventListener(`pointerup`,this.end),this.element.removeEventListener(`pointercancel`,this.end),this.element.removeEventListener(`lostpointercapture`,this.end),this.element.removeEventListener(`wheel`,this.wheel),this.cancelGesture()}},uh=class{position=0;motion=null;durationMs=350;get value(){return this.position}get target(){return this.motion?.to??this.position}get isAnimating(){return this.motion!==null}set(e){Number.isFinite(e)&&(this.cancel(),this.position=Math.max(0,Math.min(1,e)))}moveTo(e,t,n=!1){if(!Number.isFinite(e)||!Number.isFinite(t))return;let r=Math.max(0,Math.min(1,e));if(n||r===this.position){this.set(r);return}this.motion?.to!==r&&(this.motion={from:this.position,to:r,startedAt:t})}update(e,t=!0,n=!1){t||this.cancel();let r=this.motion;if(!r||!Number.isFinite(e))return this.position;if(n||e>=r.startedAt+this.durationMs)return this.set(r.to),this.position;let i=Math.max(0,(e-r.startedAt)/this.durationMs),a=i*i*(3-2*i);return this.position=r.from+(r.to-r.from)*a,this.position}cancel(){this.motion=null}},dh={x:0,y:0},fh=class{camera;value=1;offset=new H;constructor(e){this.camera=e}setZoom(e,t=dh,n=t){if(![e,t.x,t.y,n.x,n.y].every(Number.isFinite))return;let r=V.clamp(e,1,3),i=r/this.value,a=r-1;this.offset.set(V.clamp(n.x-i*(t.x-this.offset.x),-a,a),V.clamp(n.y-i*(t.y-this.offset.y),-a,a)),r===1&&this.offset.set(0,0),this.value=r,this.updateProjection()}updateProjection(){this.camera.zoom=this.value,this.camera.updateProjectionMatrix(),this.camera.projectionMatrix.elements[8]-=this.offset.x,this.camera.projectionMatrix.elements[9]-=this.offset.y,this.camera.projectionMatrixInverse.copy(this.camera.projectionMatrix).invert()}},ph=class{camera;maxOffset;target=new H;current=new H;composition=`legacy`;setCompositionMode(e){this.composition=e}room=null;neutralNear;neutralFov;constructor(e,t=.75){this.camera=e,this.maxOffset=t,this.neutralNear=e.near,this.neutralFov=e.fov}setRoomBounds(e,t,n,r=!0){if(![e,t,n].every(Number.isFinite)||e<=0||t<=0)return;this.room=r?{width:e,height:t,glassZ:n}:null;let i=t/2+.24*Math.min(e,t),a=r?Math.min(this.neutralNear,i*.35,Im(e,t,n).halfWidth*.1):this.neutralNear;if(this.camera.near!==a){let e=this.camera.projectionMatrix.elements[8],t=this.camera.projectionMatrix.elements[9];this.camera.near=a,this.camera.updateProjectionMatrix(),this.camera.projectionMatrix.elements[8]=e,this.camera.projectionMatrix.elements[9]=t,this.camera.projectionMatrixInverse.copy(this.camera.projectionMatrix).invert()}}setFov(e){if(this.camera.fov===e)return;let t=this.camera.projectionMatrix.elements[8],n=this.camera.projectionMatrix.elements[9];this.camera.fov=e,this.camera.updateProjectionMatrix(),this.camera.projectionMatrix.elements[8]=t,this.camera.projectionMatrix.elements[9]=n,this.camera.projectionMatrixInverse.copy(this.camera.projectionMatrix).invert()}get isMoving(){return this.target.distanceToSquared(this.current)>1e-12}setMaxOffset(e){Number.isFinite(e)&&(this.maxOffset=V.clamp(e,.35,.9))}add(e,t){Number.isFinite(e)&&Number.isFinite(t)&&this.target.set(V.clamp(this.target.x+e,-1,1),V.clamp(this.target.y+t,-1,1))}setView(e,t){Number.isFinite(e)&&Number.isFinite(t)&&this.target.set(V.clamp(e,-1,1),V.clamp(t,-1,1))}hold(){this.target.copy(this.current)}reset(){this.target.set(0,0),this.current.set(0,0)}update(e,t){this.current.lerp(this.target,1-Math.exp(-8*Math.max(0,e))),this.isMoving||this.current.copy(this.target);let n=this.current.clone().multiplyScalar(t);if(n.x=V.clamp(n.x,-1,1),n.y=V.clamp(n.y,-1,1),!this.room)return this.setFov(this.neutralFov),this.camera.position.set(n.x*this.maxOffset,n.y*this.maxOffset,3),this.camera.lookAt(0,0,0),n;let{width:r,height:i,glassZ:a}=this.room,o=Math.min(r,i),s=this.maxOffset/.75,c=Math.max(Math.abs(n.x),Math.abs(n.y)),l=V.clamp((c-.15)/.85*s,0,1),u=l*l*(3-2*l),d=a+.4471*o+.24,f=-i/2-.24*o,p=Math.max(.75,r/2+.2*o)*s,m=Math.min(this.maxOffset,-f*.5);if(this.camera.position.set(n.x*p,n.y*(n.y<0?m:this.maxOffset),V.lerp(3,d,u)),this.composition===`wall`){let e=V.smoothstep(Math.abs(n.x)*s,.35,1),t=Im(r,i,a),c=Math.sign(n.x),l=Math.max(t.floor+.35*t.unit,n.y*Math.min(this.maxOffset*.4,t.unit*.3)),d=1-V.smoothstep(this.camera.aspect,.7,1),f=new W(c*.65*t.halfWidth,l,a+.6*t.unit),p=new W(-c,0,-Math.tan(V.degToRad(25))),m=f.clone().addScaledVector(p,1.65*t.halfWidth);if(f.z+=2.6*t.unit*d,d>0){let e=new W(-c*(t.halfWidth-.018*t.unit),Math.min(.08*i,t.floor+1.05*t.unit),a+.07*o+.5*t.unit),n=new W(0,0,a).sub(f).normalize(),r=e.sub(f).normalize(),s=f.clone().addScaledVector(n.add(r).normalize(),1.65*t.halfWidth);m.lerp(s,d)}this.camera.position.lerp(f,e),this.camera.position.x=V.clamp(this.camera.position.x,-.78*t.halfWidth,.78*t.halfWidth);let h=new W(0,0,a*u).lerp(m,e);return this.setFov(V.lerp(this.neutralFov,64,d*e)),this.camera.lookAt(h),n}let h=V.smoothstep(Math.abs(n.x)*s,.35,1),g=Im(r,i,a),_=Math.sign(n.x),v=1-V.smoothstep(this.camera.aspect,.7,1.4),y=Math.min(0,g.floor+.8*g.unit),b=new W(_*.75*g.halfWidth,Math.max(g.floor+.4*g.unit,y+n.y*Math.min(this.maxOffset*.4,g.unit*.3)),a+V.lerp(2,3.7,v)*g.unit);this.camera.position.lerp(b,h),this.camera.position.x=V.clamp(this.camera.position.x,-.78*g.halfWidth,.78*g.halfWidth);let x=new W(0,0,a*u).lerp(new W(-_*.68*g.halfWidth,y-V.lerp(.2,-.05,v)*g.unit+n.y*.12*g.unit,a+.1*o),h),S=V.lerp(this.neutralFov,60,v);return this.setFov(V.lerp(this.neutralFov,S,h)),this.camera.lookAt(x),n}},mh=Math.PI/180,hh=e=>Math.max(-1,Math.min(1,e));function gh(e,t,n){let r=e*mh/2,i=t*mh/2,a=n*mh/2,o=Math.cos(r),s=Math.sin(r),c=Math.cos(i),l=Math.sin(i),u=Math.cos(a),d=Math.sin(a);return{x:o*l*u-s*c*d,y:o*c*d+s*l*u,z:s*c*u+o*l*d,w:o*c*u-s*l*d}}function _h(e,t){let n=e.w*t.x-e.x*t.w-e.y*t.z+e.z*t.y,r=e.w*t.y+e.x*t.z-e.y*t.w-e.z*t.x,i=e.w*t.z-e.x*t.y+e.y*t.x-e.z*t.w,a=e.w*t.w+e.x*t.x+e.y*t.y+e.z*t.z,o=Math.hypot(n,r,i),s=o<1e-9?0:2*Math.atan2(o,Math.abs(a))/o*(a<0?-1:1)/(35*mh);return{x:r*s,y:n*s}}var vh=class{setView;status;getView;onIntent;state=`off`;enabled=!1;pending=!1;generation=0;paused=!1;disposed=!1;hasOutput=!1;hasReading=!1;base=null;intentPose=null;baseView={x:0,y:0};timer;angle=0;orientation=window.screen?.orientation;constructor(e,t,n,r=()=>{}){this.setView=e,this.status=t,this.getView=n,this.onIntent=r,document.addEventListener(`visibilitychange`,this.visibility),window.addEventListener(`pagehide`,this.pagehide),window.addEventListener(`orientationchange`,this.reorient),this.orientation?.addEventListener(`change`,this.reorient)}report(e,t){this.state=e,this.status(e,t)}clearTimer(){this.timer!==void 0&&window.clearTimeout(this.timer),this.timer=void 0}waitForReading(){this.clearTimer(),!this.hasReading&&(this.timer=window.setTimeout(()=>this.fail(`기울기 신호를 받지 못했어요. 드래그로 둘러보세요.`),4e3))}readAngle(){let e=window.screen?.orientation?.angle??window.orientation??0;return Number.isFinite(e)?e:0}detach(){window.removeEventListener(`deviceorientation`,this.onOrientation),this.clearTimer()}listen(){this.enabled&&!document.hidden&&(this.angle=this.readAngle(),window.addEventListener(`deviceorientation`,this.onOrientation),this.report(this.hasReading?`active`:`waiting`,this.hasReading?`기울기 켜짐 · 현재 자세에서 이어갈게요.`:`휴대폰을 편하게 들고 잠깐 기다려 주세요.`),this.waitForReading())}stop(){++this.generation,this.pending=!1,this.enabled=!1,this.base=null,this.intentPose=null,this.hasOutput=!1,this.hasReading=!1,this.detach()}fail(e){this.stop(),this.report(`unavailable`,e)}disconnect(){this.disposed||(this.stop(),this.paused=!1,this.baseView={x:0,y:0},this.report(`off`,`기울기는 꺼져 있어요. 드래그로 둘러볼 수 있어요.`))}async toggle(){if(this.disposed)return!1;if(this.enabled||this.pending)return this.stop(),this.report(`off`,`기울기 조작을 껐어요. 드래그로 둘러보세요.`),!1;if(!window.isSecureContext||!window.DeviceOrientationEvent)return this.fail(`이 환경에서는 기울기를 사용할 수 없어요. 드래그로 둘러보세요.`),!1;let e=++this.generation;this.pending=!0;try{let t=window.DeviceOrientationEvent;if(typeof t.requestPermission==`function`){this.report(`permission`,`브라우저에서 동작 및 방향 접근을 선택해 주세요.`);let n=await t.requestPermission();if(e!==this.generation)return!1;if(n!==`granted`)return this.fail(`기울기 접근이 허용되지 않았어요. 드래그로 둘러보세요.`),!1}return e!==this.generation||this.disposed?!1:document.hidden?(this.stop(),this.report(`off`,`화면으로 돌아온 뒤 기울여 보기를 눌러 주세요.`),!1):(this.pending=!1,this.enabled=!0,this.base=null,this.intentPose=null,this.baseView={x:0,y:0},this.hasOutput=!1,this.listen(),!0)}catch{return e===this.generation&&this.fail(`기울기 접근을 시작하지 못했어요. 드래그로 둘러보세요.`),!1}}setPaused(e){this.paused!==e&&(this.paused=e,this.enabled&&(this.rebase(),e?this.report(`paused`,`기울기 켜짐 · 화면 조작을 마치면 이어져요.`):document.hidden||(this.report(this.hasReading?`active`:`waiting`,`현재 자세를 기준으로 이어갈게요.`),this.waitForReading())))}rebase(){this.base=null,this.intentPose=null,this.baseView=this.hasOutput?this.getView():{x:0,y:0}}syncManualView(){this.hasOutput=!0,this.rebase()}reset(){this.base=null,this.intentPose=null,this.baseView={x:0,y:0},this.hasOutput=!1,this.enabled&&!document.hidden&&(this.report(this.hasReading?`active`:`waiting`,`현재 자세를 정면으로 맞출게요.`),this.waitForReading())}reorient=()=>{this.enabled&&(this.angle=this.readAngle(),this.rebase(),document.hidden||this.waitForReading())};visibility=()=>{document.hidden?this.pending?(this.stop(),this.report(`off`,`화면으로 돌아온 뒤 기울여 보기를 눌러 주세요.`)):this.enabled&&(this.detach(),this.rebase(),this.report(`paused`,`기울기 켜짐 · 화면으로 돌아오면 이어져요.`)):this.enabled&&(this.rebase(),this.listen())};pagehide=()=>{this.stop(),this.report(`off`,`다시 기울여 보기를 눌러 시작할 수 있어요.`)};onOrientation=e=>{if(!this.enabled||document.hidden)return;let{alpha:t,beta:n,gamma:r}=e;if(t===null||n===null||r===null||![t,n,r].every(Number.isFinite))return;this.clearTimer(),this.hasReading=!0;let i=this.readAngle();i!==this.angle&&(this.angle=i,this.rebase());let a=gh(t,n,r);if(this.paused){this.base=null,this.intentPose=null,this.state!==`paused`&&this.report(`paused`,`기울기 켜짐 · 설정을 닫고 휴대폰을 살짝 기울여 보세요.`);return}this.base||=a,this.intentPose||=a;let o=_h(this.intentPose,a);Math.hypot(o.x,o.y)>.12&&(this.intentPose=a,this.onIntent());let s=_h(this.base,a),c=this.angle*mh;this.setView(hh(this.baseView.x+s.x*Math.cos(c)+s.y*Math.sin(c)),hh(this.baseView.y+s.y*Math.cos(c)-s.x*Math.sin(c))),this.hasOutput=!0,this.state!==`active`&&this.report(`active`,`기울기 켜짐 · 현재 자세가 기준이에요.`)};dispose(){this.stop(),this.disposed=!0,document.removeEventListener(`visibilitychange`,this.visibility),window.removeEventListener(`pagehide`,this.pagehide),window.removeEventListener(`orientationchange`,this.reorient),this.orientation?.removeEventListener(`change`,this.reorient)}},yh={lowerQuantile:.5,upperQuantile:.85,fallbackLowerQuantile:.05,fallbackUpperQuantile:.95,minimumSpan:12/255},bh={blend:.65,maxCellCorrection:.35},xh={inputSize:770,modelId:`onnx-community/depth-anything-v2-small-ONNX`,modelName:`Small`},Sh={nearThreshold:.99},Ch=class{static evidenceRange(e){let t=e.image?.data;if(!t||t.length<4)return[1,1];let n=new Uint32Array(256);for(let e=0;e{let t=0;for(let i=0;i=r*e)return i/255;return 1},a=i(yh.lowerQuantile),o=i(yh.upperQuantile);return o-a{this.pending={id:t,started:performance.now(),image:e,fallbackAttempted:!1,preparationMs:0,inferenceMs:0,resolve:n,reject:r},this.captureAndSend(e,t).catch(e=>{this.fail(t,e instanceof Error?e:Error(`AI depth 생성에 실패했습니다.`))})})}cancel(){let e=this.pending;this.pending=null,this.requestId+=1,this.worker?.terminate(),this.worker=null,e?.reject(new DOMException(`AI depth 요청이 취소되었습니다.`,`AbortError`))}async captureAndSend(e,t,n=!1){let r=e.naturalWidth||e.width,i=e.naturalHeight||e.height;if(!r||!i)throw Error(`사진 크기를 확인할 수 없습니다.`);let a=Math.min(1,1024/Math.max(r,i)),o=await createImageBitmap(e,{resizeWidth:Math.max(1,Math.round(r*a)),resizeHeight:Math.max(1,Math.round(i*a)),resizeQuality:`high`});if(this.pending?.id!==t){o.close();return}try{this.ensureWorker().postMessage({type:`infer`,id:t,image:o,...n?{forceWasm:!0}:{}},[o])}catch(e){throw o.close(),e}}ensureWorker(){if(this.worker)return this.worker;let e=new Worker(new URL(`/assets/aiDepth.worker-BZp93h00.js`,``+import.meta.url),{type:`module`});return e.onmessage=t=>{if(this.worker!==e)return;let n=t.data;if(this.pending?.id===n.id){if(n.type===`status`)this.onStatus(n.message);else if(n.type===`result`){let t=this.pending;this.pending=null,this.resetWorker(e);try{let e=Ch.fromNormalizedDepth(new Uint8Array(n.values),n.width,n.height);e.userData.normalizedDepth=new Float32Array(n.normalizedValues),e.userData.aiDepthRun={...n.run,preparationMs:t.preparationMs+n.run.preparationMs,inferenceMs:t.inferenceMs+n.run.inferenceMs,totalMs:performance.now()-t.started},t.resolve(e)}catch(e){t.reject(e instanceof Error?e:Error(`AI depth 결과를 읽지 못했습니다.`))}}else if(n.type===`fallback`){let t=this.pending;if(this.resetWorker(e),t.fallbackAttempted){this.fail(n.id,Error(`이 기기에서 AI 깊이를 계산하지 못했습니다. 다시 시도하거나 평면 사진으로 볼 수 있어요.`));return}t.fallbackAttempted=!0,t.preparationMs+=n.preparationMs,t.inferenceMs+=n.inferenceMs,this.onStatus(`다른 길을 찾고 있어요. 조금만 더 기다려 주세요…`),this.captureAndSend(t.image,t.id,!0).catch(e=>{this.fail(t.id,e instanceof Error?e:Error(`AI depth 생성에 실패했습니다.`))})}else this.resetWorker(e),this.fail(n.id,Error(n.message))}},e.onerror=t=>{this.worker===e&&(this.resetWorker(e),this.fail(this.pending?.id??-1,Error(t.message||`AI depth worker 오류가 발생했습니다.`)))},e.onmessageerror=()=>{this.worker===e&&(this.resetWorker(e),this.fail(this.pending?.id??-1,Error(`AI depth worker 결과를 읽지 못했습니다.`)))},this.worker=e,e}fail(e,t){if(this.pending?.id!==e)return;let n=this.pending;this.pending=null,n.reject(t)}resetWorker(e){e.terminate(),this.worker===e&&(this.worker=null)}},Th=`uniform sampler2D uDepthMap; +uniform float uDepthScale; +uniform float uDepthBias; +varying vec2 vUv; + +void main() { + vUv = uv; + float depth = texture2D(uDepthMap, uv).r; + vec3 displacedPosition = position; + displacedPosition.z += (depth - uDepthBias) * uDepthScale; + gl_Position = projectionMatrix * modelViewMatrix * vec4(displacedPosition, 1.0); +} +`,Eh=`uniform sampler2D uTexture; +uniform bool uIsVideo; +uniform bool uUsePhotoAlpha; +varying vec2 vUv; + +vec3 srgbToLinear(vec3 value) { + return mix(value / 12.92, pow((value + 0.055) / 1.055, vec3(2.4)), step(vec3(0.04045), value)); +} + +void main() { + vec4 color = texture2D(uTexture, vUv); + if (uIsVideo) color.rgb = srgbToLinear(color.rgb); + if(uUsePhotoAlpha) { if(color.a < .003) discard; } + else color.a = 1.0; + gl_FragColor = color; + #include +} +`,Dh=class extends q{constructor(e,t,n=.25,r=0){let i=new za(1,1,128,128),a=new ya({uniforms:{uTexture:{value:e},uDepthMap:{value:t},uDepthScale:{value:V.clamp(n,0,.4)},uDepthBias:{value:r},uIsVideo:{value:!1},uUsePhotoAlpha:{value:!1}},vertexShader:Th,fragmentShader:Eh,alphaToCoverage:!0});super(i,a)}setTexture(e){this.material.uniforms.uTexture.value=e}setDepthMap(e){this.material.uniforms.uDepthMap.value=e}setDepthScale(e){this.material.uniforms.uDepthScale.value=V.clamp(e,0,.4)}setVideo(e){this.material.uniforms.uIsVideo.value=e}get depthMap(){return this.material.uniforms.uDepthMap.value}},Oh=[{name:`nose`,x:235,y:310},{name:`left-eye`,x:198,y:278},{name:`right-eye`,x:249,y:273},{name:`face`,x:221,y:267},{name:`left-ear`,x:158,y:213},{name:`right-ear`,x:262,y:206},{name:`body`,x:139,y:419}],kh=class{values=null;width=0;height=0;sampleKind=``;setSample(e){let t=e.naturalWidth||e.width,n=e.naturalHeight||e.height,r=document.createElement(`canvas`);r.width=t,r.height=n;let i=r.getContext(`2d`);if(!i||t<1||n<1){this.clear();return}i.drawImage(e,0,0,t,n),this.values=i.getImageData(0,0,t,n).data,this.width=t,this.height=n,this.sampleKind=`sample`}clear(){this.values=null,this.width=0,this.height=0,this.sampleKind=``}update(e,t,n,r,i,a,o){if(!this.values||!e||!t||this.sampleKind===``)return``;e.updateMatrixWorld(),t.updateMatrixWorld(!0);let s=a+(o-r)*n,c=Math.max(0,.6-s),l=[`cameraX=${e.position.x.toFixed(3)} sample=${this.sampleKind}`,`contentBaseZ=${a.toFixed(3)} maxFrontZ=${s.toFixed(3)} glassGap=${c.toFixed(3)}`],u=new W,d=new W,f=new W;for(let a of Oh){let o=this.sampleBilinear(a.x,a.y),s=(a.x+.5)/this.width,c=1-(a.y+.5)/this.height;u.set(s-.5,c-.5,(o-r)*n),d.copy(u),t.localToWorld(d),f.copy(d).project(e);let p=(f.x*.5+.5)*i;l.push(`${a.name}: depth=${o.toFixed(3)} worldZ=${d.z.toFixed(3)} projectedX=${p.toFixed(3)}px`)}return l.join(` +`)}sampleBilinear(e,t){if(!this.values||this.width<1||this.height<1)return 0;let n=V.clamp(e,0,this.width-1),r=V.clamp(t,0,this.height-1),i=Math.floor(n),a=Math.floor(r),o=Math.min(i+1,this.width-1),s=Math.min(a+1,this.height-1),c=n-i,l=r-a,u=this.gray(i,a),d=this.gray(o,a),f=this.gray(i,s),p=this.gray(o,s);return V.lerp(V.lerp(u,d,c),V.lerp(f,p,c),l)}gray(e,t){return this.values[(t*this.width+e)*4]/255}},Ah=class{canvas=document.querySelector(`#depth-inspection-canvas`);summary=document.querySelector(`#depth-inspection-summary`);point=document.querySelector(`#depth-inspection-point`);xInput=document.querySelector(`#depth-inspection-x`);yInput=document.querySelector(`#depth-inspection-y`);image=null;data=null;normalized=null;overlay=document.createElement(`canvas`);max=0;gap=0;scale=0;constructor(e){this.canvas.addEventListener(`click`,e=>{let t=this.canvas.getBoundingClientRect();this.xInput.value=String(Math.min(this.canvas.width-1,Math.floor((e.clientX-t.left)/t.width*this.canvas.width))),this.yInput.value=String(Math.min(this.canvas.height-1,Math.floor((e.clientY-t.top)/t.height*this.canvas.height))),this.updatePoint()},{signal:e}),[this.xInput,this.yInput].forEach(t=>t.addEventListener(`input`,()=>this.updatePoint(),{signal:e}))}setDepth(e,t){let{data:n,width:r,height:i}=t.image;if(this.image=e instanceof HTMLImageElement?e:null,this.data=n&&r*i>1?n:null,this.normalized=t.userData.normalizedDepth??null,this.canvas.hidden=!this.image||!this.data,this.point.textContent=``,this.canvas.hidden||!this.data){this.summary.textContent=`사진과 깊이를 불러오세요.`;return}this.canvas.width=this.overlay.width=r,this.canvas.height=this.overlay.height=i,this.xInput.max=String(r-1),this.yInput.max=String(i-1);let a=this.overlay.getContext(`2d`),o=a.createImageData(r,i),s=0,c=0,l=0,u=0;this.max=0;for(let e=0;ethis.max&&(this.max=Number(this.data[e*4])/255,u=e);let d=-1/0;for(let e=0;ed&&(d=n,u=e),n===1&&(s+=1),t===1&&(c+=1),n>=Sh.nearThreshold&&(l+=1);let r=n===1?[255,55,180]:t===1?[0,240,255]:n>=Sh.nearThreshold?[255,210,40]:null;r&&o.data.set([...r,210],e*4)}a.putImageData(o,0,0);let f=e=>(100*e/(r*i)).toFixed(4);this.summary.textContent=`${r}×${i} · 최대 depth=${this.max.toFixed(5)}\n${this.normalized?`모델`:`입력`} 최대 1: ${s}px (${f(s)}%)\n8비트 depth=1: ${c}px (${f(c)}%)\ndepth≥${Sh.nearThreshold}: ${l}px (${f(l)}%)\n최대 위치: (${u%r}, ${Math.floor(u/r)})`,this.xInput.value=String(u%r),this.yInput.value=String(Math.floor(u/r)),this.updatePoint()}updateDistance(e,t){this.gap=e,this.scale=t,this.updatePoint()}updatePoint(){if(!this.data||!this.image)return;let e=Math.max(0,Math.min(this.canvas.width-1,Math.round(Number(this.xInput.value)))),t=Math.max(0,Math.min(this.canvas.height-1,Math.round(Number(this.yInput.value)))),n=t*this.canvas.width+e,r=Number(this.data[n*4])/255,i=this.gap+(this.max-r)*this.scale;this.point.textContent=`픽셀 (${e}, ${t})\n${this.normalized?`모델 상대 깊이: ${this.normalized[n].toFixed(6)}\n`:``}8비트 깊이: ${r.toFixed(6)}\n최대 표면 간격: ${this.gap.toFixed(4)}\n선택 지점 간격: ${i.toFixed(4)}\n뒤로 물러난 양: ${((this.max-r)*this.scale).toFixed(4)}`;let a=this.canvas.getContext(`2d`);a.drawImage(this.image,0,0,this.canvas.width,this.canvas.height),a.drawImage(this.overlay,0,0),a.strokeStyle=`#ffffff`,a.lineWidth=Math.max(1,this.canvas.width/250),a.beginPath(),a.arc(e+.5,t+.5,Math.max(3,this.canvas.width/50),0,Math.PI*2),a.stroke()}},jh=class{meshes;geometries;constructor(e){this.geometries=Array.from({length:4},(e,t)=>{let n=new Zi;return n.setAttribute(`position`,new Bi(new Float32Array(12),3)),n.setIndex([0,1,2,0,2,3]),n.setAttribute(`uv`,new Ui(t<2?[0,0,0,1,1,1,1,0]:[0,0,1,0,1,1,0,1],2)),n.computeVertexNormals(),n}),this.meshes=this.geometries.map(t=>new q(t,e))}update(e,t,n,r,i,a){let o=e*.5,s=t*.5,c=n*.5,l=r*.5,u=Math.min(e,t)*.002,d=i+u,f=Math.max(0,c-u),p=Math.max(0,l-u),m=[[[-o-u,-s-u,d],[-o-u,s+u,d],[-f,p,a],[-f,-p,a]],[[o+u,s+u,d],[o+u,-s-u,d],[f,-p,a],[f,p,a]],[[-o-u,s+u,d],[o+u,s+u,d],[f,p,a],[-f,p,a]],[[o+u,-s-u,d],[-o-u,-s-u,d],[-f,-p,a],[f,-p,a]]];for(let e=0;ee.dispose())}},Mh=class{group=new Lc;pocket=new Na(new W(1,0,0),1);material=new ud({color:10320214,roughness:.86,clippingPlanes:[this.pocket]});geometry=new da(1,1,1);vertical=new q(this.geometry,this.material);horizontal=new q(this.geometry,this.material);width=1;open=0;constructor(){this.group.name=`experimental-structural-door-grid`,this.group.add(this.vertical,this.horizontal),this.group.visible=!1}resize(e,t,n){this.width=e;let r=Math.min(e,t),i=.065*r;this.vertical.scale.set(i,t,.11*r),this.vertical.position.set(0,0,n+.038*r),this.horizontal.scale.set(e,i,.11*r),this.horizontal.position.set(0,.015*t,n+.038*r),this.pocket.constant=e/2+.05*r,this.setOpen(this.open)}setOpen(e){this.open=V.clamp(e,0,1),this.group.position.x=this.open===0?0:-this.width*this.open}dispose(){this.group.removeFromParent(),this.geometry.dispose(),this.material.dispose()}},Nh=.74;function Ph(e,t){let n=Om(e,Nh)*.82,r=Om(e,t)*.82,i=n*Nh*.8,a=n*.8,o=[r*t*.8,r*.8,.6];return{width:i,height:a,cameraBounds:o,clearanceScale:Math.min(i,a,...o.slice(0,2))}}function Fh(e,t,n,r,i,a,o){let s=e.height,c=e.width,l=Math.min(.48*s,.43*c/(Math.max(.01,n.width)*t/Math.max(.01,n.height)))*i,u=l/Math.max(.01,n.height),d=u*t,f=.24*c+a*.35*c,p=-.56*s+l+o*.35*s;return{x:f-(n.x+n.width/2-.5)*d,y:p-(.5-n.y)*u,z:r,width:d,height:u}}var Ih=`modulepreload`,Lh=function(e){return`/`+e},Rh={},zh=function(e){return e.pathname.endsWith(`.css`)},Bh=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e,i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}function s(e){return import.meta.resolve?new URL(import.meta.resolve(e)):new URL(e,import.meta.url)}r=o(t.map(t=>{t=Lh(t,n);let r=s(t);if(r.href in Rh)return;Rh[r.href]=!0;let i=zh(r);if(e===void 0){e={all:new Set,styles:new Set};let t=document.getElementsByTagName(`link`);for(let n=t.length-1;n>=0;n--){let r=t[n];e.all.add(r.href),r.rel===`stylesheet`&&e.styles.add(r.href)}}if((i?e.styles:e.all).has(r.href))return;let o=document.createElement(`link`);if(o.rel=i?`stylesheet`:Ih,i||(o.as=`script`),o.crossOrigin=``,o.href=r.href,a&&o.setAttribute(`nonce`,a),document.head.appendChild(o),i)return new Promise((e,t)=>{o.addEventListener(`load`,e),o.addEventListener(`error`,()=>t(Error(`Unable to preload CSS for ${r}`)))})}).filter(e=>e!==void 0))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})};function Vh(e,t,n){let r=e.querySelector(`#internal-controls`),i=e.querySelector(`#settings-dialog`),a=new AbortController,o={signal:a.signal},s=(t,n,r=``)=>{let i=e.createElement(t);return i.id=n,i.textContent=r,i},c=(e,t)=>{let n=s(`button`,e,t);return n.type=`button`,n},l=s(`section`,`peeking-experiment`);l.className=`peeking-experiment`,l.setAttribute(`aria-labelledby`,`peeking-title`);let u=s(`h3`,`peeking-title`,`마당에서 빼꼼`),d=s(`p`,`peeking-limitations`,`가벼운 누끼 실험이라 털이 잘리거나 배경이 남을 수 있어요. 사진 속 자세를 새로 만들지 않으며, 옆에서 보면 납작해 보일 수 있어요.`),f=s(`p`,`peeking-route-note`,`할머니집 + B에서 보여요. A·포토부스·비교에서는 잠시 원본 사진을 보여줘요.`),p=c(`peeking-choose`,`마당에서 빼꼼 · 실험`);p.setAttribute(`aria-describedby`,`peeking-limitations peeking-route-note`);let m=s(`input`,`peeking-photo`);m.type=`file`,m.accept=`image/*`,m.hidden=!0,m.setAttribute(`aria-label`,`마당 실험에 사용할 사진 선택`);let h=c(`peeking-toggle`,`원본 사진으로 돌아가기`);l.append(u,d,f,p,m,h),r.append(l);let g=s(`dialog`,`peeking-preview-dialog`);g.className=`peeking-preview-dialog`,g.setAttribute(`aria-labelledby`,`peeking-preview-title`),g.setAttribute(`aria-describedby`,`peeking-preview-note`);let _=s(`h2`,`peeking-preview-title`,`누끼를 먼저 확인해 주세요`),v=s(`p`,`peeking-preview-note`,`털·귀·발과 남은 배경을 확인해 주세요. 괜찮을 때만 마당에 배치해요.`),y=s(`p`,`peeking-progress`);y.setAttribute(`role`,`status`),y.setAttribute(`aria-live`,`polite`),y.setAttribute(`aria-atomic`,`true`);let b=s(`p`,`peeking-error`);b.setAttribute(`role`,`alert`);let x=s(`div`,`peeking-comparison`);x.className=`peeking-comparison`;let S=s(`img`,`peeking-original`);S.alt=`배경을 포함한 원본 사진`;let C=s(`img`,`peeking-cutout`);C.alt=`배경 제거 결과, 체크무늬는 투명한 부분`;for(let[e,t,n]of[[S,`원본 사진`,`original`],[C,`누끼 · 체크무늬는 투명`,`cutout`]]){let r=s(`figure`,`peeking-figure-${n}`),i=s(`div`,`peeking-surface-${n}`);i.className=`peeking-preview-surface`,i.append(e),r.append(i,s(`figcaption`,`peeking-caption-${n}`,t)),x.append(r)}let w=s(`p`,`peeking-warning`),T=s(`div`,`peeking-actions`);T.className=`peeking-actions`;let E=c(`peeking-accept`,`이 누끼로 배치`),D=c(`peeking-retry`,`다시 시도하기`),O=c(`peeking-another`,`다른 사진 선택`),k=c(`peeking-cancel`,`취소`);T.append(E,D,O,k),g.append(_,v,y,b,x,w,T),e.body.append(g);let A={available:!1,enabled:!1,busy:!1},j=null,M=null,N=!1,P=()=>{p.disabled=A.busy||N,h.hidden=!A.available,h.disabled=!A.available||A.busy||N,h.textContent=A.enabled?`원본 사진으로 돌아가기`:`마당 실험 다시 보기`,h.setAttribute(`aria-pressed`,String(A.enabled)),E.disabled=!j?.result||A.busy||N},F=()=>{S.removeAttribute(`src`),C.removeAttribute(`src`),x.hidden=!0,w.hidden=!0,w.textContent=``,b.hidden=!0,b.textContent=``,D.hidden=!0,g.setAttribute(`aria-busy`,`false`),P()},I=()=>{g.open&&g.close(),!N&&i.open&&p.isConnected&&!p.disabled&&p.focus({preventScroll:!0})},ee=()=>{let e=j;j=null,M=null,e?.controller.abort(),e?.result?.dispose(),e?.preparation?.dispose(),F(),y.textContent=``,I()},te=async e=>{if(N||A.busy||!i.open)return;ee(),M=e;let t={controller:new AbortController,preparation:null,result:null};j=t;let n=()=>!N&&j===t&&!t.controller.signal.aborted&&i.open;y.textContent=`누끼 미리보기를 준비하는 중…`,g.setAttribute(`aria-busy`,`true`),g.showModal(),k.focus({preventScroll:!0}),P();try{let{CutoutPreparation:r}=await Bh(async()=>{let{CutoutPreparation:e}=await import(`./CutoutPreparation-9rCu4swh.js`);return{CutoutPreparation:e}},[]);if(!n())return;t.preparation=new r;let i=await t.preparation.prepare(e,e=>{n()&&(y.textContent=e)},t.controller.signal);if(!n()){i.dispose(),t.preparation.dispose();return}t.result=i,S.src=i.originalUrl,C.src=i.cutoutUrl,x.hidden=!1;let a=[];i.warnings.includes(`multiple-foreground`)&&a.push(`여러 대상이 남아 있을 수 있어요.`),i.warnings.includes(`tiny-foreground`)&&a.push(`남은 대상이 아주 작아요. 다른 사진이 더 나을 수 있어요.`),w.textContent=a.join(` `),w.hidden=a.length===0,y.textContent=`결과를 확인한 뒤 직접 배치해 주세요.`,g.setAttribute(`aria-busy`,`false`),P()}catch(e){if(!n())return;t.preparation?.dispose(),t.preparation=null,b.textContent=e instanceof Error?e.message:`누끼를 준비하지 못했어요. 다시 시도하거나 다른 사진을 골라 주세요.`,b.hidden=!1,D.hidden=!1,y.textContent=`사진은 아직 바뀌지 않았어요.`,g.setAttribute(`aria-busy`,`false`),P()}},ne=()=>{N||A.busy||!i.open||(ee(),m.value=``,m.click())};p.addEventListener(`click`,ne,o),O.addEventListener(`click`,ne,o),m.addEventListener(`change`,()=>{let e=m.files?.[0];m.value=``,e&&te(e)},o),D.addEventListener(`click`,()=>{M&&te(M)},o),k.addEventListener(`click`,ee,o),g.addEventListener(`cancel`,e=>{e.preventDefault(),e.stopPropagation(),ee()},o),g.addEventListener(`close`,()=>{!g.open&&j&&ee()},o),i.addEventListener(`close`,()=>{i.open||ee()},o),E.addEventListener(`click`,()=>{if(N||A.busy||!j?.result||!j.preparation)return;let{result:e,preparation:t}=j;j=null,M=null;let r=!1,i={...e,dispose(){r||(r=!0,e.dispose(),t.dispose())}};F(),I(),n.onAccept(i)},o),h.addEventListener(`click`,()=>{!N&&A.available&&!A.busy&&n.onToggle(!A.enabled)},o);let re=()=>{N||(N=!0,ee(),a.abort(),t.removeEventListener(`abort`,re),l.remove(),g.remove())};return t.addEventListener(`abort`,re,{once:!0}),F(),t.aborted&&re(),{cancel:ee,dispose:re,setState(e){N||(A={...e},P())}}}var Hh=document.querySelector(`#canvas-wrap`),Uh=document.querySelector(`#status`),Wh=document.querySelector(`#depth-provenance`),Gh=document.querySelector(`#ai-depth`),Kh=document.querySelector(`#empty`),qh=document.querySelector(`#hint`);qh.dataset.phase=`hidden`;var X=new Jc({antialias:!0}),Jh=new Xf;X.localClippingEnabled=!0,X.setPixelRatio(Math.min(devicePixelRatio,1.5)),Hh.append(X.domElement);var Yh=new Yc,Xh=new Yc;Yh.background=new K(16249061);var Zh=new wa(40,1,.1,100);Zh.position.z=3;var Qh=new za(1,1),$h=document.createElement(`canvas`);$h.width=$h.height=512;var eg=$h.getContext(`2d`);function tg(e){let t=Sp[e],n=eg.createLinearGradient(0,0,512,512);t.room.forEach((e,t)=>n.addColorStop(t/2,e)),eg.fillStyle=n,eg.fillRect(0,0,512,512),eg.fillStyle=t.light,eg.fillRect(75,50,115,340),eg.fillStyle=t.mullion,eg.fillRect(320,0,28,512)}tg(`wood`);var ng=new Gl($h);ng.colorSpace=Xt;var rg=new Mi({map:ng}),ig=new q(Qh,rg);Yh.add(ig);var ag=Ch.flatTexture(),og=new Dh(ng,ag,.25,0),sg=og.material,cg=sg.uniforms;Yh.add(og);var Z={uSceneZoom:{value:1},uSceneOffset:{value:new H},uSceneTexture:{value:ng},uSceneDepth:{value:ng},uProtectionDepthMap:cg.uDepthMap,uPetWorldToLocal:{value:new G},uContentViewProjection:{value:new G},uContentInverseViewProjection:{value:new G},uContentCameraPosition:{value:new W},uLightPosition:{value:new W(.6,.8,2.6)},uBackgroundColor:{value:Yh.background.clone()},uGlassZ:{value:.6},uSourceZ:{value:.56},uGridSize:{value:tp.grid},uMosaicStyle:{value:2},uStrength:{value:1},uGlossStrength:{value:.3},uCurvature:{value:1},uRegionStrength:{value:0},uRegionAvailable:{value:0},uRegionAtlasSize:{value:new H(104,104)},uRegionGridSize:{value:new H(13,13)},uRegionPaletteSize:{value:new H(65,13)},uRegionPalette:{value:ng},uRegionAtlas:{value:ng},uViewOffset:{value:new H},uPaneRect:{value:new rr(0,0,1,1)},uResolution:{value:new H},uTime:{value:0},uPetSize:{value:new H(1,1)},uPaneSize:{value:new H(1,1)}},lg={value:ng},ug={value:new H(1,1)};Object.assign(Z,{uRegionHistory:lg,uDepthEvidenceRange:ug,uEnvironmentStrength:{value:$f},uGobangSurface:{value:new rr(tp.heightPerCell,tp.flatHalfWidth,tp.refractiveIndex,tp.thickness)},uGobangBevelRound:{value:tp.bevelRound},uGobangEnvironmentStrength:{value:tp.environmentStrength},uDepthCorrection:{value:new H(bh.blend,bh.maxCellCorrection)}});var dg=new da(1,1,1),fg=[new Mi({color:11837637}),new Mi({color:12824531}),new Mi({color:10323632}),new Mi({color:14272486}),new Mi({color:11178429}),new Mi({color:12626386})],pg=new q(dg,fg),mg=new q(dg,fg),hg=new q(dg,fg),gg=new q(dg,fg);Xh.add(pg,mg,hg,gg);var _g=new Mi({color:fg[1].color,side:2}),vg=new jh(_g);Xh.add(...vg.meshes);var yg=new Zm(Xh,[pg,mg,hg,gg],vg,fg,_g),bg=document.querySelector(`#frame-notice`),xg=document.querySelector(`#frame-retry`),Sg=document.querySelector(`#house-retry`),Cg=!1,wg=!1;function Tg(){bg.hidden=!Cg&&!wg,xg.hidden=!Cg,Sg.hidden=!wg,bg.textContent=[Cg?`나무 창틀을 불러오지 못해 임시 창틀을 보여드려요.`:``,wg?`집 주변 공간을 불러오지 못해 창문만 보여드려요.`:``,Cg||wg?`설정에서 다시 불러올 수 있어요.`:``].filter(Boolean).join(` `)}var Eg=new Fm(Xh,(e,t)=>{yg.setAssetActive(e),Cg=t===`error`,Tg(),Jh.invalidate()}),Dg=new Jm(Xh,e=>{wg=e===`error`,Tg(),Jh.invalidate()}),Og=Ym(og);Xh.add(Og.mesh);var kg=new pp,Ag=new Mh;Xh.add(Ag.group);var jg=null,Mg=null,Ng=null,Pg=!1,Fg=null,Ig=null,Lg=null;function Rg(){return!!(jg&&Ng&&Pg&&Eg.isWood&&p_===`b`&&!v_)}function zg(){return Rg()?Ng:Vg}function Bg(){Fg?.cancel(),Mg?.dispose(),Mg=null,Ng?.dispose(),Ng=null,jg?.dispose(),jg=null,Pg=!1,Fg?.setState({available:!1,enabled:!1,busy:a_||s_||c_})}var Vg=ng,Hg=!1,Ug=1,Wg=1,Gg=1,Kg=1,qg=0,Jg=0,Yg=V.lerp(ep.minGap,ep.maxGap,ep.defaultPercent/100),Xg=!1,Zg=!1,Qg=`noglass`,$g=new Kf,e_=null,t_=null,n_=!1,r_=0,i_=0,a_=!1,o_=!1,s_=!1,c_=!1,l_=!1,u_=null,d_=null,f_=new vp(X,og),p_=`b`,m_=`b`,h_=0,g_=!1,__=null,v_=!1,y_=0,b_=1,x_=null,S_=null,C_=0,w_=new Yf,T_=document.querySelector(`#comparison-toggle`),E_=document.querySelector(`#comparison-exit`),D_=document.querySelector(`#comparison-overlay`),O_=document.querySelector(`#comparison-state`),k_=document.querySelector(`#comparison-timing`),A_=document.querySelector(`#comparison-memory`),Q=new AbortController;xg.addEventListener(`click`,()=>{Eg.load()},{signal:Q.signal}),Sg.addEventListener(`click`,()=>{Dg.load()},{signal:Q.signal});var j_=!1,M_=new uh,N_=document.defaultView?.matchMedia?.(`(prefers-reduced-motion: reduce)`),P_=Af(()=>document.defaultView?.localStorage),F_=zf({visitorId:Pf({getStorage:()=>document.defaultView?.localStorage,randomUUID:()=>globalThis.crypto.randomUUID()}),makeDogId:(e,t)=>Ff(e,t,(e,t)=>globalThis.crypto.subtle.digest(e,t)),transport:Rf(),onCount:e=>Vf([...document.querySelectorAll(`[data-arrival-count]`)],e)}),I_=null,L_=null,R_=null;function z_(){F_?.invalidate(),R_=null}function B_(e){return!F_||!I_||e!==L_||c_||g_||l_?null:(R_===null&&(R_=F_.begin(I_.origin,I_.name)),R_)}Tf(document,Q.signal);var $=Cp(document,Q.signal,e=>{Yh.background.set(Sp[e].background),Z.uBackgroundColor.value.copy(Yh.background),M_.cancel(),yg.apply(e),Eg.apply(e),Dg.apply(e),tg(e),ng.needsUpdate=!0,u_?.invalidate(),j_&&ev()},()=>{nv(),Lg?.start()},e=>{nb(e)},P_,iv,e=>{Bv(),mv.hold(),kv.setPaused(e||$.isBlocked()),rv(),Jh.invalidate()});function V_(e,t=e){Uh.textContent=e,$.setDetail(t)}function H_(){return $.canAdjustPhoto()&&!l_&&!c_&&!g_&&!a_&&!s_&&!o_&&!Hg&&Vg!==ng&&p_===`b`&&Qg===`final`&&!v_&&!Rg()}function U_(){return $.canExportPhoto()&&!l_&&!c_&&!g_&&!a_&&!s_&&!o_&&!Hg&&Vg!==ng&&p_===`b`&&Qg===`final`&&!v_&&!Rg()}async function W_(e,t){if(!U_())throw Error(`사진 준비가 끝난 뒤 일반 화면에서 저장해 주세요.`);let n=r_,r=await Sf(X,document,e,t,t=>{f_.sync({width:Z.uPaneSize.value.x,height:Z.uPaneSize.value.y,grid:Z.uGridSize.value,curvature:Z.uCurvature.value},Z.uGlassZ.value,Z.uLightPosition.value,Yh.background),f_.syncReveal(vg.meshes,Xh),f_.syncCourtyard(null),f_.renderForExport(Zh,Xh,t,e===`photo`)});if(n!==r_||t.aborted||!U_())throw new DOMException(`Cancelled`,`AbortError`);return r}Ig=Cf(document,Q.signal,U_,W_,()=>$.refreshBlocking());var G_=new Ah(Q.signal);function K_(){Fg?.setState({available:!!jg,enabled:Pg,busy:a_||o_||s_||c_||l_}),ry.disabled=c_||Vg===ng||Hg||a_||o_||l_,Gh.disabled=c_||Vg===ng||Hg||a_||o_||s_||l_,Gh.textContent=s_?`사진 분석 중…`:`AI 입체감 만들기`}var q_=new wh(e=>{!l_&&s_&&V_(e)});function J_(){z_(),i_+=1,q_.cancel(),s_=!1,o_=!1,K_()}function Y_(){e_&&e_.dispose(),e_=null}var X_=0;function Z_(){return Z.uGlassZ.value-Yg-(X_-cg.uDepthBias.value)*cg.uDepthScale.value}function Q_(){Y_(),t_=null,Xg=!1,n_=!1}function $_(){Jh.invalidate(),cg.uUsePhotoAlpha.value=Rg(),cg.uTexture.value=zg(),Ag.group.visible=Rg(),kg.setEnabled(Rg()),Yh.background.copy(Rg()?kg.uniforms.uYardSkyColor.value:new K(Sp[Eg.isWood?`wood`:`booth`].background)),Z.uBackgroundColor.value.copy(Yh.background);let e=Z_(),t=(3-e)/3,n=Wg*(Kg-1)*.5*qg*t,r=Gg*(Kg-1)*.5*Jg*t;if(ig.scale.set(Wg*Kg*t,Gg*Kg*t,1),ig.position.set(n,r,e),og.scale.copy(ig.scale),og.position.copy(ig.position),Z.uSourceZ.value=e,vg.update(Z.uPaneSize.value.x,Z.uPaneSize.value.y,Wg*(3-e)/3,Gg*(3-e)/3,Z.uGlassZ.value,e),Rg()&&jg){let t=Ph(Zh.aspect,Ug),n=jg.bounds,r=Fh(t,Ug,{x:n.x0/jg.width,y:n.y0/jg.height,width:(n.x1-n.x0)/jg.width,height:(n.y1-n.y0)/jg.height},e,Kg,qg,Jg);og.position.set(r.x,r.y,r.z),og.scale.set(r.width,r.height,1);let i=r.y+(.5-n.y1/jg.height)*r.height,a=-t.height/2-.1*t.width;kg.setDogContact(r.x+(n.x0/jg.width+(n.x1-n.x0)/jg.width/2-.5)*r.width,e,.2*t.width*Kg,Math.max(0,1-Math.abs(i-a)/(.1*t.height))*.42),vg.update(t.width,t.height,t.width,t.height,Z.uGlassZ.value,Z.uGlassZ.value-.08*Math.min(t.width,t.height))}G_.updateDistance(Yg,cg.uDepthScale.value)}function ev(){Jh.invalidate(),Bv();let e=Hh.getBoundingClientRect();X.setSize(e.width,e.height,!1),x_=__?qf(e.width,e.height,b_).panes:null;let t=x_?x_[0]:e;x_&&(x_.forEach((t,n)=>{let r=document.querySelector(n===0?`#comparison-label-a`:`#comparison-label-b`);r.style.left=`${t.x+t.width/2}px`,r.style.top=`${t.y-32}px`,r.style.width=`${e.width<720?e.width-20:(e.width-36)/2}px`}),__.resize(Math.max(1,Math.floor(t.width*X.getPixelRatio())),Math.max(1,Math.floor(t.height*X.getPixelRatio())))),Zh.aspect=t.width/t.height,yv.updateProjection();let n=Rg()?.74:Ug,r=Om(t.width/t.height,n)*zm(Eg.isWood?`wood`:`booth`);Wg=r*n,Gg=r,$_(),Z.uPetSize.value.set(Wg,Gg),Z.uResolution.value.set(t.width,t.height);let i=4.8*Math.tan(V.degToRad(Zh.fov/2));Z.uPetSize.value.set(i*Zh.aspect,i),Z.uPaneSize.value.set(Wg*(3-Z.uGlassZ.value)/3,Gg*(3-Z.uGlassZ.value)/3),vg.update(Z.uPaneSize.value.x,Z.uPaneSize.value.y,Wg*(3-Z_())/3,Gg*(3-Z_())/3,Z.uGlassZ.value,Z_()),u_?.resize(Math.max(1,Math.floor(t.width*X.getPixelRatio())),Math.max(1,Math.floor(t.height*X.getPixelRatio())));let a=Z.uPaneSize.value.x,o=Z.uPaneSize.value.y,s=Math.min(a,o)*.052,c=s*1.5,l=Z.uGlassZ.value+c*.25;if(pg.position.set(-(a+s)*.5,0,l),mg.position.set((a+s)*.5,0,l),hg.position.set(0,(o+s)*.5,l),gg.position.set(0,-(o+s)*.5,l),pg.scale.set(s,o,c),mg.scale.set(s,o,c),hg.scale.set(a+s*2,s,c),gg.scale.set(a+s*2,s,c),yg.update(a,o,Z.uGlassZ.value,s,c),Eg.resize(a,o,Z.uGlassZ.value),Rg()){let e=Ph(Zh.aspect,Ug);Dg.resize(a,o,Z.uGlassZ.value,e.clearanceScale,{grid:Z.uGridSize.value,curvature:Z.uCurvature.value}),mv.setRoomBounds(a,o,Z.uGlassZ.value),kg.resize(a,o,Z.uGlassZ.value),Ag.resize(a,o,Z.uGlassZ.value),vg.update(a,o,a,o,Z.uGlassZ.value,Z.uGlassZ.value-.08*Math.min(a,o))}else Dg.resize(a,o,Z.uGlassZ.value,void 0,{grid:Z.uGridSize.value,curvature:Z.uCurvature.value}),mv.setRoomBounds(a,o,Z.uGlassZ.value,Eg.isWood);let u=6*Math.tan(V.degToRad(20)),d=u*Zh.aspect;Z.uPaneRect.value.set(Math.max(0,.5-Wg/(2*d)),Math.max(0,.5-Gg/(2*u)),Math.min(1,.5+Wg/(2*d)),Math.min(1,.5+Gg/(2*u)))}function tv(){rv()}function nv(){rv()}function rv(e){$g.interact(performance.now(),e),qh.dataset.phase=`hidden`}function iv(){r_+=1,pv.cancelPending(),J_(),I_=null,L_=null,Fg?.cancel(),Mg?.dispose(),Mg=null,Q_(),a_=!1,Bv(),kv.setPaused(!0),rv(),K_()}function av(e=`personal`,t=!0){z_(),I_=F_&&t?Object.freeze({origin:e,name:P_.name}):null,L_=null,I_&&(R_=F_.begin(I_.origin,I_.name)),$.setMediaOrigin(e),Bv(),$.setPhoto(``),$.setState(`loading`),V_(`사진을 읽고 있어요.`)}function ov(){$.stopPhotoAdjust(),Bv(),kv.disconnect(),mv.reset(),Z.uViewOffset.value.copy(mv.update(0,Zy)),Zh.updateMatrixWorld(!0),xv(1),Kg=1,qg=Jg=0,Vv(0),Jh.invalidate()}function sv(e,t,n){let r=Mg;Mg=null,Bg(),r&&!n?(jg=r,Ng=new nr(r.cutoutImage),Ng.colorSpace=Xt,Ng.needsUpdate=!0,Pg=!0,Kg=1,qg=Jg=0):r?.dispose(),Vg!==ng&&Vg.dispose(),Vg=e,Hg=!!n,a_=!1,Ug=t,L_=!n&&I_?e:null,n&&z_(),Xg=!1,n||ov(),$y(),e.colorSpace=Xt,cg.uTexture.value=zg(),rg.map=e,rg.needsUpdate=!0,$.setPhoto(e.image instanceof HTMLImageElement?e.image.src:``),Kh.style.display=`none`,ev(),K_()}function cv(e){Jh.invalidate(),cg.uDepthMap.value!==ag&&cg.uDepthMap.value.dispose(),cg.uDepthMap.value=e,e.colorSpace=``,ug.value.fromArray(Ch.evidenceRange(e));let t=e.image?.data;if(X_=0,t&&t.length>=4)for(let e=0;e{let r=Xg&&e_!==null,i=n_,a=!n&&!r;sv(e,t,n),og.setVideo(!!n),cv(e_??Ch.flatTexture()),e_=null,r&&t_?fv.setSample(t_):fv.clear(),t_=null,Zg=i,n_=!1,Wh.hidden=!(r||Zg),r?Wh.textContent=`수작업 테스트 Depth · AI 추정 아님`:Zg&&(Wh.textContent=`Depth 없음 · 평면 사진 테스트`),lv(`final`),a||($.setState(`ready`),nv()),iy&&(iy.textContent=`이 사진으로 해보기`),a&&eb(!0)},e=>{let t=a_&&!!e;a_=!1,K_(),(e||!s_)&&V_(e);let n=!!e&&!t&&Hg;uv.hidden=!n,e?(z_(),Mg?.dispose(),Mg=null,$.setState(`error`,!1,n),Q_(),iy&&(iy.textContent=`이 사진으로 해보기`)):Hg&&$.setState(`ready`)});uv.onclick=()=>pv.retry();var mv=new ph(Zh),hv;try{hv=window.localStorage}catch{}var gv=Uf(hv);mv.setCompositionMode(gv),Dg.setCompositionMode(gv);var _v=document.querySelector(`#camera-composition`),vv=document.querySelector(`#camera-composition-note`);_v.value=gv,_v.addEventListener(`change`,()=>{gv=_v.value===`legacy`?`legacy`:`wall`,mv.setCompositionMode(gv),Dg.setCompositionMode(gv);let e=Wf(hv,gv);vv.textContent=(gv===`legacy`?`기존의 넓은 방 구도로 돌아왔어요. `:`벽 옆에서 보는 실험 구도예요. `)+(e?`선택은 이 브라우저에 저장돼요.`:`선택을 저장하지 못했어요. 새로고침하면 이번 선택이 유지되지 않을 수 있어요.`),mv.update(0,Zy),Zh.updateMatrixWorld(!0),Jh.invalidate()},{signal:Q.signal});var yv=new fh(Zh),bv=document.querySelector(`#scene-zoom-reset`);function xv(e,t,n){yv.setZoom(e,t,n),Z.uSceneZoom.value=yv.value,Z.uSceneOffset.value.copy(yv.offset),bv.hidden=yv.value===1}bv.addEventListener(`click`,()=>{xv(1),rv()},{signal:Q.signal});var Sv=document.querySelector(`#gyro`),Cv=document.querySelector(`#gyro-label`),wv=document.querySelector(`#scene-motion`),Tv=wf(globalThis.navigator);Lg=Oe(document,Q.signal,Tv,()=>$.canShowFirstGuide(),()=>{$.refreshBlocking(),ey(performance.now()),Uv(),!Q.signal.aborted&&!$.isBlocked()&&Hh.focus({preventScroll:!0})});var Ev=document.querySelector(`#gyro-recenter`),Dv=document.querySelector(`#gyro-status`),Ov=document.querySelector(`#gyro-notice`),kv=new vh((e,t)=>mv.setView(e,t),(e,t)=>{let n=e===`active`||e===`paused`||e===`waiting`;Cv.textContent=e===`permission`?`권한 요청 취소`:e===`waiting`?`기울기 연결 중`:n?`기울기 켜짐`:`기울기 연결`,Sv.setAttribute(`aria-label`,n?`${Cv.textContent}, 끄기`:Cv.textContent),Sv.setAttribute(`aria-pressed`,String(n)),Sv.setAttribute(`aria-busy`,String(e===`permission`||e===`waiting`)),Ev.hidden=!Tv||e!==`active`&&e!==`paused`||$.isBlocked()&&!$.isGuideOpen()||$.isPhotoAdjusting(),Dv.textContent=t,Ov.textContent=e===`unavailable`?t:``,Ov.hidden=e!==`unavailable`||!Tv||$.isBlocked(),e===`unavailable`&&rv()},()=>({x:mv.target.x,y:mv.target.y}),()=>rv(`tilt`)),Av=null,jv=document.querySelector(`#door-handle`),Mv=document.querySelector(`#door-controls`),Nv=document.querySelector(`#door-toggle`),Pv=document.querySelector(`#door-notice`),Fv=new W,Iv=new vf,Lv=new Na(new W(0,0,1));function Rv(){return p_===`b`&&!v_&&Qg===`final`&&Eg.isWood&&Eg.isReady}function zv(){return Rv()&&Vg!==ng&&!$.isBlocked()&&!$.isPhotoAdjusting()&&!c_&&!g_&&!document.hidden}function Bv(){$v.cancelGesture(),M_.cancel()}function Vv(e){M_.set(e),Uv()}function Hv(e){M_.moveTo(e,performance.now(),!!N_?.matches),Uv()}function Uv(){let e=Rv(),t=zv(),n=M_.value,r=e?n:0;Ag.setOpen(r),Eg.setOpen(r),f_.setSlide(-Z.uPaneSize.value.x*r);let i=$.isGuideOpen()&&e&&Vg!==ng&&!c_&&!g_&&!document.hidden;Mv.hidden=!t&&!i,Nv.disabled=!t&&!i;let a=M_.target>.001;Nv.textContent=a?`문 닫기`:`문 열기`,Nv.setAttribute(`aria-label`,`문 ${Math.round(n*100)}% 열림. ${a?`닫기`:`열기`}. 방향키로 조금씩, Home으로 닫기, End로 열기`),Pv.textContent=v_?`A·B 비교는 닫힌 문으로 표시해요. 비교를 끝내면 열림 위치가 돌아와요.`:p_===`a`?`A 진단은 닫힌 문으로 표시해요. B로 돌아가면 열림 위치가 돌아와요.`:Qg===`final`?Eg.isWood?Eg.isReady?`손잡이만 드래그하면 문, 나머지 영역은 시점 이동이에요. 두 손가락은 항상 확대·축소해요.`:`나무 창틀을 불러온 뒤 손잡이를 밀어 열 수 있어요.`:`미닫이는 할머니집 창가 테마에서 사용할 수 있어요.`:`미닫이는 Final에서 사용할 수 있어요. 진단 화면은 닫힌 상태이며 열림 위치는 보존해요.`;let o=t?Eg.handlePosition(Fv):null;if(jv.hidden=!o,o){let e=X.domElement.getBoundingClientRect();o.project(Zh),jv.hidden=o.z<-1||o.z>1||Math.abs(o.x)>1||Math.abs(o.y)>1,jv.style.left=`${(o.x+1)*e.width/2}px`,jv.style.top=`${(1-o.y)*e.height/2}px`}}function Wv(e){let t=X.domElement.getBoundingClientRect();return!t.width||!t.height?null:(Iv.setFromCamera(new H((e.x-t.left)/t.width*2-1,1-(e.y-t.top)/t.height*2),Zh),Lv.constant=-Z.uGlassZ.value,Iv.ray.intersectPlane(Lv,Fv)?.x??null)}Nv.addEventListener(`click`,()=>{zv()&&($v.cancelGesture(),rv(M_.target>.001?`door-close`:`door-open`),Hv(M_.target>.001?0:1))},{signal:Q.signal}),Nv.addEventListener(`keydown`,e=>{if(!zv())return;let t=e.key===`Home`?0:e.key===`End`?1:e.key===`ArrowLeft`?M_.target+.1:e.key===`ArrowRight`?M_.target-.1:null;if(t===null)return;e.preventDefault(),$v.cancelGesture();let n=Math.max(0,Math.min(1,t));rv(n===M_.target?void 0:n1e-8?V.clamp(l/s,-1,1):0,Jg=c>1e-8?V.clamp(u/c,-1,1):0,$_(),$y()}function Zv(e,t,n=t){let r=Jv(t),i=Jv(n);r&&i&&Xv(e,r,i)}function Qv(e,t){Zv(Kg,{x:0,y:0},{x:e*2,y:t*2})}var $v=new lh(X.domElement,(e,t)=>{$.isBlocked()||($.isPhotoAdjusting()?Qv(e,t):(mv.add(e,t),kv.syncManualView()),rv(`drag`))},rv,{getZoom:()=>$.isPhotoAdjusting()?Kg:yv.value,setZoom:(e,t,n)=>{$.isPhotoAdjusting()?Zv(e,t,n):xv(e,t,n)},isEnabled:()=>!$.isBlocked(),getBounds:e=>{if(!x_)return X.domElement.getBoundingClientRect();let t=X.domElement.getBoundingClientRect(),n=S_??Jf(x_,e.x-t.left,e.y-t.top);return n?{left:t.left+n.x,top:t.top+n.y,width:n.width,height:n.height}:null},subjectDrag:{begin:e=>{if($.isPhotoAdjusting())return qv=Yv(e),!!qv;if(!zv())return!1;let t=Eg.handlePosition(Fv);if(!t)return!1;let n=X.domElement.getBoundingClientRect();t.project(Zh);let r=n.left+(t.x+1)*n.width/2,i=n.top+(1-t.y)*n.height/2;if(t.z<-1||t.z>1||Math.abs(e.x-r)>22||Math.abs(e.y-i)>22)return!1;mv.hold();let a=Wv(e);return a!==null&&(M_.cancel(),Av={startX:a,open:M_.value,screenX:e.x,screenY:e.y,moved:!1},!0)},move:e=>{if($.isPhotoAdjusting()){let t=Yv(e);t&&qv&&Xv(Kg,qv,t),qv=t;return}if(!Av||!zv())return;let t=Wv(e);if(t===null)return;Av.moved||=Math.hypot(e.x-Av.screenX,e.y-Av.screenY)>5;let n=M_.value;Vv(Av.open-(t-Av.startX)/Z.uPaneSize.value.x),Av.moved&&M_.value!==n&&rv(M_.value>n?`door-open`:`door-close`)},end:e=>{if(qv=null,$.isPhotoAdjusting()){Av=null;return}!e&&Av&&!Av.moved&&zv()&&(rv(Av.open>.001?`door-close`:`door-open`),Hv(Av.open>.001?0:1)),Av=null}},onGestureChange:(e,t)=>{e||(S_=null),t&&(mv.hold(),M_.cancel()),kv.setPaused(e||$.isBlocked()||$.isPhotoAdjusting())}});X.domElement.addEventListener(`pointerdown`,e=>{if(x_&&!S_){let t=X.domElement.getBoundingClientRect();S_=Jf(x_,e.clientX-t.left,e.clientY-t.top)}},{capture:!0,signal:Q.signal}),document.addEventListener(`visibilitychange`,()=>{Jh.invalidate(),document.hidden&&Bv()},{signal:Q.signal}),document.querySelector(`#settings-open`).addEventListener(`click`,()=>{Bv(),kv.setPaused(!0)},{signal:Q.signal}),document.querySelector(`#scene-menu-open`).addEventListener(`click`,()=>{Bv(),kv.setPaused(!0)},{signal:Q.signal}),document.querySelector(`#sample-home`).addEventListener(`click`,()=>{Bv(),kv.setPaused(!0)},{signal:Q.signal}),document.querySelector(`#entry-samples`).addEventListener(`click`,()=>{Bv(),kv.setPaused(!0)},{signal:Q.signal}),wv.addEventListener(`click`,()=>rv(),{signal:Q.signal});function ey(e){Ig?.setAvailable(U_());let t=$.isPhotoAdjusting(),n=H_();t&&!n&&$.stopPhotoAdjust(),document.querySelector(`#photo-adjust-open`).hidden=!n||t||$.isBlocked();let r=$.isBlocked()||$.isPhotoAdjusting()||c_||g_||document.hidden,i=$.isGuideOpen()&&!c_&&!g_&&!document.hidden;Ev.hidden=r&&!i||!Tv||kv.state!==`active`&&kv.state!==`paused`;let a=r&&!i||!Tv;wv.hidden!==a&&(wv.hidden=a),!r&&kv.state===`active`&&Lg?.recenter();let o=r||!Tv||kv.state!==`unavailable`;Ov.hidden!==o&&(Ov.hidden=o);let s=$g.update(e,{enabled:!r&&!$v.isInteracting&&!v_&&!M_.isAnimating,tiltActive:kv.state===`active`,sliding:zv(),doorOpen:M_.value,reducedMotion:!!N_?.matches}),c=s?.phase??`hidden`;s&&qh.textContent!==s.text&&(qh.textContent=s.text),qh.dataset.phase!==c&&(qh.dataset.phase=c)}var ty=document.querySelector(`#image`),ny=document.querySelector(`#video`),ry=document.querySelector(`#depth-image`),iy=document.querySelector(`#sample`),ay=document.querySelector(`#test-photo`),oy=document.querySelector(`#reference-strip`),sy=document.querySelector(`#reference-status`),cy=[document.querySelector(`#reference-image-1`),document.querySelector(`#reference-image-2`)];oy.hidden=!1;var ly=()=>{sy.hidden=!1};cy.forEach(e=>e.addEventListener(`error`,ly,{signal:Q.signal})),Promise.all([Bh(()=>import(`./reference1-BphJMCNh.js`),[]),Bh(()=>import(`./reference2-DHNjbprc.js`),[])]).then(([e,t])=>{l_||(cy[0].src=e.default,cy[1].src=t.default)}).catch(()=>{l_||ly()});var uy=document.querySelector(`#effect`),dy=document.querySelector(`#view-mode`),fy=document.querySelector(`#sensitivity`),py=document.querySelector(`#depth-scale`),my=document.querySelector(`#camera-offset`),hy=document.querySelector(`#grid-size`),gy=document.querySelector(`#gridOut`),_y=document.querySelector(`#mosaic-style`),vy=_y.closest(`label`),yy=document.querySelector(`#curvature-controls`),by=document.querySelector(`#region-fixed-note`),xy=document.querySelector(`#curvature`),Sy=document.querySelector(`#light-x`),Cy=document.querySelector(`#light-y`),wy=document.querySelector(`#lightXOut`),Ty=document.querySelector(`#lightYOut`),Ey=document.querySelector(`#cameraOut`),Dy=document.querySelector(`#photo-glass-distance`),Oy=document.querySelector(`#photoGlassDistanceOut`),ky=document.querySelector(`#sensitivityOut`),Ay=document.querySelector(`#depthOut`),jy=document.querySelector(`#photo-zoom`),My=document.querySelector(`#photoZoomOut`),Ny=document.querySelector(`#photo-pan-x`),Py=document.querySelector(`#photoPanXOut`),Fy=document.querySelector(`#photo-pan-y`),Iy=document.querySelector(`#photoPanYOut`),Ly=document.querySelector(`#photo-reset`),Ry=document.querySelector(`#reset`),zy=document.querySelector(`#glass-renderer`),By=document.querySelector(`#renderer-notice`),Vy=document.querySelector(`#mesh-render-error`);async function Hy(){return u_||(d_||=Bh(async()=>{let{createOriginalGlassRenderer:e}=await import(`./OriginalGlassRenderer-DLs_logl.js`);return{createOriginalGlassRenderer:e}},[]).then(({createOriginalGlassRenderer:e})=>{if(l_)throw Error(`Scene disposed`);return u_=e({renderer:X,scene:Yh,frameScene:Xh,camera:Zh,petDepth:og,uniforms:Z,depthUniforms:cg,emptyTex:ng,regionHistoryUniform:lg,state:()=>({mode:Qg,active:Vg,activeIsVideo:Hg,effect:uy.value,style:_y.value})}),u_.setEffect(uy.value),ev(),u_}).finally(()=>{d_=null}),d_)}function Uy(){p_===`b`&&m_===`b`&&!v_&&(u_?.dispose(),u_=null)}function Wy(){let e=p_===`a`;zy.value=p_,document.querySelector(`#pattern-cards`).hidden=uy.value!==`mosaic`,uy.disabled=!e,document.querySelectorAll(`[data-pattern]`).forEach(t=>{t.hidden=!e&&t.dataset.pattern!==`2`}),By.textContent=e?`A 진단 모드 · 기존 무늬와 화면 기반 굴절`:`기본 B · 실제 고방 메시 + 맞춤 굴절`+(f_.environmentOnly?` · 환경광만`:``),Qy()}async function Gy(e){Bv();let t=++h_;m_=e;try{if(e===`a`&&await Hy(),l_||c_||t!==h_){Uy();return}Bv(),p_=e,v_&&Yy(),e===`b`&&(uy.value=`mosaic`,_y.value=`2`,Z.uMosaicStyle.value=2,Z.uRegionStrength.value=0,Z.uStrength.value=1,u_?.setEffect(`mosaic`),document.querySelectorAll(`[data-pattern]`).forEach(e=>e.setAttribute(`aria-pressed`,String(e.dataset.pattern===`2`)))),Uy(),Wy(),ev(),g_&&(g_=!1,Vy.close(),$.setRenderLost(!1))}catch{t===h_&&(m_=p_),Uy(),zy.value=p_,By.textContent=`A 진단 렌더러를 불러오지 못했어요. 현재 화면을 유지해요.`}}function Ky(){c_||l_||g_||(z_(),g_=!0,Bv(),kv.setPaused(!0),$.setRenderLost(!0),v_&&Yy(`B 렌더링이 멈췄어요. 복구 방법을 선택해주세요.`),Vy.showModal())}Vy.addEventListener(`cancel`,e=>e.preventDefault(),{signal:Q.signal}),document.querySelector(`#mesh-retry`).addEventListener(`click`,()=>{c_||l_||(f_.dispose(),f_=new vp(X,og),Jh.invalidate(),g_=!1,Vy.close(),$.setRenderLost(!1),Wy())},{signal:Q.signal}),document.querySelector(`#mesh-use-a`).addEventListener(`click`,()=>{Gy(`a`)},{signal:Q.signal}),zy.addEventListener(`change`,()=>{Gy(zy.value===`a`?`a`:`b`)},{signal:Q.signal});function qy(e){if(p_===`a`){u_.render(e);return}if(Qg===`rgb`||Qg===`depth`){X.setRenderTarget(null),X.render(Yh,Zh);return}try{f_.sync({width:Z.uPaneSize.value.x,height:Z.uPaneSize.value.y,grid:Z.uGridSize.value,curvature:Z.uCurvature.value},Z.uGlassZ.value,Z.uLightPosition.value,Yh.background),f_.syncReveal(vg.meshes,Xh),f_.syncCourtyard(Rg()?kg:null),f_.render(Zh,Xh,Qg===`final`||Qg===`glass`,null,Qg!==`glass`)}catch{Ky()}}function Jy(){return uy.value===`mosaic`&&_y.value===`2`&&(Qg===`final`||Qg===`noglass`)}function Yy(e=`비교를 끝냈어요. 선택한 단독 렌더러로 돌아왔어요.`){y_+=1,v_=!1,Bv(),S_=null,__?.dispose(),__=null,x_=null,Uy(),X.info.autoReset=!0,D_.hidden=!0,E_.hidden=!0,T_.textContent=`비교 켜기 · 추가 렌더 비용`,T_.setAttribute(`aria-pressed`,`false`),O_.textContent=e,document.querySelector(`#experience`).removeAttribute(`data-comparison`),w_.reset(),c_||ev()}async function Xy(){if(v_){Yy();return}if(Vg===ng||s_||o_||a_){O_.textContent=`사진 준비가 끝난 뒤 비교를 켜주세요.`;return}if(c_||l_||!Jy()){O_.textContent=`고방유리와 Final 또는 No Glass를 선택한 뒤 비교를 켜주세요.`;return}Bv(),v_=!0;let e=++y_;T_.textContent=`비교 준비 취소`,O_.textContent=`굴절 보정 B를 준비하고 있어요.`;try{let{PhysicalGlassComparison:t}=await Bh(async()=>{let{PhysicalGlassComparison:e}=await import(`./PhysicalGlassComparison-B37yDBlH.js`);return{PhysicalGlassComparison:e}},[]);if(await Hy(),l_||c_||e!==y_||!v_){Uy();return}if(!Jy()){Yy(`고방유리 Final / No Glass에서 비교할 수 있어요.`);return}b_=Zh.aspect,__=new t(X,Yh.background),Bv(),rv(),X.info.autoReset=!1,w_.reset(),k_.textContent=`첫 프레임을 준비하는 중…`,A_.textContent=``,C_=0,D_.hidden=!1,E_.hidden=!1,T_.textContent=`비교 끝내기`,T_.setAttribute(`aria-pressed`,`true`),O_.textContent=`A 기존 코드 / 굴절 보정 B · 실제 메시 + 맞춤 굴절. 두 화면의 드래그·확대·거리·깊이를 공유해요.`,document.querySelector(`#comparison-label-b`).textContent=f_.environmentOnly?`굴절 보정 B · 맞춤 굴절 (환경광만)`:`굴절 보정 B · 맞춤 굴절`,document.querySelector(`#experience`).setAttribute(`data-comparison`,`true`),ev(),document.querySelector(`#settings-dialog`).close(),Hh.focus({preventScroll:!0})}catch{Yy(`비교 렌더러를 준비하지 못했어요. 단독 화면을 유지해요.`)}}T_.addEventListener(`click`,()=>{Xy()},{signal:Q.signal}),E_.addEventListener(`click`,()=>{Yy(),Hh.focus({preventScroll:!0})},{signal:Q.signal});for(let e of[uy,_y,dy])e?.addEventListener(`change`,()=>{queueMicrotask(()=>{v_&&!Jy()&&Yy(`다른 무늬·진단 화면을 선택해 비교를 끝냈어요.`)})},{signal:Q.signal});var Zy=1;function Qy(){let e=uy.value===`mosaic`;vy&&(vy.style.display=e?`grid`:`none`),_y.disabled=!e,yy&&(yy.hidden=!e,yy.style.display=e?`grid`:`none`),by&&(by.hidden=!e,by.textContent=_y.value===`2`?`고방유리 · 표면 요철에 따른 굴절 · 색면 처리 없음`:_y.value===`0`?`Ref1 옵션 2 · 색면 단순화 1 · 굴절 1 (고정)`:`기존 촘촘 유리 · 굴절 1 (고정)`),[Sy,Cy,xy].forEach(t=>{t&&(t.disabled=!e)})}function $y(){jy&&(jy.value=Kg.toFixed(2)),My&&(My.value=Kg.toFixed(2)),document.querySelector(`#photo-adjust-zoom`).value=Kg.toFixed(2),document.querySelector(`#photo-adjust-value`).value=Kg.toFixed(2),document.querySelector(`#photo-adjust-help`).textContent=Kg<=1.001?`사진을 확대한 뒤 드래그해서 위치를 맞춰주세요`:`드래그·방향키로 이동 · 두 손가락·휠로 확대`,Ny&&(Ny.value=qg.toFixed(2)),Py&&(Py.value=qg.toFixed(2)),Fy&&(Fy.value=Jg.toFixed(2)),Iy&&(Iy.value=Jg.toFixed(2))}async function eb(e=!1){if(Gh.disabled||!(Vg.image instanceof HTMLImageElement))return;let t=Vg,n=B_(t),r=Vg.image,i=++i_;s_=!0,Bv(),$.startJourney(),V_(`출발 준비 중이에요. 처음에는 조금 더 걸릴 수 있어요.`),K_();try{let a=await q_.getDepthMap(r);if(l_||i!==i_||Vg!==t||Hg){a.dispose();return}cv(a),fv.clear(),Zg=!1,Wh.hidden=!1,Wh.textContent=`AI 추정 · Depth Anything V2 ${xh.modelName} · 입력 ${xh.inputSize} (상대 깊이, 0=뒤 · 1=앞)`,lv(`final`),!c_&&!g_&&n!==null&&n===R_&&F_?.arrived(n),$.setState(`ready`),V_(e?`입체감 준비 완료! 사진을 살짝 움직여보세요.`:`새 입체감을 적용했어요. 사진을 움직여 확인해보세요.`),nv()}catch(e){!l_&&i===i_&&(z_(),$.setState(`error`,!0),V_(`사진 분석 실패: ${e instanceof Error?e.message:`알 수 없는 오류`}. 다시 시도하거나 평면 사진으로 볼 수 있어요.`,`사진을 준비하지 못했어요. 다시 시도하거나 다른 사진을 골라 주세요. 평면 사진으로 볼 수도 있어요.`))}finally{i===i_&&(s_=!1,K_())}}Gh.addEventListener(`click`,()=>{eb()},{signal:Q.signal}),Fg=Vh(document,Q.signal,{onAccept(e){if(c_||l_){e.dispose();return}tv(),r_+=1,J_(),pv.cancelPending(),Q_(),Mg?.dispose(),Mg=e,a_=!0,av(),K_(),pv.load(new File([e.originalBlob],`peeking-original.png`,{type:`image/png`}))},onToggle(e){!jg||a_||s_||c_||(Bv(),Pg=e,Kg=1,qg=Jg=0,$y(),ev(),lv(Qg),u_?.invalidate(),Fg?.setState({available:!0,enabled:e,busy:!1}))}});function tb(e){return c_||l_||!e.type.startsWith(`image/`)?!1:(Fg?.cancel(),Mg?.dispose(),Mg=null,tv(),r_+=1,J_(),av(),a_=!0,K_(),Q_(),pv.load(e),!0)}ty.onchange=e=>{let t=e.target,n=t.files?.[0];n&&tb(n),t.value=``},Ef(document,Q.signal,()=>!l_&&!c_&&!g_&&$.canAcceptPhotoPaste(),tb),ny.onchange=e=>{let t=e.target,n=t.files?.[0];n&&!c_&&(Fg?.cancel(),Mg?.dispose(),Mg=null,tv(),r_+=1,J_(),av(`personal`,!1),a_=!0,K_(),Q_(),pv.load(n)),t.value=``},document.querySelector(`#photo-adjust-open`).addEventListener(`click`,()=>{H_()&&!$.isBlocked()&&($.startPhotoAdjust(),$y())},{signal:Q.signal}),document.querySelector(`#photo-adjust-zoom`).addEventListener(`input`,e=>{$.isPhotoAdjusting()&&H_()&&(Kg=V.clamp(Number(e.target.value)||1,1,3),$_(),$y())},{signal:Q.signal}),document.querySelector(`#photo-adjust-reset`).addEventListener(`click`,()=>{$.isPhotoAdjusting()&&H_()&&(Kg=1,qg=Jg=0,$_(),$y())},{signal:Q.signal}),jy?.addEventListener(`input`,e=>{Kg=Number(e.target.value),$_(),$y()},{signal:Q.signal}),Ny?.addEventListener(`input`,e=>{qg=Number(e.target.value),$_(),$y()},{signal:Q.signal}),Fy?.addEventListener(`input`,e=>{Jg=Number(e.target.value),$_(),$y()},{signal:Q.signal}),Ly?.addEventListener(`click`,()=>{Kg=1,qg=0,Jg=0,$_(),$y()},{signal:Q.signal});async function nb(e){if(c_||l_||![`dog1`,`dog2`,`dog3`,`dog4`,`dog5`].includes(e))return;tv(),ay.value=e,$.setSampleName?.({dog1:`호두`,dog2:`두부`,dog3:`보리`,dog4:`콩이`,dog5:`누렁이`}[e]),Fg?.cancel(),Mg?.dispose(),Mg=null;let t=++r_,n=`/assets/samples/${e}.jpg`;J_(),a_=!0,av(`sample`),K_(),pv.cancelPending(),Q_(),iy&&(iy.textContent=`사진을 불러오는 중…`),V_(``);try{let e=await fetch(n);if(!e.ok)throw Error(`image`);let r=await e.blob();if(l_||t!==r_)return;n_=!0,pv.load(new File([r],n.split(`/`).pop()??`test-photo`,{type:e.headers.get(`content-type`)??`image/jpeg`}))}catch{!l_&&t===r_&&(z_(),a_=!1,K_(),$.setState(`error`),Q_(),V_(`샘플 사진을 읽지 못했습니다. 다른 사진을 고르거나 다시 시도해 주세요.`),iy&&(iy.textContent=`이 사진으로 해보기`))}}iy?.addEventListener(`click`,()=>{nb(ay.value)},{signal:Q.signal}),uy.addEventListener(`change`,e=>{u_?.setEffect(e.target.value),Qy()},{signal:Q.signal}),dy?.addEventListener(`change`,e=>lv(e.target.value),{signal:Q.signal}),fy.oninput=e=>{let t=Number(e.target.value);Zy=t,ky.value=t.toFixed(2)},py?.addEventListener(`input`,e=>{let t=Math.min(Number(e.target.value),.4);cg.uDepthScale.value=t,$_(),u_?.invalidate(),Ay&&(Ay.value=t.toFixed(2))},{signal:Q.signal}),my.addEventListener(`input`,e=>{let t=Number(e.target.value);mv.setMaxOffset(t),Ey.value=t.toFixed(2)},{signal:Q.signal}),Dy.addEventListener(`input`,e=>{let t=Number(e.target.value);Yg=V.lerp(ep.minGap,ep.maxGap,t/100),$_(),Oy.value=`${t.toFixed(0)}%`},{signal:Q.signal}),hy.addEventListener(`input`,e=>{let t=Number(e.target.value);Z.uGridSize.value=t,gy.value=t.toFixed(0),ev()},{signal:Q.signal}),_y.addEventListener(`change`,e=>{if(uy.value!==`mosaic`)return;let t=Number(e.target.value);Z.uMosaicStyle.value=t,Z.uGridSize.value=t===0?13:t===2?tp.grid:24,Z.uRegionStrength.value=+(t===0),Z.uStrength.value=1,hy.value=String(Z.uGridSize.value),gy.value=String(Z.uGridSize.value),ev(),Qy()},{signal:Q.signal}),xy?.addEventListener(`change`,e=>{Z.uCurvature.value=e.target.value===`-1`?-1:1},{signal:Q.signal}),Sy?.addEventListener(`input`,e=>{let t=Number(e.target.value);Z.uLightPosition.value.x=t,wy&&(wy.value=t.toFixed(2))},{signal:Q.signal}),Cy?.addEventListener(`input`,e=>{let t=Number(e.target.value);Z.uLightPosition.value.y=t,Ty&&(Ty.value=t.toFixed(2))},{signal:Q.signal}),ry?.addEventListener(`change`,async()=>{if(c_){ry.value=``;return}let e=ry.files?.[0];if(!e||Vg===ng||Hg||a_)return;J_();let t=i_;o_=!0,Bv(),$.setState(`loading`),V_(`깊이 이미지를 읽고 있어요.`),K_(),fv.clear();let n=URL.createObjectURL(e),r=null;try{let e=new Image;if(e.src=n,await e.decode(),l_||t!==i_)return;if(Ug>0&&Math.abs(e.width/e.height-Ug)>.02)throw Error(`aspect`);if(r=Ch.toTexture(e),l_||t!==i_){r.dispose(),r=null;return}cv(r),r=null,Wh.hidden=!1,Wh.textContent=`직접 올린 깊이 이미지 · AI 추정 아님 (0=뒤, 1=앞)`,V_(`직접 올린 깊이 이미지를 적용했어요.`),$.setState(`ready`),nv()}catch{!l_&&t===i_&&(V_(`깊이 이미지를 읽지 못했거나 사진과 종횡비가 다릅니다.`),$.setState(`error`,Vg!==ng&&!Hg))}finally{r?.dispose(),URL.revokeObjectURL(n),t===i_&&(ry.value=``,o_=!1,K_())}},{signal:Q.signal}),Ry.onclick=()=>{mv.reset(),kv.reset(),xv(1)},Sv.onclick=()=>{Tv&&!$.isBlocked()&&!$.isPhotoAdjusting()&&kv.toggle()},Ev.addEventListener(`click`,()=>{$.isBlocked()||$.isPhotoAdjusting()||(mv.reset(),kv.reset())},{signal:Q.signal}),document.querySelector(`#scene-guide-replay`).addEventListener(`click`,()=>Lg?.start(!0),{signal:Q.signal}),document.querySelector(`#guide-replay`).addEventListener(`click`,()=>{let e=document.querySelector(`#settings-dialog`);e.open&&(e.addEventListener(`close`,()=>Lg?.start(!0),{once:!0,signal:Q.signal}),e.close())},{signal:Q.signal}),Hh.addEventListener(`keydown`,e=>{if($.isBlocked())return;let t=e.key===`ArrowLeft`?[-.06,0]:e.key===`ArrowRight`?[.06,0]:e.key===`ArrowUp`?[0,.06]:e.key===`ArrowDown`?[0,-.06]:null;t&&(e.preventDefault(),$.isPhotoAdjusting()?Qv(t[0],t[1]):(mv.add(t[0],t[1]),kv.syncManualView()),rv(`drag`))},{signal:Q.signal}),document.querySelectorAll(`[data-pick-photo]`).forEach(e=>e.addEventListener(`click`,()=>ty.click(),{signal:Q.signal})),document.querySelector(`#flow-retry`).addEventListener(`click`,()=>{Hg?pv.retry():eb()},{signal:Q.signal}),document.querySelector(`#flow-flat`).addEventListener(`click`,()=>{Vg!==ng&&(z_(),cv(Ch.flatTexture()),lv(`final`),Wh.hidden=!1,Wh.textContent=`입체감 없는 평면 사진 · AI 추정 아님`,$.setState(`ready`),nv())},{signal:Q.signal}),bp(document,Q.signal);var rb=new wp(X.domElement,document.querySelector(`#render-recovery`),document.querySelector(`#render-reload`),()=>{c_=!0,h_+=1,m_=p_,Vy.open&&Vy.close(),v_&&Yy(`그래픽 연결이 끊겨 비교를 종료했어요. 복구 후 선택한 단독 렌더러로 돌아가요.`);let e=s_||o_||a_;$.setRenderLost(!0),Bv(),kv.setPaused(!0),rv(),Fg?.cancel(),Mg?.dispose(),Mg=null,r_+=1,pv.cancelPending(!0),a_=!1,ry.value=``,J_(),Q_(),e&&($.setState(`error`,Vg!==ng&&!Hg),V_(`그래픽 연결이 끊겨 사진 준비를 멈췄어요. 화면이 복구되면 다시 시도하거나 평면 사진으로 볼 수 있어요.`))},()=>{u_?.invalidate(),f_.restore(),ev(),c_=!1,g_=!1,$.setRenderLost(!1),K_()},()=>window.location.reload()),ib=new ResizeObserver(ev);ib.observe(Hh),ev(),lv(`final`),Qy(),K_(),Wy(),Eg.load(),j_=!0,Dg.load(),F_?.start();var ab=performance.now(),ob=0;function sb(){let e=new Set([`uTime`,`uSceneTexture`,`uSceneDepth`,`uRegionPalette`,`uRegionAtlas`,`uRegionHistory`]),t=Object.entries({...Z,...cg}).filter(([t])=>!e.has(t)).map(([e,t])=>{let n=t.value;if(n instanceof nr){let t=n===Vg&&Hg?n.image:null,r=t&&typeof t.requestVideoFrameCallback!=`function`?t.currentTime:n.version;return`${e}:${n.uuid}:${r}`}return n&&typeof n.toArray==`function`?`${e}:${n.toArray().join(`,`)}`:`${e}:${n}`});return[p_,Qg,__?`comparison`:`single`,uy.value,_y.value,X.domElement.width,X.domElement.height,Eg.isReady,Dg.isReady,Eg.isWood,...Zh.matrixWorld.elements,...Zh.projectionMatrix.elements,...og.matrixWorld.elements,M_.value,...t].join(`|`)}function cb(e){let t=Math.min((e-ab)/1e3,.1);if(ab=e,kv.setPaused($.isBlocked()||$.isPhotoAdjusting()||$v.isInteracting),ey(e),M_.update(e,zv(),!!N_?.matches),Uv(),c_||s_||document.hidden){Jh.invalidate(),w_.reset(),ob=requestAnimationFrame(cb);return}if(g_){Jh.invalidate(),ob=requestAnimationFrame(cb);return}!$.isBlocked()&&!$.isPhotoAdjusting()&&Z.uViewOffset.value.copy(mv.update(t,Zy)),Zh.updateMatrixWorld(!0),og.updateMatrixWorld(!0),Uv(),Og.sync(Dg.isReady&&Eg.isWood&&(Qg===`final`||Qg===`noglass`&&cg.uUsePhotoAlpha?.value)&&Vg!==ng),Z.uPetWorldToLocal.value.copy(og.matrixWorld).invert(),Z.uContentViewProjection.value.multiplyMatrices(Zh.projectionMatrix,Zh.matrixWorldInverse),Z.uContentInverseViewProjection.value.copy(Z.uContentViewProjection.value).invert(),Z.uContentCameraPosition.value.copy(Zh.position),Z.uTime.value=e/1e3;let n=fv.update(Zh,og,cg.uDepthScale.value,cg.uDepthBias.value,Hh.clientWidth,Z.uSourceZ.value,X_);dv.textContent=n,dv.hidden=!n;let r=(p_===`a`||!!__)&&(Qg===`final`||Qg===`glass`)&&uy.value===`mosaic`&&_y.value===`0`&&Z.uRegionAvailable.value>.5&&Z.uRegionStrength.value>.001&&Z.uStrength.value>.001;if(!Jh.shouldRender(t,{signature:sb(),continuous:M_.isAnimating,temporal:r})){w_.reset(),__&&(k_.textContent=`정지 화면 · 추가 렌더링 대기 중`),ob=requestAnimationFrame(cb);return}if(__&&x_){X.info.reset();let n=performance.now();u_.render(t,__.targetA),w_.record(`a`,performance.now()-n,X.info.render);let r=X.info.render.calls,i=X.info.render.triangles;n=performance.now();try{if(f_.sync({width:Z.uPaneSize.value.x,height:Z.uPaneSize.value.y,grid:Z.uGridSize.value,curvature:Z.uCurvature.value},Z.uGlassZ.value,Z.uLightPosition.value,Yh.background),f_.syncReveal(vg.meshes,Xh),f_.syncCourtyard(Rg()?kg:null),f_.render(Zh,Xh,Qg===`final`,__.targetB),w_.record(`b`,performance.now()-n,{calls:X.info.render.calls-r,triangles:X.info.render.triangles-i}),__.composite(x_,Hh.clientHeight),w_.frame(e),e-C_>500){C_=e;let t=w_.snapshot();k_.textContent=`CPU 제출 A ${t.a.cpuMs.toFixed(2)}ms · B ${t.b.cpuMs.toFixed(2)}ms\n화면 간격 ${t.frameMs?.toFixed(1)??`—`}ms (A+B 동시)\nDraw A ${t.a.calls} · B ${t.b.calls} / Tri A ${t.a.triangles.toLocaleString()} · B ${t.b.triangles.toLocaleString()}`;let n=performance.memory?.usedJSHeapSize;A_.textContent=`GL 형상 ${X.info.memory.geometries} · 텍스처 ${X.info.memory.textures} / B CPU ${(f_.geometryBytes/1048576).toFixed(2)}MiB\n${Number.isFinite(n)?`JS heap 약 ${(n/1048576).toFixed(1)}MiB (페이지·비표준)`:`JS heap API 미지원`}${f_.reducedSampling?` · B 세분화 축소`:``}`}}catch{Ky()}}else qy(t);ob=requestAnimationFrame(cb)}ob=requestAnimationFrame(cb);function lb(){F_?.dispose(),Bg(),Fg?.dispose(),kg.dispose(),Ag.dispose(),M_.cancel(),h_+=1,y_+=1,v_=!1,__?.dispose(),__=null,l_=!0,r_+=1,i_+=1,q_.cancel(),Gh.disabled=!0,Y_(),Q.abort(),rb.dispose(),cancelAnimationFrame(ob),ib.disconnect(),ty.onchange=null,ny.onchange=null,uy.onchange=null,fy.oninput=null,Ry.onclick=null,Sv.onclick=null,uv.onclick=null,$v.dispose(),kv.dispose(),pv.dispose(),u_?.dispose(),f_.dispose(),Eg.dispose(),Dg.dispose(),Og.dispose(),yg.dispose(),vg.dispose(),_g.dispose(),fg.forEach(e=>e.dispose()),Vg!==ng&&Vg.dispose(),cg.uDepthMap.value!==ag&&cg.uDepthMap.value.dispose(),ag.dispose(),og.geometry.dispose(),sg.dispose(),Qh.dispose(),rg.dispose(),dg.dispose(),ng.dispose(),X.domElement.remove(),X.dispose(),qh.dataset.phase=`hidden`,uv.remove(),dv.remove()}import.meta.hot?.dispose(lb);export{Ke as a,Ne as c,Yc as d,ya as f,ar as h,To as i,Xa as l,We as m,K as n,q as o,ze as p,nt as r,Mi as s,ih as t,za as u}; \ No newline at end of file diff --git a/dist/assets/index-CAEr_JzP.css b/dist/assets/index-CAEr_JzP.css new file mode 100644 index 0000000..15e5885 --- /dev/null +++ b/dist/assets/index-CAEr_JzP.css @@ -0,0 +1 @@ +.driver-popover{all:unset;font-family:var(--driver-popover-font-family,"Helvetica Neue", Inter, ui-sans-serif, "Apple Color Emoji", Helvetica, Arial, sans-serif);box-sizing:border-box;color:#2d2d2d;z-index:1000000000;background-color:#fff;border-radius:5px;min-width:250px;max-width:300px;margin:0;padding:15px;position:fixed;top:0;right:0;box-shadow:0 1px 10px #0006}.driver-popover-title{zoom:1;margin:0;font-size:19px;font-weight:700;line-height:1.5;display:block;position:relative}.driver-popover-close-btn{all:unset;cursor:pointer;color:#d2d2d2;z-index:1;text-align:center;width:32px;height:28px;font-size:18px;font-weight:500;transition:color .2s;position:absolute;top:0;right:0}.driver-popover-close-btn:hover,.driver-popover-close-btn:focus{color:#2d2d2d}.driver-popover-title[style*=block]+.driver-popover-description{margin-top:5px}.driver-popover-description{zoom:1;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.5}.driver-popover-footer{text-align:right;zoom:1;justify-content:space-between;align-items:center;margin-top:15px;display:flex}.driver-popover-progress-text{color:#727272;zoom:1;font-size:13px;font-weight:400}.driver-popover-footer-btn{all:unset;box-sizing:border-box;color:#2d2d2d;cursor:pointer;zoom:1;background-color:#fff;border:1px solid #ccc;border-radius:3px;outline:0;padding:3px 7px;font-size:12px;line-height:1.3;text-decoration:none;display:inline-block}.driver-popover-footer .driver-popover-btn-disabled{opacity:.5;pointer-events:none}.driver-popover-footer-btn:hover,.driver-popover-footer-btn:focus{background-color:#f7f7f7}.driver-popover-navigation-btns{flex-grow:1;justify-content:flex-end;display:flex}.driver-popover-navigation-btns button+button{margin-left:4px}.driver-popover-arrow{content:"";border:5px solid #fff;position:absolute}.driver-popover-arrow-side-over{display:none}.driver-popover-arrow-side-left{border-top-color:#0000;border-bottom-color:#0000;border-right-color:#0000;left:100%}.driver-popover-arrow-side-right{border-top-color:#0000;border-bottom-color:#0000;border-left-color:#0000;right:100%}.driver-popover-arrow-side-top{border-bottom-color:#0000;border-left-color:#0000;border-right-color:#0000;top:100%}.driver-popover-arrow-side-bottom{border-top-color:#0000;border-left-color:#0000;border-right-color:#0000;bottom:100%}.driver-popover-arrow-side-center,.driver-popover-arrow-none{display:none}.driver-active .driver-overlay{pointer-events:none}.driver-active.driver-no-scroll{overflow:hidden}.driver-active *{pointer-events:none}.driver-active .driver-active-element,.driver-active .driver-active-element *,.driver-popover,.driver-popover *{pointer-events:auto}@keyframes animate-fade-in{0%{opacity:0}to{opacity:1}}.driver-fade .driver-overlay{animation:animate-fade-in var(--driver-animation-duration,.4s) ease-in-out}.driver-fade .driver-popover{animation:animate-fade-in var(--driver-animation-duration,.4s)}.driver-active-element-parent-no-scroll{overflow:hidden!important}.driver-no-interaction,.driver-no-interaction *{pointer-events:none!important}@font-face{font-family:BM Kkubulim;src:url(/fonts/BMKkubulim.woff)format("woff");font-style:normal;font-weight:400;font-display:swap}:root{--font-ui:"BM Kkubulim","Apple SD Gothic Neo","Noto Sans KR",system-ui,sans-serif;--font-values:ui-monospace,"SFMono-Regular",Consolas,monospace;font-family:var(--font-ui);color:#453653;font-synthesis:none;--ink:#453653;--muted:#71637f;--purple:#7651a8;--lavender:#e4d6fb;--cream:#fffbf2;--apricot:#ffd5b4;--line:#d9cbea;--shadow:#b29bc9;--radius:24px;background:#f1ebff;font-weight:400}*{box-sizing:border-box}body{margin:0;font-size:16px;line-height:1.65}button,input,select{font:inherit;color:inherit}strong,b{font-weight:400}output,input[type=number],pre,code{font-family:var(--font-values);letter-spacing:normal;font-weight:400}button,select,summary,.upload,input[type=range]{-webkit-tap-highlight-color:transparent}button,select,input[type=number]{min-height:44px}button{cursor:pointer}button:disabled{cursor:default;color:#867d8b;box-shadow:none;background:#f0ebf2;border-color:#d9d1df}button:focus-visible,select:focus-visible,input:focus-visible,summary:focus-visible,a:focus-visible,#canvas-wrap:focus-visible{outline-offset:4px;outline:3px solid #6b439d}button,select{border:1px solid var(--line);background:var(--cream);border-radius:14px}button{transition:transform .16s,box-shadow .16s,background .16s}button:not(:disabled):active,.upload:active{box-shadow:0 1px 0 var(--shadow);transform:translateY(2px)scale(.97)}[hidden]{display:none!important}#app{max-width:1600px;margin:0 auto}.app-header{flex-wrap:wrap;align-items:center;gap:24px;padding:28px 44px 26px;display:flex}.brand{letter-spacing:-1.4px;color:var(--ink);align-items:center;gap:10px;font-size:29px;font-weight:400;line-height:.83;text-decoration:none;display:flex}.brand-second{display:block}.brand-mark{color:#77559e;font-size:45px;font-weight:400;line-height:1}.brand-dot{color:#bd6545;align-self:flex-end;font-size:38px}.header-note{color:var(--muted);margin-top:5px;font-size:14px}.primary-upload{background:var(--apricot);color:#593c31;white-space:nowrap;border:1.5px solid #a76948;justify-content:center;align-items:center;gap:7px;min-height:48px;margin-left:auto;padding:10px 20px;font-weight:400;transition:transform .16s;display:flex;box-shadow:0 4px #cc9b7b}.primary-upload>span{font-size:23px;font-weight:400;line-height:1}.upload{cursor:pointer;border-radius:16px;position:relative}.upload input[type=file],.sr-only{clip:rect(0,0,0,0);clip-path:inset(50%);white-space:nowrap;border:0!important;width:1px!important;height:1px!important;margin:-1px!important;padding:0!important;position:absolute!important;overflow:hidden!important}.upload:focus-within{outline-offset:4px;outline:3px solid #6b439d}main{grid-template-columns:minmax(0,1fr) 366px;align-items:start;gap:28px;padding:0 44px;display:grid}.visual-column{min-width:0;position:sticky;top:20px}.photo-mat{background:var(--cream);border:1px solid #d0bddf;border-radius:28px;padding:20px 20px 0;box-shadow:0 6px #d3c4e3,0 16px 32px #70508b0d}.preview-heading{justify-content:space-between;align-items:center;gap:12px;margin-bottom:15px;display:flex}.eyebrow{letter-spacing:1.8px;color:#79628e;margin:0 0 5px;font-size:12px;font-weight:400}.preview-chip{color:#71558e;background:#f0e5ff;border:1px solid #dfcdec;border-radius:18px;padding:7px 11px;font-size:12px;line-height:1.25}.stage{background:#f7f0e5;border:1px solid #e4d9eb;border-radius:16px;height:clamp(410px,62vh,740px);position:relative;overflow:hidden}#canvas-wrap{touch-action:none;border-radius:inherit;position:absolute;inset:0}#canvas-wrap:focus-visible{outline-offset:-4px}#canvas-wrap canvas{cursor:grab;border-radius:inherit;width:100%;height:100%;display:block}#canvas-wrap canvas.is-dragging{cursor:grabbing}#empty{z-index:1;text-align:center;pointer-events:none;color:var(--muted);background:#f7f0e5ed;flex-direction:column;justify-content:center;align-items:center;gap:16px;padding:24px;display:flex;position:absolute;inset:0}#empty strong{letter-spacing:-.6px;color:var(--ink);font-size:clamp(19px,2vw,26px)}#empty>span:last-child{font-size:14px;line-height:1.8}.empty-star{color:#a082bf;font-size:62px;line-height:1.2}#hint{color:#665177;text-align:center;pointer-events:none;background:#fffbf2ed;border:1px solid #d4c2e6;border-radius:25px;width:max-content;max-width:calc(100% - 28px);margin:0;padding:10px 16px;font-size:13px;transition:opacity .25s;position:absolute;bottom:18px;left:50%;transform:translate(-50%)}.photo-caption{color:#7c6a88;justify-content:space-between;align-items:center;gap:12px;min-height:55px;padding:3px 4px;font-size:13px;display:flex}.caption-spark{color:#97b;letter-spacing:5px;white-space:nowrap;font-size:26px}.processing-card{align-items:center;gap:14px;padding:22px 4px 10px;display:flex}.processing-copy{flex:1;min-width:0}#status{overflow-wrap:anywhere;margin:0;font-size:14px}#depth-provenance{color:var(--muted);overflow-wrap:anywhere;margin:6px 0 0;font-size:12px;line-height:1.6}#ai-depth{flex:none;padding:9px 14px;font-size:13px}.editor-heading{justify-content:space-between;align-items:center;margin:0 0 18px;padding:3px 4px;display:flex}.editor-heading h1{letter-spacing:-.8px;margin:5px 0 0;font-size:25px;line-height:1.3}.editor-sticker{color:#8e573c;background:var(--apricot);border:1px solid #dfb49c;border-radius:15px;place-items:center;width:47px;height:47px;font-size:29px;display:grid;transform:rotate(9deg);box-shadow:0 3px #dbc9ca}aside{background:#faf6ff;border:1px solid #d4c1e6;border-radius:28px;min-width:0;padding:23px 22px;box-shadow:0 5px #d8cbea}#tool-tabs{background:#eadff4;border:1px solid #dfd0ec;border-radius:18px;grid-template-columns:repeat(2,minmax(0,1fr));gap:5px;margin-bottom:20px;padding:5px;display:grid}#tool-tabs button{color:#715b87;min-width:0;min-height:44px;box-shadow:none;background:0 0;border:1px solid #0000;border-radius:12px;justify-content:center;align-items:center;gap:6px;padding:8px 3px;font-size:14px;font-weight:400;display:flex}#tool-tabs button[aria-selected=true]{background:var(--cream);color:#573672;border-color:#d5c4e5;box-shadow:0 2px #ccb8dd}#tool-tabs button>span{font-size:20px;font-weight:400;line-height:1}.tool-panel{gap:20px;min-width:0;display:grid}#pattern-cards{grid-template-columns:repeat(3,minmax(0,1fr));gap:9px;display:grid}.pattern-card{background:#fffcf7;border:2px solid #e5d9ed;border-radius:16px;flex-direction:column;align-items:stretch;min-width:0;padding:7px 6px 10px;display:flex;box-shadow:0 3px #e3d7eb}.pattern-card[aria-pressed=true]{background:#eee1ff;border-color:#8057aa;animation:.22s ease-out selection-pop;box-shadow:0 3px #9875b7}.pattern-swatch{border:1px solid #b7a6bd;border-radius:9px;height:75px;margin-bottom:9px;display:block;position:relative;overflow:hidden}.swatch-gobang{background-color:#cab7df;background-image:repeating-linear-gradient(0deg,#0000 0 17px,#7d69825c 18px,#fffbf2bf 20px,#ac94b369 23px),repeating-linear-gradient(90deg,#0000 0 17px,#7d69825c 18px,#fffbf2bf 20px,#ac94b369 23px),linear-gradient(135deg,#b3abd3,#e6cbb5 50%,#bcbad6)}.swatch-color{background-color:#d3b1cd;background-image:conic-gradient(#d8b898 25%,#796880 0 50%,#ebd9c1 0 75%,#b39db9 0);background-size:37px 37px}.swatch-fine{background-color:#c8bfd6;background-image:repeating-linear-gradient(0deg,#0000 0 8px,#f8f0e6bf 9px,#927caa80 11px),repeating-linear-gradient(90deg,#0000 0 8px,#f8f0e6bf 9px,#927caa80 11px),linear-gradient(125deg,#c3b0da,#edd5bf)}.pattern-name{letter-spacing:-.3px;font-size:14px;font-weight:400}.pattern-detail{color:#6d587b;margin-top:3px;font-size:12px;line-height:1.4}.control-help{color:var(--muted);word-break:keep-all;margin:-8px 0 0;font-size:12px;line-height:1.7}.range-control{gap:4px;font-size:14px;font-weight:400;display:grid}.range-control>span:first-child{justify-content:space-between;align-items:center;gap:12px;display:flex}output{color:#744fa0;text-align:center;font-variant-numeric:tabular-nums;background:#eae0f5;border-radius:8px;min-width:38px;padding:3px 8px;font-size:13px;font-weight:400}input[type=range]{appearance:none;cursor:pointer;accent-color:#8660ad;background:0 0;width:100%;min-width:0;min-height:44px;margin:0}input[type=range]::-webkit-slider-runnable-track{background:#dac9eb;border-radius:8px;height:7px}input[type=range]::-webkit-slider-thumb{appearance:none;background:#8861b3;border:3px solid #fffbf2;border-radius:50%;width:23px;height:23px;margin-top:-8px;box-shadow:0 0 0 1px #9d7fb5,0 2px #b59bc9}input[type=range]::-moz-range-track{background:#dac9eb;border-radius:8px;height:7px}input[type=range]::-moz-range-thumb{background:#8861b3;border:3px solid #fffbf2;border-radius:50%;width:18px;height:18px;box-shadow:0 0 0 1px #9d7fb5}.range-ends{color:#7a6a87;justify-content:space-between;margin-top:-8px;font-size:12px;font-weight:400;display:flex}.inline-control{justify-content:space-between;align-items:center;gap:15px;font-size:14px;font-weight:400;display:flex}.inline-control select{width:120px}.core-optics{display:grid}.quiet-button,.tactile-button{min-height:44px;padding:11px 16px;font-size:14px;font-weight:400}.quiet-button{background:#fffbf2;box-shadow:0 2px #ddcfe7}.tactile-button{color:#593979;background:#e1cdfa;border:1px solid #aa88c6;box-shadow:0 3px #b69acb}.section-intro{text-align:center;padding:12px 0 4px}.section-intro h2{margin:8px 0;font-size:18px}.section-intro p{color:var(--muted);margin:0;font-size:14px;line-height:1.8}.intro-symbol{color:#9b6347;background:#f5e2d1;border-radius:20px;place-items:center;width:64px;height:64px;margin:0 auto 13px;font-size:36px;display:grid}.section-intro.compact{text-align:left;padding:0}.section-intro.compact h2{margin-top:0}details{border-top:1px solid #dfd2e8;margin-top:24px}summary{cursor:pointer;justify-content:space-between;align-items:center;gap:12px;min-height:52px;padding:8px 2px;font-size:14px;font-weight:400;list-style:none;display:flex}summary::-webkit-details-marker{display:none}summary>span{color:#8f70a8;font-size:21px;font-weight:400}details[open]>summary>span{transform:rotate(45deg)}.details-content{gap:14px;padding:8px 0 14px;display:grid}.details-content>label{gap:6px;font-size:14px;display:grid}.details-content input[type=number],select{background:#fffcf8;border:1px solid #cdbadb;border-radius:12px;width:100%;min-width:0;padding:10px 12px;font-size:14px}#test-photo{max-width:100%}.sample-strip{grid-template-columns:repeat(5,minmax(0,1fr));gap:5px;display:grid}.sample-strip img{aspect-ratio:1;object-fit:cover;border:2px solid #fff;border-radius:10px;width:100%;box-shadow:0 2px #d9c9e5}.local-note{text-align:center;color:var(--muted);margin:16px 0 0;font-size:12px;line-height:1.7}#developer-tools{margin-top:0}#developer-tools>summary{color:#79678b;font-size:13px;font-weight:400}#developer-tools .upload{text-align:center;background:#efe6f9;border:1px solid #cdbadb;min-height:44px;padding:10px 12px;font-size:14px;display:grid}#developer-tools details{margin-top:0}#developer-tools .control-note{color:#73637e;margin:0;font-size:12px;line-height:1.65}.reference-strip{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;min-width:0;display:grid}.reference-strip figure{background:#fffcf8;border:1px solid #d7c6e4;border-radius:12px;flex-direction:column;gap:5px;min-width:0;margin:0;padding:6px;display:flex}.reference-strip img{object-fit:contain;border-radius:7px;width:100%;height:120px;display:block}.reference-strip figcaption{text-align:center;color:#746180;font-size:12px}#reference-status{color:#9b3c38;grid-column:1/-1;margin:0;font-size:12px}#depth-inspection-canvas{cursor:crosshair;width:100%;height:auto;margin:10px 0}#depth-inspection pre,#depth-debug{white-space:pre-wrap;overflow-wrap:anywhere;color:#6b577b;max-width:100%;font-size:12px}.depth-coordinates{grid-template-columns:1fr 1fr;gap:8px;display:grid}.depth-coordinates label{gap:5px;font-size:13px;display:grid}.depth-coordinates input{width:100%;min-width:0}.app-footer{letter-spacing:.4px;color:#73607f;justify-content:space-between;gap:20px;padding:28px 48px 22px;font-size:12px;display:flex}.app-footer>span:last-child{font-style:italic}@keyframes selection-pop{0%{transform:scale(.96)}65%{transform:scale(1.035)}to{transform:scale(1)}}@media (hover:hover){button:not(:disabled):hover{filter:brightness(.98)}.pattern-card:hover{border-color:#aa88c6}.primary-upload:hover{background:#ffcca6}}@media (width>=1600px){.stage{height:740px}}@media (width<=1100px){.app-header{padding:24px 28px}main{grid-template-columns:minmax(0,1fr) 340px;gap:22px;padding:0 28px}aside{padding:21px 18px}.photo-mat{padding:16px 16px 0}.stage{height:clamp(410px,61vh,660px)}.processing-card{flex-direction:column;align-items:flex-start;gap:10px}.preview-heading .eyebrow{letter-spacing:1px}.preview-chip{display:none}}@media (width<=850px){.app-header{padding:24px 24px 22px}main{flex-direction:column;gap:18px;padding:0 24px;display:flex}.visual-column{width:100%;position:static}.photo-mat{padding:18px 18px 0}.stage{height:clamp(360px,60vh,610px)}aside{width:100%;padding:23px 24px}.editor-heading{margin-bottom:17px}.processing-card{flex-direction:row;align-items:center;padding:20px 4px 0}.pattern-swatch{height:88px}.tool-panel{gap:22px}.app-footer{padding:24px 28px}.preview-chip{display:inline-block}.header-note{display:none}}@media (width<=480px){.app-header{gap:12px;padding:21px 17px 19px}.brand{letter-spacing:-1px;gap:7px;font-size:24px}.brand-mark{font-size:35px}.brand-dot{font-size:31px}.primary-upload{border-radius:14px;min-height:44px;padding:9px 12px;font-size:13px}.primary-upload>span{font-size:20px}main{gap:17px;padding:0 12px}.photo-mat{border-radius:23px;padding:11px 11px 0}.preview-heading{gap:6px;margin:2px 2px 11px}.eyebrow{letter-spacing:1.2px;font-size:12px}.preview-chip{padding:5px 8px;font-size:12px}.stage{border-radius:13px;height:clamp(320px,49svh,455px)}.photo-caption{min-height:45px;padding:0 4px;font-size:12px}.caption-spark{font-size:22px}#hint{padding:8px 10px;font-size:12px;bottom:13px}#empty{gap:13px;padding:20px}#empty strong{font-size:19px}.empty-star{font-size:49px}.processing-card{flex-direction:column;align-items:flex-start;gap:9px;padding:19px 5px 0}#status{font-size:13px}#ai-depth{min-height:44px;padding:8px 12px;font-size:12px}aside{border-radius:24px;padding:21px 17px}.editor-heading h1{font-size:23px}.editor-sticker{border-radius:12px;width:40px;height:40px;font-size:26px}.editor-heading .eyebrow{font-size:12px}.pattern-swatch{height:76px}.pattern-detail{font-size:12px}.pattern-name{font-size:14px}#pattern-cards{gap:8px}.tool-panel{gap:20px}.app-footer{padding:22px 19px;font-size:12px}.app-footer>span:last-child{display:none}}@media (prefers-reduced-motion:reduce){*,:before,:after{scroll-behavior:auto!important;transition:none!important;animation:none!important}button:not(:disabled):active,.upload:active{transform:none}}html,body,#app{width:100%;min-height:100%}body{overflow:hidden}#app{max-width:none}#experience{width:100%;height:100dvh;min-height:320px;margin:0;padding:0;display:block;position:relative;overflow:hidden}#experience .stage{background:var(--room);border:0;border-radius:0;width:100%;height:100%;position:absolute;inset:0}#canvas-wrap,#canvas-wrap canvas{border-radius:0}#canvas-wrap{transition:opacity .65s}#experience:not([data-flow=ready]) #canvas-wrap{opacity:0;pointer-events:none}#experience:not([data-flow=ready]) #hint{visibility:hidden}.scene-toolbar{z-index:2;padding:max(18px,env(safe-area-inset-top)) max(22px,env(safe-area-inset-right)) 12px max(22px,env(safe-area-inset-left));pointer-events:none;justify-content:space-between;align-items:center;gap:16px;display:flex;position:absolute;top:0;left:0;right:0}.scene-toolbar>*{pointer-events:auto}.scene-brand{color:var(--ink);letter-spacing:-.5px;font-size:15px;font-weight:400;text-decoration:none}.scene-actions{align-items:center;gap:7px;display:flex}.scene-actions button,.scene-actions .upload{border:1px solid var(--line);background:var(--cream);min-height:44px;color:var(--ink);border-radius:6px;place-items:center;padding:8px 13px;font-size:14px;display:grid;box-shadow:0 1px 3px #35261510}#experience[data-flow=entry] .scene-brand,#experience:not([data-flow=ready]) .scene-actions>.upload{visibility:hidden}.welcome,.flow-overlay{background:var(--room);text-align:center;flex-direction:column;justify-content:center;align-items:center;padding:70px 24px 36px;display:flex;position:absolute;inset:0;overflow:auto}.welcome h1{letter-spacing:0;margin:8px 0 15px;font-family:inherit;font-size:clamp(30px,4.5vw,48px);font-weight:400;line-height:1.35}.entry-kicker{color:var(--muted);letter-spacing:.8px;margin:19px 0 0;font-size:13px}.welcome .primary-upload{color:#fffaf0;background:#6e4932;border:1px solid #63422d;border-radius:5px;min-width:208px;margin:0;padding:12px 23px;font-size:15px;box-shadow:0 2px 3px #4223111c}.entry-samples{min-height:44px;color:var(--muted);text-underline-offset:4px;background:0 0;border:0;border-radius:0;margin:10px 0 0;padding:8px 14px;font-size:13px;text-decoration:underline}.entry-privacy{color:var(--muted);margin:27px 0 0;font-size:12px}.entry-door{border:3px solid #79583e;border-bottom-width:7px;border-radius:2px;width:39px;height:59px;padding:3px;position:relative}.entry-door:before{content:"";background:#a38851;border:1px solid #735d35;width:4px;height:8px;position:absolute;bottom:15px;right:-3px}.entry-door>span{opacity:.6;background:#b8c0b3;border:1px solid #8b967f;width:100%;height:37px;display:block}.flow-overlay{z-index:1}.flow-photo{object-fit:contain;border:6px solid var(--cream);width:auto;max-width:min(43vw,190px);height:auto;max-height:27svh;margin-bottom:30px;display:block;box-shadow:0 2px 8px #49341d1f}.flow-overlay h2{letter-spacing:-.6px;word-break:keep-all;max-width:500px;margin:0;font-size:clamp(20px,3vw,27px);font-weight:400;line-height:1.6}#flow-detail{max-width:470px;color:var(--muted);overflow-wrap:anywhere;margin:13px 0 23px;font-size:14px;line-height:1.8}.flow-actions{flex-wrap:wrap;justify-content:center;align-items:center;gap:10px;max-width:450px;display:flex}.flow-actions button,.flow-actions .upload{border:1px solid var(--line);background:var(--cream);border-radius:5px;min-height:44px;padding:10px 15px;font-size:14px}#flow-flat{background:0 0}#hint{bottom:max(25px,env(safe-area-inset-bottom));border:1px solid var(--line);background:var(--cream);max-width:calc(100% - 40px);color:var(--ink);border-radius:4px;padding:11px 18px;font-size:14px;line-height:1.65;box-shadow:0 2px 10px #382a1410}#hint strong{font-size:15px;font-weight:400;display:block}#hint .hint-secondary{color:var(--muted);font-size:12px;display:block}#settings-dialog{border:0;border-left:1px solid var(--line);background:var(--cream);width:min(410px,100%);max-width:100%;height:100dvh;max-height:100dvh;color:var(--ink);overscroll-behavior:contain;border-radius:0;margin:0 0 0 auto;padding:0}#settings-dialog::backdrop{background:#201a1366}#settings-dialog aside{width:100%;min-height:100%;padding:25px 24px max(24px,env(safe-area-inset-bottom));box-shadow:none;border:0;border-radius:0}#settings-dialog .editor-heading{margin-bottom:17px;padding:0}.editor-heading h2{letter-spacing:-.5px;margin:0;font-size:20px}#settings-close{background:0 0;border-radius:5px;padding:7px 12px;font-size:13px}.theme-setting{grid-template-columns:auto minmax(0,1fr);align-items:center;gap:20px;padding-bottom:22px;font-size:14px;display:grid}.theme-setting select{width:100%}#settings-dialog .processing-card{border-top:1px solid var(--line);flex-direction:column;align-items:stretch;margin-top:20px;padding-top:20px}#settings-dialog .processing-card button{width:100%}:root{--room:#f1ebff}:root[data-theme=wood]{color:#3e3429;--room:#e6dfcf;--ink:#3e3429;--muted:#726554;--cream:#f8f4e9;--purple:#705039;--lavender:#e8dfcf;--apricot:#e0d1b5;--line:#cfc3ad;--shadow:#b1a084;background:#e6dfcf}[data-theme=wood] button,[data-theme=wood] select,[data-theme=wood] .upload{border-radius:5px}[data-theme=wood] button:not(:disabled):active,[data-theme=wood] .upload:active{box-shadow:none;transform:translateY(1px)}[data-theme=wood] button:focus-visible,[data-theme=wood] select:focus-visible,[data-theme=wood] input:focus-visible,[data-theme=wood] summary:focus-visible,[data-theme=wood] a:focus-visible,[data-theme=wood] #canvas-wrap:focus-visible,[data-theme=wood] .upload:focus-within{outline-color:#765534}[data-theme=wood] aside{background:#f8f4e9}[data-theme=wood] #tool-tabs{background:0 0;border:0;border-bottom:1px solid #cfc3ad;border-radius:0;gap:0;padding:0}[data-theme=wood] #tool-tabs button{color:#756651;border-radius:0}[data-theme=wood] #tool-tabs button[aria-selected=true]{box-shadow:none;color:#3e3429;background:0 0;border:0;border-bottom:2px solid #785735}[data-theme=wood] .pattern-card{box-shadow:none;background:#faf7ed;border:1px solid #cfc3ad;border-radius:4px;padding:5px 5px 9px}[data-theme=wood] .pattern-card[aria-pressed=true]{background:#e9dfca;border:1px solid #725334;animation:none;box-shadow:inset 0 0 0 1px #725334}[data-theme=wood] .pattern-swatch{filter:saturate(.35)sepia(.12);border-color:#a99b84;border-radius:1px}[data-theme=wood] .pattern-detail{color:#6c5d47}[data-theme=wood] output{color:#614831;background:#e9e0ce;border-radius:3px}[data-theme=wood] input[type=range]{accent-color:#84633f}[data-theme=wood] input[type=range]::-webkit-slider-runnable-track{background:#d1c5ae;height:4px}[data-theme=wood] input[type=range]::-webkit-slider-thumb{background:#856344;width:20px;height:20px;margin-top:-8px;box-shadow:0 0 0 1px #a28967}[data-theme=wood] input[type=range]::-moz-range-track{background:#d1c5ae;height:4px}[data-theme=wood] input[type=range]::-moz-range-thumb{background:#856344;width:16px;height:16px;box-shadow:0 0 0 1px #a28967}[data-theme=wood] .range-ends,[data-theme=wood] #developer-tools>summary,[data-theme=wood] #developer-tools .control-note,[data-theme=wood] #depth-inspection pre,[data-theme=wood] #depth-debug,[data-theme=wood] .reference-strip figcaption{color:#726554}[data-theme=wood] .quiet-button,[data-theme=wood] .tactile-button{box-shadow:none;color:#584630;background:#ede4d2;border-color:#baa98d}[data-theme=wood] .intro-symbol{color:#816440;background:#e9dfcc;border-radius:4px}[data-theme=wood] details{border-color:#d6cbb9}[data-theme=wood] summary>span{color:#8b7657}[data-theme=wood] .details-content input[type=number],[data-theme=wood] select{background:#fffdf6;border-color:#cfc3ad}[data-theme=wood] .sample-strip img{box-shadow:none;border-radius:3px}[data-theme=wood] #developer-tools .upload{background:#e9e0ce;border-color:#cfc3ad}[data-theme=wood] .reference-strip figure{background:#fffdf6;border-color:#cfc3ad;border-radius:3px}[data-theme=booth] .welcome .primary-upload{background:var(--apricot);color:#593c31;border-color:#a76948;border-radius:16px;box-shadow:0 4px #cc9b7b}[data-theme=booth] .welcome h1{font-family:inherit;font-weight:400}[data-theme=booth] .entry-door{border-color:#967ab1}[data-theme=booth] .scene-actions button,[data-theme=booth] .scene-actions .upload,[data-theme=booth] #hint{border-radius:18px}@media (width<=480px){.scene-toolbar{padding:14px 14px 8px}.scene-brand{font-size:13px}.scene-actions{gap:5px}.scene-actions button,.scene-actions .upload{padding:7px 10px;font-size:14px}#settings-dialog{border-top:1px solid var(--line);border-radius:12px 12px 0 0;width:100%;height:90dvh;max-height:90dvh;margin:auto 0 0}#settings-dialog aside{padding:21px 20px max(28px,env(safe-area-inset-bottom))}.welcome{padding-top:64px}#hint{bottom:max(18px,env(safe-area-inset-bottom));padding:9px 13px;font-size:12px}#hint strong{font-size:14px}}@media (height<=590px){.welcome{justify-content:flex-start}.entry-door{display:none}.welcome h1{font-size:27px;line-height:1.35}.entry-privacy{margin-top:14px}.flow-photo{max-height:20svh;margin-bottom:16px}}@media (prefers-reduced-motion:reduce){#canvas-wrap{transition:none}}@media (height<=590px){#hint{padding:8px 12px;font-size:12px;bottom:12px}#hint strong,#hint .hint-secondary{display:none}}#gyro-notice{bottom:max(20px,env(safe-area-inset-bottom));width:max-content;max-width:calc(100% - 40px);color:var(--ink);background:var(--cream);border:1px solid var(--line);text-align:center;pointer-events:none;z-index:5;border-radius:14px;margin:0;padding:10px 14px;font-size:14px;line-height:1.6;position:absolute;left:50%;transform:translate(-50%)}#experience:not([data-flow=ready]) #gyro-notice{display:none}#render-recovery{border:1px solid var(--line);background:var(--cream);width:min(420px,100% - 36px);color:var(--ink);text-align:center;border-radius:12px;padding:28px}#render-recovery::backdrop{background:var(--room)}#render-recovery h2{font-size:24px;font-weight:400;line-height:1.4}#render-recovery p{font-size:15px}#render-reload{border-color:var(--line);padding:10px 24px}.journey{--journey-height:clamp(144px,30dvh,236px);--journey-car-width:58%;width:min(460px,88vw);height:var(--journey-height);flex:none;margin:0 0 24px;position:relative;overflow:hidden}.journey-scenery{position:absolute;inset:0;overflow:hidden}.journey-sun{opacity:.65;background:#dfbb73;border-radius:50%;width:34px;height:34px;position:absolute;top:9%;right:15%}.journey-cloud{background:var(--cream);border-radius:50%;width:65px;height:13px;position:absolute;top:21%;left:16%}.journey-cloud:before{content:"";background:inherit;border-radius:50%;width:30px;height:24px;position:absolute;bottom:0;left:17px}.journey-hill{opacity:.45;background:#b6bc9c;border-radius:50% 50% 0 0;width:95%;height:45%;position:absolute;bottom:26px;left:-8%}.journey-tree{background:#9b8563;width:9px;height:55px;position:absolute;bottom:29px;right:18%}.journey-tree:before{content:"";background:#9ca883;border-radius:50% 50% 42% 42%;width:43px;height:54px;position:absolute;top:-22px;left:-17px}.journey-road{background:repeating-linear-gradient(90deg,#0000 0 22px,#bcb099 22px 44px,#0000 44px 66px) 0 12px/132px 2px repeat-x;border-top:2px solid #ada289;height:20px;position:absolute;bottom:11px;left:0;right:0}.journey-car,.journey-traveler{width:min(var(--journey-car-width),calc((var(--journey-height) - 38px) * 5 / 3));aspect-ratio:5/3;transform-origin:50% 85%;max-width:267px;position:absolute;bottom:24px;left:16%}.journey-traveler{z-index:3;pointer-events:none}.journey-car-body{z-index:2;width:100%;height:100%;position:absolute;inset:0;overflow:visible}.journey-passenger{z-index:3;background:#fcf5df;border:5px solid #fcf5df;border-radius:9px;width:34%;height:65%;position:absolute;top:0;left:22%;transform:rotate(-5deg);box-shadow:0 2px 3px #50392226}.journey-passenger .flow-photo{object-fit:contain;width:100%;max-width:none;height:100%;max-height:none;box-shadow:none;border:0;border-radius:4px;margin:0;display:block}.journey-house{opacity:0;width:27%;max-height:88%;position:absolute;bottom:26px;right:3%;transform:translate(20px)}.journey-wheel{transform-box:fill-box;transform-origin:50%}#flow-overlay[data-journey=driving] :is(.journey-car,.journey-traveler){animation:1.7s ease-in-out infinite journey-ride}#flow-overlay[data-journey=driving] .journey-wheel{animation:1.4s linear infinite journey-wheel-turn}#flow-overlay[data-journey=driving] .journey-road{animation:2.8s linear infinite journey-road-pass}#flow-overlay[data-journey=driving] .journey-tree{animation:8s linear infinite journey-tree-pass}#journey-motion{color:var(--muted);text-underline-offset:3px;background:0 0;border-color:#0000;text-decoration:underline}#flow-overlay[data-journey=unpacking]{animation:.2s ease-in 1.3s both journey-arrival-fade}#flow-overlay:is([data-journey=arrived],[data-journey=unpacking]) :is(.journey-car,.journey-traveler){transition:transform .35s ease-out;transform:translate(-10%)}#flow-overlay:is([data-journey=arrived],[data-journey=unpacking]) .journey-house{opacity:1;transition:opacity .25s ease-out,transform .35s ease-out;transform:none}#flow-overlay:is([data-journey=arrived],[data-journey=unpacking]) .journey-tree{opacity:0}#flow-overlay[data-journey=unpacking] .journey-traveler{transition:none;animation:1.3s linear both journey-walk}#flow-overlay[data-journey=unpacking] .journey-passenger{transform-origin:50% 100%;animation:1.3s ease-in-out both journey-waddle}#flow-overlay[data-motion=paused] .journey *{animation-play-state:paused}[data-theme=booth] .journey-hill{background:#c3afd9}[data-theme=booth] .journey-tree:before{background:#baa6c7}@keyframes journey-ride{0%,to{transform:translateY(0)rotate(-.3deg)}50%{transform:translateY(-2px)rotate(.3deg)}}@keyframes journey-wheel-turn{to{transform:rotate(360deg)}}@keyframes journey-road-pass{to{background-position:-132px 12px}}@keyframes journey-tree-pass{0%{transform:translate(180px)}to{transform:translate(-460px)}}@keyframes journey-walk{0%,28%{left:16%;transform:translate(-10%)}to{left:87.5%;transform:translate(-39%)}}@keyframes journey-waddle{0%{animation-timing-function:ease-out;top:0;transform:translateY(0)rotate(-5deg)scaleY(1)}8%{animation-timing-function:cubic-bezier(.4,0,.65,1);top:0;transform:translateY(-6px)rotate(-5deg)scaleY(1)}24%{animation-timing-function:ease-out;top:35%;transform:translateY(0)rotate(-5deg)scaleY(.97)}28%{top:35%;transform:translateY(0)rotate(-5deg)scaleY(1)}40%{top:35%;transform:translateY(-3px)rotate(5deg)}52%{top:35%;transform:translateY(0)rotate(-5deg)}64%{top:35%;transform:translateY(-3px)rotate(5deg)}76%{top:35%;transform:translateY(0)rotate(-5deg)}88%{top:35%;transform:translateY(-3px)rotate(5deg)}to{top:35%;transform:translateY(0)rotate(0)}}@keyframes journey-arrival-fade{0%{opacity:1}to{opacity:0}}@media (height<=650px){.flow-overlay{padding:52px 18px 18px}.journey{--journey-height:clamp(100px,27dvh,160px);--journey-car-width:54%;width:min(380px,80vw);margin-bottom:12px}.flow-overlay h2{font-size:20px;line-height:1.4}#flow-detail{margin:9px 0 14px;font-size:13px;line-height:1.55}}@media (height<=430px) and (width>=560px){.flow-overlay{grid-template-columns:minmax(170px,40%) minmax(0,1fr);align-content:center;justify-items:center;column-gap:24px;padding:52px 30px 18px;display:grid}.journey{--journey-height:170px;grid-row:1/4;width:100%;margin:0}.flow-overlay h2,#flow-detail,.flow-actions{grid-column:2}}@media (prefers-reduced-motion:reduce){.journey *{transition:none!important;animation:none!important}#flow-overlay[data-journey=unpacking]{animation:none}}.comparison-control{border:1px solid var(--line);border-radius:12px;padding:14px}.comparison-control h3{margin:0 0 8px;font-size:17px;font-weight:400}.comparison-control button{width:100%;padding:10px}.comparison-control details{margin-top:10px}#comparison-overlay{z-index:1;pointer-events:none;position:absolute;inset:0}.comparison-label{text-align:center;color:var(--ink);font-size:14px;line-height:1.3;position:absolute;transform:translate(-50%)}#comparison-metrics{bottom:max(10px,env(safe-area-inset-bottom));text-align:center;font-family:var(--font-values);color:var(--ink);font-size:12px;line-height:1.45;position:absolute;left:10px;right:10px}#comparison-metrics p{white-space:pre-line;margin:3px 0}#experience:not([data-flow=ready]) #comparison-overlay,#experience[data-comparison] #hint{visibility:hidden}#experience[data-comparison] .scene-brand{display:none}#experience[data-comparison] .scene-toolbar{justify-content:flex-end}@media (width<=480px){#experience[data-comparison] .scene-actions{flex-wrap:wrap;justify-content:flex-end}#comparison-metrics{font-size:12px}}@media (height<=500px){#comparison-memory{display:none}#comparison-metrics{line-height:1.25}}#mesh-render-error{border:1px solid var(--line);border-radius:1rem;max-width:28rem;padding:1.5rem}#mesh-render-error::backdrop{background:#21172aaa}#mesh-render-error button{margin:.5rem .5rem 0 0}.frame-notice{color:#402c21;pointer-events:none;z-index:4;background:#fff9e9ee;border-radius:.75rem;max-width:32rem;padding:.65rem 1rem;font-size:.875rem;position:absolute;bottom:1rem;left:1rem;right:1rem}#door-handle{pointer-events:none;color:#fff8df;text-shadow:0 1px 3px #32200f;z-index:1;background:#3e2c151c;border:1px solid #fff8dc66;border-radius:50%;place-items:center;width:44px;height:44px;font-family:system-ui,sans-serif;font-size:22px;display:grid;position:absolute;transform:translate(-50%,-50%)}#door-handle[hidden],#door-controls[hidden]{display:none}#door-controls{left:max(16px,env(safe-area-inset-left));bottom:max(88px,env(safe-area-inset-bottom));z-index:2;flex-direction:column;align-items:flex-start;gap:6px;display:flex;position:absolute}#door-toggle{border:1px solid var(--line);background:var(--cream);min-width:88px;min-height:44px;color:var(--ink);border-radius:6px;padding:8px 13px}#door-help{color:var(--ink);background:var(--cream);border-radius:4px;padding:3px 7px;font-size:12px}#door-toggle:focus-visible{outline-offset:3px;outline:3px solid #996130}.scene-motion{top:calc(76px + env(safe-area-inset-top));right:max(16px,env(safe-area-inset-right));z-index:4;align-items:flex-start;gap:8px;display:flex;position:absolute}.scene-motion[hidden]{display:none}.scene-motion>button,#motion-tools>summary,#door-toggle{color:#fffdf6;min-height:44px;box-shadow:none;text-shadow:0 1px 3px #211910,0 0 7px #211910;background:0 0;border:0;border-radius:4px;padding:8px 10px;font-size:14px}.scene-motion>button{align-items:center;gap:6px;display:flex}.scene-motion>button[aria-pressed=true]{text-underline-offset:5px;text-decoration:underline}#motion-tools{background:0 0;border:0;margin:0;position:relative}#motion-tools>summary{cursor:pointer;align-items:center;list-style:none;display:flex}#motion-tools>summary::-webkit-details-marker{display:none}#motion-tools>summary:after{content:"+";margin-left:6px}#motion-tools[open]>summary:after{content:"−"}#motion-tools .motion-panel{color:#fffdf6;background:#302b25f5;border:1px solid #fff5;border-radius:10px;width:min(290px,100vw - 32px);max-height:calc(100dvh - 165px);padding:16px;position:absolute;top:100%;right:0;overflow:auto;box-shadow:0 6px 24px #0003}.motion-panel .control-help,.motion-panel .range-ends{color:#ede6dc}.motion-panel .control-help{font-size:14px}.motion-panel button{color:#fffdf6;min-height:44px;box-shadow:none;background:0 0;border:1px solid #fff5;margin:4px 0}.scene-motion button:focus-visible,#motion-tools>summary:focus-visible,#door-toggle:focus-visible{outline-offset:2px;outline:2px solid #fffdf6;box-shadow:0 0 0 5px #302b25}#door-controls{left:max(16px,env(safe-area-inset-left));bottom:calc(56px + env(safe-area-inset-bottom))}#door-toggle{text-underline-offset:5px;min-width:88px;text-decoration:underline}#hint,[data-theme=booth] #hint{bottom:calc(20px + env(safe-area-inset-bottom));max-width:calc(100% - 24px);box-shadow:none;color:#fffdf6;white-space:nowrap;text-shadow:0 1px 3px #211910,0 0 8px #211910,0 0 14px #211910;opacity:0;z-index:2;background:0 0;border:0;border-radius:0;padding:0;font-size:14px;line-height:1.5;transition:none}#hint[data-phase=in]{animation:.6s ease-out both scene-hint-in}#hint[data-phase=hold]{opacity:1}#hint[data-phase=out]{animation:.8s ease-in both scene-hint-out}@keyframes scene-hint-in{0%{opacity:0}to{opacity:1}}@keyframes scene-hint-out{0%{opacity:1}to{opacity:0}}#gyro-notice{top:calc(125px + env(safe-area-inset-top));font-size:14px;bottom:auto}@media (width<=480px){.scene-motion{top:calc(67px + env(safe-area-inset-top));gap:2px;right:10px}}@media (prefers-reduced-motion:reduce){#hint[data-phase]{animation:none}#hint[data-phase=in],#hint[data-phase=hold]{opacity:1}}#hint{white-space:normal;text-wrap:balance}.photo-tip{color:var(--ink);margin:-12px 0 18px;font-size:14px;line-height:1.7}#sample-dialog{border:1px solid var(--line);background:var(--cream);width:min(520px,100% - 28px);max-height:calc(100dvh - 28px);color:var(--ink);overscroll-behavior:contain;border-radius:12px;padding:20px;overflow:auto}#sample-dialog::backdrop{background:#201a1366}.sample-heading{justify-content:space-between;align-items:center;gap:12px;display:flex}.sample-heading h2{margin:0;font-size:21px;line-height:1.4}#sample-close{border-radius:5px;flex:none;padding:6px 12px}#sample-description{color:var(--muted);margin:10px 0 18px;font-size:13px}.sample-choices{grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;display:grid}.sample-choices button{border:2px solid var(--line);text-align:left;background:var(--cream);border-radius:7px;flex-direction:column;align-items:stretch;min-width:0;padding:6px;display:flex}.sample-choices button[aria-pressed=true]{background:#e9dec6;border-color:#79583e;box-shadow:0 0 0 1px #79583e}.sample-choices img{object-fit:contain;background:#e6dfcf;border-radius:3px;width:100%;height:120px}.sample-choices span{margin-top:6px;font-size:12px;line-height:1.5}.sample-choices small{color:#67492f;font-size:11px}.sample-footer{background:var(--cream);padding:16px 0 4px;position:sticky;bottom:-20px}#sample-confirm{color:#fffaf0;background:#6e4932;border-radius:5px;width:100%;min-height:48px}@media (width<=420px){.sample-choices{grid-template-columns:repeat(2,minmax(0,1fr))}.sample-choices img{height:110px}}.pet-name-field{text-align:left;flex-direction:column;gap:7px;display:flex}.pet-name-field label{margin:0;font-size:15px;display:block}.pet-name-field input{width:100%;min-width:0;min-height:44px;color:var(--ink);font:inherit;background:#fffaf080;border:1px solid #a89170;border-radius:5px;padding:10px 12px;font-size:17px}.pet-name-field input::placeholder{color:#817565;opacity:1}.pet-name-field small{color:var(--muted);font-size:11px;line-height:1.5}.pet-name-field .name-storage-notice{color:#77472d}.entry-name-field{flex-shrink:0;width:min(100%,280px);margin:0 0 18px}.settings-name-field{margin:0 0 22px}#welcome-name,#entry-photo-button,#flow-title{overflow-wrap:anywhere}#entry-photo-button{max-width:100%}#internal-controls[hidden]{display:none!important}.arrival-count{color:var(--muted);margin:8px 0 0;font-size:12px;line-height:1.6}#settings-dialog .arrival-count{margin:0 0 18px}.welcome{justify-content:flex-start}.welcome>*{flex-shrink:0;max-width:100%}.welcome .entry-door{margin-top:auto}#entry-photo-step{margin-bottom:0}.entry-step{flex-direction:column;flex-shrink:0;align-items:center;gap:12px;width:min(100%,360px);display:flex}.entry-step>*{flex-shrink:0;max-width:100%}.entry-step .entry-name-field{width:100%;margin:0}.entry-step .photo-tip{margin:0}.entry-step .primary-upload{min-height:48px}.entry-step .entry-samples{margin:0}#entry-name-edit{align-self:center;min-height:44px;margin:0 0 16px;font-size:14px}#paste-tip span{white-space:nowrap}.welcome[data-step=name] #entry-name-step{margin-bottom:auto}.scene-actions{flex-wrap:wrap;justify-content:flex-end}#entry-notices{width:min(100%,360px);color:var(--muted);touch-action:pan-y pinch-zoom;flex-shrink:0;grid-template-columns:44px minmax(0,1fr) 44px;align-items:center;margin:8px 0 auto;display:grid}#entry-notices>button{min-width:44px;min-height:44px;box-shadow:none;color:var(--ink);background:0 0;border:0;padding:0;font-family:system-ui,sans-serif;font-size:24px}.notice-slides{align-items:center;min-width:0;display:grid}#entry-notices .entry-notice-slide{overflow-wrap:anywhere;word-break:keep-all;visibility:hidden;grid-area:1/1;margin:0;padding:0;font-size:13px;line-height:1.65}#entry-notices .entry-notice-slide[data-active=true]{visibility:visible}#entry-notices .entry-notice-slide[hidden]{display:none}#notice-position{opacity:.75;grid-column:2;font-family:inherit;font-size:10px;line-height:1.4}#entry-notices[hidden]{display:none}@media (width<=640px){.welcome[data-step=photo]{padding-bottom:max(16px,env(safe-area-inset-bottom))}.welcome[data-step=photo] #entry-photo-step{margin-bottom:24px}.welcome[data-step=photo] #entry-notices{margin-top:auto;margin-bottom:0}}.scene-toolbar{grid-template-columns:auto minmax(0,1fr);align-items:start;gap:6px 12px;display:grid}.scene-brand{white-space:nowrap;padding-top:10px}.scene-actions{grid-column:2;min-width:0}.scene-motion{flex-direction:column;grid-column:1/-1;justify-self:end;align-items:flex-end;gap:6px;max-width:100%;display:flex;position:static}#gyro,#gyro[aria-pressed=true],#gyro[aria-busy=true]{color:#fffdf6;min-height:44px;box-shadow:none;text-shadow:0 1px 3px #211910,0 0 7px #211910;text-underline-offset:5px;background:0 0;border:0;border-radius:4px;padding:8px 10px;text-decoration:underline}#scene-motion[hidden]{display:none}#gyro-notice{width:auto;max-width:min(290px,100%);color:var(--ink);background:var(--cream);text-shadow:none;margin:0;padding:8px 12px;font-size:13px;position:static;inset:auto;transform:none}#panel-view{color:var(--ink);gap:16px}#panel-view select{color:var(--ink);background:var(--cream)}#panel-view .control-help{margin:0}#panel-view button{min-height:44px}#tool-tabs{grid-template-columns:repeat(3,minmax(0,1fr))}#gyro:focus-visible{outline-offset:2px;outline:2px solid #fffdf6;box-shadow:0 0 0 5px #302b25}#credits-dialog{border:1px solid var(--line);background:var(--cream);width:min(400px,100% - 32px);max-height:calc(100dvh - 32px);color:var(--ink);border-radius:12px;padding:24px;overflow:auto}#credits-dialog::backdrop{background:#201a1366}.credits-heading{justify-content:space-between;align-items:center;gap:12px;display:flex}.credits-heading h2{margin:0;font-size:22px}#credits-close{min-height:44px;padding:6px 12px}.credits-info{gap:6px;margin:20px 0;display:grid}.credits-info dt{color:var(--muted);font-size:13px}.credits-info dd{overflow-wrap:anywhere;margin:0 0 10px}#credits-dialog a{color:var(--ink);text-underline-offset:4px}.credits-licenses{padding:8px 0;font-size:13px;display:inline-block}#experience[data-flow=entry] #scene-zoom-reset,#experience[data-flow=entry] #comparison-exit{display:none}#export-dialog{border:1px solid var(--line);background:var(--cream);width:min(560px,100% - 24px);max-height:calc(100dvh - 24px);color:var(--ink);border-radius:12px;padding:20px;overflow:auto}#export-dialog::backdrop{background:#201a1380}.export-heading{justify-content:space-between;align-items:center;gap:12px;display:flex}.export-heading h2{margin:0;font-size:22px}#export-dialog button,.export-actions a{min-height:44px;padding:9px 12px}.export-choices,.export-actions{flex-wrap:wrap;gap:8px;margin-top:16px;display:flex}#export-status{font-size:14px;line-height:1.6}#export-preview{object-fit:contain;border:1px solid var(--line);background-color:#fff;background-image:linear-gradient(45deg,#ddd 25%,#0000 25%),linear-gradient(-45deg,#ddd 25%,#0000 25%),linear-gradient(45deg,#0000 75%,#ddd 75%),linear-gradient(-45deg,#0000 75%,#ddd 75%);background-position:0 0,0 8px,8px -8px,-8px 0;background-size:16px 16px;width:100%;max-height:50dvh;display:block}#export-preview[hidden]{display:none}.export-actions a{color:var(--cream);background:var(--ink);border-radius:6px;align-items:center;display:inline-flex}.export-actions a[hidden]{display:none}#gyro-recenter{right:max(16px,env(safe-area-inset-right));bottom:calc(56px + env(safe-area-inset-bottom));z-index:3;color:#fffdf6;min-height:44px;box-shadow:none;text-shadow:0 1px 3px #211910,0 0 7px #211910;text-underline-offset:5px;background:0 0;border:0;border-radius:4px;padding:8px 10px;text-decoration:underline;position:absolute}#gyro-recenter:focus-visible{outline-offset:2px;outline:2px solid #fffdf6;box-shadow:0 0 0 5px #302b25}#first-guide{display:none}#guide-scene-target{pointer-events:none;width:52%;height:27%;position:absolute;top:28%;left:24%}.behind-glass-tour{font-family:var(--font-ui);color:var(--ink);background:var(--cream);border:1px solid var(--line);border-radius:10px;width:min(340px,100vw - 32px);min-width:0;max-width:calc(100vw - 32px);padding:18px;font-weight:400;overflow:visible;box-shadow:0 4px 20px #201a1326}.behind-glass-tour .driver-popover-title{font-family:inherit;font-size:21px;font-weight:400;line-height:1.5}.behind-glass-tour .driver-popover-description{font-family:inherit;font-size:15px;line-height:1.8}.behind-glass-tour .driver-popover-footer button{min-height:44px;font:inherit;text-shadow:none;border:1px solid var(--line);border-radius:5px;padding:8px 14px;font-size:14px}.behind-glass-tour .driver-popover-next-btn{background:var(--ink);color:var(--cream)}.behind-glass-tour .driver-popover-prev-btn{color:var(--ink);background:0 0}.behind-glass-tour .driver-popover-close-btn{width:auto;height:auto;min-height:44px;font:inherit;color:var(--muted);box-shadow:none;background:0 0;border:0;margin:0 0 8px auto;padding:4px 8px;font-size:13px;display:block;position:static}.behind-glass-tour .driver-popover-progress-text{font:inherit;color:var(--muted);font-size:12px}.behind-glass-tour .driver-popover-arrow-side-top{border-top-color:var(--cream)}.behind-glass-tour .driver-popover-arrow-side-bottom{border-bottom-color:var(--cream)}.behind-glass-tour button:focus-visible{outline:2px solid var(--ink);outline-offset:3px}.behind-glass-tour .guide-popover-content{max-height:max(80px,calc(100dvh - 68px - env(safe-area-inset-top) - env(safe-area-inset-bottom)));overflow:auto}.behind-glass-tour .driver-popover-arrow-side-left{border-left-color:var(--cream)}.behind-glass-tour .driver-popover-arrow-side-right{border-right-color:var(--cream)}.scene-toolbar{grid-template-columns:minmax(0,1fr) auto;align-items:start}.scene-brand{display:none}#scene-menu-open{color:#fffdf6;min-width:44px;min-height:44px;box-shadow:none;text-shadow:0 1px 3px #211910,0 0 7px #211910;text-underline-offset:5px;background:0 0;border:0;border-radius:4px;grid-area:1/1;justify-self:start;padding:8px 10px;font-size:14px;text-decoration:underline}#scene-menu-open:focus-visible{outline-offset:2px;outline:2px solid #fffdf6;box-shadow:0 0 0 5px #302b25}.scene-toolbar .scene-motion{grid-area:1/2;min-width:0;max-width:min(65vw,290px)}.scene-toolbar .scene-actions{grid-area:1/2}#experience:not([data-flow=entry]) .scene-actions{display:none}#scene-menu{width:min(440px,100%);max-width:100%;max-height:calc(100dvh - max(24px,env(safe-area-inset-top)));padding:20px max(20px,env(safe-area-inset-right)) max(20px,env(safe-area-inset-bottom)) max(20px,env(safe-area-inset-left));border:1px solid var(--line);background:var(--cream);color:var(--ink);overscroll-behavior:contain;border-bottom:0;border-radius:18px 18px 0 0;margin:auto auto 0;overflow:auto}#scene-menu::backdrop{background:#201a1380}.scene-menu-heading{justify-content:space-between;align-items:center;gap:16px;margin-bottom:8px;display:flex}.scene-menu-heading h2{margin:0;font-size:22px}#scene-menu-close{min-width:44px;min-height:44px;color:var(--muted);box-shadow:none;background:0 0;border:0;padding:8px}.scene-menu-items{flex-direction:column;display:flex}.scene-menu-items>button{text-align:left;border:0;border-bottom:1px solid var(--line);width:100%;min-height:52px;color:var(--ink);box-shadow:none;background:0 0;border-radius:0;padding:12px 4px;font-family:inherit;font-size:16px}.scene-menu-items>button:last-child{border-bottom:0}.scene-menu-items>button:disabled{opacity:.45}#scene-menu button:focus-visible{outline:2px solid var(--ink);outline-offset:-2px}#scene-menu-open[hidden],.scene-menu-items>button[hidden]{display:none}.scene-toolbar{grid-template-columns:minmax(0,1fr) 44px minmax(0,1fr);column-gap:6px}.scene-toolbar .scene-motion,.scene-toolbar .scene-actions{grid-column:3}#sample-home{color:#fffdf6;width:44px;min-height:44px;box-shadow:none;background:0 0;border:0;border-radius:4px;grid-area:1/2;place-items:center;padding:8px;display:grid}#sample-home svg{filter:drop-shadow(0 1px 2px #211910)}#sample-home:focus-visible,#photo-adjust-open:focus-visible{outline-offset:2px;outline:2px solid #fffdf6;box-shadow:0 0 0 5px #302b25}#sample-home[hidden]{display:none}#gyro{white-space:nowrap;padding-inline:4px}#photo-adjust-open{left:50%;bottom:max(12px,env(safe-area-inset-bottom));z-index:3;color:#fffdf6;min-height:44px;box-shadow:none;text-shadow:0 1px 3px #211910,0 0 7px #211910;text-underline-offset:5px;white-space:nowrap;background:0 0;border:0;border-radius:4px;padding:8px 12px;font-size:14px;text-decoration:underline;position:absolute;transform:translate(-50%)}#photo-adjust-panel{z-index:4;left:50%;bottom:max(12px,env(safe-area-inset-bottom));border:1px solid var(--line);width:min(400px,100% - 24px);max-height:45dvh;color:var(--ink);background:var(--cream);border-radius:12px;padding:12px 16px;position:absolute;overflow:auto;transform:translate(-50%);box-shadow:0 3px 16px #201a1326}.photo-adjust-heading{justify-content:space-between;align-items:center;gap:12px;display:flex}.photo-adjust-heading strong{font-size:17px;font-weight:400}#photo-adjust-panel button{min-height:44px;padding:8px 12px}#photo-adjust-done{color:var(--cream);background:var(--ink)}#photo-adjust-panel label{align-items:center;gap:8px;margin-top:8px;font-size:14px;display:flex}#photo-adjust-zoom{flex:1;min-width:0;min-height:44px}#photo-adjust-help{word-break:keep-all;margin:8px 0 0;font-size:13px;line-height:1.6}#photo-adjust-reset{color:var(--muted);box-shadow:none;background:0 0;border:0;font-size:13px;padding-left:0!important}#photo-adjust-panel[hidden],#photo-adjust-open[hidden]{display:none}#home-dialog{border:1px solid var(--line);background:var(--cream);width:min(380px,100% - 32px);max-height:calc(100dvh - 32px);color:var(--ink);border-radius:12px;padding:24px;overflow:auto}#home-dialog::backdrop{background:#201a1380}#home-title{word-break:keep-all;margin:0 0 12px;font-size:22px;line-height:1.5}#home-detail{color:var(--muted);font-size:14px;line-height:1.7}.home-actions{flex-wrap:wrap;justify-content:flex-end;gap:8px;margin-top:20px;display:flex}.home-actions button{min-height:44px;padding:10px 14px}#home-confirm{color:var(--cream);background:var(--ink)}#hint,[data-theme=booth] #hint{bottom:calc(112px + env(safe-area-inset-bottom))}.peeking-experiment{border-top:1px solid var(--line,#cfc3ad);margin-top:20px;padding-top:18px}.peeking-experiment h3{margin:0 0 8px;font-size:16px}.peeking-experiment p{color:var(--ink,#3e3429);margin:8px 0 12px;font-size:13px;line-height:1.65}.peeking-experiment button{width:100%;min-height:44px;margin-top:8px;padding:10px 12px;font-size:14px}.peeking-experiment [hidden],.peeking-preview-dialog [hidden]{display:none!important}.peeking-preview-dialog{overscroll-behavior:contain;border:1px solid var(--line,#cfc3ad);background:var(--cream,#f7f1e5);width:min(760px,100% - 32px);max-width:760px;max-height:calc(100dvh - 32px);color:var(--ink,#3e3429);box-sizing:border-box;border-radius:12px;margin:auto;padding:24px;overflow:auto}.peeking-preview-dialog::backdrop{background:#201a13a6}.peeking-preview-dialog h2{margin:0 0 10px;font-size:20px;line-height:1.4}.peeking-preview-dialog p{overflow-wrap:anywhere;font-size:14px;line-height:1.6}.peeking-preview-dialog #peeking-error{color:#862d25}.peeking-comparison{grid-template-columns:1fr 1fr;gap:14px;margin:18px 0;display:grid}.peeking-comparison figure{min-width:0;margin:0}.peeking-preview-surface{aspect-ratio:1;background-color:#fff;background-image:repeating-conic-gradient(#e3dfd5 0% 25%,#0000 0% 50%);background-size:20px 20px;border:1px solid #aa9c85;border-radius:6px;place-items:center;display:grid;overflow:hidden}.peeking-preview-surface img{object-fit:contain;width:100%;min-width:0;height:100%;min-height:0;display:block}.peeking-comparison figcaption{margin-top:7px;font-size:13px;line-height:1.4}.peeking-actions{flex-wrap:wrap;gap:10px;margin-top:20px;display:flex}.peeking-actions button{min-height:44px;padding:10px 14px;font-size:14px}.peeking-actions #peeking-accept{color:#3e3429;background:#ede4d2;border-color:#aa9674}.peeking-experiment button:focus-visible,.peeking-preview-dialog button:focus-visible{outline-offset:3px;outline:3px solid #765534}@media (width<=480px){.peeking-preview-dialog{width:calc(100% - 20px);max-height:calc(100dvh - 20px);padding:18px}.peeking-comparison{gap:8px}.peeking-comparison figcaption{font-size:12px}.peeking-actions button{flex:calc(50% - 10px)}} diff --git a/dist/assets/index-DOC1JJ07.js b/dist/assets/index-DOC1JJ07.js deleted file mode 100644 index c70988a..0000000 --- a/dist/assets/index-DOC1JJ07.js +++ /dev/null @@ -1,4317 +0,0 @@ -var au=Object.defineProperty;var ou=(i,e,t)=>e in i?au(i,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):i[e]=t;var ke=(i,e,t)=>ou(i,typeof e!="symbol"?e+"":e,t);(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const r of document.querySelectorAll('link[rel="modulepreload"]'))n(r);new MutationObserver(r=>{for(const s of r)if(s.type==="childList")for(const a of s.addedNodes)a.tagName==="LINK"&&a.rel==="modulepreload"&&n(a)}).observe(document,{childList:!0,subtree:!0});function t(r){const s={};return r.integrity&&(s.integrity=r.integrity),r.referrerPolicy&&(s.referrerPolicy=r.referrerPolicy),r.crossOrigin==="use-credentials"?s.credentials="include":r.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function n(r){if(r.ep)return;r.ep=!0;const s=t(r);fetch(r.href,s)}})();const lu="modulepreload",cu=function(i){return"/"+i},Vo={},ko=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){document.getElementsByTagName("link");const a=document.querySelector("meta[property=csp-nonce]"),o=(a==null?void 0:a.nonce)||(a==null?void 0:a.getAttribute("nonce"));r=Promise.allSettled(t.map(l=>{if(l=cu(l),l in Vo)return;Vo[l]=!0;const c=l.endsWith(".css"),u=c?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${l}"]${u}`))return;const d=document.createElement("link");if(d.rel=c?"stylesheet":lu,c||(d.as="script"),d.crossOrigin="",d.href=l,o&&d.setAttribute("nonce",o),document.head.appendChild(d),c)return new Promise((p,m)=>{d.addEventListener("load",p),d.addEventListener("error",()=>m(new Error(`Unable to preload CSS for ${l}`)))})}))}function s(a){const o=new Event("vite:preloadError",{cancelable:!0});if(o.payload=a,window.dispatchEvent(o),!o.defaultPrevented)throw a}return r.then(a=>{for(const o of a||[])o.status==="rejected"&&s(o.reason);return e().catch(s)})};/** - * @license - * Copyright 2010-2024 Three.js Authors - * SPDX-License-Identifier: MIT - */const so="169",uu=0,Wo=1,du=2,Ql=1,hu=2,vn=3,In=0,Lt=1,on=2,Ln=0,Ci=1,Xo=2,qo=3,Yo=4,fu=5,jn=100,pu=101,mu=102,gu=103,vu=104,_u=200,xu=201,Su=202,Mu=203,da=204,ha=205,yu=206,Eu=207,Tu=208,bu=209,Au=210,wu=211,Ru=212,Cu=213,Pu=214,fa=0,pa=1,ma=2,Li=3,ga=4,va=5,_a=6,xa=7,ec=0,Du=1,Lu=2,Un=0,Uu=1,Iu=2,Nu=3,Fu=4,Ou=5,Bu=6,zu=7,tc=300,Ui=301,Ii=302,Sa=303,Ma=304,_s=306,ya=1e3,Jn=1001,Ea=1002,ot=1003,Hu=1004,Ar=1005,ut=1006,Us=1007,Qn=1008,cn=1009,nc=1010,ic=1011,cr=1012,ao=1013,Nn=1014,Mn=1015,Bn=1016,oo=1017,lo=1018,Ni=1020,rc=35902,sc=1021,ac=1022,Pt=1023,oc=1024,lc=1025,ei=1026,Fi=1027,cc=1028,co=1029,uc=1030,uo=1031,ho=1033,Zr=33776,Kr=33777,jr=33778,$r=33779,Ta=35840,ba=35841,Aa=35842,wa=35843,Ra=36196,Ca=37492,Pa=37496,Da=37808,La=37809,Ua=37810,Ia=37811,Na=37812,Fa=37813,Oa=37814,Ba=37815,za=37816,Ha=37817,Ga=37818,Va=37819,ka=37820,Wa=37821,Jr=36492,Xa=36494,qa=36495,dc=36283,Ya=36284,Za=36285,Ka=36286,Gu=3200,Vu=3201,ku=0,Wu=1,Mt="",Bt="srgb",zn="srgb-linear",fo="display-p3",xs="display-p3-linear",ls="linear",et="srgb",cs="rec709",us="p3",di=7680,Zo=519,Xu=512,qu=513,Yu=514,hc=515,Zu=516,Ku=517,ju=518,$u=519,Ko=35044,jo="300 es",yn=2e3,ds=2001;class Gi{addEventListener(e,t){this._listeners===void 0&&(this._listeners={});const n=this._listeners;n[e]===void 0&&(n[e]=[]),n[e].indexOf(t)===-1&&n[e].push(t)}hasEventListener(e,t){if(this._listeners===void 0)return!1;const n=this._listeners;return n[e]!==void 0&&n[e].indexOf(t)!==-1}removeEventListener(e,t){if(this._listeners===void 0)return;const r=this._listeners[e];if(r!==void 0){const s=r.indexOf(t);s!==-1&&r.splice(s,1)}}dispatchEvent(e){if(this._listeners===void 0)return;const n=this._listeners[e.type];if(n!==void 0){e.target=this;const r=n.slice(0);for(let s=0,a=r.length;s>8&255]+_t[i>>16&255]+_t[i>>24&255]+"-"+_t[e&255]+_t[e>>8&255]+"-"+_t[e>>16&15|64]+_t[e>>24&255]+"-"+_t[t&63|128]+_t[t>>8&255]+"-"+_t[t>>16&255]+_t[t>>24&255]+_t[n&255]+_t[n>>8&255]+_t[n>>16&255]+_t[n>>24&255]).toLowerCase()}function bt(i,e,t){return Math.max(e,Math.min(t,i))}function po(i,e){return(i%e+e)%e}function Ju(i,e,t,n,r){return n+(i-e)*(r-n)/(t-e)}function Qu(i,e,t){return i!==e?(t-i)/(e-i):0}function nr(i,e,t){return(1-t)*i+t*e}function ed(i,e,t,n){return nr(i,e,1-Math.exp(-t*n))}function td(i,e=1){return e-Math.abs(po(i,e*2)-e)}function nd(i,e,t){return i<=e?0:i>=t?1:(i=(i-e)/(t-e),i*i*(3-2*i))}function id(i,e,t){return i<=e?0:i>=t?1:(i=(i-e)/(t-e),i*i*i*(i*(i*6-15)+10))}function rd(i,e){return i+Math.floor(Math.random()*(e-i+1))}function sd(i,e){return i+Math.random()*(e-i)}function ad(i){return i*(.5-Math.random())}function od(i){i!==void 0&&($o=i);let e=$o+=1831565813;return e=Math.imul(e^e>>>15,e|1),e^=e+Math.imul(e^e>>>7,e|61),((e^e>>>14)>>>0)/4294967296}function ld(i){return i*tr}function cd(i){return i*ur}function ud(i){return(i&i-1)===0&&i!==0}function dd(i){return Math.pow(2,Math.ceil(Math.log(i)/Math.LN2))}function hd(i){return Math.pow(2,Math.floor(Math.log(i)/Math.LN2))}function fd(i,e,t,n,r){const s=Math.cos,a=Math.sin,o=s(t/2),l=a(t/2),c=s((e+n)/2),u=a((e+n)/2),d=s((e-n)/2),p=a((e-n)/2),m=s((n-e)/2),_=a((n-e)/2);switch(r){case"XYX":i.set(o*u,l*d,l*p,o*c);break;case"YZY":i.set(l*p,o*u,l*d,o*c);break;case"ZXZ":i.set(l*d,l*p,o*u,o*c);break;case"XZX":i.set(o*u,l*_,l*m,o*c);break;case"YXY":i.set(l*m,o*u,l*_,o*c);break;case"ZYZ":i.set(l*_,l*m,o*u,o*c);break;default:console.warn("THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: "+r)}}function Ai(i,e){switch(e.constructor){case Float32Array:return i;case Uint32Array:return i/4294967295;case Uint16Array:return i/65535;case Uint8Array:return i/255;case Int32Array:return Math.max(i/2147483647,-1);case Int16Array:return Math.max(i/32767,-1);case Int8Array:return Math.max(i/127,-1);default:throw new Error("Invalid component type.")}}function Et(i,e){switch(e.constructor){case Float32Array:return i;case Uint32Array:return Math.round(i*4294967295);case Uint16Array:return Math.round(i*65535);case Uint8Array:return Math.round(i*255);case Int32Array:return Math.round(i*2147483647);case Int16Array:return Math.round(i*32767);case Int8Array:return Math.round(i*127);default:throw new Error("Invalid component type.")}}const yt={DEG2RAD:tr,RAD2DEG:ur,generateUUID:Vi,clamp:bt,euclideanModulo:po,mapLinear:Ju,inverseLerp:Qu,lerp:nr,damp:ed,pingpong:td,smoothstep:nd,smootherstep:id,randInt:rd,randFloat:sd,randFloatSpread:ad,seededRandom:od,degToRad:ld,radToDeg:cd,isPowerOfTwo:ud,ceilPowerOfTwo:dd,floorPowerOfTwo:hd,setQuaternionFromProperEuler:fd,normalize:Et,denormalize:Ai};class Le{constructor(e=0,t=0){Le.prototype.isVector2=!0,this.x=e,this.y=t}get width(){return this.x}set width(e){this.x=e}get height(){return this.y}set height(e){this.y=e}set(e,t){return this.x=e,this.y=t,this}setScalar(e){return this.x=e,this.y=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;default:throw new Error("index is out of range: "+e)}return this}getComponent(e){switch(e){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+e)}}clone(){return new this.constructor(this.x,this.y)}copy(e){return this.x=e.x,this.y=e.y,this}add(e){return this.x+=e.x,this.y+=e.y,this}addScalar(e){return this.x+=e,this.y+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this}subScalar(e){return this.x-=e,this.y-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this}multiply(e){return this.x*=e.x,this.y*=e.y,this}multiplyScalar(e){return this.x*=e,this.y*=e,this}divide(e){return this.x/=e.x,this.y/=e.y,this}divideScalar(e){return this.multiplyScalar(1/e)}applyMatrix3(e){const t=this.x,n=this.y,r=e.elements;return this.x=r[0]*t+r[3]*n+r[6],this.y=r[1]*t+r[4]*n+r[7],this}min(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this}max(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this}clamp(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this}clampScalar(e,t){return this.x=Math.max(e,Math.min(t,this.x)),this.y=Math.max(e,Math.min(t,this.y)),this}clampLength(e,t){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(e,Math.min(t,n)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this}negate(){return this.x=-this.x,this.y=-this.y,this}dot(e){return this.x*e.x+this.y*e.y}cross(e){return this.x*e.y-this.y*e.x}lengthSq(){return this.x*this.x+this.y*this.y}length(){return Math.sqrt(this.x*this.x+this.y*this.y)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)}normalize(){return this.divideScalar(this.length()||1)}angle(){return Math.atan2(-this.y,-this.x)+Math.PI}angleTo(e){const t=Math.sqrt(this.lengthSq()*e.lengthSq());if(t===0)return Math.PI/2;const n=this.dot(e)/t;return Math.acos(bt(n,-1,1))}distanceTo(e){return Math.sqrt(this.distanceToSquared(e))}distanceToSquared(e){const t=this.x-e.x,n=this.y-e.y;return t*t+n*n}manhattanDistanceTo(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)}setLength(e){return this.normalize().multiplyScalar(e)}lerp(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this}lerpVectors(e,t,n){return this.x=e.x+(t.x-e.x)*n,this.y=e.y+(t.y-e.y)*n,this}equals(e){return e.x===this.x&&e.y===this.y}fromArray(e,t=0){return this.x=e[t],this.y=e[t+1],this}toArray(e=[],t=0){return e[t]=this.x,e[t+1]=this.y,e}fromBufferAttribute(e,t){return this.x=e.getX(t),this.y=e.getY(t),this}rotateAround(e,t){const n=Math.cos(t),r=Math.sin(t),s=this.x-e.x,a=this.y-e.y;return this.x=s*n-a*r+e.x,this.y=s*r+a*n+e.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}}class De{constructor(e,t,n,r,s,a,o,l,c){De.prototype.isMatrix3=!0,this.elements=[1,0,0,0,1,0,0,0,1],e!==void 0&&this.set(e,t,n,r,s,a,o,l,c)}set(e,t,n,r,s,a,o,l,c){const u=this.elements;return u[0]=e,u[1]=r,u[2]=o,u[3]=t,u[4]=s,u[5]=l,u[6]=n,u[7]=a,u[8]=c,this}identity(){return this.set(1,0,0,0,1,0,0,0,1),this}copy(e){const t=this.elements,n=e.elements;return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],this}extractBasis(e,t,n){return e.setFromMatrix3Column(this,0),t.setFromMatrix3Column(this,1),n.setFromMatrix3Column(this,2),this}setFromMatrix4(e){const t=e.elements;return this.set(t[0],t[4],t[8],t[1],t[5],t[9],t[2],t[6],t[10]),this}multiply(e){return this.multiplyMatrices(this,e)}premultiply(e){return this.multiplyMatrices(e,this)}multiplyMatrices(e,t){const n=e.elements,r=t.elements,s=this.elements,a=n[0],o=n[3],l=n[6],c=n[1],u=n[4],d=n[7],p=n[2],m=n[5],_=n[8],M=r[0],f=r[3],h=r[6],T=r[1],y=r[4],b=r[7],O=r[2],C=r[5],A=r[8];return s[0]=a*M+o*T+l*O,s[3]=a*f+o*y+l*C,s[6]=a*h+o*b+l*A,s[1]=c*M+u*T+d*O,s[4]=c*f+u*y+d*C,s[7]=c*h+u*b+d*A,s[2]=p*M+m*T+_*O,s[5]=p*f+m*y+_*C,s[8]=p*h+m*b+_*A,this}multiplyScalar(e){const t=this.elements;return t[0]*=e,t[3]*=e,t[6]*=e,t[1]*=e,t[4]*=e,t[7]*=e,t[2]*=e,t[5]*=e,t[8]*=e,this}determinant(){const e=this.elements,t=e[0],n=e[1],r=e[2],s=e[3],a=e[4],o=e[5],l=e[6],c=e[7],u=e[8];return t*a*u-t*o*c-n*s*u+n*o*l+r*s*c-r*a*l}invert(){const e=this.elements,t=e[0],n=e[1],r=e[2],s=e[3],a=e[4],o=e[5],l=e[6],c=e[7],u=e[8],d=u*a-o*c,p=o*l-u*s,m=c*s-a*l,_=t*d+n*p+r*m;if(_===0)return this.set(0,0,0,0,0,0,0,0,0);const M=1/_;return e[0]=d*M,e[1]=(r*c-u*n)*M,e[2]=(o*n-r*a)*M,e[3]=p*M,e[4]=(u*t-r*l)*M,e[5]=(r*s-o*t)*M,e[6]=m*M,e[7]=(n*l-c*t)*M,e[8]=(a*t-n*s)*M,this}transpose(){let e;const t=this.elements;return e=t[1],t[1]=t[3],t[3]=e,e=t[2],t[2]=t[6],t[6]=e,e=t[5],t[5]=t[7],t[7]=e,this}getNormalMatrix(e){return this.setFromMatrix4(e).invert().transpose()}transposeIntoArray(e){const t=this.elements;return e[0]=t[0],e[1]=t[3],e[2]=t[6],e[3]=t[1],e[4]=t[4],e[5]=t[7],e[6]=t[2],e[7]=t[5],e[8]=t[8],this}setUvTransform(e,t,n,r,s,a,o){const l=Math.cos(s),c=Math.sin(s);return this.set(n*l,n*c,-n*(l*a+c*o)+a+e,-r*c,r*l,-r*(-c*a+l*o)+o+t,0,0,1),this}scale(e,t){return this.premultiply(Is.makeScale(e,t)),this}rotate(e){return this.premultiply(Is.makeRotation(-e)),this}translate(e,t){return this.premultiply(Is.makeTranslation(e,t)),this}makeTranslation(e,t){return e.isVector2?this.set(1,0,e.x,0,1,e.y,0,0,1):this.set(1,0,e,0,1,t,0,0,1),this}makeRotation(e){const t=Math.cos(e),n=Math.sin(e);return this.set(t,-n,0,n,t,0,0,0,1),this}makeScale(e,t){return this.set(e,0,0,0,t,0,0,0,1),this}equals(e){const t=this.elements,n=e.elements;for(let r=0;r<9;r++)if(t[r]!==n[r])return!1;return!0}fromArray(e,t=0){for(let n=0;n<9;n++)this.elements[n]=e[n+t];return this}toArray(e=[],t=0){const n=this.elements;return e[t]=n[0],e[t+1]=n[1],e[t+2]=n[2],e[t+3]=n[3],e[t+4]=n[4],e[t+5]=n[5],e[t+6]=n[6],e[t+7]=n[7],e[t+8]=n[8],e}clone(){return new this.constructor().fromArray(this.elements)}}const Is=new De;function fc(i){for(let e=i.length-1;e>=0;--e)if(i[e]>=65535)return!0;return!1}function hs(i){return document.createElementNS("http://www.w3.org/1999/xhtml",i)}function pd(){const i=hs("canvas");return i.style.display="block",i}const Jo={};function Qr(i){i in Jo||(Jo[i]=!0,console.warn(i))}function md(i,e,t){return new Promise(function(n,r){function s(){switch(i.clientWaitSync(e,i.SYNC_FLUSH_COMMANDS_BIT,0)){case i.WAIT_FAILED:r();break;case i.TIMEOUT_EXPIRED:setTimeout(s,t);break;default:n()}}setTimeout(s,t)})}function gd(i){const e=i.elements;e[2]=.5*e[2]+.5*e[3],e[6]=.5*e[6]+.5*e[7],e[10]=.5*e[10]+.5*e[11],e[14]=.5*e[14]+.5*e[15]}function vd(i){const e=i.elements;e[11]===-1?(e[10]=-e[10]-1,e[14]=-e[14]):(e[10]=-e[10],e[14]=-e[14]+1)}const Qo=new De().set(.8224621,.177538,0,.0331941,.9668058,0,.0170827,.0723974,.9105199),el=new De().set(1.2249401,-.2249404,0,-.0420569,1.0420571,0,-.0196376,-.0786361,1.0982735),Yi={[zn]:{transfer:ls,primaries:cs,luminanceCoefficients:[.2126,.7152,.0722],toReference:i=>i,fromReference:i=>i},[Bt]:{transfer:et,primaries:cs,luminanceCoefficients:[.2126,.7152,.0722],toReference:i=>i.convertSRGBToLinear(),fromReference:i=>i.convertLinearToSRGB()},[xs]:{transfer:ls,primaries:us,luminanceCoefficients:[.2289,.6917,.0793],toReference:i=>i.applyMatrix3(el),fromReference:i=>i.applyMatrix3(Qo)},[fo]:{transfer:et,primaries:us,luminanceCoefficients:[.2289,.6917,.0793],toReference:i=>i.convertSRGBToLinear().applyMatrix3(el),fromReference:i=>i.applyMatrix3(Qo).convertLinearToSRGB()}},_d=new Set([zn,xs]),qe={enabled:!0,_workingColorSpace:zn,get workingColorSpace(){return this._workingColorSpace},set workingColorSpace(i){if(!_d.has(i))throw new Error(`Unsupported working color space, "${i}".`);this._workingColorSpace=i},convert:function(i,e,t){if(this.enabled===!1||e===t||!e||!t)return i;const n=Yi[e].toReference,r=Yi[t].fromReference;return r(n(i))},fromWorkingColorSpace:function(i,e){return this.convert(i,this._workingColorSpace,e)},toWorkingColorSpace:function(i,e){return this.convert(i,e,this._workingColorSpace)},getPrimaries:function(i){return Yi[i].primaries},getTransfer:function(i){return i===Mt?ls:Yi[i].transfer},getLuminanceCoefficients:function(i,e=this._workingColorSpace){return i.fromArray(Yi[e].luminanceCoefficients)}};function Pi(i){return i<.04045?i*.0773993808:Math.pow(i*.9478672986+.0521327014,2.4)}function Ns(i){return i<.0031308?i*12.92:1.055*Math.pow(i,.41666)-.055}let hi;class xd{static getDataURL(e){if(/^data:/i.test(e.src)||typeof HTMLCanvasElement>"u")return e.src;let t;if(e instanceof HTMLCanvasElement)t=e;else{hi===void 0&&(hi=hs("canvas")),hi.width=e.width,hi.height=e.height;const n=hi.getContext("2d");e instanceof ImageData?n.putImageData(e,0,0):n.drawImage(e,0,0,e.width,e.height),t=hi}return t.width>2048||t.height>2048?(console.warn("THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons",e),t.toDataURL("image/jpeg",.6)):t.toDataURL("image/png")}static sRGBToLinear(e){if(typeof HTMLImageElement<"u"&&e instanceof HTMLImageElement||typeof HTMLCanvasElement<"u"&&e instanceof HTMLCanvasElement||typeof ImageBitmap<"u"&&e instanceof ImageBitmap){const t=hs("canvas");t.width=e.width,t.height=e.height;const n=t.getContext("2d");n.drawImage(e,0,0,e.width,e.height);const r=n.getImageData(0,0,e.width,e.height),s=r.data;for(let a=0;a0&&(n.userData=this.userData),t||(e.textures[this.uuid]=n),n}dispose(){this.dispatchEvent({type:"dispose"})}transformUv(e){if(this.mapping!==tc)return e;if(e.applyMatrix3(this.matrix),e.x<0||e.x>1)switch(this.wrapS){case ya:e.x=e.x-Math.floor(e.x);break;case Jn:e.x=e.x<0?0:1;break;case Ea:Math.abs(Math.floor(e.x)%2)===1?e.x=Math.ceil(e.x)-e.x:e.x=e.x-Math.floor(e.x);break}if(e.y<0||e.y>1)switch(this.wrapT){case ya:e.y=e.y-Math.floor(e.y);break;case Jn:e.y=e.y<0?0:1;break;case Ea:Math.abs(Math.floor(e.y)%2)===1?e.y=Math.ceil(e.y)-e.y:e.y=e.y-Math.floor(e.y);break}return this.flipY&&(e.y=1-e.y),e}set needsUpdate(e){e===!0&&(this.version++,this.source.needsUpdate=!0)}set needsPMREMUpdate(e){e===!0&&this.pmremVersion++}}vt.DEFAULT_IMAGE=null;vt.DEFAULT_MAPPING=tc;vt.DEFAULT_ANISOTROPY=1;class it{constructor(e=0,t=0,n=0,r=1){it.prototype.isVector4=!0,this.x=e,this.y=t,this.z=n,this.w=r}get width(){return this.z}set width(e){this.z=e}get height(){return this.w}set height(e){this.w=e}set(e,t,n,r){return this.x=e,this.y=t,this.z=n,this.w=r,this}setScalar(e){return this.x=e,this.y=e,this.z=e,this.w=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setZ(e){return this.z=e,this}setW(e){return this.w=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;case 3:this.w=t;break;default:throw new Error("index is out of range: "+e)}return this}getComponent(e){switch(e){case 0:return this.x;case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw new Error("index is out of range: "+e)}}clone(){return new this.constructor(this.x,this.y,this.z,this.w)}copy(e){return this.x=e.x,this.y=e.y,this.z=e.z,this.w=e.w!==void 0?e.w:1,this}add(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this.w+=e.w,this}addScalar(e){return this.x+=e,this.y+=e,this.z+=e,this.w+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this.w=e.w+t.w,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this.w+=e.w*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this.z-=e.z,this.w-=e.w,this}subScalar(e){return this.x-=e,this.y-=e,this.z-=e,this.w-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this.w=e.w-t.w,this}multiply(e){return this.x*=e.x,this.y*=e.y,this.z*=e.z,this.w*=e.w,this}multiplyScalar(e){return this.x*=e,this.y*=e,this.z*=e,this.w*=e,this}applyMatrix4(e){const t=this.x,n=this.y,r=this.z,s=this.w,a=e.elements;return this.x=a[0]*t+a[4]*n+a[8]*r+a[12]*s,this.y=a[1]*t+a[5]*n+a[9]*r+a[13]*s,this.z=a[2]*t+a[6]*n+a[10]*r+a[14]*s,this.w=a[3]*t+a[7]*n+a[11]*r+a[15]*s,this}divideScalar(e){return this.multiplyScalar(1/e)}setAxisAngleFromQuaternion(e){this.w=2*Math.acos(e.w);const t=Math.sqrt(1-e.w*e.w);return t<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=e.x/t,this.y=e.y/t,this.z=e.z/t),this}setAxisAngleFromRotationMatrix(e){let t,n,r,s;const l=e.elements,c=l[0],u=l[4],d=l[8],p=l[1],m=l[5],_=l[9],M=l[2],f=l[6],h=l[10];if(Math.abs(u-p)<.01&&Math.abs(d-M)<.01&&Math.abs(_-f)<.01){if(Math.abs(u+p)<.1&&Math.abs(d+M)<.1&&Math.abs(_+f)<.1&&Math.abs(c+m+h-3)<.1)return this.set(1,0,0,0),this;t=Math.PI;const y=(c+1)/2,b=(m+1)/2,O=(h+1)/2,C=(u+p)/4,A=(d+M)/4,F=(_+f)/4;return y>b&&y>O?y<.01?(n=0,r=.707106781,s=.707106781):(n=Math.sqrt(y),r=C/n,s=A/n):b>O?b<.01?(n=.707106781,r=0,s=.707106781):(r=Math.sqrt(b),n=C/r,s=F/r):O<.01?(n=.707106781,r=.707106781,s=0):(s=Math.sqrt(O),n=A/s,r=F/s),this.set(n,r,s,t),this}let T=Math.sqrt((f-_)*(f-_)+(d-M)*(d-M)+(p-u)*(p-u));return Math.abs(T)<.001&&(T=1),this.x=(f-_)/T,this.y=(d-M)/T,this.z=(p-u)/T,this.w=Math.acos((c+m+h-1)/2),this}setFromMatrixPosition(e){const t=e.elements;return this.x=t[12],this.y=t[13],this.z=t[14],this.w=t[15],this}min(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this.z=Math.min(this.z,e.z),this.w=Math.min(this.w,e.w),this}max(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this.z=Math.max(this.z,e.z),this.w=Math.max(this.w,e.w),this}clamp(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this.z=Math.max(e.z,Math.min(t.z,this.z)),this.w=Math.max(e.w,Math.min(t.w,this.w)),this}clampScalar(e,t){return this.x=Math.max(e,Math.min(t,this.x)),this.y=Math.max(e,Math.min(t,this.y)),this.z=Math.max(e,Math.min(t,this.z)),this.w=Math.max(e,Math.min(t,this.w)),this}clampLength(e,t){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(e,Math.min(t,n)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this.w=Math.floor(this.w),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this.w=Math.ceil(this.w),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this.w=Math.round(this.w),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this.z=Math.trunc(this.z),this.w=Math.trunc(this.w),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this.w=-this.w,this}dot(e){return this.x*e.x+this.y*e.y+this.z*e.z+this.w*e.w}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)+Math.abs(this.w)}normalize(){return this.divideScalar(this.length()||1)}setLength(e){return this.normalize().multiplyScalar(e)}lerp(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this.z+=(e.z-this.z)*t,this.w+=(e.w-this.w)*t,this}lerpVectors(e,t,n){return this.x=e.x+(t.x-e.x)*n,this.y=e.y+(t.y-e.y)*n,this.z=e.z+(t.z-e.z)*n,this.w=e.w+(t.w-e.w)*n,this}equals(e){return e.x===this.x&&e.y===this.y&&e.z===this.z&&e.w===this.w}fromArray(e,t=0){return this.x=e[t],this.y=e[t+1],this.z=e[t+2],this.w=e[t+3],this}toArray(e=[],t=0){return e[t]=this.x,e[t+1]=this.y,e[t+2]=this.z,e[t+3]=this.w,e}fromBufferAttribute(e,t){return this.x=e.getX(t),this.y=e.getY(t),this.z=e.getZ(t),this.w=e.getW(t),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this.w=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z,yield this.w}}class yd extends Gi{constructor(e=1,t=1,n={}){super(),this.isRenderTarget=!0,this.width=e,this.height=t,this.depth=1,this.scissor=new it(0,0,e,t),this.scissorTest=!1,this.viewport=new it(0,0,e,t);const r={width:e,height:t,depth:1};n=Object.assign({generateMipmaps:!1,internalFormat:null,minFilter:ut,depthBuffer:!0,stencilBuffer:!1,resolveDepthBuffer:!0,resolveStencilBuffer:!0,depthTexture:null,samples:0,count:1},n);const s=new vt(r,n.mapping,n.wrapS,n.wrapT,n.magFilter,n.minFilter,n.format,n.type,n.anisotropy,n.colorSpace);s.flipY=!1,s.generateMipmaps=n.generateMipmaps,s.internalFormat=n.internalFormat,this.textures=[];const a=n.count;for(let o=0;o=0?1:-1,y=1-h*h;if(y>Number.EPSILON){const O=Math.sqrt(y),C=Math.atan2(O,h*T);f=Math.sin(f*C)/O,o=Math.sin(o*C)/O}const b=o*T;if(l=l*f+p*b,c=c*f+m*b,u=u*f+_*b,d=d*f+M*b,f===1-o){const O=1/Math.sqrt(l*l+c*c+u*u+d*d);l*=O,c*=O,u*=O,d*=O}}e[t]=l,e[t+1]=c,e[t+2]=u,e[t+3]=d}static multiplyQuaternionsFlat(e,t,n,r,s,a){const o=n[r],l=n[r+1],c=n[r+2],u=n[r+3],d=s[a],p=s[a+1],m=s[a+2],_=s[a+3];return e[t]=o*_+u*d+l*m-c*p,e[t+1]=l*_+u*p+c*d-o*m,e[t+2]=c*_+u*m+o*p-l*d,e[t+3]=u*_-o*d-l*p-c*m,e}get x(){return this._x}set x(e){this._x=e,this._onChangeCallback()}get y(){return this._y}set y(e){this._y=e,this._onChangeCallback()}get z(){return this._z}set z(e){this._z=e,this._onChangeCallback()}get w(){return this._w}set w(e){this._w=e,this._onChangeCallback()}set(e,t,n,r){return this._x=e,this._y=t,this._z=n,this._w=r,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._w)}copy(e){return this._x=e.x,this._y=e.y,this._z=e.z,this._w=e.w,this._onChangeCallback(),this}setFromEuler(e,t=!0){const n=e._x,r=e._y,s=e._z,a=e._order,o=Math.cos,l=Math.sin,c=o(n/2),u=o(r/2),d=o(s/2),p=l(n/2),m=l(r/2),_=l(s/2);switch(a){case"XYZ":this._x=p*u*d+c*m*_,this._y=c*m*d-p*u*_,this._z=c*u*_+p*m*d,this._w=c*u*d-p*m*_;break;case"YXZ":this._x=p*u*d+c*m*_,this._y=c*m*d-p*u*_,this._z=c*u*_-p*m*d,this._w=c*u*d+p*m*_;break;case"ZXY":this._x=p*u*d-c*m*_,this._y=c*m*d+p*u*_,this._z=c*u*_+p*m*d,this._w=c*u*d-p*m*_;break;case"ZYX":this._x=p*u*d-c*m*_,this._y=c*m*d+p*u*_,this._z=c*u*_-p*m*d,this._w=c*u*d+p*m*_;break;case"YZX":this._x=p*u*d+c*m*_,this._y=c*m*d+p*u*_,this._z=c*u*_-p*m*d,this._w=c*u*d-p*m*_;break;case"XZY":this._x=p*u*d-c*m*_,this._y=c*m*d-p*u*_,this._z=c*u*_+p*m*d,this._w=c*u*d+p*m*_;break;default:console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: "+a)}return t===!0&&this._onChangeCallback(),this}setFromAxisAngle(e,t){const n=t/2,r=Math.sin(n);return this._x=e.x*r,this._y=e.y*r,this._z=e.z*r,this._w=Math.cos(n),this._onChangeCallback(),this}setFromRotationMatrix(e){const t=e.elements,n=t[0],r=t[4],s=t[8],a=t[1],o=t[5],l=t[9],c=t[2],u=t[6],d=t[10],p=n+o+d;if(p>0){const m=.5/Math.sqrt(p+1);this._w=.25/m,this._x=(u-l)*m,this._y=(s-c)*m,this._z=(a-r)*m}else if(n>o&&n>d){const m=2*Math.sqrt(1+n-o-d);this._w=(u-l)/m,this._x=.25*m,this._y=(r+a)/m,this._z=(s+c)/m}else if(o>d){const m=2*Math.sqrt(1+o-n-d);this._w=(s-c)/m,this._x=(r+a)/m,this._y=.25*m,this._z=(l+u)/m}else{const m=2*Math.sqrt(1+d-n-o);this._w=(a-r)/m,this._x=(s+c)/m,this._y=(l+u)/m,this._z=.25*m}return this._onChangeCallback(),this}setFromUnitVectors(e,t){let n=e.dot(t)+1;return nMath.abs(e.z)?(this._x=-e.y,this._y=e.x,this._z=0,this._w=n):(this._x=0,this._y=-e.z,this._z=e.y,this._w=n)):(this._x=e.y*t.z-e.z*t.y,this._y=e.z*t.x-e.x*t.z,this._z=e.x*t.y-e.y*t.x,this._w=n),this.normalize()}angleTo(e){return 2*Math.acos(Math.abs(bt(this.dot(e),-1,1)))}rotateTowards(e,t){const n=this.angleTo(e);if(n===0)return this;const r=Math.min(1,t/n);return this.slerp(e,r),this}identity(){return this.set(0,0,0,1)}invert(){return this.conjugate()}conjugate(){return this._x*=-1,this._y*=-1,this._z*=-1,this._onChangeCallback(),this}dot(e){return this._x*e._x+this._y*e._y+this._z*e._z+this._w*e._w}lengthSq(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w}length(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)}normalize(){let e=this.length();return e===0?(this._x=0,this._y=0,this._z=0,this._w=1):(e=1/e,this._x=this._x*e,this._y=this._y*e,this._z=this._z*e,this._w=this._w*e),this._onChangeCallback(),this}multiply(e){return this.multiplyQuaternions(this,e)}premultiply(e){return this.multiplyQuaternions(e,this)}multiplyQuaternions(e,t){const n=e._x,r=e._y,s=e._z,a=e._w,o=t._x,l=t._y,c=t._z,u=t._w;return this._x=n*u+a*o+r*c-s*l,this._y=r*u+a*l+s*o-n*c,this._z=s*u+a*c+n*l-r*o,this._w=a*u-n*o-r*l-s*c,this._onChangeCallback(),this}slerp(e,t){if(t===0)return this;if(t===1)return this.copy(e);const n=this._x,r=this._y,s=this._z,a=this._w;let o=a*e._w+n*e._x+r*e._y+s*e._z;if(o<0?(this._w=-e._w,this._x=-e._x,this._y=-e._y,this._z=-e._z,o=-o):this.copy(e),o>=1)return this._w=a,this._x=n,this._y=r,this._z=s,this;const l=1-o*o;if(l<=Number.EPSILON){const m=1-t;return this._w=m*a+t*this._w,this._x=m*n+t*this._x,this._y=m*r+t*this._y,this._z=m*s+t*this._z,this.normalize(),this}const c=Math.sqrt(l),u=Math.atan2(c,o),d=Math.sin((1-t)*u)/c,p=Math.sin(t*u)/c;return this._w=a*d+this._w*p,this._x=n*d+this._x*p,this._y=r*d+this._y*p,this._z=s*d+this._z*p,this._onChangeCallback(),this}slerpQuaternions(e,t,n){return this.copy(e).slerp(t,n)}random(){const e=2*Math.PI*Math.random(),t=2*Math.PI*Math.random(),n=Math.random(),r=Math.sqrt(1-n),s=Math.sqrt(n);return this.set(r*Math.sin(e),r*Math.cos(e),s*Math.sin(t),s*Math.cos(t))}equals(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._w===this._w}fromArray(e,t=0){return this._x=e[t],this._y=e[t+1],this._z=e[t+2],this._w=e[t+3],this._onChangeCallback(),this}toArray(e=[],t=0){return e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._w,e}fromBufferAttribute(e,t){return this._x=e.getX(t),this._y=e.getY(t),this._z=e.getZ(t),this._w=e.getW(t),this._onChangeCallback(),this}toJSON(){return this.toArray()}_onChange(e){return this._onChangeCallback=e,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._w}}class N{constructor(e=0,t=0,n=0){N.prototype.isVector3=!0,this.x=e,this.y=t,this.z=n}set(e,t,n){return n===void 0&&(n=this.z),this.x=e,this.y=t,this.z=n,this}setScalar(e){return this.x=e,this.y=e,this.z=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setZ(e){return this.z=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;default:throw new Error("index is out of range: "+e)}return this}getComponent(e){switch(e){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+e)}}clone(){return new this.constructor(this.x,this.y,this.z)}copy(e){return this.x=e.x,this.y=e.y,this.z=e.z,this}add(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this}addScalar(e){return this.x+=e,this.y+=e,this.z+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this.z-=e.z,this}subScalar(e){return this.x-=e,this.y-=e,this.z-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this}multiply(e){return this.x*=e.x,this.y*=e.y,this.z*=e.z,this}multiplyScalar(e){return this.x*=e,this.y*=e,this.z*=e,this}multiplyVectors(e,t){return this.x=e.x*t.x,this.y=e.y*t.y,this.z=e.z*t.z,this}applyEuler(e){return this.applyQuaternion(tl.setFromEuler(e))}applyAxisAngle(e,t){return this.applyQuaternion(tl.setFromAxisAngle(e,t))}applyMatrix3(e){const t=this.x,n=this.y,r=this.z,s=e.elements;return this.x=s[0]*t+s[3]*n+s[6]*r,this.y=s[1]*t+s[4]*n+s[7]*r,this.z=s[2]*t+s[5]*n+s[8]*r,this}applyNormalMatrix(e){return this.applyMatrix3(e).normalize()}applyMatrix4(e){const t=this.x,n=this.y,r=this.z,s=e.elements,a=1/(s[3]*t+s[7]*n+s[11]*r+s[15]);return this.x=(s[0]*t+s[4]*n+s[8]*r+s[12])*a,this.y=(s[1]*t+s[5]*n+s[9]*r+s[13])*a,this.z=(s[2]*t+s[6]*n+s[10]*r+s[14])*a,this}applyQuaternion(e){const t=this.x,n=this.y,r=this.z,s=e.x,a=e.y,o=e.z,l=e.w,c=2*(a*r-o*n),u=2*(o*t-s*r),d=2*(s*n-a*t);return this.x=t+l*c+a*d-o*u,this.y=n+l*u+o*c-s*d,this.z=r+l*d+s*u-a*c,this}project(e){return this.applyMatrix4(e.matrixWorldInverse).applyMatrix4(e.projectionMatrix)}unproject(e){return this.applyMatrix4(e.projectionMatrixInverse).applyMatrix4(e.matrixWorld)}transformDirection(e){const t=this.x,n=this.y,r=this.z,s=e.elements;return this.x=s[0]*t+s[4]*n+s[8]*r,this.y=s[1]*t+s[5]*n+s[9]*r,this.z=s[2]*t+s[6]*n+s[10]*r,this.normalize()}divide(e){return this.x/=e.x,this.y/=e.y,this.z/=e.z,this}divideScalar(e){return this.multiplyScalar(1/e)}min(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this.z=Math.min(this.z,e.z),this}max(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this.z=Math.max(this.z,e.z),this}clamp(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this.z=Math.max(e.z,Math.min(t.z,this.z)),this}clampScalar(e,t){return this.x=Math.max(e,Math.min(t,this.x)),this.y=Math.max(e,Math.min(t,this.y)),this.z=Math.max(e,Math.min(t,this.z)),this}clampLength(e,t){const n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(e,Math.min(t,n)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this.z=Math.trunc(this.z),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this}dot(e){return this.x*e.x+this.y*e.y+this.z*e.z}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)}normalize(){return this.divideScalar(this.length()||1)}setLength(e){return this.normalize().multiplyScalar(e)}lerp(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this.z+=(e.z-this.z)*t,this}lerpVectors(e,t,n){return this.x=e.x+(t.x-e.x)*n,this.y=e.y+(t.y-e.y)*n,this.z=e.z+(t.z-e.z)*n,this}cross(e){return this.crossVectors(this,e)}crossVectors(e,t){const n=e.x,r=e.y,s=e.z,a=t.x,o=t.y,l=t.z;return this.x=r*l-s*o,this.y=s*a-n*l,this.z=n*o-r*a,this}projectOnVector(e){const t=e.lengthSq();if(t===0)return this.set(0,0,0);const n=e.dot(this)/t;return this.copy(e).multiplyScalar(n)}projectOnPlane(e){return Os.copy(this).projectOnVector(e),this.sub(Os)}reflect(e){return this.sub(Os.copy(e).multiplyScalar(2*this.dot(e)))}angleTo(e){const t=Math.sqrt(this.lengthSq()*e.lengthSq());if(t===0)return Math.PI/2;const n=this.dot(e)/t;return Math.acos(bt(n,-1,1))}distanceTo(e){return Math.sqrt(this.distanceToSquared(e))}distanceToSquared(e){const t=this.x-e.x,n=this.y-e.y,r=this.z-e.z;return t*t+n*n+r*r}manhattanDistanceTo(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)+Math.abs(this.z-e.z)}setFromSpherical(e){return this.setFromSphericalCoords(e.radius,e.phi,e.theta)}setFromSphericalCoords(e,t,n){const r=Math.sin(t)*e;return this.x=r*Math.sin(n),this.y=Math.cos(t)*e,this.z=r*Math.cos(n),this}setFromCylindrical(e){return this.setFromCylindricalCoords(e.radius,e.theta,e.y)}setFromCylindricalCoords(e,t,n){return this.x=e*Math.sin(t),this.y=n,this.z=e*Math.cos(t),this}setFromMatrixPosition(e){const t=e.elements;return this.x=t[12],this.y=t[13],this.z=t[14],this}setFromMatrixScale(e){const t=this.setFromMatrixColumn(e,0).length(),n=this.setFromMatrixColumn(e,1).length(),r=this.setFromMatrixColumn(e,2).length();return this.x=t,this.y=n,this.z=r,this}setFromMatrixColumn(e,t){return this.fromArray(e.elements,t*4)}setFromMatrix3Column(e,t){return this.fromArray(e.elements,t*3)}setFromEuler(e){return this.x=e._x,this.y=e._y,this.z=e._z,this}setFromColor(e){return this.x=e.r,this.y=e.g,this.z=e.b,this}equals(e){return e.x===this.x&&e.y===this.y&&e.z===this.z}fromArray(e,t=0){return this.x=e[t],this.y=e[t+1],this.z=e[t+2],this}toArray(e=[],t=0){return e[t]=this.x,e[t+1]=this.y,e[t+2]=this.z,e}fromBufferAttribute(e,t){return this.x=e.getX(t),this.y=e.getY(t),this.z=e.getZ(t),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}randomDirection(){const e=Math.random()*Math.PI*2,t=Math.random()*2-1,n=Math.sqrt(1-t*t);return this.x=n*Math.cos(e),this.y=t,this.z=n*Math.sin(e),this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}}const Os=new N,tl=new _r;class xr{constructor(e=new N(1/0,1/0,1/0),t=new N(-1/0,-1/0,-1/0)){this.isBox3=!0,this.min=e,this.max=t}set(e,t){return this.min.copy(e),this.max.copy(t),this}setFromArray(e){this.makeEmpty();for(let t=0,n=e.length;t=this.min.x&&e.x<=this.max.x&&e.y>=this.min.y&&e.y<=this.max.y&&e.z>=this.min.z&&e.z<=this.max.z}containsBox(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y&&this.min.z<=e.min.z&&e.max.z<=this.max.z}getParameter(e,t){return t.set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y),(e.z-this.min.z)/(this.max.z-this.min.z))}intersectsBox(e){return e.max.x>=this.min.x&&e.min.x<=this.max.x&&e.max.y>=this.min.y&&e.min.y<=this.max.y&&e.max.z>=this.min.z&&e.min.z<=this.max.z}intersectsSphere(e){return this.clampPoint(e.center,Kt),Kt.distanceToSquared(e.center)<=e.radius*e.radius}intersectsPlane(e){let t,n;return e.normal.x>0?(t=e.normal.x*this.min.x,n=e.normal.x*this.max.x):(t=e.normal.x*this.max.x,n=e.normal.x*this.min.x),e.normal.y>0?(t+=e.normal.y*this.min.y,n+=e.normal.y*this.max.y):(t+=e.normal.y*this.max.y,n+=e.normal.y*this.min.y),e.normal.z>0?(t+=e.normal.z*this.min.z,n+=e.normal.z*this.max.z):(t+=e.normal.z*this.max.z,n+=e.normal.z*this.min.z),t<=-e.constant&&n>=-e.constant}intersectsTriangle(e){if(this.isEmpty())return!1;this.getCenter(Zi),Rr.subVectors(this.max,Zi),fi.subVectors(e.a,Zi),pi.subVectors(e.b,Zi),mi.subVectors(e.c,Zi),bn.subVectors(pi,fi),An.subVectors(mi,pi),Vn.subVectors(fi,mi);let t=[0,-bn.z,bn.y,0,-An.z,An.y,0,-Vn.z,Vn.y,bn.z,0,-bn.x,An.z,0,-An.x,Vn.z,0,-Vn.x,-bn.y,bn.x,0,-An.y,An.x,0,-Vn.y,Vn.x,0];return!Bs(t,fi,pi,mi,Rr)||(t=[1,0,0,0,1,0,0,0,1],!Bs(t,fi,pi,mi,Rr))?!1:(Cr.crossVectors(bn,An),t=[Cr.x,Cr.y,Cr.z],Bs(t,fi,pi,mi,Rr))}clampPoint(e,t){return t.copy(e).clamp(this.min,this.max)}distanceToPoint(e){return this.clampPoint(e,Kt).distanceTo(e)}getBoundingSphere(e){return this.isEmpty()?e.makeEmpty():(this.getCenter(e.center),e.radius=this.getSize(Kt).length()*.5),e}intersect(e){return this.min.max(e.min),this.max.min(e.max),this.isEmpty()&&this.makeEmpty(),this}union(e){return this.min.min(e.min),this.max.max(e.max),this}applyMatrix4(e){return this.isEmpty()?this:(hn[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(e),hn[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(e),hn[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(e),hn[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(e),hn[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(e),hn[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(e),hn[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(e),hn[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(e),this.setFromPoints(hn),this)}translate(e){return this.min.add(e),this.max.add(e),this}equals(e){return e.min.equals(this.min)&&e.max.equals(this.max)}}const hn=[new N,new N,new N,new N,new N,new N,new N,new N],Kt=new N,wr=new xr,fi=new N,pi=new N,mi=new N,bn=new N,An=new N,Vn=new N,Zi=new N,Rr=new N,Cr=new N,kn=new N;function Bs(i,e,t,n,r){for(let s=0,a=i.length-3;s<=a;s+=3){kn.fromArray(i,s);const o=r.x*Math.abs(kn.x)+r.y*Math.abs(kn.y)+r.z*Math.abs(kn.z),l=e.dot(kn),c=t.dot(kn),u=n.dot(kn);if(Math.max(-Math.max(l,c,u),Math.min(l,c,u))>o)return!1}return!0}const Td=new xr,Ki=new N,zs=new N;class mo{constructor(e=new N,t=-1){this.isSphere=!0,this.center=e,this.radius=t}set(e,t){return this.center.copy(e),this.radius=t,this}setFromPoints(e,t){const n=this.center;t!==void 0?n.copy(t):Td.setFromPoints(e).getCenter(n);let r=0;for(let s=0,a=e.length;sthis.radius*this.radius&&(t.sub(this.center).normalize(),t.multiplyScalar(this.radius).add(this.center)),t}getBoundingBox(e){return this.isEmpty()?(e.makeEmpty(),e):(e.set(this.center,this.center),e.expandByScalar(this.radius),e)}applyMatrix4(e){return this.center.applyMatrix4(e),this.radius=this.radius*e.getMaxScaleOnAxis(),this}translate(e){return this.center.add(e),this}expandByPoint(e){if(this.isEmpty())return this.center.copy(e),this.radius=0,this;Ki.subVectors(e,this.center);const t=Ki.lengthSq();if(t>this.radius*this.radius){const n=Math.sqrt(t),r=(n-this.radius)*.5;this.center.addScaledVector(Ki,r/n),this.radius+=r}return this}union(e){return e.isEmpty()?this:this.isEmpty()?(this.copy(e),this):(this.center.equals(e.center)===!0?this.radius=Math.max(this.radius,e.radius):(zs.subVectors(e.center,this.center).setLength(e.radius),this.expandByPoint(Ki.copy(e.center).add(zs)),this.expandByPoint(Ki.copy(e.center).sub(zs))),this)}equals(e){return e.center.equals(this.center)&&e.radius===this.radius}clone(){return new this.constructor().copy(this)}}const fn=new N,Hs=new N,Pr=new N,wn=new N,Gs=new N,Dr=new N,Vs=new N;class bd{constructor(e=new N,t=new N(0,0,-1)){this.origin=e,this.direction=t}set(e,t){return this.origin.copy(e),this.direction.copy(t),this}copy(e){return this.origin.copy(e.origin),this.direction.copy(e.direction),this}at(e,t){return t.copy(this.origin).addScaledVector(this.direction,e)}lookAt(e){return this.direction.copy(e).sub(this.origin).normalize(),this}recast(e){return this.origin.copy(this.at(e,fn)),this}closestPointToPoint(e,t){t.subVectors(e,this.origin);const n=t.dot(this.direction);return n<0?t.copy(this.origin):t.copy(this.origin).addScaledVector(this.direction,n)}distanceToPoint(e){return Math.sqrt(this.distanceSqToPoint(e))}distanceSqToPoint(e){const t=fn.subVectors(e,this.origin).dot(this.direction);return t<0?this.origin.distanceToSquared(e):(fn.copy(this.origin).addScaledVector(this.direction,t),fn.distanceToSquared(e))}distanceSqToSegment(e,t,n,r){Hs.copy(e).add(t).multiplyScalar(.5),Pr.copy(t).sub(e).normalize(),wn.copy(this.origin).sub(Hs);const s=e.distanceTo(t)*.5,a=-this.direction.dot(Pr),o=wn.dot(this.direction),l=-wn.dot(Pr),c=wn.lengthSq(),u=Math.abs(1-a*a);let d,p,m,_;if(u>0)if(d=a*l-o,p=a*o-l,_=s*u,d>=0)if(p>=-_)if(p<=_){const M=1/u;d*=M,p*=M,m=d*(d+a*p+2*o)+p*(a*d+p+2*l)+c}else p=s,d=Math.max(0,-(a*p+o)),m=-d*d+p*(p+2*l)+c;else p=-s,d=Math.max(0,-(a*p+o)),m=-d*d+p*(p+2*l)+c;else p<=-_?(d=Math.max(0,-(-a*s+o)),p=d>0?-s:Math.min(Math.max(-s,-l),s),m=-d*d+p*(p+2*l)+c):p<=_?(d=0,p=Math.min(Math.max(-s,-l),s),m=p*(p+2*l)+c):(d=Math.max(0,-(a*s+o)),p=d>0?s:Math.min(Math.max(-s,-l),s),m=-d*d+p*(p+2*l)+c);else p=a>0?-s:s,d=Math.max(0,-(a*p+o)),m=-d*d+p*(p+2*l)+c;return n&&n.copy(this.origin).addScaledVector(this.direction,d),r&&r.copy(Hs).addScaledVector(Pr,p),m}intersectSphere(e,t){fn.subVectors(e.center,this.origin);const n=fn.dot(this.direction),r=fn.dot(fn)-n*n,s=e.radius*e.radius;if(r>s)return null;const a=Math.sqrt(s-r),o=n-a,l=n+a;return l<0?null:o<0?this.at(l,t):this.at(o,t)}intersectsSphere(e){return this.distanceSqToPoint(e.center)<=e.radius*e.radius}distanceToPlane(e){const t=e.normal.dot(this.direction);if(t===0)return e.distanceToPoint(this.origin)===0?0:null;const n=-(this.origin.dot(e.normal)+e.constant)/t;return n>=0?n:null}intersectPlane(e,t){const n=this.distanceToPlane(e);return n===null?null:this.at(n,t)}intersectsPlane(e){const t=e.distanceToPoint(this.origin);return t===0||e.normal.dot(this.direction)*t<0}intersectBox(e,t){let n,r,s,a,o,l;const c=1/this.direction.x,u=1/this.direction.y,d=1/this.direction.z,p=this.origin;return c>=0?(n=(e.min.x-p.x)*c,r=(e.max.x-p.x)*c):(n=(e.max.x-p.x)*c,r=(e.min.x-p.x)*c),u>=0?(s=(e.min.y-p.y)*u,a=(e.max.y-p.y)*u):(s=(e.max.y-p.y)*u,a=(e.min.y-p.y)*u),n>a||s>r||((s>n||isNaN(n))&&(n=s),(a=0?(o=(e.min.z-p.z)*d,l=(e.max.z-p.z)*d):(o=(e.max.z-p.z)*d,l=(e.min.z-p.z)*d),n>l||o>r)||((o>n||n!==n)&&(n=o),(l=0?n:r,t)}intersectsBox(e){return this.intersectBox(e,fn)!==null}intersectTriangle(e,t,n,r,s){Gs.subVectors(t,e),Dr.subVectors(n,e),Vs.crossVectors(Gs,Dr);let a=this.direction.dot(Vs),o;if(a>0){if(r)return null;o=1}else if(a<0)o=-1,a=-a;else return null;wn.subVectors(this.origin,e);const l=o*this.direction.dot(Dr.crossVectors(wn,Dr));if(l<0)return null;const c=o*this.direction.dot(Gs.cross(wn));if(c<0||l+c>a)return null;const u=-o*wn.dot(Vs);return u<0?null:this.at(u/a,s)}applyMatrix4(e){return this.origin.applyMatrix4(e),this.direction.transformDirection(e),this}equals(e){return e.origin.equals(this.origin)&&e.direction.equals(this.direction)}clone(){return new this.constructor().copy(this)}}class tt{constructor(e,t,n,r,s,a,o,l,c,u,d,p,m,_,M,f){tt.prototype.isMatrix4=!0,this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],e!==void 0&&this.set(e,t,n,r,s,a,o,l,c,u,d,p,m,_,M,f)}set(e,t,n,r,s,a,o,l,c,u,d,p,m,_,M,f){const h=this.elements;return h[0]=e,h[4]=t,h[8]=n,h[12]=r,h[1]=s,h[5]=a,h[9]=o,h[13]=l,h[2]=c,h[6]=u,h[10]=d,h[14]=p,h[3]=m,h[7]=_,h[11]=M,h[15]=f,this}identity(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this}clone(){return new tt().fromArray(this.elements)}copy(e){const t=this.elements,n=e.elements;return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t[9]=n[9],t[10]=n[10],t[11]=n[11],t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15],this}copyPosition(e){const t=this.elements,n=e.elements;return t[12]=n[12],t[13]=n[13],t[14]=n[14],this}setFromMatrix3(e){const t=e.elements;return this.set(t[0],t[3],t[6],0,t[1],t[4],t[7],0,t[2],t[5],t[8],0,0,0,0,1),this}extractBasis(e,t,n){return e.setFromMatrixColumn(this,0),t.setFromMatrixColumn(this,1),n.setFromMatrixColumn(this,2),this}makeBasis(e,t,n){return this.set(e.x,t.x,n.x,0,e.y,t.y,n.y,0,e.z,t.z,n.z,0,0,0,0,1),this}extractRotation(e){const t=this.elements,n=e.elements,r=1/gi.setFromMatrixColumn(e,0).length(),s=1/gi.setFromMatrixColumn(e,1).length(),a=1/gi.setFromMatrixColumn(e,2).length();return t[0]=n[0]*r,t[1]=n[1]*r,t[2]=n[2]*r,t[3]=0,t[4]=n[4]*s,t[5]=n[5]*s,t[6]=n[6]*s,t[7]=0,t[8]=n[8]*a,t[9]=n[9]*a,t[10]=n[10]*a,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this}makeRotationFromEuler(e){const t=this.elements,n=e.x,r=e.y,s=e.z,a=Math.cos(n),o=Math.sin(n),l=Math.cos(r),c=Math.sin(r),u=Math.cos(s),d=Math.sin(s);if(e.order==="XYZ"){const p=a*u,m=a*d,_=o*u,M=o*d;t[0]=l*u,t[4]=-l*d,t[8]=c,t[1]=m+_*c,t[5]=p-M*c,t[9]=-o*l,t[2]=M-p*c,t[6]=_+m*c,t[10]=a*l}else if(e.order==="YXZ"){const p=l*u,m=l*d,_=c*u,M=c*d;t[0]=p+M*o,t[4]=_*o-m,t[8]=a*c,t[1]=a*d,t[5]=a*u,t[9]=-o,t[2]=m*o-_,t[6]=M+p*o,t[10]=a*l}else if(e.order==="ZXY"){const p=l*u,m=l*d,_=c*u,M=c*d;t[0]=p-M*o,t[4]=-a*d,t[8]=_+m*o,t[1]=m+_*o,t[5]=a*u,t[9]=M-p*o,t[2]=-a*c,t[6]=o,t[10]=a*l}else if(e.order==="ZYX"){const p=a*u,m=a*d,_=o*u,M=o*d;t[0]=l*u,t[4]=_*c-m,t[8]=p*c+M,t[1]=l*d,t[5]=M*c+p,t[9]=m*c-_,t[2]=-c,t[6]=o*l,t[10]=a*l}else if(e.order==="YZX"){const p=a*l,m=a*c,_=o*l,M=o*c;t[0]=l*u,t[4]=M-p*d,t[8]=_*d+m,t[1]=d,t[5]=a*u,t[9]=-o*u,t[2]=-c*u,t[6]=m*d+_,t[10]=p-M*d}else if(e.order==="XZY"){const p=a*l,m=a*c,_=o*l,M=o*c;t[0]=l*u,t[4]=-d,t[8]=c*u,t[1]=p*d+M,t[5]=a*u,t[9]=m*d-_,t[2]=_*d-m,t[6]=o*u,t[10]=M*d+p}return t[3]=0,t[7]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this}makeRotationFromQuaternion(e){return this.compose(Ad,e,wd)}lookAt(e,t,n){const r=this.elements;return Ft.subVectors(e,t),Ft.lengthSq()===0&&(Ft.z=1),Ft.normalize(),Rn.crossVectors(n,Ft),Rn.lengthSq()===0&&(Math.abs(n.z)===1?Ft.x+=1e-4:Ft.z+=1e-4,Ft.normalize(),Rn.crossVectors(n,Ft)),Rn.normalize(),Lr.crossVectors(Ft,Rn),r[0]=Rn.x,r[4]=Lr.x,r[8]=Ft.x,r[1]=Rn.y,r[5]=Lr.y,r[9]=Ft.y,r[2]=Rn.z,r[6]=Lr.z,r[10]=Ft.z,this}multiply(e){return this.multiplyMatrices(this,e)}premultiply(e){return this.multiplyMatrices(e,this)}multiplyMatrices(e,t){const n=e.elements,r=t.elements,s=this.elements,a=n[0],o=n[4],l=n[8],c=n[12],u=n[1],d=n[5],p=n[9],m=n[13],_=n[2],M=n[6],f=n[10],h=n[14],T=n[3],y=n[7],b=n[11],O=n[15],C=r[0],A=r[4],F=r[8],te=r[12],g=r[1],S=r[5],V=r[9],z=r[13],k=r[2],K=r[6],B=r[10],Q=r[14],G=r[3],le=r[7],ce=r[11],ve=r[15];return s[0]=a*C+o*g+l*k+c*G,s[4]=a*A+o*S+l*K+c*le,s[8]=a*F+o*V+l*B+c*ce,s[12]=a*te+o*z+l*Q+c*ve,s[1]=u*C+d*g+p*k+m*G,s[5]=u*A+d*S+p*K+m*le,s[9]=u*F+d*V+p*B+m*ce,s[13]=u*te+d*z+p*Q+m*ve,s[2]=_*C+M*g+f*k+h*G,s[6]=_*A+M*S+f*K+h*le,s[10]=_*F+M*V+f*B+h*ce,s[14]=_*te+M*z+f*Q+h*ve,s[3]=T*C+y*g+b*k+O*G,s[7]=T*A+y*S+b*K+O*le,s[11]=T*F+y*V+b*B+O*ce,s[15]=T*te+y*z+b*Q+O*ve,this}multiplyScalar(e){const t=this.elements;return t[0]*=e,t[4]*=e,t[8]*=e,t[12]*=e,t[1]*=e,t[5]*=e,t[9]*=e,t[13]*=e,t[2]*=e,t[6]*=e,t[10]*=e,t[14]*=e,t[3]*=e,t[7]*=e,t[11]*=e,t[15]*=e,this}determinant(){const e=this.elements,t=e[0],n=e[4],r=e[8],s=e[12],a=e[1],o=e[5],l=e[9],c=e[13],u=e[2],d=e[6],p=e[10],m=e[14],_=e[3],M=e[7],f=e[11],h=e[15];return _*(+s*l*d-r*c*d-s*o*p+n*c*p+r*o*m-n*l*m)+M*(+t*l*m-t*c*p+s*a*p-r*a*m+r*c*u-s*l*u)+f*(+t*c*d-t*o*m-s*a*d+n*a*m+s*o*u-n*c*u)+h*(-r*o*u-t*l*d+t*o*p+r*a*d-n*a*p+n*l*u)}transpose(){const e=this.elements;let t;return t=e[1],e[1]=e[4],e[4]=t,t=e[2],e[2]=e[8],e[8]=t,t=e[6],e[6]=e[9],e[9]=t,t=e[3],e[3]=e[12],e[12]=t,t=e[7],e[7]=e[13],e[13]=t,t=e[11],e[11]=e[14],e[14]=t,this}setPosition(e,t,n){const r=this.elements;return e.isVector3?(r[12]=e.x,r[13]=e.y,r[14]=e.z):(r[12]=e,r[13]=t,r[14]=n),this}invert(){const e=this.elements,t=e[0],n=e[1],r=e[2],s=e[3],a=e[4],o=e[5],l=e[6],c=e[7],u=e[8],d=e[9],p=e[10],m=e[11],_=e[12],M=e[13],f=e[14],h=e[15],T=d*f*c-M*p*c+M*l*m-o*f*m-d*l*h+o*p*h,y=_*p*c-u*f*c-_*l*m+a*f*m+u*l*h-a*p*h,b=u*M*c-_*d*c+_*o*m-a*M*m-u*o*h+a*d*h,O=_*d*l-u*M*l-_*o*p+a*M*p+u*o*f-a*d*f,C=t*T+n*y+r*b+s*O;if(C===0)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);const A=1/C;return e[0]=T*A,e[1]=(M*p*s-d*f*s-M*r*m+n*f*m+d*r*h-n*p*h)*A,e[2]=(o*f*s-M*l*s+M*r*c-n*f*c-o*r*h+n*l*h)*A,e[3]=(d*l*s-o*p*s-d*r*c+n*p*c+o*r*m-n*l*m)*A,e[4]=y*A,e[5]=(u*f*s-_*p*s+_*r*m-t*f*m-u*r*h+t*p*h)*A,e[6]=(_*l*s-a*f*s-_*r*c+t*f*c+a*r*h-t*l*h)*A,e[7]=(a*p*s-u*l*s+u*r*c-t*p*c-a*r*m+t*l*m)*A,e[8]=b*A,e[9]=(_*d*s-u*M*s-_*n*m+t*M*m+u*n*h-t*d*h)*A,e[10]=(a*M*s-_*o*s+_*n*c-t*M*c-a*n*h+t*o*h)*A,e[11]=(u*o*s-a*d*s-u*n*c+t*d*c+a*n*m-t*o*m)*A,e[12]=O*A,e[13]=(u*M*r-_*d*r+_*n*p-t*M*p-u*n*f+t*d*f)*A,e[14]=(_*o*r-a*M*r-_*n*l+t*M*l+a*n*f-t*o*f)*A,e[15]=(a*d*r-u*o*r+u*n*l-t*d*l-a*n*p+t*o*p)*A,this}scale(e){const t=this.elements,n=e.x,r=e.y,s=e.z;return t[0]*=n,t[4]*=r,t[8]*=s,t[1]*=n,t[5]*=r,t[9]*=s,t[2]*=n,t[6]*=r,t[10]*=s,t[3]*=n,t[7]*=r,t[11]*=s,this}getMaxScaleOnAxis(){const e=this.elements,t=e[0]*e[0]+e[1]*e[1]+e[2]*e[2],n=e[4]*e[4]+e[5]*e[5]+e[6]*e[6],r=e[8]*e[8]+e[9]*e[9]+e[10]*e[10];return Math.sqrt(Math.max(t,n,r))}makeTranslation(e,t,n){return e.isVector3?this.set(1,0,0,e.x,0,1,0,e.y,0,0,1,e.z,0,0,0,1):this.set(1,0,0,e,0,1,0,t,0,0,1,n,0,0,0,1),this}makeRotationX(e){const t=Math.cos(e),n=Math.sin(e);return this.set(1,0,0,0,0,t,-n,0,0,n,t,0,0,0,0,1),this}makeRotationY(e){const t=Math.cos(e),n=Math.sin(e);return this.set(t,0,n,0,0,1,0,0,-n,0,t,0,0,0,0,1),this}makeRotationZ(e){const t=Math.cos(e),n=Math.sin(e);return this.set(t,-n,0,0,n,t,0,0,0,0,1,0,0,0,0,1),this}makeRotationAxis(e,t){const n=Math.cos(t),r=Math.sin(t),s=1-n,a=e.x,o=e.y,l=e.z,c=s*a,u=s*o;return this.set(c*a+n,c*o-r*l,c*l+r*o,0,c*o+r*l,u*o+n,u*l-r*a,0,c*l-r*o,u*l+r*a,s*l*l+n,0,0,0,0,1),this}makeScale(e,t,n){return this.set(e,0,0,0,0,t,0,0,0,0,n,0,0,0,0,1),this}makeShear(e,t,n,r,s,a){return this.set(1,n,s,0,e,1,a,0,t,r,1,0,0,0,0,1),this}compose(e,t,n){const r=this.elements,s=t._x,a=t._y,o=t._z,l=t._w,c=s+s,u=a+a,d=o+o,p=s*c,m=s*u,_=s*d,M=a*u,f=a*d,h=o*d,T=l*c,y=l*u,b=l*d,O=n.x,C=n.y,A=n.z;return r[0]=(1-(M+h))*O,r[1]=(m+b)*O,r[2]=(_-y)*O,r[3]=0,r[4]=(m-b)*C,r[5]=(1-(p+h))*C,r[6]=(f+T)*C,r[7]=0,r[8]=(_+y)*A,r[9]=(f-T)*A,r[10]=(1-(p+M))*A,r[11]=0,r[12]=e.x,r[13]=e.y,r[14]=e.z,r[15]=1,this}decompose(e,t,n){const r=this.elements;let s=gi.set(r[0],r[1],r[2]).length();const a=gi.set(r[4],r[5],r[6]).length(),o=gi.set(r[8],r[9],r[10]).length();this.determinant()<0&&(s=-s),e.x=r[12],e.y=r[13],e.z=r[14],jt.copy(this);const c=1/s,u=1/a,d=1/o;return jt.elements[0]*=c,jt.elements[1]*=c,jt.elements[2]*=c,jt.elements[4]*=u,jt.elements[5]*=u,jt.elements[6]*=u,jt.elements[8]*=d,jt.elements[9]*=d,jt.elements[10]*=d,t.setFromRotationMatrix(jt),n.x=s,n.y=a,n.z=o,this}makePerspective(e,t,n,r,s,a,o=yn){const l=this.elements,c=2*s/(t-e),u=2*s/(n-r),d=(t+e)/(t-e),p=(n+r)/(n-r);let m,_;if(o===yn)m=-(a+s)/(a-s),_=-2*a*s/(a-s);else if(o===ds)m=-a/(a-s),_=-a*s/(a-s);else throw new Error("THREE.Matrix4.makePerspective(): Invalid coordinate system: "+o);return l[0]=c,l[4]=0,l[8]=d,l[12]=0,l[1]=0,l[5]=u,l[9]=p,l[13]=0,l[2]=0,l[6]=0,l[10]=m,l[14]=_,l[3]=0,l[7]=0,l[11]=-1,l[15]=0,this}makeOrthographic(e,t,n,r,s,a,o=yn){const l=this.elements,c=1/(t-e),u=1/(n-r),d=1/(a-s),p=(t+e)*c,m=(n+r)*u;let _,M;if(o===yn)_=(a+s)*d,M=-2*d;else if(o===ds)_=s*d,M=-1*d;else throw new Error("THREE.Matrix4.makeOrthographic(): Invalid coordinate system: "+o);return l[0]=2*c,l[4]=0,l[8]=0,l[12]=-p,l[1]=0,l[5]=2*u,l[9]=0,l[13]=-m,l[2]=0,l[6]=0,l[10]=M,l[14]=-_,l[3]=0,l[7]=0,l[11]=0,l[15]=1,this}equals(e){const t=this.elements,n=e.elements;for(let r=0;r<16;r++)if(t[r]!==n[r])return!1;return!0}fromArray(e,t=0){for(let n=0;n<16;n++)this.elements[n]=e[n+t];return this}toArray(e=[],t=0){const n=this.elements;return e[t]=n[0],e[t+1]=n[1],e[t+2]=n[2],e[t+3]=n[3],e[t+4]=n[4],e[t+5]=n[5],e[t+6]=n[6],e[t+7]=n[7],e[t+8]=n[8],e[t+9]=n[9],e[t+10]=n[10],e[t+11]=n[11],e[t+12]=n[12],e[t+13]=n[13],e[t+14]=n[14],e[t+15]=n[15],e}}const gi=new N,jt=new tt,Ad=new N(0,0,0),wd=new N(1,1,1),Rn=new N,Lr=new N,Ft=new N,nl=new tt,il=new _r;class En{constructor(e=0,t=0,n=0,r=En.DEFAULT_ORDER){this.isEuler=!0,this._x=e,this._y=t,this._z=n,this._order=r}get x(){return this._x}set x(e){this._x=e,this._onChangeCallback()}get y(){return this._y}set y(e){this._y=e,this._onChangeCallback()}get z(){return this._z}set z(e){this._z=e,this._onChangeCallback()}get order(){return this._order}set order(e){this._order=e,this._onChangeCallback()}set(e,t,n,r=this._order){return this._x=e,this._y=t,this._z=n,this._order=r,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._order)}copy(e){return this._x=e._x,this._y=e._y,this._z=e._z,this._order=e._order,this._onChangeCallback(),this}setFromRotationMatrix(e,t=this._order,n=!0){const r=e.elements,s=r[0],a=r[4],o=r[8],l=r[1],c=r[5],u=r[9],d=r[2],p=r[6],m=r[10];switch(t){case"XYZ":this._y=Math.asin(bt(o,-1,1)),Math.abs(o)<.9999999?(this._x=Math.atan2(-u,m),this._z=Math.atan2(-a,s)):(this._x=Math.atan2(p,c),this._z=0);break;case"YXZ":this._x=Math.asin(-bt(u,-1,1)),Math.abs(u)<.9999999?(this._y=Math.atan2(o,m),this._z=Math.atan2(l,c)):(this._y=Math.atan2(-d,s),this._z=0);break;case"ZXY":this._x=Math.asin(bt(p,-1,1)),Math.abs(p)<.9999999?(this._y=Math.atan2(-d,m),this._z=Math.atan2(-a,c)):(this._y=0,this._z=Math.atan2(l,s));break;case"ZYX":this._y=Math.asin(-bt(d,-1,1)),Math.abs(d)<.9999999?(this._x=Math.atan2(p,m),this._z=Math.atan2(l,s)):(this._x=0,this._z=Math.atan2(-a,c));break;case"YZX":this._z=Math.asin(bt(l,-1,1)),Math.abs(l)<.9999999?(this._x=Math.atan2(-u,c),this._y=Math.atan2(-d,s)):(this._x=0,this._y=Math.atan2(o,m));break;case"XZY":this._z=Math.asin(-bt(a,-1,1)),Math.abs(a)<.9999999?(this._x=Math.atan2(p,c),this._y=Math.atan2(o,s)):(this._x=Math.atan2(-u,m),this._y=0);break;default:console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: "+t)}return this._order=t,n===!0&&this._onChangeCallback(),this}setFromQuaternion(e,t,n){return nl.makeRotationFromQuaternion(e),this.setFromRotationMatrix(nl,t,n)}setFromVector3(e,t=this._order){return this.set(e.x,e.y,e.z,t)}reorder(e){return il.setFromEuler(this),this.setFromQuaternion(il,e)}equals(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._order===this._order}fromArray(e){return this._x=e[0],this._y=e[1],this._z=e[2],e[3]!==void 0&&(this._order=e[3]),this._onChangeCallback(),this}toArray(e=[],t=0){return e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._order,e}_onChange(e){return this._onChangeCallback=e,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._order}}En.DEFAULT_ORDER="XYZ";class gc{constructor(){this.mask=1}set(e){this.mask=(1<>>0}enable(e){this.mask|=1<1){for(let t=0;t1){for(let n=0;n0&&(r.userData=this.userData),r.layers=this.layers.mask,r.matrix=this.matrix.toArray(),r.up=this.up.toArray(),this.matrixAutoUpdate===!1&&(r.matrixAutoUpdate=!1),this.isInstancedMesh&&(r.type="InstancedMesh",r.count=this.count,r.instanceMatrix=this.instanceMatrix.toJSON(),this.instanceColor!==null&&(r.instanceColor=this.instanceColor.toJSON())),this.isBatchedMesh&&(r.type="BatchedMesh",r.perObjectFrustumCulled=this.perObjectFrustumCulled,r.sortObjects=this.sortObjects,r.drawRanges=this._drawRanges,r.reservedRanges=this._reservedRanges,r.visibility=this._visibility,r.active=this._active,r.bounds=this._bounds.map(o=>({boxInitialized:o.boxInitialized,boxMin:o.box.min.toArray(),boxMax:o.box.max.toArray(),sphereInitialized:o.sphereInitialized,sphereRadius:o.sphere.radius,sphereCenter:o.sphere.center.toArray()})),r.maxInstanceCount=this._maxInstanceCount,r.maxVertexCount=this._maxVertexCount,r.maxIndexCount=this._maxIndexCount,r.geometryInitialized=this._geometryInitialized,r.geometryCount=this._geometryCount,r.matricesTexture=this._matricesTexture.toJSON(e),this._colorsTexture!==null&&(r.colorsTexture=this._colorsTexture.toJSON(e)),this.boundingSphere!==null&&(r.boundingSphere={center:r.boundingSphere.center.toArray(),radius:r.boundingSphere.radius}),this.boundingBox!==null&&(r.boundingBox={min:r.boundingBox.min.toArray(),max:r.boundingBox.max.toArray()}));function s(o,l){return o[l.uuid]===void 0&&(o[l.uuid]=l.toJSON(e)),l.uuid}if(this.isScene)this.background&&(this.background.isColor?r.background=this.background.toJSON():this.background.isTexture&&(r.background=this.background.toJSON(e).uuid)),this.environment&&this.environment.isTexture&&this.environment.isRenderTargetTexture!==!0&&(r.environment=this.environment.toJSON(e).uuid);else if(this.isMesh||this.isLine||this.isPoints){r.geometry=s(e.geometries,this.geometry);const o=this.geometry.parameters;if(o!==void 0&&o.shapes!==void 0){const l=o.shapes;if(Array.isArray(l))for(let c=0,u=l.length;c0){r.children=[];for(let o=0;o0){r.animations=[];for(let o=0;o0&&(n.geometries=o),l.length>0&&(n.materials=l),c.length>0&&(n.textures=c),u.length>0&&(n.images=u),d.length>0&&(n.shapes=d),p.length>0&&(n.skeletons=p),m.length>0&&(n.animations=m),_.length>0&&(n.nodes=_)}return n.object=r,n;function a(o){const l=[];for(const c in o){const u=o[c];delete u.metadata,l.push(u)}return l}}clone(e){return new this.constructor().copy(this,e)}copy(e,t=!0){if(this.name=e.name,this.up.copy(e.up),this.position.copy(e.position),this.rotation.order=e.rotation.order,this.quaternion.copy(e.quaternion),this.scale.copy(e.scale),this.matrix.copy(e.matrix),this.matrixWorld.copy(e.matrixWorld),this.matrixAutoUpdate=e.matrixAutoUpdate,this.matrixWorldAutoUpdate=e.matrixWorldAutoUpdate,this.matrixWorldNeedsUpdate=e.matrixWorldNeedsUpdate,this.layers.mask=e.layers.mask,this.visible=e.visible,this.castShadow=e.castShadow,this.receiveShadow=e.receiveShadow,this.frustumCulled=e.frustumCulled,this.renderOrder=e.renderOrder,this.animations=e.animations.slice(),this.userData=JSON.parse(JSON.stringify(e.userData)),t===!0)for(let n=0;n0?r.multiplyScalar(1/Math.sqrt(s)):r.set(0,0,0)}static getBarycoord(e,t,n,r,s){$t.subVectors(r,t),mn.subVectors(n,t),Ws.subVectors(e,t);const a=$t.dot($t),o=$t.dot(mn),l=$t.dot(Ws),c=mn.dot(mn),u=mn.dot(Ws),d=a*c-o*o;if(d===0)return s.set(0,0,0),null;const p=1/d,m=(c*l-o*u)*p,_=(a*u-o*l)*p;return s.set(1-m-_,_,m)}static containsPoint(e,t,n,r){return this.getBarycoord(e,t,n,r,gn)===null?!1:gn.x>=0&&gn.y>=0&&gn.x+gn.y<=1}static getInterpolation(e,t,n,r,s,a,o,l){return this.getBarycoord(e,t,n,r,gn)===null?(l.x=0,l.y=0,"z"in l&&(l.z=0),"w"in l&&(l.w=0),null):(l.setScalar(0),l.addScaledVector(s,gn.x),l.addScaledVector(a,gn.y),l.addScaledVector(o,gn.z),l)}static getInterpolatedAttribute(e,t,n,r,s,a){return Zs.setScalar(0),Ks.setScalar(0),js.setScalar(0),Zs.fromBufferAttribute(e,t),Ks.fromBufferAttribute(e,n),js.fromBufferAttribute(e,r),a.setScalar(0),a.addScaledVector(Zs,s.x),a.addScaledVector(Ks,s.y),a.addScaledVector(js,s.z),a}static isFrontFacing(e,t,n,r){return $t.subVectors(n,t),mn.subVectors(e,t),$t.cross(mn).dot(r)<0}set(e,t,n){return this.a.copy(e),this.b.copy(t),this.c.copy(n),this}setFromPointsAndIndices(e,t,n,r){return this.a.copy(e[t]),this.b.copy(e[n]),this.c.copy(e[r]),this}setFromAttributeAndIndices(e,t,n,r){return this.a.fromBufferAttribute(e,t),this.b.fromBufferAttribute(e,n),this.c.fromBufferAttribute(e,r),this}clone(){return new this.constructor().copy(this)}copy(e){return this.a.copy(e.a),this.b.copy(e.b),this.c.copy(e.c),this}getArea(){return $t.subVectors(this.c,this.b),mn.subVectors(this.a,this.b),$t.cross(mn).length()*.5}getMidpoint(e){return e.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(e){return Jt.getNormal(this.a,this.b,this.c,e)}getPlane(e){return e.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(e,t){return Jt.getBarycoord(e,this.a,this.b,this.c,t)}getInterpolation(e,t,n,r,s){return Jt.getInterpolation(e,this.a,this.b,this.c,t,n,r,s)}containsPoint(e){return Jt.containsPoint(e,this.a,this.b,this.c)}isFrontFacing(e){return Jt.isFrontFacing(this.a,this.b,this.c,e)}intersectsBox(e){return e.intersectsTriangle(this)}closestPointToPoint(e,t){const n=this.a,r=this.b,s=this.c;let a,o;xi.subVectors(r,n),Si.subVectors(s,n),Xs.subVectors(e,n);const l=xi.dot(Xs),c=Si.dot(Xs);if(l<=0&&c<=0)return t.copy(n);qs.subVectors(e,r);const u=xi.dot(qs),d=Si.dot(qs);if(u>=0&&d<=u)return t.copy(r);const p=l*d-u*c;if(p<=0&&l>=0&&u<=0)return a=l/(l-u),t.copy(n).addScaledVector(xi,a);Ys.subVectors(e,s);const m=xi.dot(Ys),_=Si.dot(Ys);if(_>=0&&m<=_)return t.copy(s);const M=m*c-l*_;if(M<=0&&c>=0&&_<=0)return o=c/(c-_),t.copy(n).addScaledVector(Si,o);const f=u*_-m*d;if(f<=0&&d-u>=0&&m-_>=0)return cl.subVectors(s,r),o=(d-u)/(d-u+(m-_)),t.copy(r).addScaledVector(cl,o);const h=1/(f+M+p);return a=M*h,o=p*h,t.copy(n).addScaledVector(xi,a).addScaledVector(Si,o)}equals(e){return e.a.equals(this.a)&&e.b.equals(this.b)&&e.c.equals(this.c)}}const vc={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074},Cn={h:0,s:0,l:0},Ir={h:0,s:0,l:0};function $s(i,e,t){return t<0&&(t+=1),t>1&&(t-=1),t<1/6?i+(e-i)*6*t:t<1/2?e:t<2/3?i+(e-i)*6*(2/3-t):i}class Ye{constructor(e,t,n){return this.isColor=!0,this.r=1,this.g=1,this.b=1,this.set(e,t,n)}set(e,t,n){if(t===void 0&&n===void 0){const r=e;r&&r.isColor?this.copy(r):typeof r=="number"?this.setHex(r):typeof r=="string"&&this.setStyle(r)}else this.setRGB(e,t,n);return this}setScalar(e){return this.r=e,this.g=e,this.b=e,this}setHex(e,t=Bt){return e=Math.floor(e),this.r=(e>>16&255)/255,this.g=(e>>8&255)/255,this.b=(e&255)/255,qe.toWorkingColorSpace(this,t),this}setRGB(e,t,n,r=qe.workingColorSpace){return this.r=e,this.g=t,this.b=n,qe.toWorkingColorSpace(this,r),this}setHSL(e,t,n,r=qe.workingColorSpace){if(e=po(e,1),t=bt(t,0,1),n=bt(n,0,1),t===0)this.r=this.g=this.b=n;else{const s=n<=.5?n*(1+t):n+t-n*t,a=2*n-s;this.r=$s(a,s,e+1/3),this.g=$s(a,s,e),this.b=$s(a,s,e-1/3)}return qe.toWorkingColorSpace(this,r),this}setStyle(e,t=Bt){function n(s){s!==void 0&&parseFloat(s)<1&&console.warn("THREE.Color: Alpha component of "+e+" will be ignored.")}let r;if(r=/^(\w+)\(([^\)]*)\)/.exec(e)){let s;const a=r[1],o=r[2];switch(a){case"rgb":case"rgba":if(s=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return n(s[4]),this.setRGB(Math.min(255,parseInt(s[1],10))/255,Math.min(255,parseInt(s[2],10))/255,Math.min(255,parseInt(s[3],10))/255,t);if(s=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return n(s[4]),this.setRGB(Math.min(100,parseInt(s[1],10))/100,Math.min(100,parseInt(s[2],10))/100,Math.min(100,parseInt(s[3],10))/100,t);break;case"hsl":case"hsla":if(s=/^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return n(s[4]),this.setHSL(parseFloat(s[1])/360,parseFloat(s[2])/100,parseFloat(s[3])/100,t);break;default:console.warn("THREE.Color: Unknown color model "+e)}}else if(r=/^\#([A-Fa-f\d]+)$/.exec(e)){const s=r[1],a=s.length;if(a===3)return this.setRGB(parseInt(s.charAt(0),16)/15,parseInt(s.charAt(1),16)/15,parseInt(s.charAt(2),16)/15,t);if(a===6)return this.setHex(parseInt(s,16),t);console.warn("THREE.Color: Invalid hex color "+e)}else if(e&&e.length>0)return this.setColorName(e,t);return this}setColorName(e,t=Bt){const n=vc[e.toLowerCase()];return n!==void 0?this.setHex(n,t):console.warn("THREE.Color: Unknown color "+e),this}clone(){return new this.constructor(this.r,this.g,this.b)}copy(e){return this.r=e.r,this.g=e.g,this.b=e.b,this}copySRGBToLinear(e){return this.r=Pi(e.r),this.g=Pi(e.g),this.b=Pi(e.b),this}copyLinearToSRGB(e){return this.r=Ns(e.r),this.g=Ns(e.g),this.b=Ns(e.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(e=Bt){return qe.fromWorkingColorSpace(xt.copy(this),e),Math.round(bt(xt.r*255,0,255))*65536+Math.round(bt(xt.g*255,0,255))*256+Math.round(bt(xt.b*255,0,255))}getHexString(e=Bt){return("000000"+this.getHex(e).toString(16)).slice(-6)}getHSL(e,t=qe.workingColorSpace){qe.fromWorkingColorSpace(xt.copy(this),t);const n=xt.r,r=xt.g,s=xt.b,a=Math.max(n,r,s),o=Math.min(n,r,s);let l,c;const u=(o+a)/2;if(o===a)l=0,c=0;else{const d=a-o;switch(c=u<=.5?d/(a+o):d/(2-a-o),a){case n:l=(r-s)/d+(r0!=e>0&&this.version++,this._alphaTest=e}onBeforeRender(){}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(e){if(e!==void 0)for(const t in e){const n=e[t];if(n===void 0){console.warn(`THREE.Material: parameter '${t}' has value of undefined.`);continue}const r=this[t];if(r===void 0){console.warn(`THREE.Material: '${t}' is not a property of THREE.${this.type}.`);continue}r&&r.isColor?r.set(n):r&&r.isVector3&&n&&n.isVector3?r.copy(n):this[t]=n}}toJSON(e){const t=e===void 0||typeof e=="string";t&&(e={textures:{},images:{}});const n={metadata:{version:4.6,type:"Material",generator:"Material.toJSON"}};n.uuid=this.uuid,n.type=this.type,this.name!==""&&(n.name=this.name),this.color&&this.color.isColor&&(n.color=this.color.getHex()),this.roughness!==void 0&&(n.roughness=this.roughness),this.metalness!==void 0&&(n.metalness=this.metalness),this.sheen!==void 0&&(n.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(n.sheenColor=this.sheenColor.getHex()),this.sheenRoughness!==void 0&&(n.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(n.emissive=this.emissive.getHex()),this.emissiveIntensity!==void 0&&this.emissiveIntensity!==1&&(n.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(n.specular=this.specular.getHex()),this.specularIntensity!==void 0&&(n.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(n.specularColor=this.specularColor.getHex()),this.shininess!==void 0&&(n.shininess=this.shininess),this.clearcoat!==void 0&&(n.clearcoat=this.clearcoat),this.clearcoatRoughness!==void 0&&(n.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(n.clearcoatMap=this.clearcoatMap.toJSON(e).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(n.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(e).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(n.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(e).uuid,n.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),this.dispersion!==void 0&&(n.dispersion=this.dispersion),this.iridescence!==void 0&&(n.iridescence=this.iridescence),this.iridescenceIOR!==void 0&&(n.iridescenceIOR=this.iridescenceIOR),this.iridescenceThicknessRange!==void 0&&(n.iridescenceThicknessRange=this.iridescenceThicknessRange),this.iridescenceMap&&this.iridescenceMap.isTexture&&(n.iridescenceMap=this.iridescenceMap.toJSON(e).uuid),this.iridescenceThicknessMap&&this.iridescenceThicknessMap.isTexture&&(n.iridescenceThicknessMap=this.iridescenceThicknessMap.toJSON(e).uuid),this.anisotropy!==void 0&&(n.anisotropy=this.anisotropy),this.anisotropyRotation!==void 0&&(n.anisotropyRotation=this.anisotropyRotation),this.anisotropyMap&&this.anisotropyMap.isTexture&&(n.anisotropyMap=this.anisotropyMap.toJSON(e).uuid),this.map&&this.map.isTexture&&(n.map=this.map.toJSON(e).uuid),this.matcap&&this.matcap.isTexture&&(n.matcap=this.matcap.toJSON(e).uuid),this.alphaMap&&this.alphaMap.isTexture&&(n.alphaMap=this.alphaMap.toJSON(e).uuid),this.lightMap&&this.lightMap.isTexture&&(n.lightMap=this.lightMap.toJSON(e).uuid,n.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(n.aoMap=this.aoMap.toJSON(e).uuid,n.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(n.bumpMap=this.bumpMap.toJSON(e).uuid,n.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(n.normalMap=this.normalMap.toJSON(e).uuid,n.normalMapType=this.normalMapType,n.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(n.displacementMap=this.displacementMap.toJSON(e).uuid,n.displacementScale=this.displacementScale,n.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(n.roughnessMap=this.roughnessMap.toJSON(e).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(n.metalnessMap=this.metalnessMap.toJSON(e).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(n.emissiveMap=this.emissiveMap.toJSON(e).uuid),this.specularMap&&this.specularMap.isTexture&&(n.specularMap=this.specularMap.toJSON(e).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(n.specularIntensityMap=this.specularIntensityMap.toJSON(e).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(n.specularColorMap=this.specularColorMap.toJSON(e).uuid),this.envMap&&this.envMap.isTexture&&(n.envMap=this.envMap.toJSON(e).uuid,this.combine!==void 0&&(n.combine=this.combine)),this.envMapRotation!==void 0&&(n.envMapRotation=this.envMapRotation.toArray()),this.envMapIntensity!==void 0&&(n.envMapIntensity=this.envMapIntensity),this.reflectivity!==void 0&&(n.reflectivity=this.reflectivity),this.refractionRatio!==void 0&&(n.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(n.gradientMap=this.gradientMap.toJSON(e).uuid),this.transmission!==void 0&&(n.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(n.transmissionMap=this.transmissionMap.toJSON(e).uuid),this.thickness!==void 0&&(n.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(n.thicknessMap=this.thicknessMap.toJSON(e).uuid),this.attenuationDistance!==void 0&&this.attenuationDistance!==1/0&&(n.attenuationDistance=this.attenuationDistance),this.attenuationColor!==void 0&&(n.attenuationColor=this.attenuationColor.getHex()),this.size!==void 0&&(n.size=this.size),this.shadowSide!==null&&(n.shadowSide=this.shadowSide),this.sizeAttenuation!==void 0&&(n.sizeAttenuation=this.sizeAttenuation),this.blending!==Ci&&(n.blending=this.blending),this.side!==In&&(n.side=this.side),this.vertexColors===!0&&(n.vertexColors=!0),this.opacity<1&&(n.opacity=this.opacity),this.transparent===!0&&(n.transparent=!0),this.blendSrc!==da&&(n.blendSrc=this.blendSrc),this.blendDst!==ha&&(n.blendDst=this.blendDst),this.blendEquation!==jn&&(n.blendEquation=this.blendEquation),this.blendSrcAlpha!==null&&(n.blendSrcAlpha=this.blendSrcAlpha),this.blendDstAlpha!==null&&(n.blendDstAlpha=this.blendDstAlpha),this.blendEquationAlpha!==null&&(n.blendEquationAlpha=this.blendEquationAlpha),this.blendColor&&this.blendColor.isColor&&(n.blendColor=this.blendColor.getHex()),this.blendAlpha!==0&&(n.blendAlpha=this.blendAlpha),this.depthFunc!==Li&&(n.depthFunc=this.depthFunc),this.depthTest===!1&&(n.depthTest=this.depthTest),this.depthWrite===!1&&(n.depthWrite=this.depthWrite),this.colorWrite===!1&&(n.colorWrite=this.colorWrite),this.stencilWriteMask!==255&&(n.stencilWriteMask=this.stencilWriteMask),this.stencilFunc!==Zo&&(n.stencilFunc=this.stencilFunc),this.stencilRef!==0&&(n.stencilRef=this.stencilRef),this.stencilFuncMask!==255&&(n.stencilFuncMask=this.stencilFuncMask),this.stencilFail!==di&&(n.stencilFail=this.stencilFail),this.stencilZFail!==di&&(n.stencilZFail=this.stencilZFail),this.stencilZPass!==di&&(n.stencilZPass=this.stencilZPass),this.stencilWrite===!0&&(n.stencilWrite=this.stencilWrite),this.rotation!==void 0&&this.rotation!==0&&(n.rotation=this.rotation),this.polygonOffset===!0&&(n.polygonOffset=!0),this.polygonOffsetFactor!==0&&(n.polygonOffsetFactor=this.polygonOffsetFactor),this.polygonOffsetUnits!==0&&(n.polygonOffsetUnits=this.polygonOffsetUnits),this.linewidth!==void 0&&this.linewidth!==1&&(n.linewidth=this.linewidth),this.dashSize!==void 0&&(n.dashSize=this.dashSize),this.gapSize!==void 0&&(n.gapSize=this.gapSize),this.scale!==void 0&&(n.scale=this.scale),this.dithering===!0&&(n.dithering=!0),this.alphaTest>0&&(n.alphaTest=this.alphaTest),this.alphaHash===!0&&(n.alphaHash=!0),this.alphaToCoverage===!0&&(n.alphaToCoverage=!0),this.premultipliedAlpha===!0&&(n.premultipliedAlpha=!0),this.forceSinglePass===!0&&(n.forceSinglePass=!0),this.wireframe===!0&&(n.wireframe=!0),this.wireframeLinewidth>1&&(n.wireframeLinewidth=this.wireframeLinewidth),this.wireframeLinecap!=="round"&&(n.wireframeLinecap=this.wireframeLinecap),this.wireframeLinejoin!=="round"&&(n.wireframeLinejoin=this.wireframeLinejoin),this.flatShading===!0&&(n.flatShading=!0),this.visible===!1&&(n.visible=!1),this.toneMapped===!1&&(n.toneMapped=!1),this.fog===!1&&(n.fog=!1),Object.keys(this.userData).length>0&&(n.userData=this.userData);function r(s){const a=[];for(const o in s){const l=s[o];delete l.metadata,a.push(l)}return a}if(t){const s=r(e.textures),a=r(e.images);s.length>0&&(n.textures=s),a.length>0&&(n.images=a)}return n}clone(){return new this.constructor().copy(this)}copy(e){this.name=e.name,this.blending=e.blending,this.side=e.side,this.vertexColors=e.vertexColors,this.opacity=e.opacity,this.transparent=e.transparent,this.blendSrc=e.blendSrc,this.blendDst=e.blendDst,this.blendEquation=e.blendEquation,this.blendSrcAlpha=e.blendSrcAlpha,this.blendDstAlpha=e.blendDstAlpha,this.blendEquationAlpha=e.blendEquationAlpha,this.blendColor.copy(e.blendColor),this.blendAlpha=e.blendAlpha,this.depthFunc=e.depthFunc,this.depthTest=e.depthTest,this.depthWrite=e.depthWrite,this.stencilWriteMask=e.stencilWriteMask,this.stencilFunc=e.stencilFunc,this.stencilRef=e.stencilRef,this.stencilFuncMask=e.stencilFuncMask,this.stencilFail=e.stencilFail,this.stencilZFail=e.stencilZFail,this.stencilZPass=e.stencilZPass,this.stencilWrite=e.stencilWrite;const t=e.clippingPlanes;let n=null;if(t!==null){const r=t.length;n=new Array(r);for(let s=0;s!==r;++s)n[s]=t[s].clone()}return this.clippingPlanes=n,this.clipIntersection=e.clipIntersection,this.clipShadows=e.clipShadows,this.shadowSide=e.shadowSide,this.colorWrite=e.colorWrite,this.precision=e.precision,this.polygonOffset=e.polygonOffset,this.polygonOffsetFactor=e.polygonOffsetFactor,this.polygonOffsetUnits=e.polygonOffsetUnits,this.dithering=e.dithering,this.alphaTest=e.alphaTest,this.alphaHash=e.alphaHash,this.alphaToCoverage=e.alphaToCoverage,this.premultipliedAlpha=e.premultipliedAlpha,this.forceSinglePass=e.forceSinglePass,this.visible=e.visible,this.toneMapped=e.toneMapped,this.userData=JSON.parse(JSON.stringify(e.userData)),this}dispose(){this.dispatchEvent({type:"dispose"})}set needsUpdate(e){e===!0&&this.version++}onBuild(){console.warn("Material: onBuild() has been removed.")}}class sn extends Ss{constructor(e){super(),this.isMeshBasicMaterial=!0,this.type="MeshBasicMaterial",this.color=new Ye(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new En,this.combine=ec,this.reflectivity=1,this.refractionRatio=.98,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.fog=!0,this.setValues(e)}copy(e){return super.copy(e),this.color.copy(e.color),this.map=e.map,this.lightMap=e.lightMap,this.lightMapIntensity=e.lightMapIntensity,this.aoMap=e.aoMap,this.aoMapIntensity=e.aoMapIntensity,this.specularMap=e.specularMap,this.alphaMap=e.alphaMap,this.envMap=e.envMap,this.envMapRotation.copy(e.envMapRotation),this.combine=e.combine,this.reflectivity=e.reflectivity,this.refractionRatio=e.refractionRatio,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.fog=e.fog,this}}const at=new N,Nr=new Le;class en{constructor(e,t,n=!1){if(Array.isArray(e))throw new TypeError("THREE.BufferAttribute: array should be a Typed Array.");this.isBufferAttribute=!0,this.name="",this.array=e,this.itemSize=t,this.count=e!==void 0?e.length/t:0,this.normalized=n,this.usage=Ko,this.updateRanges=[],this.gpuType=Mn,this.version=0}onUploadCallback(){}set needsUpdate(e){e===!0&&this.version++}setUsage(e){return this.usage=e,this}addUpdateRange(e,t){this.updateRanges.push({start:e,count:t})}clearUpdateRanges(){this.updateRanges.length=0}copy(e){return this.name=e.name,this.array=new e.array.constructor(e.array),this.itemSize=e.itemSize,this.count=e.count,this.normalized=e.normalized,this.usage=e.usage,this.gpuType=e.gpuType,this}copyAt(e,t,n){e*=this.itemSize,n*=t.itemSize;for(let r=0,s=this.itemSize;r0&&(e.userData=this.userData),this.parameters!==void 0){const l=this.parameters;for(const c in l)l[c]!==void 0&&(e[c]=l[c]);return e}e.data={attributes:{}};const t=this.index;t!==null&&(e.data.index={type:t.array.constructor.name,array:Array.prototype.slice.call(t.array)});const n=this.attributes;for(const l in n){const c=n[l];e.data.attributes[l]=c.toJSON(e.data)}const r={};let s=!1;for(const l in this.morphAttributes){const c=this.morphAttributes[l],u=[];for(let d=0,p=c.length;d0&&(r[l]=u,s=!0)}s&&(e.data.morphAttributes=r,e.data.morphTargetsRelative=this.morphTargetsRelative);const a=this.groups;a.length>0&&(e.data.groups=JSON.parse(JSON.stringify(a)));const o=this.boundingSphere;return o!==null&&(e.data.boundingSphere={center:o.center.toArray(),radius:o.radius}),e}clone(){return new this.constructor().copy(this)}copy(e){this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null;const t={};this.name=e.name;const n=e.index;n!==null&&this.setIndex(n.clone(t));const r=e.attributes;for(const c in r){const u=r[c];this.setAttribute(c,u.clone(t))}const s=e.morphAttributes;for(const c in s){const u=[],d=s[c];for(let p=0,m=d.length;p0){const r=t[n[0]];if(r!==void 0){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let s=0,a=r.length;s(e.far-e.near)**2))&&(ul.copy(s).invert(),Wn.copy(e.ray).applyMatrix4(ul),!(n.boundingBox!==null&&Wn.intersectsBox(n.boundingBox)===!1)&&this._computeIntersections(e,t,Wn)))}_computeIntersections(e,t,n){let r;const s=this.geometry,a=this.material,o=s.index,l=s.attributes.position,c=s.attributes.uv,u=s.attributes.uv1,d=s.attributes.normal,p=s.groups,m=s.drawRange;if(o!==null)if(Array.isArray(a))for(let _=0,M=p.length;_t.far?null:{distance:c,point:Gr.clone(),object:i}}function Vr(i,e,t,n,r,s,a,o,l,c){i.getVertexPosition(o,Or),i.getVertexPosition(l,Br),i.getVertexPosition(c,zr);const u=Id(i,e,t,n,Or,Br,zr,hl);if(u){const d=new N;Jt.getBarycoord(hl,Or,Br,zr,d),r&&(u.uv=Jt.getInterpolatedAttribute(r,o,l,c,d,new Le)),s&&(u.uv1=Jt.getInterpolatedAttribute(s,o,l,c,d,new Le)),a&&(u.normal=Jt.getInterpolatedAttribute(a,o,l,c,d,new N),u.normal.dot(n.direction)>0&&u.normal.multiplyScalar(-1));const p={a:o,b:l,c,normal:new N,materialIndex:0};Jt.getNormal(Or,Br,zr,p.normal),u.face=p,u.barycoord=d}return u}class ki extends Hn{constructor(e=1,t=1,n=1,r=1,s=1,a=1){super(),this.type="BoxGeometry",this.parameters={width:e,height:t,depth:n,widthSegments:r,heightSegments:s,depthSegments:a};const o=this;r=Math.floor(r),s=Math.floor(s),a=Math.floor(a);const l=[],c=[],u=[],d=[];let p=0,m=0;_("z","y","x",-1,-1,n,t,e,a,s,0),_("z","y","x",1,-1,n,t,-e,a,s,1),_("x","z","y",1,1,e,n,t,r,a,2),_("x","z","y",1,-1,e,n,-t,r,a,3),_("x","y","z",1,-1,e,t,n,r,s,4),_("x","y","z",-1,-1,e,t,-n,r,s,5),this.setIndex(l),this.setAttribute("position",new ti(c,3)),this.setAttribute("normal",new ti(u,3)),this.setAttribute("uv",new ti(d,2));function _(M,f,h,T,y,b,O,C,A,F,te){const g=b/A,S=O/F,V=b/2,z=O/2,k=C/2,K=A+1,B=F+1;let Q=0,G=0;const le=new N;for(let ce=0;ce0?1:-1,u.push(le.x,le.y,le.z),d.push(Ge/A),d.push(1-ce/F),Q+=1}}for(let ce=0;ce0&&(t.defines=this.defines),t.vertexShader=this.vertexShader,t.fragmentShader=this.fragmentShader,t.lights=this.lights,t.clipping=this.clipping;const n={};for(const r in this.extensions)this.extensions[r]===!0&&(n[r]=!0);return Object.keys(n).length>0&&(t.extensions=n),t}}class Mc extends Ht{constructor(){super(),this.isCamera=!0,this.type="Camera",this.matrixWorldInverse=new tt,this.projectionMatrix=new tt,this.projectionMatrixInverse=new tt,this.coordinateSystem=yn}copy(e,t){return super.copy(e,t),this.matrixWorldInverse.copy(e.matrixWorldInverse),this.projectionMatrix.copy(e.projectionMatrix),this.projectionMatrixInverse.copy(e.projectionMatrixInverse),this.coordinateSystem=e.coordinateSystem,this}getWorldDirection(e){return super.getWorldDirection(e).negate()}updateMatrixWorld(e){super.updateMatrixWorld(e),this.matrixWorldInverse.copy(this.matrixWorld).invert()}updateWorldMatrix(e,t){super.updateWorldMatrix(e,t),this.matrixWorldInverse.copy(this.matrixWorld).invert()}clone(){return new this.constructor().copy(this)}}const Pn=new N,fl=new Le,pl=new Le;class Wt extends Mc{constructor(e=50,t=1,n=.1,r=2e3){super(),this.isPerspectiveCamera=!0,this.type="PerspectiveCamera",this.fov=e,this.zoom=1,this.near=n,this.far=r,this.focus=10,this.aspect=t,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}copy(e,t){return super.copy(e,t),this.fov=e.fov,this.zoom=e.zoom,this.near=e.near,this.far=e.far,this.focus=e.focus,this.aspect=e.aspect,this.view=e.view===null?null:Object.assign({},e.view),this.filmGauge=e.filmGauge,this.filmOffset=e.filmOffset,this}setFocalLength(e){const t=.5*this.getFilmHeight()/e;this.fov=ur*2*Math.atan(t),this.updateProjectionMatrix()}getFocalLength(){const e=Math.tan(tr*.5*this.fov);return .5*this.getFilmHeight()/e}getEffectiveFOV(){return ur*2*Math.atan(Math.tan(tr*.5*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}getViewBounds(e,t,n){Pn.set(-1,-1,.5).applyMatrix4(this.projectionMatrixInverse),t.set(Pn.x,Pn.y).multiplyScalar(-e/Pn.z),Pn.set(1,1,.5).applyMatrix4(this.projectionMatrixInverse),n.set(Pn.x,Pn.y).multiplyScalar(-e/Pn.z)}getViewSize(e,t){return this.getViewBounds(e,fl,pl),t.subVectors(pl,fl)}setViewOffset(e,t,n,r,s,a){this.aspect=e/t,this.view===null&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=e,this.view.fullHeight=t,this.view.offsetX=n,this.view.offsetY=r,this.view.width=s,this.view.height=a,this.updateProjectionMatrix()}clearViewOffset(){this.view!==null&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const e=this.near;let t=e*Math.tan(tr*.5*this.fov)/this.zoom,n=2*t,r=this.aspect*n,s=-.5*r;const a=this.view;if(this.view!==null&&this.view.enabled){const l=a.fullWidth,c=a.fullHeight;s+=a.offsetX*r/l,t-=a.offsetY*n/c,r*=a.width/l,n*=a.height/c}const o=this.filmOffset;o!==0&&(s+=e*o/this.getFilmWidth()),this.projectionMatrix.makePerspective(s,s+r,t,t-n,e,this.far,this.coordinateSystem),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(e){const t=super.toJSON(e);return t.object.fov=this.fov,t.object.zoom=this.zoom,t.object.near=this.near,t.object.far=this.far,t.object.focus=this.focus,t.object.aspect=this.aspect,this.view!==null&&(t.object.view=Object.assign({},this.view)),t.object.filmGauge=this.filmGauge,t.object.filmOffset=this.filmOffset,t}}const yi=-90,Ei=1;class zd extends Ht{constructor(e,t,n){super(),this.type="CubeCamera",this.renderTarget=n,this.coordinateSystem=null,this.activeMipmapLevel=0;const r=new Wt(yi,Ei,e,t);r.layers=this.layers,this.add(r);const s=new Wt(yi,Ei,e,t);s.layers=this.layers,this.add(s);const a=new Wt(yi,Ei,e,t);a.layers=this.layers,this.add(a);const o=new Wt(yi,Ei,e,t);o.layers=this.layers,this.add(o);const l=new Wt(yi,Ei,e,t);l.layers=this.layers,this.add(l);const c=new Wt(yi,Ei,e,t);c.layers=this.layers,this.add(c)}updateCoordinateSystem(){const e=this.coordinateSystem,t=this.children.concat(),[n,r,s,a,o,l]=t;for(const c of t)this.remove(c);if(e===yn)n.up.set(0,1,0),n.lookAt(1,0,0),r.up.set(0,1,0),r.lookAt(-1,0,0),s.up.set(0,0,-1),s.lookAt(0,1,0),a.up.set(0,0,1),a.lookAt(0,-1,0),o.up.set(0,1,0),o.lookAt(0,0,1),l.up.set(0,1,0),l.lookAt(0,0,-1);else if(e===ds)n.up.set(0,-1,0),n.lookAt(-1,0,0),r.up.set(0,-1,0),r.lookAt(1,0,0),s.up.set(0,0,1),s.lookAt(0,1,0),a.up.set(0,0,-1),a.lookAt(0,-1,0),o.up.set(0,-1,0),o.lookAt(0,0,1),l.up.set(0,-1,0),l.lookAt(0,0,-1);else throw new Error("THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: "+e);for(const c of t)this.add(c),c.updateMatrixWorld()}update(e,t){this.parent===null&&this.updateMatrixWorld();const{renderTarget:n,activeMipmapLevel:r}=this;this.coordinateSystem!==e.coordinateSystem&&(this.coordinateSystem=e.coordinateSystem,this.updateCoordinateSystem());const[s,a,o,l,c,u]=this.children,d=e.getRenderTarget(),p=e.getActiveCubeFace(),m=e.getActiveMipmapLevel(),_=e.xr.enabled;e.xr.enabled=!1;const M=n.texture.generateMipmaps;n.texture.generateMipmaps=!1,e.setRenderTarget(n,0,r),e.render(t,s),e.setRenderTarget(n,1,r),e.render(t,a),e.setRenderTarget(n,2,r),e.render(t,o),e.setRenderTarget(n,3,r),e.render(t,l),e.setRenderTarget(n,4,r),e.render(t,c),n.texture.generateMipmaps=M,e.setRenderTarget(n,5,r),e.render(t,u),e.setRenderTarget(d,p,m),e.xr.enabled=_,n.texture.needsPMREMUpdate=!0}}class yc extends vt{constructor(e,t,n,r,s,a,o,l,c,u){e=e!==void 0?e:[],t=t!==void 0?t:Ui,super(e,t,n,r,s,a,o,l,c,u),this.isCubeTexture=!0,this.flipY=!1}get images(){return this.image}set images(e){this.image=e}}class Hd extends nn{constructor(e=1,t={}){super(e,e,t),this.isWebGLCubeRenderTarget=!0;const n={width:e,height:e,depth:1},r=[n,n,n,n,n,n];this.texture=new yc(r,t.mapping,t.wrapS,t.wrapT,t.magFilter,t.minFilter,t.format,t.type,t.anisotropy,t.colorSpace),this.texture.isRenderTargetTexture=!0,this.texture.generateMipmaps=t.generateMipmaps!==void 0?t.generateMipmaps:!1,this.texture.minFilter=t.minFilter!==void 0?t.minFilter:ut}fromEquirectangularTexture(e,t){this.texture.type=t.type,this.texture.colorSpace=t.colorSpace,this.texture.generateMipmaps=t.generateMipmaps,this.texture.minFilter=t.minFilter,this.texture.magFilter=t.magFilter;const n={uniforms:{tEquirect:{value:null}},vertexShader:` - - varying vec3 vWorldDirection; - - vec3 transformDirection( in vec3 dir, in mat4 matrix ) { - - return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz ); - - } - - void main() { - - vWorldDirection = transformDirection( position, modelMatrix ); - - #include - #include - - } - `,fragmentShader:` - - uniform sampler2D tEquirect; - - varying vec3 vWorldDirection; - - #include - - void main() { - - vec3 direction = normalize( vWorldDirection ); - - vec2 sampleUV = equirectUv( direction ); - - gl_FragColor = texture2D( tEquirect, sampleUV ); - - } - `},r=new ki(5,5,5),s=new Gt({name:"CubemapFromEquirect",uniforms:Oi(n.uniforms),vertexShader:n.vertexShader,fragmentShader:n.fragmentShader,side:Lt,blending:Ln});s.uniforms.tEquirect.value=t;const a=new lt(r,s),o=t.minFilter;return t.minFilter===Qn&&(t.minFilter=ut),new zd(1,10,this).update(e,a),t.minFilter=o,a.geometry.dispose(),a.material.dispose(),this}clear(e,t,n,r){const s=e.getRenderTarget();for(let a=0;a<6;a++)e.setRenderTarget(this,a),e.clear(t,n,r);e.setRenderTarget(s)}}const ea=new N,Gd=new N,Vd=new De;class Zn{constructor(e=new N(1,0,0),t=0){this.isPlane=!0,this.normal=e,this.constant=t}set(e,t){return this.normal.copy(e),this.constant=t,this}setComponents(e,t,n,r){return this.normal.set(e,t,n),this.constant=r,this}setFromNormalAndCoplanarPoint(e,t){return this.normal.copy(e),this.constant=-t.dot(this.normal),this}setFromCoplanarPoints(e,t,n){const r=ea.subVectors(n,t).cross(Gd.subVectors(e,t)).normalize();return this.setFromNormalAndCoplanarPoint(r,e),this}copy(e){return this.normal.copy(e.normal),this.constant=e.constant,this}normalize(){const e=1/this.normal.length();return this.normal.multiplyScalar(e),this.constant*=e,this}negate(){return this.constant*=-1,this.normal.negate(),this}distanceToPoint(e){return this.normal.dot(e)+this.constant}distanceToSphere(e){return this.distanceToPoint(e.center)-e.radius}projectPoint(e,t){return t.copy(e).addScaledVector(this.normal,-this.distanceToPoint(e))}intersectLine(e,t){const n=e.delta(ea),r=this.normal.dot(n);if(r===0)return this.distanceToPoint(e.start)===0?t.copy(e.start):null;const s=-(e.start.dot(this.normal)+this.constant)/r;return s<0||s>1?null:t.copy(e.start).addScaledVector(n,s)}intersectsLine(e){const t=this.distanceToPoint(e.start),n=this.distanceToPoint(e.end);return t<0&&n>0||n<0&&t>0}intersectsBox(e){return e.intersectsPlane(this)}intersectsSphere(e){return e.intersectsPlane(this)}coplanarPoint(e){return e.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(e,t){const n=t||Vd.getNormalMatrix(e),r=this.coplanarPoint(ea).applyMatrix4(e),s=this.normal.applyMatrix3(n).normalize();return this.constant=-r.dot(s),this}translate(e){return this.constant-=e.dot(this.normal),this}equals(e){return e.normal.equals(this.normal)&&e.constant===this.constant}clone(){return new this.constructor().copy(this)}}const Xn=new mo,kr=new N;class Ec{constructor(e=new Zn,t=new Zn,n=new Zn,r=new Zn,s=new Zn,a=new Zn){this.planes=[e,t,n,r,s,a]}set(e,t,n,r,s,a){const o=this.planes;return o[0].copy(e),o[1].copy(t),o[2].copy(n),o[3].copy(r),o[4].copy(s),o[5].copy(a),this}copy(e){const t=this.planes;for(let n=0;n<6;n++)t[n].copy(e.planes[n]);return this}setFromProjectionMatrix(e,t=yn){const n=this.planes,r=e.elements,s=r[0],a=r[1],o=r[2],l=r[3],c=r[4],u=r[5],d=r[6],p=r[7],m=r[8],_=r[9],M=r[10],f=r[11],h=r[12],T=r[13],y=r[14],b=r[15];if(n[0].setComponents(l-s,p-c,f-m,b-h).normalize(),n[1].setComponents(l+s,p+c,f+m,b+h).normalize(),n[2].setComponents(l+a,p+u,f+_,b+T).normalize(),n[3].setComponents(l-a,p-u,f-_,b-T).normalize(),n[4].setComponents(l-o,p-d,f-M,b-y).normalize(),t===yn)n[5].setComponents(l+o,p+d,f+M,b+y).normalize();else if(t===ds)n[5].setComponents(o,d,M,y).normalize();else throw new Error("THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: "+t);return this}intersectsObject(e){if(e.boundingSphere!==void 0)e.boundingSphere===null&&e.computeBoundingSphere(),Xn.copy(e.boundingSphere).applyMatrix4(e.matrixWorld);else{const t=e.geometry;t.boundingSphere===null&&t.computeBoundingSphere(),Xn.copy(t.boundingSphere).applyMatrix4(e.matrixWorld)}return this.intersectsSphere(Xn)}intersectsSprite(e){return Xn.center.set(0,0,0),Xn.radius=.7071067811865476,Xn.applyMatrix4(e.matrixWorld),this.intersectsSphere(Xn)}intersectsSphere(e){const t=this.planes,n=e.center,r=-e.radius;for(let s=0;s<6;s++)if(t[s].distanceToPoint(n)0?e.max.x:e.min.x,kr.y=r.normal.y>0?e.max.y:e.min.y,kr.z=r.normal.z>0?e.max.z:e.min.z,r.distanceToPoint(kr)<0)return!1}return!0}containsPoint(e){const t=this.planes;for(let n=0;n<6;n++)if(t[n].distanceToPoint(e)<0)return!1;return!0}clone(){return new this.constructor().copy(this)}}function Tc(){let i=null,e=!1,t=null,n=null;function r(s,a){t(s,a),n=i.requestAnimationFrame(r)}return{start:function(){e!==!0&&t!==null&&(n=i.requestAnimationFrame(r),e=!0)},stop:function(){i.cancelAnimationFrame(n),e=!1},setAnimationLoop:function(s){t=s},setContext:function(s){i=s}}}function kd(i){const e=new WeakMap;function t(o,l){const c=o.array,u=o.usage,d=c.byteLength,p=i.createBuffer();i.bindBuffer(l,p),i.bufferData(l,c,u),o.onUploadCallback();let m;if(c instanceof Float32Array)m=i.FLOAT;else if(c instanceof Uint16Array)o.isFloat16BufferAttribute?m=i.HALF_FLOAT:m=i.UNSIGNED_SHORT;else if(c instanceof Int16Array)m=i.SHORT;else if(c instanceof Uint32Array)m=i.UNSIGNED_INT;else if(c instanceof Int32Array)m=i.INT;else if(c instanceof Int8Array)m=i.BYTE;else if(c instanceof Uint8Array)m=i.UNSIGNED_BYTE;else if(c instanceof Uint8ClampedArray)m=i.UNSIGNED_BYTE;else throw new Error("THREE.WebGLAttributes: Unsupported buffer data format: "+c);return{buffer:p,type:m,bytesPerElement:c.BYTES_PER_ELEMENT,version:o.version,size:d}}function n(o,l,c){const u=l.array,d=l.updateRanges;if(i.bindBuffer(c,o),d.length===0)i.bufferSubData(c,0,u);else{d.sort((m,_)=>m.start-_.start);let p=0;for(let m=1;m 0 - vec4 plane; - #ifdef ALPHA_TO_COVERAGE - float distanceToPlane, distanceGradient; - float clipOpacity = 1.0; - #pragma unroll_loop_start - for ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) { - plane = clippingPlanes[ i ]; - distanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w; - distanceGradient = fwidth( distanceToPlane ) / 2.0; - clipOpacity *= smoothstep( - distanceGradient, distanceGradient, distanceToPlane ); - if ( clipOpacity == 0.0 ) discard; - } - #pragma unroll_loop_end - #if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES - float unionClipOpacity = 1.0; - #pragma unroll_loop_start - for ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) { - plane = clippingPlanes[ i ]; - distanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w; - distanceGradient = fwidth( distanceToPlane ) / 2.0; - unionClipOpacity *= 1.0 - smoothstep( - distanceGradient, distanceGradient, distanceToPlane ); - } - #pragma unroll_loop_end - clipOpacity *= 1.0 - unionClipOpacity; - #endif - diffuseColor.a *= clipOpacity; - if ( diffuseColor.a == 0.0 ) discard; - #else - #pragma unroll_loop_start - for ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) { - plane = clippingPlanes[ i ]; - if ( dot( vClipPosition, plane.xyz ) > plane.w ) discard; - } - #pragma unroll_loop_end - #if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES - bool clipped = true; - #pragma unroll_loop_start - for ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) { - plane = clippingPlanes[ i ]; - clipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped; - } - #pragma unroll_loop_end - if ( clipped ) discard; - #endif - #endif -#endif`,ah=`#if NUM_CLIPPING_PLANES > 0 - varying vec3 vClipPosition; - uniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ]; -#endif`,oh=`#if NUM_CLIPPING_PLANES > 0 - varying vec3 vClipPosition; -#endif`,lh=`#if NUM_CLIPPING_PLANES > 0 - vClipPosition = - mvPosition.xyz; -#endif`,ch=`#if defined( USE_COLOR_ALPHA ) - diffuseColor *= vColor; -#elif defined( USE_COLOR ) - diffuseColor.rgb *= vColor; -#endif`,uh=`#if defined( USE_COLOR_ALPHA ) - varying vec4 vColor; -#elif defined( USE_COLOR ) - varying vec3 vColor; -#endif`,dh=`#if defined( USE_COLOR_ALPHA ) - varying vec4 vColor; -#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR ) - varying vec3 vColor; -#endif`,hh=`#if defined( USE_COLOR_ALPHA ) - vColor = vec4( 1.0 ); -#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_COLOR ) - vColor = vec3( 1.0 ); -#endif -#ifdef USE_COLOR - vColor *= color; -#endif -#ifdef USE_INSTANCING_COLOR - vColor.xyz *= instanceColor.xyz; -#endif -#ifdef USE_BATCHING_COLOR - vec3 batchingColor = getBatchingColor( getIndirectIndex( gl_DrawID ) ); - vColor.xyz *= batchingColor.xyz; -#endif`,fh=`#define PI 3.141592653589793 -#define PI2 6.283185307179586 -#define PI_HALF 1.5707963267948966 -#define RECIPROCAL_PI 0.3183098861837907 -#define RECIPROCAL_PI2 0.15915494309189535 -#define EPSILON 1e-6 -#ifndef saturate -#define saturate( a ) clamp( a, 0.0, 1.0 ) -#endif -#define whiteComplement( a ) ( 1.0 - saturate( a ) ) -float pow2( const in float x ) { return x*x; } -vec3 pow2( const in vec3 x ) { return x*x; } -float pow3( const in float x ) { return x*x*x; } -float pow4( const in float x ) { float x2 = x*x; return x2*x2; } -float max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); } -float average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); } -highp float rand( const in vec2 uv ) { - const highp float a = 12.9898, b = 78.233, c = 43758.5453; - highp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI ); - return fract( sin( sn ) * c ); -} -#ifdef HIGH_PRECISION - float precisionSafeLength( vec3 v ) { return length( v ); } -#else - float precisionSafeLength( vec3 v ) { - float maxComponent = max3( abs( v ) ); - return length( v / maxComponent ) * maxComponent; - } -#endif -struct IncidentLight { - vec3 color; - vec3 direction; - bool visible; -}; -struct ReflectedLight { - vec3 directDiffuse; - vec3 directSpecular; - vec3 indirectDiffuse; - vec3 indirectSpecular; -}; -#ifdef USE_ALPHAHASH - varying vec3 vPosition; -#endif -vec3 transformDirection( in vec3 dir, in mat4 matrix ) { - return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz ); -} -vec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) { - return normalize( ( vec4( dir, 0.0 ) * matrix ).xyz ); -} -mat3 transposeMat3( const in mat3 m ) { - mat3 tmp; - tmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x ); - tmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y ); - tmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z ); - return tmp; -} -bool isPerspectiveMatrix( mat4 m ) { - return m[ 2 ][ 3 ] == - 1.0; -} -vec2 equirectUv( in vec3 dir ) { - float u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5; - float v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5; - return vec2( u, v ); -} -vec3 BRDF_Lambert( const in vec3 diffuseColor ) { - return RECIPROCAL_PI * diffuseColor; -} -vec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) { - float fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH ); - return f0 * ( 1.0 - fresnel ) + ( f90 * fresnel ); -} -float F_Schlick( const in float f0, const in float f90, const in float dotVH ) { - float fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH ); - return f0 * ( 1.0 - fresnel ) + ( f90 * fresnel ); -} // validated`,ph=`#ifdef ENVMAP_TYPE_CUBE_UV - #define cubeUV_minMipLevel 4.0 - #define cubeUV_minTileSize 16.0 - float getFace( vec3 direction ) { - vec3 absDirection = abs( direction ); - float face = - 1.0; - if ( absDirection.x > absDirection.z ) { - if ( absDirection.x > absDirection.y ) - face = direction.x > 0.0 ? 0.0 : 3.0; - else - face = direction.y > 0.0 ? 1.0 : 4.0; - } else { - if ( absDirection.z > absDirection.y ) - face = direction.z > 0.0 ? 2.0 : 5.0; - else - face = direction.y > 0.0 ? 1.0 : 4.0; - } - return face; - } - vec2 getUV( vec3 direction, float face ) { - vec2 uv; - if ( face == 0.0 ) { - uv = vec2( direction.z, direction.y ) / abs( direction.x ); - } else if ( face == 1.0 ) { - uv = vec2( - direction.x, - direction.z ) / abs( direction.y ); - } else if ( face == 2.0 ) { - uv = vec2( - direction.x, direction.y ) / abs( direction.z ); - } else if ( face == 3.0 ) { - uv = vec2( - direction.z, direction.y ) / abs( direction.x ); - } else if ( face == 4.0 ) { - uv = vec2( - direction.x, direction.z ) / abs( direction.y ); - } else { - uv = vec2( direction.x, direction.y ) / abs( direction.z ); - } - return 0.5 * ( uv + 1.0 ); - } - vec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) { - float face = getFace( direction ); - float filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 ); - mipInt = max( mipInt, cubeUV_minMipLevel ); - float faceSize = exp2( mipInt ); - highp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0; - if ( face > 2.0 ) { - uv.y += faceSize; - face -= 3.0; - } - uv.x += face * faceSize; - uv.x += filterInt * 3.0 * cubeUV_minTileSize; - uv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize ); - uv.x *= CUBEUV_TEXEL_WIDTH; - uv.y *= CUBEUV_TEXEL_HEIGHT; - #ifdef texture2DGradEXT - return texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb; - #else - return texture2D( envMap, uv ).rgb; - #endif - } - #define cubeUV_r0 1.0 - #define cubeUV_m0 - 2.0 - #define cubeUV_r1 0.8 - #define cubeUV_m1 - 1.0 - #define cubeUV_r4 0.4 - #define cubeUV_m4 2.0 - #define cubeUV_r5 0.305 - #define cubeUV_m5 3.0 - #define cubeUV_r6 0.21 - #define cubeUV_m6 4.0 - float roughnessToMip( float roughness ) { - float mip = 0.0; - if ( roughness >= cubeUV_r1 ) { - mip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0; - } else if ( roughness >= cubeUV_r4 ) { - mip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1; - } else if ( roughness >= cubeUV_r5 ) { - mip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4; - } else if ( roughness >= cubeUV_r6 ) { - mip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5; - } else { - mip = - 2.0 * log2( 1.16 * roughness ); } - return mip; - } - vec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) { - float mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP ); - float mipF = fract( mip ); - float mipInt = floor( mip ); - vec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt ); - if ( mipF == 0.0 ) { - return vec4( color0, 1.0 ); - } else { - vec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 ); - return vec4( mix( color0, color1, mipF ), 1.0 ); - } - } -#endif`,mh=`vec3 transformedNormal = objectNormal; -#ifdef USE_TANGENT - vec3 transformedTangent = objectTangent; -#endif -#ifdef USE_BATCHING - mat3 bm = mat3( batchingMatrix ); - transformedNormal /= vec3( dot( bm[ 0 ], bm[ 0 ] ), dot( bm[ 1 ], bm[ 1 ] ), dot( bm[ 2 ], bm[ 2 ] ) ); - transformedNormal = bm * transformedNormal; - #ifdef USE_TANGENT - transformedTangent = bm * transformedTangent; - #endif -#endif -#ifdef USE_INSTANCING - mat3 im = mat3( instanceMatrix ); - transformedNormal /= vec3( dot( im[ 0 ], im[ 0 ] ), dot( im[ 1 ], im[ 1 ] ), dot( im[ 2 ], im[ 2 ] ) ); - transformedNormal = im * transformedNormal; - #ifdef USE_TANGENT - transformedTangent = im * transformedTangent; - #endif -#endif -transformedNormal = normalMatrix * transformedNormal; -#ifdef FLIP_SIDED - transformedNormal = - transformedNormal; -#endif -#ifdef USE_TANGENT - transformedTangent = ( modelViewMatrix * vec4( transformedTangent, 0.0 ) ).xyz; - #ifdef FLIP_SIDED - transformedTangent = - transformedTangent; - #endif -#endif`,gh=`#ifdef USE_DISPLACEMENTMAP - uniform sampler2D displacementMap; - uniform float displacementScale; - uniform float displacementBias; -#endif`,vh=`#ifdef USE_DISPLACEMENTMAP - transformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias ); -#endif`,_h=`#ifdef USE_EMISSIVEMAP - vec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv ); - totalEmissiveRadiance *= emissiveColor.rgb; -#endif`,xh=`#ifdef USE_EMISSIVEMAP - uniform sampler2D emissiveMap; -#endif`,Sh="gl_FragColor = linearToOutputTexel( gl_FragColor );",Mh=` -const mat3 LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = mat3( - vec3( 0.8224621, 0.177538, 0.0 ), - vec3( 0.0331941, 0.9668058, 0.0 ), - vec3( 0.0170827, 0.0723974, 0.9105199 ) -); -const mat3 LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = mat3( - vec3( 1.2249401, - 0.2249404, 0.0 ), - vec3( - 0.0420569, 1.0420571, 0.0 ), - vec3( - 0.0196376, - 0.0786361, 1.0982735 ) -); -vec4 LinearSRGBToLinearDisplayP3( in vec4 value ) { - return vec4( value.rgb * LINEAR_SRGB_TO_LINEAR_DISPLAY_P3, value.a ); -} -vec4 LinearDisplayP3ToLinearSRGB( in vec4 value ) { - return vec4( value.rgb * LINEAR_DISPLAY_P3_TO_LINEAR_SRGB, value.a ); -} -vec4 LinearTransferOETF( in vec4 value ) { - return value; -} -vec4 sRGBTransferOETF( in vec4 value ) { - return vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a ); -}`,yh=`#ifdef USE_ENVMAP - #ifdef ENV_WORLDPOS - vec3 cameraToFrag; - if ( isOrthographic ) { - cameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) ); - } else { - cameraToFrag = normalize( vWorldPosition - cameraPosition ); - } - vec3 worldNormal = inverseTransformDirection( normal, viewMatrix ); - #ifdef ENVMAP_MODE_REFLECTION - vec3 reflectVec = reflect( cameraToFrag, worldNormal ); - #else - vec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio ); - #endif - #else - vec3 reflectVec = vReflect; - #endif - #ifdef ENVMAP_TYPE_CUBE - vec4 envColor = textureCube( envMap, envMapRotation * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) ); - #else - vec4 envColor = vec4( 0.0 ); - #endif - #ifdef ENVMAP_BLENDING_MULTIPLY - outgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity ); - #elif defined( ENVMAP_BLENDING_MIX ) - outgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity ); - #elif defined( ENVMAP_BLENDING_ADD ) - outgoingLight += envColor.xyz * specularStrength * reflectivity; - #endif -#endif`,Eh=`#ifdef USE_ENVMAP - uniform float envMapIntensity; - uniform float flipEnvMap; - uniform mat3 envMapRotation; - #ifdef ENVMAP_TYPE_CUBE - uniform samplerCube envMap; - #else - uniform sampler2D envMap; - #endif - -#endif`,Th=`#ifdef USE_ENVMAP - uniform float reflectivity; - #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT ) - #define ENV_WORLDPOS - #endif - #ifdef ENV_WORLDPOS - varying vec3 vWorldPosition; - uniform float refractionRatio; - #else - varying vec3 vReflect; - #endif -#endif`,bh=`#ifdef USE_ENVMAP - #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT ) - #define ENV_WORLDPOS - #endif - #ifdef ENV_WORLDPOS - - varying vec3 vWorldPosition; - #else - varying vec3 vReflect; - uniform float refractionRatio; - #endif -#endif`,Ah=`#ifdef USE_ENVMAP - #ifdef ENV_WORLDPOS - vWorldPosition = worldPosition.xyz; - #else - vec3 cameraToVertex; - if ( isOrthographic ) { - cameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) ); - } else { - cameraToVertex = normalize( worldPosition.xyz - cameraPosition ); - } - vec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix ); - #ifdef ENVMAP_MODE_REFLECTION - vReflect = reflect( cameraToVertex, worldNormal ); - #else - vReflect = refract( cameraToVertex, worldNormal, refractionRatio ); - #endif - #endif -#endif`,wh=`#ifdef USE_FOG - vFogDepth = - mvPosition.z; -#endif`,Rh=`#ifdef USE_FOG - varying float vFogDepth; -#endif`,Ch=`#ifdef USE_FOG - #ifdef FOG_EXP2 - float fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth ); - #else - float fogFactor = smoothstep( fogNear, fogFar, vFogDepth ); - #endif - gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor ); -#endif`,Ph=`#ifdef USE_FOG - uniform vec3 fogColor; - varying float vFogDepth; - #ifdef FOG_EXP2 - uniform float fogDensity; - #else - uniform float fogNear; - uniform float fogFar; - #endif -#endif`,Dh=`#ifdef USE_GRADIENTMAP - uniform sampler2D gradientMap; -#endif -vec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) { - float dotNL = dot( normal, lightDirection ); - vec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 ); - #ifdef USE_GRADIENTMAP - return vec3( texture2D( gradientMap, coord ).r ); - #else - vec2 fw = fwidth( coord ) * 0.5; - return mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) ); - #endif -}`,Lh=`#ifdef USE_LIGHTMAP - uniform sampler2D lightMap; - uniform float lightMapIntensity; -#endif`,Uh=`LambertMaterial material; -material.diffuseColor = diffuseColor.rgb; -material.specularStrength = specularStrength;`,Ih=`varying vec3 vViewPosition; -struct LambertMaterial { - vec3 diffuseColor; - float specularStrength; -}; -void RE_Direct_Lambert( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) { - float dotNL = saturate( dot( geometryNormal, directLight.direction ) ); - vec3 irradiance = dotNL * directLight.color; - reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); -} -void RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) { - reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); -} -#define RE_Direct RE_Direct_Lambert -#define RE_IndirectDiffuse RE_IndirectDiffuse_Lambert`,Nh=`uniform bool receiveShadow; -uniform vec3 ambientLightColor; -#if defined( USE_LIGHT_PROBES ) - uniform vec3 lightProbe[ 9 ]; -#endif -vec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) { - float x = normal.x, y = normal.y, z = normal.z; - vec3 result = shCoefficients[ 0 ] * 0.886227; - result += shCoefficients[ 1 ] * 2.0 * 0.511664 * y; - result += shCoefficients[ 2 ] * 2.0 * 0.511664 * z; - result += shCoefficients[ 3 ] * 2.0 * 0.511664 * x; - result += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y; - result += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z; - result += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 ); - result += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z; - result += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y ); - return result; -} -vec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) { - vec3 worldNormal = inverseTransformDirection( normal, viewMatrix ); - vec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe ); - return irradiance; -} -vec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) { - vec3 irradiance = ambientLightColor; - return irradiance; -} -float getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) { - float distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 ); - if ( cutoffDistance > 0.0 ) { - distanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) ); - } - return distanceFalloff; -} -float getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) { - return smoothstep( coneCosine, penumbraCosine, angleCosine ); -} -#if NUM_DIR_LIGHTS > 0 - struct DirectionalLight { - vec3 direction; - vec3 color; - }; - uniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ]; - void getDirectionalLightInfo( const in DirectionalLight directionalLight, out IncidentLight light ) { - light.color = directionalLight.color; - light.direction = directionalLight.direction; - light.visible = true; - } -#endif -#if NUM_POINT_LIGHTS > 0 - struct PointLight { - vec3 position; - vec3 color; - float distance; - float decay; - }; - uniform PointLight pointLights[ NUM_POINT_LIGHTS ]; - void getPointLightInfo( const in PointLight pointLight, const in vec3 geometryPosition, out IncidentLight light ) { - vec3 lVector = pointLight.position - geometryPosition; - light.direction = normalize( lVector ); - float lightDistance = length( lVector ); - light.color = pointLight.color; - light.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay ); - light.visible = ( light.color != vec3( 0.0 ) ); - } -#endif -#if NUM_SPOT_LIGHTS > 0 - struct SpotLight { - vec3 position; - vec3 direction; - vec3 color; - float distance; - float decay; - float coneCos; - float penumbraCos; - }; - uniform SpotLight spotLights[ NUM_SPOT_LIGHTS ]; - void getSpotLightInfo( const in SpotLight spotLight, const in vec3 geometryPosition, out IncidentLight light ) { - vec3 lVector = spotLight.position - geometryPosition; - light.direction = normalize( lVector ); - float angleCos = dot( light.direction, spotLight.direction ); - float spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos ); - if ( spotAttenuation > 0.0 ) { - float lightDistance = length( lVector ); - light.color = spotLight.color * spotAttenuation; - light.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay ); - light.visible = ( light.color != vec3( 0.0 ) ); - } else { - light.color = vec3( 0.0 ); - light.visible = false; - } - } -#endif -#if NUM_RECT_AREA_LIGHTS > 0 - struct RectAreaLight { - vec3 color; - vec3 position; - vec3 halfWidth; - vec3 halfHeight; - }; - uniform sampler2D ltc_1; uniform sampler2D ltc_2; - uniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ]; -#endif -#if NUM_HEMI_LIGHTS > 0 - struct HemisphereLight { - vec3 direction; - vec3 skyColor; - vec3 groundColor; - }; - uniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ]; - vec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) { - float dotNL = dot( normal, hemiLight.direction ); - float hemiDiffuseWeight = 0.5 * dotNL + 0.5; - vec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight ); - return irradiance; - } -#endif`,Fh=`#ifdef USE_ENVMAP - vec3 getIBLIrradiance( const in vec3 normal ) { - #ifdef ENVMAP_TYPE_CUBE_UV - vec3 worldNormal = inverseTransformDirection( normal, viewMatrix ); - vec4 envMapColor = textureCubeUV( envMap, envMapRotation * worldNormal, 1.0 ); - return PI * envMapColor.rgb * envMapIntensity; - #else - return vec3( 0.0 ); - #endif - } - vec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) { - #ifdef ENVMAP_TYPE_CUBE_UV - vec3 reflectVec = reflect( - viewDir, normal ); - reflectVec = normalize( mix( reflectVec, normal, roughness * roughness) ); - reflectVec = inverseTransformDirection( reflectVec, viewMatrix ); - vec4 envMapColor = textureCubeUV( envMap, envMapRotation * reflectVec, roughness ); - return envMapColor.rgb * envMapIntensity; - #else - return vec3( 0.0 ); - #endif - } - #ifdef USE_ANISOTROPY - vec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) { - #ifdef ENVMAP_TYPE_CUBE_UV - vec3 bentNormal = cross( bitangent, viewDir ); - bentNormal = normalize( cross( bentNormal, bitangent ) ); - bentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) ); - return getIBLRadiance( viewDir, bentNormal, roughness ); - #else - return vec3( 0.0 ); - #endif - } - #endif -#endif`,Oh=`ToonMaterial material; -material.diffuseColor = diffuseColor.rgb;`,Bh=`varying vec3 vViewPosition; -struct ToonMaterial { - vec3 diffuseColor; -}; -void RE_Direct_Toon( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) { - vec3 irradiance = getGradientIrradiance( geometryNormal, directLight.direction ) * directLight.color; - reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); -} -void RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) { - reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); -} -#define RE_Direct RE_Direct_Toon -#define RE_IndirectDiffuse RE_IndirectDiffuse_Toon`,zh=`BlinnPhongMaterial material; -material.diffuseColor = diffuseColor.rgb; -material.specularColor = specular; -material.specularShininess = shininess; -material.specularStrength = specularStrength;`,Hh=`varying vec3 vViewPosition; -struct BlinnPhongMaterial { - vec3 diffuseColor; - vec3 specularColor; - float specularShininess; - float specularStrength; -}; -void RE_Direct_BlinnPhong( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) { - float dotNL = saturate( dot( geometryNormal, directLight.direction ) ); - vec3 irradiance = dotNL * directLight.color; - reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); - reflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometryViewDir, geometryNormal, material.specularColor, material.specularShininess ) * material.specularStrength; -} -void RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) { - reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); -} -#define RE_Direct RE_Direct_BlinnPhong -#define RE_IndirectDiffuse RE_IndirectDiffuse_BlinnPhong`,Gh=`PhysicalMaterial material; -material.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor ); -vec3 dxy = max( abs( dFdx( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) ); -float geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z ); -material.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness; -material.roughness = min( material.roughness, 1.0 ); -#ifdef IOR - material.ior = ior; - #ifdef USE_SPECULAR - float specularIntensityFactor = specularIntensity; - vec3 specularColorFactor = specularColor; - #ifdef USE_SPECULAR_COLORMAP - specularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb; - #endif - #ifdef USE_SPECULAR_INTENSITYMAP - specularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a; - #endif - material.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor ); - #else - float specularIntensityFactor = 1.0; - vec3 specularColorFactor = vec3( 1.0 ); - material.specularF90 = 1.0; - #endif - material.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor ); -#else - material.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor ); - material.specularF90 = 1.0; -#endif -#ifdef USE_CLEARCOAT - material.clearcoat = clearcoat; - material.clearcoatRoughness = clearcoatRoughness; - material.clearcoatF0 = vec3( 0.04 ); - material.clearcoatF90 = 1.0; - #ifdef USE_CLEARCOATMAP - material.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x; - #endif - #ifdef USE_CLEARCOAT_ROUGHNESSMAP - material.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y; - #endif - material.clearcoat = saturate( material.clearcoat ); material.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 ); - material.clearcoatRoughness += geometryRoughness; - material.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 ); -#endif -#ifdef USE_DISPERSION - material.dispersion = dispersion; -#endif -#ifdef USE_IRIDESCENCE - material.iridescence = iridescence; - material.iridescenceIOR = iridescenceIOR; - #ifdef USE_IRIDESCENCEMAP - material.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r; - #endif - #ifdef USE_IRIDESCENCE_THICKNESSMAP - material.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum; - #else - material.iridescenceThickness = iridescenceThicknessMaximum; - #endif -#endif -#ifdef USE_SHEEN - material.sheenColor = sheenColor; - #ifdef USE_SHEEN_COLORMAP - material.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb; - #endif - material.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 ); - #ifdef USE_SHEEN_ROUGHNESSMAP - material.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a; - #endif -#endif -#ifdef USE_ANISOTROPY - #ifdef USE_ANISOTROPYMAP - mat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x ); - vec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb; - vec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b; - #else - vec2 anisotropyV = anisotropyVector; - #endif - material.anisotropy = length( anisotropyV ); - if( material.anisotropy == 0.0 ) { - anisotropyV = vec2( 1.0, 0.0 ); - } else { - anisotropyV /= material.anisotropy; - material.anisotropy = saturate( material.anisotropy ); - } - material.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) ); - material.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y; - material.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y; -#endif`,Vh=`struct PhysicalMaterial { - vec3 diffuseColor; - float roughness; - vec3 specularColor; - float specularF90; - float dispersion; - #ifdef USE_CLEARCOAT - float clearcoat; - float clearcoatRoughness; - vec3 clearcoatF0; - float clearcoatF90; - #endif - #ifdef USE_IRIDESCENCE - float iridescence; - float iridescenceIOR; - float iridescenceThickness; - vec3 iridescenceFresnel; - vec3 iridescenceF0; - #endif - #ifdef USE_SHEEN - vec3 sheenColor; - float sheenRoughness; - #endif - #ifdef IOR - float ior; - #endif - #ifdef USE_TRANSMISSION - float transmission; - float transmissionAlpha; - float thickness; - float attenuationDistance; - vec3 attenuationColor; - #endif - #ifdef USE_ANISOTROPY - float anisotropy; - float alphaT; - vec3 anisotropyT; - vec3 anisotropyB; - #endif -}; -vec3 clearcoatSpecularDirect = vec3( 0.0 ); -vec3 clearcoatSpecularIndirect = vec3( 0.0 ); -vec3 sheenSpecularDirect = vec3( 0.0 ); -vec3 sheenSpecularIndirect = vec3(0.0 ); -vec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) { - float x = clamp( 1.0 - dotVH, 0.0, 1.0 ); - float x2 = x * x; - float x5 = clamp( x * x2 * x2, 0.0, 0.9999 ); - return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 ); -} -float V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) { - float a2 = pow2( alpha ); - float gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) ); - float gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) ); - return 0.5 / max( gv + gl, EPSILON ); -} -float D_GGX( const in float alpha, const in float dotNH ) { - float a2 = pow2( alpha ); - float denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0; - return RECIPROCAL_PI * a2 / pow2( denom ); -} -#ifdef USE_ANISOTROPY - float V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) { - float gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) ); - float gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) ); - float v = 0.5 / ( gv + gl ); - return saturate(v); - } - float D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) { - float a2 = alphaT * alphaB; - highp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH ); - highp float v2 = dot( v, v ); - float w2 = a2 / v2; - return RECIPROCAL_PI * a2 * pow2 ( w2 ); - } -#endif -#ifdef USE_CLEARCOAT - vec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) { - vec3 f0 = material.clearcoatF0; - float f90 = material.clearcoatF90; - float roughness = material.clearcoatRoughness; - float alpha = pow2( roughness ); - vec3 halfDir = normalize( lightDir + viewDir ); - float dotNL = saturate( dot( normal, lightDir ) ); - float dotNV = saturate( dot( normal, viewDir ) ); - float dotNH = saturate( dot( normal, halfDir ) ); - float dotVH = saturate( dot( viewDir, halfDir ) ); - vec3 F = F_Schlick( f0, f90, dotVH ); - float V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV ); - float D = D_GGX( alpha, dotNH ); - return F * ( V * D ); - } -#endif -vec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) { - vec3 f0 = material.specularColor; - float f90 = material.specularF90; - float roughness = material.roughness; - float alpha = pow2( roughness ); - vec3 halfDir = normalize( lightDir + viewDir ); - float dotNL = saturate( dot( normal, lightDir ) ); - float dotNV = saturate( dot( normal, viewDir ) ); - float dotNH = saturate( dot( normal, halfDir ) ); - float dotVH = saturate( dot( viewDir, halfDir ) ); - vec3 F = F_Schlick( f0, f90, dotVH ); - #ifdef USE_IRIDESCENCE - F = mix( F, material.iridescenceFresnel, material.iridescence ); - #endif - #ifdef USE_ANISOTROPY - float dotTL = dot( material.anisotropyT, lightDir ); - float dotTV = dot( material.anisotropyT, viewDir ); - float dotTH = dot( material.anisotropyT, halfDir ); - float dotBL = dot( material.anisotropyB, lightDir ); - float dotBV = dot( material.anisotropyB, viewDir ); - float dotBH = dot( material.anisotropyB, halfDir ); - float V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL ); - float D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH ); - #else - float V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV ); - float D = D_GGX( alpha, dotNH ); - #endif - return F * ( V * D ); -} -vec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) { - const float LUT_SIZE = 64.0; - const float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE; - const float LUT_BIAS = 0.5 / LUT_SIZE; - float dotNV = saturate( dot( N, V ) ); - vec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) ); - uv = uv * LUT_SCALE + LUT_BIAS; - return uv; -} -float LTC_ClippedSphereFormFactor( const in vec3 f ) { - float l = length( f ); - return max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 ); -} -vec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) { - float x = dot( v1, v2 ); - float y = abs( x ); - float a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y; - float b = 3.4175940 + ( 4.1616724 + y ) * y; - float v = a / b; - float theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v; - return cross( v1, v2 ) * theta_sintheta; -} -vec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) { - vec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ]; - vec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ]; - vec3 lightNormal = cross( v1, v2 ); - if( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 ); - vec3 T1, T2; - T1 = normalize( V - N * dot( V, N ) ); - T2 = - cross( N, T1 ); - mat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) ); - vec3 coords[ 4 ]; - coords[ 0 ] = mat * ( rectCoords[ 0 ] - P ); - coords[ 1 ] = mat * ( rectCoords[ 1 ] - P ); - coords[ 2 ] = mat * ( rectCoords[ 2 ] - P ); - coords[ 3 ] = mat * ( rectCoords[ 3 ] - P ); - coords[ 0 ] = normalize( coords[ 0 ] ); - coords[ 1 ] = normalize( coords[ 1 ] ); - coords[ 2 ] = normalize( coords[ 2 ] ); - coords[ 3 ] = normalize( coords[ 3 ] ); - vec3 vectorFormFactor = vec3( 0.0 ); - vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] ); - vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] ); - vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] ); - vectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] ); - float result = LTC_ClippedSphereFormFactor( vectorFormFactor ); - return vec3( result ); -} -#if defined( USE_SHEEN ) -float D_Charlie( float roughness, float dotNH ) { - float alpha = pow2( roughness ); - float invAlpha = 1.0 / alpha; - float cos2h = dotNH * dotNH; - float sin2h = max( 1.0 - cos2h, 0.0078125 ); - return ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI ); -} -float V_Neubelt( float dotNV, float dotNL ) { - return saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) ); -} -vec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) { - vec3 halfDir = normalize( lightDir + viewDir ); - float dotNL = saturate( dot( normal, lightDir ) ); - float dotNV = saturate( dot( normal, viewDir ) ); - float dotNH = saturate( dot( normal, halfDir ) ); - float D = D_Charlie( sheenRoughness, dotNH ); - float V = V_Neubelt( dotNV, dotNL ); - return sheenColor * ( D * V ); -} -#endif -float IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) { - float dotNV = saturate( dot( normal, viewDir ) ); - float r2 = roughness * roughness; - float a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95; - float b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72; - float DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) ); - return saturate( DG * RECIPROCAL_PI ); -} -vec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) { - float dotNV = saturate( dot( normal, viewDir ) ); - const vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 ); - const vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 ); - vec4 r = roughness * c0 + c1; - float a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y; - vec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw; - return fab; -} -vec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) { - vec2 fab = DFGApprox( normal, viewDir, roughness ); - return specularColor * fab.x + specularF90 * fab.y; -} -#ifdef USE_IRIDESCENCE -void computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) { -#else -void computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) { -#endif - vec2 fab = DFGApprox( normal, viewDir, roughness ); - #ifdef USE_IRIDESCENCE - vec3 Fr = mix( specularColor, iridescenceF0, iridescence ); - #else - vec3 Fr = specularColor; - #endif - vec3 FssEss = Fr * fab.x + specularF90 * fab.y; - float Ess = fab.x + fab.y; - float Ems = 1.0 - Ess; - vec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619; vec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg ); - singleScatter += FssEss; - multiScatter += Fms * Ems; -} -#if NUM_RECT_AREA_LIGHTS > 0 - void RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) { - vec3 normal = geometryNormal; - vec3 viewDir = geometryViewDir; - vec3 position = geometryPosition; - vec3 lightPos = rectAreaLight.position; - vec3 halfWidth = rectAreaLight.halfWidth; - vec3 halfHeight = rectAreaLight.halfHeight; - vec3 lightColor = rectAreaLight.color; - float roughness = material.roughness; - vec3 rectCoords[ 4 ]; - rectCoords[ 0 ] = lightPos + halfWidth - halfHeight; rectCoords[ 1 ] = lightPos - halfWidth - halfHeight; - rectCoords[ 2 ] = lightPos - halfWidth + halfHeight; - rectCoords[ 3 ] = lightPos + halfWidth + halfHeight; - vec2 uv = LTC_Uv( normal, viewDir, roughness ); - vec4 t1 = texture2D( ltc_1, uv ); - vec4 t2 = texture2D( ltc_2, uv ); - mat3 mInv = mat3( - vec3( t1.x, 0, t1.y ), - vec3( 0, 1, 0 ), - vec3( t1.z, 0, t1.w ) - ); - vec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y ); - reflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords ); - reflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords ); - } -#endif -void RE_Direct_Physical( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) { - float dotNL = saturate( dot( geometryNormal, directLight.direction ) ); - vec3 irradiance = dotNL * directLight.color; - #ifdef USE_CLEARCOAT - float dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) ); - vec3 ccIrradiance = dotNLcc * directLight.color; - clearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material ); - #endif - #ifdef USE_SHEEN - sheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness ); - #endif - reflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometryViewDir, geometryNormal, material ); - reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); -} -void RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) { - reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor ); -} -void RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) { - #ifdef USE_CLEARCOAT - clearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness ); - #endif - #ifdef USE_SHEEN - sheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness ); - #endif - vec3 singleScattering = vec3( 0.0 ); - vec3 multiScattering = vec3( 0.0 ); - vec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI; - #ifdef USE_IRIDESCENCE - computeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering ); - #else - computeMultiscattering( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering ); - #endif - vec3 totalScattering = singleScattering + multiScattering; - vec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) ); - reflectedLight.indirectSpecular += radiance * singleScattering; - reflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance; - reflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance; -} -#define RE_Direct RE_Direct_Physical -#define RE_Direct_RectArea RE_Direct_RectArea_Physical -#define RE_IndirectDiffuse RE_IndirectDiffuse_Physical -#define RE_IndirectSpecular RE_IndirectSpecular_Physical -float computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) { - return saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion ); -}`,kh=` -vec3 geometryPosition = - vViewPosition; -vec3 geometryNormal = normal; -vec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition ); -vec3 geometryClearcoatNormal = vec3( 0.0 ); -#ifdef USE_CLEARCOAT - geometryClearcoatNormal = clearcoatNormal; -#endif -#ifdef USE_IRIDESCENCE - float dotNVi = saturate( dot( normal, geometryViewDir ) ); - if ( material.iridescenceThickness == 0.0 ) { - material.iridescence = 0.0; - } else { - material.iridescence = saturate( material.iridescence ); - } - if ( material.iridescence > 0.0 ) { - material.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor ); - material.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi ); - } -#endif -IncidentLight directLight; -#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct ) - PointLight pointLight; - #if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0 - PointLightShadow pointLightShadow; - #endif - #pragma unroll_loop_start - for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) { - pointLight = pointLights[ i ]; - getPointLightInfo( pointLight, geometryPosition, directLight ); - #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS ) - pointLightShadow = pointLightShadows[ i ]; - directLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowIntensity, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0; - #endif - RE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); - } - #pragma unroll_loop_end -#endif -#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct ) - SpotLight spotLight; - vec4 spotColor; - vec3 spotLightCoord; - bool inSpotLightMap; - #if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0 - SpotLightShadow spotLightShadow; - #endif - #pragma unroll_loop_start - for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) { - spotLight = spotLights[ i ]; - getSpotLightInfo( spotLight, geometryPosition, directLight ); - #if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS ) - #define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX - #elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS ) - #define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS - #else - #define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS ) - #endif - #if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS ) - spotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w; - inSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) ); - spotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy ); - directLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color; - #endif - #undef SPOT_LIGHT_MAP_INDEX - #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS ) - spotLightShadow = spotLightShadows[ i ]; - directLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowIntensity, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0; - #endif - RE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); - } - #pragma unroll_loop_end -#endif -#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct ) - DirectionalLight directionalLight; - #if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0 - DirectionalLightShadow directionalLightShadow; - #endif - #pragma unroll_loop_start - for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) { - directionalLight = directionalLights[ i ]; - getDirectionalLightInfo( directionalLight, directLight ); - #if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS ) - directionalLightShadow = directionalLightShadows[ i ]; - directLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowIntensity, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0; - #endif - RE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); - } - #pragma unroll_loop_end -#endif -#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea ) - RectAreaLight rectAreaLight; - #pragma unroll_loop_start - for ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) { - rectAreaLight = rectAreaLights[ i ]; - RE_Direct_RectArea( rectAreaLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); - } - #pragma unroll_loop_end -#endif -#if defined( RE_IndirectDiffuse ) - vec3 iblIrradiance = vec3( 0.0 ); - vec3 irradiance = getAmbientLightIrradiance( ambientLightColor ); - #if defined( USE_LIGHT_PROBES ) - irradiance += getLightProbeIrradiance( lightProbe, geometryNormal ); - #endif - #if ( NUM_HEMI_LIGHTS > 0 ) - #pragma unroll_loop_start - for ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) { - irradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometryNormal ); - } - #pragma unroll_loop_end - #endif -#endif -#if defined( RE_IndirectSpecular ) - vec3 radiance = vec3( 0.0 ); - vec3 clearcoatRadiance = vec3( 0.0 ); -#endif`,Wh=`#if defined( RE_IndirectDiffuse ) - #ifdef USE_LIGHTMAP - vec4 lightMapTexel = texture2D( lightMap, vLightMapUv ); - vec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity; - irradiance += lightMapIrradiance; - #endif - #if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV ) - iblIrradiance += getIBLIrradiance( geometryNormal ); - #endif -#endif -#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular ) - #ifdef USE_ANISOTROPY - radiance += getIBLAnisotropyRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy ); - #else - radiance += getIBLRadiance( geometryViewDir, geometryNormal, material.roughness ); - #endif - #ifdef USE_CLEARCOAT - clearcoatRadiance += getIBLRadiance( geometryViewDir, geometryClearcoatNormal, material.clearcoatRoughness ); - #endif -#endif`,Xh=`#if defined( RE_IndirectDiffuse ) - RE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); -#endif -#if defined( RE_IndirectSpecular ) - RE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight ); -#endif`,qh=`#if defined( USE_LOGDEPTHBUF ) - gl_FragDepth = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5; -#endif`,Yh=`#if defined( USE_LOGDEPTHBUF ) - uniform float logDepthBufFC; - varying float vFragDepth; - varying float vIsPerspective; -#endif`,Zh=`#ifdef USE_LOGDEPTHBUF - varying float vFragDepth; - varying float vIsPerspective; -#endif`,Kh=`#ifdef USE_LOGDEPTHBUF - vFragDepth = 1.0 + gl_Position.w; - vIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) ); -#endif`,jh=`#ifdef USE_MAP - vec4 sampledDiffuseColor = texture2D( map, vMapUv ); - #ifdef DECODE_VIDEO_TEXTURE - sampledDiffuseColor = vec4( mix( pow( sampledDiffuseColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), sampledDiffuseColor.rgb * 0.0773993808, vec3( lessThanEqual( sampledDiffuseColor.rgb, vec3( 0.04045 ) ) ) ), sampledDiffuseColor.w ); - - #endif - diffuseColor *= sampledDiffuseColor; -#endif`,$h=`#ifdef USE_MAP - uniform sampler2D map; -#endif`,Jh=`#if defined( USE_MAP ) || defined( USE_ALPHAMAP ) - #if defined( USE_POINTS_UV ) - vec2 uv = vUv; - #else - vec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy; - #endif -#endif -#ifdef USE_MAP - diffuseColor *= texture2D( map, uv ); -#endif -#ifdef USE_ALPHAMAP - diffuseColor.a *= texture2D( alphaMap, uv ).g; -#endif`,Qh=`#if defined( USE_POINTS_UV ) - varying vec2 vUv; -#else - #if defined( USE_MAP ) || defined( USE_ALPHAMAP ) - uniform mat3 uvTransform; - #endif -#endif -#ifdef USE_MAP - uniform sampler2D map; -#endif -#ifdef USE_ALPHAMAP - uniform sampler2D alphaMap; -#endif`,ef=`float metalnessFactor = metalness; -#ifdef USE_METALNESSMAP - vec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv ); - metalnessFactor *= texelMetalness.b; -#endif`,tf=`#ifdef USE_METALNESSMAP - uniform sampler2D metalnessMap; -#endif`,nf=`#ifdef USE_INSTANCING_MORPH - float morphTargetInfluences[ MORPHTARGETS_COUNT ]; - float morphTargetBaseInfluence = texelFetch( morphTexture, ivec2( 0, gl_InstanceID ), 0 ).r; - for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) { - morphTargetInfluences[i] = texelFetch( morphTexture, ivec2( i + 1, gl_InstanceID ), 0 ).r; - } -#endif`,rf=`#if defined( USE_MORPHCOLORS ) - vColor *= morphTargetBaseInfluence; - for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) { - #if defined( USE_COLOR_ALPHA ) - if ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ]; - #elif defined( USE_COLOR ) - if ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ]; - #endif - } -#endif`,sf=`#ifdef USE_MORPHNORMALS - objectNormal *= morphTargetBaseInfluence; - for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) { - if ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ]; - } -#endif`,af=`#ifdef USE_MORPHTARGETS - #ifndef USE_INSTANCING_MORPH - uniform float morphTargetBaseInfluence; - uniform float morphTargetInfluences[ MORPHTARGETS_COUNT ]; - #endif - uniform sampler2DArray morphTargetsTexture; - uniform ivec2 morphTargetsTextureSize; - vec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) { - int texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset; - int y = texelIndex / morphTargetsTextureSize.x; - int x = texelIndex - y * morphTargetsTextureSize.x; - ivec3 morphUV = ivec3( x, y, morphTargetIndex ); - return texelFetch( morphTargetsTexture, morphUV, 0 ); - } -#endif`,of=`#ifdef USE_MORPHTARGETS - transformed *= morphTargetBaseInfluence; - for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) { - if ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ]; - } -#endif`,lf=`float faceDirection = gl_FrontFacing ? 1.0 : - 1.0; -#ifdef FLAT_SHADED - vec3 fdx = dFdx( vViewPosition ); - vec3 fdy = dFdy( vViewPosition ); - vec3 normal = normalize( cross( fdx, fdy ) ); -#else - vec3 normal = normalize( vNormal ); - #ifdef DOUBLE_SIDED - normal *= faceDirection; - #endif -#endif -#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) - #ifdef USE_TANGENT - mat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal ); - #else - mat3 tbn = getTangentFrame( - vViewPosition, normal, - #if defined( USE_NORMALMAP ) - vNormalMapUv - #elif defined( USE_CLEARCOAT_NORMALMAP ) - vClearcoatNormalMapUv - #else - vUv - #endif - ); - #endif - #if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED ) - tbn[0] *= faceDirection; - tbn[1] *= faceDirection; - #endif -#endif -#ifdef USE_CLEARCOAT_NORMALMAP - #ifdef USE_TANGENT - mat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal ); - #else - mat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv ); - #endif - #if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED ) - tbn2[0] *= faceDirection; - tbn2[1] *= faceDirection; - #endif -#endif -vec3 nonPerturbedNormal = normal;`,cf=`#ifdef USE_NORMALMAP_OBJECTSPACE - normal = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0; - #ifdef FLIP_SIDED - normal = - normal; - #endif - #ifdef DOUBLE_SIDED - normal = normal * faceDirection; - #endif - normal = normalize( normalMatrix * normal ); -#elif defined( USE_NORMALMAP_TANGENTSPACE ) - vec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0; - mapN.xy *= normalScale; - normal = normalize( tbn * mapN ); -#elif defined( USE_BUMPMAP ) - normal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection ); -#endif`,uf=`#ifndef FLAT_SHADED - varying vec3 vNormal; - #ifdef USE_TANGENT - varying vec3 vTangent; - varying vec3 vBitangent; - #endif -#endif`,df=`#ifndef FLAT_SHADED - varying vec3 vNormal; - #ifdef USE_TANGENT - varying vec3 vTangent; - varying vec3 vBitangent; - #endif -#endif`,hf=`#ifndef FLAT_SHADED - vNormal = normalize( transformedNormal ); - #ifdef USE_TANGENT - vTangent = normalize( transformedTangent ); - vBitangent = normalize( cross( vNormal, vTangent ) * tangent.w ); - #endif -#endif`,ff=`#ifdef USE_NORMALMAP - uniform sampler2D normalMap; - uniform vec2 normalScale; -#endif -#ifdef USE_NORMALMAP_OBJECTSPACE - uniform mat3 normalMatrix; -#endif -#if ! defined ( USE_TANGENT ) && ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) ) - mat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) { - vec3 q0 = dFdx( eye_pos.xyz ); - vec3 q1 = dFdy( eye_pos.xyz ); - vec2 st0 = dFdx( uv.st ); - vec2 st1 = dFdy( uv.st ); - vec3 N = surf_norm; - vec3 q1perp = cross( q1, N ); - vec3 q0perp = cross( N, q0 ); - vec3 T = q1perp * st0.x + q0perp * st1.x; - vec3 B = q1perp * st0.y + q0perp * st1.y; - float det = max( dot( T, T ), dot( B, B ) ); - float scale = ( det == 0.0 ) ? 0.0 : inversesqrt( det ); - return mat3( T * scale, B * scale, N ); - } -#endif`,pf=`#ifdef USE_CLEARCOAT - vec3 clearcoatNormal = nonPerturbedNormal; -#endif`,mf=`#ifdef USE_CLEARCOAT_NORMALMAP - vec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0; - clearcoatMapN.xy *= clearcoatNormalScale; - clearcoatNormal = normalize( tbn2 * clearcoatMapN ); -#endif`,gf=`#ifdef USE_CLEARCOATMAP - uniform sampler2D clearcoatMap; -#endif -#ifdef USE_CLEARCOAT_NORMALMAP - uniform sampler2D clearcoatNormalMap; - uniform vec2 clearcoatNormalScale; -#endif -#ifdef USE_CLEARCOAT_ROUGHNESSMAP - uniform sampler2D clearcoatRoughnessMap; -#endif`,vf=`#ifdef USE_IRIDESCENCEMAP - uniform sampler2D iridescenceMap; -#endif -#ifdef USE_IRIDESCENCE_THICKNESSMAP - uniform sampler2D iridescenceThicknessMap; -#endif`,_f=`#ifdef OPAQUE -diffuseColor.a = 1.0; -#endif -#ifdef USE_TRANSMISSION -diffuseColor.a *= material.transmissionAlpha; -#endif -gl_FragColor = vec4( outgoingLight, diffuseColor.a );`,xf=`vec3 packNormalToRGB( const in vec3 normal ) { - return normalize( normal ) * 0.5 + 0.5; -} -vec3 unpackRGBToNormal( const in vec3 rgb ) { - return 2.0 * rgb.xyz - 1.0; -} -const float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;const float ShiftRight8 = 1. / 256.; -const float Inv255 = 1. / 255.; -const vec4 PackFactors = vec4( 1.0, 256.0, 256.0 * 256.0, 256.0 * 256.0 * 256.0 ); -const vec2 UnpackFactors2 = vec2( UnpackDownscale, 1.0 / PackFactors.g ); -const vec3 UnpackFactors3 = vec3( UnpackDownscale / PackFactors.rg, 1.0 / PackFactors.b ); -const vec4 UnpackFactors4 = vec4( UnpackDownscale / PackFactors.rgb, 1.0 / PackFactors.a ); -vec4 packDepthToRGBA( const in float v ) { - if( v <= 0.0 ) - return vec4( 0., 0., 0., 0. ); - if( v >= 1.0 ) - return vec4( 1., 1., 1., 1. ); - float vuf; - float af = modf( v * PackFactors.a, vuf ); - float bf = modf( vuf * ShiftRight8, vuf ); - float gf = modf( vuf * ShiftRight8, vuf ); - return vec4( vuf * Inv255, gf * PackUpscale, bf * PackUpscale, af ); -} -vec3 packDepthToRGB( const in float v ) { - if( v <= 0.0 ) - return vec3( 0., 0., 0. ); - if( v >= 1.0 ) - return vec3( 1., 1., 1. ); - float vuf; - float bf = modf( v * PackFactors.b, vuf ); - float gf = modf( vuf * ShiftRight8, vuf ); - return vec3( vuf * Inv255, gf * PackUpscale, bf ); -} -vec2 packDepthToRG( const in float v ) { - if( v <= 0.0 ) - return vec2( 0., 0. ); - if( v >= 1.0 ) - return vec2( 1., 1. ); - float vuf; - float gf = modf( v * 256., vuf ); - return vec2( vuf * Inv255, gf ); -} -float unpackRGBAToDepth( const in vec4 v ) { - return dot( v, UnpackFactors4 ); -} -float unpackRGBToDepth( const in vec3 v ) { - return dot( v, UnpackFactors3 ); -} -float unpackRGToDepth( const in vec2 v ) { - return v.r * UnpackFactors2.r + v.g * UnpackFactors2.g; -} -vec4 pack2HalfToRGBA( const in vec2 v ) { - vec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) ); - return vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w ); -} -vec2 unpackRGBATo2Half( const in vec4 v ) { - return vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) ); -} -float viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) { - return ( viewZ + near ) / ( near - far ); -} -float orthographicDepthToViewZ( const in float depth, const in float near, const in float far ) { - return depth * ( near - far ) - near; -} -float viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) { - return ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ ); -} -float perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) { - return ( near * far ) / ( ( far - near ) * depth - far ); -}`,Sf=`#ifdef PREMULTIPLIED_ALPHA - gl_FragColor.rgb *= gl_FragColor.a; -#endif`,Mf=`vec4 mvPosition = vec4( transformed, 1.0 ); -#ifdef USE_BATCHING - mvPosition = batchingMatrix * mvPosition; -#endif -#ifdef USE_INSTANCING - mvPosition = instanceMatrix * mvPosition; -#endif -mvPosition = modelViewMatrix * mvPosition; -gl_Position = projectionMatrix * mvPosition;`,yf=`#ifdef DITHERING - gl_FragColor.rgb = dithering( gl_FragColor.rgb ); -#endif`,Ef=`#ifdef DITHERING - vec3 dithering( vec3 color ) { - float grid_position = rand( gl_FragCoord.xy ); - vec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 ); - dither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position ); - return color + dither_shift_RGB; - } -#endif`,Tf=`float roughnessFactor = roughness; -#ifdef USE_ROUGHNESSMAP - vec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv ); - roughnessFactor *= texelRoughness.g; -#endif`,bf=`#ifdef USE_ROUGHNESSMAP - uniform sampler2D roughnessMap; -#endif`,Af=`#if NUM_SPOT_LIGHT_COORDS > 0 - varying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ]; -#endif -#if NUM_SPOT_LIGHT_MAPS > 0 - uniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ]; -#endif -#ifdef USE_SHADOWMAP - #if NUM_DIR_LIGHT_SHADOWS > 0 - uniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ]; - varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ]; - struct DirectionalLightShadow { - float shadowIntensity; - float shadowBias; - float shadowNormalBias; - float shadowRadius; - vec2 shadowMapSize; - }; - uniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ]; - #endif - #if NUM_SPOT_LIGHT_SHADOWS > 0 - uniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ]; - struct SpotLightShadow { - float shadowIntensity; - float shadowBias; - float shadowNormalBias; - float shadowRadius; - vec2 shadowMapSize; - }; - uniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ]; - #endif - #if NUM_POINT_LIGHT_SHADOWS > 0 - uniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ]; - varying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ]; - struct PointLightShadow { - float shadowIntensity; - float shadowBias; - float shadowNormalBias; - float shadowRadius; - vec2 shadowMapSize; - float shadowCameraNear; - float shadowCameraFar; - }; - uniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ]; - #endif - float texture2DCompare( sampler2D depths, vec2 uv, float compare ) { - return step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) ); - } - vec2 texture2DDistribution( sampler2D shadow, vec2 uv ) { - return unpackRGBATo2Half( texture2D( shadow, uv ) ); - } - float VSMShadow (sampler2D shadow, vec2 uv, float compare ){ - float occlusion = 1.0; - vec2 distribution = texture2DDistribution( shadow, uv ); - float hard_shadow = step( compare , distribution.x ); - if (hard_shadow != 1.0 ) { - float distance = compare - distribution.x ; - float variance = max( 0.00000, distribution.y * distribution.y ); - float softness_probability = variance / (variance + distance * distance ); softness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 ); occlusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 ); - } - return occlusion; - } - float getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord ) { - float shadow = 1.0; - shadowCoord.xyz /= shadowCoord.w; - shadowCoord.z += shadowBias; - bool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0; - bool frustumTest = inFrustum && shadowCoord.z <= 1.0; - if ( frustumTest ) { - #if defined( SHADOWMAP_TYPE_PCF ) - vec2 texelSize = vec2( 1.0 ) / shadowMapSize; - float dx0 = - texelSize.x * shadowRadius; - float dy0 = - texelSize.y * shadowRadius; - float dx1 = + texelSize.x * shadowRadius; - float dy1 = + texelSize.y * shadowRadius; - float dx2 = dx0 / 2.0; - float dy2 = dy0 / 2.0; - float dx3 = dx1 / 2.0; - float dy3 = dy1 / 2.0; - shadow = ( - texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) + - texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) + - texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) + - texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) + - texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) + - texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) + - texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) + - texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) + - texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) + - texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) + - texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) + - texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) + - texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) + - texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) + - texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) + - texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) + - texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z ) - ) * ( 1.0 / 17.0 ); - #elif defined( SHADOWMAP_TYPE_PCF_SOFT ) - vec2 texelSize = vec2( 1.0 ) / shadowMapSize; - float dx = texelSize.x; - float dy = texelSize.y; - vec2 uv = shadowCoord.xy; - vec2 f = fract( uv * shadowMapSize + 0.5 ); - uv -= f * texelSize; - shadow = ( - texture2DCompare( shadowMap, uv, shadowCoord.z ) + - texture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) + - texture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) + - texture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) + - mix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ), - texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ), - f.x ) + - mix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ), - texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ), - f.x ) + - mix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ), - texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ), - f.y ) + - mix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ), - texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ), - f.y ) + - mix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ), - texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ), - f.x ), - mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ), - texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ), - f.x ), - f.y ) - ) * ( 1.0 / 9.0 ); - #elif defined( SHADOWMAP_TYPE_VSM ) - shadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z ); - #else - shadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ); - #endif - } - return mix( 1.0, shadow, shadowIntensity ); - } - vec2 cubeToUV( vec3 v, float texelSizeY ) { - vec3 absV = abs( v ); - float scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) ); - absV *= scaleToCube; - v *= scaleToCube * ( 1.0 - 2.0 * texelSizeY ); - vec2 planar = v.xy; - float almostATexel = 1.5 * texelSizeY; - float almostOne = 1.0 - almostATexel; - if ( absV.z >= almostOne ) { - if ( v.z > 0.0 ) - planar.x = 4.0 - v.x; - } else if ( absV.x >= almostOne ) { - float signX = sign( v.x ); - planar.x = v.z * signX + 2.0 * signX; - } else if ( absV.y >= almostOne ) { - float signY = sign( v.y ); - planar.x = v.x + 2.0 * signY + 2.0; - planar.y = v.z * signY - 2.0; - } - return vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 ); - } - float getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) { - float shadow = 1.0; - vec3 lightToPosition = shadowCoord.xyz; - - float lightToPositionLength = length( lightToPosition ); - if ( lightToPositionLength - shadowCameraFar <= 0.0 && lightToPositionLength - shadowCameraNear >= 0.0 ) { - float dp = ( lightToPositionLength - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear ); dp += shadowBias; - vec3 bd3D = normalize( lightToPosition ); - vec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) ); - #if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM ) - vec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y; - shadow = ( - texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) + - texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) + - texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) + - texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) + - texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) + - texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) + - texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) + - texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) + - texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp ) - ) * ( 1.0 / 9.0 ); - #else - shadow = texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ); - #endif - } - return mix( 1.0, shadow, shadowIntensity ); - } -#endif`,wf=`#if NUM_SPOT_LIGHT_COORDS > 0 - uniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ]; - varying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ]; -#endif -#ifdef USE_SHADOWMAP - #if NUM_DIR_LIGHT_SHADOWS > 0 - uniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ]; - varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ]; - struct DirectionalLightShadow { - float shadowIntensity; - float shadowBias; - float shadowNormalBias; - float shadowRadius; - vec2 shadowMapSize; - }; - uniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ]; - #endif - #if NUM_SPOT_LIGHT_SHADOWS > 0 - struct SpotLightShadow { - float shadowIntensity; - float shadowBias; - float shadowNormalBias; - float shadowRadius; - vec2 shadowMapSize; - }; - uniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ]; - #endif - #if NUM_POINT_LIGHT_SHADOWS > 0 - uniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ]; - varying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ]; - struct PointLightShadow { - float shadowIntensity; - float shadowBias; - float shadowNormalBias; - float shadowRadius; - vec2 shadowMapSize; - float shadowCameraNear; - float shadowCameraFar; - }; - uniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ]; - #endif -#endif`,Rf=`#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 ) - vec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix ); - vec4 shadowWorldPosition; -#endif -#if defined( USE_SHADOWMAP ) - #if NUM_DIR_LIGHT_SHADOWS > 0 - #pragma unroll_loop_start - for ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) { - shadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 ); - vDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition; - } - #pragma unroll_loop_end - #endif - #if NUM_POINT_LIGHT_SHADOWS > 0 - #pragma unroll_loop_start - for ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) { - shadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 ); - vPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition; - } - #pragma unroll_loop_end - #endif -#endif -#if NUM_SPOT_LIGHT_COORDS > 0 - #pragma unroll_loop_start - for ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) { - shadowWorldPosition = worldPosition; - #if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS ) - shadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias; - #endif - vSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition; - } - #pragma unroll_loop_end -#endif`,Cf=`float getShadowMask() { - float shadow = 1.0; - #ifdef USE_SHADOWMAP - #if NUM_DIR_LIGHT_SHADOWS > 0 - DirectionalLightShadow directionalLight; - #pragma unroll_loop_start - for ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) { - directionalLight = directionalLightShadows[ i ]; - shadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowIntensity, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0; - } - #pragma unroll_loop_end - #endif - #if NUM_SPOT_LIGHT_SHADOWS > 0 - SpotLightShadow spotLight; - #pragma unroll_loop_start - for ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) { - spotLight = spotLightShadows[ i ]; - shadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowIntensity, spotLight.shadowBias, spotLight.shadowRadius, vSpotLightCoord[ i ] ) : 1.0; - } - #pragma unroll_loop_end - #endif - #if NUM_POINT_LIGHT_SHADOWS > 0 - PointLightShadow pointLight; - #pragma unroll_loop_start - for ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) { - pointLight = pointLightShadows[ i ]; - shadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowIntensity, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0; - } - #pragma unroll_loop_end - #endif - #endif - return shadow; -}`,Pf=`#ifdef USE_SKINNING - mat4 boneMatX = getBoneMatrix( skinIndex.x ); - mat4 boneMatY = getBoneMatrix( skinIndex.y ); - mat4 boneMatZ = getBoneMatrix( skinIndex.z ); - mat4 boneMatW = getBoneMatrix( skinIndex.w ); -#endif`,Df=`#ifdef USE_SKINNING - uniform mat4 bindMatrix; - uniform mat4 bindMatrixInverse; - uniform highp sampler2D boneTexture; - mat4 getBoneMatrix( const in float i ) { - int size = textureSize( boneTexture, 0 ).x; - int j = int( i ) * 4; - int x = j % size; - int y = j / size; - vec4 v1 = texelFetch( boneTexture, ivec2( x, y ), 0 ); - vec4 v2 = texelFetch( boneTexture, ivec2( x + 1, y ), 0 ); - vec4 v3 = texelFetch( boneTexture, ivec2( x + 2, y ), 0 ); - vec4 v4 = texelFetch( boneTexture, ivec2( x + 3, y ), 0 ); - return mat4( v1, v2, v3, v4 ); - } -#endif`,Lf=`#ifdef USE_SKINNING - vec4 skinVertex = bindMatrix * vec4( transformed, 1.0 ); - vec4 skinned = vec4( 0.0 ); - skinned += boneMatX * skinVertex * skinWeight.x; - skinned += boneMatY * skinVertex * skinWeight.y; - skinned += boneMatZ * skinVertex * skinWeight.z; - skinned += boneMatW * skinVertex * skinWeight.w; - transformed = ( bindMatrixInverse * skinned ).xyz; -#endif`,Uf=`#ifdef USE_SKINNING - mat4 skinMatrix = mat4( 0.0 ); - skinMatrix += skinWeight.x * boneMatX; - skinMatrix += skinWeight.y * boneMatY; - skinMatrix += skinWeight.z * boneMatZ; - skinMatrix += skinWeight.w * boneMatW; - skinMatrix = bindMatrixInverse * skinMatrix * bindMatrix; - objectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz; - #ifdef USE_TANGENT - objectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz; - #endif -#endif`,If=`float specularStrength; -#ifdef USE_SPECULARMAP - vec4 texelSpecular = texture2D( specularMap, vSpecularMapUv ); - specularStrength = texelSpecular.r; -#else - specularStrength = 1.0; -#endif`,Nf=`#ifdef USE_SPECULARMAP - uniform sampler2D specularMap; -#endif`,Ff=`#if defined( TONE_MAPPING ) - gl_FragColor.rgb = toneMapping( gl_FragColor.rgb ); -#endif`,Of=`#ifndef saturate -#define saturate( a ) clamp( a, 0.0, 1.0 ) -#endif -uniform float toneMappingExposure; -vec3 LinearToneMapping( vec3 color ) { - return saturate( toneMappingExposure * color ); -} -vec3 ReinhardToneMapping( vec3 color ) { - color *= toneMappingExposure; - return saturate( color / ( vec3( 1.0 ) + color ) ); -} -vec3 CineonToneMapping( vec3 color ) { - color *= toneMappingExposure; - color = max( vec3( 0.0 ), color - 0.004 ); - return pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) ); -} -vec3 RRTAndODTFit( vec3 v ) { - vec3 a = v * ( v + 0.0245786 ) - 0.000090537; - vec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081; - return a / b; -} -vec3 ACESFilmicToneMapping( vec3 color ) { - const mat3 ACESInputMat = mat3( - vec3( 0.59719, 0.07600, 0.02840 ), vec3( 0.35458, 0.90834, 0.13383 ), - vec3( 0.04823, 0.01566, 0.83777 ) - ); - const mat3 ACESOutputMat = mat3( - vec3( 1.60475, -0.10208, -0.00327 ), vec3( -0.53108, 1.10813, -0.07276 ), - vec3( -0.07367, -0.00605, 1.07602 ) - ); - color *= toneMappingExposure / 0.6; - color = ACESInputMat * color; - color = RRTAndODTFit( color ); - color = ACESOutputMat * color; - return saturate( color ); -} -const mat3 LINEAR_REC2020_TO_LINEAR_SRGB = mat3( - vec3( 1.6605, - 0.1246, - 0.0182 ), - vec3( - 0.5876, 1.1329, - 0.1006 ), - vec3( - 0.0728, - 0.0083, 1.1187 ) -); -const mat3 LINEAR_SRGB_TO_LINEAR_REC2020 = mat3( - vec3( 0.6274, 0.0691, 0.0164 ), - vec3( 0.3293, 0.9195, 0.0880 ), - vec3( 0.0433, 0.0113, 0.8956 ) -); -vec3 agxDefaultContrastApprox( vec3 x ) { - vec3 x2 = x * x; - vec3 x4 = x2 * x2; - return + 15.5 * x4 * x2 - - 40.14 * x4 * x - + 31.96 * x4 - - 6.868 * x2 * x - + 0.4298 * x2 - + 0.1191 * x - - 0.00232; -} -vec3 AgXToneMapping( vec3 color ) { - const mat3 AgXInsetMatrix = mat3( - vec3( 0.856627153315983, 0.137318972929847, 0.11189821299995 ), - vec3( 0.0951212405381588, 0.761241990602591, 0.0767994186031903 ), - vec3( 0.0482516061458583, 0.101439036467562, 0.811302368396859 ) - ); - const mat3 AgXOutsetMatrix = mat3( - vec3( 1.1271005818144368, - 0.1413297634984383, - 0.14132976349843826 ), - vec3( - 0.11060664309660323, 1.157823702216272, - 0.11060664309660294 ), - vec3( - 0.016493938717834573, - 0.016493938717834257, 1.2519364065950405 ) - ); - const float AgxMinEv = - 12.47393; const float AgxMaxEv = 4.026069; - color *= toneMappingExposure; - color = LINEAR_SRGB_TO_LINEAR_REC2020 * color; - color = AgXInsetMatrix * color; - color = max( color, 1e-10 ); color = log2( color ); - color = ( color - AgxMinEv ) / ( AgxMaxEv - AgxMinEv ); - color = clamp( color, 0.0, 1.0 ); - color = agxDefaultContrastApprox( color ); - color = AgXOutsetMatrix * color; - color = pow( max( vec3( 0.0 ), color ), vec3( 2.2 ) ); - color = LINEAR_REC2020_TO_LINEAR_SRGB * color; - color = clamp( color, 0.0, 1.0 ); - return color; -} -vec3 NeutralToneMapping( vec3 color ) { - const float StartCompression = 0.8 - 0.04; - const float Desaturation = 0.15; - color *= toneMappingExposure; - float x = min( color.r, min( color.g, color.b ) ); - float offset = x < 0.08 ? x - 6.25 * x * x : 0.04; - color -= offset; - float peak = max( color.r, max( color.g, color.b ) ); - if ( peak < StartCompression ) return color; - float d = 1. - StartCompression; - float newPeak = 1. - d * d / ( peak + d - StartCompression ); - color *= newPeak / peak; - float g = 1. - 1. / ( Desaturation * ( peak - newPeak ) + 1. ); - return mix( color, vec3( newPeak ), g ); -} -vec3 CustomToneMapping( vec3 color ) { return color; }`,Bf=`#ifdef USE_TRANSMISSION - material.transmission = transmission; - material.transmissionAlpha = 1.0; - material.thickness = thickness; - material.attenuationDistance = attenuationDistance; - material.attenuationColor = attenuationColor; - #ifdef USE_TRANSMISSIONMAP - material.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r; - #endif - #ifdef USE_THICKNESSMAP - material.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g; - #endif - vec3 pos = vWorldPosition; - vec3 v = normalize( cameraPosition - pos ); - vec3 n = inverseTransformDirection( normal, viewMatrix ); - vec4 transmitted = getIBLVolumeRefraction( - n, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90, - pos, modelMatrix, viewMatrix, projectionMatrix, material.dispersion, material.ior, material.thickness, - material.attenuationColor, material.attenuationDistance ); - material.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission ); - totalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission ); -#endif`,zf=`#ifdef USE_TRANSMISSION - uniform float transmission; - uniform float thickness; - uniform float attenuationDistance; - uniform vec3 attenuationColor; - #ifdef USE_TRANSMISSIONMAP - uniform sampler2D transmissionMap; - #endif - #ifdef USE_THICKNESSMAP - uniform sampler2D thicknessMap; - #endif - uniform vec2 transmissionSamplerSize; - uniform sampler2D transmissionSamplerMap; - uniform mat4 modelMatrix; - uniform mat4 projectionMatrix; - varying vec3 vWorldPosition; - float w0( float a ) { - return ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 ); - } - float w1( float a ) { - return ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 ); - } - float w2( float a ){ - return ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 ); - } - float w3( float a ) { - return ( 1.0 / 6.0 ) * ( a * a * a ); - } - float g0( float a ) { - return w0( a ) + w1( a ); - } - float g1( float a ) { - return w2( a ) + w3( a ); - } - float h0( float a ) { - return - 1.0 + w1( a ) / ( w0( a ) + w1( a ) ); - } - float h1( float a ) { - return 1.0 + w3( a ) / ( w2( a ) + w3( a ) ); - } - vec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) { - uv = uv * texelSize.zw + 0.5; - vec2 iuv = floor( uv ); - vec2 fuv = fract( uv ); - float g0x = g0( fuv.x ); - float g1x = g1( fuv.x ); - float h0x = h0( fuv.x ); - float h1x = h1( fuv.x ); - float h0y = h0( fuv.y ); - float h1y = h1( fuv.y ); - vec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy; - vec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy; - vec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy; - vec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy; - return g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) + - g1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) ); - } - vec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) { - vec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) ); - vec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) ); - vec2 fLodSizeInv = 1.0 / fLodSize; - vec2 cLodSizeInv = 1.0 / cLodSize; - vec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) ); - vec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) ); - return mix( fSample, cSample, fract( lod ) ); - } - vec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) { - vec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior ); - vec3 modelScale; - modelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) ); - modelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) ); - modelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) ); - return normalize( refractionVector ) * thickness * modelScale; - } - float applyIorToRoughness( const in float roughness, const in float ior ) { - return roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 ); - } - vec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) { - float lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior ); - return textureBicubic( transmissionSamplerMap, fragCoord.xy, lod ); - } - vec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) { - if ( isinf( attenuationDistance ) ) { - return vec3( 1.0 ); - } else { - vec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance; - vec3 transmittance = exp( - attenuationCoefficient * transmissionDistance ); return transmittance; - } - } - vec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor, - const in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix, - const in mat4 viewMatrix, const in mat4 projMatrix, const in float dispersion, const in float ior, const in float thickness, - const in vec3 attenuationColor, const in float attenuationDistance ) { - vec4 transmittedLight; - vec3 transmittance; - #ifdef USE_DISPERSION - float halfSpread = ( ior - 1.0 ) * 0.025 * dispersion; - vec3 iors = vec3( ior - halfSpread, ior, ior + halfSpread ); - for ( int i = 0; i < 3; i ++ ) { - vec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, iors[ i ], modelMatrix ); - vec3 refractedRayExit = position + transmissionRay; - - vec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 ); - vec2 refractionCoords = ndcPos.xy / ndcPos.w; - refractionCoords += 1.0; - refractionCoords /= 2.0; - - vec4 transmissionSample = getTransmissionSample( refractionCoords, roughness, iors[ i ] ); - transmittedLight[ i ] = transmissionSample[ i ]; - transmittedLight.a += transmissionSample.a; - transmittance[ i ] = diffuseColor[ i ] * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance )[ i ]; - } - transmittedLight.a /= 3.0; - - #else - - vec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix ); - vec3 refractedRayExit = position + transmissionRay; - vec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 ); - vec2 refractionCoords = ndcPos.xy / ndcPos.w; - refractionCoords += 1.0; - refractionCoords /= 2.0; - transmittedLight = getTransmissionSample( refractionCoords, roughness, ior ); - transmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance ); - - #endif - vec3 attenuatedColor = transmittance * transmittedLight.rgb; - vec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness ); - float transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0; - return vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor ); - } -#endif`,Hf=`#if defined( USE_UV ) || defined( USE_ANISOTROPY ) - varying vec2 vUv; -#endif -#ifdef USE_MAP - varying vec2 vMapUv; -#endif -#ifdef USE_ALPHAMAP - varying vec2 vAlphaMapUv; -#endif -#ifdef USE_LIGHTMAP - varying vec2 vLightMapUv; -#endif -#ifdef USE_AOMAP - varying vec2 vAoMapUv; -#endif -#ifdef USE_BUMPMAP - varying vec2 vBumpMapUv; -#endif -#ifdef USE_NORMALMAP - varying vec2 vNormalMapUv; -#endif -#ifdef USE_EMISSIVEMAP - varying vec2 vEmissiveMapUv; -#endif -#ifdef USE_METALNESSMAP - varying vec2 vMetalnessMapUv; -#endif -#ifdef USE_ROUGHNESSMAP - varying vec2 vRoughnessMapUv; -#endif -#ifdef USE_ANISOTROPYMAP - varying vec2 vAnisotropyMapUv; -#endif -#ifdef USE_CLEARCOATMAP - varying vec2 vClearcoatMapUv; -#endif -#ifdef USE_CLEARCOAT_NORMALMAP - varying vec2 vClearcoatNormalMapUv; -#endif -#ifdef USE_CLEARCOAT_ROUGHNESSMAP - varying vec2 vClearcoatRoughnessMapUv; -#endif -#ifdef USE_IRIDESCENCEMAP - varying vec2 vIridescenceMapUv; -#endif -#ifdef USE_IRIDESCENCE_THICKNESSMAP - varying vec2 vIridescenceThicknessMapUv; -#endif -#ifdef USE_SHEEN_COLORMAP - varying vec2 vSheenColorMapUv; -#endif -#ifdef USE_SHEEN_ROUGHNESSMAP - varying vec2 vSheenRoughnessMapUv; -#endif -#ifdef USE_SPECULARMAP - varying vec2 vSpecularMapUv; -#endif -#ifdef USE_SPECULAR_COLORMAP - varying vec2 vSpecularColorMapUv; -#endif -#ifdef USE_SPECULAR_INTENSITYMAP - varying vec2 vSpecularIntensityMapUv; -#endif -#ifdef USE_TRANSMISSIONMAP - uniform mat3 transmissionMapTransform; - varying vec2 vTransmissionMapUv; -#endif -#ifdef USE_THICKNESSMAP - uniform mat3 thicknessMapTransform; - varying vec2 vThicknessMapUv; -#endif`,Gf=`#if defined( USE_UV ) || defined( USE_ANISOTROPY ) - varying vec2 vUv; -#endif -#ifdef USE_MAP - uniform mat3 mapTransform; - varying vec2 vMapUv; -#endif -#ifdef USE_ALPHAMAP - uniform mat3 alphaMapTransform; - varying vec2 vAlphaMapUv; -#endif -#ifdef USE_LIGHTMAP - uniform mat3 lightMapTransform; - varying vec2 vLightMapUv; -#endif -#ifdef USE_AOMAP - uniform mat3 aoMapTransform; - varying vec2 vAoMapUv; -#endif -#ifdef USE_BUMPMAP - uniform mat3 bumpMapTransform; - varying vec2 vBumpMapUv; -#endif -#ifdef USE_NORMALMAP - uniform mat3 normalMapTransform; - varying vec2 vNormalMapUv; -#endif -#ifdef USE_DISPLACEMENTMAP - uniform mat3 displacementMapTransform; - varying vec2 vDisplacementMapUv; -#endif -#ifdef USE_EMISSIVEMAP - uniform mat3 emissiveMapTransform; - varying vec2 vEmissiveMapUv; -#endif -#ifdef USE_METALNESSMAP - uniform mat3 metalnessMapTransform; - varying vec2 vMetalnessMapUv; -#endif -#ifdef USE_ROUGHNESSMAP - uniform mat3 roughnessMapTransform; - varying vec2 vRoughnessMapUv; -#endif -#ifdef USE_ANISOTROPYMAP - uniform mat3 anisotropyMapTransform; - varying vec2 vAnisotropyMapUv; -#endif -#ifdef USE_CLEARCOATMAP - uniform mat3 clearcoatMapTransform; - varying vec2 vClearcoatMapUv; -#endif -#ifdef USE_CLEARCOAT_NORMALMAP - uniform mat3 clearcoatNormalMapTransform; - varying vec2 vClearcoatNormalMapUv; -#endif -#ifdef USE_CLEARCOAT_ROUGHNESSMAP - uniform mat3 clearcoatRoughnessMapTransform; - varying vec2 vClearcoatRoughnessMapUv; -#endif -#ifdef USE_SHEEN_COLORMAP - uniform mat3 sheenColorMapTransform; - varying vec2 vSheenColorMapUv; -#endif -#ifdef USE_SHEEN_ROUGHNESSMAP - uniform mat3 sheenRoughnessMapTransform; - varying vec2 vSheenRoughnessMapUv; -#endif -#ifdef USE_IRIDESCENCEMAP - uniform mat3 iridescenceMapTransform; - varying vec2 vIridescenceMapUv; -#endif -#ifdef USE_IRIDESCENCE_THICKNESSMAP - uniform mat3 iridescenceThicknessMapTransform; - varying vec2 vIridescenceThicknessMapUv; -#endif -#ifdef USE_SPECULARMAP - uniform mat3 specularMapTransform; - varying vec2 vSpecularMapUv; -#endif -#ifdef USE_SPECULAR_COLORMAP - uniform mat3 specularColorMapTransform; - varying vec2 vSpecularColorMapUv; -#endif -#ifdef USE_SPECULAR_INTENSITYMAP - uniform mat3 specularIntensityMapTransform; - varying vec2 vSpecularIntensityMapUv; -#endif -#ifdef USE_TRANSMISSIONMAP - uniform mat3 transmissionMapTransform; - varying vec2 vTransmissionMapUv; -#endif -#ifdef USE_THICKNESSMAP - uniform mat3 thicknessMapTransform; - varying vec2 vThicknessMapUv; -#endif`,Vf=`#if defined( USE_UV ) || defined( USE_ANISOTROPY ) - vUv = vec3( uv, 1 ).xy; -#endif -#ifdef USE_MAP - vMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy; -#endif -#ifdef USE_ALPHAMAP - vAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy; -#endif -#ifdef USE_LIGHTMAP - vLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy; -#endif -#ifdef USE_AOMAP - vAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy; -#endif -#ifdef USE_BUMPMAP - vBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy; -#endif -#ifdef USE_NORMALMAP - vNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy; -#endif -#ifdef USE_DISPLACEMENTMAP - vDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy; -#endif -#ifdef USE_EMISSIVEMAP - vEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy; -#endif -#ifdef USE_METALNESSMAP - vMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy; -#endif -#ifdef USE_ROUGHNESSMAP - vRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy; -#endif -#ifdef USE_ANISOTROPYMAP - vAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy; -#endif -#ifdef USE_CLEARCOATMAP - vClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy; -#endif -#ifdef USE_CLEARCOAT_NORMALMAP - vClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy; -#endif -#ifdef USE_CLEARCOAT_ROUGHNESSMAP - vClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy; -#endif -#ifdef USE_IRIDESCENCEMAP - vIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy; -#endif -#ifdef USE_IRIDESCENCE_THICKNESSMAP - vIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy; -#endif -#ifdef USE_SHEEN_COLORMAP - vSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy; -#endif -#ifdef USE_SHEEN_ROUGHNESSMAP - vSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy; -#endif -#ifdef USE_SPECULARMAP - vSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy; -#endif -#ifdef USE_SPECULAR_COLORMAP - vSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy; -#endif -#ifdef USE_SPECULAR_INTENSITYMAP - vSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy; -#endif -#ifdef USE_TRANSMISSIONMAP - vTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy; -#endif -#ifdef USE_THICKNESSMAP - vThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy; -#endif`,kf=`#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0 - vec4 worldPosition = vec4( transformed, 1.0 ); - #ifdef USE_BATCHING - worldPosition = batchingMatrix * worldPosition; - #endif - #ifdef USE_INSTANCING - worldPosition = instanceMatrix * worldPosition; - #endif - worldPosition = modelMatrix * worldPosition; -#endif`;const Wf=`varying vec2 vUv; -uniform mat3 uvTransform; -void main() { - vUv = ( uvTransform * vec3( uv, 1 ) ).xy; - gl_Position = vec4( position.xy, 1.0, 1.0 ); -}`,Xf=`uniform sampler2D t2D; -uniform float backgroundIntensity; -varying vec2 vUv; -void main() { - vec4 texColor = texture2D( t2D, vUv ); - #ifdef DECODE_VIDEO_TEXTURE - texColor = vec4( mix( pow( texColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), texColor.rgb * 0.0773993808, vec3( lessThanEqual( texColor.rgb, vec3( 0.04045 ) ) ) ), texColor.w ); - #endif - texColor.rgb *= backgroundIntensity; - gl_FragColor = texColor; - #include - #include -}`,qf=`varying vec3 vWorldDirection; -#include -void main() { - vWorldDirection = transformDirection( position, modelMatrix ); - #include - #include - gl_Position.z = gl_Position.w; -}`,Yf=`#ifdef ENVMAP_TYPE_CUBE - uniform samplerCube envMap; -#elif defined( ENVMAP_TYPE_CUBE_UV ) - uniform sampler2D envMap; -#endif -uniform float flipEnvMap; -uniform float backgroundBlurriness; -uniform float backgroundIntensity; -uniform mat3 backgroundRotation; -varying vec3 vWorldDirection; -#include -void main() { - #ifdef ENVMAP_TYPE_CUBE - vec4 texColor = textureCube( envMap, backgroundRotation * vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) ); - #elif defined( ENVMAP_TYPE_CUBE_UV ) - vec4 texColor = textureCubeUV( envMap, backgroundRotation * vWorldDirection, backgroundBlurriness ); - #else - vec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 ); - #endif - texColor.rgb *= backgroundIntensity; - gl_FragColor = texColor; - #include - #include -}`,Zf=`varying vec3 vWorldDirection; -#include -void main() { - vWorldDirection = transformDirection( position, modelMatrix ); - #include - #include - gl_Position.z = gl_Position.w; -}`,Kf=`uniform samplerCube tCube; -uniform float tFlip; -uniform float opacity; -varying vec3 vWorldDirection; -void main() { - vec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) ); - gl_FragColor = texColor; - gl_FragColor.a *= opacity; - #include - #include -}`,jf=`#include -#include -#include -#include -#include -#include -#include -#include -varying vec2 vHighPrecisionZW; -void main() { - #include - #include - #include - #include - #ifdef USE_DISPLACEMENTMAP - #include - #include - #include - #endif - #include - #include - #include - #include - #include - #include - #include - vHighPrecisionZW = gl_Position.zw; -}`,$f=`#if DEPTH_PACKING == 3200 - uniform float opacity; -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -varying vec2 vHighPrecisionZW; -void main() { - vec4 diffuseColor = vec4( 1.0 ); - #include - #if DEPTH_PACKING == 3200 - diffuseColor.a = opacity; - #endif - #include - #include - #include - #include - #include - float fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5; - #if DEPTH_PACKING == 3200 - gl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity ); - #elif DEPTH_PACKING == 3201 - gl_FragColor = packDepthToRGBA( fragCoordZ ); - #elif DEPTH_PACKING == 3202 - gl_FragColor = vec4( packDepthToRGB( fragCoordZ ), 1.0 ); - #elif DEPTH_PACKING == 3203 - gl_FragColor = vec4( packDepthToRG( fragCoordZ ), 0.0, 1.0 ); - #endif -}`,Jf=`#define DISTANCE -varying vec3 vWorldPosition; -#include -#include -#include -#include -#include -#include -#include -void main() { - #include - #include - #include - #include - #ifdef USE_DISPLACEMENTMAP - #include - #include - #include - #endif - #include - #include - #include - #include - #include - #include - #include - vWorldPosition = worldPosition.xyz; -}`,Qf=`#define DISTANCE -uniform vec3 referencePosition; -uniform float nearDistance; -uniform float farDistance; -varying vec3 vWorldPosition; -#include -#include -#include -#include -#include -#include -#include -#include -void main () { - vec4 diffuseColor = vec4( 1.0 ); - #include - #include - #include - #include - #include - float dist = length( vWorldPosition - referencePosition ); - dist = ( dist - nearDistance ) / ( farDistance - nearDistance ); - dist = saturate( dist ); - gl_FragColor = packDepthToRGBA( dist ); -}`,ep=`varying vec3 vWorldDirection; -#include -void main() { - vWorldDirection = transformDirection( position, modelMatrix ); - #include - #include -}`,tp=`uniform sampler2D tEquirect; -varying vec3 vWorldDirection; -#include -void main() { - vec3 direction = normalize( vWorldDirection ); - vec2 sampleUV = equirectUv( direction ); - gl_FragColor = texture2D( tEquirect, sampleUV ); - #include - #include -}`,np=`uniform float scale; -attribute float lineDistance; -varying float vLineDistance; -#include -#include -#include -#include -#include -#include -#include -void main() { - vLineDistance = scale * lineDistance; - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include -}`,ip=`uniform vec3 diffuse; -uniform float opacity; -uniform float dashSize; -uniform float totalSize; -varying float vLineDistance; -#include -#include -#include -#include -#include -#include -#include -void main() { - vec4 diffuseColor = vec4( diffuse, opacity ); - #include - if ( mod( vLineDistance, totalSize ) > dashSize ) { - discard; - } - vec3 outgoingLight = vec3( 0.0 ); - #include - #include - #include - outgoingLight = diffuseColor.rgb; - #include - #include - #include - #include - #include -}`,rp=`#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -void main() { - #include - #include - #include - #include - #include - #if defined ( USE_ENVMAP ) || defined ( USE_SKINNING ) - #include - #include - #include - #include - #include - #endif - #include - #include - #include - #include - #include - #include - #include - #include - #include -}`,sp=`uniform vec3 diffuse; -uniform float opacity; -#ifndef FLAT_SHADED - varying vec3 vNormal; -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -void main() { - vec4 diffuseColor = vec4( diffuse, opacity ); - #include - #include - #include - #include - #include - #include - #include - #include - ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) ); - #ifdef USE_LIGHTMAP - vec4 lightMapTexel = texture2D( lightMap, vLightMapUv ); - reflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI; - #else - reflectedLight.indirectDiffuse += vec3( 1.0 ); - #endif - #include - reflectedLight.indirectDiffuse *= diffuseColor.rgb; - vec3 outgoingLight = reflectedLight.indirectDiffuse; - #include - #include - #include - #include - #include - #include - #include -}`,ap=`#define LAMBERT -varying vec3 vViewPosition; -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -void main() { - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - vViewPosition = - mvPosition.xyz; - #include - #include - #include - #include -}`,op=`#define LAMBERT -uniform vec3 diffuse; -uniform vec3 emissive; -uniform float opacity; -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -void main() { - vec4 diffuseColor = vec4( diffuse, opacity ); - #include - ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) ); - vec3 totalEmissiveRadiance = emissive; - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance; - #include - #include - #include - #include - #include - #include - #include -}`,lp=`#define MATCAP -varying vec3 vViewPosition; -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -void main() { - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - vViewPosition = - mvPosition.xyz; -}`,cp=`#define MATCAP -uniform vec3 diffuse; -uniform float opacity; -uniform sampler2D matcap; -varying vec3 vViewPosition; -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -void main() { - vec4 diffuseColor = vec4( diffuse, opacity ); - #include - #include - #include - #include - #include - #include - #include - #include - #include - vec3 viewDir = normalize( vViewPosition ); - vec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) ); - vec3 y = cross( viewDir, x ); - vec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5; - #ifdef USE_MATCAP - vec4 matcapColor = texture2D( matcap, uv ); - #else - vec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 ); - #endif - vec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb; - #include - #include - #include - #include - #include - #include -}`,up=`#define NORMAL -#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE ) - varying vec3 vViewPosition; -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -void main() { - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include -#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE ) - vViewPosition = - mvPosition.xyz; -#endif -}`,dp=`#define NORMAL -uniform float opacity; -#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE ) - varying vec3 vViewPosition; -#endif -#include -#include -#include -#include -#include -#include -#include -void main() { - vec4 diffuseColor = vec4( 0.0, 0.0, 0.0, opacity ); - #include - #include - #include - #include - gl_FragColor = vec4( packNormalToRGB( normal ), diffuseColor.a ); - #ifdef OPAQUE - gl_FragColor.a = 1.0; - #endif -}`,hp=`#define PHONG -varying vec3 vViewPosition; -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -void main() { - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - vViewPosition = - mvPosition.xyz; - #include - #include - #include - #include -}`,fp=`#define PHONG -uniform vec3 diffuse; -uniform vec3 emissive; -uniform vec3 specular; -uniform float shininess; -uniform float opacity; -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -void main() { - vec4 diffuseColor = vec4( diffuse, opacity ); - #include - ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) ); - vec3 totalEmissiveRadiance = emissive; - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance; - #include - #include - #include - #include - #include - #include - #include -}`,pp=`#define STANDARD -varying vec3 vViewPosition; -#ifdef USE_TRANSMISSION - varying vec3 vWorldPosition; -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -void main() { - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - vViewPosition = - mvPosition.xyz; - #include - #include - #include -#ifdef USE_TRANSMISSION - vWorldPosition = worldPosition.xyz; -#endif -}`,mp=`#define STANDARD -#ifdef PHYSICAL - #define IOR - #define USE_SPECULAR -#endif -uniform vec3 diffuse; -uniform vec3 emissive; -uniform float roughness; -uniform float metalness; -uniform float opacity; -#ifdef IOR - uniform float ior; -#endif -#ifdef USE_SPECULAR - uniform float specularIntensity; - uniform vec3 specularColor; - #ifdef USE_SPECULAR_COLORMAP - uniform sampler2D specularColorMap; - #endif - #ifdef USE_SPECULAR_INTENSITYMAP - uniform sampler2D specularIntensityMap; - #endif -#endif -#ifdef USE_CLEARCOAT - uniform float clearcoat; - uniform float clearcoatRoughness; -#endif -#ifdef USE_DISPERSION - uniform float dispersion; -#endif -#ifdef USE_IRIDESCENCE - uniform float iridescence; - uniform float iridescenceIOR; - uniform float iridescenceThicknessMinimum; - uniform float iridescenceThicknessMaximum; -#endif -#ifdef USE_SHEEN - uniform vec3 sheenColor; - uniform float sheenRoughness; - #ifdef USE_SHEEN_COLORMAP - uniform sampler2D sheenColorMap; - #endif - #ifdef USE_SHEEN_ROUGHNESSMAP - uniform sampler2D sheenRoughnessMap; - #endif -#endif -#ifdef USE_ANISOTROPY - uniform vec2 anisotropyVector; - #ifdef USE_ANISOTROPYMAP - uniform sampler2D anisotropyMap; - #endif -#endif -varying vec3 vViewPosition; -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -void main() { - vec4 diffuseColor = vec4( diffuse, opacity ); - #include - ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) ); - vec3 totalEmissiveRadiance = emissive; - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - vec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse; - vec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular; - #include - vec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance; - #ifdef USE_SHEEN - float sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor ); - outgoingLight = outgoingLight * sheenEnergyComp + sheenSpecularDirect + sheenSpecularIndirect; - #endif - #ifdef USE_CLEARCOAT - float dotNVcc = saturate( dot( geometryClearcoatNormal, geometryViewDir ) ); - vec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc ); - outgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + ( clearcoatSpecularDirect + clearcoatSpecularIndirect ) * material.clearcoat; - #endif - #include - #include - #include - #include - #include - #include -}`,gp=`#define TOON -varying vec3 vViewPosition; -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -void main() { - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - vViewPosition = - mvPosition.xyz; - #include - #include - #include -}`,vp=`#define TOON -uniform vec3 diffuse; -uniform vec3 emissive; -uniform float opacity; -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -void main() { - vec4 diffuseColor = vec4( diffuse, opacity ); - #include - ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) ); - vec3 totalEmissiveRadiance = emissive; - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance; - #include - #include - #include - #include - #include - #include -}`,_p=`uniform float size; -uniform float scale; -#include -#include -#include -#include -#include -#include -#ifdef USE_POINTS_UV - varying vec2 vUv; - uniform mat3 uvTransform; -#endif -void main() { - #ifdef USE_POINTS_UV - vUv = ( uvTransform * vec3( uv, 1 ) ).xy; - #endif - #include - #include - #include - #include - #include - #include - gl_PointSize = size; - #ifdef USE_SIZEATTENUATION - bool isPerspective = isPerspectiveMatrix( projectionMatrix ); - if ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z ); - #endif - #include - #include - #include - #include -}`,xp=`uniform vec3 diffuse; -uniform float opacity; -#include -#include -#include -#include -#include -#include -#include -#include -void main() { - vec4 diffuseColor = vec4( diffuse, opacity ); - #include - vec3 outgoingLight = vec3( 0.0 ); - #include - #include - #include - #include - #include - outgoingLight = diffuseColor.rgb; - #include - #include - #include - #include - #include -}`,Sp=`#include -#include -#include -#include -#include -#include -#include -void main() { - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include -}`,Mp=`uniform vec3 color; -uniform float opacity; -#include -#include -#include -#include -#include -#include -#include -#include -void main() { - #include - gl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) ); - #include - #include - #include -}`,yp=`uniform float rotation; -uniform vec2 center; -#include -#include -#include -#include -#include -void main() { - #include - vec4 mvPosition = modelViewMatrix[ 3 ]; - vec2 scale = vec2( length( modelMatrix[ 0 ].xyz ), length( modelMatrix[ 1 ].xyz ) ); - #ifndef USE_SIZEATTENUATION - bool isPerspective = isPerspectiveMatrix( projectionMatrix ); - if ( isPerspective ) scale *= - mvPosition.z; - #endif - vec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale; - vec2 rotatedPosition; - rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y; - rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y; - mvPosition.xy += rotatedPosition; - gl_Position = projectionMatrix * mvPosition; - #include - #include - #include -}`,Ep=`uniform vec3 diffuse; -uniform float opacity; -#include -#include -#include -#include -#include -#include -#include -#include -#include -void main() { - vec4 diffuseColor = vec4( diffuse, opacity ); - #include - vec3 outgoingLight = vec3( 0.0 ); - #include - #include - #include - #include - #include - outgoingLight = diffuseColor.rgb; - #include - #include - #include - #include -}`,Pe={alphahash_fragment:Wd,alphahash_pars_fragment:Xd,alphamap_fragment:qd,alphamap_pars_fragment:Yd,alphatest_fragment:Zd,alphatest_pars_fragment:Kd,aomap_fragment:jd,aomap_pars_fragment:$d,batching_pars_vertex:Jd,batching_vertex:Qd,begin_vertex:eh,beginnormal_vertex:th,bsdfs:nh,iridescence_fragment:ih,bumpmap_pars_fragment:rh,clipping_planes_fragment:sh,clipping_planes_pars_fragment:ah,clipping_planes_pars_vertex:oh,clipping_planes_vertex:lh,color_fragment:ch,color_pars_fragment:uh,color_pars_vertex:dh,color_vertex:hh,common:fh,cube_uv_reflection_fragment:ph,defaultnormal_vertex:mh,displacementmap_pars_vertex:gh,displacementmap_vertex:vh,emissivemap_fragment:_h,emissivemap_pars_fragment:xh,colorspace_fragment:Sh,colorspace_pars_fragment:Mh,envmap_fragment:yh,envmap_common_pars_fragment:Eh,envmap_pars_fragment:Th,envmap_pars_vertex:bh,envmap_physical_pars_fragment:Fh,envmap_vertex:Ah,fog_vertex:wh,fog_pars_vertex:Rh,fog_fragment:Ch,fog_pars_fragment:Ph,gradientmap_pars_fragment:Dh,lightmap_pars_fragment:Lh,lights_lambert_fragment:Uh,lights_lambert_pars_fragment:Ih,lights_pars_begin:Nh,lights_toon_fragment:Oh,lights_toon_pars_fragment:Bh,lights_phong_fragment:zh,lights_phong_pars_fragment:Hh,lights_physical_fragment:Gh,lights_physical_pars_fragment:Vh,lights_fragment_begin:kh,lights_fragment_maps:Wh,lights_fragment_end:Xh,logdepthbuf_fragment:qh,logdepthbuf_pars_fragment:Yh,logdepthbuf_pars_vertex:Zh,logdepthbuf_vertex:Kh,map_fragment:jh,map_pars_fragment:$h,map_particle_fragment:Jh,map_particle_pars_fragment:Qh,metalnessmap_fragment:ef,metalnessmap_pars_fragment:tf,morphinstance_vertex:nf,morphcolor_vertex:rf,morphnormal_vertex:sf,morphtarget_pars_vertex:af,morphtarget_vertex:of,normal_fragment_begin:lf,normal_fragment_maps:cf,normal_pars_fragment:uf,normal_pars_vertex:df,normal_vertex:hf,normalmap_pars_fragment:ff,clearcoat_normal_fragment_begin:pf,clearcoat_normal_fragment_maps:mf,clearcoat_pars_fragment:gf,iridescence_pars_fragment:vf,opaque_fragment:_f,packing:xf,premultiplied_alpha_fragment:Sf,project_vertex:Mf,dithering_fragment:yf,dithering_pars_fragment:Ef,roughnessmap_fragment:Tf,roughnessmap_pars_fragment:bf,shadowmap_pars_fragment:Af,shadowmap_pars_vertex:wf,shadowmap_vertex:Rf,shadowmask_pars_fragment:Cf,skinbase_vertex:Pf,skinning_pars_vertex:Df,skinning_vertex:Lf,skinnormal_vertex:Uf,specularmap_fragment:If,specularmap_pars_fragment:Nf,tonemapping_fragment:Ff,tonemapping_pars_fragment:Of,transmission_fragment:Bf,transmission_pars_fragment:zf,uv_pars_fragment:Hf,uv_pars_vertex:Gf,uv_vertex:Vf,worldpos_vertex:kf,background_vert:Wf,background_frag:Xf,backgroundCube_vert:qf,backgroundCube_frag:Yf,cube_vert:Zf,cube_frag:Kf,depth_vert:jf,depth_frag:$f,distanceRGBA_vert:Jf,distanceRGBA_frag:Qf,equirect_vert:ep,equirect_frag:tp,linedashed_vert:np,linedashed_frag:ip,meshbasic_vert:rp,meshbasic_frag:sp,meshlambert_vert:ap,meshlambert_frag:op,meshmatcap_vert:lp,meshmatcap_frag:cp,meshnormal_vert:up,meshnormal_frag:dp,meshphong_vert:hp,meshphong_frag:fp,meshphysical_vert:pp,meshphysical_frag:mp,meshtoon_vert:gp,meshtoon_frag:vp,points_vert:_p,points_frag:xp,shadow_vert:Sp,shadow_frag:Mp,sprite_vert:yp,sprite_frag:Ep},ne={common:{diffuse:{value:new Ye(16777215)},opacity:{value:1},map:{value:null},mapTransform:{value:new De},alphaMap:{value:null},alphaMapTransform:{value:new De},alphaTest:{value:0}},specularmap:{specularMap:{value:null},specularMapTransform:{value:new De}},envmap:{envMap:{value:null},envMapRotation:{value:new De},flipEnvMap:{value:-1},reflectivity:{value:1},ior:{value:1.5},refractionRatio:{value:.98}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1},aoMapTransform:{value:new De}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1},lightMapTransform:{value:new De}},bumpmap:{bumpMap:{value:null},bumpMapTransform:{value:new De},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalMapTransform:{value:new De},normalScale:{value:new Le(1,1)}},displacementmap:{displacementMap:{value:null},displacementMapTransform:{value:new De},displacementScale:{value:1},displacementBias:{value:0}},emissivemap:{emissiveMap:{value:null},emissiveMapTransform:{value:new De}},metalnessmap:{metalnessMap:{value:null},metalnessMapTransform:{value:new De}},roughnessmap:{roughnessMap:{value:null},roughnessMapTransform:{value:new De}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new Ye(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},spotLightMap:{value:[]},spotShadowMap:{value:[]},spotLightMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{},shadowCameraNear:{},shadowCameraFar:{}}},pointShadowMap:{value:[]},pointShadowMatrix:{value:[]},hemisphereLights:{value:[],properties:{direction:{},skyColor:{},groundColor:{}}},rectAreaLights:{value:[],properties:{color:{},position:{},width:{},height:{}}},ltc_1:{value:null},ltc_2:{value:null}},points:{diffuse:{value:new Ye(16777215)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},alphaMapTransform:{value:new De},alphaTest:{value:0},uvTransform:{value:new De}},sprite:{diffuse:{value:new Ye(16777215)},opacity:{value:1},center:{value:new Le(.5,.5)},rotation:{value:0},map:{value:null},mapTransform:{value:new De},alphaMap:{value:null},alphaMapTransform:{value:new De},alphaTest:{value:0}}},an={basic:{uniforms:Tt([ne.common,ne.specularmap,ne.envmap,ne.aomap,ne.lightmap,ne.fog]),vertexShader:Pe.meshbasic_vert,fragmentShader:Pe.meshbasic_frag},lambert:{uniforms:Tt([ne.common,ne.specularmap,ne.envmap,ne.aomap,ne.lightmap,ne.emissivemap,ne.bumpmap,ne.normalmap,ne.displacementmap,ne.fog,ne.lights,{emissive:{value:new Ye(0)}}]),vertexShader:Pe.meshlambert_vert,fragmentShader:Pe.meshlambert_frag},phong:{uniforms:Tt([ne.common,ne.specularmap,ne.envmap,ne.aomap,ne.lightmap,ne.emissivemap,ne.bumpmap,ne.normalmap,ne.displacementmap,ne.fog,ne.lights,{emissive:{value:new Ye(0)},specular:{value:new Ye(1118481)},shininess:{value:30}}]),vertexShader:Pe.meshphong_vert,fragmentShader:Pe.meshphong_frag},standard:{uniforms:Tt([ne.common,ne.envmap,ne.aomap,ne.lightmap,ne.emissivemap,ne.bumpmap,ne.normalmap,ne.displacementmap,ne.roughnessmap,ne.metalnessmap,ne.fog,ne.lights,{emissive:{value:new Ye(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:Pe.meshphysical_vert,fragmentShader:Pe.meshphysical_frag},toon:{uniforms:Tt([ne.common,ne.aomap,ne.lightmap,ne.emissivemap,ne.bumpmap,ne.normalmap,ne.displacementmap,ne.gradientmap,ne.fog,ne.lights,{emissive:{value:new Ye(0)}}]),vertexShader:Pe.meshtoon_vert,fragmentShader:Pe.meshtoon_frag},matcap:{uniforms:Tt([ne.common,ne.bumpmap,ne.normalmap,ne.displacementmap,ne.fog,{matcap:{value:null}}]),vertexShader:Pe.meshmatcap_vert,fragmentShader:Pe.meshmatcap_frag},points:{uniforms:Tt([ne.points,ne.fog]),vertexShader:Pe.points_vert,fragmentShader:Pe.points_frag},dashed:{uniforms:Tt([ne.common,ne.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:Pe.linedashed_vert,fragmentShader:Pe.linedashed_frag},depth:{uniforms:Tt([ne.common,ne.displacementmap]),vertexShader:Pe.depth_vert,fragmentShader:Pe.depth_frag},normal:{uniforms:Tt([ne.common,ne.bumpmap,ne.normalmap,ne.displacementmap,{opacity:{value:1}}]),vertexShader:Pe.meshnormal_vert,fragmentShader:Pe.meshnormal_frag},sprite:{uniforms:Tt([ne.sprite,ne.fog]),vertexShader:Pe.sprite_vert,fragmentShader:Pe.sprite_frag},background:{uniforms:{uvTransform:{value:new De},t2D:{value:null},backgroundIntensity:{value:1}},vertexShader:Pe.background_vert,fragmentShader:Pe.background_frag},backgroundCube:{uniforms:{envMap:{value:null},flipEnvMap:{value:-1},backgroundBlurriness:{value:0},backgroundIntensity:{value:1},backgroundRotation:{value:new De}},vertexShader:Pe.backgroundCube_vert,fragmentShader:Pe.backgroundCube_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:Pe.cube_vert,fragmentShader:Pe.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:Pe.equirect_vert,fragmentShader:Pe.equirect_frag},distanceRGBA:{uniforms:Tt([ne.common,ne.displacementmap,{referencePosition:{value:new N},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:Pe.distanceRGBA_vert,fragmentShader:Pe.distanceRGBA_frag},shadow:{uniforms:Tt([ne.lights,ne.fog,{color:{value:new Ye(0)},opacity:{value:1}}]),vertexShader:Pe.shadow_vert,fragmentShader:Pe.shadow_frag}};an.physical={uniforms:Tt([an.standard.uniforms,{clearcoat:{value:0},clearcoatMap:{value:null},clearcoatMapTransform:{value:new De},clearcoatNormalMap:{value:null},clearcoatNormalMapTransform:{value:new De},clearcoatNormalScale:{value:new Le(1,1)},clearcoatRoughness:{value:0},clearcoatRoughnessMap:{value:null},clearcoatRoughnessMapTransform:{value:new De},dispersion:{value:0},iridescence:{value:0},iridescenceMap:{value:null},iridescenceMapTransform:{value:new De},iridescenceIOR:{value:1.3},iridescenceThicknessMinimum:{value:100},iridescenceThicknessMaximum:{value:400},iridescenceThicknessMap:{value:null},iridescenceThicknessMapTransform:{value:new De},sheen:{value:0},sheenColor:{value:new Ye(0)},sheenColorMap:{value:null},sheenColorMapTransform:{value:new De},sheenRoughness:{value:1},sheenRoughnessMap:{value:null},sheenRoughnessMapTransform:{value:new De},transmission:{value:0},transmissionMap:{value:null},transmissionMapTransform:{value:new De},transmissionSamplerSize:{value:new Le},transmissionSamplerMap:{value:null},thickness:{value:0},thicknessMap:{value:null},thicknessMapTransform:{value:new De},attenuationDistance:{value:0},attenuationColor:{value:new Ye(0)},specularColor:{value:new Ye(1,1,1)},specularColorMap:{value:null},specularColorMapTransform:{value:new De},specularIntensity:{value:1},specularIntensityMap:{value:null},specularIntensityMapTransform:{value:new De},anisotropyVector:{value:new Le},anisotropyMap:{value:null},anisotropyMapTransform:{value:new De}}]),vertexShader:Pe.meshphysical_vert,fragmentShader:Pe.meshphysical_frag};const Wr={r:0,b:0,g:0},qn=new En,Tp=new tt;function bp(i,e,t,n,r,s,a){const o=new Ye(0);let l=s===!0?0:1,c,u,d=null,p=0,m=null;function _(T){let y=T.isScene===!0?T.background:null;return y&&y.isTexture&&(y=(T.backgroundBlurriness>0?t:e).get(y)),y}function M(T){let y=!1;const b=_(T);b===null?h(o,l):b&&b.isColor&&(h(b,1),y=!0);const O=i.xr.getEnvironmentBlendMode();O==="additive"?n.buffers.color.setClear(0,0,0,1,a):O==="alpha-blend"&&n.buffers.color.setClear(0,0,0,0,a),(i.autoClear||y)&&(n.buffers.depth.setTest(!0),n.buffers.depth.setMask(!0),n.buffers.color.setMask(!0),i.clear(i.autoClearColor,i.autoClearDepth,i.autoClearStencil))}function f(T,y){const b=_(y);b&&(b.isCubeTexture||b.mapping===_s)?(u===void 0&&(u=new lt(new ki(1,1,1),new Gt({name:"BackgroundCubeMaterial",uniforms:Oi(an.backgroundCube.uniforms),vertexShader:an.backgroundCube.vertexShader,fragmentShader:an.backgroundCube.fragmentShader,side:Lt,depthTest:!1,depthWrite:!1,fog:!1})),u.geometry.deleteAttribute("normal"),u.geometry.deleteAttribute("uv"),u.onBeforeRender=function(O,C,A){this.matrixWorld.copyPosition(A.matrixWorld)},Object.defineProperty(u.material,"envMap",{get:function(){return this.uniforms.envMap.value}}),r.update(u)),qn.copy(y.backgroundRotation),qn.x*=-1,qn.y*=-1,qn.z*=-1,b.isCubeTexture&&b.isRenderTargetTexture===!1&&(qn.y*=-1,qn.z*=-1),u.material.uniforms.envMap.value=b,u.material.uniforms.flipEnvMap.value=b.isCubeTexture&&b.isRenderTargetTexture===!1?-1:1,u.material.uniforms.backgroundBlurriness.value=y.backgroundBlurriness,u.material.uniforms.backgroundIntensity.value=y.backgroundIntensity,u.material.uniforms.backgroundRotation.value.setFromMatrix4(Tp.makeRotationFromEuler(qn)),u.material.toneMapped=qe.getTransfer(b.colorSpace)!==et,(d!==b||p!==b.version||m!==i.toneMapping)&&(u.material.needsUpdate=!0,d=b,p=b.version,m=i.toneMapping),u.layers.enableAll(),T.unshift(u,u.geometry,u.material,0,0,null)):b&&b.isTexture&&(c===void 0&&(c=new lt(new un(2,2),new Gt({name:"BackgroundMaterial",uniforms:Oi(an.background.uniforms),vertexShader:an.background.vertexShader,fragmentShader:an.background.fragmentShader,side:In,depthTest:!1,depthWrite:!1,fog:!1})),c.geometry.deleteAttribute("normal"),Object.defineProperty(c.material,"map",{get:function(){return this.uniforms.t2D.value}}),r.update(c)),c.material.uniforms.t2D.value=b,c.material.uniforms.backgroundIntensity.value=y.backgroundIntensity,c.material.toneMapped=qe.getTransfer(b.colorSpace)!==et,b.matrixAutoUpdate===!0&&b.updateMatrix(),c.material.uniforms.uvTransform.value.copy(b.matrix),(d!==b||p!==b.version||m!==i.toneMapping)&&(c.material.needsUpdate=!0,d=b,p=b.version,m=i.toneMapping),c.layers.enableAll(),T.unshift(c,c.geometry,c.material,0,0,null))}function h(T,y){T.getRGB(Wr,Sc(i)),n.buffers.color.setClear(Wr.r,Wr.g,Wr.b,y,a)}return{getClearColor:function(){return o},setClearColor:function(T,y=1){o.set(T),l=y,h(o,l)},getClearAlpha:function(){return l},setClearAlpha:function(T){l=T,h(o,l)},render:M,addToRenderList:f}}function Ap(i,e){const t=i.getParameter(i.MAX_VERTEX_ATTRIBS),n={},r=p(null);let s=r,a=!1;function o(g,S,V,z,k){let K=!1;const B=d(z,V,S);s!==B&&(s=B,c(s.object)),K=m(g,z,V,k),K&&_(g,z,V,k),k!==null&&e.update(k,i.ELEMENT_ARRAY_BUFFER),(K||a)&&(a=!1,b(g,S,V,z),k!==null&&i.bindBuffer(i.ELEMENT_ARRAY_BUFFER,e.get(k).buffer))}function l(){return i.createVertexArray()}function c(g){return i.bindVertexArray(g)}function u(g){return i.deleteVertexArray(g)}function d(g,S,V){const z=V.wireframe===!0;let k=n[g.id];k===void 0&&(k={},n[g.id]=k);let K=k[S.id];K===void 0&&(K={},k[S.id]=K);let B=K[z];return B===void 0&&(B=p(l()),K[z]=B),B}function p(g){const S=[],V=[],z=[];for(let k=0;k=0){const ce=k[G];let ve=K[G];if(ve===void 0&&(G==="instanceMatrix"&&g.instanceMatrix&&(ve=g.instanceMatrix),G==="instanceColor"&&g.instanceColor&&(ve=g.instanceColor)),ce===void 0||ce.attribute!==ve||ve&&ce.data!==ve.data)return!0;B++}return s.attributesNum!==B||s.index!==z}function _(g,S,V,z){const k={},K=S.attributes;let B=0;const Q=V.getAttributes();for(const G in Q)if(Q[G].location>=0){let ce=K[G];ce===void 0&&(G==="instanceMatrix"&&g.instanceMatrix&&(ce=g.instanceMatrix),G==="instanceColor"&&g.instanceColor&&(ce=g.instanceColor));const ve={};ve.attribute=ce,ce&&ce.data&&(ve.data=ce.data),k[G]=ve,B++}s.attributes=k,s.attributesNum=B,s.index=z}function M(){const g=s.newAttributes;for(let S=0,V=g.length;S=0){let le=k[Q];if(le===void 0&&(Q==="instanceMatrix"&&g.instanceMatrix&&(le=g.instanceMatrix),Q==="instanceColor"&&g.instanceColor&&(le=g.instanceColor)),le!==void 0){const ce=le.normalized,ve=le.itemSize,Ge=e.get(le);if(Ge===void 0)continue;const Ze=Ge.buffer,W=Ge.type,j=Ge.bytesPerElement,me=W===i.INT||W===i.UNSIGNED_INT||le.gpuType===ao;if(le.isInterleavedBufferAttribute){const ue=le.data,Re=ue.stride,ye=le.offset;if(ue.isInstancedInterleavedBuffer){for(let Fe=0;Fe0&&i.getShaderPrecisionFormat(i.FRAGMENT_SHADER,i.HIGH_FLOAT).precision>0)return"highp";A="mediump"}return A==="mediump"&&i.getShaderPrecisionFormat(i.VERTEX_SHADER,i.MEDIUM_FLOAT).precision>0&&i.getShaderPrecisionFormat(i.FRAGMENT_SHADER,i.MEDIUM_FLOAT).precision>0?"mediump":"lowp"}let c=t.precision!==void 0?t.precision:"highp";const u=l(c);u!==c&&(console.warn("THREE.WebGLRenderer:",c,"not supported, using",u,"instead."),c=u);const d=t.logarithmicDepthBuffer===!0,p=t.reverseDepthBuffer===!0&&e.has("EXT_clip_control");if(p===!0){const A=e.get("EXT_clip_control");A.clipControlEXT(A.LOWER_LEFT_EXT,A.ZERO_TO_ONE_EXT)}const m=i.getParameter(i.MAX_TEXTURE_IMAGE_UNITS),_=i.getParameter(i.MAX_VERTEX_TEXTURE_IMAGE_UNITS),M=i.getParameter(i.MAX_TEXTURE_SIZE),f=i.getParameter(i.MAX_CUBE_MAP_TEXTURE_SIZE),h=i.getParameter(i.MAX_VERTEX_ATTRIBS),T=i.getParameter(i.MAX_VERTEX_UNIFORM_VECTORS),y=i.getParameter(i.MAX_VARYING_VECTORS),b=i.getParameter(i.MAX_FRAGMENT_UNIFORM_VECTORS),O=_>0,C=i.getParameter(i.MAX_SAMPLES);return{isWebGL2:!0,getMaxAnisotropy:s,getMaxPrecision:l,textureFormatReadable:a,textureTypeReadable:o,precision:c,logarithmicDepthBuffer:d,reverseDepthBuffer:p,maxTextures:m,maxVertexTextures:_,maxTextureSize:M,maxCubemapSize:f,maxAttributes:h,maxVertexUniforms:T,maxVaryings:y,maxFragmentUniforms:b,vertexTextures:O,maxSamples:C}}function Cp(i){const e=this;let t=null,n=0,r=!1,s=!1;const a=new Zn,o=new De,l={value:null,needsUpdate:!1};this.uniform=l,this.numPlanes=0,this.numIntersection=0,this.init=function(d,p){const m=d.length!==0||p||n!==0||r;return r=p,n=d.length,m},this.beginShadows=function(){s=!0,u(null)},this.endShadows=function(){s=!1},this.setGlobalState=function(d,p){t=u(d,p,0)},this.setState=function(d,p,m){const _=d.clippingPlanes,M=d.clipIntersection,f=d.clipShadows,h=i.get(d);if(!r||_===null||_.length===0||s&&!f)s?u(null):c();else{const T=s?0:n,y=T*4;let b=h.clippingState||null;l.value=b,b=u(_,p,y,m);for(let O=0;O!==y;++O)b[O]=t[O];h.clippingState=b,this.numIntersection=M?this.numPlanes:0,this.numPlanes+=T}};function c(){l.value!==t&&(l.value=t,l.needsUpdate=n>0),e.numPlanes=n,e.numIntersection=0}function u(d,p,m,_){const M=d!==null?d.length:0;let f=null;if(M!==0){if(f=l.value,_!==!0||f===null){const h=m+M*4,T=p.matrixWorldInverse;o.getNormalMatrix(T),(f===null||f.length0){const c=new Hd(l.height);return c.fromEquirectangularTexture(i,a),e.set(a,c),a.addEventListener("dispose",r),t(c.texture,a.mapping)}else return null}}return a}function r(a){const o=a.target;o.removeEventListener("dispose",r);const l=e.get(o);l!==void 0&&(e.delete(o),l.dispose())}function s(){e=new WeakMap}return{get:n,dispose:s}}class bc extends Mc{constructor(e=-1,t=1,n=1,r=-1,s=.1,a=2e3){super(),this.isOrthographicCamera=!0,this.type="OrthographicCamera",this.zoom=1,this.view=null,this.left=e,this.right=t,this.top=n,this.bottom=r,this.near=s,this.far=a,this.updateProjectionMatrix()}copy(e,t){return super.copy(e,t),this.left=e.left,this.right=e.right,this.top=e.top,this.bottom=e.bottom,this.near=e.near,this.far=e.far,this.zoom=e.zoom,this.view=e.view===null?null:Object.assign({},e.view),this}setViewOffset(e,t,n,r,s,a){this.view===null&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=e,this.view.fullHeight=t,this.view.offsetX=n,this.view.offsetY=r,this.view.width=s,this.view.height=a,this.updateProjectionMatrix()}clearViewOffset(){this.view!==null&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const e=(this.right-this.left)/(2*this.zoom),t=(this.top-this.bottom)/(2*this.zoom),n=(this.right+this.left)/2,r=(this.top+this.bottom)/2;let s=n-e,a=n+e,o=r+t,l=r-t;if(this.view!==null&&this.view.enabled){const c=(this.right-this.left)/this.view.fullWidth/this.zoom,u=(this.top-this.bottom)/this.view.fullHeight/this.zoom;s+=c*this.view.offsetX,a=s+c*this.view.width,o-=u*this.view.offsetY,l=o-u*this.view.height}this.projectionMatrix.makeOrthographic(s,a,o,l,this.near,this.far,this.coordinateSystem),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(e){const t=super.toJSON(e);return t.object.zoom=this.zoom,t.object.left=this.left,t.object.right=this.right,t.object.top=this.top,t.object.bottom=this.bottom,t.object.near=this.near,t.object.far=this.far,this.view!==null&&(t.object.view=Object.assign({},this.view)),t}}const wi=4,ml=[.125,.215,.35,.446,.526,.582],$n=20,ta=new bc,gl=new Ye;let na=null,ia=0,ra=0,sa=!1;const Kn=(1+Math.sqrt(5))/2,Ti=1/Kn,vl=[new N(-Kn,Ti,0),new N(Kn,Ti,0),new N(-Ti,0,Kn),new N(Ti,0,Kn),new N(0,Kn,-Ti),new N(0,Kn,Ti),new N(-1,1,-1),new N(1,1,-1),new N(-1,1,1),new N(1,1,1)];class _l{constructor(e){this._renderer=e,this._pingPongRenderTarget=null,this._lodMax=0,this._cubeSize=0,this._lodPlanes=[],this._sizeLods=[],this._sigmas=[],this._blurMaterial=null,this._cubemapMaterial=null,this._equirectMaterial=null,this._compileMaterial(this._blurMaterial)}fromScene(e,t=0,n=.1,r=100){na=this._renderer.getRenderTarget(),ia=this._renderer.getActiveCubeFace(),ra=this._renderer.getActiveMipmapLevel(),sa=this._renderer.xr.enabled,this._renderer.xr.enabled=!1,this._setSize(256);const s=this._allocateTargets();return s.depthBuffer=!0,this._sceneToCubeUV(e,n,r,s),t>0&&this._blur(s,0,0,t),this._applyPMREM(s),this._cleanup(s),s}fromEquirectangular(e,t=null){return this._fromTexture(e,t)}fromCubemap(e,t=null){return this._fromTexture(e,t)}compileCubemapShader(){this._cubemapMaterial===null&&(this._cubemapMaterial=Ml(),this._compileMaterial(this._cubemapMaterial))}compileEquirectangularShader(){this._equirectMaterial===null&&(this._equirectMaterial=Sl(),this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),this._cubemapMaterial!==null&&this._cubemapMaterial.dispose(),this._equirectMaterial!==null&&this._equirectMaterial.dispose()}_setSize(e){this._lodMax=Math.floor(Math.log2(e)),this._cubeSize=Math.pow(2,this._lodMax)}_dispose(){this._blurMaterial!==null&&this._blurMaterial.dispose(),this._pingPongRenderTarget!==null&&this._pingPongRenderTarget.dispose();for(let e=0;e2?y:0,y,y),u.setRenderTarget(r),M&&u.render(_,o),u.render(e,o)}_.geometry.dispose(),_.material.dispose(),u.toneMapping=p,u.autoClear=d,e.background=f}_textureToCubeUV(e,t){const n=this._renderer,r=e.mapping===Ui||e.mapping===Ii;r?(this._cubemapMaterial===null&&(this._cubemapMaterial=Ml()),this._cubemapMaterial.uniforms.flipEnvMap.value=e.isRenderTargetTexture===!1?-1:1):this._equirectMaterial===null&&(this._equirectMaterial=Sl());const s=r?this._cubemapMaterial:this._equirectMaterial,a=new lt(this._lodPlanes[0],s),o=s.uniforms;o.envMap.value=e;const l=this._cubeSize;Xr(t,0,0,3*l,2*l),n.setRenderTarget(t),n.render(a,ta)}_applyPMREM(e){const t=this._renderer,n=t.autoClear;t.autoClear=!1;const r=this._lodPlanes.length;for(let s=1;s$n&&console.warn(`sigmaRadians, ${s}, is too large and will clip, as it requested ${f} samples when the maximum is set to ${$n}`);const h=[];let T=0;for(let A=0;A<$n;++A){const F=A/M,te=Math.exp(-F*F/2);h.push(te),A===0?T+=te:Ay-wi?r-y+wi:0),C=4*(this._cubeSize-b);Xr(t,O,C,3*b,2*b),l.setRenderTarget(t),l.render(d,ta)}}function Dp(i){const e=[],t=[],n=[];let r=i;const s=i-wi+1+ml.length;for(let a=0;ai-wi?l=ml[a-i+wi-1]:a===0&&(l=0),n.push(l);const c=1/(o-2),u=-c,d=1+c,p=[u,u,d,u,d,d,u,u,d,d,u,d],m=6,_=6,M=3,f=2,h=1,T=new Float32Array(M*_*m),y=new Float32Array(f*_*m),b=new Float32Array(h*_*m);for(let C=0;C2?0:-1,te=[A,F,0,A+2/3,F,0,A+2/3,F+1,0,A,F,0,A+2/3,F+1,0,A,F+1,0];T.set(te,M*_*C),y.set(p,f*_*C);const g=[C,C,C,C,C,C];b.set(g,h*_*C)}const O=new Hn;O.setAttribute("position",new en(T,M)),O.setAttribute("uv",new en(y,f)),O.setAttribute("faceIndex",new en(b,h)),e.push(O),r>wi&&r--}return{lodPlanes:e,sizeLods:t,sigmas:n}}function xl(i,e,t){const n=new nn(i,e,t);return n.texture.mapping=_s,n.texture.name="PMREM.cubeUv",n.scissorTest=!0,n}function Xr(i,e,t,n,r){i.viewport.set(e,t,n,r),i.scissor.set(e,t,n,r)}function Lp(i,e,t){const n=new Float32Array($n),r=new N(0,1,0);return new Gt({name:"SphericalGaussianBlur",defines:{n:$n,CUBEUV_TEXEL_WIDTH:1/e,CUBEUV_TEXEL_HEIGHT:1/t,CUBEUV_MAX_MIP:`${i}.0`},uniforms:{envMap:{value:null},samples:{value:1},weights:{value:n},latitudinal:{value:!1},dTheta:{value:0},mipInt:{value:0},poleAxis:{value:r}},vertexShader:go(),fragmentShader:` - - precision mediump float; - precision mediump int; - - varying vec3 vOutputDirection; - - uniform sampler2D envMap; - uniform int samples; - uniform float weights[ n ]; - uniform bool latitudinal; - uniform float dTheta; - uniform float mipInt; - uniform vec3 poleAxis; - - #define ENVMAP_TYPE_CUBE_UV - #include - - vec3 getSample( float theta, vec3 axis ) { - - float cosTheta = cos( theta ); - // Rodrigues' axis-angle rotation - vec3 sampleDirection = vOutputDirection * cosTheta - + cross( axis, vOutputDirection ) * sin( theta ) - + axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta ); - - return bilinearCubeUV( envMap, sampleDirection, mipInt ); - - } - - void main() { - - vec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection ); - - if ( all( equal( axis, vec3( 0.0 ) ) ) ) { - - axis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x ); - - } - - axis = normalize( axis ); - - gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 ); - gl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis ); - - for ( int i = 1; i < n; i++ ) { - - if ( i >= samples ) { - - break; - - } - - float theta = dTheta * float( i ); - gl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis ); - gl_FragColor.rgb += weights[ i ] * getSample( theta, axis ); - - } - - } - `,blending:Ln,depthTest:!1,depthWrite:!1})}function Sl(){return new Gt({name:"EquirectangularToCubeUV",uniforms:{envMap:{value:null}},vertexShader:go(),fragmentShader:` - - precision mediump float; - precision mediump int; - - varying vec3 vOutputDirection; - - uniform sampler2D envMap; - - #include - - void main() { - - vec3 outputDirection = normalize( vOutputDirection ); - vec2 uv = equirectUv( outputDirection ); - - gl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 ); - - } - `,blending:Ln,depthTest:!1,depthWrite:!1})}function Ml(){return new Gt({name:"CubemapToCubeUV",uniforms:{envMap:{value:null},flipEnvMap:{value:-1}},vertexShader:go(),fragmentShader:` - - precision mediump float; - precision mediump int; - - uniform float flipEnvMap; - - varying vec3 vOutputDirection; - - uniform samplerCube envMap; - - void main() { - - gl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) ); - - } - `,blending:Ln,depthTest:!1,depthWrite:!1})}function go(){return` - - precision mediump float; - precision mediump int; - - attribute float faceIndex; - - varying vec3 vOutputDirection; - - // RH coordinate system; PMREM face-indexing convention - vec3 getDirection( vec2 uv, float face ) { - - uv = 2.0 * uv - 1.0; - - vec3 direction = vec3( uv, 1.0 ); - - if ( face == 0.0 ) { - - direction = direction.zyx; // ( 1, v, u ) pos x - - } else if ( face == 1.0 ) { - - direction = direction.xzy; - direction.xz *= -1.0; // ( -u, 1, -v ) pos y - - } else if ( face == 2.0 ) { - - direction.x *= -1.0; // ( -u, v, 1 ) pos z - - } else if ( face == 3.0 ) { - - direction = direction.zyx; - direction.xz *= -1.0; // ( -1, v, -u ) neg x - - } else if ( face == 4.0 ) { - - direction = direction.xzy; - direction.xy *= -1.0; // ( -u, -1, v ) neg y - - } else if ( face == 5.0 ) { - - direction.z *= -1.0; // ( u, v, -1 ) neg z - - } - - return direction; - - } - - void main() { - - vOutputDirection = getDirection( uv, faceIndex ); - gl_Position = vec4( position, 1.0 ); - - } - `}function Up(i){let e=new WeakMap,t=null;function n(o){if(o&&o.isTexture){const l=o.mapping,c=l===Sa||l===Ma,u=l===Ui||l===Ii;if(c||u){let d=e.get(o);const p=d!==void 0?d.texture.pmremVersion:0;if(o.isRenderTargetTexture&&o.pmremVersion!==p)return t===null&&(t=new _l(i)),d=c?t.fromEquirectangular(o,d):t.fromCubemap(o,d),d.texture.pmremVersion=o.pmremVersion,e.set(o,d),d.texture;if(d!==void 0)return d.texture;{const m=o.image;return c&&m&&m.height>0||u&&m&&r(m)?(t===null&&(t=new _l(i)),d=c?t.fromEquirectangular(o):t.fromCubemap(o),d.texture.pmremVersion=o.pmremVersion,e.set(o,d),o.addEventListener("dispose",s),d.texture):null}}}return o}function r(o){let l=0;const c=6;for(let u=0;ue.maxTextureSize&&(O=Math.ceil(b/e.maxTextureSize),b=e.maxTextureSize);const C=new Float32Array(b*O*4*d),A=new mc(C,b,O,d);A.type=Mn,A.needsUpdate=!0;const F=y*4;for(let g=0;g0)return i;const r=e*t;let s=El[r];if(s===void 0&&(s=new Float32Array(r),El[r]=s),e!==0){n.toArray(s,0);for(let a=1,o=0;a!==e;++a)o+=t,i[a].toArray(s,o)}return s}function ht(i,e){if(i.length!==e.length)return!1;for(let t=0,n=i.length;t":" "} ${o}: ${t[a]}`)}return n.join(` -`)}function Um(i){const e=qe.getPrimaries(qe.workingColorSpace),t=qe.getPrimaries(i);let n;switch(e===t?n="":e===us&&t===cs?n="LinearDisplayP3ToLinearSRGB":e===cs&&t===us&&(n="LinearSRGBToLinearDisplayP3"),i){case zn:case xs:return[n,"LinearTransferOETF"];case Bt:case fo:return[n,"sRGBTransferOETF"];default:return console.warn("THREE.WebGLProgram: Unsupported color space:",i),[n,"LinearTransferOETF"]}}function Pl(i,e,t){const n=i.getShaderParameter(e,i.COMPILE_STATUS),r=i.getShaderInfoLog(e).trim();if(n&&r==="")return"";const s=/ERROR: 0:(\d+)/.exec(r);if(s){const a=parseInt(s[1]);return t.toUpperCase()+` - -`+r+` - -`+Lm(i.getShaderSource(e),a)}else return r}function Im(i,e){const t=Um(e);return`vec4 ${i}( vec4 value ) { return ${t[0]}( ${t[1]}( value ) ); }`}function Nm(i,e){let t;switch(e){case Uu:t="Linear";break;case Iu:t="Reinhard";break;case Nu:t="Cineon";break;case Fu:t="ACESFilmic";break;case Bu:t="AgX";break;case zu:t="Neutral";break;case Ou:t="Custom";break;default:console.warn("THREE.WebGLProgram: Unsupported toneMapping:",e),t="Linear"}return"vec3 "+i+"( vec3 color ) { return "+t+"ToneMapping( color ); }"}const qr=new N;function Fm(){qe.getLuminanceCoefficients(qr);const i=qr.x.toFixed(4),e=qr.y.toFixed(4),t=qr.z.toFixed(4);return["float luminance( const in vec3 rgb ) {",` const vec3 weights = vec3( ${i}, ${e}, ${t} );`," return dot( weights, rgb );","}"].join(` -`)}function Om(i){return[i.extensionClipCullDistance?"#extension GL_ANGLE_clip_cull_distance : require":"",i.extensionMultiDraw?"#extension GL_ANGLE_multi_draw : require":""].filter(Qi).join(` -`)}function Bm(i){const e=[];for(const t in i){const n=i[t];n!==!1&&e.push("#define "+t+" "+n)}return e.join(` -`)}function zm(i,e){const t={},n=i.getProgramParameter(e,i.ACTIVE_ATTRIBUTES);for(let r=0;r/gm;function ja(i){return i.replace(Hm,Vm)}const Gm=new Map;function Vm(i,e){let t=Pe[e];if(t===void 0){const n=Gm.get(e);if(n!==void 0)t=Pe[n],console.warn('THREE.WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.',e,n);else throw new Error("Can not resolve #include <"+e+">")}return ja(t)}const km=/#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g;function Ul(i){return i.replace(km,Wm)}function Wm(i,e,t,n){let r="";for(let s=parseInt(e);s0&&(f+=` -`),h=["#define SHADER_TYPE "+t.shaderType,"#define SHADER_NAME "+t.shaderName,_].filter(Qi).join(` -`),h.length>0&&(h+=` -`)):(f=[Il(t),"#define SHADER_TYPE "+t.shaderType,"#define SHADER_NAME "+t.shaderName,_,t.extensionClipCullDistance?"#define USE_CLIP_DISTANCE":"",t.batching?"#define USE_BATCHING":"",t.batchingColor?"#define USE_BATCHING_COLOR":"",t.instancing?"#define USE_INSTANCING":"",t.instancingColor?"#define USE_INSTANCING_COLOR":"",t.instancingMorph?"#define USE_INSTANCING_MORPH":"",t.useFog&&t.fog?"#define USE_FOG":"",t.useFog&&t.fogExp2?"#define FOG_EXP2":"",t.map?"#define USE_MAP":"",t.envMap?"#define USE_ENVMAP":"",t.envMap?"#define "+u:"",t.lightMap?"#define USE_LIGHTMAP":"",t.aoMap?"#define USE_AOMAP":"",t.bumpMap?"#define USE_BUMPMAP":"",t.normalMap?"#define USE_NORMALMAP":"",t.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",t.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",t.displacementMap?"#define USE_DISPLACEMENTMAP":"",t.emissiveMap?"#define USE_EMISSIVEMAP":"",t.anisotropy?"#define USE_ANISOTROPY":"",t.anisotropyMap?"#define USE_ANISOTROPYMAP":"",t.clearcoatMap?"#define USE_CLEARCOATMAP":"",t.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",t.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",t.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",t.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",t.specularMap?"#define USE_SPECULARMAP":"",t.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",t.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",t.roughnessMap?"#define USE_ROUGHNESSMAP":"",t.metalnessMap?"#define USE_METALNESSMAP":"",t.alphaMap?"#define USE_ALPHAMAP":"",t.alphaHash?"#define USE_ALPHAHASH":"",t.transmission?"#define USE_TRANSMISSION":"",t.transmissionMap?"#define USE_TRANSMISSIONMAP":"",t.thicknessMap?"#define USE_THICKNESSMAP":"",t.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",t.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",t.mapUv?"#define MAP_UV "+t.mapUv:"",t.alphaMapUv?"#define ALPHAMAP_UV "+t.alphaMapUv:"",t.lightMapUv?"#define LIGHTMAP_UV "+t.lightMapUv:"",t.aoMapUv?"#define AOMAP_UV "+t.aoMapUv:"",t.emissiveMapUv?"#define EMISSIVEMAP_UV "+t.emissiveMapUv:"",t.bumpMapUv?"#define BUMPMAP_UV "+t.bumpMapUv:"",t.normalMapUv?"#define NORMALMAP_UV "+t.normalMapUv:"",t.displacementMapUv?"#define DISPLACEMENTMAP_UV "+t.displacementMapUv:"",t.metalnessMapUv?"#define METALNESSMAP_UV "+t.metalnessMapUv:"",t.roughnessMapUv?"#define ROUGHNESSMAP_UV "+t.roughnessMapUv:"",t.anisotropyMapUv?"#define ANISOTROPYMAP_UV "+t.anisotropyMapUv:"",t.clearcoatMapUv?"#define CLEARCOATMAP_UV "+t.clearcoatMapUv:"",t.clearcoatNormalMapUv?"#define CLEARCOAT_NORMALMAP_UV "+t.clearcoatNormalMapUv:"",t.clearcoatRoughnessMapUv?"#define CLEARCOAT_ROUGHNESSMAP_UV "+t.clearcoatRoughnessMapUv:"",t.iridescenceMapUv?"#define IRIDESCENCEMAP_UV "+t.iridescenceMapUv:"",t.iridescenceThicknessMapUv?"#define IRIDESCENCE_THICKNESSMAP_UV "+t.iridescenceThicknessMapUv:"",t.sheenColorMapUv?"#define SHEEN_COLORMAP_UV "+t.sheenColorMapUv:"",t.sheenRoughnessMapUv?"#define SHEEN_ROUGHNESSMAP_UV "+t.sheenRoughnessMapUv:"",t.specularMapUv?"#define SPECULARMAP_UV "+t.specularMapUv:"",t.specularColorMapUv?"#define SPECULAR_COLORMAP_UV "+t.specularColorMapUv:"",t.specularIntensityMapUv?"#define SPECULAR_INTENSITYMAP_UV "+t.specularIntensityMapUv:"",t.transmissionMapUv?"#define TRANSMISSIONMAP_UV "+t.transmissionMapUv:"",t.thicknessMapUv?"#define THICKNESSMAP_UV "+t.thicknessMapUv:"",t.vertexTangents&&t.flatShading===!1?"#define USE_TANGENT":"",t.vertexColors?"#define USE_COLOR":"",t.vertexAlphas?"#define USE_COLOR_ALPHA":"",t.vertexUv1s?"#define USE_UV1":"",t.vertexUv2s?"#define USE_UV2":"",t.vertexUv3s?"#define USE_UV3":"",t.pointsUvs?"#define USE_POINTS_UV":"",t.flatShading?"#define FLAT_SHADED":"",t.skinning?"#define USE_SKINNING":"",t.morphTargets?"#define USE_MORPHTARGETS":"",t.morphNormals&&t.flatShading===!1?"#define USE_MORPHNORMALS":"",t.morphColors?"#define USE_MORPHCOLORS":"",t.morphTargetsCount>0?"#define MORPHTARGETS_TEXTURE_STRIDE "+t.morphTextureStride:"",t.morphTargetsCount>0?"#define MORPHTARGETS_COUNT "+t.morphTargetsCount:"",t.doubleSided?"#define DOUBLE_SIDED":"",t.flipSided?"#define FLIP_SIDED":"",t.shadowMapEnabled?"#define USE_SHADOWMAP":"",t.shadowMapEnabled?"#define "+l:"",t.sizeAttenuation?"#define USE_SIZEATTENUATION":"",t.numLightProbes>0?"#define USE_LIGHT_PROBES":"",t.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",t.reverseDepthBuffer?"#define USE_REVERSEDEPTHBUF":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;","#ifdef USE_INSTANCING"," attribute mat4 instanceMatrix;","#endif","#ifdef USE_INSTANCING_COLOR"," attribute vec3 instanceColor;","#endif","#ifdef USE_INSTANCING_MORPH"," uniform sampler2D morphTexture;","#endif","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_UV1"," attribute vec2 uv1;","#endif","#ifdef USE_UV2"," attribute vec2 uv2;","#endif","#ifdef USE_UV3"," attribute vec2 uv3;","#endif","#ifdef USE_TANGENT"," attribute vec4 tangent;","#endif","#if defined( USE_COLOR_ALPHA )"," attribute vec4 color;","#elif defined( USE_COLOR )"," attribute vec3 color;","#endif","#ifdef USE_SKINNING"," attribute vec4 skinIndex;"," attribute vec4 skinWeight;","#endif",` -`].filter(Qi).join(` -`),h=[Il(t),"#define SHADER_TYPE "+t.shaderType,"#define SHADER_NAME "+t.shaderName,_,t.useFog&&t.fog?"#define USE_FOG":"",t.useFog&&t.fogExp2?"#define FOG_EXP2":"",t.alphaToCoverage?"#define ALPHA_TO_COVERAGE":"",t.map?"#define USE_MAP":"",t.matcap?"#define USE_MATCAP":"",t.envMap?"#define USE_ENVMAP":"",t.envMap?"#define "+c:"",t.envMap?"#define "+u:"",t.envMap?"#define "+d:"",p?"#define CUBEUV_TEXEL_WIDTH "+p.texelWidth:"",p?"#define CUBEUV_TEXEL_HEIGHT "+p.texelHeight:"",p?"#define CUBEUV_MAX_MIP "+p.maxMip+".0":"",t.lightMap?"#define USE_LIGHTMAP":"",t.aoMap?"#define USE_AOMAP":"",t.bumpMap?"#define USE_BUMPMAP":"",t.normalMap?"#define USE_NORMALMAP":"",t.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",t.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",t.emissiveMap?"#define USE_EMISSIVEMAP":"",t.anisotropy?"#define USE_ANISOTROPY":"",t.anisotropyMap?"#define USE_ANISOTROPYMAP":"",t.clearcoat?"#define USE_CLEARCOAT":"",t.clearcoatMap?"#define USE_CLEARCOATMAP":"",t.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",t.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",t.dispersion?"#define USE_DISPERSION":"",t.iridescence?"#define USE_IRIDESCENCE":"",t.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",t.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",t.specularMap?"#define USE_SPECULARMAP":"",t.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",t.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",t.roughnessMap?"#define USE_ROUGHNESSMAP":"",t.metalnessMap?"#define USE_METALNESSMAP":"",t.alphaMap?"#define USE_ALPHAMAP":"",t.alphaTest?"#define USE_ALPHATEST":"",t.alphaHash?"#define USE_ALPHAHASH":"",t.sheen?"#define USE_SHEEN":"",t.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",t.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",t.transmission?"#define USE_TRANSMISSION":"",t.transmissionMap?"#define USE_TRANSMISSIONMAP":"",t.thicknessMap?"#define USE_THICKNESSMAP":"",t.vertexTangents&&t.flatShading===!1?"#define USE_TANGENT":"",t.vertexColors||t.instancingColor||t.batchingColor?"#define USE_COLOR":"",t.vertexAlphas?"#define USE_COLOR_ALPHA":"",t.vertexUv1s?"#define USE_UV1":"",t.vertexUv2s?"#define USE_UV2":"",t.vertexUv3s?"#define USE_UV3":"",t.pointsUvs?"#define USE_POINTS_UV":"",t.gradientMap?"#define USE_GRADIENTMAP":"",t.flatShading?"#define FLAT_SHADED":"",t.doubleSided?"#define DOUBLE_SIDED":"",t.flipSided?"#define FLIP_SIDED":"",t.shadowMapEnabled?"#define USE_SHADOWMAP":"",t.shadowMapEnabled?"#define "+l:"",t.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",t.numLightProbes>0?"#define USE_LIGHT_PROBES":"",t.decodeVideoTexture?"#define DECODE_VIDEO_TEXTURE":"",t.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",t.reverseDepthBuffer?"#define USE_REVERSEDEPTHBUF":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;",t.toneMapping!==Un?"#define TONE_MAPPING":"",t.toneMapping!==Un?Pe.tonemapping_pars_fragment:"",t.toneMapping!==Un?Nm("toneMapping",t.toneMapping):"",t.dithering?"#define DITHERING":"",t.opaque?"#define OPAQUE":"",Pe.colorspace_pars_fragment,Im("linearToOutputTexel",t.outputColorSpace),Fm(),t.useDepthPacking?"#define DEPTH_PACKING "+t.depthPacking:"",` -`].filter(Qi).join(` -`)),a=ja(a),a=Dl(a,t),a=Ll(a,t),o=ja(o),o=Dl(o,t),o=Ll(o,t),a=Ul(a),o=Ul(o),t.isRawShaderMaterial!==!0&&(T=`#version 300 es -`,f=[m,"#define attribute in","#define varying out","#define texture2D texture"].join(` -`)+` -`+f,h=["#define varying in",t.glslVersion===jo?"":"layout(location = 0) out highp vec4 pc_fragColor;",t.glslVersion===jo?"":"#define gl_FragColor pc_fragColor","#define gl_FragDepthEXT gl_FragDepth","#define texture2D texture","#define textureCube texture","#define texture2DProj textureProj","#define texture2DLodEXT textureLod","#define texture2DProjLodEXT textureProjLod","#define textureCubeLodEXT textureLod","#define texture2DGradEXT textureGrad","#define texture2DProjGradEXT textureProjGrad","#define textureCubeGradEXT textureGrad"].join(` -`)+` -`+h);const y=T+f+a,b=T+h+o,O=Cl(r,r.VERTEX_SHADER,y),C=Cl(r,r.FRAGMENT_SHADER,b);r.attachShader(M,O),r.attachShader(M,C),t.index0AttributeName!==void 0?r.bindAttribLocation(M,0,t.index0AttributeName):t.morphTargets===!0&&r.bindAttribLocation(M,0,"position"),r.linkProgram(M);function A(S){if(i.debug.checkShaderErrors){const V=r.getProgramInfoLog(M).trim(),z=r.getShaderInfoLog(O).trim(),k=r.getShaderInfoLog(C).trim();let K=!0,B=!0;if(r.getProgramParameter(M,r.LINK_STATUS)===!1)if(K=!1,typeof i.debug.onShaderError=="function")i.debug.onShaderError(r,M,O,C);else{const Q=Pl(r,O,"vertex"),G=Pl(r,C,"fragment");console.error("THREE.WebGLProgram: Shader Error "+r.getError()+" - VALIDATE_STATUS "+r.getProgramParameter(M,r.VALIDATE_STATUS)+` - -Material Name: `+S.name+` -Material Type: `+S.type+` - -Program Info Log: `+V+` -`+Q+` -`+G)}else V!==""?console.warn("THREE.WebGLProgram: Program Info Log:",V):(z===""||k==="")&&(B=!1);B&&(S.diagnostics={runnable:K,programLog:V,vertexShader:{log:z,prefix:f},fragmentShader:{log:k,prefix:h}})}r.deleteShader(O),r.deleteShader(C),F=new es(r,M),te=zm(r,M)}let F;this.getUniforms=function(){return F===void 0&&A(this),F};let te;this.getAttributes=function(){return te===void 0&&A(this),te};let g=t.rendererExtensionParallelShaderCompile===!1;return this.isReady=function(){return g===!1&&(g=r.getProgramParameter(M,Pm)),g},this.destroy=function(){n.releaseStatesOfProgram(this),r.deleteProgram(M),this.program=void 0},this.type=t.shaderType,this.name=t.shaderName,this.id=Dm++,this.cacheKey=e,this.usedTimes=1,this.program=M,this.vertexShader=O,this.fragmentShader=C,this}let $m=0;class Jm{constructor(){this.shaderCache=new Map,this.materialCache=new Map}update(e){const t=e.vertexShader,n=e.fragmentShader,r=this._getShaderStage(t),s=this._getShaderStage(n),a=this._getShaderCacheForMaterial(e);return a.has(r)===!1&&(a.add(r),r.usedTimes++),a.has(s)===!1&&(a.add(s),s.usedTimes++),this}remove(e){const t=this.materialCache.get(e);for(const n of t)n.usedTimes--,n.usedTimes===0&&this.shaderCache.delete(n.code);return this.materialCache.delete(e),this}getVertexShaderID(e){return this._getShaderStage(e.vertexShader).id}getFragmentShaderID(e){return this._getShaderStage(e.fragmentShader).id}dispose(){this.shaderCache.clear(),this.materialCache.clear()}_getShaderCacheForMaterial(e){const t=this.materialCache;let n=t.get(e);return n===void 0&&(n=new Set,t.set(e,n)),n}_getShaderStage(e){const t=this.shaderCache;let n=t.get(e);return n===void 0&&(n=new Qm(e),t.set(e,n)),n}}class Qm{constructor(e){this.id=$m++,this.code=e,this.usedTimes=0}}function eg(i,e,t,n,r,s,a){const o=new gc,l=new Jm,c=new Set,u=[],d=r.logarithmicDepthBuffer,p=r.reverseDepthBuffer,m=r.vertexTextures;let _=r.precision;const M={MeshDepthMaterial:"depth",MeshDistanceMaterial:"distanceRGBA",MeshNormalMaterial:"normal",MeshBasicMaterial:"basic",MeshLambertMaterial:"lambert",MeshPhongMaterial:"phong",MeshToonMaterial:"toon",MeshStandardMaterial:"physical",MeshPhysicalMaterial:"physical",MeshMatcapMaterial:"matcap",LineBasicMaterial:"basic",LineDashedMaterial:"dashed",PointsMaterial:"points",ShadowMaterial:"shadow",SpriteMaterial:"sprite"};function f(g){return c.add(g),g===0?"uv":`uv${g}`}function h(g,S,V,z,k){const K=z.fog,B=k.geometry,Q=g.isMeshStandardMaterial?z.environment:null,G=(g.isMeshStandardMaterial?t:e).get(g.envMap||Q),le=G&&G.mapping===_s?G.image.height:null,ce=M[g.type];g.precision!==null&&(_=r.getMaxPrecision(g.precision),_!==g.precision&&console.warn("THREE.WebGLProgram.getParameters:",g.precision,"not supported, using",_,"instead."));const ve=B.morphAttributes.position||B.morphAttributes.normal||B.morphAttributes.color,Ge=ve!==void 0?ve.length:0;let Ze=0;B.morphAttributes.position!==void 0&&(Ze=1),B.morphAttributes.normal!==void 0&&(Ze=2),B.morphAttributes.color!==void 0&&(Ze=3);let W,j,me,ue;if(ce){const Rt=an[ce];W=Rt.vertexShader,j=Rt.fragmentShader}else W=g.vertexShader,j=g.fragmentShader,l.update(g),me=l.getVertexShaderID(g),ue=l.getFragmentShaderID(g);const Re=i.getRenderTarget(),ye=k.isInstancedMesh===!0,Fe=k.isBatchedMesh===!0,je=!!g.map,Oe=!!g.matcap,w=!!G,Ut=!!g.aoMap,Ue=!!g.lightMap,ze=!!g.bumpMap,Te=!!g.normalMap,Je=!!g.displacementMap,we=!!g.emissiveMap,E=!!g.metalnessMap,v=!!g.roughnessMap,L=g.anisotropy>0,q=g.clearcoat>0,Z=g.dispersion>0,X=g.iridescence>0,_e=g.sheen>0,ie=g.transmission>0,de=L&&!!g.anisotropyMap,He=q&&!!g.clearcoatMap,$=q&&!!g.clearcoatNormalMap,he=q&&!!g.clearcoatRoughnessMap,be=X&&!!g.iridescenceMap,Ae=X&&!!g.iridescenceThicknessMap,fe=_e&&!!g.sheenColorMap,Ie=_e&&!!g.sheenRoughnessMap,Ce=!!g.specularMap,$e=!!g.specularColorMap,R=!!g.specularIntensityMap,ae=ie&&!!g.transmissionMap,H=ie&&!!g.thicknessMap,Y=!!g.gradientMap,re=!!g.alphaMap,oe=g.alphaTest>0,Be=!!g.alphaHash,st=!!g.extensions;let wt=Un;g.toneMapped&&(Re===null||Re.isXRRenderTarget===!0)&&(wt=i.toneMapping);const Ve={shaderID:ce,shaderType:g.type,shaderName:g.name,vertexShader:W,fragmentShader:j,defines:g.defines,customVertexShaderID:me,customFragmentShaderID:ue,isRawShaderMaterial:g.isRawShaderMaterial===!0,glslVersion:g.glslVersion,precision:_,batching:Fe,batchingColor:Fe&&k._colorsTexture!==null,instancing:ye,instancingColor:ye&&k.instanceColor!==null,instancingMorph:ye&&k.morphTexture!==null,supportsVertexTextures:m,outputColorSpace:Re===null?i.outputColorSpace:Re.isXRRenderTarget===!0?Re.texture.colorSpace:zn,alphaToCoverage:!!g.alphaToCoverage,map:je,matcap:Oe,envMap:w,envMapMode:w&&G.mapping,envMapCubeUVHeight:le,aoMap:Ut,lightMap:Ue,bumpMap:ze,normalMap:Te,displacementMap:m&&Je,emissiveMap:we,normalMapObjectSpace:Te&&g.normalMapType===Wu,normalMapTangentSpace:Te&&g.normalMapType===ku,metalnessMap:E,roughnessMap:v,anisotropy:L,anisotropyMap:de,clearcoat:q,clearcoatMap:He,clearcoatNormalMap:$,clearcoatRoughnessMap:he,dispersion:Z,iridescence:X,iridescenceMap:be,iridescenceThicknessMap:Ae,sheen:_e,sheenColorMap:fe,sheenRoughnessMap:Ie,specularMap:Ce,specularColorMap:$e,specularIntensityMap:R,transmission:ie,transmissionMap:ae,thicknessMap:H,gradientMap:Y,opaque:g.transparent===!1&&g.blending===Ci&&g.alphaToCoverage===!1,alphaMap:re,alphaTest:oe,alphaHash:Be,combine:g.combine,mapUv:je&&f(g.map.channel),aoMapUv:Ut&&f(g.aoMap.channel),lightMapUv:Ue&&f(g.lightMap.channel),bumpMapUv:ze&&f(g.bumpMap.channel),normalMapUv:Te&&f(g.normalMap.channel),displacementMapUv:Je&&f(g.displacementMap.channel),emissiveMapUv:we&&f(g.emissiveMap.channel),metalnessMapUv:E&&f(g.metalnessMap.channel),roughnessMapUv:v&&f(g.roughnessMap.channel),anisotropyMapUv:de&&f(g.anisotropyMap.channel),clearcoatMapUv:He&&f(g.clearcoatMap.channel),clearcoatNormalMapUv:$&&f(g.clearcoatNormalMap.channel),clearcoatRoughnessMapUv:he&&f(g.clearcoatRoughnessMap.channel),iridescenceMapUv:be&&f(g.iridescenceMap.channel),iridescenceThicknessMapUv:Ae&&f(g.iridescenceThicknessMap.channel),sheenColorMapUv:fe&&f(g.sheenColorMap.channel),sheenRoughnessMapUv:Ie&&f(g.sheenRoughnessMap.channel),specularMapUv:Ce&&f(g.specularMap.channel),specularColorMapUv:$e&&f(g.specularColorMap.channel),specularIntensityMapUv:R&&f(g.specularIntensityMap.channel),transmissionMapUv:ae&&f(g.transmissionMap.channel),thicknessMapUv:H&&f(g.thicknessMap.channel),alphaMapUv:re&&f(g.alphaMap.channel),vertexTangents:!!B.attributes.tangent&&(Te||L),vertexColors:g.vertexColors,vertexAlphas:g.vertexColors===!0&&!!B.attributes.color&&B.attributes.color.itemSize===4,pointsUvs:k.isPoints===!0&&!!B.attributes.uv&&(je||re),fog:!!K,useFog:g.fog===!0,fogExp2:!!K&&K.isFogExp2,flatShading:g.flatShading===!0,sizeAttenuation:g.sizeAttenuation===!0,logarithmicDepthBuffer:d,reverseDepthBuffer:p,skinning:k.isSkinnedMesh===!0,morphTargets:B.morphAttributes.position!==void 0,morphNormals:B.morphAttributes.normal!==void 0,morphColors:B.morphAttributes.color!==void 0,morphTargetsCount:Ge,morphTextureStride:Ze,numDirLights:S.directional.length,numPointLights:S.point.length,numSpotLights:S.spot.length,numSpotLightMaps:S.spotLightMap.length,numRectAreaLights:S.rectArea.length,numHemiLights:S.hemi.length,numDirLightShadows:S.directionalShadowMap.length,numPointLightShadows:S.pointShadowMap.length,numSpotLightShadows:S.spotShadowMap.length,numSpotLightShadowsWithMaps:S.numSpotLightShadowsWithMaps,numLightProbes:S.numLightProbes,numClippingPlanes:a.numPlanes,numClipIntersection:a.numIntersection,dithering:g.dithering,shadowMapEnabled:i.shadowMap.enabled&&V.length>0,shadowMapType:i.shadowMap.type,toneMapping:wt,decodeVideoTexture:je&&g.map.isVideoTexture===!0&&qe.getTransfer(g.map.colorSpace)===et,premultipliedAlpha:g.premultipliedAlpha,doubleSided:g.side===on,flipSided:g.side===Lt,useDepthPacking:g.depthPacking>=0,depthPacking:g.depthPacking||0,index0AttributeName:g.index0AttributeName,extensionClipCullDistance:st&&g.extensions.clipCullDistance===!0&&n.has("WEBGL_clip_cull_distance"),extensionMultiDraw:(st&&g.extensions.multiDraw===!0||Fe)&&n.has("WEBGL_multi_draw"),rendererExtensionParallelShaderCompile:n.has("KHR_parallel_shader_compile"),customProgramCacheKey:g.customProgramCacheKey()};return Ve.vertexUv1s=c.has(1),Ve.vertexUv2s=c.has(2),Ve.vertexUv3s=c.has(3),c.clear(),Ve}function T(g){const S=[];if(g.shaderID?S.push(g.shaderID):(S.push(g.customVertexShaderID),S.push(g.customFragmentShaderID)),g.defines!==void 0)for(const V in g.defines)S.push(V),S.push(g.defines[V]);return g.isRawShaderMaterial===!1&&(y(S,g),b(S,g),S.push(i.outputColorSpace)),S.push(g.customProgramCacheKey),S.join()}function y(g,S){g.push(S.precision),g.push(S.outputColorSpace),g.push(S.envMapMode),g.push(S.envMapCubeUVHeight),g.push(S.mapUv),g.push(S.alphaMapUv),g.push(S.lightMapUv),g.push(S.aoMapUv),g.push(S.bumpMapUv),g.push(S.normalMapUv),g.push(S.displacementMapUv),g.push(S.emissiveMapUv),g.push(S.metalnessMapUv),g.push(S.roughnessMapUv),g.push(S.anisotropyMapUv),g.push(S.clearcoatMapUv),g.push(S.clearcoatNormalMapUv),g.push(S.clearcoatRoughnessMapUv),g.push(S.iridescenceMapUv),g.push(S.iridescenceThicknessMapUv),g.push(S.sheenColorMapUv),g.push(S.sheenRoughnessMapUv),g.push(S.specularMapUv),g.push(S.specularColorMapUv),g.push(S.specularIntensityMapUv),g.push(S.transmissionMapUv),g.push(S.thicknessMapUv),g.push(S.combine),g.push(S.fogExp2),g.push(S.sizeAttenuation),g.push(S.morphTargetsCount),g.push(S.morphAttributeCount),g.push(S.numDirLights),g.push(S.numPointLights),g.push(S.numSpotLights),g.push(S.numSpotLightMaps),g.push(S.numHemiLights),g.push(S.numRectAreaLights),g.push(S.numDirLightShadows),g.push(S.numPointLightShadows),g.push(S.numSpotLightShadows),g.push(S.numSpotLightShadowsWithMaps),g.push(S.numLightProbes),g.push(S.shadowMapType),g.push(S.toneMapping),g.push(S.numClippingPlanes),g.push(S.numClipIntersection),g.push(S.depthPacking)}function b(g,S){o.disableAll(),S.supportsVertexTextures&&o.enable(0),S.instancing&&o.enable(1),S.instancingColor&&o.enable(2),S.instancingMorph&&o.enable(3),S.matcap&&o.enable(4),S.envMap&&o.enable(5),S.normalMapObjectSpace&&o.enable(6),S.normalMapTangentSpace&&o.enable(7),S.clearcoat&&o.enable(8),S.iridescence&&o.enable(9),S.alphaTest&&o.enable(10),S.vertexColors&&o.enable(11),S.vertexAlphas&&o.enable(12),S.vertexUv1s&&o.enable(13),S.vertexUv2s&&o.enable(14),S.vertexUv3s&&o.enable(15),S.vertexTangents&&o.enable(16),S.anisotropy&&o.enable(17),S.alphaHash&&o.enable(18),S.batching&&o.enable(19),S.dispersion&&o.enable(20),S.batchingColor&&o.enable(21),g.push(o.mask),o.disableAll(),S.fog&&o.enable(0),S.useFog&&o.enable(1),S.flatShading&&o.enable(2),S.logarithmicDepthBuffer&&o.enable(3),S.reverseDepthBuffer&&o.enable(4),S.skinning&&o.enable(5),S.morphTargets&&o.enable(6),S.morphNormals&&o.enable(7),S.morphColors&&o.enable(8),S.premultipliedAlpha&&o.enable(9),S.shadowMapEnabled&&o.enable(10),S.doubleSided&&o.enable(11),S.flipSided&&o.enable(12),S.useDepthPacking&&o.enable(13),S.dithering&&o.enable(14),S.transmission&&o.enable(15),S.sheen&&o.enable(16),S.opaque&&o.enable(17),S.pointsUvs&&o.enable(18),S.decodeVideoTexture&&o.enable(19),S.alphaToCoverage&&o.enable(20),g.push(o.mask)}function O(g){const S=M[g.type];let V;if(S){const z=an[S];V=Fd.clone(z.uniforms)}else V=g.uniforms;return V}function C(g,S){let V;for(let z=0,k=u.length;z0?n.push(h):m.transparent===!0?r.push(h):t.push(h)}function l(d,p,m,_,M,f){const h=a(d,p,m,_,M,f);m.transmission>0?n.unshift(h):m.transparent===!0?r.unshift(h):t.unshift(h)}function c(d,p){t.length>1&&t.sort(d||ng),n.length>1&&n.sort(p||Nl),r.length>1&&r.sort(p||Nl)}function u(){for(let d=e,p=i.length;d=s.length?(a=new Fl,s.push(a)):a=s[r],a}function t(){i=new WeakMap}return{get:e,dispose:t}}function rg(){const i={};return{get:function(e){if(i[e.id]!==void 0)return i[e.id];let t;switch(e.type){case"DirectionalLight":t={direction:new N,color:new Ye};break;case"SpotLight":t={position:new N,direction:new N,color:new Ye,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case"PointLight":t={position:new N,color:new Ye,distance:0,decay:0};break;case"HemisphereLight":t={direction:new N,skyColor:new Ye,groundColor:new Ye};break;case"RectAreaLight":t={color:new Ye,position:new N,halfWidth:new N,halfHeight:new N};break}return i[e.id]=t,t}}}function sg(){const i={};return{get:function(e){if(i[e.id]!==void 0)return i[e.id];let t;switch(e.type){case"DirectionalLight":t={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new Le};break;case"SpotLight":t={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new Le};break;case"PointLight":t={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new Le,shadowCameraNear:1,shadowCameraFar:1e3};break}return i[e.id]=t,t}}}let ag=0;function og(i,e){return(e.castShadow?2:0)-(i.castShadow?2:0)+(e.map?1:0)-(i.map?1:0)}function lg(i){const e=new rg,t=sg(),n={version:0,hash:{directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1,numSpotMaps:-1,numLightProbes:-1},ambient:[0,0,0],probe:[],directional:[],directionalShadow:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotLightMap:[],spotShadow:[],spotShadowMap:[],spotLightMatrix:[],rectArea:[],rectAreaLTC1:null,rectAreaLTC2:null,point:[],pointShadow:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[],numSpotLightShadowsWithMaps:0,numLightProbes:0};for(let c=0;c<9;c++)n.probe.push(new N);const r=new N,s=new tt,a=new tt;function o(c){let u=0,d=0,p=0;for(let te=0;te<9;te++)n.probe[te].set(0,0,0);let m=0,_=0,M=0,f=0,h=0,T=0,y=0,b=0,O=0,C=0,A=0;c.sort(og);for(let te=0,g=c.length;te0&&(i.has("OES_texture_float_linear")===!0?(n.rectAreaLTC1=ne.LTC_FLOAT_1,n.rectAreaLTC2=ne.LTC_FLOAT_2):(n.rectAreaLTC1=ne.LTC_HALF_1,n.rectAreaLTC2=ne.LTC_HALF_2)),n.ambient[0]=u,n.ambient[1]=d,n.ambient[2]=p;const F=n.hash;(F.directionalLength!==m||F.pointLength!==_||F.spotLength!==M||F.rectAreaLength!==f||F.hemiLength!==h||F.numDirectionalShadows!==T||F.numPointShadows!==y||F.numSpotShadows!==b||F.numSpotMaps!==O||F.numLightProbes!==A)&&(n.directional.length=m,n.spot.length=M,n.rectArea.length=f,n.point.length=_,n.hemi.length=h,n.directionalShadow.length=T,n.directionalShadowMap.length=T,n.pointShadow.length=y,n.pointShadowMap.length=y,n.spotShadow.length=b,n.spotShadowMap.length=b,n.directionalShadowMatrix.length=T,n.pointShadowMatrix.length=y,n.spotLightMatrix.length=b+O-C,n.spotLightMap.length=O,n.numSpotLightShadowsWithMaps=C,n.numLightProbes=A,F.directionalLength=m,F.pointLength=_,F.spotLength=M,F.rectAreaLength=f,F.hemiLength=h,F.numDirectionalShadows=T,F.numPointShadows=y,F.numSpotShadows=b,F.numSpotMaps=O,F.numLightProbes=A,n.version=ag++)}function l(c,u){let d=0,p=0,m=0,_=0,M=0;const f=u.matrixWorldInverse;for(let h=0,T=c.length;h=a.length?(o=new Ol(i),a.push(o)):o=a[s],o}function n(){e=new WeakMap}return{get:t,dispose:n}}class ug extends Ss{constructor(e){super(),this.isMeshDepthMaterial=!0,this.type="MeshDepthMaterial",this.depthPacking=Gu,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.setValues(e)}copy(e){return super.copy(e),this.depthPacking=e.depthPacking,this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this}}class dg extends Ss{constructor(e){super(),this.isMeshDistanceMaterial=!0,this.type="MeshDistanceMaterial",this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.setValues(e)}copy(e){return super.copy(e),this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this}}const hg=`void main() { - gl_Position = vec4( position, 1.0 ); -}`,fg=`uniform sampler2D shadow_pass; -uniform vec2 resolution; -uniform float radius; -#include -void main() { - const float samples = float( VSM_SAMPLES ); - float mean = 0.0; - float squared_mean = 0.0; - float uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 ); - float uvStart = samples <= 1.0 ? 0.0 : - 1.0; - for ( float i = 0.0; i < samples; i ++ ) { - float uvOffset = uvStart + i * uvStride; - #ifdef HORIZONTAL_PASS - vec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) ); - mean += distribution.x; - squared_mean += distribution.y * distribution.y + distribution.x * distribution.x; - #else - float depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) ); - mean += depth; - squared_mean += depth * depth; - #endif - } - mean = mean / samples; - squared_mean = squared_mean / samples; - float std_dev = sqrt( squared_mean - mean * mean ); - gl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) ); -}`;function pg(i,e,t){let n=new Ec;const r=new Le,s=new Le,a=new it,o=new ug({depthPacking:Vu}),l=new dg,c={},u=t.maxTextureSize,d={[In]:Lt,[Lt]:In,[on]:on},p=new Gt({defines:{VSM_SAMPLES:8},uniforms:{shadow_pass:{value:null},resolution:{value:new Le},radius:{value:4}},vertexShader:hg,fragmentShader:fg}),m=p.clone();m.defines.HORIZONTAL_PASS=1;const _=new Hn;_.setAttribute("position",new en(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));const M=new lt(_,p),f=this;this.enabled=!1,this.autoUpdate=!0,this.needsUpdate=!1,this.type=Ql;let h=this.type;this.render=function(C,A,F){if(f.enabled===!1||f.autoUpdate===!1&&f.needsUpdate===!1||C.length===0)return;const te=i.getRenderTarget(),g=i.getActiveCubeFace(),S=i.getActiveMipmapLevel(),V=i.state;V.setBlending(Ln),V.buffers.color.setClear(1,1,1,1),V.buffers.depth.setTest(!0),V.setScissorTest(!1);const z=h!==vn&&this.type===vn,k=h===vn&&this.type!==vn;for(let K=0,B=C.length;Ku||r.y>u)&&(r.x>u&&(s.x=Math.floor(u/le.x),r.x=s.x*le.x,G.mapSize.x=s.x),r.y>u&&(s.y=Math.floor(u/le.y),r.y=s.y*le.y,G.mapSize.y=s.y)),G.map===null||z===!0||k===!0){const ve=this.type!==vn?{minFilter:ot,magFilter:ot}:{};G.map!==null&&G.map.dispose(),G.map=new nn(r.x,r.y,ve),G.map.texture.name=Q.name+".shadowMap",G.camera.updateProjectionMatrix()}i.setRenderTarget(G.map),i.clear();const ce=G.getViewportCount();for(let ve=0;ve0||A.map&&A.alphaTest>0){const V=g.uuid,z=A.uuid;let k=c[V];k===void 0&&(k={},c[V]=k);let K=k[z];K===void 0&&(K=g.clone(),k[z]=K,A.addEventListener("dispose",O)),g=K}if(g.visible=A.visible,g.wireframe=A.wireframe,te===vn?g.side=A.shadowSide!==null?A.shadowSide:A.side:g.side=A.shadowSide!==null?A.shadowSide:d[A.side],g.alphaMap=A.alphaMap,g.alphaTest=A.alphaTest,g.map=A.map,g.clipShadows=A.clipShadows,g.clippingPlanes=A.clippingPlanes,g.clipIntersection=A.clipIntersection,g.displacementMap=A.displacementMap,g.displacementScale=A.displacementScale,g.displacementBias=A.displacementBias,g.wireframeLinewidth=A.wireframeLinewidth,g.linewidth=A.linewidth,F.isPointLight===!0&&g.isMeshDistanceMaterial===!0){const V=i.properties.get(g);V.light=F}return g}function b(C,A,F,te,g){if(C.visible===!1)return;if(C.layers.test(A.layers)&&(C.isMesh||C.isLine||C.isPoints)&&(C.castShadow||C.receiveShadow&&g===vn)&&(!C.frustumCulled||n.intersectsObject(C))){C.modelViewMatrix.multiplyMatrices(F.matrixWorldInverse,C.matrixWorld);const z=e.update(C),k=C.material;if(Array.isArray(k)){const K=z.groups;for(let B=0,Q=K.length;B=1):Q.indexOf("OpenGL ES")!==-1&&(B=parseFloat(/^OpenGL ES (\d)/.exec(Q)[1]),K=B>=2);let G=null,le={};const ce=i.getParameter(i.SCISSOR_BOX),ve=i.getParameter(i.VIEWPORT),Ge=new it().fromArray(ce),Ze=new it().fromArray(ve);function W(R,ae,H,Y){const re=new Uint8Array(4),oe=i.createTexture();i.bindTexture(R,oe),i.texParameteri(R,i.TEXTURE_MIN_FILTER,i.NEAREST),i.texParameteri(R,i.TEXTURE_MAG_FILTER,i.NEAREST);for(let Be=0;Be"u"?!1:/OculusBrowser/g.test(navigator.userAgent),c=new Le,u=new WeakMap;let d;const p=new WeakMap;let m=!1;try{m=typeof OffscreenCanvas<"u"&&new OffscreenCanvas(1,1).getContext("2d")!==null}catch{}function _(E,v){return m?new OffscreenCanvas(E,v):hs("canvas")}function M(E,v,L){let q=1;const Z=we(E);if((Z.width>L||Z.height>L)&&(q=L/Math.max(Z.width,Z.height)),q<1)if(typeof HTMLImageElement<"u"&&E instanceof HTMLImageElement||typeof HTMLCanvasElement<"u"&&E instanceof HTMLCanvasElement||typeof ImageBitmap<"u"&&E instanceof ImageBitmap||typeof VideoFrame<"u"&&E instanceof VideoFrame){const X=Math.floor(q*Z.width),_e=Math.floor(q*Z.height);d===void 0&&(d=_(X,_e));const ie=v?_(X,_e):d;return ie.width=X,ie.height=_e,ie.getContext("2d").drawImage(E,0,0,X,_e),console.warn("THREE.WebGLRenderer: Texture has been resized from ("+Z.width+"x"+Z.height+") to ("+X+"x"+_e+")."),ie}else return"data"in E&&console.warn("THREE.WebGLRenderer: Image in DataTexture is too big ("+Z.width+"x"+Z.height+")."),E;return E}function f(E){return E.generateMipmaps&&E.minFilter!==ot&&E.minFilter!==ut}function h(E){i.generateMipmap(E)}function T(E,v,L,q,Z=!1){if(E!==null){if(i[E]!==void 0)return i[E];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+E+"'")}let X=v;if(v===i.RED&&(L===i.FLOAT&&(X=i.R32F),L===i.HALF_FLOAT&&(X=i.R16F),L===i.UNSIGNED_BYTE&&(X=i.R8)),v===i.RED_INTEGER&&(L===i.UNSIGNED_BYTE&&(X=i.R8UI),L===i.UNSIGNED_SHORT&&(X=i.R16UI),L===i.UNSIGNED_INT&&(X=i.R32UI),L===i.BYTE&&(X=i.R8I),L===i.SHORT&&(X=i.R16I),L===i.INT&&(X=i.R32I)),v===i.RG&&(L===i.FLOAT&&(X=i.RG32F),L===i.HALF_FLOAT&&(X=i.RG16F),L===i.UNSIGNED_BYTE&&(X=i.RG8)),v===i.RG_INTEGER&&(L===i.UNSIGNED_BYTE&&(X=i.RG8UI),L===i.UNSIGNED_SHORT&&(X=i.RG16UI),L===i.UNSIGNED_INT&&(X=i.RG32UI),L===i.BYTE&&(X=i.RG8I),L===i.SHORT&&(X=i.RG16I),L===i.INT&&(X=i.RG32I)),v===i.RGB_INTEGER&&(L===i.UNSIGNED_BYTE&&(X=i.RGB8UI),L===i.UNSIGNED_SHORT&&(X=i.RGB16UI),L===i.UNSIGNED_INT&&(X=i.RGB32UI),L===i.BYTE&&(X=i.RGB8I),L===i.SHORT&&(X=i.RGB16I),L===i.INT&&(X=i.RGB32I)),v===i.RGBA_INTEGER&&(L===i.UNSIGNED_BYTE&&(X=i.RGBA8UI),L===i.UNSIGNED_SHORT&&(X=i.RGBA16UI),L===i.UNSIGNED_INT&&(X=i.RGBA32UI),L===i.BYTE&&(X=i.RGBA8I),L===i.SHORT&&(X=i.RGBA16I),L===i.INT&&(X=i.RGBA32I)),v===i.RGB&&L===i.UNSIGNED_INT_5_9_9_9_REV&&(X=i.RGB9_E5),v===i.RGBA){const _e=Z?ls:qe.getTransfer(q);L===i.FLOAT&&(X=i.RGBA32F),L===i.HALF_FLOAT&&(X=i.RGBA16F),L===i.UNSIGNED_BYTE&&(X=_e===et?i.SRGB8_ALPHA8:i.RGBA8),L===i.UNSIGNED_SHORT_4_4_4_4&&(X=i.RGBA4),L===i.UNSIGNED_SHORT_5_5_5_1&&(X=i.RGB5_A1)}return(X===i.R16F||X===i.R32F||X===i.RG16F||X===i.RG32F||X===i.RGBA16F||X===i.RGBA32F)&&e.get("EXT_color_buffer_float"),X}function y(E,v){let L;return E?v===null||v===Nn||v===Ni?L=i.DEPTH24_STENCIL8:v===Mn?L=i.DEPTH32F_STENCIL8:v===cr&&(L=i.DEPTH24_STENCIL8,console.warn("DepthTexture: 16 bit depth attachment is not supported with stencil. Using 24-bit attachment.")):v===null||v===Nn||v===Ni?L=i.DEPTH_COMPONENT24:v===Mn?L=i.DEPTH_COMPONENT32F:v===cr&&(L=i.DEPTH_COMPONENT16),L}function b(E,v){return f(E)===!0||E.isFramebufferTexture&&E.minFilter!==ot&&E.minFilter!==ut?Math.log2(Math.max(v.width,v.height))+1:E.mipmaps!==void 0&&E.mipmaps.length>0?E.mipmaps.length:E.isCompressedTexture&&Array.isArray(E.image)?v.mipmaps.length:1}function O(E){const v=E.target;v.removeEventListener("dispose",O),A(v),v.isVideoTexture&&u.delete(v)}function C(E){const v=E.target;v.removeEventListener("dispose",C),te(v)}function A(E){const v=n.get(E);if(v.__webglInit===void 0)return;const L=E.source,q=p.get(L);if(q){const Z=q[v.__cacheKey];Z.usedTimes--,Z.usedTimes===0&&F(E),Object.keys(q).length===0&&p.delete(L)}n.remove(E)}function F(E){const v=n.get(E);i.deleteTexture(v.__webglTexture);const L=E.source,q=p.get(L);delete q[v.__cacheKey],a.memory.textures--}function te(E){const v=n.get(E);if(E.depthTexture&&E.depthTexture.dispose(),E.isWebGLCubeRenderTarget)for(let q=0;q<6;q++){if(Array.isArray(v.__webglFramebuffer[q]))for(let Z=0;Z=r.maxTextures&&console.warn("THREE.WebGLTextures: Trying to use "+E+" texture units while this GPU supports only "+r.maxTextures),g+=1,E}function z(E){const v=[];return v.push(E.wrapS),v.push(E.wrapT),v.push(E.wrapR||0),v.push(E.magFilter),v.push(E.minFilter),v.push(E.anisotropy),v.push(E.internalFormat),v.push(E.format),v.push(E.type),v.push(E.generateMipmaps),v.push(E.premultiplyAlpha),v.push(E.flipY),v.push(E.unpackAlignment),v.push(E.colorSpace),v.join()}function k(E,v){const L=n.get(E);if(E.isVideoTexture&&Te(E),E.isRenderTargetTexture===!1&&E.version>0&&L.__version!==E.version){const q=E.image;if(q===null)console.warn("THREE.WebGLRenderer: Texture marked for update but no image data found.");else if(q.complete===!1)console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete");else{Ze(L,E,v);return}}t.bindTexture(i.TEXTURE_2D,L.__webglTexture,i.TEXTURE0+v)}function K(E,v){const L=n.get(E);if(E.version>0&&L.__version!==E.version){Ze(L,E,v);return}t.bindTexture(i.TEXTURE_2D_ARRAY,L.__webglTexture,i.TEXTURE0+v)}function B(E,v){const L=n.get(E);if(E.version>0&&L.__version!==E.version){Ze(L,E,v);return}t.bindTexture(i.TEXTURE_3D,L.__webglTexture,i.TEXTURE0+v)}function Q(E,v){const L=n.get(E);if(E.version>0&&L.__version!==E.version){W(L,E,v);return}t.bindTexture(i.TEXTURE_CUBE_MAP,L.__webglTexture,i.TEXTURE0+v)}const G={[ya]:i.REPEAT,[Jn]:i.CLAMP_TO_EDGE,[Ea]:i.MIRRORED_REPEAT},le={[ot]:i.NEAREST,[Hu]:i.NEAREST_MIPMAP_NEAREST,[Ar]:i.NEAREST_MIPMAP_LINEAR,[ut]:i.LINEAR,[Us]:i.LINEAR_MIPMAP_NEAREST,[Qn]:i.LINEAR_MIPMAP_LINEAR},ce={[Xu]:i.NEVER,[$u]:i.ALWAYS,[qu]:i.LESS,[hc]:i.LEQUAL,[Yu]:i.EQUAL,[ju]:i.GEQUAL,[Zu]:i.GREATER,[Ku]:i.NOTEQUAL};function ve(E,v){if(v.type===Mn&&e.has("OES_texture_float_linear")===!1&&(v.magFilter===ut||v.magFilter===Us||v.magFilter===Ar||v.magFilter===Qn||v.minFilter===ut||v.minFilter===Us||v.minFilter===Ar||v.minFilter===Qn)&&console.warn("THREE.WebGLRenderer: Unable to use linear filtering with floating point textures. OES_texture_float_linear not supported on this device."),i.texParameteri(E,i.TEXTURE_WRAP_S,G[v.wrapS]),i.texParameteri(E,i.TEXTURE_WRAP_T,G[v.wrapT]),(E===i.TEXTURE_3D||E===i.TEXTURE_2D_ARRAY)&&i.texParameteri(E,i.TEXTURE_WRAP_R,G[v.wrapR]),i.texParameteri(E,i.TEXTURE_MAG_FILTER,le[v.magFilter]),i.texParameteri(E,i.TEXTURE_MIN_FILTER,le[v.minFilter]),v.compareFunction&&(i.texParameteri(E,i.TEXTURE_COMPARE_MODE,i.COMPARE_REF_TO_TEXTURE),i.texParameteri(E,i.TEXTURE_COMPARE_FUNC,ce[v.compareFunction])),e.has("EXT_texture_filter_anisotropic")===!0){if(v.magFilter===ot||v.minFilter!==Ar&&v.minFilter!==Qn||v.type===Mn&&e.has("OES_texture_float_linear")===!1)return;if(v.anisotropy>1||n.get(v).__currentAnisotropy){const L=e.get("EXT_texture_filter_anisotropic");i.texParameterf(E,L.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(v.anisotropy,r.getMaxAnisotropy())),n.get(v).__currentAnisotropy=v.anisotropy}}}function Ge(E,v){let L=!1;E.__webglInit===void 0&&(E.__webglInit=!0,v.addEventListener("dispose",O));const q=v.source;let Z=p.get(q);Z===void 0&&(Z={},p.set(q,Z));const X=z(v);if(X!==E.__cacheKey){Z[X]===void 0&&(Z[X]={texture:i.createTexture(),usedTimes:0},a.memory.textures++,L=!0),Z[X].usedTimes++;const _e=Z[E.__cacheKey];_e!==void 0&&(Z[E.__cacheKey].usedTimes--,_e.usedTimes===0&&F(v)),E.__cacheKey=X,E.__webglTexture=Z[X].texture}return L}function Ze(E,v,L){let q=i.TEXTURE_2D;(v.isDataArrayTexture||v.isCompressedArrayTexture)&&(q=i.TEXTURE_2D_ARRAY),v.isData3DTexture&&(q=i.TEXTURE_3D);const Z=Ge(E,v),X=v.source;t.bindTexture(q,E.__webglTexture,i.TEXTURE0+L);const _e=n.get(X);if(X.version!==_e.__version||Z===!0){t.activeTexture(i.TEXTURE0+L);const ie=qe.getPrimaries(qe.workingColorSpace),de=v.colorSpace===Mt?null:qe.getPrimaries(v.colorSpace),He=v.colorSpace===Mt||ie===de?i.NONE:i.BROWSER_DEFAULT_WEBGL;i.pixelStorei(i.UNPACK_FLIP_Y_WEBGL,v.flipY),i.pixelStorei(i.UNPACK_PREMULTIPLY_ALPHA_WEBGL,v.premultiplyAlpha),i.pixelStorei(i.UNPACK_ALIGNMENT,v.unpackAlignment),i.pixelStorei(i.UNPACK_COLORSPACE_CONVERSION_WEBGL,He);let $=M(v.image,!1,r.maxTextureSize);$=Je(v,$);const he=s.convert(v.format,v.colorSpace),be=s.convert(v.type);let Ae=T(v.internalFormat,he,be,v.colorSpace,v.isVideoTexture);ve(q,v);let fe;const Ie=v.mipmaps,Ce=v.isVideoTexture!==!0,$e=_e.__version===void 0||Z===!0,R=X.dataReady,ae=b(v,$);if(v.isDepthTexture)Ae=y(v.format===Fi,v.type),$e&&(Ce?t.texStorage2D(i.TEXTURE_2D,1,Ae,$.width,$.height):t.texImage2D(i.TEXTURE_2D,0,Ae,$.width,$.height,0,he,be,null));else if(v.isDataTexture)if(Ie.length>0){Ce&&$e&&t.texStorage2D(i.TEXTURE_2D,ae,Ae,Ie[0].width,Ie[0].height);for(let H=0,Y=Ie.length;H0){const re=Bl(fe.width,fe.height,v.format,v.type);for(const oe of v.layerUpdates){const Be=fe.data.subarray(oe*re/fe.data.BYTES_PER_ELEMENT,(oe+1)*re/fe.data.BYTES_PER_ELEMENT);t.compressedTexSubImage3D(i.TEXTURE_2D_ARRAY,H,0,0,oe,fe.width,fe.height,1,he,Be,0,0)}v.clearLayerUpdates()}else t.compressedTexSubImage3D(i.TEXTURE_2D_ARRAY,H,0,0,0,fe.width,fe.height,$.depth,he,fe.data,0,0)}else t.compressedTexImage3D(i.TEXTURE_2D_ARRAY,H,Ae,fe.width,fe.height,$.depth,0,fe.data,0,0);else console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()");else Ce?R&&t.texSubImage3D(i.TEXTURE_2D_ARRAY,H,0,0,0,fe.width,fe.height,$.depth,he,be,fe.data):t.texImage3D(i.TEXTURE_2D_ARRAY,H,Ae,fe.width,fe.height,$.depth,0,he,be,fe.data)}else{Ce&&$e&&t.texStorage2D(i.TEXTURE_2D,ae,Ae,Ie[0].width,Ie[0].height);for(let H=0,Y=Ie.length;H0){const H=Bl($.width,$.height,v.format,v.type);for(const Y of v.layerUpdates){const re=$.data.subarray(Y*H/$.data.BYTES_PER_ELEMENT,(Y+1)*H/$.data.BYTES_PER_ELEMENT);t.texSubImage3D(i.TEXTURE_2D_ARRAY,0,0,0,Y,$.width,$.height,1,he,be,re)}v.clearLayerUpdates()}else t.texSubImage3D(i.TEXTURE_2D_ARRAY,0,0,0,0,$.width,$.height,$.depth,he,be,$.data)}else t.texImage3D(i.TEXTURE_2D_ARRAY,0,Ae,$.width,$.height,$.depth,0,he,be,$.data);else if(v.isData3DTexture)Ce?($e&&t.texStorage3D(i.TEXTURE_3D,ae,Ae,$.width,$.height,$.depth),R&&t.texSubImage3D(i.TEXTURE_3D,0,0,0,0,$.width,$.height,$.depth,he,be,$.data)):t.texImage3D(i.TEXTURE_3D,0,Ae,$.width,$.height,$.depth,0,he,be,$.data);else if(v.isFramebufferTexture){if($e)if(Ce)t.texStorage2D(i.TEXTURE_2D,ae,Ae,$.width,$.height);else{let H=$.width,Y=$.height;for(let re=0;re>=1,Y>>=1}}else if(Ie.length>0){if(Ce&&$e){const H=we(Ie[0]);t.texStorage2D(i.TEXTURE_2D,ae,Ae,H.width,H.height)}for(let H=0,Y=Ie.length;H0&&ae++;const Y=we(he[0]);t.texStorage2D(i.TEXTURE_CUBE_MAP,ae,Ie,Y.width,Y.height)}for(let Y=0;Y<6;Y++)if($){Ce?R&&t.texSubImage2D(i.TEXTURE_CUBE_MAP_POSITIVE_X+Y,0,0,0,he[Y].width,he[Y].height,Ae,fe,he[Y].data):t.texImage2D(i.TEXTURE_CUBE_MAP_POSITIVE_X+Y,0,Ie,he[Y].width,he[Y].height,0,Ae,fe,he[Y].data);for(let re=0;re>X),he=Math.max(1,v.height>>X);Z===i.TEXTURE_3D||Z===i.TEXTURE_2D_ARRAY?t.texImage3D(Z,X,de,$,he,v.depth,0,_e,ie,null):t.texImage2D(Z,X,de,$,he,0,_e,ie,null)}t.bindFramebuffer(i.FRAMEBUFFER,E),ze(v)?o.framebufferTexture2DMultisampleEXT(i.FRAMEBUFFER,q,Z,n.get(L).__webglTexture,0,Ue(v)):(Z===i.TEXTURE_2D||Z>=i.TEXTURE_CUBE_MAP_POSITIVE_X&&Z<=i.TEXTURE_CUBE_MAP_NEGATIVE_Z)&&i.framebufferTexture2D(i.FRAMEBUFFER,q,Z,n.get(L).__webglTexture,X),t.bindFramebuffer(i.FRAMEBUFFER,null)}function me(E,v,L){if(i.bindRenderbuffer(i.RENDERBUFFER,E),v.depthBuffer){const q=v.depthTexture,Z=q&&q.isDepthTexture?q.type:null,X=y(v.stencilBuffer,Z),_e=v.stencilBuffer?i.DEPTH_STENCIL_ATTACHMENT:i.DEPTH_ATTACHMENT,ie=Ue(v);ze(v)?o.renderbufferStorageMultisampleEXT(i.RENDERBUFFER,ie,X,v.width,v.height):L?i.renderbufferStorageMultisample(i.RENDERBUFFER,ie,X,v.width,v.height):i.renderbufferStorage(i.RENDERBUFFER,X,v.width,v.height),i.framebufferRenderbuffer(i.FRAMEBUFFER,_e,i.RENDERBUFFER,E)}else{const q=v.textures;for(let Z=0;Z{delete v.__boundDepthTexture,delete v.__depthDisposeCallback,q.removeEventListener("dispose",Z)};q.addEventListener("dispose",Z),v.__depthDisposeCallback=Z}v.__boundDepthTexture=q}if(E.depthTexture&&!v.__autoAllocateDepthBuffer){if(L)throw new Error("target.depthTexture not supported in Cube render targets");ue(v.__webglFramebuffer,E)}else if(L){v.__webglDepthbuffer=[];for(let q=0;q<6;q++)if(t.bindFramebuffer(i.FRAMEBUFFER,v.__webglFramebuffer[q]),v.__webglDepthbuffer[q]===void 0)v.__webglDepthbuffer[q]=i.createRenderbuffer(),me(v.__webglDepthbuffer[q],E,!1);else{const Z=E.stencilBuffer?i.DEPTH_STENCIL_ATTACHMENT:i.DEPTH_ATTACHMENT,X=v.__webglDepthbuffer[q];i.bindRenderbuffer(i.RENDERBUFFER,X),i.framebufferRenderbuffer(i.FRAMEBUFFER,Z,i.RENDERBUFFER,X)}}else if(t.bindFramebuffer(i.FRAMEBUFFER,v.__webglFramebuffer),v.__webglDepthbuffer===void 0)v.__webglDepthbuffer=i.createRenderbuffer(),me(v.__webglDepthbuffer,E,!1);else{const q=E.stencilBuffer?i.DEPTH_STENCIL_ATTACHMENT:i.DEPTH_ATTACHMENT,Z=v.__webglDepthbuffer;i.bindRenderbuffer(i.RENDERBUFFER,Z),i.framebufferRenderbuffer(i.FRAMEBUFFER,q,i.RENDERBUFFER,Z)}t.bindFramebuffer(i.FRAMEBUFFER,null)}function ye(E,v,L){const q=n.get(E);v!==void 0&&j(q.__webglFramebuffer,E,E.texture,i.COLOR_ATTACHMENT0,i.TEXTURE_2D,0),L!==void 0&&Re(E)}function Fe(E){const v=E.texture,L=n.get(E),q=n.get(v);E.addEventListener("dispose",C);const Z=E.textures,X=E.isWebGLCubeRenderTarget===!0,_e=Z.length>1;if(_e||(q.__webglTexture===void 0&&(q.__webglTexture=i.createTexture()),q.__version=v.version,a.memory.textures++),X){L.__webglFramebuffer=[];for(let ie=0;ie<6;ie++)if(v.mipmaps&&v.mipmaps.length>0){L.__webglFramebuffer[ie]=[];for(let de=0;de0){L.__webglFramebuffer=[];for(let ie=0;ie0&&ze(E)===!1){L.__webglMultisampledFramebuffer=i.createFramebuffer(),L.__webglColorRenderbuffer=[],t.bindFramebuffer(i.FRAMEBUFFER,L.__webglMultisampledFramebuffer);for(let ie=0;ie0)for(let de=0;de0)for(let de=0;de0){if(ze(E)===!1){const v=E.textures,L=E.width,q=E.height;let Z=i.COLOR_BUFFER_BIT;const X=E.stencilBuffer?i.DEPTH_STENCIL_ATTACHMENT:i.DEPTH_ATTACHMENT,_e=n.get(E),ie=v.length>1;if(ie)for(let de=0;de0&&e.has("WEBGL_multisampled_render_to_texture")===!0&&v.__useRenderToTexture!==!1}function Te(E){const v=a.render.frame;u.get(E)!==v&&(u.set(E,v),E.update())}function Je(E,v){const L=E.colorSpace,q=E.format,Z=E.type;return E.isCompressedTexture===!0||E.isVideoTexture===!0||L!==zn&&L!==Mt&&(qe.getTransfer(L)===et?(q!==Pt||Z!==cn)&&console.warn("THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType."):console.error("THREE.WebGLTextures: Unsupported texture color space:",L)),v}function we(E){return typeof HTMLImageElement<"u"&&E instanceof HTMLImageElement?(c.width=E.naturalWidth||E.width,c.height=E.naturalHeight||E.height):typeof VideoFrame<"u"&&E instanceof VideoFrame?(c.width=E.displayWidth,c.height=E.displayHeight):(c.width=E.width,c.height=E.height),c}this.allocateTextureUnit=V,this.resetTextureUnits=S,this.setTexture2D=k,this.setTexture2DArray=K,this.setTexture3D=B,this.setTextureCube=Q,this.rebindTextures=ye,this.setupRenderTarget=Fe,this.updateRenderTargetMipmap=je,this.updateMultisampleRenderTarget=Ut,this.setupDepthRenderbuffer=Re,this.setupFrameBufferTexture=j,this.useMultisampledRTT=ze}function xg(i,e){function t(n,r=Mt){let s;const a=qe.getTransfer(r);if(n===cn)return i.UNSIGNED_BYTE;if(n===oo)return i.UNSIGNED_SHORT_4_4_4_4;if(n===lo)return i.UNSIGNED_SHORT_5_5_5_1;if(n===rc)return i.UNSIGNED_INT_5_9_9_9_REV;if(n===nc)return i.BYTE;if(n===ic)return i.SHORT;if(n===cr)return i.UNSIGNED_SHORT;if(n===ao)return i.INT;if(n===Nn)return i.UNSIGNED_INT;if(n===Mn)return i.FLOAT;if(n===Bn)return i.HALF_FLOAT;if(n===sc)return i.ALPHA;if(n===ac)return i.RGB;if(n===Pt)return i.RGBA;if(n===oc)return i.LUMINANCE;if(n===lc)return i.LUMINANCE_ALPHA;if(n===ei)return i.DEPTH_COMPONENT;if(n===Fi)return i.DEPTH_STENCIL;if(n===cc)return i.RED;if(n===co)return i.RED_INTEGER;if(n===uc)return i.RG;if(n===uo)return i.RG_INTEGER;if(n===ho)return i.RGBA_INTEGER;if(n===Zr||n===Kr||n===jr||n===$r)if(a===et)if(s=e.get("WEBGL_compressed_texture_s3tc_srgb"),s!==null){if(n===Zr)return s.COMPRESSED_SRGB_S3TC_DXT1_EXT;if(n===Kr)return s.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;if(n===jr)return s.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;if(n===$r)return s.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT}else return null;else if(s=e.get("WEBGL_compressed_texture_s3tc"),s!==null){if(n===Zr)return s.COMPRESSED_RGB_S3TC_DXT1_EXT;if(n===Kr)return s.COMPRESSED_RGBA_S3TC_DXT1_EXT;if(n===jr)return s.COMPRESSED_RGBA_S3TC_DXT3_EXT;if(n===$r)return s.COMPRESSED_RGBA_S3TC_DXT5_EXT}else return null;if(n===Ta||n===ba||n===Aa||n===wa)if(s=e.get("WEBGL_compressed_texture_pvrtc"),s!==null){if(n===Ta)return s.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;if(n===ba)return s.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;if(n===Aa)return s.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;if(n===wa)return s.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG}else return null;if(n===Ra||n===Ca||n===Pa)if(s=e.get("WEBGL_compressed_texture_etc"),s!==null){if(n===Ra||n===Ca)return a===et?s.COMPRESSED_SRGB8_ETC2:s.COMPRESSED_RGB8_ETC2;if(n===Pa)return a===et?s.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:s.COMPRESSED_RGBA8_ETC2_EAC}else return null;if(n===Da||n===La||n===Ua||n===Ia||n===Na||n===Fa||n===Oa||n===Ba||n===za||n===Ha||n===Ga||n===Va||n===ka||n===Wa)if(s=e.get("WEBGL_compressed_texture_astc"),s!==null){if(n===Da)return a===et?s.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:s.COMPRESSED_RGBA_ASTC_4x4_KHR;if(n===La)return a===et?s.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:s.COMPRESSED_RGBA_ASTC_5x4_KHR;if(n===Ua)return a===et?s.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:s.COMPRESSED_RGBA_ASTC_5x5_KHR;if(n===Ia)return a===et?s.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:s.COMPRESSED_RGBA_ASTC_6x5_KHR;if(n===Na)return a===et?s.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:s.COMPRESSED_RGBA_ASTC_6x6_KHR;if(n===Fa)return a===et?s.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:s.COMPRESSED_RGBA_ASTC_8x5_KHR;if(n===Oa)return a===et?s.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:s.COMPRESSED_RGBA_ASTC_8x6_KHR;if(n===Ba)return a===et?s.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:s.COMPRESSED_RGBA_ASTC_8x8_KHR;if(n===za)return a===et?s.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:s.COMPRESSED_RGBA_ASTC_10x5_KHR;if(n===Ha)return a===et?s.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:s.COMPRESSED_RGBA_ASTC_10x6_KHR;if(n===Ga)return a===et?s.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:s.COMPRESSED_RGBA_ASTC_10x8_KHR;if(n===Va)return a===et?s.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:s.COMPRESSED_RGBA_ASTC_10x10_KHR;if(n===ka)return a===et?s.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:s.COMPRESSED_RGBA_ASTC_12x10_KHR;if(n===Wa)return a===et?s.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:s.COMPRESSED_RGBA_ASTC_12x12_KHR}else return null;if(n===Jr||n===Xa||n===qa)if(s=e.get("EXT_texture_compression_bptc"),s!==null){if(n===Jr)return a===et?s.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:s.COMPRESSED_RGBA_BPTC_UNORM_EXT;if(n===Xa)return s.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT;if(n===qa)return s.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT}else return null;if(n===dc||n===Ya||n===Za||n===Ka)if(s=e.get("EXT_texture_compression_rgtc"),s!==null){if(n===Jr)return s.COMPRESSED_RED_RGTC1_EXT;if(n===Ya)return s.COMPRESSED_SIGNED_RED_RGTC1_EXT;if(n===Za)return s.COMPRESSED_RED_GREEN_RGTC2_EXT;if(n===Ka)return s.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT}else return null;return n===Ni?i.UNSIGNED_INT_24_8:i[n]!==void 0?i[n]:null}return{convert:t}}class Sg extends Wt{constructor(e=[]){super(),this.isArrayCamera=!0,this.cameras=e}}class Yr extends Ht{constructor(){super(),this.isGroup=!0,this.type="Group"}}const Mg={type:"move"};class oa{constructor(){this._targetRay=null,this._grip=null,this._hand=null}getHandSpace(){return this._hand===null&&(this._hand=new Yr,this._hand.matrixAutoUpdate=!1,this._hand.visible=!1,this._hand.joints={},this._hand.inputState={pinching:!1}),this._hand}getTargetRaySpace(){return this._targetRay===null&&(this._targetRay=new Yr,this._targetRay.matrixAutoUpdate=!1,this._targetRay.visible=!1,this._targetRay.hasLinearVelocity=!1,this._targetRay.linearVelocity=new N,this._targetRay.hasAngularVelocity=!1,this._targetRay.angularVelocity=new N),this._targetRay}getGripSpace(){return this._grip===null&&(this._grip=new Yr,this._grip.matrixAutoUpdate=!1,this._grip.visible=!1,this._grip.hasLinearVelocity=!1,this._grip.linearVelocity=new N,this._grip.hasAngularVelocity=!1,this._grip.angularVelocity=new N),this._grip}dispatchEvent(e){return this._targetRay!==null&&this._targetRay.dispatchEvent(e),this._grip!==null&&this._grip.dispatchEvent(e),this._hand!==null&&this._hand.dispatchEvent(e),this}connect(e){if(e&&e.hand){const t=this._hand;if(t)for(const n of e.hand.values())this._getHandJoint(t,n)}return this.dispatchEvent({type:"connected",data:e}),this}disconnect(e){return this.dispatchEvent({type:"disconnected",data:e}),this._targetRay!==null&&(this._targetRay.visible=!1),this._grip!==null&&(this._grip.visible=!1),this._hand!==null&&(this._hand.visible=!1),this}update(e,t,n){let r=null,s=null,a=null;const o=this._targetRay,l=this._grip,c=this._hand;if(e&&t.session.visibilityState!=="visible-blurred"){if(c&&e.hand){a=!0;for(const M of e.hand.values()){const f=t.getJointPose(M,n),h=this._getHandJoint(c,M);f!==null&&(h.matrix.fromArray(f.transform.matrix),h.matrix.decompose(h.position,h.rotation,h.scale),h.matrixWorldNeedsUpdate=!0,h.jointRadius=f.radius),h.visible=f!==null}const u=c.joints["index-finger-tip"],d=c.joints["thumb-tip"],p=u.position.distanceTo(d.position),m=.02,_=.005;c.inputState.pinching&&p>m+_?(c.inputState.pinching=!1,this.dispatchEvent({type:"pinchend",handedness:e.handedness,target:this})):!c.inputState.pinching&&p<=m-_&&(c.inputState.pinching=!0,this.dispatchEvent({type:"pinchstart",handedness:e.handedness,target:this}))}else l!==null&&e.gripSpace&&(s=t.getPose(e.gripSpace,n),s!==null&&(l.matrix.fromArray(s.transform.matrix),l.matrix.decompose(l.position,l.rotation,l.scale),l.matrixWorldNeedsUpdate=!0,s.linearVelocity?(l.hasLinearVelocity=!0,l.linearVelocity.copy(s.linearVelocity)):l.hasLinearVelocity=!1,s.angularVelocity?(l.hasAngularVelocity=!0,l.angularVelocity.copy(s.angularVelocity)):l.hasAngularVelocity=!1));o!==null&&(r=t.getPose(e.targetRaySpace,n),r===null&&s!==null&&(r=s),r!==null&&(o.matrix.fromArray(r.transform.matrix),o.matrix.decompose(o.position,o.rotation,o.scale),o.matrixWorldNeedsUpdate=!0,r.linearVelocity?(o.hasLinearVelocity=!0,o.linearVelocity.copy(r.linearVelocity)):o.hasLinearVelocity=!1,r.angularVelocity?(o.hasAngularVelocity=!0,o.angularVelocity.copy(r.angularVelocity)):o.hasAngularVelocity=!1,this.dispatchEvent(Mg)))}return o!==null&&(o.visible=r!==null),l!==null&&(l.visible=s!==null),c!==null&&(c.visible=a!==null),this}_getHandJoint(e,t){if(e.joints[t.jointName]===void 0){const n=new Yr;n.matrixAutoUpdate=!1,n.visible=!1,e.joints[t.jointName]=n,e.add(n)}return e.joints[t.jointName]}}const yg=` -void main() { - - gl_Position = vec4( position, 1.0 ); - -}`,Eg=` -uniform sampler2DArray depthColor; -uniform float depthWidth; -uniform float depthHeight; - -void main() { - - vec2 coord = vec2( gl_FragCoord.x / depthWidth, gl_FragCoord.y / depthHeight ); - - if ( coord.x >= 1.0 ) { - - gl_FragDepth = texture( depthColor, vec3( coord.x - 1.0, coord.y, 1 ) ).r; - - } else { - - gl_FragDepth = texture( depthColor, vec3( coord.x, coord.y, 0 ) ).r; - - } - -}`;class Tg{constructor(){this.texture=null,this.mesh=null,this.depthNear=0,this.depthFar=0}init(e,t,n){if(this.texture===null){const r=new vt,s=e.properties.get(r);s.__webglTexture=t.texture,(t.depthNear!=n.depthNear||t.depthFar!=n.depthFar)&&(this.depthNear=t.depthNear,this.depthFar=t.depthFar),this.texture=r}}getMesh(e){if(this.texture!==null&&this.mesh===null){const t=e.cameras[0].viewport,n=new Gt({vertexShader:yg,fragmentShader:Eg,uniforms:{depthColor:{value:this.texture},depthWidth:{value:t.z},depthHeight:{value:t.w}}});this.mesh=new lt(new un(20,20),n)}return this.mesh}reset(){this.texture=null,this.mesh=null}getDepthTexture(){return this.texture}}class bg extends Gi{constructor(e,t){super();const n=this;let r=null,s=1,a=null,o="local-floor",l=1,c=null,u=null,d=null,p=null,m=null,_=null;const M=new Tg,f=t.getContextAttributes();let h=null,T=null;const y=[],b=[],O=new Le;let C=null;const A=new Wt;A.layers.enable(1),A.viewport=new it;const F=new Wt;F.layers.enable(2),F.viewport=new it;const te=[A,F],g=new Sg;g.layers.enable(1),g.layers.enable(2);let S=null,V=null;this.cameraAutoUpdate=!0,this.enabled=!1,this.isPresenting=!1,this.getController=function(W){let j=y[W];return j===void 0&&(j=new oa,y[W]=j),j.getTargetRaySpace()},this.getControllerGrip=function(W){let j=y[W];return j===void 0&&(j=new oa,y[W]=j),j.getGripSpace()},this.getHand=function(W){let j=y[W];return j===void 0&&(j=new oa,y[W]=j),j.getHandSpace()};function z(W){const j=b.indexOf(W.inputSource);if(j===-1)return;const me=y[j];me!==void 0&&(me.update(W.inputSource,W.frame,c||a),me.dispatchEvent({type:W.type,data:W.inputSource}))}function k(){r.removeEventListener("select",z),r.removeEventListener("selectstart",z),r.removeEventListener("selectend",z),r.removeEventListener("squeeze",z),r.removeEventListener("squeezestart",z),r.removeEventListener("squeezeend",z),r.removeEventListener("end",k),r.removeEventListener("inputsourceschange",K);for(let W=0;W=0&&(b[ue]=null,y[ue].disconnect(me))}for(let j=0;j=b.length){b.push(me),ue=ye;break}else if(b[ye]===null){b[ye]=me,ue=ye;break}if(ue===-1)break}const Re=y[ue];Re&&Re.connect(me)}}const B=new N,Q=new N;function G(W,j,me){B.setFromMatrixPosition(j.matrixWorld),Q.setFromMatrixPosition(me.matrixWorld);const ue=B.distanceTo(Q),Re=j.projectionMatrix.elements,ye=me.projectionMatrix.elements,Fe=Re[14]/(Re[10]-1),je=Re[14]/(Re[10]+1),Oe=(Re[9]+1)/Re[5],w=(Re[9]-1)/Re[5],Ut=(Re[8]-1)/Re[0],Ue=(ye[8]+1)/ye[0],ze=Fe*Ut,Te=Fe*Ue,Je=ue/(-Ut+Ue),we=Je*-Ut;if(j.matrixWorld.decompose(W.position,W.quaternion,W.scale),W.translateX(we),W.translateZ(Je),W.matrixWorld.compose(W.position,W.quaternion,W.scale),W.matrixWorldInverse.copy(W.matrixWorld).invert(),Re[10]===-1)W.projectionMatrix.copy(j.projectionMatrix),W.projectionMatrixInverse.copy(j.projectionMatrixInverse);else{const E=Fe+Je,v=je+Je,L=ze-we,q=Te+(ue-we),Z=Oe*je/v*E,X=w*je/v*E;W.projectionMatrix.makePerspective(L,q,Z,X,E,v),W.projectionMatrixInverse.copy(W.projectionMatrix).invert()}}function le(W,j){j===null?W.matrixWorld.copy(W.matrix):W.matrixWorld.multiplyMatrices(j.matrixWorld,W.matrix),W.matrixWorldInverse.copy(W.matrixWorld).invert()}this.updateCamera=function(W){if(r===null)return;let j=W.near,me=W.far;M.texture!==null&&(M.depthNear>0&&(j=M.depthNear),M.depthFar>0&&(me=M.depthFar)),g.near=F.near=A.near=j,g.far=F.far=A.far=me,(S!==g.near||V!==g.far)&&(r.updateRenderState({depthNear:g.near,depthFar:g.far}),S=g.near,V=g.far);const ue=W.parent,Re=g.cameras;le(g,ue);for(let ye=0;ye0&&(f.alphaTest.value=h.alphaTest);const T=e.get(h),y=T.envMap,b=T.envMapRotation;y&&(f.envMap.value=y,Yn.copy(b),Yn.x*=-1,Yn.y*=-1,Yn.z*=-1,y.isCubeTexture&&y.isRenderTargetTexture===!1&&(Yn.y*=-1,Yn.z*=-1),f.envMapRotation.value.setFromMatrix4(Ag.makeRotationFromEuler(Yn)),f.flipEnvMap.value=y.isCubeTexture&&y.isRenderTargetTexture===!1?-1:1,f.reflectivity.value=h.reflectivity,f.ior.value=h.ior,f.refractionRatio.value=h.refractionRatio),h.lightMap&&(f.lightMap.value=h.lightMap,f.lightMapIntensity.value=h.lightMapIntensity,t(h.lightMap,f.lightMapTransform)),h.aoMap&&(f.aoMap.value=h.aoMap,f.aoMapIntensity.value=h.aoMapIntensity,t(h.aoMap,f.aoMapTransform))}function a(f,h){f.diffuse.value.copy(h.color),f.opacity.value=h.opacity,h.map&&(f.map.value=h.map,t(h.map,f.mapTransform))}function o(f,h){f.dashSize.value=h.dashSize,f.totalSize.value=h.dashSize+h.gapSize,f.scale.value=h.scale}function l(f,h,T,y){f.diffuse.value.copy(h.color),f.opacity.value=h.opacity,f.size.value=h.size*T,f.scale.value=y*.5,h.map&&(f.map.value=h.map,t(h.map,f.uvTransform)),h.alphaMap&&(f.alphaMap.value=h.alphaMap,t(h.alphaMap,f.alphaMapTransform)),h.alphaTest>0&&(f.alphaTest.value=h.alphaTest)}function c(f,h){f.diffuse.value.copy(h.color),f.opacity.value=h.opacity,f.rotation.value=h.rotation,h.map&&(f.map.value=h.map,t(h.map,f.mapTransform)),h.alphaMap&&(f.alphaMap.value=h.alphaMap,t(h.alphaMap,f.alphaMapTransform)),h.alphaTest>0&&(f.alphaTest.value=h.alphaTest)}function u(f,h){f.specular.value.copy(h.specular),f.shininess.value=Math.max(h.shininess,1e-4)}function d(f,h){h.gradientMap&&(f.gradientMap.value=h.gradientMap)}function p(f,h){f.metalness.value=h.metalness,h.metalnessMap&&(f.metalnessMap.value=h.metalnessMap,t(h.metalnessMap,f.metalnessMapTransform)),f.roughness.value=h.roughness,h.roughnessMap&&(f.roughnessMap.value=h.roughnessMap,t(h.roughnessMap,f.roughnessMapTransform)),h.envMap&&(f.envMapIntensity.value=h.envMapIntensity)}function m(f,h,T){f.ior.value=h.ior,h.sheen>0&&(f.sheenColor.value.copy(h.sheenColor).multiplyScalar(h.sheen),f.sheenRoughness.value=h.sheenRoughness,h.sheenColorMap&&(f.sheenColorMap.value=h.sheenColorMap,t(h.sheenColorMap,f.sheenColorMapTransform)),h.sheenRoughnessMap&&(f.sheenRoughnessMap.value=h.sheenRoughnessMap,t(h.sheenRoughnessMap,f.sheenRoughnessMapTransform))),h.clearcoat>0&&(f.clearcoat.value=h.clearcoat,f.clearcoatRoughness.value=h.clearcoatRoughness,h.clearcoatMap&&(f.clearcoatMap.value=h.clearcoatMap,t(h.clearcoatMap,f.clearcoatMapTransform)),h.clearcoatRoughnessMap&&(f.clearcoatRoughnessMap.value=h.clearcoatRoughnessMap,t(h.clearcoatRoughnessMap,f.clearcoatRoughnessMapTransform)),h.clearcoatNormalMap&&(f.clearcoatNormalMap.value=h.clearcoatNormalMap,t(h.clearcoatNormalMap,f.clearcoatNormalMapTransform),f.clearcoatNormalScale.value.copy(h.clearcoatNormalScale),h.side===Lt&&f.clearcoatNormalScale.value.negate())),h.dispersion>0&&(f.dispersion.value=h.dispersion),h.iridescence>0&&(f.iridescence.value=h.iridescence,f.iridescenceIOR.value=h.iridescenceIOR,f.iridescenceThicknessMinimum.value=h.iridescenceThicknessRange[0],f.iridescenceThicknessMaximum.value=h.iridescenceThicknessRange[1],h.iridescenceMap&&(f.iridescenceMap.value=h.iridescenceMap,t(h.iridescenceMap,f.iridescenceMapTransform)),h.iridescenceThicknessMap&&(f.iridescenceThicknessMap.value=h.iridescenceThicknessMap,t(h.iridescenceThicknessMap,f.iridescenceThicknessMapTransform))),h.transmission>0&&(f.transmission.value=h.transmission,f.transmissionSamplerMap.value=T.texture,f.transmissionSamplerSize.value.set(T.width,T.height),h.transmissionMap&&(f.transmissionMap.value=h.transmissionMap,t(h.transmissionMap,f.transmissionMapTransform)),f.thickness.value=h.thickness,h.thicknessMap&&(f.thicknessMap.value=h.thicknessMap,t(h.thicknessMap,f.thicknessMapTransform)),f.attenuationDistance.value=h.attenuationDistance,f.attenuationColor.value.copy(h.attenuationColor)),h.anisotropy>0&&(f.anisotropyVector.value.set(h.anisotropy*Math.cos(h.anisotropyRotation),h.anisotropy*Math.sin(h.anisotropyRotation)),h.anisotropyMap&&(f.anisotropyMap.value=h.anisotropyMap,t(h.anisotropyMap,f.anisotropyMapTransform))),f.specularIntensity.value=h.specularIntensity,f.specularColor.value.copy(h.specularColor),h.specularColorMap&&(f.specularColorMap.value=h.specularColorMap,t(h.specularColorMap,f.specularColorMapTransform)),h.specularIntensityMap&&(f.specularIntensityMap.value=h.specularIntensityMap,t(h.specularIntensityMap,f.specularIntensityMapTransform))}function _(f,h){h.matcap&&(f.matcap.value=h.matcap)}function M(f,h){const T=e.get(h).light;f.referencePosition.value.setFromMatrixPosition(T.matrixWorld),f.nearDistance.value=T.shadow.camera.near,f.farDistance.value=T.shadow.camera.far}return{refreshFogUniforms:n,refreshMaterialUniforms:r}}function Rg(i,e,t,n){let r={},s={},a=[];const o=i.getParameter(i.MAX_UNIFORM_BUFFER_BINDINGS);function l(T,y){const b=y.program;n.uniformBlockBinding(T,b)}function c(T,y){let b=r[T.id];b===void 0&&(_(T),b=u(T),r[T.id]=b,T.addEventListener("dispose",f));const O=y.program;n.updateUBOMapping(T,O);const C=e.render.frame;s[T.id]!==C&&(p(T),s[T.id]=C)}function u(T){const y=d();T.__bindingPointIndex=y;const b=i.createBuffer(),O=T.__size,C=T.usage;return i.bindBuffer(i.UNIFORM_BUFFER,b),i.bufferData(i.UNIFORM_BUFFER,O,C),i.bindBuffer(i.UNIFORM_BUFFER,null),i.bindBufferBase(i.UNIFORM_BUFFER,y,b),b}function d(){for(let T=0;T0&&(b+=O-C),T.__size=b,T.__cache={},this}function M(T){const y={boundary:0,storage:0};return typeof T=="number"||typeof T=="boolean"?(y.boundary=4,y.storage=4):T.isVector2?(y.boundary=8,y.storage=8):T.isVector3||T.isColor?(y.boundary=16,y.storage=12):T.isVector4?(y.boundary=16,y.storage=16):T.isMatrix3?(y.boundary=48,y.storage=48):T.isMatrix4?(y.boundary=64,y.storage=64):T.isTexture?console.warn("THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group."):console.warn("THREE.WebGLRenderer: Unsupported uniform value type.",T),y}function f(T){const y=T.target;y.removeEventListener("dispose",f);const b=a.indexOf(y.__bindingPointIndex);a.splice(b,1),i.deleteBuffer(r[y.id]),delete r[y.id],delete s[y.id]}function h(){for(const T in r)i.deleteBuffer(r[T]);a=[],r={},s={}}return{bind:l,update:c,dispose:h}}class Cg{constructor(e={}){const{canvas:t=pd(),context:n=null,depth:r=!0,stencil:s=!1,alpha:a=!1,antialias:o=!1,premultipliedAlpha:l=!0,preserveDrawingBuffer:c=!1,powerPreference:u="default",failIfMajorPerformanceCaveat:d=!1}=e;this.isWebGLRenderer=!0;let p;if(n!==null){if(typeof WebGLRenderingContext<"u"&&n instanceof WebGLRenderingContext)throw new Error("THREE.WebGLRenderer: WebGL 1 is not supported since r163.");p=n.getContextAttributes().alpha}else p=a;const m=new Uint32Array(4),_=new Int32Array(4);let M=null,f=null;const h=[],T=[];this.domElement=t,this.debug={checkShaderErrors:!0,onShaderError:null},this.autoClear=!0,this.autoClearColor=!0,this.autoClearDepth=!0,this.autoClearStencil=!0,this.sortObjects=!0,this.clippingPlanes=[],this.localClippingEnabled=!1,this._outputColorSpace=Bt,this.toneMapping=Un,this.toneMappingExposure=1;const y=this;let b=!1,O=0,C=0,A=null,F=-1,te=null;const g=new it,S=new it;let V=null;const z=new Ye(0);let k=0,K=t.width,B=t.height,Q=1,G=null,le=null;const ce=new it(0,0,K,B),ve=new it(0,0,K,B);let Ge=!1;const Ze=new Ec;let W=!1,j=!1;const me=new tt,ue=new tt,Re=new N,ye=new it,Fe={background:null,fog:null,environment:null,overrideMaterial:null,isScene:!0};let je=!1;function Oe(){return A===null?Q:1}let w=n;function Ut(x,P){return t.getContext(x,P)}try{const x={alpha:!0,depth:r,stencil:s,antialias:o,premultipliedAlpha:l,preserveDrawingBuffer:c,powerPreference:u,failIfMajorPerformanceCaveat:d};if("setAttribute"in t&&t.setAttribute("data-engine",`three.js r${so}`),t.addEventListener("webglcontextlost",Y,!1),t.addEventListener("webglcontextrestored",re,!1),t.addEventListener("webglcontextcreationerror",oe,!1),w===null){const P="webgl2";if(w=Ut(P,x),w===null)throw Ut(P)?new Error("Error creating WebGL context with your selected attributes."):new Error("Error creating WebGL context.")}}catch(x){throw console.error("THREE.WebGLRenderer: "+x.message),x}let Ue,ze,Te,Je,we,E,v,L,q,Z,X,_e,ie,de,He,$,he,be,Ae,fe,Ie,Ce,$e,R;function ae(){Ue=new Ip(w),Ue.init(),Ce=new xg(w,Ue),ze=new Rp(w,Ue,e,Ce),Te=new gg(w),ze.reverseDepthBuffer&&Te.buffers.depth.setReversed(!0),Je=new Op(w),we=new tg,E=new _g(w,Ue,Te,we,ze,Ce,Je),v=new Pp(y),L=new Up(y),q=new kd(w),$e=new Ap(w,q),Z=new Np(w,q,Je,$e),X=new zp(w,Z,q,Je),Ae=new Bp(w,ze,E),$=new Cp(we),_e=new eg(y,v,L,Ue,ze,$e,$),ie=new wg(y,we),de=new ig,He=new cg(Ue),be=new bp(y,v,L,Te,X,p,l),he=new pg(y,X,ze),R=new Rg(w,Je,ze,Te),fe=new wp(w,Ue,Je),Ie=new Fp(w,Ue,Je),Je.programs=_e.programs,y.capabilities=ze,y.extensions=Ue,y.properties=we,y.renderLists=de,y.shadowMap=he,y.state=Te,y.info=Je}ae();const H=new bg(y,w);this.xr=H,this.getContext=function(){return w},this.getContextAttributes=function(){return w.getContextAttributes()},this.forceContextLoss=function(){const x=Ue.get("WEBGL_lose_context");x&&x.loseContext()},this.forceContextRestore=function(){const x=Ue.get("WEBGL_lose_context");x&&x.restoreContext()},this.getPixelRatio=function(){return Q},this.setPixelRatio=function(x){x!==void 0&&(Q=x,this.setSize(K,B,!1))},this.getSize=function(x){return x.set(K,B)},this.setSize=function(x,P,U=!0){if(H.isPresenting){console.warn("THREE.WebGLRenderer: Can't change size while VR device is presenting.");return}K=x,B=P,t.width=Math.floor(x*Q),t.height=Math.floor(P*Q),U===!0&&(t.style.width=x+"px",t.style.height=P+"px"),this.setViewport(0,0,x,P)},this.getDrawingBufferSize=function(x){return x.set(K*Q,B*Q).floor()},this.setDrawingBufferSize=function(x,P,U){K=x,B=P,Q=U,t.width=Math.floor(x*U),t.height=Math.floor(P*U),this.setViewport(0,0,x,P)},this.getCurrentViewport=function(x){return x.copy(g)},this.getViewport=function(x){return x.copy(ce)},this.setViewport=function(x,P,U,I){x.isVector4?ce.set(x.x,x.y,x.z,x.w):ce.set(x,P,U,I),Te.viewport(g.copy(ce).multiplyScalar(Q).round())},this.getScissor=function(x){return x.copy(ve)},this.setScissor=function(x,P,U,I){x.isVector4?ve.set(x.x,x.y,x.z,x.w):ve.set(x,P,U,I),Te.scissor(S.copy(ve).multiplyScalar(Q).round())},this.getScissorTest=function(){return Ge},this.setScissorTest=function(x){Te.setScissorTest(Ge=x)},this.setOpaqueSort=function(x){G=x},this.setTransparentSort=function(x){le=x},this.getClearColor=function(x){return x.copy(be.getClearColor())},this.setClearColor=function(){be.setClearColor.apply(be,arguments)},this.getClearAlpha=function(){return be.getClearAlpha()},this.setClearAlpha=function(){be.setClearAlpha.apply(be,arguments)},this.clear=function(x=!0,P=!0,U=!0){let I=0;if(x){let D=!1;if(A!==null){const ee=A.texture.format;D=ee===ho||ee===uo||ee===co}if(D){const ee=A.texture.type,se=ee===cn||ee===Nn||ee===cr||ee===Ni||ee===oo||ee===lo,pe=be.getClearColor(),ge=be.getClearAlpha(),Me=pe.r,Ee=pe.g,xe=pe.b;se?(m[0]=Me,m[1]=Ee,m[2]=xe,m[3]=ge,w.clearBufferuiv(w.COLOR,0,m)):(_[0]=Me,_[1]=Ee,_[2]=xe,_[3]=ge,w.clearBufferiv(w.COLOR,0,_))}else I|=w.COLOR_BUFFER_BIT}P&&(I|=w.DEPTH_BUFFER_BIT,w.clearDepth(this.capabilities.reverseDepthBuffer?0:1)),U&&(I|=w.STENCIL_BUFFER_BIT,this.state.buffers.stencil.setMask(4294967295)),w.clear(I)},this.clearColor=function(){this.clear(!0,!1,!1)},this.clearDepth=function(){this.clear(!1,!0,!1)},this.clearStencil=function(){this.clear(!1,!1,!0)},this.dispose=function(){t.removeEventListener("webglcontextlost",Y,!1),t.removeEventListener("webglcontextrestored",re,!1),t.removeEventListener("webglcontextcreationerror",oe,!1),de.dispose(),He.dispose(),we.dispose(),v.dispose(),L.dispose(),X.dispose(),$e.dispose(),R.dispose(),_e.dispose(),H.dispose(),H.removeEventListener("sessionstart",Io),H.removeEventListener("sessionend",No),Gn.stop()};function Y(x){x.preventDefault(),console.log("THREE.WebGLRenderer: Context Lost."),b=!0}function re(){console.log("THREE.WebGLRenderer: Context Restored."),b=!1;const x=Je.autoReset,P=he.enabled,U=he.autoUpdate,I=he.needsUpdate,D=he.type;ae(),Je.autoReset=x,he.enabled=P,he.autoUpdate=U,he.needsUpdate=I,he.type=D}function oe(x){console.error("THREE.WebGLRenderer: A WebGL context could not be created. Reason: ",x.statusMessage)}function Be(x){const P=x.target;P.removeEventListener("dispose",Be),st(P)}function st(x){wt(x),we.remove(x)}function wt(x){const P=we.get(x).programs;P!==void 0&&(P.forEach(function(U){_e.releaseProgram(U)}),x.isShaderMaterial&&_e.releaseShaderCache(x))}this.renderBufferDirect=function(x,P,U,I,D,ee){P===null&&(P=Fe);const se=D.isMesh&&D.matrixWorld.determinant()<0,pe=nu(x,P,U,I,D);Te.setMaterial(I,se);let ge=U.index,Me=1;if(I.wireframe===!0){if(ge=Z.getWireframeAttribute(U),ge===void 0)return;Me=2}const Ee=U.drawRange,xe=U.attributes.position;let Ke=Ee.start*Me,Qe=(Ee.start+Ee.count)*Me;ee!==null&&(Ke=Math.max(Ke,ee.start*Me),Qe=Math.min(Qe,(ee.start+ee.count)*Me)),ge!==null?(Ke=Math.max(Ke,0),Qe=Math.min(Qe,ge.count)):xe!=null&&(Ke=Math.max(Ke,0),Qe=Math.min(Qe,xe.count));const nt=Qe-Ke;if(nt<0||nt===1/0)return;$e.setup(D,I,pe,U,ge);let It,We=fe;if(ge!==null&&(It=q.get(ge),We=Ie,We.setIndex(It)),D.isMesh)I.wireframe===!0?(Te.setLineWidth(I.wireframeLinewidth*Oe()),We.setMode(w.LINES)):We.setMode(w.TRIANGLES);else if(D.isLine){let Se=I.linewidth;Se===void 0&&(Se=1),Te.setLineWidth(Se*Oe()),D.isLineSegments?We.setMode(w.LINES):D.isLineLoop?We.setMode(w.LINE_LOOP):We.setMode(w.LINE_STRIP)}else D.isPoints?We.setMode(w.POINTS):D.isSprite&&We.setMode(w.TRIANGLES);if(D.isBatchedMesh)if(D._multiDrawInstances!==null)We.renderMultiDrawInstances(D._multiDrawStarts,D._multiDrawCounts,D._multiDrawCount,D._multiDrawInstances);else if(Ue.get("WEBGL_multi_draw"))We.renderMultiDraw(D._multiDrawStarts,D._multiDrawCounts,D._multiDrawCount);else{const Se=D._multiDrawStarts,gt=D._multiDrawCounts,Xe=D._multiDrawCount,Zt=ge?q.get(ge).bytesPerElement:1,ui=we.get(I).currentProgram.getUniforms();for(let Nt=0;Nt{function ee(){if(I.forEach(function(se){we.get(se).currentProgram.isReady()&&I.delete(se)}),I.size===0){D(x);return}setTimeout(ee,10)}Ue.get("KHR_parallel_shader_compile")!==null?ee():setTimeout(ee,10)})};let Rt=null;function dn(x){Rt&&Rt(x)}function Io(){Gn.stop()}function No(){Gn.start()}const Gn=new Tc;Gn.setAnimationLoop(dn),typeof self<"u"&&Gn.setContext(self),this.setAnimationLoop=function(x){Rt=x,H.setAnimationLoop(x),x===null?Gn.stop():Gn.start()},H.addEventListener("sessionstart",Io),H.addEventListener("sessionend",No),this.render=function(x,P){if(P!==void 0&&P.isCamera!==!0){console.error("THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.");return}if(b===!0)return;if(x.matrixWorldAutoUpdate===!0&&x.updateMatrixWorld(),P.parent===null&&P.matrixWorldAutoUpdate===!0&&P.updateMatrixWorld(),H.enabled===!0&&H.isPresenting===!0&&(H.cameraAutoUpdate===!0&&H.updateCamera(P),P=H.getCamera()),x.isScene===!0&&x.onBeforeRender(y,x,P,A),f=He.get(x,T.length),f.init(P),T.push(f),ue.multiplyMatrices(P.projectionMatrix,P.matrixWorldInverse),Ze.setFromProjectionMatrix(ue),j=this.localClippingEnabled,W=$.init(this.clippingPlanes,j),M=de.get(x,h.length),M.init(),h.push(M),H.enabled===!0&&H.isPresenting===!0){const ee=y.xr.getDepthSensingMesh();ee!==null&&Cs(ee,P,-1/0,y.sortObjects)}Cs(x,P,0,y.sortObjects),M.finish(),y.sortObjects===!0&&M.sort(G,le),je=H.enabled===!1||H.isPresenting===!1||H.hasDepthSensing()===!1,je&&be.addToRenderList(M,x),this.info.render.frame++,W===!0&&$.beginShadows();const U=f.state.shadowsArray;he.render(U,x,P),W===!0&&$.endShadows(),this.info.autoReset===!0&&this.info.reset();const I=M.opaque,D=M.transmissive;if(f.setupLights(),P.isArrayCamera){const ee=P.cameras;if(D.length>0)for(let se=0,pe=ee.length;se0&&Oo(I,D,x,P),je&&be.render(x),Fo(M,x,P);A!==null&&(E.updateMultisampleRenderTarget(A),E.updateRenderTargetMipmap(A)),x.isScene===!0&&x.onAfterRender(y,x,P),$e.resetDefaultState(),F=-1,te=null,T.pop(),T.length>0?(f=T[T.length-1],W===!0&&$.setGlobalState(y.clippingPlanes,f.state.camera)):f=null,h.pop(),h.length>0?M=h[h.length-1]:M=null};function Cs(x,P,U,I){if(x.visible===!1)return;if(x.layers.test(P.layers)){if(x.isGroup)U=x.renderOrder;else if(x.isLOD)x.autoUpdate===!0&&x.update(P);else if(x.isLight)f.pushLight(x),x.castShadow&&f.pushShadow(x);else if(x.isSprite){if(!x.frustumCulled||Ze.intersectsSprite(x)){I&&ye.setFromMatrixPosition(x.matrixWorld).applyMatrix4(ue);const se=X.update(x),pe=x.material;pe.visible&&M.push(x,se,pe,U,ye.z,null)}}else if((x.isMesh||x.isLine||x.isPoints)&&(!x.frustumCulled||Ze.intersectsObject(x))){const se=X.update(x),pe=x.material;if(I&&(x.boundingSphere!==void 0?(x.boundingSphere===null&&x.computeBoundingSphere(),ye.copy(x.boundingSphere.center)):(se.boundingSphere===null&&se.computeBoundingSphere(),ye.copy(se.boundingSphere.center)),ye.applyMatrix4(x.matrixWorld).applyMatrix4(ue)),Array.isArray(pe)){const ge=se.groups;for(let Me=0,Ee=ge.length;Me0&&Tr(D,P,U),ee.length>0&&Tr(ee,P,U),se.length>0&&Tr(se,P,U),Te.buffers.depth.setTest(!0),Te.buffers.depth.setMask(!0),Te.buffers.color.setMask(!0),Te.setPolygonOffset(!1)}function Oo(x,P,U,I){if((U.isScene===!0?U.overrideMaterial:null)!==null)return;f.state.transmissionRenderTarget[I.id]===void 0&&(f.state.transmissionRenderTarget[I.id]=new nn(1,1,{generateMipmaps:!0,type:Ue.has("EXT_color_buffer_half_float")||Ue.has("EXT_color_buffer_float")?Bn:cn,minFilter:Qn,samples:4,stencilBuffer:s,resolveDepthBuffer:!1,resolveStencilBuffer:!1,colorSpace:qe.workingColorSpace}));const ee=f.state.transmissionRenderTarget[I.id],se=I.viewport||g;ee.setSize(se.z,se.w);const pe=y.getRenderTarget();y.setRenderTarget(ee),y.getClearColor(z),k=y.getClearAlpha(),k<1&&y.setClearColor(16777215,.5),y.clear(),je&&be.render(U);const ge=y.toneMapping;y.toneMapping=Un;const Me=I.viewport;if(I.viewport!==void 0&&(I.viewport=void 0),f.setupLightsView(I),W===!0&&$.setGlobalState(y.clippingPlanes,I),Tr(x,U,I),E.updateMultisampleRenderTarget(ee),E.updateRenderTargetMipmap(ee),Ue.has("WEBGL_multisampled_render_to_texture")===!1){let Ee=!1;for(let xe=0,Ke=P.length;xe0),xe=!!U.morphAttributes.position,Ke=!!U.morphAttributes.normal,Qe=!!U.morphAttributes.color;let nt=Un;I.toneMapped&&(A===null||A.isXRRenderTarget===!0)&&(nt=y.toneMapping);const It=U.morphAttributes.position||U.morphAttributes.normal||U.morphAttributes.color,We=It!==void 0?It.length:0,Se=we.get(I),gt=f.state.lights;if(W===!0&&(j===!0||x!==te)){const Vt=x===te&&I.id===F;$.setState(I,x,Vt)}let Xe=!1;I.version===Se.__version?(Se.needsLights&&Se.lightsStateVersion!==gt.state.version||Se.outputColorSpace!==pe||D.isBatchedMesh&&Se.batching===!1||!D.isBatchedMesh&&Se.batching===!0||D.isBatchedMesh&&Se.batchingColor===!0&&D.colorTexture===null||D.isBatchedMesh&&Se.batchingColor===!1&&D.colorTexture!==null||D.isInstancedMesh&&Se.instancing===!1||!D.isInstancedMesh&&Se.instancing===!0||D.isSkinnedMesh&&Se.skinning===!1||!D.isSkinnedMesh&&Se.skinning===!0||D.isInstancedMesh&&Se.instancingColor===!0&&D.instanceColor===null||D.isInstancedMesh&&Se.instancingColor===!1&&D.instanceColor!==null||D.isInstancedMesh&&Se.instancingMorph===!0&&D.morphTexture===null||D.isInstancedMesh&&Se.instancingMorph===!1&&D.morphTexture!==null||Se.envMap!==ge||I.fog===!0&&Se.fog!==ee||Se.numClippingPlanes!==void 0&&(Se.numClippingPlanes!==$.numPlanes||Se.numIntersection!==$.numIntersection)||Se.vertexAlphas!==Me||Se.vertexTangents!==Ee||Se.morphTargets!==xe||Se.morphNormals!==Ke||Se.morphColors!==Qe||Se.toneMapping!==nt||Se.morphTargetsCount!==We)&&(Xe=!0):(Xe=!0,Se.__version=I.version);let Zt=Se.currentProgram;Xe===!0&&(Zt=br(I,P,D));let ui=!1,Nt=!1,Ps=!1;const rt=Zt.getUniforms(),Tn=Se.uniforms;if(Te.useProgram(Zt.program)&&(ui=!0,Nt=!0,Ps=!0),I.id!==F&&(F=I.id,Nt=!0),ui||te!==x){ze.reverseDepthBuffer?(me.copy(x.projectionMatrix),gd(me),vd(me),rt.setValue(w,"projectionMatrix",me)):rt.setValue(w,"projectionMatrix",x.projectionMatrix),rt.setValue(w,"viewMatrix",x.matrixWorldInverse);const Vt=rt.map.cameraPosition;Vt!==void 0&&Vt.setValue(w,Re.setFromMatrixPosition(x.matrixWorld)),ze.logarithmicDepthBuffer&&rt.setValue(w,"logDepthBufFC",2/(Math.log(x.far+1)/Math.LN2)),(I.isMeshPhongMaterial||I.isMeshToonMaterial||I.isMeshLambertMaterial||I.isMeshBasicMaterial||I.isMeshStandardMaterial||I.isShaderMaterial)&&rt.setValue(w,"isOrthographic",x.isOrthographicCamera===!0),te!==x&&(te=x,Nt=!0,Ps=!0)}if(D.isSkinnedMesh){rt.setOptional(w,D,"bindMatrix"),rt.setOptional(w,D,"bindMatrixInverse");const Vt=D.skeleton;Vt&&(Vt.boneTexture===null&&Vt.computeBoneTexture(),rt.setValue(w,"boneTexture",Vt.boneTexture,E))}D.isBatchedMesh&&(rt.setOptional(w,D,"batchingTexture"),rt.setValue(w,"batchingTexture",D._matricesTexture,E),rt.setOptional(w,D,"batchingIdTexture"),rt.setValue(w,"batchingIdTexture",D._indirectTexture,E),rt.setOptional(w,D,"batchingColorTexture"),D._colorsTexture!==null&&rt.setValue(w,"batchingColorTexture",D._colorsTexture,E));const Ds=U.morphAttributes;if((Ds.position!==void 0||Ds.normal!==void 0||Ds.color!==void 0)&&Ae.update(D,U,Zt),(Nt||Se.receiveShadow!==D.receiveShadow)&&(Se.receiveShadow=D.receiveShadow,rt.setValue(w,"receiveShadow",D.receiveShadow)),I.isMeshGouraudMaterial&&I.envMap!==null&&(Tn.envMap.value=ge,Tn.flipEnvMap.value=ge.isCubeTexture&&ge.isRenderTargetTexture===!1?-1:1),I.isMeshStandardMaterial&&I.envMap===null&&P.environment!==null&&(Tn.envMapIntensity.value=P.environmentIntensity),Nt&&(rt.setValue(w,"toneMappingExposure",y.toneMappingExposure),Se.needsLights&&iu(Tn,Ps),ee&&I.fog===!0&&ie.refreshFogUniforms(Tn,ee),ie.refreshMaterialUniforms(Tn,I,Q,B,f.state.transmissionRenderTarget[x.id]),es.upload(w,zo(Se),Tn,E)),I.isShaderMaterial&&I.uniformsNeedUpdate===!0&&(es.upload(w,zo(Se),Tn,E),I.uniformsNeedUpdate=!1),I.isSpriteMaterial&&rt.setValue(w,"center",D.center),rt.setValue(w,"modelViewMatrix",D.modelViewMatrix),rt.setValue(w,"normalMatrix",D.normalMatrix),rt.setValue(w,"modelMatrix",D.matrixWorld),I.isShaderMaterial||I.isRawShaderMaterial){const Vt=I.uniformsGroups;for(let Ls=0,su=Vt.length;Ls0&&E.useMultisampledRTT(x)===!1?D=we.get(x).__webglMultisampledFramebuffer:Array.isArray(Ee)?D=Ee[U]:D=Ee,g.copy(x.viewport),S.copy(x.scissor),V=x.scissorTest}else g.copy(ce).multiplyScalar(Q).floor(),S.copy(ve).multiplyScalar(Q).floor(),V=Ge;if(Te.bindFramebuffer(w.FRAMEBUFFER,D)&&I&&Te.drawBuffers(x,D),Te.viewport(g),Te.scissor(S),Te.setScissorTest(V),ee){const ge=we.get(x.texture);w.framebufferTexture2D(w.FRAMEBUFFER,w.COLOR_ATTACHMENT0,w.TEXTURE_CUBE_MAP_POSITIVE_X+P,ge.__webglTexture,U)}else if(se){const ge=we.get(x.texture),Me=P||0;w.framebufferTextureLayer(w.FRAMEBUFFER,w.COLOR_ATTACHMENT0,ge.__webglTexture,U||0,Me)}F=-1},this.readRenderTargetPixels=function(x,P,U,I,D,ee,se){if(!(x&&x.isWebGLRenderTarget)){console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");return}let pe=we.get(x).__webglFramebuffer;if(x.isWebGLCubeRenderTarget&&se!==void 0&&(pe=pe[se]),pe){Te.bindFramebuffer(w.FRAMEBUFFER,pe);try{const ge=x.texture,Me=ge.format,Ee=ge.type;if(!ze.textureFormatReadable(Me)){console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");return}if(!ze.textureTypeReadable(Ee)){console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");return}P>=0&&P<=x.width-I&&U>=0&&U<=x.height-D&&w.readPixels(P,U,I,D,Ce.convert(Me),Ce.convert(Ee),ee)}finally{const ge=A!==null?we.get(A).__webglFramebuffer:null;Te.bindFramebuffer(w.FRAMEBUFFER,ge)}}},this.readRenderTargetPixelsAsync=async function(x,P,U,I,D,ee,se){if(!(x&&x.isWebGLRenderTarget))throw new Error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let pe=we.get(x).__webglFramebuffer;if(x.isWebGLCubeRenderTarget&&se!==void 0&&(pe=pe[se]),pe){const ge=x.texture,Me=ge.format,Ee=ge.type;if(!ze.textureFormatReadable(Me))throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in RGBA or implementation defined format.");if(!ze.textureTypeReadable(Ee))throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in UnsignedByteType or implementation defined type.");if(P>=0&&P<=x.width-I&&U>=0&&U<=x.height-D){Te.bindFramebuffer(w.FRAMEBUFFER,pe);const xe=w.createBuffer();w.bindBuffer(w.PIXEL_PACK_BUFFER,xe),w.bufferData(w.PIXEL_PACK_BUFFER,ee.byteLength,w.STREAM_READ),w.readPixels(P,U,I,D,Ce.convert(Me),Ce.convert(Ee),0);const Ke=A!==null?we.get(A).__webglFramebuffer:null;Te.bindFramebuffer(w.FRAMEBUFFER,Ke);const Qe=w.fenceSync(w.SYNC_GPU_COMMANDS_COMPLETE,0);return w.flush(),await md(w,Qe,4),w.bindBuffer(w.PIXEL_PACK_BUFFER,xe),w.getBufferSubData(w.PIXEL_PACK_BUFFER,0,ee),w.deleteBuffer(xe),w.deleteSync(Qe),ee}else throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: requested read bounds are out of range.")}},this.copyFramebufferToTexture=function(x,P=null,U=0){x.isTexture!==!0&&(Qr("WebGLRenderer: copyFramebufferToTexture function signature has changed."),P=arguments[0]||null,x=arguments[1]);const I=Math.pow(2,-U),D=Math.floor(x.image.width*I),ee=Math.floor(x.image.height*I),se=P!==null?P.x:0,pe=P!==null?P.y:0;E.setTexture2D(x,0),w.copyTexSubImage2D(w.TEXTURE_2D,U,0,0,se,pe,D,ee),Te.unbindTexture()},this.copyTextureToTexture=function(x,P,U=null,I=null,D=0){x.isTexture!==!0&&(Qr("WebGLRenderer: copyTextureToTexture function signature has changed."),I=arguments[0]||null,x=arguments[1],P=arguments[2],D=arguments[3]||0,U=null);let ee,se,pe,ge,Me,Ee;U!==null?(ee=U.max.x-U.min.x,se=U.max.y-U.min.y,pe=U.min.x,ge=U.min.y):(ee=x.image.width,se=x.image.height,pe=0,ge=0),I!==null?(Me=I.x,Ee=I.y):(Me=0,Ee=0);const xe=Ce.convert(P.format),Ke=Ce.convert(P.type);E.setTexture2D(P,0),w.pixelStorei(w.UNPACK_FLIP_Y_WEBGL,P.flipY),w.pixelStorei(w.UNPACK_PREMULTIPLY_ALPHA_WEBGL,P.premultiplyAlpha),w.pixelStorei(w.UNPACK_ALIGNMENT,P.unpackAlignment);const Qe=w.getParameter(w.UNPACK_ROW_LENGTH),nt=w.getParameter(w.UNPACK_IMAGE_HEIGHT),It=w.getParameter(w.UNPACK_SKIP_PIXELS),We=w.getParameter(w.UNPACK_SKIP_ROWS),Se=w.getParameter(w.UNPACK_SKIP_IMAGES),gt=x.isCompressedTexture?x.mipmaps[D]:x.image;w.pixelStorei(w.UNPACK_ROW_LENGTH,gt.width),w.pixelStorei(w.UNPACK_IMAGE_HEIGHT,gt.height),w.pixelStorei(w.UNPACK_SKIP_PIXELS,pe),w.pixelStorei(w.UNPACK_SKIP_ROWS,ge),x.isDataTexture?w.texSubImage2D(w.TEXTURE_2D,D,Me,Ee,ee,se,xe,Ke,gt.data):x.isCompressedTexture?w.compressedTexSubImage2D(w.TEXTURE_2D,D,Me,Ee,gt.width,gt.height,xe,gt.data):w.texSubImage2D(w.TEXTURE_2D,D,Me,Ee,ee,se,xe,Ke,gt),w.pixelStorei(w.UNPACK_ROW_LENGTH,Qe),w.pixelStorei(w.UNPACK_IMAGE_HEIGHT,nt),w.pixelStorei(w.UNPACK_SKIP_PIXELS,It),w.pixelStorei(w.UNPACK_SKIP_ROWS,We),w.pixelStorei(w.UNPACK_SKIP_IMAGES,Se),D===0&&P.generateMipmaps&&w.generateMipmap(w.TEXTURE_2D),Te.unbindTexture()},this.copyTextureToTexture3D=function(x,P,U=null,I=null,D=0){x.isTexture!==!0&&(Qr("WebGLRenderer: copyTextureToTexture3D function signature has changed."),U=arguments[0]||null,I=arguments[1]||null,x=arguments[2],P=arguments[3],D=arguments[4]||0);let ee,se,pe,ge,Me,Ee,xe,Ke,Qe;const nt=x.isCompressedTexture?x.mipmaps[D]:x.image;U!==null?(ee=U.max.x-U.min.x,se=U.max.y-U.min.y,pe=U.max.z-U.min.z,ge=U.min.x,Me=U.min.y,Ee=U.min.z):(ee=nt.width,se=nt.height,pe=nt.depth,ge=0,Me=0,Ee=0),I!==null?(xe=I.x,Ke=I.y,Qe=I.z):(xe=0,Ke=0,Qe=0);const It=Ce.convert(P.format),We=Ce.convert(P.type);let Se;if(P.isData3DTexture)E.setTexture3D(P,0),Se=w.TEXTURE_3D;else if(P.isDataArrayTexture||P.isCompressedArrayTexture)E.setTexture2DArray(P,0),Se=w.TEXTURE_2D_ARRAY;else{console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.");return}w.pixelStorei(w.UNPACK_FLIP_Y_WEBGL,P.flipY),w.pixelStorei(w.UNPACK_PREMULTIPLY_ALPHA_WEBGL,P.premultiplyAlpha),w.pixelStorei(w.UNPACK_ALIGNMENT,P.unpackAlignment);const gt=w.getParameter(w.UNPACK_ROW_LENGTH),Xe=w.getParameter(w.UNPACK_IMAGE_HEIGHT),Zt=w.getParameter(w.UNPACK_SKIP_PIXELS),ui=w.getParameter(w.UNPACK_SKIP_ROWS),Nt=w.getParameter(w.UNPACK_SKIP_IMAGES);w.pixelStorei(w.UNPACK_ROW_LENGTH,nt.width),w.pixelStorei(w.UNPACK_IMAGE_HEIGHT,nt.height),w.pixelStorei(w.UNPACK_SKIP_PIXELS,ge),w.pixelStorei(w.UNPACK_SKIP_ROWS,Me),w.pixelStorei(w.UNPACK_SKIP_IMAGES,Ee),x.isDataTexture||x.isData3DTexture?w.texSubImage3D(Se,D,xe,Ke,Qe,ee,se,pe,It,We,nt.data):P.isCompressedArrayTexture?w.compressedTexSubImage3D(Se,D,xe,Ke,Qe,ee,se,pe,It,nt.data):w.texSubImage3D(Se,D,xe,Ke,Qe,ee,se,pe,It,We,nt),w.pixelStorei(w.UNPACK_ROW_LENGTH,gt),w.pixelStorei(w.UNPACK_IMAGE_HEIGHT,Xe),w.pixelStorei(w.UNPACK_SKIP_PIXELS,Zt),w.pixelStorei(w.UNPACK_SKIP_ROWS,ui),w.pixelStorei(w.UNPACK_SKIP_IMAGES,Nt),D===0&&P.generateMipmaps&&w.generateMipmap(Se),Te.unbindTexture()},this.initRenderTarget=function(x){we.get(x).__webglFramebuffer===void 0&&E.setupRenderTarget(x)},this.initTexture=function(x){x.isCubeTexture?E.setTextureCube(x,0):x.isData3DTexture?E.setTexture3D(x,0):x.isDataArrayTexture||x.isCompressedArrayTexture?E.setTexture2DArray(x,0):E.setTexture2D(x,0),Te.unbindTexture()},this.resetState=function(){O=0,C=0,A=null,Te.reset(),$e.reset()},typeof __THREE_DEVTOOLS__<"u"&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}get coordinateSystem(){return yn}get outputColorSpace(){return this._outputColorSpace}set outputColorSpace(e){this._outputColorSpace=e;const t=this.getContext();t.drawingBufferColorSpace=e===fo?"display-p3":"srgb",t.unpackColorSpace=qe.workingColorSpace===xs?"display-p3":"srgb"}}class Xi extends Ht{constructor(){super(),this.isScene=!0,this.type="Scene",this.background=null,this.environment=null,this.fog=null,this.backgroundBlurriness=0,this.backgroundIntensity=1,this.backgroundRotation=new En,this.environmentIntensity=1,this.environmentRotation=new En,this.overrideMaterial=null,typeof __THREE_DEVTOOLS__<"u"&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}copy(e,t){return super.copy(e,t),e.background!==null&&(this.background=e.background.clone()),e.environment!==null&&(this.environment=e.environment.clone()),e.fog!==null&&(this.fog=e.fog.clone()),this.backgroundBlurriness=e.backgroundBlurriness,this.backgroundIntensity=e.backgroundIntensity,this.backgroundRotation.copy(e.backgroundRotation),this.environmentIntensity=e.environmentIntensity,this.environmentRotation.copy(e.environmentRotation),e.overrideMaterial!==null&&(this.overrideMaterial=e.overrideMaterial.clone()),this.matrixAutoUpdate=e.matrixAutoUpdate,this}toJSON(e){const t=super.toJSON(e);return this.fog!==null&&(t.object.fog=this.fog.toJSON()),this.backgroundBlurriness>0&&(t.object.backgroundBlurriness=this.backgroundBlurriness),this.backgroundIntensity!==1&&(t.object.backgroundIntensity=this.backgroundIntensity),t.object.backgroundRotation=this.backgroundRotation.toArray(),this.environmentIntensity!==1&&(t.object.environmentIntensity=this.environmentIntensity),t.object.environmentRotation=this.environmentRotation.toArray(),t}}class ts extends vt{constructor(e=null,t=1,n=1,r,s,a,o,l,c=ot,u=ot,d,p){super(null,a,o,l,c,u,r,s,d,p),this.isDataTexture=!0,this.image={data:e,width:t,height:n},this.generateMipmaps=!1,this.flipY=!1,this.unpackAlignment=1}}class Pg extends vt{constructor(e,t,n,r,s,a,o,l,c){super(e,t,n,r,s,a,o,l,c),this.isVideoTexture=!0,this.minFilter=a!==void 0?a:ut,this.magFilter=s!==void 0?s:ut,this.generateMipmaps=!1;const u=this;function d(){u.needsUpdate=!0,e.requestVideoFrameCallback(d)}"requestVideoFrameCallback"in e&&e.requestVideoFrameCallback(d)}clone(){return new this.constructor(this.image).copy(this)}update(){const e=this.image;"requestVideoFrameCallback"in e===!1&&e.readyState>=e.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}}typeof __THREE_DEVTOOLS__<"u"&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("register",{detail:{revision:so}}));typeof window<"u"&&(window.__THREE__?console.warn("WARNING: Multiple instances of Three.js being imported."):window.__THREE__=so);const _o=`uniform sampler2D uSceneTexture,uSceneDepth; -uniform sampler2D uProtectionDepthMap; -uniform mat4 uContentViewProjection,uContentInverseViewProjection; -uniform mat4 uPetWorldToLocal; -uniform vec3 uContentCameraPosition,uLightPosition,uBackgroundColor; -uniform float uGlassZ,uSourceZ,uGridSize,uStrength,uMosaicStyle,uCurvature,uGlossStrength; -uniform vec2 uViewOffset,uPetSize,uPaneSize; -uniform vec2 uDepthEvidenceRange,uDepthCorrection; -uniform float uEnvironmentStrength; -uniform float uTransmissionDetail; -uniform float uCellLensScale; -uniform vec4 uPaneRect; -uniform sampler2D uRegionPalette; -uniform sampler2D uRegionAtlas,uRegionHistory; -uniform vec2 uRegionAtlasSize,uRegionGridSize,uRegionPaletteSize; -uniform float uRegionStrength,uRegionAvailable; -varying vec2 vUv; -vec2 projectUv(vec3 p){vec4 c=uContentViewProjection*vec4(p,1.);float w=abs(c.w)<.0001?(c.w<0.?-.0001:.0001):c.w;return c.xy/w*.5+.5;} -vec4 sampleScene(vec2 uv){return texture2D(uSceneTexture,clamp(uv,0.,1.));} -vec4 samplePane(vec2 pane){return sampleScene(projectUv(vec3((pane-.5)*uPaneSize,uGlassZ)));} -float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);} -vec2 hash2(vec2 p){return vec2(hash(p),hash(p+vec2(19.19,73.73)));} -vec2 cellBlurStep(vec2 cell,vec2 cellSize,float style){ - if(style<=.5)return cellSize*mix(.006,.018,hash(cell+vec2(5.))); - return cellSize*mix(.006,.012,hash(cell+vec2(5.))); -} -vec4 sampleCell(vec2 pane,vec2 sourceUv,float strength,vec2 cell,vec2 cellSize,float style){ - vec2 center=mix(pane,sourceUv,strength); - vec2 blurOffset=strength*cellBlurStep(cell,cellSize,style); - vec4 color; - if(style<=.5){ - color=samplePane(center)*.6; - color+=samplePane(center+vec2(blurOffset.x,0.))*.1; - color+=samplePane(center-vec2(blurOffset.x,0.))*.1; - color+=samplePane(center+vec2(0.,blurOffset.y))*.1; - color+=samplePane(center-vec2(0.,blurOffset.y))*.1; - }else{ - color=samplePane(center)*.4; - color+=samplePane(center+vec2(blurOffset.x,0.))*.15; - color+=samplePane(center-vec2(blurOffset.x,0.))*.15; - color+=samplePane(center+vec2(0.,blurOffset.y))*.15; - color+=samplePane(center-vec2(0.,blurOffset.y))*.15; - } - return color; -} -float safeZ(float z){return abs(z)<.0001?(z<0.?-.0001:.0001):z;} -vec3 bend(vec3 i,vec3 n){vec3 r=refract(i,n,.75);return length(r)<.0001?i:r;} -float softLimit(float value,float limit){return value*limit/(limit+abs(value));} -float surfaceCurvature(){float curvature=clamp(uCurvature,-1.,1.),excess=max(curvature-.65,0.);return curvature-(.25/.35)*excess*excess;} -float signedCurvatureScale(){return clamp(surfaceCurvature()/.65,-1.25,1.25);} -float regionDistance(vec3 a,vec3 b){vec3 d=a-b;float y=dot(d,vec3(.299,.587,.114));return dot(d,d)+.35*y*y;} -float regionLuminance(vec3 c){return dot(c,vec3(.299,.587,.114));} -vec3 regionColor(vec2 cell,float index){vec2 uv=(vec2(cell.x*5.+index,cell.y)+.5)/uRegionPaletteSize;return texture2D(uRegionPalette,uv).rgb;} -float nearestRegion(vec3 color,vec2 cell){float best=0.,distance=regionDistance(color,regionColor(cell,0.));for(int i=1;i<4;i++){float candidate=regionDistance(color,regionColor(cell,float(i)));if(candidate1.||sceneUv.y<0.||sceneUv.y>1.)return false; - float depth=texture2D(uSceneDepth,sceneUv).x; - if(depth>=.999999)return false; - vec4 clip=vec4(sceneUv*2.-1.,depth*2.-1.,1.); - vec4 world=uContentInverseViewProjection*clip; - if(abs(world.w)<.0001)return false; - worldPoint=world.xyz/world.w; - return true; -} -float regionSurfaceValid(vec2 sceneUv,vec3 glassHit){ - vec3 worldPoint; - if(!reconstructScenePoint(sceneUv,worldPoint))return 0.; - float axialGap=glassHit.z-worldPoint.z; - if(axialGap<=.0001)return 0.; - return 1.; -} -float regionProtectionWeight(vec2 sceneUv){ - vec3 worldPoint; - if(!reconstructScenePoint(sceneUv,worldPoint))return 0.; - vec3 localPoint=(uPetWorldToLocal*vec4(worldPoint,1.)).xyz; - if(localPoint.x<-.5||localPoint.x>.5||localPoint.y<-.5||localPoint.y>.5)return 0.; - vec2 sourceUv=localPoint.xy+.5; - float sourceDepth=texture2D(uProtectionDepthMap,sourceUv).r; - if(uDepthEvidenceRange.y-uDepthEvidenceRange.x<.0001)return 0.; - return smoothstep(uDepthEvidenceRange.x,uDepthEvidenceRange.y,sourceDepth); -} -// Screen-depth refinement of an artistic ray. Occluded surfaces are unavailable; -// retain the original sample if the visible-depth solve cannot converge. -vec3 refineSceneHit(vec3 glassHit,vec3 ray,vec3 artisticHit,float cellWorld){ - vec3 planeHit=glassHit+ray*((uSourceZ-glassHit.z)/safeZ(ray.z)); - vec3 origin=glassHit+vec3(artisticHit.xy-planeHit.xy,0.); - vec3 hit=artisticHit,surface; - for(int iteration=0;iteration<3;iteration++){ - if(!reconstructScenePoint(projectUv(hit),surface))return artisticHit; - vec3 localPoint=(uPetWorldToLocal*vec4(surface,1.)).xyz; - if(any(greaterThan(abs(localPoint.xy),vec2(.5)))||surface.z>=uGlassZ-.0001)return artisticHit; - hit=origin+ray*((surface.z-origin.z)/safeZ(ray.z)); - } - if(!reconstructScenePoint(projectUv(hit),surface))return artisticHit; - if(surface.z>=uGlassZ-.0001)return artisticHit; - float confidence=1.-smoothstep(cellWorld*.05,cellWorld*.25,abs(hit.z-surface.z)); - // Compare at the same reference Z, so only the projected sampling position changes. - vec3 viewRay=hit-uContentCameraPosition; - vec3 projected=uContentCameraPosition+viewRay*((uSourceZ-uContentCameraPosition.z)/safeZ(viewRay.z)); - vec2 delta=projected.xy-artisticHit.xy; - float limit=cellWorld*uDepthCorrection.y; - delta*=min(1.,limit/max(length(delta),.00001)); - return artisticHit+vec3(delta*uDepthCorrection.x*confidence,0.); -} -#ifdef REGION_ATLAS -float regionAtlasEvidence(vec2 sceneUv,vec3 color,vec3 glassHit){ - if(regionSurfaceValid(sceneUv,glassHit)<=0.)return 0.; - return regionProtectionWeight(sceneUv)*(1.-smoothstep(.10,.20,regionLuminance(color))); -} -vec4 regionAtlasProbe(vec3 sceneHit,vec2 worldOffset,vec3 glassHit){ - vec2 probeSceneUv=projectUv(sceneHit+vec3(worldOffset,0.)); - vec4 probe=sampleScene(probeSceneUv); - return vec4(probe.rgb,regionAtlasEvidence(probeSceneUv,probe.rgb,glassHit)); -} -vec4 regionAtlasScore(vec3 centerColor,float centerEvidence,vec3 probeColor,float probeEvidence){ - float evidenceGain=probeEvidence-centerEvidence,darkGain=regionLuminance(centerColor)-regionLuminance(probeColor),blend=0.; - if(probeEvidence>.05&&evidenceGain>.02&&darkGain>.015)blend=min(.4,evidenceGain*2.)*min(1.,max(0.,darkGain*4.)); - return vec4(blend,probeEvidence,0.,0.); -} -vec3 regionAtlasRepresentative(vec3 centerColor,float centerEvidence,vec3 sceneHit,vec3 glassHit,out float evidence){ - vec3 bestColor=centerColor;float bestEvidence=centerEvidence,bestBlend=0.; - vec2 probeStep=uPaneSize/(uRegionGridSize*8.)*.25; - vec4 probe,score; - probe=regionAtlasProbe(sceneHit,vec2(probeStep.x,0.),glassHit);score=regionAtlasScore(centerColor,centerEvidence,probe.rgb,probe.a);if(score.x>bestBlend){bestColor=mix(centerColor,probe.rgb,score.x);bestEvidence=max(centerEvidence,probe.a);bestBlend=score.x;} - probe=regionAtlasProbe(sceneHit,vec2(-probeStep.x,0.),glassHit);score=regionAtlasScore(centerColor,centerEvidence,probe.rgb,probe.a);if(score.x>bestBlend){bestColor=mix(centerColor,probe.rgb,score.x);bestEvidence=max(centerEvidence,probe.a);bestBlend=score.x;} - probe=regionAtlasProbe(sceneHit,vec2(0.,probeStep.y),glassHit);score=regionAtlasScore(centerColor,centerEvidence,probe.rgb,probe.a);if(score.x>bestBlend){bestColor=mix(centerColor,probe.rgb,score.x);bestEvidence=max(centerEvidence,probe.a);bestBlend=score.x;} - probe=regionAtlasProbe(sceneHit,vec2(0.,-probeStep.y),glassHit);score=regionAtlasScore(centerColor,centerEvidence,probe.rgb,probe.a);if(score.x>bestBlend){bestColor=mix(centerColor,probe.rgb,score.x);bestEvidence=max(centerEvidence,probe.a);bestBlend=score.x;} - evidence=bestEvidence; - return bestColor; -} -#endif -void evaluateCell(vec2 cell,vec2 local,vec2 grid,vec2 cellSize,vec2 cellDimensions,float cellWorld,float opticalTravel,float style,out vec2 affineUv,out mat2 transform,out vec2 curvedSlope,out vec2 facetSlope){ - vec2 random=hash2(cell),widths; - if(style>.5){ - widths=mix(vec2(.82),vec2(1.12),hash2(cell+vec2(11.4,9.8))); - float angle=(random.x-.5)*.08,c=cos(angle),s=sin(angle); - transform=mat2(widths.x*c,-widths.y*s,widths.x*s,widths.y*c); - float centerJitter=.16; - vec2 sourceCenter=(cell+.5)/grid+(random-.5)*centerJitter*cellSize; - affineUv=sourceCenter+transform*(local*cellSize); - }else{ - // Default style keeps a single continuous image footprint across cells. - transform=mat2(1.); - affineUv=(cell+.5)/grid+local*cellSize; - } - - // Positive height bulges toward the observer (+Z); negative height is concave. - float curvature=clamp(uCurvature,-1.,1.),surfaceCurvatureValue=surfaceCurvature(); - vec2 q=clamp(2.*local,-1.,1.),q2=q*q,q3=q2*q,b=1.-q2*q2; - if(style>.5){ - float amplitude=mix(.92,1.08,hash(cell+vec2(41.7,17.3))),height=.009*cellWorld*surfaceCurvatureValue*amplitude; - vec2 skew=(hash2(cell+vec2(23.8,61.2))-.5)*.28;float asym=1.+dot(skew,q); - vec2 dhdq=height*vec2(-4.*q3.x*b.y*asym+b.x*b.y*skew.x,-4.*q3.y*b.x*asym+b.x*b.y*skew.y); - vec2 grad=-2.*dhdq/cellDimensions; - curvedSlope=grad+(random-.5)*.012;facetSlope=(random-.5)*.012; - }else{ - curvedSlope=.30*uCellLensScale*cellDimensions/max(abs(opticalTravel),.6)*signedCurvatureScale()*sin(6.2831853*local); - facetSlope=vec2(0.); - } -} -void main(){ - vec2 screenUv=vUv; -#ifdef REGION_ATLAS - vec2 atlasPixel=floor(vUv*uRegionAtlasSize),atlasCell=floor(atlasPixel/8.),atlasLocal=(mod(atlasPixel,8.)+.5)/8.; - vec2 atlasPaneUv=(atlasCell+atlasLocal)/uRegionGridSize; - screenUv=projectUv(vec3((atlasPaneUv-.5)*uPaneSize,uGlassZ)); -#endif - if(uStrength<=.001){ -#ifdef REGION_ATLAS - gl_FragColor=vec4(sampleScene(screenUv).rgb,0.); -#else - gl_FragColor=sampleScene(screenUv); - #include -#endif - return;} - vec4 f=uContentInverseViewProjection*vec4(screenUv*2.-1.,1.,1.);float fw=abs(f.w)<.0001?(f.w<0.?-.0001:.0001):f.w;vec3 farWorld=f.xyz/fw;vec3 i=normalize(farWorld-uContentCameraPosition);float gt=(uGlassZ-uContentCameraPosition.z)/safeZ(i.z);vec3 gh=uContentCameraPosition+i*gt; - vec2 paneUv=gh.xy/uPaneSize+.5;vec2 grid=vec2(uGridSize,max(1.,uGridSize*uPaneSize.y/uPaneSize.x));vec2 gridUv=paneUv*grid,cell=floor(gridUv),local=fract(gridUv)-.5,cellSize=1./grid;float style=clamp(uMosaicStyle,0.,1.),cellWorld=min(uPaneSize.x/grid.x,uPaneSize.y/grid.y); -#ifdef REGION_ATLAS - paneUv=atlasPaneUv;grid= uRegionGridSize;gridUv=paneUv*grid;cell=floor(gridUv);local=fract(gridUv)-.5;cellSize=1./grid;cellWorld=min(uPaneSize.x/grid.x,uPaneSize.y/grid.y); -#endif - if(paneUv.x<0.||paneUv.x>1.||paneUv.y<0.||paneUv.y>1.){ -#ifdef REGION_ATLAS - gl_FragColor=vec4(uBackgroundColor,0.); -#else - gl_FragColor=vec4(uBackgroundColor,1.); - #include -#endif - return;} - vec2 cellDimensions=uPaneSize/grid; - float opticalTravel=-max(abs(uSourceZ-gh.z),.6); - vec2 affineUv,curvedSlope,facetSlope;mat2 transform; - evaluateCell(cell,local,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,affineUv,transform,curvedSlope,facetSlope); - if(style<=.5){ - vec2 smoothFacet=.003*vec2(sin(6.2831853*paneUv.x),sin(6.2831853*paneUv.y)); - curvedSlope+=smoothFacet;facetSlope=smoothFacet; - }else{ - vec2 edge=.5-abs(local),neighborSign=mix(vec2(-1.),vec2(1.),step(vec2(0.),local)); - float normalBlend=.16; - vec2 weights=1.-smoothstep(vec2(-normalBlend),vec2(normalBlend),edge); - float xSplitWeight=weights.x*(1.-weights.y),ySplitWeight=(1.-weights.x)*weights.y; - float diagonalSplitWeight=weights.x*weights.y,centerSplitWeight=(1.-weights.x)*(1.-weights.y); - if(weights.x>0.||weights.y>0.){ - vec2 neighborAffine,neighborCurved,neighborFacet;mat2 neighborTransform; - vec2 xWeight=vec2(xSplitWeight,0.); - vec2 yWeight=vec2(0.,ySplitWeight); - affineUv*=centerSplitWeight;transform*=centerSplitWeight;curvedSlope*=centerSplitWeight;facetSlope*=centerSplitWeight; - if(xWeight.x>0.){ - vec2 offset=vec2(neighborSign.x,0.); - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*xWeight.x;transform+=neighborTransform*xWeight.x;curvedSlope+=neighborCurved*xWeight.x;facetSlope+=neighborFacet*xWeight.x; - } - if(yWeight.y>0.){ - vec2 offset=vec2(0.,neighborSign.y); - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*yWeight.y;transform+=neighborTransform*yWeight.y;curvedSlope+=neighborCurved*yWeight.y;facetSlope+=neighborFacet*yWeight.y; - } - if(diagonalSplitWeight>0.){ - vec2 offset=neighborSign; - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*diagonalSplitWeight;transform+=neighborTransform*diagonalSplitWeight;curvedSlope+=neighborCurved*diagonalSplitWeight;facetSlope+=neighborFacet*diagonalSplitWeight; - } - } - } - vec3 nCurved=normalize(vec3(curvedSlope,1.)),nFacet=normalize(vec3(facetSlope,1.)); - vec3 straightHit=gh+i*((uSourceZ-gh.z)/safeZ(i.z)); - vec3 curvedRay=bend(i,nCurved),curvedHit=gh+curvedRay*((uSourceZ-gh.z)/safeZ(curvedRay.z)); - // Keep the artistic Mosaic optical path independent of physical glass-to-photo contact distance. - vec2 rawDelta=(curvedRay.xy/safeZ(curvedRay.z)-i.xy/safeZ(i.z))*opticalTravel; - vec2 worldDelta=vec2(softLimit(rawDelta.x,cellWorld*.55),softLimit(rawDelta.y,cellWorld*.55)); - if(style>.5){ - vec3 facetRay=bend(i,nFacet);vec3 facetHit=gh+facetRay*((uSourceZ-gh.z)/safeZ(facetRay.z)); - vec2 base=facetHit.xy-straightHit.xy,curve=curvedHit.xy-facetHit.xy; - worldDelta=vec2(softLimit(base.x,cellWorld*.08),softLimit(base.y,cellWorld*.08)); - vec2 d=curve/cellWorld; - worldDelta+=vec2(.3*d.x/(.3+abs(d.x)),.3*d.y/(.3+abs(d.y)))*cellWorld; - }else{ - vec3 referenceI=normalize(gh-vec3(0.,0.,uContentCameraPosition.z)),referenceRay=bend(referenceI,nCurved); - vec2 incidenceDelta=curvedRay.xy/max(-curvedRay.z,.0001)-referenceRay.xy/max(-referenceRay.z,.0001); - vec2 boundedIncidence=incidenceDelta/sqrt(incidenceDelta*incidenceDelta+vec2(.025*.025)); - vec2 cellEnvelope=.5+.5*cos(6.2831853*local); - worldDelta+=boundedIncidence*cellEnvelope*cellDimensions*signedCurvatureScale()*.18; - } - vec2 sampleUv=affineUv+transform*(worldDelta/uPaneSize); - float edgeDistance=min(min(paneUv.x,paneUv.y),min(1.-paneUv.x,1.-paneUv.y));float edgeTaper=style<=.5?1.25:.75;float edgeWeight=smoothstep(0.,max(cellSize.x,cellSize.y)*edgeTaper,edgeDistance);float strength=clamp(uStrength,0.,1.)*edgeWeight; - vec4 color;vec3 sceneHit=straightHit+vec3(worldDelta*strength,0.);vec2 finalSceneUv=projectUv(sceneHit); - if(style<=.5){ - sceneHit=refineSceneHit(gh,normalize(mix(i,curvedRay,strength)),sceneHit,cellWorld); - finalSceneUv=projectUv(sceneHit); - } -#ifdef REGION_ATLAS - vec3 atlasCenterColor=sampleScene(finalSceneUv).rgb; - float atlasEvidence=regionProtectionWeight(finalSceneUv)*(1.-smoothstep(.10,.20,regionLuminance(atlasCenterColor))); -#endif -#ifdef REGION_ATLAS - if(style<=.5){ - float representativeEvidence=atlasEvidence; - color=vec4(regionAtlasRepresentative(atlasCenterColor,atlasEvidence,sceneHit,gh,representativeEvidence),representativeEvidence); - atlasEvidence=representativeEvidence; - }else{ - color=sampleCell(paneUv,sampleUv,strength,cell,cellSize,style); - } -#else - if(style<=.5){ - color=sampleScene(finalSceneUv); - }else{ - color=sampleCell(paneUv,sampleUv,strength,cell,cellSize,style); - } -#endif -#ifndef REGION_ATLAS - if(uRegionAvailable>.5&&uRegionStrength>.001&&uMosaicStyle<.5){ - vec3 p0=regionColor(cell,0.),p1=regionColor(cell,1.),p2=regionColor(cell,2.),p3=regionColor(cell,3.); - float ownLabel=nearestRegion(color.rgb,p0,p1,p2,p3);vec4 votes=vec4(0.);float totalWeight=0.,ownWeight=0.; - vec2 texelCoord=fract(gridUv)*8.-.5,anchor=floor(texelCoord+.5); - for(int y=-1;y<=1;y++)for(int x=-1;x<=1;x++){ - vec2 offset=vec2(float(x),float(y)),delta=anchor+offset-texelCoord; - float weight=pow(max(0.,1.-length(delta)/1.5),2.); - if(weight>0.){ - vec3 atlasColor=regionAtlasColor(cell,anchor+offset);float label=nearestRegion(atlasColor,p0,p1,p2,p3); - votes+=vec4(step(abs(label-vec4(0.,1.,2.,3.)),vec4(.1)))*weight;totalWeight+=weight; - ownWeight+=step(abs(label-ownLabel),.1)*weight; - } - } - float winningLabel=ownLabel,winningWeight=ownWeight; - if(votes.x>winningWeight){winningLabel=0.;winningWeight=votes.x;}if(votes.y>winningWeight){winningLabel=1.;winningWeight=votes.y;}if(votes.z>winningWeight){winningLabel=2.;winningWeight=votes.z;}if(votes.w>winningWeight){winningLabel=3.;winningWeight=votes.w;} - bool simplify=totalWeight>0.&&winningWeight/totalWeight>.55&&ownWeight/totalWeight<.40; - float radialLabel=simplify?winningLabel:ownLabel;vec3 radialColor=selectRegion(p0,p1,p2,p3,radialLabel); - vec2 historyTexel=clamp(floor(fract(gridUv)*8.),vec2(0.),vec2(7.)); - vec2 historyUv=(cell*8.+historyTexel+.5)/uRegionAtlasSize; - vec4 splitHistory=texture2D(uRegionHistory,historyUv); - vec3 splitColor=splitHistory.a>.00001?splitHistory.rgb/splitHistory.a:radialColor; - vec3 candidateColor=mix(radialColor,splitColor,splitHistory.a); - // The palette describes broad color planes, not an opaque replacement image. - // Preserve the same continuously refracted sample underneath every plane. - candidateColor=mix(candidateColor,color.rgb,uTransmissionDetail); - color.rgb=mix(color.rgb,candidateColor,clamp(uRegionStrength*clamp(uStrength,0.,1.)*regionSurfaceValid(finalSceneUv,gh),0.,1.)); - } -#endif -#ifndef REGION_ATLAS - color.a=1.; - vec3 v=normalize(uContentCameraPosition-gh),reflected=reflect(-v,nCurved); float lightT=(uLightPosition.z-gh.z)/safeZ(reflected.z); vec2 lightHit=gh.xy+reflected.xy*lightT; vec2 halfSize=vec2(.32,.42)*min(uPaneSize.x,uPaneSize.y); vec2 windowCoord=abs(lightHit-uLightPosition.xy)/halfSize; vec2 windowMask=1.-smoothstep(vec2(.45),vec2(1.15),windowCoord); float surfaceReflectionWeight=mix(.35,1.,edgeWeight); float glossStrength=clamp(uGlossStrength,0.,1.); float spec=windowMask.x*windowMask.y*step(.0001,reflected.z)*step(0.,lightT); float specGloss=spec*glossStrength*.12*surfaceReflectionWeight*clamp(uStrength,0.,1.); vec2 broadWindowMask=1.-smoothstep(vec2(.15),vec2(1.75),windowCoord); float broadFacing=pow(max(dot(nCurved,v),0.),2.); float broadReflection=broadWindowMask.x*broadWindowMask.y*broadFacing*glossStrength*.035*surfaceReflectionWeight*clamp(uStrength,0.,1.); color.rgb=mix(color.rgb,vec3(1.),specGloss+broadReflection); gl_FragColor=color; - // Common, static room environment. Reflected direction varies with the same - // curved normal as transmission; no image relighting or timed sparkle. - float fresnel=.04+.96*pow(1.-clamp(dot(nCurved,v),0.,1.),5.); - float environmentWeight=uEnvironmentStrength*glossStrength*(.35+.65*fresnel)*surfaceReflectionWeight*clamp(uStrength,0.,1.); - vec3 environmentColor=mix(vec3(.10,.13,.18),vec3(.65,.72,.80),smoothstep(-.35,.65,reflected.y)); - if(style<=.5)color.rgb=mix(color.rgb,environmentColor,environmentWeight); - gl_FragColor=color; - #include -#else - color.a=atlasEvidence; - gl_FragColor=color; -#endif -} -`,Dg=`uniform sampler2D uSceneTexture; uniform mat4 uContentViewProjection; uniform mat4 uContentInverseViewProjection; uniform vec3 uContentCameraPosition,uBackgroundColor; uniform float uGlassZ,uSourceZ,uGridSize,uStrength,uTime; uniform vec2 uViewOffset,uResolution,uPetSize,uPaneSize; -varying vec2 vUv; -vec2 projectUv(vec3 p){vec4 c=uContentViewProjection*vec4(p,1.);float w=abs(c.w)<.0001?(c.w<0.?-.0001:.0001):c.w;return c.xy/w*.5+.5;} vec4 sampleScene(vec2 uv){if(any(lessThan(uv,vec2(0.)))||any(greaterThan(uv,vec2(1.))))return vec4(.005605,.009721,.016807,1.);return texture2D(uSceneTexture,uv);} float hash(float x){return fract(sin(x*91.7)*43758.5453);} float safeZ(float z){return abs(z)<.0001?(z<0.?-.0001:.0001):z;} vec3 bend(vec3 i,vec3 n){vec3 r=refract(i,n,.75);return length(r)<.0001?i:r;} -void main(){if(uStrength<=.001){gl_FragColor=texture2D(uSceneTexture,vUv); -#include -return;}vec2 q=vUv*2.-1.;vec4 fh=uContentInverseViewProjection*vec4(q,1.,1.);float fwDen=abs(fh.w)<.0001?(fh.w<0.?-.0001:.0001):fh.w;vec3 fw=fh.xyz/fwDen;vec3 i=normalize(fw-uContentCameraPosition);float gt=(uGlassZ-uContentCameraPosition.z)/safeZ(i.z);vec3 gh=uContentCameraPosition+i*gt;vec2 paneUv=gh.xy/uPaneSize+.5;if(any(lessThan(paneUv,vec2(0.)))||any(greaterThan(paneUv,vec2(1.)))){gl_FragColor=vec4(uBackgroundColor,1.); -#include -return;}float count=max(1.,uGridSize*uPetSize.x/uPetSize.y),coord=vUv.x*count,cell=floor(coord),phase=fract(coord)*6.2831853,ridge=sin(phase+uViewOffset.x*.9),variation=mix(.92,1.08,hash(cell));vec3 r=bend(i,normalize(vec3(-ridge*.34*variation,0.,1.)));vec3 sh=gh+i*((uSourceZ-gh.z)/safeZ(i.z)),bh=gh+r*((uSourceZ-gh.z)/safeZ(r.z));vec2 ru=vUv+projectUv(bh)-projectUv(sh);vec2 uv=mix(vUv,ru,clamp(uStrength,0.,1.));vec4 c=sampleScene(uv);c.a=1.;gl_FragColor=c; -#include -} -`,Lg=`uniform sampler2D uSceneTexture; uniform mat4 uContentViewProjection; uniform mat4 uContentInverseViewProjection; uniform vec3 uContentCameraPosition,uBackgroundColor; uniform float uGlassZ,uSourceZ,uGridSize,uStrength,uTime; uniform vec2 uViewOffset,uResolution,uPetSize,uPaneSize; -varying vec2 vUv; -vec2 projectUv(vec3 p){vec4 c=uContentViewProjection*vec4(p,1.);float w=abs(c.w)<.0001?(c.w<0.?-.0001:.0001):c.w;return c.xy/w*.5+.5;} vec4 sampleScene(vec2 uv){if(any(lessThan(uv,vec2(0.)))||any(greaterThan(uv,vec2(1.))))return vec4(.005605,.009721,.016807,1.);return texture2D(uSceneTexture,uv);} float hash(vec2 p){return fract(sin(dot(p,vec2(41.3,17.9)))*15731.743);} float noise(vec2 p){vec2 i=floor(p),f=fract(p);f=f*f*(3.-2.*f);return mix(mix(hash(i),hash(i+vec2(1.,0.)),f.x),mix(hash(i+vec2(0.,1.)),hash(i+vec2(1.)),f.x),f.y);} float safeZ(float z){return abs(z)<.0001?(z<0.?-.0001:.0001):z;} vec3 bend(vec3 i,vec3 n){vec3 r=refract(i,n,.75);return length(r)<.0001?i:r;} -void main(){if(uStrength<=.001){gl_FragColor=texture2D(uSceneTexture,vUv); -#include -return;}vec2 q=vUv*2.-1.;vec4 fh=uContentInverseViewProjection*vec4(q,1.,1.);float fwDen=abs(fh.w)<.0001?(fh.w<0.?-.0001:.0001):fh.w;vec3 fw=fh.xyz/fwDen;vec3 i=normalize(fw-uContentCameraPosition);float gt=(uGlassZ-uContentCameraPosition.z)/safeZ(i.z);vec3 gh=uContentCameraPosition+i*gt;vec2 paneUv=gh.xy/uPaneSize+.5;if(any(lessThan(paneUv,vec2(0.)))||any(greaterThan(paneUv,vec2(1.)))){gl_FragColor=vec4(uBackgroundColor,1.); -#include -return;}vec2 st=vUv*(uResolution/max(uResolution.y,1.)),np=st*9.+uViewOffset*.6,nn=vec2(noise(np),noise(np+vec2(23.7)))-vec2(.5);vec3 r=bend(i,normalize(vec3(nn*.32,1.)));vec3 sh=gh+i*((uSourceZ-gh.z)/safeZ(i.z)),bh=gh+r*((uSourceZ-gh.z)/safeZ(r.z));vec2 ru=vUv+projectUv(bh)-projectUv(sh),center=mix(vUv,ru,clamp(uStrength,0.,1.)),rad=vec2(.008)*clamp(uStrength,0.,1.);vec4 c=vec4(0.);c+=sampleScene(center+vec2(-rad.x,-rad.y));c+=sampleScene(center+vec2(0.,-rad.y));c+=sampleScene(center+vec2(rad.x,-rad.y));c+=sampleScene(center+vec2(-rad.x,0.));c+=sampleScene(center);c+=sampleScene(center+vec2(rad.x,0.));c+=sampleScene(center+vec2(-rad.x,rad.y));c+=sampleScene(center+vec2(0.,rad.y));c+=sampleScene(center+vec2(rad.x,rad.y));c/=9.;c.a=1.;gl_FragColor=c; -#include -} -`;class Ug{constructor(e,t){ke(this,"token",0);ke(this,"activeUrl","");ke(this,"pendingUrl","");ke(this,"pendingVideo",null);ke(this,"activeVideo",null);ke(this,"retryVideo",null);this.onReady=e,this.onStatus=t}cancelPending(){++this.token,this.clearPending(),this.retryVideo=null}load(e){const t=++this.token;this.clearPending(),this.retryVideo=null;const n=URL.createObjectURL(e);if(this.pendingUrl=n,e.type.startsWith("image/")){const a=new Image;a.onload=()=>{if(t!==this.token)return this.disposeUrl(n);this.pendingUrl===n&&(this.pendingUrl="");const o=new vt(a);o.colorSpace=Bt,o.needsUpdate=!0,this.replaceActive(n,null),this.onReady(o,a.width/a.height,null),t===this.token&&this.onStatus("")},a.onerror=()=>{t===this.token&&this.onStatus("이미지를 읽지 못했습니다."),this.disposeUrl(n)},a.src=n;return}const r=document.createElement("video");this.pendingVideo=r,r.muted=!0,r.loop=!0,r.playsInline=!0,r.preload="auto",r.src=n;const s=()=>{r.onloadeddata=null,r.onerror=null,r.pause(),r.removeAttribute("src"),r.load(),this.pendingVideo===r&&(this.pendingVideo=null),this.pendingUrl===n&&(this.pendingUrl=""),this.disposeUrl(n)};r.onerror=()=>{t===this.token&&this.onStatus("동영상을 읽지 못했습니다."),s()},r.onloadeddata=()=>{if(t!==this.token)return s();r.onloadeddata=null,r.onerror=null,this.pendingUrl===n&&(this.pendingUrl=""),this.pendingVideo===r&&(this.pendingVideo=null);const a=new Pg(r);a.colorSpace=Bt,this.replaceActive(n,r),this.retryVideo=r,this.onReady(a,r.videoWidth/r.videoHeight,r),t===this.token&&this.activeVideo===r&&this.onStatus(""),r.play().catch(()=>{t===this.token&&r===this.activeVideo&&this.onStatus("자동 재생이 차단되었습니다. 화면을 눌러 재생하세요.")})},r.load()}retry(){const e=this.retryVideo,t=this.token;e==null||e.play().catch(()=>{t===this.token&&e===this.activeVideo&&this.onStatus("재생할 수 없습니다.")})}dispose(){++this.token,this.clearPending(),this.retryVideo=null,this.activeVideo&&(this.activeVideo.pause(),this.activeVideo.removeAttribute("src"),this.activeVideo.load(),this.activeVideo=null),this.disposeUrl(this.activeUrl),this.activeUrl=""}replaceActive(e,t){this.activeVideo&&this.activeVideo!==t&&(this.activeVideo.pause(),this.activeVideo.removeAttribute("src"),this.activeVideo.load()),this.activeUrl&&this.activeUrl!==e&&this.disposeUrl(this.activeUrl),this.activeUrl=e,this.activeVideo=t,this.retryVideo=t}clearPending(){this.pendingVideo&&(this.pendingVideo.onloadeddata=null,this.pendingVideo.onerror=null,this.pendingVideo.pause(),this.pendingVideo.removeAttribute("src"),this.pendingVideo.load(),this.pendingVideo=null),this.pendingUrl&&this.disposeUrl(this.pendingUrl),this.pendingUrl=""}disposeUrl(e){e&&URL.revokeObjectURL(e)}}class Ig{constructor(e,t,n){ke(this,"activeId",null);ke(this,"lastX",0);ke(this,"lastY",0);ke(this,"hasDragged",!1);ke(this,"down",e=>{this.activeId=e.pointerId,this.lastX=e.clientX,this.lastY=e.clientY,this.element.setPointerCapture(e.pointerId)});ke(this,"move",e=>{var s;if(e.pointerId!==this.activeId)return;const t=e.clientX-this.lastX,n=e.clientY-this.lastY;if(t===0&&n===0)return;this.hasDragged||(this.hasDragged=!0,this.element.classList.add("is-dragging"),(s=this.onDrag)==null||s.call(this));const r=this.element.getBoundingClientRect();this.setView(t/r.width,-n/r.height),this.lastX=e.clientX,this.lastY=e.clientY});ke(this,"end",e=>{e.pointerId===this.activeId&&(this.activeId=null,this.hasDragged=!1,this.element.classList.remove("is-dragging"),this.element.hasPointerCapture(e.pointerId)&&this.element.releasePointerCapture(e.pointerId))});this.element=e,this.setView=t,this.onDrag=n,e.addEventListener("pointerdown",this.down),e.addEventListener("pointermove",this.move),e.addEventListener("pointerup",this.end),e.addEventListener("pointercancel",this.end)}dispose(){this.element.removeEventListener("pointerdown",this.down),this.element.removeEventListener("pointermove",this.move),this.element.removeEventListener("pointerup",this.end),this.element.removeEventListener("pointercancel",this.end)}}class Ng{constructor(e,t=.5){ke(this,"target",new Le);ke(this,"current",new Le);this.camera=e,this.maxOffset=t}setMaxOffset(e){this.maxOffset=yt.clamp(e,0,.9)}add(e,t){this.target.set(yt.clamp(this.target.x+e,-1,1),yt.clamp(this.target.y+t,-1,1))}reset(){this.target.set(0,0),this.current.set(0,0)}update(e,t){this.current.lerp(this.target,1-Math.exp(-8*e));const n=this.current.clone().multiplyScalar(t);return n.x=yt.clamp(n.x,-1,1),n.y=yt.clamp(n.y,-1,1),this.camera.position.set(n.x*this.maxOffset,n.y*this.maxOffset,3),this.camera.lookAt(0,0,0),n}}class Fg{constructor(e,t){ke(this,"enabled",!1);ke(this,"pending",!1);ke(this,"generation",0);ke(this,"hasReading",!1);ke(this,"base",null);ke(this,"onOrientation",e=>{var s;if(!this.enabled||e.beta==null||e.gamma==null)return;this.base||(this.base={beta:e.beta,gamma:e.gamma});const t=(((s=screen.orientation)==null?void 0:s.angle)??0)*Math.PI/180,n=e.gamma-this.base.gamma,r=e.beta-this.base.beta;this.setView((n*Math.cos(t)+r*Math.sin(t))/35,(r*Math.cos(t)-n*Math.sin(t))/35),this.hasReading||(this.hasReading=!0,this.status("자이로스코프 활성"))});this.setView=e,this.status=t}async toggle(){if(this.enabled||this.pending)return this.dispose(),!1;if(!window.isSecureContext||!("DeviceOrientationEvent"in window))return this.status("자이로스코프를 사용할 수 없습니다."),!1;const e=++this.generation;this.pending=!0;try{const t=window.DeviceOrientationEvent;if(this.status("센서 권한을 기다리는 중…"),t.requestPermission&&await t.requestPermission()!=="granted")throw new Error("권한 거절됨");return e!==this.generation?!1:(this.base=null,this.hasReading=!1,this.pending=!1,this.enabled=!0,window.addEventListener("deviceorientation",this.onOrientation),this.status("센서값을 기다리는 중…"),!0)}catch(t){return this.pending=!1,e===this.generation&&this.status(`자이로스코프를 사용할 수 없습니다 (${t.message})`),!1}}reset(){this.base=null}dispose(){++this.generation,this.pending=!1,this.enabled=!1,this.base=null,window.removeEventListener("deviceorientation",this.onOrientation)}}class Og{async load(e){const t=new Image;return t.src=e,await new Promise((n,r)=>{t.onload=()=>n(),t.onerror=()=>r(new Error(`Depth map could not be loaded: ${e}`))}),t}}const bi={lowerQuantile:.5,upperQuantile:.85,fallbackLowerQuantile:.05,fallbackUpperQuantile:.95,minimumSpan:12/255},zl={blend:.65,maxCellCorrection:.35};class ii{static evidenceRange(e){var l;const t=(l=e.image)==null?void 0:l.data;if(!t||t.length<4)return[1,1];const n=new Uint32Array(256);for(let c=0;c{let u=0;for(let d=0;d=r*c)return d/255;return 1};let a=s(bi.lowerQuantile),o=s(bi.upperQuantile);return o-a{this.pending={id:t,resolve:n,reject:r},this.captureAndSend(e,t).catch(s=>{this.fail(t,s instanceof Error?s:new Error("AI depth 생성에 실패했습니다."))})})}cancel(){var t;const e=this.pending;this.pending=null,this.requestId+=1,(t=this.worker)==null||t.terminate(),this.worker=null,e==null||e.reject(new Error("AI depth 요청이 취소되었습니다."))}async captureAndSend(e,t){var l;const n=e.naturalWidth||e.width,r=e.naturalHeight||e.height;if(!n||!r)throw new Error("사진 크기를 확인할 수 없습니다.");const s=Math.min(1,1024/Math.max(n,r)),a=await createImageBitmap(e,{resizeWidth:Math.max(1,Math.round(n*s)),resizeHeight:Math.max(1,Math.round(r*s)),resizeQuality:"high"});if(((l=this.pending)==null?void 0:l.id)!==t){a.close();return}const o=this.ensureWorker();try{o.postMessage({type:"infer",id:t,image:a},[a])}catch(c){throw a.close(),c}}ensureWorker(){if(this.worker)return this.worker;const e=new Worker(new URL("/assets/aiDepth.worker-DnfO2O4Q.js",import.meta.url),{type:"module"});return e.onmessage=t=>{var r;const n=t.data;if(((r=this.pending)==null?void 0:r.id)===n.id)if(n.type==="status")this.onStatus(n.message);else if(n.type==="result"){const s=this.pending;this.pending=null;try{s.resolve(ii.fromNormalizedDepth(new Uint8Array(n.values),n.width,n.height))}catch(a){s.reject(a instanceof Error?a:new Error("AI depth 결과를 읽지 못했습니다."))}}else this.fail(n.id,new Error(n.message))},e.onerror=t=>{var n;this.resetWorker(e),this.fail(((n=this.pending)==null?void 0:n.id)??-1,new Error(t.message||"AI depth worker 오류가 발생했습니다."))},e.onmessageerror=()=>{var t;this.resetWorker(e),this.fail(((t=this.pending)==null?void 0:t.id)??-1,new Error("AI depth worker 결과를 읽지 못했습니다."))},this.worker=e,e}fail(e,t){var r;if(((r=this.pending)==null?void 0:r.id)!==e)return;const n=this.pending;this.pending=null,n.reject(t)}resetWorker(e){e.terminate(),this.worker===e&&(this.worker=null)}}const kg=`uniform sampler2D uDepthMap; -uniform float uDepthScale; -uniform float uDepthBias; -varying vec2 vUv; - -void main() { - vUv = uv; - float depth = texture2D(uDepthMap, uv).r; - vec3 displacedPosition = position; - displacedPosition.z += (depth - uDepthBias) * uDepthScale; - gl_Position = projectionMatrix * modelViewMatrix * vec4(displacedPosition, 1.0); -} -`,Wg=`uniform sampler2D uTexture; -uniform bool uIsVideo; -varying vec2 vUv; - -vec3 srgbToLinear(vec3 value) { - return mix(value / 12.92, pow((value + 0.055) / 1.055, vec3(2.4)), step(vec3(0.04045), value)); -} - -void main() { - vec4 color = texture2D(uTexture, vUv); - if (uIsVideo) color.rgb = srgbToLinear(color.rgb); - color.a = 1.0; - gl_FragColor = color; - #include -} -`;class Xg extends lt{constructor(e,t,n=.25,r=0){const s=new un(1,1,128,128),a={uTexture:{value:e},uDepthMap:{value:t},uDepthScale:{value:yt.clamp(n,0,.4)},uDepthBias:{value:r},uIsVideo:{value:!1}},o=new Gt({uniforms:a,vertexShader:kg,fragmentShader:Wg});super(s,o)}setTexture(e){this.material.uniforms.uTexture.value=e}setDepthMap(e){this.material.uniforms.uDepthMap.value=e}setDepthScale(e){this.material.uniforms.uDepthScale.value=yt.clamp(e,0,.4)}setVideo(e){this.material.uniforms.uIsVideo.value=e}get depthMap(){return this.material.uniforms.uDepthMap.value}}const qg=[{name:"nose",x:235,y:310},{name:"left-eye",x:198,y:278},{name:"right-eye",x:249,y:273},{name:"face",x:221,y:267},{name:"left-ear",x:158,y:213},{name:"right-ear",x:262,y:206},{name:"body",x:139,y:419}];class Yg{constructor(){ke(this,"values",null);ke(this,"width",0);ke(this,"height",0);ke(this,"sampleKind","")}setSample(e){const t=e.naturalWidth||e.width,n=e.naturalHeight||e.height,r=document.createElement("canvas");r.width=t,r.height=n;const s=r.getContext("2d");if(!s||t<1||n<1){this.clear();return}s.drawImage(e,0,0,t,n),this.values=s.getImageData(0,0,t,n).data,this.width=t,this.height=n,this.sampleKind="sample"}clear(){this.values=null,this.width=0,this.height=0,this.sampleKind=""}update(e,t,n,r,s,a,o){if(!this.values||!e||!t||this.sampleKind==="")return"";e.updateMatrixWorld(),t.updateMatrixWorld(!0);const l=a+(o-r)*n,c=Math.max(0,.6-l),u=[`cameraX=${e.position.x.toFixed(3)} sample=${this.sampleKind}`,`contentBaseZ=${a.toFixed(3)} maxFrontZ=${l.toFixed(3)} glassGap=${c.toFixed(3)}`],d=new N,p=new N,m=new N;for(const _ of qg){const M=this.sampleBilinear(_.x,_.y),f=(_.x+.5)/this.width,h=1-(_.y+.5)/this.height;d.set(f-.5,h-.5,(M-r)*n),p.copy(d),t.localToWorld(p),m.copy(p).project(e);const T=(m.x*.5+.5)*s;u.push(`${_.name}: depth=${M.toFixed(3)} worldZ=${p.z.toFixed(3)} projectedX=${T.toFixed(3)}px`)}return u.join(` -`)}sampleBilinear(e,t){if(!this.values||this.width<1||this.height<1)return 0;const n=yt.clamp(e,0,this.width-1),r=yt.clamp(t,0,this.height-1),s=Math.floor(n),a=Math.floor(r),o=Math.min(s+1,this.width-1),l=Math.min(a+1,this.height-1),c=n-s,u=r-a,d=this.gray(s,a),p=this.gray(o,a),m=this.gray(s,l),_=this.gray(o,l);return yt.lerp(yt.lerp(d,p,c),yt.lerp(m,_,c),u)}gray(e,t){return this.values[(t*this.width+e)*4]/255}}class Zg{constructor(e){ke(this,"meshes");ke(this,"geometries");this.geometries=Array.from({length:4},()=>{const t=new Hn;return t.setAttribute("position",new en(new Float32Array(12),3)),t.setIndex([0,1,2,0,2,3]),t.computeVertexNormals(),t}),this.meshes=this.geometries.map(t=>new lt(t,e))}update(e,t,n,r,s,a){const o=e*.5,l=t*.5,c=n*.5,u=r*.5,d=Math.min(e,t)*.002,p=s+d,m=Math.max(0,c-d),_=Math.max(0,u-d),M=[[[-o-d,-l-d,p],[-o-d,l+d,p],[-m,_,a],[-m,-_,a]],[[o+d,l+d,p],[o+d,-l-d,p],[m,-_,a],[m,_,a]],[[-o-d,l+d,p],[o+d,l+d,p],[m,_,a],[-m,_,a]],[[o+d,-l-d,p],[-o-d,-l-d,p],[-m,-_,a],[m,-_,a]]];for(let f=0;fe.dispose())}}const ys=`varying vec2 vUv; - -void main() { - vUv = uv; - gl_Position = vec4(position.xy, 0.0, 1.0); -} -`,Kg=`uniform sampler2D uRegionAtlas; -uniform vec2 uRegionAtlasSize,uRegionGridSize; -varying vec2 vUv; - -float regionLuminance(vec3 c){return dot(c,vec3(.299,.587,.114));} -float distanceColor(vec3 a,vec3 b){vec3 d=a-b;float y=dot(d,vec3(.299,.587,.114));return dot(d,d)+.35*y*y;} -float sideColorCost(vec4 votes,vec3 target,vec3 c0,vec3 c1,vec3 c2,vec3 c3){return votes.x*distanceColor(c0,target)+votes.y*distanceColor(c1,target)+votes.z*distanceColor(c2,target)+votes.w*distanceColor(c3,target);} -vec4 atlasSampleData(vec2 cell,vec2 local){vec2 uv=(cell*8.+local+.5)/uRegionAtlasSize;return texture2D(uRegionAtlas,uv);} -vec3 atlasSample(vec2 cell,vec2 local){return atlasSampleData(cell,local).rgb;} -float nearestLabel(vec3 color,vec3 c0,vec3 c1,vec3 c2,vec3 c3){float d0=distanceColor(color,c0),d1=distanceColor(color,c1),d2=distanceColor(color,c2),d3=distanceColor(color,c3);if(d0<=d1&&d0<=d2&&d0<=d3)return 0.;if(d1<=d2&&d1<=d3)return 1.;if(d2<=d3)return 2.;return 3.;} -float majorityLabel(vec4 votes){float label=0.,count=votes.x;if(votes.y>count){label=1.;count=votes.y;}if(votes.z>count){label=2.;count=votes.z;}if(votes.w>count)label=3.;return label;} -void main(){ - vec2 pixel=floor(gl_FragCoord.xy);float paletteIndex=mod(pixel.x,5.);vec3 cell=vec3(floor(pixel.x/5.),pixel.y,0.); - vec3 darkest=vec3(1.),lightest=vec3(0.);float minLum=2.,maxLum=-1.; - for(int y=0;y<8;y++)for(int x=0;x<8;x++){ - vec3 c=atlasSample(cell.xy,vec2(float(x),float(y)));float l=regionLuminance(c); - if(lmaxLum){maxLum=l;lightest=c;} - } - vec3 third=darkest;float thirdDistance=-1.; - for(int y=0;y<8;y++)for(int x=0;x<8;x++){ - vec3 c=atlasSample(cell.xy,vec2(float(x),float(y)));float d=min(distanceColor(c,darkest),distanceColor(c,lightest)); - if(d>thirdDistance){thirdDistance=d;third=c;} - } - vec3 fourth=darkest;float fourthDistance=-1.; - for(int y=0;y<8;y++)for(int x=0;x<8;x++){ - vec3 c=atlasSample(cell.xy,vec2(float(x),float(y)));float d=min(distanceColor(c,darkest),min(distanceColor(c,lightest),distanceColor(c,third))); - if(d>fourthDistance){fourthDistance=d;fourth=c;} - } - vec3 c0=darkest,c1=lightest,c2=third,c3=fourth; - for(int iteration=0;iteration<2;iteration++){ - vec3 sum0=vec3(0.),sum1=vec3(0.),sum2=vec3(0.),sum3=vec3(0.);float n0=0.,n1=0.,n2=0.,n3=0.; - for(int y=0;y<8;y++)for(int x=0;x<8;x++){ - vec3 c=atlasSample(cell.xy,vec2(float(x),float(y))); - float d0=distanceColor(c,c0),d1=distanceColor(c,c1),d2=distanceColor(c,c2),d3=distanceColor(c,c3); - if(d0<=d1&&d0<=d2&&d0<=d3){sum0+=c;n0+=1.;} - else if(d1<=d2&&d1<=d3){sum1+=c;n1+=1.;} - else if(d2<=d3){sum2+=c;n2+=1.;} - else{sum3+=c;n3+=1.;} - } - if(n0>0.)c0=sum0/n0;if(n1>0.)c1=sum1/n1;if(n2>0.)c2=sum2/n2;if(n3>0.)c3=sum3/n3; - } - - vec4 metadata=vec4(0.); - if(paletteIndex>3.5){ - vec4 wholeVotes=vec4(0.);float cellEvidence=0.; - for(int y=0;y<8;y++)for(int x=0;x<8;x++){ - vec4 sampleData=atlasSampleData(cell.xy,vec2(float(x),float(y)));vec3 c=sampleData.rgb;float label=nearestLabel(c,c0,c1,c2,c3); - wholeVotes+=vec4(step(abs(label-vec4(0.,1.,2.,3.)),vec4(.1))); - cellEvidence+=sampleData.a; - } - float singleMajority=max(max(wholeVotes.x,wholeVotes.y),max(wholeVotes.z,wholeVotes.w))/64.; - float bestCost=1e20,bestConfidence=0.,bestAxis=0.,bestCut=4.,bestA=0.,bestB=0.; - for(int axis=0;axis<2;axis++)for(int candidateIndex=0;candidateIndex<5;candidateIndex++){ - float cut=4.; - if(candidateIndex==1)cut=3.;else if(candidateIndex==2)cut=5.;else if(candidateIndex==3)cut=2.;else if(candidateIndex==4)cut=6.; - vec4 votesA=vec4(0.),votesB=vec4(0.),weightedVotesA=vec4(0.),weightedVotesB=vec4(0.); - for(int y=0;y<8;y++)for(int x=0;x<8;x++){ - vec4 sampleData=atlasSampleData(cell.xy,vec2(float(x),float(y)));vec3 c=sampleData.rgb;float label=nearestLabel(c,c0,c1,c2,c3); - vec4 oneHot=vec4(step(abs(label-vec4(0.,1.,2.,3.)),vec4(.1)));float sampleWeight=1.+3.*sampleData.a; - float coordinate=axis==0?float(x)+.5:float(y)+.5; - if(coordinate0.&&votesB[b]>0.){ - vec3 colorA=a==0?c0:(a==1?c1:(a==2?c2:c3)); - vec3 colorB=b==0?c0:(b==1?c1:(b==2?c2:c3)); - float candidateCost=sideColorCost(weightedVotesA,colorA,c0,c1,c2,c3)+sideColorCost(weightedVotesB,colorB,c0,c1,c2,c3); - if(candidateCost.5&&paletteIndex<1.5)result=c1; - else if(paletteIndex>1.5&&paletteIndex<2.5)result=c2; - else if(paletteIndex>2.5&&paletteIndex<3.5)result=c3; - gl_FragColor=paletteIndex>3.5?metadata:vec4(result,1.); -} -`,jg=`uniform sampler2D uRegionPalette,uPreviousHistory; -uniform vec2 uRegionAtlasSize,uRegionGridSize,uRegionPaletteSize; -uniform float uHistoryBlend; -varying vec2 vUv; - -vec3 paletteColor(vec2 cell,float label){vec2 uv=(vec2(cell.x*5.+label,cell.y)+.5)/uRegionPaletteSize;return texture2D(uRegionPalette,uv).rgb;} -void main(){ - vec2 pixel=floor(vUv*uRegionAtlasSize),cell=floor(pixel/8.),local=(mod(pixel,8.)+.5)/8.; - vec2 metadataUv=(vec2(cell.x*5.+4.,cell.y)+.5)/uRegionPaletteSize; - vec4 metadata=texture2D(uRegionPalette,metadataUv); - float packed=floor(metadata.r*255.+.5),axis=floor(packed/8.),cut=packed-axis*8.; - float coordinate=axis<.5?local.x:local.y; - float label=coordinate=.9999){gl_FragColor=current;return;} - vec4 previous=texture2D(uPreviousHistory,vUv); - gl_FragColor=mix(previous,current,clamp(uHistoryBlend,0.,1.)); -} -`,Es=document.querySelector("#canvas-wrap"),tn=document.querySelector("#status"),Di=document.querySelector("#depth-provenance"),dr=document.querySelector("#ai-depth"),$g=document.querySelector("#empty"),Sr=document.querySelector("#hint");Sr.style.opacity="0";const Ne=new Cg({antialias:!0});Ne.setPixelRatio(Math.min(devicePixelRatio,1.5));Es.append(Ne.domElement);const Bi=new Xi,Pc=new Xi,xo=new Xi;Bi.background=new Ye(1120547);const mt=new Wt(40,1,.1,100);mt.position.z=3;const Dc=new un(1,1),zt=new ts(new Uint8Array([38,48,62,255]),1,1);zt.needsUpdate=!0;const Fn=new sn({map:zt}),Ri=new lt(Dc,Fn);Bi.add(Ri);const fs=ii.flatTexture(),qt=new Xg(zt,fs,.25,0),So=qt.material,dt=So.uniforms;Bi.add(qt);const J={uSceneTexture:{value:zt},uSceneDepth:{value:zt},uProtectionDepthMap:dt.uDepthMap,uPetWorldToLocal:{value:new tt},uContentViewProjection:{value:new tt},uContentInverseViewProjection:{value:new tt},uContentCameraPosition:{value:new N},uLightPosition:{value:new N(.6,.8,2.6)},uBackgroundColor:{value:Bi.background.clone()},uGlassZ:{value:.6},uSourceZ:{value:.56},uGridSize:{value:13},uMosaicStyle:{value:0},uStrength:{value:1},uGlossStrength:{value:.3},uCurvature:{value:1},uRegionStrength:{value:1},uRegionAvailable:{value:0},uRegionAtlasSize:{value:new Le(104,104)},uRegionGridSize:{value:new Le(13,13)},uRegionPaletteSize:{value:new Le(65,13)},uRegionPalette:{value:zt},uRegionAtlas:{value:zt},uViewOffset:{value:new Le},uPaneRect:{value:new it(0,0,1,1)},uResolution:{value:new Le},uTime:{value:0},uPetSize:{value:new Le(1,1)},uPaneSize:{value:new Le(1,1)}},Mo={value:zt},Lc={value:new Le(1,1)};Object.assign(J,{uRegionHistory:Mo,uDepthEvidenceRange:Lc,uEnvironmentStrength:{value:zg},uTransmissionDetail:{value:Hg},uCellLensScale:{value:Gg},uDepthCorrection:{value:new Le(zl.blend,zl.maxCellCorrection)}});const ps=new Gt({uniforms:J,vertexShader:ys,fragmentShader:_o}),yo=new lt(new un(2,2),ps);Pc.add(yo);const Uc=new Xi,Ic=new Gt({uniforms:J,vertexShader:ys,fragmentShader:_o,defines:{REGION_ATLAS:1},toneMapped:!1}),Nc=new lt(new un(2,2),Ic);Uc.add(Nc);const Fc=new Xi,Eo={uRegionAtlas:{value:null},uRegionAtlasSize:J.uRegionAtlasSize,uRegionGridSize:J.uRegionGridSize},Oc=new Gt({uniforms:Eo,vertexShader:ys,fragmentShader:Kg,toneMapped:!1}),Bc=new lt(new un(2,2),Oc);Fc.add(Bc);const Mr=new ki(1,1,1),qi=[new sn({color:3810329}),new sn({color:4861472}),new sn({color:2824723}),new sn({color:5321510}),new sn({color:3284759}),new sn({color:4401437})],$a=new lt(Mr,qi),Ja=new lt(Mr,qi),Qa=new lt(Mr,qi),eo=new lt(Mr,qi);xo.add($a,Ja,Qa,eo);const zc=new sn({color:qi[1].color,side:on}),Ts=new Zg(zc);xo.add(...Ts.meshes);const ms=new bc(-1,1,1,-1,0,1),rn=new nn(1,1,{colorSpace:Mt,type:Bn,depthBuffer:!0});rn.depthTexture=new vo(1,1,Nn);rn.depthTexture.format=ei;J.uSceneDepth.value=rn.depthTexture;const St=new nn(104,104,{colorSpace:Mt,type:Bn,depthBuffer:!1,minFilter:ot,magFilter:ot}),Ct=new nn(65,13,{colorSpace:Mt,type:cn,depthBuffer:!1,minFilter:ot,magFilter:ot}),ln=[0,1].map(()=>new nn(104,104,{colorSpace:Mt,type:Bn,depthBuffer:!1,minFilter:ot,magFilter:ot})),Hc=new Xi,to={uRegionPalette:{value:Ct.texture},uPreviousHistory:{value:ln[0].texture},uRegionAtlasSize:J.uRegionAtlasSize,uRegionGridSize:J.uRegionGridSize,uRegionPaletteSize:J.uRegionPaletteSize,uHistoryBlend:{value:1}},Gc=new Gt({uniforms:to,vertexShader:ys,fragmentShader:jg,toneMapped:!1}),Vc=new lt(new un(2,2),Gc);Hc.add(Vc);J.uRegionPalette.value=Ct.texture;Eo.uRegionAtlas.value=St.texture;let hr="",Hl="",er=0,no=!1;function To(){const i=Math.max(1,Math.ceil(J.uGridSize.value)),e=Math.max(1,J.uGridSize.value*J.uPaneSize.value.y/Math.max(J.uPaneSize.value.x,.001)),t=Math.ceil(e),n=i*8,r=t*8,s=i*5,a=t,o=Math.max(n,r,s,a)<=Ne.capabilities.maxTextureSize,l=J.uRegionAvailable.value!==(o?1:0)||o&&(St.width!==n||St.height!==r||Ct.width!==s||Ct.height!==a||ln[0].width!==n||ln[0].height!==r)||J.uRegionGridSize.value.x!==J.uGridSize.value||J.uRegionGridSize.value.y!==e;o&&(St.width!==n||St.height!==r)&&St.setSize(n,r),o&&(Ct.width!==s||Ct.height!==a)&&Ct.setSize(s,a);for(const c of ln)o&&(c.width!==n||c.height!==r)&&c.setSize(n,r);J.uRegionAvailable.value=o?1:0,J.uRegionAtlasSize.value.set(o?n:St.width,o?r:St.height),J.uRegionGridSize.value.set(J.uGridSize.value,e),J.uRegionPaletteSize.value.set(o?s:Ct.width,o?a:Ct.height),Eo.uRegionAtlas.value=St.texture,J.uRegionPalette.value=Ct.texture,J.uRegionAtlas.value=St.texture,l&&(hr="")}let Dt=zt,bs=!1,fr=1,_n=1,xn=1,Dn=1,pr=0,mr=0,As=!1,ns=!1,On="noglass",bo=0,Ao=-1,ni=null,ir=null,gs=!1,Sn=0,Qt=0,ri=!1,vs=!1,si=!1,At=!1;const ct=new AbortController;function Yt(){dr.disabled=Dt===zt||bs||ri||vs||si||At,dr.textContent=si?"AI 깊이 생성 중…":"AI 깊이 생성"}const wo=new Vg(i=>{!At&&si&&(tn.textContent=i)});function ws(){Qt+=1,wo.cancel(),si=!1,vs=!1,Yt()}function kc(){ni&&ni.dispose(),ni=null}let rr=0;function is(){return J.uGlassZ.value-.04-(rr-dt.uDepthBias.value)*dt.uDepthScale.value}function gr(){kc(),ir=null,As=!1,gs=!1}function li(){const i=is(),e=(mt.position.z-i)/mt.position.z,t=_n*(Dn-1)*.5*pr*e,n=xn*(Dn-1)*.5*mr*e;Ri.scale.set(_n*Dn*e,xn*Dn*e,1),Ri.position.set(t,n,i),qt.scale.copy(Ri.scale),qt.position.copy(Ri.position),J.uSourceZ.value=i,Ts.update(J.uPaneSize.value.x,J.uPaneSize.value.y,_n*(3-i)/3,xn*(3-i)/3,J.uGlassZ.value,i)}function Ro(){const i=Es.getBoundingClientRect();Ne.setSize(i.width,i.height,!1),mt.aspect=i.width/i.height,mt.updateProjectionMatrix();const e=1.7,t=Math.min(e*i.width/i.height/fr,e);_n=t*fr,xn=t,li(),J.uPetSize.value.set(_n,xn),J.uResolution.value.set(i.width,i.height);const n=2*(mt.position.z-.6)*Math.tan(yt.degToRad(mt.fov/2));J.uPetSize.value.set(n*mt.aspect,n),J.uPaneSize.value.set(_n*(3-J.uGlassZ.value)/3,xn*(3-J.uGlassZ.value)/3),Ts.update(J.uPaneSize.value.x,J.uPaneSize.value.y,_n*(3-is())/3,xn*(3-is())/3,J.uGlassZ.value,is()),To();const r=J.uPaneSize.value.x,s=J.uPaneSize.value.y,a=Math.min(r,s)*.035,o=a*1.5,l=J.uGlassZ.value+o*.25;$a.position.set(-(r+a)*.5,0,l),Ja.position.set((r+a)*.5,0,l),Qa.position.set(0,(s+a)*.5,l),eo.position.set(0,-(s+a)*.5,l),$a.scale.set(a,s,o),Ja.scale.set(a,s,o),Qa.scale.set(r+a*2,a,o),eo.scale.set(r+a*2,a,o);const c=2*3*Math.tan(yt.degToRad(40/2)),u=c*mt.aspect;J.uPaneRect.value.set(Math.max(0,.5-_n/(2*u)),Math.max(0,.5-xn/(2*c)),Math.min(1,.5+_n/(2*u)),Math.min(1,.5+xn/(2*c))),rn.setSize(Math.max(1,Math.floor(i.width*Math.min(devicePixelRatio,1.5))),Math.max(1,Math.floor(i.height*Math.min(devicePixelRatio,1.5))))}function Co(){bo+=1,Ao=-1,Sr.style.opacity="0"}function Wc(){Ao!==bo&&(Sr.style.opacity="1")}function Jg(){Ao=bo,Sr.style.opacity="0"}function Qg(i,e,t){Dt!==zt&&Dt.dispose(),Dt=i,bs=!!t,ri=!1,fr=e,As=!1,Er(),i.colorSpace=Bt,dt.uTexture.value=i,Fn.map=i,Fn.needsUpdate=!0,$g.style.display="none",Ro(),Yt()}function Po(i){var t;dt.uDepthMap.value!==fs&&dt.uDepthMap.value.dispose(),dt.uDepthMap.value=i,i.colorSpace=Mt,Lc.value.fromArray(ii.evidenceRange(i));const e=(t=i.image)==null?void 0:t.data;if(rr=0,e&&e.length>=4)for(let n=0;n{const n=As&&ni!==null,r=gs,s=!t&&!n;Qg(i,e,t),qt.setVideo(!!t),Po(ni??ii.flatTexture()),ni=null,n&&ir?vr.setSample(ir):vr.clear(),ir=null,ns=r,gs=!1,Di.hidden=!(n||ns),n?Di.textContent="수작업 테스트 Depth · AI 추정 아님":ns&&(Di.textContent="Depth 없음 · 평면 사진 테스트"),Rs("final"),Wc(),Xt&&(Xt.textContent="선택한 테스트 사진 불러오기"),s&&Qc(!0)},i=>{ri=!1,Yt(),(i||!si)&&(tn.textContent=i),ai.hidden=!i.includes("자동"),i&&(gr(),Xt&&(Xt.textContent="선택한 테스트 사진 불러오기"))});ai.onclick=()=>Hi.retry();const ev=new Bg("/assets/sample-pet-depth.png"),yr=new Ng(mt),tv=new Ig(Ne.domElement,(i,e)=>yr.add(i,e),Jg),Do=new Fg((i,e)=>yr.target.set(yt.clamp(i,-1,1),yt.clamp(e,-1,1)),i=>{tn.textContent=i}),Xc=document.querySelector("#image"),qc=document.querySelector("#video"),Ji=document.querySelector("#depth-image"),Xt=document.querySelector("#sample"),nv=document.querySelector("#test-photo"),iv=document.querySelector("#reference-strip"),rv=document.querySelector("#reference-status"),io=[document.querySelector("#reference-image-1"),document.querySelector("#reference-image-2")];iv.hidden=!1;const Yc=()=>{rv.hidden=!1};io.forEach(i=>i.addEventListener("error",Yc,{signal:ct.signal}));Promise.all([ko(()=>import("./reference1-CTRCB8p3.js"),[]),ko(()=>import("./reference2-BQxeTItX.js"),[])]).then(([i,e])=>{At||(io[0].src=i.default,io[1].src=e.default)}).catch(()=>{At||Yc()});const ci=document.querySelector("#effect"),sr=document.querySelector("#view-mode"),Zc=document.querySelector("#sensitivity"),la=document.querySelector("#depth-scale"),sv=document.querySelector("#camera-offset"),Kc=document.querySelector("#grid-size"),jc=document.querySelector("#gridOut"),oi=document.querySelector("#mosaic-style"),Gl=oi.closest("label"),ca=document.querySelector("#gloss-controls"),Vl=document.querySelector("#region-fixed-note"),rs=document.querySelector("#curvature"),ss=document.querySelector("#gloss-strength"),as=document.querySelector("#light-x"),os=document.querySelector("#light-y"),kl=document.querySelector("#glossOut"),Wl=document.querySelector("#lightXOut"),Xl=document.querySelector("#lightYOut"),av=document.querySelector("#cameraOut"),ov=document.querySelector("#sensitivityOut"),ql=document.querySelector("#depthOut"),ar=document.querySelector("#photo-zoom"),Yl=document.querySelector("#photoZoomOut"),or=document.querySelector("#photo-pan-x"),Zl=document.querySelector("#photoPanXOut"),lr=document.querySelector("#photo-pan-y"),Kl=document.querySelector("#photoPanYOut"),ua=document.querySelector("#photo-reset"),$c=document.querySelector("#reset"),ro=document.querySelector("#gyro"),lv=[_o,Dg,Lg];let Jc=1;function Lo(){const i=ci.value==="mosaic",e=i&&oi.value==="0";Gl&&(Gl.style.display=i?"grid":"none"),oi.disabled=!i,ca&&(ca.hidden=!i,ca.style.display=i?"grid":"none"),Vl&&(Vl.hidden=!e),[ss,as,os,rs].forEach(t=>{t&&(t.disabled=!i)})}function Er(){ar&&(ar.value=Dn.toFixed(2)),Yl&&(Yl.value=Dn.toFixed(2)),or&&(or.value=pr.toFixed(2)),Zl&&(Zl.value=pr.toFixed(2)),lr&&(lr.value=mr.toFixed(2)),Kl&&(Kl.value=mr.toFixed(2))}async function Qc(i=!1){if(dr.disabled||!(Dt.image instanceof HTMLImageElement))return;const e=Dt,t=Dt.image,n=++Qt;si=!0,tn.textContent="AI 모델을 준비하는 중입니다. 처음 실행하면 모델 파일을 다운로드합니다.",Yt();try{const r=await wo.getDepthMap(t);if(At||n!==Qt||Dt!==e||bs){r.dispose();return}Po(r),vr.clear(),ns=!1,Di.hidden=!1,Di.textContent="AI 추정 · Depth Anything V2 Small (상대 깊이, 0=뒤 · 1=앞)",Rs("final"),tn.textContent=i?"자동 AI 추정 depth를 적용했습니다.":"AI 추정 depth를 적용하고 Final 뷰로 돌아왔습니다.",Wc()}catch(r){if(!At&&n===Qt){const s=r instanceof Error?r.message:"알 수 없는 오류";tn.textContent=i?`자동 depth 생성 실패 (${s}). 평면 사진 배치를 유지합니다. AI 깊이 생성 버튼으로 다시 시도할 수 있습니다.`:`AI 깊이 생성 실패 (${s}). 다시 시도할 수 있으며 기존 depth는 유지됩니다.`}}finally{n===Qt&&(si=!1,Yt())}}dr.addEventListener("click",()=>{Qc()},{signal:ct.signal});Xc.onchange=i=>{var n;const e=i.target,t=(n=e.files)==null?void 0:n[0];t&&(Co(),Sn+=1,ws(),ri=!0,Yt(),gr(),Hi.load(t)),e.value=""};qc.onchange=i=>{var n;const e=i.target,t=(n=e.files)==null?void 0:n[0];t&&(Co(),Sn+=1,ws(),ri=!0,Yt(),gr(),Hi.load(t)),e.value=""};ar==null||ar.addEventListener("input",i=>{Dn=Number(i.target.value),li(),Er()},{signal:ct.signal});or==null||or.addEventListener("input",i=>{pr=Number(i.target.value),li(),Er()},{signal:ct.signal});lr==null||lr.addEventListener("input",i=>{mr=Number(i.target.value),li(),Er()},{signal:ct.signal});ua==null||ua.addEventListener("click",()=>{Dn=1,pr=0,mr=0,li(),Er()},{signal:ct.signal});Xt==null||Xt.addEventListener("click",async()=>{const i=++Sn,e=nv.value,t=e==="sample",n=t?"/assets/sample-pet.png":`/assets/qa/${e==="dog3"?"dog3.webp":`${e}.jpeg`}`;ws(),ri=!0,Yt(),Hi.cancelPending(),gr(),Xt.textContent=`불러오는 중: ${n.split("/").pop()}`,tn.textContent="";let r="";try{const s=await fetch(n);if(!s.ok)throw new Error("image");const a=await s.blob();if(At||i!==Sn)return;if(t){const o=await fetch("/assets/sample-pet-depth.png");if(!o.ok)throw new Error("depth");const l=await o.blob();if(At||i!==Sn)return;r=URL.createObjectURL(l);const c=new Image;if(c.src=r,await c.decode(),At||i!==Sn)return;const u=await ev.getDepthMap(c);if(At||i!==Sn){u.dispose();return}ni=u,ir=c,As=!0}gs=!t,Hi.load(new File([a],n.split("/").pop()??"test-photo",{type:s.headers.get("content-type")??"image/jpeg"})),t&&(tn.textContent="수작업 테스트 Depth · AI 추정 아님")}catch{!At&&i===Sn&&(ri=!1,Yt(),gr(),tn.textContent=t?"샘플 사진 또는 depth map을 읽지 못했습니다.":"테스트 사진을 읽지 못했습니다.",Xt.textContent="선택한 테스트 사진 불러오기")}finally{r&&URL.revokeObjectURL(r)}},{signal:ct.signal});Xt==null||Xt.addEventListener("click",Co,{signal:ct.signal});ci.addEventListener("change",i=>{const e=["mosaic","reeded","frosted"].indexOf(i.target.value);ps.fragmentShader=lv[e],ps.needsUpdate=!0,Lo()},{signal:ct.signal});sr==null||sr.addEventListener("change",i=>Rs(i.target.value),{signal:ct.signal});Zc.oninput=i=>{const e=Number(i.target.value);Jc=e,ov.value=e.toFixed(2)};la==null||la.addEventListener("input",i=>{const e=Math.min(Number(i.target.value),.4);dt.uDepthScale.value=e,li(),hr="",ql&&(ql.value=e.toFixed(2))},{signal:ct.signal});sv.addEventListener("input",i=>{const e=Number(i.target.value);yr.setMaxOffset(e),av.value=e.toFixed(2)},{signal:ct.signal});Kc.addEventListener("input",i=>{const e=Number(i.target.value);J.uGridSize.value=e,jc.value=e.toFixed(0),To()},{signal:ct.signal});oi.addEventListener("change",i=>{if(ci.value!=="mosaic")return;const e=Number(i.target.value);J.uMosaicStyle.value=e,J.uGridSize.value=e===0?13:24,J.uStrength.value=1,Kc.value=String(J.uGridSize.value),jc.value=String(J.uGridSize.value),To(),Lo()},{signal:ct.signal});rs==null||rs.addEventListener("input",i=>{const e=Number(i.target.value);J.uCurvature.value=e;const t=document.querySelector("#curvatureOut");t&&(t.value=e.toFixed(2))},{signal:ct.signal});ss==null||ss.addEventListener("input",i=>{const e=Number(i.target.value);J.uGlossStrength.value=e,kl&&(kl.value=e.toFixed(2))},{signal:ct.signal});as==null||as.addEventListener("input",i=>{const e=Number(i.target.value);J.uLightPosition.value.x=e,Wl&&(Wl.value=e.toFixed(2))},{signal:ct.signal});os==null||os.addEventListener("input",i=>{const e=Number(i.target.value);J.uLightPosition.value.y=e,Xl&&(Xl.value=e.toFixed(2))},{signal:ct.signal});Ji==null||Ji.addEventListener("change",async()=>{var r;ws();const i=Qt,e=(r=Ji.files)==null?void 0:r[0];if(!e)return;vs=!0,Yt(),vr.clear();const t=URL.createObjectURL(e);let n=null;try{const s=new Image;if(s.src=t,await s.decode(),At||i!==Qt)return;if(fr>0&&Math.abs(s.width/s.height-fr)>.02)throw new Error("aspect");if(n=ii.toTexture(s),At||i!==Qt){n.dispose(),n=null;return}Po(n),n=null,Di.hidden=!0,tn.textContent="수동 depth map 적용됨 (0=뒤, 1=앞)"}catch{!At&&i===Qt&&(tn.textContent="RGB와 종횡비가 다른 depth map입니다.")}finally{n==null||n.dispose(),URL.revokeObjectURL(t),i===Qt&&(Ji.value="",vs=!1,Yt())}},{signal:ct.signal});$c.onclick=()=>{yr.reset(),Do.reset()};ro.onclick=async()=>{ro.textContent=`Gyroscope: ${await Do.toggle()?"ON":"OFF"}`};const eu=new ResizeObserver(Ro);eu.observe(Es);Ro();Rs("final");Lo();Yt();let jl=performance.now(),Uo=0;function cv(){const i=J.uContentViewProjection.value.elements.map(n=>n.toFixed(4)).join(","),e=qt.matrixWorld.elements.map(n=>n.toFixed(4)).join(","),t=dt.uDepthMap.value;return[On,Dt.uuid,t.uuid,i,e,J.uGridSize.value,J.uStrength.value,J.uCurvature.value,J.uMosaicStyle.value,J.uPaneSize.value.x,J.uPaneSize.value.y,dt.uDepthScale.value,dt.uDepthBias.value,rn.width,rn.height,St.width,St.height].join("|")}function uv(){const i=qt.matrixWorld.elements.map(t=>t.toFixed(4)).join(","),e=dt.uDepthMap.value;return[On,ci.value,oi.value,Dt.uuid,e.uuid,J.uRegionAvailable.value,J.uGridSize.value,J.uMosaicStyle.value,J.uStrength.value,J.uRegionStrength.value,J.uCurvature.value,J.uGlassZ.value,J.uSourceZ.value,J.uPaneSize.value.x,J.uPaneSize.value.y,i,dt.uDepthScale.value,dt.uDepthBias.value,rn.width,rn.height,St.width,St.height,Ct.width,Ct.height].join("|")}function dv(){const i=Ne.getRenderTarget(),e=Ne.getClearColor(new Ye),t=Ne.getClearAlpha();Ne.setClearColor(0,0);for(const n of ln)Ne.setRenderTarget(n),Ne.clear(!0,!1,!1);Ne.setRenderTarget(i),Ne.setClearColor(e,t),er=0,no=!1,Mo.value=ln[0].texture}function $l(i){const e=uv();if(e!==Hl&&(dv(),Hl=e),!((On==="final"||On==="glass")&&ci.value==="mosaic"&&oi.value==="0"&&J.uRegionAvailable.value>.5&&J.uRegionStrength.value>.001&&J.uStrength.value>.001))return;const n=1-er;to.uPreviousHistory.value=ln[er].texture,to.uHistoryBlend.value=no?1-Math.exp(-i/.07):1,Ne.setRenderTarget(ln[n]),Ne.render(Hc,ms),Ne.setRenderTarget(null),er=n,no=!0,Mo.value=ln[er].texture}function hv(){if(!(ci.value==="mosaic"&&oi.value==="0"&&J.uRegionAvailable.value>.5&&J.uRegionStrength.value>.001&&J.uStrength.value>.001))return;const e=cv();!bs&&e===hr||(Ne.setRenderTarget(St),Ne.render(Uc,ms),Ne.setRenderTarget(Ct),Ne.render(Fc,ms),Ne.setRenderTarget(null),hr=e)}function tu(i){const e=Math.min((i-jl)/1e3,.1);jl=i,J.uViewOffset.value.copy(yr.update(e,Jc)),mt.updateMatrixWorld(!0),qt.updateMatrixWorld(!0),J.uPetWorldToLocal.value.copy(qt.matrixWorld).invert(),J.uContentViewProjection.value.multiplyMatrices(mt.projectionMatrix,mt.matrixWorldInverse),J.uContentInverseViewProjection.value.copy(J.uContentViewProjection.value).invert(),J.uContentCameraPosition.value.copy(mt.position),J.uTime.value=i/1e3;const t=vr.update(mt,qt,dt.uDepthScale.value,dt.uDepthBias.value,Es.clientWidth,J.uSourceZ.value,rr);if(zi.textContent=t,zi.hidden=!t,On==="final"||On==="glass"){Ne.setRenderTarget(rn),Ne.render(Bi,mt),J.uSceneTexture.value=rn.texture,hv(),$l(e),Ne.setRenderTarget(null),Ne.render(Pc,ms);const n=Ne.autoClear;Ne.autoClear=!1,Ne.clearDepth(),Ne.render(xo,mt),Ne.autoClear=n}else $l(e),Ne.setRenderTarget(null),Ne.render(Bi,mt);Uo=requestAnimationFrame(tu)}Uo=requestAnimationFrame(tu);function fv(){At=!0,Sn+=1,Qt+=1,wo.cancel(),dr.disabled=!0,kc(),ct.abort(),cancelAnimationFrame(Uo),eu.disconnect(),Xc.onchange=null,qc.onchange=null,ci.onchange=null,Zc.oninput=null,$c.onclick=null,ro.onclick=null,ai.onclick=null,tv.dispose(),Do.dispose(),Hi.dispose(),rn.dispose(),St.dispose(),Ct.dispose(),ln.forEach(i=>i.dispose()),Vc.geometry.dispose(),Gc.dispose(),Nc.geometry.dispose(),Ic.dispose(),Bc.geometry.dispose(),Oc.dispose(),Ts.dispose(),zc.dispose(),qi.forEach(i=>i.dispose()),Dt!==zt&&Dt.dispose(),dt.uDepthMap.value!==fs&&dt.uDepthMap.value.dispose(),fs.dispose(),qt.geometry.dispose(),So.dispose(),Dc.dispose(),Fn.dispose(),yo.geometry.dispose(),ps.dispose(),Mr.dispose(),zt.dispose(),Ne.domElement.remove(),Ne.dispose(),Sr.style.opacity="0",ai.remove(),zi.remove()}const pv=import.meta;var Jl;(Jl=pv.hot)==null||Jl.dispose(fv); diff --git a/dist/assets/index-JVljdMQi.css b/dist/assets/index-JVljdMQi.css deleted file mode 100644 index b755fc3..0000000 --- a/dist/assets/index-JVljdMQi.css +++ /dev/null @@ -1 +0,0 @@ -*{box-sizing:border-box}body{margin:0;background:#0d1117;color:#e6edf3;font:14px system-ui,sans-serif}main{min-height:100vh;display:flex;flex-direction:column}.stage{position:relative;flex:1;min-height:60vh;background:#111923}#canvas-wrap{position:absolute;top:0;right:0;bottom:0;left:0;touch-action:none}canvas{width:100%;height:100%;display:block;cursor:grab}canvas.is-dragging{cursor:grabbing}#empty{position:absolute;top:0;right:0;bottom:0;left:0;display:grid;place-items:center;color:#82909f;pointer-events:none;font-size:1rem}#hint{position:absolute;bottom:12px;left:50%;transform:translate(-50%);margin:0;padding:8px 12px;border-radius:20px;background:#0008;color:#c8d1dc;transition:opacity .5s}aside{padding:18px;display:grid;gap:12px;background:#161d27;border-top:1px solid #293544;min-width:0;overflow:hidden}h1{font-size:1.1rem;margin:0 0 4px}label{display:grid;gap:5px;color:#aeb9c6}input,select,button{font:inherit;color:inherit;background:#202b38;border:1px solid #3b4a5c;border-radius:7px;padding:9px}#test-photo{min-width:0;width:100%;max-width:100%}input[type=range]{padding:0;accent-color:#72b6ff}.upload{position:relative;cursor:pointer;text-align:center;background:#25364a;border-radius:7px;padding:10px;color:#dcecff}.upload input[type=file]{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);clip-path:inset(50%);white-space:nowrap;border:0}.upload:focus-within{outline:2px solid #8bc5ff;outline-offset:2px}output{float:right;color:#8bc5ff}button{cursor:pointer}#status{min-height:20px;margin:0;color:#ffbe79}#depth-provenance{margin:0;color:#aeb9c6;font-size:12px}#depth-debug{max-width:100%;overflow-x:auto;white-space:pre-wrap;word-break:break-word;font-size:11px}@media (min-width:720px){main{height:100dvh;min-height:0;flex-direction:row}.stage{min-height:0}aside{width:280px;flex:0 0 280px;align-content:start;border-top:0;border-left:1px solid #293544;overflow-y:auto}}.visual-column{display:flex;flex:1;flex-direction:column;min-width:0;min-height:0}.reference-strip{position:relative;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;width:100%;height:200px;flex:0 0 200px;padding:10px 12px;background:#0d1117;border-bottom:1px solid #293544;overflow:hidden}.reference-strip[hidden]{display:none}.reference-strip figure{display:grid;grid-template-rows:minmax(0,1fr) auto;gap:5px;min-width:0;min-height:0;margin:0;padding:6px;border:1px solid #293544;border-radius:8px;background:#111923}.reference-strip img{display:block;width:100%;height:100%;min-width:0;min-height:0;object-fit:contain}.reference-strip figcaption{text-align:center;color:#aeb9c6;font-size:12px}#reference-status{position:absolute;left:50%;bottom:16px;transform:translate(-50%);margin:0;padding:5px 8px;border-radius:6px;background:#000b;color:#ffbe79;font-size:12px;white-space:nowrap}#reference-status[hidden]{display:none}@media (min-width:720px){.visual-column{min-height:0}.reference-strip{height:clamp(180px,30vh,300px);flex-basis:clamp(180px,30vh,300px)}}details{border:1px solid #344255;border-radius:8px;padding:10px 12px;background:#111923}details summary{cursor:pointer;color:#dce6f2;font-weight:600}details[open] summary{margin-bottom:8px}.details-content{display:grid;gap:12px;padding-top:4px}.control-note,.control-help{margin:0;color:#9eacbb;font-size:12px}.control-help{margin-top:-7px}.core-optics{gap:12px} diff --git a/dist/assets/ort-wasm-simd-threaded.jsep-B0T3yYHD.wasm b/dist/assets/ort-wasm-simd-threaded.jsep-B0T3yYHD.wasm deleted file mode 100644 index b05d1ad..0000000 Binary files a/dist/assets/ort-wasm-simd-threaded.jsep-B0T3yYHD.wasm and /dev/null differ diff --git a/dist/assets/qa/dog1.jpeg b/dist/assets/qa/dog1.jpeg deleted file mode 100644 index d0dc8ae..0000000 Binary files a/dist/assets/qa/dog1.jpeg and /dev/null differ diff --git a/dist/assets/qa/dog2.jpeg b/dist/assets/qa/dog2.jpeg deleted file mode 100644 index af31ee7..0000000 Binary files a/dist/assets/qa/dog2.jpeg and /dev/null differ diff --git a/dist/assets/qa/dog3.webp b/dist/assets/qa/dog3.webp deleted file mode 100644 index 639a94c..0000000 Binary files a/dist/assets/qa/dog3.webp and /dev/null differ diff --git a/dist/assets/qa/dog4.jpeg b/dist/assets/qa/dog4.jpeg deleted file mode 100644 index 6fee9db..0000000 Binary files a/dist/assets/qa/dog4.jpeg and /dev/null differ diff --git a/dist/assets/reference1-BphJMCNh.js b/dist/assets/reference1-BphJMCNh.js new file mode 100644 index 0000000..d8d5b3c --- /dev/null +++ b/dist/assets/reference1-BphJMCNh.js @@ -0,0 +1 @@ +var e=`/assets/reference1-D4rK2azX.png`;export{e as default}; \ No newline at end of file diff --git a/dist/assets/reference1-CTRCB8p3.js b/dist/assets/reference1-CTRCB8p3.js deleted file mode 100644 index 1b644f8..0000000 --- a/dist/assets/reference1-CTRCB8p3.js +++ /dev/null @@ -1 +0,0 @@ -const e="/assets/reference1-D4rK2azX.png";export{e as default}; diff --git a/dist/assets/reference2-BQxeTItX.js b/dist/assets/reference2-BQxeTItX.js deleted file mode 100644 index 79e0573..0000000 --- a/dist/assets/reference2-BQxeTItX.js +++ /dev/null @@ -1 +0,0 @@ -const e="/assets/reference2-6y7JVIce.png";export{e as default}; diff --git a/dist/assets/reference2-DHNjbprc.js b/dist/assets/reference2-DHNjbprc.js new file mode 100644 index 0000000..915e975 --- /dev/null +++ b/dist/assets/reference2-DHNjbprc.js @@ -0,0 +1 @@ +var e=`/assets/reference2-6y7JVIce.png`;export{e as default}; \ No newline at end of file diff --git a/dist/assets/sample-pet-depth.json b/dist/assets/sample-pet-depth.json deleted file mode 100644 index 763bd63..0000000 --- a/dist/assets/sample-pet-depth.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "width": 415, - "height": 739, - "convention": "0 = far/background, 1 = near/foreground", - "source": "Hand-authored procedural Gaussian ellipses for local testing; not AI-estimated or physically measured.", - "landmarks": [ - { - "name": "nose", - "x": 235, - "y": 310, - "depth": 0.98 - }, - { - "name": "left-eye", - "x": 198, - "y": 278, - "depth": 0.68 - }, - { - "name": "right-eye", - "x": 249, - "y": 273, - "depth": 0.68 - }, - { - "name": "face", - "x": 221, - "y": 267, - "depth": 0.6 - }, - { - "name": "left-ear", - "x": 158, - "y": 213, - "depth": 0.43 - }, - { - "name": "right-ear", - "x": 262, - "y": 206, - "depth": 0.43 - }, - { - "name": "body", - "x": 139, - "y": 419, - "depth": 0.3 - }, - { - "name": "muzzle", - "x": 224, - "y": 305, - "depth": 0.82 - } - ] -} diff --git a/dist/assets/sample-pet-depth.png b/dist/assets/sample-pet-depth.png deleted file mode 100644 index c764035..0000000 Binary files a/dist/assets/sample-pet-depth.png and /dev/null differ diff --git a/dist/assets/sample-pet.png b/dist/assets/sample-pet.png deleted file mode 100644 index 320c9fa..0000000 Binary files a/dist/assets/sample-pet.png and /dev/null differ diff --git a/dist/assets/samples/dog1.jpg b/dist/assets/samples/dog1.jpg new file mode 100644 index 0000000..ac5ec47 Binary files /dev/null and b/dist/assets/samples/dog1.jpg differ diff --git a/dist/assets/samples/dog2.jpg b/dist/assets/samples/dog2.jpg new file mode 100644 index 0000000..905b076 Binary files /dev/null and b/dist/assets/samples/dog2.jpg differ diff --git a/dist/assets/samples/dog3.jpg b/dist/assets/samples/dog3.jpg new file mode 100644 index 0000000..513b01a Binary files /dev/null and b/dist/assets/samples/dog3.jpg differ diff --git a/dist/assets/samples/dog4.jpg b/dist/assets/samples/dog4.jpg new file mode 100644 index 0000000..80d5f8d Binary files /dev/null and b/dist/assets/samples/dog4.jpg differ diff --git a/dist/assets/samples/dog5.jpg b/dist/assets/samples/dog5.jpg new file mode 100644 index 0000000..18f9201 Binary files /dev/null and b/dist/assets/samples/dog5.jpg differ diff --git a/dist/assets/window/grandma-house-surround.glb b/dist/assets/window/grandma-house-surround.glb new file mode 100644 index 0000000..1061398 Binary files /dev/null and b/dist/assets/window/grandma-house-surround.glb differ diff --git a/dist/assets/window/grandma-wood-sash.glb b/dist/assets/window/grandma-wood-sash.glb new file mode 100644 index 0000000..6b4cf54 Binary files /dev/null and b/dist/assets/window/grandma-wood-sash.glb differ diff --git a/dist/fonts/BMKkubulim.woff b/dist/fonts/BMKkubulim.woff new file mode 100644 index 0000000..4a1a660 Binary files /dev/null and b/dist/fonts/BMKkubulim.woff differ diff --git a/dist/index.html b/dist/index.html index a93460d..d13b1f7 100644 --- a/dist/index.html +++ b/dist/index.html @@ -1,16 +1,242 @@ - + - Pet Behind Glass - - + + + Behind Glass · 할머니집 창가 + + +
-
-
+ +
+
+
+ + + + + + + +
+ +
+ behind glass + + +
+ +
+
+ +

behind glass

+

할머니 집에
멍멍이가 왔어요

+ +
+
+ + + 비워두어도 괜찮아요 · 이 브라우저에만 저장돼요 + +
+ + +
+ + + +
+ +
+ +

정말 첫 화면으로 갈까요?

+

돌아오려면 사진을 다시 골라야 해요.

+
+
+ +

메뉴

+
+ + + + + + +
+
+ +

어떤 멍멍이를 만나볼까요?

+

사진을 고른 뒤 아래 버튼을 눌러주세요

+
+ + + + + +
+ +
+ +

화면을 잠시 그리지 못했어요

+

그래픽 연결이 끊겼어요. 브라우저가 복구하면 같은 사진으로 돌아가요.
계속 이 화면이면 새로고침해 주세요.

+ +

새로고침하면 사진을 다시 선택해야 해요

+
+ +

B 유리를 그리지 못했어요

+

사진과 설정은 그대로예요. B를 다시 시도하거나 A 진단 모드를 직접 선택할 수 있어요.

+ + +
+ + +

현재 구도 저장

+
+

마음에 드는 현재 구도를 저장해 보세요

+ +
+
+ +

만든 사람

+
제작
horoli
버그 제보
sunha321@gmail.com
+ 리소스·라이선스 안내 +
+ + + + + - -

- -
+ +
+

사진을 선택하면 AI가 입체감을 준비해요

+ diff --git a/dist/licenses/BMKkubulim-OFL.txt b/dist/licenses/BMKkubulim-OFL.txt new file mode 100644 index 0000000..490ae30 --- /dev/null +++ b/dist/licenses/BMKkubulim-OFL.txt @@ -0,0 +1,105 @@ +Baemin Kkubulim font licensing + +Official font source: https://www.woowahan.com/fonts +Official copyright and license page: https://www.woowahan.com/fonts/license +OFL text source: https://openfontlicense.org/documents/OFL.txt +Retrieved 2026-10-06. Font-specific introductory notice and copyright/RFN statement below are copied from Woowa Brothers. Full OFL body is copied from SIL's official text. + +The intellectual property rights of Hanna, Hanna Air, Hanna Pro, Jua, Dohyeon, Yeonsung, KirangHaerang, Euljiro, and Euljiro 10 Years Later, Baemin Geullim, Baemin Euljiro OraeOrae, BM Kkubulim fonts are held by Woowa Brothers. + Fonts distributed free of charge by Baedal Minjok (Hanna, Jua, Dohyeon, Yeonsung, KirangHaerang, Hanna Air, Hanna Pro, Euljiro, Euljiro 10 Years Later, Baemin Geullim, Baemin Euljiro OraeOrae, BM kkubulim) can be modified and hanged freely and used by both individual and corporate users for commercial or non-profit purposes. + However, please note that sales of the font file (OTF/TTF) is prohibited. + Images of prints, advertisements (including online advertisements), and other products using free fonts distributed by Baemin (Hanna, Jua, Dohyeon, Yeonsung, KirangHaerang, Hanna Air, Hanna Pro, Euljiro, Euljiro 10 Years Later, Baemin Geullim, Baemin Euljiro OraeOrae, BM Kkubulim) may be used for the company’s data collection and research purposes. If you wish to opt out of such use, please feel free to contact our Customer Service Center (+82-1600-0987 / CS@woowahan.com). + Provided that the full text of the "Intellectual Property Guide and License" below is shown, the fonts may be bundled, redistributed, or sold with other software. + Copyright © 2013, Woowa Brothers Corporation (https://www.woowahan.com), with Reserved Font Name BM HANNA 11yrs old, BM HANNA 11yrs old OTF, BMHANNAAir_otf, BMHANNAAir_ttf, BMHANNAPro_otf, BMHANNAPro_ttf, BM JUA_TTF, BM JUA_OTF, BM DoHyeon, BM DoHyeon OTF, BM YEONSUNG, BM YEONSUNG OTF, BM KIRANGHAERANG, BM KIRANGHAERANG OTF, BMEULJIRO, BMEULJIROTTF, BM EULJITO 10 YEARS LATER, BM EULJITO 10 YEARS LATER TTF, BMEuljirooraeoraeOTF, BMkkubulimTTF, BMkkubulim. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + diff --git a/dist/licenses/Driverjs-MIT.txt b/dist/licenses/Driverjs-MIT.txt new file mode 100644 index 0000000..7ceaeef --- /dev/null +++ b/dist/licenses/Driverjs-MIT.txt @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) Kamran Ahmed + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/dist/licenses/HuggingFace-Jinja-MIT.txt b/dist/licenses/HuggingFace-Jinja-MIT.txt new file mode 100644 index 0000000..a3ce68e --- /dev/null +++ b/dist/licenses/HuggingFace-Jinja-MIT.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Hugging Face + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/dist/licenses/ONNX-Runtime-MIT.txt b/dist/licenses/ONNX-Runtime-MIT.txt new file mode 100644 index 0000000..48bc6bb --- /dev/null +++ b/dist/licenses/ONNX-Runtime-MIT.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Microsoft Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/dist/licenses/ONNX-Runtime-ThirdPartyNotices.txt b/dist/licenses/ONNX-Runtime-ThirdPartyNotices.txt new file mode 100644 index 0000000..75af6ad --- /dev/null +++ b/dist/licenses/ONNX-Runtime-ThirdPartyNotices.txt @@ -0,0 +1,6369 @@ +THIRD PARTY SOFTWARE NOTICES AND INFORMATION + +Do Not Translate or Localize + +This software incorporates material from third parties. Microsoft makes certain +open source code available at http://3rdpartysource.microsoft.com, or you may +send a check or money order for US $5.00, including the product name, the open +source component name, and version number, to: + +Source Code Compliance Team +Microsoft Corporation +One Microsoft Way +Redmond, WA 98052 +USA + +Notwithstanding any other terms, you may reverse engineer this software to the +extent required to debug changes to any libraries licensed under the GNU Lesser +General Public License. + +_____ + +Intel Math Kernel Library (Intel MKL) + +Intel Simplified Software License (Version April 2018) + +Copyright (c) 2018 Intel Corporation. + +Use and Redistribution. You may use and redistribute the software (the “Software”), without modification, +provided the following conditions are met: + +* Redistributions must reproduce the above copyright notice and the following terms of use in the Software +and in the documentation and/or other materials provided with the distribution. + +* Neither the name of Intel nor the names of its suppliers may be used to endorse or promote products +derived from this Software without specific prior written permission. + +* No reverse engineering, decompilation, or disassembly of this Software is permitted. + +Limited patent license. Intel grants you a world-wide, royalty-free, non-exclusive license under patents it now +or hereafter owns or controls to make, have made, use, import, offer to sell and sell (“Utilize”) this Software, +but solely to the extent that any such patent is necessary to Utilize the Software alone. The patent license +shall not apply to any combinations which include this software. No hardware per se is licensed hereunder. + +Third party and other Intel programs. “Third Party Programs” are the files listed in the “third-party-programs.txt” +text file that is included with the Software and may include Intel programs under separate license terms. +Third Party Programs, even if included with the distribution of the Materials, are governed by +separate license terms and those license terms solely govern your use of those programs. + +DISCLAIMER. THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED. THIS SOFTWARE IS +NOT INTENDED FOR USE IN SYSTEMS OR APPLICATIONS WHERE FAILURE OF THE SOFTWARE +MAY CAUSE PERSONAL INJURY OR DEATH AND YOU AGREE THAT YOU ARE FULLY RESPONSIBLE FOR ANY +CLAIMS, COSTS, DAMAGES, EXPENSES, AND ATTORNEYS’ FEES ARISING OUT OF ANY SUCH USE, +EVEN IF ANY CLAIM ALLEGES THAT INTEL WAS NEGLIGENT REGARDING THE DESIGN OR MANUFACTURE OF +THE MATERIALS. + +LIMITATION OF LIABILITY. IN NO EVENT WILL INTEL BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. YOU AGREE TO INDEMNIFY AND HOLD INTEL HARMLESS AGAINST ANY CLAIMS +AND EXPENSES RESULTING FROM YOUR USE OR UNAUTHORIZED USE OF THE SOFTWARE. + +No support. Intel may make changes to the Software, at any time without notice, and is not obligated to +support, update or provide training for the Software. + +Termination. Intel may terminate your right to use the Software in the event of your breach of this Agreement +and you fail to cure the breach within a reasonable period of time. + +Feedback. Should you provide Intel with comments, modifications, corrections, enhancements or other input +(“Feedback”) related to the Software Intel will be free to use, disclose, reproduce, license or otherwise +distribute or exploit the Feedback in its sole discretion without any obligations or restrictions of any kind, +including without limitation, intellectual property rights or licensing obligations. + +Compliance with laws. You agree to comply with all relevant laws and regulations governing your use, +transfer, import or export (or prohibition thereof) of the Software. + +Governing law. All disputes will be governed by the laws of the United States of America and the State of +Delaware without reference to conflict of law principles and subject to the exclusive jurisdiction of the state or +federal courts sitting in the State of Delaware, and each party agrees that it submits to the personal +jurisdiction and venue of those courts and waives any objections. The United Nations Convention on +Contracts for the International Sale of Goods (1980) is specifically excluded and will not apply to the +Software. + +*Other names and brands may be claimed as the property of others. + +_____ + +protocolbuffers/protobuf + +Copyright 2008 Google Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Code generated by the Protocol Buffer compiler is owned by the owner +of the input file used when generating it. This code is not +standalone and requires a support library to be linked with it. This +support library is itself covered by the above license. + +_____ + +madler/zlib + +The deflate format used by zlib was defined by Phil Katz. The deflate and +zlib specifications were written by L. Peter Deutsch. Thanks to all the +people who reported problems and suggested various improvements in zlib; they +are too numerous to cite here. + +Copyright notice: + + (C) 1995-2017 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* receiving +lengthy legal documents to sign. The sources are provided for free but without +warranty of any kind. The library has been entirely written by Jean-loup +Gailly and Mark Adler; it does not include third-party code. + +If you redistribute modified sources, we would appreciate that you include in +the file ChangeLog history information documenting your changes. Please read +the FAQ for more information on the distribution of modified source versions. + +_____ + +pybind/pybind11 + +Copyright (c) 2016 Wenzel Jakob , All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Please also refer to the file CONTRIBUTING.md, which clarifies licensing of +external contributions to this project including patches, pull requests, etc. + +_____ + +onnx +Open Neural Network Exchange + +Copyright (c) Facebook, Inc. and Microsoft Corporation. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +_____ + +Eigen + +MPL v2.0 +Mozilla Public License Version 2.0 + + +================================== + +1. Definitions + +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions + +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities + +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination + +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. + +_____ + +intel/dnnl + +Copyright 2016-2018 Intel Corporation + +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +sub-components: + +xbyak + +Copyright (c) 2007 MITSUNARI Shigeo. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +Neither the name of the copyright owner nor the names of its contributors may +be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +_____ + +Microsoft GSL + +Copyright (c) 2015 Microsoft Corporation. All rights reserved. + +This code is licensed under the MIT License (MIT). + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +_____ + +Tensorflow + +Copyright 2018 The TensorFlow Authors. All rights reserved. + +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, +and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by +the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all +other entities that control, are controlled by, or are under common +control with that entity. For the purposes of this definition, +"control" means (i) the power, direct or indirect, to cause the +direction or management of such entity, whether by contract or +otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity +exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, +including but not limited to software source code, documentation +source, and configuration files. + +"Object" form shall mean any form resulting from mechanical +transformation or translation of a Source form, including but +not limited to compiled object code, generated documentation, +and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or +Object form, made available under the License, as indicated by a +copyright notice that is included in or attached to the work +(an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object +form, that is based on (or derived from) the Work and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. For the purposes +of this License, Derivative Works shall not include works that remain +separable from, or merely link (or bind by name) to the interfaces of, +the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including +the original version of the Work and any modifications or additions +to that Work or Derivative Works thereof, that is intentionally +submitted to Licensor for inclusion in the Work by the copyright owner +or by an individual or Legal Entity authorized to submit on behalf of +the copyright owner. For the purposes of this definition, "submitted" +means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, +and issue tracking systems that are managed by, or on behalf of, the +Licensor for the purpose of discussing and improving the Work, but +excluding communication that is conspicuously marked or otherwise +designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity +on behalf of whom a Contribution has been received by Licensor and +subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable +copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the +Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable +(except as stated in this section) patent license to make, have made, +use, offer to sell, sell, import, and otherwise transfer the Work, +where such license applies only to those patent claims licensable +by such Contributor that are necessarily infringed by their +Contribution(s) alone or by combination of their Contribution(s) +with the Work to which such Contribution(s) was submitted. If You +institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work +or a Contribution incorporated within the Work constitutes direct +or contributory patent infringement, then any patent licenses +granted to You under this License for that Work shall terminate +as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the +Work or Derivative Works thereof in any medium, with or without +modifications, and in Source or Object form, provided that You +meet the following conditions: + +(a) You must give any other recipients of the Work or +Derivative Works a copy of this License; and + +(b) You must cause any modified files to carry prominent notices +stating that You changed the files; and + +(c) You must retain, in the Source form of any Derivative Works +that You distribute, all copyright, patent, trademark, and +attribution notices from the Source form of the Work, +excluding those notices that do not pertain to any part of +the Derivative Works; and + +(d) If the Work includes a "NOTICE" text file as part of its +distribution, then any Derivative Works that You distribute must +include a readable copy of the attribution notices contained +within such NOTICE file, excluding those notices that do not +pertain to any part of the Derivative Works, in at least one +of the following places: within a NOTICE text file distributed +as part of the Derivative Works; within the Source form or +documentation, if provided along with the Derivative Works; or, +within a display generated by the Derivative Works, if and +wherever such third-party notices normally appear. The contents +of the NOTICE file are for informational purposes only and +do not modify the License. You may add Your own attribution +notices within Derivative Works that You distribute, alongside +or as an addendum to the NOTICE text from the Work, provided +that such additional attribution notices cannot be construed +as modifying the License. + +You may add Your own copyright statement to Your modifications and +may provide additional or different license terms and conditions +for use, reproduction, or distribution of Your modifications, or +for any such Derivative Works as a whole, provided Your use, +reproduction, and distribution of the Work otherwise complies with +the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, +any Contribution intentionally submitted for inclusion in the Work +by You to the Licensor shall be under the terms and conditions of +this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify +the terms of any separate license agreement you may have executed +with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade +names, trademarks, service marks, or product names of the Licensor, +except as required for reasonable and customary use in describing the +origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or +agreed to in writing, Licensor provides the Work (and each +Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied, including, without limitation, any warranties or conditions +of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +PARTICULAR PURPOSE. You are solely responsible for determining the +appropriateness of using or redistributing the Work and assume any +risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, +whether in tort (including negligence), contract, or otherwise, +unless required by applicable law (such as deliberate and grossly +negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, +incidental, or consequential damages of any character arising as a +result of this License or out of the use or inability to use the +Work (including but not limited to damages for loss of goodwill, +work stoppage, computer failure or malfunction, or any and all +other commercial damages or losses), even if such Contributor +has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing +the Work or Derivative Works thereof, You may choose to offer, +and charge a fee for, acceptance of support, warranty, indemnity, +or other liability obligations and/or rights consistent with this +License. However, in accepting such obligations, You may act only +on Your own behalf and on Your sole responsibility, not on behalf +of any other Contributor, and only if You agree to indemnify, +defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason +of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2017, The TensorFlow Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +_____ + +Microsoft Cognitive Toolkit (CNTK) + +Copyright (c) Microsoft Corporation. All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +_____ + +NumPy License + +Copyright (c) 2005, NumPy Developers + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + Neither the name of the NumPy Developers nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +_____ + +Pytorch / Caffe2 + +From PyTorch: + +Copyright (c) 2016- Facebook, Inc (Adam Paszke) +Copyright (c) 2014- Facebook, Inc (Soumith Chintala) +Copyright (c) 2011-2014 Idiap Research Institute (Ronan Collobert) +Copyright (c) 2012-2014 Deepmind Technologies (Koray Kavukcuoglu) +Copyright (c) 2011-2012 NEC Laboratories America (Koray Kavukcuoglu) +Copyright (c) 2011-2013 NYU (Clement Farabet) +Copyright (c) 2006-2010 NEC Laboratories America (Ronan Collobert, Leon Bottou, Iain Melvin, Jason Weston) +Copyright (c) 2006 Idiap Research Institute (Samy Bengio) +Copyright (c) 2001-2004 Idiap Research Institute (Ronan Collobert, Samy Bengio, Johnny Mariethoz) + +From Caffe2: + +Copyright (c) 2016-present, Facebook Inc. All rights reserved. + +All contributions by Facebook: +Copyright (c) 2016 Facebook Inc. + +All contributions by Google: +Copyright (c) 2015 Google Inc. +All rights reserved. + +All contributions by Yangqing Jia: +Copyright (c) 2015 Yangqing Jia +All rights reserved. + +All contributions from Caffe: +Copyright(c) 2013, 2014, 2015, the respective contributors +All rights reserved. + +All other contributions: +Copyright(c) 2015, 2016 the respective contributors +All rights reserved. + +Caffe2 uses a copyright model similar to Caffe: each contributor holds +copyright over their contributions to Caffe2. The project versioning records +all such contribution and copyright details. If a contributor wants to further +mark their specific copyright on a particular contribution, they should +indicate their copyright solely in the commit message of the change when it is +committed. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the names of Facebook, Deepmind Technologies, NYU, NEC Laboratories America + and IDIAP Research Institute nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +_____ + +Caffe + +COPYRIGHT + +All contributions by the University of California: +Copyright (c) 2014-2017 The Regents of the University of California (Regents) +All rights reserved. + +All other contributions: +Copyright (c) 2014-2017, the respective contributors +All rights reserved. + +Caffe uses a shared copyright model: each contributor holds copyright over +their contributions to Caffe. The project versioning records all such +contribution and copyright details. If a contributor wants to further mark +their specific copyright on a particular contribution, they should indicate +their copyright solely in the commit message of the change when it is +committed. + +LICENSE + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +CONTRIBUTION AGREEMENT + +By contributing to the BVLC/caffe repository through pull-request, comment, +or otherwise, the contributor releases their content to the +license and copyright terms herein. + +_____ + +The LLVM Compiler Infrastructure + +============================================================================== +LLVM Release License +============================================================================== +University of Illinois/NCSA +Open Source License + +Copyright (c) 2003-2017 University of Illinois at Urbana-Champaign. +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. + +============================================================================== +Copyrights and Licenses for Third Party Software Distributed with LLVM: +============================================================================== +The LLVM software contains code written by third parties. Such software will +have its own individual LICENSE.TXT file in the directory in which it appears. +This file will describe the copyrights, license, and restrictions which apply +to that code. + +The disclaimer of warranty in the University of Illinois Open Source License +applies to all code in the LLVM Distribution, and nothing in any of the +other licenses gives permission to use the names of the LLVM Team or the +University of Illinois to endorse or promote products derived from this +Software. + +The following pieces of software have additional or alternate copyrights, +licenses, and/or restrictions: + +Program Directory +------- --------- +Google Test llvm/utils/unittest/googletest +OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex} +pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT} +ARM contributions llvm/lib/Target/ARM/LICENSE.TXT +md5 contributions llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h + +_____ + +google/benchmark + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +CONTRIBUTORS + +# People who have agreed to one of the CLAs and can contribute patches. +# The AUTHORS file lists the copyright holders; this file +# lists people. For example, Google employees are listed here +# but not in AUTHORS, because Google holds the copyright. +# +# Names should be added to this file only after verifying that +# the individual or the individual's organization has agreed to +# the appropriate Contributor License Agreement, found here: +# +# https://developers.google.com/open-source/cla/individual +# https://developers.google.com/open-source/cla/corporate +# +# The agreement for individuals can be filled out on the web. +# +# When adding J Random Contributor's name to this file, +# either J's name or J's organization's name should be +# added to the AUTHORS file, depending on whether the +# individual or corporate CLA was used. +# +# Names should be added to this file as: +# Name +# +# Please keep the list sorted. + +Albert Pretorius +Arne Beer +Billy Robert O'Neal III +Chris Kennelly +Christopher Seymour +David Coeurjolly +Deniz Evrenci +Dominic Hamon +Dominik Czarnota +Eric Fiselier +Eugene Zhuk +Evgeny Safronov +Federico Ficarelli +Felix Homann +Ismael Jimenez Martinez +Jern-Kuan Leong +JianXiong Zhou +Joao Paulo Magalhaes +John Millikin +Jussi Knuuttila +Kai Wolf +Kishan Kumar +Kaito Udagawa +Lei Xu +Matt Clarkson +Maxim Vafin +Nick Hutchinson +Oleksandr Sochka +Pascal Leroy +Paul Redmond +Pierre Phaneuf +Radoslav Yovchev +Raul Marin +Ray Glover +Robert Guo +Roman Lebedev +Shuo Chen +Tobias Ulvgård +Tom Madams +Yixuan Qiu +Yusuke Suzuki +Zbigniew Skowron + +AUTHORS + +# This is the official list of benchmark authors for copyright purposes. +# This file is distinct from the CONTRIBUTORS files. +# See the latter for an explanation. +# +# Names should be added to this file as: +# Name or Organization +# The email address is not required for organizations. +# +# Please keep the list sorted. + +Albert Pretorius +Arne Beer +Carto +Christopher Seymour +David Coeurjolly +Deniz Evrenci +Dirac Research +Dominik Czarnota +Eric Fiselier +Eugene Zhuk +Evgeny Safronov +Federico Ficarelli +Felix Homann +Google Inc. +International Business Machines Corporation +Ismael Jimenez Martinez +Jern-Kuan Leong +JianXiong Zhou +Joao Paulo Magalhaes +Jussi Knuuttila +Kaito Udagawa +Kishan Kumar +Lei Xu +Matt Clarkson +Maxim Vafin +MongoDB Inc. +Nick Hutchinson +Oleksandr Sochka +Paul Redmond +Radoslav Yovchev +Roman Lebedev +Shuo Chen +Steinar H. Gunderson +Stripe, Inc. +Yixuan Qiu +Yusuke Suzuki +Zbigniew Skowron + +_____ + +HalideIR + +Copyright (c) 2016 HalideIR contributors +Copyright (c) 2012-2014 MIT CSAIL, Google Inc., and other contributors +HalideIR is derived from the Halide project. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +_____ + +Distributed Machine Learning Common Codebase + +Copyright (c) 2015 by Contributors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +_____ + +DLPack: Open In Memory Tensor Structure + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2017 by Contributors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +_____ + +HowardHinnant/date + +The source code in this project is released using the MIT License. There is no +global license for the project because each file is licensed individually with +different author names and/or dates. + +If you contribute to this project, please add your name to the license of each +file you modify. If you have already contributed to this project and forgot to +add your name to the license, please feel free to submit a new P/R to add your +name to the license in each file you modified. + +For convenience, here is a copy of the MIT license found in each file except +without author names or dates: + +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +_____ + +FreeBSD: getopt.c file + +Copyright (c) 1987, 1993, 1994 +The Regents of the University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +3. Neither the name of the University nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. +_____ + + +google/googletest + +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +_____ + +G3log : Asynchronous logger with Dynamic Sinks + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +_____ + +Scikit-learn + +Copyright (c) 2007–2018 The scikit-learn developers. +All rights reserved. + + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + a. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + b. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + c. Neither the name of the Scikit-learn Developers nor the names of + its contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. + + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + +_____ + +google/re2 + +Copyright (c) 2009 The RE2 Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +_____ +onnx/onnx-tensorrt + +MIT License + +Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. +Copyright (c) 2018 Open Neural Network Exchange + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +_____ +nvidia/cutlass + +Copyright (c) 2017 - 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +SPDX-License-Identifier: BSD-3-Clause + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +_____ +Boost + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + + +_____ + +JDAI-CV/DNNLibrary + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [2019] [JD.com Inc. JD AI] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +_____ + +google/flatbuffers + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2014 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +_____ + +google/glog + +Copyright (c) 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +A function gettimeofday in utilities.cc is based on + +http://www.google.com/codesearch/p?hl=en#dR3YEbitojA/COPYING&q=GetSystemTimeAsFileTime%20license:bsd + +The license of this code is: + +Copyright (c) 2003-2008, Jouni Malinen and contributors +All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name(s) of the above-listed copyright holder(s) nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +_____ + +abseil-cpp +https://github.com/abseil/abseil-cpp + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +_____ + +microsoft/wil + +MIT License + +Copyright (c) Microsoft Corporation. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE + +_____ + +nlohmann/json + +MIT License + +Copyright (c) 2013-2019 Niels Lohmann + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +_____ + +dcleblanc/SafeInt + +MIT License + +Copyright (c) 2018 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +_____ +Open MPI + +3-Clause BSD License + +Most files in this release are marked with the copyrights of the +organizations who have edited them. The copyrights below are in no +particular order and generally reflect members of the Open MPI core +team who have contributed code to this release. The copyrights for +code used under license from other parties are included in the +corresponding files. + +Copyright (c) 2004-2010 The Trustees of Indiana University and Indiana + University Research and Technology + Corporation. All rights reserved. +Copyright (c) 2004-2017 The University of Tennessee and The University + of Tennessee Research Foundation. All rights + reserved. +Copyright (c) 2004-2010 High Performance Computing Center Stuttgart, + University of Stuttgart. All rights reserved. +Copyright (c) 2004-2008 The Regents of the University of California. + All rights reserved. +Copyright (c) 2006-2017 Los Alamos National Security, LLC. All rights + reserved. +Copyright (c) 2006-2017 Cisco Systems, Inc. All rights reserved. +Copyright (c) 2006-2010 Voltaire, Inc. All rights reserved. +Copyright (c) 2006-2017 Sandia National Laboratories. All rights reserved. +Copyright (c) 2006-2010 Sun Microsystems, Inc. All rights reserved. + Use is subject to license terms. +Copyright (c) 2006-2017 The University of Houston. All rights reserved. +Copyright (c) 2006-2009 Myricom, Inc. All rights reserved. +Copyright (c) 2007-2017 UT-Battelle, LLC. All rights reserved. +Copyright (c) 2007-2017 IBM Corporation. All rights reserved. +Copyright (c) 1998-2005 Forschungszentrum Juelich, Juelich Supercomputing + Centre, Federal Republic of Germany +Copyright (c) 2005-2008 ZIH, TU Dresden, Federal Republic of Germany +Copyright (c) 2007 Evergrid, Inc. All rights reserved. +Copyright (c) 2008 Chelsio, Inc. All rights reserved. +Copyright (c) 2008-2009 Institut National de Recherche en + Informatique. All rights reserved. +Copyright (c) 2007 Lawrence Livermore National Security, LLC. + All rights reserved. +Copyright (c) 2007-2017 Mellanox Technologies. All rights reserved. +Copyright (c) 2006-2010 QLogic Corporation. All rights reserved. +Copyright (c) 2008-2017 Oak Ridge National Labs. All rights reserved. +Copyright (c) 2006-2012 Oracle and/or its affiliates. All rights reserved. +Copyright (c) 2009-2015 Bull SAS. All rights reserved. +Copyright (c) 2010 ARM ltd. All rights reserved. +Copyright (c) 2016 ARM, Inc. All rights reserved. +Copyright (c) 2010-2011 Alex Brick . All rights reserved. +Copyright (c) 2012 The University of Wisconsin-La Crosse. All rights + reserved. +Copyright (c) 2013-2016 Intel, Inc. All rights reserved. +Copyright (c) 2011-2017 NVIDIA Corporation. All rights reserved. +Copyright (c) 2016 Broadcom Limited. All rights reserved. +Copyright (c) 2011-2017 Fujitsu Limited. All rights reserved. +Copyright (c) 2014-2015 Hewlett-Packard Development Company, LP. All + rights reserved. +Copyright (c) 2013-2017 Research Organization for Information Science (RIST). + All rights reserved. +Copyright (c) 2017-2018 Amazon.com, Inc. or its affiliates. All Rights + reserved. +Copyright (c) 2018 DataDirect Networks. All rights reserved. +Copyright (c) 2018-2019 Triad National Security, LLC. All rights reserved. + +$COPYRIGHT$ + +Additional copyrights may follow + +$HEADER$ + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +- Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer listed + in this license in the documentation and/or other materials + provided with the distribution. + +- Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +The copyright holders provide no reassurances that the source code +provided does not infringe any patent, copyright, or any other +intellectual property rights of third parties. The copyright holders +disclaim any liability to any recipient for claims brought against +recipient by any third party for infringement of that parties +intellectual property rights. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +_____ + +The Android Open Source Project + +Copyright (C) 2017 The Android Open Source Project +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +------ + +libprotobuf-mutator + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + ----- + + openucx/ucx + https://github.com/openucx/ucx + + Copyright (c) 2014-2015 UT-Battelle, LLC. All rights reserved. + Copyright (C) 2014-2020 Mellanox Technologies Ltd. All rights reserved. + Copyright (C) 2014-2015 The University of Houston System. All rights reserved. + Copyright (C) 2015 The University of Tennessee and The University + of Tennessee Research Foundation. All rights reserved. + Copyright (C) 2016-2020 ARM Ltd. All rights reserved. + Copyright (c) 2016 Los Alamos National Security, LLC. All rights reserved. + Copyright (C) 2016-2020 Advanced Micro Devices, Inc. All rights reserved. + Copyright (C) 2019 UChicago Argonne, LLC. All rights reserved. + Copyright (c) 2018-2020 NVIDIA CORPORATION. All rights reserved. + Copyright (C) 2020 Huawei Technologies Co., Ltd. All rights reserved. + Copyright (C) 2016-2020 Stony Brook University. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + ----- + + From PyTorch: + + Copyright (c) 2016- Facebook, Inc (Adam Paszke) + Copyright (c) 2014- Facebook, Inc (Soumith Chintala) + Copyright (c) 2011-2014 Idiap Research Institute (Ronan Collobert) + Copyright (c) 2012-2014 Deepmind Technologies (Koray Kavukcuoglu) + Copyright (c) 2011-2012 NEC Laboratories America (Koray Kavukcuoglu) + Copyright (c) 2011-2013 NYU (Clement Farabet) + Copyright (c) 2006-2010 NEC Laboratories America (Ronan Collobert, Leon Bottou, Iain Melvin, Jason Weston) + Copyright (c) 2006 Idiap Research Institute (Samy Bengio) + Copyright (c) 2001-2004 Idiap Research Institute (Ronan Collobert, Samy Bengio, Johnny Mariethoz) + + From Caffe2: + + Copyright (c) 2016-present, Facebook Inc. All rights reserved. + + All contributions by Facebook: + Copyright (c) 2016 Facebook Inc. + + All contributions by Google: + Copyright (c) 2015 Google Inc. + All rights reserved. + + All contributions by Yangqing Jia: + Copyright (c) 2015 Yangqing Jia + All rights reserved. + + All contributions from Caffe: + Copyright(c) 2013, 2014, 2015, the respective contributors + All rights reserved. + + All other contributions: + Copyright(c) 2015, 2016 the respective contributors + All rights reserved. + + Caffe2 uses a copyright model similar to Caffe: each contributor holds + copyright over their contributions to Caffe2. The project versioning records + all such contribution and copyright details. If a contributor wants to further + mark their specific copyright on a particular contribution, they should + indicate their copyright solely in the commit message of the change when it is + committed. + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the names of Facebook, Deepmind Technologies, NYU, NEC Laboratories America + and IDIAP Research Institute nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +_____ + + mpi4py + https://github.com/mpi4py/mpi4py/ + + ======================= + LICENSE: MPI for Python + ======================= + + :Author: Lisandro Dalcin + :Contact: dalcinl@gmail.com + + + Copyright (c) 2019, Lisandro Dalcin. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +_____ +huggingface/transformers + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +_____ +msgpack/msgpack-python + +Copyright (C) 2008-2011 INADA Naoki + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +_____ +lanpa/tensorboardX + +MIT License + +Copyright (c) 2017 Tzu-Wei Huang + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +_____ +tensorflow/tensorboard + +Copyright 2017 The TensorFlow Authors. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2017, The TensorFlow Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +_____ + +cerberus + +Cerberus is a lightweight and extensible data validation library for Python. + +ISC License + +Copyright (c) 2012-2016 Nicola Iarocci. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + +_____ + +MurmurHash3 + +MIT license + +https://github.com/aappleby/smhasher + +SMHasher is a test suite designed to test the distribution, collision, and +performance properties of non-cryptographic hash functions. +This is the home for the MurmurHash family of hash functions along with the +SMHasher test suite used to verify them. +SMHasher is released under the MIT license. +All MurmurHash versions are public domain software, and the author disclaims all copyright to their code. + +_____ + +gtest-ios-framework + +https://github.com/mestevens/gtest-ios-framework + +Copyright (c) 2013 Matthew Stevens + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +_____ + +DLPack + +https://github.com/dmlc/dlpack + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2017 by Contributors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +_____ + +emsdk + +MIT/Expat license + +https://github.com/emscripten-core/emsdk + +Copyright (c) 2018 Emscripten authors (see AUTHORS in Emscripten) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +---------------------------------------------------------------------------- + +This is the MIT/Expat License. For more information see: + +1. http://www.opensource.org/licenses/mit-license.php + +2. http://en.wikipedia.org/wiki/MIT_License + +_____ + +coremltools + +BSD-3-Clause License + +https://github.com/apple/coremltools + +Copyright (c) 2020, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +© 2021 GitHub, Inc. + +_____ + +react-native + +MIT License + +https://github.com/facebook/react-native + +Copyright (c) Facebook, Inc. and its affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +_____ + +pytorch/cpuinfo + +BSD 2-Clause "Simplified" License + +https://github.com/pytorch/cpuinfo + +Copyright (c) 2019 Google LLC +Copyright (c) 2017-2018 Facebook Inc. +Copyright (C) 2012-2017 Georgia Institute of Technology +Copyright (C) 2010-2012 Marat Dukhan + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +_____ + +SQLite Is Public Domain + +All of the code and documentation in SQLite has been dedicated to the public +domain by the authors. All code authors, and representatives of the companies +they work for, have signed affidavits dedicating their contributions to the +public domain and originals of those signed affidavits are stored in a firesafe +at the main offices of Hwaci. Anyone is free to copy, modify, publish, use, +compile, sell, or distribute the original SQLite code, either in source code +form or as a compiled binary, for any purpose, commercial or non-commercial, +and by any means. + +The previous paragraph applies to the deliverable code and documentation in +SQLite - those parts of the SQLite library that you actually bundle and ship +with a larger application. Some scripts used as part of the build process (for +example the "configure" scripts generated by autoconf) might fall under other +open-source licenses. Nothing from these build scripts ever reaches the final +deliverable SQLite library, however, and so the licenses associated with those +scripts should not be a factor in assessing your rights to copy and use the +SQLite library. + +All of the deliverable code in SQLite has been written from scratch. No code +has been taken from other projects or from the open internet. Every line of +code can be traced back to its original author, and all of those authors have +public domain dedications on file. So the SQLite code base is clean and is +uncontaminated with licensed code from other projects. + +_____ + +google/XNNPACK + +BSD License + +For XNNPACK software + +Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. +Copyright 2019 Google LLC + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name Facebook nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +_____ + +google/sentencepiece, https://github.com/google/sentencepiece +(included when statically linked with onnxruntime-extensions) + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +_____ + +dlfcn-win32/dlfcn-win32 is licensed under the MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +_____ + +The Python Imaging Library (PIL) is + + Copyright © 1997-2011 by Secret Labs AB + Copyright © 1995-2011 by Fredrik Lundh + +Pillow is the friendly PIL fork. It is + + Copyright © 2010-2023 by Alex Clark and contributors + +Like PIL, Pillow is licensed under the open source HPND License: + +By obtaining, using, and/or copying this software and/or its associated +documentation, you agree that you have read, understood, and will comply +with the following terms and conditions: + +Permission to use, copy, modify, and distribute this software and its +associated documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies, and that +both that copyright notice and this permission notice appear in supporting +documentation, and that the name of Secret Labs AB or the author not be +used in advertising or publicity pertaining to distribution of the software +without specific, written prior permission. + +SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + +_____ + +openssl/openssl, https://github.com/openssl/openssl + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + +_____ + +Tencent/rapidjson, https://github.com/Tencent/rapidjson + +Tencent is pleased to support the open source community by making RapidJSON available. + +Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. + +If you have downloaded a copy of the RapidJSON binary from Tencent, please note that the RapidJSON binary is licensed under the MIT License. +If you have downloaded a copy of the RapidJSON source code from Tencent, please note that RapidJSON source code is licensed under the MIT License, except for the third-party components listed below which are subject to different license terms. Your integration of RapidJSON into your own projects may require compliance with the MIT License, as well as the other licenses applicable to the third-party components included within RapidJSON. To avoid the problematic JSON license in your own projects, it's sufficient to exclude the bin/jsonchecker/ directory, as it's the only code under the JSON license. +A copy of the MIT License is included in this file. + +Other dependencies and licenses: + +Open Source Software Licensed Under the BSD License: +-------------------------------------------------------------------- + +The msinttypes r29 +Copyright (c) 2006-2013 Alexander Chemeris +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Open Source Software Licensed Under the JSON License: +-------------------------------------------------------------------- + +json.org +Copyright (c) 2002 JSON.org +All Rights Reserved. + +JSON_checker +Copyright (c) 2002 JSON.org +All Rights Reserved. + + +Terms of the JSON License: +--------------------------------------------------- + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +Terms of the MIT License: +-------------------------------------------------------------------- + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +_____ + +boostorg/boost, https://github.com/boostorg/boost + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +_____ + +libb64/libb64, https://github.com/libb64/libb64 + +Copyright-Only Dedication (based on United States law) or Public Domain Certification + +The person or persons who have associated work with this document (the "Dedicator" or "Certifier") hereby either (a) certifies that, to the best of his knowledge, the work of authorship identified is in the public domain of the country from which the work is published, or (b) hereby dedicates whatever copyright the dedicators holds in the work of authorship identified below (the "Work") to the public domain. A certifier, moreover, dedicates any copyright interest he may have in the associated work, and for these purposes, is described as a "dedicator" below. + +A certifier has taken reasonable steps to verify the copyright status of this work. Certifier recognizes that his good faith efforts may not shield him from liability if in fact the work certified is not in the public domain. + +Dedicator makes this dedication for the benefit of the public at large and to the detriment of the Dedicator's heirs and successors. Dedicator intends this dedication to be an overt act of relinquishment in perpetuity of all present and future rights under copyright law, whether vested or contingent, in the Work. Dedicator understands that such relinquishment of all rights includes the relinquishment of all rights to enforce (by lawsuit or otherwise) those copyrights in the Work. + +Dedicator recognizes that, once placed in the public domain, the Work may be freely reproduced, distributed, transmitted, used, modified, built upon, or otherwise exploited by anyone for any purpose, commercial or non-commercial, and in any way, including by methods that have not yet been invented or conceived. + +_____ + +posix pthread library, https://sourceforge.net/projects/pthreads4w + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +_____ + +Triton Inference Server & Client, https://github.com/triton-inference-server + +Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of NVIDIA CORPORATION nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +_____ + +microsoft/mimalloc, https://github.com/microsoft/mimalloc + +MIT License + +Copyright (c) 2018-2021 Microsoft Corporation, Daan Leijen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +_____ + +TensorFlow.js + +https://github.com/tensorflow/tfjs + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +—— + +curl/curl + +https://github.com/curl + +COPYRIGHT AND PERMISSION NOTICE + +Copyright (C) Daniel Stenberg, , and many +contributors, see the THANKS file. + +All rights reserved. + +Permission to use, copy, modify, and distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright +notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall not +be used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization of the copyright holder. + +_____ + +Mbed TLS + +https://github.com/Mbed-TLS/mbedtls + +Copyright The Mbed TLS Contributors + +Mbed TLS is available under the Apache License 2.0 OR the GNU General Public +License, version 2 or later. This distribution uses Mbed TLS under the Apache +License 2.0. The full Apache License 2.0 terms are reproduced above in this +file. + +_____ + +Intel neural-compressor + +https://github.com/intel/neural-compressor + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + ============================================================================ + + Copyright 2016-2019 Intel Corporation + Copyright 2018 YANDEX LLC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + This distribution includes third party software ("third party programs"). + This third party software, even if included with the distribution of + the Intel software, may be governed by separate license terms, including + without limitation, third party license terms, other Intel software license + terms, and open source software license terms. These separate license terms + govern your use of the third party programs as set forth in the + "THIRD-PARTY-PROGRAMS" file. + +_____ + +FlashAttention, https://github.com/Dao-AILab/flash-attention + +BSD 3-Clause License + +Copyright (c) 2022, the respective contributors, as shown by the AUTHORS file. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +_____ + +neural-speed + +https://github.com/intel/neural-speed + + Apache License + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + ============================================================================ + + Copyright 2016-2019 Intel Corporation + Copyright 2018 YANDEX LLC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + This distribution includes third party software ("third party programs"). + This third party software, even if included with the distribution of + the Intel software, may be governed by separate license terms, including + without limitation, third party license terms, other Intel software license + terms, and open source software license terms. These separate license terms + govern your use of the third party programs as set forth in the + "THIRD-PARTY-PROGRAMS" file. + +_____ + +dawn + +https://dawn.googlesource.com/dawn + + BSD 3-Clause License + + Copyright 2017-2023 The Dawn & Tint Authors + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +_____ + +KleidiAI + +https://gitlab.arm.com/kleidi/kleidiai + +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +Copyright 2024-2025 Arm Limited and/or its affiliates + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +_____ + +microsoft/cpp_client_telemetry, https://github.com/microsoft/cpp_client_telemetry/ + +Apache License + +Copyright (c) Microsoft Corporation. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +_____ +DeepSeek DeepGEMM (https://github.com/deepseek-ai/DeepGEMM) +Commit: 559d79fb6994a58b8a15b4b93bf13ccc16edf247 + +MIT License + +Copyright (c) 2025 DeepSeek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/dist/licenses/Threejs-MIT.txt b/dist/licenses/Threejs-MIT.txt new file mode 100644 index 0000000..d33709f --- /dev/null +++ b/dist/licenses/Threejs-MIT.txt @@ -0,0 +1,21 @@ +The MIT License + +Copyright © 2010-2024 three.js authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/dist/models/u2netp/LICENSES.txt b/dist/models/u2netp/LICENSES.txt new file mode 100644 index 0000000..278b5a4 --- /dev/null +++ b/dist/models/u2netp/LICENSES.txt @@ -0,0 +1,222 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +MIT License + +Copyright (c) 2020 Daniel Gatis + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/dist/models/u2netp/manifest.json b/dist/models/u2netp/manifest.json new file mode 100644 index 0000000..6a4cea6 --- /dev/null +++ b/dist/models/u2netp/manifest.json @@ -0,0 +1,182 @@ +{ + "name": "u2netp", + "revision": "sha256:309c8469258dda742793dce0ebea8e6dd393174f89934733ecc8b14c76f4ddd8", + "bytes": 4574861, + "sha256": "309c8469258dda742793dce0ebea8e6dd393174f89934733ecc8b14c76f4ddd8", + "md5": "8e83ca70e441ab06c318d82300c84806", + "source": { + "url": "https://github.com/danielgatis/rembg/releases/download/v0.0.0/u2netp.onnx", + "release": "v0.0.0", + "releaseAssetId": 85857953, + "assetUpdatedAt": "2022-11-24T19:22:32Z", + "publisher": "danielgatis", + "rembgRevision": "202e42649a8492a7c49f808de36608a7d1cbbfe3", + "upstreamU2NetRevision": "ac7e1c817ecab7c7dff5ce6b1abba61cd213ff29" + }, + "tensorContract": { + "input": [ + { + "name": "input.1", + "isTensor": true, + "type": "float32", + "shape": [ + 1, + 3, + 320, + 320 + ] + } + ], + "outputs": [ + { + "name": "1959", + "isTensor": true, + "type": "float32", + "shape": [ + 1, + 1, + 320, + 320 + ] + }, + { + "name": "1960", + "isTensor": true, + "type": "float32", + "shape": [ + 1, + 1, + 320, + 320 + ] + }, + { + "name": "1961", + "isTensor": true, + "type": "float32", + "shape": [ + 1, + 1, + 320, + 320 + ] + }, + { + "name": "1962", + "isTensor": true, + "type": "float32", + "shape": [ + 1, + 1, + 320, + 320 + ] + }, + { + "name": "1963", + "isTensor": true, + "type": "float32", + "shape": [ + 1, + 1, + 320, + 320 + ] + }, + { + "name": "1964", + "isTensor": true, + "type": "float32", + "shape": [ + 1, + 1, + 320, + 320 + ] + }, + { + "name": "1965", + "isTensor": true, + "type": "float32", + "shape": [ + 1, + 1, + 320, + 320 + ] + } + ], + "selectedOutput": "1959", + "resize": [ + 320, + 320 + ], + "layout": "NCHW", + "rgbScaling": "divide by max(maxRGB,1e-6)", + "mean": [ + 0.485, + 0.456, + 0.406 + ], + "std": [ + 0.229, + 0.224, + 0.225 + ], + "alphaPostprocess": "finite min/max normalize first output; uint8; restore canonical size" + }, + "conversionHistory": { + "status": "NOT FULLY VERIFIED", + "known": { + "1": [ + 6 + ], + "2": [ + "pytorch" + ], + "3": [ + "1.9" + ], + "8": [ + [ + [ + 2, + 0, + 11 + ] + ] + ] + }, + "missing": [ + "exact original checkpoint hash", + "export script/revision used for this release artifact", + "fully reproducible conversion chain" + ] + }, + "license": { + "upstreamU2Net": "Apache-2.0", + "rembgCode": "MIT", + "redistributionStatus": "NOT CLEARED FOR INTEGRATION: upstream license and publisher source verified, exact conversion chain remains unverified", + "licenseFiles": [ + "u2net-LICENSE", + "rembg-LICENSE.txt" + ] + }, + "qualityGate": "FAIL", + "browserRuntimeGate": "NOT RUN", + "localCpuEvidence": "u2netp-runtime-results.json", + "report": "model-gate.md", + "deploymentScope": { + "mode": "owner-private experiment", + "requiresExplicitMaskReviewForEveryPhoto": true, + "strictQualityGate": "failed", + "browserMobileGate": "not run", + "userApprovalDate": "2026-10-07", + "limitations": [ + "general foreground model, not dog-only semantic segmentation", + "body regions may disappear and background may remain", + "not a person-photo blocking mechanism" + ], + "downloadBytesMeaning": "Uncompressed model payload bytes, not measured network transfer bytes" + } +} diff --git a/dist/models/u2netp/model.onnx b/dist/models/u2netp/model.onnx new file mode 100644 index 0000000..4f21f9a Binary files /dev/null and b/dist/models/u2netp/model.onnx differ diff --git a/docs/ai-depth-baseline-noglass.png b/docs/ai-depth-baseline-noglass.png deleted file mode 100644 index 70949b6..0000000 Binary files a/docs/ai-depth-baseline-noglass.png and /dev/null differ diff --git a/docs/ai-depth-first-run.png b/docs/ai-depth-first-run.png deleted file mode 100644 index 2cccfdb..0000000 Binary files a/docs/ai-depth-first-run.png and /dev/null differ diff --git a/docs/ai-depth-task-brief.md b/docs/ai-depth-task-brief.md deleted file mode 100644 index 8d9fcb5..0000000 --- a/docs/ai-depth-task-brief.md +++ /dev/null @@ -1,34 +0,0 @@ -# 사진용 AI Depth 도입 - -2026-09-14 사용자 승인: Depth Anything V2 Small의 브라우저 로컬 추론 적용 검토 후 “그럼 해봐”. - -## 범위 - -- 사진을 선택하고 `AI 깊이 생성`을 눌러 정적 depth를 한 번 생성한다. -- Depth Anything V2 Small의 Apache 2.0 모델과 Transformers.js용 ONNX 변환본을 사용한다. 사진은 서버에 업로드하지 않는다. -- 모델은 기능을 처음 사용할 때 로드한다. 로딩·추론·실패 상태를 안내한다. -- 기존 DepthProvider → PetDepthMesh → RenderTarget → Glass 경로를 유지한다. -- 기존 수작업 샘플, 수동 depth 입력, 영상, Mosaic/Reeded/Frosted를 보존한다. -- AI 결과는 `AI 추정`으로 표시한다. 기존 수작업 depth와 실측 깊이를 구분한다. -- AI 결과 적용 후 No Glass로 전환하여 시차를 먼저 확인한다. - -## 구현·검증 기준 - -- 내부 depth는 0=뒤, 1=앞. 원본 RGB와 depth의 방향·비율·구도를 일치시킨다. -- 사진·영상·수동 depth 변경 및 종료 뒤 오래된 추론 결과가 적용되지 않게 한다. -- 추론 실패 시 기존 depth를 유지하고 다시 시도할 수 있다. -- 같은 샘플/구도에서 No Glass의 코·눈·얼굴 시차를 확인한 다음 Final의 Mosaic를 확인한다. -- 빌드·타입 검사와 실제 모델 실행·시각 검증 결과를 구분해 기록한다. -- 모바일의 다운로드·추론 시간·메모리는 실제로 측정하기 전에는 보장하지 않는다. - -## 이번 범위 외 - -실시간 영상 depth, 사진 리라이팅, 완전한 3D 복원, 유리 셰이더 전면 교체, 서버 추론은 포함하지 않는다. - -## 확인한 배포 자료 - -- https://github.com/DepthAnything/Depth-Anything-V2#license -- https://huggingface.co/onnx-community/depth-anything-v2-small-ONNX -- https://huggingface.co/docs/transformers.js/guides/webgpu - -Small만 상업 이용 가능한 Apache 2.0 조건으로 검토했으며 배포 시 라이선스 및 관련 고지를 보존한다. diff --git a/docs/ai-depth.md b/docs/ai-depth.md deleted file mode 100644 index 535d04d..0000000 --- a/docs/ai-depth.md +++ /dev/null @@ -1,38 +0,0 @@ -# AI depth for photos - -Choose a photo, then select **AI 깊이 생성**. The app snapshots the decoded photo, sends the snapshot to a module worker, and runs Depth Anything V2 Small through Transformers.js. WebGPU is tried first; the worker retries with WASM if WebGPU is unavailable or fails. The first run downloads the model files from Hugging Face. Inference itself runs in the browser, and the photo pixels are not sent to the model host. - -For the 2026-10-06 comparison, **개발 비교 → AI 깊이 모델** can select V2 Base, then **AI 깊이 생성** recomputes the same photo at input 770. Small remains the default; Base is a noncommercial test option. Switching the model keeps the current depth until inference succeeds and does not change zoom, pan, glass settings or photo–glass distance. Only one estimator is kept in the worker at a time. - -The same-photo Small/Base values, maximum masks and distance checks are recorded in [the Base QA report](qa-ai-depth-base-2026-10-06/report.md). Both models' maxima were in the nose region; Base did not establish a dramatic improvement of facial geometry. - -**최대 깊이 영역 확인** overlays the normalized Float32 maximum (`1`, pink), byte-texture maximum (`255/255`, cyan), and near-maximum (`≥0.99`, yellow) on the original photo. Counts and the first maximum's image coordinates are displayed. Clicking the preview or entering pixel coordinates shows both normalized model and byte-rendering values. The Float32 map is retained solely for inspection; the geometry still uses the existing byte texture and 128×128 mesh. A normalized maximum is guaranteed for any nonconstant finite prediction and is not evidence of correct anatomical depth. Byte rounding can create a larger `depth=1` area. - -Distance stays anchored to the **whole-map maximum**, without a semantic nose detector: `gap(pixel) = photoGlassGap + (maxDepth - byteDepth(pixel)) * depthScale`. The diagnostic gap is the map-point value in scene units, not cm or an exact measure of the interpolated mesh triangle. The maximum surface's gap is 0.04–0.60. Other points retain their depth differences and the RGB/Depth transform and refraction base plane move together. - -The source image is resized proportionally so its longest edge is at most 1024 pixels. Transformers.js preserves the image aspect ratio when preparing its model input and resizes the prediction to that same snapshot. The relative depth output is normalized per image to grayscale bytes: **0 is far/back and 255 is near/front**. The shader samples those bytes as normalized red-channel values from 0 to 1. Depth Anything V2 predicts relative inverse depth, so larger raw prediction values map to nearer points. This is an estimate, not measured distance or a complete 3D reconstruction. - -As of 2026-10-06, the processor's nominal input size is **770**, configured by `AI_DEPTH.inputSize` in `src/constants/depth.ts`. The shared estimator loader applies it to both WebGPU and WASM. Aspect ratio and alignment to multiples of 14 still determine the actual tensor dimensions; the final map remains the snapshot's size. The UI displays `입력 770`. Browser verification and the 518 comparison are recorded in [the 770 QA report](qa-ai-depth-770-2026-10-06/report.md). - -AI depth can be generated for still photos only. While the photo is changing, a manual depth map is loading, or inference is running, the button is disabled. A source change cancels the worker request. A successful result replaces the active depth and switches to **Final**; choose **No Glass** for parallax review. A failure leaves the current depth in place and the button can be used to retry. - -## Model and license - -- Model: [`onnx-community/depth-anything-v2-small-ONNX`](https://huggingface.co/onnx-community/depth-anything-v2-small-ONNX), Apache-2.0. -- Optional test model: [`onnx-community/depth-anything-v2-base-ONNX`](https://huggingface.co/onnx-community/depth-anything-v2-base-ONNX), CC-BY-NC-4.0. -- Runtime: [`@huggingface/transformers` 4.3.0](https://github.com/huggingface/transformers.js), Apache-2.0. -- The model follows [Depth Anything V2](https://github.com/DepthAnything/Depth-Anything-V2); the Small model is distributed under Apache-2.0 in the upstream project. - -The AI depth provenance label names the model. The deployed [third-party notice](../public/THIRD-PARTY-NOTICES.txt) and [Apache 2.0 license text](../public/licenses/Apache-2.0.txt) are copied into `dist/` by Vite. Model weights are cached by the browser runtime when available. - -## Browser smoke test - -Start the app on a local URL, then run `npm run ai-depth-smoke`. The script loads the supplied sample, performs real model inference, records the normalized worker result at the sample's nose, eye, face, ear, and body landmarks, captures No Glass before and after a drag, captures Final after the drag, checks 390-pixel horizontal overflow, captures a mobile screenshot, and switches photos during a second request to check stale-result cancellation. It records browser console/page/request errors alongside the results. - -Set `AI_DEPTH_BASE_URL` if Vite is running on a different local address. Set `CHROME_EXECUTABLE_PATH` or `PLAYWRIGHT_CHROMIUM_PATH` when using a specific installed Chrome/Chromium executable; without either variable, Playwright's default executable is used. The script does not hard-code a machine-specific browser path. Output is written to `test-results/ai-depth/`. - -## Validation - -On 2026-09-14, headless Chrome with WebGPU completed first-use model download and inference in 11.1 seconds. No Glass showed a recognizable dog face; Final Mosaic and Reeded/Frosted rendered without page errors. The captured normalized landmark depths were nose 0.722, left eye 0.694, right eye 0.651, ears 0.667/0.596, and body 0.671. These facial/object differences are subtle compared with the deliberately exaggerated hand-authored test map. The 390-pixel layout had no horizontal overflow, manual depth input remained usable, and switching photos during a second request prevented the stale AI result from applying. - -The browser console still reported ONNX CPU-assignment warnings and the existing missing-favicon 404; the page-error count was zero. Actual video playback, WASM-only runtime, and inference performance on a physical mobile device were not measured. diff --git a/docs/arrival-backend-operations.md b/docs/arrival-backend-operations.md new file mode 100644 index 0000000..c918c00 --- /dev/null +++ b/docs/arrival-backend-operations.md @@ -0,0 +1,119 @@ +# 방문·도착 집계 운영 및 이전 안내 + +이 안내는 Fastify + SQLite 서버 운영 절차다. 이번 ZIP에는 현재 소스와 집계 활성 서버용 빌드가 포함되어 있다. 실행 방법과 검증 범위는 루트의 README-서버실행.md를 확인한다. 사용자의 서버에 실제 배포한 기록은 아니다. + +## 데이터와 집계 기준 + +- 방문은 브라우저 UUID와 서버가 계산한 한국 날짜(Asia/Seoul)당 한 행이다. MAU는 해당 한국 달력 월의 서로 다른 UUID 수이며 일별 합계가 아니다. 페이지 진입 때 기록하고 열린 탭을 자정마다 새 방문으로 만들지 않는다. +- 도착은 현재 개인 사진의 유효한 AI 성공 때만 기록한다. 샘플·영상·직접 올린 깊이·실패·평면 보기는 제외한다. 샘플 방문도 MAU에는 남는다. +- 이름은 브라우저에서 NFC/공백 정리/20 Unicode code point 제한 후 사용하고 빈 이름만 `멍멍이`로 취급한다. UUID와 이름을 사진 시작 때 고정한 뒤 버전이 포함된 JSON 배열을 SHA-256으로 해시한다. 서버에는 방문 UUID 또는 도착 해시만 전송하며 사진·파일명·이름 원문을 보내지 않는다. +- 같은 UUID·같은 이름의 도착은 중복되지 않는다. 이름 변경·저장소 초기화·다른 기기는 추가 집계될 수 있다. 실제 사람이나 반려견의 정확한 고유 수가 아니다. 해시를 완전한 익명화로 보지 않는다. +- 요청은 3초 제한, 일시 장애·429·5xx만 최대 두 번 재시도한다. 페이지 종료나 오프라인으로 유실될 수 있으며 영구 오프라인 큐는 없다. 서버 장애가 사진 체험을 막지 않는다. + +## 하나의 프런트엔드 소스와 두 가지 빌드 + +사진 체험·화면·기능은 같은 `src` 소스를 사용한다. 기능 수정은 한 번만 하고, 정적 Site와 Fastify 서버용으로 각각 빌드한다. 두 개의 프런트엔드 복사본이나 별도 기능 브랜치를 장기 운영하지 않는다. 빌드 차이는 집계 활성 여부이며, 한 곳에 배포했다고 다른 곳에 자동 배포되는 것은 아니다. 이번 배포본은 현재 테스트 Site와 같은 소스 커밋에서 서버용으로 빌드했다. + +소스 및 `package-lock.json`을 함께 옮긴다. 지원 대상은 Node 24이며 `.node-version`의 검증된 패치를 사용한다. 대상 서버 OS/CPU에서 better-sqlite3 네이티브 모듈이 실제 로드되는지 먼저 확인한다. 이 작업에서 만든 `node_modules`를 다른 서버로 복사하지 않는다. + +```sh +npm ci +node -p "process.version + ' ' + process.platform + ' ' + process.arch" +node --input-type=module -e "import Database from 'better-sqlite3'; const db = new Database(':memory:'); console.log(db.prepare('select sqlite_version() as version').get()); db.close()" +npm run test:arrival +``` + +기존 정적 Site용 기본 빌드는 집계를 끈다. 집계 UUID 생성·저장소 읽기와 API 요청이 없다. + +```sh +npm run build +``` + +Fastify 서버와 함께 사용할 때만 집계 활성 빌드를 만든다. + +```sh +npm run build:server +``` + +두 명령 모두 빌드 출력은 `dist`다. 기존 Site에 집계 활성 결과물을 덮어 올리지 않는다. 빌드/타입 확인과 실제 브라우저·휴대폰 확인은 다르며 이후 배포 단계에서 별도로 검사한다. + +## 서버 환경과 데이터 위치 + +- `DB_PATH`: 반드시 명시한 절대경로. 소스·dist·public 밖의 영구 로컬 디스크에 둔다. 예: `/var/lib/behind-glass/analytics.sqlite`. +- `PORT`: 기본 3000. +- `HOST`: 기본 `127.0.0.1`. 외부 공개와 네트워크 설정 변경은 배포 승인 뒤 진행한다. +- `PUBLIC_ORIGIN`: 운영 환경에서 필수. 경로·쿼리·계정정보 없는 HTTP(S) origin. 예: `https://your-approved-host.example`. +- `NODE_ENV=production`: 운영 Origin 필수 검사를 사용한다. + +설치 경로·데이터 경로와 서비스 계정은 미래 서버에서 확정한다. 데이터 폴더와 파일은 해당 서비스 계정만 사용할 수 있게 하며, 디렉터리 0700/DB 0600 수준을 유지한다. 기존 권한을 넓히지 않는다. DB 본체와 WAL/SHM, 백업을 공개 정적 경로나 소스/빌드에 넣지 않는다. + +```sh +DB_PATH=/var/lib/behind-glass/analytics.sqlite \ +PUBLIC_ORIGIN=https://your-approved-host.example \ +NODE_ENV=production npm start +``` + +한 프로세스·한 SQLite 연결·한 서버 로컬 디스크를 전제로 한다. 클러스터 워커나 여러 컨테이너 복제본, 공유 네트워크 파일시스템으로 확장하지 않는다. 시작 시 버전 마이그레이션을 트랜잭션으로 적용하고 WAL과 제한된 busy timeout을 사용한다. SIGTERM/SIGINT로 정상 종료한 후 서비스 관리자에서 재시작한다. 새 릴리스로 바꾸거나 빌드 출력을 지워도 `DB_PATH`는 그대로 유지한다. + +## 공개 API와 운영 조회 + +공개 API는 다음 세 가지뿐이다. 관리자·식별자 목록·MAU HTTP 경로는 없다. + +- `POST /api/visits` JSON `{ "visitor_id": "UUID-v4" }` → 204 +- `POST /api/arrivals` JSON `{ "dog_id": "64자리 소문자 SHA-256" }` → 204 (신규와 중복 동일) +- `GET /api/arrivals/count` → `{ "count": 0 }` 같은 실제 누적 정수 + +1 KiB 본문 제한과 엄격한 형식·추가 필드 거부를 적용한다. 없는 API는 JSON 404다. 공개 화면의 숫자는 마지막 정상값을 유지하며 아직 성공한 조회가 없으면 숨긴다. + +MAU는 서버 터미널에서만 조회한다. 기존 DB를 읽기 전용으로 열며 오타 경로에 빈 DB를 만들지 않는다. + +```sh +DB_PATH=/var/lib/behind-glass/analytics.sqlite npm run --silent metrics -- --month 2026-10 +``` + +`--silent`는 npm의 실행 안내를 숨겨 JSON만 출력한다. 명령 결과는 월·MAU·누적 도착 합계뿐이다. 월은 한국 달력 기준 `YYYY-MM`이다. 방문 UUID·도착 해시를 출력하거나 운영 로그에 기록하지 않는다. + +## 일관된 백업과 복원 + +운영 중에는 SQLite backup API를 사용한다. WAL 모드에서 DB 본체 파일 하나만 복사하면 최신 기록을 잃을 수 있다. 백업 경로도 공개 루트 밖의 절대경로로 지정한다. 같은 경로와 기존 파일 덮어쓰기를 허용하지 않는다. + +```sh +DB_PATH=/var/lib/behind-glass/analytics.sqlite npm run --silent backup -- \ + --output /var/backups/behind-glass/analytics-2026-10-08.sqlite +``` + +복원 절차: + +1. 해당 DB를 사용하는 서버와 운영 명령을 모두 종료한다. 자동 재시작도 잠시 멈춘다. +2. 현재 DB/WAL/SHM을 덮어쓰지 말고 안전한 별도 보관 위치로 옮겨 복구 지점을 남긴다. +3. 검증할 백업을 새로운 비공개 데이터 경로로 복사하고 서비스 계정 소유·제한된 권한을 유지한다. 과거 WAL/SHM 파일과 섞지 않는다. +4. 다음처럼 복원된 파일의 무결성과 합계를 확인한다. 결과가 맞지 않으면 재시작하지 않는다. +5. `DB_PATH`를 검증된 복원 파일로 지정해 재시작한다. 집계/체험 동작을 확인한다. + +```sh +DB_PATH=/var/lib/behind-glass-restored/analytics.sqlite node --input-type=module -e \ + "import Database from 'better-sqlite3'; const db = new Database(process.env.DB_PATH, {readonly:true,fileMustExist:true}); console.log(db.pragma('integrity_check')); db.close()" +DB_PATH=/var/lib/behind-glass-restored/analytics.sqlite npm run --silent metrics -- --month 2026-10 +``` + +`integrity_check`가 `ok`인지 확인하고 백업 당시 합계와 비교한다. 백업·복원 성공은 QA에서 실제 임시 SQLite 파일을 사용해 확인한 범위와 미래 운영 데이터 복원을 구분한다. 정기 백업 스케줄과 보존 정책은 배포 단계에서 별도 결정한다. + +## 향후 HTTPS 프록시와 정적 파일 점검 + +이번 구현은 프록시나 방화벽을 설정하지 않는다. 배포 승인 뒤 같은 HTTPS origin에서 정적 앱과 `/api`가 함께 동작하도록 연결한다. `PUBLIC_ORIGIN`에는 사용자가 실제 접속하는 정확한 origin을 넣는다. + +Origin 검사와 메모리 기반 요청 제한은 허위 집계를 완전히 막는 인증 기능이 아니다. Origin 없는 비브라우저 요청도 가능하다. 제한 카운터는 프로세스 재시작 시 초기화한다. `trustProxy:false`를 유지하므로 프록시 뒤에서는 연결 IP를 공유해 제한을 함께 받을 수 있다. 임의 forwarded header를 신뢰하도록 즉석 변경하지 말고 배포 구조와 신뢰 경계를 검토한다. + +앱은 본문·UUID·해시·IP를 로그에 남기지 않는다. 프록시·호스팅의 기본 접속 로그에는 IP가 남을 수 있으므로 배포 전에 기록 범위·보존·접근 권한을 확인한다. + +HTML/API는 오래 캐시하지 않고, 해시 자산은 immutable 장기 캐시, 일반 정적 자산은 재검증한다. AI worker·모델·외부 ONNX WASM 다운로드 경로는 기존 설정을 유지한다. 별도 분석 서비스나 사진 업로드를 추가하지 않는다. CSP/COEP/COOP를 일괄 추가하면 기존 외부 AI 자산이 차단될 수 있으므로 이번 작업에서 변경하지 않는다. + +## 배포 전 남은 실제 확인 + +- 미래 서버의 Node/네이티브 의존성 설치, 데이터 권한·영구 저장·프로세스 재시작 +- 승인된 HTTPS 주소에서 실제 API와 정적 파일, 외부 모델/WASM 로딩 +- 실제 휴대폰/WebGL, 사진 선택·성공·실패·평면 보기·취소·이름 수정·샘플 흐름 +- 도착 숫자 표시와 스크린리더/IME 등 브라우저 상호작용 +- 프록시의 Origin 전달·캐시·요청 제한과 로그 정책 + +현재 클라우드 작업 공간을 상시 운영 서버로 약속하지 않으며, 실제 접속 주소는 배포가 확인될 때 별도로 제공한다. diff --git a/docs/asymmetric-window-validation.md b/docs/asymmetric-window-validation.md deleted file mode 100644 index 293e83f..0000000 --- a/docs/asymmetric-window-validation.md +++ /dev/null @@ -1,13 +0,0 @@ -# 비대칭 곡면·창 반사 보정 - -2026-09-11. Astra 설계, Luna 코드, 조정 에이전트 시각 검증. - -src/shaders/mosaic.frag의 높이/법선과 광택 두 블록만 수정. 기존 world pane/grid/RT/샘플링/UI 유지. - -- H=A(1-qx^4)(1-qy^4)(1+skew·q). 중심을 더 평탄하게 하고 고정 hash 기반 작은 비대칭을 적용. 높이 .009cell과 ±8% 편차로 과도한 테두리 경사 억제. 미분 법선은 굴절과 반사 공유. -- 반사 시선을 기존 조명 Z 평면에 교차시켜 부드러운 직사각형 광원 mask 계산. 반사 경계가 가는 격자로 보이는 초기 결과를 보고 smoothstep 범위 .78..1을 .45..1.15로 넓힘. 최대 흰색 혼합 gain .12 유지. -- 신규 API/자산/리라이팅 없음. README/AGENTS 갱신. 이전 shader는 docs/before-asymmetric-glass/에 보존. - -검증: Glass Only 조명XY0 전후 비교에서 둥근 반복 하이라이트가 직사각형 반사로 바뀜. 기본 샘플 Final에서 눈/코 정보 유지. 조명X +.6→-.6 및 실제 카메라 드래그 후 반사 영역 변화, 광택0에서도 곡면 굴절 보존 확인. 390x844 모바일 샘플 확인, override 복원. 최종 브라우저 error 로그 []. Luna npm.cmd run build 성공. - -한계: 셀 경계 반복이 완전히 사라지는 것은 아님. 단일 직사각형 광원 근사이며 환경맵/다중반사/실제 유리 두께는 없음. 이 변경에서 영상/실기기gyro/성능 측정은 재실행하지 않음. diff --git a/docs/baseline-shaders/frosted.frag b/docs/baseline-shaders/frosted.frag deleted file mode 100644 index c3486ac..0000000 --- a/docs/baseline-shaders/frosted.frag +++ /dev/null @@ -1,62 +0,0 @@ -uniform sampler2D uTexture; -uniform float uGridSize; -uniform float uStrength; -uniform vec2 uViewOffset; -uniform vec2 uResolution; -uniform float uTime; -uniform vec2 uPetSize; -uniform bool uIsVideo; - -varying vec2 vUv; -varying vec3 vWorldPosition; - -float hash(vec2 p) { return fract(sin(dot(p, vec2(41.3, 17.9))) * 15731.743); } -float noise(vec2 p) { - vec2 i = floor(p); - vec2 f = fract(p); - f = f * f * (3.0 - 2.0 * f); - return mix(mix(hash(i), hash(i + vec2(1.0, 0.0)), f.x), mix(hash(i + vec2(0.0, 1.0)), hash(i + vec2(1.0)), f.x), f.y); -} - -vec3 srgbToLinear(vec3 value) { - return mix(value / 12.92, pow((value + 0.055) / 1.055, vec3(2.4)), step(vec3(0.04045), value)); -} - -vec4 mediaSample(vec2 uv) { - vec3 background = srgbToLinear(vec3(17.0, 25.0, 35.0) / 255.0); - if (any(lessThan(uv, vec2(0.0))) || any(greaterThan(uv, vec2(1.0)))) return vec4(background, 1.0); - vec4 color = texture2D(uTexture, uv); - if (uIsVideo) color.rgb = srgbToLinear(color.rgb); - return color; -} - -vec2 hitUv(vec3 ray) { - float rayZ = abs(ray.z) < 0.0001 ? (ray.z < 0.0 ? -0.0001 : 0.0001) : ray.z; - float signedT = -vWorldPosition.z / rayZ; - return (vWorldPosition + ray * signedT).xy / uPetSize + 0.5; -} - -void main() { - vec2 stableUv = vUv * (uResolution / max(uResolution.y, 1.0)); - vec2 noisePos = stableUv * 9.0 + uViewOffset * 0.6; - vec2 randomNormal = vec2(noise(noisePos), noise(noisePos + vec2(23.7))) - vec2(0.5); - vec3 incident = normalize(vWorldPosition - cameraPosition); - vec3 normal = normalize(vec3(randomNormal * 0.32, 1.0)); - vec3 refracted = refract(incident, normal, 0.75); - vec2 centerUv = mix(hitUv(incident), hitUv(refracted), clamp(uStrength, 0.0, 1.0)); - vec2 radius = vec2(0.008) * clamp(uStrength, 0.0, 1.0); - vec4 color = vec4(0.0); - color += mediaSample(centerUv + vec2(-radius.x, -radius.y)); - color += mediaSample(centerUv + vec2(0.0, -radius.y)); - color += mediaSample(centerUv + vec2(radius.x, -radius.y)); - color += mediaSample(centerUv + vec2(-radius.x, 0.0)); - color += mediaSample(centerUv); - color += mediaSample(centerUv + vec2(radius.x, 0.0)); - color += mediaSample(centerUv + vec2(-radius.x, radius.y)); - color += mediaSample(centerUv + vec2(0.0, radius.y)); - color += mediaSample(centerUv + vec2(radius.x, radius.y)); - color /= 9.0; - color.a = 1.0; - gl_FragColor = color; - #include -} diff --git a/docs/baseline-shaders/mosaic.frag b/docs/baseline-shaders/mosaic.frag deleted file mode 100644 index 30854e5..0000000 --- a/docs/baseline-shaders/mosaic.frag +++ /dev/null @@ -1,56 +0,0 @@ -uniform sampler2D uTexture; -uniform float uGridSize; -uniform float uStrength; -uniform vec2 uViewOffset; -uniform vec2 uResolution; -uniform float uTime; -uniform vec2 uPetSize; -uniform bool uIsVideo; - -varying vec2 vUv; -varying vec3 vWorldPosition; - -float hash(vec2 p) { - return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453); -} - -vec3 srgbToLinear(vec3 value) { - return mix(value / 12.92, pow((value + 0.055) / 1.055, vec3(2.4)), step(vec3(0.04045), value)); -} - -vec4 mediaSample(vec2 uv) { - vec3 background = srgbToLinear(vec3(17.0, 25.0, 35.0) / 255.0); - if (any(lessThan(uv, vec2(0.0))) || any(greaterThan(uv, vec2(1.0)))) return vec4(background, 1.0); - vec4 color = texture2D(uTexture, uv); - if (uIsVideo) color.rgb = srgbToLinear(color.rgb); - return color; -} - -vec2 hitUv(vec3 ray) { - float rayZ = ray.z; - rayZ = abs(rayZ) < 0.0001 ? (rayZ < 0.0 ? -0.0001 : 0.0001) : rayZ; - float signedT = -vWorldPosition.z / rayZ; - return (vWorldPosition + ray * signedT).xy / uPetSize + 0.5; -} - -void main() { - vec2 grid = vec2(uGridSize, max(1.0, uGridSize * uPetSize.y / uPetSize.x)); - vec2 scaled = vUv * grid; - vec2 cell = floor(scaled); - vec2 local = fract(scaled) - 0.5; - float variation = mix(0.85, 1.15, hash(cell)); - vec2 lensLocal = local + uViewOffset * (0.12 + 0.08 * hash(cell + vec2(9.0))); - float bulge = max(0.0, 0.25 - dot(lensLocal, lensLocal)); - vec3 normal = normalize(vec3(-lensLocal * bulge * 1.8 * variation, 1.0)); - vec3 incident = normalize(vWorldPosition - cameraPosition); - vec3 refracted = refract(incident, normal, 0.75); - vec2 straightUv = hitUv(incident); - vec2 refractedUv = hitUv(refracted); - vec2 uv = mix(straightUv, refractedUv, clamp(uStrength, 0.0, 1.0)); - vec4 color = mediaSample(uv); - float edge = smoothstep(0.46, 0.5, max(abs(local.x), abs(local.y))); - color.rgb *= mix(1.0, 0.75, edge * clamp(uStrength, 0.0, 1.0)); - color.a = 1.0; - gl_FragColor = color; - #include -} diff --git a/docs/baseline-shaders/reeded.frag b/docs/baseline-shaders/reeded.frag deleted file mode 100644 index fd11cfd..0000000 --- a/docs/baseline-shaders/reeded.frag +++ /dev/null @@ -1,48 +0,0 @@ -uniform sampler2D uTexture; -uniform float uGridSize; -uniform float uStrength; -uniform vec2 uViewOffset; -uniform vec2 uResolution; -uniform float uTime; -uniform vec2 uPetSize; -uniform bool uIsVideo; - -varying vec2 vUv; -varying vec3 vWorldPosition; - -float hash(float value) { return fract(sin(value * 91.7) * 43758.5453); } - -vec3 srgbToLinear(vec3 value) { - return mix(value / 12.92, pow((value + 0.055) / 1.055, vec3(2.4)), step(vec3(0.04045), value)); -} - -vec4 mediaSample(vec2 uv) { - vec3 background = srgbToLinear(vec3(17.0, 25.0, 35.0) / 255.0); - if (any(lessThan(uv, vec2(0.0))) || any(greaterThan(uv, vec2(1.0)))) return vec4(background, 1.0); - vec4 color = texture2D(uTexture, uv); - if (uIsVideo) color.rgb = srgbToLinear(color.rgb); - return color; -} - -vec2 hitUv(vec3 ray) { - float rayZ = abs(ray.z) < 0.0001 ? (ray.z < 0.0 ? -0.0001 : 0.0001) : ray.z; - float signedT = -vWorldPosition.z / rayZ; - return (vWorldPosition + ray * signedT).xy / uPetSize + 0.5; -} - -void main() { - float ridgeCount = max(1.0, uGridSize * uPetSize.x / uPetSize.y); - float ridgeCoordinate = vUv.x * ridgeCount; - float ridgeCell = floor(ridgeCoordinate); - float phase = fract(ridgeCoordinate) * 6.2831853; - float ridge = sin(phase + uViewOffset.x * 0.9); - float ridgeVariation = mix(0.92, 1.08, hash(ridgeCell)); - vec3 normal = normalize(vec3(-ridge * 0.34 * ridgeVariation, 0.0, 1.0)); - vec3 incident = normalize(vWorldPosition - cameraPosition); - vec3 refracted = refract(incident, normal, 0.75); - vec2 uv = mix(hitUv(incident), hitUv(refracted), clamp(uStrength, 0.0, 1.0)); - vec4 color = mediaSample(uv); - color.a = 1.0; - gl_FragColor = color; - #include -} diff --git a/docs/before-asymmetric-glass/mosaic.frag b/docs/before-asymmetric-glass/mosaic.frag deleted file mode 100644 index afd9031..0000000 --- a/docs/before-asymmetric-glass/mosaic.frag +++ /dev/null @@ -1,31 +0,0 @@ -uniform sampler2D uSceneTexture; -uniform mat4 uContentViewProjection,uContentInverseViewProjection; -uniform vec3 uContentCameraPosition,uLightPosition; -uniform float uGlassZ,uGridSize,uStrength,uMosaicStyle,uCurvature,uGlossStrength; -uniform vec2 uViewOffset,uPetSize,uPaneSize; -uniform vec4 uPaneRect; -varying vec2 vUv; -vec2 projectUv(vec3 p){vec4 c=uContentViewProjection*vec4(p,1.);float w=abs(c.w)<.0001?(c.w<0.?-.0001:.0001):c.w;return c.xy/w*.5+.5;} -vec4 sampleScene(vec2 uv){return texture2D(uSceneTexture,clamp(uv,0.,1.));} -vec4 samplePane(vec2 pane){return sampleScene(projectUv(vec3((pane-.5)*uPaneSize,uGlassZ)));} -float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);} -vec2 hash2(vec2 p){return vec2(hash(p),hash(p+vec2(19.19,73.73)));} -float safeZ(float z){return abs(z)<.0001?(z<0.?-.0001:.0001):z;} -vec3 bend(vec3 i,vec3 n){vec3 r=refract(i,n,.75);return length(r)<.0001?i:r;} -float softLimit(float value,float limit){return value*limit/(limit+abs(value));} -void main(){ - if(uStrength<=.001){gl_FragColor=sampleScene(vUv); - #include - return;} - vec4 f=uContentInverseViewProjection*vec4(vUv*2.-1.,1.,1.);float fw=abs(f.w)<.0001?(f.w<0.?-.0001:.0001):f.w;vec3 farWorld=f.xyz/fw;vec3 i=normalize(farWorld-uContentCameraPosition);float gt=(uGlassZ-uContentCameraPosition.z)/safeZ(i.z);vec3 gh=uContentCameraPosition+i*gt; - vec2 paneUv=gh.xy/uPaneSize+.5;vec2 grid=vec2(uGridSize,max(1.,uGridSize*uPaneSize.y/uPaneSize.x));vec2 gridUv=paneUv*grid,cell=floor(gridUv),local=fract(gridUv)-.5,cellSize=1./grid,random=hash2(cell);float style=clamp(uMosaicStyle,0.,1.),cellWorld=min(uPaneSize.x/grid.x,uPaneSize.y/grid.y); - if(paneUv.x<0.||paneUv.x>1.||paneUv.y<0.||paneUv.y>1.){gl_FragColor=sampleScene(vUv); - #include - return;} - float height=.016*cellWorld*clamp(uCurvature,0.,1.)*mix(.88,1.12,hash(cell+vec2(41.7,17.3)));vec2 q=2.*local;vec2 grad=4.*height/cellWorld*vec2(q.x*(1.-q.y*q.y),q.y*(1.-q.x*q.x));vec3 nCurved=normalize(vec3(grad+(random-.5)*.012,1.)),nFacet=normalize(vec3((random-.5)*.012,1.)); - vec3 straightHit=gh+i*(-gh.z/safeZ(i.z));vec3 facetRay=bend(i,nFacet),curvedRay=bend(i,nCurved);vec3 facetHit=gh+facetRay*(-gh.z/safeZ(facetRay.z)),curvedHit=gh+curvedRay*(-gh.z/safeZ(curvedRay.z));vec2 base=facetHit.xy-straightHit.xy,curve=curvedHit.xy-facetHit.xy;vec2 worldDelta=vec2(softLimit(base.x,cellWorld*.08),softLimit(base.y,cellWorld*.08));vec2 d=curve/cellWorld;worldDelta+=vec2(.3*d.x/(.3+abs(d.x)),.3*d.y/(.3+abs(d.y)))*cellWorld; - vec2 sourceCenter=(cell+.5)/grid+(random-.5)*.20*cellSize+worldDelta/uPaneSize;vec2 widths=mix(vec2(.72),vec2(1.08),hash2(cell+vec2(7.2,3.1)));if(style>.5)widths=mix(vec2(.82),vec2(1.12),hash2(cell+vec2(11.4,9.8)));float angle=(random.x-.5)*.08,c=cos(angle),s=sin(angle);vec2 sampleUv=sourceCenter+mat2(c,-s,s,c)*(local*cellSize)*widths; - float edgeDistance=min(min(paneUv.x,paneUv.y),min(1.-paneUv.x,1.-paneUv.y));float edgeWeight=smoothstep(0.,max(cellSize.x,cellSize.y)*.75,edgeDistance);float strength=clamp(uStrength,0.,1.)*edgeWeight;vec2 blurStep=cellSize*mix(.006,.012,hash(cell+vec2(5.)));vec2 centerUv=mix(paneUv,sampleUv,strength);vec4 color=samplePane(centerUv)*.4;color+=samplePane(mix(paneUv,sampleUv+vec2(blurStep.x,0.),strength))*.15;color+=samplePane(mix(paneUv,sampleUv-vec2(blurStep.x,0.),strength))*.15;color+=samplePane(mix(paneUv,sampleUv+vec2(0.,blurStep.y),strength))*.15;color+=samplePane(mix(paneUv,sampleUv-vec2(0.,blurStep.y),strength))*.15;color.a=1.; - vec3 l=normalize(uLightPosition-gh),v=normalize(uContentCameraPosition-gh),h=normalize(l+v);float spec=pow(max(dot(nCurved,h),0.),160.);float gloss=spec*clamp(uGlossStrength,0.,1.)*.12*edgeWeight*clamp(uStrength,0.,1.);color.rgb=mix(color.rgb,vec3(1.),gloss);gl_FragColor=color; - #include -} diff --git a/docs/before-cell-curvature/main.ts b/docs/before-cell-curvature/main.ts deleted file mode 100644 index 1968751..0000000 --- a/docs/before-cell-curvature/main.ts +++ /dev/null @@ -1,172 +0,0 @@ -import * as THREE from 'three'; -import './style.css'; -import vertexShader from './shaders/common.vert?raw'; -import mosaicShader from './shaders/mosaic.frag?raw'; -import reededShader from './shaders/reeded.frag?raw'; -import frostedShader from './shaders/frosted.frag?raw'; -import { MediaLoader } from './input/MediaLoader'; -import { PointerController } from './input/PointerController'; -import { CameraController } from './input/CameraController'; -import { GyroController } from './input/GyroController'; -import { StaticDepthProvider } from './depth/StaticDepthProvider'; -import { DepthProcessor } from './depth/DepthProcessor'; -import { PetDepthMesh } from './objects/PetDepthMesh'; -import { DepthDebug } from './depth/DepthDebug'; -import glassScreenVertex from './shaders/glassScreen.vert?raw'; - -const wrap = document.querySelector('#canvas-wrap') as HTMLElement; -const status = document.querySelector('#status') as HTMLElement; -const empty = document.querySelector('#empty') as HTMLElement; -const hintElement = document.querySelector('#hint') as HTMLElement; -hintElement.style.opacity = '0'; -const renderer = new THREE.WebGLRenderer({ antialias: true }); -renderer.setPixelRatio(Math.min(devicePixelRatio, 1.5)); -wrap.append(renderer.domElement); -const scene = new THREE.Scene(); -const glassScene = new THREE.Scene(); -scene.background = new THREE.Color(0x111923); -const camera = new THREE.PerspectiveCamera(40, 1, 0.1, 100); -camera.position.z = 3; -const geometry = new THREE.PlaneGeometry(1, 1); -const emptyTex = new THREE.DataTexture(new Uint8Array([38, 48, 62, 255]), 1, 1); -emptyTex.needsUpdate = true; -const petMat = new THREE.MeshBasicMaterial({ map: emptyTex }); -const pet = new THREE.Mesh(geometry, petMat); -scene.add(pet); -const depthMap: THREE.Texture = DepthProcessor.flatTexture(); -const petDepth = new PetDepthMesh(emptyTex, depthMap, 0.25, 0); -const petDepthMaterial = petDepth.material; -const depthUniforms = petDepthMaterial.uniforms; -scene.add(petDepth); -const uniforms = { uSceneTexture: { value: emptyTex as THREE.Texture }, uContentViewProjection: { value: new THREE.Matrix4() }, uContentInverseViewProjection: { value: new THREE.Matrix4() }, uContentCameraPosition: { value: new THREE.Vector3() }, uLightPosition: { value: new THREE.Vector3(0.6, 0.8, 2.6) }, uGlassZ: { value: 0.6 }, uGridSize: { value: 28 }, uMosaicStyle: { value: 0 }, uStrength: { value: 0.9 }, uGlossStrength: { value: 0.55 }, uViewOffset: { value: new THREE.Vector2() }, uPaneRect: { value: new THREE.Vector4(0, 0, 1, 1) }, uResolution: { value: new THREE.Vector2() }, uTime: { value: 0 }, uPetSize: { value: new THREE.Vector2(1, 1) } }; -const glassMat = new THREE.ShaderMaterial({ uniforms, vertexShader: glassScreenVertex, fragmentShader: mosaicShader }); -const glass = new THREE.Mesh(new THREE.PlaneGeometry(2, 2), glassMat); -glassScene.add(glass); -const postCamera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1); -const renderTarget = new THREE.WebGLRenderTarget(1, 1, { colorSpace: THREE.NoColorSpace, type: THREE.HalfFloatType, depthBuffer: true }); -let active: THREE.Texture = emptyTex; -let aspect = 1; -let mode = 'noglass'; -let hintTimeout = 0; -let pendingPairDepth: THREE.Texture | null = null; -let mediaRequest = 0; -let depthRequest = 0; -let disposed = false; -const listenerAbort = new AbortController(); -function clearPendingPair(): void { if (pendingPairDepth) pendingPairDepth.dispose(); pendingPairDepth = null; } -function resize(): void { - const bounds = wrap.getBoundingClientRect(); - renderer.setSize(bounds.width, bounds.height, false); - camera.aspect = bounds.width / bounds.height; - camera.updateProjectionMatrix(); - const height = 1.7; - const scale = Math.min(height * bounds.width / bounds.height / aspect, height); - pet.scale.set(scale * aspect, scale, 1); - petDepth.scale.copy(pet.scale); - uniforms.uPetSize.value.set(pet.scale.x, pet.scale.y); - uniforms.uResolution.value.set(bounds.width, bounds.height); - const glassHeight = 2 * (camera.position.z - 0.6) * Math.tan(THREE.MathUtils.degToRad(camera.fov / 2)); - uniforms.uPetSize.value.set(glassHeight * camera.aspect, glassHeight); - const neutralGlassHeight = 2 * 3 * Math.tan(THREE.MathUtils.degToRad(40 / 2)); - const neutralGlassWidth = neutralGlassHeight * camera.aspect; - uniforms.uPaneRect.value.set(Math.max(0, 0.5 - pet.scale.x / (2 * neutralGlassWidth)), Math.max(0, 0.5 - pet.scale.y / (2 * neutralGlassHeight)), Math.min(1, 0.5 + pet.scale.x / (2 * neutralGlassWidth)), Math.min(1, 0.5 + pet.scale.y / (2 * neutralGlassHeight))); - renderTarget.setSize(Math.max(1, Math.floor(bounds.width * Math.min(devicePixelRatio, 1.5))), Math.max(1, Math.floor(bounds.height * Math.min(devicePixelRatio, 1.5)))); -} -function hint(): void { - window.clearTimeout(hintTimeout); - hintElement.style.opacity = '1'; - hintTimeout = window.setTimeout(() => { hintElement.style.opacity = '0'; }, 2000); -} -function applyMedia(texture: THREE.Texture, mediaAspect: number, video: HTMLVideoElement | null): void { - if (active !== emptyTex) active.dispose(); - active = texture; aspect = mediaAspect; - texture.colorSpace = THREE.SRGBColorSpace; - depthUniforms.uTexture.value = texture; - petMat.map = texture; petMat.needsUpdate = true; - empty.style.display = 'none'; resize(); -} -function setDepth(texture: THREE.Texture): void { - if (depthUniforms.uDepthMap.value !== depthMap) depthUniforms.uDepthMap.value.dispose(); - depthUniforms.uDepthMap.value = texture; texture.colorSpace = THREE.NoColorSpace; - if (mode === 'depth') { petMat.map = texture; petMat.needsUpdate = true; } -} -function setMode(next: string): void { - mode = next; - if (modeInput) modeInput.value = next; - pet.visible = next === 'rgb' || next === 'depth'; - petDepth.visible = next === 'noglass' || next === 'final'; - glass.visible = next === 'final' || next === 'glass'; - petMat.map = next === 'depth' ? depthUniforms.uDepthMap.value : active; - petMat.needsUpdate = true; - petDepthMaterial.uniforms.uTexture.value = active; -} -const retry = document.createElement('button'); -retry.textContent = '재생'; retry.hidden = true; -(document.querySelector('aside') as HTMLElement).append(retry); -const debugOutput = document.createElement('pre'); -debugOutput.id = 'depth-debug'; -debugOutput.hidden = true; -(document.querySelector('aside') as HTMLElement).append(debugOutput); -const depthDebug = new DepthDebug(); -const loader = new MediaLoader((texture, mediaAspect, video) => { applyMedia(texture, mediaAspect, video); petDepth.setVideo(Boolean(video)); setDepth(pendingPairDepth ?? DepthProcessor.flatTexture()); pendingPairDepth = null; setMode('final'); hint(); }, (message) => { status.textContent = message; retry.hidden = !message.includes('자동'); }); -retry.onclick = () => loader.retry(); -const sampleDepthProvider = new StaticDepthProvider('/assets/sample-pet-depth.png'); -const cameraController = new CameraController(camera); -const pointer = new PointerController(renderer.domElement, (x, y) => cameraController.add(x, y)); -const gyro = new GyroController((x, y) => cameraController.target.set(THREE.MathUtils.clamp(x, -1, 1), THREE.MathUtils.clamp(y, -1, 1)), (message) => { status.textContent = message; }); -const imageInput = document.querySelector('#image') as HTMLInputElement; -const videoInput = document.querySelector('#video') as HTMLInputElement; -const depthFileInput = document.querySelector('#depth-image') as HTMLInputElement; -const sampleButton = document.querySelector('#sample') as HTMLButtonElement | null; -const effectInput = document.querySelector('#effect') as HTMLSelectElement; -const modeInput = document.querySelector('#view-mode') as HTMLSelectElement | null; -const strengthInput = document.querySelector('#strength') as HTMLInputElement; -const sensitivityInput = document.querySelector('#sensitivity') as HTMLInputElement; -const depthInput = document.querySelector('#depth-scale') as HTMLInputElement | null; -const cameraOffsetInput = document.querySelector('#camera-offset') as HTMLInputElement; -const gridInput = document.querySelector('#grid-size') as HTMLInputElement; -const gridOutput = document.querySelector('#gridOut') as HTMLOutputElement; -const mosaicStyleInput = document.querySelector('#mosaic-style') as HTMLSelectElement; -const glossControls = document.querySelector('#gloss-controls') as HTMLElement | null; -const glossInput = document.querySelector('#gloss-strength') as HTMLInputElement | null; -const lightXInput = document.querySelector('#light-x') as HTMLInputElement | null; -const lightYInput = document.querySelector('#light-y') as HTMLInputElement | null; -const glossOutput = document.querySelector('#glossOut') as HTMLOutputElement | null; -const lightXOutput = document.querySelector('#lightXOut') as HTMLOutputElement | null; -const lightYOutput = document.querySelector('#lightYOut') as HTMLOutputElement | null; -const cameraOutput = document.querySelector('#cameraOut') as HTMLOutputElement; -const strengthOutput = document.querySelector('#strengthOut') as HTMLOutputElement; -const sensitivityOutput = document.querySelector('#sensitivityOut') as HTMLOutputElement; -const depthOutput = document.querySelector('#depthOut') as HTMLOutputElement | null; -const resetButton = document.querySelector('#reset') as HTMLButtonElement; -const gyroButton = document.querySelector('#gyro') as HTMLButtonElement; -const effects = [mosaicShader, reededShader, frostedShader]; -let sensitivity = 1; -function setGlossControlsVisibility(): void { - const enabled = effectInput.value === 'mosaic'; - if (glossControls) { glossControls.hidden = !enabled; glossControls.style.display = enabled ? 'grid' : 'none'; } - [glossInput, lightXInput, lightYInput].forEach((input) => { if (input) input.disabled = !enabled; }); -} -imageInput.onchange = (event) => { const input = event.target as HTMLInputElement; mediaRequest += 1; depthRequest += 1; clearPendingPair(); depthDebug.clear(); if (input.files?.[0]) loader.load(input.files[0]); input.value = ''; }; -videoInput.onchange = (event) => { const input = event.target as HTMLInputElement; mediaRequest += 1; depthRequest += 1; clearPendingPair(); depthDebug.clear(); if (input.files?.[0]) loader.load(input.files[0]); input.value = ''; }; -sampleButton?.addEventListener('click', async () => { const request = ++mediaRequest; depthRequest += 1; clearPendingPair(); depthDebug.clear(); let url = ''; try { const [rgb, depth] = await Promise.all([fetch('/assets/sample-pet.png').then((r) => r.blob()), fetch('/assets/sample-pet-depth.png').then((r) => r.blob())]); if (disposed || request !== mediaRequest) return; url = URL.createObjectURL(depth); const image = new Image(); image.src = url; await image.decode(); if (disposed || request !== mediaRequest) return; const loadedDepth = await sampleDepthProvider.getDepthMap(image); if (disposed || request !== mediaRequest) { loadedDepth.dispose(); return; } clearPendingPair(); pendingPairDepth = loadedDepth; depthDebug.setSample(image); loader.load(new File([rgb], 'sample-pet.png', { type: 'image/png' })); status.textContent = '수작업 테스트 Depth · AI추정 아님'; } catch { if (!disposed && request === mediaRequest) status.textContent = '샘플 depth map을 읽지 못했습니다.'; } finally { if (url) URL.revokeObjectURL(url); } }, { signal: listenerAbort.signal }); -effectInput.addEventListener('change', (event) => { const index = ['mosaic', 'reeded', 'frosted'].indexOf((event.target as HTMLSelectElement).value); glassMat.fragmentShader = effects[index]; glassMat.needsUpdate = true; setGlossControlsVisibility(); }, { signal: listenerAbort.signal }); -modeInput?.addEventListener('change', (event) => setMode((event.target as HTMLSelectElement).value), { signal: listenerAbort.signal }); -strengthInput.oninput = (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uStrength.value = value; strengthOutput.value = value.toFixed(2); }; -sensitivityInput.oninput = (event) => { const value = Number((event.target as HTMLInputElement).value); sensitivity = value; sensitivityOutput.value = value.toFixed(2); }; -depthInput?.addEventListener('input', (event) => { const value = Math.min(Number((event.target as HTMLInputElement).value), 0.4); depthUniforms.uDepthScale.value = value; if (depthOutput) depthOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -cameraOffsetInput.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); cameraController.setMaxOffset(value); cameraOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -gridInput.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uGridSize.value = value; gridOutput.value = value.toFixed(0); }, { signal: listenerAbort.signal }); -mosaicStyleInput.addEventListener('change', (event) => { const style = Number((event.target as HTMLSelectElement).value); uniforms.uMosaicStyle.value = style; uniforms.uGridSize.value = style === 0 ? 28 : 40; uniforms.uStrength.value = style === 0 ? 0.9 : 1; gridInput.value = String(uniforms.uGridSize.value); gridOutput.value = String(uniforms.uGridSize.value); strengthInput.value = String(uniforms.uStrength.value); strengthOutput.value = uniforms.uStrength.value.toFixed(2); }, { signal: listenerAbort.signal }); -glossInput?.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uGlossStrength.value = value; if (glossOutput) glossOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -lightXInput?.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uLightPosition.value.x = value; if (lightXOutput) lightXOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -lightYInput?.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uLightPosition.value.y = value; if (lightYOutput) lightYOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -depthFileInput?.addEventListener('change', async () => { const request = ++depthRequest; const file = depthFileInput.files?.[0]; if (!file) return; depthDebug.clear(); const url = URL.createObjectURL(file); let texture: THREE.Texture | null = null; try { const image = new Image(); image.src = url; await image.decode(); if (disposed || request !== depthRequest) return; if (aspect > 0 && Math.abs(image.width / image.height - aspect) > 0.02) throw new Error('aspect'); texture = DepthProcessor.toTexture(image); if (disposed || request !== depthRequest) { texture.dispose(); texture = null; return; } setDepth(texture); texture = null; status.textContent = '수동 depth map 적용됨 (0=뒤, 1=앞)'; } catch { if (!disposed && request === depthRequest) status.textContent = 'RGB와 종횡비가 다른 depth map입니다.'; } finally { texture?.dispose(); URL.revokeObjectURL(url); depthFileInput.value = ''; } }, { signal: listenerAbort.signal }); -resetButton.onclick = () => { cameraController.reset(); gyro.reset(); }; -gyroButton.onclick = async () => { gyroButton.textContent = `Gyroscope: ${(await gyro.toggle()) ? 'ON' : 'OFF'}`; }; -const observer = new ResizeObserver(resize); observer.observe(wrap); resize(); setMode('final'); setGlossControlsVisibility(); -let last = performance.now(); let raf = 0; -function frame(now: number): void { const dt = Math.min((now - last) / 1000, 0.1); last = now; uniforms.uViewOffset.value.copy(cameraController.update(dt, sensitivity)); camera.updateMatrixWorld(true); petDepth.updateMatrixWorld(true); uniforms.uContentViewProjection.value.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse); uniforms.uContentInverseViewProjection.value.copy(uniforms.uContentViewProjection.value).invert(); uniforms.uContentCameraPosition.value.copy(camera.position); uniforms.uTime.value = now / 1000; const diagnostic = depthDebug.update(camera, petDepth, depthUniforms.uDepthScale.value, depthUniforms.uDepthBias.value, wrap.clientWidth); debugOutput.textContent = diagnostic; debugOutput.hidden = !diagnostic; if (mode === 'final' || mode === 'glass') { renderer.setRenderTarget(renderTarget); renderer.render(scene, camera); renderer.setRenderTarget(null); uniforms.uSceneTexture.value = renderTarget.texture; renderer.render(glassScene, postCamera); } else { renderer.setRenderTarget(null); renderer.render(scene, camera); } raf = requestAnimationFrame(frame); } -raf = requestAnimationFrame(frame); -function teardown(): void { disposed = true; mediaRequest += 1; depthRequest += 1; clearPendingPair(); listenerAbort.abort(); cancelAnimationFrame(raf); window.clearTimeout(hintTimeout); observer.disconnect(); imageInput.onchange = null; videoInput.onchange = null; effectInput.onchange = null; strengthInput.oninput = null; sensitivityInput.oninput = null; resetButton.onclick = null; gyroButton.onclick = null; retry.onclick = null; pointer.dispose(); gyro.dispose(); loader.dispose(); renderTarget.dispose(); if (active !== emptyTex) active.dispose(); if (depthUniforms.uDepthMap.value !== depthMap) depthUniforms.uDepthMap.value.dispose(); depthMap.dispose(); petDepth.geometry.dispose(); petDepthMaterial.dispose(); geometry.dispose(); petMat.dispose(); glass.geometry.dispose(); glassMat.dispose(); emptyTex.dispose(); renderer.domElement.remove(); renderer.dispose(); hintElement.style.opacity = '0'; retry.remove(); debugOutput.remove(); } -const hot = import.meta as ImportMeta & { hot?: { dispose(fn: () => void): void } }; hot.hot?.dispose(teardown); diff --git a/docs/before-cell-curvature/mosaic.frag b/docs/before-cell-curvature/mosaic.frag deleted file mode 100644 index 39a53eb..0000000 --- a/docs/before-cell-curvature/mosaic.frag +++ /dev/null @@ -1,32 +0,0 @@ -uniform sampler2D uSceneTexture; -uniform mat4 uContentViewProjection; -uniform mat4 uContentInverseViewProjection; -uniform vec3 uContentCameraPosition; -uniform vec3 uLightPosition; -uniform float uGlassZ,uGridSize,uStrength,uMosaicStyle; -uniform float uGlossStrength; -uniform vec2 uViewOffset,uPetSize; -uniform vec4 uPaneRect; -varying vec2 vUv; -vec2 projectUv(vec3 p){vec4 c=uContentViewProjection*vec4(p,1.);float w=abs(c.w)<.0001?(c.w<0.?-.0001:.0001):c.w;return c.xy/w*.5+.5;} -vec4 sampleScene(vec2 uv){return texture2D(uSceneTexture,clamp(uv,0.,1.));} -vec4 samplePane(vec2 uv){return texture2D(uSceneTexture,clamp(uv,uPaneRect.xy,uPaneRect.zw));} -float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);} -vec2 hash2(vec2 p){return vec2(hash(p),hash(p+vec2(19.19,73.73)));} -float safeZ(float z){return abs(z)<.0001?(z<0.?-.0001:.0001):z;} -vec3 bend(vec3 i,vec3 n){vec3 r=refract(i,n,.75);return length(r)<.0001?i:r;} -void main(){ - if(vUv.xuPaneRect.z||vUv.yuPaneRect.w){ - gl_FragColor=sampleScene(vUv); - #include - return; - } - vec4 f=uContentInverseViewProjection*vec4(vUv*2.-1.,1.,1.);float fw=abs(f.w)<.0001?(f.w<0.?-.0001:.0001):f.w;vec3 farWorld=f.xyz/fw;vec3 i=normalize(farWorld-uContentCameraPosition);float gt=(uGlassZ-uContentCameraPosition.z)/safeZ(i.z);vec3 gh=uContentCameraPosition+i*gt; - vec2 grid=vec2(uGridSize,max(1.,uGridSize*uPetSize.y/uPetSize.x)),gridUv=vUv*grid,cell=floor(gridUv),local=fract(gridUv)-.5,cellSize=1./grid,random=hash2(cell); - vec3 n=normalize(vec3((random-.5)*.10+local*.025,1.)),r=bend(i,n);vec3 sh=gh+i*(-gh.z/safeZ(i.z)),rh=gh+r*(-gh.z/safeZ(r.z));vec2 viewRefraction=clamp(projectUv(rh)-projectUv(sh),-cellSize*.4,cellSize*.4)+(uViewOffset*(random-.5))*cellSize*.12; - float style=clamp(uMosaicStyle,0.,1.);vec2 sourceCenter=(cell+.5)/grid+(random-.5)*.45*cellSize+viewRefraction;float footprint=mix(mix(.35,.50,random.y),mix(.03,.10,random.y),style);float angle=(random.x-.5)*mix(.06,.12,1.-style),c=cos(angle),s=sin(angle);vec2 sampleUv=clamp(sourceCenter+mat2(c,-s,s,c)*local*footprint*cellSize,uPaneRect.xy,uPaneRect.zw); - float edgeDistance=min(min(vUv.x-uPaneRect.x,uPaneRect.z-vUv.x),min(vUv.y-uPaneRect.y,uPaneRect.w-vUv.y));float edgeWeight=smoothstep(0.,max(cellSize.x,cellSize.y)*.75,edgeDistance);float strength=clamp(uStrength,0.,1.)*edgeWeight;vec2 blurStep=cellSize*mix(.015,.07,style); - vec4 color=samplePane(mix(vUv,sampleUv,strength))*.4;color+=samplePane(mix(vUv,sampleUv+vec2(blurStep.x,0.),strength))*.15;color+=samplePane(mix(vUv,sampleUv-vec2(blurStep.x,0.),strength))*.15;color+=samplePane(mix(vUv,sampleUv+vec2(0.,blurStep.y),strength))*.15;color+=samplePane(mix(vUv,sampleUv-vec2(0.,blurStep.y),strength))*.15;color.a=1.; - vec3 l=normalize(uLightPosition-gh),v=normalize(uContentCameraPosition-gh),h=normalize(l+v);float spec=pow(max(dot(n,h),0.),64.);float gloss=spec*clamp(uGlossStrength,0.,1.)*.28*edgeWeight*clamp(uStrength,0.,1.);color.rgb=mix(color.rgb,vec3(1.),gloss);gl_FragColor=color; - #include -} diff --git a/docs/before-mosaic-reference/main.ts b/docs/before-mosaic-reference/main.ts deleted file mode 100644 index c5f9f6e..0000000 --- a/docs/before-mosaic-reference/main.ts +++ /dev/null @@ -1,152 +0,0 @@ -import * as THREE from 'three'; -import './style.css'; -import vertexShader from './shaders/common.vert?raw'; -import mosaicShader from './shaders/mosaic.frag?raw'; -import reededShader from './shaders/reeded.frag?raw'; -import frostedShader from './shaders/frosted.frag?raw'; -import { MediaLoader } from './input/MediaLoader'; -import { PointerController } from './input/PointerController'; -import { CameraController } from './input/CameraController'; -import { GyroController } from './input/GyroController'; -import { StaticDepthProvider } from './depth/StaticDepthProvider'; -import { DepthProcessor } from './depth/DepthProcessor'; -import { PetDepthMesh } from './objects/PetDepthMesh'; -import { DepthDebug } from './depth/DepthDebug'; -import glassScreenVertex from './shaders/glassScreen.vert?raw'; - -const wrap = document.querySelector('#canvas-wrap') as HTMLElement; -const status = document.querySelector('#status') as HTMLElement; -const empty = document.querySelector('#empty') as HTMLElement; -const hintElement = document.querySelector('#hint') as HTMLElement; -hintElement.style.opacity = '0'; -const renderer = new THREE.WebGLRenderer({ antialias: true }); -renderer.setPixelRatio(Math.min(devicePixelRatio, 1.5)); -wrap.append(renderer.domElement); -const scene = new THREE.Scene(); -const glassScene = new THREE.Scene(); -scene.background = new THREE.Color(0x111923); -const camera = new THREE.PerspectiveCamera(40, 1, 0.1, 100); -camera.position.z = 3; -const geometry = new THREE.PlaneGeometry(1, 1); -const emptyTex = new THREE.DataTexture(new Uint8Array([38, 48, 62, 255]), 1, 1); -emptyTex.needsUpdate = true; -const petMat = new THREE.MeshBasicMaterial({ map: emptyTex }); -const pet = new THREE.Mesh(geometry, petMat); -scene.add(pet); -const depthMap: THREE.Texture = DepthProcessor.flatTexture(); -const petDepth = new PetDepthMesh(emptyTex, depthMap, 0.25, 0); -const petDepthMaterial = petDepth.material; -const depthUniforms = petDepthMaterial.uniforms; -scene.add(petDepth); -const uniforms = { uSceneTexture: { value: emptyTex as THREE.Texture }, uContentViewProjection: { value: new THREE.Matrix4() }, uContentInverseViewProjection: { value: new THREE.Matrix4() }, uContentCameraPosition: { value: new THREE.Vector3() }, uGlassZ: { value: 0.6 }, uGridSize: { value: 8 }, uStrength: { value: 0.65 }, uViewOffset: { value: new THREE.Vector2() }, uResolution: { value: new THREE.Vector2() }, uTime: { value: 0 }, uPetSize: { value: new THREE.Vector2(1, 1) } }; -const glassMat = new THREE.ShaderMaterial({ uniforms, vertexShader: glassScreenVertex, fragmentShader: mosaicShader }); -const glass = new THREE.Mesh(new THREE.PlaneGeometry(2, 2), glassMat); -glassScene.add(glass); -const postCamera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1); -const renderTarget = new THREE.WebGLRenderTarget(1, 1, { colorSpace: THREE.NoColorSpace, type: THREE.HalfFloatType, depthBuffer: true }); -let active: THREE.Texture = emptyTex; -let aspect = 1; -let mode = 'noglass'; -let hintTimeout = 0; -let pendingPairDepth: THREE.Texture | null = null; -let mediaRequest = 0; -let depthRequest = 0; -let disposed = false; -const listenerAbort = new AbortController(); -function clearPendingPair(): void { if (pendingPairDepth) pendingPairDepth.dispose(); pendingPairDepth = null; } -function resize(): void { - const bounds = wrap.getBoundingClientRect(); - renderer.setSize(bounds.width, bounds.height, false); - camera.aspect = bounds.width / bounds.height; - camera.updateProjectionMatrix(); - const height = 1.7; - const scale = Math.min(height * bounds.width / bounds.height / aspect, height); - pet.scale.set(scale * aspect, scale, 1); - petDepth.scale.copy(pet.scale); - uniforms.uPetSize.value.set(pet.scale.x, pet.scale.y); - uniforms.uResolution.value.set(bounds.width, bounds.height); - const glassHeight = 2 * (camera.position.z - 0.6) * Math.tan(THREE.MathUtils.degToRad(camera.fov / 2)); - uniforms.uPetSize.value.set(glassHeight * camera.aspect, glassHeight); - renderTarget.setSize(Math.max(1, Math.floor(bounds.width * Math.min(devicePixelRatio, 1.5))), Math.max(1, Math.floor(bounds.height * Math.min(devicePixelRatio, 1.5)))); -} -function hint(): void { - window.clearTimeout(hintTimeout); - hintElement.style.opacity = '1'; - hintTimeout = window.setTimeout(() => { hintElement.style.opacity = '0'; }, 2000); -} -function applyMedia(texture: THREE.Texture, mediaAspect: number, video: HTMLVideoElement | null): void { - if (active !== emptyTex) active.dispose(); - active = texture; aspect = mediaAspect; - texture.colorSpace = THREE.SRGBColorSpace; - depthUniforms.uTexture.value = texture; - petMat.map = texture; petMat.needsUpdate = true; - empty.style.display = 'none'; resize(); -} -function setDepth(texture: THREE.Texture): void { - if (depthUniforms.uDepthMap.value !== depthMap) depthUniforms.uDepthMap.value.dispose(); - depthUniforms.uDepthMap.value = texture; texture.colorSpace = THREE.NoColorSpace; - if (mode === 'depth') { petMat.map = texture; petMat.needsUpdate = true; } -} -function setMode(next: string): void { - mode = next; - if (modeInput) modeInput.value = next; - pet.visible = next === 'rgb' || next === 'depth'; - petDepth.visible = next === 'noglass' || next === 'final'; - glass.visible = next === 'final' || next === 'glass'; - petMat.map = next === 'depth' ? depthUniforms.uDepthMap.value : active; - petMat.needsUpdate = true; - petDepthMaterial.uniforms.uTexture.value = active; -} -const retry = document.createElement('button'); -retry.textContent = '재생'; retry.hidden = true; -(document.querySelector('aside') as HTMLElement).append(retry); -const debugOutput = document.createElement('pre'); -debugOutput.id = 'depth-debug'; -debugOutput.hidden = true; -(document.querySelector('aside') as HTMLElement).append(debugOutput); -const depthDebug = new DepthDebug(); -const loader = new MediaLoader((texture, mediaAspect, video) => { applyMedia(texture, mediaAspect, video); petDepth.setVideo(Boolean(video)); setDepth(pendingPairDepth ?? DepthProcessor.flatTexture()); pendingPairDepth = null; setMode('noglass'); hint(); }, (message) => { status.textContent = message; retry.hidden = !message.includes('자동'); }); -retry.onclick = () => loader.retry(); -const sampleDepthProvider = new StaticDepthProvider('/assets/sample-pet-depth.png'); -const cameraController = new CameraController(camera); -const pointer = new PointerController(renderer.domElement, (x, y) => cameraController.add(x, y)); -const gyro = new GyroController((x, y) => cameraController.target.set(THREE.MathUtils.clamp(x, -1, 1), THREE.MathUtils.clamp(y, -1, 1)), (message) => { status.textContent = message; }); -const imageInput = document.querySelector('#image') as HTMLInputElement; -const videoInput = document.querySelector('#video') as HTMLInputElement; -const depthFileInput = document.querySelector('#depth-image') as HTMLInputElement; -const sampleButton = document.querySelector('#sample') as HTMLButtonElement | null; -const effectInput = document.querySelector('#effect') as HTMLSelectElement; -const modeInput = document.querySelector('#view-mode') as HTMLSelectElement | null; -const strengthInput = document.querySelector('#strength') as HTMLInputElement; -const sensitivityInput = document.querySelector('#sensitivity') as HTMLInputElement; -const depthInput = document.querySelector('#depth-scale') as HTMLInputElement | null; -const cameraOffsetInput = document.querySelector('#camera-offset') as HTMLInputElement; -const gridInput = document.querySelector('#grid-size') as HTMLInputElement; -const gridOutput = document.querySelector('#gridOut') as HTMLOutputElement; -const cameraOutput = document.querySelector('#cameraOut') as HTMLOutputElement; -const strengthOutput = document.querySelector('#strengthOut') as HTMLOutputElement; -const sensitivityOutput = document.querySelector('#sensitivityOut') as HTMLOutputElement; -const depthOutput = document.querySelector('#depthOut') as HTMLOutputElement | null; -const resetButton = document.querySelector('#reset') as HTMLButtonElement; -const gyroButton = document.querySelector('#gyro') as HTMLButtonElement; -const effects = [mosaicShader, reededShader, frostedShader]; -let sensitivity = 1; -imageInput.onchange = (event) => { const input = event.target as HTMLInputElement; mediaRequest += 1; depthRequest += 1; clearPendingPair(); depthDebug.clear(); if (input.files?.[0]) loader.load(input.files[0]); input.value = ''; }; -videoInput.onchange = (event) => { const input = event.target as HTMLInputElement; mediaRequest += 1; depthRequest += 1; clearPendingPair(); depthDebug.clear(); if (input.files?.[0]) loader.load(input.files[0]); input.value = ''; }; -sampleButton?.addEventListener('click', async () => { const request = ++mediaRequest; depthRequest += 1; clearPendingPair(); depthDebug.clear(); let url = ''; try { const [rgb, depth] = await Promise.all([fetch('/assets/sample-pet.png').then((r) => r.blob()), fetch('/assets/sample-pet-depth.png').then((r) => r.blob())]); if (disposed || request !== mediaRequest) return; url = URL.createObjectURL(depth); const image = new Image(); image.src = url; await image.decode(); if (disposed || request !== mediaRequest) return; const loadedDepth = await sampleDepthProvider.getDepthMap(image); if (disposed || request !== mediaRequest) { loadedDepth.dispose(); return; } clearPendingPair(); pendingPairDepth = loadedDepth; depthDebug.setSample(image); loader.load(new File([rgb], 'sample-pet.png', { type: 'image/png' })); status.textContent = '수작업 테스트 Depth · AI추정 아님'; } catch { if (!disposed && request === mediaRequest) status.textContent = '샘플 depth map을 읽지 못했습니다.'; } finally { if (url) URL.revokeObjectURL(url); } }, { signal: listenerAbort.signal }); -effectInput.onchange = (event) => { const index = ['mosaic', 'reeded', 'frosted'].indexOf((event.target as HTMLSelectElement).value); glassMat.fragmentShader = effects[index]; glassMat.needsUpdate = true; }; -modeInput?.addEventListener('change', (event) => setMode((event.target as HTMLSelectElement).value), { signal: listenerAbort.signal }); -strengthInput.oninput = (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uStrength.value = value; strengthOutput.value = value.toFixed(2); }; -sensitivityInput.oninput = (event) => { const value = Number((event.target as HTMLInputElement).value); sensitivity = value; sensitivityOutput.value = value.toFixed(2); }; -depthInput?.addEventListener('input', (event) => { const value = Math.min(Number((event.target as HTMLInputElement).value), 0.4); depthUniforms.uDepthScale.value = value; if (depthOutput) depthOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -cameraOffsetInput.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); cameraController.setMaxOffset(value); cameraOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -gridInput.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uGridSize.value = value; gridOutput.value = value.toFixed(0); }, { signal: listenerAbort.signal }); -depthFileInput?.addEventListener('change', async () => { const request = ++depthRequest; const file = depthFileInput.files?.[0]; if (!file) return; depthDebug.clear(); const url = URL.createObjectURL(file); let texture: THREE.Texture | null = null; try { const image = new Image(); image.src = url; await image.decode(); if (disposed || request !== depthRequest) return; if (aspect > 0 && Math.abs(image.width / image.height - aspect) > 0.02) throw new Error('aspect'); texture = DepthProcessor.toTexture(image); if (disposed || request !== depthRequest) { texture.dispose(); texture = null; return; } setDepth(texture); texture = null; status.textContent = '수동 depth map 적용됨 (0=뒤, 1=앞)'; } catch { if (!disposed && request === depthRequest) status.textContent = 'RGB와 종횡비가 다른 depth map입니다.'; } finally { texture?.dispose(); URL.revokeObjectURL(url); depthFileInput.value = ''; } }, { signal: listenerAbort.signal }); -resetButton.onclick = () => { cameraController.reset(); gyro.reset(); }; -gyroButton.onclick = async () => { gyroButton.textContent = `Gyroscope: ${(await gyro.toggle()) ? 'ON' : 'OFF'}`; }; -const observer = new ResizeObserver(resize); observer.observe(wrap); resize(); setMode('noglass'); -let last = performance.now(); let raf = 0; -function frame(now: number): void { const dt = Math.min((now - last) / 1000, 0.1); last = now; uniforms.uViewOffset.value.copy(cameraController.update(dt, sensitivity)); camera.updateMatrixWorld(true); petDepth.updateMatrixWorld(true); uniforms.uContentViewProjection.value.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse); uniforms.uContentInverseViewProjection.value.copy(uniforms.uContentViewProjection.value).invert(); uniforms.uContentCameraPosition.value.copy(camera.position); uniforms.uTime.value = now / 1000; const diagnostic = depthDebug.update(camera, petDepth, depthUniforms.uDepthScale.value, depthUniforms.uDepthBias.value, wrap.clientWidth); debugOutput.textContent = diagnostic; debugOutput.hidden = !diagnostic; if (mode === 'final' || mode === 'glass') { renderer.setRenderTarget(renderTarget); renderer.render(scene, camera); renderer.setRenderTarget(null); uniforms.uSceneTexture.value = renderTarget.texture; renderer.render(glassScene, postCamera); } else { renderer.setRenderTarget(null); renderer.render(scene, camera); } raf = requestAnimationFrame(frame); } -raf = requestAnimationFrame(frame); -function teardown(): void { disposed = true; mediaRequest += 1; depthRequest += 1; clearPendingPair(); listenerAbort.abort(); cancelAnimationFrame(raf); window.clearTimeout(hintTimeout); observer.disconnect(); imageInput.onchange = null; videoInput.onchange = null; effectInput.onchange = null; strengthInput.oninput = null; sensitivityInput.oninput = null; resetButton.onclick = null; gyroButton.onclick = null; retry.onclick = null; pointer.dispose(); gyro.dispose(); loader.dispose(); renderTarget.dispose(); if (active !== emptyTex) active.dispose(); if (depthUniforms.uDepthMap.value !== depthMap) depthUniforms.uDepthMap.value.dispose(); depthMap.dispose(); petDepth.geometry.dispose(); petDepthMaterial.dispose(); geometry.dispose(); petMat.dispose(); glass.geometry.dispose(); glassMat.dispose(); emptyTex.dispose(); renderer.domElement.remove(); renderer.dispose(); hintElement.style.opacity = '0'; retry.remove(); debugOutput.remove(); } -const hot = import.meta as ImportMeta & { hot?: { dispose(fn: () => void): void } }; hot.hot?.dispose(teardown); diff --git a/docs/before-mosaic-reference/mosaic.frag b/docs/before-mosaic-reference/mosaic.frag deleted file mode 100644 index d2017ba..0000000 --- a/docs/before-mosaic-reference/mosaic.frag +++ /dev/null @@ -1,9 +0,0 @@ -uniform sampler2D uSceneTexture; uniform mat4 uContentViewProjection; uniform mat4 uContentInverseViewProjection; uniform vec3 uContentCameraPosition; uniform float uGlassZ,uGridSize,uStrength,uTime; uniform vec2 uViewOffset,uResolution,uPetSize; -varying vec2 vUv; -vec2 projectUv(vec3 p){vec4 c=uContentViewProjection*vec4(p,1.);float w=abs(c.w)<.0001?(c.w<0.?-.0001:.0001):c.w;return c.xy/w*.5+.5;} -vec4 sampleScene(vec2 uv){if(any(lessThan(uv,vec2(0.)))||any(greaterThan(uv,vec2(1.))))return vec4(.005605,.009721,.016807,1.);return texture2D(uSceneTexture,uv);} -float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);} float safeZ(float z){return abs(z)<.0001?(z<0.?-.0001:.0001):z;} -vec3 bend(vec3 i,vec3 n){vec3 r=refract(i,n,.75);return length(r)<.0001?i:r;} -void main(){vec2 q=vUv*2.-1.;vec4 fh=uContentInverseViewProjection*vec4(q,1.,1.);float fwDen=abs(fh.w)<.0001?(fh.w<0.?-.0001:.0001):fh.w;vec3 fw=fh.xyz/fwDen;vec3 i=normalize(fw-uContentCameraPosition);float gt=(uGlassZ-uContentCameraPosition.z)/safeZ(i.z);vec3 gh=uContentCameraPosition+i*gt;vec2 grid=vec2(uGridSize,max(1.,uGridSize*uPetSize.y/uPetSize.x));vec2 s=vUv*grid,cell=floor(s),local=fract(s)-.5;float var=mix(.85,1.15,hash(cell));vec2 ll=local+uViewOffset*(.12+.08*hash(cell+vec2(9.)));float bulge=max(0.,.25-dot(ll,ll));vec3 n=normalize(vec3(-ll*bulge*1.8*var,1.));vec3 r=bend(i,n);vec3 sh=gh+i*(-gh.z/safeZ(i.z)),bh=gh+r*(-gh.z/safeZ(r.z));vec2 ru=vUv+projectUv(bh)-projectUv(sh);vec2 uv=mix(vUv,ru,clamp(uStrength,0.,1.));vec4 c=sampleScene(uv);float edge=smoothstep(.46,.5,max(abs(local.x),abs(local.y)));c.rgb*=mix(1.,.75,edge*clamp(uStrength,0.,1.));c.a=1.;gl_FragColor=c; - #include -} diff --git a/docs/before-qa-improvements/mosaic.frag b/docs/before-qa-improvements/mosaic.frag deleted file mode 100644 index 98f7fce..0000000 --- a/docs/before-qa-improvements/mosaic.frag +++ /dev/null @@ -1,32 +0,0 @@ -uniform sampler2D uSceneTexture; -uniform mat4 uContentViewProjection,uContentInverseViewProjection; -uniform vec3 uContentCameraPosition,uLightPosition,uBackgroundColor; -uniform float uGlassZ,uGridSize,uStrength,uMosaicStyle,uCurvature,uGlossStrength; -uniform vec2 uViewOffset,uPetSize,uPaneSize; -uniform vec4 uPaneRect; -varying vec2 vUv; -vec2 projectUv(vec3 p){vec4 c=uContentViewProjection*vec4(p,1.);float w=abs(c.w)<.0001?(c.w<0.?-.0001:.0001):c.w;return c.xy/w*.5+.5;} -vec4 sampleScene(vec2 uv){return texture2D(uSceneTexture,clamp(uv,0.,1.));} -vec4 samplePane(vec2 pane){return sampleScene(projectUv(vec3((pane-.5)*uPaneSize,uGlassZ)));} -float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);} -vec2 hash2(vec2 p){return vec2(hash(p),hash(p+vec2(19.19,73.73)));} -float safeZ(float z){return abs(z)<.0001?(z<0.?-.0001:.0001):z;} -vec3 bend(vec3 i,vec3 n){vec3 r=refract(i,n,.75);return length(r)<.0001?i:r;} -float softLimit(float value,float limit){return value*limit/(limit+abs(value));} -void main(){ - if(uStrength<=.001){gl_FragColor=sampleScene(vUv); - #include - return;} - vec4 f=uContentInverseViewProjection*vec4(vUv*2.-1.,1.,1.);float fw=abs(f.w)<.0001?(f.w<0.?-.0001:.0001):f.w;vec3 farWorld=f.xyz/fw;vec3 i=normalize(farWorld-uContentCameraPosition);float gt=(uGlassZ-uContentCameraPosition.z)/safeZ(i.z);vec3 gh=uContentCameraPosition+i*gt; - vec2 paneUv=gh.xy/uPaneSize+.5;vec2 grid=vec2(uGridSize,max(1.,uGridSize*uPaneSize.y/uPaneSize.x));vec2 gridUv=paneUv*grid,cell=floor(gridUv),local=fract(gridUv)-.5,cellSize=1./grid,random=hash2(cell);float style=clamp(uMosaicStyle,0.,1.),cellWorld=min(uPaneSize.x/grid.x,uPaneSize.y/grid.y); - if(paneUv.x<0.||paneUv.x>1.||paneUv.y<0.||paneUv.y>1.){gl_FragColor=vec4(uBackgroundColor,1.); - #include - return;} - // Positive height bulges toward the observer (+Z); negative height is concave. - float height=.009*cellWorld*clamp(uCurvature,-1.,1.)*mix(.92,1.08,hash(cell+vec2(41.7,17.3))); vec2 q=2.*local; vec2 q2=q*q,q3=q2*q,b=1.-q2*q2; vec2 skew=(hash2(cell+vec2(23.8,61.2))-.5)*.28; float asym=1.+dot(skew,q); vec2 dhdq=height*vec2(-4.*q3.x*b.y*asym+b.x*b.y*skew.x,-4.*q3.y*b.x*asym+b.x*b.y*skew.y); vec2 cellDimensions=uPaneSize/grid; vec2 grad=-2.*dhdq/cellDimensions; vec3 nCurved=normalize(vec3(grad+(random-.5)*.012,1.)),nFacet=normalize(vec3((random-.5)*.012,1.)); - vec3 straightHit=gh+i*(-gh.z/safeZ(i.z));vec3 facetRay=bend(i,nFacet),curvedRay=bend(i,nCurved);vec3 facetHit=gh+facetRay*(-gh.z/safeZ(facetRay.z)),curvedHit=gh+curvedRay*(-gh.z/safeZ(curvedRay.z));vec2 base=facetHit.xy-straightHit.xy,curve=curvedHit.xy-facetHit.xy;vec2 worldDelta=vec2(softLimit(base.x,cellWorld*.08),softLimit(base.y,cellWorld*.08));vec2 d=curve/cellWorld;worldDelta+=vec2(.3*d.x/(.3+abs(d.x)),.3*d.y/(.3+abs(d.y)))*cellWorld; - vec2 sourceCenter=(cell+.5)/grid+(random-.5)*.32*cellSize+worldDelta/uPaneSize;vec2 widths;if(style>.5){widths=mix(vec2(.82),vec2(1.12),hash2(cell+vec2(11.4,9.8)));}else{float widthSeed=hash(cell+vec2(53.1,27.4));if(widthSeed<.6)widths=mix(vec2(.90),vec2(1.08),hash2(cell+vec2(7.2,3.1)));else if(widthSeed<.9)widths=mix(vec2(.46),vec2(.70),hash2(cell+vec2(7.2,3.1)));else widths=mix(vec2(1.10),vec2(1.28),hash2(cell+vec2(7.2,3.1)));}float angle=(random.x-.5)*.08,c=cos(angle),s=sin(angle);vec2 sampleUv=sourceCenter+mat2(c,-s,s,c)*(local*cellSize)*widths; - float edgeDistance=min(min(paneUv.x,paneUv.y),min(1.-paneUv.x,1.-paneUv.y));float edgeWeight=smoothstep(0.,max(cellSize.x,cellSize.y)*.75,edgeDistance);float strength=clamp(uStrength,0.,1.)*edgeWeight;vec2 blurStep=cellSize*mix(.006,.012,hash(cell+vec2(5.)));vec2 centerUv=mix(paneUv,sampleUv,strength);vec4 color=samplePane(centerUv)*.4;color+=samplePane(mix(paneUv,sampleUv+vec2(blurStep.x,0.),strength))*.15;color+=samplePane(mix(paneUv,sampleUv-vec2(blurStep.x,0.),strength))*.15;color+=samplePane(mix(paneUv,sampleUv+vec2(0.,blurStep.y),strength))*.15;color+=samplePane(mix(paneUv,sampleUv-vec2(0.,blurStep.y),strength))*.15;color.a=1.; - vec3 v=normalize(uContentCameraPosition-gh),reflected=reflect(-v,nCurved); float lightT=(uLightPosition.z-gh.z)/safeZ(reflected.z); vec2 lightHit=gh.xy+reflected.xy*lightT; vec2 halfSize=vec2(.32,.42)*min(uPaneSize.x,uPaneSize.y); vec2 windowCoord=abs(lightHit-uLightPosition.xy)/halfSize; vec2 windowMask=1.-smoothstep(vec2(.45),vec2(1.15),windowCoord); float spec=windowMask.x*windowMask.y*step(.0001,reflected.z)*step(0.,lightT); float gloss=spec*clamp(uGlossStrength,0.,1.)*.12*edgeWeight*clamp(uStrength,0.,1.); color.rgb=mix(color.rgb,vec3(1.),gloss); gl_FragColor=color; - #include -} diff --git a/docs/before-reference2/main.ts b/docs/before-reference2/main.ts deleted file mode 100644 index 4e2171d..0000000 --- a/docs/before-reference2/main.ts +++ /dev/null @@ -1,175 +0,0 @@ -import * as THREE from 'three'; -import './style.css'; -import vertexShader from './shaders/common.vert?raw'; -import mosaicShader from './shaders/mosaic.frag?raw'; -import reededShader from './shaders/reeded.frag?raw'; -import frostedShader from './shaders/frosted.frag?raw'; -import { MediaLoader } from './input/MediaLoader'; -import { PointerController } from './input/PointerController'; -import { CameraController } from './input/CameraController'; -import { GyroController } from './input/GyroController'; -import { StaticDepthProvider } from './depth/StaticDepthProvider'; -import { DepthProcessor } from './depth/DepthProcessor'; -import { PetDepthMesh } from './objects/PetDepthMesh'; -import { DepthDebug } from './depth/DepthDebug'; -import glassScreenVertex from './shaders/glassScreen.vert?raw'; - -const wrap = document.querySelector('#canvas-wrap') as HTMLElement; -const status = document.querySelector('#status') as HTMLElement; -const empty = document.querySelector('#empty') as HTMLElement; -const hintElement = document.querySelector('#hint') as HTMLElement; -hintElement.style.opacity = '0'; -const renderer = new THREE.WebGLRenderer({ antialias: true }); -renderer.setPixelRatio(Math.min(devicePixelRatio, 1.5)); -wrap.append(renderer.domElement); -const scene = new THREE.Scene(); -const glassScene = new THREE.Scene(); -scene.background = new THREE.Color(0x111923); -const camera = new THREE.PerspectiveCamera(40, 1, 0.1, 100); -camera.position.z = 3; -const geometry = new THREE.PlaneGeometry(1, 1); -const emptyTex = new THREE.DataTexture(new Uint8Array([38, 48, 62, 255]), 1, 1); -emptyTex.needsUpdate = true; -const petMat = new THREE.MeshBasicMaterial({ map: emptyTex }); -const pet = new THREE.Mesh(geometry, petMat); -scene.add(pet); -const depthMap: THREE.Texture = DepthProcessor.flatTexture(); -const petDepth = new PetDepthMesh(emptyTex, depthMap, 0.25, 0); -const petDepthMaterial = petDepth.material; -const depthUniforms = petDepthMaterial.uniforms; -scene.add(petDepth); -const uniforms = { uSceneTexture: { value: emptyTex as THREE.Texture }, uContentViewProjection: { value: new THREE.Matrix4() }, uContentInverseViewProjection: { value: new THREE.Matrix4() }, uContentCameraPosition: { value: new THREE.Vector3() }, uLightPosition: { value: new THREE.Vector3(0.6, 0.8, 2.6) }, uGlassZ: { value: 0.6 }, uGridSize: { value: 18 }, uMosaicStyle: { value: 0 }, uStrength: { value: 0.75 }, uGlossStrength: { value: 0.3 }, uCurvature: { value: 0.65 }, uViewOffset: { value: new THREE.Vector2() }, uPaneRect: { value: new THREE.Vector4(0, 0, 1, 1) }, uResolution: { value: new THREE.Vector2() }, uTime: { value: 0 }, uPetSize: { value: new THREE.Vector2(1, 1) }, uPaneSize: { value: new THREE.Vector2(1, 1) } }; -const glassMat = new THREE.ShaderMaterial({ uniforms, vertexShader: glassScreenVertex, fragmentShader: mosaicShader }); -const glass = new THREE.Mesh(new THREE.PlaneGeometry(2, 2), glassMat); -glassScene.add(glass); -const postCamera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1); -const renderTarget = new THREE.WebGLRenderTarget(1, 1, { colorSpace: THREE.NoColorSpace, type: THREE.HalfFloatType, depthBuffer: true }); -let active: THREE.Texture = emptyTex; -let aspect = 1; -let mode = 'noglass'; -let hintTimeout = 0; -let pendingPairDepth: THREE.Texture | null = null; -let mediaRequest = 0; -let depthRequest = 0; -let disposed = false; -const listenerAbort = new AbortController(); -function clearPendingPair(): void { if (pendingPairDepth) pendingPairDepth.dispose(); pendingPairDepth = null; } -function resize(): void { - const bounds = wrap.getBoundingClientRect(); - renderer.setSize(bounds.width, bounds.height, false); - camera.aspect = bounds.width / bounds.height; - camera.updateProjectionMatrix(); - const height = 1.7; - const scale = Math.min(height * bounds.width / bounds.height / aspect, height); - pet.scale.set(scale * aspect, scale, 1); - petDepth.scale.copy(pet.scale); - uniforms.uPetSize.value.set(pet.scale.x, pet.scale.y); - uniforms.uResolution.value.set(bounds.width, bounds.height); - const glassHeight = 2 * (camera.position.z - 0.6) * Math.tan(THREE.MathUtils.degToRad(camera.fov / 2)); - uniforms.uPetSize.value.set(glassHeight * camera.aspect, glassHeight); - uniforms.uPaneSize.value.set(pet.scale.x * (3 - uniforms.uGlassZ.value) / 3, pet.scale.y * (3 - uniforms.uGlassZ.value) / 3); - const neutralGlassHeight = 2 * 3 * Math.tan(THREE.MathUtils.degToRad(40 / 2)); - const neutralGlassWidth = neutralGlassHeight * camera.aspect; - uniforms.uPaneRect.value.set(Math.max(0, 0.5 - pet.scale.x / (2 * neutralGlassWidth)), Math.max(0, 0.5 - pet.scale.y / (2 * neutralGlassHeight)), Math.min(1, 0.5 + pet.scale.x / (2 * neutralGlassWidth)), Math.min(1, 0.5 + pet.scale.y / (2 * neutralGlassHeight))); - renderTarget.setSize(Math.max(1, Math.floor(bounds.width * Math.min(devicePixelRatio, 1.5))), Math.max(1, Math.floor(bounds.height * Math.min(devicePixelRatio, 1.5)))); -} -function hint(): void { - window.clearTimeout(hintTimeout); - hintElement.style.opacity = '1'; - hintTimeout = window.setTimeout(() => { hintElement.style.opacity = '0'; }, 2000); -} -function applyMedia(texture: THREE.Texture, mediaAspect: number, video: HTMLVideoElement | null): void { - if (active !== emptyTex) active.dispose(); - active = texture; aspect = mediaAspect; - texture.colorSpace = THREE.SRGBColorSpace; - depthUniforms.uTexture.value = texture; - petMat.map = texture; petMat.needsUpdate = true; - empty.style.display = 'none'; resize(); -} -function setDepth(texture: THREE.Texture): void { - if (depthUniforms.uDepthMap.value !== depthMap) depthUniforms.uDepthMap.value.dispose(); - depthUniforms.uDepthMap.value = texture; texture.colorSpace = THREE.NoColorSpace; - if (mode === 'depth') { petMat.map = texture; petMat.needsUpdate = true; } -} -function setMode(next: string): void { - mode = next; - if (modeInput) modeInput.value = next; - pet.visible = next === 'rgb' || next === 'depth'; - petDepth.visible = next === 'noglass' || next === 'final'; - glass.visible = next === 'final' || next === 'glass'; - petMat.map = next === 'depth' ? depthUniforms.uDepthMap.value : active; - petMat.needsUpdate = true; - petDepthMaterial.uniforms.uTexture.value = active; -} -const retry = document.createElement('button'); -retry.textContent = '재생'; retry.hidden = true; -(document.querySelector('aside') as HTMLElement).append(retry); -const debugOutput = document.createElement('pre'); -debugOutput.id = 'depth-debug'; -debugOutput.hidden = true; -(document.querySelector('aside') as HTMLElement).append(debugOutput); -const depthDebug = new DepthDebug(); -const loader = new MediaLoader((texture, mediaAspect, video) => { applyMedia(texture, mediaAspect, video); petDepth.setVideo(Boolean(video)); setDepth(pendingPairDepth ?? DepthProcessor.flatTexture()); pendingPairDepth = null; setMode('final'); hint(); }, (message) => { status.textContent = message; retry.hidden = !message.includes('자동'); }); -retry.onclick = () => loader.retry(); -const sampleDepthProvider = new StaticDepthProvider('/assets/sample-pet-depth.png'); -const cameraController = new CameraController(camera); -const pointer = new PointerController(renderer.domElement, (x, y) => cameraController.add(x, y)); -const gyro = new GyroController((x, y) => cameraController.target.set(THREE.MathUtils.clamp(x, -1, 1), THREE.MathUtils.clamp(y, -1, 1)), (message) => { status.textContent = message; }); -const imageInput = document.querySelector('#image') as HTMLInputElement; -const videoInput = document.querySelector('#video') as HTMLInputElement; -const depthFileInput = document.querySelector('#depth-image') as HTMLInputElement; -const sampleButton = document.querySelector('#sample') as HTMLButtonElement | null; -const effectInput = document.querySelector('#effect') as HTMLSelectElement; -const modeInput = document.querySelector('#view-mode') as HTMLSelectElement | null; -const strengthInput = document.querySelector('#strength') as HTMLInputElement; -const sensitivityInput = document.querySelector('#sensitivity') as HTMLInputElement; -const depthInput = document.querySelector('#depth-scale') as HTMLInputElement | null; -const cameraOffsetInput = document.querySelector('#camera-offset') as HTMLInputElement; -const gridInput = document.querySelector('#grid-size') as HTMLInputElement; -const gridOutput = document.querySelector('#gridOut') as HTMLOutputElement; -const mosaicStyleInput = document.querySelector('#mosaic-style') as HTMLSelectElement; -const glossControls = document.querySelector('#gloss-controls') as HTMLElement | null; -const curvatureInput = document.querySelector('#curvature') as HTMLInputElement | null; -const glossInput = document.querySelector('#gloss-strength') as HTMLInputElement | null; -const lightXInput = document.querySelector('#light-x') as HTMLInputElement | null; -const lightYInput = document.querySelector('#light-y') as HTMLInputElement | null; -const glossOutput = document.querySelector('#glossOut') as HTMLOutputElement | null; -const lightXOutput = document.querySelector('#lightXOut') as HTMLOutputElement | null; -const lightYOutput = document.querySelector('#lightYOut') as HTMLOutputElement | null; -const cameraOutput = document.querySelector('#cameraOut') as HTMLOutputElement; -const strengthOutput = document.querySelector('#strengthOut') as HTMLOutputElement; -const sensitivityOutput = document.querySelector('#sensitivityOut') as HTMLOutputElement; -const depthOutput = document.querySelector('#depthOut') as HTMLOutputElement | null; -const resetButton = document.querySelector('#reset') as HTMLButtonElement; -const gyroButton = document.querySelector('#gyro') as HTMLButtonElement; -const effects = [mosaicShader, reededShader, frostedShader]; -let sensitivity = 1; -function setGlossControlsVisibility(): void { - const enabled = effectInput.value === 'mosaic'; - if (glossControls) { glossControls.hidden = !enabled; glossControls.style.display = enabled ? 'grid' : 'none'; } - [glossInput, lightXInput, lightYInput, curvatureInput].forEach((input) => { if (input) input.disabled = !enabled; }); -} -imageInput.onchange = (event) => { const input = event.target as HTMLInputElement; mediaRequest += 1; depthRequest += 1; clearPendingPair(); depthDebug.clear(); if (input.files?.[0]) loader.load(input.files[0]); input.value = ''; }; -videoInput.onchange = (event) => { const input = event.target as HTMLInputElement; mediaRequest += 1; depthRequest += 1; clearPendingPair(); depthDebug.clear(); if (input.files?.[0]) loader.load(input.files[0]); input.value = ''; }; -sampleButton?.addEventListener('click', async () => { const request = ++mediaRequest; depthRequest += 1; clearPendingPair(); depthDebug.clear(); let url = ''; try { const [rgb, depth] = await Promise.all([fetch('/assets/sample-pet.png').then((r) => r.blob()), fetch('/assets/sample-pet-depth.png').then((r) => r.blob())]); if (disposed || request !== mediaRequest) return; url = URL.createObjectURL(depth); const image = new Image(); image.src = url; await image.decode(); if (disposed || request !== mediaRequest) return; const loadedDepth = await sampleDepthProvider.getDepthMap(image); if (disposed || request !== mediaRequest) { loadedDepth.dispose(); return; } clearPendingPair(); pendingPairDepth = loadedDepth; depthDebug.setSample(image); loader.load(new File([rgb], 'sample-pet.png', { type: 'image/png' })); status.textContent = '수작업 테스트 Depth · AI추정 아님'; } catch { if (!disposed && request === mediaRequest) status.textContent = '샘플 depth map을 읽지 못했습니다.'; } finally { if (url) URL.revokeObjectURL(url); } }, { signal: listenerAbort.signal }); -effectInput.addEventListener('change', (event) => { const index = ['mosaic', 'reeded', 'frosted'].indexOf((event.target as HTMLSelectElement).value); glassMat.fragmentShader = effects[index]; glassMat.needsUpdate = true; setGlossControlsVisibility(); }, { signal: listenerAbort.signal }); -modeInput?.addEventListener('change', (event) => setMode((event.target as HTMLSelectElement).value), { signal: listenerAbort.signal }); -strengthInput.oninput = (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uStrength.value = value; strengthOutput.value = value.toFixed(2); }; -sensitivityInput.oninput = (event) => { const value = Number((event.target as HTMLInputElement).value); sensitivity = value; sensitivityOutput.value = value.toFixed(2); }; -depthInput?.addEventListener('input', (event) => { const value = Math.min(Number((event.target as HTMLInputElement).value), 0.4); depthUniforms.uDepthScale.value = value; if (depthOutput) depthOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -cameraOffsetInput.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); cameraController.setMaxOffset(value); cameraOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -gridInput.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uGridSize.value = value; gridOutput.value = value.toFixed(0); }, { signal: listenerAbort.signal }); -mosaicStyleInput.addEventListener('change', (event) => { const style = Number((event.target as HTMLSelectElement).value); uniforms.uMosaicStyle.value = style; uniforms.uGridSize.value = style === 0 ? 18 : 28; uniforms.uStrength.value = style === 0 ? 0.75 : 0.85; gridInput.value = String(uniforms.uGridSize.value); gridOutput.value = String(uniforms.uGridSize.value); strengthInput.value = String(uniforms.uStrength.value); strengthOutput.value = uniforms.uStrength.value.toFixed(2); }, { signal: listenerAbort.signal }); -curvatureInput?.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uCurvature.value = value; const output = document.querySelector('#curvatureOut') as HTMLOutputElement | null; if (output) output.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -glossInput?.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uGlossStrength.value = value; if (glossOutput) glossOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -lightXInput?.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uLightPosition.value.x = value; if (lightXOutput) lightXOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -lightYInput?.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uLightPosition.value.y = value; if (lightYOutput) lightYOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -depthFileInput?.addEventListener('change', async () => { const request = ++depthRequest; const file = depthFileInput.files?.[0]; if (!file) return; depthDebug.clear(); const url = URL.createObjectURL(file); let texture: THREE.Texture | null = null; try { const image = new Image(); image.src = url; await image.decode(); if (disposed || request !== depthRequest) return; if (aspect > 0 && Math.abs(image.width / image.height - aspect) > 0.02) throw new Error('aspect'); texture = DepthProcessor.toTexture(image); if (disposed || request !== depthRequest) { texture.dispose(); texture = null; return; } setDepth(texture); texture = null; status.textContent = '수동 depth map 적용됨 (0=뒤, 1=앞)'; } catch { if (!disposed && request === depthRequest) status.textContent = 'RGB와 종횡비가 다른 depth map입니다.'; } finally { texture?.dispose(); URL.revokeObjectURL(url); depthFileInput.value = ''; } }, { signal: listenerAbort.signal }); -resetButton.onclick = () => { cameraController.reset(); gyro.reset(); }; -gyroButton.onclick = async () => { gyroButton.textContent = `Gyroscope: ${(await gyro.toggle()) ? 'ON' : 'OFF'}`; }; -const observer = new ResizeObserver(resize); observer.observe(wrap); resize(); setMode('final'); setGlossControlsVisibility(); -let last = performance.now(); let raf = 0; -function frame(now: number): void { const dt = Math.min((now - last) / 1000, 0.1); last = now; uniforms.uViewOffset.value.copy(cameraController.update(dt, sensitivity)); camera.updateMatrixWorld(true); petDepth.updateMatrixWorld(true); uniforms.uContentViewProjection.value.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse); uniforms.uContentInverseViewProjection.value.copy(uniforms.uContentViewProjection.value).invert(); uniforms.uContentCameraPosition.value.copy(camera.position); uniforms.uTime.value = now / 1000; const diagnostic = depthDebug.update(camera, petDepth, depthUniforms.uDepthScale.value, depthUniforms.uDepthBias.value, wrap.clientWidth); debugOutput.textContent = diagnostic; debugOutput.hidden = !diagnostic; if (mode === 'final' || mode === 'glass') { renderer.setRenderTarget(renderTarget); renderer.render(scene, camera); renderer.setRenderTarget(null); uniforms.uSceneTexture.value = renderTarget.texture; renderer.render(glassScene, postCamera); } else { renderer.setRenderTarget(null); renderer.render(scene, camera); } raf = requestAnimationFrame(frame); } -raf = requestAnimationFrame(frame); -function teardown(): void { disposed = true; mediaRequest += 1; depthRequest += 1; clearPendingPair(); listenerAbort.abort(); cancelAnimationFrame(raf); window.clearTimeout(hintTimeout); observer.disconnect(); imageInput.onchange = null; videoInput.onchange = null; effectInput.onchange = null; strengthInput.oninput = null; sensitivityInput.oninput = null; resetButton.onclick = null; gyroButton.onclick = null; retry.onclick = null; pointer.dispose(); gyro.dispose(); loader.dispose(); renderTarget.dispose(); if (active !== emptyTex) active.dispose(); if (depthUniforms.uDepthMap.value !== depthMap) depthUniforms.uDepthMap.value.dispose(); depthMap.dispose(); petDepth.geometry.dispose(); petDepthMaterial.dispose(); geometry.dispose(); petMat.dispose(); glass.geometry.dispose(); glassMat.dispose(); emptyTex.dispose(); renderer.domElement.remove(); renderer.dispose(); hintElement.style.opacity = '0'; retry.remove(); debugOutput.remove(); } -const hot = import.meta as ImportMeta & { hot?: { dispose(fn: () => void): void } }; hot.hot?.dispose(teardown); diff --git a/docs/before-reference2/mosaic.frag b/docs/before-reference2/mosaic.frag deleted file mode 100644 index d1d23a8..0000000 --- a/docs/before-reference2/mosaic.frag +++ /dev/null @@ -1,31 +0,0 @@ -uniform sampler2D uSceneTexture; -uniform mat4 uContentViewProjection,uContentInverseViewProjection; -uniform vec3 uContentCameraPosition,uLightPosition; -uniform float uGlassZ,uGridSize,uStrength,uMosaicStyle,uCurvature,uGlossStrength; -uniform vec2 uViewOffset,uPetSize,uPaneSize; -uniform vec4 uPaneRect; -varying vec2 vUv; -vec2 projectUv(vec3 p){vec4 c=uContentViewProjection*vec4(p,1.);float w=abs(c.w)<.0001?(c.w<0.?-.0001:.0001):c.w;return c.xy/w*.5+.5;} -vec4 sampleScene(vec2 uv){return texture2D(uSceneTexture,clamp(uv,0.,1.));} -vec4 samplePane(vec2 pane){return sampleScene(projectUv(vec3((pane-.5)*uPaneSize,uGlassZ)));} -float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);} -vec2 hash2(vec2 p){return vec2(hash(p),hash(p+vec2(19.19,73.73)));} -float safeZ(float z){return abs(z)<.0001?(z<0.?-.0001:.0001):z;} -vec3 bend(vec3 i,vec3 n){vec3 r=refract(i,n,.75);return length(r)<.0001?i:r;} -float softLimit(float value,float limit){return value*limit/(limit+abs(value));} -void main(){ - if(uStrength<=.001){gl_FragColor=sampleScene(vUv); - #include - return;} - vec4 f=uContentInverseViewProjection*vec4(vUv*2.-1.,1.,1.);float fw=abs(f.w)<.0001?(f.w<0.?-.0001:.0001):f.w;vec3 farWorld=f.xyz/fw;vec3 i=normalize(farWorld-uContentCameraPosition);float gt=(uGlassZ-uContentCameraPosition.z)/safeZ(i.z);vec3 gh=uContentCameraPosition+i*gt; - vec2 paneUv=gh.xy/uPaneSize+.5;vec2 grid=vec2(uGridSize,max(1.,uGridSize*uPaneSize.y/uPaneSize.x));vec2 gridUv=paneUv*grid,cell=floor(gridUv),local=fract(gridUv)-.5,cellSize=1./grid,random=hash2(cell);float style=clamp(uMosaicStyle,0.,1.),cellWorld=min(uPaneSize.x/grid.x,uPaneSize.y/grid.y); - if(paneUv.x<0.||paneUv.x>1.||paneUv.y<0.||paneUv.y>1.){gl_FragColor=sampleScene(vUv); - #include - return;} - float height=.009*cellWorld*clamp(uCurvature,0.,1.)*mix(.92,1.08,hash(cell+vec2(41.7,17.3))); vec2 q=2.*local; vec2 q2=q*q,q3=q2*q,b=1.-q2*q2; vec2 skew=(hash2(cell+vec2(23.8,61.2))-.5)*.28; float asym=1.+dot(skew,q); vec2 dhdq=height*vec2(-4.*q3.x*b.y*asym+b.x*b.y*skew.x,-4.*q3.y*b.x*asym+b.x*b.y*skew.y); vec2 cellDimensions=uPaneSize/grid; vec2 grad=-2.*dhdq/cellDimensions; vec3 nCurved=normalize(vec3(grad+(random-.5)*.012,1.)),nFacet=normalize(vec3((random-.5)*.012,1.)); - vec3 straightHit=gh+i*(-gh.z/safeZ(i.z));vec3 facetRay=bend(i,nFacet),curvedRay=bend(i,nCurved);vec3 facetHit=gh+facetRay*(-gh.z/safeZ(facetRay.z)),curvedHit=gh+curvedRay*(-gh.z/safeZ(curvedRay.z));vec2 base=facetHit.xy-straightHit.xy,curve=curvedHit.xy-facetHit.xy;vec2 worldDelta=vec2(softLimit(base.x,cellWorld*.08),softLimit(base.y,cellWorld*.08));vec2 d=curve/cellWorld;worldDelta+=vec2(.3*d.x/(.3+abs(d.x)),.3*d.y/(.3+abs(d.y)))*cellWorld; - vec2 sourceCenter=(cell+.5)/grid+(random-.5)*.20*cellSize+worldDelta/uPaneSize;vec2 widths=mix(vec2(.72),vec2(1.08),hash2(cell+vec2(7.2,3.1)));if(style>.5)widths=mix(vec2(.82),vec2(1.12),hash2(cell+vec2(11.4,9.8)));float angle=(random.x-.5)*.08,c=cos(angle),s=sin(angle);vec2 sampleUv=sourceCenter+mat2(c,-s,s,c)*(local*cellSize)*widths; - float edgeDistance=min(min(paneUv.x,paneUv.y),min(1.-paneUv.x,1.-paneUv.y));float edgeWeight=smoothstep(0.,max(cellSize.x,cellSize.y)*.75,edgeDistance);float strength=clamp(uStrength,0.,1.)*edgeWeight;vec2 blurStep=cellSize*mix(.006,.012,hash(cell+vec2(5.)));vec2 centerUv=mix(paneUv,sampleUv,strength);vec4 color=samplePane(centerUv)*.4;color+=samplePane(mix(paneUv,sampleUv+vec2(blurStep.x,0.),strength))*.15;color+=samplePane(mix(paneUv,sampleUv-vec2(blurStep.x,0.),strength))*.15;color+=samplePane(mix(paneUv,sampleUv+vec2(0.,blurStep.y),strength))*.15;color+=samplePane(mix(paneUv,sampleUv-vec2(0.,blurStep.y),strength))*.15;color.a=1.; - vec3 v=normalize(uContentCameraPosition-gh),reflected=reflect(-v,nCurved); float lightT=(uLightPosition.z-gh.z)/safeZ(reflected.z); vec2 lightHit=gh.xy+reflected.xy*lightT; vec2 halfSize=vec2(.32,.42)*min(uPaneSize.x,uPaneSize.y); vec2 windowCoord=abs(lightHit-uLightPosition.xy)/halfSize; vec2 windowMask=1.-smoothstep(vec2(.45),vec2(1.15),windowCoord); float spec=windowMask.x*windowMask.y*step(.0001,reflected.z)*step(0.,lightT); float gloss=spec*clamp(uGlossStrength,0.,1.)*.12*edgeWeight*clamp(uStrength,0.,1.); color.rgb=mix(color.rgb,vec3(1.),gloss); gl_FragColor=color; - #include -} diff --git a/docs/cell-continuity-fix.md b/docs/cell-continuity-fix.md deleted file mode 100644 index 25206d6..0000000 --- a/docs/cell-continuity-fix.md +++ /dev/null @@ -1,26 +0,0 @@ -# 인접 셀 연결성 재보정 - -## 요구와 원인 - -유리는 공통 사진의 눈·코 윤곽을 셀 내부에서 확대/압축하되, 인접 셀이 서로 무관한 사진 조각을 가져오는 인상을 만들면 안 된다. 자동 확대·팬·크롭과 RGB/depth 배치는 변경하지 않는다. - -이전의 광학 거리 0.6 보정은 셀 끝까지 커지는 곡면 기울기와 폭 0.04의 급격한 방향 전환을 함께 증폭했다. 셀 폭 0.55의 변위 상한은 좌표 변화율을 제한하지 않으므로 국소적으로 사진을 읽는 순서가 뒤집히는 것을 방지하지 못한다. 공통 광선 사용만으로 연결성이 보장되지는 않는다. - -## 설계 - -기본 조각 유리는 전 셀에 이어지는 사인 곡면 기울기를 사용한다. 셀 중심과 경계에서 기울기가 0이며, 확대와 압축은 셀 전체에 분산한다. 독립 셀 난수 기울기는 작은 유리판 전체 기울기로 대체한다. 굴절·반사는 같은 법선을 사용하며 색면 atlas도 같은 좌표 계산을 따른다. - -강도는 셀 크기와 유효 광학 거리로 보정한다. 실제 가까운 피사체 배치는 유지한다. 이는 연출용 광학 근사이며 유리 두께의 물리 시뮬레이션은 아니다. - -## 검증 기준 - -- 색면·광택 0에서 같은 눈·코 윤곽이 셀 경계를 넘어 연결되는지 확인한다. -- 실제 투영 좌표의 변화율을 수치 검사한다. 양의 행렬식뿐 아니라 가로·세로 좌표 진행 방향도 확인한다. -- 셀 경계 근처, 유리판 테두리, Grid/굴곡/카메라/피사체 간격의 여러 조건을 포함한다. -- 색면 복원 후 색상 경계와 굴절 좌표 단절을 구분한다. 셀별 팔레트 자체의 색상 차이는 별도 한계이며 기하 검사를 통과했다고 없어지는 것은 아니다. - -## 적용 및 결과 - -`src/shaders/mosaic.frag`에 기본 조각 유리의 사인 곡면과 전역 facet 기울기를 적용했다. 촘촘 유리 분기는 기존 동작을 유지했다. `scripts/test-mosaic-continuity.mjs`는 Grid 6/10/96, 굴곡 -1/0/0.65/1, 두 패널 비율, 카메라 세 위치, 두 sourceZ를 순회하며 최종 투영 좌표의 Jacobian과 셀 경계 수렴을 검사한다. - -2026-09-14 결과: 66,816개 Jacobian과 52,320개 경계 검사를 통과했다. `npm run build`도 통과했다(기존 500KB 초과 번들 경고). 브라우저에서 색면·광택 0의 dog1을 확인한 뒤 기본 색면 0.65·광택 0.3·depth 0.25를 복원했다. 정성적으로 인접 셀의 눈·코 윤곽은 이전처럼 서로 다른 조각으로 튀지 않고 이어졌지만, Ref2의 큰 얼굴 구도와 색면 내부 명암 보존은 별도 작업이다. diff --git a/docs/cell-curvature-plan.md b/docs/cell-curvature-plan.md deleted file mode 100644 index d9845de..0000000 --- a/docs/cell-curvature-plan.md +++ /dev/null @@ -1,11 +0,0 @@ -# 셀 곡면 보정 설계 - -2026-09-11. 기존 QA 원인 대응. - -- Mosaic 셀은 world z=uGlassZ 유리판 기준으로 고정. uPaneSize는 중립 사진 크기와 투영이 일치하도록 계산. Grid Size는 유리 가로 셀 수이며 화면 비율에 무관하다. -- 각 셀은 얕은 사각 pillow 곡면으로 모델링한다. 동일한 곡면 법선을 굴절/광택에 공유하며 고정 hash로 미세 높이 편차만 준다. 시간 난수, 검은 격자, 방사형 파문은 제외. -- 곡면 굴절과 평면 기울기의 굴절을 따로 제한해, 큰 시점 이동이 작은 굴곡을 지우지 않도록 한다. RenderTarget을 사용하는 얕은 렌즈 근사이며 정확한 광선추적은 아니다. -- 샘플 폭을 넓혀 셀 안의 사진 정보 보존. 기본 조각18칸/.75, 촘촘28칸/.85. 광택 .30에서 시작하며 강한 회색 덧칠을 줄인다. -- 셀 굴곡 조절로 광택을 끈 상태에서 곡률 유무 비교. 사진 리라이팅은 제외. Depth/RT와 다른 유리 셰이더는 유지. - -완료 기준: 두 viewport에서 동일 가로 셀 수; 눈/코 정보 유지; 광택0에서도 곡면 왜곡; 곡면 법선에 따른 반사; 실제 drag에서 world 판 좌표 일관성; Distortion0 원본 복원; 빌드/브라우저 셰이더 오류 확인. 정밀 물리 유리 두께/환경맵/새 이미지 생성은 범위 밖. diff --git a/docs/cell-curvature-validation.md b/docs/cell-curvature-validation.md deleted file mode 100644 index 9ffb47d..0000000 --- a/docs/cell-curvature-validation.md +++ /dev/null @@ -1,24 +0,0 @@ -# 셀 곡면 수정 검증 - -2026-09-11. Astra 설계/정적 검토, GPT-5.6 Luna 소스 구현, 조정 에이전트 브라우저 QA. - -## 반영 - -- src/shaders/mosaic.frag: 유리판 world 좌표에서 셀/마스크/곡면 계산, pane→world→screen projection으로 RT 샘플. 동일 사각 pillow 곡면 법선을 굴절과 광택에 사용. 곡면 변화량과 기본 굴절량을 별도 soft limit. 작은 샘플 폭/색블록 문제 완화. 기존 셀 hash, 렌더타깃, 굴절 및 5-tap 흐름 유지. -- src/main.ts, index.html: uPaneSize, 셀 굴곡 0~1 기본 .65, 조각18/.75·촘촘28/.85, 광택 .30. Mosaic 전용 컨트롤 숨김 유지. -- 원본은 docs/before-cell-curvature/에 보존. README와 AGENTS 갱신. - -## 수행한 QA - -- 코드 변경 전 No Glass 실제 드래그로 Depth 시차가 유지됨을 재확인. -- 같은 샘플 사진/시점에서 광택0+굴곡0/.65 비교. 곡면ON에서 사진 윤곽이 셀 내부에서 휘고 OFF에서는 평면 조각으로 돌아감. 눈/코가 이전 극단적 확대보다 더 식별됨. -- 기본 광택 .30에서 셀 곡면의 밝기 차이 관찰. 이전 .55/white mix .28보다 회색 덧칠 감소. -- 390x844 모바일과 데스크톱에서 동일 가로18칸과 사진/셀 비율 확인. 모바일 문서 폭375로 가로 넘침 없음. viewport override 복원. -- 카메라 offset .6 실제 drag에서 world pane 변형/반사와 배경 시차 확인. 유리판과 사진의 외곽은 서로 다른 깊이이므로 이동 시 같지 않음. -- 움직인 시점에서 Distortion0 Final/No Glass 시각 비교: 정렬과 색상 일치. 픽셀 차이 자동 측정은 미수행. -- 두 Mosaic 프리셋, Reeded/Frosted 전환 확인. 최종 파일 저장 후 새 탭 error 로그 [] 확인. -- npm.cmd run build: tsc -b / Vite 성공,20 modules, JS489.37kB(gzip125.06kB). - -## 범위와 한계 - -얕은 유리 표면과 굴절을 셰이더로 근사한다. 실제 두께/환경맵 반사/그림자 광선추적은 없다. 참고 사진의 프레임·피사체 구도까지 재현한 것은 아니며, 테스트 원본은 그대로다. 수작업 Depth의 외곽 늘어짐 한계는 유지된다. 실제 영상/gyro/프레임 성능 측정은 이번에 수행하지 않았다. diff --git a/docs/closeup-framing.md b/docs/closeup-framing.md deleted file mode 100644 index 151a838..0000000 --- a/docs/closeup-framing.md +++ /dev/null @@ -1,13 +0,0 @@ -# 얼굴이 유리를 채우는 구도 - -사용자 요청: 멀리 떨어진 강아지 사진을 유리 너머로 보는 인상보다, 강아지가 유리 바로 뒤에 있고 얼굴이 크게 보이는 구도를 원한다. - -현재 dog1 테스트 사진의 사진 확대1은 전신과 잔디를 보여준다. 기존 RGB/Depth 공통 구도 조절로 확대2.2, 가로0, 세로-0.4를 적용한 실제 사용자 화면에서 얼굴이 유리판 대부분을 채우는 것을 확인했다. - -최소 변경은 dog1을 다시 불러올 때 이 얼굴 구도를 기본 적용하는 것이다. 원본 파일, 유리 효과, 색면, 격자, 카메라와 실제 유리-사진 간격은 변경하지 않는다. 임의 업로드에 얼굴 위치 자동 인식을 추가하지 않는다. 기존 사진 구도 초기화로 전체 사진으로 돌아갈 수 있다. - -실제 간격을 크게 줄이면 현재 광선 모델의 굴절 이동량도 줄어 사용자가 긍정적으로 평가한 셀 효과가 약해진다. 이번 결과는 얼굴 구도 확대이며, 실제 3차원 강아지가 유리에 접촉하도록 바꾼 결과로 표현하지 않는다. - -검증 기준: dog1 재로드에 확대2.2/가로0/세로-0.4, 기존 sample 프리셋 유지, 원래 구도 초기화와 재로드 복귀, 브라우저 오류 없음. 실제 거리 모델과 AI depth는 변경하지 않는다. - -적용/검증: `src/main.ts`에서 dog1의 일회성 대기 구도 플래그를 추가하고 취소 시 해제하도록 했다. 빌드·타입 검사 통과. 실제 5173 사용자 탭에서 sample 기존 구도, dog1 자동 얼굴 구도, 초기화1/0/0, 재로드2.2/0/-0.4를 확인했다. 최종 오류 로그 없음. 화면은 dog1 얼굴 구도와 사용자의 색면1·Grid14로 두었다. 강아지 얼굴이 유리 대부분을 채우는 것을 최종 화면에서 확인했다. diff --git a/docs/contact-depth-geometry.md b/docs/contact-depth-geometry.md deleted file mode 100644 index bdc2db4..0000000 --- a/docs/contact-depth-geometry.md +++ /dev/null @@ -1,18 +0,0 @@ -# Contact depth placement - -Depth uses normalized values where 0 is behind and 1 is in front. For each installed `DataTexture`, the app scans the red channel once and places the photo and depth mesh at - -```text -contentBaseZ = glassZ - 0.04 - (maxDepth - depthBias) * depthScale -``` - -The depth mesh keeps a Z scale of 1, so its highest vertex remains 0.04 world units behind the glass as the depth scale changes. The XY photo size and pan are multiplied by `(cameraZ - contentBaseZ) / cameraZ` to keep the flat photo footprint stable as it moves closer. A flat depth map stays at the near-flat placement `glassZ - 0.04`. - -Mosaic, Reeded, and Frosted trace refracted rays to the same `contentBaseZ` plane. The Mosaic color-region atlas shares that uniform. Existing glass surface normals and Mosaic height cap are unchanged; no extra slab or optical surface is added. - -New still photos without paired manual depth start the existing Depth Anything V2 Small provider automatically. Videos and the paired local sample remain unchanged. Automatic depth keeps the current view mode; the manual AI button still switches to No Glass for parallax inspection. The model does not detect or crop faces, and the highest depth point may be a paw or another foreground part, so general uploads keep their chosen framing. - -## Verification - -- `npm run build` passed (`tsc -b` and Vite production build); Vite reports the existing large-chunk advisory. -- Glass-off sample check at depth scale 0.25 reported `contentBaseZ=0.315`, `maxFrontZ=0.560`, and `glassGap=0.040`. At scale 0, the placement formula keeps the front at 0.560 with the base at 0.560. Scale 0.4 keeps the same front clearance by moving the base farther back. diff --git a/docs/contact-regression-review.md b/docs/contact-regression-review.md deleted file mode 100644 index ad954bf..0000000 --- a/docs/contact-regression-review.md +++ /dev/null @@ -1,50 +0,0 @@ -# 근접 배치 이후 시점 변형 약화 검토 - -## 수정 완료 — 2026-09-14 - -## 후속 수정 — 시점에 따른 셀 내부 굴절 - -기본 Mosaic에만 셀 내부 시점 반응 항을 추가했다. 현재 입사광선과 같은 곡면 법선을 통과하는 중심 기준광선의 굴절 기울기 차이를 부드럽게 제한해, cosine envelope가 0인 셀 경계는 고정하고 내부 이동만 만든다. 계산은 공유 signed curvature scale을 사용하며 REGION_ATLAS와 최종 Mosaic 모두 같은 셰이더 경로를 거친다. 초기 gain .18 cell로 두었다. 이는 유리 입출사면을 추가한 물리 광선 추적이 아니라 현재 평면 교점 광학 모델 안의 연출 근사다. - -CPU 연속성 검사는 296,256개 Jacobian과 52,320개 경계 수렴 사례에서 양수 방향/연속성을 통과했고, 정면 기준 변위 0·셀 축 경계 고정·비스듬한 시점의 셀 내부 변위 분산도 통과했다. - -브라우저에서는 dog4/AI depth/Grid10/Distortion .9/굴곡 .65/광택 0/Depth .25/확대 1/팬 0에서 중앙과 좌우 약 120px 이동을 비교했다. 색면 0에서 코·가슴 윤곽의 폭과 위치가 달라졌고, 색면 1에서도 셀 내부 경계와 목줄·가슴의 색 영역 변화가 확인됐다. 변화는 사진틀 이동에만 그치지 않았다. 색면 1에는 포스터화 인상이 여전히 남는다. 실제 연속 영상의 깜빡임은 정량 검증하지 않았으며, Ref1의 최종 달성으로 판단하지 않는다. 추가 샘플 확인은 진행 중이다. - -후속 실화면 확인에서 정면 시점과 좌우 약 120px 이동 시 색면 1에서도 내부 변형이 보였고, Distortion 0에서는 기존 무효과 출력으로 돌아가는 것을 확인했다. 이 역시 특정 테스트 사진의 시각 확인이며, 일반 사진 전체나 연속 프레임 flicker의 검증은 아니다. - -기본 Mosaic의 굴절 변위만 실제 피사체 간격에서 분리했다. `mosaic.frag`에서 입사/굴절 광선의 XY 기울기 차이에 최소 0.6의 음수 광학 이동 거리를 곱하고 기존 셀 크기 기반 제한을 적용한다. 직진 교점과 최종 투영은 실제 `uSourceZ`를 유지한다. 사진/깊이 배치, 확대·팬, 곡면 법선과 반사, 색면 알고리즘은 변경하지 않았다. 이 최소 거리는 연출용 근사이며 실제 유리 두께가 아니다. 촘촘 유리/Reeded/Frosted는 이번 수정 대상이 아니다. - -Luna 구현 후 `npm run build` 통과(기존 번들 크기 경고), Astra 독립 수식/분기 검토에서 차단 문제 없음. 브라우저 5173에서 멍멍이1/자동 AI depth/zoom1/pan0/Grid10/Distortion0.9로 확인했다. HMR로 사진이 초기화되어 같은 테스트 사진을 다시 로드했다. - -- No Glass에서 수평 드래그 후 깊이 장면 이동을 확인했다. 이번에는 랜드마크별 시차를 계측하지 않았다. -- 색면0·광택0의 Final에서 눈·코와 털 윤곽이 셀별로 확대/압축되어 보이는 것을 확인했다. 좌우 드래그에서 형태와 위치 변화가 보였지만 연속 프레임 안정성을 정량 측정하지 않았다. -- Depth Scale0으로 실제 간격이 최소일 때도 굴절 변형이 유지됐다. Distortion0에서는 셀 변형 없이 원본 윤곽으로 돌아왔다. -- 브라우저 오류 로그 없음. 색면1·광택0.3·depth0.25·Distortion0.9를 복원하고 시점을 초기화했다. Ref1|Ref2 비교 배치 유지. - -이번 통과 범위는 근접 배치 때문에 굴절이 약화되는 회귀 수정이다. 색면1에서 눈 내부 명암이 평평해지고 잔디의 작은 영역이 많이 남는 문제는 여전히 보인다. Ref2와 최종 시각 일치까지 완료했다고 판단하지 않는다. - -사용자 지적: 유리에 붙은 이미지 개념을 적용한 뒤 시점에 따른 강아지 형상 변화가 거의 없어졌다. - -## 결론 - -근접 배치와 굴절 변형의 이동 거리를 동일하게 묶은 변경이 원인이다. 피사체를 가까이 배치해야 한다는 요구를 만족시키면서 기존 셀의 시점 의존 변형을 유지하는지를 검증하지 못했다. 이전의 간격0.040/관통 방지 검증만으로 시각 목표를 통과 처리한 것은 불충분했다. - -`src/main.ts`의 contentBaseZ와 uSourceZ는 같은 값이다. `src/shaders/mosaic.frag`의 직진·굴절 교점 차이는 유리에서 이 기준 평면까지의 거리에 비례한다. Reeded/Frosted도 같은 방식이다. - -기존 간격0.6은 maxDepth1/depthScale0.25일 때0.29로 줄고, 평면 입력이나 depthScale0일 때0.04로 줄었다. 같은 광선과 법선의 제한 전 변위는 각각 기존의 약48%/7%다. 정면 투영의 작은 변위로 환산하면 약54%/8%지만, 실제 셰이더에는 변위 제한이 있어 화면 전체가 이 비율로 변한다고 단정하지 않는다. - -## 구분해야 할 점 - -- depth mesh의 점 사이 z차이는 여전히 depthScale×깊이차다. 카메라도 실제 이동한다. 따라서 깊이 자체가 평면화됐다고 설명하면 부정확하다. -- XY 보정은 기준 평면의 정면 크기를 유지한다. 상대 깊이를 없애는 계산은 아니다. -- 현재 유리는 평면 교점에서 곡면 법선으로 광선을 한 번 굴절시키는 근사다. 유리 두께와 출사면, 실제 depth 표면과의 굴절광선 교차는 구현돼 있지 않다. 피사체 간격만 줄여서는 Ref의 렌즈 같은 변형을 유지할 수 없다. - -## 이번 확인 - -5173 사용자 dog1/AIdepth/색면1/Grid10/depthScale0.25/CameraOffset0.3 설정에서 Final과 No Glass를 비교하고, 짧은 수평 드래그 후 반대 방향으로 되돌렸다. Final에서는 큰 형상 변화보다 작은 이동과 색면 변화가 두드러졌다. 정확한 랜드마크 변형량이나 모든 연속 프레임을 측정한 검사는 아니다. 코드와 광선식에 근거해 원인을 분리했다. 소스 수정·빌드는 하지 않았다. - -## 다음 수정 기준 - -사진 구도와 자동 구도 조정 금지, 근접 배치는 유지한다. 공통 광선과 같은 곡면 법선을 사용하면서 굴절 변형의 유효 광학 거리를 피사체의 실제 간격에서 분리하는 것이 작은 수정 방향이다. 직진 기준과 최종 장면 투영은 실제 평면을 사용해야 하며, 임의 셀별 사진 크롭으로 대체하지 않는다. 이 경우 의도적인 광학 근사라고 명시한다. 더 물리적인 대안인 유리 두께·입출사 양면 구현은 별도 범위다. - -검증 순서: 같은 사진·같은 구도에서 No Glass 상대 시차 → 색면/광택0 Mosaic의 셀 내부 변형 → 색면/광택 복원. 근접한 배치에서도 드래그 시 눈·코 윤곽과 배율 변화가 확인돼야 하며, 간격 수치가 맞는 것만으로 완료하지 않는다. diff --git a/docs/current-state-qa.md b/docs/current-state-qa.md deleted file mode 100644 index 28ac44d..0000000 --- a/docs/current-state-qa.md +++ /dev/null @@ -1,26 +0,0 @@ -# 현재 상태 QA — 2026-09-11 - -소스 수정 없이 브라우저 QA와 Astra 정적 검토를 수행했다. - -## 재현된 개선 항목 - -1. 창틀 밖 효과: 샘플 얼굴 구도에서 Final → Reeded/Frosted 전환 시 확대 사진과 효과가 창틀 밖까지 표시된다. 기존 문서에 명시된 한계로, 이번 곡률 변경의 회귀는 아니다. 모든 효과의 유리 영역을 같은 pane 경계로 맞추는 것이 시각 일관성의 우선 과제다. Distortion 0의 원본 출력 요구사항은 별도로 유지해야 한다. -2. P2 키보드 업로드: 새로고침 후 첫 Tab이 샘플 버튼으로 이동한다. 사진/영상/Depth input은 computed display:none이며 label은 키보드 동작을 제공하지 않는다. src/style.css:1, index.html:4. -3. P2 샘플 출처 안내: 샘플 로딩 완료 후 #status.textContent가 빈 문자열이다. main.ts의 안내를 MediaLoader.ts:31에서 지운다. 수작업 Depth이며 AI가 아니라는 안내를 지속적으로 표시해야 한다. - -## 시각 판단 - -- 창틀과 Mosaic 경계는 데스크톱/모바일 및 이동 시 함께 유지된다. -- 강한 볼록(+1), 특히 이동한 모바일 화면에서는 눈·코를 가로지르는 조각의 불연속이 뚜렷하다. 오목(-1)은 윤곽이 상대적으로 이어지지만 다른 유리 형태이므로 이를 단순한 품질 우위로 간주하지 않는다. -- 다음 시각 보정은 광택 강도를 올리기보다 셀별 샘플 이동/배율 불연속과 곡면 기여를 분리해 비교하는 방향을 권한다. 레퍼런스의 조각별 정보 차이는 보존해야 하므로 경계를 모두 흐리는 방식은 피한다. 이번 QA에서 재튜닝은 하지 않았다. - -## 확인한 동작 - -- npm.cmd run build 통과, 브라우저 error 로그 없음. -- No Glass 카메라 시차: cameraX 0→0.107에서 nose X 531.509→528.377, eye 459.283→457.303, body 350.477→350.378 px. 부위별 이동량 차이 확인. 수작업 테스트 Depth 기준이다. -- Final/No Glass 전환, Mosaic/Reeded/Frosted 전환 및 Mosaic 전용 굴곡/광택 컨트롤 숨김. -- 오목 -1, 볼록 +1 표시, 기본 설정 및 Reset view. -- 1280×720와 390×844 화면. 모바일 Camera Offset .6 설정 후 드래그, 창틀 경계 결합 확인. 실제 도달 cameraX .324를 관측했으며 최대 offset 도달을 주장하지 않는다. -- 정적 검토: signed 높이 방향 및 공유 법선, 곡률0의 facet 유지, RGB/Depth 공통 구도, RT 구조, 창틀 좌표 및 자원 정리 일치. - -영상 재생, 실제 센서/터치 하드웨어, 성능 계측, 장시간 메모리 누수는 이번 검증에서 실행하지 않았다. 뷰포트 override는 복원했고 임시 QA 탭은 닫았다. diff --git a/docs/depth-implementation-plan.md b/docs/depth-implementation-plan.md deleted file mode 100644 index 350d2dc..0000000 --- a/docs/depth-implementation-plan.md +++ /dev/null @@ -1,56 +0,0 @@ -# Depth 확장 구현 명세 - -## 판단과 범위 - -사용자 수정지시 원문은 `docs/depth-task-brief.txt`이다. 기존 main.ts 기반의 작은 앱을 유지하고, 조직만을 위한 SceneManager 등 전면 재구성은 하지 않는다. 현재 카메라도 실제로 이동하지만 피사체는 평면이며 Glass가 원본 이미지를 직접 읽는다. 이번 핵심은 이 두 지점을 depth mesh와 content render target으로 바꾸는 것이다. 기존 Mosaic의 셀별 normal/refract/lens variation은 보존한다. - -첨부 사진의 깊이는 실측 또는 AI 추정 데이터가 없다. 따라서 테스트용 깊이는 사진을 직접 확인하여 만든 수작업 가상 깊이이며 UI/보고에서 이 사실을 밝힌다. 사용자 업로드에 샘플용 깊이를 적용하지 않는다. 업로드 후 깊이가 없으면 flat depth로 복귀한다. AI, segmentation, video depth estimation은 제외한다. - -## 단계 1A: 샘플 깊이 자산 - -- 원본은 `public/assets/sample-pet.png` (415 × 739)를 그대로 사용한다. -- 동일 크기 grayscale `public/assets/sample-pet-depth.png`와 재생성 가능한 작은 스크립트를 만든다. RGB 이미지 자체의 편집은 하지 않는다. -- 좌표는 이미지 좌상단 원점이다. 사진을 직접 확인한 대략의 landmark: 코 (235,310), 왼쪽 눈 (198,278), 오른쪽 눈 (249,273), 얼굴 (221,267), 왼쪽 귀 (158,213), 오른쪽 귀 (262,206), 몸 (139,419). 좌우는 보는 사람 기준이다. -- 0=뒤, 1=앞. 배경 약 .08, 몸 .30, 귀 .43, 얼굴 .60, 눈 .68, 주둥이 .82, 코 .98을 목표로 부드러운 타원/마스크를 합성한다. 단순 전체 gradient나 코와 눈이 같은 plateau인 map은 피한다. 겹친 영역의 최종 깊이를 실제 PNG에서 읽고 확인한다. -- 얼굴/몸/귀의 크기를 사진에 맞춰 선택하고 타원 가장자리는 연속적으로 부드럽게 처리한다. 코와 눈은 별도의 작은 영역이며 사진 배경을 과도하게 앞으로 끌어오지 않는다. -- CPU 측정과 shader에서 같은 좌표/값을 사용할 수 있도록 landmark 좌표와 grayscale 값을 보고한다. 이미지 상단 y와 texture UV의 v 반전을 명확히 한다. - -## 단계 1B: Glass OFF 깊이 구현 - -이 단계에서는 RenderTarget과 Glass shader 변경을 금지한다. 검증 통과 후 별도 단계로 연결한다. - -1. `DepthProvider`와 static loader를 최소한으로 추가한다. 입력은 별도 depth 이미지와 샘플 pair이며, 내부 depth texture는 NoColorSpace / 0뒤1앞이다. grayscale 및 필요 시 invert UI로 규칙을 명확히 한다. RGB와 depth의 aspect가 다르면 사용자가 알 수 있는 오류를 표시한다. async stale 요청을 무시하고 교체/실패/HMR에서 texture 및 object URL을 정리한다. -2. `PetDepthMesh`를 추가한다. PlaneGeometry(1,1,128,128), RGB texture, depth texture, ShaderMaterial을 갖는다. vertex shader에서 z += (depth - bias) * scale을 실제로 적용한다. fragment는 RGB를 읽고 출력 색공간 처리를 한다. RGB는 sRGB, depth는 비색상 데이터다. 기존 VideoTexture는 flat depth 또는 명시 업로드한 static depth로 지원한다. -3. Depth scale 기본 .25, 범위 0~.4. bias는 .08 정도의 고정값도 충분하다. 미디어 contain 계산은 기존 resize를 이용하고 z축 scale은 1을 유지한다. 기존 flat pet을 RGB/debug 또는 fallback으로 활용해도 된다. -4. View mode: Final(기존 Glass 경로, 임시), RGB(평면 원본), Depth(평면 grayscale map), No Glass(depth mesh). 샘플 로드 시 No Glass를 선택해 단계 목표를 바로 보이게 한다. Depth view는 조명/굴절 없이 map을 확인할 수 있어야 한다. -5. camera offset UI 기본 .3, 최대 .6, z=3, lookAt(0,0,0). 기존 target/current 보간, pointer, gyro, sensitivity/reset은 유지한다. viewOffset은 현 Glass용 보조 입력으로 그대로 남긴다. 실제 parallax 검증은 No Glass 경로만 대상으로 한다. -6. 사진/영상 업로드와 sample pair 전환에서 이전 sample depth가 새 미디어에 남지 않게 한다. sample pair load도 기존 loader의 request lifetime과 충돌하지 않도록 하나의 로딩 경로를 재사용한다. - -### 단계 1 게이트 - -- `npm run build` 통과를 기록한다. 이는 시각 동작 검증을 대체하지 않는다. -- 실제 브라우저에서 샘플 RGB/Depth/No Glass를 확인한다. No Glass, scale .3, 카메라 왼쪽/중앙/오른쪽 이미지를 캡처한다. depth 0에서도 동일 카메라 조건을 캡처한다. -- landmark별 실제 map 값을 읽고 world 위치 및 camera projection으로 CSS pixel 위치를 측정한다. mesh local x=u-.5, y=.5-yTop, z=(d-bias)*scale에 실제 mesh transform을 적용하고, 현재 camera matrix로 project한다. 측정에 사용한 depth 샘플링은 GPU linear sampling 및 UV 방향과 일치해야 한다. -- 각 landmark i의 좌우 이동 D_i(scale)=x_i(right)-x_i(left)를 얻는다. depth로 추가된 이동 E_i=D_i(.3)-D_i(0)를 기록한다. flat 상태에서도 perspective/lookAt 때문에 영역별 움직임이 조금 다르므로 raw 이동만으로 성공을 주장하지 않는다. -- 코-눈 평균 및 코-몸의 상대 이동 차이 E_nose-E_eyes, E_nose-E_body를 기록한다. 의도한 방향에서 코가 눈보다, 눈이 몸보다 크게 추가 이동해야 한다. 800px 안팎의 데스크톱 canvas에서 코-눈 상대 차이 절댓값 1 CSS px 이상을 목표로 하고 값이 작으면 map/offset을 허용 범위 안에서 조정한다. 코/눈/몸의 차이를 화면에서도 확인해야 한다. -- scale 0에서 displaced mesh가 RGB와 맞고 Depth map의 코/눈/귀/몸 위치가 원본과 정렬되는지 확인한다. 정상 이미지 로딩, flat fallback, video 유지와 반복 콘솔 오류 없음도 확인한다. -- 통과 판정 이전에는 단계 2를 구현하지 않는다. - -## 단계 2: Content → RenderTarget → 기존 Glass - -단계 1 통과 후 수행한다. - -- contentScene에 depth mesh/배경을 두고 실제 이동 camera로 renderTarget에 렌더한다. 화면 출력을 위한 glassScene 또는 fullscreen surface는 별도로 둔다. contentScene에 glass 자체를 넣지 않아 feedback을 방지한다. -- renderer/RT DPR을 최대 1.5로 제한하고 resize 시 실제 drawing buffer size에 맞춘다. target은 교체/teardown에서 dispose한다. -- 기존 Mosaic 셀별 lens normal, variation, refract, viewOffset 보조 효과를 유지한다. Reel/Frosted도 source sampling만 scene texture로 전환한다. 새 입력 이름은 uSceneTexture 권장. -- renderTarget은 전체 viewport 이미지이다. 기존 hitUv의 pet-local UV를 그대로 RT UV로 사용하면 contain/카메라 이동이 어긋난다. world hit를 현재 content camera의 view-projection matrix로 투영하거나 screen-space straight UV + projection된 refracted displacement로 바꾼다. strength=0에서 screen pixel의 원본 scene 결과가 정확히 유지되는 것을 기준으로 삼는다. -- fullscreen quad를 택하면 실제 content camera 정보/virtual glass plane ray를 명시적으로 제공한다. post camera의 cameraPosition을 content camera로 잘못 사용하는 일이 없어야 한다. world-space GlassPlane을 유지하면 glass가 maximum displaced mesh보다 앞에 있도록 배치하고 나머지 화면에도 content가 보이게 한다. -- RT의 linear color를 glass에서 다시 sRGB decode하지 않는다. video decode는 content 단계에서 끝낸다. 최종 screen 출력만 colorspace 변환한다. 밝기/색이 No Glass와 strength0 Final에서 일치해야 한다. -- Final은 새 2-pass 결과, No Glass는 직접 content 렌더, RGB는 평면, Depth는 map, Glass Only는 중립 배경 위 lens 패턴의 진단이다. gridSize도 UI에 노출한다. - -### 최종 검증 - -- stage1 parallax 게이트 재확인, Mosaic에서 좌우 이동 시 코/눈이 셀 안에서 달라지는 실제 화면 확인. -- strength0 Final vs No Glass의 정렬/색 일치, 세 효과 모두 scene target sampling 확인. -- 데스크톱/모바일 contain, resize, 사진 업로드→sample→video→image 전환, depth 교체, reset, build 및 반복 콘솔 오류 확인. -- 보고: 수정/신규 파일, depth 규칙과 수작업 한계, 128 mesh 및 z displacement, camera 이동, 2-pass와 lens 보존, 측정 결과, 실행 방법, 미실행 검증, AI provider를 교체할 위치를 간단히 정리한다. diff --git a/docs/depth-task-brief.txt b/docs/depth-task-brief.txt deleted file mode 100644 index fcacb4f..0000000 --- a/docs/depth-task-brief.txt +++ /dev/null @@ -1,904 +0,0 @@ -[수정 작업지시서] -프로젝트명 -Pet Glass / Pet Behind Glass - -수정 목적 -현재 진행 중인 구현은 -"PetPlane 평면 Texture + GlassPlane Shader + viewOffset 기반 UV 왜곡" -방식으로 구성되어 있다. - -하지만 이 방식만으로는 -실제 사진에서 보이는 핵심 시각효과를 충분히 재현하기 어렵다. - -실제 모자이크/굴절 유리에서 재미있는 변화는 -유리 뒤 피사체의 눈, 코, 얼굴, 몸 등이 서로 다른 깊이에 있기 때문에 -관찰 시점이 변할 때 각 부분이 서로 다른 위치로 보이는 데서 발생한다. - -따라서 기존 구조를 전면 폐기하지 말고, -현재 구현을 기반으로 아래 방향으로 확장한다. - - -======================================== -1. 핵심 변경사항 -======================================== - -기존: - -Camera -↓ -Glass Plane -↓ -Pet Plane (완전한 평면) - -+ -Pointer 위치를 uViewOffset으로 Shader에 전달 -+ -UV sampling 위치를 인위적으로 이동 - - -변경: - -Camera -↓ -Glass Surface -↓ -Depth-displaced Pet Mesh -↓ -Background - -즉, -Pet 이미지를 단순 평면으로 두지 않고 -Depth Map을 이용하여 얕은 3D 형태의 Mesh로 변환한다. - -카메라 이동에 따라 -실제 perspective/parallax가 발생하도록 만들고, -Glass Shader는 이 결과를 굴절시킨다. - - -======================================== -2. 기존 코드 유지 원칙 -======================================== - -현재 작성된 코드를 전부 다시 만들지 않는다. - -가능하면 다음 구조는 유지: - -- SceneManager -- CameraController -- RendererManager -- MediaLoader -- PointerController -- GyroController -- GlassPlane -- 기존 UI -- 기존 Mosaic/Reeded/Frosted shader - -수정 핵심은: - -PetPlane -→ -PetDepthMesh - -로 확장하는 것. - -기존 PetPlane 구현은 필요하면 fallback 용도로 남겨도 된다. - - -======================================== -3. 새 구조 -======================================== - -권장 구조: - -src/ -├─ scene/ -│ ├─ SceneManager.ts -│ ├─ CameraController.ts -│ └─ RendererManager.ts -├─ objects/ -│ ├─ PetPlane.ts -│ ├─ PetDepthMesh.ts // 신규 -│ ├─ BackgroundPlane.ts // 선택 -│ └─ GlassPlane.ts -├─ depth/ -│ ├─ DepthMapLoader.ts // 신규 -│ ├─ DepthProcessor.ts // 신규 -│ └─ DepthProvider.ts // 신규 interface -├─ shaders/ -│ ├─ common.vert -│ ├─ petDepth.vert // 신규 -│ ├─ petDepth.frag // 필요시 -│ ├─ mosaic.frag -│ ├─ reeded.frag -│ └─ frosted.frag -├─ input/ -│ ├─ MediaLoader.ts -│ ├─ PointerController.ts -│ └─ GyroController.ts -└─ types/ - ├─ glass.ts - └─ depth.ts // 신규 - - -======================================== -4. Depth Map 우선 구현 전략 -======================================== - -1차 수정에서는 -AI depth estimation을 즉시 통합하지 않아도 된다. - -먼저 Depth Map이 이미 존재한다고 가정하고 -렌더링 파이프라인부터 완성한다. - -즉: - -RGB Image -+ -Depth Image - -두 장을 입력받아 -Depth 기반 2.5D Mesh가 정상 동작하도록 구현한다. - -개발 테스트용으로: - -assets/ -├─ sample-pet.jpg -└─ sample-pet-depth.png - -형태를 지원. - -실제 depth 이미지 파일이 없으면 -gradient 또는 procedural depth texture를 생성해서 -기능 검증 가능하도록 한다. - - -======================================== -5. PetDepthMesh 구현 -======================================== - -기존 PlaneGeometry보다 segment 수가 많은 -PlaneGeometry를 사용. - -예: - -new THREE.PlaneGeometry( - width, - height, - 128, - 128 -) - -또는 - -256 x 256 - -모바일 성능을 고려하여 -기본값은 128x128 정도에서 시작. - -PetDepthMesh는: - -- RGB Texture -- Depth Texture -- ShaderMaterial -- depthScale -- depthBias - -를 가진다. - - -======================================== -6. PetDepth Vertex Shader -======================================== - -새 vertex shader를 작성. - -목적: -Depth Map의 값을 읽어서 -각 vertex를 Z 방향으로 이동. - -개념: - -uniform sampler2D uDepthMap; -uniform float uDepthScale; -uniform float uDepthBias; - -varying vec2 vUv; - -void main() { - vUv = uv; - - float depth = - texture2D(uDepthMap, uv).r; - - depth = - (depth - uDepthBias) - * uDepthScale; - - vec3 displacedPosition = - position; - - displacedPosition.z += depth; - - gl_Position = - projectionMatrix - * modelViewMatrix - * vec4(displacedPosition, 1.0); -} - - -주의: - -Depth Map에 따라 -흰색이 가까운지, -검정이 가까운지는 -DepthProvider 쪽에서 통일할 것. - -내부 규칙: - -0.0 = 뒤 -1.0 = 앞 - -으로 통일 권장. - - -======================================== -7. Depth Scale -======================================== - -UI에 Depth Strength 또는 Depth Scale 추가. - -예: - -Depth -[----------] - -기본값: -0.15 ~ 0.3 정도 - -목표는 -실제 3D 모델처럼 과도하게 튀어나오게 만드는 것이 아니라 -카메라 좌우 이동 시 -코/눈/얼굴 간 parallax가 눈에 보이는 수준. - -Depth Scale이 너무 크면 -사진이 고무판처럼 찌그러져 보이므로 -최대값 제한. - - -======================================== -8. Camera 이동 방식 수정 -======================================== - -기존에는 Pointer 값을 -Shader의 uViewOffset에 직접 사용하는 비중이 컸다. - -이제는 실제 Camera 이동을 우선한다. - -예: - -targetCameraX = - normalizedPointerX * maxCameraOffset; - -targetCameraY = - normalizedPointerY * maxCameraOffsetY; - -camera.position.x = lerp(...) -camera.position.y = lerp(...) - -camera.lookAt(targetLookAt) - -시점 변화의 핵심은 -실제 PerspectiveCamera 위치 변화로 발생해야 한다. - - -======================================== -9. Shader uViewOffset 역할 변경 -======================================== - -기존 uViewOffset은 완전히 제거하지 않는다. - -다만 역할을 변경. - -기존: -uViewOffset이 시점 변화를 거의 전부 흉내냄 - -수정: -실제 Camera 이동이 기본 시점 변화를 담당 - -uViewOffset: -유리 표면 자체의 굴절 변화 보조용 - -즉, - -Camera movement -= -피사체의 parallax - -Glass uViewOffset -= -유리 렌즈를 비스듬히 보는 효과 - -이 두 가지를 분리. - - -======================================== -10. Mosaic Shader 수정 방향 -======================================== - -현재 Mosaic Shader가 -단순하게 texture UV를 grid 단위로 왜곡한다면 -구조를 수정. - -중요: - -이제 Glass Shader가 직접 원본 petTexture만 sampling하는 구조는 -가능하면 줄인다. - -최종 목표는: - -PetDepthMesh가 먼저 -카메라 기준으로 렌더링되고, - -Glass 효과는 -그 렌더 결과를 굴절시키는 구조. - -즉: - -PetDepth Scene -↓ -Render Target -↓ -Glass Shader -↓ -Screen - - -======================================== -11. RenderTarget 기반 구조 -======================================== - -가능하면 이번 수정에서 -WebGLRenderTarget 기반 2-pass rendering을 도입. - -권장 파이프라인: - -Pass 1: -PetDepthMesh + Background 렌더링 -→ RenderTarget - -Pass 2: -GlassPlane 또는 Fullscreen Quad -→ RenderTarget texture를 입력받아 -굴절 처리 -→ Screen - - -구조: - -Scene A -- PetDepthMesh -- Background - -↓ render - -THREE.WebGLRenderTarget - -↓ texture - -Scene B -- Glass surface / fullscreen plane - -↓ render - -Screen - - -이 방식이 중요한 이유: - -Glass Shader가 -"원본 사진 Texture"를 직접 왜곡하는 것이 아니라 - -현재 카메라 시점에서 이미 -Depth / parallax가 반영된 장면을 -굴절시키게 됨. - - -======================================== -12. SceneManager 수정 -======================================== - -SceneManager를 필요하면 아래와 같이 분리. - -- contentScene -- glassScene - -또는 - -- contentScene -- postProcessScene - -예: - -private contentScene: THREE.Scene; -private glassScene: THREE.Scene; -private renderTarget: THREE.WebGLRenderTarget; - -render loop: - -renderer.setRenderTarget(renderTarget); -renderer.render(contentScene, camera); - -renderer.setRenderTarget(null); -glassMaterial.uniforms.uSceneTexture.value = - renderTarget.texture; - -renderer.render(glassScene, postCamera); - - -======================================== -13. Glass Shader 입력 변경 -======================================== - -기존: - -uTexture = Pet Texture - -수정 권장: - -uSceneTexture = RenderTarget Texture - -예: - -uniform sampler2D uSceneTexture; - -vec4 color = - texture2D( - uSceneTexture, - refractedUv - ); - - -이렇게 해야 -Depth 기반 시점변화가 적용된 결과 전체가 -유리를 통해 보임. - - -======================================== -14. Mosaic Lens 모델 -======================================== - -Mosaic 셀마다 -작은 독립 lens처럼 동작시키는 방향은 유지. - -다만 기존처럼 - -"cell마다 petTexture UV 이동" - -이 아니라 - -"현재 camera view가 반영된 scene texture를 -cell마다 다른 refracted UV로 sample" - -하도록 변경. - -핵심: - -vec2 gridUv = vUv * uGridSize; -vec2 cell = floor(gridUv); -vec2 local = fract(gridUv); - -vec2 centered = - local - 0.5; - -lens distortion 계산 - -+ -view-dependent refraction - -↓ - -sample uSceneTexture - - -======================================== -15. 실제 시점 변화 확인 기준 -======================================== - -아래 현상이 실제로 보여야 한다. - -예: - -강아지 얼굴에서 - -코: -depth 값 큼 - -눈: -중간 - -귀: -조금 뒤 - -몸: -더 뒤 - - -사용자가 카메라를 왼쪽으로 이동하면 - -코가 가장 크게 이동 - -눈이 그보다 작게 이동 - -귀/몸이 더 작게 이동 - -그 결과 -모자이크 셀 안에서 -눈과 코가 서로 다른 위치에 나타남. - - -이 현상이 나오지 않으면 -이번 수정 목적을 달성한 것이 아님. - - -======================================== -16. Depth Debug Mode 추가 -======================================== - -개발 편의를 위해 -Debug UI 추가. - -옵션: - -View Mode: - -- Final -- RGB -- Depth -- No Glass -- Glass Only - -특히 Depth Map을 -화면에 직접 확인할 수 있어야 함. - -또한: - -- depthScale -- gridSize -- glassStrength -- cameraOffset - -값을 실시간 조절 가능하게 한다. - - -======================================== -17. Background 처리 -======================================== - -1차 구현에서는 -사진 전체를 하나의 Depth Mesh로 사용해도 됨. - -다만 구조적으로 향후: - -Background -+ -Pet Foreground - -분리가 가능하도록 작성. - -향후 개선: - -Pet segmentation mask -↓ -Pet Depth Mesh - -Background -↓ -Separate plane - - -지금은 필수 구현 아님. - - -======================================== -18. Depth Map 생성 방식 -======================================== - -이번 수정 범위에서는 -DepthProvider 인터페이스만 정의. - -예: - -interface DepthProvider { - getDepthMap( - image: HTMLImageElement - ): Promise; -} - - -구현체: - -StaticDepthProvider -- 현재는 사용자가 제공한 depth 이미지 -- 또는 test asset 사용 - - -향후: - -AiDepthProvider -- Depth Anything -- MiDaS -- DPT -- ONNX Runtime Web -- Transformers.js - -등으로 교체할 수 있도록 구조화. - - -======================================== -19. AI Depth Estimation은 후순위 -======================================== - -이번 작업에서 -AI 모델 integration 때문에 -렌더링 구조 완성이 늦어지지 않도록 한다. - -우선순위: - -1. -RGB + Depth Texture 입력 - -2. -PetDepthMesh 생성 - -3. -Camera parallax 확인 - -4. -RenderTarget 생성 - -5. -Glass shader 적용 - -6. -실제 Mosaic 시점 변화 확인 - -7. -그 후 AI Depth Provider 검토 - - -======================================== -20. Video 처리 -======================================== - -동영상은 이번 수정에서 -기존 VideoTexture 기능을 유지. - -단, -동영상에 대해 매 프레임 depth estimation하는 것은 -이번 범위에서 제외. - -Video는 우선: - -- RGB VideoTexture -- Flat depth -또는 -- 사용자가 지정한 static depth map - -으로 처리 가능. - -동영상 depth estimation은 -향후 별도 기능으로 남긴다. - - -======================================== -21. 성능 -======================================== - -Depth Mesh segment는 -모바일 성능을 고려. - -기본: - -128 x 128 - -선택적으로: - -64 x 64 -128 x 128 -256 x 256 - -Quality 설정 가능하게 해도 됨. - -RenderTarget resolution도 -devicePixelRatio 그대로 쓰지 말고 -성능을 고려해 제한. - -예: - -Math.min( - window.devicePixelRatio, - 1.5 -) - - -======================================== -22. 모바일 시점 제한 -======================================== - -사진 기반 2.5D이므로 -과도한 시점 이동 금지. - -카메라 좌우 회전/이동은 -약 ±5° ~ ±15° 범위 느낌으로 제한. - -목표는 - -"옆에서 보는 느낌" - -이지 - -"사진 주변을 3D 모델처럼 회전" - -하는 것이 아님. - - -======================================== -23. 기존 효과 재검증 -======================================== - -Mosaic: -가장 중요 - -Reeded: -RenderTarget texture를 대상으로 -X 방향 굴절 - -Frosted: -RenderTarget texture를 대상으로 -blur/noise distortion - - -모든 효과는 -원본 Texture가 아니라 -가능하면 Scene RenderTarget을 기준으로 동작하도록 변경. - - -======================================== -24. 완료 기준 -======================================== - -수정 작업 완료 조건: - -1. -기존 프로젝트가 정상 실행됨 - -2. -RGB Texture 로딩 가능 - -3. -Depth Texture 로딩 가능 - -4. -PetDepthMesh 생성됨 - -5. -Depth Map에 따라 Z displacement가 실제 적용됨 - -6. -Glass OFF 상태에서 -카메라 좌우 이동 시 -피사체 내부에 parallax가 보임 - -7. -코/눈/몸처럼 서로 다른 depth 영역이 -다르게 이동함 - -8. -RenderTarget 기반 2-pass 구조 적용 - -9. -Mosaic Glass가 -RenderTarget texture를 굴절시킴 - -10. -카메라 이동 시 -Mosaic 셀 내부에 보이는 피사체가 동적으로 변경됨 - -11. -기존 단순 UV translate보다 -확실한 깊이감 차이가 보임 - -12. -Depth Scale UI 동작 - -13. -Debug Depth View 제공 - -14. -기존 사진 업로드 기능 유지 - -15. -기존 동영상 기능이 깨지지 않음 - -16. -TypeScript 오류 없음 - -17. -콘솔 반복 오류 없음 - - -======================================== -25. 이번 수정에서 하지 않을 것 -======================================== - -이번 작업에서는 아래는 후순위로 둔다. - -- 완전한 3D pet reconstruction -- NeRF -- Gaussian Splatting -- multi-view reconstruction -- 실시간 video depth estimation -- 서버 AI 구축 -- 복잡한 segmentation -- 물리적으로 완벽한 ray tracing - -목표는 -Monocular Depth 기반 2.5D로 -실제 사진에서 느껴지는 -"눈/코/얼굴의 서로 다른 깊이에 따른 -시점별 유리 굴절 변화" -를 재현하는 것. - - -======================================== -26. 가장 중요한 검증 포인트 -======================================== - -이번 수정의 핵심은 아래다. - -기존: - -사진 전체가 평면이므로 -카메라를 움직여도 -눈/코/얼굴이 사실상 같은 깊이로 움직임. - -수정 후: - -Depth Map으로 -코/눈/얼굴/몸의 Z 위치가 달라지고, - -카메라 이동 시 -각 영역에 서로 다른 parallax가 발생하며, - -그 결과를 -Mosaic Glass가 다시 굴절시킨다. - - -즉, - -Depth -+ -Perspective -+ -Glass Refraction - -세 요소가 실제로 연결되어야 한다. - - -======================================== -27. 작업 완료 후 보고 -======================================== - -작업 완료 후 아래를 정리해서 보고한다. - -- 수정한 파일 목록 -- 신규 파일 목록 -- 기존 구조에서 변경된 부분 -- PetDepthMesh 구현 방식 -- RenderTarget 구성 방식 -- Camera 이동 방식 -- Mosaic Shader 변경점 -- Depth Map 규칙 -- 현재 한계 -- AI Depth Estimation을 붙일 위치 -- 다음 작업 추천 \ No newline at end of file diff --git a/docs/depth-validation.md b/docs/depth-validation.md deleted file mode 100644 index f51b934..0000000 --- a/docs/depth-validation.md +++ /dev/null @@ -1,43 +0,0 @@ -# Depth 수정 검증 기록 - -## Stage 1 — Glass OFF 선행 검증 - -사용자가 제공한 `public/assets/sample-pet.png`와 동일 크기의 수작업 `sample-pet-depth.png`를 사용했다. 테스트 depth는 AI 추정이나 실측 데이터가 아니다. - -브라우저 No Glass에서 Depth Scale 0.3, 실제 camera x=-0.6/+0.6, z=3, canvas 폭 985 CSS px 조건으로 확인했다. 같은 카메라 조건에서 scale=0 대조군도 확인했다. 사진의 코/얼굴/몸이 서로 다르게 움직이는 것을 좌우 화면에서 관찰했고, Depth 보기의 코와 눈 영역이 사진 방향과 일치하는 것을 확인했다. - -| 지점 | depth .3 왼쪽 NDC x | depth .3 오른쪽 NDC x | depth 0 왼쪽 NDC x | depth 0 오른쪽 NDC x | -|---|---:|---:|---:|---:| -| 코 | .116 | .004 | .054 | .055 | -| 눈 사이 중앙부 | .069 | -.004 | .031 | .031 | -| 몸 | -.125 | -.154 | -.137 | -.134 | - -깊이로 추가된 좌우 이동은 `(오른쪽-왼쪽 at .3) - (오른쪽-왼쪽 at 0)`으로 계산한다. NDC에 canvas 폭/2를 곱하면 CSS px이다. 코와 몸의 추가 상대 이동 차이는 약 39.9 CSS px이다. 화면 수치는 NDC 소수 3자리 반올림이므로 근삿값이다. - -초기 진단의 'eyes'는 실제 양쪽 눈 대신 눈 사이 중앙부였으므로, 이를 실제 눈의 측정 결과로 보고하지 않는다. 최종 진단에서는 양쪽 눈 좌표를 따로 사용해야 한다. - -Astra는 위 실제 화면 관찰과 flat 대조 결과를 근거로 Stage 2 착수를 승인했다. 이 검증 후에만 RenderTarget/Glass 연결 작업을 시작했다. - -## 최종 검증 - -Stage 2 후 같은 사진과 실제 양쪽 눈 좌표로 확인한 CSS pixel 진단 결과다. 화면 크기가 달라 앞선 Stage 1과 절대 픽셀 크기는 다르다. - -| 지점 | .3 왼쪽 | .3 오른쪽 | 0 왼쪽 | 0 오른쪽 | -|---|---:|---:|---:|---:| -| 코 | 542.938 | 501.965 | 520.336 | 520.504 | -| 왼쪽 눈 | 506.793 | 479.203 | 493.428 | 493.445 | -| 오른쪽 눈 | 546.265 | 519.088 | 530.441 | 530.820 | -| 몸 | 454.311 | 443.692 | 449.908 | 450.902 | - -Depth로 추가된 좌우 이동은 코 -41.141px, 왼쪽 눈 -27.607px, 오른쪽 눈 -27.556px, 몸 -11.613px다. 코와 양쪽 눈 평균 차이는 약 13.56px, 코와 몸 차이는 약 29.53px다. Depth 데이터/실제 카메라의 투영 진단값이며 GPU 메시 삼각형 보간 및 화면 특징점 추적과는 작은 차이가 있을 수 있다. - -확인한 항목: - -- 사용자 사진이 RenderTarget을 통해 Mosaic/Reeded/Frosted로 렌더됨. -- Mosaic 강도 0 Final과 No Glass의 위치·색상이 육안상 일치. 픽셀 단위 이미지 차이 검사는 수행하지 않음. -- Depth Scale 0/.3, camera offset ±.6, reset, 시점 이동, 효과 전환. -- 별도 RGB와 Depth PNG 업로드 성공. 비율이 다른 Depth 입력은 오류 표시. -- 390×844 모바일 viewport에서 가로 넘침 없음(document width 375, viewport width 390; 세로 스크롤바 포함). 물리적 터치 기기 테스트는 아님. -- 최종 효과 전환 중 브라우저 error 로그 빈 배열 확인. TypeScript와 Vite production build 통과. - -미검증: 실제 영상 재생/loop, 실기기 gyro/권한 UI, 60fps 실측. 영상·자원 수명·요청 경쟁은 코드 검토했으며 모든 경쟁 타이밍을 런타임 테스트했다고 주장하지 않는다. diff --git a/docs/distance-clarity.md b/docs/distance-clarity.md deleted file mode 100644 index 8fc6c7b..0000000 --- a/docs/distance-clarity.md +++ /dev/null @@ -1,23 +0,0 @@ -# 유리와 피사체 간격에 따른 선명도 — 이전 실험 기록 - -> 현재 동작: 사용자의 Ref1 방향 결정에 따라 가까운 표면의 색면 효과를 약화하던 거리 감쇠는 제거됐다. 아래 설계와 브라우저 관찰은 감쇠가 있던 이전 구현의 기록이며, 현재 동작 설명으로 사용하지 않는다. 유효성 검사만 남아 유효한 표면에는 유리 간격과 무관하게 설정된 색면 강도가 적용된다. - -## 목표 - -당시 목표는 표면 간격으로 색면 강도를 달리하는 것이었다. 이 거리 의존성은 제거 결정으로 폐기됐다. - -## 설계 - -이전 구현은 장면 RenderTarget의 깊이를 DepthTexture로 전달하고 최종 굴절 RGB 샘플과 같은 화면 좌표의 깊이를 역투영했다. 복원한 유리-표면 간격에 따라 색면 강도를 정했으나, 현재는 간격에 따른 혼합 강도를 적용하지 않는다. 깊이 텍스처는 범위 밖 UV, 배경, 역투영 실패, 유리 앞 또는 접촉 표면을 걸러내는 데만 사용한다. - -색면 0은 기존 굴절 출력을 유지하고 Distortion 0은 무효과 출력을 유지한다. 배경 깊이는 유효한 피사체로 취급하지 않는다. 카메라 이동 시 현재 렌더링 깊이로 다시 계산한다. - -이는 화면에 보이는 깊이 기반 근사다. 유리 두께의 입출사 양면이나 굴절 광선과 전체 입체 표면의 정확한 교차를 계산하는 광선 추적은 아니다. 한 장의 RGB+상대 depth로 가려진 옆면을 새로 생성하지 않는다. 거리 단위는 장면 내부 값이며 실제 센티미터가 아니다. - -## 브라우저 확인 - -2026-09-14, 5173의 멍멍이3/자동 AI depth/Grid10/Distortion0.9/색면1/광택0.3/사진확대1/팬0으로 확인했다. 변경 전에는 두 얼굴 모두 강하게 양자화됐다. 변경 후 앞쪽 왼쪽 강아지의 눈·코 명암은 유지되고 뒤쪽 강아지와 배경은 강하게 단순화된다. - -Depth Scale을 0으로 바꾸어 전체 사진을 최소 간격에 놓으면 색면1에서도 사진 전반의 세부가 복원된다. 0.25로 복원하면 깊이에 따른 대비가 다시 나타난다. 수평 드래그 후에도 깊이에 맞는 처리와 렌더링이 유지됐으며 오류 로그는 비어 있었다. 시점 변화가 항상 큰 흐림 변화를 일으키는 것은 아니다. 정량적인 동영상 안정성이나 실제 모바일 성능은 이번 검증에 포함하지 않았다. - -위 관찰은 거리 감쇠가 활성화돼 있던 이전 버전의 결과다. 현재 구현에서는 이 곡선과 거리 기반 선명도 설명이 더는 적용되지 않는다. diff --git a/docs/fixed-frame-validation.md b/docs/fixed-frame-validation.md deleted file mode 100644 index c577cfd..0000000 --- a/docs/fixed-frame-validation.md +++ /dev/null @@ -1,10 +0,0 @@ -# 고정 창틀 검증 - -2026-09-11. Astra 설계, GPT-5.6 Luna 구현. - -- `src/main.ts`: 유리판의 `uPaneSize`와 같은 월드 좌표에 두께가 있는 갈색 창틀 4개를 배치했다. 사진 zoom/pan과 독립적이다. -- Glass 합성 후 같은 원근 카메라로 별도 frameScene을 렌더링한다. 창틀이 굴절 입력에 포함되지 않는다. 공유 geometry/material은 teardown에서 dispose한다. -- Final/Glass Only에서 표시하며 No Glass/RGB/Depth 진단 모드에는 표시하지 않는다. -- Luna의 `npm.cmd run build` 통과. -- 실제 브라우저: 샘플 사진 기본 화면, 우측 드래그, 사진 확대 1.8 및 가로 위치 0.5 변경에서 창틀과 Mosaic 경계 결합 확인. No Glass에서 창틀 제거 확인. 390×844 모바일 표시 확인. -- 카메라 제어 및 기존 셰이더는 변경하지 않았다. Reeded/Frosted의 기존 fullscreen 출력은 창틀 외부까지 이어질 수 있다. 목재 텍스처나 그림자는 구현하지 않고 면별 갈색 명암으로 깊이를 표현한다. diff --git a/docs/glass-contact.md b/docs/glass-contact.md deleted file mode 100644 index 26e2101..0000000 --- a/docs/glass-contact.md +++ /dev/null @@ -1,42 +0,0 @@ -# 유리 바로 뒤의 피사체 배치 - -2026-10-06: 고정 간격 0.04를 기본으로 보존하면서 사진–유리 거리 슬라이더(0–100%, 장면 간격 0.04–0.60)를 추가했다. RGB/Depth 공통 배치와 자동 구도 금지를 유지한다. 최신 구현과 검증은 [거리 조절 기록](qa-photo-glass-distance-2026-10-06/report.md)을 따른다. 아래 고정 근접 배치와 자동 구도 실험은 과거 기록이다. - -최신 변경: 사용자가 자동 구도 조정을 제외하도록 요청했다. 아래 자동 구도 보완·검증은 과거 실험 기록이다. 현재 동작에서는 사진별 확대 프리셋과 AI 앞쪽 영역 자동 확대/팬을 제거하고, 입력 사진 구도와 실제 유리 근접 배치만 유지한다. 수동 구도 조절은 가능하다. - -제거 검증: `src/main.ts`와 `src/depth/DepthProcessor.ts`의 자동 구도 경로·미사용 분석 도우미를 제거했다. 기존 수작업 샘플도 확대1/팬0으로 입력된다. 실제5173에서 sample의 간격0.040 유지, dog3 자동 AI 완료 후에도 확대1/가로0/세로0 및 Final 유지, 오류 로그없음을 확인했다. 빌드·타입 검사 통과. - -사용자 정정: 얼굴 확대 프리셋이 목적이 아니다. 사진을 넣었을 때 강아지 얼굴이 유리 바로 뒤에 가까이 있는 공간감을 원한다. 이전 구도 확대만의 처리를 충분한 해결로 보지 않는다. - -이번 구현 기준: -- 유리 z=0.6은 유지하고 추정 깊이의 가장 앞 표면을 z=0.56에 배치한다. baseZ=0.56-(maxDepth-depthBias)*depthScale. -- RGB/depth는 같은 변환을 적용한다. 평면 사진의 정면 크기는 거리 보정으로 유지하여 단순 확대와 구분한다. -- 세 유리 효과의 굴절 교차 기준도 실제 배치한 기준 평면으로 옮긴다. 색면 처리와 곡면 법선은 유지한다. -- 새 정지 사진에 기존 브라우저 로컬 AI depth를 자동 적용한다. 수작업 depth가 있는 샘플과 영상은 제외한다. 자동 완료는 사용자가 선택한 보기 모드를 바꾸지 않는다. -- dog1만의 고정 확대 프리셋은 제거한다. 기존 일반 구도 조절과 수작업 샘플 프리셋은 유지한다. - -검증 기준: No Glass에서 앞 표면 위치와 눈·코 시차를 먼저 확인, depth강도0/0.25/0.4에서 유리 관통 없음, 이후 Final/다른 유리 효과 확인, 사진 교체 시 오래된 AI 결과 배제, 오류 시 평면 배치와 상태 안내. - -모델은 상대 깊이를 추정하며 얼굴 검출기는 아니다. 가장 가까운 부분이 앞발이나 다른 물체라면 얼굴만을 선택해 붙이는 것을 보장하지 않는다. 실제 굴절은 여전히 깊이 표면의 정밀 광선 교차가 아니라 기준 평면을 이용한 근사다. 이 두 한계를 숨기지 않는다. - -## 실제 배치 검증 - -- No Glass 수작업 샘플: depth0.25에서 baseZ0.315, 코0.560, 눈0.485, 몸0.389. 유리와 가장 앞 표면 간격0.040. -- depth0에서는 모든 표면0.560, depth0.4에서는 baseZ0.168/앞표면0.560. 관통 없음. -- 카메라X0→0.051에서 코 투영X329.980→326.555, 왼눈264.823→261.986, 몸167.359→165.523. 같은 평행 이동이 아닌 깊이별 시차를 확인했다. -- 이후 Mosaic/Reeded/Frosted의 실제 출력과 오류 로그없음을 확인했다. -- dog1은 버튼 추가 클릭 없이 자동 AI 추정 완료 후 Final 유지. 추정 중 dog2→수작업 sample 교체 시 sample 상태가 유지되어 오래된 결과가 덮어쓰지 않았다. - -## 자동 구도 보완 - -거리 배치만 바꾸고 원래 전신 구도를 유지한 첫 결과는 여전히 얼굴이 작아 시각적 목표가 부족했다. 따라서 고정 dog1 프리셋 대신 자동 AI 깊이의 앞쪽 연결 영역을 찾아, 그 영역 중심으로 구도를 맞추는 보완을 한다. 실제 유리 근접 배치와 자동 구도를 함께 적용한다. 앞쪽의 작은 코만 잘리는 것을 피하려고 여유를 두고 최대 확대를 제한한다. 사용자가 추정 대기 중 구도를 직접 바꾸면 자동 구도는 적용하지 않는다. - -## 최종 구현과 검증 - -- 변경: `src/main.ts`, `src/depth/DepthProcessor.ts`, `src/depth/DepthDebug.ts`, 세 유리 fragment shader. 원본 사진은 변경하지 않았다. -- 자동 구도: 깊이 최대값에서 전체 범위의12% 이내인 표본을 사용한다. 최대변128의 분석 격자에서 가장 큰8연결영역을 선택한다. 깊이범위0.1 미만 또는 면적0.5% 미만이면 자동 구도를 건너뛴다. 경계에1.25배 여유, 깊이 원근 보정, 최대3배 확대를 적용한다. -- 실제 5173에서 dog1을 다시 불러오는 것만으로 로컬 AI 처리와 Final 유지를 확인했다. 수동 확대 없이 약2.05배/가로-0.21/세로-0.31이 계산되었고 얼굴이 유리 대부분을 채웠다. 색면1/Grid14에서 정면·드래그·복귀 화면을 확인했다. -- 별도 탭에서 dog2 추정 대기 중 확대1.5/세로0.17 및 No Glass를 선택했다. AI 완료 후에도 세 설정이 유지됐다. 오류 로그없음. -- 구현 에이전트의 실제 DepthProcessor 임시 실행 검증: 평면→null, 위쪽 연결영역의 좌표/범위 정확성, 작은 이상치가 있는 경우, 분리된 여러 영역 중 큰 영역 선택을 확인했다. 별도 테스트 프레임워크는 추가하지 않았다. -- 최종 빌드·타입 검사 통과. 기존 큰 번들 안내는 남는다. AI 실패의 안내/폴백은 소스 검토했고 네트워크 장애를 강제로 만들어 재현하지 않았다. 실기기 모바일과 영상 성능은 이번 턴에서 다시 측정하지 않았다. -- 현재 사용자 화면은 자동 AI·자동 구도가 적용된 dog1 Final이다. 이 결과는 단순 확대 프리셋이 아니라 실제 깊이 근접 배치와 깊이에 따른 자동 구도의 조합이다. 얼굴 인식을 보장하는 모델로 소개하지 않는다. diff --git a/docs/glass-qa-round2/after-close.png b/docs/glass-qa-round2/after-close.png deleted file mode 100644 index eb403f6..0000000 Binary files a/docs/glass-qa-round2/after-close.png and /dev/null differ diff --git a/docs/glass-qa-round2/after-default.png b/docs/glass-qa-round2/after-default.png deleted file mode 100644 index 3258a72..0000000 Binary files a/docs/glass-qa-round2/after-default.png and /dev/null differ diff --git a/docs/glass-qa-round2/after-mobile.png b/docs/glass-qa-round2/after-mobile.png deleted file mode 100644 index 634cec8..0000000 Binary files a/docs/glass-qa-round2/after-mobile.png and /dev/null differ diff --git a/docs/glass-qa-round2/before-close.png b/docs/glass-qa-round2/before-close.png deleted file mode 100644 index f188830..0000000 Binary files a/docs/glass-qa-round2/before-close.png and /dev/null differ diff --git a/docs/glass-qa-round2/before-main.ts b/docs/glass-qa-round2/before-main.ts deleted file mode 100644 index a849049..0000000 --- a/docs/glass-qa-round2/before-main.ts +++ /dev/null @@ -1,240 +0,0 @@ -import * as THREE from 'three'; -import './style.css'; -import vertexShader from './shaders/common.vert?raw'; -import mosaicShader from './shaders/mosaic.frag?raw'; -import reededShader from './shaders/reeded.frag?raw'; -import frostedShader from './shaders/frosted.frag?raw'; -import { MediaLoader } from './input/MediaLoader'; -import { PointerController } from './input/PointerController'; -import { CameraController } from './input/CameraController'; -import { GyroController } from './input/GyroController'; -import { StaticDepthProvider } from './depth/StaticDepthProvider'; -import { DepthProcessor } from './depth/DepthProcessor'; -import { PetDepthMesh } from './objects/PetDepthMesh'; -import { DepthDebug } from './depth/DepthDebug'; -import glassScreenVertex from './shaders/glassScreen.vert?raw'; - -const wrap = document.querySelector('#canvas-wrap') as HTMLElement; -const status = document.querySelector('#status') as HTMLElement; -const depthProvenance = document.querySelector('#depth-provenance') as HTMLElement; -const empty = document.querySelector('#empty') as HTMLElement; -const hintElement = document.querySelector('#hint') as HTMLElement; -hintElement.style.opacity = '0'; -const renderer = new THREE.WebGLRenderer({ antialias: true }); -renderer.setPixelRatio(Math.min(devicePixelRatio, 1.5)); -wrap.append(renderer.domElement); -const scene = new THREE.Scene(); -const glassScene = new THREE.Scene(); -const frameScene = new THREE.Scene(); -scene.background = new THREE.Color(0x111923); -const camera = new THREE.PerspectiveCamera(40, 1, 0.1, 100); -camera.position.z = 3; -const geometry = new THREE.PlaneGeometry(1, 1); -const emptyTex = new THREE.DataTexture(new Uint8Array([38, 48, 62, 255]), 1, 1); -emptyTex.needsUpdate = true; -const petMat = new THREE.MeshBasicMaterial({ map: emptyTex }); -const pet = new THREE.Mesh(geometry, petMat); -scene.add(pet); -const depthMap: THREE.Texture = DepthProcessor.flatTexture(); -const petDepth = new PetDepthMesh(emptyTex, depthMap, 0.25, 0); -const petDepthMaterial = petDepth.material; -const depthUniforms = petDepthMaterial.uniforms; -scene.add(petDepth); -const uniforms = { uSceneTexture: { value: emptyTex as THREE.Texture }, uContentViewProjection: { value: new THREE.Matrix4() }, uContentInverseViewProjection: { value: new THREE.Matrix4() }, uContentCameraPosition: { value: new THREE.Vector3() }, uLightPosition: { value: new THREE.Vector3(0.6, 0.8, 2.6) }, uBackgroundColor: { value: scene.background.clone() }, uGlassZ: { value: 0.6 }, uGridSize: { value: 10 }, uMosaicStyle: { value: 0 }, uStrength: { value: 0.9 }, uGlossStrength: { value: 0.3 }, uCurvature: { value: 0.65 }, uViewOffset: { value: new THREE.Vector2() }, uPaneRect: { value: new THREE.Vector4(0, 0, 1, 1) }, uResolution: { value: new THREE.Vector2() }, uTime: { value: 0 }, uPetSize: { value: new THREE.Vector2(1, 1) }, uPaneSize: { value: new THREE.Vector2(1, 1) } }; -const glassMat = new THREE.ShaderMaterial({ uniforms, vertexShader: glassScreenVertex, fragmentShader: mosaicShader }); -const glass = new THREE.Mesh(new THREE.PlaneGeometry(2, 2), glassMat); -glassScene.add(glass); -const frameGeometry = new THREE.BoxGeometry(1, 1, 1); -const frameMaterials = [ - new THREE.MeshBasicMaterial({ color: 0x3a2419 }), - new THREE.MeshBasicMaterial({ color: 0x4a2e20 }), - new THREE.MeshBasicMaterial({ color: 0x2b1a13 }), - new THREE.MeshBasicMaterial({ color: 0x513326 }), - new THREE.MeshBasicMaterial({ color: 0x321f17 }), - new THREE.MeshBasicMaterial({ color: 0x43291d }) -]; -const frameLeft = new THREE.Mesh(frameGeometry, frameMaterials); -const frameRight = new THREE.Mesh(frameGeometry, frameMaterials); -const frameTop = new THREE.Mesh(frameGeometry, frameMaterials); -const frameBottom = new THREE.Mesh(frameGeometry, frameMaterials); -frameScene.add(frameLeft, frameRight, frameTop, frameBottom); -const postCamera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1); -const renderTarget = new THREE.WebGLRenderTarget(1, 1, { colorSpace: THREE.NoColorSpace, type: THREE.HalfFloatType, depthBuffer: true }); -let active: THREE.Texture = emptyTex; -let aspect = 1; -let baseW = 1; -let baseH = 1; -let photoZoom = 1; -let photoPanX = 0; -let photoPanY = 0; -let pendingSampleFraming = false; -let mode = 'noglass'; -let hintTimeout = 0; -let pendingPairDepth: THREE.Texture | null = null; -let mediaRequest = 0; -let depthRequest = 0; -let disposed = false; -const listenerAbort = new AbortController(); -function clearPendingPair(): void { if (pendingPairDepth) pendingPairDepth.dispose(); pendingPairDepth = null; } -function applyFraming(): void { - const x = baseW * (photoZoom - 1) * 0.5 * photoPanX; - const y = baseH * (photoZoom - 1) * 0.5 * photoPanY; - pet.scale.set(baseW * photoZoom, baseH * photoZoom, 1); - pet.position.set(x, y, 0); - petDepth.scale.copy(pet.scale); - petDepth.position.copy(pet.position); -} -function resize(): void { - const bounds = wrap.getBoundingClientRect(); - renderer.setSize(bounds.width, bounds.height, false); - camera.aspect = bounds.width / bounds.height; - camera.updateProjectionMatrix(); - const height = 1.7; - const scale = Math.min(height * bounds.width / bounds.height / aspect, height); - baseW = scale * aspect; - baseH = scale; - applyFraming(); - uniforms.uPetSize.value.set(baseW, baseH); - uniforms.uResolution.value.set(bounds.width, bounds.height); - const glassHeight = 2 * (camera.position.z - 0.6) * Math.tan(THREE.MathUtils.degToRad(camera.fov / 2)); - uniforms.uPetSize.value.set(glassHeight * camera.aspect, glassHeight); - uniforms.uPaneSize.value.set(baseW * (3 - uniforms.uGlassZ.value) / 3, baseH * (3 - uniforms.uGlassZ.value) / 3); - const frameW = uniforms.uPaneSize.value.x; - const frameH = uniforms.uPaneSize.value.y; - const frameThickness = Math.min(frameW, frameH) * 0.035; - const frameDepth = frameThickness * 1.5; - const frameZ = uniforms.uGlassZ.value + frameDepth * 0.25; - frameLeft.position.set(-(frameW + frameThickness) * 0.5, 0, frameZ); - frameRight.position.set((frameW + frameThickness) * 0.5, 0, frameZ); - frameTop.position.set(0, (frameH + frameThickness) * 0.5, frameZ); - frameBottom.position.set(0, -(frameH + frameThickness) * 0.5, frameZ); - frameLeft.scale.set(frameThickness, frameH, frameDepth); - frameRight.scale.set(frameThickness, frameH, frameDepth); - frameTop.scale.set(frameW + frameThickness * 2, frameThickness, frameDepth); - frameBottom.scale.set(frameW + frameThickness * 2, frameThickness, frameDepth); - const neutralGlassHeight = 2 * 3 * Math.tan(THREE.MathUtils.degToRad(40 / 2)); - const neutralGlassWidth = neutralGlassHeight * camera.aspect; - uniforms.uPaneRect.value.set(Math.max(0, 0.5 - baseW / (2 * neutralGlassWidth)), Math.max(0, 0.5 - baseH / (2 * neutralGlassHeight)), Math.min(1, 0.5 + baseW / (2 * neutralGlassWidth)), Math.min(1, 0.5 + baseH / (2 * neutralGlassHeight))); - renderTarget.setSize(Math.max(1, Math.floor(bounds.width * Math.min(devicePixelRatio, 1.5))), Math.max(1, Math.floor(bounds.height * Math.min(devicePixelRatio, 1.5)))); -} -function hint(): void { - window.clearTimeout(hintTimeout); - hintElement.style.opacity = '1'; - hintTimeout = window.setTimeout(() => { hintElement.style.opacity = '0'; }, 2000); -} -function applyMedia(texture: THREE.Texture, mediaAspect: number, video: HTMLVideoElement | null): void { - if (active !== emptyTex) active.dispose(); - active = texture; aspect = mediaAspect; - if (pendingSampleFraming) { photoZoom = 2.4; photoPanX = -0.10; photoPanY = -0.35; pendingSampleFraming = false; } else { photoZoom = 1; photoPanX = 0; photoPanY = 0; } - syncPhotoControls(); - texture.colorSpace = THREE.SRGBColorSpace; - depthUniforms.uTexture.value = texture; - petMat.map = texture; petMat.needsUpdate = true; - empty.style.display = 'none'; resize(); -} -function setDepth(texture: THREE.Texture): void { - if (depthUniforms.uDepthMap.value !== depthMap) depthUniforms.uDepthMap.value.dispose(); - depthUniforms.uDepthMap.value = texture; texture.colorSpace = THREE.NoColorSpace; - if (mode === 'depth') { petMat.map = texture; petMat.needsUpdate = true; } -} -function setMode(next: string): void { - mode = next; - if (modeInput) modeInput.value = next; - pet.visible = next === 'rgb' || next === 'depth'; - petDepth.visible = next === 'noglass' || next === 'final'; - glass.visible = next === 'final' || next === 'glass'; - petMat.map = next === 'depth' ? depthUniforms.uDepthMap.value : active; - petMat.needsUpdate = true; - petDepthMaterial.uniforms.uTexture.value = active; -} -const retry = document.createElement('button'); -retry.textContent = '재생'; retry.hidden = true; -(document.querySelector('aside') as HTMLElement).append(retry); -const debugOutput = document.createElement('pre'); -debugOutput.id = 'depth-debug'; -debugOutput.hidden = true; -(document.querySelector('aside') as HTMLElement).append(debugOutput); -const depthDebug = new DepthDebug(); -const loader = new MediaLoader((texture, mediaAspect, video) => { const hasSampleDepth = pendingSampleFraming && pendingPairDepth !== null; applyMedia(texture, mediaAspect, video); petDepth.setVideo(Boolean(video)); setDepth(pendingPairDepth ?? DepthProcessor.flatTexture()); pendingPairDepth = null; depthProvenance.hidden = !hasSampleDepth; if (hasSampleDepth) depthProvenance.textContent = '수작업 테스트 Depth · AI 추정 아님'; setMode('final'); hint(); }, (message) => { status.textContent = message; retry.hidden = !message.includes('자동'); }); -retry.onclick = () => loader.retry(); -const sampleDepthProvider = new StaticDepthProvider('/assets/sample-pet-depth.png'); -const cameraController = new CameraController(camera); -const pointer = new PointerController(renderer.domElement, (x, y) => cameraController.add(x, y)); -const gyro = new GyroController((x, y) => cameraController.target.set(THREE.MathUtils.clamp(x, -1, 1), THREE.MathUtils.clamp(y, -1, 1)), (message) => { status.textContent = message; }); -const imageInput = document.querySelector('#image') as HTMLInputElement; -const videoInput = document.querySelector('#video') as HTMLInputElement; -const depthFileInput = document.querySelector('#depth-image') as HTMLInputElement; -const sampleButton = document.querySelector('#sample') as HTMLButtonElement | null; -const effectInput = document.querySelector('#effect') as HTMLSelectElement; -const modeInput = document.querySelector('#view-mode') as HTMLSelectElement | null; -const strengthInput = document.querySelector('#strength') as HTMLInputElement; -const sensitivityInput = document.querySelector('#sensitivity') as HTMLInputElement; -const depthInput = document.querySelector('#depth-scale') as HTMLInputElement | null; -const cameraOffsetInput = document.querySelector('#camera-offset') as HTMLInputElement; -const gridInput = document.querySelector('#grid-size') as HTMLInputElement; -const gridOutput = document.querySelector('#gridOut') as HTMLOutputElement; -const mosaicStyleInput = document.querySelector('#mosaic-style') as HTMLSelectElement; -const glossControls = document.querySelector('#gloss-controls') as HTMLElement | null; -const curvatureInput = document.querySelector('#curvature') as HTMLInputElement | null; -const glossInput = document.querySelector('#gloss-strength') as HTMLInputElement | null; -const lightXInput = document.querySelector('#light-x') as HTMLInputElement | null; -const lightYInput = document.querySelector('#light-y') as HTMLInputElement | null; -const glossOutput = document.querySelector('#glossOut') as HTMLOutputElement | null; -const lightXOutput = document.querySelector('#lightXOut') as HTMLOutputElement | null; -const lightYOutput = document.querySelector('#lightYOut') as HTMLOutputElement | null; -const cameraOutput = document.querySelector('#cameraOut') as HTMLOutputElement; -const strengthOutput = document.querySelector('#strengthOut') as HTMLOutputElement; -const sensitivityOutput = document.querySelector('#sensitivityOut') as HTMLOutputElement; -const depthOutput = document.querySelector('#depthOut') as HTMLOutputElement | null; -const photoZoomInput = document.querySelector('#photo-zoom') as HTMLInputElement | null; -const photoZoomOutput = document.querySelector('#photoZoomOut') as HTMLOutputElement | null; -const photoPanXInput = document.querySelector('#photo-pan-x') as HTMLInputElement | null; -const photoPanXOutput = document.querySelector('#photoPanXOut') as HTMLOutputElement | null; -const photoPanYInput = document.querySelector('#photo-pan-y') as HTMLInputElement | null; -const photoPanYOutput = document.querySelector('#photoPanYOut') as HTMLOutputElement | null; -const photoResetButton = document.querySelector('#photo-reset') as HTMLButtonElement | null; -const resetButton = document.querySelector('#reset') as HTMLButtonElement; -const gyroButton = document.querySelector('#gyro') as HTMLButtonElement; -const effects = [mosaicShader, reededShader, frostedShader]; -let sensitivity = 1; -function setGlossControlsVisibility(): void { - const enabled = effectInput.value === 'mosaic'; - if (glossControls) { glossControls.hidden = !enabled; glossControls.style.display = enabled ? 'grid' : 'none'; } - [glossInput, lightXInput, lightYInput, curvatureInput].forEach((input) => { if (input) input.disabled = !enabled; }); -} -function syncPhotoControls(): void { - if (photoZoomInput) photoZoomInput.value = photoZoom.toFixed(2); - if (photoZoomOutput) photoZoomOutput.value = photoZoom.toFixed(2); - if (photoPanXInput) photoPanXInput.value = photoPanX.toFixed(2); - if (photoPanXOutput) photoPanXOutput.value = photoPanX.toFixed(2); - if (photoPanYInput) photoPanYInput.value = photoPanY.toFixed(2); - if (photoPanYOutput) photoPanYOutput.value = photoPanY.toFixed(2); -} -imageInput.onchange = (event) => { const input = event.target as HTMLInputElement; pendingSampleFraming = false; mediaRequest += 1; depthRequest += 1; clearPendingPair(); depthDebug.clear(); if (input.files?.[0]) loader.load(input.files[0]); input.value = ''; }; -videoInput.onchange = (event) => { const input = event.target as HTMLInputElement; pendingSampleFraming = false; mediaRequest += 1; depthRequest += 1; clearPendingPair(); depthDebug.clear(); if (input.files?.[0]) loader.load(input.files[0]); input.value = ''; }; -photoZoomInput?.addEventListener('input', (event) => { photoZoom = Number((event.target as HTMLInputElement).value); applyFraming(); syncPhotoControls(); }, { signal: listenerAbort.signal }); -photoPanXInput?.addEventListener('input', (event) => { photoPanX = Number((event.target as HTMLInputElement).value); applyFraming(); syncPhotoControls(); }, { signal: listenerAbort.signal }); -photoPanYInput?.addEventListener('input', (event) => { photoPanY = Number((event.target as HTMLInputElement).value); applyFraming(); syncPhotoControls(); }, { signal: listenerAbort.signal }); -photoResetButton?.addEventListener('click', () => { photoZoom = 1; photoPanX = 0; photoPanY = 0; applyFraming(); syncPhotoControls(); }, { signal: listenerAbort.signal }); -sampleButton?.addEventListener('click', async () => { const request = ++mediaRequest; depthRequest += 1; clearPendingPair(); depthDebug.clear(); let url = ''; try { const [rgb, depth] = await Promise.all([fetch('/assets/sample-pet.png').then((r) => r.blob()), fetch('/assets/sample-pet-depth.png').then((r) => r.blob())]); if (disposed || request !== mediaRequest) return; url = URL.createObjectURL(depth); const image = new Image(); image.src = url; await image.decode(); if (disposed || request !== mediaRequest) return; const loadedDepth = await sampleDepthProvider.getDepthMap(image); if (disposed || request !== mediaRequest) { loadedDepth.dispose(); return; } clearPendingPair(); pendingPairDepth = loadedDepth; depthDebug.setSample(image); pendingSampleFraming = true; loader.load(new File([rgb], 'sample-pet.png', { type: 'image/png' })); status.textContent = '수작업 테스트 Depth · AI추정 아님'; } catch { if (!disposed && request === mediaRequest) status.textContent = '샘플 depth map을 읽지 못했습니다.'; } finally { if (url) URL.revokeObjectURL(url); } }, { signal: listenerAbort.signal }); -effectInput.addEventListener('change', (event) => { const index = ['mosaic', 'reeded', 'frosted'].indexOf((event.target as HTMLSelectElement).value); glassMat.fragmentShader = effects[index]; glassMat.needsUpdate = true; setGlossControlsVisibility(); }, { signal: listenerAbort.signal }); -modeInput?.addEventListener('change', (event) => setMode((event.target as HTMLSelectElement).value), { signal: listenerAbort.signal }); -strengthInput.oninput = (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uStrength.value = value; strengthOutput.value = value.toFixed(2); }; -sensitivityInput.oninput = (event) => { const value = Number((event.target as HTMLInputElement).value); sensitivity = value; sensitivityOutput.value = value.toFixed(2); }; -depthInput?.addEventListener('input', (event) => { const value = Math.min(Number((event.target as HTMLInputElement).value), 0.4); depthUniforms.uDepthScale.value = value; if (depthOutput) depthOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -cameraOffsetInput.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); cameraController.setMaxOffset(value); cameraOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -gridInput.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uGridSize.value = value; gridOutput.value = value.toFixed(0); }, { signal: listenerAbort.signal }); -mosaicStyleInput.addEventListener('change', (event) => { const style = Number((event.target as HTMLSelectElement).value); uniforms.uMosaicStyle.value = style; uniforms.uGridSize.value = style === 0 ? 10 : 28; uniforms.uStrength.value = style === 0 ? 0.9 : 0.85; gridInput.value = String(uniforms.uGridSize.value); gridOutput.value = String(uniforms.uGridSize.value); strengthInput.value = String(uniforms.uStrength.value); strengthOutput.value = uniforms.uStrength.value.toFixed(2); }, { signal: listenerAbort.signal }); -curvatureInput?.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uCurvature.value = value; const output = document.querySelector('#curvatureOut') as HTMLOutputElement | null; if (output) output.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -glossInput?.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uGlossStrength.value = value; if (glossOutput) glossOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -lightXInput?.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uLightPosition.value.x = value; if (lightXOutput) lightXOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -lightYInput?.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uLightPosition.value.y = value; if (lightYOutput) lightYOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -depthFileInput?.addEventListener('change', async () => { const request = ++depthRequest; const file = depthFileInput.files?.[0]; if (!file) return; depthDebug.clear(); const url = URL.createObjectURL(file); let texture: THREE.Texture | null = null; try { const image = new Image(); image.src = url; await image.decode(); if (disposed || request !== depthRequest) return; if (aspect > 0 && Math.abs(image.width / image.height - aspect) > 0.02) throw new Error('aspect'); texture = DepthProcessor.toTexture(image); if (disposed || request !== depthRequest) { texture.dispose(); texture = null; return; } setDepth(texture); texture = null; depthProvenance.hidden = true; status.textContent = '수동 depth map 적용됨 (0=뒤, 1=앞)'; } catch { if (!disposed && request === depthRequest) status.textContent = 'RGB와 종횡비가 다른 depth map입니다.'; } finally { texture?.dispose(); URL.revokeObjectURL(url); depthFileInput.value = ''; } }, { signal: listenerAbort.signal }); -resetButton.onclick = () => { cameraController.reset(); gyro.reset(); }; -gyroButton.onclick = async () => { gyroButton.textContent = `Gyroscope: ${(await gyro.toggle()) ? 'ON' : 'OFF'}`; }; -const observer = new ResizeObserver(resize); observer.observe(wrap); resize(); setMode('final'); setGlossControlsVisibility(); -let last = performance.now(); let raf = 0; -function frame(now: number): void { const dt = Math.min((now - last) / 1000, 0.1); last = now; uniforms.uViewOffset.value.copy(cameraController.update(dt, sensitivity)); camera.updateMatrixWorld(true); petDepth.updateMatrixWorld(true); uniforms.uContentViewProjection.value.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse); uniforms.uContentInverseViewProjection.value.copy(uniforms.uContentViewProjection.value).invert(); uniforms.uContentCameraPosition.value.copy(camera.position); uniforms.uTime.value = now / 1000; const diagnostic = depthDebug.update(camera, petDepth, depthUniforms.uDepthScale.value, depthUniforms.uDepthBias.value, wrap.clientWidth); debugOutput.textContent = diagnostic; debugOutput.hidden = !diagnostic; if (mode === 'final' || mode === 'glass') { renderer.setRenderTarget(renderTarget); renderer.render(scene, camera); renderer.setRenderTarget(null); uniforms.uSceneTexture.value = renderTarget.texture; renderer.render(glassScene, postCamera); const previousAutoClear = renderer.autoClear; renderer.autoClear = false; renderer.clearDepth(); renderer.render(frameScene, camera); renderer.autoClear = previousAutoClear; } else { renderer.setRenderTarget(null); renderer.render(scene, camera); } raf = requestAnimationFrame(frame); } -raf = requestAnimationFrame(frame); -function teardown(): void { disposed = true; mediaRequest += 1; depthRequest += 1; clearPendingPair(); listenerAbort.abort(); cancelAnimationFrame(raf); window.clearTimeout(hintTimeout); observer.disconnect(); imageInput.onchange = null; videoInput.onchange = null; effectInput.onchange = null; strengthInput.oninput = null; sensitivityInput.oninput = null; resetButton.onclick = null; gyroButton.onclick = null; retry.onclick = null; pointer.dispose(); gyro.dispose(); loader.dispose(); renderTarget.dispose(); if (active !== emptyTex) active.dispose(); if (depthUniforms.uDepthMap.value !== depthMap) depthUniforms.uDepthMap.value.dispose(); depthMap.dispose(); petDepth.geometry.dispose(); petDepthMaterial.dispose(); geometry.dispose(); petMat.dispose(); glass.geometry.dispose(); glassMat.dispose(); frameGeometry.dispose(); frameMaterials.forEach((material) => material.dispose()); emptyTex.dispose(); renderer.domElement.remove(); renderer.dispose(); hintElement.style.opacity = '0'; retry.remove(); debugOutput.remove(); } -const hot = import.meta as ImportMeta & { hot?: { dispose(fn: () => void): void } }; hot.hot?.dispose(teardown); diff --git a/docs/glass-qa-round2/before.frag b/docs/glass-qa-round2/before.frag deleted file mode 100644 index 0562016..0000000 --- a/docs/glass-qa-round2/before.frag +++ /dev/null @@ -1,48 +0,0 @@ -uniform sampler2D uSceneTexture; -uniform mat4 uContentViewProjection,uContentInverseViewProjection; -uniform vec3 uContentCameraPosition,uLightPosition,uBackgroundColor; -uniform float uGlassZ,uGridSize,uStrength,uMosaicStyle,uCurvature,uGlossStrength; -uniform vec2 uViewOffset,uPetSize,uPaneSize; -uniform vec4 uPaneRect; -varying vec2 vUv; -vec2 projectUv(vec3 p){vec4 c=uContentViewProjection*vec4(p,1.);float w=abs(c.w)<.0001?(c.w<0.?-.0001:.0001):c.w;return c.xy/w*.5+.5;} -vec4 sampleScene(vec2 uv){return texture2D(uSceneTexture,clamp(uv,0.,1.));} -vec4 samplePane(vec2 pane){return sampleScene(projectUv(vec3((pane-.5)*uPaneSize,uGlassZ)));} -float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);} -vec2 hash2(vec2 p){return vec2(hash(p),hash(p+vec2(19.19,73.73)));} -float safeZ(float z){return abs(z)<.0001?(z<0.?-.0001:.0001):z;} -vec3 bend(vec3 i,vec3 n){vec3 r=refract(i,n,.75);return length(r)<.0001?i:r;} -float softLimit(float value,float limit){return value*limit/(limit+abs(value));} -void main(){ - if(uStrength<=.001){gl_FragColor=sampleScene(vUv); - #include - return;} - vec4 f=uContentInverseViewProjection*vec4(vUv*2.-1.,1.,1.);float fw=abs(f.w)<.0001?(f.w<0.?-.0001:.0001):f.w;vec3 farWorld=f.xyz/fw;vec3 i=normalize(farWorld-uContentCameraPosition);float gt=(uGlassZ-uContentCameraPosition.z)/safeZ(i.z);vec3 gh=uContentCameraPosition+i*gt; - vec2 paneUv=gh.xy/uPaneSize+.5;vec2 grid=vec2(uGridSize,max(1.,uGridSize*uPaneSize.y/uPaneSize.x));vec2 gridUv=paneUv*grid,cell=floor(gridUv),local=fract(gridUv)-.5,cellSize=1./grid,random=hash2(cell);float style=clamp(uMosaicStyle,0.,1.),cellWorld=min(uPaneSize.x/grid.x,uPaneSize.y/grid.y); - if(paneUv.x<0.||paneUv.x>1.||paneUv.y<0.||paneUv.y>1.){gl_FragColor=vec4(uBackgroundColor,1.); - #include - return;} - // Positive height bulges toward the observer (+Z); negative height is concave. - float curvature=clamp(uCurvature,-1.,1.),excess=max(curvature-.65,0.),surfaceCurvature=curvature-(.25/.35)*excess*excess; float height=.009*cellWorld*surfaceCurvature*mix(.92,1.08,hash(cell+vec2(41.7,17.3))); vec2 q=2.*local; vec2 q2=q*q,q3=q2*q,b=1.-q2*q2; vec2 skew=(hash2(cell+vec2(23.8,61.2))-.5)*.28; float asym=1.+dot(skew,q); vec2 dhdq=height*vec2(-4.*q3.x*b.y*asym+b.x*b.y*skew.x,-4.*q3.y*b.x*asym+b.x*b.y*skew.y); vec2 cellDimensions=uPaneSize/grid; vec2 grad=-2.*dhdq/cellDimensions; vec3 nCurved=normalize(vec3(grad+(random-.5)*.012,1.)),nFacet=normalize(vec3((random-.5)*.012,1.)); - vec3 straightHit=gh+i*(-gh.z/safeZ(i.z));vec3 facetRay=bend(i,nFacet),curvedRay=bend(i,nCurved);vec3 facetHit=gh+facetRay*(-gh.z/safeZ(facetRay.z)),curvedHit=gh+curvedRay*(-gh.z/safeZ(curvedRay.z));vec2 base=facetHit.xy-straightHit.xy,curve=curvedHit.xy-facetHit.xy;vec2 worldDelta=vec2(softLimit(base.x,cellWorld*.08),softLimit(base.y,cellWorld*.08));vec2 d=curve/cellWorld;worldDelta+=vec2(.3*d.x/(.3+abs(d.x)),.3*d.y/(.3+abs(d.y)))*cellWorld; - vec2 sourceCenter=(cell+.5)/grid+(random-.5)*.16*cellSize; - vec2 widths; - if(style>.5){ - widths=mix(vec2(.82),vec2(1.12),hash2(cell+vec2(11.4,9.8))); - }else{ - float widthSeed=hash(cell+vec2(53.1,27.4)); - if(widthSeed<.6)widths=mix(vec2(.90),vec2(1.08),hash2(cell+vec2(7.2,3.1))); - else if(widthSeed<.9)widths=mix(vec2(.46),vec2(.70),hash2(cell+vec2(7.2,3.1))); - else widths=mix(vec2(1.10),vec2(1.28),hash2(cell+vec2(7.2,3.1))); - } - float angle=(random.x-.5)*.08,c=cos(angle),s=sin(angle); - vec2 warpedLocal=local*cellSize+worldDelta/uPaneSize; - vec2 rawSampleUv=sourceCenter+(mat2(c,-s,s,c)*warpedLocal)*widths; - // Fade cell displacement near its edges to keep neighboring samples continuous. - vec2 cellEdge=.5-abs(local); - float interiorWeight=smoothstep(0.,.085,cellEdge.x)*smoothstep(0.,.085,cellEdge.y); - vec2 sampleUv=paneUv+(rawSampleUv-paneUv)*interiorWeight; - float edgeDistance=min(min(paneUv.x,paneUv.y),min(1.-paneUv.x,1.-paneUv.y));float edgeWeight=smoothstep(0.,max(cellSize.x,cellSize.y)*.75,edgeDistance);float strength=clamp(uStrength,0.,1.)*edgeWeight;vec2 blurStep=cellSize*mix(.006,.012,hash(cell+vec2(5.)));vec2 centerUv=mix(paneUv,sampleUv,strength);vec4 color=samplePane(centerUv)*.4;color+=samplePane(mix(paneUv,sampleUv+vec2(blurStep.x,0.),strength))*.15;color+=samplePane(mix(paneUv,sampleUv-vec2(blurStep.x,0.),strength))*.15;color+=samplePane(mix(paneUv,sampleUv+vec2(0.,blurStep.y),strength))*.15;color+=samplePane(mix(paneUv,sampleUv-vec2(0.,blurStep.y),strength))*.15;color.a=1.; - vec3 v=normalize(uContentCameraPosition-gh),reflected=reflect(-v,nCurved); float lightT=(uLightPosition.z-gh.z)/safeZ(reflected.z); vec2 lightHit=gh.xy+reflected.xy*lightT; vec2 halfSize=vec2(.32,.42)*min(uPaneSize.x,uPaneSize.y); vec2 windowCoord=abs(lightHit-uLightPosition.xy)/halfSize; vec2 windowMask=1.-smoothstep(vec2(.45),vec2(1.15),windowCoord); float spec=windowMask.x*windowMask.y*step(.0001,reflected.z)*step(0.,lightT); float gloss=spec*clamp(uGlossStrength,0.,1.)*.12*edgeWeight*clamp(uStrength,0.,1.); color.rgb=mix(color.rgb,vec3(1.),gloss); gl_FragColor=color; - #include -} diff --git a/docs/glass-qa-round2/narrow-close.png b/docs/glass-qa-round2/narrow-close.png deleted file mode 100644 index f5789de..0000000 Binary files a/docs/glass-qa-round2/narrow-close.png and /dev/null differ diff --git a/docs/glass-qa-round2/narrow-default.png b/docs/glass-qa-round2/narrow-default.png deleted file mode 100644 index 9b9562c..0000000 Binary files a/docs/glass-qa-round2/narrow-default.png and /dev/null differ diff --git a/docs/glass-qa-round2/plan.md b/docs/glass-qa-round2/plan.md deleted file mode 100644 index 0da5719..0000000 --- a/docs/glass-qa-round2/plan.md +++ /dev/null @@ -1,21 +0,0 @@ -# 1차 수정본 QA 및 2차 개선 계획 - -2026-09-13. 사용자 요청: 1차 수정본 QA, 개선점을 보고하고 구현. karpathy-guidelines 적용. - -## 재현한 문제 - -1. 샘플 확대3/X-.15/Y-.35/Grid8/Distortion.9에서 오른눈을 가로지르는 흰 선과 코/입 아래 뾰족한 이음새. gloss0 및 curvature0에서도 남는다. 현재 edge product weight가 두 축의 UV 변위를 원본으로 복귀시켜 경계 위치를 원본에 고정하는 구조가 유력 원인이다. -2. Reeded에서 Mosaic 스타일을 촘촘 유리로 변경하면 Grid28/Distortion.85로 덮어쓴다. Mosaic 전용 UI가 타 효과에도 활성화되어 있다. - -## 개선 명세 - -- 경계에서 원본 좌표로 되돌리는 1차 방식 제거. 중심 셀과 가까운 이웃 최대4개에서 affine UV, 배율/회전 행렬, 표면 기울기를 연속 가중치로 혼합한다. 내부는 1개, 모서리2개, 코너4개 셀 평가를 목표로 한다. -- 혼합한 곡면/facet 법선으로 기존 굴절을 1회 계산하고, 동일 곡면 법선을 반사에 공유한다. 기존 확대분포, seed, jitter.16, signed default+.65, curve0 셀효과,5tap,2pass,외곽,Distortion0는 유지한다. -- 전이 half-width .16셀에서 시작. affine 위치는 전이구간만큼 이웃셀 밖으로 연장하고, 곡면 q만 [-1,1]로 제한한다. 전역 단조성을 보장하는 광학 해법은 아니므로 접힘/늘어짐을 시각 검증한다. -- Mosaic 스타일 label은 Mosaic에서만 표시, select disabled와 handler guard를 함께 적용한다. 효과 전환 시 기존 스타일/Grid/Distortion을 초기화하지 않는다. - -## 검증 - -변경 전 NoGlass 코/눈/몸 카메라 시차를 먼저 재확인했다(cameraX0→.092). 같은 샘플/구도/광택0에서 눈의 선과 뾰족한 이음새 감소, 큰눈코/셀정보 차이 보존을 확인한다. 이후 signed0/±값,drag,mobile,compact스타일,RT효과전환,브라우저shader오류와 build를 확인한다. UI는 Grid20/Distortion.72로 맞춘 후 Reeded→Frosted→Mosaic에서 설정 비활성/복원과 값 보존을 확인한다. - -추가 texture fetch는 없지만 셀별 ALU 연산은 증가한다. 실제 기기 성능 측정 없이 모바일 성능 동등성을 주장하지 않는다. 원본/샘플 depth를 변경하거나 외부에 게시하지 않는다. 기존 Distortion0 액자밖 출력 계약은 이번 수정에서 유지한다. diff --git a/docs/glass-qa-round2/validation.md b/docs/glass-qa-round2/validation.md deleted file mode 100644 index 5900d28..0000000 --- a/docs/glass-qa-round2/validation.md +++ /dev/null @@ -1,38 +0,0 @@ -# 1차 수정본 QA 및 2차 개선 결과 - -2026-09-13. karpathy-guidelines 적용. Astra 설계/독립 정적·이미지 검토, Luna 두 에이전트가 각각 shader와 UI 구현, 주 에이전트 실제 브라우저 검증. - -## QA 결과와 해결 - -1. **눈의 가는 절개선과 입/목의 뾰족한 이음새**: 1차 구현의 원본 UV 복귀가 유력 원인. 광택0, 곡률0, 드래그에서 재현했다. 셀 경계에서 원본 UV로 되돌리는 방식은 제거하고, 가까운 이웃 셀의 affine UV/회전·배율/표면 기울기를 최대4개까지 보간했다. 같은 혼합 법선으로 굴절과 반사를 계산한다. 사진 색상을 이중 혼합하지 않으며 5회 texture fetch는 유지한다. -2. **Reeded/Frosted에 Mosaic 스타일이 간섭**: 전용 label을 숨기고 select disabled 및 change handler guard를 적용했다. 일반 Grid/Distortion 조절과 효과 전환 시 값 보존은 유지한다. - -변경 소스: src/shaders/mosaic.frag, src/main.ts. 원본은 before.frag / before-main.ts에 보존. 추가 UI/새 자산/새 라이브러리/AI depth/사진 리라이팅 없음. 기존 signed default+.65, 확대 seed/widths, jitter.16,곡률0facet,Depth/RT,외곽,Distortion0 계약 유지. - -## 시각 판단 - -before-close.png와 after-close.png는 같은 샘플 확대3/X-.15/Y-.35/Grid8/Distortion.9/곡률+.65/광택0이다. 눈 가로 절개선과 입/목의 날카로운 연결이 크게 완화된다. 일부 늘어남과 셀별 배율 차이는 남으며, 완전한 물리 유리 재현이나 결함 전부 제거를 주장하지 않는다. - -기본 확대2.4/X-.10/Y-.35/Grid10/.9/+.65/광택.3은 docs/natural-glass/after-default.png가 1차, 이 폴더 after-default.png가 2차다. 이마/몸의 사각 조각감은 약해지는 절충이 있다. 전이 half-width .12도 비교했으나 명확한 조각감 개선이 없어 .16을 최종 채택했다. narrow-*.png는 미채택 .12 후보다. Astra도 .16 수용 가능, 정적 차단 결함 없음으로 판단했다. - -## 검증 증거 - -- 변경 전 Glass OFF cameraX0→.092: 코531.509→528.803px, 왼눈459.283→457.560px, 몸350.477→350.467px. 수작업 Depth 기반 실제 부위별 카메라 시차 확인. -- 최종 .16에서 광택0/곡률0,-1,+1, 기본/근접 구도 비교. 곡률0에서도 셀 샘플 효과가 남음. 같은 법선 사용은 정적 검토와 Glass Only 반사 드래그로 확인. -- 390×844 근접 화면에서 눈·코 식별과 액자/유리 경계 고정, 드래그cameraX .123 관측. 최대시점 도달 테스트가 아님. 뷰포트 override 복원. after-mobile.png는 광택.15이다. -- Glass Only 광택1/조명0,0에서 사각 반사 영역과 드래그에 따른 위치변화 확인. 이 진단에서 일부 셀 반복은 보인다. -- Distortion0 원본 출력 확인. 기존 액자밖 원본 노출 한계는 계약에 따라 유지. -- 조각/촘촘 스타일, Reeded/Frosted 실제 렌더 확인. -- UI: 촘촘 선택 후 Grid20/Distortion.72 설정 → Reeded에서 styleVisible=false/styleEnabled=false → Frosted → Mosaic 복귀 시 촘촘 선택과20/.72 유지. CSS label display:grid에 hidden만 사용하는 문제를 피하도록 display를 명시했다. -- Luna 최종 npm.cmd run build: tsc-b와 Vite production build 성공. -- 작업 중 누적 로그에서 중간 저장본의 evaluateCell 대각 인수 순서 오류 1건을 발견. 최종 파일은 올바른 순서이며, **새 탭**에서 최종 샘플을 다시 로딩/렌더한 후 error logs=[] 확인. 중간 오류를 최종 오류로 보고하거나 누적 로그 전체가 없었다고 주장하지 않는다. - -## 남은 개선과 한계 - -- 가장 큰 미완료는 레퍼런스처럼 넓게 늘어나는 셀과 특징이 보이는 셀 사이의 정보량 차이. 현재는 선 제거와 경계 연속성을 우선했고 주변 털/배경이 비교적 많이 남는다. -- 셀 경계 보간은 광학적으로 완전한 렌즈 해법이 아니며 모든 사진/시점에서 접힘 없는 UV를 보장하지 않는다. 과도한 배율차와 극단 설정의 한계는 별도이다. -- 인접 셀 평가로 ALU 연산 증가. texture fetch 개수는 동일하지만 실제 모바일 FPS/배터리/GPU별 성능은 측정하지 않았다. -- 영상 재생, 실기기 자이로/터치, 장시간 메모리, 일반 사용자 사진 여러 장 QA는 이번에 실행하지 않았다. 샘플은 수작업 Depth이며 일반 사진 자동 깊이를 의미하지 않는다. -- 모바일 시작 안내문 줄바꿈도 관찰했으나 이번 유리 경계 및 효과 전용 컨트롤 범위에서는 변경하지 않았다. - -실행: npm.cmd run dev -- --host 127.0.0.1, http://127.0.0.1:5173/ 에서 샘플 로드. 최종 미리보기는 확대3/-.15/-.35/Grid8/.9/+.65/광택.15, 나머지 기본값, 정면이다. 원본 사진/Depth 변경 및 외부 게시 없음. diff --git a/docs/glass-resolution-after-matched.png b/docs/glass-resolution-after-matched.png deleted file mode 100644 index 6d1bdb8..0000000 Binary files a/docs/glass-resolution-after-matched.png and /dev/null differ diff --git a/docs/glass-resolution-after.png b/docs/glass-resolution-after.png deleted file mode 100644 index 9555b92..0000000 Binary files a/docs/glass-resolution-after.png and /dev/null differ diff --git a/docs/glass-resolution-before.png b/docs/glass-resolution-before.png deleted file mode 100644 index d7ae9e8..0000000 Binary files a/docs/glass-resolution-before.png and /dev/null differ diff --git a/docs/glass-resolution-curvature-1.png b/docs/glass-resolution-curvature-1.png deleted file mode 100644 index 89a2c37..0000000 Binary files a/docs/glass-resolution-curvature-1.png and /dev/null differ diff --git a/docs/glass-resolution-curvature0.png b/docs/glass-resolution-curvature0.png deleted file mode 100644 index 8b1a5c5..0000000 Binary files a/docs/glass-resolution-curvature0.png and /dev/null differ diff --git a/docs/glass-resolution-curvature1.png b/docs/glass-resolution-curvature1.png deleted file mode 100644 index ac400a0..0000000 Binary files a/docs/glass-resolution-curvature1.png and /dev/null differ diff --git a/docs/glass-resolution-drag.png b/docs/glass-resolution-drag.png deleted file mode 100644 index 10dfb5e..0000000 Binary files a/docs/glass-resolution-drag.png and /dev/null differ diff --git a/docs/glass-resolution-gloss0.png b/docs/glass-resolution-gloss0.png deleted file mode 100644 index 97a172b..0000000 Binary files a/docs/glass-resolution-gloss0.png and /dev/null differ diff --git a/docs/glass-resolution-mobile.png b/docs/glass-resolution-mobile.png deleted file mode 100644 index f430bec..0000000 Binary files a/docs/glass-resolution-mobile.png and /dev/null differ diff --git a/docs/glass-resolution-task.md b/docs/glass-resolution-task.md deleted file mode 100644 index ec6908f..0000000 --- a/docs/glass-resolution-task.md +++ /dev/null @@ -1,32 +0,0 @@ -# 유리 투과 해상감 보정 · 2026-09-14 - -사용자 요청: -- 레퍼런스처럼 유리를 통과하면서 해상도가 크게 깨져 보이는 표현을 추가한다. -- 기존 `Ref1 | Ref2` 위쪽 비교 영역과 아래 작업 이미지 배치를 복구한다. - -해석 및 구현 기준: -- Ref2를 주 기준으로, 셀마다 털 등의 세부 정보가 줄고 눈·코 조각이 서로 다른 크기와 위치로 보이게 한다. -- 셀별 확대·압축 및 국소 샘플 퍼짐으로 표현한다. 원본 이미지나 전체 RenderTarget의 해상도를 낮추거나 단색 pixelation으로 대체하지 않는다. -- 기존 과도한 셀 샘플 이동 제한을 완화해 확대 효과가 실제 출력에 나타나도록 한다. -- Depth/AI 입력, 시점 이동, 유리판 기준 격자, 부호 있는 굴곡과 반사의 공통 법선을 보존한다. -- Distortion 0에서는 무효과 출력을 보존하며, 광택 0에서도 굴곡 및 셀별 정보 손실은 남는다. -- 비교 영역은 개발 모드와 로컬 배포 미리보기 모두에 표시한다. 이 변경은 외부 게시를 포함하지 않는다. - -검증: -- 같은 샘플·구도의 정지 화면에서 변경 전후 비교. -- Ref1/Ref2 로드 및 작업 이미지 위 배치, 모바일 가로 넘침 확인. -- 눈·코 식별, 셀별 정보량 차이, 드래그 시 좌표 일관성 확인. -- TypeScript/빌드와 실제 브라우저 시각 검증을 구분해 보고. - -## 구현 및 검증 결과 - -- 수정 파일: `src/main.ts`(비교 영역 개발 모드 제한 제거), `index.html`(Ref 캡션), `src/shaders/mosaic.frag`(조각 유리 샘플링). -- 조각 유리의 과도한 샘플 이동 제한을 제거했다. 셀별 확대·압축 비율과 중심 이동량을 변경하고, 9개 주변 샘플로 국소 세부 정보 손실을 강화했다. 촘촘 유리의 기존 샘플 범위와 5개 샘플 필터는 보존했다. -- `npm run build` 통과. 기존 번들 크기 안내는 남는다. -- 로컬 배포 미리보기 `http://127.0.0.1:5175/`에서 Ref1/Ref2 실제 이미지 로드 확인. -- 동일 1440×1000 화면과 샘플·구도의 변경 전후 비교: `glass-resolution-before.png`, `glass-resolution-after-matched.png`. 후자는 비교 조건을 맞추기 위해 테스트 페이지에서만 Ref 영역을 잠시 숨겨 캡처했으며 실제 앱은 Ref를 표시한다. -- 실제 비교 UI: `glass-resolution-after.png`. 눈·코를 식별할 수 있고 셀별 얼굴 조각의 확대·정보량 차이가 이전보다 커졌다. -- 광택 0에서도 조각화와 흐림 유지. 굴곡 -1/0/+1 렌더링 및 드래그, Mosaic/Reeded/Frosted 전환에서 셰이더·페이지 오류 없음. -- Distortion 0과 No Glass의 중앙 80×80 캡처 일치. 전체 프레임 경계의 픽셀 일치를 검사한 것은 아니다. -- 390px 화면에서 문서 너비 390px, Ref 영역 하단과 작업 이미지 상단이 모두 y=200. 가로 넘침 없음. `glass-resolution-mobile.png` 참조. -- 이번 검증은 수작업 샘플 depth를 사용했다. AI 추론 코드는 변경하지 않았으며 이번 보정에서 모델 추론 속도 및 실제 모바일 GPU 성능을 재측정하지 않았다. diff --git a/docs/glass-resolution-validation.json b/docs/glass-resolution-validation.json deleted file mode 100644 index 0ff4f25..0000000 --- a/docs/glass-resolution-validation.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "errors": [], - "distortionZeroCenterMatchesNoGlass": true, - "mobile": { - "width": 390, - "scrollWidth": 390, - "refs": [ - 1160, - 1387 - ], - "refsBottom": 200, - "stageTop": 200 - } -} \ No newline at end of file diff --git a/docs/gloss-validation.md b/docs/gloss-validation.md deleted file mode 100644 index ca6ef5d..0000000 --- a/docs/gloss-validation.md +++ /dev/null @@ -1,22 +0,0 @@ -# Mosaic 셀 광택 MVP 검증 - -2026-09-11. Astra 설계·정적 검토, GPT-5.6 Luna 코드 구현, 조정 에이전트 브라우저 검증. - -## 변경 - -- src/shaders/mosaic.frag: 기존 셀 법선과 월드 유리 교차점, 실제 카메라 방향으로 half-vector 반사 계산. 공통 광원 기본 (0.6, 0.8, 2.6), 반사 지수 64, 선형 색상에서 흰색으로 약하게 합성. -- src/main.ts / index.html: 광택 0~1(기본 .55), 조명 X/Y -2~2. 조명 Z는 고정. Mosaic 외 효과에서 조절 그룹 숨김/비활성화. 이벤트는 기존 AbortSignal 사용. -- 사진 리라이팅 없음. 기존 Depth/RT/굴절과 Reeded/Frosted 셰이더 보존. - -## 실제 확인 - -- npm.cmd run build 성공(Luna 실행): TypeScript 및 Vite production build. -- 사용자 sample-pet 사진으로 두 Mosaic 스타일 확인. 광택 0/.55 비교에서 셀 내부 밝기 변화, 조명 X +.6/-.6 및 Y +.8/-.8에 따른 반사 영역 이동 확인. 검은 격자선 추가 없음. -- 실제 좌우 드래그 시 카메라 진단 X 양수/음수 및 반사 변화 확인. Reset view 후 X=0과 원래 구도 복귀. -- Distortion 0 Final/No Glass 시각 비교에서 원본 구도와 색상 일치. 픽셀 단위 차이 검사는 하지 않음. -- Reeded/Frosted 전환 후 광택 그룹 숨김 확인. 브라우저 error 로그 빈 배열. -- Grid 96, 광택 1, 조명 X 2 입력 경로 확인. - -## 한계 - -물리적 면광원 또는 환경맵 반사가 아닌 간단한 넓은 하이라이트 근사다. 어두운 사진에서는 반사가 회색 밝은 면처럼 보일 수 있으며 광택 강도로 조절한다. 영상/실기기 gyro/성능 측정은 이번 수정에서 재검증하지 않았다. diff --git a/docs/implementation-plan.md b/docs/implementation-plan.md deleted file mode 100644 index 52ac6dd..0000000 --- a/docs/implementation-plan.md +++ /dev/null @@ -1,103 +0,0 @@ -# Pet Glass MVP 상세 구현 지시 - -원문은 `task-brief.txt`이며 이 문서는 구현 방법과 검증 기준을 구체화한다. - -## 범위와 가정 - -- Vite + strict TypeScript + Three.js + GLSL, Vanilla TS. 백엔드와 React는 사용하지 않는다. -- 업로드 미디어는 브라우저 내부에서만 처리한다. 외부 샘플 이미지가 없어도 안내 placeholder로 실행된다. -- 실제 PetPlane과 GlassPlane 사이 거리를 갖는 단일 표면 굴절 근사를 구현한다. 물리적으로 정확한 두꺼운 유리 시뮬레이션이나 여러 렌더 패스는 MVP 범위가 아니다. -- 구조는 원문 예상 폴더를 참고하되, 빈 관리자나 한 번만 쓰는 기능을 위한 추가 추상화를 만들지 않는다. - -## 구현 순서 - -1. Scene, PerspectiveCamera, renderer와 이미지 업로드, PetPlane을 구현하고 비율 보존을 확인한다. -2. 실제 GlassPlane, pointer drag, Mosaic 셰이더를 구현하여 시점 변화에 따른 서로 다른 셀 굴절을 눈으로 검증한다. -3. VideoTexture와 미디어 수명 관리를 추가한다. -4. Reeded, Frosted, gyro와 반응형 컨트롤을 완성한다. -5. 타입 검사와 빌드, 브라우저 동작을 검증하고 제한사항을 기록한다. - -## Scene과 굴절 - -- PerspectiveCamera는 대략 fov 40도, (0,0,3)에서 시작하고 원점을 바라본다. -- PetPlane은 z=0, GlassPlane은 z=0.2에 배치한다. 실제 PlaneGeometry 두 개를 scene에 추가한다. 셀이나 ridge마다 mesh를 만들지 않는다. -- 미디어 texture는 두 plane에서 공유하되 MediaLoader만 texture의 수명을 소유한다. -- vertex shader에서 유리 표면 world position을 전달한다. fragment shader는 cameraPosition에서 표면으로 향하는 입사 ray를 계산하고, 셀 내부 위치에 따라 변화하는 +z 방향 normal로 굴절시킨다. -- 유리 위치에서 굴절 ray와 pet z=0의 교차점을 구한 뒤 pet의 실제 width/height로 UV를 계산한다. 이렇게 해야 유리와 미디어 사이 거리, 카메라 시점, 셀 normal이 함께 샘플 위치를 결정한다. -- strength=0은 기본 직진 ray, strength가 증가하면 굴절 ray가 반영되도록 한다. ray.z는 교차점 계산에서 0이 되지 않도록 제한한다. -- 원문의 uTexture, uGridSize, uStrength, uViewOffset, uResolution, uTime uniform을 유지한다. uViewOffset는 작은 셀별 normal 또는 굴절 응답 변화에 사용할 수 있지만 모든 UV에 동일한 이동만 주는 구현은 허용하지 않는다. -- 컬러 텍스처 색공간과 fragment 출력 색공간 처리를 맞추고 이미지·비디오에서 방향과 색상이 일치하는지 확인한다. - -## Contain과 겹침 처리 - -- 원본 가로세로 비율을 항상 보존한다. 캔버스의 실제 컨테이너 크기와 카메라 frustum으로 크기를 계산한다. -- 유리 평면이 카메라에 더 가까우므로 **앞쪽 GlassPlane의 가시 영역**을 기준으로 두 평면 크기를 정한다. 약 15% 여백과 최대 약 0.15 world-unit의 카메라 이동 제한을 시작값으로 사용한다. -- resize 시 두 plane 크기와 shader의 pet 크기, 해상도 uniform을 함께 갱신한다. 드래그 중 이미지 크기가 수시로 변하는 자동 확대는 피한다. -- 같은 크기의 앞쪽 유리는 정면 투영에서 뒤쪽 PetPlane을 덮는다. 카메라 이동 극단과 portrait/landscape viewport에서도 뒤쪽 원본 사진이 가장자리에 중복 노출되지 않는지 반드시 확인한다. 필요하면 유리의 면적을 소폭 넓히되 pet 크기 기반 sampling 좌표는 유지한다. -- GlassPlane에서 texture를 샘플하여 최종 색상을 출력할 때 opaque 출력으로 시작한다. 원본 사진과 반투명 합성하여 얼굴이 이중으로 보이는 결과를 만들지 않는다. -- 굴절된 UV가 미디어 범위를 벗어나면 scene과 맞는 배경색 또는 부드러운 가장자리 fade를 사용한다. clamp만으로 사진 가장자리를 길게 늘이지 않는다. -- contain은 배치상 원본 미디어가 잘리지 않는다는 의미다. 굴절 때문에 경계의 일부가 다른 샘플로 바뀌는 것은 효과에 포함되지만, 드래그 시 평면 자체가 viewport 밖으로 잘리면 안 된다. - -## 효과별 요구사항 - -### Mosaic - -- vUv를 grid로 나누고 cell=floor(scaled), local=fract(scaled)-0.5를 계산한다. -- local에 따라 변화하는 볼록/오목 렌즈 normal과 cell hash 기반 약 ±15% 강도 차이를 사용한다. -- 카메라 이동 시 서로 다른 cell에서 얼굴의 눈·코 등 feature가 다르게 움직여야 한다. cell 중심의 단일 texel로 양자화하는 pixelation은 금지한다. -- 셀 경계는 은은하게 표현한다. 종횡비가 극단적인 사진에서도 사각형 렌즈 셀 형태가 과도하게 찌그러지지 않도록 grid의 축별 비율을 고려한다. - -### Reeded - -- x 방향으로 반복되는 원통 렌즈 normal을 만든다. y 방향 변형은 거의 없도록 한다. -- local ridge 위치와 약한 ridge별 차이가 굴절에 반영되어야 한다. 좌우 시점 변화가 전체 사진 이동에 그치면 안 된다. - -### Frosted - -- 안정된 공간 noise로 normal 또는 UV를 왜곡하고 5~9개의 주변 texture 샘플을 평균한다. -- 대략적인 형태는 남기고 디테일을 흐리게 한다. 시점 변화에 굴절 방향이 반응하게 하되 시간만으로 noise가 끓는 효과는 피한다. - -## 입력과 애니메이션 - -- pointerdown/move/up/cancel, pointer capture를 사용하고 canvas에만 touch-action:none을 설정한다. -- drag delta를 canvas 크기로 정규화하여 target에 누적한 뒤 [-1,1]로 clamp한다. -- pointer와 gyro는 하나의 target/current 상태를 공유한다. sensitivity는 한 곳에서만 적용한다. -- requestAnimationFrame에서 시간 기반 보간으로 카메라와 shader 상태를 갱신한다. VideoTexture를 매 프레임 새로 만들지 않는다. -- Reset은 target/current를 중앙으로 돌리고 gyro 사용 중이면 기준 자세도 재설정한다. -- ResizeObserver로 실제 canvas container 크기를 반영하고 DPR은 최대 2로 제한한다. - -## 미디어 수명과 오류 - -- jpg/jpeg/png/webp 이미지와 브라우저에서 재생할 수 있는 mp4/webm 영상을 지원한다. -- 새 미디어가 준비된 다음 기존 미디어를 교체한다. 로드 실패 시 기존 화면을 보존하고 읽을 수 있는 오류를 표시한다. -- 증가하는 요청 ID를 사용하여 연속 업로드 중 늦게 준비된 이전 파일이 최신 파일을 덮지 않게 한다. stale 결과도 dispose/revoke한다. -- 비디오는 muted, loop, playsInline을 설정하고 metadata와 첫 frame을 준비한 뒤 VideoTexture를 적용한다. play() 실패 시 사용자용 재생 버튼과 상태 메시지를 제공한다. -- 교체/실패/해제 시 texture.dispose, video.pause, video src 해제와 load, URL.revokeObjectURL을 빠뜨리지 않는다. 활성 미디어와 로드 중 미디어의 정리를 구분한다. -- scene 해제 시 RAF, observer, DOM/sensor 이벤트, material, geometry, renderer와 미디어를 정리한다. material 교체 시 이전 material을 dispose한다. - -## Gyroscope - -- 기본 OFF이며 사용자 버튼 클릭에서 권한을 요청한다. iOS requestPermission은 클릭 핸들러에서 다른 비동기 대기 전에 호출한다. -- 권한 거절, 미지원, 비보안 컨텍스트를 표시하고 drag는 계속 사용 가능하게 한다. -- 권한 API가 없는 환경에서도 orientation 이벤트를 연결하되 null beta/gamma는 무시한다. -- 첫 유효 reading을 기준 자세로 삼고 약 30도 기울기를 [-1,1]로 변환한다. 화면 회전 방향을 보정한다. -- 이벤트가 없으면 센서값 대기 상태로 표시한다. OFF 또는 해제 시 listener를 제거한다. 권한 허용만으로 실제 센서 동작이 검증됐다고 보고하지 않는다. - -## UI - -- Dark UI, 큰 canvas, 모바일에서 접근 가능한 반투명 컨트롤 패널을 사용한다. -- 사진/영상 업로드, Mosaic/Reeded/Frosted, strength, sensitivity, Reset, gyro toggle, 현재 효과와 상태 표시를 제공한다. -- 초기에는 “반려동물 사진 또는 영상을 선택하세요”, 미디어 준비 후 약 2초간 drag 안내를 표시한다. -- 패널 스크롤과 canvas drag가 충돌하지 않도록 한다. WebGL 초기화 실패 시 화면에 설명한다. - -## 완료 검증 - -- npm install, npm run build, npm run dev가 동작하고 TypeScript 오류가 없다. -- 가로/세로 이미지 업로드, canvas resize, 모바일 viewport에서 비율과 contain이 유지된다. -- 드래그 전후 Mosaic의 서로 다른 셀 내부 feature가 서로 다르게 움직인다. Reeded는 x 중심 굴절, Frosted는 흐림과 시점 반응을 보인다. -- strength 0부터 최대값, sensitivity, Reset, pointer cancel을 확인한다. -- 영상 loop 및 재생 실패 UI, 영상→이미지→영상 교체, 빠른 연속 업로드를 확인한다. -- 카메라 이동 극단에서 원본 사진이 유리 옆에 중복 노출되지 않고, 유리/미디어 평면이 viewport 밖으로 잘리지 않는다. -- gyro 미지원/거절 시 drag가 유지된다. 실제 센서와 성능 수치를 검증하지 못하면 미검증으로 표시한다. -- 브라우저에 지속적인 콘솔 오류나 GLSL 컴파일 오류가 없다. 빌드 성공만으로 WebGL 셰이더 정상 동작을 주장하지 않는다. -- 결과 보고에는 생성/수정 파일, 구현 기능, 미완료 또는 미검증 항목, 실행 방법, 셰이더 원리와 다음 개선점을 포함한다. diff --git a/docs/mosaic-reference-validation.md b/docs/mosaic-reference-validation.md deleted file mode 100644 index fe032ef..0000000 --- a/docs/mosaic-reference-validation.md +++ /dev/null @@ -1,22 +0,0 @@ -# Mosaic 시각 보정 - -사용자 레퍼런스에 따라 원형 물결과 검은 격자 대신 사각 셀별 이미지 분절을 목표로 했다. Astra가 명세·검토, GPT-5.6 Luna가 코드를 수정했다. 이전 구현은 `before-mosaic-reference/`에 보존했다. - -수정 파일: `src/shaders/mosaic.frag`, `src/main.ts`, `index.html`. 프로젝트 지침과 README도 갱신했다. - -- 셀별 샘플 중심, 확대율, 미세 회전, 카메라 굴절 보조를 적용한다. -- 조각 유리의 샘플 폭은 셀의 .35~.50, 촘촘 유리는 .03~.10이며 5-tap 샘플을 사용한다. 단일 색 texel을 고정하는 pixelation은 아니다. -- 검은 셀 경계선과 원형 bulge를 제거했다. -- 중립 사진 사각형 밖은 원 RT를 유지하고 가장자리 약 .75셀에서 굴절 강도를 줄인다. 큰 카메라 이동에서는 실제 사진 경계와 정적 패널 경계가 다를 수 있다. -- 기본 Final, 프리셋별 Grid/Strength 동기화, grid 범위 6~96. - -브라우저 확인: - -- 동일 사용자 사진·동일 구도에서 두 스타일 비교. 셀 경계에서 눈·코·얼굴이 분절되고, 이전 검은 격자·원형 물결이 사라짐을 확인했다. -- 좌우 drag에서 셀 내부의 눈/코 조각이 달라짐을 확인했다. -- 강도 0 Final과 No Glass의 위치·색상을 육안 비교했다. 픽셀 단위 차이 검사는 수행하지 않았다. -- 새 검증 탭에서 Mosaic 두 스타일 및 Reeded/Frosted를 전환하고 error 로그 빈 배열을 확인했다. 개발 중 HMR로 발생한 이전 오류는 새 세션 검증과 구분했다. -- 390×844 및 844×390 viewport에서 가로 넘침 없이 레이아웃이 유지됨을 확인했다. -- TypeScript/production build 통과. - -사진 속 실제 유리의 광학 물성을 추정·복원한 결과가 아니라, 레퍼런스의 인상을 목표로 한 시각 근사다. 사진 구도·얼굴 크기·격자 수에 따라 인상이 달라진다. 이번 변경에서는 실제 영상·물리 gyro·성능 실측을 추가 수행하지 않았다. diff --git a/docs/natural-glass/after-close.png b/docs/natural-glass/after-close.png deleted file mode 100644 index f188830..0000000 Binary files a/docs/natural-glass/after-close.png and /dev/null differ diff --git a/docs/natural-glass/after-default.png b/docs/natural-glass/after-default.png deleted file mode 100644 index 3e98efa..0000000 Binary files a/docs/natural-glass/after-default.png and /dev/null differ diff --git a/docs/natural-glass/after-mobile.png b/docs/natural-glass/after-mobile.png deleted file mode 100644 index e6363c0..0000000 Binary files a/docs/natural-glass/after-mobile.png and /dev/null differ diff --git a/docs/natural-glass/before-close.png b/docs/natural-glass/before-close.png deleted file mode 100644 index 1be1d65..0000000 Binary files a/docs/natural-glass/before-close.png and /dev/null differ diff --git a/docs/natural-glass/before-default.png b/docs/natural-glass/before-default.png deleted file mode 100644 index 52cad8f..0000000 Binary files a/docs/natural-glass/before-default.png and /dev/null differ diff --git a/docs/natural-glass/before.frag b/docs/natural-glass/before.frag deleted file mode 100644 index 515c856..0000000 --- a/docs/natural-glass/before.frag +++ /dev/null @@ -1,32 +0,0 @@ -uniform sampler2D uSceneTexture; -uniform mat4 uContentViewProjection,uContentInverseViewProjection; -uniform vec3 uContentCameraPosition,uLightPosition,uBackgroundColor; -uniform float uGlassZ,uGridSize,uStrength,uMosaicStyle,uCurvature,uGlossStrength; -uniform vec2 uViewOffset,uPetSize,uPaneSize; -uniform vec4 uPaneRect; -varying vec2 vUv; -vec2 projectUv(vec3 p){vec4 c=uContentViewProjection*vec4(p,1.);float w=abs(c.w)<.0001?(c.w<0.?-.0001:.0001):c.w;return c.xy/w*.5+.5;} -vec4 sampleScene(vec2 uv){return texture2D(uSceneTexture,clamp(uv,0.,1.));} -vec4 samplePane(vec2 pane){return sampleScene(projectUv(vec3((pane-.5)*uPaneSize,uGlassZ)));} -float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);} -vec2 hash2(vec2 p){return vec2(hash(p),hash(p+vec2(19.19,73.73)));} -float safeZ(float z){return abs(z)<.0001?(z<0.?-.0001:.0001):z;} -vec3 bend(vec3 i,vec3 n){vec3 r=refract(i,n,.75);return length(r)<.0001?i:r;} -float softLimit(float value,float limit){return value*limit/(limit+abs(value));} -void main(){ - if(uStrength<=.001){gl_FragColor=sampleScene(vUv); - #include - return;} - vec4 f=uContentInverseViewProjection*vec4(vUv*2.-1.,1.,1.);float fw=abs(f.w)<.0001?(f.w<0.?-.0001:.0001):f.w;vec3 farWorld=f.xyz/fw;vec3 i=normalize(farWorld-uContentCameraPosition);float gt=(uGlassZ-uContentCameraPosition.z)/safeZ(i.z);vec3 gh=uContentCameraPosition+i*gt; - vec2 paneUv=gh.xy/uPaneSize+.5;vec2 grid=vec2(uGridSize,max(1.,uGridSize*uPaneSize.y/uPaneSize.x));vec2 gridUv=paneUv*grid,cell=floor(gridUv),local=fract(gridUv)-.5,cellSize=1./grid,random=hash2(cell);float style=clamp(uMosaicStyle,0.,1.),cellWorld=min(uPaneSize.x/grid.x,uPaneSize.y/grid.y); - if(paneUv.x<0.||paneUv.x>1.||paneUv.y<0.||paneUv.y>1.){gl_FragColor=vec4(uBackgroundColor,1.); - #include - return;} - // Positive height bulges toward the observer (+Z); negative height is concave. - float curvature=clamp(uCurvature,-1.,1.),excess=max(curvature-.65,0.),surfaceCurvature=curvature-(.25/.35)*excess*excess; float height=.009*cellWorld*surfaceCurvature*mix(.92,1.08,hash(cell+vec2(41.7,17.3))); vec2 q=2.*local; vec2 q2=q*q,q3=q2*q,b=1.-q2*q2; vec2 skew=(hash2(cell+vec2(23.8,61.2))-.5)*.28; float asym=1.+dot(skew,q); vec2 dhdq=height*vec2(-4.*q3.x*b.y*asym+b.x*b.y*skew.x,-4.*q3.y*b.x*asym+b.x*b.y*skew.y); vec2 cellDimensions=uPaneSize/grid; vec2 grad=-2.*dhdq/cellDimensions; vec3 nCurved=normalize(vec3(grad+(random-.5)*.012,1.)),nFacet=normalize(vec3((random-.5)*.012,1.)); - vec3 straightHit=gh+i*(-gh.z/safeZ(i.z));vec3 facetRay=bend(i,nFacet),curvedRay=bend(i,nCurved);vec3 facetHit=gh+facetRay*(-gh.z/safeZ(facetRay.z)),curvedHit=gh+curvedRay*(-gh.z/safeZ(curvedRay.z));vec2 base=facetHit.xy-straightHit.xy,curve=curvedHit.xy-facetHit.xy;vec2 worldDelta=vec2(softLimit(base.x,cellWorld*.08),softLimit(base.y,cellWorld*.08));vec2 d=curve/cellWorld;worldDelta+=vec2(.3*d.x/(.3+abs(d.x)),.3*d.y/(.3+abs(d.y)))*cellWorld; - vec2 sourceCenter=(cell+.5)/grid+(random-.5)*.32*cellSize+worldDelta/uPaneSize;vec2 widths;if(style>.5){widths=mix(vec2(.82),vec2(1.12),hash2(cell+vec2(11.4,9.8)));}else{float widthSeed=hash(cell+vec2(53.1,27.4));if(widthSeed<.6)widths=mix(vec2(.90),vec2(1.08),hash2(cell+vec2(7.2,3.1)));else if(widthSeed<.9)widths=mix(vec2(.46),vec2(.70),hash2(cell+vec2(7.2,3.1)));else widths=mix(vec2(1.10),vec2(1.28),hash2(cell+vec2(7.2,3.1)));}float angle=(random.x-.5)*.08,c=cos(angle),s=sin(angle);vec2 sampleUv=sourceCenter+mat2(c,-s,s,c)*(local*cellSize)*widths; - float edgeDistance=min(min(paneUv.x,paneUv.y),min(1.-paneUv.x,1.-paneUv.y));float edgeWeight=smoothstep(0.,max(cellSize.x,cellSize.y)*.75,edgeDistance);float strength=clamp(uStrength,0.,1.)*edgeWeight;vec2 blurStep=cellSize*mix(.006,.012,hash(cell+vec2(5.)));vec2 centerUv=mix(paneUv,sampleUv,strength);vec4 color=samplePane(centerUv)*.4;color+=samplePane(mix(paneUv,sampleUv+vec2(blurStep.x,0.),strength))*.15;color+=samplePane(mix(paneUv,sampleUv-vec2(blurStep.x,0.),strength))*.15;color+=samplePane(mix(paneUv,sampleUv+vec2(0.,blurStep.y),strength))*.15;color+=samplePane(mix(paneUv,sampleUv-vec2(0.,blurStep.y),strength))*.15;color.a=1.; - vec3 v=normalize(uContentCameraPosition-gh),reflected=reflect(-v,nCurved); float lightT=(uLightPosition.z-gh.z)/safeZ(reflected.z); vec2 lightHit=gh.xy+reflected.xy*lightT; vec2 halfSize=vec2(.32,.42)*min(uPaneSize.x,uPaneSize.y); vec2 windowCoord=abs(lightHit-uLightPosition.xy)/halfSize; vec2 windowMask=1.-smoothstep(vec2(.45),vec2(1.15),windowCoord); float spec=windowMask.x*windowMask.y*step(.0001,reflected.z)*step(0.,lightT); float gloss=spec*clamp(uGlossStrength,0.,1.)*.12*edgeWeight*clamp(uStrength,0.,1.); color.rgb=mix(color.rgb,vec3(1.),gloss); gl_FragColor=color; - #include -} diff --git a/docs/natural-glass/candidate-close.png b/docs/natural-glass/candidate-close.png deleted file mode 100644 index bfa947d..0000000 Binary files a/docs/natural-glass/candidate-close.png and /dev/null differ diff --git a/docs/natural-glass/candidate-default.png b/docs/natural-glass/candidate-default.png deleted file mode 100644 index e70ba50..0000000 Binary files a/docs/natural-glass/candidate-default.png and /dev/null differ diff --git a/docs/natural-glass/plan.md b/docs/natural-glass/plan.md deleted file mode 100644 index b8dae31..0000000 --- a/docs/natural-glass/plan.md +++ /dev/null @@ -1,13 +0,0 @@ -# 자연스러운 셀 경계 1차 보정 - -2026-09-13. 사용자 구현 승인. karpathy-guidelines 적용. - -가정: 레퍼런스2의 큰 눈·코 조각을 유지하면서 cut-paste 인상을 줄인다. 전면적인 물리 유리 재구현이 아닌 기존 Mosaic 최소 수정이다. 비교 구도는 기본 샘플 2.4/-.10/-.35/Grid10/.90/곡률+.65 및 얼굴 근접3/-.15/-.35/Grid8/.90/곡률+.65/광택0. - -첫 후보: 곡면에 의한 worldDelta를 셀의 회전/축별 배율 변환 내부에서 처리한다. 셀 가장자리6.5% 구간에서 최종 UV 변위를 smoothstep으로0에 수렴시킨다. 원본 색과 효과 색을 이중 혼합하지 않는다. 기존 seed/샘플 폭/곡면 법선/반사/5tap 필터/Distortion0/외곽처리는 유지한다. - -리스크: 좁은 구간에 변형이 집중되면 늘어진 띠나 두꺼운 격자가 보일 수 있다. 실제 화면 비교 후 폭을 조정하거나 방식을 재검토한다. 연속적인 UV가 물리적으로 정확한 굴절을 의미하지는 않는다. - -검증: 변경 전 Glass OFF 부위별 카메라 시차 → 같은 구도의 전후 정지 비교 → 광택0에서 곡률0,±.65,±1 비교 → 드래그 유리좌표 → 모바일 → 기존 효과/Distortion0와 shader error → TypeScript/Vite build. 영상/실기기gyro/성능 측정은 별도. - -기존 셰이더는 before.frag, 기준 이미지 before-default.png / before-close.png로 보존했다. 제품 기본값 변경, 미디어 게시, AI depth 추가는 하지 않는다. diff --git a/docs/natural-glass/tuned-close.png b/docs/natural-glass/tuned-close.png deleted file mode 100644 index a7a9532..0000000 Binary files a/docs/natural-glass/tuned-close.png and /dev/null differ diff --git a/docs/natural-glass/tuned-default.png b/docs/natural-glass/tuned-default.png deleted file mode 100644 index 6d82608..0000000 Binary files a/docs/natural-glass/tuned-default.png and /dev/null differ diff --git a/docs/natural-glass/validation.md b/docs/natural-glass/validation.md deleted file mode 100644 index 9af0ce6..0000000 --- a/docs/natural-glass/validation.md +++ /dev/null @@ -1,41 +0,0 @@ -# 자연스러운 셀 경계 1차 구현 결과 - -2026-09-13. Astra 설계 및 최종 정적/이미지 검토, Luna 소스 구현, 주 에이전트 실제 브라우저 검증. 적용 스킬 karpathy-guidelines. - -## 변경 - -소스 변경은 src/shaders/mosaic.frag 한 파일이다. - -- 곡면에 따른 worldDelta를 셀 로컬 좌표에 더한 후 기존 회전/축별 배율을 적용한다. 굴절 변위가 셀 확대·압축과 함께 변한다. -- 셀별 독립 이동 계수 .32→.16. 최대 이동 ±.16셀에서 ±.08셀로 감소. 기존 큰 확대/압축의 seed와 widths 분포는 보존. -- 셀 경계에서 rawSampleUv의 변위를 paneUv로 수렴시킨다. 최종 전이폭은 각 축 .085셀. 첫 .065 후보에서 가는 뾰족한 이음새를 보고 jitter 감소 후 폭을 조정했다. -- 색상 두 겹 혼합이나 전체 블러 증가 없이 UV 변위를 연결한다. 추가 texture fetch 없음. -- 기본 굴곡+.65, signed 높이/공유 법선, 사각 창 반사, 5tap 필터, outer pane fade, Distortion0 우회, Depth/RT/UI는 유지했다. - -## 시각 결과 - -동일 사진/동일 구도 before-default→after-default, before-close→after-close 비교. 이마·뺨·목의 일부 사각 절단이 완만해지고 큰 눈·코·입 조각을 유지한다. close는 광택0이므로 반사로 가린 개선이 아니다. Astra 독립 이미지 검토도 1차 변경 수용 가능으로 판단했다. - -레퍼런스 수준의 완전한 유리 질감은 아직 아니다. 오른눈을 가로지르는 가는 선, 입/목과 상단 검은 배경의 일부 이음새가 남는다. 최종 UV 전이는 렌즈의 물리 표면을 정확히 재구성한 것이 아니며, 기존 반사 법선에 이 전이 자체를 반영한 것도 아니다. 곡면·배율 연결의 시각 근사이고 후속 개선 여지가 있다. 촘촘 유리에서도 세부가 유지되나 배경 격자 반복은 보인다. - -## 실행한 검증 - -- 변경 전 Glass OFF: cameraX0→.095, 코531.509→528.716px, 왼눈459.283→457.506px, 몸350.477→350.471px. 부위별 카메라 시차 확인. 수작업 테스트 Depth이며 AI 추정 아님. -- 1280×720 기본 샘플 확대2.4/X-.10/Y-.35/Grid10/Distortion.90/굴곡+.65/광택.30 전후. -- 근접 확대3/X-.15/Y-.35/Grid8/Distortion.90/굴곡+.65/광택0 전후. -- 최종 근접 화면에서 광택0, 곡률0/-1/+1 시각 비교. 평탄에서도 셀 확대/이동이 남고 부호에 따른 윤곽 변화가 나타남. 중간 후보에서는 -.65도 비교했다. -- 390×844 최종 근접 화면: 눈·코 식별, 드래그 시 액자/유리 경계 함께 유지. cameraX .127 관측. 최대 이동 한계에 도달했다고 주장하지 않는다. 뷰포트 override 복원. -- Distortion0에서 기존 무효과 출력 확인. 사진이 액자 밖까지 보이는 기존 계약/한계는 유지된다. -- Mosaic 조각/촘촘 스타일, Reeded, Frosted 전환과 정면 화면 확인. -- 최종 브라우저 error logs 빈 배열. -- Luna 최종 npm.cmd run build 통과: TypeScript 및 Vite. 자동 시각 테스트나 성능 테스트 통과를 의미하지 않는다. - -미검증: 영상 재생, 실제 모바일 센서/터치, GPU별 호환성, FPS와 장시간 메모리. 새 반사 모델/방향성 퍼짐은 이번에 추가하지 않았다. Astra는 이번 범위에서 더 많은 변수를 동시에 바꾸지 않고 비교 가능한 1차 결과로 유지하는 것을 권했다. - -## 재현과 보존 - -npm.cmd run dev -- --host 127.0.0.1 후 http://127.0.0.1:5173/ 에서 샘플 로드. 기본 또는 위 근접값 적용. - -브라우저 전달 화면은 근접값, 광택.15, 굴곡+.65, Camera Offset.30/감도1의 정면이다. 저장된 after-close는 비교용 광택0, after-mobile은 광택.30이다. 원본 사진/Depth 변경 및 외부 게시 없음. 소스 기본값은 변경하지 않았다. - -before.frag와 before-*.png는 작업 전, candidate-*.png는 .32/.065 후보, tuned-*.png는 .16/.065 후보, after-*.png는 최종 .16/.085 결과다. Git 저장소를 사용할 수 없어 원본 파일 백업과 직접 대조로 변경을 검토했다. diff --git a/docs/qa-2026-09-13/default-desktop.png b/docs/qa-2026-09-13/default-desktop.png deleted file mode 100644 index 93808a9..0000000 Binary files a/docs/qa-2026-09-13/default-desktop.png and /dev/null differ diff --git a/docs/qa-2026-09-13/recommended-desktop.png b/docs/qa-2026-09-13/recommended-desktop.png deleted file mode 100644 index 2a7250b..0000000 Binary files a/docs/qa-2026-09-13/recommended-desktop.png and /dev/null differ diff --git a/docs/qa-2026-09-13/recommended-mobile.png b/docs/qa-2026-09-13/recommended-mobile.png deleted file mode 100644 index 72542dd..0000000 Binary files a/docs/qa-2026-09-13/recommended-mobile.png and /dev/null differ diff --git a/docs/qa-2026-09-13/review.md b/docs/qa-2026-09-13/review.md deleted file mode 100644 index 238f5a1..0000000 --- a/docs/qa-2026-09-13/review.md +++ /dev/null @@ -1,72 +0,0 @@ -# 레퍼런스 재비교 QA / 설정 / 제품 제시 검토 - -2026-09-13. 소스 변경 없이 수행. karpathy-guidelines 적용, GPT-6 Astra 독립 정적 검토와 주 에이전트 실제 브라우저 비교. 코드 변경이 없으므로 Luna 구현 작업은 없음. - -## 기준과 결론 - -지정 세션 `01a08e32-c332-7262-b2f2-537cb07bac41`에서 첨부 경로를 회수하고 원본 레퍼런스 1·2를 직접 열었다. 주 기준은 두 번째 `codex-clipboard-8f482fae-74a8-4a4f-9f11-e7be24c6638f.png`. 레퍼런스와 테스트는 서로 다른 사진이다. 같은 테스트 사진/구도에서 설정을 비교하되 픽셀 일치나 물리 재현도를 수치로 주장하지 않는다. - -핵심 동작은 확인되지만 레퍼런스의 시각적 완성도에는 미달한다. 레퍼런스는 일부 눈·코가 확대되고 주변 털·배경은 넓게 늘어나며 매끈한 유리 면을 이룬다. 현재는 눈·코 식별은 가능하나 사진을 사각형으로 어긋나게 붙인 느낌이 강하고, 털 세부가 많은 셀과 날카롭게 끊기는 경계가 여전히 눈에 띈다. 샘플의 어두운 차량 배경과 좁고 긴 원본 비율도 레퍼런스의 밝고 넓은 화면과 다르다. 설정만으로 해결되는 차이와 셰이더/원본 차이를 구분해야 한다. - -## 관찰한 설정 후보 - -아래는 수동으로 비교한 후보이며 전 범위 최적화 결과가 아니다. 공통 Final / Mosaic / 조각 유리 / 사진 Y -0.35 / Depth .25 / 조명 .60,.80 / 정면. - -| 후보 | 확대/X | Grid | Distortion | 굴곡 | 광택 | 판단 | -|---|---|---|---|---|---|---| -| 현재 기본 | 2.4 / -.10 | 10 | .90 | +.65 | .30 | 표정은 보이나 얼굴 대비 조각이 작고 배경 비중이 큼 | -| 완만한 큰 셀 | 2.4 / -.10 | 8 | .80 | +.30 | .15 | 덜 거칠지만 레퍼런스의 확대된 얼굴 인상이 약함 | -| 오목 비교 | 2.4 / -.10 | 10 | 1.00 | -.45 | .15 | 표면 경계는 달라져도 핵심 조각 배율 차이는 해결되지 않음 | -| 강한 굴절 비교 | 2.4 / -.10 | 10 | 1.00 | +.65 | .15 | 코·입의 사각 단절이 남음 | -| 촘촘한 확대 | 3 / -.15 | 12 | .90 | +.35 | .15 | 작은 절편이 많아져 목표에서 멀어짐 | -| 중간 확대 | 2.8 / -.10 | 8 | .85 | +.35 | .15 | 무난하지만 눈·코가 셀 경계에 걸리는 배치 | -| 가장 큰 셀 | 2.8 / -.10 | 6 | .85 | +.65 | .15 | 큰 조각은 생기지만 눈이 눌리고 배치가 덜 안정적 | -| **추천 후보** | **3 / -.15** | **8** | **.90** | **+.35** | **.15** | 비교 후보 중 큰 눈·코와 표정 식별의 균형이 가장 나음 | - -추천의 나머지 값: Camera Offset .20, View sensitivity .70, Gyroscope OFF, Reset view로 정면 복귀. 카메라/감도 값은 약한 조작감을 위한 선택이며 정면 정지 화면 유사도에는 기여하지 않는다. 조명 위치는 기존 유지값으로, 광원 위치 전 범위 최적화를 수행하지 않았다. 확대3은 현재 UI 상한이며 귀/얼굴 외곽이 잘리므로 얼굴 중심 효과용이다. 이 값을 일반 사진의 보편적 프리셋으로 적용하면 안 된다. 권장 탭에만 적용했고 소스의 기본 +.65를 포함한 기본값은 변경하지 않았다. - -## 실제 QA - -- npm.cmd run build: TypeScript + Vite 성공. 테스트 스위트 성공을 의미하지 않는다. -- Glass OFF를 먼저 확인. 샘플 기본 구도에서 cameraX 0→.101: 코 projectedX 531.509→528.550, 왼눈 459.283→457.405, 몸 350.477→350.486 px. 부위별 이동 차이가 있는 실제 카메라 parallax를 진단 출력에서 확인. -- Final/No Glass, Mosaic/Reeded/Frosted, 굴곡 -.45/+.30/+.35/+.65, 여러 Grid/확대/굴절 값을 화면 비교. -- 추천 후보를 1280×720 및 390×844에서 확인. 모바일 눈·코 식별 가능. 모바일 드래그에서 액자/유리 경계 유지, cameraX .055 관측. 최대 이동 범위 검증은 아님. 뷰포트 override 복원. -- 모바일 광택0에서도 사진 굴절이 남음. 다만 곡면 기여와 셀별 샘플 변형 기여를 정량적으로 분리한 검증은 아님. -- 현재 Reeded/Frosted 정면 화면은 액자 안에 유지된다. 이전 QA의 외곽 노출 결함을 그대로 재보고하지 않는다. 타 효과의 드래그 좌표 일관성은 이번에 검증하지 않음. -- 새 탭 첫 Tab으로 사진 업로드 input에 초점 도달. 업로드 키보드 접근의 이전 문제가 개선됨. 파일 선택/업로드 완료 전체 흐름은 재실행하지 않음. -- 수작업 Depth 안내가 샘플 로딩 후 계속 표시됨. -- 브라우저 error 로그 빈 배열. 영상, 실제 모바일 센서/터치, 프레임률, GPU 호환성, 장시간 메모리는 미검증. - -## 남은 문제와 구현상 한계 - -1. 실제 재현: Distortion .01→0에서 확대 사진이 액자 밖까지 펼쳐진다. 원본 무효과 출력을 유지하는 기존 계약의 결과이므로 무조건 셰이더 bypass를 제거할 사안은 아니다. 사용자용 전후 비교는 동일 구도/동일 액자 영역을 유지하는 별도 표현이 필요하다. -2. 실제 재현: Reeded 상태에서도 Mosaic 스타일 선택이 활성화되어 있고 촘촘 유리로 바꾸면 Grid28 / Distortion.85로 덮어쓴다. 해당 컨트롤을 Mosaic에만 노출하는 것이 명확하다. -3. 정적 확인: 일반 사진은 구도1/0/0 및 평탄 Depth로 로딩된다. 샘플은 전용 확대와 수작업 Depth가 있다. 일반 사진에서 Depth Scale을 높여도 코·눈의 상대 깊이를 생성하지 않는다. 샘플 수준의 입체감을 일반 업로드 결과로 약속할 수 없다. -4. 정적 확인: 셀 확대/압축은 고정 난수이며 눈·코를 인식하지 않는다. 원하는 부위가 큰 셀에 들어가는지는 구도/Grid에 의존한다. 현재 값으로 모든 사진을 레퍼런스처럼 만들 수 없다. -5. 제품상 부족: 저장/내보내기/프리셋 영속 저장이 없다. 화면을 만져보고 끝나는 상태라 공유형 제품의 핵심 완료 행동이 비어 있다. - -셰이더는 Depth mesh를 RT로 그린 뒤 유리판 기준 셀별 이동·축별 배율·회전/주변 샘플을 적용하며, 얕은 사각 곡면의 법선을 굴절과 창 반사에 공유한다. 다음 시각 개선은 광택 증가보다 셀 내부의 연속적인 늘어남과 경계 전이, 특징이 남는 셀과 넓은 색면 셀의 정보량 차이에 집중해야 한다. 모든 셀 흐림이나 단색 픽셀화는 권하지 않는다. - -## 보여주는 방식 - -권장 포지셔닝은 ‘내 반려동물이 유리창 뒤에서 빼꼼 보는 사진 효과’. 현재 기능 범위에서는 로컬 사진 효과/감상 도구로 소개하고, 고급 깊이 편집기는 뒤로 둔다. - -첫 화면: 결과 예시 크게 → 짧은 드래그 안내 → 사진 선택. 사용자의 첫 결과는 사진 선택 → 얼굴 구도 → 프리셋 2~3개 → 강도 조절 순서. Depth, RGB, Glass Only, 조명XY, 진단 수치는 고급/개발 패널로 이동하는 설계가 좋다. 모바일은 결과를 보면서 얼굴 구도/강도를 바꿀 수 있게 하단 패널과 미리보기를 결합하는 편이 현재의 긴 세로 슬라이더 목록보다 적합하다. - -스타일명은 ‘Classic glass / Soft glass / Chunky glass’처럼 결과 중심으로 제안한다. 실제 구현/검증한 프리셋 이름은 아니며, 본 QA가 새로운 스타일을 추가한 것은 아니다. 주된 결과는 큰 눈·코가 남는 조각 유리로 두고 과도한 왜곡은 선택지로 제공한다. 공유 기능을 추가할 경우 9:16 짧은 좌우 시점 루프와 정지 이미지가 후보지만 현재 미구현이다. 정지 이미지 자체는 시점 상호작용을 보존하지 못하므로 제품 소개에서 구분한다. - -## 타깃 판단: 검증할 가설 - -‘해외 남성이 주 수요층’이라는 결론을 이 QA로 확인할 수 없다. 성별별 취향을 전제하기보다 제작·저장·공유하려는 반려인과 시각 효과를 실험하는 사람을 나누어 본다. 영어권에서 신기한 WebGL 장난감으로 초기 반응을 얻는 것과, 반복 제작/저장/결제 수요는 서로 다르다. 여성 타깃을 지금 버릴 근거도 없다. - -외부 맥락: Pew의 2025 미국 성인 조사에서 Instagram 이용률은 여성55%/남성44%, Reddit과 X는 남성이 더 높다. 이는 채널 선택 참고이며 이 효과의 수요나 해외 전체 성향을 입증하지 않는다. 출처: https://www.pewresearch.org/internet/2025/11/20/americans-social-media-use-2025/ - -작은 검증을 권한다. 같은 언어·채널 안에서 같은 결과 영상을 쓰고 ‘귀여운 내 반려동물 결과 만들기’와 ‘직접 움직여 보는 유리 효과’ 메시지만 나눈다. 채널 간 성과 차이를 성별 효과로 해석하지 않는다. 클릭보다 자기 사진 선택→만족스러운 결과 완성→두 번째 사진 시도, 향후 저장/공유 완료와 재방문을 본다. 실제 내보내기 구현 전엔 내보내기 완료율을 측정했다고 주장할 수 없다. 현재 판단은 영어권 테스트는 열되, 남성 전용 브랜드로 좁히지 않는 것이다. - -## 보존물 - -- default-desktop.png: 기본 시각값 재적용 정면. Camera Offset/.감도는 추천값이나 정면 정지에는 영향 없음. -- recommended-desktop.png: 권장 후보 데스크톱. -- recommended-mobile.png: 같은 후보 모바일. - -모든 이미지와 샘플 사용은 로컬 QA이며 게시하지 않았다. 실행은 npm.cmd run dev, 브라우저 localhost:5173에서 샘플 로드 후 표의 값 적용. 개선 우선순위는 일반 사진 첫 결과/구도 조절 → 셀 내부 굴절 질감 → 저장/공유 완료 흐름 → 타깃 실험이다. diff --git a/docs/qa-ai-depth-770-2026-10-06/dog1-depth-518.png b/docs/qa-ai-depth-770-2026-10-06/dog1-depth-518.png deleted file mode 100644 index e7ab75c..0000000 Binary files a/docs/qa-ai-depth-770-2026-10-06/dog1-depth-518.png and /dev/null differ diff --git a/docs/qa-ai-depth-770-2026-10-06/dog1-depth-770-detail.png b/docs/qa-ai-depth-770-2026-10-06/dog1-depth-770-detail.png deleted file mode 100644 index 1fc829e..0000000 Binary files a/docs/qa-ai-depth-770-2026-10-06/dog1-depth-770-detail.png and /dev/null differ diff --git a/docs/qa-ai-depth-770-2026-10-06/dog1-depth-770.png b/docs/qa-ai-depth-770-2026-10-06/dog1-depth-770.png deleted file mode 100644 index f47b8e3..0000000 Binary files a/docs/qa-ai-depth-770-2026-10-06/dog1-depth-770.png and /dev/null differ diff --git a/docs/qa-ai-depth-770-2026-10-06/dog1-final-770.png b/docs/qa-ai-depth-770-2026-10-06/dog1-final-770.png deleted file mode 100644 index c19bff8..0000000 Binary files a/docs/qa-ai-depth-770-2026-10-06/dog1-final-770.png and /dev/null differ diff --git a/docs/qa-ai-depth-770-2026-10-06/dog1-noglass-770-drag.png b/docs/qa-ai-depth-770-2026-10-06/dog1-noglass-770-drag.png deleted file mode 100644 index 132ac98..0000000 Binary files a/docs/qa-ai-depth-770-2026-10-06/dog1-noglass-770-drag.png and /dev/null differ diff --git a/docs/qa-ai-depth-770-2026-10-06/dog1-noglass-770.png b/docs/qa-ai-depth-770-2026-10-06/dog1-noglass-770.png deleted file mode 100644 index 76c0a73..0000000 Binary files a/docs/qa-ai-depth-770-2026-10-06/dog1-noglass-770.png and /dev/null differ diff --git a/docs/qa-ai-depth-770-2026-10-06/original-settings.json b/docs/qa-ai-depth-770-2026-10-06/original-settings.json deleted file mode 100644 index e1787c1..0000000 --- a/docs/qa-ai-depth-770-2026-10-06/original-settings.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "camera-offset": "0.9", - "curvature": "1", - "depth-scale": "0.4", - "effect": "mosaic", - "gloss-strength": "0.35", - "grid-size": "20", - "light-x": "2", - "light-y": "0.8", - "mosaic-style": "2", - "photo-glass-distance": "0", - "photo-pan-x": "0", - "photo-pan-y": "0", - "photo-zoom": "1", - "sensitivity": "0.2", - "test-photo": "dog1", - "view-mode": "depth" -} \ No newline at end of file diff --git a/docs/qa-ai-depth-770-2026-10-06/preprocessor-check.json b/docs/qa-ai-depth-770-2026-10-06/preprocessor-check.json deleted file mode 100644 index 02e8b6e..0000000 --- a/docs/qa-ai-depth-770-2026-10-06/preprocessor-check.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "sourceSize": [ - 400, - 500 - ], - "snapshotSize": [ - 400, - 500 - ], - "results": [ - { - "nominalSize": 518, - "tensorDimensions": [ - 1, - 3, - 518, - 420 - ] - }, - { - "nominalSize": 770, - "tensorDimensions": [ - 1, - 3, - 770, - 616 - ] - } - ] -} \ No newline at end of file diff --git a/docs/qa-ai-depth-770-2026-10-06/report.md b/docs/qa-ai-depth-770-2026-10-06/report.md deleted file mode 100644 index b04d188..0000000 --- a/docs/qa-ai-depth-770-2026-10-06/report.md +++ /dev/null @@ -1,41 +0,0 @@ -# Small 모델의 770 입력 추론 - -2026-10-06 사용자 요청에 따라 기본 모델을 바꾸지 않고 추론 전처리 기준 크기를 518에서 770으로 높였다. - -## 변경 - -- `src/constants/depth.ts`: `AI_DEPTH.inputSize = 770`. -- `src/depth/aiDepth.worker.ts`: 모델을 로드한 뒤 `processor.image_processor.size`를 `{ width: 770, height: 770 }`으로 지정한다. 새 ONNX 모델이나 의존성을 추가하지 않았다. WebGPU와 WASM 재시도는 같은 로더를 사용하므로 모두 이 설정을 적용한다. -- `src/main.ts`: AI 완료 표시에 `입력 770`을 표시한다. -- 기존 모델 설정의 종횡비 유지와 14배수 정렬은 보존한다. 긴 변 1024의 사진 스냅샷 상한, 8비트 정규화, 128×128 Depth mesh, 거리·광학·사진 구도 처리도 유지한다. - -## 검증 - -TypeScript와 Vite 빌드 통과: `npm.cmd run build -- --outDir test-results/ai-depth-770-build`. 기존 큰 번들 경고는 유지됐다. 검증용 빌드 출력은 제거했다. - -설치된 Transformers.js의 같은 ImageProcessor 설정으로 dog1을 전처리했다(`preprocessor-check.json`). 원본과 스냅샷은 모두 **400×500**이며 입력 텐서는 다음과 같다. DPTImageProcessor는 이 ImageProcessor를 상속하며 별도의 크기 처리 재정의가 없다. - -| 기준 크기 | 입력 텐서 [batch, channel, height, width] | -| --- | --- | -| 518 | [1, 3, 518, 420] | -| 770 | [1, 3, 770, 616] | - -이는 출력 그림을 확대하기만 하는 설정 변경이 아니라 모델에 들어가는 실제 전처리 텐서를 키우는 변경이다. 최종 DepthMap은 pipeline에서 사진 스냅샷 크기로 다시 보간하므로 이 사진에서는 여전히 400×500이다. - -Windows Codex in-app browser에서 기존 518의 dog1 Depth 화면을 시점 초기화 후 저장했다. 변경 후 같은 사진을 다시 불러와 자동 770 추론이 완료되는 것을 확인했다. 표시: `AI 추정 · Depth Anything V2 Small · 입력 770`, 상태: `자동 AI 추정 depth를 적용했습니다.`. console error는 없었다. - -Depth 출력 후 No Glass 사진과 드래그 출력, Final 유리 출력을 확인하고 원래 Depth 보기로 돌아왔다. 현재 비교는 같은 화면 크기와 정면 시점에서 수행했다. 770 결과에서 머리·몸·발의 Depth 형상과 외곽이 달라지지만 얼굴의 미세한 굴곡은 여전히 부드럽다. 고해상도 입력이 눈·코·털의 정확한 3D 구조를 복원했다고 판정하지 않았다. - -기존 설정은 `original-settings.json`과 `restored-settings.json`에서 모두 일치한다: dog1 / Depth / Grid 20 / 굴곡 +1 / 광택 0.35 / 거리 0% / Camera Offset 0.9 / Depth Scale 0.4 / 조명 X 2, Y 0.8 / sensitivity 0.2 / 확대 1, 팬 0/0. 비교를 위해 실제 드래그 시점은 초기화했다. - -화면: `dog1-depth-518.png`, `dog1-depth-770.png`, `dog1-depth-770-detail.png`, `dog1-noglass-770.png`, `dog1-noglass-770-drag.png`, `dog1-final-770.png`. - -## 한계와 실행 - -현재 dog1 원본은 400×500이므로 추론 입력을 높여도 원본에 없는 세부 정보가 생기지는 않는다. 모델은 단안 상대 깊이를 추정한다. 기존 8비트 저장과 128×128 표면 해상도는 별개의 제한이며 이번 요청에서 함께 변경하지 않았다. - -실제 770 추론 성공은 확인했으나 WebGPU/WASM 경로를 강제로 나눠 실행하거나 기기별 처리 시간·메모리를 계측하지 않았다. 물리 모바일 기기의 추론 성능도 측정하지 않았다. 518과 770의 속도 차이에 대한 수치 주장은 하지 않는다. - -프로젝트 루트에서 `npm.cmd run dev -- --host 127.0.0.1 --port 5174`로 실행한다. 현재 `http://127.0.0.1:5174/`에는 770 추론을 마친 dog1의 Depth 보기를 남겨두었다. - -![770 입력으로 생성한 Depth](dog1-depth-770-detail.png) diff --git a/docs/qa-ai-depth-770-2026-10-06/restored-settings.json b/docs/qa-ai-depth-770-2026-10-06/restored-settings.json deleted file mode 100644 index e1787c1..0000000 --- a/docs/qa-ai-depth-770-2026-10-06/restored-settings.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "camera-offset": "0.9", - "curvature": "1", - "depth-scale": "0.4", - "effect": "mosaic", - "gloss-strength": "0.35", - "grid-size": "20", - "light-x": "2", - "light-y": "0.8", - "mosaic-style": "2", - "photo-glass-distance": "0", - "photo-pan-x": "0", - "photo-pan-y": "0", - "photo-zoom": "1", - "sensitivity": "0.2", - "test-photo": "dog1", - "view-mode": "depth" -} \ No newline at end of file diff --git a/docs/qa-ai-depth-base-2026-10-06/after-reinference.json b/docs/qa-ai-depth-base-2026-10-06/after-reinference.json deleted file mode 100644 index 772b58d..0000000 --- a/docs/qa-ai-depth-base-2026-10-06/after-reinference.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "distance": "50", - "panX": "0", - "panY": "0", - "point": "픽셀 (209, 236)\n모델 상대 깊이: 1.000000\n8비트 깊이: 1.000000\n최대 표면 간격: 0.3200\n선택 지점 간격: 0.3200\n뒤로 물러난 양: 0.0000", - "provenance": "AI 추정 · Depth Anything V2 Base · 입력 770 (상대 깊이, 0=뒤 · 1=앞)", - "zoom": "1" -} \ No newline at end of file diff --git a/docs/qa-ai-depth-base-2026-10-06/base-final-mid.png b/docs/qa-ai-depth-base-2026-10-06/base-final-mid.png deleted file mode 100644 index a8f08e3..0000000 Binary files a/docs/qa-ai-depth-base-2026-10-06/base-final-mid.png and /dev/null differ diff --git a/docs/qa-ai-depth-base-2026-10-06/base-inspection.png b/docs/qa-ai-depth-base-2026-10-06/base-inspection.png deleted file mode 100644 index 9cc7380..0000000 Binary files a/docs/qa-ai-depth-base-2026-10-06/base-inspection.png and /dev/null differ diff --git a/docs/qa-ai-depth-base-2026-10-06/base-noglass-far.png b/docs/qa-ai-depth-base-2026-10-06/base-noglass-far.png deleted file mode 100644 index 881f6ef..0000000 Binary files a/docs/qa-ai-depth-base-2026-10-06/base-noglass-far.png and /dev/null differ diff --git a/docs/qa-ai-depth-base-2026-10-06/base-noglass-near-drag.png b/docs/qa-ai-depth-base-2026-10-06/base-noglass-near-drag.png deleted file mode 100644 index 10c1496..0000000 Binary files a/docs/qa-ai-depth-base-2026-10-06/base-noglass-near-drag.png and /dev/null differ diff --git a/docs/qa-ai-depth-base-2026-10-06/base-noglass-near.png b/docs/qa-ai-depth-base-2026-10-06/base-noglass-near.png deleted file mode 100644 index 3526bc2..0000000 Binary files a/docs/qa-ai-depth-base-2026-10-06/base-noglass-near.png and /dev/null differ diff --git a/docs/qa-ai-depth-base-2026-10-06/base-result.png b/docs/qa-ai-depth-base-2026-10-06/base-result.png deleted file mode 100644 index 989b2c4..0000000 Binary files a/docs/qa-ai-depth-base-2026-10-06/base-result.png and /dev/null differ diff --git a/docs/qa-ai-depth-base-2026-10-06/base-values.json b/docs/qa-ai-depth-base-2026-10-06/base-values.json deleted file mode 100644 index ff82c62..0000000 --- a/docs/qa-ai-depth-base-2026-10-06/base-values.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "summary": "400×500 · 최대 depth=1.00000\n모델 최대 1: 1px (0.0005%)\n8비트 depth=1: 26px (0.0130%)\ndepth≥0.99: 126px (0.0630%)\n최대 위치: (209, 236)", - "samples": [ - { - "name": "nose-tip", - "x": 207, - "y": 239, - "text": "픽셀 (207, 239)\n모델 상대 깊이: 0.996319\n8비트 깊이: 0.996078\n최대 표면 간격: 0.0400\n선택 지점 간격: 0.0410\n뒤로 물러난 양: 0.0010" - }, - { - "name": "nose-upper", - "x": 210, - "y": 235, - "text": "픽셀 (210, 235)\n모델 상대 깊이: 0.999133\n8비트 깊이: 1.000000\n최대 표면 간격: 0.0400\n선택 지점 간격: 0.0400\n뒤로 물러난 양: 0.0000" - }, - { - "name": "forehead", - "x": 210, - "y": 175, - "text": "픽셀 (210, 175)\n모델 상대 깊이: 0.958692\n8비트 깊이: 0.956863\n최대 표면 간격: 0.0400\n선택 지점 간격: 0.0508\n뒤로 물러난 양: 0.0108" - }, - { - "name": "left-eye", - "x": 181, - "y": 210, - "text": "픽셀 (181, 210)\n모델 상대 깊이: 0.854450\n8비트 깊이: 0.854902\n최대 표면 간격: 0.0400\n선택 지점 간격: 0.0763\n뒤로 물러난 양: 0.0363" - }, - { - "name": "right-eye", - "x": 236, - "y": 218, - "text": "픽셀 (236, 218)\n모델 상대 깊이: 0.847300\n8비트 깊이: 0.847059\n최대 표면 간격: 0.0400\n선택 지점 간격: 0.0782\n뒤로 물러난 양: 0.0382" - }, - { - "name": "muzzle", - "x": 190, - "y": 240, - "text": "픽셀 (190, 240)\n모델 상대 깊이: 0.963951\n8비트 깊이: 0.964706\n최대 표면 간격: 0.0400\n선택 지점 간격: 0.0488\n뒤로 물러난 양: 0.0088" - }, - { - "name": "tongue", - "x": 204, - "y": 267, - "text": "픽셀 (204, 267)\n모델 상대 깊이: 0.881356\n8비트 깊이: 0.882353\n최대 표면 간격: 0.0400\n선택 지점 간격: 0.0694\n뒤로 물러난 양: 0.0294" - }, - { - "name": "body", - "x": 270, - "y": 320, - "text": "픽셀 (270, 320)\n모델 상대 깊이: 0.616040\n8비트 깊이: 0.615686\n최대 표면 간격: 0.0400\n선택 지점 간격: 0.1361\n뒤로 물러난 양: 0.0961" - }, - { - "name": "front-paw", - "x": 183, - "y": 414, - "text": "픽셀 (183, 414)\n모델 상대 깊이: 0.506277\n8비트 깊이: 0.505882\n최대 표면 간격: 0.0400\n선택 지점 간격: 0.1635\n뒤로 물러난 양: 0.1235" - } - ] -} \ No newline at end of file diff --git a/docs/qa-ai-depth-base-2026-10-06/distance-values.json b/docs/qa-ai-depth-base-2026-10-06/distance-values.json deleted file mode 100644 index d7cc4e7..0000000 --- a/docs/qa-ai-depth-base-2026-10-06/distance-values.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "nearPoint": "픽셀 (209, 236)\n모델 상대 깊이: 1.000000\n8비트 깊이: 1.000000\n최대 표면 간격: 0.0400\n선택 지점 간격: 0.0400\n뒤로 물러난 양: 0.0000", - "midPoint": "픽셀 (209, 236)\n모델 상대 깊이: 1.000000\n8비트 깊이: 1.000000\n최대 표면 간격: 0.3200\n선택 지점 간격: 0.3200\n뒤로 물러난 양: 0.0000", - "farPoint": "픽셀 (209, 236)\n모델 상대 깊이: 1.000000\n8비트 깊이: 1.000000\n최대 표면 간격: 0.6000\n선택 지점 간격: 0.6000\n뒤로 물러난 양: 0.0000", - "farFace": "픽셀 (210, 175)\n모델 상대 깊이: 0.958692\n8비트 깊이: 0.956863\n최대 표면 간격: 0.6000\n선택 지점 간격: 0.6108\n뒤로 물러난 양: 0.0108" -} \ No newline at end of file diff --git a/docs/qa-ai-depth-base-2026-10-06/mobile-inspection.png b/docs/qa-ai-depth-base-2026-10-06/mobile-inspection.png deleted file mode 100644 index e9de032..0000000 Binary files a/docs/qa-ai-depth-base-2026-10-06/mobile-inspection.png and /dev/null differ diff --git a/docs/qa-ai-depth-base-2026-10-06/report.md b/docs/qa-ai-depth-base-2026-10-06/report.md deleted file mode 100644 index fe92545..0000000 --- a/docs/qa-ai-depth-base-2026-10-06/report.md +++ /dev/null @@ -1,74 +0,0 @@ -# V2 Base 770 / 최대 깊이 표면 기준 거리 검증 - -2026-10-06. 요청: Base로 depth=1 영역이 앞쪽 부위를 명확하게 추정하는지 확인하고, 그 최대 깊이 표면을 유리와 피사체 거리 기준으로 사용한다. - -## 구현 - -- `개발 비교 → AI 깊이 모델`에서 Small/Base 선택 후 기존 `AI 깊이 생성` 버튼으로 추론한다. 두 모델 모두 입력 770, 종횡비/14 배수 정렬, 스냅샷 긴 변 상한 1024를 공유한다. 기본값 Small, Base는 비상업적 테스트 옵션이다. 새 의존성 없음. -- 단일 worker estimator를 유지하고 다른 모델을 선택해 추론할 때 이전 estimator를 dispose한다. 기존 WebGPU 우선/WASM fallback을 유지한다. -- 기존 8비트 텍스처와 128×128 Depth mesh를 유지한다. 양자화 이전 정규화 Float32 값은 진단용으로 함께 전달한다. -- `최대 깊이 영역 확인`은 원본 사진 위에 Float32 최대 1(분홍), 8비트 255/255(청록), Float32 ≥0.99(노랑)를 표시한다. 픽셀 수/비율/첫 최대 좌표와 선택 지점 값을 표시한다. 사진 클릭 또는 X/Y 숫자 입력으로 검사한다. -- 기존 `contentBaseZ`/`applyFraming`을 사용한다. 거리 도움말을 최대 depth 표면 기준으로 명시하고 진단에 최대 표면/선택 지점 간격을 추가했다. RGB/Depth 공통 변환, 굴절 기준 평면, 프레임 가림을 함께 갱신한다. 자동 확대/팬 변경 없음. - -## 같은 사진의 실제 추론 결과 - -원본 `public/assets/qa/dog1.jpeg`는 400×500이다. 입력 770은 이전 전처리 검증에서 실제 텐서 `[1,3,770,616]`으로 확인했으며 이번에도 같은 전처리 설정을 사용한다. 반환 깊이는 스냅샷 400×500으로 보간된다. 좌표는 좌상단 원점, X 오른쪽/Y 아래쪽이다. 지점은 원본을 보고 수동으로 고른 비교 좌표이며 모델의 의미적 코/눈 검출 결과가 아니다. - -| 항목 | Small 770 | Base 770 | -|---|---:|---:| -| 정규화 Float32 최대=1 | 1px | 1px | -| 8비트 depth=1 | 24px | 26px | -| 정규화 depth≥0.99 | 153px | 126px | -| 최대 좌표 | (210,235) | (209,236) | -| 코 중앙 부근 (207,239) | 0.992057 | 0.996319 | -| 코 위쪽 (210,235) | 1.000000 | 0.999133 | -| 이마 (210,175) | 0.942435 | 0.958692 | -| 왼눈 (181,210) | 0.845839 | 0.854450 | -| 오른눈 (236,218) | 0.834167 | 0.847300 | -| 주둥이 (190,240) | 0.958051 | 0.963951 | -| 혀 (204,267) | 0.909496 | 0.881356 | -| 몸 (270,320) | 0.579217 | 0.616040 | -| 앞발 (183,414) | 0.481518 | 0.506277 | - -두 모델 모두 최대 좌표는 원본 사진의 코 주변에 위치한다. Base의 ≥0.99 영역은 더 작지만 8비트 최대 영역은 약간 더 크다. 이것만으로 Base가 실제 형상을 더 정확하게 복원했다고 판정할 수 없다. 코와 이마/눈 사이의 값 차이는 이미 Small에도 존재했고, 흑백 화면에서는 모두 밝아 읽기 어려웠다. Base Depth 화면도 부드러운 형태이며 얼굴 내부 굴곡이 크게 개선되었다고 단정하지 않는다. - -각 사진/모델별 정규화 기준이 다르므로 표의 수치를 모델 간 실제 거리 차이처럼 해석하지 않는다. Float32 최대 1은 비상수 예측을 min/max 정규화하면 항상 만들어진다. 이번 코 위치 결과는 한 사진의 검증이며 다른 사진의 최대값이 항상 코라는 보장은 없다. 정규화는 전체 사진을 대상으로 하고 피사체 마스크나 이상값 제거는 하지 않는다. - -수치 원본: [Small](small-values.json), [Base](base-values.json). 동일 뷰/설정의 화면: [Small](small-inspection.png), [Base](base-inspection.png). 최대 영역은 진단 색상만 적용하며 실제 깊이값을 강조/변경하지 않는다. - -## 거리 기준 - -``` -baseZ = glassZ - requestedGap - (maxDepth - depthBias) * depthScale -surfaceZ(pixel) = baseZ + (byteDepth(pixel) - depthBias) * depthScale -gap(pixel) = requestedGap + (maxDepth - byteDepth(pixel)) * depthScale -``` - -Base 최대 픽셀 (209,236)의 byteDepth는 1. depthScale=0.25에서 검사: - -| UI 거리 | 최대 표면 간격 | 이마 간격 | 이마의 상대적 후퇴 | -|---|---:|---:|---:| -| 0% | 0.0400 | 0.0508 | 0.0108 | -| 50% | 0.3200 | 0.3308 (같은 식) | 0.0108 | -| 100% | 0.6000 | 0.6108 | 0.0108 | - -최대 픽셀의 0/50/100%, 이마 100%는 실제 UI 진단에서 읽었다. 이마 0%는 동일 위치 Base 수치 JSON에 기록돼 있다. 이마 50%는 수식 계산값이다. 거리와 깊이 차이는 장면 단위이며 cm가 아니다. `≥0.99`는 영역 가시화용이고 배치 기준은 항상 최대값이므로 가까운 표면의 관통을 막는다. - -진단 간격은 텍스처 픽셀의 계산값이다. 128×128 mesh의 버텍스 샘플/삼각형 보간이 최대 픽셀을 정확히 통과하지 않을 수 있으므로 실제 mesh 최소 간격은 요청값보다 클 수 있다. 선형 텍스처 보간과 mesh 보간이 원본 최대값보다 더 앞선 값을 생성하지는 않으므로 전체 표면 기준 안전 여유는 유지된다. - -[거리 수치](distance-values.json). No Glass [근접](base-noglass-near.png), [드래그](base-noglass-near-drag.png), [먼 거리](base-noglass-far.png). No Glass에서 RGB와 깊이 형상 및 시점에 따른 변화가 렌더링되는 것을 확인한 뒤 [Final 50%](base-final-mid.png)를 확인했다. 픽셀별 GPU projected 좌표/실제 측정 3D 정답과의 오차는 이번 테스트에서 측정하지 않았다. - -Base 재추론은 같은 최대 좌표/픽셀 수를 반환했고 거리 50%, 수동 zoom=1/pan=0/0을 유지했다. [재추론 후 설정](after-reinference.json). - -## 실행 검증과 한계 - -- `npm.cmd run build -- --outDir test-results/base-depth-build`: TypeScript/Vite 빌드 통과. 기존 큰 chunk 경고만 있었다. 생성한 임시 빌드 결과는 정리했다. -- `node --experimental-strip-types scripts/test-depth-refraction.mjs`: 통과. -- `node --experimental-strip-types scripts/test-window-reveal-coverage.mjs`: 통과. 두 거리/세 깊이 스케일/두 종횡비/17 시점의 프레임 가림 검사 포함. -- Node 22.13에서 옵션 없이 테스트를 실행한 첫 시도는 `.ts` 확장자 로딩 오류였다. TypeScript strip 옵션으로 재실행해 통과했다. -- 실제 브라우저에서 Small/Base 모두 추론 완료. Base는 첫 다운로드 후 같은 estimator로 재추론도 확인했다. 콘솔 error 0건. 강제 WASM-only/실제 모바일 GPU 추론 시간/메모리는 측정하지 않았다. -- 모바일 390×844에서 문서 너비 375, 가로 넘침 없음. [모바일 진단](mobile-inspection.png). 임시 viewport는 원복했다. -- 기본 뷰포트의 미리보기는 Base 770, Depth, 거리 0%, 최대 지점 선택 상태로 남겼다. [최종 화면](base-result.png). -- 원본이 400×500이므로 770 입력이 원본에 없는 디테일을 보장하지 않는다. 더 나은 모델/더 높은 입력에서도 코의 실제 돌출 길이 복원을 보장할 수 없다. - -후속 판단: 현재 최대 깊이 표면 기준 거리 방식은 사용자 의도와 일치한다. 이 사진에서는 Base와 Small 모두 코 주변이 최대이므로 Base 교체만으로 거리 기준 문제가 해결됐다고 설명하지 않는다. 향후 여러 사진에서 최대 위치가 피사체가 아닌 배경/노이즈로 이동하는지 확인한 뒤 피사체 범위 제한이나 이상값 처리를 별도로 판단한다. diff --git a/docs/qa-ai-depth-base-2026-10-06/small-inspection.png b/docs/qa-ai-depth-base-2026-10-06/small-inspection.png deleted file mode 100644 index 5cdd3c3..0000000 Binary files a/docs/qa-ai-depth-base-2026-10-06/small-inspection.png and /dev/null differ diff --git a/docs/qa-ai-depth-base-2026-10-06/small-values.json b/docs/qa-ai-depth-base-2026-10-06/small-values.json deleted file mode 100644 index 91a4ba2..0000000 --- a/docs/qa-ai-depth-base-2026-10-06/small-values.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "summary": "400×500 · 최대 depth=1.00000\n모델 최대 1: 1px (0.0005%)\n8비트 depth=1: 24px (0.0120%)\ndepth≥0.99: 153px (0.0765%)\n최대 위치: (210, 235)", - "samples": [ - { - "name": "nose-tip", - "x": 207, - "y": 239, - "text": "픽셀 (207, 239)\n모델 상대 깊이: 0.992057\n8비트 깊이: 0.992157\n최대 표면 간격: 0.0400\n선택 지점 간격: 0.0420\n뒤로 물러난 양: 0.0020" - }, - { - "name": "nose-upper", - "x": 210, - "y": 235, - "text": "픽셀 (210, 235)\n모델 상대 깊이: 1.000000\n8비트 깊이: 1.000000\n최대 표면 간격: 0.0400\n선택 지점 간격: 0.0400\n뒤로 물러난 양: 0.0000" - }, - { - "name": "forehead", - "x": 210, - "y": 175, - "text": "픽셀 (210, 175)\n모델 상대 깊이: 0.942435\n8비트 깊이: 0.941176\n최대 표면 간격: 0.0400\n선택 지점 간격: 0.0547\n뒤로 물러난 양: 0.0147" - }, - { - "name": "left-eye", - "x": 181, - "y": 210, - "text": "픽셀 (181, 210)\n모델 상대 깊이: 0.845839\n8비트 깊이: 0.847059\n최대 표면 간격: 0.0400\n선택 지점 간격: 0.0782\n뒤로 물러난 양: 0.0382" - }, - { - "name": "right-eye", - "x": 236, - "y": 218, - "text": "픽셀 (236, 218)\n모델 상대 깊이: 0.834167\n8비트 깊이: 0.835294\n최대 표면 간격: 0.0400\n선택 지점 간격: 0.0812\n뒤로 물러난 양: 0.0412" - }, - { - "name": "muzzle", - "x": 190, - "y": 240, - "text": "픽셀 (190, 240)\n모델 상대 깊이: 0.958051\n8비트 깊이: 0.956863\n최대 표면 간격: 0.0400\n선택 지점 간격: 0.0508\n뒤로 물러난 양: 0.0108" - }, - { - "name": "tongue", - "x": 204, - "y": 267, - "text": "픽셀 (204, 267)\n모델 상대 깊이: 0.909496\n8비트 깊이: 0.909804\n최대 표면 간격: 0.0400\n선택 지점 간격: 0.0625\n뒤로 물러난 양: 0.0225" - }, - { - "name": "body", - "x": 270, - "y": 320, - "text": "픽셀 (270, 320)\n모델 상대 깊이: 0.579217\n8비트 깊이: 0.580392\n최대 표면 간격: 0.0400\n선택 지점 간격: 0.1449\n뒤로 물러난 양: 0.1049" - }, - { - "name": "front-paw", - "x": 183, - "y": 414, - "text": "픽셀 (183, 414)\n모델 상대 깊이: 0.481518\n8비트 깊이: 0.482353\n최대 표면 간격: 0.0400\n선택 지점 간격: 0.1694\n뒤로 물러난 양: 0.1294" - } - ] -} \ No newline at end of file diff --git a/docs/qa-cell-continuity/before-mosaic.frag b/docs/qa-cell-continuity/before-mosaic.frag deleted file mode 100644 index 688ebe7..0000000 --- a/docs/qa-cell-continuity/before-mosaic.frag +++ /dev/null @@ -1,123 +0,0 @@ -uniform sampler2D uSceneTexture; -uniform mat4 uContentViewProjection,uContentInverseViewProjection; -uniform vec3 uContentCameraPosition,uLightPosition,uBackgroundColor; -uniform float uGlassZ,uGridSize,uStrength,uMosaicStyle,uCurvature,uGlossStrength; -uniform vec2 uViewOffset,uPetSize,uPaneSize; -uniform vec4 uPaneRect; -varying vec2 vUv; -vec2 projectUv(vec3 p){vec4 c=uContentViewProjection*vec4(p,1.);float w=abs(c.w)<.0001?(c.w<0.?-.0001:.0001):c.w;return c.xy/w*.5+.5;} -vec4 sampleScene(vec2 uv){return texture2D(uSceneTexture,clamp(uv,0.,1.));} -vec4 samplePane(vec2 pane){return sampleScene(projectUv(vec3((pane-.5)*uPaneSize,uGlassZ)));} -vec4 sampleCell(vec2 pane,vec2 sourceUv,float strength,vec2 blurStep){ - vec4 color=samplePane(mix(pane,sourceUv,strength))*.4; - color+=samplePane(mix(pane,sourceUv+vec2(blurStep.x,0.),strength))*.15; - color+=samplePane(mix(pane,sourceUv-vec2(blurStep.x,0.),strength))*.15; - color+=samplePane(mix(pane,sourceUv+vec2(0.,blurStep.y),strength))*.15; - color+=samplePane(mix(pane,sourceUv-vec2(0.,blurStep.y),strength))*.15; - return color; -} -float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);} -vec2 hash2(vec2 p){return vec2(hash(p),hash(p+vec2(19.19,73.73)));} -float safeZ(float z){return abs(z)<.0001?(z<0.?-.0001:.0001):z;} -vec3 bend(vec3 i,vec3 n){vec3 r=refract(i,n,.75);return length(r)<.0001?i:r;} -float softLimit(float value,float limit){return value*limit/(limit+abs(value));} -void evaluateCell(vec2 cell,vec2 local,vec2 grid,vec2 cellSize,vec2 cellDimensions,float cellWorld,float style,out vec2 affineUv,out mat2 transform,out vec2 curvedSlope,out vec2 facetSlope){ - vec2 random=hash2(cell),widths; - if(style>.5){ - widths=mix(vec2(.82),vec2(1.12),hash2(cell+vec2(11.4,9.8))); - }else{ - float widthSeed=hash(cell+vec2(53.1,27.4)); - if(widthSeed<.3)widths=mix(vec2(.90),vec2(1.08),hash2(cell+vec2(7.2,3.1))); - else if(widthSeed<.9)widths=mix(vec2(.46),vec2(.70),hash2(cell+vec2(7.2,3.1))); - else widths=mix(vec2(1.10),vec2(1.28),hash2(cell+vec2(7.2,3.1))); - } - float angle=(random.x-.5)*.08,c=cos(angle),s=sin(angle); - transform=mat2(widths.x*c,-widths.y*s,widths.x*s,widths.y*c); - vec2 sourceCenter=(cell+.5)/grid+(random-.5)*.16*cellSize; - affineUv=sourceCenter+transform*(local*cellSize); - - // Positive height bulges toward the observer (+Z); negative height is concave. - float curvature=clamp(uCurvature,-1.,1.),excess=max(curvature-.65,0.),surfaceCurvature=curvature-(.25/.35)*excess*excess; - float height=.009*cellWorld*surfaceCurvature*mix(.92,1.08,hash(cell+vec2(41.7,17.3))); - vec2 q=clamp(2.*local,-1.,1.),q2=q*q,q3=q2*q,b=1.-q2*q2; - vec2 skew=(hash2(cell+vec2(23.8,61.2))-.5)*.28;float asym=1.+dot(skew,q); - vec2 dhdq=height*vec2(-4.*q3.x*b.y*asym+b.x*b.y*skew.x,-4.*q3.y*b.x*asym+b.x*b.y*skew.y); - vec2 grad=-2.*dhdq/cellDimensions; - curvedSlope=grad+(random-.5)*.012;facetSlope=(random-.5)*.012; -} -void main(){ - if(uStrength<=.001){gl_FragColor=sampleScene(vUv); - #include - return;} - vec4 f=uContentInverseViewProjection*vec4(vUv*2.-1.,1.,1.);float fw=abs(f.w)<.0001?(f.w<0.?-.0001:.0001):f.w;vec3 farWorld=f.xyz/fw;vec3 i=normalize(farWorld-uContentCameraPosition);float gt=(uGlassZ-uContentCameraPosition.z)/safeZ(i.z);vec3 gh=uContentCameraPosition+i*gt; - vec2 paneUv=gh.xy/uPaneSize+.5;vec2 grid=vec2(uGridSize,max(1.,uGridSize*uPaneSize.y/uPaneSize.x));vec2 gridUv=paneUv*grid,cell=floor(gridUv),local=fract(gridUv)-.5,cellSize=1./grid;float style=clamp(uMosaicStyle,0.,1.),cellWorld=min(uPaneSize.x/grid.x,uPaneSize.y/grid.y); - if(paneUv.x<0.||paneUv.x>1.||paneUv.y<0.||paneUv.y>1.){gl_FragColor=vec4(uBackgroundColor,1.); - #include - return;} - vec2 cellDimensions=uPaneSize/grid; - vec2 affineUv,curvedSlope,facetSlope;mat2 transform; - evaluateCell(cell,local,grid,cellSize,cellDimensions,cellWorld,style,affineUv,transform,curvedSlope,facetSlope); - vec2 edge=.5-abs(local),neighborSign=mix(vec2(-1.),vec2(1.),step(vec2(0.),local)); - // Keep a broad shared surface-normal transition; color footprints are blended separately. - vec2 blendAxis=1.-smoothstep(vec2(-.16),vec2(.16),edge); - vec2 weights=blendAxis; - vec2 centerAffine=affineUv;mat2 centerTransform=transform; - vec2 xAffine=vec2(0.),yAffine=vec2(0.),diagonalAffine=vec2(0.); - mat2 xTransform=mat2(0.),yTransform=mat2(0.),diagonalTransform=mat2(0.); - float xSplitWeight=weights.x*(1.-weights.y),ySplitWeight=(1.-weights.x)*weights.y; - float diagonalSplitWeight=weights.x*weights.y,centerSplitWeight=(1.-weights.x)*(1.-weights.y); - vec2 colorAxis=1.-smoothstep(vec2(-.06),vec2(.06),edge); - float colorXWeight=colorAxis.x*(1.-colorAxis.y),colorYWeight=(1.-colorAxis.x)*colorAxis.y; - float colorDiagonalWeight=colorAxis.x*colorAxis.y,colorCenterWeight=(1.-colorAxis.x)*(1.-colorAxis.y); - if(weights.x>0.||weights.y>0.){ - vec2 neighborAffine,neighborCurved,neighborFacet;mat2 neighborTransform; - vec2 xWeight=vec2(xSplitWeight,0.); - vec2 yWeight=vec2(0.,ySplitWeight); - affineUv*=centerSplitWeight;transform*=centerSplitWeight;curvedSlope*=centerSplitWeight;facetSlope*=centerSplitWeight; - if(xWeight.x>0.){ - vec2 offset=vec2(neighborSign.x,0.); - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - xAffine=neighborAffine;xTransform=neighborTransform; - affineUv+=neighborAffine*xWeight.x;transform+=neighborTransform*xWeight.x;curvedSlope+=neighborCurved*xWeight.x;facetSlope+=neighborFacet*xWeight.x; - } - if(yWeight.y>0.){ - vec2 offset=vec2(0.,neighborSign.y); - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - yAffine=neighborAffine;yTransform=neighborTransform; - affineUv+=neighborAffine*yWeight.y;transform+=neighborTransform*yWeight.y;curvedSlope+=neighborCurved*yWeight.y;facetSlope+=neighborFacet*yWeight.y; - } - if(diagonalSplitWeight>0.){ - vec2 offset=neighborSign; - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - diagonalAffine=neighborAffine;diagonalTransform=neighborTransform; - affineUv+=neighborAffine*diagonalSplitWeight;transform+=neighborTransform*diagonalSplitWeight;curvedSlope+=neighborCurved*diagonalSplitWeight;facetSlope+=neighborFacet*diagonalSplitWeight; - } - } - vec3 nCurved=normalize(vec3(curvedSlope,1.)),nFacet=normalize(vec3(facetSlope,1.)); - vec3 straightHit=gh+i*(-gh.z/safeZ(i.z));vec3 facetRay=bend(i,nFacet),curvedRay=bend(i,nCurved);vec3 facetHit=gh+facetRay*(-gh.z/safeZ(facetRay.z)),curvedHit=gh+curvedRay*(-gh.z/safeZ(curvedRay.z));vec2 base=facetHit.xy-straightHit.xy,curve=curvedHit.xy-facetHit.xy;vec2 worldDelta=vec2(softLimit(base.x,cellWorld*.08),softLimit(base.y,cellWorld*.08));vec2 d=curve/cellWorld;worldDelta+=vec2(.3*d.x/(.3+abs(d.x)),.3*d.y/(.3+abs(d.y)))*cellWorld; - vec2 sampleUv=affineUv+transform*(worldDelta/uPaneSize); - float edgeDistance=min(min(paneUv.x,paneUv.y),min(1.-paneUv.x,1.-paneUv.y));float edgeWeight=smoothstep(0.,max(cellSize.x,cellSize.y)*.75,edgeDistance);float strength=clamp(uStrength,0.,1.)*edgeWeight;vec2 blurStep=cellSize*mix(.006,.012,hash(cell+vec2(5.))); - vec4 color; - // The .06-.16 band must retain the independent center transform to avoid reintroducing UV compression. - if(style<=.5&&(weights.x>0.||weights.y>0.)){ - color=vec4(0.); - if(colorCenterWeight>0.)color+=sampleCell(paneUv,centerAffine+centerTransform*(worldDelta/uPaneSize),strength,blurStep)*colorCenterWeight; - if(colorXWeight>0.){ - vec2 xBlurStep=cellSize*mix(.006,.012,hash(cell+vec2(neighborSign.x,0.)+vec2(5.))); - color+=sampleCell(paneUv,xAffine+xTransform*(worldDelta/uPaneSize),strength,xBlurStep)*colorXWeight; - } - if(colorYWeight>0.){ - vec2 yBlurStep=cellSize*mix(.006,.012,hash(cell+vec2(0.,neighborSign.y)+vec2(5.))); - color+=sampleCell(paneUv,yAffine+yTransform*(worldDelta/uPaneSize),strength,yBlurStep)*colorYWeight; - } - if(colorDiagonalWeight>0.){ - vec2 diagonalBlurStep=cellSize*mix(.006,.012,hash(cell+neighborSign+vec2(5.))); - color+=sampleCell(paneUv,diagonalAffine+diagonalTransform*(worldDelta/uPaneSize),strength,diagonalBlurStep)*colorDiagonalWeight; - } - }else{ - color=sampleCell(paneUv,sampleUv,strength,blurStep); - } - color.a=1.; - vec3 v=normalize(uContentCameraPosition-gh),reflected=reflect(-v,nCurved); float lightT=(uLightPosition.z-gh.z)/safeZ(reflected.z); vec2 lightHit=gh.xy+reflected.xy*lightT; vec2 halfSize=vec2(.32,.42)*min(uPaneSize.x,uPaneSize.y); vec2 windowCoord=abs(lightHit-uLightPosition.xy)/halfSize; vec2 windowMask=1.-smoothstep(vec2(.45),vec2(1.15),windowCoord); float spec=windowMask.x*windowMask.y*step(.0001,reflected.z)*step(0.,lightT); float gloss=spec*clamp(uGlossStrength,0.,1.)*.12*edgeWeight*clamp(uStrength,0.,1.); color.rgb=mix(color.rgb,vec3(1.),gloss); gl_FragColor=color; - #include -} diff --git a/docs/qa-cell-continuity/cap18-mosaic.frag b/docs/qa-cell-continuity/cap18-mosaic.frag deleted file mode 100644 index d25b9ee..0000000 --- a/docs/qa-cell-continuity/cap18-mosaic.frag +++ /dev/null @@ -1,131 +0,0 @@ -uniform sampler2D uSceneTexture; -uniform mat4 uContentViewProjection,uContentInverseViewProjection; -uniform vec3 uContentCameraPosition,uLightPosition,uBackgroundColor; -uniform float uGlassZ,uGridSize,uStrength,uMosaicStyle,uCurvature,uGlossStrength; -uniform vec2 uViewOffset,uPetSize,uPaneSize; -uniform vec4 uPaneRect; -varying vec2 vUv; -vec2 projectUv(vec3 p){vec4 c=uContentViewProjection*vec4(p,1.);float w=abs(c.w)<.0001?(c.w<0.?-.0001:.0001):c.w;return c.xy/w*.5+.5;} -vec4 sampleScene(vec2 uv){return texture2D(uSceneTexture,clamp(uv,0.,1.));} -vec4 samplePane(vec2 pane){return sampleScene(projectUv(vec3((pane-.5)*uPaneSize,uGlassZ)));} -vec4 sampleCell(vec2 pane,vec2 sourceUv,float strength,vec2 blurStep,vec2 cellSize){ - vec2 center=mix(pane,sourceUv,strength); - // Limit Mosaic shifts to reduce missing strips at cell edges. - if(uMosaicStyle<=.5){ - vec2 d=(center-pane)/cellSize; - vec2 dSafe=d/sqrt(vec2(1.)+(d/.18)*(d/.18)); - center=pane+dSafe*cellSize; - } - vec2 blurOffset=strength*blurStep; - vec4 color=samplePane(center)*.4; - color+=samplePane(center+vec2(blurOffset.x,0.))*.15; - color+=samplePane(center-vec2(blurOffset.x,0.))*.15; - color+=samplePane(center+vec2(0.,blurOffset.y))*.15; - color+=samplePane(center-vec2(0.,blurOffset.y))*.15; - return color; -} -float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);} -vec2 hash2(vec2 p){return vec2(hash(p),hash(p+vec2(19.19,73.73)));} -float safeZ(float z){return abs(z)<.0001?(z<0.?-.0001:.0001):z;} -vec3 bend(vec3 i,vec3 n){vec3 r=refract(i,n,.75);return length(r)<.0001?i:r;} -float softLimit(float value,float limit){return value*limit/(limit+abs(value));} -void evaluateCell(vec2 cell,vec2 local,vec2 grid,vec2 cellSize,vec2 cellDimensions,float cellWorld,float style,out vec2 affineUv,out mat2 transform,out vec2 curvedSlope,out vec2 facetSlope){ - vec2 random=hash2(cell),widths; - if(style>.5){ - widths=mix(vec2(.82),vec2(1.12),hash2(cell+vec2(11.4,9.8))); - }else{ - float widthSeed=hash(cell+vec2(53.1,27.4)); - if(widthSeed<.3)widths=mix(vec2(.90),vec2(1.08),hash2(cell+vec2(7.2,3.1))); - else if(widthSeed<.9)widths=mix(vec2(.46),vec2(.70),hash2(cell+vec2(7.2,3.1))); - else widths=mix(vec2(1.10),vec2(1.28),hash2(cell+vec2(7.2,3.1))); - } - float angle=(random.x-.5)*.08,c=cos(angle),s=sin(angle); - transform=mat2(widths.x*c,-widths.y*s,widths.x*s,widths.y*c); - vec2 sourceCenter=(cell+.5)/grid+(random-.5)*.16*cellSize; - affineUv=sourceCenter+transform*(local*cellSize); - - // Positive height bulges toward the observer (+Z); negative height is concave. - float curvature=clamp(uCurvature,-1.,1.),excess=max(curvature-.65,0.),surfaceCurvature=curvature-(.25/.35)*excess*excess; - float height=.009*cellWorld*surfaceCurvature*mix(.92,1.08,hash(cell+vec2(41.7,17.3))); - vec2 q=clamp(2.*local,-1.,1.),q2=q*q,q3=q2*q,b=1.-q2*q2; - vec2 skew=(hash2(cell+vec2(23.8,61.2))-.5)*.28;float asym=1.+dot(skew,q); - vec2 dhdq=height*vec2(-4.*q3.x*b.y*asym+b.x*b.y*skew.x,-4.*q3.y*b.x*asym+b.x*b.y*skew.y); - vec2 grad=-2.*dhdq/cellDimensions; - curvedSlope=grad+(random-.5)*.012;facetSlope=(random-.5)*.012; -} -void main(){ - if(uStrength<=.001){gl_FragColor=sampleScene(vUv); - #include - return;} - vec4 f=uContentInverseViewProjection*vec4(vUv*2.-1.,1.,1.);float fw=abs(f.w)<.0001?(f.w<0.?-.0001:.0001):f.w;vec3 farWorld=f.xyz/fw;vec3 i=normalize(farWorld-uContentCameraPosition);float gt=(uGlassZ-uContentCameraPosition.z)/safeZ(i.z);vec3 gh=uContentCameraPosition+i*gt; - vec2 paneUv=gh.xy/uPaneSize+.5;vec2 grid=vec2(uGridSize,max(1.,uGridSize*uPaneSize.y/uPaneSize.x));vec2 gridUv=paneUv*grid,cell=floor(gridUv),local=fract(gridUv)-.5,cellSize=1./grid;float style=clamp(uMosaicStyle,0.,1.),cellWorld=min(uPaneSize.x/grid.x,uPaneSize.y/grid.y); - if(paneUv.x<0.||paneUv.x>1.||paneUv.y<0.||paneUv.y>1.){gl_FragColor=vec4(uBackgroundColor,1.); - #include - return;} - vec2 cellDimensions=uPaneSize/grid; - vec2 affineUv,curvedSlope,facetSlope;mat2 transform; - evaluateCell(cell,local,grid,cellSize,cellDimensions,cellWorld,style,affineUv,transform,curvedSlope,facetSlope); - vec2 edge=.5-abs(local),neighborSign=mix(vec2(-1.),vec2(1.),step(vec2(0.),local)); - // Keep a broad shared surface-normal transition; color footprints are blended separately. - vec2 blendAxis=1.-smoothstep(vec2(-.16),vec2(.16),edge); - vec2 weights=blendAxis; - vec2 centerAffine=affineUv;mat2 centerTransform=transform; - vec2 xAffine=vec2(0.),yAffine=vec2(0.),diagonalAffine=vec2(0.); - mat2 xTransform=mat2(0.),yTransform=mat2(0.),diagonalTransform=mat2(0.); - float xSplitWeight=weights.x*(1.-weights.y),ySplitWeight=(1.-weights.x)*weights.y; - float diagonalSplitWeight=weights.x*weights.y,centerSplitWeight=(1.-weights.x)*(1.-weights.y); - vec2 colorAxis=1.-smoothstep(vec2(-.06),vec2(.06),edge); - float colorXWeight=colorAxis.x*(1.-colorAxis.y),colorYWeight=(1.-colorAxis.x)*colorAxis.y; - float colorDiagonalWeight=colorAxis.x*colorAxis.y,colorCenterWeight=(1.-colorAxis.x)*(1.-colorAxis.y); - if(weights.x>0.||weights.y>0.){ - vec2 neighborAffine,neighborCurved,neighborFacet;mat2 neighborTransform; - vec2 xWeight=vec2(xSplitWeight,0.); - vec2 yWeight=vec2(0.,ySplitWeight); - affineUv*=centerSplitWeight;transform*=centerSplitWeight;curvedSlope*=centerSplitWeight;facetSlope*=centerSplitWeight; - if(xWeight.x>0.){ - vec2 offset=vec2(neighborSign.x,0.); - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - xAffine=neighborAffine;xTransform=neighborTransform; - affineUv+=neighborAffine*xWeight.x;transform+=neighborTransform*xWeight.x;curvedSlope+=neighborCurved*xWeight.x;facetSlope+=neighborFacet*xWeight.x; - } - if(yWeight.y>0.){ - vec2 offset=vec2(0.,neighborSign.y); - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - yAffine=neighborAffine;yTransform=neighborTransform; - affineUv+=neighborAffine*yWeight.y;transform+=neighborTransform*yWeight.y;curvedSlope+=neighborCurved*yWeight.y;facetSlope+=neighborFacet*yWeight.y; - } - if(diagonalSplitWeight>0.){ - vec2 offset=neighborSign; - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - diagonalAffine=neighborAffine;diagonalTransform=neighborTransform; - affineUv+=neighborAffine*diagonalSplitWeight;transform+=neighborTransform*diagonalSplitWeight;curvedSlope+=neighborCurved*diagonalSplitWeight;facetSlope+=neighborFacet*diagonalSplitWeight; - } - } - vec3 nCurved=normalize(vec3(curvedSlope,1.)),nFacet=normalize(vec3(facetSlope,1.)); - vec3 straightHit=gh+i*(-gh.z/safeZ(i.z));vec3 facetRay=bend(i,nFacet),curvedRay=bend(i,nCurved);vec3 facetHit=gh+facetRay*(-gh.z/safeZ(facetRay.z)),curvedHit=gh+curvedRay*(-gh.z/safeZ(curvedRay.z));vec2 base=facetHit.xy-straightHit.xy,curve=curvedHit.xy-facetHit.xy;vec2 worldDelta=vec2(softLimit(base.x,cellWorld*.08),softLimit(base.y,cellWorld*.08));vec2 d=curve/cellWorld;worldDelta+=vec2(.3*d.x/(.3+abs(d.x)),.3*d.y/(.3+abs(d.y)))*cellWorld; - vec2 sampleUv=affineUv+transform*(worldDelta/uPaneSize); - float edgeDistance=min(min(paneUv.x,paneUv.y),min(1.-paneUv.x,1.-paneUv.y));float edgeWeight=smoothstep(0.,max(cellSize.x,cellSize.y)*.75,edgeDistance);float strength=clamp(uStrength,0.,1.)*edgeWeight;vec2 blurStep=cellSize*mix(.006,.012,hash(cell+vec2(5.))); - vec4 color; - // The .06-.16 band must retain the independent center transform to avoid reintroducing UV compression. - if(style<=.5&&(weights.x>0.||weights.y>0.)){ - color=vec4(0.); - if(colorCenterWeight>0.)color+=sampleCell(paneUv,centerAffine+centerTransform*(worldDelta/uPaneSize),strength,blurStep,cellSize)*colorCenterWeight; - if(colorXWeight>0.){ - vec2 xBlurStep=cellSize*mix(.006,.012,hash(cell+vec2(neighborSign.x,0.)+vec2(5.))); - color+=sampleCell(paneUv,xAffine+xTransform*(worldDelta/uPaneSize),strength,xBlurStep,cellSize)*colorXWeight; - } - if(colorYWeight>0.){ - vec2 yBlurStep=cellSize*mix(.006,.012,hash(cell+vec2(0.,neighborSign.y)+vec2(5.))); - color+=sampleCell(paneUv,yAffine+yTransform*(worldDelta/uPaneSize),strength,yBlurStep,cellSize)*colorYWeight; - } - if(colorDiagonalWeight>0.){ - vec2 diagonalBlurStep=cellSize*mix(.006,.012,hash(cell+neighborSign+vec2(5.))); - color+=sampleCell(paneUv,diagonalAffine+diagonalTransform*(worldDelta/uPaneSize),strength,diagonalBlurStep,cellSize)*colorDiagonalWeight; - } - }else{ - color=sampleCell(paneUv,sampleUv,strength,blurStep,cellSize); - } - color.a=1.; - vec3 v=normalize(uContentCameraPosition-gh),reflected=reflect(-v,nCurved); float lightT=(uLightPosition.z-gh.z)/safeZ(reflected.z); vec2 lightHit=gh.xy+reflected.xy*lightT; vec2 halfSize=vec2(.32,.42)*min(uPaneSize.x,uPaneSize.y); vec2 windowCoord=abs(lightHit-uLightPosition.xy)/halfSize; vec2 windowMask=1.-smoothstep(vec2(.45),vec2(1.15),windowCoord); float spec=windowMask.x*windowMask.y*step(.0001,reflected.z)*step(0.,lightT); float gloss=spec*clamp(uGlossStrength,0.,1.)*.12*edgeWeight*clamp(uStrength,0.,1.); color.rgb=mix(color.rgb,vec3(1.),gloss); gl_FragColor=color; - #include -} diff --git a/docs/qa-cell-continuity/dog1-before.png b/docs/qa-cell-continuity/dog1-before.png deleted file mode 100644 index 21905fe..0000000 Binary files a/docs/qa-cell-continuity/dog1-before.png and /dev/null differ diff --git a/docs/qa-cell-continuity/dog1-cap12.png b/docs/qa-cell-continuity/dog1-cap12.png deleted file mode 100644 index d3bfe25..0000000 Binary files a/docs/qa-cell-continuity/dog1-cap12.png and /dev/null differ diff --git a/docs/qa-cell-continuity/dog1-cap18.png b/docs/qa-cell-continuity/dog1-cap18.png deleted file mode 100644 index de35bb4..0000000 Binary files a/docs/qa-cell-continuity/dog1-cap18.png and /dev/null differ diff --git a/docs/qa-cell-continuity/dog1-common.png b/docs/qa-cell-continuity/dog1-common.png deleted file mode 100644 index 58a8e3b..0000000 Binary files a/docs/qa-cell-continuity/dog1-common.png and /dev/null differ diff --git a/docs/qa-cell-continuity/dog2-common.png b/docs/qa-cell-continuity/dog2-common.png deleted file mode 100644 index 23083d8..0000000 Binary files a/docs/qa-cell-continuity/dog2-common.png and /dev/null differ diff --git a/docs/qa-cell-continuity/dog3-before-center.png b/docs/qa-cell-continuity/dog3-before-center.png deleted file mode 100644 index 13eddbd..0000000 Binary files a/docs/qa-cell-continuity/dog3-before-center.png and /dev/null differ diff --git a/docs/qa-cell-continuity/dog3-before.png b/docs/qa-cell-continuity/dog3-before.png deleted file mode 100644 index 87b1104..0000000 Binary files a/docs/qa-cell-continuity/dog3-before.png and /dev/null differ diff --git a/docs/qa-cell-continuity/dog3-cap12-drag-left.png b/docs/qa-cell-continuity/dog3-cap12-drag-left.png deleted file mode 100644 index cb82b63..0000000 Binary files a/docs/qa-cell-continuity/dog3-cap12-drag-left.png and /dev/null differ diff --git a/docs/qa-cell-continuity/dog3-cap12-drag-right.png b/docs/qa-cell-continuity/dog3-cap12-drag-right.png deleted file mode 100644 index 324082c..0000000 Binary files a/docs/qa-cell-continuity/dog3-cap12-drag-right.png and /dev/null differ diff --git a/docs/qa-cell-continuity/dog3-cap12.png b/docs/qa-cell-continuity/dog3-cap12.png deleted file mode 100644 index b3ca391..0000000 Binary files a/docs/qa-cell-continuity/dog3-cap12.png and /dev/null differ diff --git a/docs/qa-cell-continuity/dog3-cap18-drag.png b/docs/qa-cell-continuity/dog3-cap18-drag.png deleted file mode 100644 index da24e28..0000000 Binary files a/docs/qa-cell-continuity/dog3-cap18-drag.png and /dev/null differ diff --git a/docs/qa-cell-continuity/dog3-cap18-user-size.png b/docs/qa-cell-continuity/dog3-cap18-user-size.png deleted file mode 100644 index 932c736..0000000 Binary files a/docs/qa-cell-continuity/dog3-cap18-user-size.png and /dev/null differ diff --git a/docs/qa-cell-continuity/dog3-cap18.png b/docs/qa-cell-continuity/dog3-cap18.png deleted file mode 100644 index ac17f96..0000000 Binary files a/docs/qa-cell-continuity/dog3-cap18.png and /dev/null differ diff --git a/docs/qa-cell-continuity/dog3-final-pane.png b/docs/qa-cell-continuity/dog3-final-pane.png deleted file mode 100644 index 776864d..0000000 Binary files a/docs/qa-cell-continuity/dog3-final-pane.png and /dev/null differ diff --git a/docs/qa-cell-continuity/dog3-flat.png b/docs/qa-cell-continuity/dog3-flat.png deleted file mode 100644 index a6a08d1..0000000 Binary files a/docs/qa-cell-continuity/dog3-flat.png and /dev/null differ diff --git a/docs/qa-cell-continuity/dog3-mobile-drag.png b/docs/qa-cell-continuity/dog3-mobile-drag.png deleted file mode 100644 index a2a40a1..0000000 Binary files a/docs/qa-cell-continuity/dog3-mobile-drag.png and /dev/null differ diff --git a/docs/qa-cell-continuity/dog3-mobile.png b/docs/qa-cell-continuity/dog3-mobile.png deleted file mode 100644 index 87976ca..0000000 Binary files a/docs/qa-cell-continuity/dog3-mobile.png and /dev/null differ diff --git a/docs/qa-cell-continuity/dog4-common.png b/docs/qa-cell-continuity/dog4-common.png deleted file mode 100644 index a157218..0000000 Binary files a/docs/qa-cell-continuity/dog4-common.png and /dev/null differ diff --git a/docs/qa-cell-continuity/review.md b/docs/qa-cell-continuity/review.md deleted file mode 100644 index 7a75fab..0000000 --- a/docs/qa-cell-continuity/review.md +++ /dev/null @@ -1,48 +0,0 @@ -# 인접 셀 얼굴 단절 수정 QA - -2026-09-13. 사용자 첨부에서 dog3(두 마리)의 얼굴 좌우가 인접 셀 사이에서 크게 어긋나는 문제를 재현하고 보정했다. Astra 설계·독립 검토, Luna 실제 코드 수정. 로컬 테스트용 사진이며 외부 게시하지 않는다. - -## 놓친 조건과 원인 - -사용자 탭에서 읽은 실제 설정: dog3 / 조각 유리 / Grid8 / Distortion.90 / 굴곡+.65 / 광택.15 / 사진 확대1 / X0 / Y0 / Camera Offset.30. 창 크기는 885×920이었고 시점 이동 상태였다. 최초 화면을 dog3-before.png에 저장했다. 사용자의 정확한 카메라 이동 수치는 보존하지 못했으므로 이후 비교는 중앙과 재현 가능한 좌우 대각 드래그로 분리했다. - -이전 QA는 dog3를 Grid12/.75, 구도1.3/.5/0으로 개별 조정했다. 사진을 전환해도 광학 설정이 유지되는 실제 사용 조건을 확인하지 않아 큰 셀과 작은 얼굴의 실패를 놓쳤다. 이번 통과 기준은 동일 Grid8/.90에서 기본 구도 사진을 전환해도 얼굴이 과도하게 분리되지 않는 것이다. - -직접 원인은 독립 셀의 샘플 영역 사이에 생기는 간격이다. 색 혼합으로 두 결과를 연결해도 그 사이의 원본 얼굴 정보는 복원되지 않는다. 경계 폭이나 전체 블러만 늘리는 대신 샘플 중심의 과도한 이동을 제한했다. - -## 구현 및 비교 - -수정 제품 파일: src/shaders/mosaic.frag 한 파일. C2 원본은 before-mosaic.frag, .18 후보는 cap18-mosaic.frag에 보존했다. - -sampleCell에서 먼저 Distortion 보간을 적용한 샘플 중심을 계산하고, 원래 pane 좌표와의 차이를 cellSize로 나눈 d를 구한다. 조각 스타일만 각 축에 dSafe = d / sqrt(1 + (d / .12)^2)를 적용한다. 제한된 중심에서 기존 5탭 퍼짐을 샘플한다. 중심/이웃/일반 셀 내부 모든 경로에 같은 제한을 적용한다. - -법선/곡면/광택 공유, 배율분포, .06색 연결/.16법선 연결, 촘촘 유리의 효과 계산과 Distortion0 우회는 유지했다. 새 텍스처 샘플이나 얼굴 검출, 사진별 자동설정은 추가하지 않았다. - -| 후보 | 관찰 | 결정 | -|---|---|---| -| 기존C2 | 두 얼굴의 눈/코가 셀 경계에서 크게 이동하고 얼굴 일부가 생략됨 | 수정 대상 | -| D .18 | 얼굴 연결 개선, 큰 조각은 상대적으로 더 보존. 시점에 따른 경계 잘림 잔존 | 비교용 보존 | -| E .12 | 정면 차이는 D와 작지만 더 보수적으로 이동 제한. 좌우 대각 드래그에서 두 눈·코 식별 유지, 큰 도약 완화 | 최종채택 | - -E 채택은 이번 요청의 얼굴 연결성을 우선한 판단이다. 주변의 큰 확대 조각과 레퍼런스의 정보량 차이는 약해지는 대가가 있다. 완전한 경계 연속성·모든 사진의 눈 보존을 보장하는 해법은 아니다. 각축 샘플 중심 이동은 .12셀 미만이지만 서로 다른 두 셀 중심 사이의 차이는 .24셀까지 남을 수 있고, 퍼짐 탭은 별도 오프셋을 갖는다. - -## 실행한 QA - -- D/E 각각 npm run build (tsc -b && vite build) 통과. -- 사용자 탭 원래 사진/설정/드래그 상태를 변경 전에 캡처. 제어 비교는 1280×720 중앙의 Grid8/.90/+ .65/.15, dog3 구도1/0/0. -- E dog3: 중앙, 좌상 방향 드래그(500,350→200,250), 초기화 후 우하 방향(300,350→650,450). 두 얼굴 눈·코 식별 유지, 창틀과 유리 정렬 확인. 모든 프레임을 분석한 것은 아니다. -- 390×844 dog3: 같은 설정과 구도에서 중앙 및 드래그(120,230→265,275) 확인. 실제 휴대폰 하드웨어 검증은 아니다. -- 5장 공통 광학 설정 유지하며 전환: Grid8/.90/+ .65/.15. 추가4장은 각 기본 구도1/0/0, 기존 sample은 앱 기존 구도2.4/-.10/-.35. dog1-common, dog2-common, dog3-cap12, dog4-common, sample-common 이미지 보존. 작은 얼굴·검은 털의 표정 가독성 한계는 남는다. -- dog1의 기존 확대 구도2.3/-.10/-.30에서도 D/E 비교: 눈·코 크기 차이는 남지만 주변 큰 면은 약해짐. dog1-before, dog1-cap18, dog1-cap12 이미지. -- dog3 곡면0/광택0에서 출력 확인, Distortion0 기존 우회 출력 확인, 촘촘 유리28/.85 실제 출력 확인. -- 브라우저 error 로그0. Astra 독립 정적 검토에서 모든 sampleCell 경로 동일적용, 강도후 제한, 기존 퍼짐과 샘플수 보존에 actionable 코드결함 없음. - -이번에 Reeded/Frosted·영상·자이로·업로드 전체 회귀와 실제 GPU 성능 측정은 재실행하지 않았다. 직전 작업의 확인과 구분한다. Depth는 기존 sample에만 있는 수작업 테스트 근사이며 이번 변경은 Depth/2-pass 코드를 수정하지 않았다. - -## 앞으로 유지할 회귀 기준 - -사진별 최적 설정만으로 통과시키지 않는다. 공통 광학 설정으로 추가 사진을 전환한 기본 구도, 작은 얼굴이 셀 경계에 걸리는 dog3, 좌우/대각 드래그, 모바일을 먼저 확인한다. 심한 잘림을 구도나 Grid 변경만으로 감추지 않는다. - -## 실행 - -npm run dev -- --host 127.0.0.1 후 http://127.0.0.1:5173/. 이번 결과 화면은 dog3, Grid8/.90/+ .65/.15, 사진1/0/0으로 남긴다. 다음 개선이 필요하면 단순히 한도를 다시 키우기보다 인접 셀의 샘플 영역 간격을 직접 제어하는 방식을 별도 실험한다. diff --git a/docs/qa-cell-continuity/sample-common.png b/docs/qa-cell-continuity/sample-common.png deleted file mode 100644 index 8987489..0000000 Binary files a/docs/qa-cell-continuity/sample-common.png and /dev/null differ diff --git a/docs/qa-coherence/after-center.png b/docs/qa-coherence/after-center.png deleted file mode 100644 index 8520202..0000000 Binary files a/docs/qa-coherence/after-center.png and /dev/null differ diff --git a/docs/qa-coherence/after-return.png b/docs/qa-coherence/after-return.png deleted file mode 100644 index 93af605..0000000 Binary files a/docs/qa-coherence/after-return.png and /dev/null differ diff --git a/docs/qa-coherence/after-right.png b/docs/qa-coherence/after-right.png deleted file mode 100644 index 920baa5..0000000 Binary files a/docs/qa-coherence/after-right.png and /dev/null differ diff --git a/docs/qa-coherence/before-center.png b/docs/qa-coherence/before-center.png deleted file mode 100644 index 000939f..0000000 Binary files a/docs/qa-coherence/before-center.png and /dev/null differ diff --git a/docs/qa-coherence/before-right.png b/docs/qa-coherence/before-right.png deleted file mode 100644 index d7971fc..0000000 Binary files a/docs/qa-coherence/before-right.png and /dev/null differ diff --git a/docs/qa-coherence/brief.md b/docs/qa-coherence/brief.md deleted file mode 100644 index f2d8a13..0000000 --- a/docs/qa-coherence/brief.md +++ /dev/null @@ -1,34 +0,0 @@ -# 시점·셀 굴절 일관성 수정 - -사용자 지적: 시점에 따른 셀 굴곡이 일관되지 않고 각 셀이 별도 사진 정보를 보유한 것처럼 보인다. - -원인: 기본 조각 유리의 셀별 임의 확대율/샘플 중심이 광선 기반 굴절보다 크게 작용하고, 굴절 이동에도 같은 임의 변환을 적용했다. - -변경 기준: -- 기본 조각 유리의 임의 이미지 확대·중심 이동과 이웃 셀 색상 조각 혼합을 제거한다. -- 카메라에서 유리판까지의 광선, 공통 곡면 모델의 법선, 굴절 광선이 공통 기준 평면에 닿는 위치를 사용한다. -- 곡면은 셀 좌표에 고정되고 반사에도 같은 법선을 사용한다. 미세한 고정 표면 편차만 허용한다. -- 사진/Depth/RenderTarget, 곡면 부호와 기본값, Ref1/Ref2 배치를 보존한다. 강한 흐림은 추가하지 않는다. -- 조각 유리의 새 경로는 실제 depth 표면과 광선을 교차시키는 완전한 물리 모델은 아니다. Depth 시차가 반영된 장면 텍스처를 공통 z=0 기준 평면의 투영으로 샘플한다. - -검증 기준: 같은 사진의 정면/좌/우/정면복귀, 광택0, 굴곡-1/0/+1, Distortion0, 모바일 배치. 화면 오류나 블러 감소만으로 시각 목표 완료를 판단하지 않는다. - -## 적용 결과 - -- 수정: `src/shaders/mosaic.frag`. 조각 유리에서 셀별 무작위 이미지 확대/중심 이동 및 이웃 색상 조각 혼합을 제거했다. -- 같은 카메라 광선과 곡면 법선으로 공통 z=0 평면의 굴절 교점을 투영해 한 번 샘플한다. 반사도 같은 법선을 쓴다. 별도 블러는 사용하지 않는다. -- 테두리만 둥글게 강조되던 곱 형태의 4차 곡면 대신, 축별 2차/4차 성분을 섞은 얕은 사각 곡면을 사용했다. 기본 곡면 높이 계수 .12, 기본 경계 전환 .04, 광선 이동의 부드러운 상한 .55셀이다. 높이는 셀 크기의 제곱과 유리-기준평면 거리에 따라 제한해 고밀도 격자의 과도한 접힘을 줄였다. -- 미세한 고정 높이 편차와 셀 기울기는 남기고, 촘촘 유리의 기존 경로는 유지했다. - -## 검증 결과와 범위 - -- 빌드·타입 검사 통과. 기존 큰 번들 안내는 남는다. -- `dog1` 사진으로 정면/좌/우/정면복귀를 확인했다. 임의의 크롭 조각이 지배하던 이전 출력보다 눈·코가 공통 장면에 연결된 채 변한다. -- 최종 정면과 복귀 이미지의 차이는 전체 RGB 채널 중 3개 채널에서 값 1뿐이었다. 픽셀 반올림 수준이며 완전한 바이트 동일성으로 보고하지 않는다. -- Distortion0 대 No Glass의 100×100 중앙 비교는 RGB 1개 채널에서 값1 차이였다. 화면상 일치하나 완전한 바이트 동일성은 아니다. -- 굴곡 -1/0/+1 및 광택0 화면을 확인했고, 기본 격자와 96칸 반복 선 무늬 테스트를 확인했다. 같은 곡면 규칙의 반복을 확인했으며 실제 굴절 광선을 depth 표면과 교차하는 정밀 물리 검증은 아니다. -- 390px 화면 가로 넘침 없음. 페이지 오류 없음. 실기기 GPU 성능은 측정하지 않았다. -- 이번에는 광학적 일관성을 우선했다. 이전 임의 확대·크롭의 강한 조각 효과는 줄었다. 레퍼런스의 시각적 강도까지 동일하게 달성했다고 판정하지 않는다. -- 사진 가장자리의 작은 부족 영역을 완전히 해결한 변경은 아니다. AI depth 처리 코드는 변경하지 않았으며 새 프로필에서 AI 추론 자체는 재실행하지 않았다. - -증거: `before-center.png`, `before-right.png`, `final-center.png`, `final-right.png`, `final-return.png`, `grid10.png`, `grid96.png`, `final-validation.json`. diff --git a/docs/qa-coherence/curvature-1.png b/docs/qa-coherence/curvature-1.png deleted file mode 100644 index 23ffa07..0000000 Binary files a/docs/qa-coherence/curvature-1.png and /dev/null differ diff --git a/docs/qa-coherence/curvature0.png b/docs/qa-coherence/curvature0.png deleted file mode 100644 index 1715d05..0000000 Binary files a/docs/qa-coherence/curvature0.png and /dev/null differ diff --git a/docs/qa-coherence/curvature1.png b/docs/qa-coherence/curvature1.png deleted file mode 100644 index 29f82da..0000000 Binary files a/docs/qa-coherence/curvature1.png and /dev/null differ diff --git a/docs/qa-coherence/final-center.png b/docs/qa-coherence/final-center.png deleted file mode 100644 index 0695af7..0000000 Binary files a/docs/qa-coherence/final-center.png and /dev/null differ diff --git a/docs/qa-coherence/final-left.png b/docs/qa-coherence/final-left.png deleted file mode 100644 index da0679a..0000000 Binary files a/docs/qa-coherence/final-left.png and /dev/null differ diff --git a/docs/qa-coherence/final-return.png b/docs/qa-coherence/final-return.png deleted file mode 100644 index 5a1efe1..0000000 Binary files a/docs/qa-coherence/final-return.png and /dev/null differ diff --git a/docs/qa-coherence/final-right.png b/docs/qa-coherence/final-right.png deleted file mode 100644 index da8e658..0000000 Binary files a/docs/qa-coherence/final-right.png and /dev/null differ diff --git a/docs/qa-coherence/final-validation.json b/docs/qa-coherence/final-validation.json deleted file mode 100644 index 00e4604..0000000 --- a/docs/qa-coherence/final-validation.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "errors": [], - "centerReturnEqual": false, - "mobileOverflow": false, - "returnPixelComparison": { - "differingChannels": 3, - "maxChannelDifference": 1, - "meanChannelDifference": 0.0000014285714285714286 - }, - "zeroVsNoGlassPixelComparison": { - "differingChannels": 1, - "maxChannelDifference": 1, - "meanChannelDifference": 0.000033333333333333335 - } -} \ No newline at end of file diff --git a/docs/qa-coherence/gloss0.png b/docs/qa-coherence/gloss0.png deleted file mode 100644 index ea281cb..0000000 Binary files a/docs/qa-coherence/gloss0.png and /dev/null differ diff --git a/docs/qa-coherence/grid10.png b/docs/qa-coherence/grid10.png deleted file mode 100644 index 839b65d..0000000 Binary files a/docs/qa-coherence/grid10.png and /dev/null differ diff --git a/docs/qa-coherence/grid96.png b/docs/qa-coherence/grid96.png deleted file mode 100644 index 872c483..0000000 Binary files a/docs/qa-coherence/grid96.png and /dev/null differ diff --git a/docs/qa-coherence/mobile.png b/docs/qa-coherence/mobile.png deleted file mode 100644 index e25544c..0000000 Binary files a/docs/qa-coherence/mobile.png and /dev/null differ diff --git a/docs/qa-coherence/plain.png b/docs/qa-coherence/plain.png deleted file mode 100644 index 32fb6ce..0000000 Binary files a/docs/qa-coherence/plain.png and /dev/null differ diff --git a/docs/qa-coherence/tuned-center.png b/docs/qa-coherence/tuned-center.png deleted file mode 100644 index 0eb4a7a..0000000 Binary files a/docs/qa-coherence/tuned-center.png and /dev/null differ diff --git a/docs/qa-coherence/tuned-plus1.png b/docs/qa-coherence/tuned-plus1.png deleted file mode 100644 index df84707..0000000 Binary files a/docs/qa-coherence/tuned-plus1.png and /dev/null differ diff --git a/docs/qa-coherence/tuned-sample.png b/docs/qa-coherence/tuned-sample.png deleted file mode 100644 index e34eda3..0000000 Binary files a/docs/qa-coherence/tuned-sample.png and /dev/null differ diff --git a/docs/qa-coherence/validation.json b/docs/qa-coherence/validation.json deleted file mode 100644 index ad2666a..0000000 --- a/docs/qa-coherence/validation.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "errors": [], - "centerReturnEqual": true, - "zeroCenterEqualsNoGlass": false, - "mobileOverflow": false -} \ No newline at end of file diff --git a/docs/qa-coherence/zero.png b/docs/qa-coherence/zero.png deleted file mode 100644 index 7c6b057..0000000 Binary files a/docs/qa-coherence/zero.png and /dev/null differ diff --git a/docs/qa-depth-coupling/baseline-main.ts b/docs/qa-depth-coupling/baseline-main.ts deleted file mode 100644 index 7eecb6a..0000000 --- a/docs/qa-depth-coupling/baseline-main.ts +++ /dev/null @@ -1,460 +0,0 @@ -import * as THREE from 'three'; -import './style.css'; -import vertexShader from './shaders/common.vert?raw'; -import mosaicShader from './shaders/mosaic.frag?raw'; -import reededShader from './shaders/reeded.frag?raw'; -import frostedShader from './shaders/frosted.frag?raw'; -import { MediaLoader } from './input/MediaLoader'; -import { PointerController } from './input/PointerController'; -import { CameraController } from './input/CameraController'; -import { GyroController } from './input/GyroController'; -import { StaticDepthProvider } from './depth/StaticDepthProvider'; -import { DepthProcessor } from './depth/DepthProcessor'; -import { AiDepthProvider } from './depth/AiDepthProvider'; -import { PetDepthMesh } from './objects/PetDepthMesh'; -import { DepthDebug } from './depth/DepthDebug'; -import { WindowReveal } from './objects/WindowReveal'; -import glassScreenVertex from './shaders/glassScreen.vert?raw'; -import regionPaletteShader from './shaders/region-palette.frag?raw'; -import regionHistoryShader from './shaders/region-history.frag?raw'; - -const wrap = document.querySelector('#canvas-wrap') as HTMLElement; -const status = document.querySelector('#status') as HTMLElement; -const depthProvenance = document.querySelector('#depth-provenance') as HTMLElement; -const aiDepthButton = document.querySelector('#ai-depth') as HTMLButtonElement; -const empty = document.querySelector('#empty') as HTMLElement; -const hintElement = document.querySelector('#hint') as HTMLElement; -hintElement.style.opacity = '0'; -const renderer = new THREE.WebGLRenderer({ antialias: true }); -renderer.setPixelRatio(Math.min(devicePixelRatio, 1.5)); -wrap.append(renderer.domElement); -const scene = new THREE.Scene(); -const glassScene = new THREE.Scene(); -const frameScene = new THREE.Scene(); -scene.background = new THREE.Color(0x111923); -const camera = new THREE.PerspectiveCamera(40, 1, 0.1, 100); -camera.position.z = 3; -const geometry = new THREE.PlaneGeometry(1, 1); -const emptyTex = new THREE.DataTexture(new Uint8Array([38, 48, 62, 255]), 1, 1); -emptyTex.needsUpdate = true; -const petMat = new THREE.MeshBasicMaterial({ map: emptyTex }); -const pet = new THREE.Mesh(geometry, petMat); -scene.add(pet); -const depthMap: THREE.Texture = DepthProcessor.flatTexture(); -const petDepth = new PetDepthMesh(emptyTex, depthMap, 0.25, 0); -const petDepthMaterial = petDepth.material; -const depthUniforms = petDepthMaterial.uniforms; -scene.add(petDepth); -const uniforms = { uSceneTexture: { value: emptyTex as THREE.Texture }, uSceneDepth: { value: emptyTex as THREE.Texture }, uProtectionDepthMap: depthUniforms.uDepthMap, uPetWorldToLocal: { value: new THREE.Matrix4() }, uContentViewProjection: { value: new THREE.Matrix4() }, uContentInverseViewProjection: { value: new THREE.Matrix4() }, uContentCameraPosition: { value: new THREE.Vector3() }, uLightPosition: { value: new THREE.Vector3(0.6, 0.8, 2.6) }, uBackgroundColor: { value: scene.background.clone() }, uGlassZ: { value: 0.6 }, uSourceZ: { value: 0.56 }, uGridSize: { value: 13 }, uMosaicStyle: { value: 0 }, uStrength: { value: 1 }, uGlossStrength: { value: 0.3 }, uCurvature: { value: 1 }, uRegionStrength: { value: 1 }, uRegionAvailable: { value: 0 }, uRegionAtlasSize: { value: new THREE.Vector2(104, 104) }, uRegionGridSize: { value: new THREE.Vector2(13, 13) }, uRegionPaletteSize: { value: new THREE.Vector2(65, 13) }, uRegionPalette: { value: emptyTex as THREE.Texture }, uRegionAtlas: { value: emptyTex as THREE.Texture }, uViewOffset: { value: new THREE.Vector2() }, uPaneRect: { value: new THREE.Vector4(0, 0, 1, 1) }, uResolution: { value: new THREE.Vector2() }, uTime: { value: 0 }, uPetSize: { value: new THREE.Vector2(1, 1) }, uPaneSize: { value: new THREE.Vector2(1, 1) } }; -const regionHistoryUniform = { value: emptyTex as THREE.Texture }; -Object.assign(uniforms, { uRegionHistory: regionHistoryUniform }); -const glassMat = new THREE.ShaderMaterial({ uniforms, vertexShader: glassScreenVertex, fragmentShader: mosaicShader }); -const glass = new THREE.Mesh(new THREE.PlaneGeometry(2, 2), glassMat); -glassScene.add(glass); -const atlasScene = new THREE.Scene(); -const atlasMaterial = new THREE.ShaderMaterial({ uniforms, vertexShader: glassScreenVertex, fragmentShader: mosaicShader, defines: { REGION_ATLAS: 1 }, toneMapped: false }); -const atlasMesh = new THREE.Mesh(new THREE.PlaneGeometry(2, 2), atlasMaterial); -atlasScene.add(atlasMesh); -const paletteScene = new THREE.Scene(); -const paletteUniforms = { uRegionAtlas: { value: null as THREE.Texture | null }, uRegionAtlasSize: uniforms.uRegionAtlasSize, uRegionGridSize: uniforms.uRegionGridSize }; -const paletteMaterial = new THREE.ShaderMaterial({ uniforms: paletteUniforms, vertexShader: glassScreenVertex, fragmentShader: regionPaletteShader, toneMapped: false }); -const paletteMesh = new THREE.Mesh(new THREE.PlaneGeometry(2, 2), paletteMaterial); -paletteScene.add(paletteMesh); -const frameGeometry = new THREE.BoxGeometry(1, 1, 1); -const frameMaterials = [ - new THREE.MeshBasicMaterial({ color: 0x3a2419 }), - new THREE.MeshBasicMaterial({ color: 0x4a2e20 }), - new THREE.MeshBasicMaterial({ color: 0x2b1a13 }), - new THREE.MeshBasicMaterial({ color: 0x513326 }), - new THREE.MeshBasicMaterial({ color: 0x321f17 }), - new THREE.MeshBasicMaterial({ color: 0x43291d }) -]; -const frameLeft = new THREE.Mesh(frameGeometry, frameMaterials); -const frameRight = new THREE.Mesh(frameGeometry, frameMaterials); -const frameTop = new THREE.Mesh(frameGeometry, frameMaterials); -const frameBottom = new THREE.Mesh(frameGeometry, frameMaterials); -frameScene.add(frameLeft, frameRight, frameTop, frameBottom); -const windowRevealMaterial = new THREE.MeshBasicMaterial({ color: frameMaterials[1].color, side: THREE.DoubleSide }); -const windowReveal = new WindowReveal(windowRevealMaterial); -frameScene.add(...windowReveal.meshes); -const postCamera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1); -const renderTarget = new THREE.WebGLRenderTarget(1, 1, { colorSpace: THREE.NoColorSpace, type: THREE.HalfFloatType, depthBuffer: true }); -renderTarget.depthTexture = new THREE.DepthTexture(1, 1, THREE.UnsignedIntType); -renderTarget.depthTexture.format = THREE.DepthFormat; -uniforms.uSceneDepth.value = renderTarget.depthTexture; -const regionAtlasTarget = new THREE.WebGLRenderTarget(104, 104, { colorSpace: THREE.NoColorSpace, type: THREE.HalfFloatType, depthBuffer: false, minFilter: THREE.NearestFilter, magFilter: THREE.NearestFilter }); -const regionPaletteTarget = new THREE.WebGLRenderTarget(65, 13, { colorSpace: THREE.NoColorSpace, type: THREE.UnsignedByteType, depthBuffer: false, minFilter: THREE.NearestFilter, magFilter: THREE.NearestFilter }); -const splitHistoryTargets = [0, 1].map(() => new THREE.WebGLRenderTarget(104, 104, { colorSpace: THREE.NoColorSpace, type: THREE.HalfFloatType, depthBuffer: false, minFilter: THREE.NearestFilter, magFilter: THREE.NearestFilter })); -const historyScene = new THREE.Scene(); -const historyUniforms = { uRegionPalette: { value: regionPaletteTarget.texture }, uPreviousHistory: { value: splitHistoryTargets[0].texture }, uRegionAtlasSize: uniforms.uRegionAtlasSize, uRegionGridSize: uniforms.uRegionGridSize, uRegionPaletteSize: uniforms.uRegionPaletteSize, uHistoryBlend: { value: 1 } }; -const historyMaterial = new THREE.ShaderMaterial({ uniforms: historyUniforms, vertexShader: glassScreenVertex, fragmentShader: regionHistoryShader, toneMapped: false }); -const historyMesh = new THREE.Mesh(new THREE.PlaneGeometry(2, 2), historyMaterial); -historyScene.add(historyMesh); -uniforms.uRegionPalette.value = regionPaletteTarget.texture; -paletteUniforms.uRegionAtlas.value = regionAtlasTarget.texture; -let regionSignature = ''; -let splitHistorySignature = ''; -let splitHistoryRead = 0; -let splitHistoryInitialized = false; -function updateRegionTargetSizes(): void { - const gridX = Math.max(1, Math.ceil(uniforms.uGridSize.value)); - const gridYValue = Math.max(1, uniforms.uGridSize.value * uniforms.uPaneSize.value.y / Math.max(uniforms.uPaneSize.value.x, 0.001)); - const gridY = Math.ceil(gridYValue); - const atlasWidth = gridX * 8, atlasHeight = gridY * 8, paletteWidth = gridX * 5, paletteHeight = gridY; - const available = Math.max(atlasWidth, atlasHeight, paletteWidth, paletteHeight) <= renderer.capabilities.maxTextureSize; - const changed = uniforms.uRegionAvailable.value !== (available ? 1 : 0) || (available && (regionAtlasTarget.width !== atlasWidth || regionAtlasTarget.height !== atlasHeight || regionPaletteTarget.width !== paletteWidth || regionPaletteTarget.height !== paletteHeight || splitHistoryTargets[0].width !== atlasWidth || splitHistoryTargets[0].height !== atlasHeight)) || uniforms.uRegionGridSize.value.x !== uniforms.uGridSize.value || uniforms.uRegionGridSize.value.y !== gridYValue; - if (available && (regionAtlasTarget.width !== atlasWidth || regionAtlasTarget.height !== atlasHeight)) regionAtlasTarget.setSize(atlasWidth, atlasHeight); - if (available && (regionPaletteTarget.width !== paletteWidth || regionPaletteTarget.height !== paletteHeight)) regionPaletteTarget.setSize(paletteWidth, paletteHeight); - for (const target of splitHistoryTargets) if (available && (target.width !== atlasWidth || target.height !== atlasHeight)) target.setSize(atlasWidth, atlasHeight); - uniforms.uRegionAvailable.value = available ? 1 : 0; - uniforms.uRegionAtlasSize.value.set(available ? atlasWidth : regionAtlasTarget.width, available ? atlasHeight : regionAtlasTarget.height); - uniforms.uRegionGridSize.value.set(uniforms.uGridSize.value, gridYValue); - uniforms.uRegionPaletteSize.value.set(available ? paletteWidth : regionPaletteTarget.width, available ? paletteHeight : regionPaletteTarget.height); - paletteUniforms.uRegionAtlas.value = regionAtlasTarget.texture; - uniforms.uRegionPalette.value = regionPaletteTarget.texture; - uniforms.uRegionAtlas.value = regionAtlasTarget.texture; - if (changed) regionSignature = ''; -} -let active: THREE.Texture = emptyTex; -let activeIsVideo = false; -let aspect = 1; -let baseW = 1; -let baseH = 1; -let photoZoom = 1; -let photoPanX = 0; -let photoPanY = 0; -let pendingSampleFraming = false; -let activeTestPhotoHasNoDepth = false; -let mode = 'noglass'; -let hintGeneration = 0; -let hintDraggedGeneration = -1; -let pendingPairDepth: THREE.Texture | null = null; -let pendingSampleDebugImage: HTMLImageElement | null = null; -let pendingTestPhotoHasNoDepth = false; -let mediaRequest = 0; -let depthRequest = 0; -let mediaBusy = false; -let manualDepthBusy = false; -let aiDepthBusy = false; -let disposed = false; -const listenerAbort = new AbortController(); -function syncAIDepthButton(): void { - aiDepthButton.disabled = active === emptyTex || activeIsVideo || mediaBusy || manualDepthBusy || aiDepthBusy || disposed; - aiDepthButton.textContent = aiDepthBusy ? 'AI 깊이 생성 중…' : 'AI 깊이 생성'; -} -const aiDepthProvider = new AiDepthProvider((message) => { if (!disposed && aiDepthBusy) status.textContent = message; }); -function invalidateDepthRequests(): void { - depthRequest += 1; - aiDepthProvider.cancel(); - aiDepthBusy = false; - manualDepthBusy = false; - syncAIDepthButton(); -} -function clearPendingPair(): void { if (pendingPairDepth) pendingPairDepth.dispose(); pendingPairDepth = null; } -let maxDepthValue = 0; -function contentBaseZ(): number { return uniforms.uGlassZ.value - 0.04 - (maxDepthValue - depthUniforms.uDepthBias.value) * depthUniforms.uDepthScale.value; } -function clearPendingTestState(): void { clearPendingPair(); pendingSampleDebugImage = null; pendingSampleFraming = false; pendingTestPhotoHasNoDepth = false; } -function applyFraming(): void { - const baseZ = contentBaseZ(); - const worldScale = (camera.position.z - baseZ) / camera.position.z; - const x = baseW * (photoZoom - 1) * 0.5 * photoPanX * worldScale; - const y = baseH * (photoZoom - 1) * 0.5 * photoPanY * worldScale; - pet.scale.set(baseW * photoZoom * worldScale, baseH * photoZoom * worldScale, 1); - pet.position.set(x, y, baseZ); - petDepth.scale.copy(pet.scale); - petDepth.position.copy(pet.position); - uniforms.uSourceZ.value = baseZ; - windowReveal.update(uniforms.uPaneSize.value.x, uniforms.uPaneSize.value.y, baseW * (3 - baseZ) / 3, baseH * (3 - baseZ) / 3, uniforms.uGlassZ.value, baseZ); -} -function resize(): void { - const bounds = wrap.getBoundingClientRect(); - renderer.setSize(bounds.width, bounds.height, false); - camera.aspect = bounds.width / bounds.height; - camera.updateProjectionMatrix(); - const height = 1.7; - const scale = Math.min(height * bounds.width / bounds.height / aspect, height); - baseW = scale * aspect; - baseH = scale; - applyFraming(); - uniforms.uPetSize.value.set(baseW, baseH); - uniforms.uResolution.value.set(bounds.width, bounds.height); - const glassHeight = 2 * (camera.position.z - 0.6) * Math.tan(THREE.MathUtils.degToRad(camera.fov / 2)); - uniforms.uPetSize.value.set(glassHeight * camera.aspect, glassHeight); - uniforms.uPaneSize.value.set(baseW * (3 - uniforms.uGlassZ.value) / 3, baseH * (3 - uniforms.uGlassZ.value) / 3); - windowReveal.update(uniforms.uPaneSize.value.x, uniforms.uPaneSize.value.y, baseW * (3 - contentBaseZ()) / 3, baseH * (3 - contentBaseZ()) / 3, uniforms.uGlassZ.value, contentBaseZ()); - updateRegionTargetSizes(); - const frameW = uniforms.uPaneSize.value.x; - const frameH = uniforms.uPaneSize.value.y; - const frameThickness = Math.min(frameW, frameH) * 0.035; - const frameDepth = frameThickness * 1.5; - const frameZ = uniforms.uGlassZ.value + frameDepth * 0.25; - frameLeft.position.set(-(frameW + frameThickness) * 0.5, 0, frameZ); - frameRight.position.set((frameW + frameThickness) * 0.5, 0, frameZ); - frameTop.position.set(0, (frameH + frameThickness) * 0.5, frameZ); - frameBottom.position.set(0, -(frameH + frameThickness) * 0.5, frameZ); - frameLeft.scale.set(frameThickness, frameH, frameDepth); - frameRight.scale.set(frameThickness, frameH, frameDepth); - frameTop.scale.set(frameW + frameThickness * 2, frameThickness, frameDepth); - frameBottom.scale.set(frameW + frameThickness * 2, frameThickness, frameDepth); - const neutralGlassHeight = 2 * 3 * Math.tan(THREE.MathUtils.degToRad(40 / 2)); - const neutralGlassWidth = neutralGlassHeight * camera.aspect; - uniforms.uPaneRect.value.set(Math.max(0, 0.5 - baseW / (2 * neutralGlassWidth)), Math.max(0, 0.5 - baseH / (2 * neutralGlassHeight)), Math.min(1, 0.5 + baseW / (2 * neutralGlassWidth)), Math.min(1, 0.5 + baseH / (2 * neutralGlassHeight))); - renderTarget.setSize(Math.max(1, Math.floor(bounds.width * Math.min(devicePixelRatio, 1.5))), Math.max(1, Math.floor(bounds.height * Math.min(devicePixelRatio, 1.5)))); -} -function resetHintForMedia(): void { hintGeneration += 1; hintDraggedGeneration = -1; hintElement.style.opacity = '0'; } -function showHint(): void { if (hintDraggedGeneration === hintGeneration) return; hintElement.style.opacity = '1'; } -function hideHintAfterDrag(): void { hintDraggedGeneration = hintGeneration; hintElement.style.opacity = '0'; } -function applyMedia(texture: THREE.Texture, mediaAspect: number, video: HTMLVideoElement | null): void { - if (active !== emptyTex) active.dispose(); - active = texture; activeIsVideo = Boolean(video); mediaBusy = false; aspect = mediaAspect; - photoZoom = 1; photoPanX = 0; photoPanY = 0; pendingSampleFraming = false; - syncPhotoControls(); - texture.colorSpace = THREE.SRGBColorSpace; - depthUniforms.uTexture.value = texture; - petMat.map = texture; petMat.needsUpdate = true; - empty.style.display = 'none'; resize(); syncAIDepthButton(); -} -function setDepth(texture: THREE.Texture): void { - if (depthUniforms.uDepthMap.value !== depthMap) depthUniforms.uDepthMap.value.dispose(); - depthUniforms.uDepthMap.value = texture; texture.colorSpace = THREE.NoColorSpace; - const data = (texture as THREE.DataTexture).image?.data; - maxDepthValue = 0; - if (data && data.length >= 4) { - for (let i = 0; i < data.length; i += 4) maxDepthValue = Math.max(maxDepthValue, Number(data[i]) / 255); - } - applyFraming(); - regionSignature = ''; - if (mode === 'depth') { petMat.map = texture; petMat.needsUpdate = true; } -} -function setMode(next: string): void { - mode = next; - if (modeInput) modeInput.value = next; - pet.visible = next === 'rgb' || next === 'depth'; - petDepth.visible = next === 'noglass' || next === 'final'; - glass.visible = next === 'final' || next === 'glass'; - petMat.map = next === 'depth' ? depthUniforms.uDepthMap.value : active; - petMat.needsUpdate = true; - petDepthMaterial.uniforms.uTexture.value = active; -} -const retry = document.createElement('button'); -retry.textContent = '재생'; retry.hidden = true; -(document.querySelector('aside') as HTMLElement).append(retry); -const debugOutput = document.createElement('pre'); -debugOutput.id = 'depth-debug'; -debugOutput.hidden = true; -(document.querySelector('aside') as HTMLElement).append(debugOutput); -const depthDebug = new DepthDebug(); -const loader = new MediaLoader((texture, mediaAspect, video) => { const hasSampleDepth = pendingSampleFraming && pendingPairDepth !== null; const hasTestWithoutDepth = pendingTestPhotoHasNoDepth; const shouldGenerateDepth = !video && !hasSampleDepth; applyMedia(texture, mediaAspect, video); petDepth.setVideo(Boolean(video)); setDepth(pendingPairDepth ?? DepthProcessor.flatTexture()); pendingPairDepth = null; if (hasSampleDepth && pendingSampleDebugImage) depthDebug.setSample(pendingSampleDebugImage); else depthDebug.clear(); pendingSampleDebugImage = null; activeTestPhotoHasNoDepth = hasTestWithoutDepth; pendingTestPhotoHasNoDepth = false; depthProvenance.hidden = !(hasSampleDepth || activeTestPhotoHasNoDepth); if (hasSampleDepth) depthProvenance.textContent = '수작업 테스트 Depth · AI 추정 아님'; else if (activeTestPhotoHasNoDepth) depthProvenance.textContent = 'Depth 없음 · 평면 사진 테스트'; setMode('final'); showHint(); if (sampleButton) sampleButton.textContent = '선택한 테스트 사진 불러오기'; if (shouldGenerateDepth) void generateAIDepth(true); }, (message) => { mediaBusy = false; syncAIDepthButton(); if (message || !aiDepthBusy) status.textContent = message; retry.hidden = !message.includes('자동'); if (message) { clearPendingTestState(); if (sampleButton) sampleButton.textContent = '선택한 테스트 사진 불러오기'; } }); -retry.onclick = () => loader.retry(); -const sampleDepthProvider = new StaticDepthProvider('/assets/sample-pet-depth.png'); -const cameraController = new CameraController(camera); -const pointer = new PointerController(renderer.domElement, (x, y) => cameraController.add(x, y), hideHintAfterDrag); -const gyro = new GyroController((x, y) => cameraController.target.set(THREE.MathUtils.clamp(x, -1, 1), THREE.MathUtils.clamp(y, -1, 1)), (message) => { status.textContent = message; }); -const imageInput = document.querySelector('#image') as HTMLInputElement; -const videoInput = document.querySelector('#video') as HTMLInputElement; -const depthFileInput = document.querySelector('#depth-image') as HTMLInputElement; -const sampleButton = document.querySelector('#sample') as HTMLButtonElement | null; -const testPhotoInput = document.querySelector('#test-photo') as HTMLSelectElement; -const referenceStrip = document.querySelector('#reference-strip') as HTMLElement; -const referenceStatus = document.querySelector('#reference-status') as HTMLElement; -const referenceImages = [ - document.querySelector('#reference-image-1') as HTMLImageElement, - document.querySelector('#reference-image-2') as HTMLImageElement -]; -referenceStrip.hidden = false; -const showReferenceError = () => { referenceStatus.hidden = false; }; -referenceImages.forEach((image) => image.addEventListener('error', showReferenceError, { signal: listenerAbort.signal })); -void Promise.all([ - import('../docs/qa-five-photos/reference1.png?url'), - import('../docs/qa-five-photos/reference2.png?url') -]).then(([reference1, reference2]) => { - if (disposed) return; - referenceImages[0].src = reference1.default; - referenceImages[1].src = reference2.default; -}).catch(() => { if (!disposed) showReferenceError(); }); -const effectInput = document.querySelector('#effect') as HTMLSelectElement; -const modeInput = document.querySelector('#view-mode') as HTMLSelectElement | null; -const sensitivityInput = document.querySelector('#sensitivity') as HTMLInputElement; -const depthInput = document.querySelector('#depth-scale') as HTMLInputElement | null; -const cameraOffsetInput = document.querySelector('#camera-offset') as HTMLInputElement; -const gridInput = document.querySelector('#grid-size') as HTMLInputElement; -const gridOutput = document.querySelector('#gridOut') as HTMLOutputElement; -const mosaicStyleInput = document.querySelector('#mosaic-style') as HTMLSelectElement; -const mosaicStyleLabel = mosaicStyleInput.closest('label'); -const glossControls = document.querySelector('#gloss-controls') as HTMLElement | null; -const regionFixedNote = document.querySelector('#region-fixed-note') as HTMLElement | null; -const curvatureInput = document.querySelector('#curvature') as HTMLInputElement | null; -const glossInput = document.querySelector('#gloss-strength') as HTMLInputElement | null; -const lightXInput = document.querySelector('#light-x') as HTMLInputElement | null; -const lightYInput = document.querySelector('#light-y') as HTMLInputElement | null; -const glossOutput = document.querySelector('#glossOut') as HTMLOutputElement | null; -const lightXOutput = document.querySelector('#lightXOut') as HTMLOutputElement | null; -const lightYOutput = document.querySelector('#lightYOut') as HTMLOutputElement | null; -const cameraOutput = document.querySelector('#cameraOut') as HTMLOutputElement; -const sensitivityOutput = document.querySelector('#sensitivityOut') as HTMLOutputElement; -const depthOutput = document.querySelector('#depthOut') as HTMLOutputElement | null; -const photoZoomInput = document.querySelector('#photo-zoom') as HTMLInputElement | null; -const photoZoomOutput = document.querySelector('#photoZoomOut') as HTMLOutputElement | null; -const photoPanXInput = document.querySelector('#photo-pan-x') as HTMLInputElement | null; -const photoPanXOutput = document.querySelector('#photoPanXOut') as HTMLOutputElement | null; -const photoPanYInput = document.querySelector('#photo-pan-y') as HTMLInputElement | null; -const photoPanYOutput = document.querySelector('#photoPanYOut') as HTMLOutputElement | null; -const photoResetButton = document.querySelector('#photo-reset') as HTMLButtonElement | null; -const resetButton = document.querySelector('#reset') as HTMLButtonElement; -const gyroButton = document.querySelector('#gyro') as HTMLButtonElement; -const effects = [mosaicShader, reededShader, frostedShader]; -let sensitivity = 1; -function setGlossControlsVisibility(): void { - const enabled = effectInput.value === 'mosaic'; - const ref1Mosaic = enabled && mosaicStyleInput.value === '0'; - if (mosaicStyleLabel) mosaicStyleLabel.style.display = enabled ? 'grid' : 'none'; - mosaicStyleInput.disabled = !enabled; - if (glossControls) { glossControls.hidden = !enabled; glossControls.style.display = enabled ? 'grid' : 'none'; } - if (regionFixedNote) regionFixedNote.hidden = !ref1Mosaic; - [glossInput, lightXInput, lightYInput, curvatureInput].forEach((input) => { if (input) input.disabled = !enabled; }); -} -function syncPhotoControls(): void { - if (photoZoomInput) photoZoomInput.value = photoZoom.toFixed(2); - if (photoZoomOutput) photoZoomOutput.value = photoZoom.toFixed(2); - if (photoPanXInput) photoPanXInput.value = photoPanX.toFixed(2); - if (photoPanXOutput) photoPanXOutput.value = photoPanX.toFixed(2); - if (photoPanYInput) photoPanYInput.value = photoPanY.toFixed(2); - if (photoPanYOutput) photoPanYOutput.value = photoPanY.toFixed(2); -} -async function generateAIDepth(automatic = false): Promise { - if (aiDepthButton.disabled || !(active.image instanceof HTMLImageElement)) return; - const sourceTexture = active; - const sourceImage = active.image; - const request = ++depthRequest; - aiDepthBusy = true; - status.textContent = 'AI 모델을 준비하는 중입니다. 처음 실행하면 모델 파일을 다운로드합니다.'; - syncAIDepthButton(); - try { - const texture = await aiDepthProvider.getDepthMap(sourceImage); - if (disposed || request !== depthRequest || active !== sourceTexture || activeIsVideo) { - texture.dispose(); - return; - } - setDepth(texture); - depthDebug.clear(); - activeTestPhotoHasNoDepth = false; - depthProvenance.hidden = false; - depthProvenance.textContent = 'AI 추정 · Depth Anything V2 Small (상대 깊이, 0=뒤 · 1=앞)'; - setMode('final'); - status.textContent = automatic ? '자동 AI 추정 depth를 적용했습니다.' : 'AI 추정 depth를 적용하고 Final 뷰로 돌아왔습니다.'; - showHint(); - } catch (error) { - if (!disposed && request === depthRequest) { - const detail = error instanceof Error ? error.message : '알 수 없는 오류'; - status.textContent = automatic ? `자동 depth 생성 실패 (${detail}). 평면 사진 배치를 유지합니다. AI 깊이 생성 버튼으로 다시 시도할 수 있습니다.` : `AI 깊이 생성 실패 (${detail}). 다시 시도할 수 있으며 기존 depth는 유지됩니다.`; - } - } finally { - if (request === depthRequest) { - aiDepthBusy = false; - syncAIDepthButton(); - } - } -} -aiDepthButton.addEventListener('click', () => { void generateAIDepth(); }, { signal: listenerAbort.signal }); -imageInput.onchange = (event) => { const input = event.target as HTMLInputElement; const file = input.files?.[0]; if (file) { resetHintForMedia(); mediaRequest += 1; invalidateDepthRequests(); mediaBusy = true; syncAIDepthButton(); clearPendingTestState(); loader.load(file); } input.value = ''; }; -videoInput.onchange = (event) => { const input = event.target as HTMLInputElement; const file = input.files?.[0]; if (file) { resetHintForMedia(); mediaRequest += 1; invalidateDepthRequests(); mediaBusy = true; syncAIDepthButton(); clearPendingTestState(); loader.load(file); } input.value = ''; }; -photoZoomInput?.addEventListener('input', (event) => { photoZoom = Number((event.target as HTMLInputElement).value); applyFraming(); syncPhotoControls(); }, { signal: listenerAbort.signal }); -photoPanXInput?.addEventListener('input', (event) => { photoPanX = Number((event.target as HTMLInputElement).value); applyFraming(); syncPhotoControls(); }, { signal: listenerAbort.signal }); -photoPanYInput?.addEventListener('input', (event) => { photoPanY = Number((event.target as HTMLInputElement).value); applyFraming(); syncPhotoControls(); }, { signal: listenerAbort.signal }); -photoResetButton?.addEventListener('click', () => { photoZoom = 1; photoPanX = 0; photoPanY = 0; applyFraming(); syncPhotoControls(); }, { signal: listenerAbort.signal }); -sampleButton?.addEventListener('click', async () => { const request = ++mediaRequest; const selected = testPhotoInput.value; const isSample = selected === 'sample'; const filePath = isSample ? '/assets/sample-pet.png' : `/assets/qa/${selected === 'dog3' ? 'dog3.webp' : `${selected}.jpeg`}`; invalidateDepthRequests(); mediaBusy = true; syncAIDepthButton(); loader.cancelPending(); clearPendingTestState(); sampleButton.textContent = `불러오는 중: ${filePath.split('/').pop()}`; status.textContent = ''; let url = ''; try { const rgbResponse = await fetch(filePath); if (!rgbResponse.ok) throw new Error('image'); const rgb = await rgbResponse.blob(); if (disposed || request !== mediaRequest) return; if (isSample) { const depthResponse = await fetch('/assets/sample-pet-depth.png'); if (!depthResponse.ok) throw new Error('depth'); const depth = await depthResponse.blob(); if (disposed || request !== mediaRequest) return; url = URL.createObjectURL(depth); const image = new Image(); image.src = url; await image.decode(); if (disposed || request !== mediaRequest) return; const loadedDepth = await sampleDepthProvider.getDepthMap(image); if (disposed || request !== mediaRequest) { loadedDepth.dispose(); return; } pendingPairDepth = loadedDepth; pendingSampleDebugImage = image; pendingSampleFraming = true; } pendingTestPhotoHasNoDepth = !isSample; loader.load(new File([rgb], filePath.split('/').pop() ?? 'test-photo', { type: rgbResponse.headers.get('content-type') ?? 'image/jpeg' })); if (isSample) status.textContent = '수작업 테스트 Depth · AI 추정 아님'; } catch { if (!disposed && request === mediaRequest) { mediaBusy = false; syncAIDepthButton(); clearPendingTestState(); status.textContent = isSample ? '샘플 사진 또는 depth map을 읽지 못했습니다.' : '테스트 사진을 읽지 못했습니다.'; sampleButton.textContent = '선택한 테스트 사진 불러오기'; } } finally { if (url) URL.revokeObjectURL(url); } }, { signal: listenerAbort.signal }); -sampleButton?.addEventListener('click', resetHintForMedia, { signal: listenerAbort.signal }); -effectInput.addEventListener('change', (event) => { const index = ['mosaic', 'reeded', 'frosted'].indexOf((event.target as HTMLSelectElement).value); glassMat.fragmentShader = effects[index]; glassMat.needsUpdate = true; setGlossControlsVisibility(); }, { signal: listenerAbort.signal }); -modeInput?.addEventListener('change', (event) => setMode((event.target as HTMLSelectElement).value), { signal: listenerAbort.signal }); -sensitivityInput.oninput = (event) => { const value = Number((event.target as HTMLInputElement).value); sensitivity = value; sensitivityOutput.value = value.toFixed(2); }; -depthInput?.addEventListener('input', (event) => { const value = Math.min(Number((event.target as HTMLInputElement).value), 0.4); depthUniforms.uDepthScale.value = value; applyFraming(); regionSignature = ''; if (depthOutput) depthOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -cameraOffsetInput.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); cameraController.setMaxOffset(value); cameraOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -gridInput.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uGridSize.value = value; gridOutput.value = value.toFixed(0); updateRegionTargetSizes(); }, { signal: listenerAbort.signal }); -mosaicStyleInput.addEventListener('change', (event) => { if (effectInput.value !== 'mosaic') return; const style = Number((event.target as HTMLSelectElement).value); uniforms.uMosaicStyle.value = style; uniforms.uGridSize.value = style === 0 ? 13 : 24; uniforms.uStrength.value = 1; gridInput.value = String(uniforms.uGridSize.value); gridOutput.value = String(uniforms.uGridSize.value); updateRegionTargetSizes(); setGlossControlsVisibility(); }, { signal: listenerAbort.signal }); -curvatureInput?.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uCurvature.value = value; const output = document.querySelector('#curvatureOut') as HTMLOutputElement | null; if (output) output.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -glossInput?.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uGlossStrength.value = value; if (glossOutput) glossOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -lightXInput?.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uLightPosition.value.x = value; if (lightXOutput) lightXOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -lightYInput?.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uLightPosition.value.y = value; if (lightYOutput) lightYOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -depthFileInput?.addEventListener('change', async () => { invalidateDepthRequests(); const request = depthRequest; const file = depthFileInput.files?.[0]; if (!file) return; manualDepthBusy = true; syncAIDepthButton(); depthDebug.clear(); const url = URL.createObjectURL(file); let texture: THREE.Texture | null = null; try { const image = new Image(); image.src = url; await image.decode(); if (disposed || request !== depthRequest) return; if (aspect > 0 && Math.abs(image.width / image.height - aspect) > 0.02) throw new Error('aspect'); texture = DepthProcessor.toTexture(image); if (disposed || request !== depthRequest) { texture.dispose(); texture = null; return; } setDepth(texture); texture = null; depthProvenance.hidden = true; status.textContent = '수동 depth map 적용됨 (0=뒤, 1=앞)'; } catch { if (!disposed && request === depthRequest) status.textContent = 'RGB와 종횡비가 다른 depth map입니다.'; } finally { texture?.dispose(); URL.revokeObjectURL(url); if (request === depthRequest) { depthFileInput.value = ''; manualDepthBusy = false; syncAIDepthButton(); } } }, { signal: listenerAbort.signal }); -resetButton.onclick = () => { cameraController.reset(); gyro.reset(); }; -gyroButton.onclick = async () => { gyroButton.textContent = `Gyroscope: ${(await gyro.toggle()) ? 'ON' : 'OFF'}`; }; -const observer = new ResizeObserver(resize); observer.observe(wrap); resize(); setMode('final'); setGlossControlsVisibility(); syncAIDepthButton(); -let last = performance.now(); let raf = 0; -function currentRegionSignature(): string { - const view = uniforms.uContentViewProjection.value.elements.map((value) => value.toFixed(4)).join(','); - const object = petDepth.matrixWorld.elements.map((value) => value.toFixed(4)).join(','); - const depth = depthUniforms.uDepthMap.value; - return [mode, active.uuid, depth.uuid, view, object, uniforms.uGridSize.value, uniforms.uStrength.value, uniforms.uCurvature.value, uniforms.uMosaicStyle.value, uniforms.uPaneSize.value.x, uniforms.uPaneSize.value.y, depthUniforms.uDepthScale.value, depthUniforms.uDepthBias.value, renderTarget.width, renderTarget.height, regionAtlasTarget.width, regionAtlasTarget.height].join('|'); -} -function currentSplitHistorySignature(): string { - const object = petDepth.matrixWorld.elements.map((value) => value.toFixed(4)).join(','); - const depth = depthUniforms.uDepthMap.value; - return [mode, effectInput.value, mosaicStyleInput.value, active.uuid, depth.uuid, uniforms.uRegionAvailable.value, uniforms.uGridSize.value, uniforms.uMosaicStyle.value, uniforms.uStrength.value, uniforms.uRegionStrength.value, uniforms.uCurvature.value, uniforms.uGlassZ.value, uniforms.uSourceZ.value, uniforms.uPaneSize.value.x, uniforms.uPaneSize.value.y, object, depthUniforms.uDepthScale.value, depthUniforms.uDepthBias.value, renderTarget.width, renderTarget.height, regionAtlasTarget.width, regionAtlasTarget.height, regionPaletteTarget.width, regionPaletteTarget.height].join('|'); -} -function clearSplitHistory(): void { - const previousTarget = renderer.getRenderTarget(); - const clearColor = renderer.getClearColor(new THREE.Color()); - const clearAlpha = renderer.getClearAlpha(); - renderer.setClearColor(0x000000, 0); - for (const target of splitHistoryTargets) { - renderer.setRenderTarget(target); - renderer.clear(true, false, false); - } - renderer.setRenderTarget(previousTarget); - renderer.setClearColor(clearColor, clearAlpha); - splitHistoryRead = 0; - splitHistoryInitialized = false; - regionHistoryUniform.value = splitHistoryTargets[0].texture; -} -function updateSplitHistory(dt: number): void { - const signature = currentSplitHistorySignature(); - if (signature !== splitHistorySignature) { - clearSplitHistory(); - splitHistorySignature = signature; - } - const enabled = (mode === 'final' || mode === 'glass') && effectInput.value === 'mosaic' && mosaicStyleInput.value === '0' && uniforms.uRegionAvailable.value > 0.5 && uniforms.uRegionStrength.value > 0.001 && uniforms.uStrength.value > 0.001; - if (!enabled) return; - - const writeIndex = 1 - splitHistoryRead; - historyUniforms.uPreviousHistory.value = splitHistoryTargets[splitHistoryRead].texture; - historyUniforms.uHistoryBlend.value = splitHistoryInitialized ? 1 - Math.exp(-dt / 0.07) : 1; - renderer.setRenderTarget(splitHistoryTargets[writeIndex]); - renderer.render(historyScene, postCamera); - renderer.setRenderTarget(null); - splitHistoryRead = writeIndex; - splitHistoryInitialized = true; - regionHistoryUniform.value = splitHistoryTargets[splitHistoryRead].texture; -} -function updateRegionPalette(): void { - const enabled = effectInput.value === 'mosaic' && mosaicStyleInput.value === '0' && uniforms.uRegionAvailable.value > 0.5 && uniforms.uRegionStrength.value > 0.001 && uniforms.uStrength.value > 0.001; - if (!enabled) return; - const signature = currentRegionSignature(); - if (!activeIsVideo && signature === regionSignature) return; - renderer.setRenderTarget(regionAtlasTarget); - renderer.render(atlasScene, postCamera); - renderer.setRenderTarget(regionPaletteTarget); - renderer.render(paletteScene, postCamera); - renderer.setRenderTarget(null); - regionSignature = signature; -} -function frame(now: number): void { - const dt = Math.min((now - last) / 1000, 0.1); last = now; - uniforms.uViewOffset.value.copy(cameraController.update(dt, sensitivity)); camera.updateMatrixWorld(true); petDepth.updateMatrixWorld(true); - uniforms.uPetWorldToLocal.value.copy(petDepth.matrixWorld).invert(); - uniforms.uContentViewProjection.value.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse); - uniforms.uContentInverseViewProjection.value.copy(uniforms.uContentViewProjection.value).invert(); - uniforms.uContentCameraPosition.value.copy(camera.position); uniforms.uTime.value = now / 1000; - const diagnostic = depthDebug.update(camera, petDepth, depthUniforms.uDepthScale.value, depthUniforms.uDepthBias.value, wrap.clientWidth, uniforms.uSourceZ.value, maxDepthValue); - debugOutput.textContent = diagnostic; debugOutput.hidden = !diagnostic; - if (mode === 'final' || mode === 'glass') { - renderer.setRenderTarget(renderTarget); renderer.render(scene, camera); uniforms.uSceneTexture.value = renderTarget.texture; - updateRegionPalette(); - updateSplitHistory(dt); - renderer.setRenderTarget(null); renderer.render(glassScene, postCamera); - const previousAutoClear = renderer.autoClear; renderer.autoClear = false; renderer.clearDepth(); renderer.render(frameScene, camera); renderer.autoClear = previousAutoClear; - } else { updateSplitHistory(dt); renderer.setRenderTarget(null); renderer.render(scene, camera); } - raf = requestAnimationFrame(frame); -} -raf = requestAnimationFrame(frame); -function teardown(): void { disposed = true; mediaRequest += 1; depthRequest += 1; aiDepthProvider.cancel(); aiDepthButton.disabled = true; clearPendingPair(); listenerAbort.abort(); cancelAnimationFrame(raf); observer.disconnect(); imageInput.onchange = null; videoInput.onchange = null; effectInput.onchange = null; sensitivityInput.oninput = null; resetButton.onclick = null; gyroButton.onclick = null; retry.onclick = null; pointer.dispose(); gyro.dispose(); loader.dispose(); renderTarget.dispose(); regionAtlasTarget.dispose(); regionPaletteTarget.dispose(); splitHistoryTargets.forEach((target) => target.dispose()); historyMesh.geometry.dispose(); historyMaterial.dispose(); atlasMesh.geometry.dispose(); atlasMaterial.dispose(); paletteMesh.geometry.dispose(); paletteMaterial.dispose(); windowReveal.dispose(); windowRevealMaterial.dispose(); frameMaterials.forEach((material) => material.dispose()); if (active !== emptyTex) active.dispose(); if (depthUniforms.uDepthMap.value !== depthMap) depthUniforms.uDepthMap.value.dispose(); depthMap.dispose(); petDepth.geometry.dispose(); petDepthMaterial.dispose(); geometry.dispose(); petMat.dispose(); glass.geometry.dispose(); glassMat.dispose(); frameGeometry.dispose(); emptyTex.dispose(); renderer.domElement.remove(); renderer.dispose(); hintElement.style.opacity = '0'; retry.remove(); debugOutput.remove(); } -const hot = import.meta as ImportMeta & { hot?: { dispose(fn: () => void): void } }; hot.hot?.dispose(teardown); diff --git a/docs/qa-depth-coupling/baseline-mosaic.frag b/docs/qa-depth-coupling/baseline-mosaic.frag deleted file mode 100644 index 46b411c..0000000 --- a/docs/qa-depth-coupling/baseline-mosaic.frag +++ /dev/null @@ -1,274 +0,0 @@ -uniform sampler2D uSceneTexture,uSceneDepth; -uniform sampler2D uProtectionDepthMap; -uniform mat4 uContentViewProjection,uContentInverseViewProjection; -uniform mat4 uPetWorldToLocal; -uniform vec3 uContentCameraPosition,uLightPosition,uBackgroundColor; -uniform float uGlassZ,uSourceZ,uGridSize,uStrength,uMosaicStyle,uCurvature,uGlossStrength; -uniform vec2 uViewOffset,uPetSize,uPaneSize; -uniform vec4 uPaneRect; -uniform sampler2D uRegionPalette; -uniform sampler2D uRegionAtlas,uRegionHistory; -uniform vec2 uRegionAtlasSize,uRegionGridSize,uRegionPaletteSize; -uniform float uRegionStrength,uRegionAvailable; -varying vec2 vUv; -vec2 projectUv(vec3 p){vec4 c=uContentViewProjection*vec4(p,1.);float w=abs(c.w)<.0001?(c.w<0.?-.0001:.0001):c.w;return c.xy/w*.5+.5;} -vec4 sampleScene(vec2 uv){return texture2D(uSceneTexture,clamp(uv,0.,1.));} -vec4 samplePane(vec2 pane){return sampleScene(projectUv(vec3((pane-.5)*uPaneSize,uGlassZ)));} -float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);} -vec2 hash2(vec2 p){return vec2(hash(p),hash(p+vec2(19.19,73.73)));} -vec2 cellBlurStep(vec2 cell,vec2 cellSize,float style){ - if(style<=.5)return cellSize*mix(.006,.018,hash(cell+vec2(5.))); - return cellSize*mix(.006,.012,hash(cell+vec2(5.))); -} -vec4 sampleCell(vec2 pane,vec2 sourceUv,float strength,vec2 cell,vec2 cellSize,float style){ - vec2 center=mix(pane,sourceUv,strength); - vec2 blurOffset=strength*cellBlurStep(cell,cellSize,style); - vec4 color; - if(style<=.5){ - color=samplePane(center)*.6; - color+=samplePane(center+vec2(blurOffset.x,0.))*.1; - color+=samplePane(center-vec2(blurOffset.x,0.))*.1; - color+=samplePane(center+vec2(0.,blurOffset.y))*.1; - color+=samplePane(center-vec2(0.,blurOffset.y))*.1; - }else{ - color=samplePane(center)*.4; - color+=samplePane(center+vec2(blurOffset.x,0.))*.15; - color+=samplePane(center-vec2(blurOffset.x,0.))*.15; - color+=samplePane(center+vec2(0.,blurOffset.y))*.15; - color+=samplePane(center-vec2(0.,blurOffset.y))*.15; - } - return color; -} -float safeZ(float z){return abs(z)<.0001?(z<0.?-.0001:.0001):z;} -vec3 bend(vec3 i,vec3 n){vec3 r=refract(i,n,.75);return length(r)<.0001?i:r;} -float softLimit(float value,float limit){return value*limit/(limit+abs(value));} -float surfaceCurvature(){float curvature=clamp(uCurvature,-1.,1.),excess=max(curvature-.65,0.);return curvature-(.25/.35)*excess*excess;} -float signedCurvatureScale(){return clamp(surfaceCurvature()/.65,-1.25,1.25);} -float regionDistance(vec3 a,vec3 b){vec3 d=a-b;float y=dot(d,vec3(.299,.587,.114));return dot(d,d)+.35*y*y;} -float regionLuminance(vec3 c){return dot(c,vec3(.299,.587,.114));} -vec3 regionColor(vec2 cell,float index){vec2 uv=(vec2(cell.x*5.+index,cell.y)+.5)/uRegionPaletteSize;return texture2D(uRegionPalette,uv).rgb;} -float nearestRegion(vec3 color,vec2 cell){float best=0.,distance=regionDistance(color,regionColor(cell,0.));for(int i=1;i<4;i++){float candidate=regionDistance(color,regionColor(cell,float(i)));if(candidate1.||sceneUv.y<0.||sceneUv.y>1.)return false; - float depth=texture2D(uSceneDepth,sceneUv).x; - if(depth>=.999999)return false; - vec4 clip=vec4(sceneUv*2.-1.,depth*2.-1.,1.); - vec4 world=uContentInverseViewProjection*clip; - if(abs(world.w)<.0001)return false; - worldPoint=world.xyz/world.w; - return true; -} -float regionSurfaceValid(vec2 sceneUv,vec3 glassHit){ - vec3 worldPoint; - if(!reconstructScenePoint(sceneUv,worldPoint))return 0.; - float axialGap=glassHit.z-worldPoint.z; - if(axialGap<=.0001)return 0.; - return 1.; -} -float regionProtectionWeight(vec2 sceneUv){ - vec3 worldPoint; - if(!reconstructScenePoint(sceneUv,worldPoint))return 0.; - vec3 localPoint=(uPetWorldToLocal*vec4(worldPoint,1.)).xyz; - if(localPoint.x<-.5||localPoint.x>.5||localPoint.y<-.5||localPoint.y>.5)return 0.; - vec2 sourceUv=localPoint.xy+.5; - float sourceDepth=texture2D(uProtectionDepthMap,sourceUv).r; - return smoothstep(.8,.95,sourceDepth); -} -#ifdef REGION_ATLAS -float regionAtlasEvidence(vec2 sceneUv,vec3 color,vec3 glassHit){ - if(regionSurfaceValid(sceneUv,glassHit)<=0.)return 0.; - return regionProtectionWeight(sceneUv)*(1.-smoothstep(.10,.20,regionLuminance(color))); -} -vec4 regionAtlasProbe(vec3 sceneHit,vec2 worldOffset,vec3 glassHit){ - vec2 probeSceneUv=projectUv(sceneHit+vec3(worldOffset,0.)); - vec4 probe=sampleScene(probeSceneUv); - return vec4(probe.rgb,regionAtlasEvidence(probeSceneUv,probe.rgb,glassHit)); -} -vec4 regionAtlasScore(vec3 centerColor,float centerEvidence,vec3 probeColor,float probeEvidence){ - float evidenceGain=probeEvidence-centerEvidence,darkGain=regionLuminance(centerColor)-regionLuminance(probeColor),blend=0.; - if(probeEvidence>.05&&evidenceGain>.02&&darkGain>.015)blend=min(.4,evidenceGain*2.)*min(1.,max(0.,darkGain*4.)); - return vec4(blend,probeEvidence,0.,0.); -} -vec3 regionAtlasRepresentative(vec3 centerColor,float centerEvidence,vec3 sceneHit,vec3 glassHit,out float evidence){ - vec3 bestColor=centerColor;float bestEvidence=centerEvidence,bestBlend=0.; - vec2 probeStep=uPaneSize/(uRegionGridSize*8.)*.25; - vec4 probe,score; - probe=regionAtlasProbe(sceneHit,vec2(probeStep.x,0.),glassHit);score=regionAtlasScore(centerColor,centerEvidence,probe.rgb,probe.a);if(score.x>bestBlend){bestColor=mix(centerColor,probe.rgb,score.x);bestEvidence=max(centerEvidence,probe.a);bestBlend=score.x;} - probe=regionAtlasProbe(sceneHit,vec2(-probeStep.x,0.),glassHit);score=regionAtlasScore(centerColor,centerEvidence,probe.rgb,probe.a);if(score.x>bestBlend){bestColor=mix(centerColor,probe.rgb,score.x);bestEvidence=max(centerEvidence,probe.a);bestBlend=score.x;} - probe=regionAtlasProbe(sceneHit,vec2(0.,probeStep.y),glassHit);score=regionAtlasScore(centerColor,centerEvidence,probe.rgb,probe.a);if(score.x>bestBlend){bestColor=mix(centerColor,probe.rgb,score.x);bestEvidence=max(centerEvidence,probe.a);bestBlend=score.x;} - probe=regionAtlasProbe(sceneHit,vec2(0.,-probeStep.y),glassHit);score=regionAtlasScore(centerColor,centerEvidence,probe.rgb,probe.a);if(score.x>bestBlend){bestColor=mix(centerColor,probe.rgb,score.x);bestEvidence=max(centerEvidence,probe.a);bestBlend=score.x;} - evidence=bestEvidence; - return bestColor; -} -#endif -void evaluateCell(vec2 cell,vec2 local,vec2 grid,vec2 cellSize,vec2 cellDimensions,float cellWorld,float opticalTravel,float style,out vec2 affineUv,out mat2 transform,out vec2 curvedSlope,out vec2 facetSlope){ - vec2 random=hash2(cell),widths; - if(style>.5){ - widths=mix(vec2(.82),vec2(1.12),hash2(cell+vec2(11.4,9.8))); - float angle=(random.x-.5)*.08,c=cos(angle),s=sin(angle); - transform=mat2(widths.x*c,-widths.y*s,widths.x*s,widths.y*c); - float centerJitter=.16; - vec2 sourceCenter=(cell+.5)/grid+(random-.5)*centerJitter*cellSize; - affineUv=sourceCenter+transform*(local*cellSize); - }else{ - // Default style keeps a single continuous image footprint across cells. - transform=mat2(1.); - affineUv=(cell+.5)/grid+local*cellSize; - } - - // Positive height bulges toward the observer (+Z); negative height is concave. - float curvature=clamp(uCurvature,-1.,1.),surfaceCurvatureValue=surfaceCurvature(); - vec2 q=clamp(2.*local,-1.,1.),q2=q*q,q3=q2*q,b=1.-q2*q2; - if(style>.5){ - float amplitude=mix(.92,1.08,hash(cell+vec2(41.7,17.3))),height=.009*cellWorld*surfaceCurvatureValue*amplitude; - vec2 skew=(hash2(cell+vec2(23.8,61.2))-.5)*.28;float asym=1.+dot(skew,q); - vec2 dhdq=height*vec2(-4.*q3.x*b.y*asym+b.x*b.y*skew.x,-4.*q3.y*b.x*asym+b.x*b.y*skew.y); - vec2 grad=-2.*dhdq/cellDimensions; - curvedSlope=grad+(random-.5)*.012;facetSlope=(random-.5)*.012; - }else{ - curvedSlope=.30*cellDimensions/max(abs(opticalTravel),.6)*signedCurvatureScale()*sin(6.2831853*local); - facetSlope=vec2(0.); - } -} -void main(){ - vec2 screenUv=vUv; -#ifdef REGION_ATLAS - vec2 atlasPixel=floor(vUv*uRegionAtlasSize),atlasCell=floor(atlasPixel/8.),atlasLocal=(mod(atlasPixel,8.)+.5)/8.; - vec2 atlasPaneUv=(atlasCell+atlasLocal)/uRegionGridSize; - screenUv=projectUv(vec3((atlasPaneUv-.5)*uPaneSize,uGlassZ)); -#endif - if(uStrength<=.001){ -#ifdef REGION_ATLAS - gl_FragColor=vec4(sampleScene(screenUv).rgb,0.); -#else - gl_FragColor=sampleScene(screenUv); - #include -#endif - return;} - vec4 f=uContentInverseViewProjection*vec4(screenUv*2.-1.,1.,1.);float fw=abs(f.w)<.0001?(f.w<0.?-.0001:.0001):f.w;vec3 farWorld=f.xyz/fw;vec3 i=normalize(farWorld-uContentCameraPosition);float gt=(uGlassZ-uContentCameraPosition.z)/safeZ(i.z);vec3 gh=uContentCameraPosition+i*gt; - vec2 paneUv=gh.xy/uPaneSize+.5;vec2 grid=vec2(uGridSize,max(1.,uGridSize*uPaneSize.y/uPaneSize.x));vec2 gridUv=paneUv*grid,cell=floor(gridUv),local=fract(gridUv)-.5,cellSize=1./grid;float style=clamp(uMosaicStyle,0.,1.),cellWorld=min(uPaneSize.x/grid.x,uPaneSize.y/grid.y); -#ifdef REGION_ATLAS - paneUv=atlasPaneUv;grid= uRegionGridSize;gridUv=paneUv*grid;cell=floor(gridUv);local=fract(gridUv)-.5;cellSize=1./grid;cellWorld=min(uPaneSize.x/grid.x,uPaneSize.y/grid.y); -#endif - if(paneUv.x<0.||paneUv.x>1.||paneUv.y<0.||paneUv.y>1.){ -#ifdef REGION_ATLAS - gl_FragColor=vec4(uBackgroundColor,0.); -#else - gl_FragColor=vec4(uBackgroundColor,1.); - #include -#endif - return;} - vec2 cellDimensions=uPaneSize/grid; - float opticalTravel=-max(abs(uSourceZ-gh.z),.6); - vec2 affineUv,curvedSlope,facetSlope;mat2 transform; - evaluateCell(cell,local,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,affineUv,transform,curvedSlope,facetSlope); - if(style<=.5){ - vec2 smoothFacet=.003*vec2(sin(6.2831853*paneUv.x),sin(6.2831853*paneUv.y)); - curvedSlope+=smoothFacet;facetSlope=smoothFacet; - }else{ - vec2 edge=.5-abs(local),neighborSign=mix(vec2(-1.),vec2(1.),step(vec2(0.),local)); - float normalBlend=.16; - vec2 weights=1.-smoothstep(vec2(-normalBlend),vec2(normalBlend),edge); - float xSplitWeight=weights.x*(1.-weights.y),ySplitWeight=(1.-weights.x)*weights.y; - float diagonalSplitWeight=weights.x*weights.y,centerSplitWeight=(1.-weights.x)*(1.-weights.y); - if(weights.x>0.||weights.y>0.){ - vec2 neighborAffine,neighborCurved,neighborFacet;mat2 neighborTransform; - vec2 xWeight=vec2(xSplitWeight,0.); - vec2 yWeight=vec2(0.,ySplitWeight); - affineUv*=centerSplitWeight;transform*=centerSplitWeight;curvedSlope*=centerSplitWeight;facetSlope*=centerSplitWeight; - if(xWeight.x>0.){ - vec2 offset=vec2(neighborSign.x,0.); - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*xWeight.x;transform+=neighborTransform*xWeight.x;curvedSlope+=neighborCurved*xWeight.x;facetSlope+=neighborFacet*xWeight.x; - } - if(yWeight.y>0.){ - vec2 offset=vec2(0.,neighborSign.y); - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*yWeight.y;transform+=neighborTransform*yWeight.y;curvedSlope+=neighborCurved*yWeight.y;facetSlope+=neighborFacet*yWeight.y; - } - if(diagonalSplitWeight>0.){ - vec2 offset=neighborSign; - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*diagonalSplitWeight;transform+=neighborTransform*diagonalSplitWeight;curvedSlope+=neighborCurved*diagonalSplitWeight;facetSlope+=neighborFacet*diagonalSplitWeight; - } - } - } - vec3 nCurved=normalize(vec3(curvedSlope,1.)),nFacet=normalize(vec3(facetSlope,1.)); - vec3 straightHit=gh+i*((uSourceZ-gh.z)/safeZ(i.z)); - vec3 curvedRay=bend(i,nCurved),curvedHit=gh+curvedRay*((uSourceZ-gh.z)/safeZ(curvedRay.z)); - // Keep the artistic Mosaic optical path independent of physical glass-to-photo contact distance. - vec2 rawDelta=(curvedRay.xy/safeZ(curvedRay.z)-i.xy/safeZ(i.z))*opticalTravel; - vec2 worldDelta=vec2(softLimit(rawDelta.x,cellWorld*.55),softLimit(rawDelta.y,cellWorld*.55)); - if(style>.5){ - vec3 facetRay=bend(i,nFacet);vec3 facetHit=gh+facetRay*((uSourceZ-gh.z)/safeZ(facetRay.z)); - vec2 base=facetHit.xy-straightHit.xy,curve=curvedHit.xy-facetHit.xy; - worldDelta=vec2(softLimit(base.x,cellWorld*.08),softLimit(base.y,cellWorld*.08)); - vec2 d=curve/cellWorld; - worldDelta+=vec2(.3*d.x/(.3+abs(d.x)),.3*d.y/(.3+abs(d.y)))*cellWorld; - }else{ - vec3 referenceI=normalize(gh-vec3(0.,0.,uContentCameraPosition.z)),referenceRay=bend(referenceI,nCurved); - vec2 incidenceDelta=curvedRay.xy/max(-curvedRay.z,.0001)-referenceRay.xy/max(-referenceRay.z,.0001); - vec2 boundedIncidence=incidenceDelta/sqrt(incidenceDelta*incidenceDelta+vec2(.025*.025)); - vec2 cellEnvelope=.5+.5*cos(6.2831853*local); - worldDelta+=boundedIncidence*cellEnvelope*cellDimensions*signedCurvatureScale()*.18; - } - vec2 sampleUv=affineUv+transform*(worldDelta/uPaneSize); - float edgeDistance=min(min(paneUv.x,paneUv.y),min(1.-paneUv.x,1.-paneUv.y));float edgeTaper=style<=.5?1.25:.75;float edgeWeight=smoothstep(0.,max(cellSize.x,cellSize.y)*edgeTaper,edgeDistance);float strength=clamp(uStrength,0.,1.)*edgeWeight; - vec4 color;vec3 sceneHit=straightHit+vec3(worldDelta*strength,0.);vec2 finalSceneUv=projectUv(sceneHit); -#ifdef REGION_ATLAS - vec3 atlasCenterColor=sampleScene(finalSceneUv).rgb; - float atlasEvidence=regionProtectionWeight(finalSceneUv)*(1.-smoothstep(.10,.20,regionLuminance(atlasCenterColor))); -#endif -#ifdef REGION_ATLAS - if(style<=.5){ - float representativeEvidence=atlasEvidence; - color=vec4(regionAtlasRepresentative(atlasCenterColor,atlasEvidence,sceneHit,gh,representativeEvidence),representativeEvidence); - atlasEvidence=representativeEvidence; - }else{ - color=sampleCell(paneUv,sampleUv,strength,cell,cellSize,style); - } -#else - if(style<=.5){ - color=sampleScene(finalSceneUv); - }else{ - color=sampleCell(paneUv,sampleUv,strength,cell,cellSize,style); - } -#endif -#ifndef REGION_ATLAS - if(uRegionAvailable>.5&&uRegionStrength>.001&&uMosaicStyle<.5){ - vec3 p0=regionColor(cell,0.),p1=regionColor(cell,1.),p2=regionColor(cell,2.),p3=regionColor(cell,3.); - float ownLabel=nearestRegion(color.rgb,p0,p1,p2,p3);vec4 votes=vec4(0.);float totalWeight=0.,ownWeight=0.; - vec2 texelCoord=fract(gridUv)*8.-.5,anchor=floor(texelCoord+.5); - for(int y=-1;y<=1;y++)for(int x=-1;x<=1;x++){ - vec2 offset=vec2(float(x),float(y)),delta=anchor+offset-texelCoord; - float weight=pow(max(0.,1.-length(delta)/1.5),2.); - if(weight>0.){ - vec3 atlasColor=regionAtlasColor(cell,anchor+offset);float label=nearestRegion(atlasColor,p0,p1,p2,p3); - votes+=vec4(step(abs(label-vec4(0.,1.,2.,3.)),vec4(.1)))*weight;totalWeight+=weight; - ownWeight+=step(abs(label-ownLabel),.1)*weight; - } - } - float winningLabel=ownLabel,winningWeight=ownWeight; - if(votes.x>winningWeight){winningLabel=0.;winningWeight=votes.x;}if(votes.y>winningWeight){winningLabel=1.;winningWeight=votes.y;}if(votes.z>winningWeight){winningLabel=2.;winningWeight=votes.z;}if(votes.w>winningWeight){winningLabel=3.;winningWeight=votes.w;} - bool simplify=totalWeight>0.&&winningWeight/totalWeight>.55&&ownWeight/totalWeight<.40; - float radialLabel=simplify?winningLabel:ownLabel;vec3 radialColor=selectRegion(p0,p1,p2,p3,radialLabel); - vec2 historyTexel=clamp(floor(fract(gridUv)*8.),vec2(0.),vec2(7.)); - vec2 historyUv=(cell*8.+historyTexel+.5)/uRegionAtlasSize; - vec4 splitHistory=texture2D(uRegionHistory,historyUv); - vec3 splitColor=splitHistory.a>.00001?splitHistory.rgb/splitHistory.a:radialColor; - vec3 candidateColor=mix(radialColor,splitColor,splitHistory.a); - color.rgb=mix(color.rgb,candidateColor,clamp(uRegionStrength*clamp(uStrength,0.,1.)*regionSurfaceValid(finalSceneUv,gh),0.,1.)); - } -#endif -#ifndef REGION_ATLAS - color.a=1.; - vec3 v=normalize(uContentCameraPosition-gh),reflected=reflect(-v,nCurved); float lightT=(uLightPosition.z-gh.z)/safeZ(reflected.z); vec2 lightHit=gh.xy+reflected.xy*lightT; vec2 halfSize=vec2(.32,.42)*min(uPaneSize.x,uPaneSize.y); vec2 windowCoord=abs(lightHit-uLightPosition.xy)/halfSize; vec2 windowMask=1.-smoothstep(vec2(.45),vec2(1.15),windowCoord); float surfaceReflectionWeight=mix(.35,1.,edgeWeight); float glossStrength=clamp(uGlossStrength,0.,1.); float spec=windowMask.x*windowMask.y*step(.0001,reflected.z)*step(0.,lightT); float specGloss=spec*glossStrength*.12*surfaceReflectionWeight*clamp(uStrength,0.,1.); vec2 broadWindowMask=1.-smoothstep(vec2(.15),vec2(1.75),windowCoord); float broadFacing=pow(max(dot(nCurved,v),0.),2.); float broadReflection=broadWindowMask.x*broadWindowMask.y*broadFacing*glossStrength*.035*surfaceReflectionWeight*clamp(uStrength,0.,1.); color.rgb=mix(color.rgb,vec3(1.),specGloss+broadReflection); gl_FragColor=color; - #include -#else - color.a=atlasEvidence; - gl_FragColor=color; -#endif -} diff --git a/docs/qa-depth-coupling/dog1-drag.jpg b/docs/qa-depth-coupling/dog1-drag.jpg deleted file mode 100644 index aa5709b..0000000 Binary files a/docs/qa-depth-coupling/dog1-drag.jpg and /dev/null differ diff --git a/docs/qa-depth-coupling/dog1-final.jpg b/docs/qa-depth-coupling/dog1-final.jpg deleted file mode 100644 index ebd63ac..0000000 Binary files a/docs/qa-depth-coupling/dog1-final.jpg and /dev/null differ diff --git a/docs/qa-depth-coupling/dog2-final.jpg b/docs/qa-depth-coupling/dog2-final.jpg deleted file mode 100644 index e508543..0000000 Binary files a/docs/qa-depth-coupling/dog2-final.jpg and /dev/null differ diff --git a/docs/qa-depth-coupling/dog2-mobile.jpg b/docs/qa-depth-coupling/dog2-mobile.jpg deleted file mode 100644 index 2995181..0000000 Binary files a/docs/qa-depth-coupling/dog2-mobile.jpg and /dev/null differ diff --git a/docs/qa-depth-coupling/dog2-noglass.jpg b/docs/qa-depth-coupling/dog2-noglass.jpg deleted file mode 100644 index 416af6e..0000000 Binary files a/docs/qa-depth-coupling/dog2-noglass.jpg and /dev/null differ diff --git a/docs/qa-depth-coupling/glass-only-gloss0.jpg b/docs/qa-depth-coupling/glass-only-gloss0.jpg deleted file mode 100644 index a6c0664..0000000 Binary files a/docs/qa-depth-coupling/glass-only-gloss0.jpg and /dev/null differ diff --git a/docs/qa-depth-coupling/glass-only.jpg b/docs/qa-depth-coupling/glass-only.jpg deleted file mode 100644 index 50f9ccb..0000000 Binary files a/docs/qa-depth-coupling/glass-only.jpg and /dev/null differ diff --git a/docs/qa-depth-coupling/report.md b/docs/qa-depth-coupling/report.md deleted file mode 100644 index 4315d45..0000000 --- a/docs/qa-depth-coupling/report.md +++ /dev/null @@ -1,35 +0,0 @@ -# 깊이·굴절 연결 개선 — 2026-09-30 - -사용자가 승인한 재점검 후속 구현. 옵션 1·2 문서는 보존하며 이번 결과를 새 개선안으로 구분한다. 수정 직전 `main.ts`, `mosaic.frag`는 이 폴더 baseline 파일에 보존했다. Git 저장소가 아니므로 커밋은 생성하지 않았다. - -## 변경 - -- `src/main.ts`: 미디어 로드 시 zoom/pan 초기화 제거. 명시적 구도 초기화 버튼은 유지. RGB/Depth 공통 변환, 최대 depth 기준 안전 간격은 유지한다. -- `src/depth/DepthProcessor.ts`, `src/constants/depth.ts`: 사진의 상대 depth 히스토그램에서 P50–P85 증거 범위를 계산. 범위가 좁으면 P5–P95로 재평가하고, 여전히 평탄하면 어두운 색면 증거를 끈다. 단일 가까운 이상치에 고정 문턱이 끌리지 않게 한다. 사진 전체 통계이며 얼굴/강아지 검출은 아니다. -- `src/shaders/mosaic.frag`: 기존 연출 굴절을 출발점으로 세 번의 screen-depth 반복 보정을 추가. atlas/final에 동일 적용. 미수렴·무효 depth·유리 앞 표면에서는 원래 샘플로 복귀한다. 이동은 최대 셀 폭 0.35에 혼합 0.65를 적용하므로 0.2275셀 이하. 색면 강도의 거리 감쇠나 최종 원본 눈·코 복원은 없다. -- `src/constants/glass.ts`, Mosaic: 공통 환경의 어두운 아래/밝은 위 명암과 Fresnel 각도 항을 작은 반사로 추가. 기존 직사각 광원은 유지. 광택·굴절 0에서 새 반사도 0. 조각 유리 모드에만 적용하며 임의 시간 변화는 없다. - -## 검증 - -- `npm.cmd run build`: TypeScript/Vite 통과. 기존 500kB 청크 경고 유지. -- `scripts/test-*.mjs` 9개 모두 통과. 새 depth-evidence 테스트는 미구현 상태와 bimodal 결함에서 각각 실패를 확인한 뒤 통과했다. 새 depth-refraction 테스트는 반사 게이트 추가 전 실패 후 통과했다. -- 기존 surface-reflection의 atlas 전체 바이트 동일성 검사는 의도적으로 바뀐 광학 계산을 허용하고 반사가 atlas에 들어가지 않는 검사로 변경했다. 기존 반사 상수 출력/atlas 오염 mutation 검사는 계속 통과한다. 고정 depth 문턱 source 검사는 새 uniform 연결 검사로 변경했다. -- 수학/소스 검사는 GPU 품질의 증명이 아니다. 기존 continuity 수치도 새 screen-depth 보정의 모든 경계/시점 연속성을 증명하지 않는다. -- 브라우저: dog1/dog2 자동 AI 추론 성공. dog1 정면·드래그, dog2 Final/No Glass, Glass Only 및 광택 0을 확인. 광택 0의 유리 단독 화면에는 반사가 남지 않았다. -- dog1 확대1.50/팬+0.10/-0.10을 설정한 후 같은 사진 재로드: 로드 직후와 AI 완료 후 값 유지. 명시적 구도 초기화 후 기본 구도로 돌아왔다. -- dog2 390×844 viewport에서 유리/사진 배치 확인, override 해제. 실제 휴대폰 검증은 아니다. -- 최종 콘솔 조회에서 error는 없었고 X3595(가변 반복문 내 gradient 연산) 경고 1건이 수집됐다. 기존에도 있던 종류의 경고이나 새 depth 반복 샘플링에도 관련될 수 있다. 다른 GPU에서의 영향은 미검증이다. -- 창 크기 변경으로 캡처마다 viewport가 다르다. 저장 화면은 정성적 확인용이며 픽셀 단위 전후 비교나 효과 크기의 정량 증거로 사용하지 않는다. - -## 시각 판단과 남은 한계 - -흰 강아지의 두 눈·코 사각 면은 유지된다. 깊이에 따른 색면 위치가 바뀌며 반사는 절제된 수준이다. 어두운 강아지는 Grid13에서 눈·코 구분이 여전히 약하다. 이 결과를 모든 사진의 식별성 개선 또는 Ref1 재현 완료로 판정하지 않는다. - -단일 깊이 표면과 화면에 보이는 depth만 사용하므로 가려진 옆면/배경을 복원하지 않는다. 실제 굴절 광선 추적의 완전한 해법이 아닌 기존 연출에 대한 제한된 보정이다. 강아지/얼굴을 분리하지 않으므로 얼굴을 유리 바로 뒤에 놓는 의미 기반 배치는 미구현이며 관통 방지를 위한 기존 전체 최대 depth 배치를 유지한다. 얼굴 확대·자동 팬은 추가하지 않았다. - -연속 영상의 깜빡임, GPU별 성능/FPS, 카메라 범위 전체 끝점, 실기기 터치·자이로, 다른 사진 크기에서의 전수 검증은 미실시. 사진은 로컬 QA 용도이며 게시하지 않았다. - -실행: `npm.cmd run dev -- --host 127.0.0.1 --port 5174`. - -![흰 강아지 개선안](dog1-final.jpg) -![어두운 강아지 개선안](dog2-final.jpg) diff --git a/docs/qa-five-photos/asset-hashes.json b/docs/qa-five-photos/asset-hashes.json deleted file mode 100644 index f5c830d..0000000 --- a/docs/qa-five-photos/asset-hashes.json +++ /dev/null @@ -1,22 +0,0 @@ -[ - { - "file": "public/assets/qa/dog1.jpeg", - "same": true, - "sha256": "513BD52B036D0150C97361D38F56F1260E00B5E4A52F2D308200DA2B82630667" - }, - { - "file": "public/assets/qa/dog2.jpeg", - "same": true, - "sha256": "FC5BC7517A9728B3119E080071C976A1378E7C4B36FAD2F756ED32C15BB23B6D" - }, - { - "file": "public/assets/qa/dog3.webp", - "same": true, - "sha256": "20F9DBF91AA31B900F9ECF8C68A412169C9122597FEBB820596E54009DCB27E3" - }, - { - "file": "public/assets/qa/dog4.jpeg", - "same": true, - "sha256": "B311E7803D96CB19B5A13080A045C14EA563CCF9CC7DFEBA235A3664BB5C9DF6" - } -] diff --git a/docs/qa-five-photos/dog1-default.png b/docs/qa-five-photos/dog1-default.png deleted file mode 100644 index 97f4dad..0000000 Binary files a/docs/qa-five-photos/dog1-default.png and /dev/null differ diff --git a/docs/qa-five-photos/dog1-final-ui.png b/docs/qa-five-photos/dog1-final-ui.png deleted file mode 100644 index 1181144..0000000 Binary files a/docs/qa-five-photos/dog1-final-ui.png and /dev/null differ diff --git a/docs/qa-five-photos/dog1-mobile-drag.png b/docs/qa-five-photos/dog1-mobile-drag.png deleted file mode 100644 index ac35650..0000000 Binary files a/docs/qa-five-photos/dog1-mobile-drag.png and /dev/null differ diff --git a/docs/qa-five-photos/dog1-mobile.png b/docs/qa-five-photos/dog1-mobile.png deleted file mode 100644 index 3f62f78..0000000 Binary files a/docs/qa-five-photos/dog1-mobile.png and /dev/null differ diff --git a/docs/qa-five-photos/dog1-noglass.png b/docs/qa-five-photos/dog1-noglass.png deleted file mode 100644 index 453200a..0000000 Binary files a/docs/qa-five-photos/dog1-noglass.png and /dev/null differ diff --git a/docs/qa-five-photos/dog1-tuned.png b/docs/qa-five-photos/dog1-tuned.png deleted file mode 100644 index 4226365..0000000 Binary files a/docs/qa-five-photos/dog1-tuned.png and /dev/null differ diff --git a/docs/qa-five-photos/dog2-default.png b/docs/qa-five-photos/dog2-default.png deleted file mode 100644 index 1c3b810..0000000 Binary files a/docs/qa-five-photos/dog2-default.png and /dev/null differ diff --git a/docs/qa-five-photos/dog2-mobile.png b/docs/qa-five-photos/dog2-mobile.png deleted file mode 100644 index b87c95a..0000000 Binary files a/docs/qa-five-photos/dog2-mobile.png and /dev/null differ diff --git a/docs/qa-five-photos/dog2-noglass.png b/docs/qa-five-photos/dog2-noglass.png deleted file mode 100644 index b1bfc76..0000000 Binary files a/docs/qa-five-photos/dog2-noglass.png and /dev/null differ diff --git a/docs/qa-five-photos/dog2-tuned.png b/docs/qa-five-photos/dog2-tuned.png deleted file mode 100644 index ea0963f..0000000 Binary files a/docs/qa-five-photos/dog2-tuned.png and /dev/null differ diff --git a/docs/qa-five-photos/dog3-default.png b/docs/qa-five-photos/dog3-default.png deleted file mode 100644 index ef58da9..0000000 Binary files a/docs/qa-five-photos/dog3-default.png and /dev/null differ diff --git a/docs/qa-five-photos/dog3-mobile.png b/docs/qa-five-photos/dog3-mobile.png deleted file mode 100644 index 5f5ad37..0000000 Binary files a/docs/qa-five-photos/dog3-mobile.png and /dev/null differ diff --git a/docs/qa-five-photos/dog3-noglass.png b/docs/qa-five-photos/dog3-noglass.png deleted file mode 100644 index a873e81..0000000 Binary files a/docs/qa-five-photos/dog3-noglass.png and /dev/null differ diff --git a/docs/qa-five-photos/dog3-tuned.png b/docs/qa-five-photos/dog3-tuned.png deleted file mode 100644 index 621e3ed..0000000 Binary files a/docs/qa-five-photos/dog3-tuned.png and /dev/null differ diff --git a/docs/qa-five-photos/dog4-default.png b/docs/qa-five-photos/dog4-default.png deleted file mode 100644 index 24c65bd..0000000 Binary files a/docs/qa-five-photos/dog4-default.png and /dev/null differ diff --git a/docs/qa-five-photos/dog4-mobile-drag.png b/docs/qa-five-photos/dog4-mobile-drag.png deleted file mode 100644 index 132b3c9..0000000 Binary files a/docs/qa-five-photos/dog4-mobile-drag.png and /dev/null differ diff --git a/docs/qa-five-photos/dog4-mobile.png b/docs/qa-five-photos/dog4-mobile.png deleted file mode 100644 index 762a4a4..0000000 Binary files a/docs/qa-five-photos/dog4-mobile.png and /dev/null differ diff --git a/docs/qa-five-photos/dog4-noglass.png b/docs/qa-five-photos/dog4-noglass.png deleted file mode 100644 index 8a4308d..0000000 Binary files a/docs/qa-five-photos/dog4-noglass.png and /dev/null differ diff --git a/docs/qa-five-photos/dog4-tuned.png b/docs/qa-five-photos/dog4-tuned.png deleted file mode 100644 index 9fe6345..0000000 Binary files a/docs/qa-five-photos/dog4-tuned.png and /dev/null differ diff --git a/docs/qa-five-photos/review.md b/docs/qa-five-photos/review.md deleted file mode 100644 index 6f7bbe4..0000000 --- a/docs/qa-five-photos/review.md +++ /dev/null @@ -1,52 +0,0 @@ -# 테스트 사진 5장 / 레퍼런스 2장 QA - -2026-09-13. 로컬 테스트 전용. 원본 사진·레퍼런스의 외부 게시 권한을 의미하지 않는다. - -## 기준과 입력 - -레퍼런스1 `reference1.png`는 강한 색면/사각 셀의 보조 기준. 레퍼런스2 `reference2.png`가 주 기준이며 큰 눈·코 조각, 주변의 넓게 늘어난 면, 셀별 정보량 차이와 자연스러운 사각 유리 질감을 평가한다. 서로 다른 원본 사진이므로 픽셀 유사도 수치는 사용하지 않는다. - -기존 `sample-pet.png` + 사용자 첨부 멍멍이1~4 = 총 5장. 추가 파일은 `public/assets/qa/dog1.jpeg`, `dog2.jpeg`, `dog3.webp`, `dog4.jpeg`로 원본 그대로 복사했다. SHA-256 일치는 `asset-hashes.json`에 기록했다. - -기존 샘플에만 수작업 테스트 Depth가 있다. 추가 4장은 Depth 없는 평면 사진이며 부위별 3D parallax 검증 대상이 아니다. 원본에 없는 깊이를 생성하거나 추정했다고 표현하지 않는다. - -## 실제 비교 설정 - -기본 광학 설정은 Mosaic 조각 유리, Grid10 / Distortion .90 / 굴곡 +.65 / 광택 .30. 추가 사진 기본 구도는 1/0/0, 기존 샘플은 기존 2.4/-.10/-.35를 유지했다. 데스크톱 1280×720에서 각 사진 No Glass, 기본 Final, 조정 Final을 기록했다. 아래는 제한된 수동 비교에서 선택한 후보이며 전역 최적값이 아니다. - -| 사진 | 확대 / X / Y | Grid | Distortion | 굴곡 | 광택 | 판단 | -|---|---|---:|---:|---:|---:|---| -| 기존 샘플 | 3 / -.15 / -.35 | 8 | .90 | +.65 | .15 | 눈·코 식별 양호. 좁은 세로 구도와 어두운 배경의 한계 | -| 멍멍이1: 흰 포메라니안 | 2.3 / -.10 / -.30 | 8 | .90 | +.65 | .15 | 가장 유망. 큰 눈·코와 밝은 얼굴, 다만 큰 사각 면보다 얼굴 확대 인상이 강함 | -| 멍멍이2: 검은 털 전신 | 2.2 / +.60 / -.60 | 8 | .90 | +.65 | .15 | 얼굴이 커져 식별 개선. 검은 눈 주변 세부가 묻히고 물결 느낌이 남음 | -| 멍멍이3: 두 마리 | 1.3 / +.50 / 0 | 12 | .75 | +.65 | .15 | 두 표정 유지 우선. 확대1.45/X.10은 왼쪽 얼굴이 잘려 제외 | -| 멍멍이4: 옆얼굴 | 1.55 / +.10 / -.85 | 12 | .65 | +.35 | .15 | 기본값에서 눌리던 눈 식별 개선. 두 눈 정면 레퍼런스와 직접 일치는 어려움 | - -공통 조명 X .60/Y .80, Camera Offset .30, sensitivity1. 셰이더와 광학 기본값은 이번 작업에서 수정하지 않았다. 사진 선택은 구도를 초기화하며, 위 후보값은 수동 적용한다. - -## 시각 결과 - -5장 모두 레퍼런스2의 자연스러운 사각 유리 질감에 도달하지 않았다. 표정 식별은 개선되지만 주변 털·배경 세부가 많이 남아 셀마다 정보량이 크게 달라지는 효과가 약하다. 1번 잔디, 2번 벽, 3번 가구, 4번 벤치에서는 물결처럼 이어지는 윤곽이 특히 보인다. 레퍼런스1의 강한 단색 색면도 재현하지 않지만 이를 주 목표로 삼지는 않는다. - -다음 시각 개선은 (1) 눈·코 조각을 남기면서 주변 셀의 확대·압축 분포 차이를 강화하고, (2) 길게 이어지는 물결을 얕은 사각 면의 굴절로 정리하며, (3) 한 마리 정면/두 마리/옆얼굴의 구도 안내를 나누는 순서가 적절하다. 광택만 올리는 방식으로 해결되지 않는다. - -사용자에게는 멍멍이1 같은 정면 근접 사진을 첫 예시로 보여주고, 효과 강도보다 먼저 얼굴 크기·위치를 조정하도록 안내하는 편이 낫다. 두 마리 사진에는 둘을 함께 담는 구도를 우선한다. 이 5장 QA만으로 성별·국가별 실제 수요를 판단할 근거는 없다. - -## 증거 파일 - -- `sample`, `dog1`~`dog4` 각각 `-noglass.png`, `-default.png`, `-tuned.png`. -- 기존 샘플 No Glass 드래그: `sample-noglass-drag.png`. cameraX 0→.081에서 코 projectedX 531.509→529.123, 몸 350.477→350.437로 상대 이동 차이 확인. -- 모바일 `sample-mobile.png`, `dog1-mobile.png`~`dog4-mobile.png`; 드래그 대표 `dog1-mobile-drag.png`, `dog4-mobile-drag.png`. 일부 캡처는 패널 폭 수정 전이며 광학 결과는 동일하다. 최종 패널 화면은 `dog1-final-ui.png`. - -## 최종 구현 / 검증 - -수정 파일: `index.html`, `src/main.ts`, `src/input/MediaLoader.ts`, `src/style.css`, 추가 사진 4장. 테스트 사진 select에서 선택 후 '선택한 테스트 사진 불러오기'로 전환한다. 기존 샘플 버튼 기능은 유지했다. - -- 모바일 390×844에서 5장 조정 구도 모두 렌더링 확인. 멍멍이1·4 드래그 시 유리/창틀 정렬 유지. 실제 휴대폰 하드웨어·자이로·FPS 측정은 하지 않았다. -- 기존→추가→기존 전환에서 수작업 Depth 안내와 2.4/-.10/-.35 복귀 확인. 추가 사진은 1/0/0, 평면 안내, 기존 진단 숨김 확인. -- dog1→dog3→sample→dog1 연속 선택·불러오기 후 최종 dog1/평면 안내/구도1/0/0 확인. 네트워크 지연을 강제로 주입한 경합 테스트는 하지 않았다. -- select의 긴 라벨로 설정 패널이 잘리던 문제를 재현 후 너비 제한·짧은 라벨로 수정. 최종 desktop aside client/scrollWidth 모두264, select228. 모바일 aside client/scrollWidth 모두375 확인. -- Astra 검토에서 발견한 로딩 실패 시 이전 RGB와 새 출처가 섞이는 문제는 성공 callback에서 Depth·구도·출처를 함께 반영하도록 수정. 수정은 정적 재검토 완료; 실패를 강제 주입한 브라우저 테스트는 하지 않았다. -- 최종 Luna 빌드 `tsc -b && vite build` 통과. QA 탭 error 로그 0건. 이번 작업에서 영상/일반 업로드/수동 Depth 업로드 전체 회귀 테스트는 실행하지 않았다. - -현재 셰이더는 기존 이웃 셀의 좌표변환·표면기울기를 연결하고 공유 법선으로 굴절/반사를 계산하는 방식 그대로다. 이번 변경으로 유리 질감이 개선됐다고 해석하면 안 된다. 테스트 사진 다양화를 통해 한 장에만 맞춘 평가의 한계를 확인한 작업이다. diff --git a/docs/qa-five-photos/sample-default.png b/docs/qa-five-photos/sample-default.png deleted file mode 100644 index e4ad037..0000000 Binary files a/docs/qa-five-photos/sample-default.png and /dev/null differ diff --git a/docs/qa-five-photos/sample-mobile.png b/docs/qa-five-photos/sample-mobile.png deleted file mode 100644 index 924c8a9..0000000 Binary files a/docs/qa-five-photos/sample-mobile.png and /dev/null differ diff --git a/docs/qa-five-photos/sample-noglass-drag.png b/docs/qa-five-photos/sample-noglass-drag.png deleted file mode 100644 index 23e22a0..0000000 Binary files a/docs/qa-five-photos/sample-noglass-drag.png and /dev/null differ diff --git a/docs/qa-five-photos/sample-noglass.png b/docs/qa-five-photos/sample-noglass.png deleted file mode 100644 index 613d95b..0000000 Binary files a/docs/qa-five-photos/sample-noglass.png and /dev/null differ diff --git a/docs/qa-five-photos/sample-tuned.png b/docs/qa-five-photos/sample-tuned.png deleted file mode 100644 index 5cb688d..0000000 Binary files a/docs/qa-five-photos/sample-tuned.png and /dev/null differ diff --git a/docs/qa-followup/dog1-compact.png b/docs/qa-followup/dog1-compact.png deleted file mode 100644 index d07577e..0000000 Binary files a/docs/qa-followup/dog1-compact.png and /dev/null differ diff --git a/docs/qa-followup/dog1-concave.png b/docs/qa-followup/dog1-concave.png deleted file mode 100644 index 5fc1608..0000000 Binary files a/docs/qa-followup/dog1-concave.png and /dev/null differ diff --git a/docs/qa-followup/dog1-drag.png b/docs/qa-followup/dog1-drag.png deleted file mode 100644 index 2382ef3..0000000 Binary files a/docs/qa-followup/dog1-drag.png and /dev/null differ diff --git a/docs/qa-followup/dog1-flat.png b/docs/qa-followup/dog1-flat.png deleted file mode 100644 index 94392de..0000000 Binary files a/docs/qa-followup/dog1-flat.png and /dev/null differ diff --git a/docs/qa-followup/dog1-gloss.png b/docs/qa-followup/dog1-gloss.png deleted file mode 100644 index 3567a48..0000000 Binary files a/docs/qa-followup/dog1-gloss.png and /dev/null differ diff --git a/docs/qa-followup/dog1-strength0.png b/docs/qa-followup/dog1-strength0.png deleted file mode 100644 index d97c684..0000000 Binary files a/docs/qa-followup/dog1-strength0.png and /dev/null differ diff --git a/docs/qa-followup/dog1-strength001.png b/docs/qa-followup/dog1-strength001.png deleted file mode 100644 index fe89954..0000000 Binary files a/docs/qa-followup/dog1-strength001.png and /dev/null differ diff --git a/docs/qa-followup/dog1-strong.png b/docs/qa-followup/dog1-strong.png deleted file mode 100644 index bd4dfe8..0000000 Binary files a/docs/qa-followup/dog1-strong.png and /dev/null differ diff --git a/docs/qa-followup/dog4-convex.png b/docs/qa-followup/dog4-convex.png deleted file mode 100644 index bffb604..0000000 Binary files a/docs/qa-followup/dog4-convex.png and /dev/null differ diff --git a/docs/qa-followup/dog4-flat.png b/docs/qa-followup/dog4-flat.png deleted file mode 100644 index d00db18..0000000 Binary files a/docs/qa-followup/dog4-flat.png and /dev/null differ diff --git a/docs/qa-followup/review.md b/docs/qa-followup/review.md deleted file mode 100644 index 4c4214a..0000000 --- a/docs/qa-followup/review.md +++ /dev/null @@ -1,30 +0,0 @@ -# 추가 개선점 검토 및 설정 테스트 - -2026-09-13. 소스 수정 없이 실제 브라우저 1280×720 설정 비교와 Astra 정적 검토를 진행했다. 앞선 5장 QA를 바탕으로 이번 추가 실험은 정면 멍멍이1과 옆얼굴 멍멍이4에 집중했다. 레퍼런스2가 주 판단 기준이다. - -## 실제 테스트 - -멍멍이1 구도2.3/-.10/-.30 고정. 기본 비교값 Grid8/Distortion.90/굴곡+.65/광택.15/조명.6,.8. - -| 실험 | 관찰 | 증거 | -|---|---|---| -| Grid8/.90, 굴곡0·광택0 | 눈 크기 차이와 얼굴 변형은 남음. 곡면만 없애도 원본에 가까운 넓은 영역은 그대로 | dog1-flat.png | -| Grid6/Distortion1/굴곡1/광택0 | 사각 정보량 차이보다 눈·코 비대칭과 눌림이 강해짐 | dog1-strong.png | -| Grid8/.90, 굴곡-1·광택0 | 경계 휘는 방향은 달라지지만 사각 조각감 확보에는 부족 | dog1-concave.png | -| Grid8/.90/+.65, 광택1·조명0,0 | 눈·코에 흰 반사가 겹침. 확대·압축의 차이는 개선되지 않음 | dog1-gloss.png | -| 촘촘 유리 Grid28/.85/+.65/광택.15 | 원본 표정은 잘 남지만 주 레퍼런스의 큰 조각과 더 멀어짐 | dog1-compact.png | -| Camera Offset.6 + 드래그 | 창틀 정렬은 유지되나 눈·코가 옆 셀로 넘어가며 국소 늘어짐이 보임 | dog1-drag.png | -| Distortion .01→0 | .01에서는 창틀 안, 0에서는 확대 사진이 창틀 밖까지 나타나는 불연속 확인 | dog1-strength001.png / dog1-strength0.png | - -멍멍이4 구도1.55/+.10/-.85, Grid12/Distortion.65/광택0에서 굴곡0과+1 비교. +1은 이마·벤치·귀의 윤곽 휘어짐이 늘지만 표정·사각 유리 표현 개선은 뚜렷하지 않다. `dog4-flat.png`, `dog4-convex.png`. 종료 시 앞선 후보값 굴곡+.35/광택.15로 복원했다. - -브라우저 error 로그0. 이번에는 코드 변경이 없어 빌드를 다시 실행하지 않았다. 실기기 성능·영상·자이로는 미검증. 첨부4장은 Depth 없는 평면 테스트다. - -## 개선 우선순위 - -1. **셀별 배율 분포부터 수정할 필요가 있다.** 현재 조각 스타일은 해시 분포상60%의 샘플 폭이.90~1.08,30%만.46~.70이다. 대부분이 원본에 가까우며 중심 이동도 최대.08셀이다. Grid를 줄여도 분포 자체는 변하지 않는다. 거의 원본인 셀 비중을 줄이고 한 축 확대/압축과 주변의 낮은 정보량 영역 차이를 먼저 실험해야 한다. 얼굴 검출 기능을 바로 추가할 필요는 없다. -2. **경계 연결은 사각 면과 연속성을 함께 평가해야 한다.** .16셀 혼합이 적용되는 면적은 이론상53.76%다. 연결로 끊김을 줄인 대가로 셀 독립성이 약해질 가능성이 있다. 단순히 폭만 줄이는 것은 이전 .12 비교에서 명확한 개선이 없었고 눈 주변 선이 재발할 수 있다. 배율 분포 실험을 먼저 한 뒤 경계 폭/방식을 한 변수씩 A/B 비교한다. 동일 법선의 굴절·반사 공유를 유지한다. -3. **퍼짐은 보조 수단이다.** 현재5탭의 .006~.012셀 반경으로는 주변 털·잔디의 세부가 많이 남는다. 일부 셀의 퍼짐 편차를 확대할 수 있으나 전체 블러나 단색 픽셀화로 바꾸지 않는다. 광택 증가는 대체 해결책이 아니다. -4. **무효과 전환의 표시 범위를 정리해야 한다.** Distortion0의 창틀 밖 출현은 기존 raw RenderTarget bypass를 유지한 알려진 동작이며 이번 변경의 회귀는 아니다. 기존 프로젝트 지침이0에서 기존 출력을 유지하도록 명시하므로 이번에 수정하지 않았다. 향후 제품 표시 규칙을 바꾼다면0에서도 프레임 안 원본을 보여주는 방식으로 별도 변경한다. - -실험의 통과 기준은 같은 사진·같은 구도에서 (a) 눈·코가 남고 주변 셀 정보량 차이가 커짐, (b) 광택0에서도 사각 면이 읽힘, (c) 눈을 가로지르는 가는 선이나 검은 격자 재발 없음, (d) 드래그와 모바일에서 정렬 유지다. 설정 실험만으로 레퍼런스 달성을 주장하지 않는다. diff --git a/docs/qa-glass-material/baseline-mosaic.frag b/docs/qa-glass-material/baseline-mosaic.frag deleted file mode 100644 index 2ff2bda..0000000 --- a/docs/qa-glass-material/baseline-mosaic.frag +++ /dev/null @@ -1,311 +0,0 @@ -uniform sampler2D uSceneTexture,uSceneDepth; -uniform sampler2D uProtectionDepthMap; -uniform mat4 uContentViewProjection,uContentInverseViewProjection; -uniform mat4 uPetWorldToLocal; -uniform vec3 uContentCameraPosition,uLightPosition,uBackgroundColor; -uniform float uGlassZ,uSourceZ,uGridSize,uStrength,uMosaicStyle,uCurvature,uGlossStrength; -uniform vec2 uViewOffset,uPetSize,uPaneSize; -uniform vec2 uDepthEvidenceRange,uDepthCorrection; -uniform float uEnvironmentStrength; -uniform vec4 uPaneRect; -uniform sampler2D uRegionPalette; -uniform sampler2D uRegionAtlas,uRegionHistory; -uniform vec2 uRegionAtlasSize,uRegionGridSize,uRegionPaletteSize; -uniform float uRegionStrength,uRegionAvailable; -varying vec2 vUv; -vec2 projectUv(vec3 p){vec4 c=uContentViewProjection*vec4(p,1.);float w=abs(c.w)<.0001?(c.w<0.?-.0001:.0001):c.w;return c.xy/w*.5+.5;} -vec4 sampleScene(vec2 uv){return texture2D(uSceneTexture,clamp(uv,0.,1.));} -vec4 samplePane(vec2 pane){return sampleScene(projectUv(vec3((pane-.5)*uPaneSize,uGlassZ)));} -float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);} -vec2 hash2(vec2 p){return vec2(hash(p),hash(p+vec2(19.19,73.73)));} -vec2 cellBlurStep(vec2 cell,vec2 cellSize,float style){ - if(style<=.5)return cellSize*mix(.006,.018,hash(cell+vec2(5.))); - return cellSize*mix(.006,.012,hash(cell+vec2(5.))); -} -vec4 sampleCell(vec2 pane,vec2 sourceUv,float strength,vec2 cell,vec2 cellSize,float style){ - vec2 center=mix(pane,sourceUv,strength); - vec2 blurOffset=strength*cellBlurStep(cell,cellSize,style); - vec4 color; - if(style<=.5){ - color=samplePane(center)*.6; - color+=samplePane(center+vec2(blurOffset.x,0.))*.1; - color+=samplePane(center-vec2(blurOffset.x,0.))*.1; - color+=samplePane(center+vec2(0.,blurOffset.y))*.1; - color+=samplePane(center-vec2(0.,blurOffset.y))*.1; - }else{ - color=samplePane(center)*.4; - color+=samplePane(center+vec2(blurOffset.x,0.))*.15; - color+=samplePane(center-vec2(blurOffset.x,0.))*.15; - color+=samplePane(center+vec2(0.,blurOffset.y))*.15; - color+=samplePane(center-vec2(0.,blurOffset.y))*.15; - } - return color; -} -float safeZ(float z){return abs(z)<.0001?(z<0.?-.0001:.0001):z;} -vec3 bend(vec3 i,vec3 n){vec3 r=refract(i,n,.75);return length(r)<.0001?i:r;} -float softLimit(float value,float limit){return value*limit/(limit+abs(value));} -float surfaceCurvature(){float curvature=clamp(uCurvature,-1.,1.),excess=max(curvature-.65,0.);return curvature-(.25/.35)*excess*excess;} -float signedCurvatureScale(){return clamp(surfaceCurvature()/.65,-1.25,1.25);} -float regionDistance(vec3 a,vec3 b){vec3 d=a-b;float y=dot(d,vec3(.299,.587,.114));return dot(d,d)+.35*y*y;} -float regionLuminance(vec3 c){return dot(c,vec3(.299,.587,.114));} -vec3 regionColor(vec2 cell,float index){vec2 uv=(vec2(cell.x*5.+index,cell.y)+.5)/uRegionPaletteSize;return texture2D(uRegionPalette,uv).rgb;} -float nearestRegion(vec3 color,vec2 cell){float best=0.,distance=regionDistance(color,regionColor(cell,0.));for(int i=1;i<4;i++){float candidate=regionDistance(color,regionColor(cell,float(i)));if(candidate1.||sceneUv.y<0.||sceneUv.y>1.)return false; - float depth=texture2D(uSceneDepth,sceneUv).x; - if(depth>=.999999)return false; - vec4 clip=vec4(sceneUv*2.-1.,depth*2.-1.,1.); - vec4 world=uContentInverseViewProjection*clip; - if(abs(world.w)<.0001)return false; - worldPoint=world.xyz/world.w; - return true; -} -float regionSurfaceValid(vec2 sceneUv,vec3 glassHit){ - vec3 worldPoint; - if(!reconstructScenePoint(sceneUv,worldPoint))return 0.; - float axialGap=glassHit.z-worldPoint.z; - if(axialGap<=.0001)return 0.; - return 1.; -} -float regionProtectionWeight(vec2 sceneUv){ - vec3 worldPoint; - if(!reconstructScenePoint(sceneUv,worldPoint))return 0.; - vec3 localPoint=(uPetWorldToLocal*vec4(worldPoint,1.)).xyz; - if(localPoint.x<-.5||localPoint.x>.5||localPoint.y<-.5||localPoint.y>.5)return 0.; - vec2 sourceUv=localPoint.xy+.5; - float sourceDepth=texture2D(uProtectionDepthMap,sourceUv).r; - if(uDepthEvidenceRange.y-uDepthEvidenceRange.x<.0001)return 0.; - return smoothstep(uDepthEvidenceRange.x,uDepthEvidenceRange.y,sourceDepth); -} -// Screen-depth refinement of an artistic ray. Occluded surfaces are unavailable; -// retain the original sample if the visible-depth solve cannot converge. -vec3 refineSceneHit(vec3 glassHit,vec3 ray,vec3 artisticHit,float cellWorld){ - vec3 planeHit=glassHit+ray*((uSourceZ-glassHit.z)/safeZ(ray.z)); - vec3 origin=glassHit+vec3(artisticHit.xy-planeHit.xy,0.); - vec3 hit=artisticHit,surface; - for(int iteration=0;iteration<3;iteration++){ - if(!reconstructScenePoint(projectUv(hit),surface))return artisticHit; - vec3 localPoint=(uPetWorldToLocal*vec4(surface,1.)).xyz; - if(any(greaterThan(abs(localPoint.xy),vec2(.5)))||surface.z>=uGlassZ-.0001)return artisticHit; - hit=origin+ray*((surface.z-origin.z)/safeZ(ray.z)); - } - if(!reconstructScenePoint(projectUv(hit),surface))return artisticHit; - if(surface.z>=uGlassZ-.0001)return artisticHit; - float confidence=1.-smoothstep(cellWorld*.05,cellWorld*.25,abs(hit.z-surface.z)); - // Compare at the same reference Z, so only the projected sampling position changes. - vec3 viewRay=hit-uContentCameraPosition; - vec3 projected=uContentCameraPosition+viewRay*((uSourceZ-uContentCameraPosition.z)/safeZ(viewRay.z)); - vec2 delta=projected.xy-artisticHit.xy; - float limit=cellWorld*uDepthCorrection.y; - delta*=min(1.,limit/max(length(delta),.00001)); - return artisticHit+vec3(delta*uDepthCorrection.x*confidence,0.); -} -#ifdef REGION_ATLAS -float regionAtlasEvidence(vec2 sceneUv,vec3 color,vec3 glassHit){ - if(regionSurfaceValid(sceneUv,glassHit)<=0.)return 0.; - return regionProtectionWeight(sceneUv)*(1.-smoothstep(.10,.20,regionLuminance(color))); -} -vec4 regionAtlasProbe(vec3 sceneHit,vec2 worldOffset,vec3 glassHit){ - vec2 probeSceneUv=projectUv(sceneHit+vec3(worldOffset,0.)); - vec4 probe=sampleScene(probeSceneUv); - return vec4(probe.rgb,regionAtlasEvidence(probeSceneUv,probe.rgb,glassHit)); -} -vec4 regionAtlasScore(vec3 centerColor,float centerEvidence,vec3 probeColor,float probeEvidence){ - float evidenceGain=probeEvidence-centerEvidence,darkGain=regionLuminance(centerColor)-regionLuminance(probeColor),blend=0.; - if(probeEvidence>.05&&evidenceGain>.02&&darkGain>.015)blend=min(.4,evidenceGain*2.)*min(1.,max(0.,darkGain*4.)); - return vec4(blend,probeEvidence,0.,0.); -} -vec3 regionAtlasRepresentative(vec3 centerColor,float centerEvidence,vec3 sceneHit,vec3 glassHit,out float evidence){ - vec3 bestColor=centerColor;float bestEvidence=centerEvidence,bestBlend=0.; - vec2 probeStep=uPaneSize/(uRegionGridSize*8.)*.25; - vec4 probe,score; - probe=regionAtlasProbe(sceneHit,vec2(probeStep.x,0.),glassHit);score=regionAtlasScore(centerColor,centerEvidence,probe.rgb,probe.a);if(score.x>bestBlend){bestColor=mix(centerColor,probe.rgb,score.x);bestEvidence=max(centerEvidence,probe.a);bestBlend=score.x;} - probe=regionAtlasProbe(sceneHit,vec2(-probeStep.x,0.),glassHit);score=regionAtlasScore(centerColor,centerEvidence,probe.rgb,probe.a);if(score.x>bestBlend){bestColor=mix(centerColor,probe.rgb,score.x);bestEvidence=max(centerEvidence,probe.a);bestBlend=score.x;} - probe=regionAtlasProbe(sceneHit,vec2(0.,probeStep.y),glassHit);score=regionAtlasScore(centerColor,centerEvidence,probe.rgb,probe.a);if(score.x>bestBlend){bestColor=mix(centerColor,probe.rgb,score.x);bestEvidence=max(centerEvidence,probe.a);bestBlend=score.x;} - probe=regionAtlasProbe(sceneHit,vec2(0.,-probeStep.y),glassHit);score=regionAtlasScore(centerColor,centerEvidence,probe.rgb,probe.a);if(score.x>bestBlend){bestColor=mix(centerColor,probe.rgb,score.x);bestEvidence=max(centerEvidence,probe.a);bestBlend=score.x;} - evidence=bestEvidence; - return bestColor; -} -#endif -void evaluateCell(vec2 cell,vec2 local,vec2 grid,vec2 cellSize,vec2 cellDimensions,float cellWorld,float opticalTravel,float style,out vec2 affineUv,out mat2 transform,out vec2 curvedSlope,out vec2 facetSlope){ - vec2 random=hash2(cell),widths; - if(style>.5){ - widths=mix(vec2(.82),vec2(1.12),hash2(cell+vec2(11.4,9.8))); - float angle=(random.x-.5)*.08,c=cos(angle),s=sin(angle); - transform=mat2(widths.x*c,-widths.y*s,widths.x*s,widths.y*c); - float centerJitter=.16; - vec2 sourceCenter=(cell+.5)/grid+(random-.5)*centerJitter*cellSize; - affineUv=sourceCenter+transform*(local*cellSize); - }else{ - // Default style keeps a single continuous image footprint across cells. - transform=mat2(1.); - affineUv=(cell+.5)/grid+local*cellSize; - } - - // Positive height bulges toward the observer (+Z); negative height is concave. - float curvature=clamp(uCurvature,-1.,1.),surfaceCurvatureValue=surfaceCurvature(); - vec2 q=clamp(2.*local,-1.,1.),q2=q*q,q3=q2*q,b=1.-q2*q2; - if(style>.5){ - float amplitude=mix(.92,1.08,hash(cell+vec2(41.7,17.3))),height=.009*cellWorld*surfaceCurvatureValue*amplitude; - vec2 skew=(hash2(cell+vec2(23.8,61.2))-.5)*.28;float asym=1.+dot(skew,q); - vec2 dhdq=height*vec2(-4.*q3.x*b.y*asym+b.x*b.y*skew.x,-4.*q3.y*b.x*asym+b.x*b.y*skew.y); - vec2 grad=-2.*dhdq/cellDimensions; - curvedSlope=grad+(random-.5)*.012;facetSlope=(random-.5)*.012; - }else{ - curvedSlope=.30*cellDimensions/max(abs(opticalTravel),.6)*signedCurvatureScale()*sin(6.2831853*local); - facetSlope=vec2(0.); - } -} -void main(){ - vec2 screenUv=vUv; -#ifdef REGION_ATLAS - vec2 atlasPixel=floor(vUv*uRegionAtlasSize),atlasCell=floor(atlasPixel/8.),atlasLocal=(mod(atlasPixel,8.)+.5)/8.; - vec2 atlasPaneUv=(atlasCell+atlasLocal)/uRegionGridSize; - screenUv=projectUv(vec3((atlasPaneUv-.5)*uPaneSize,uGlassZ)); -#endif - if(uStrength<=.001){ -#ifdef REGION_ATLAS - gl_FragColor=vec4(sampleScene(screenUv).rgb,0.); -#else - gl_FragColor=sampleScene(screenUv); - #include -#endif - return;} - vec4 f=uContentInverseViewProjection*vec4(screenUv*2.-1.,1.,1.);float fw=abs(f.w)<.0001?(f.w<0.?-.0001:.0001):f.w;vec3 farWorld=f.xyz/fw;vec3 i=normalize(farWorld-uContentCameraPosition);float gt=(uGlassZ-uContentCameraPosition.z)/safeZ(i.z);vec3 gh=uContentCameraPosition+i*gt; - vec2 paneUv=gh.xy/uPaneSize+.5;vec2 grid=vec2(uGridSize,max(1.,uGridSize*uPaneSize.y/uPaneSize.x));vec2 gridUv=paneUv*grid,cell=floor(gridUv),local=fract(gridUv)-.5,cellSize=1./grid;float style=clamp(uMosaicStyle,0.,1.),cellWorld=min(uPaneSize.x/grid.x,uPaneSize.y/grid.y); -#ifdef REGION_ATLAS - paneUv=atlasPaneUv;grid= uRegionGridSize;gridUv=paneUv*grid;cell=floor(gridUv);local=fract(gridUv)-.5;cellSize=1./grid;cellWorld=min(uPaneSize.x/grid.x,uPaneSize.y/grid.y); -#endif - if(paneUv.x<0.||paneUv.x>1.||paneUv.y<0.||paneUv.y>1.){ -#ifdef REGION_ATLAS - gl_FragColor=vec4(uBackgroundColor,0.); -#else - gl_FragColor=vec4(uBackgroundColor,1.); - #include -#endif - return;} - vec2 cellDimensions=uPaneSize/grid; - float opticalTravel=-max(abs(uSourceZ-gh.z),.6); - vec2 affineUv,curvedSlope,facetSlope;mat2 transform; - evaluateCell(cell,local,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,affineUv,transform,curvedSlope,facetSlope); - if(style<=.5){ - vec2 smoothFacet=.003*vec2(sin(6.2831853*paneUv.x),sin(6.2831853*paneUv.y)); - curvedSlope+=smoothFacet;facetSlope=smoothFacet; - }else{ - vec2 edge=.5-abs(local),neighborSign=mix(vec2(-1.),vec2(1.),step(vec2(0.),local)); - float normalBlend=.16; - vec2 weights=1.-smoothstep(vec2(-normalBlend),vec2(normalBlend),edge); - float xSplitWeight=weights.x*(1.-weights.y),ySplitWeight=(1.-weights.x)*weights.y; - float diagonalSplitWeight=weights.x*weights.y,centerSplitWeight=(1.-weights.x)*(1.-weights.y); - if(weights.x>0.||weights.y>0.){ - vec2 neighborAffine,neighborCurved,neighborFacet;mat2 neighborTransform; - vec2 xWeight=vec2(xSplitWeight,0.); - vec2 yWeight=vec2(0.,ySplitWeight); - affineUv*=centerSplitWeight;transform*=centerSplitWeight;curvedSlope*=centerSplitWeight;facetSlope*=centerSplitWeight; - if(xWeight.x>0.){ - vec2 offset=vec2(neighborSign.x,0.); - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*xWeight.x;transform+=neighborTransform*xWeight.x;curvedSlope+=neighborCurved*xWeight.x;facetSlope+=neighborFacet*xWeight.x; - } - if(yWeight.y>0.){ - vec2 offset=vec2(0.,neighborSign.y); - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*yWeight.y;transform+=neighborTransform*yWeight.y;curvedSlope+=neighborCurved*yWeight.y;facetSlope+=neighborFacet*yWeight.y; - } - if(diagonalSplitWeight>0.){ - vec2 offset=neighborSign; - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*diagonalSplitWeight;transform+=neighborTransform*diagonalSplitWeight;curvedSlope+=neighborCurved*diagonalSplitWeight;facetSlope+=neighborFacet*diagonalSplitWeight; - } - } - } - vec3 nCurved=normalize(vec3(curvedSlope,1.)),nFacet=normalize(vec3(facetSlope,1.)); - vec3 straightHit=gh+i*((uSourceZ-gh.z)/safeZ(i.z)); - vec3 curvedRay=bend(i,nCurved),curvedHit=gh+curvedRay*((uSourceZ-gh.z)/safeZ(curvedRay.z)); - // Keep the artistic Mosaic optical path independent of physical glass-to-photo contact distance. - vec2 rawDelta=(curvedRay.xy/safeZ(curvedRay.z)-i.xy/safeZ(i.z))*opticalTravel; - vec2 worldDelta=vec2(softLimit(rawDelta.x,cellWorld*.55),softLimit(rawDelta.y,cellWorld*.55)); - if(style>.5){ - vec3 facetRay=bend(i,nFacet);vec3 facetHit=gh+facetRay*((uSourceZ-gh.z)/safeZ(facetRay.z)); - vec2 base=facetHit.xy-straightHit.xy,curve=curvedHit.xy-facetHit.xy; - worldDelta=vec2(softLimit(base.x,cellWorld*.08),softLimit(base.y,cellWorld*.08)); - vec2 d=curve/cellWorld; - worldDelta+=vec2(.3*d.x/(.3+abs(d.x)),.3*d.y/(.3+abs(d.y)))*cellWorld; - }else{ - vec3 referenceI=normalize(gh-vec3(0.,0.,uContentCameraPosition.z)),referenceRay=bend(referenceI,nCurved); - vec2 incidenceDelta=curvedRay.xy/max(-curvedRay.z,.0001)-referenceRay.xy/max(-referenceRay.z,.0001); - vec2 boundedIncidence=incidenceDelta/sqrt(incidenceDelta*incidenceDelta+vec2(.025*.025)); - vec2 cellEnvelope=.5+.5*cos(6.2831853*local); - worldDelta+=boundedIncidence*cellEnvelope*cellDimensions*signedCurvatureScale()*.18; - } - vec2 sampleUv=affineUv+transform*(worldDelta/uPaneSize); - float edgeDistance=min(min(paneUv.x,paneUv.y),min(1.-paneUv.x,1.-paneUv.y));float edgeTaper=style<=.5?1.25:.75;float edgeWeight=smoothstep(0.,max(cellSize.x,cellSize.y)*edgeTaper,edgeDistance);float strength=clamp(uStrength,0.,1.)*edgeWeight; - vec4 color;vec3 sceneHit=straightHit+vec3(worldDelta*strength,0.);vec2 finalSceneUv=projectUv(sceneHit); - if(style<=.5){ - sceneHit=refineSceneHit(gh,normalize(mix(i,curvedRay,strength)),sceneHit,cellWorld); - finalSceneUv=projectUv(sceneHit); - } -#ifdef REGION_ATLAS - vec3 atlasCenterColor=sampleScene(finalSceneUv).rgb; - float atlasEvidence=regionProtectionWeight(finalSceneUv)*(1.-smoothstep(.10,.20,regionLuminance(atlasCenterColor))); -#endif -#ifdef REGION_ATLAS - if(style<=.5){ - float representativeEvidence=atlasEvidence; - color=vec4(regionAtlasRepresentative(atlasCenterColor,atlasEvidence,sceneHit,gh,representativeEvidence),representativeEvidence); - atlasEvidence=representativeEvidence; - }else{ - color=sampleCell(paneUv,sampleUv,strength,cell,cellSize,style); - } -#else - if(style<=.5){ - color=sampleScene(finalSceneUv); - }else{ - color=sampleCell(paneUv,sampleUv,strength,cell,cellSize,style); - } -#endif -#ifndef REGION_ATLAS - if(uRegionAvailable>.5&&uRegionStrength>.001&&uMosaicStyle<.5){ - vec3 p0=regionColor(cell,0.),p1=regionColor(cell,1.),p2=regionColor(cell,2.),p3=regionColor(cell,3.); - float ownLabel=nearestRegion(color.rgb,p0,p1,p2,p3);vec4 votes=vec4(0.);float totalWeight=0.,ownWeight=0.; - vec2 texelCoord=fract(gridUv)*8.-.5,anchor=floor(texelCoord+.5); - for(int y=-1;y<=1;y++)for(int x=-1;x<=1;x++){ - vec2 offset=vec2(float(x),float(y)),delta=anchor+offset-texelCoord; - float weight=pow(max(0.,1.-length(delta)/1.5),2.); - if(weight>0.){ - vec3 atlasColor=regionAtlasColor(cell,anchor+offset);float label=nearestRegion(atlasColor,p0,p1,p2,p3); - votes+=vec4(step(abs(label-vec4(0.,1.,2.,3.)),vec4(.1)))*weight;totalWeight+=weight; - ownWeight+=step(abs(label-ownLabel),.1)*weight; - } - } - float winningLabel=ownLabel,winningWeight=ownWeight; - if(votes.x>winningWeight){winningLabel=0.;winningWeight=votes.x;}if(votes.y>winningWeight){winningLabel=1.;winningWeight=votes.y;}if(votes.z>winningWeight){winningLabel=2.;winningWeight=votes.z;}if(votes.w>winningWeight){winningLabel=3.;winningWeight=votes.w;} - bool simplify=totalWeight>0.&&winningWeight/totalWeight>.55&&ownWeight/totalWeight<.40; - float radialLabel=simplify?winningLabel:ownLabel;vec3 radialColor=selectRegion(p0,p1,p2,p3,radialLabel); - vec2 historyTexel=clamp(floor(fract(gridUv)*8.),vec2(0.),vec2(7.)); - vec2 historyUv=(cell*8.+historyTexel+.5)/uRegionAtlasSize; - vec4 splitHistory=texture2D(uRegionHistory,historyUv); - vec3 splitColor=splitHistory.a>.00001?splitHistory.rgb/splitHistory.a:radialColor; - vec3 candidateColor=mix(radialColor,splitColor,splitHistory.a); - color.rgb=mix(color.rgb,candidateColor,clamp(uRegionStrength*clamp(uStrength,0.,1.)*regionSurfaceValid(finalSceneUv,gh),0.,1.)); - } -#endif -#ifndef REGION_ATLAS - color.a=1.; - vec3 v=normalize(uContentCameraPosition-gh),reflected=reflect(-v,nCurved); float lightT=(uLightPosition.z-gh.z)/safeZ(reflected.z); vec2 lightHit=gh.xy+reflected.xy*lightT; vec2 halfSize=vec2(.32,.42)*min(uPaneSize.x,uPaneSize.y); vec2 windowCoord=abs(lightHit-uLightPosition.xy)/halfSize; vec2 windowMask=1.-smoothstep(vec2(.45),vec2(1.15),windowCoord); float surfaceReflectionWeight=mix(.35,1.,edgeWeight); float glossStrength=clamp(uGlossStrength,0.,1.); float spec=windowMask.x*windowMask.y*step(.0001,reflected.z)*step(0.,lightT); float specGloss=spec*glossStrength*.12*surfaceReflectionWeight*clamp(uStrength,0.,1.); vec2 broadWindowMask=1.-smoothstep(vec2(.15),vec2(1.75),windowCoord); float broadFacing=pow(max(dot(nCurved,v),0.),2.); float broadReflection=broadWindowMask.x*broadWindowMask.y*broadFacing*glossStrength*.035*surfaceReflectionWeight*clamp(uStrength,0.,1.); color.rgb=mix(color.rgb,vec3(1.),specGloss+broadReflection); gl_FragColor=color; - // Common, static room environment. Reflected direction varies with the same - // curved normal as transmission; no image relighting or timed sparkle. - float fresnel=.04+.96*pow(1.-clamp(dot(nCurved,v),0.,1.),5.); - float environmentWeight=uEnvironmentStrength*glossStrength*(.35+.65*fresnel)*surfaceReflectionWeight*clamp(uStrength,0.,1.); - vec3 environmentColor=mix(vec3(.10,.13,.18),vec3(.65,.72,.80),smoothstep(-.35,.65,reflected.y)); - if(style<=.5)color.rgb=mix(color.rgb,environmentColor,environmentWeight); - gl_FragColor=color; - #include -#else - color.a=atlasEvidence; - gl_FragColor=color; -#endif -} diff --git a/docs/qa-glass-material/dog1-drag.jpg b/docs/qa-glass-material/dog1-drag.jpg deleted file mode 100644 index a330901..0000000 Binary files a/docs/qa-glass-material/dog1-drag.jpg and /dev/null differ diff --git a/docs/qa-glass-material/dog1-final.jpg b/docs/qa-glass-material/dog1-final.jpg deleted file mode 100644 index d106d1b..0000000 Binary files a/docs/qa-glass-material/dog1-final.jpg and /dev/null differ diff --git a/docs/qa-glass-material/report.md b/docs/qa-glass-material/report.md deleted file mode 100644 index c0777e7..0000000 --- a/docs/qa-glass-material/report.md +++ /dev/null @@ -1,15 +0,0 @@ -# 유리가 저해상도 필터처럼 보인다는 피드백 반영 - -> 2026-10-06: 사용자 요청으로 아래 실험의 42% 디테일 혼합과 셀 법선 1.2배 보정을 되돌렸다. 이 문서는 당시 실험 기록이며 현재 적용 상태가 아니다. 복원 범위와 고방유리 재검토는 `../qa-gobang-review-2026-10-06/report.md`에 기록한다. - -2026-09-30. 사용자 첨부에서 셀 내부가 평평한 색 블록으로 보인다는 지적을 받았다. 기존 코드에서 region strength=1은 굴절된 샘플을 palette/history 색으로 완전히 덮었다. 이는 반사만 강화해도 해결되지 않는 구조였다. - -수정: `src/constants/glass.ts`의 transmission detail 0.42를 최종 Mosaic 색면 합성에 적용한다. 색면 58%와 같은 위치의 연속적인 굴절 샘플 42%가 남는다. 원본 사진 UV나 눈·코만 선택하는 fallback이 아니며, 사진 전체에 동일 적용한다. UI의 강도 1은 유지하지만 그 최대 강도의 표현 자체가 바뀐 새 비교안이다. 기존 옵션 1·2와 수정 전 셰이더(`baseline-mosaic.frag`)는 보존했다. - -굴절/반사에 공유하는 기본 셀 법선 기울기를 1.2배로 조정했다. 2.5배와 1.6배 후보는 projected UV 연속성 검사에서 일부 시점의 뒤집힘이 검출되어 폐기했다. 검사 코드도 실제 상수를 사용하도록 갱신했으며 성공 기준을 완화하지 않았다. 실제 screen-depth 보정 이후 모든 영상 프레임의 연속성까지 증명하는 검사는 아니다. - -검증: 새 transmission 계약 검사는 변경 전 실패 후 통과. 전체 10개 검사와 TypeScript/Vite build 통과. 브라우저에서 dog1 자동 AI 성공과 기본 정면을 확인했다. 이전 탭 연결은 timeout이 났지만 새 탭에서는 정상 실행됐다. - -판단: 큰 사각 경계 안에 눈·코/털/잔디의 연속 명암이 남는다. 이전보다 사진 질감이 더 드러나는 절충이며 Ref1의 정보 단순화와 유리 투과감을 함께 평가해야 한다. 물리적으로 완전한 유리, 모든 사진의 시각 품질, 실기기 FPS를 검증한 것은 아니다. 반사 강도와 블러는 이번에 추가하지 않았다. - -![기본 화면](dog1-final.jpg) diff --git a/docs/qa-gobang-facets-2026-10-06/before-current-settings.png b/docs/qa-gobang-facets-2026-10-06/before-current-settings.png deleted file mode 100644 index 8ded11d..0000000 Binary files a/docs/qa-gobang-facets-2026-10-06/before-current-settings.png and /dev/null differ diff --git a/docs/qa-gobang-facets-2026-10-06/dog1-concave.png b/docs/qa-gobang-facets-2026-10-06/dog1-concave.png deleted file mode 100644 index da3cf45..0000000 Binary files a/docs/qa-gobang-facets-2026-10-06/dog1-concave.png and /dev/null differ diff --git a/docs/qa-gobang-facets-2026-10-06/dog1-current-settings.png b/docs/qa-gobang-facets-2026-10-06/dog1-current-settings.png deleted file mode 100644 index 4dae518..0000000 Binary files a/docs/qa-gobang-facets-2026-10-06/dog1-current-settings.png and /dev/null differ diff --git a/docs/qa-gobang-facets-2026-10-06/dog1-directional-grid20.png b/docs/qa-gobang-facets-2026-10-06/dog1-directional-grid20.png deleted file mode 100644 index 6b2768f..0000000 Binary files a/docs/qa-gobang-facets-2026-10-06/dog1-directional-grid20.png and /dev/null differ diff --git a/docs/qa-gobang-facets-2026-10-06/dog1-drag.png b/docs/qa-gobang-facets-2026-10-06/dog1-drag.png deleted file mode 100644 index f360640..0000000 Binary files a/docs/qa-gobang-facets-2026-10-06/dog1-drag.png and /dev/null differ diff --git a/docs/qa-gobang-facets-2026-10-06/dog1-final-desktop.png b/docs/qa-gobang-facets-2026-10-06/dog1-final-desktop.png deleted file mode 100644 index 4b84ff9..0000000 Binary files a/docs/qa-gobang-facets-2026-10-06/dog1-final-desktop.png and /dev/null differ diff --git a/docs/qa-gobang-facets-2026-10-06/dog1-final-pane.png b/docs/qa-gobang-facets-2026-10-06/dog1-final-pane.png deleted file mode 100644 index 19e8094..0000000 Binary files a/docs/qa-gobang-facets-2026-10-06/dog1-final-pane.png and /dev/null differ diff --git a/docs/qa-gobang-facets-2026-10-06/dog1-flat-gloss0.png b/docs/qa-gobang-facets-2026-10-06/dog1-flat-gloss0.png deleted file mode 100644 index 25f6c98..0000000 Binary files a/docs/qa-gobang-facets-2026-10-06/dog1-flat-gloss0.png and /dev/null differ diff --git a/docs/qa-gobang-facets-2026-10-06/dog1-gloss0.png b/docs/qa-gobang-facets-2026-10-06/dog1-gloss0.png deleted file mode 100644 index 05d85f2..0000000 Binary files a/docs/qa-gobang-facets-2026-10-06/dog1-gloss0.png and /dev/null differ diff --git a/docs/qa-gobang-facets-2026-10-06/dog1-mobile.png b/docs/qa-gobang-facets-2026-10-06/dog1-mobile.png deleted file mode 100644 index 67870fe..0000000 Binary files a/docs/qa-gobang-facets-2026-10-06/dog1-mobile.png and /dev/null differ diff --git a/docs/qa-gobang-facets-2026-10-06/dog2-grid20.png b/docs/qa-gobang-facets-2026-10-06/dog2-grid20.png deleted file mode 100644 index 75e0606..0000000 Binary files a/docs/qa-gobang-facets-2026-10-06/dog2-grid20.png and /dev/null differ diff --git a/docs/qa-gobang-facets-2026-10-06/initial-controls.json b/docs/qa-gobang-facets-2026-10-06/initial-controls.json deleted file mode 100644 index 8f81c1d..0000000 --- a/docs/qa-gobang-facets-2026-10-06/initial-controls.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "camera-offset": "0.13", - "curvature": "0.78", - "gloss-strength": "0.4", - "grid-size": "16", - "photo-pan-x": "0", - "photo-pan-y": "0", - "photo-zoom": "1", - "test-photo": "dog1", - "view-mode": "glass" -} \ No newline at end of file diff --git a/docs/qa-gobang-facets-2026-10-06/report.md b/docs/qa-gobang-facets-2026-10-06/report.md deleted file mode 100644 index 331e5be..0000000 --- a/docs/qa-gobang-facets-2026-10-06/report.md +++ /dev/null @@ -1,34 +0,0 @@ -# 확대 사진에 따른 고방유리 표면 보정 - -2026-10-06 사용자가 추가한 300×300 실물 사진을 현재 고방유리의 시각 목표로 삼았다. `target.png`는 그 첨부 파일의 원본 복사다. 기존 Ref1/Ref2 비교와 색면 옵션은 별도의 과거 표현으로 보존한다. - -## 판단과 변경 - -첫 구현은 평탄한 중심과 둥근 경사면의 곱으로 높이를 구성해 사각 쿠션/버튼처럼 보였다. 확대 사진에는 가로·세로 방향의 능선과 그 사이에서 늘어나고 꺾이는 투과 영상이 보인다. 후속 실험에서 X/Y 높이의 부드러운 최솟값으로 네 면을 만들었지만 대각선 삼각 조각이 두드러져 채택하지 않았다. - -현재 높이는 `0.25 px + 0.55 py + 0.20 px py`로 구성한다. `px`와 `py`는 중심과 셀 경계 부근만 둥글고 중간은 기울기가 일정한 반복 프로파일이다. 가로 능선에 더 큰 비중을 두고, 연속적인 작은 물결을 더한다. 셀별 사진 크롭이나 사각 색면, 검은 격자선을 추가하지 않는다. 동일 높이의 미분으로 얻은 법선을 기존 새 모드의 두 경계 굴절과 반사에 공유한다. 경계의 높이가 항상 0인 초기 곱 방식과 달리, 교차 능선의 높이와 기울기가 인접 셀에 주기적으로 이어진다. - -수정 코드는 `src/shaders/mosaic.frag`, `src/constants/glass.ts`, `src/main.ts`의 고방유리 표면 부분이다. 상수는 Grid 20, 높이/셀 크기 0.085, 중심 반폭 0.07셀, 경사 전환 둥글림 0.10, 굴절률 1.5, 기본 두께 0.008, 환경 반사 강도 0.45다. 기본 UI는 굴곡 +1 / 광택 0.3 / Camera 0.5를 유지한다. RGB/Depth 배치와 수동 구도는 변경하지 않았다. - -## 검증 - -- Codex in-app browser에서 최신 페이지와 WebGL 출력을 직접 확인했다. 기존 탭의 갱신이 실패해 같은 브라우저에 새 로컬 검증 탭을 열었다. -- dog1의 자동 AI depth 완료 후 Grid 20 기본값과 사용자 기존 설정 Grid 16 / 굴곡 0.78 / 광택 0.4 / Camera 0.13을 비교했다. 넓은 사각 방향의 사진 변형과 능선 반복을 확인했다. 첫 화면의 과도한 삼각 조각은 현재 높이에서 줄었다. -- dog2의 실내 배경에서도 자동 AI depth 완료 후 가로 능선을 따라 배경과 몸 윤곽이 꺾이는 출력을 확인했다(`dog2-grid20.png`). -- 광택 0에서도 굴절이 남는다. 광택 0 / 굴곡 0에서는 반복 변형이 사라진다. 굴곡 −1의 반대 변형과 드래그 시 시점 반응도 출력했다. -- 사진 확대 1 / 가로 팬 0 / 세로 팬 0 유지. 1280×900과 390×844 출력 확인. 모바일 문서 폭 375px, viewport 390px로 가로 넘침 없음. -- console error 없음. 기존 공유 depth 교점 반복에 대한 ANGLE implicit derivative 경고는 첫 구현과 동일한 제한이다. -- `npm.cmd run build -- --outDir test-results/gobang-facets-build`: 타입 검사와 Vite 빌드 통과. 기존 큰 번들 경고는 유지된다. -- 기존 surface-reflection, mosaic-continuity, region-axis-split 검사 통과. 이 검사는 기존 비교 경로를 보호하며 새 표면의 실물 일치도를 보증하지 않는다. - -비교 파일: `before-current-settings.png`는 변경 전 화면(기본 브라우저 폭), `dog1-current-settings.png`는 같은 재질 설정의 변경 후 화면(데스크톱 검증 폭)이다. `initial-controls.json`에 변경 전 값이 남아 있다. `dog1-directional-grid20.png`, `dog1-gloss0.png`, `dog1-flat-gloss0.png`, `dog1-concave.png`, `dog1-drag.png`, `dog1-final-desktop.png`, `dog1-final-pane.png`, `dog1-mobile.png`에 조건별 출력을 저장했다. 확대·팬 값은 모두 동일하지만 화면 크기가 다른 두 파일을 픽셀 단위 전후 비교로 취급하지 않는다. - -## 현재 한계 - -실물의 측정된 표면을 복원한 재질은 아니다. 규칙적인 절차적 높이장으로 방향성 있는 굴절을 근사했다. 실물의 비대칭 경사, 미세한 능선 반사, 제품별 불규칙성은 더 보정할 여지가 있고 첨부 사진과 완전히 같다고 판정하지 않았다. 실물 사진은 뒤 배경과 조명 조건도 다르므로 강아지 사진의 색이나 명암이 같아질 것을 완료 기준으로 삼지 않는다. 실기기 FPS와 영상 flicker 계측은 수행하지 않았다. - -실행: 프로젝트 루트에서 `npm.cmd run dev -- --host 127.0.0.1 --port 5174`, 로컬 미리보기 `http://127.0.0.1:5174/`. 유리 패턴은 `고방유리 · 표면 굴절`, 개발 비교의 View Mode는 `Final`로 확인한다. - -![사용자 확대 레퍼런스](target.png) - -![현재 기본값의 사진 투과 결과](dog1-final-pane.png) diff --git a/docs/qa-gobang-facets-2026-10-06/target.png b/docs/qa-gobang-facets-2026-10-06/target.png deleted file mode 100644 index e67e89e..0000000 Binary files a/docs/qa-gobang-facets-2026-10-06/target.png and /dev/null differ diff --git a/docs/qa-gobang-review-2026-10-06/before-rollback/glass.ts b/docs/qa-gobang-review-2026-10-06/before-rollback/glass.ts deleted file mode 100644 index 9720e26..0000000 --- a/docs/qa-gobang-review-2026-10-06/before-rollback/glass.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const ENVIRONMENT_REFLECTION_STRENGTH = 0.12; -// Keep color planes dominant without flattening all continuous lens detail. -export const GLASS_TRANSMISSION_DETAIL = 0.42; -export const CELL_LENS_SCALE = 1.2; diff --git a/docs/qa-gobang-review-2026-10-06/before-rollback/main.ts b/docs/qa-gobang-review-2026-10-06/before-rollback/main.ts deleted file mode 100644 index c2a3f59..0000000 --- a/docs/qa-gobang-review-2026-10-06/before-rollback/main.ts +++ /dev/null @@ -1,468 +0,0 @@ -import * as THREE from 'three'; -import './style.css'; -import vertexShader from './shaders/common.vert?raw'; -import mosaicShader from './shaders/mosaic.frag?raw'; -import reededShader from './shaders/reeded.frag?raw'; -import frostedShader from './shaders/frosted.frag?raw'; -import { MediaLoader } from './input/MediaLoader'; -import { PointerController } from './input/PointerController'; -import { CameraController } from './input/CameraController'; -import { GyroController } from './input/GyroController'; -import { StaticDepthProvider } from './depth/StaticDepthProvider'; -import { DepthProcessor } from './depth/DepthProcessor'; -import { DEPTH_REFRACTION } from './constants/depth'; -import { ENVIRONMENT_REFLECTION_STRENGTH, GLASS_TRANSMISSION_DETAIL, CELL_LENS_SCALE } from './constants/glass'; -import { AiDepthProvider } from './depth/AiDepthProvider'; -import { PetDepthMesh } from './objects/PetDepthMesh'; -import { DepthDebug } from './depth/DepthDebug'; -import { WindowReveal } from './objects/WindowReveal'; -import glassScreenVertex from './shaders/glassScreen.vert?raw'; -import regionPaletteShader from './shaders/region-palette.frag?raw'; -import regionHistoryShader from './shaders/region-history.frag?raw'; - -const wrap = document.querySelector('#canvas-wrap') as HTMLElement; -const status = document.querySelector('#status') as HTMLElement; -const depthProvenance = document.querySelector('#depth-provenance') as HTMLElement; -const aiDepthButton = document.querySelector('#ai-depth') as HTMLButtonElement; -const empty = document.querySelector('#empty') as HTMLElement; -const hintElement = document.querySelector('#hint') as HTMLElement; -hintElement.style.opacity = '0'; -const renderer = new THREE.WebGLRenderer({ antialias: true }); -renderer.setPixelRatio(Math.min(devicePixelRatio, 1.5)); -wrap.append(renderer.domElement); -const scene = new THREE.Scene(); -const glassScene = new THREE.Scene(); -const frameScene = new THREE.Scene(); -scene.background = new THREE.Color(0x111923); -const camera = new THREE.PerspectiveCamera(40, 1, 0.1, 100); -camera.position.z = 3; -const geometry = new THREE.PlaneGeometry(1, 1); -const emptyTex = new THREE.DataTexture(new Uint8Array([38, 48, 62, 255]), 1, 1); -emptyTex.needsUpdate = true; -const petMat = new THREE.MeshBasicMaterial({ map: emptyTex }); -const pet = new THREE.Mesh(geometry, petMat); -scene.add(pet); -const depthMap: THREE.Texture = DepthProcessor.flatTexture(); -const petDepth = new PetDepthMesh(emptyTex, depthMap, 0.25, 0); -const petDepthMaterial = petDepth.material; -const depthUniforms = petDepthMaterial.uniforms; -scene.add(petDepth); -const uniforms = { uSceneTexture: { value: emptyTex as THREE.Texture }, uSceneDepth: { value: emptyTex as THREE.Texture }, uProtectionDepthMap: depthUniforms.uDepthMap, uPetWorldToLocal: { value: new THREE.Matrix4() }, uContentViewProjection: { value: new THREE.Matrix4() }, uContentInverseViewProjection: { value: new THREE.Matrix4() }, uContentCameraPosition: { value: new THREE.Vector3() }, uLightPosition: { value: new THREE.Vector3(0.6, 0.8, 2.6) }, uBackgroundColor: { value: scene.background.clone() }, uGlassZ: { value: 0.6 }, uSourceZ: { value: 0.56 }, uGridSize: { value: 13 }, uMosaicStyle: { value: 0 }, uStrength: { value: 1 }, uGlossStrength: { value: 0.3 }, uCurvature: { value: 1 }, uRegionStrength: { value: 1 }, uRegionAvailable: { value: 0 }, uRegionAtlasSize: { value: new THREE.Vector2(104, 104) }, uRegionGridSize: { value: new THREE.Vector2(13, 13) }, uRegionPaletteSize: { value: new THREE.Vector2(65, 13) }, uRegionPalette: { value: emptyTex as THREE.Texture }, uRegionAtlas: { value: emptyTex as THREE.Texture }, uViewOffset: { value: new THREE.Vector2() }, uPaneRect: { value: new THREE.Vector4(0, 0, 1, 1) }, uResolution: { value: new THREE.Vector2() }, uTime: { value: 0 }, uPetSize: { value: new THREE.Vector2(1, 1) }, uPaneSize: { value: new THREE.Vector2(1, 1) } }; -const regionHistoryUniform = { value: emptyTex as THREE.Texture }; -const depthEvidenceUniform = { value: new THREE.Vector2(1, 1) }; -Object.assign(uniforms, { uRegionHistory: regionHistoryUniform, uDepthEvidenceRange: depthEvidenceUniform, - uEnvironmentStrength: { value: ENVIRONMENT_REFLECTION_STRENGTH }, - uTransmissionDetail: { value: GLASS_TRANSMISSION_DETAIL }, - uCellLensScale: { value: CELL_LENS_SCALE }, - uDepthCorrection: { value: new THREE.Vector2(DEPTH_REFRACTION.blend, DEPTH_REFRACTION.maxCellCorrection) } }); -const glassMat = new THREE.ShaderMaterial({ uniforms, vertexShader: glassScreenVertex, fragmentShader: mosaicShader }); -const glass = new THREE.Mesh(new THREE.PlaneGeometry(2, 2), glassMat); -glassScene.add(glass); -const atlasScene = new THREE.Scene(); -const atlasMaterial = new THREE.ShaderMaterial({ uniforms, vertexShader: glassScreenVertex, fragmentShader: mosaicShader, defines: { REGION_ATLAS: 1 }, toneMapped: false }); -const atlasMesh = new THREE.Mesh(new THREE.PlaneGeometry(2, 2), atlasMaterial); -atlasScene.add(atlasMesh); -const paletteScene = new THREE.Scene(); -const paletteUniforms = { uRegionAtlas: { value: null as THREE.Texture | null }, uRegionAtlasSize: uniforms.uRegionAtlasSize, uRegionGridSize: uniforms.uRegionGridSize }; -const paletteMaterial = new THREE.ShaderMaterial({ uniforms: paletteUniforms, vertexShader: glassScreenVertex, fragmentShader: regionPaletteShader, toneMapped: false }); -const paletteMesh = new THREE.Mesh(new THREE.PlaneGeometry(2, 2), paletteMaterial); -paletteScene.add(paletteMesh); -const frameGeometry = new THREE.BoxGeometry(1, 1, 1); -const frameMaterials = [ - new THREE.MeshBasicMaterial({ color: 0x3a2419 }), - new THREE.MeshBasicMaterial({ color: 0x4a2e20 }), - new THREE.MeshBasicMaterial({ color: 0x2b1a13 }), - new THREE.MeshBasicMaterial({ color: 0x513326 }), - new THREE.MeshBasicMaterial({ color: 0x321f17 }), - new THREE.MeshBasicMaterial({ color: 0x43291d }) -]; -const frameLeft = new THREE.Mesh(frameGeometry, frameMaterials); -const frameRight = new THREE.Mesh(frameGeometry, frameMaterials); -const frameTop = new THREE.Mesh(frameGeometry, frameMaterials); -const frameBottom = new THREE.Mesh(frameGeometry, frameMaterials); -frameScene.add(frameLeft, frameRight, frameTop, frameBottom); -const windowRevealMaterial = new THREE.MeshBasicMaterial({ color: frameMaterials[1].color, side: THREE.DoubleSide }); -const windowReveal = new WindowReveal(windowRevealMaterial); -frameScene.add(...windowReveal.meshes); -const postCamera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1); -const renderTarget = new THREE.WebGLRenderTarget(1, 1, { colorSpace: THREE.NoColorSpace, type: THREE.HalfFloatType, depthBuffer: true }); -renderTarget.depthTexture = new THREE.DepthTexture(1, 1, THREE.UnsignedIntType); -renderTarget.depthTexture.format = THREE.DepthFormat; -uniforms.uSceneDepth.value = renderTarget.depthTexture; -const regionAtlasTarget = new THREE.WebGLRenderTarget(104, 104, { colorSpace: THREE.NoColorSpace, type: THREE.HalfFloatType, depthBuffer: false, minFilter: THREE.NearestFilter, magFilter: THREE.NearestFilter }); -const regionPaletteTarget = new THREE.WebGLRenderTarget(65, 13, { colorSpace: THREE.NoColorSpace, type: THREE.UnsignedByteType, depthBuffer: false, minFilter: THREE.NearestFilter, magFilter: THREE.NearestFilter }); -const splitHistoryTargets = [0, 1].map(() => new THREE.WebGLRenderTarget(104, 104, { colorSpace: THREE.NoColorSpace, type: THREE.HalfFloatType, depthBuffer: false, minFilter: THREE.NearestFilter, magFilter: THREE.NearestFilter })); -const historyScene = new THREE.Scene(); -const historyUniforms = { uRegionPalette: { value: regionPaletteTarget.texture }, uPreviousHistory: { value: splitHistoryTargets[0].texture }, uRegionAtlasSize: uniforms.uRegionAtlasSize, uRegionGridSize: uniforms.uRegionGridSize, uRegionPaletteSize: uniforms.uRegionPaletteSize, uHistoryBlend: { value: 1 } }; -const historyMaterial = new THREE.ShaderMaterial({ uniforms: historyUniforms, vertexShader: glassScreenVertex, fragmentShader: regionHistoryShader, toneMapped: false }); -const historyMesh = new THREE.Mesh(new THREE.PlaneGeometry(2, 2), historyMaterial); -historyScene.add(historyMesh); -uniforms.uRegionPalette.value = regionPaletteTarget.texture; -paletteUniforms.uRegionAtlas.value = regionAtlasTarget.texture; -let regionSignature = ''; -let splitHistorySignature = ''; -let splitHistoryRead = 0; -let splitHistoryInitialized = false; -function updateRegionTargetSizes(): void { - const gridX = Math.max(1, Math.ceil(uniforms.uGridSize.value)); - const gridYValue = Math.max(1, uniforms.uGridSize.value * uniforms.uPaneSize.value.y / Math.max(uniforms.uPaneSize.value.x, 0.001)); - const gridY = Math.ceil(gridYValue); - const atlasWidth = gridX * 8, atlasHeight = gridY * 8, paletteWidth = gridX * 5, paletteHeight = gridY; - const available = Math.max(atlasWidth, atlasHeight, paletteWidth, paletteHeight) <= renderer.capabilities.maxTextureSize; - const changed = uniforms.uRegionAvailable.value !== (available ? 1 : 0) || (available && (regionAtlasTarget.width !== atlasWidth || regionAtlasTarget.height !== atlasHeight || regionPaletteTarget.width !== paletteWidth || regionPaletteTarget.height !== paletteHeight || splitHistoryTargets[0].width !== atlasWidth || splitHistoryTargets[0].height !== atlasHeight)) || uniforms.uRegionGridSize.value.x !== uniforms.uGridSize.value || uniforms.uRegionGridSize.value.y !== gridYValue; - if (available && (regionAtlasTarget.width !== atlasWidth || regionAtlasTarget.height !== atlasHeight)) regionAtlasTarget.setSize(atlasWidth, atlasHeight); - if (available && (regionPaletteTarget.width !== paletteWidth || regionPaletteTarget.height !== paletteHeight)) regionPaletteTarget.setSize(paletteWidth, paletteHeight); - for (const target of splitHistoryTargets) if (available && (target.width !== atlasWidth || target.height !== atlasHeight)) target.setSize(atlasWidth, atlasHeight); - uniforms.uRegionAvailable.value = available ? 1 : 0; - uniforms.uRegionAtlasSize.value.set(available ? atlasWidth : regionAtlasTarget.width, available ? atlasHeight : regionAtlasTarget.height); - uniforms.uRegionGridSize.value.set(uniforms.uGridSize.value, gridYValue); - uniforms.uRegionPaletteSize.value.set(available ? paletteWidth : regionPaletteTarget.width, available ? paletteHeight : regionPaletteTarget.height); - paletteUniforms.uRegionAtlas.value = regionAtlasTarget.texture; - uniforms.uRegionPalette.value = regionPaletteTarget.texture; - uniforms.uRegionAtlas.value = regionAtlasTarget.texture; - if (changed) regionSignature = ''; -} -let active: THREE.Texture = emptyTex; -let activeIsVideo = false; -let aspect = 1; -let baseW = 1; -let baseH = 1; -let photoZoom = 1; -let photoPanX = 0; -let photoPanY = 0; -let pendingSampleFraming = false; -let activeTestPhotoHasNoDepth = false; -let mode = 'noglass'; -let hintGeneration = 0; -let hintDraggedGeneration = -1; -let pendingPairDepth: THREE.Texture | null = null; -let pendingSampleDebugImage: HTMLImageElement | null = null; -let pendingTestPhotoHasNoDepth = false; -let mediaRequest = 0; -let depthRequest = 0; -let mediaBusy = false; -let manualDepthBusy = false; -let aiDepthBusy = false; -let disposed = false; -const listenerAbort = new AbortController(); -function syncAIDepthButton(): void { - aiDepthButton.disabled = active === emptyTex || activeIsVideo || mediaBusy || manualDepthBusy || aiDepthBusy || disposed; - aiDepthButton.textContent = aiDepthBusy ? 'AI 깊이 생성 중…' : 'AI 깊이 생성'; -} -const aiDepthProvider = new AiDepthProvider((message) => { if (!disposed && aiDepthBusy) status.textContent = message; }); -function invalidateDepthRequests(): void { - depthRequest += 1; - aiDepthProvider.cancel(); - aiDepthBusy = false; - manualDepthBusy = false; - syncAIDepthButton(); -} -function clearPendingPair(): void { if (pendingPairDepth) pendingPairDepth.dispose(); pendingPairDepth = null; } -let maxDepthValue = 0; -function contentBaseZ(): number { return uniforms.uGlassZ.value - 0.04 - (maxDepthValue - depthUniforms.uDepthBias.value) * depthUniforms.uDepthScale.value; } -function clearPendingTestState(): void { clearPendingPair(); pendingSampleDebugImage = null; pendingSampleFraming = false; pendingTestPhotoHasNoDepth = false; } -function applyFraming(): void { - const baseZ = contentBaseZ(); - const worldScale = (camera.position.z - baseZ) / camera.position.z; - const x = baseW * (photoZoom - 1) * 0.5 * photoPanX * worldScale; - const y = baseH * (photoZoom - 1) * 0.5 * photoPanY * worldScale; - pet.scale.set(baseW * photoZoom * worldScale, baseH * photoZoom * worldScale, 1); - pet.position.set(x, y, baseZ); - petDepth.scale.copy(pet.scale); - petDepth.position.copy(pet.position); - uniforms.uSourceZ.value = baseZ; - windowReveal.update(uniforms.uPaneSize.value.x, uniforms.uPaneSize.value.y, baseW * (3 - baseZ) / 3, baseH * (3 - baseZ) / 3, uniforms.uGlassZ.value, baseZ); -} -function resize(): void { - const bounds = wrap.getBoundingClientRect(); - renderer.setSize(bounds.width, bounds.height, false); - camera.aspect = bounds.width / bounds.height; - camera.updateProjectionMatrix(); - const height = 1.7; - const scale = Math.min(height * bounds.width / bounds.height / aspect, height); - baseW = scale * aspect; - baseH = scale; - applyFraming(); - uniforms.uPetSize.value.set(baseW, baseH); - uniforms.uResolution.value.set(bounds.width, bounds.height); - const glassHeight = 2 * (camera.position.z - 0.6) * Math.tan(THREE.MathUtils.degToRad(camera.fov / 2)); - uniforms.uPetSize.value.set(glassHeight * camera.aspect, glassHeight); - uniforms.uPaneSize.value.set(baseW * (3 - uniforms.uGlassZ.value) / 3, baseH * (3 - uniforms.uGlassZ.value) / 3); - windowReveal.update(uniforms.uPaneSize.value.x, uniforms.uPaneSize.value.y, baseW * (3 - contentBaseZ()) / 3, baseH * (3 - contentBaseZ()) / 3, uniforms.uGlassZ.value, contentBaseZ()); - updateRegionTargetSizes(); - const frameW = uniforms.uPaneSize.value.x; - const frameH = uniforms.uPaneSize.value.y; - const frameThickness = Math.min(frameW, frameH) * 0.035; - const frameDepth = frameThickness * 1.5; - const frameZ = uniforms.uGlassZ.value + frameDepth * 0.25; - frameLeft.position.set(-(frameW + frameThickness) * 0.5, 0, frameZ); - frameRight.position.set((frameW + frameThickness) * 0.5, 0, frameZ); - frameTop.position.set(0, (frameH + frameThickness) * 0.5, frameZ); - frameBottom.position.set(0, -(frameH + frameThickness) * 0.5, frameZ); - frameLeft.scale.set(frameThickness, frameH, frameDepth); - frameRight.scale.set(frameThickness, frameH, frameDepth); - frameTop.scale.set(frameW + frameThickness * 2, frameThickness, frameDepth); - frameBottom.scale.set(frameW + frameThickness * 2, frameThickness, frameDepth); - const neutralGlassHeight = 2 * 3 * Math.tan(THREE.MathUtils.degToRad(40 / 2)); - const neutralGlassWidth = neutralGlassHeight * camera.aspect; - uniforms.uPaneRect.value.set(Math.max(0, 0.5 - baseW / (2 * neutralGlassWidth)), Math.max(0, 0.5 - baseH / (2 * neutralGlassHeight)), Math.min(1, 0.5 + baseW / (2 * neutralGlassWidth)), Math.min(1, 0.5 + baseH / (2 * neutralGlassHeight))); - renderTarget.setSize(Math.max(1, Math.floor(bounds.width * Math.min(devicePixelRatio, 1.5))), Math.max(1, Math.floor(bounds.height * Math.min(devicePixelRatio, 1.5)))); -} -function resetHintForMedia(): void { hintGeneration += 1; hintDraggedGeneration = -1; hintElement.style.opacity = '0'; } -function showHint(): void { if (hintDraggedGeneration === hintGeneration) return; hintElement.style.opacity = '1'; } -function hideHintAfterDrag(): void { hintDraggedGeneration = hintGeneration; hintElement.style.opacity = '0'; } -function applyMedia(texture: THREE.Texture, mediaAspect: number, video: HTMLVideoElement | null): void { - if (active !== emptyTex) active.dispose(); - active = texture; activeIsVideo = Boolean(video); mediaBusy = false; aspect = mediaAspect; - pendingSampleFraming = false; - syncPhotoControls(); - texture.colorSpace = THREE.SRGBColorSpace; - depthUniforms.uTexture.value = texture; - petMat.map = texture; petMat.needsUpdate = true; - empty.style.display = 'none'; resize(); syncAIDepthButton(); -} -function setDepth(texture: THREE.Texture): void { - if (depthUniforms.uDepthMap.value !== depthMap) depthUniforms.uDepthMap.value.dispose(); - depthUniforms.uDepthMap.value = texture; texture.colorSpace = THREE.NoColorSpace; - depthEvidenceUniform.value.fromArray(DepthProcessor.evidenceRange(texture)); - const data = (texture as THREE.DataTexture).image?.data; - maxDepthValue = 0; - if (data && data.length >= 4) { - for (let i = 0; i < data.length; i += 4) maxDepthValue = Math.max(maxDepthValue, Number(data[i]) / 255); - } - applyFraming(); - regionSignature = ''; - if (mode === 'depth') { petMat.map = texture; petMat.needsUpdate = true; } -} -function setMode(next: string): void { - mode = next; - if (modeInput) modeInput.value = next; - pet.visible = next === 'rgb' || next === 'depth'; - petDepth.visible = next === 'noglass' || next === 'final'; - glass.visible = next === 'final' || next === 'glass'; - petMat.map = next === 'depth' ? depthUniforms.uDepthMap.value : active; - petMat.needsUpdate = true; - petDepthMaterial.uniforms.uTexture.value = active; -} -const retry = document.createElement('button'); -retry.textContent = '재생'; retry.hidden = true; -(document.querySelector('aside') as HTMLElement).append(retry); -const debugOutput = document.createElement('pre'); -debugOutput.id = 'depth-debug'; -debugOutput.hidden = true; -(document.querySelector('aside') as HTMLElement).append(debugOutput); -const depthDebug = new DepthDebug(); -const loader = new MediaLoader((texture, mediaAspect, video) => { const hasSampleDepth = pendingSampleFraming && pendingPairDepth !== null; const hasTestWithoutDepth = pendingTestPhotoHasNoDepth; const shouldGenerateDepth = !video && !hasSampleDepth; applyMedia(texture, mediaAspect, video); petDepth.setVideo(Boolean(video)); setDepth(pendingPairDepth ?? DepthProcessor.flatTexture()); pendingPairDepth = null; if (hasSampleDepth && pendingSampleDebugImage) depthDebug.setSample(pendingSampleDebugImage); else depthDebug.clear(); pendingSampleDebugImage = null; activeTestPhotoHasNoDepth = hasTestWithoutDepth; pendingTestPhotoHasNoDepth = false; depthProvenance.hidden = !(hasSampleDepth || activeTestPhotoHasNoDepth); if (hasSampleDepth) depthProvenance.textContent = '수작업 테스트 Depth · AI 추정 아님'; else if (activeTestPhotoHasNoDepth) depthProvenance.textContent = 'Depth 없음 · 평면 사진 테스트'; setMode('final'); showHint(); if (sampleButton) sampleButton.textContent = '선택한 테스트 사진 불러오기'; if (shouldGenerateDepth) void generateAIDepth(true); }, (message) => { mediaBusy = false; syncAIDepthButton(); if (message || !aiDepthBusy) status.textContent = message; retry.hidden = !message.includes('자동'); if (message) { clearPendingTestState(); if (sampleButton) sampleButton.textContent = '선택한 테스트 사진 불러오기'; } }); -retry.onclick = () => loader.retry(); -const sampleDepthProvider = new StaticDepthProvider('/assets/sample-pet-depth.png'); -const cameraController = new CameraController(camera); -const pointer = new PointerController(renderer.domElement, (x, y) => cameraController.add(x, y), hideHintAfterDrag); -const gyro = new GyroController((x, y) => cameraController.target.set(THREE.MathUtils.clamp(x, -1, 1), THREE.MathUtils.clamp(y, -1, 1)), (message) => { status.textContent = message; }); -const imageInput = document.querySelector('#image') as HTMLInputElement; -const videoInput = document.querySelector('#video') as HTMLInputElement; -const depthFileInput = document.querySelector('#depth-image') as HTMLInputElement; -const sampleButton = document.querySelector('#sample') as HTMLButtonElement | null; -const testPhotoInput = document.querySelector('#test-photo') as HTMLSelectElement; -const referenceStrip = document.querySelector('#reference-strip') as HTMLElement; -const referenceStatus = document.querySelector('#reference-status') as HTMLElement; -const referenceImages = [ - document.querySelector('#reference-image-1') as HTMLImageElement, - document.querySelector('#reference-image-2') as HTMLImageElement -]; -referenceStrip.hidden = false; -const showReferenceError = () => { referenceStatus.hidden = false; }; -referenceImages.forEach((image) => image.addEventListener('error', showReferenceError, { signal: listenerAbort.signal })); -void Promise.all([ - import('../docs/qa-five-photos/reference1.png?url'), - import('../docs/qa-five-photos/reference2.png?url') -]).then(([reference1, reference2]) => { - if (disposed) return; - referenceImages[0].src = reference1.default; - referenceImages[1].src = reference2.default; -}).catch(() => { if (!disposed) showReferenceError(); }); -const effectInput = document.querySelector('#effect') as HTMLSelectElement; -const modeInput = document.querySelector('#view-mode') as HTMLSelectElement | null; -const sensitivityInput = document.querySelector('#sensitivity') as HTMLInputElement; -const depthInput = document.querySelector('#depth-scale') as HTMLInputElement | null; -const cameraOffsetInput = document.querySelector('#camera-offset') as HTMLInputElement; -const gridInput = document.querySelector('#grid-size') as HTMLInputElement; -const gridOutput = document.querySelector('#gridOut') as HTMLOutputElement; -const mosaicStyleInput = document.querySelector('#mosaic-style') as HTMLSelectElement; -const mosaicStyleLabel = mosaicStyleInput.closest('label'); -const glossControls = document.querySelector('#gloss-controls') as HTMLElement | null; -const regionFixedNote = document.querySelector('#region-fixed-note') as HTMLElement | null; -const curvatureInput = document.querySelector('#curvature') as HTMLInputElement | null; -const glossInput = document.querySelector('#gloss-strength') as HTMLInputElement | null; -const lightXInput = document.querySelector('#light-x') as HTMLInputElement | null; -const lightYInput = document.querySelector('#light-y') as HTMLInputElement | null; -const glossOutput = document.querySelector('#glossOut') as HTMLOutputElement | null; -const lightXOutput = document.querySelector('#lightXOut') as HTMLOutputElement | null; -const lightYOutput = document.querySelector('#lightYOut') as HTMLOutputElement | null; -const cameraOutput = document.querySelector('#cameraOut') as HTMLOutputElement; -const sensitivityOutput = document.querySelector('#sensitivityOut') as HTMLOutputElement; -const depthOutput = document.querySelector('#depthOut') as HTMLOutputElement | null; -const photoZoomInput = document.querySelector('#photo-zoom') as HTMLInputElement | null; -const photoZoomOutput = document.querySelector('#photoZoomOut') as HTMLOutputElement | null; -const photoPanXInput = document.querySelector('#photo-pan-x') as HTMLInputElement | null; -const photoPanXOutput = document.querySelector('#photoPanXOut') as HTMLOutputElement | null; -const photoPanYInput = document.querySelector('#photo-pan-y') as HTMLInputElement | null; -const photoPanYOutput = document.querySelector('#photoPanYOut') as HTMLOutputElement | null; -const photoResetButton = document.querySelector('#photo-reset') as HTMLButtonElement | null; -const resetButton = document.querySelector('#reset') as HTMLButtonElement; -const gyroButton = document.querySelector('#gyro') as HTMLButtonElement; -const effects = [mosaicShader, reededShader, frostedShader]; -let sensitivity = 1; -function setGlossControlsVisibility(): void { - const enabled = effectInput.value === 'mosaic'; - const ref1Mosaic = enabled && mosaicStyleInput.value === '0'; - if (mosaicStyleLabel) mosaicStyleLabel.style.display = enabled ? 'grid' : 'none'; - mosaicStyleInput.disabled = !enabled; - if (glossControls) { glossControls.hidden = !enabled; glossControls.style.display = enabled ? 'grid' : 'none'; } - if (regionFixedNote) regionFixedNote.hidden = !ref1Mosaic; - [glossInput, lightXInput, lightYInput, curvatureInput].forEach((input) => { if (input) input.disabled = !enabled; }); -} -function syncPhotoControls(): void { - if (photoZoomInput) photoZoomInput.value = photoZoom.toFixed(2); - if (photoZoomOutput) photoZoomOutput.value = photoZoom.toFixed(2); - if (photoPanXInput) photoPanXInput.value = photoPanX.toFixed(2); - if (photoPanXOutput) photoPanXOutput.value = photoPanX.toFixed(2); - if (photoPanYInput) photoPanYInput.value = photoPanY.toFixed(2); - if (photoPanYOutput) photoPanYOutput.value = photoPanY.toFixed(2); -} -async function generateAIDepth(automatic = false): Promise { - if (aiDepthButton.disabled || !(active.image instanceof HTMLImageElement)) return; - const sourceTexture = active; - const sourceImage = active.image; - const request = ++depthRequest; - aiDepthBusy = true; - status.textContent = 'AI 모델을 준비하는 중입니다. 처음 실행하면 모델 파일을 다운로드합니다.'; - syncAIDepthButton(); - try { - const texture = await aiDepthProvider.getDepthMap(sourceImage); - if (disposed || request !== depthRequest || active !== sourceTexture || activeIsVideo) { - texture.dispose(); - return; - } - setDepth(texture); - depthDebug.clear(); - activeTestPhotoHasNoDepth = false; - depthProvenance.hidden = false; - depthProvenance.textContent = 'AI 추정 · Depth Anything V2 Small (상대 깊이, 0=뒤 · 1=앞)'; - setMode('final'); - status.textContent = automatic ? '자동 AI 추정 depth를 적용했습니다.' : 'AI 추정 depth를 적용하고 Final 뷰로 돌아왔습니다.'; - showHint(); - } catch (error) { - if (!disposed && request === depthRequest) { - const detail = error instanceof Error ? error.message : '알 수 없는 오류'; - status.textContent = automatic ? `자동 depth 생성 실패 (${detail}). 평면 사진 배치를 유지합니다. AI 깊이 생성 버튼으로 다시 시도할 수 있습니다.` : `AI 깊이 생성 실패 (${detail}). 다시 시도할 수 있으며 기존 depth는 유지됩니다.`; - } - } finally { - if (request === depthRequest) { - aiDepthBusy = false; - syncAIDepthButton(); - } - } -} -aiDepthButton.addEventListener('click', () => { void generateAIDepth(); }, { signal: listenerAbort.signal }); -imageInput.onchange = (event) => { const input = event.target as HTMLInputElement; const file = input.files?.[0]; if (file) { resetHintForMedia(); mediaRequest += 1; invalidateDepthRequests(); mediaBusy = true; syncAIDepthButton(); clearPendingTestState(); loader.load(file); } input.value = ''; }; -videoInput.onchange = (event) => { const input = event.target as HTMLInputElement; const file = input.files?.[0]; if (file) { resetHintForMedia(); mediaRequest += 1; invalidateDepthRequests(); mediaBusy = true; syncAIDepthButton(); clearPendingTestState(); loader.load(file); } input.value = ''; }; -photoZoomInput?.addEventListener('input', (event) => { photoZoom = Number((event.target as HTMLInputElement).value); applyFraming(); syncPhotoControls(); }, { signal: listenerAbort.signal }); -photoPanXInput?.addEventListener('input', (event) => { photoPanX = Number((event.target as HTMLInputElement).value); applyFraming(); syncPhotoControls(); }, { signal: listenerAbort.signal }); -photoPanYInput?.addEventListener('input', (event) => { photoPanY = Number((event.target as HTMLInputElement).value); applyFraming(); syncPhotoControls(); }, { signal: listenerAbort.signal }); -photoResetButton?.addEventListener('click', () => { photoZoom = 1; photoPanX = 0; photoPanY = 0; applyFraming(); syncPhotoControls(); }, { signal: listenerAbort.signal }); -sampleButton?.addEventListener('click', async () => { const request = ++mediaRequest; const selected = testPhotoInput.value; const isSample = selected === 'sample'; const filePath = isSample ? '/assets/sample-pet.png' : `/assets/qa/${selected === 'dog3' ? 'dog3.webp' : `${selected}.jpeg`}`; invalidateDepthRequests(); mediaBusy = true; syncAIDepthButton(); loader.cancelPending(); clearPendingTestState(); sampleButton.textContent = `불러오는 중: ${filePath.split('/').pop()}`; status.textContent = ''; let url = ''; try { const rgbResponse = await fetch(filePath); if (!rgbResponse.ok) throw new Error('image'); const rgb = await rgbResponse.blob(); if (disposed || request !== mediaRequest) return; if (isSample) { const depthResponse = await fetch('/assets/sample-pet-depth.png'); if (!depthResponse.ok) throw new Error('depth'); const depth = await depthResponse.blob(); if (disposed || request !== mediaRequest) return; url = URL.createObjectURL(depth); const image = new Image(); image.src = url; await image.decode(); if (disposed || request !== mediaRequest) return; const loadedDepth = await sampleDepthProvider.getDepthMap(image); if (disposed || request !== mediaRequest) { loadedDepth.dispose(); return; } pendingPairDepth = loadedDepth; pendingSampleDebugImage = image; pendingSampleFraming = true; } pendingTestPhotoHasNoDepth = !isSample; loader.load(new File([rgb], filePath.split('/').pop() ?? 'test-photo', { type: rgbResponse.headers.get('content-type') ?? 'image/jpeg' })); if (isSample) status.textContent = '수작업 테스트 Depth · AI 추정 아님'; } catch { if (!disposed && request === mediaRequest) { mediaBusy = false; syncAIDepthButton(); clearPendingTestState(); status.textContent = isSample ? '샘플 사진 또는 depth map을 읽지 못했습니다.' : '테스트 사진을 읽지 못했습니다.'; sampleButton.textContent = '선택한 테스트 사진 불러오기'; } } finally { if (url) URL.revokeObjectURL(url); } }, { signal: listenerAbort.signal }); -sampleButton?.addEventListener('click', resetHintForMedia, { signal: listenerAbort.signal }); -effectInput.addEventListener('change', (event) => { const index = ['mosaic', 'reeded', 'frosted'].indexOf((event.target as HTMLSelectElement).value); glassMat.fragmentShader = effects[index]; glassMat.needsUpdate = true; setGlossControlsVisibility(); }, { signal: listenerAbort.signal }); -modeInput?.addEventListener('change', (event) => setMode((event.target as HTMLSelectElement).value), { signal: listenerAbort.signal }); -sensitivityInput.oninput = (event) => { const value = Number((event.target as HTMLInputElement).value); sensitivity = value; sensitivityOutput.value = value.toFixed(2); }; -depthInput?.addEventListener('input', (event) => { const value = Math.min(Number((event.target as HTMLInputElement).value), 0.4); depthUniforms.uDepthScale.value = value; applyFraming(); regionSignature = ''; if (depthOutput) depthOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -cameraOffsetInput.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); cameraController.setMaxOffset(value); cameraOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -gridInput.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uGridSize.value = value; gridOutput.value = value.toFixed(0); updateRegionTargetSizes(); }, { signal: listenerAbort.signal }); -mosaicStyleInput.addEventListener('change', (event) => { if (effectInput.value !== 'mosaic') return; const style = Number((event.target as HTMLSelectElement).value); uniforms.uMosaicStyle.value = style; uniforms.uGridSize.value = style === 0 ? 13 : 24; uniforms.uStrength.value = 1; gridInput.value = String(uniforms.uGridSize.value); gridOutput.value = String(uniforms.uGridSize.value); updateRegionTargetSizes(); setGlossControlsVisibility(); }, { signal: listenerAbort.signal }); -curvatureInput?.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uCurvature.value = value; const output = document.querySelector('#curvatureOut') as HTMLOutputElement | null; if (output) output.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -glossInput?.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uGlossStrength.value = value; if (glossOutput) glossOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -lightXInput?.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uLightPosition.value.x = value; if (lightXOutput) lightXOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -lightYInput?.addEventListener('input', (event) => { const value = Number((event.target as HTMLInputElement).value); uniforms.uLightPosition.value.y = value; if (lightYOutput) lightYOutput.value = value.toFixed(2); }, { signal: listenerAbort.signal }); -depthFileInput?.addEventListener('change', async () => { invalidateDepthRequests(); const request = depthRequest; const file = depthFileInput.files?.[0]; if (!file) return; manualDepthBusy = true; syncAIDepthButton(); depthDebug.clear(); const url = URL.createObjectURL(file); let texture: THREE.Texture | null = null; try { const image = new Image(); image.src = url; await image.decode(); if (disposed || request !== depthRequest) return; if (aspect > 0 && Math.abs(image.width / image.height - aspect) > 0.02) throw new Error('aspect'); texture = DepthProcessor.toTexture(image); if (disposed || request !== depthRequest) { texture.dispose(); texture = null; return; } setDepth(texture); texture = null; depthProvenance.hidden = true; status.textContent = '수동 depth map 적용됨 (0=뒤, 1=앞)'; } catch { if (!disposed && request === depthRequest) status.textContent = 'RGB와 종횡비가 다른 depth map입니다.'; } finally { texture?.dispose(); URL.revokeObjectURL(url); if (request === depthRequest) { depthFileInput.value = ''; manualDepthBusy = false; syncAIDepthButton(); } } }, { signal: listenerAbort.signal }); -resetButton.onclick = () => { cameraController.reset(); gyro.reset(); }; -gyroButton.onclick = async () => { gyroButton.textContent = `Gyroscope: ${(await gyro.toggle()) ? 'ON' : 'OFF'}`; }; -const observer = new ResizeObserver(resize); observer.observe(wrap); resize(); setMode('final'); setGlossControlsVisibility(); syncAIDepthButton(); -let last = performance.now(); let raf = 0; -function currentRegionSignature(): string { - const view = uniforms.uContentViewProjection.value.elements.map((value) => value.toFixed(4)).join(','); - const object = petDepth.matrixWorld.elements.map((value) => value.toFixed(4)).join(','); - const depth = depthUniforms.uDepthMap.value; - return [mode, active.uuid, depth.uuid, view, object, uniforms.uGridSize.value, uniforms.uStrength.value, uniforms.uCurvature.value, uniforms.uMosaicStyle.value, uniforms.uPaneSize.value.x, uniforms.uPaneSize.value.y, depthUniforms.uDepthScale.value, depthUniforms.uDepthBias.value, renderTarget.width, renderTarget.height, regionAtlasTarget.width, regionAtlasTarget.height].join('|'); -} -function currentSplitHistorySignature(): string { - const object = petDepth.matrixWorld.elements.map((value) => value.toFixed(4)).join(','); - const depth = depthUniforms.uDepthMap.value; - return [mode, effectInput.value, mosaicStyleInput.value, active.uuid, depth.uuid, uniforms.uRegionAvailable.value, uniforms.uGridSize.value, uniforms.uMosaicStyle.value, uniforms.uStrength.value, uniforms.uRegionStrength.value, uniforms.uCurvature.value, uniforms.uGlassZ.value, uniforms.uSourceZ.value, uniforms.uPaneSize.value.x, uniforms.uPaneSize.value.y, object, depthUniforms.uDepthScale.value, depthUniforms.uDepthBias.value, renderTarget.width, renderTarget.height, regionAtlasTarget.width, regionAtlasTarget.height, regionPaletteTarget.width, regionPaletteTarget.height].join('|'); -} -function clearSplitHistory(): void { - const previousTarget = renderer.getRenderTarget(); - const clearColor = renderer.getClearColor(new THREE.Color()); - const clearAlpha = renderer.getClearAlpha(); - renderer.setClearColor(0x000000, 0); - for (const target of splitHistoryTargets) { - renderer.setRenderTarget(target); - renderer.clear(true, false, false); - } - renderer.setRenderTarget(previousTarget); - renderer.setClearColor(clearColor, clearAlpha); - splitHistoryRead = 0; - splitHistoryInitialized = false; - regionHistoryUniform.value = splitHistoryTargets[0].texture; -} -function updateSplitHistory(dt: number): void { - const signature = currentSplitHistorySignature(); - if (signature !== splitHistorySignature) { - clearSplitHistory(); - splitHistorySignature = signature; - } - const enabled = (mode === 'final' || mode === 'glass') && effectInput.value === 'mosaic' && mosaicStyleInput.value === '0' && uniforms.uRegionAvailable.value > 0.5 && uniforms.uRegionStrength.value > 0.001 && uniforms.uStrength.value > 0.001; - if (!enabled) return; - - const writeIndex = 1 - splitHistoryRead; - historyUniforms.uPreviousHistory.value = splitHistoryTargets[splitHistoryRead].texture; - historyUniforms.uHistoryBlend.value = splitHistoryInitialized ? 1 - Math.exp(-dt / 0.07) : 1; - renderer.setRenderTarget(splitHistoryTargets[writeIndex]); - renderer.render(historyScene, postCamera); - renderer.setRenderTarget(null); - splitHistoryRead = writeIndex; - splitHistoryInitialized = true; - regionHistoryUniform.value = splitHistoryTargets[splitHistoryRead].texture; -} -function updateRegionPalette(): void { - const enabled = effectInput.value === 'mosaic' && mosaicStyleInput.value === '0' && uniforms.uRegionAvailable.value > 0.5 && uniforms.uRegionStrength.value > 0.001 && uniforms.uStrength.value > 0.001; - if (!enabled) return; - const signature = currentRegionSignature(); - if (!activeIsVideo && signature === regionSignature) return; - renderer.setRenderTarget(regionAtlasTarget); - renderer.render(atlasScene, postCamera); - renderer.setRenderTarget(regionPaletteTarget); - renderer.render(paletteScene, postCamera); - renderer.setRenderTarget(null); - regionSignature = signature; -} -function frame(now: number): void { - const dt = Math.min((now - last) / 1000, 0.1); last = now; - uniforms.uViewOffset.value.copy(cameraController.update(dt, sensitivity)); camera.updateMatrixWorld(true); petDepth.updateMatrixWorld(true); - uniforms.uPetWorldToLocal.value.copy(petDepth.matrixWorld).invert(); - uniforms.uContentViewProjection.value.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse); - uniforms.uContentInverseViewProjection.value.copy(uniforms.uContentViewProjection.value).invert(); - uniforms.uContentCameraPosition.value.copy(camera.position); uniforms.uTime.value = now / 1000; - const diagnostic = depthDebug.update(camera, petDepth, depthUniforms.uDepthScale.value, depthUniforms.uDepthBias.value, wrap.clientWidth, uniforms.uSourceZ.value, maxDepthValue); - debugOutput.textContent = diagnostic; debugOutput.hidden = !diagnostic; - if (mode === 'final' || mode === 'glass') { - renderer.setRenderTarget(renderTarget); renderer.render(scene, camera); uniforms.uSceneTexture.value = renderTarget.texture; - updateRegionPalette(); - updateSplitHistory(dt); - renderer.setRenderTarget(null); renderer.render(glassScene, postCamera); - const previousAutoClear = renderer.autoClear; renderer.autoClear = false; renderer.clearDepth(); renderer.render(frameScene, camera); renderer.autoClear = previousAutoClear; - } else { updateSplitHistory(dt); renderer.setRenderTarget(null); renderer.render(scene, camera); } - raf = requestAnimationFrame(frame); -} -raf = requestAnimationFrame(frame); -function teardown(): void { disposed = true; mediaRequest += 1; depthRequest += 1; aiDepthProvider.cancel(); aiDepthButton.disabled = true; clearPendingPair(); listenerAbort.abort(); cancelAnimationFrame(raf); observer.disconnect(); imageInput.onchange = null; videoInput.onchange = null; effectInput.onchange = null; sensitivityInput.oninput = null; resetButton.onclick = null; gyroButton.onclick = null; retry.onclick = null; pointer.dispose(); gyro.dispose(); loader.dispose(); renderTarget.dispose(); regionAtlasTarget.dispose(); regionPaletteTarget.dispose(); splitHistoryTargets.forEach((target) => target.dispose()); historyMesh.geometry.dispose(); historyMaterial.dispose(); atlasMesh.geometry.dispose(); atlasMaterial.dispose(); paletteMesh.geometry.dispose(); paletteMaterial.dispose(); windowReveal.dispose(); windowRevealMaterial.dispose(); frameMaterials.forEach((material) => material.dispose()); if (active !== emptyTex) active.dispose(); if (depthUniforms.uDepthMap.value !== depthMap) depthUniforms.uDepthMap.value.dispose(); depthMap.dispose(); petDepth.geometry.dispose(); petDepthMaterial.dispose(); geometry.dispose(); petMat.dispose(); glass.geometry.dispose(); glassMat.dispose(); frameGeometry.dispose(); emptyTex.dispose(); renderer.domElement.remove(); renderer.dispose(); hintElement.style.opacity = '0'; retry.remove(); debugOutput.remove(); } -const hot = import.meta as ImportMeta & { hot?: { dispose(fn: () => void): void } }; hot.hot?.dispose(teardown); diff --git a/docs/qa-gobang-review-2026-10-06/before-rollback/mosaic.frag b/docs/qa-gobang-review-2026-10-06/before-rollback/mosaic.frag deleted file mode 100644 index 2f02f2d..0000000 --- a/docs/qa-gobang-review-2026-10-06/before-rollback/mosaic.frag +++ /dev/null @@ -1,316 +0,0 @@ -uniform sampler2D uSceneTexture,uSceneDepth; -uniform sampler2D uProtectionDepthMap; -uniform mat4 uContentViewProjection,uContentInverseViewProjection; -uniform mat4 uPetWorldToLocal; -uniform vec3 uContentCameraPosition,uLightPosition,uBackgroundColor; -uniform float uGlassZ,uSourceZ,uGridSize,uStrength,uMosaicStyle,uCurvature,uGlossStrength; -uniform vec2 uViewOffset,uPetSize,uPaneSize; -uniform vec2 uDepthEvidenceRange,uDepthCorrection; -uniform float uEnvironmentStrength; -uniform float uTransmissionDetail; -uniform float uCellLensScale; -uniform vec4 uPaneRect; -uniform sampler2D uRegionPalette; -uniform sampler2D uRegionAtlas,uRegionHistory; -uniform vec2 uRegionAtlasSize,uRegionGridSize,uRegionPaletteSize; -uniform float uRegionStrength,uRegionAvailable; -varying vec2 vUv; -vec2 projectUv(vec3 p){vec4 c=uContentViewProjection*vec4(p,1.);float w=abs(c.w)<.0001?(c.w<0.?-.0001:.0001):c.w;return c.xy/w*.5+.5;} -vec4 sampleScene(vec2 uv){return texture2D(uSceneTexture,clamp(uv,0.,1.));} -vec4 samplePane(vec2 pane){return sampleScene(projectUv(vec3((pane-.5)*uPaneSize,uGlassZ)));} -float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);} -vec2 hash2(vec2 p){return vec2(hash(p),hash(p+vec2(19.19,73.73)));} -vec2 cellBlurStep(vec2 cell,vec2 cellSize,float style){ - if(style<=.5)return cellSize*mix(.006,.018,hash(cell+vec2(5.))); - return cellSize*mix(.006,.012,hash(cell+vec2(5.))); -} -vec4 sampleCell(vec2 pane,vec2 sourceUv,float strength,vec2 cell,vec2 cellSize,float style){ - vec2 center=mix(pane,sourceUv,strength); - vec2 blurOffset=strength*cellBlurStep(cell,cellSize,style); - vec4 color; - if(style<=.5){ - color=samplePane(center)*.6; - color+=samplePane(center+vec2(blurOffset.x,0.))*.1; - color+=samplePane(center-vec2(blurOffset.x,0.))*.1; - color+=samplePane(center+vec2(0.,blurOffset.y))*.1; - color+=samplePane(center-vec2(0.,blurOffset.y))*.1; - }else{ - color=samplePane(center)*.4; - color+=samplePane(center+vec2(blurOffset.x,0.))*.15; - color+=samplePane(center-vec2(blurOffset.x,0.))*.15; - color+=samplePane(center+vec2(0.,blurOffset.y))*.15; - color+=samplePane(center-vec2(0.,blurOffset.y))*.15; - } - return color; -} -float safeZ(float z){return abs(z)<.0001?(z<0.?-.0001:.0001):z;} -vec3 bend(vec3 i,vec3 n){vec3 r=refract(i,n,.75);return length(r)<.0001?i:r;} -float softLimit(float value,float limit){return value*limit/(limit+abs(value));} -float surfaceCurvature(){float curvature=clamp(uCurvature,-1.,1.),excess=max(curvature-.65,0.);return curvature-(.25/.35)*excess*excess;} -float signedCurvatureScale(){return clamp(surfaceCurvature()/.65,-1.25,1.25);} -float regionDistance(vec3 a,vec3 b){vec3 d=a-b;float y=dot(d,vec3(.299,.587,.114));return dot(d,d)+.35*y*y;} -float regionLuminance(vec3 c){return dot(c,vec3(.299,.587,.114));} -vec3 regionColor(vec2 cell,float index){vec2 uv=(vec2(cell.x*5.+index,cell.y)+.5)/uRegionPaletteSize;return texture2D(uRegionPalette,uv).rgb;} -float nearestRegion(vec3 color,vec2 cell){float best=0.,distance=regionDistance(color,regionColor(cell,0.));for(int i=1;i<4;i++){float candidate=regionDistance(color,regionColor(cell,float(i)));if(candidate1.||sceneUv.y<0.||sceneUv.y>1.)return false; - float depth=texture2D(uSceneDepth,sceneUv).x; - if(depth>=.999999)return false; - vec4 clip=vec4(sceneUv*2.-1.,depth*2.-1.,1.); - vec4 world=uContentInverseViewProjection*clip; - if(abs(world.w)<.0001)return false; - worldPoint=world.xyz/world.w; - return true; -} -float regionSurfaceValid(vec2 sceneUv,vec3 glassHit){ - vec3 worldPoint; - if(!reconstructScenePoint(sceneUv,worldPoint))return 0.; - float axialGap=glassHit.z-worldPoint.z; - if(axialGap<=.0001)return 0.; - return 1.; -} -float regionProtectionWeight(vec2 sceneUv){ - vec3 worldPoint; - if(!reconstructScenePoint(sceneUv,worldPoint))return 0.; - vec3 localPoint=(uPetWorldToLocal*vec4(worldPoint,1.)).xyz; - if(localPoint.x<-.5||localPoint.x>.5||localPoint.y<-.5||localPoint.y>.5)return 0.; - vec2 sourceUv=localPoint.xy+.5; - float sourceDepth=texture2D(uProtectionDepthMap,sourceUv).r; - if(uDepthEvidenceRange.y-uDepthEvidenceRange.x<.0001)return 0.; - return smoothstep(uDepthEvidenceRange.x,uDepthEvidenceRange.y,sourceDepth); -} -// Screen-depth refinement of an artistic ray. Occluded surfaces are unavailable; -// retain the original sample if the visible-depth solve cannot converge. -vec3 refineSceneHit(vec3 glassHit,vec3 ray,vec3 artisticHit,float cellWorld){ - vec3 planeHit=glassHit+ray*((uSourceZ-glassHit.z)/safeZ(ray.z)); - vec3 origin=glassHit+vec3(artisticHit.xy-planeHit.xy,0.); - vec3 hit=artisticHit,surface; - for(int iteration=0;iteration<3;iteration++){ - if(!reconstructScenePoint(projectUv(hit),surface))return artisticHit; - vec3 localPoint=(uPetWorldToLocal*vec4(surface,1.)).xyz; - if(any(greaterThan(abs(localPoint.xy),vec2(.5)))||surface.z>=uGlassZ-.0001)return artisticHit; - hit=origin+ray*((surface.z-origin.z)/safeZ(ray.z)); - } - if(!reconstructScenePoint(projectUv(hit),surface))return artisticHit; - if(surface.z>=uGlassZ-.0001)return artisticHit; - float confidence=1.-smoothstep(cellWorld*.05,cellWorld*.25,abs(hit.z-surface.z)); - // Compare at the same reference Z, so only the projected sampling position changes. - vec3 viewRay=hit-uContentCameraPosition; - vec3 projected=uContentCameraPosition+viewRay*((uSourceZ-uContentCameraPosition.z)/safeZ(viewRay.z)); - vec2 delta=projected.xy-artisticHit.xy; - float limit=cellWorld*uDepthCorrection.y; - delta*=min(1.,limit/max(length(delta),.00001)); - return artisticHit+vec3(delta*uDepthCorrection.x*confidence,0.); -} -#ifdef REGION_ATLAS -float regionAtlasEvidence(vec2 sceneUv,vec3 color,vec3 glassHit){ - if(regionSurfaceValid(sceneUv,glassHit)<=0.)return 0.; - return regionProtectionWeight(sceneUv)*(1.-smoothstep(.10,.20,regionLuminance(color))); -} -vec4 regionAtlasProbe(vec3 sceneHit,vec2 worldOffset,vec3 glassHit){ - vec2 probeSceneUv=projectUv(sceneHit+vec3(worldOffset,0.)); - vec4 probe=sampleScene(probeSceneUv); - return vec4(probe.rgb,regionAtlasEvidence(probeSceneUv,probe.rgb,glassHit)); -} -vec4 regionAtlasScore(vec3 centerColor,float centerEvidence,vec3 probeColor,float probeEvidence){ - float evidenceGain=probeEvidence-centerEvidence,darkGain=regionLuminance(centerColor)-regionLuminance(probeColor),blend=0.; - if(probeEvidence>.05&&evidenceGain>.02&&darkGain>.015)blend=min(.4,evidenceGain*2.)*min(1.,max(0.,darkGain*4.)); - return vec4(blend,probeEvidence,0.,0.); -} -vec3 regionAtlasRepresentative(vec3 centerColor,float centerEvidence,vec3 sceneHit,vec3 glassHit,out float evidence){ - vec3 bestColor=centerColor;float bestEvidence=centerEvidence,bestBlend=0.; - vec2 probeStep=uPaneSize/(uRegionGridSize*8.)*.25; - vec4 probe,score; - probe=regionAtlasProbe(sceneHit,vec2(probeStep.x,0.),glassHit);score=regionAtlasScore(centerColor,centerEvidence,probe.rgb,probe.a);if(score.x>bestBlend){bestColor=mix(centerColor,probe.rgb,score.x);bestEvidence=max(centerEvidence,probe.a);bestBlend=score.x;} - probe=regionAtlasProbe(sceneHit,vec2(-probeStep.x,0.),glassHit);score=regionAtlasScore(centerColor,centerEvidence,probe.rgb,probe.a);if(score.x>bestBlend){bestColor=mix(centerColor,probe.rgb,score.x);bestEvidence=max(centerEvidence,probe.a);bestBlend=score.x;} - probe=regionAtlasProbe(sceneHit,vec2(0.,probeStep.y),glassHit);score=regionAtlasScore(centerColor,centerEvidence,probe.rgb,probe.a);if(score.x>bestBlend){bestColor=mix(centerColor,probe.rgb,score.x);bestEvidence=max(centerEvidence,probe.a);bestBlend=score.x;} - probe=regionAtlasProbe(sceneHit,vec2(0.,-probeStep.y),glassHit);score=regionAtlasScore(centerColor,centerEvidence,probe.rgb,probe.a);if(score.x>bestBlend){bestColor=mix(centerColor,probe.rgb,score.x);bestEvidence=max(centerEvidence,probe.a);bestBlend=score.x;} - evidence=bestEvidence; - return bestColor; -} -#endif -void evaluateCell(vec2 cell,vec2 local,vec2 grid,vec2 cellSize,vec2 cellDimensions,float cellWorld,float opticalTravel,float style,out vec2 affineUv,out mat2 transform,out vec2 curvedSlope,out vec2 facetSlope){ - vec2 random=hash2(cell),widths; - if(style>.5){ - widths=mix(vec2(.82),vec2(1.12),hash2(cell+vec2(11.4,9.8))); - float angle=(random.x-.5)*.08,c=cos(angle),s=sin(angle); - transform=mat2(widths.x*c,-widths.y*s,widths.x*s,widths.y*c); - float centerJitter=.16; - vec2 sourceCenter=(cell+.5)/grid+(random-.5)*centerJitter*cellSize; - affineUv=sourceCenter+transform*(local*cellSize); - }else{ - // Default style keeps a single continuous image footprint across cells. - transform=mat2(1.); - affineUv=(cell+.5)/grid+local*cellSize; - } - - // Positive height bulges toward the observer (+Z); negative height is concave. - float curvature=clamp(uCurvature,-1.,1.),surfaceCurvatureValue=surfaceCurvature(); - vec2 q=clamp(2.*local,-1.,1.),q2=q*q,q3=q2*q,b=1.-q2*q2; - if(style>.5){ - float amplitude=mix(.92,1.08,hash(cell+vec2(41.7,17.3))),height=.009*cellWorld*surfaceCurvatureValue*amplitude; - vec2 skew=(hash2(cell+vec2(23.8,61.2))-.5)*.28;float asym=1.+dot(skew,q); - vec2 dhdq=height*vec2(-4.*q3.x*b.y*asym+b.x*b.y*skew.x,-4.*q3.y*b.x*asym+b.x*b.y*skew.y); - vec2 grad=-2.*dhdq/cellDimensions; - curvedSlope=grad+(random-.5)*.012;facetSlope=(random-.5)*.012; - }else{ - curvedSlope=.30*uCellLensScale*cellDimensions/max(abs(opticalTravel),.6)*signedCurvatureScale()*sin(6.2831853*local); - facetSlope=vec2(0.); - } -} -void main(){ - vec2 screenUv=vUv; -#ifdef REGION_ATLAS - vec2 atlasPixel=floor(vUv*uRegionAtlasSize),atlasCell=floor(atlasPixel/8.),atlasLocal=(mod(atlasPixel,8.)+.5)/8.; - vec2 atlasPaneUv=(atlasCell+atlasLocal)/uRegionGridSize; - screenUv=projectUv(vec3((atlasPaneUv-.5)*uPaneSize,uGlassZ)); -#endif - if(uStrength<=.001){ -#ifdef REGION_ATLAS - gl_FragColor=vec4(sampleScene(screenUv).rgb,0.); -#else - gl_FragColor=sampleScene(screenUv); - #include -#endif - return;} - vec4 f=uContentInverseViewProjection*vec4(screenUv*2.-1.,1.,1.);float fw=abs(f.w)<.0001?(f.w<0.?-.0001:.0001):f.w;vec3 farWorld=f.xyz/fw;vec3 i=normalize(farWorld-uContentCameraPosition);float gt=(uGlassZ-uContentCameraPosition.z)/safeZ(i.z);vec3 gh=uContentCameraPosition+i*gt; - vec2 paneUv=gh.xy/uPaneSize+.5;vec2 grid=vec2(uGridSize,max(1.,uGridSize*uPaneSize.y/uPaneSize.x));vec2 gridUv=paneUv*grid,cell=floor(gridUv),local=fract(gridUv)-.5,cellSize=1./grid;float style=clamp(uMosaicStyle,0.,1.),cellWorld=min(uPaneSize.x/grid.x,uPaneSize.y/grid.y); -#ifdef REGION_ATLAS - paneUv=atlasPaneUv;grid= uRegionGridSize;gridUv=paneUv*grid;cell=floor(gridUv);local=fract(gridUv)-.5;cellSize=1./grid;cellWorld=min(uPaneSize.x/grid.x,uPaneSize.y/grid.y); -#endif - if(paneUv.x<0.||paneUv.x>1.||paneUv.y<0.||paneUv.y>1.){ -#ifdef REGION_ATLAS - gl_FragColor=vec4(uBackgroundColor,0.); -#else - gl_FragColor=vec4(uBackgroundColor,1.); - #include -#endif - return;} - vec2 cellDimensions=uPaneSize/grid; - float opticalTravel=-max(abs(uSourceZ-gh.z),.6); - vec2 affineUv,curvedSlope,facetSlope;mat2 transform; - evaluateCell(cell,local,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,affineUv,transform,curvedSlope,facetSlope); - if(style<=.5){ - vec2 smoothFacet=.003*vec2(sin(6.2831853*paneUv.x),sin(6.2831853*paneUv.y)); - curvedSlope+=smoothFacet;facetSlope=smoothFacet; - }else{ - vec2 edge=.5-abs(local),neighborSign=mix(vec2(-1.),vec2(1.),step(vec2(0.),local)); - float normalBlend=.16; - vec2 weights=1.-smoothstep(vec2(-normalBlend),vec2(normalBlend),edge); - float xSplitWeight=weights.x*(1.-weights.y),ySplitWeight=(1.-weights.x)*weights.y; - float diagonalSplitWeight=weights.x*weights.y,centerSplitWeight=(1.-weights.x)*(1.-weights.y); - if(weights.x>0.||weights.y>0.){ - vec2 neighborAffine,neighborCurved,neighborFacet;mat2 neighborTransform; - vec2 xWeight=vec2(xSplitWeight,0.); - vec2 yWeight=vec2(0.,ySplitWeight); - affineUv*=centerSplitWeight;transform*=centerSplitWeight;curvedSlope*=centerSplitWeight;facetSlope*=centerSplitWeight; - if(xWeight.x>0.){ - vec2 offset=vec2(neighborSign.x,0.); - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*xWeight.x;transform+=neighborTransform*xWeight.x;curvedSlope+=neighborCurved*xWeight.x;facetSlope+=neighborFacet*xWeight.x; - } - if(yWeight.y>0.){ - vec2 offset=vec2(0.,neighborSign.y); - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*yWeight.y;transform+=neighborTransform*yWeight.y;curvedSlope+=neighborCurved*yWeight.y;facetSlope+=neighborFacet*yWeight.y; - } - if(diagonalSplitWeight>0.){ - vec2 offset=neighborSign; - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*diagonalSplitWeight;transform+=neighborTransform*diagonalSplitWeight;curvedSlope+=neighborCurved*diagonalSplitWeight;facetSlope+=neighborFacet*diagonalSplitWeight; - } - } - } - vec3 nCurved=normalize(vec3(curvedSlope,1.)),nFacet=normalize(vec3(facetSlope,1.)); - vec3 straightHit=gh+i*((uSourceZ-gh.z)/safeZ(i.z)); - vec3 curvedRay=bend(i,nCurved),curvedHit=gh+curvedRay*((uSourceZ-gh.z)/safeZ(curvedRay.z)); - // Keep the artistic Mosaic optical path independent of physical glass-to-photo contact distance. - vec2 rawDelta=(curvedRay.xy/safeZ(curvedRay.z)-i.xy/safeZ(i.z))*opticalTravel; - vec2 worldDelta=vec2(softLimit(rawDelta.x,cellWorld*.55),softLimit(rawDelta.y,cellWorld*.55)); - if(style>.5){ - vec3 facetRay=bend(i,nFacet);vec3 facetHit=gh+facetRay*((uSourceZ-gh.z)/safeZ(facetRay.z)); - vec2 base=facetHit.xy-straightHit.xy,curve=curvedHit.xy-facetHit.xy; - worldDelta=vec2(softLimit(base.x,cellWorld*.08),softLimit(base.y,cellWorld*.08)); - vec2 d=curve/cellWorld; - worldDelta+=vec2(.3*d.x/(.3+abs(d.x)),.3*d.y/(.3+abs(d.y)))*cellWorld; - }else{ - vec3 referenceI=normalize(gh-vec3(0.,0.,uContentCameraPosition.z)),referenceRay=bend(referenceI,nCurved); - vec2 incidenceDelta=curvedRay.xy/max(-curvedRay.z,.0001)-referenceRay.xy/max(-referenceRay.z,.0001); - vec2 boundedIncidence=incidenceDelta/sqrt(incidenceDelta*incidenceDelta+vec2(.025*.025)); - vec2 cellEnvelope=.5+.5*cos(6.2831853*local); - worldDelta+=boundedIncidence*cellEnvelope*cellDimensions*signedCurvatureScale()*.18; - } - vec2 sampleUv=affineUv+transform*(worldDelta/uPaneSize); - float edgeDistance=min(min(paneUv.x,paneUv.y),min(1.-paneUv.x,1.-paneUv.y));float edgeTaper=style<=.5?1.25:.75;float edgeWeight=smoothstep(0.,max(cellSize.x,cellSize.y)*edgeTaper,edgeDistance);float strength=clamp(uStrength,0.,1.)*edgeWeight; - vec4 color;vec3 sceneHit=straightHit+vec3(worldDelta*strength,0.);vec2 finalSceneUv=projectUv(sceneHit); - if(style<=.5){ - sceneHit=refineSceneHit(gh,normalize(mix(i,curvedRay,strength)),sceneHit,cellWorld); - finalSceneUv=projectUv(sceneHit); - } -#ifdef REGION_ATLAS - vec3 atlasCenterColor=sampleScene(finalSceneUv).rgb; - float atlasEvidence=regionProtectionWeight(finalSceneUv)*(1.-smoothstep(.10,.20,regionLuminance(atlasCenterColor))); -#endif -#ifdef REGION_ATLAS - if(style<=.5){ - float representativeEvidence=atlasEvidence; - color=vec4(regionAtlasRepresentative(atlasCenterColor,atlasEvidence,sceneHit,gh,representativeEvidence),representativeEvidence); - atlasEvidence=representativeEvidence; - }else{ - color=sampleCell(paneUv,sampleUv,strength,cell,cellSize,style); - } -#else - if(style<=.5){ - color=sampleScene(finalSceneUv); - }else{ - color=sampleCell(paneUv,sampleUv,strength,cell,cellSize,style); - } -#endif -#ifndef REGION_ATLAS - if(uRegionAvailable>.5&&uRegionStrength>.001&&uMosaicStyle<.5){ - vec3 p0=regionColor(cell,0.),p1=regionColor(cell,1.),p2=regionColor(cell,2.),p3=regionColor(cell,3.); - float ownLabel=nearestRegion(color.rgb,p0,p1,p2,p3);vec4 votes=vec4(0.);float totalWeight=0.,ownWeight=0.; - vec2 texelCoord=fract(gridUv)*8.-.5,anchor=floor(texelCoord+.5); - for(int y=-1;y<=1;y++)for(int x=-1;x<=1;x++){ - vec2 offset=vec2(float(x),float(y)),delta=anchor+offset-texelCoord; - float weight=pow(max(0.,1.-length(delta)/1.5),2.); - if(weight>0.){ - vec3 atlasColor=regionAtlasColor(cell,anchor+offset);float label=nearestRegion(atlasColor,p0,p1,p2,p3); - votes+=vec4(step(abs(label-vec4(0.,1.,2.,3.)),vec4(.1)))*weight;totalWeight+=weight; - ownWeight+=step(abs(label-ownLabel),.1)*weight; - } - } - float winningLabel=ownLabel,winningWeight=ownWeight; - if(votes.x>winningWeight){winningLabel=0.;winningWeight=votes.x;}if(votes.y>winningWeight){winningLabel=1.;winningWeight=votes.y;}if(votes.z>winningWeight){winningLabel=2.;winningWeight=votes.z;}if(votes.w>winningWeight){winningLabel=3.;winningWeight=votes.w;} - bool simplify=totalWeight>0.&&winningWeight/totalWeight>.55&&ownWeight/totalWeight<.40; - float radialLabel=simplify?winningLabel:ownLabel;vec3 radialColor=selectRegion(p0,p1,p2,p3,radialLabel); - vec2 historyTexel=clamp(floor(fract(gridUv)*8.),vec2(0.),vec2(7.)); - vec2 historyUv=(cell*8.+historyTexel+.5)/uRegionAtlasSize; - vec4 splitHistory=texture2D(uRegionHistory,historyUv); - vec3 splitColor=splitHistory.a>.00001?splitHistory.rgb/splitHistory.a:radialColor; - vec3 candidateColor=mix(radialColor,splitColor,splitHistory.a); - // The palette describes broad color planes, not an opaque replacement image. - // Preserve the same continuously refracted sample underneath every plane. - candidateColor=mix(candidateColor,color.rgb,uTransmissionDetail); - color.rgb=mix(color.rgb,candidateColor,clamp(uRegionStrength*clamp(uStrength,0.,1.)*regionSurfaceValid(finalSceneUv,gh),0.,1.)); - } -#endif -#ifndef REGION_ATLAS - color.a=1.; - vec3 v=normalize(uContentCameraPosition-gh),reflected=reflect(-v,nCurved); float lightT=(uLightPosition.z-gh.z)/safeZ(reflected.z); vec2 lightHit=gh.xy+reflected.xy*lightT; vec2 halfSize=vec2(.32,.42)*min(uPaneSize.x,uPaneSize.y); vec2 windowCoord=abs(lightHit-uLightPosition.xy)/halfSize; vec2 windowMask=1.-smoothstep(vec2(.45),vec2(1.15),windowCoord); float surfaceReflectionWeight=mix(.35,1.,edgeWeight); float glossStrength=clamp(uGlossStrength,0.,1.); float spec=windowMask.x*windowMask.y*step(.0001,reflected.z)*step(0.,lightT); float specGloss=spec*glossStrength*.12*surfaceReflectionWeight*clamp(uStrength,0.,1.); vec2 broadWindowMask=1.-smoothstep(vec2(.15),vec2(1.75),windowCoord); float broadFacing=pow(max(dot(nCurved,v),0.),2.); float broadReflection=broadWindowMask.x*broadWindowMask.y*broadFacing*glossStrength*.035*surfaceReflectionWeight*clamp(uStrength,0.,1.); color.rgb=mix(color.rgb,vec3(1.),specGloss+broadReflection); gl_FragColor=color; - // Common, static room environment. Reflected direction varies with the same - // curved normal as transmission; no image relighting or timed sparkle. - float fresnel=.04+.96*pow(1.-clamp(dot(nCurved,v),0.,1.),5.); - float environmentWeight=uEnvironmentStrength*glossStrength*(.35+.65*fresnel)*surfaceReflectionWeight*clamp(uStrength,0.,1.); - vec3 environmentColor=mix(vec3(.10,.13,.18),vec3(.65,.72,.80),smoothstep(-.35,.65,reflected.y)); - if(style<=.5)color.rgb=mix(color.rgb,environmentColor,environmentWeight); - gl_FragColor=color; - #include -#else - color.a=atlasEvidence; - gl_FragColor=color; -#endif -} diff --git a/docs/qa-gobang-review-2026-10-06/before-rollback/test-glass-transmission.mjs b/docs/qa-gobang-review-2026-10-06/before-rollback/test-glass-transmission.mjs deleted file mode 100644 index 6eefc9d..0000000 --- a/docs/qa-gobang-review-2026-10-06/before-rollback/test-glass-transmission.mjs +++ /dev/null @@ -1,9 +0,0 @@ -import assert from 'node:assert/strict'; -import { readFile } from 'node:fs/promises'; -import * as settings from '../src/constants/glass.ts'; -const shader = await readFile(new URL('../src/shaders/mosaic.frag', import.meta.url), 'utf8'); -assert.ok(settings.GLASS_TRANSMISSION_DETAIL > 0 && settings.GLASS_TRANSMISSION_DETAIL < 0.5, - 'maximum simplification must retain optical detail while keeping color planes dominant'); -assert.match(shader, /candidateColor=mix\(candidateColor,color.rgb,uTransmissionDetail\)/, - 'retain the refracted scene, not raw photo UV or a facial-feature fallback'); -console.log('Glass material keeps continuous refracted detail under maximum color-plane simplification.'); diff --git a/docs/qa-gobang-review-2026-10-06/before-rollback/test-mosaic-continuity.mjs b/docs/qa-gobang-review-2026-10-06/before-rollback/test-mosaic-continuity.mjs deleted file mode 100644 index fa44a5b..0000000 --- a/docs/qa-gobang-review-2026-10-06/before-rollback/test-mosaic-continuity.mjs +++ /dev/null @@ -1,202 +0,0 @@ -import assert from 'node:assert/strict'; -import { CELL_LENS_SCALE } from '../src/constants/glass.ts'; -import { readFile } from 'node:fs/promises'; - -const shader = await readFile(new URL('../src/shaders/mosaic.frag', import.meta.url), 'utf8'); -assert.match(shader, /curvedSlope=\.30\*uCellLensScale\*cellDimensions\/max\(abs\(opticalTravel\),\.6\)\*signedCurvatureScale\(\)\*sin\(6\.2831853\*local\)/); -assert.match(shader, /smoothFacet=\.003\*vec2\(sin\(6\.2831853\*paneUv\.x\),sin\(6\.2831853\*paneUv\.y\)\)/); -assert.match(shader, /float opticalTravel=-max\(abs\(uSourceZ-gh\.z\),\.6\)/); -assert.match(shader, /if\(style<=\.5\)\{\s*vec2 smoothFacet/); -assert.match(shader, /vec3 referenceI=normalize\(gh-vec3\(0\.,0\.,uContentCameraPosition\.z\)\),referenceRay=bend\(referenceI,nCurved\)/); -assert.match(shader, /incidenceDelta\/sqrt\(incidenceDelta\*incidenceDelta\+vec2\(\.025\*\.025\)\)/); -assert.match(shader, /cellEnvelope\*cellDimensions\*signedCurvatureScale\(\)\*\.18/); -assert.match(shader, /edgeTaper=style<=\.5\?1\.25:\.75/); -assert.match(shader, /float normalBlend=\.16/); -assert.match(shader, /vec3 sceneHit=straightHit\+vec3\(worldDelta\*strength,0\.\);vec2 finalSceneUv=projectUv\(sceneHit\)/); -assert.match(shader, /color=sampleScene\(finalSceneUv\)/); - -const TAU = Math.PI * 2; -const cameraZ = 3; -const glassZ = 0.6; -const strengthSetting = 0.9; -const fovScale = Math.tan(20 * Math.PI / 180); -const add = (a, b) => a.map((v, i) => v + b[i]); -const sub = (a, b) => a.map((v, i) => v - b[i]); -const mul = (a, s) => a.map(v => v * s); -const dot = (a, b) => a.reduce((sum, v, i) => sum + v * b[i], 0); -const norm = a => mul(a, 1 / Math.hypot(...a)); -const safeZ = z => Math.abs(z) < 1e-4 ? (z < 0 ? -1e-4 : 1e-4) : z; -const smoothstep = (a, b, x) => { - const t = Math.max(0, Math.min(1, (x - a) / (b - a))); - return t * t * (3 - 2 * t); -}; -const softLimit = (value, limit) => value * limit / (limit + Math.abs(value)); -const surfaceCurvature = curvature => { - const clamped = Math.max(-1, Math.min(1, curvature)); - const excess = Math.max(clamped - 0.65, 0); - return clamped - (0.25 / 0.35) * excess * excess; -}; -const curvatureScale = curvature => Math.max(-1.25, Math.min(1.25, surfaceCurvature(curvature) / 0.65)); -function refract(i, n) { - const eta = 0.75; - const d = dot(n, i); - const k = 1 - eta * eta * (1 - d * d); - if (k < 0) return i; - return sub(mul(i, eta), mul(n, eta * d + Math.sqrt(k))); -} - -function mapToSource(uv, { gridSize, curvature, pane, cameraXY, sourceZ }) { - const [width, height] = pane; - const grid = [gridSize, Math.max(1, gridSize * height / width)]; - const cellSize = [1 / grid[0], 1 / grid[1]]; - const cellDimensions = [width / grid[0], height / grid[1]]; - const cellWorld = Math.min(...cellDimensions); - const gx = uv[0] * grid[0], gy = uv[1] * grid[1]; - const local = [gx - Math.floor(gx) - 0.5, gy - Math.floor(gy) - 0.5]; - const gh = [(uv[0] - 0.5) * width, (uv[1] - 0.5) * height, glassZ]; - const camera = [cameraXY[0], cameraXY[1], cameraZ]; - const i = norm(sub(gh, camera)); - const opticalTravel = -Math.max(Math.abs(sourceZ - gh[2]), 0.6); - const signedScale = curvatureScale(curvature); - const curvedSlope = [0, 1].map(axis => - 0.30 * CELL_LENS_SCALE * cellDimensions[axis] / Math.max(Math.abs(opticalTravel), 0.6) * signedScale * Math.sin(TAU * local[axis]) - ); - const smoothFacet = [0.003 * Math.sin(TAU * uv[0]), 0.003 * Math.sin(TAU * uv[1])]; - const nCurved = norm([curvedSlope[0] + smoothFacet[0], curvedSlope[1] + smoothFacet[1], 1]); - const curvedRay = refract(i, nCurved); - const rawDelta = [0, 1].map(axis => - (curvedRay[axis] / safeZ(curvedRay[2]) - i[axis] / safeZ(i[2])) * opticalTravel - ); - const worldDelta = rawDelta.map(value => softLimit(value, cellWorld * 0.55)); - const referenceI = norm([gh[0], gh[1], gh[2] - cameraZ]); - const referenceRay = refract(referenceI, nCurved); - const cellEnvelope = local.map(value => 0.5 + 0.5 * Math.cos(TAU * value)); - const incidenceDelta = [0, 1].map(axis => curvedRay[axis] / -curvedRay[2] - referenceRay[axis] / -referenceRay[2]); - const boundedIncidence = incidenceDelta.map(value => value / Math.sqrt(value * value + 0.025 ** 2)); - for (let axis = 0; axis < 2; axis++) { - worldDelta[axis] += boundedIncidence[axis] * cellEnvelope[axis] * cellDimensions[axis] * signedScale * 0.18; - } - const straightT = (sourceZ - gh[2]) / safeZ(i[2]); - const straightHit = add(gh, mul(i, straightT)); - const edgeDistance = Math.min(uv[0], uv[1], 1 - uv[0], 1 - uv[1]); - const edgeWeight = smoothstep(0, Math.max(...cellSize) * 1.25, edgeDistance); - const sceneHit = add(straightHit, [worldDelta[0] * strengthSetting * edgeWeight, worldDelta[1] * strengthSetting * edgeWeight, 0]); - const depth = cameraZ - sceneHit[2]; - return [ - 0.5 + 0.5 * (sceneHit[0] - cameraXY[0]) / (depth * fovScale), - 0.5 + 0.5 * (sceneHit[1] - cameraXY[1]) / (depth * fovScale) - ]; -} - -const distance = (a, b) => Math.hypot(a[0] - b[0], a[1] - b[1]); -const grids = [6, 10, 96]; -const curvatures = [-1, 0, 0.65, 1]; -const panes = [[1.2, 0.8], [1.28, 1.6]]; -const cameras = [[0, 0], [0.3, -0.3], [-0.6, 0.6], [-0.9, 0.9], [0.9, -0.9]]; -const sourcePlanes = [0.16, 0.56]; -const phases = [0.03, 0.25, 0.49, 0.5, 0.75, 0.97]; -const interiorPhases = [-0.4, -0.25, 0, 0.25, 0.4]; -let pointsChecked = 0; -let seamsChecked = 0; - -for (const gridSize of grids) for (const curvature of curvatures) for (const pane of panes) { - for (const cameraXY of cameras) for (const sourceZ of sourcePlanes) { - const config = { gridSize, curvature, pane, cameraXY, sourceZ }; - const points = []; - for (let line = 0; line <= gridSize; line++) { - const seam = line / gridSize; - for (const phase of phases) { - points.push([seam, phase], [phase, seam]); - } - for (let cell = 1; cell < gridSize; cell += Math.max(1, Math.floor(gridSize / 4))) { - for (const local of interiorPhases) { - points.push([(cell + 0.5 + local) / gridSize, (cell + 0.5) / gridSize]); - points.push([(cell + 0.5) / gridSize, (cell + 0.5 + local) / gridSize]); - } - } - } - points.push([0.001, 0.001], [0.999, 0.001], [0.001, 0.999], [0.999, 0.999]); - const h = Math.min(1e-6, 1e-4 / gridSize); - for (const [u0, v0] of points) { - const u = Math.max(h * 2, Math.min(1 - h * 2, u0)); - const v = Math.max(h * 2, Math.min(1 - h * 2, v0)); - const left = mapToSource([u - h, v], config), right = mapToSource([u + h, v], config); - const down = mapToSource([u, v - h], config), up = mapToSource([u, v + h], config); - const dx = [(right[0] - left[0]) / (2 * h), (right[1] - left[1]) / (2 * h)]; - const dy = [(up[0] - down[0]) / (2 * h), (up[1] - down[1]) / (2 * h)]; - const determinant = dx[0] * dy[1] - dy[0] * dx[1]; - assert.ok(dx[0] > 0 && dy[1] > 0 && determinant > 0, - `folded projected UV at grid=${gridSize}, curvature=${curvature}, pane=${pane}, camera=${cameraXY}, sourceZ=${sourceZ}, uv=${u},${v}; jac=[${dx},${dy}]`); - pointsChecked++; - } - - const epsilon = 1e-4 / gridSize; - for (let line = 1; line < gridSize; line++) { - const seam = line / gridSize; - for (const phase of [0.07, 0.31, 0.5, 0.69, 0.93]) { - for (const [axis, other] of [[0, phase], [1, phase]]) { - const a = axis === 0 ? [seam - epsilon, other] : [other, seam - epsilon]; - const b = axis === 0 ? [seam + epsilon, other] : [other, seam + epsilon]; - const aHalf = axis === 0 ? [seam - epsilon / 2, other] : [other, seam - epsilon / 2]; - const bHalf = axis === 0 ? [seam + epsilon / 2, other] : [other, seam + epsilon / 2]; - const fullStep = distance(mapToSource(a, config), mapToSource(b, config)); - const halfStep = distance(mapToSource(aHalf, config), mapToSource(bHalf, config)); - assert.ok(fullStep > 0 && Math.abs(fullStep - 2 * halfStep) < fullStep * 0.03, - `seam does not converge continuously at grid=${gridSize}, curvature=${curvature}, uv=${seam},${other}`); - seamsChecked++; - } - } - } - } -} - -function displacementAt(uv, config) { - const { gridSize, pane, cameraXY, sourceZ } = config; - const [width, height] = pane; - const grid = [gridSize, Math.max(1, gridSize * height / width)]; - const gh = [(uv[0] - 0.5) * width, (uv[1] - 0.5) * height, glassZ]; - const i = norm(sub(gh, [cameraXY[0], cameraXY[1], cameraZ])); - const cell = [Math.floor(uv[0] * grid[0]), Math.floor(uv[1] * grid[1])]; - const local = [uv[0] * grid[0] - cell[0] - 0.5, uv[1] * grid[1] - cell[1] - 0.5]; - const cellDimensions = [width / grid[0], height / grid[1]]; - const travel = -Math.max(Math.abs(sourceZ - glassZ), 0.6); - const scale = curvatureScale(config.curvature); - const slope = local.map((v, axis) => 0.30 * CELL_LENS_SCALE * cellDimensions[axis] / Math.max(Math.abs(travel), 0.6) * scale * Math.sin(TAU * v)); - const smoothFacet = [0.003 * Math.sin(TAU * uv[0]), 0.003 * Math.sin(TAU * uv[1])]; - const n = norm([slope[0] + smoothFacet[0], slope[1] + smoothFacet[1], 1]); - const ray = refract(i, n); - const reference = refract(norm([gh[0], gh[1], gh[2] - cameraZ]), n); - const envelope = local.map(v => 0.5 + 0.5 * Math.cos(TAU * v)); - return [0, 1].map(axis => { - const a = ray[axis] / -ray[2] - reference[axis] / -reference[2]; - return a / Math.sqrt(a * a + 0.025 ** 2) * envelope[axis] * cellDimensions[axis] * scale * 0.18; - }); -} - -for (const curvature of [-1, -0.65, 0.65, 1]) { - const centered = { gridSize: 10, curvature, pane: [1.2, 0.8], cameraXY: [0, 0], sourceZ: 0.16 }; - const cameraView = { ...centered, cameraXY: [0.3, -0.3] }; - const gridY = Math.max(1, centered.gridSize * centered.pane[1] / centered.pane[0]); - const cellCenter = [(4 + 0.5) / centered.gridSize, (Math.floor(gridY / 2) + 0.5) / gridY]; - const xEdges = [4 / centered.gridSize, 5 / centered.gridSize]; - const yIndex = Math.floor(gridY / 2), yEdges = [yIndex / gridY, (yIndex + 1) / gridY]; - const atCellCenter = displacementAt(cellCenter, centered); - assert.ok(Math.hypot(...atCellCenter) < 1e-10, `center view should add no local displacement at curvature=${curvature}`); - const edgePoints = [ - [[xEdges[0], cellCenter[1]], 0], [[xEdges[1], cellCenter[1]], 0], - [[cellCenter[0], yEdges[0]], 1], [[cellCenter[0], yEdges[1]], 1] - ]; - for (const [uv, fixedAxis] of edgePoints) { - assert.ok(Math.abs(displacementAt(uv, cameraView)[fixedAxis]) < 1e-8, `cell edge axis should remain fixed at curvature=${curvature}, uv=${uv}`); - } - const samples = [ - [cellCenter[0] - 0.02, cellCenter[1]], cellCenter, [cellCenter[0] + 0.02, cellCenter[1]], - [cellCenter[0], cellCenter[1] - 0.02], [cellCenter[0], cellCenter[1] + 0.02] - ]; - const offsets = samples.map(uv => displacementAt(uv, cameraView)); - const mean = offsets.reduce((sum, value) => add(sum, value), [0, 0]).map(value => value / offsets.length); - const variance = offsets.reduce((sum, value) => sum + dot(sub(value, mean), sub(value, mean)), 0) / offsets.length; - assert.ok(variance > 1e-8, `camera incidence should create varying within-cell displacement at curvature=${curvature}`); -} - -console.log(`Mosaic projected-UV continuity passed: ${pointsChecked} Jacobians, ${seamsChecked} seam convergence checks, center/edge anchors, and view-dependent within-cell displacement.`); diff --git a/docs/qa-gobang-review-2026-10-06/report.md b/docs/qa-gobang-review-2026-10-06/report.md deleted file mode 100644 index 8e2eab4..0000000 --- a/docs/qa-gobang-review-2026-10-06/report.md +++ /dev/null @@ -1,70 +0,0 @@ -# 고방유리 질감 재검토 및 마지막 작업 복원 - -2026-10-06 - -## 사용자 요청과 이번 적용 범위 - -지정된 대화의 마지막 완료 작업을 되돌리고, 첨부 이미지와 설명을 기준으로 고방유리의 표면 질감을 재검토한다. 사진을 올리기 전에도 모자이크 유리 패턴이 명확하게 보여야 한다는 요구를 다음 구현의 필수 완료 기준으로 삼는다. - -이번 코드 변경은 마지막 작업의 실행 취소에 한정한다. 아래 표면 재설계는 검토안이며 아직 구현하지 않았다. 따라서 사진 업로드 전 패턴 가시성이 개선됐다고 보고하지 않는다. - -## 복원 근거와 변경 파일 - -대화에서 확인한 마지막 완료 작업은 굴절된 사진 디테일을 색면에 42% 다시 섞고, 기본 셀 법선의 기울기를 1.2배로 늘린 실험이다. `../qa-glass-material/report.md`에도 두 변경이 기록되어 있다. 현재 셰이더와 해당 작업 직전의 `../qa-glass-material/baseline-mosaic.frag`를 직접 비교해 이 두 변경과 uniform 선언 외의 차이가 없음을 확인한 뒤 복원했다. - -| 파일 | 복원 내용 | -| --- | --- | -| `src/shaders/mosaic.frag` | `uTransmissionDetail`, `uCellLensScale`과 관련 계산을 제거하고 작업 직전 셰이더로 복원 | -| `src/main.ts` | 해당 상수의 import와 두 uniform 연결만 제거 | -| `src/constants/glass.ts` | 마지막 작업에서 추가된 두 상수 제거. 기존 환경 반사 강도 0.12 유지 | -| `scripts/test-mosaic-continuity.mjs` | 법선 배율 추가 전의 계산과 셰이더 계약으로 복원. 연속성 판정 기준은 유지 | -| `scripts/test-glass-transmission.mjs` | 취소된 42% 혼합을 강제하던 마지막 작업의 신규 검사 제거 | - -복원 직전의 위 다섯 파일은 `before-rollback/`에 보존했다. 과거 실험 보고서와 비교 이미지는 삭제하지 않고 보고서 상단에 적용 취소 상태를 표시했다. 이전 작업의 depth 보정, 어두운 색면 대표색 선택, 환경 반사, 창틀, 수동 사진 구도, UI 설정은 변경하지 않았다. - -프로젝트에서 `git status`와 `git log`는 “not a git repository”로 실패했다. 따라서 commit 단위의 reset/revert를 사용하지 않았으며, 대화의 변경 기록과 로컬 백업을 근거로 해당 변경만 역적용했다. - -## 첨부 자료를 바탕으로 한 판단 - -원하는 결과는 사진 앞에 고방유리판이 놓여 있는 모습이다. 첨부 이미지의 사각 패턴은 작은 칸의 경사면과 가장자리에 생기는 밝고 어두운 변화가 반복되어 읽힌다. 사진의 색면과 별개로 그 표면이 인식되는지가 우선 평가 대상이다. - -사진의 depth는 유리 뒤 장면의 앞뒤 배치를 담당하고, 유리 표면의 height/normal은 유리 자체의 요철을 담당하도록 구분해야 한다. 이 구분은 사용자가 첨부한 설명의 설계 근거이며, 이번 작업에서 AI 모델이나 depth 경로를 교체할 이유는 없다. - -### 현재 코드에서 확인한 원인 - -1. **빈 화면의 투과 대상이 단색이다.** `src/main.ts`의 `emptyTex`는 1×1 단색 텍스처이며 `scene.background`도 단색이다. 같은 색을 굴절해 읽는 위치만 바꾸면 유리의 사각 패턴을 강하게 드러내기 어렵다. 렌더링 루프는 사진을 올리기 전에도 Final을 그리므로, 유리가 아예 렌더링되지 않는 문제로 단정해서는 안 된다. -2. **기본 셀은 완만한 사인 기울기다.** `evaluateCell()`의 기본 Mosaic 법선은 사인 함수 기반이다. 현재 반사는 같은 법선을 사용하지만 공통 직사각 광원과 부드러운 환경 그라데이션으로 구성되어 있다. 첨부 이미지의 평탄한 면과 좁은 가장자리 변화가 충분히 표현되는지는 별도 시각 검증이 필요하다. -3. **기존 환경 반사 비중이 작다.** 초기 설정에서 환경 반사 가중치는 `0.12 × 0.3 × (0.35 + 0.65 × fresnel) × surfaceReflectionWeight`다. 표면이 정면을 향하는 곳의 Fresnel을 약 0.04로 놓으면 외곽 감쇠 전에도 약 0.0135다. 이 값은 코드상 합성 계수이며 화면 밝기 변화율이나 가시성을 측정한 값은 아니다. -4. **42% 혼합은 사진 쪽 변화였다.** 취소한 혼합은 굴절 샘플의 세부 정보를 다시 보여준다. 사진이 없는 상태의 표면 요철과 반사 환경을 새로 구성하는 변경은 아니었다. 셀 기울기만 1.2배로 늘리는 것도 사용자가 지적한 질감을 직접 해결했다고 볼 수 없다. - -## 다음 구현안 - -기존 2-pass 구조와 공통 장면 좌표를 유지하면서 유리 재질을 독립적으로 검증하는 방향을 권한다. - -- **유리 표면:** 사각 셀의 비교적 평탄한 중심, 좁은 경사면, 연속적인 경계를 정의한 반복 height에서 법선을 만든다. 동일 법선을 굴절과 반사에 공유하고, 격자는 유리 좌표에 고정한다. 사진이나 시점에 따라 셀별로 임의의 다른 장면을 배정하지 않는다. -- **사진 전 화면:** 사용자 사진 대신 명암이 있는 중립 배경을 유리 뒤에 배치하고, 공통의 정적인 반사 환경을 제공한다. 배경에는 유리 격자를 직접 그리지 않는다. 유리 표면을 통과하거나 반사한 결과로 패턴이 나타나야 한다. 사진을 올리면 뒤 장면만 교체하고 같은 유리 재질을 유지한다. -- **합성 순서:** 사진 색면 처리 이후에 유리 표면 반사를 합성해 표면 정보가 색면 대표색에 흡수되지 않게 한다. 현재 코드도 이 순서를 사용하므로 순서 자체를 새로 고치는 대신 실제 표면/환경 표현을 보강하는 데 집중한다. 기존 42% 사진 혼합은 다시 도입하지 않는다. -- **Depth 연동:** 평면 사진과 빈 유리에서 표면을 먼저 평가한 후, 기존 depth 보정과 연결해 유리와 피사체 간격에 따른 굴절 차이를 확인한다. 사진 확대·팬·크롭 자동 변경은 하지 않는다. 유리 곡면을 바꾸면 공통 법선과 UV 연속성도 함께 다시 검증한다. - -사진 없이 보이는 유리만을 위해 별도의 CSS 격자나 업로드 후 사라지는 장식 그림을 추가하는 방식은 이 검토안의 목표를 충족하지 않는다. - -## 다음 구현의 완료 기준 - -| 조건 | 확인할 결과 | -| --- | --- | -| 사진 미업로드, 기본 설정 | 사각 셀의 경사면과 반사가 정지 화면에서도 분명하게 구별됨 | -| 같은 설정에서 사진 업로드 전후 | 같은 유리판의 패턴이 유지되고 뒤 장면만 바뀜 | -| 드래그 | 격자는 유리 좌표에 남고 내부 굴절과 반사가 시점에 반응함 | -| 광택 0 | 투과 대상에 명암이 있을 때 곡면에 의한 굴절이 남음. 완전 단색 배경에서 강한 격자 가시성을 보장하는 기준으로 사용하지 않음 | -| Glass OFF / Final | 먼저 지정 샘플의 깊이 시차를 확인하고, Final에서 같은 장면과 구도를 유지함 | -| 모바일 폭 390px / 데스크톱 | 동일 재질과 설정으로 표시되며 가로 넘침과 셰이더 실행 오류가 없음 | - -## 실행한 검증과 남은 검증 - -- 복원된 Mosaic 셰이더가 마지막 작업 전 백업과 일치함을 Node assertion으로 확인했다. -- 기존 `scripts/test-*.mjs` 9개를 실행해 전부 통과했다. 카메라/history, depth 증거·굴절, Mosaic 연속성·거리, 어두운 색면 표본·축 분할, 표면 반사, 창틀 범위 검사다. 이들은 소스/수학/형상 검사이며 GPU 시각 품질 검증을 대신하지 않는다. -- `npm.cmd run build`에서 TypeScript 단계는 통과했으나 Vite 단계가 `EPERM: operation not permitted, realpath 'D:\project\behind_glass\src\style.css'`로 실패했다. 진단 결과 일반 읽기와 JS realpath는 가능하지만 `fs.realpathSync.native`는 main.ts, style.css, mosaic.frag 모두에서 EPERM을 반환했다. -- 샌드박스 밖 빌드를 요청했으나 자동 승인 검토가 사용량 한도로 완료되지 않아 명령은 실행되지 않았다. 안전하지 않다는 판정이 아니며, 승인 검토를 우회하지 않았다. -- 로컬 5174 미리보기는 접속에 실패했다. 이번 작업에서 브라우저/GPU 실행, 사진 전후 화면 비교, 실제 모바일 성능을 검증하지 않았다. 빌드 재검증과 실화면 검증이 남아 있다. - -승인 검토가 가능한 환경에서 프로젝트 루트의 `npm.cmd run build`로 빌드를 다시 확인하고, `npm.cmd run dev -- --host 127.0.0.1 --port 5174`로 로컬 미리보기를 실행할 수 있다. 다음 구현안의 화면 개선은 아직 적용되지 않았다. diff --git a/docs/qa-gobang-surface-2026-10-06/dog1-gobang-concave.png b/docs/qa-gobang-surface-2026-10-06/dog1-gobang-concave.png deleted file mode 100644 index 374d615..0000000 Binary files a/docs/qa-gobang-surface-2026-10-06/dog1-gobang-concave.png and /dev/null differ diff --git a/docs/qa-gobang-surface-2026-10-06/dog1-gobang-drag.png b/docs/qa-gobang-surface-2026-10-06/dog1-gobang-drag.png deleted file mode 100644 index c9e04c6..0000000 Binary files a/docs/qa-gobang-surface-2026-10-06/dog1-gobang-drag.png and /dev/null differ diff --git a/docs/qa-gobang-surface-2026-10-06/dog1-gobang-final.png b/docs/qa-gobang-surface-2026-10-06/dog1-gobang-final.png deleted file mode 100644 index 8dc4145..0000000 Binary files a/docs/qa-gobang-surface-2026-10-06/dog1-gobang-final.png and /dev/null differ diff --git a/docs/qa-gobang-surface-2026-10-06/dog1-gobang-flat-gloss0.png b/docs/qa-gobang-surface-2026-10-06/dog1-gobang-flat-gloss0.png deleted file mode 100644 index 9b1ae2e..0000000 Binary files a/docs/qa-gobang-surface-2026-10-06/dog1-gobang-flat-gloss0.png and /dev/null differ diff --git a/docs/qa-gobang-surface-2026-10-06/dog1-gobang-gloss0.png b/docs/qa-gobang-surface-2026-10-06/dog1-gobang-gloss0.png deleted file mode 100644 index e322da4..0000000 Binary files a/docs/qa-gobang-surface-2026-10-06/dog1-gobang-gloss0.png and /dev/null differ diff --git a/docs/qa-gobang-surface-2026-10-06/dog1-gobang-grid13.png b/docs/qa-gobang-surface-2026-10-06/dog1-gobang-grid13.png deleted file mode 100644 index 0277ade..0000000 Binary files a/docs/qa-gobang-surface-2026-10-06/dog1-gobang-grid13.png and /dev/null differ diff --git a/docs/qa-gobang-surface-2026-10-06/dog1-gobang-grid20.png b/docs/qa-gobang-surface-2026-10-06/dog1-gobang-grid20.png deleted file mode 100644 index c1a2eb1..0000000 Binary files a/docs/qa-gobang-surface-2026-10-06/dog1-gobang-grid20.png and /dev/null differ diff --git a/docs/qa-gobang-surface-2026-10-06/dog1-gobang-mobile.png b/docs/qa-gobang-surface-2026-10-06/dog1-gobang-mobile.png deleted file mode 100644 index 9ea6f38..0000000 Binary files a/docs/qa-gobang-surface-2026-10-06/dog1-gobang-mobile.png and /dev/null differ diff --git a/docs/qa-gobang-surface-2026-10-06/dog1-ref1-option2-grid13.png b/docs/qa-gobang-surface-2026-10-06/dog1-ref1-option2-grid13.png deleted file mode 100644 index 9760189..0000000 Binary files a/docs/qa-gobang-surface-2026-10-06/dog1-ref1-option2-grid13.png and /dev/null differ diff --git a/docs/qa-gobang-surface-2026-10-06/dog2-gobang-grid20.png b/docs/qa-gobang-surface-2026-10-06/dog2-gobang-grid20.png deleted file mode 100644 index c952815..0000000 Binary files a/docs/qa-gobang-surface-2026-10-06/dog2-gobang-grid20.png and /dev/null differ diff --git a/docs/qa-gobang-surface-2026-10-06/empty-glass-desktop.png b/docs/qa-gobang-surface-2026-10-06/empty-glass-desktop.png deleted file mode 100644 index 4bb2d9e..0000000 Binary files a/docs/qa-gobang-surface-2026-10-06/empty-glass-desktop.png and /dev/null differ diff --git a/docs/qa-gobang-surface-2026-10-06/report.md b/docs/qa-gobang-surface-2026-10-06/report.md deleted file mode 100644 index 260c0ef..0000000 --- a/docs/qa-gobang-surface-2026-10-06/report.md +++ /dev/null @@ -1,57 +0,0 @@ -# 고방유리 표면과 투과 영상 - -이 문서는 첫 구현의 기록이다. 같은 날 사용자가 올린 300×300 확대 사진에 따른 후속 표면 보정과 현재 수치는 [후속 보고서](../qa-gobang-facets-2026-10-06/report.md)를 따른다. - -2026-10-06 사용자 요청: 첨부 실물 고방유리처럼 반복 패턴에 맞춰 뒤쪽 사진이 굴절되는 표현을 구현한다. GPT 답변은 설명 자료로 검토했으며 유리문 상호작용 등의 추가 제안을 구현 지시로 취급하지 않았다. - -## 적용 - -- 기본 패턴을 `고방유리 · 표면 굴절`로 바꿨다. Grid 20 / 굴곡 +1 / 광택 0.3 / Camera 0.5에서 시작한다. 주 화면의 패턴 선택에서 기존 Ref1 옵션 2(Grid 13, 색면 1)와 기존 촘촘 유리(Grid 24)로 전환할 수 있다. 사진 확대·팬은 바꾸지 않는다. -- `src/shaders/mosaic.frag`: 새로운 style 2 경로는 사각 셀의 평탄한 중심과 둥근 경사면을 반복 높이 함수로 정의한다. 셀 경계에서 높이와 첫 미분이 이어진다. 높이의 미분에서 얻은 동일 법선으로 굴절과 환경 반사를 계산한다. 별도 격자선이나 셀별 무작위 사진 크롭을 합성하지 않는다. -- 카메라 광선의 얕은 앞면 교점을 두 번 보정하고, 굴절률 1.5의 요철 앞면과 평탄한 뒷면을 거쳐 배경을 읽는다. 새 모드에는 기존의 최소 0.6 연출 광학 거리를 사용하지 않는다. 기존 visible-depth 교점 보정 함수를 재사용한다. 색면 atlas/palette/history는 새 모드에서 실행되지 않는다. 기존 Ref1/촘촘 유리의 광학 및 색면 셰이더 경로는 유지했다. -- `src/constants/glass.ts`: 높이/셀 크기 0.065, 평탄 중심 반폭 0.18셀, 굴절률 1.5, 기본 두께 0.008, 환경 반사 강도 0.65를 기록했다. 뒷면은 음의 굴곡도 수용하도록 기본 두께에 최대 셀 높이를 더해 배치한다. 실물 유리의 측정값이 아니라 장면 좌표의 초기 재질 설정이다. -- `src/main.ts`: 사진 미입력 시 넓은 명암 영역과 하나의 창 형태가 있는 중립 배경을 그린다. 배경에는 반복 격자가 없다. 업로드 전후 동일한 유리 셰이더가 사용되고 중립 배경 텍스처도 기존 teardown에서 dispose된다. -- `index.html`: 유리 패턴 선택을 주 화면으로 옮기고 현재 모드의 설명과 Grid 기본값을 맞췄다. 기존 비교 이미지와 수동 구도 조절을 유지했다. -- `src/depth/aiDepth.worker.ts`: 이미 설치된 Transformers.js 4.3의 출력 타입 `DepthEstimationOutput`을 기존 지역 타입 이름으로 import해 빌드 오류를 해결했다. 추론·정규화 알고리즘은 변경하지 않았다. 작업 전 존재한 package.json/package-lock.json 변경은 건드리지 않았다. -- 기존 axis-split 검사의 UI 기본값/선택 위치 기대값을 갱신했다. 기존 표면 반사 검사에는 Windows CRLF 정규화를 추가했다. 새 테스트 프레임워크나 의존성은 추가하지 않았다. - -## 검증 - -검증 환경은 Windows의 Codex in-app browser다. 먼저 수작업 샘플을 Glass OFF로 확인한 후 사진과 Final 모드를 비교했다. - -| 조건 | 확인 결과 | -| --- | --- | -| Glass OFF, 수작업 샘플 | 앞 표면 z 0.560, 유리 z 0.600, 간격 0.040 유지. 카메라 X 0→약 0.053에서 코 투영 X 520.448→516.916, 왼눈 493.625→490.661, 몸 453.585→451.358px로 서로 다른 시차 확인 | -| 사진 미입력 | 사각 경사면의 명암과 중립 배경의 굴절이 정지 화면에서 보임 | -| dog1, 자동 AI depth | AI 추정 완료 후 동일 사진·구도에서 고방유리와 Ref1 옵션 2 비교. 새 모드의 셀 내부 윤곽 늘어남/반복과 사각 경사면 확인 | -| dog1, Grid 13/20 | Grid 13에서 같은 크기의 기존 색면과 새 굴절을 비교. 기본 Grid 20의 더 작은 패턴도 확인 | -| 광택 0, 굴곡 +1 | 표면 반사가 사라져도 사진 윤곽의 굴절 유지 | -| 광택 0, 굴곡 0 | 반복적인 사진 변형이 사라지고 평탄 유리의 투과 영상으로 복귀 | -| 굴곡 −1 | 오목한 표면의 다른 굴절 결과 확인 | -| 드래그 | 패턴이 유리 좌표에 남고 뒤 영상과 반사가 시점에 반응함 | -| dog2, 자동 AI depth | 두 번째 사진에서도 같은 유리 재질과 AI depth 적용 성공 | -| 기존 Reeded / Frosted | 두 모드의 렌더링과 고방유리로 복귀 확인 | -| 1280×900 / 390×844 | 데스크톱·모바일 폭 출력 확인. 모바일 innerWidth 390, document.scrollWidth 375로 가로 넘침 없음 | -| 사진 구도 | dog1 AI 완료·모드 전환·모바일 크기 변경 뒤에도 확대 1 / 팬 X 0 / 팬 Y 0 | - -브라우저 console error는 없었다. ANGLE 셰이더 컴파일러는 공유 depth 교점 반복의 텍스처 implicit derivative에 대한 warning을 출력했다. 이 경고와 모바일 실기기 성능 검증은 별도로 남는다. - -기존 검사 9개가 통과했다: camera/history, depth evidence, depth refraction, Mosaic continuity, depth-distance, atlas dark sampling, axis split, surface reflection, window reveal coverage. 이들은 기존 비교 경로의 소스/수학/형상 검사이며 새 고방유리의 시각 품질은 위 실화면 검증으로 평가했다. Node 22에서 `.ts`를 import하는 검사는 `--experimental-strip-types`로 실행했다. - -최종 TypeScript/Vite 빌드 통과: `npm.cmd run build -- --outDir test-results/gobang-build`. 최초 `npm.cmd run build`도 타입 호환 수정 후 통과했다. 기존 큰 번들 경고는 남는다. 빌드가 생성한 추적 dist 변경은 작업 전 상태로 복구하고 검증 산출물은 제거했다. - -## 비교 이미지 - -- `empty-glass-desktop.png`: 사진 미입력 -- `sample-no-glass.png`, `sample-no-glass-drag.png`: 수작업 depth의 실제 시차 -- `dog1-ref1-option2-grid13.png`: 보존된 기존 옵션 2 -- `dog1-gobang-grid13.png`, `dog1-gobang-grid20.png`: 새로운 표면 굴절 -- `dog1-gobang-gloss0.png`, `dog1-gobang-flat-gloss0.png`: 반사와 굴절의 역할 분리 -- `dog1-gobang-concave.png`, `dog1-gobang-drag.png`: 부호/시점 반응 -- `dog1-gobang-mobile.png`, `dog2-gobang-grid20.png`: 모바일 폭 및 다른 사진 - -## 한계와 실행 - -사진의 depth는 상대 깊이다. 유리 형상은 첨부 스크린샷을 바탕으로 만든 절차적 근사이며 특정 제품의 실측 복원이 아니다. 앞면 교점은 얕은 높이장의 반복 근사이고, 배경 교점은 현재 시점에서 보이는 depth만 재사용한다. 가려진 영역을 복원하거나 다중 내부 반사·광학 caustics를 계산하지 않는다. 참고 사진과 완전히 동일한 재질이라는 판정, 영상 flicker 계측, 모바일 실기기 FPS 측정은 하지 않았다. - -프로젝트 루트에서 `npm.cmd run dev -- --host 127.0.0.1 --port 5174`로 실행한다. 이번 작업의 로컬 미리보기는 `http://127.0.0.1:5174/`다. 사진은 브라우저 로컬에서 처리하며 외부 게시나 배포는 하지 않았다. diff --git a/docs/qa-gobang-surface-2026-10-06/sample-no-glass-drag.png b/docs/qa-gobang-surface-2026-10-06/sample-no-glass-drag.png deleted file mode 100644 index 8c1531b..0000000 Binary files a/docs/qa-gobang-surface-2026-10-06/sample-no-glass-drag.png and /dev/null differ diff --git a/docs/qa-gobang-surface-2026-10-06/sample-no-glass.png b/docs/qa-gobang-surface-2026-10-06/sample-no-glass.png deleted file mode 100644 index 853f269..0000000 Binary files a/docs/qa-gobang-surface-2026-10-06/sample-no-glass.png and /dev/null differ diff --git a/docs/qa-improvement-plan.md b/docs/qa-improvement-plan.md deleted file mode 100644 index ce2404b..0000000 --- a/docs/qa-improvement-plan.md +++ /dev/null @@ -1,8 +0,0 @@ -# QA 개선 계획 — 2026-09-12 - - -- Reeded/Frosted는 기존 유리면 교점 gh로 pane 좌표를 구해 외부를 배경색으로 제한한다. 내부 효과와 Distortion 0 원본 우회는 보존한다. -- 사진/영상/Depth의 native file input을 키보드로 접근할 수 있게 하고 초점을 표시한다. -- 일시적인 상태 메시지와 별개로 샘플의 수작업·절차적 근사 Depth 출처를 유지한다. 일반 미디어 및 사용자 Depth 성공 적용 시 샘플 안내를 숨긴다. 실패/취소에는 현재 출처를 보존한다. -- 강한 볼록 후보: +.65 초과분 e에 대해 유효 곡률 c-(.25/.35)*e²를 사용한다. +1은 .9125이며 반응 기울기는 항상 양수다. 원래 이동량 cap .30 및 선택적 셀 배율은 보존하고 결과 법선을 굴절/반사가 공유한다. cap 자체를 낮추는 초기 후보는 슬라이더 반응 역전 위험으로 제외했다. -- 빌드와 실제 브라우저 검증을 구분한다. 기존 shader baseline은 docs/before-qa-improvements/mosaic.frag에 보존했다. diff --git a/docs/qa-improvement-validation.md b/docs/qa-improvement-validation.md deleted file mode 100644 index 4f7b5f4..0000000 --- a/docs/qa-improvement-validation.md +++ /dev/null @@ -1,15 +0,0 @@ -# QA 개선 검증 - -2026-09-12 시작. Astra 설계 / Luna 구현. - -수정 파일: index.html, src/style.css, src/main.ts, src/shaders/mosaic.frag, reeded.frag, frosted.frag. - -- Reeded/Frosted의 유리판 밖 출력을 배경색으로 제한했다. 각 early return에도 colorspace 변환을 적용했다. 정면 및 드래그한 화면에서 창틀 밖 사진이 사라지고 배경색이 일치함을 확인했다. -- Frosted Distortion 0에서 기존 원본 출력 확인. 이 진단 성격의 설정에서는 사진이 창틀 밖에도 보이는 기존 요구사항을 유지한다. -- 키보드 Tab으로 사진 입력에 접근하고 focus ring 표시 확인. Enter로 사진/Depth 파일 선택 및 실제 로딩 완료 확인. 중간 hot reload로 첫 filechooser 검증이 실패하여 최종 파일에서 재실행했다. -- 샘플 안내가 로딩 완료 후 유지되고 일반 사진 성공 로딩 및 수동 Depth 성공 적용 시 숨겨지는 것을 확인했다. 실패/취소 시 유지 경로는 코드 검토만 수행했다. -- 볼록 +.65 초과에서만 높이 증가폭을 완만하게 제한했다. +1 유효 곡률 .9125이며 음수/0/+.65 및 기존 셀별 배율은 보존한다. 광택0/+1 데스크톱 전후 비교에서 변화는 작으며 조각 경계를 완전히 해소하는 보정은 아니다. 모바일 +1 드래그와 기본+.65 표시도 확인했다. -- No Glass 부위별 카메라 시차 확인. 기존 Depth/RT 경로는 변경하지 않았다. -- Luna 빌드 통과. 최종 브라우저 error 로그 없음. 1280×720 / 390×844 검증 후 viewport와 기본 설정을 복원했다. - -영상/실제 센서/성능 측정은 미실행. 셀별 배율 차이로 인한 일부 불연속은 남아 있으며, 이번 변경은 기존 표정을 유지하는 소폭 보정이다. diff --git a/docs/qa-mosaic-improvement/anisotropic-mosaic.frag b/docs/qa-mosaic-improvement/anisotropic-mosaic.frag deleted file mode 100644 index 318c08c..0000000 --- a/docs/qa-mosaic-improvement/anisotropic-mosaic.frag +++ /dev/null @@ -1,88 +0,0 @@ -uniform sampler2D uSceneTexture; -uniform mat4 uContentViewProjection,uContentInverseViewProjection; -uniform vec3 uContentCameraPosition,uLightPosition,uBackgroundColor; -uniform float uGlassZ,uGridSize,uStrength,uMosaicStyle,uCurvature,uGlossStrength; -uniform vec2 uViewOffset,uPetSize,uPaneSize; -uniform vec4 uPaneRect; -varying vec2 vUv; -vec2 projectUv(vec3 p){vec4 c=uContentViewProjection*vec4(p,1.);float w=abs(c.w)<.0001?(c.w<0.?-.0001:.0001):c.w;return c.xy/w*.5+.5;} -vec4 sampleScene(vec2 uv){return texture2D(uSceneTexture,clamp(uv,0.,1.));} -vec4 samplePane(vec2 pane){return sampleScene(projectUv(vec3((pane-.5)*uPaneSize,uGlassZ)));} -float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);} -vec2 hash2(vec2 p){return vec2(hash(p),hash(p+vec2(19.19,73.73)));} -float safeZ(float z){return abs(z)<.0001?(z<0.?-.0001:.0001):z;} -vec3 bend(vec3 i,vec3 n){vec3 r=refract(i,n,.75);return length(r)<.0001?i:r;} -float softLimit(float value,float limit){return value*limit/(limit+abs(value));} -void evaluateCell(vec2 cell,vec2 local,vec2 grid,vec2 cellSize,vec2 cellDimensions,float cellWorld,float style,out vec2 affineUv,out mat2 transform,out vec2 curvedSlope,out vec2 facetSlope){ - vec2 random=hash2(cell),widths; - if(style>.5){ - widths=mix(vec2(.82),vec2(1.12),hash2(cell+vec2(11.4,9.8))); - }else{ - float widthSeed=hash(cell+vec2(53.1,27.4)); - if(widthSeed<.3)widths=mix(vec2(.90),vec2(1.08),hash2(cell+vec2(7.2,3.1))); - else if(widthSeed<.9){ - widths=mix(vec2(.46),vec2(.70),hash2(cell+vec2(7.2,3.1))); - float area=sqrt(widths.x*widths.y),longWidth=area*1.41421356,shortWidth=area*.70710678; - widths=hash(cell+vec2(101.3,37.7))<.5?vec2(longWidth,shortWidth):vec2(shortWidth,longWidth); - } - else widths=mix(vec2(1.10),vec2(1.28),hash2(cell+vec2(7.2,3.1))); - } - float angle=(random.x-.5)*.08,c=cos(angle),s=sin(angle); - transform=mat2(widths.x*c,-widths.y*s,widths.x*s,widths.y*c); - vec2 sourceCenter=(cell+.5)/grid+(random-.5)*.16*cellSize; - affineUv=sourceCenter+transform*(local*cellSize); - - // Positive height bulges toward the observer (+Z); negative height is concave. - float curvature=clamp(uCurvature,-1.,1.),excess=max(curvature-.65,0.),surfaceCurvature=curvature-(.25/.35)*excess*excess; - float height=.009*cellWorld*surfaceCurvature*mix(.92,1.08,hash(cell+vec2(41.7,17.3))); - vec2 q=clamp(2.*local,-1.,1.),q2=q*q,q3=q2*q,b=1.-q2*q2; - vec2 skew=(hash2(cell+vec2(23.8,61.2))-.5)*.28;float asym=1.+dot(skew,q); - vec2 dhdq=height*vec2(-4.*q3.x*b.y*asym+b.x*b.y*skew.x,-4.*q3.y*b.x*asym+b.x*b.y*skew.y); - vec2 grad=-2.*dhdq/cellDimensions; - curvedSlope=grad+(random-.5)*.012;facetSlope=(random-.5)*.012; -} -void main(){ - if(uStrength<=.001){gl_FragColor=sampleScene(vUv); - #include - return;} - vec4 f=uContentInverseViewProjection*vec4(vUv*2.-1.,1.,1.);float fw=abs(f.w)<.0001?(f.w<0.?-.0001:.0001):f.w;vec3 farWorld=f.xyz/fw;vec3 i=normalize(farWorld-uContentCameraPosition);float gt=(uGlassZ-uContentCameraPosition.z)/safeZ(i.z);vec3 gh=uContentCameraPosition+i*gt; - vec2 paneUv=gh.xy/uPaneSize+.5;vec2 grid=vec2(uGridSize,max(1.,uGridSize*uPaneSize.y/uPaneSize.x));vec2 gridUv=paneUv*grid,cell=floor(gridUv),local=fract(gridUv)-.5,cellSize=1./grid;float style=clamp(uMosaicStyle,0.,1.),cellWorld=min(uPaneSize.x/grid.x,uPaneSize.y/grid.y); - if(paneUv.x<0.||paneUv.x>1.||paneUv.y<0.||paneUv.y>1.){gl_FragColor=vec4(uBackgroundColor,1.); - #include - return;} - vec2 cellDimensions=uPaneSize/grid; - vec2 affineUv,curvedSlope,facetSlope;mat2 transform; - evaluateCell(cell,local,grid,cellSize,cellDimensions,cellWorld,style,affineUv,transform,curvedSlope,facetSlope); - vec2 edge=.5-abs(local),neighborSign=mix(vec2(-1.),vec2(1.),step(vec2(0.),local)); - vec2 blendAxis=1.-smoothstep(vec2(-.16),vec2(.16),edge); - vec2 weights=blendAxis; - if(weights.x>0.||weights.y>0.){ - vec2 neighborAffine,neighborCurved,neighborFacet;mat2 neighborTransform; - vec2 xWeight=vec2(weights.x*(1.-weights.y),0.); - vec2 yWeight=vec2(0.,(1.-weights.x)*weights.y); - float diagonalWeight=weights.x*weights.y; - float centerWeight=(1.-weights.x)*(1.-weights.y); - affineUv*=centerWeight;transform*=centerWeight;curvedSlope*=centerWeight;facetSlope*=centerWeight; - if(xWeight.x>0.){ - vec2 offset=vec2(neighborSign.x,0.); - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*xWeight.x;transform+=neighborTransform*xWeight.x;curvedSlope+=neighborCurved*xWeight.x;facetSlope+=neighborFacet*xWeight.x; - } - if(yWeight.y>0.){ - vec2 offset=vec2(0.,neighborSign.y); - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*yWeight.y;transform+=neighborTransform*yWeight.y;curvedSlope+=neighborCurved*yWeight.y;facetSlope+=neighborFacet*yWeight.y; - } - if(diagonalWeight>0.){ - vec2 offset=neighborSign; - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*diagonalWeight;transform+=neighborTransform*diagonalWeight;curvedSlope+=neighborCurved*diagonalWeight;facetSlope+=neighborFacet*diagonalWeight; - } - } - vec3 nCurved=normalize(vec3(curvedSlope,1.)),nFacet=normalize(vec3(facetSlope,1.)); - vec3 straightHit=gh+i*(-gh.z/safeZ(i.z));vec3 facetRay=bend(i,nFacet),curvedRay=bend(i,nCurved);vec3 facetHit=gh+facetRay*(-gh.z/safeZ(facetRay.z)),curvedHit=gh+curvedRay*(-gh.z/safeZ(curvedRay.z));vec2 base=facetHit.xy-straightHit.xy,curve=curvedHit.xy-facetHit.xy;vec2 worldDelta=vec2(softLimit(base.x,cellWorld*.08),softLimit(base.y,cellWorld*.08));vec2 d=curve/cellWorld;worldDelta+=vec2(.3*d.x/(.3+abs(d.x)),.3*d.y/(.3+abs(d.y)))*cellWorld; - vec2 sampleUv=affineUv+transform*(worldDelta/uPaneSize); - float edgeDistance=min(min(paneUv.x,paneUv.y),min(1.-paneUv.x,1.-paneUv.y));float edgeWeight=smoothstep(0.,max(cellSize.x,cellSize.y)*.75,edgeDistance);float strength=clamp(uStrength,0.,1.)*edgeWeight;vec2 blurStep=cellSize*mix(.006,.012,hash(cell+vec2(5.)));vec2 centerUv=mix(paneUv,sampleUv,strength);vec4 color=samplePane(centerUv)*.4;color+=samplePane(mix(paneUv,sampleUv+vec2(blurStep.x,0.),strength))*.15;color+=samplePane(mix(paneUv,sampleUv-vec2(blurStep.x,0.),strength))*.15;color+=samplePane(mix(paneUv,sampleUv+vec2(0.,blurStep.y),strength))*.15;color+=samplePane(mix(paneUv,sampleUv-vec2(0.,blurStep.y),strength))*.15;color.a=1.; - vec3 v=normalize(uContentCameraPosition-gh),reflected=reflect(-v,nCurved); float lightT=(uLightPosition.z-gh.z)/safeZ(reflected.z); vec2 lightHit=gh.xy+reflected.xy*lightT; vec2 halfSize=vec2(.32,.42)*min(uPaneSize.x,uPaneSize.y); vec2 windowCoord=abs(lightHit-uLightPosition.xy)/halfSize; vec2 windowMask=1.-smoothstep(vec2(.45),vec2(1.15),windowCoord); float spec=windowMask.x*windowMask.y*step(.0001,reflected.z)*step(0.,lightT); float gloss=spec*clamp(uGlossStrength,0.,1.)*.12*edgeWeight*clamp(uStrength,0.,1.); color.rgb=mix(color.rgb,vec3(1.),gloss); gl_FragColor=color; - #include -} diff --git a/docs/qa-mosaic-improvement/baseline-mosaic.frag b/docs/qa-mosaic-improvement/baseline-mosaic.frag deleted file mode 100644 index 146b443..0000000 --- a/docs/qa-mosaic-improvement/baseline-mosaic.frag +++ /dev/null @@ -1,84 +0,0 @@ -uniform sampler2D uSceneTexture; -uniform mat4 uContentViewProjection,uContentInverseViewProjection; -uniform vec3 uContentCameraPosition,uLightPosition,uBackgroundColor; -uniform float uGlassZ,uGridSize,uStrength,uMosaicStyle,uCurvature,uGlossStrength; -uniform vec2 uViewOffset,uPetSize,uPaneSize; -uniform vec4 uPaneRect; -varying vec2 vUv; -vec2 projectUv(vec3 p){vec4 c=uContentViewProjection*vec4(p,1.);float w=abs(c.w)<.0001?(c.w<0.?-.0001:.0001):c.w;return c.xy/w*.5+.5;} -vec4 sampleScene(vec2 uv){return texture2D(uSceneTexture,clamp(uv,0.,1.));} -vec4 samplePane(vec2 pane){return sampleScene(projectUv(vec3((pane-.5)*uPaneSize,uGlassZ)));} -float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);} -vec2 hash2(vec2 p){return vec2(hash(p),hash(p+vec2(19.19,73.73)));} -float safeZ(float z){return abs(z)<.0001?(z<0.?-.0001:.0001):z;} -vec3 bend(vec3 i,vec3 n){vec3 r=refract(i,n,.75);return length(r)<.0001?i:r;} -float softLimit(float value,float limit){return value*limit/(limit+abs(value));} -void evaluateCell(vec2 cell,vec2 local,vec2 grid,vec2 cellSize,vec2 cellDimensions,float cellWorld,float style,out vec2 affineUv,out mat2 transform,out vec2 curvedSlope,out vec2 facetSlope){ - vec2 random=hash2(cell),widths; - if(style>.5){ - widths=mix(vec2(.82),vec2(1.12),hash2(cell+vec2(11.4,9.8))); - }else{ - float widthSeed=hash(cell+vec2(53.1,27.4)); - if(widthSeed<.6)widths=mix(vec2(.90),vec2(1.08),hash2(cell+vec2(7.2,3.1))); - else if(widthSeed<.9)widths=mix(vec2(.46),vec2(.70),hash2(cell+vec2(7.2,3.1))); - else widths=mix(vec2(1.10),vec2(1.28),hash2(cell+vec2(7.2,3.1))); - } - float angle=(random.x-.5)*.08,c=cos(angle),s=sin(angle); - transform=mat2(widths.x*c,-widths.y*s,widths.x*s,widths.y*c); - vec2 sourceCenter=(cell+.5)/grid+(random-.5)*.16*cellSize; - affineUv=sourceCenter+transform*(local*cellSize); - - // Positive height bulges toward the observer (+Z); negative height is concave. - float curvature=clamp(uCurvature,-1.,1.),excess=max(curvature-.65,0.),surfaceCurvature=curvature-(.25/.35)*excess*excess; - float height=.009*cellWorld*surfaceCurvature*mix(.92,1.08,hash(cell+vec2(41.7,17.3))); - vec2 q=clamp(2.*local,-1.,1.),q2=q*q,q3=q2*q,b=1.-q2*q2; - vec2 skew=(hash2(cell+vec2(23.8,61.2))-.5)*.28;float asym=1.+dot(skew,q); - vec2 dhdq=height*vec2(-4.*q3.x*b.y*asym+b.x*b.y*skew.x,-4.*q3.y*b.x*asym+b.x*b.y*skew.y); - vec2 grad=-2.*dhdq/cellDimensions; - curvedSlope=grad+(random-.5)*.012;facetSlope=(random-.5)*.012; -} -void main(){ - if(uStrength<=.001){gl_FragColor=sampleScene(vUv); - #include - return;} - vec4 f=uContentInverseViewProjection*vec4(vUv*2.-1.,1.,1.);float fw=abs(f.w)<.0001?(f.w<0.?-.0001:.0001):f.w;vec3 farWorld=f.xyz/fw;vec3 i=normalize(farWorld-uContentCameraPosition);float gt=(uGlassZ-uContentCameraPosition.z)/safeZ(i.z);vec3 gh=uContentCameraPosition+i*gt; - vec2 paneUv=gh.xy/uPaneSize+.5;vec2 grid=vec2(uGridSize,max(1.,uGridSize*uPaneSize.y/uPaneSize.x));vec2 gridUv=paneUv*grid,cell=floor(gridUv),local=fract(gridUv)-.5,cellSize=1./grid;float style=clamp(uMosaicStyle,0.,1.),cellWorld=min(uPaneSize.x/grid.x,uPaneSize.y/grid.y); - if(paneUv.x<0.||paneUv.x>1.||paneUv.y<0.||paneUv.y>1.){gl_FragColor=vec4(uBackgroundColor,1.); - #include - return;} - vec2 cellDimensions=uPaneSize/grid; - vec2 affineUv,curvedSlope,facetSlope;mat2 transform; - evaluateCell(cell,local,grid,cellSize,cellDimensions,cellWorld,style,affineUv,transform,curvedSlope,facetSlope); - vec2 edge=.5-abs(local),neighborSign=mix(vec2(-1.),vec2(1.),step(vec2(0.),local)); - vec2 blendAxis=1.-smoothstep(vec2(-.16),vec2(.16),edge); - vec2 weights=blendAxis; - if(weights.x>0.||weights.y>0.){ - vec2 neighborAffine,neighborCurved,neighborFacet;mat2 neighborTransform; - vec2 xWeight=vec2(weights.x*(1.-weights.y),0.); - vec2 yWeight=vec2(0.,(1.-weights.x)*weights.y); - float diagonalWeight=weights.x*weights.y; - float centerWeight=(1.-weights.x)*(1.-weights.y); - affineUv*=centerWeight;transform*=centerWeight;curvedSlope*=centerWeight;facetSlope*=centerWeight; - if(xWeight.x>0.){ - vec2 offset=vec2(neighborSign.x,0.); - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*xWeight.x;transform+=neighborTransform*xWeight.x;curvedSlope+=neighborCurved*xWeight.x;facetSlope+=neighborFacet*xWeight.x; - } - if(yWeight.y>0.){ - vec2 offset=vec2(0.,neighborSign.y); - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*yWeight.y;transform+=neighborTransform*yWeight.y;curvedSlope+=neighborCurved*yWeight.y;facetSlope+=neighborFacet*yWeight.y; - } - if(diagonalWeight>0.){ - vec2 offset=neighborSign; - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*diagonalWeight;transform+=neighborTransform*diagonalWeight;curvedSlope+=neighborCurved*diagonalWeight;facetSlope+=neighborFacet*diagonalWeight; - } - } - vec3 nCurved=normalize(vec3(curvedSlope,1.)),nFacet=normalize(vec3(facetSlope,1.)); - vec3 straightHit=gh+i*(-gh.z/safeZ(i.z));vec3 facetRay=bend(i,nFacet),curvedRay=bend(i,nCurved);vec3 facetHit=gh+facetRay*(-gh.z/safeZ(facetRay.z)),curvedHit=gh+curvedRay*(-gh.z/safeZ(curvedRay.z));vec2 base=facetHit.xy-straightHit.xy,curve=curvedHit.xy-facetHit.xy;vec2 worldDelta=vec2(softLimit(base.x,cellWorld*.08),softLimit(base.y,cellWorld*.08));vec2 d=curve/cellWorld;worldDelta+=vec2(.3*d.x/(.3+abs(d.x)),.3*d.y/(.3+abs(d.y)))*cellWorld; - vec2 sampleUv=affineUv+transform*(worldDelta/uPaneSize); - float edgeDistance=min(min(paneUv.x,paneUv.y),min(1.-paneUv.x,1.-paneUv.y));float edgeWeight=smoothstep(0.,max(cellSize.x,cellSize.y)*.75,edgeDistance);float strength=clamp(uStrength,0.,1.)*edgeWeight;vec2 blurStep=cellSize*mix(.006,.012,hash(cell+vec2(5.)));vec2 centerUv=mix(paneUv,sampleUv,strength);vec4 color=samplePane(centerUv)*.4;color+=samplePane(mix(paneUv,sampleUv+vec2(blurStep.x,0.),strength))*.15;color+=samplePane(mix(paneUv,sampleUv-vec2(blurStep.x,0.),strength))*.15;color+=samplePane(mix(paneUv,sampleUv+vec2(0.,blurStep.y),strength))*.15;color+=samplePane(mix(paneUv,sampleUv-vec2(0.,blurStep.y),strength))*.15;color.a=1.; - vec3 v=normalize(uContentCameraPosition-gh),reflected=reflect(-v,nCurved); float lightT=(uLightPosition.z-gh.z)/safeZ(reflected.z); vec2 lightHit=gh.xy+reflected.xy*lightT; vec2 halfSize=vec2(.32,.42)*min(uPaneSize.x,uPaneSize.y); vec2 windowCoord=abs(lightHit-uLightPosition.xy)/halfSize; vec2 windowMask=1.-smoothstep(vec2(.45),vec2(1.15),windowCoord); float spec=windowMask.x*windowMask.y*step(.0001,reflected.z)*step(0.,lightT); float gloss=spec*clamp(uGlossStrength,0.,1.)*.12*edgeWeight*clamp(uStrength,0.,1.); color.rgb=mix(color.rgb,vec3(1.),gloss); gl_FragColor=color; - #include -} diff --git a/docs/qa-mosaic-improvement/color-boundary-mosaic.frag b/docs/qa-mosaic-improvement/color-boundary-mosaic.frag deleted file mode 100644 index 20634a7..0000000 --- a/docs/qa-mosaic-improvement/color-boundary-mosaic.frag +++ /dev/null @@ -1,118 +0,0 @@ -uniform sampler2D uSceneTexture; -uniform mat4 uContentViewProjection,uContentInverseViewProjection; -uniform vec3 uContentCameraPosition,uLightPosition,uBackgroundColor; -uniform float uGlassZ,uGridSize,uStrength,uMosaicStyle,uCurvature,uGlossStrength; -uniform vec2 uViewOffset,uPetSize,uPaneSize; -uniform vec4 uPaneRect; -varying vec2 vUv; -vec2 projectUv(vec3 p){vec4 c=uContentViewProjection*vec4(p,1.);float w=abs(c.w)<.0001?(c.w<0.?-.0001:.0001):c.w;return c.xy/w*.5+.5;} -vec4 sampleScene(vec2 uv){return texture2D(uSceneTexture,clamp(uv,0.,1.));} -vec4 samplePane(vec2 pane){return sampleScene(projectUv(vec3((pane-.5)*uPaneSize,uGlassZ)));} -vec4 sampleCell(vec2 pane,vec2 sourceUv,float strength,vec2 blurStep){ - vec4 color=samplePane(mix(pane,sourceUv,strength))*.4; - color+=samplePane(mix(pane,sourceUv+vec2(blurStep.x,0.),strength))*.15; - color+=samplePane(mix(pane,sourceUv-vec2(blurStep.x,0.),strength))*.15; - color+=samplePane(mix(pane,sourceUv+vec2(0.,blurStep.y),strength))*.15; - color+=samplePane(mix(pane,sourceUv-vec2(0.,blurStep.y),strength))*.15; - return color; -} -float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);} -vec2 hash2(vec2 p){return vec2(hash(p),hash(p+vec2(19.19,73.73)));} -float safeZ(float z){return abs(z)<.0001?(z<0.?-.0001:.0001):z;} -vec3 bend(vec3 i,vec3 n){vec3 r=refract(i,n,.75);return length(r)<.0001?i:r;} -float softLimit(float value,float limit){return value*limit/(limit+abs(value));} -void evaluateCell(vec2 cell,vec2 local,vec2 grid,vec2 cellSize,vec2 cellDimensions,float cellWorld,float style,out vec2 affineUv,out mat2 transform,out vec2 curvedSlope,out vec2 facetSlope){ - vec2 random=hash2(cell),widths; - if(style>.5){ - widths=mix(vec2(.82),vec2(1.12),hash2(cell+vec2(11.4,9.8))); - }else{ - float widthSeed=hash(cell+vec2(53.1,27.4)); - if(widthSeed<.3)widths=mix(vec2(.90),vec2(1.08),hash2(cell+vec2(7.2,3.1))); - else if(widthSeed<.9)widths=mix(vec2(.46),vec2(.70),hash2(cell+vec2(7.2,3.1))); - else widths=mix(vec2(1.10),vec2(1.28),hash2(cell+vec2(7.2,3.1))); - } - float angle=(random.x-.5)*.08,c=cos(angle),s=sin(angle); - transform=mat2(widths.x*c,-widths.y*s,widths.x*s,widths.y*c); - vec2 sourceCenter=(cell+.5)/grid+(random-.5)*.16*cellSize; - affineUv=sourceCenter+transform*(local*cellSize); - - // Positive height bulges toward the observer (+Z); negative height is concave. - float curvature=clamp(uCurvature,-1.,1.),excess=max(curvature-.65,0.),surfaceCurvature=curvature-(.25/.35)*excess*excess; - float height=.009*cellWorld*surfaceCurvature*mix(.92,1.08,hash(cell+vec2(41.7,17.3))); - vec2 q=clamp(2.*local,-1.,1.),q2=q*q,q3=q2*q,b=1.-q2*q2; - vec2 skew=(hash2(cell+vec2(23.8,61.2))-.5)*.28;float asym=1.+dot(skew,q); - vec2 dhdq=height*vec2(-4.*q3.x*b.y*asym+b.x*b.y*skew.x,-4.*q3.y*b.x*asym+b.x*b.y*skew.y); - vec2 grad=-2.*dhdq/cellDimensions; - curvedSlope=grad+(random-.5)*.012;facetSlope=(random-.5)*.012; -} -void main(){ - if(uStrength<=.001){gl_FragColor=sampleScene(vUv); - #include - return;} - vec4 f=uContentInverseViewProjection*vec4(vUv*2.-1.,1.,1.);float fw=abs(f.w)<.0001?(f.w<0.?-.0001:.0001):f.w;vec3 farWorld=f.xyz/fw;vec3 i=normalize(farWorld-uContentCameraPosition);float gt=(uGlassZ-uContentCameraPosition.z)/safeZ(i.z);vec3 gh=uContentCameraPosition+i*gt; - vec2 paneUv=gh.xy/uPaneSize+.5;vec2 grid=vec2(uGridSize,max(1.,uGridSize*uPaneSize.y/uPaneSize.x));vec2 gridUv=paneUv*grid,cell=floor(gridUv),local=fract(gridUv)-.5,cellSize=1./grid;float style=clamp(uMosaicStyle,0.,1.),cellWorld=min(uPaneSize.x/grid.x,uPaneSize.y/grid.y); - if(paneUv.x<0.||paneUv.x>1.||paneUv.y<0.||paneUv.y>1.){gl_FragColor=vec4(uBackgroundColor,1.); - #include - return;} - vec2 cellDimensions=uPaneSize/grid; - vec2 affineUv,curvedSlope,facetSlope;mat2 transform; - evaluateCell(cell,local,grid,cellSize,cellDimensions,cellWorld,style,affineUv,transform,curvedSlope,facetSlope); - vec2 edge=.5-abs(local),neighborSign=mix(vec2(-1.),vec2(1.),step(vec2(0.),local)); - vec2 blendAxis=1.-smoothstep(vec2(-.16),vec2(.16),edge); - vec2 weights=blendAxis; - vec2 centerAffine=affineUv;mat2 centerTransform=transform; - vec2 xAffine=vec2(0.),yAffine=vec2(0.),diagonalAffine=vec2(0.); - mat2 xTransform=mat2(0.),yTransform=mat2(0.),diagonalTransform=mat2(0.); - float xSplitWeight=weights.x*(1.-weights.y),ySplitWeight=(1.-weights.x)*weights.y; - float diagonalSplitWeight=weights.x*weights.y,centerSplitWeight=(1.-weights.x)*(1.-weights.y); - if(weights.x>0.||weights.y>0.){ - vec2 neighborAffine,neighborCurved,neighborFacet;mat2 neighborTransform; - vec2 xWeight=vec2(xSplitWeight,0.); - vec2 yWeight=vec2(0.,ySplitWeight); - affineUv*=centerSplitWeight;transform*=centerSplitWeight;curvedSlope*=centerSplitWeight;facetSlope*=centerSplitWeight; - if(xWeight.x>0.){ - vec2 offset=vec2(neighborSign.x,0.); - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - xAffine=neighborAffine;xTransform=neighborTransform; - affineUv+=neighborAffine*xWeight.x;transform+=neighborTransform*xWeight.x;curvedSlope+=neighborCurved*xWeight.x;facetSlope+=neighborFacet*xWeight.x; - } - if(yWeight.y>0.){ - vec2 offset=vec2(0.,neighborSign.y); - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - yAffine=neighborAffine;yTransform=neighborTransform; - affineUv+=neighborAffine*yWeight.y;transform+=neighborTransform*yWeight.y;curvedSlope+=neighborCurved*yWeight.y;facetSlope+=neighborFacet*yWeight.y; - } - if(diagonalSplitWeight>0.){ - vec2 offset=neighborSign; - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - diagonalAffine=neighborAffine;diagonalTransform=neighborTransform; - affineUv+=neighborAffine*diagonalSplitWeight;transform+=neighborTransform*diagonalSplitWeight;curvedSlope+=neighborCurved*diagonalSplitWeight;facetSlope+=neighborFacet*diagonalSplitWeight; - } - } - vec3 nCurved=normalize(vec3(curvedSlope,1.)),nFacet=normalize(vec3(facetSlope,1.)); - vec3 straightHit=gh+i*(-gh.z/safeZ(i.z));vec3 facetRay=bend(i,nFacet),curvedRay=bend(i,nCurved);vec3 facetHit=gh+facetRay*(-gh.z/safeZ(facetRay.z)),curvedHit=gh+curvedRay*(-gh.z/safeZ(curvedRay.z));vec2 base=facetHit.xy-straightHit.xy,curve=curvedHit.xy-facetHit.xy;vec2 worldDelta=vec2(softLimit(base.x,cellWorld*.08),softLimit(base.y,cellWorld*.08));vec2 d=curve/cellWorld;worldDelta+=vec2(.3*d.x/(.3+abs(d.x)),.3*d.y/(.3+abs(d.y)))*cellWorld; - vec2 sampleUv=affineUv+transform*(worldDelta/uPaneSize); - float edgeDistance=min(min(paneUv.x,paneUv.y),min(1.-paneUv.x,1.-paneUv.y));float edgeWeight=smoothstep(0.,max(cellSize.x,cellSize.y)*.75,edgeDistance);float strength=clamp(uStrength,0.,1.)*edgeWeight;vec2 blurStep=cellSize*mix(.006,.012,hash(cell+vec2(5.))); - vec4 color; - if(style<=.5&&(weights.x>0.||weights.y>0.)){ - color=vec4(0.); - if(centerSplitWeight>0.)color+=sampleCell(paneUv,centerAffine+centerTransform*(worldDelta/uPaneSize),strength,blurStep)*centerSplitWeight; - if(xSplitWeight>0.){ - vec2 xBlurStep=cellSize*mix(.006,.012,hash(cell+vec2(neighborSign.x,0.)+vec2(5.))); - color+=sampleCell(paneUv,xAffine+xTransform*(worldDelta/uPaneSize),strength,xBlurStep)*xSplitWeight; - } - if(ySplitWeight>0.){ - vec2 yBlurStep=cellSize*mix(.006,.012,hash(cell+vec2(0.,neighborSign.y)+vec2(5.))); - color+=sampleCell(paneUv,yAffine+yTransform*(worldDelta/uPaneSize),strength,yBlurStep)*ySplitWeight; - } - if(diagonalSplitWeight>0.){ - vec2 diagonalBlurStep=cellSize*mix(.006,.012,hash(cell+neighborSign+vec2(5.))); - color+=sampleCell(paneUv,diagonalAffine+diagonalTransform*(worldDelta/uPaneSize),strength,diagonalBlurStep)*diagonalSplitWeight; - } - }else{ - color=sampleCell(paneUv,sampleUv,strength,blurStep); - } - color.a=1.; - vec3 v=normalize(uContentCameraPosition-gh),reflected=reflect(-v,nCurved); float lightT=(uLightPosition.z-gh.z)/safeZ(reflected.z); vec2 lightHit=gh.xy+reflected.xy*lightT; vec2 halfSize=vec2(.32,.42)*min(uPaneSize.x,uPaneSize.y); vec2 windowCoord=abs(lightHit-uLightPosition.xy)/halfSize; vec2 windowMask=1.-smoothstep(vec2(.45),vec2(1.15),windowCoord); float spec=windowMask.x*windowMask.y*step(.0001,reflected.z)*step(0.,lightT); float gloss=spec*clamp(uGlossStrength,0.,1.)*.12*edgeWeight*clamp(uStrength,0.,1.); color.rgb=mix(color.rgb,vec3(1.),gloss); gl_FragColor=color; - #include -} diff --git a/docs/qa-mosaic-improvement/distribution-mosaic.frag b/docs/qa-mosaic-improvement/distribution-mosaic.frag deleted file mode 100644 index bcee012..0000000 --- a/docs/qa-mosaic-improvement/distribution-mosaic.frag +++ /dev/null @@ -1,84 +0,0 @@ -uniform sampler2D uSceneTexture; -uniform mat4 uContentViewProjection,uContentInverseViewProjection; -uniform vec3 uContentCameraPosition,uLightPosition,uBackgroundColor; -uniform float uGlassZ,uGridSize,uStrength,uMosaicStyle,uCurvature,uGlossStrength; -uniform vec2 uViewOffset,uPetSize,uPaneSize; -uniform vec4 uPaneRect; -varying vec2 vUv; -vec2 projectUv(vec3 p){vec4 c=uContentViewProjection*vec4(p,1.);float w=abs(c.w)<.0001?(c.w<0.?-.0001:.0001):c.w;return c.xy/w*.5+.5;} -vec4 sampleScene(vec2 uv){return texture2D(uSceneTexture,clamp(uv,0.,1.));} -vec4 samplePane(vec2 pane){return sampleScene(projectUv(vec3((pane-.5)*uPaneSize,uGlassZ)));} -float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);} -vec2 hash2(vec2 p){return vec2(hash(p),hash(p+vec2(19.19,73.73)));} -float safeZ(float z){return abs(z)<.0001?(z<0.?-.0001:.0001):z;} -vec3 bend(vec3 i,vec3 n){vec3 r=refract(i,n,.75);return length(r)<.0001?i:r;} -float softLimit(float value,float limit){return value*limit/(limit+abs(value));} -void evaluateCell(vec2 cell,vec2 local,vec2 grid,vec2 cellSize,vec2 cellDimensions,float cellWorld,float style,out vec2 affineUv,out mat2 transform,out vec2 curvedSlope,out vec2 facetSlope){ - vec2 random=hash2(cell),widths; - if(style>.5){ - widths=mix(vec2(.82),vec2(1.12),hash2(cell+vec2(11.4,9.8))); - }else{ - float widthSeed=hash(cell+vec2(53.1,27.4)); - if(widthSeed<.3)widths=mix(vec2(.90),vec2(1.08),hash2(cell+vec2(7.2,3.1))); - else if(widthSeed<.9)widths=mix(vec2(.46),vec2(.70),hash2(cell+vec2(7.2,3.1))); - else widths=mix(vec2(1.10),vec2(1.28),hash2(cell+vec2(7.2,3.1))); - } - float angle=(random.x-.5)*.08,c=cos(angle),s=sin(angle); - transform=mat2(widths.x*c,-widths.y*s,widths.x*s,widths.y*c); - vec2 sourceCenter=(cell+.5)/grid+(random-.5)*.16*cellSize; - affineUv=sourceCenter+transform*(local*cellSize); - - // Positive height bulges toward the observer (+Z); negative height is concave. - float curvature=clamp(uCurvature,-1.,1.),excess=max(curvature-.65,0.),surfaceCurvature=curvature-(.25/.35)*excess*excess; - float height=.009*cellWorld*surfaceCurvature*mix(.92,1.08,hash(cell+vec2(41.7,17.3))); - vec2 q=clamp(2.*local,-1.,1.),q2=q*q,q3=q2*q,b=1.-q2*q2; - vec2 skew=(hash2(cell+vec2(23.8,61.2))-.5)*.28;float asym=1.+dot(skew,q); - vec2 dhdq=height*vec2(-4.*q3.x*b.y*asym+b.x*b.y*skew.x,-4.*q3.y*b.x*asym+b.x*b.y*skew.y); - vec2 grad=-2.*dhdq/cellDimensions; - curvedSlope=grad+(random-.5)*.012;facetSlope=(random-.5)*.012; -} -void main(){ - if(uStrength<=.001){gl_FragColor=sampleScene(vUv); - #include - return;} - vec4 f=uContentInverseViewProjection*vec4(vUv*2.-1.,1.,1.);float fw=abs(f.w)<.0001?(f.w<0.?-.0001:.0001):f.w;vec3 farWorld=f.xyz/fw;vec3 i=normalize(farWorld-uContentCameraPosition);float gt=(uGlassZ-uContentCameraPosition.z)/safeZ(i.z);vec3 gh=uContentCameraPosition+i*gt; - vec2 paneUv=gh.xy/uPaneSize+.5;vec2 grid=vec2(uGridSize,max(1.,uGridSize*uPaneSize.y/uPaneSize.x));vec2 gridUv=paneUv*grid,cell=floor(gridUv),local=fract(gridUv)-.5,cellSize=1./grid;float style=clamp(uMosaicStyle,0.,1.),cellWorld=min(uPaneSize.x/grid.x,uPaneSize.y/grid.y); - if(paneUv.x<0.||paneUv.x>1.||paneUv.y<0.||paneUv.y>1.){gl_FragColor=vec4(uBackgroundColor,1.); - #include - return;} - vec2 cellDimensions=uPaneSize/grid; - vec2 affineUv,curvedSlope,facetSlope;mat2 transform; - evaluateCell(cell,local,grid,cellSize,cellDimensions,cellWorld,style,affineUv,transform,curvedSlope,facetSlope); - vec2 edge=.5-abs(local),neighborSign=mix(vec2(-1.),vec2(1.),step(vec2(0.),local)); - vec2 blendAxis=1.-smoothstep(vec2(-.16),vec2(.16),edge); - vec2 weights=blendAxis; - if(weights.x>0.||weights.y>0.){ - vec2 neighborAffine,neighborCurved,neighborFacet;mat2 neighborTransform; - vec2 xWeight=vec2(weights.x*(1.-weights.y),0.); - vec2 yWeight=vec2(0.,(1.-weights.x)*weights.y); - float diagonalWeight=weights.x*weights.y; - float centerWeight=(1.-weights.x)*(1.-weights.y); - affineUv*=centerWeight;transform*=centerWeight;curvedSlope*=centerWeight;facetSlope*=centerWeight; - if(xWeight.x>0.){ - vec2 offset=vec2(neighborSign.x,0.); - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*xWeight.x;transform+=neighborTransform*xWeight.x;curvedSlope+=neighborCurved*xWeight.x;facetSlope+=neighborFacet*xWeight.x; - } - if(yWeight.y>0.){ - vec2 offset=vec2(0.,neighborSign.y); - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*yWeight.y;transform+=neighborTransform*yWeight.y;curvedSlope+=neighborCurved*yWeight.y;facetSlope+=neighborFacet*yWeight.y; - } - if(diagonalWeight>0.){ - vec2 offset=neighborSign; - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*diagonalWeight;transform+=neighborTransform*diagonalWeight;curvedSlope+=neighborCurved*diagonalWeight;facetSlope+=neighborFacet*diagonalWeight; - } - } - vec3 nCurved=normalize(vec3(curvedSlope,1.)),nFacet=normalize(vec3(facetSlope,1.)); - vec3 straightHit=gh+i*(-gh.z/safeZ(i.z));vec3 facetRay=bend(i,nFacet),curvedRay=bend(i,nCurved);vec3 facetHit=gh+facetRay*(-gh.z/safeZ(facetRay.z)),curvedHit=gh+curvedRay*(-gh.z/safeZ(curvedRay.z));vec2 base=facetHit.xy-straightHit.xy,curve=curvedHit.xy-facetHit.xy;vec2 worldDelta=vec2(softLimit(base.x,cellWorld*.08),softLimit(base.y,cellWorld*.08));vec2 d=curve/cellWorld;worldDelta+=vec2(.3*d.x/(.3+abs(d.x)),.3*d.y/(.3+abs(d.y)))*cellWorld; - vec2 sampleUv=affineUv+transform*(worldDelta/uPaneSize); - float edgeDistance=min(min(paneUv.x,paneUv.y),min(1.-paneUv.x,1.-paneUv.y));float edgeWeight=smoothstep(0.,max(cellSize.x,cellSize.y)*.75,edgeDistance);float strength=clamp(uStrength,0.,1.)*edgeWeight;vec2 blurStep=cellSize*mix(.006,.012,hash(cell+vec2(5.)));vec2 centerUv=mix(paneUv,sampleUv,strength);vec4 color=samplePane(centerUv)*.4;color+=samplePane(mix(paneUv,sampleUv+vec2(blurStep.x,0.),strength))*.15;color+=samplePane(mix(paneUv,sampleUv-vec2(blurStep.x,0.),strength))*.15;color+=samplePane(mix(paneUv,sampleUv+vec2(0.,blurStep.y),strength))*.15;color+=samplePane(mix(paneUv,sampleUv-vec2(0.,blurStep.y),strength))*.15;color.a=1.; - vec3 v=normalize(uContentCameraPosition-gh),reflected=reflect(-v,nCurved); float lightT=(uLightPosition.z-gh.z)/safeZ(reflected.z); vec2 lightHit=gh.xy+reflected.xy*lightT; vec2 halfSize=vec2(.32,.42)*min(uPaneSize.x,uPaneSize.y); vec2 windowCoord=abs(lightHit-uLightPosition.xy)/halfSize; vec2 windowMask=1.-smoothstep(vec2(.45),vec2(1.15),windowCoord); float spec=windowMask.x*windowMask.y*step(.0001,reflected.z)*step(0.,lightT); float gloss=spec*clamp(uGlossStrength,0.,1.)*.12*edgeWeight*clamp(uStrength,0.,1.); color.rgb=mix(color.rgb,vec3(1.),gloss); gl_FragColor=color; - #include -} diff --git a/docs/qa-mosaic-improvement/dog1-anisotropic-flat.png b/docs/qa-mosaic-improvement/dog1-anisotropic-flat.png deleted file mode 100644 index 4b387f9..0000000 Binary files a/docs/qa-mosaic-improvement/dog1-anisotropic-flat.png and /dev/null differ diff --git a/docs/qa-mosaic-improvement/dog1-anisotropic.png b/docs/qa-mosaic-improvement/dog1-anisotropic.png deleted file mode 100644 index 9f8e82d..0000000 Binary files a/docs/qa-mosaic-improvement/dog1-anisotropic.png and /dev/null differ diff --git a/docs/qa-mosaic-improvement/dog1-color-boundary-flat.png b/docs/qa-mosaic-improvement/dog1-color-boundary-flat.png deleted file mode 100644 index 7b3714f..0000000 Binary files a/docs/qa-mosaic-improvement/dog1-color-boundary-flat.png and /dev/null differ diff --git a/docs/qa-mosaic-improvement/dog1-color-boundary.png b/docs/qa-mosaic-improvement/dog1-color-boundary.png deleted file mode 100644 index e0f92b2..0000000 Binary files a/docs/qa-mosaic-improvement/dog1-color-boundary.png and /dev/null differ diff --git a/docs/qa-mosaic-improvement/dog1-color-narrow.png b/docs/qa-mosaic-improvement/dog1-color-narrow.png deleted file mode 100644 index 91b77b4..0000000 Binary files a/docs/qa-mosaic-improvement/dog1-color-narrow.png and /dev/null differ diff --git a/docs/qa-mosaic-improvement/dog1-distribution.png b/docs/qa-mosaic-improvement/dog1-distribution.png deleted file mode 100644 index 03fb11e..0000000 Binary files a/docs/qa-mosaic-improvement/dog1-distribution.png and /dev/null differ diff --git a/docs/qa-mosaic-improvement/dog1-final-drag.png b/docs/qa-mosaic-improvement/dog1-final-drag.png deleted file mode 100644 index b413145..0000000 Binary files a/docs/qa-mosaic-improvement/dog1-final-drag.png and /dev/null differ diff --git a/docs/qa-mosaic-improvement/dog1-final-flat.png b/docs/qa-mosaic-improvement/dog1-final-flat.png deleted file mode 100644 index 577f6e3..0000000 Binary files a/docs/qa-mosaic-improvement/dog1-final-flat.png and /dev/null differ diff --git a/docs/qa-mosaic-improvement/dog1-final-pane.png b/docs/qa-mosaic-improvement/dog1-final-pane.png deleted file mode 100644 index 876e22b..0000000 Binary files a/docs/qa-mosaic-improvement/dog1-final-pane.png and /dev/null differ diff --git a/docs/qa-mosaic-improvement/dog1-final.png b/docs/qa-mosaic-improvement/dog1-final.png deleted file mode 100644 index 469a4c4..0000000 Binary files a/docs/qa-mosaic-improvement/dog1-final.png and /dev/null differ diff --git a/docs/qa-mosaic-improvement/dog1-mobile-drag.png b/docs/qa-mosaic-improvement/dog1-mobile-drag.png deleted file mode 100644 index 635ec34..0000000 Binary files a/docs/qa-mosaic-improvement/dog1-mobile-drag.png and /dev/null differ diff --git a/docs/qa-mosaic-improvement/dog1-mobile.png b/docs/qa-mosaic-improvement/dog1-mobile.png deleted file mode 100644 index 91fac55..0000000 Binary files a/docs/qa-mosaic-improvement/dog1-mobile.png and /dev/null differ diff --git a/docs/qa-mosaic-improvement/dog2-final.png b/docs/qa-mosaic-improvement/dog2-final.png deleted file mode 100644 index 1910ddd..0000000 Binary files a/docs/qa-mosaic-improvement/dog2-final.png and /dev/null differ diff --git a/docs/qa-mosaic-improvement/dog3-final.png b/docs/qa-mosaic-improvement/dog3-final.png deleted file mode 100644 index b91f8e8..0000000 Binary files a/docs/qa-mosaic-improvement/dog3-final.png and /dev/null differ diff --git a/docs/qa-mosaic-improvement/dog4-final.png b/docs/qa-mosaic-improvement/dog4-final.png deleted file mode 100644 index 1d62213..0000000 Binary files a/docs/qa-mosaic-improvement/dog4-final.png and /dev/null differ diff --git a/docs/qa-mosaic-improvement/dog4-mobile-drag.png b/docs/qa-mosaic-improvement/dog4-mobile-drag.png deleted file mode 100644 index 5347655..0000000 Binary files a/docs/qa-mosaic-improvement/dog4-mobile-drag.png and /dev/null differ diff --git a/docs/qa-mosaic-improvement/dog4-mobile.png b/docs/qa-mosaic-improvement/dog4-mobile.png deleted file mode 100644 index a4d4b1a..0000000 Binary files a/docs/qa-mosaic-improvement/dog4-mobile.png and /dev/null differ diff --git a/docs/qa-mosaic-improvement/review.md b/docs/qa-mosaic-improvement/review.md deleted file mode 100644 index 15588ec..0000000 --- a/docs/qa-mosaic-improvement/review.md +++ /dev/null @@ -1,65 +0,0 @@ -# Mosaic 개선 실험 결과 - -2026-09-13. 사용자 요청에 따라 원인 분석 후 실제 개선을 수행했다. Astra 설계·독립 검토, Luna 코드 수정, 주 에이전트 브라우저 검증. 사진은 로컬 테스트용이며 외부 게시하지 않았다. - -## 채택 결과 - -최종 C2: 조각 유리의 근원본/확대/축소 기대 비중을 60/30/10에서 30/60/10으로 변경했다. 기존 샘플 폭 범위·중심 이동·퍼짐 반경은 유지한다. 실제 얼굴 영역의 셀 비율은 해시와 구도에 따라 다르다. - -유리 법선은 기존 .16셀 폭으로 연결한다. 조각 유리의 RGB는 각 셀의 독립 affine/transform에 공통 굴절 변위를 적용해 기존 5탭으로 샘플한 뒤 .06셀 폭에서 색으로 연결한다. .06~.16 띠에서도 독립 중심 셀 샘플을 유지해 혼합 UV의 압축이 재도입되지 않게 했다. 촘촘 유리는 기존 UV 경로를 사용한다. - -공유 법선, 굴곡 기본+.65, 굴곡0의 기울기/샘플 변환, 광택 후처리1회, 기존2-pass 및 수작업 Depth 경로를 유지했다. Distortion<=.001의 raw RenderTarget 우회도 유지한다. - -## 고정 비교 조건과 후보 - -1280×720, dog1, 확대2.3 / X-.10 / Y-.30, 조각 유리 Grid8 / Distortion.90, 시점 중앙. A/B/C/C2 비교는 광택0, 굴곡+.65. 평탄0 캡처는 별도 진단이며 동일 굴곡 비교와 구분한다. final 캡처는 광택.15로 복원했다. - -| 후보 | 변경 | 실제 관찰 | 결정 | -|---|---|---|---| -| 원본 | baseline-mosaic.frag | 기존 QA의 원본에 가까운 넓은 영역, 물결 인상 | 원본 보존 | -| A | 비중만30/60/10 | 확대면 증가, 입 왼쪽 수평 압축선 부각 | 단독 미채택 | -| B | A의 확대 셀 면적을 유지하며 축비율2:1/1:2 | 오른눈 세로 늘어짐·코 비대칭 증가 | 제외 | -| C | A + .16폭 완전 색 혼합 | 입 왼쪽 압축선 감소, 넓은 중첩/흐림으로 사각면 약화 | 단독 미채택 | -| C2 | C의 색 혼합만.06, 법선.16 유지 | C보다 사각면 명확, A보다 입 압축선 감소, 눈·코·혀 식별 유지 | 채택 | - -원본 비교는 기존 docs/qa-five-photos/dog1-tuned.png와 docs/qa-followup/dog1-flat.png를 참고했다. 이번 A/B/C/C2는 같은 브라우저에서 새로 캡처했다. 이전 캡처와 이번 캡처는 저장 경로·인코딩이 달라 픽셀 단위 유사도 평가를 하지 않았다. - -## 사진별 최종 검증 - -| 사진 | 확대 / X / Y | Grid / Distortion / 굴곡 / 광택 | 관찰 | -|---|---|---|---| -| sample | 3 / -.15 / -.35 | 8 / .90 / +.65 / .15 | 사각 얼굴 조각 증가, 두눈·코·입 식별. 눈/입 경계 잘림은 남음 | -| dog1 | 2.3 / -.10 / -.30 | 8 / .90 / +.65 / .15 | 가장 안정적인 비교. 확대면·사각 경계 개선, 코·혀 약한 중첩 잔존 | -| dog2 | 2.2 / +.60 / -.60 | 8 / .90 / +.65 / .15 | 볼/귀/배경 조각 차이 증가. 어두운 눈 주변 구분은 여전히 제한적 | -| dog3 | 1.3 / +.50 / 0 | 12 / .75 / +.65 / .15 | 두 얼굴 식별 유지. 작은 얼굴과 배경 세부의 한계 | -| dog4 | 1.55 / +.10 / -.85 | 12 / .65 / +.35 / .15 | 눈·코·입 식별, 사각 윤곽 증가. 측면 코의 조각 잘림 남음 | - -사진 전환은 위 값을 자동 적용하지 않는다. 기존과 같이 수동 적용했다. 추가4장은 Depth 없는 평면 입력이다. - -## 실행한 검증 - -- 모든 후보 및 최종 C2의 npm run build (tsc -b && vite build) 통과. 셰이더 실제 컴파일/화면은 브라우저에서 별도로 확인했다. -- 실제 브라우저 1280×720: 5장 위 설정으로 렌더링·사진 전환 확인. -- 390×844: dog1/dog4 동일 설정, 두 사진의 수평 드래그에서 창틀/셀 정렬과 표정 확인. 데스크톱 dog1 수평 드래그도 확인. 전체 드래그 경로에 대한 프레임 단위 분석은 하지 않았다. -- Glass OFF에서 기존 sample 기본 구도2.4/-.10/-.35 parallax 재확인: cameraX0→.063 관측 시 nose projectedX531.509→529.658, body350.477→350.490. 위치 변화가 부위마다 다름. Depth는 수작업 근사이며 AI 추정/측정값이 아니다. -- 촘촘 유리 Grid28/.85, Reeded, Frosted 실제 렌더링을 확인했다. 수치적 이전버전 동일성 비교나 영상 전체 회귀로 해석하지 않는다. -- Distortion0에서 기존 창틀 밖 raw 출력 유지 확인. -- QA 브라우저 error 로그0. -- Astra 최종 정적 검토: 가중치 분리·이웃좌표 초기화·셀별 퍼짐·법선 공유에 즉시 수정할 결함 없음. - -## 성능과 남은 한계 - -조각 경계의 텍스처 샘플은 활성셀당5탭, 최악20탭이다. .06 색 혼합에서 완전한 정사각 셀을 가정한 이론 평균은 약6.27탭으로 기존5보다 증가한다. GPU의 분기실행·캐시·해상도가 영향을 주므로 실제 실행시간/FPS로 환산하지 않았다. 실제 휴대폰 성능·자이로·영상·일반 업로드·수동 Depth 업로드 전체 회귀는 미검증이다. - -레퍼런스2 달성으로 판정하지 않는다. 셀별 큰 정보량 대비는 여전히 부족하고, 검은 눈·코·혀 및 측면 얼굴의 경계 잘림/중첩이 남는다. 12셀 정량 분류 등 앞서 제안한 모든 평가표를 실행한 것은 아니며 이번 채택은 고정 구도의 수동 시각 비교에 따른 증분 개선이다. 다음 개선은 한 축 확대를 다시 강하게 하기보다 얼굴을 가로지르는 셀의 위치 제어 또는 낮은 정보량 셀의 제한적 퍼짐을 개별 실험하는 방향이다. - -## 파일과 재현 - -- 제품 수정: src/shaders/mosaic.frag 한 파일. -- 원본/후보: baseline-mosaic.frag, distribution-mosaic.frag, anisotropic-mosaic.frag, color-boundary-mosaic.frag. -- 비교 이미지: dog1-distribution.png, dog1-anisotropic.png, dog1-color-boundary.png, dog1-color-narrow.png, dog1-final.png 및 각 평탄 이미지. -- 회귀 이미지: sample-final.png, dog2-final.png, dog3-final.png, dog4-final.png, dog1/dog4-mobile*.png, sample-noglass*.png, sample-compact.png, sample-reeded.png, sample-frosted.png, sample-strength0.png. -- 실행: npm run dev -- --host 127.0.0.1, http://127.0.0.1:5173/. 프로젝트 실행 중인 서버에서도 변경 반영됨. - -## 후속 수정 -사용자의 dog3 공통 설정(Grid8/.90, 구도1/0/0) 제보로 인접 셀 얼굴 단절이 확인되었다. 이 문서의 C2 채택만으로 해당 조건을 통과한 것은 아니다. 후속 보정과 확대 효과 감소의 절충은 ../qa-cell-continuity/review.md를 따른다. diff --git a/docs/qa-mosaic-improvement/sample-compact.png b/docs/qa-mosaic-improvement/sample-compact.png deleted file mode 100644 index da444b1..0000000 Binary files a/docs/qa-mosaic-improvement/sample-compact.png and /dev/null differ diff --git a/docs/qa-mosaic-improvement/sample-final.png b/docs/qa-mosaic-improvement/sample-final.png deleted file mode 100644 index c7a5581..0000000 Binary files a/docs/qa-mosaic-improvement/sample-final.png and /dev/null differ diff --git a/docs/qa-mosaic-improvement/sample-frosted.png b/docs/qa-mosaic-improvement/sample-frosted.png deleted file mode 100644 index 28948af..0000000 Binary files a/docs/qa-mosaic-improvement/sample-frosted.png and /dev/null differ diff --git a/docs/qa-mosaic-improvement/sample-noglass-drag.png b/docs/qa-mosaic-improvement/sample-noglass-drag.png deleted file mode 100644 index bb61795..0000000 Binary files a/docs/qa-mosaic-improvement/sample-noglass-drag.png and /dev/null differ diff --git a/docs/qa-mosaic-improvement/sample-noglass.png b/docs/qa-mosaic-improvement/sample-noglass.png deleted file mode 100644 index 6ee4580..0000000 Binary files a/docs/qa-mosaic-improvement/sample-noglass.png and /dev/null differ diff --git a/docs/qa-mosaic-improvement/sample-reeded.png b/docs/qa-mosaic-improvement/sample-reeded.png deleted file mode 100644 index bbd6496..0000000 Binary files a/docs/qa-mosaic-improvement/sample-reeded.png and /dev/null differ diff --git a/docs/qa-mosaic-improvement/sample-strength0.png b/docs/qa-mosaic-improvement/sample-strength0.png deleted file mode 100644 index ad29e1a..0000000 Binary files a/docs/qa-mosaic-improvement/sample-strength0.png and /dev/null differ diff --git a/docs/qa-photo-glass-distance-2026-10-06/ai-framing-evidence.json b/docs/qa-photo-glass-distance-2026-10-06/ai-framing-evidence.json deleted file mode 100644 index 01a5fcb..0000000 --- a/docs/qa-photo-glass-distance-2026-10-06/ai-framing-evidence.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "curvature": "1", - "grid-size": "20", - "photo-glass-distance": "50", - "photo-pan-x": "-0.2", - "photo-pan-y": "0.25", - "photo-zoom": "1.4" -} \ No newline at end of file diff --git a/docs/qa-photo-glass-distance-2026-10-06/dog1-far-pane.png b/docs/qa-photo-glass-distance-2026-10-06/dog1-far-pane.png deleted file mode 100644 index fb5da75..0000000 Binary files a/docs/qa-photo-glass-distance-2026-10-06/dog1-far-pane.png and /dev/null differ diff --git a/docs/qa-photo-glass-distance-2026-10-06/dog1-far.png b/docs/qa-photo-glass-distance-2026-10-06/dog1-far.png deleted file mode 100644 index 2424d9c..0000000 Binary files a/docs/qa-photo-glass-distance-2026-10-06/dog1-far.png and /dev/null differ diff --git a/docs/qa-photo-glass-distance-2026-10-06/dog1-mid.png b/docs/qa-photo-glass-distance-2026-10-06/dog1-mid.png deleted file mode 100644 index 3fcd2a1..0000000 Binary files a/docs/qa-photo-glass-distance-2026-10-06/dog1-mid.png and /dev/null differ diff --git a/docs/qa-photo-glass-distance-2026-10-06/dog1-near-pane.png b/docs/qa-photo-glass-distance-2026-10-06/dog1-near-pane.png deleted file mode 100644 index 7227a04..0000000 Binary files a/docs/qa-photo-glass-distance-2026-10-06/dog1-near-pane.png and /dev/null differ diff --git a/docs/qa-photo-glass-distance-2026-10-06/dog1-near.png b/docs/qa-photo-glass-distance-2026-10-06/dog1-near.png deleted file mode 100644 index 6a17aad..0000000 Binary files a/docs/qa-photo-glass-distance-2026-10-06/dog1-near.png and /dev/null differ diff --git a/docs/qa-photo-glass-distance-2026-10-06/mobile-distance-control.png b/docs/qa-photo-glass-distance-2026-10-06/mobile-distance-control.png deleted file mode 100644 index ad181c6..0000000 Binary files a/docs/qa-photo-glass-distance-2026-10-06/mobile-distance-control.png and /dev/null differ diff --git a/docs/qa-photo-glass-distance-2026-10-06/report.md b/docs/qa-photo-glass-distance-2026-10-06/report.md deleted file mode 100644 index cead129..0000000 --- a/docs/qa-photo-glass-distance-2026-10-06/report.md +++ /dev/null @@ -1,50 +0,0 @@ -# 사진–유리 거리 조절 - -2026-10-06 사용자 요청: 고방유리 표면과 시점에 더해, 뒤 사진과 유리 사이 거리를 조절한다. 사진의 가장 앞쪽 표면을 기준으로 하며 사진의 확대·팬 값은 유지한다. - -## 구현 - -- `index.html`: 주요 조절에 `사진–유리 거리` 슬라이더를 추가했다. 범위 0–100%, 기본값 0%. 실측 cm/m가 아닌 상대 조절값이다. -- `src/constants/glass.ts`: `PHOTO_GLASS_DISTANCE`에 장면 간격 최소 0.04 / 최대 0.60을 정의했다. 0%는 기존 근접 배치와 같다. -- `src/main.ts`: 고정 간격을 상태 `photoGlassGap`으로 교체했다. 기존 `contentBaseZ()`와 `applyFraming()`을 재사용해 `baseZ = glassZ - gap - (maxDepth - depthBias) * depthScale`로 배치한다. RGB 평면과 Depth mesh에 같은 위치·스케일을 적용하고, `uSourceZ` 및 `WindowReveal`도 함께 갱신한다. 기존 원근 크기 보정을 재사용하며 사진 확대·팬 값을 바꾸지 않는다. 유리 위치·Grid·표면 법선·광택·시점 설정도 바꾸지 않는다. -- 사진 교체와 AI depth 완료는 설정된 간격을 사용해 다시 배치한다. 사진 구도 초기화와 시점 초기화는 거리 조절을 초기화하지 않는다. -- 기존 region/history 시그니처에 물체 배치가 이미 포함되어 있어 추가 초기화 경로를 만들지 않았다. 광학 셰이더와 새 의존성도 추가하지 않았다. -- `scripts/test-window-reveal-coverage.mjs`: 기존 프레임 가림 검사를 거리 양 끝값으로 확장했다. - -## 실제 화면 검증 - -Windows Codex in-app browser에서 먼저 수작업 샘플을 No Glass로 확인한 후 Final을 비교했다. 샘플 depth는 수작업 테스트이며 AI 추정 또는 실측값이 아니다. - -| 거리 | 앞쪽 간격 | 기준 평면 Z | 가장 앞쪽 Z | -| --- | --- | --- | --- | -| 0% | 0.040 | 0.315 | 0.560 | -| 50% | 0.320 | 0.035 | 0.280 | -| 100% | 0.600 | −0.245 | 0.000 | - -유리 Z는 0.600, 위 표의 Depth Scale은 0.25다. 가장 앞쪽 Z와 기준 평면 Z가 함께 감소하고 표면 간 상대 깊이는 유지된다. 거리를 늘려도 정면 사진 크기는 기존 원근 보정으로 거의 유지된다. Depth가 있는 앞쪽 표면의 투영은 거리 변경에 따라 소폭 달라질 수 있다. - -- No Glass의 100%에서 Camera X 0→약 0.052로 드래그했다. 코 투영 X 520.100→520.088, 왼눈 493.698→494.076, 몸 453.812→454.658px로 깊이에 따른 서로 다른 시차가 남는다. -- 100% / Depth Scale 0.4: 앞쪽 Z 0.000 / 간격 0.600. 0% / Depth Scale 0: 전체 표면 Z 0.560 / 간격 0.040. 유리 관통 없음. -- 샘플과 dog1의 같은 사진·구도·Grid 20 / 굴곡 +1 / 광택 0.3에서 0%와 100%를 비교했다. 먼 배치에서 사진 조각의 굴절 이동과 반복이 더 커진다. dog1의 50%도 저장했다. -- 거리 50% / 확대 1.4 / 가로 팬 −0.2 / 세로 팬 0.25에서 dog1로 사진을 교체하고 자동 AI depth 완료를 기다렸다. 네 값과 Grid 20 / 굴곡 +1이 모두 유지됐다. 이후 테스트용 수동 구도만 1/0/0으로 복귀했다. -- 1280×900 데스크톱과 390×844 모바일에서 조작·출력을 확인했다. 모바일 document.scrollWidth 375px ≤ innerWidth 390px. 거리 50%와 구도 1/0/0 유지. -- 브라우저 console error 없음. 새 거리 기능에 셰이더를 수정하지 않았다. 기존 광학/visible-depth 근사와 ANGLE 경고의 한계는 이전 보고서와 같다. - -수치 기록: `sample-depth-evidence.json`, `ai-framing-evidence.json`. 화면 기록: `sample-noglass-near.png`, `sample-noglass-far.png`, `sample-final-near.png`, `sample-final-far.png`, `dog1-near.png`, `dog1-far.png`, `dog1-mid.png`, `mobile-distance-control.png`. - -## 자동 검사 - -- `npm.cmd run build -- --outDir test-results/photo-glass-distance-build`: TypeScript + Vite 빌드 통과. 기존 큰 번들 경고는 유지. 검증용 빌드 출력은 제거했다. -- `node --experimental-strip-types scripts/test-window-reveal-coverage.mjs`: 2종 종횡비 × 3종 Depth Scale × 2종 거리 × 17종 시점 × 49개 aperture 샘플에서 프레임 안쪽 기하 가림 통과. geometry 재사용·dispose도 통과했다. -- 기존 depth-refraction, camera-history 검사 통과. -- `git diff --check` 통과. - -## 사용과 한계 - -주 화면에서 `사진–유리 거리`를 조절한다. 초기 0%는 가까운 기존 배치이고, 검증 후 미리보기는 차이를 보기 쉽게 50%에 두었다. 실행은 프로젝트 루트에서 `npm.cmd run dev -- --host 127.0.0.1 --port 5174`, 미리보기는 `http://127.0.0.1:5174/`다. - -Depth는 상대 깊이이며, 간격의 기준점이 얼굴이나 코라는 의미적 보장은 없다. 가장 앞쪽 부분이 앞발이나 다른 물체일 수 있다. 큰 거리에서는 굴절이 강해져 반복과 프레임 안쪽의 어두운 영역이 더 보일 수 있다. 현재 RenderTarget에서 가려진 장면이나 화면 밖 영역을 새로 복원하지 않는다. 실물 광학의 정밀 시뮬레이션, 모바일 실기기 FPS 또는 영상 flicker 계측은 수행하지 않았다. - -| 0% 가까움 | 100% 멀어짐 | -| --- | --- | -| ![가까운 배치](dog1-near-pane.png) | ![먼 배치](dog1-far-pane.png) | diff --git a/docs/qa-photo-glass-distance-2026-10-06/sample-depth-evidence.json b/docs/qa-photo-glass-distance-2026-10-06/sample-depth-evidence.json deleted file mode 100644 index 65a631a..0000000 --- a/docs/qa-photo-glass-distance-2026-10-06/sample-depth-evidence.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "near": "cameraX=0.000 sample=sample\ncontentBaseZ=0.315 maxFrontZ=0.560 glassGap=0.040\nnose: depth=0.980 worldZ=0.560 projectedX=520.448px\nleft-eye: depth=0.678 worldZ=0.485 projectedX=493.625px\nright-eye: depth=0.678 worldZ=0.485 projectedX=529.752px\nface: depth=0.600 worldZ=0.465 projectedX=509.841px\nleft-ear: depth=0.431 worldZ=0.423 projectedX=466.121px\nright-ear: depth=0.431 worldZ=0.423 projectedX=538.027px\nbody: depth=0.298 worldZ=0.389 projectedX=453.585px", - "far": "cameraX=0.000 sample=sample\ncontentBaseZ=-0.245 maxFrontZ=0.000 glassGap=0.600\nnose: depth=0.980 worldZ=0.000 projectedX=520.100px\nleft-eye: depth=0.678 worldZ=-0.075 projectedX=493.698px\nright-eye: depth=0.678 worldZ=-0.075 projectedX=529.410px\nface: depth=0.600 worldZ=-0.095 projectedX=509.741px\nleft-ear: depth=0.431 worldZ=-0.137 projectedX=466.364px\nright-ear: depth=0.431 worldZ=-0.137 projectedX=537.754px\nbody: depth=0.298 worldZ=-0.171 projectedX=453.812px", - "farDrag": "cameraX=0.052 sample=sample\ncontentBaseZ=-0.245 maxFrontZ=0.000 glassGap=0.600\nnose: depth=0.980 worldZ=0.000 projectedX=520.088px\nleft-eye: depth=0.678 worldZ=-0.075 projectedX=494.076px\nright-eye: depth=0.678 worldZ=-0.075 projectedX=529.757px\nface: depth=0.600 worldZ=-0.095 projectedX=510.191px\nleft-ear: depth=0.431 worldZ=-0.137 projectedX=467.107px\nright-ear: depth=0.431 worldZ=-0.137 projectedX=538.366px\nbody: depth=0.298 worldZ=-0.171 projectedX=454.658px", - "farDepth04": "cameraX=0.000 sample=sample\ncontentBaseZ=-0.392 maxFrontZ=0.000 glassGap=0.600\nnose: depth=0.980 worldZ=0.000 projectedX=521.011px\nleft-eye: depth=0.678 worldZ=-0.121 projectedX=493.508px\nright-eye: depth=0.678 worldZ=-0.121 projectedX=530.296px\nface: depth=0.600 worldZ=-0.152 projectedX=509.998px\nleft-ear: depth=0.431 worldZ=-0.220 projectedX=465.739px\nright-ear: depth=0.431 worldZ=-0.220 projectedX=538.456px\nbody: depth=0.298 worldZ=-0.273 projectedX=453.229px", - "nearDepth0": "cameraX=0.000 sample=sample\ncontentBaseZ=0.560 maxFrontZ=0.560 glassGap=0.040\nnose: depth=0.980 worldZ=0.560 projectedX=518.582px\nleft-eye: depth=0.678 worldZ=0.560 projectedX=494.027px\nright-eye: depth=0.678 worldZ=0.560 projectedX=527.873px\nface: depth=0.600 worldZ=0.560 projectedX=509.291px\nleft-ear: depth=0.431 worldZ=0.560 projectedX=467.482px\nright-ear: depth=0.431 worldZ=0.560 projectedX=536.500px\nbody: depth=0.298 worldZ=0.560 projectedX=454.873px", - "mid": "cameraX=0.000 sample=sample\ncontentBaseZ=0.035 maxFrontZ=0.280 glassGap=0.320\nnose: depth=0.980 worldZ=0.280 projectedX=520.256px\nleft-eye: depth=0.678 worldZ=0.205 projectedX=493.665px\nright-eye: depth=0.678 worldZ=0.205 projectedX=529.564px\nface: depth=0.600 worldZ=0.185 projectedX=509.786px\nleft-ear: depth=0.431 worldZ=0.143 projectedX=466.255px\nright-ear: depth=0.431 worldZ=0.143 projectedX=537.877px\nbody: depth=0.298 worldZ=0.109 projectedX=453.710px" -} \ No newline at end of file diff --git a/docs/qa-photo-glass-distance-2026-10-06/sample-final-far.png b/docs/qa-photo-glass-distance-2026-10-06/sample-final-far.png deleted file mode 100644 index 684e712..0000000 Binary files a/docs/qa-photo-glass-distance-2026-10-06/sample-final-far.png and /dev/null differ diff --git a/docs/qa-photo-glass-distance-2026-10-06/sample-final-near.png b/docs/qa-photo-glass-distance-2026-10-06/sample-final-near.png deleted file mode 100644 index bf3e1cd..0000000 Binary files a/docs/qa-photo-glass-distance-2026-10-06/sample-final-near.png and /dev/null differ diff --git a/docs/qa-photo-glass-distance-2026-10-06/sample-noglass-far.png b/docs/qa-photo-glass-distance-2026-10-06/sample-noglass-far.png deleted file mode 100644 index f90ca99..0000000 Binary files a/docs/qa-photo-glass-distance-2026-10-06/sample-noglass-far.png and /dev/null differ diff --git a/docs/qa-photo-glass-distance-2026-10-06/sample-noglass-near.png b/docs/qa-photo-glass-distance-2026-10-06/sample-noglass-near.png deleted file mode 100644 index a905540..0000000 Binary files a/docs/qa-photo-glass-distance-2026-10-06/sample-noglass-near.png and /dev/null differ diff --git a/docs/qa-recheck/dog2-ai-drag.png b/docs/qa-recheck/dog2-ai-drag.png deleted file mode 100644 index 5af00a7..0000000 Binary files a/docs/qa-recheck/dog2-ai-drag.png and /dev/null differ diff --git a/docs/qa-recheck/dog2-ai-neutral.png b/docs/qa-recheck/dog2-ai-neutral.png deleted file mode 100644 index a79fbfb..0000000 Binary files a/docs/qa-recheck/dog2-ai-neutral.png and /dev/null differ diff --git a/docs/qa-recheck/dog2-ai-noglass.png b/docs/qa-recheck/dog2-ai-noglass.png deleted file mode 100644 index 62afbfb..0000000 Binary files a/docs/qa-recheck/dog2-ai-noglass.png and /dev/null differ diff --git a/docs/qa-recheck/dog2-face-gloss0.png b/docs/qa-recheck/dog2-face-gloss0.png deleted file mode 100644 index 5d46d01..0000000 Binary files a/docs/qa-recheck/dog2-face-gloss0.png and /dev/null differ diff --git a/docs/qa-recheck/dog2-face-neutral.png b/docs/qa-recheck/dog2-face-neutral.png deleted file mode 100644 index 14bba7b..0000000 Binary files a/docs/qa-recheck/dog2-face-neutral.png and /dev/null differ diff --git a/docs/qa-recheck/dog2-face-noglass.png b/docs/qa-recheck/dog2-face-noglass.png deleted file mode 100644 index bb2b110..0000000 Binary files a/docs/qa-recheck/dog2-face-noglass.png and /dev/null differ diff --git a/docs/qa-recheck/dog2-flat-drag.png b/docs/qa-recheck/dog2-flat-drag.png deleted file mode 100644 index 2d7d8ff..0000000 Binary files a/docs/qa-recheck/dog2-flat-drag.png and /dev/null differ diff --git a/docs/qa-recheck/dog2-flat-neutral.png b/docs/qa-recheck/dog2-flat-neutral.png deleted file mode 100644 index 20fc9dd..0000000 Binary files a/docs/qa-recheck/dog2-flat-neutral.png and /dev/null differ diff --git a/docs/qa-recheck/dog2-sharp-face.png b/docs/qa-recheck/dog2-sharp-face.png deleted file mode 100644 index 039a097..0000000 Binary files a/docs/qa-recheck/dog2-sharp-face.png and /dev/null differ diff --git a/docs/qa-recheck/dog2-sharp-full.png b/docs/qa-recheck/dog2-sharp-full.png deleted file mode 100644 index 3c39798..0000000 Binary files a/docs/qa-recheck/dog2-sharp-full.png and /dev/null differ diff --git a/docs/qa-recheck/review.md b/docs/qa-recheck/review.md deleted file mode 100644 index b2649ad..0000000 --- a/docs/qa-recheck/review.md +++ /dev/null @@ -1,41 +0,0 @@ -# Ref2 기준 재QA · 2026-09-14 - -## 판정 - -**시각 목표 미달.** 이전 빌드·기능 검증 통과는 유지되지만, 눈·코 식별과 레퍼런스 유사성에 대한 이전 합격 판단은 이번 결과로 정정한다. - -## 재현 조건 - -- 사용자 첨부의 원본 사진은 로컬 `public/assets/qa/dog2.jpeg`와 일치한다. -- 로컬 배포 미리보기 5175, Chrome, 1280×1000. 기본 조각 유리: Grid 10, Distortion .90, 굴곡 .65, 광택 .30. -- 원본 전체 구도에서 평면 depth와 실제 AI depth를 각각 확인. 정면/드래그 출력을 캡처했다. -- 별도로 사진 확대2.2, 가로 .4, 세로 -.4로 얼굴 구도를 만들고 Final / 광택0 / No Glass를 비교했다. 사용자 첨부의 정확한 설정값과 시점은 제공되지 않았으므로 픽셀 단위 동일 재현은 아니다. -- 테스트 페이지의 UI만 조절했고 앱 소스와 셰이더를 변경하지 않았다. - -## 발견 사항 - -1. **눈·코 조각 식별 실패 — 높음.** 전체 구도에서 검은 얼굴 띠와 작은 밝은 점이 주로 남는다. 얼굴을 확대해도 개별 눈·코 윤곽이 충분히 회복되지 않는다. Ref2의 확대된 눈·코 조각과 차이가 크다. -2. **정보 손실 방식 부적합 — 높음.** 셀마다 선명한 특징 조각과 정보가 적은 면이 공존해야 하나, 현재는 얼굴·가슴·바닥이 넓은 흐릿한 패치로 보이는 비중이 크다. 확대 구도의 주둥이에 줄무늬/겹침 인상도 있다. -3. **프레임 안쪽 빈 띠 — 높음.** 사용자 첨부의 왼쪽과 하단에 어두운 불규칙 틈이 보인다. 로컬 드래그에서도 왼쪽 빈 띠가 평면/AI depth 모두에서 나타났다. AI depth만의 문제로 볼 수 없다. 사용자 첨부만큼 큰 틈을 동일 설정으로 재현한 것은 아니다. -4. **비교 구도 통제 부족.** Ref2는 얼굴 확대인데 사용자 결과는 전신이다. 이전의 흰 강아지 샘플 한 장 중심 판단으로 다른 사진의 실패를 놓쳤다. 얼굴 확대 후에도 실패가 남아 구도만 고쳐서는 해결되지 않는다. - -## 코드와 연결한 원인 가설 - -- 대부분 셀의 샘플 폭은 .28–.48배인데 흐림 간격 .055–.13셀은 축소된 샘플 폭과 무관하다. 확대 셀의 정보까지 과하게 평균화할 수 있다. 9개 떨어진 샘플의 혼합이 줄무늬·겹침 인상에 기여하는지는 별도 분리 실험이 필요하다. -- 샘플 제한은 RenderTarget 전체 UV에만 걸려 있다. 사진이 실제로 채우는 영역 밖의 배경을 읽는 경우를 막지 못한다. 사진/유리의 깊이 차이와 카메라 이동, 셀별 샘플 이동의 영향을 분리해야 한다. -- AI depth를 켜도 셀 내부 정보 소실은 해결되지 않는다. 이번 원인은 모델 교체보다 유리 샘플링 설계에서 우선 찾아야 한다. - -## 다음 수정 순서와 합격 기준 - -1. 같은 사진·얼굴 크기·정면으로 고정하고 흐림과 확대 효과를 각각 분리 비교한다. 선명한 눈·코 윤곽이 남는 셀과 저정보 셀이 공존하도록 샘플 범위에 맞춰 흐림을 조정한다. -2. 프레임 내 유효 사진 영역을 검증하고 좌우 드래그 시 빈 띠가 나타나지 않도록 처리한다. 전체 UV clamp만으로 해결됐다고 판단하지 않는다. -3. 흰 강아지와 검정·갈색 강아지 모두에서 눈 두 개와 코의 개별 식별을 확인한다. 광택0에서도 굴곡을 유지하고 Distortion0 원본 경로도 확인한다. -4. Ref1/Ref2 비교 배치를 유지한다. 모델 추론 성공이나 셰이더 컴파일 성공을 시각 합격과 분리한다. - -증거: `dog2-flat-neutral.png`, `dog2-flat-drag.png`, `dog2-face-neutral.png`, `dog2-face-gloss0.png`, `dog2-face-noglass.png`, `dog2-ai-noglass.png`, `dog2-ai-neutral.png`, `dog2-ai-drag.png`. - -## 후속 보정: 과도한 흐림 축소 - -사용자가 흐림으로 유리 느낌이 사라진다고 재지적하여 조각 유리의 필터만 수정했다. `src/shaders/mosaic.frag`에서 퍼짐 간격을 .055–.13셀에서 .006–.018셀로 줄이고, 9개 샘플 평균을 중심 .6 + 상하좌우 각 .1의 5개 샘플로 변경했다. 셀별 확대·중심 이동·곡면과 촘촘 유리는 유지했다. - -빌드/타입 검사 통과. 동일한 dog2 전체/확대 구도와 흰 강아지 샘플에서 브라우저 페이지 오류 없이 렌더링했다. `dog2-sharp-face.png`에서 이전보다 수염·코·눈 주변의 세부가 살아나는 것을 확인했다. `dog2-sharp-full.png`, `sample-sharp.png`도 확인했다. 작은 얼굴에서 눈이 셀 경계에 걸리는 문제와 드래그 시 가장자리 빈 띠까지 해결한 변경은 아니며 전체 Ref2 시각 QA 합격으로 판정하지 않는다. diff --git a/docs/qa-recheck/sample-sharp.png b/docs/qa-recheck/sample-sharp.png deleted file mode 100644 index 6b7f2c4..0000000 Binary files a/docs/qa-recheck/sample-sharp.png and /dev/null differ diff --git a/docs/qa-reference-comparison/desktop-reference2.png b/docs/qa-reference-comparison/desktop-reference2.png deleted file mode 100644 index 0447ce5..0000000 Binary files a/docs/qa-reference-comparison/desktop-reference2.png and /dev/null differ diff --git a/docs/qa-reference-comparison/mobile-reference2.png b/docs/qa-reference-comparison/mobile-reference2.png deleted file mode 100644 index db26c3f..0000000 Binary files a/docs/qa-reference-comparison/mobile-reference2.png and /dev/null differ diff --git a/docs/qa-reference-comparison/review.md b/docs/qa-reference-comparison/review.md deleted file mode 100644 index f090c69..0000000 --- a/docs/qa-reference-comparison/review.md +++ /dev/null @@ -1,43 +0,0 @@ -# 거리와 선명도 점검 / 레퍼런스 비교 도구 - -2026-09-14. 사용자 요청: 레퍼런스의 거리감에 따른 해상도 저하를 점검하고 디버그 테스트 위에 레퍼런스 2장을 놓고 비교할 수 있게 한다. Astra 분석·검토, Luna UI 구현. 이번 광학 셰이더는 변경하지 않는다. - -## 점검 결과 - -현재 거리 연동 선명도 저하 모델은 없다. Mosaic의 퍼짐은 strength × cellSize × hash(.006~.012)이며 카메라 거리나 사진 부위별 Depth를 입력받지 않는다. 사진 확대는 XY scale이므로 거리 조절이 아니다. 카메라는 Z3에서 XY 이동하며 유리는 Z.6에 있다. 굴절 계산의 교점은 Z0 평면을 사용한다. - -RenderTarget은 화면 크기와 DPR(상한1.5)에 따라 해상도가 정해진다. depthBuffer:true는 가림 처리에 쓰이지만 Glass가 샘플하는 depthTexture는 생성하지 않는다. 기존 sample의 수작업 Depth는 정점 Z와 parallax에 반영되지만 부위별 퍼짐에는 연결되지 않는다. 추가4장은 Depth 없는 평면이다. - -‘픽셀 수가 줄어드는 해상도 저하’, ‘유리/렌즈가 넓은 영역을 섞는 선명도 저하’, ‘셀의 확대에 따라 원본 정보가 크게 늘어나는 현상’을 분리해 평가해야 한다. - -레퍼런스1은 창틀 세부와 평탄한 동물 셀이 공존하고 레퍼런스2는 눈·코 윤곽과 큰 저정보량 면이 공존한다. 레퍼런스2의 창틀도 부드러워 원본 화질·촬영 초점·압축의 영향을 배제할 수 없다. 이미지 두 장만으로 유리/카메라/피사체의 실제 거리와 촬영 조건을 역산하거나 흐림 원인을 확정하지 않는다. - -## 다음 광학 실험 (아직 구현/실행하지 않음) - -1. 같은 사진·구도·Grid·.12변위제한·광택0·viewport/DPR에서 기존 퍼짐과 반경2배를 비교한다. 셀 중심과 배율은 유지해 순수 선명도 변화만 확인한다. -2. 유망하면 카메라·구도·렌더해상도를 고정하고 ‘유리-사진 평균 간격’에 퍼짐을 연동하는 평면 근사를 실험한다. 미세한 각도 분산에 의해 소스 영역이 넓어진다는 모델링 가정이며 실제 측정거리나 AI 추정으로 표시하지 않는다. -3. 기존샘플의 부위별 효과는 정렬된 Depth 또는 RT depthTexture에서 선형 거리를 복원한 뒤 검토한다. 추가4장은 단일평면 간격을 적용한다. - -전체 RenderTarget 해상도를 낮추거나 5탭 반경을 무작정 크게 늘리면 창틀까지 흐리거나 복제 윤곽/십자형 잔상이 생길 수 있으므로 첫 해법으로 채택하지 않는다. 통과 기준은 눈·코 식별, 주변 셀 정보량 감소, 기존 얼굴 단절 재발 없음, 광택0·드래그·모바일에서도 유지되는지다. - -촬영 초점 흐림은 단순 카메라 거리 증가와 같지 않다. 설정한 초점면과의 차이 및 조리개 등의 영향을 받는다. 1차 자료: https://www.edmundoptics.com/knowledge-center/application-notes/imaging/depth-of-field-and-depth-of-focus/ -Patterned glass의 패턴·확산 설명: https://www.pilkington.com/en/gbl/architectural-and-technical-glass/product-categories/decoration/pilkington-texture-glass (특정한 거리 법칙이나 본 레퍼런스의 조건을 입증하는 자료는 아님). - -## 비교 UI 검증 - -구현 및 실제 브라우저 확인 결과는 아래에 추가한다. 레퍼런스는 로컬 비교용이며 게시하지 않는다. - -- 수정 파일: index.html, src/main.ts, src/style.css. 광학 셰이더는 이번 변경에서 유지했다. -- 개발 모드 테스트 사진 선택 위에 두 썸네일 표시. 썸네일/선택기로 레퍼런스 선택, 0~100% 불투명도 조절, 끄기 지원. 화면 고정 contain 오버레이이며 사진/Depth 입력은 바꾸지 않는다. -- 실제 브라우저: 두 이미지 원본 폭 1160/1387 로딩 확인. 0% 이미지 opacity 0, 100% 레퍼런스 표시, 끄기 display:none 및 슬라이더 disabled 확인. 레퍼런스2 50% 표시 및 오버레이 위 드래그 확인. pointer-events:none. -- dog2→dog3 사진 전환에도 선택한 레퍼런스와 오버레이 유지. dog2, Grid8, Distortion1, 굴곡.55, 광택.15, 확대1/위치0으로 복원하고 시점 초기화. -- 데스크톱 및 390×844 브라우저 뷰포트 확인. 모바일 썸네일 각각154.5px, 문서 가로 넘침 없음. 테스트 후 뷰포트 재설정. -- 브라우저 error 로그 0건. Luna 최종 npm run build 통과. dist에 reference1/reference2 및 docs/qa-five-photos 참조 없음 확인. hidden 강제 CSS로 production 패널 비표시 보장. production 브라우저 별도 실행 및 실제 휴대폰 검증은 하지 않음. -- 증거: desktop-reference2.png, mobile-reference2.png. 캡처는 레퍼런스2 불투명도50%와 테스트 사진을 겹친 상태다. -- 제한: 화면 전체에 고정한 시각 비교 도구이며 서로 다른 사진의 얼굴 정렬/정량 차분 기능은 아니다. 거리 연동 퍼짐은 분석만 했고 새로 구현하지 않았다. - -## 사용자 배치 정정 - -사용자의 ‘위에’는 레이어 중첩이 아니라 공간 배치였다. 최종 요구는 레퍼런스1 | 레퍼런스2를 한 행에 두고 그 아래 테스트 캔버스를 표시하는 것이다. 앞선 오버레이 UI 설명과 캡처는 이전 구현 기록이며 최종 배치 기준이 아니다. 오버레이 선택/불투명도 기능을 제거하고 개발 전용 참조 행으로 교체한다. 거리 분석 결과는 유지한다. -- 정정 구현 검증 완료: 데스크톱과 390×844에서 두 레퍼런스 한 행/그 아래 캔버스 확인. 모바일 reference 하단과 stage 상단 모두 y200, 가로 넘침 없음, overlay DOM 없음. stacked-desktop.png / stacked-mobile.png 캡처. -- 최종 build 통과 및 dist 레퍼런스 제외 확인(Luna). HTML/TS 교체 중 HMR null 오류 1건 기록되었으나 최종 파일로 새로 로드 후 새 오류 없음. 사용자 dog2와 Grid8/Distortion1/굴곡.55/광택.15 복원. 뷰포트 원복. diff --git a/docs/qa-reference-comparison/stacked-desktop.png b/docs/qa-reference-comparison/stacked-desktop.png deleted file mode 100644 index a216be9..0000000 Binary files a/docs/qa-reference-comparison/stacked-desktop.png and /dev/null differ diff --git a/docs/qa-reference-comparison/stacked-mobile.png b/docs/qa-reference-comparison/stacked-mobile.png deleted file mode 100644 index 45c11cd..0000000 Binary files a/docs/qa-reference-comparison/stacked-mobile.png and /dev/null differ diff --git a/docs/qa-regions/brief.md b/docs/qa-regions/brief.md deleted file mode 100644 index ea508ac..0000000 --- a/docs/qa-regions/brief.md +++ /dev/null @@ -1,44 +0,0 @@ -# 색면·경계 단순화 작업 - -사용자 요청: 유리를 통과하면서 단순히 해상도가 낮아지거나 흐려지는 대신, 셀 내부의 비슷한 색을 묶고 작은 경계를 정리하여 Ref1~2의 색면 느낌을 시험한다. - -기존의 일관된 굴절 좌표, 셀 곡면, 시점 반응과 Ref1 | Ref2 비교 영역을 유지한다. 단색 셀이나 다른 사진 조각을 무작위로 배치하는 방식으로 대체하지 않는다. - -검증 기준: -- 잔디·털의 작은 무늬가 줄고 큰 색면으로 정리되는지 원본 설정과 같은 구도에서 비교. -- 눈·코의 어두운 형태와 얼굴 윤곽을 보존. -- 처리 강도 0에서 기존 결과 복원, Distortion 0과 No Glass 경로 유지. -- 드래그와 원위치 복귀, 셀 수 변경, 모바일 레이아웃 및 다른 유리 효과 확인. -- 빌드 성공과 시각적 완성도를 구분하여 기록. - -수정 전 캡처: dog1-before.png, dog2-before.png, sample-before.png. 테스트 사진은 로컬 검증용이며 게시 허가를 의미하지 않는다. - -## 구현 결과 - -수정 파일: `src/main.ts`, `src/shaders/mosaic.frag`, `src/shaders/region-palette.frag`, `index.html`. - -- 기본 조각 유리에 `색면 단순화` 0~1 조절을 추가했다. 기본값 0.65. 촘촘 유리/Reeded/Frosted에는 적용하지 않는다. -- 같은 굴절 셰이더로 유리 좌표의 셀별 8×8 색상 표본을 만든다. 셀마다 네 대표 색을 결정적으로 초기화하고 두 번 군집 갱신한다. -- 실제 화면은 원래 해상도로 샘플한다. 가장 가까운 대표 색으로 분류한 뒤, 주변 3×3 표본의 색상 분류 투표로 작은 고립 영역을 정리한다. RGB 공간 평균 블러나 저해상도 이미지 확대가 아니다. 전체 연결 요소를 추적하는 완전한 영역 분할 알고리즘은 아니다. -- 원래 색과 대표 색을 강도에 따라 혼합하고, 눈·코의 어두운 특징이 크게 밝아지는 경우는 보호한다. 기존 표면 광택은 그 뒤에 적용한다. -- 정지 사진의 같은 상태에서는 표본과 팔레트를 재사용한다. 시점·사진·depth·구도 등의 상태 변화에는 갱신한다. 영상은 갱신 경로를 유지하되 이번 QA에서 실제 영상은 재생하지 않았다. -- 장치 최대 텍스처 크기를 넘는 극단적 종횡비는 색면 처리만 건너뛰고 기존 굴절을 출력한다. - -## 검증 결과 - -- 최종 빌드와 타입 검사 통과. 기존 번들 크기 안내는 남는다. -- Chrome 실제 WebGL 실행으로 셰이더 오류를 확인하고 수정했다. 최종 실행에서 페이지/셰이더 오류 없음. favicon 404는 기능 오류와 별개로 기존에 남아 있다. -- dog1/dog2/sample의 강도 0·0.65·1을 같은 구도로 비교했다. 색면이 드러나고 털·잔디의 작은 무늬가 줄며 눈·코는 식별 가능하다. 1은 회화적 느낌이 강해 기본값 0.65를 유지했다. -- 세 사진 모두 강도0 화면과 수정 전 화면이 모든 픽셀에서 일치했다. -- 8단계 시점 이동과 원위치 복귀를 캡처했다. 복귀 차이는 RGB 채널 하나에서 값1뿐이었다. 캡처에서 장면 조각의 큰 점프는 보이지 않았지만 모든 연속 프레임의 깜빡임 부재를 보장하는 검증은 아니다. -- Distortion0/No Glass 중앙150×150 비교는 3개 채널에서 값1 차이. 다른 유리 효과의 강도0/1 비교는 완전히 같거나 값1 이하 반올림 차이뿐이었다. -- Grid96 출력과 390px 모바일 화면 확인. 가로 넘침 없음, Ref1/Ref2 모두 로드됨. PC 정지 화면의 30개 프레임 간격은 대체로16.7ms였으나 실기기 모바일/동영상/움직이는 고밀도 격자 성능 측정은 아니다. -- 최종 소스 재빌드 후 세 사진의 기본값을 다시 캡처하고 극단적인 2×2048 사진 입력도 오류 없이 처리했다. - -최종 화면: `dog1-final.png`, `dog2-final.png`, `sample-final.png`. 기타 근거: `runtime.json`, `pixel-checks.json`, `final-smoke.json`, `motion-*.png`. - -## 한계와 다음 판단 - -이번 결과는 사용자가 요청한 색면·경계 단순화 실험이다. Ref2의 강한 조각 확대와 동일한 광학적 질감을 달성했다고 판단하지 않는다. 8×8 표본과 셀별 네 색 때문에 고강도에서 색면 경계가 거칠거나 포스터화되어 보일 수 있다. 다음 개선은 사용자가 선호하는 강도에서 색면 크기와 경계 보존 정도를 조정하는 것이다. AI 추론과 실제 모바일 GPU/영상은 이번 변경에서 재검증하지 않았다. - -실행: 현재 `http://127.0.0.1:5175/`를 새로고침하고 기본 Mosaic의 `색면 단순화`를 조절한다. 개발 실행은 `npm run dev`, 배포 빌드는 `npm run build`. diff --git a/docs/qa-regions/distortion0.png b/docs/qa-regions/distortion0.png deleted file mode 100644 index 6e9df15..0000000 Binary files a/docs/qa-regions/distortion0.png and /dev/null differ diff --git a/docs/qa-regions/dog1-0.65.png b/docs/qa-regions/dog1-0.65.png deleted file mode 100644 index 7403f92..0000000 Binary files a/docs/qa-regions/dog1-0.65.png and /dev/null differ diff --git a/docs/qa-regions/dog1-0.png b/docs/qa-regions/dog1-0.png deleted file mode 100644 index 5fae822..0000000 Binary files a/docs/qa-regions/dog1-0.png and /dev/null differ diff --git a/docs/qa-regions/dog1-1.png b/docs/qa-regions/dog1-1.png deleted file mode 100644 index 8ccb87a..0000000 Binary files a/docs/qa-regions/dog1-1.png and /dev/null differ diff --git a/docs/qa-regions/dog1-before.png b/docs/qa-regions/dog1-before.png deleted file mode 100644 index 5fae822..0000000 Binary files a/docs/qa-regions/dog1-before.png and /dev/null differ diff --git a/docs/qa-regions/dog1-final.png b/docs/qa-regions/dog1-final.png deleted file mode 100644 index 11f7bcc..0000000 Binary files a/docs/qa-regions/dog1-final.png and /dev/null differ diff --git a/docs/qa-regions/dog2-0.65.png b/docs/qa-regions/dog2-0.65.png deleted file mode 100644 index 2bd4c5b..0000000 Binary files a/docs/qa-regions/dog2-0.65.png and /dev/null differ diff --git a/docs/qa-regions/dog2-0.png b/docs/qa-regions/dog2-0.png deleted file mode 100644 index d68d595..0000000 Binary files a/docs/qa-regions/dog2-0.png and /dev/null differ diff --git a/docs/qa-regions/dog2-1.png b/docs/qa-regions/dog2-1.png deleted file mode 100644 index a78ce04..0000000 Binary files a/docs/qa-regions/dog2-1.png and /dev/null differ diff --git a/docs/qa-regions/dog2-before.png b/docs/qa-regions/dog2-before.png deleted file mode 100644 index d68d595..0000000 Binary files a/docs/qa-regions/dog2-before.png and /dev/null differ diff --git a/docs/qa-regions/dog2-final.png b/docs/qa-regions/dog2-final.png deleted file mode 100644 index 1732784..0000000 Binary files a/docs/qa-regions/dog2-final.png and /dev/null differ diff --git a/docs/qa-regions/final-smoke.json b/docs/qa-regions/final-smoke.json deleted file mode 100644 index e7f0538..0000000 --- a/docs/qa-regions/final-smoke.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "errors": [], - "extremeAspectSurvived": true -} \ No newline at end of file diff --git a/docs/qa-regions/frosted-off.png b/docs/qa-regions/frosted-off.png deleted file mode 100644 index 26705dd..0000000 Binary files a/docs/qa-regions/frosted-off.png and /dev/null differ diff --git a/docs/qa-regions/frosted-on.png b/docs/qa-regions/frosted-on.png deleted file mode 100644 index 26705dd..0000000 Binary files a/docs/qa-regions/frosted-on.png and /dev/null differ diff --git a/docs/qa-regions/grid96.png b/docs/qa-regions/grid96.png deleted file mode 100644 index 6615d41..0000000 Binary files a/docs/qa-regions/grid96.png and /dev/null differ diff --git a/docs/qa-regions/mobile.png b/docs/qa-regions/mobile.png deleted file mode 100644 index 180adcb..0000000 Binary files a/docs/qa-regions/mobile.png and /dev/null differ diff --git a/docs/qa-regions/mosaic-off.png b/docs/qa-regions/mosaic-off.png deleted file mode 100644 index 977a37f..0000000 Binary files a/docs/qa-regions/mosaic-off.png and /dev/null differ diff --git a/docs/qa-regions/mosaic-on.png b/docs/qa-regions/mosaic-on.png deleted file mode 100644 index 683268e..0000000 Binary files a/docs/qa-regions/mosaic-on.png and /dev/null differ diff --git a/docs/qa-regions/motion-1.png b/docs/qa-regions/motion-1.png deleted file mode 100644 index f2b054b..0000000 Binary files a/docs/qa-regions/motion-1.png and /dev/null differ diff --git a/docs/qa-regions/motion-2.png b/docs/qa-regions/motion-2.png deleted file mode 100644 index 9ac6585..0000000 Binary files a/docs/qa-regions/motion-2.png and /dev/null differ diff --git a/docs/qa-regions/motion-3.png b/docs/qa-regions/motion-3.png deleted file mode 100644 index f092798..0000000 Binary files a/docs/qa-regions/motion-3.png and /dev/null differ diff --git a/docs/qa-regions/motion-4.png b/docs/qa-regions/motion-4.png deleted file mode 100644 index 33a9b05..0000000 Binary files a/docs/qa-regions/motion-4.png and /dev/null differ diff --git a/docs/qa-regions/motion-5.png b/docs/qa-regions/motion-5.png deleted file mode 100644 index bd6c37b..0000000 Binary files a/docs/qa-regions/motion-5.png and /dev/null differ diff --git a/docs/qa-regions/motion-6.png b/docs/qa-regions/motion-6.png deleted file mode 100644 index 185a3d5..0000000 Binary files a/docs/qa-regions/motion-6.png and /dev/null differ diff --git a/docs/qa-regions/motion-7.png b/docs/qa-regions/motion-7.png deleted file mode 100644 index 512c12f..0000000 Binary files a/docs/qa-regions/motion-7.png and /dev/null differ diff --git a/docs/qa-regions/motion-8.png b/docs/qa-regions/motion-8.png deleted file mode 100644 index 453858e..0000000 Binary files a/docs/qa-regions/motion-8.png and /dev/null differ diff --git a/docs/qa-regions/motion-center.png b/docs/qa-regions/motion-center.png deleted file mode 100644 index 8512572..0000000 Binary files a/docs/qa-regions/motion-center.png and /dev/null differ diff --git a/docs/qa-regions/motion-return.png b/docs/qa-regions/motion-return.png deleted file mode 100644 index 9b031db..0000000 Binary files a/docs/qa-regions/motion-return.png and /dev/null differ diff --git a/docs/qa-regions/noglass.png b/docs/qa-regions/noglass.png deleted file mode 100644 index 11231d6..0000000 Binary files a/docs/qa-regions/noglass.png and /dev/null differ diff --git a/docs/qa-regions/pixel-checks.json b/docs/qa-regions/pixel-checks.json deleted file mode 100644 index 15a14a3..0000000 --- a/docs/qa-regions/pixel-checks.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "dog1ZeroVsBefore": { - "changedChannels": 0, - "maxDifference": 0, - "meanDifference": 0 - }, - "dog2ZeroVsBefore": { - "changedChannels": 0, - "maxDifference": 0, - "meanDifference": 0 - }, - "sampleZeroVsBefore": { - "changedChannels": 0, - "maxDifference": 0, - "meanDifference": 0 - }, - "reededBypass": { - "changedChannels": 144, - "maxDifference": 1, - "meanDifference": 0.00006857142857142857 - }, - "frostedBypass": { - "changedChannels": 0, - "maxDifference": 0, - "meanDifference": 0 - }, - "mosaicBypass": { - "changedChannels": 347, - "maxDifference": 1, - "meanDifference": 0.00016523809523809525 - }, - "return": { - "changedChannels": 1, - "maxDifference": 1, - "meanDifference": 4.761904761904762e-7 - }, - "distortion0": { - "changedChannels": 3, - "maxDifference": 1, - "meanDifference": 0.000044444444444444447 - } -} \ No newline at end of file diff --git a/docs/qa-regions/reeded-off.png b/docs/qa-regions/reeded-off.png deleted file mode 100644 index b718b78..0000000 Binary files a/docs/qa-regions/reeded-off.png and /dev/null differ diff --git a/docs/qa-regions/reeded-on.png b/docs/qa-regions/reeded-on.png deleted file mode 100644 index aa63e28..0000000 Binary files a/docs/qa-regions/reeded-on.png and /dev/null differ diff --git a/docs/qa-regions/review-current.md b/docs/qa-regions/review-current.md deleted file mode 100644 index 4034c30..0000000 --- a/docs/qa-regions/review-current.md +++ /dev/null @@ -1,47 +0,0 @@ -# 색면 단순화 재QA — 2026-09-14 - -## 판정 - -시각 방향은 유지할 가치가 있다. 큰 색면이 생기고 전체 사진이 흐려지는 이전 문제는 줄었다. 다만 Ref2 수준의 완료 판정은 보류한다. 실제 사용자 설정에서 표정의 세부 명암 손실과 기울어진 유리 가장자리의 빈 영역을 확인했다. 이번에는 QA만 수행했으며 소스와 기본값은 변경하지 않았다. - -## 실제 확인 환경 - -- 사용자 탭: `http://127.0.0.1:5173/`. -- dog1, 조각 유리, 색면 단순화1, Grid8, Distortion1, 굴곡0.65, 광택0.4, 조명X0.6/Y2, 사진 확대1. -- 사용자 탭의 Camera Offset0.6, sensitivity2, Depth Scale0.4. 해당 사진은 UI상 Depth 없음/평면 테스트이므로 이 결과를 AI depth 시차로 해석하지 않는다. -- 사용자 탭에서 같은 카메라 시점의 색면1/0/0.65를 비교한 뒤1로 복원했다. 사용자 사진과 카메라 시점은 변경하지 않았다. -- 별도의 임시 탭에서 동일 색면/격자/왜곡 조건의 dog1 작은/큰 드래그, dog2 정면, sample 확대 얼굴을 확인했다. sample은 수작업 테스트 depth이며 AI 추정이 아니다. 별도 탭의 Depth Scale은 기본0.25를 유지했다. -- 모바일 viewport390×844에서 DOM 가로 넘침 없음(scrollWidth375≤innerWidth390), 두 Ref 이미지 정상 로드, Ref1|Ref2 아래 작업 화면 배치 유지. 실기기 GPU 성능 테스트는 아니다. - -## 확인한 개선점 - -- 셀 내부의 얼굴·털이 넓은 색 영역으로 정리된다. 색면0과 비교하면 잔무늬 감소가 명확하다. -- 강한 전체 블러로 경계를 지우는 결과는 아니다. 셀 굴절과 색면 경계가 구분된다. -- 사용자 탭의 Ref1/Ref2 비교 배치가 실제 개발 서버에서도 유지된다. -- 별도 QA 탭에서 콘솔 error 기록 없음. 이번 턴에서 소스 변경이 없어 빌드를 반복하지 않았다. - -## 보정 우선순위 - -### 1. 눈·코 내부 특징 보존 — 시각적으로 확인 - -사용자 탭의 색면1에서 눈의 밝은 점과 코 내부 명암이 거의 사라지고 어두운 평면 조각처럼 보인다. 색면0에서는 같은 시점에서 눈 반사와 코가 더 명확하다. 별도 정면 dog1에서도 강도1에서 눈이 단순한 어두운 쐐기 모양으로 정리되었다. dog2는 검은 얼굴과 눈의 구분이 특히 약하다. 확대 sample은 눈·코 식별이 상대적으로 양호했다. - -전체 색면 효과를 약하게 되돌리는 대신, 고대비의 작은 밝은 특징과 어두운 특징을 함께 보존하도록 보호 조건을 보완하는 것이 적합하다. 현재 보호는 어두운 색이 크게 밝아지는 특정 경우만 대상으로 한다(`mosaic.frag`의 preserveDark). Ref2의 눈도 단순한 검은 면이 아니라 내부 밝은 특징을 유지한다. - -### 2. 비스듬한 시점의 사진 채움 범위 — 시각적으로 확인 - -사용자 화면 왼쪽과 위쪽의 프레임 안에 배경색 빈 영역과 들쭉날쭉한 사진 끝이 보인다. 색면0에서도 같은 틈이 남았다. 별도 탭의 큰 드래그에서도 재현되었다. 따라서 색면 처리만의 결함으로 분류하지 않는다. - -사진/깊이의 일치된 구도를 유지하면서 허용 시점에서 충분한 원본 영역을 확보하는 방안을 별도로 검토해야 한다. 실제 깊이 표면을 완전히 복원한 것으로 표현하거나, 큰 블러로 숨겨서는 안 된다. - -### 3. 배경의 작은 색 조각 — 시각적으로 확인 - -얼굴은 넓은 색면이 되었지만 잔디에는 작은 섬 같은 색 조각이 많이 남는다. 강도1에서는 이 차이 때문에 일부 영역이 유리보다 포스터화된 그림처럼 보인다. 대표 색 혼합 강도와 작은 영역 병합 정도를 분리해서 검토할 필요가 있다. 단색 셀로 대체하는 방식은 요구사항과 맞지 않는다. - -## 아직 통과로 판정하지 않은 항목 - -- 작은 드래그에서 같은 장면이 이어지는 것은 확인했지만, 연속 프레임 전체의 팔레트 깜빡임 부재는 검증하지 못했다. 8×8 표본으로 시점마다 팔레트를 재계산하므로 원위치 재현성과 시간적 부드러움은 구분해야 한다. -- 독립 소스 검토에서 마지막 부분 셀의 유리 바깥 표본이 배경색으로 팔레트에 들어가는 것을 확인했다. `main.ts`의 ceil(gridY) 할당, `mosaic.frag`의 바깥 배경 출력, `region-palette.frag`의 전체64표본 군집화 조합이다. 이는 가장자리에 한정된 잠재적 색 오염이며, 이번 눈·코 문제의 원인으로 단정하지 않는다. 유효 표본 제외가 최소 보정 방향이다. -- AI 추론, 실제 모바일/영상 성능, 모든 유리 효과의 회귀 검사를 이번 턴에서 다시 수행하지 않았다. - -이번 QA의 다음 보정 순서는 눈·코의 작은 명암 보존 → 큰 시점의 빈 영역 → 잔디의 작은 색 영역 정리다. 사용자가 긍정적으로 평가한 색면 강도와 시점 일관성은 유지하는 방향이다. diff --git a/docs/qa-regions/runtime.json b/docs/qa-regions/runtime.json deleted file mode 100644 index 87410e1..0000000 --- a/docs/qa-regions/runtime.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "errors": [], - "mobileOverflow": false, - "references": [ - 1160, - 1387 - ], - "grid96FrameTimes": [ - 6.799999994039354, - 16.699999999999818, - 16.700000000000728, - 16.699999999999818, - 16.599999999999454, - 16.700000000000728, - 16.599999999999454, - 16.900000000000546, - 16.5, - 16.699999999999818, - 16.699999999999818, - 16.699999999999818, - 16.699999999999818, - 16.600000000000364, - 16.699999999999818, - 16.699999999999818, - 16.700000000000728, - 16.599999999999454, - 16.800000000000182, - 16.699999999999818, - 16.600000000000364, - 16.699999999999818, - 16.699999999999818, - 16.699999999999818, - 16.700000000000728, - 16.599999999999454, - 16.699999999999818, - 16.700000000000728, - 16.699999999999818, - 16.699999999999818 - ] -} \ No newline at end of file diff --git a/docs/qa-regions/sample-0.65.png b/docs/qa-regions/sample-0.65.png deleted file mode 100644 index 56bddb2..0000000 Binary files a/docs/qa-regions/sample-0.65.png and /dev/null differ diff --git a/docs/qa-regions/sample-0.png b/docs/qa-regions/sample-0.png deleted file mode 100644 index d6807c9..0000000 Binary files a/docs/qa-regions/sample-0.png and /dev/null differ diff --git a/docs/qa-regions/sample-1.png b/docs/qa-regions/sample-1.png deleted file mode 100644 index 58ba4f1..0000000 Binary files a/docs/qa-regions/sample-1.png and /dev/null differ diff --git a/docs/qa-regions/sample-before.png b/docs/qa-regions/sample-before.png deleted file mode 100644 index d6807c9..0000000 Binary files a/docs/qa-regions/sample-before.png and /dev/null differ diff --git a/docs/qa-regions/sample-final-off.png b/docs/qa-regions/sample-final-off.png deleted file mode 100644 index 9f89a1b..0000000 Binary files a/docs/qa-regions/sample-final-off.png and /dev/null differ diff --git a/docs/qa-regions/sample-final.png b/docs/qa-regions/sample-final.png deleted file mode 100644 index 3262a8c..0000000 Binary files a/docs/qa-regions/sample-final.png and /dev/null differ diff --git a/docs/qa-surface-reflection/after-camera090-right.png b/docs/qa-surface-reflection/after-camera090-right.png deleted file mode 100644 index 6b5a129..0000000 Binary files a/docs/qa-surface-reflection/after-camera090-right.png and /dev/null differ diff --git a/docs/qa-surface-reflection/after-curvature-minus1.png b/docs/qa-surface-reflection/after-curvature-minus1.png deleted file mode 100644 index 09112b0..0000000 Binary files a/docs/qa-surface-reflection/after-curvature-minus1.png and /dev/null differ diff --git a/docs/qa-surface-reflection/after-curvature0.png b/docs/qa-surface-reflection/after-curvature0.png deleted file mode 100644 index 4c737f6..0000000 Binary files a/docs/qa-surface-reflection/after-curvature0.png and /dev/null differ diff --git a/docs/qa-surface-reflection/after-default.png b/docs/qa-surface-reflection/after-default.png deleted file mode 100644 index 8978970..0000000 Binary files a/docs/qa-surface-reflection/after-default.png and /dev/null differ diff --git a/docs/qa-surface-reflection/after-glass-only.png b/docs/qa-surface-reflection/after-glass-only.png deleted file mode 100644 index 7671851..0000000 Binary files a/docs/qa-surface-reflection/after-glass-only.png and /dev/null differ diff --git a/docs/qa-surface-reflection/after-gloss0.png b/docs/qa-surface-reflection/after-gloss0.png deleted file mode 100644 index 64e39cc..0000000 Binary files a/docs/qa-surface-reflection/after-gloss0.png and /dev/null differ diff --git a/docs/qa-surface-reflection/after-gloss040.png b/docs/qa-surface-reflection/after-gloss040.png deleted file mode 100644 index 9489ee2..0000000 Binary files a/docs/qa-surface-reflection/after-gloss040.png and /dev/null differ diff --git a/docs/qa-surface-reflection/after-indoor.png b/docs/qa-surface-reflection/after-indoor.png deleted file mode 100644 index 1a09fbe..0000000 Binary files a/docs/qa-surface-reflection/after-indoor.png and /dev/null differ diff --git a/docs/qa-surface-reflection/after-portrait.png b/docs/qa-surface-reflection/after-portrait.png deleted file mode 100644 index 4681c00..0000000 Binary files a/docs/qa-surface-reflection/after-portrait.png and /dev/null differ diff --git a/docs/qa-surface-reflection/after-right.png b/docs/qa-surface-reflection/after-right.png deleted file mode 100644 index acc756d..0000000 Binary files a/docs/qa-surface-reflection/after-right.png and /dev/null differ diff --git a/docs/qa-surface-reflection/baseline-mosaic.frag b/docs/qa-surface-reflection/baseline-mosaic.frag deleted file mode 100644 index 53b75c5..0000000 --- a/docs/qa-surface-reflection/baseline-mosaic.frag +++ /dev/null @@ -1,274 +0,0 @@ -uniform sampler2D uSceneTexture,uSceneDepth; -uniform sampler2D uProtectionDepthMap; -uniform mat4 uContentViewProjection,uContentInverseViewProjection; -uniform mat4 uPetWorldToLocal; -uniform vec3 uContentCameraPosition,uLightPosition,uBackgroundColor; -uniform float uGlassZ,uSourceZ,uGridSize,uStrength,uMosaicStyle,uCurvature,uGlossStrength; -uniform vec2 uViewOffset,uPetSize,uPaneSize; -uniform vec4 uPaneRect; -uniform sampler2D uRegionPalette; -uniform sampler2D uRegionAtlas,uRegionHistory; -uniform vec2 uRegionAtlasSize,uRegionGridSize,uRegionPaletteSize; -uniform float uRegionStrength,uRegionAvailable; -varying vec2 vUv; -vec2 projectUv(vec3 p){vec4 c=uContentViewProjection*vec4(p,1.);float w=abs(c.w)<.0001?(c.w<0.?-.0001:.0001):c.w;return c.xy/w*.5+.5;} -vec4 sampleScene(vec2 uv){return texture2D(uSceneTexture,clamp(uv,0.,1.));} -vec4 samplePane(vec2 pane){return sampleScene(projectUv(vec3((pane-.5)*uPaneSize,uGlassZ)));} -float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);} -vec2 hash2(vec2 p){return vec2(hash(p),hash(p+vec2(19.19,73.73)));} -vec2 cellBlurStep(vec2 cell,vec2 cellSize,float style){ - if(style<=.5)return cellSize*mix(.006,.018,hash(cell+vec2(5.))); - return cellSize*mix(.006,.012,hash(cell+vec2(5.))); -} -vec4 sampleCell(vec2 pane,vec2 sourceUv,float strength,vec2 cell,vec2 cellSize,float style){ - vec2 center=mix(pane,sourceUv,strength); - vec2 blurOffset=strength*cellBlurStep(cell,cellSize,style); - vec4 color; - if(style<=.5){ - color=samplePane(center)*.6; - color+=samplePane(center+vec2(blurOffset.x,0.))*.1; - color+=samplePane(center-vec2(blurOffset.x,0.))*.1; - color+=samplePane(center+vec2(0.,blurOffset.y))*.1; - color+=samplePane(center-vec2(0.,blurOffset.y))*.1; - }else{ - color=samplePane(center)*.4; - color+=samplePane(center+vec2(blurOffset.x,0.))*.15; - color+=samplePane(center-vec2(blurOffset.x,0.))*.15; - color+=samplePane(center+vec2(0.,blurOffset.y))*.15; - color+=samplePane(center-vec2(0.,blurOffset.y))*.15; - } - return color; -} -float safeZ(float z){return abs(z)<.0001?(z<0.?-.0001:.0001):z;} -vec3 bend(vec3 i,vec3 n){vec3 r=refract(i,n,.75);return length(r)<.0001?i:r;} -float softLimit(float value,float limit){return value*limit/(limit+abs(value));} -float surfaceCurvature(){float curvature=clamp(uCurvature,-1.,1.),excess=max(curvature-.65,0.);return curvature-(.25/.35)*excess*excess;} -float signedCurvatureScale(){return clamp(surfaceCurvature()/.65,-1.25,1.25);} -float regionDistance(vec3 a,vec3 b){vec3 d=a-b;float y=dot(d,vec3(.299,.587,.114));return dot(d,d)+.35*y*y;} -float regionLuminance(vec3 c){return dot(c,vec3(.299,.587,.114));} -vec3 regionColor(vec2 cell,float index){vec2 uv=(vec2(cell.x*5.+index,cell.y)+.5)/uRegionPaletteSize;return texture2D(uRegionPalette,uv).rgb;} -float nearestRegion(vec3 color,vec2 cell){float best=0.,distance=regionDistance(color,regionColor(cell,0.));for(int i=1;i<4;i++){float candidate=regionDistance(color,regionColor(cell,float(i)));if(candidate1.||sceneUv.y<0.||sceneUv.y>1.)return false; - float depth=texture2D(uSceneDepth,sceneUv).x; - if(depth>=.999999)return false; - vec4 clip=vec4(sceneUv*2.-1.,depth*2.-1.,1.); - vec4 world=uContentInverseViewProjection*clip; - if(abs(world.w)<.0001)return false; - worldPoint=world.xyz/world.w; - return true; -} -float regionSurfaceValid(vec2 sceneUv,vec3 glassHit){ - vec3 worldPoint; - if(!reconstructScenePoint(sceneUv,worldPoint))return 0.; - float axialGap=glassHit.z-worldPoint.z; - if(axialGap<=.0001)return 0.; - return 1.; -} -float regionProtectionWeight(vec2 sceneUv){ - vec3 worldPoint; - if(!reconstructScenePoint(sceneUv,worldPoint))return 0.; - vec3 localPoint=(uPetWorldToLocal*vec4(worldPoint,1.)).xyz; - if(localPoint.x<-.5||localPoint.x>.5||localPoint.y<-.5||localPoint.y>.5)return 0.; - vec2 sourceUv=localPoint.xy+.5; - float sourceDepth=texture2D(uProtectionDepthMap,sourceUv).r; - return smoothstep(.8,.95,sourceDepth); -} -#ifdef REGION_ATLAS -float regionAtlasEvidence(vec2 sceneUv,vec3 color,vec3 glassHit){ - if(regionSurfaceValid(sceneUv,glassHit)<=0.)return 0.; - return regionProtectionWeight(sceneUv)*(1.-smoothstep(.10,.20,regionLuminance(color))); -} -vec4 regionAtlasProbe(vec3 sceneHit,vec2 worldOffset,vec3 glassHit){ - vec2 probeSceneUv=projectUv(sceneHit+vec3(worldOffset,0.)); - vec4 probe=sampleScene(probeSceneUv); - return vec4(probe.rgb,regionAtlasEvidence(probeSceneUv,probe.rgb,glassHit)); -} -vec4 regionAtlasScore(vec3 centerColor,float centerEvidence,vec3 probeColor,float probeEvidence){ - float evidenceGain=probeEvidence-centerEvidence,darkGain=regionLuminance(centerColor)-regionLuminance(probeColor),blend=0.; - if(probeEvidence>.05&&evidenceGain>.02&&darkGain>.015)blend=min(.4,evidenceGain*2.)*min(1.,max(0.,darkGain*4.)); - return vec4(blend,probeEvidence,0.,0.); -} -vec3 regionAtlasRepresentative(vec3 centerColor,float centerEvidence,vec3 sceneHit,vec3 glassHit,out float evidence){ - vec3 bestColor=centerColor;float bestEvidence=centerEvidence,bestBlend=0.; - vec2 probeStep=uPaneSize/(uRegionGridSize*8.)*.25; - vec4 probe,score; - probe=regionAtlasProbe(sceneHit,vec2(probeStep.x,0.),glassHit);score=regionAtlasScore(centerColor,centerEvidence,probe.rgb,probe.a);if(score.x>bestBlend){bestColor=mix(centerColor,probe.rgb,score.x);bestEvidence=max(centerEvidence,probe.a);bestBlend=score.x;} - probe=regionAtlasProbe(sceneHit,vec2(-probeStep.x,0.),glassHit);score=regionAtlasScore(centerColor,centerEvidence,probe.rgb,probe.a);if(score.x>bestBlend){bestColor=mix(centerColor,probe.rgb,score.x);bestEvidence=max(centerEvidence,probe.a);bestBlend=score.x;} - probe=regionAtlasProbe(sceneHit,vec2(0.,probeStep.y),glassHit);score=regionAtlasScore(centerColor,centerEvidence,probe.rgb,probe.a);if(score.x>bestBlend){bestColor=mix(centerColor,probe.rgb,score.x);bestEvidence=max(centerEvidence,probe.a);bestBlend=score.x;} - probe=regionAtlasProbe(sceneHit,vec2(0.,-probeStep.y),glassHit);score=regionAtlasScore(centerColor,centerEvidence,probe.rgb,probe.a);if(score.x>bestBlend){bestColor=mix(centerColor,probe.rgb,score.x);bestEvidence=max(centerEvidence,probe.a);bestBlend=score.x;} - evidence=bestEvidence; - return bestColor; -} -#endif -void evaluateCell(vec2 cell,vec2 local,vec2 grid,vec2 cellSize,vec2 cellDimensions,float cellWorld,float opticalTravel,float style,out vec2 affineUv,out mat2 transform,out vec2 curvedSlope,out vec2 facetSlope){ - vec2 random=hash2(cell),widths; - if(style>.5){ - widths=mix(vec2(.82),vec2(1.12),hash2(cell+vec2(11.4,9.8))); - float angle=(random.x-.5)*.08,c=cos(angle),s=sin(angle); - transform=mat2(widths.x*c,-widths.y*s,widths.x*s,widths.y*c); - float centerJitter=.16; - vec2 sourceCenter=(cell+.5)/grid+(random-.5)*centerJitter*cellSize; - affineUv=sourceCenter+transform*(local*cellSize); - }else{ - // Default style keeps a single continuous image footprint across cells. - transform=mat2(1.); - affineUv=(cell+.5)/grid+local*cellSize; - } - - // Positive height bulges toward the observer (+Z); negative height is concave. - float curvature=clamp(uCurvature,-1.,1.),surfaceCurvatureValue=surfaceCurvature(); - vec2 q=clamp(2.*local,-1.,1.),q2=q*q,q3=q2*q,b=1.-q2*q2; - if(style>.5){ - float amplitude=mix(.92,1.08,hash(cell+vec2(41.7,17.3))),height=.009*cellWorld*surfaceCurvatureValue*amplitude; - vec2 skew=(hash2(cell+vec2(23.8,61.2))-.5)*.28;float asym=1.+dot(skew,q); - vec2 dhdq=height*vec2(-4.*q3.x*b.y*asym+b.x*b.y*skew.x,-4.*q3.y*b.x*asym+b.x*b.y*skew.y); - vec2 grad=-2.*dhdq/cellDimensions; - curvedSlope=grad+(random-.5)*.012;facetSlope=(random-.5)*.012; - }else{ - curvedSlope=.30*cellDimensions/max(abs(opticalTravel),.6)*signedCurvatureScale()*sin(6.2831853*local); - facetSlope=vec2(0.); - } -} -void main(){ - vec2 screenUv=vUv; -#ifdef REGION_ATLAS - vec2 atlasPixel=floor(vUv*uRegionAtlasSize),atlasCell=floor(atlasPixel/8.),atlasLocal=(mod(atlasPixel,8.)+.5)/8.; - vec2 atlasPaneUv=(atlasCell+atlasLocal)/uRegionGridSize; - screenUv=projectUv(vec3((atlasPaneUv-.5)*uPaneSize,uGlassZ)); -#endif - if(uStrength<=.001){ -#ifdef REGION_ATLAS - gl_FragColor=vec4(sampleScene(screenUv).rgb,0.); -#else - gl_FragColor=sampleScene(screenUv); - #include -#endif - return;} - vec4 f=uContentInverseViewProjection*vec4(screenUv*2.-1.,1.,1.);float fw=abs(f.w)<.0001?(f.w<0.?-.0001:.0001):f.w;vec3 farWorld=f.xyz/fw;vec3 i=normalize(farWorld-uContentCameraPosition);float gt=(uGlassZ-uContentCameraPosition.z)/safeZ(i.z);vec3 gh=uContentCameraPosition+i*gt; - vec2 paneUv=gh.xy/uPaneSize+.5;vec2 grid=vec2(uGridSize,max(1.,uGridSize*uPaneSize.y/uPaneSize.x));vec2 gridUv=paneUv*grid,cell=floor(gridUv),local=fract(gridUv)-.5,cellSize=1./grid;float style=clamp(uMosaicStyle,0.,1.),cellWorld=min(uPaneSize.x/grid.x,uPaneSize.y/grid.y); -#ifdef REGION_ATLAS - paneUv=atlasPaneUv;grid= uRegionGridSize;gridUv=paneUv*grid;cell=floor(gridUv);local=fract(gridUv)-.5;cellSize=1./grid;cellWorld=min(uPaneSize.x/grid.x,uPaneSize.y/grid.y); -#endif - if(paneUv.x<0.||paneUv.x>1.||paneUv.y<0.||paneUv.y>1.){ -#ifdef REGION_ATLAS - gl_FragColor=vec4(uBackgroundColor,0.); -#else - gl_FragColor=vec4(uBackgroundColor,1.); - #include -#endif - return;} - vec2 cellDimensions=uPaneSize/grid; - float opticalTravel=-max(abs(uSourceZ-gh.z),.6); - vec2 affineUv,curvedSlope,facetSlope;mat2 transform; - evaluateCell(cell,local,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,affineUv,transform,curvedSlope,facetSlope); - if(style<=.5){ - vec2 smoothFacet=.003*vec2(sin(6.2831853*paneUv.x),sin(6.2831853*paneUv.y)); - curvedSlope+=smoothFacet;facetSlope=smoothFacet; - }else{ - vec2 edge=.5-abs(local),neighborSign=mix(vec2(-1.),vec2(1.),step(vec2(0.),local)); - float normalBlend=.16; - vec2 weights=1.-smoothstep(vec2(-normalBlend),vec2(normalBlend),edge); - float xSplitWeight=weights.x*(1.-weights.y),ySplitWeight=(1.-weights.x)*weights.y; - float diagonalSplitWeight=weights.x*weights.y,centerSplitWeight=(1.-weights.x)*(1.-weights.y); - if(weights.x>0.||weights.y>0.){ - vec2 neighborAffine,neighborCurved,neighborFacet;mat2 neighborTransform; - vec2 xWeight=vec2(xSplitWeight,0.); - vec2 yWeight=vec2(0.,ySplitWeight); - affineUv*=centerSplitWeight;transform*=centerSplitWeight;curvedSlope*=centerSplitWeight;facetSlope*=centerSplitWeight; - if(xWeight.x>0.){ - vec2 offset=vec2(neighborSign.x,0.); - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*xWeight.x;transform+=neighborTransform*xWeight.x;curvedSlope+=neighborCurved*xWeight.x;facetSlope+=neighborFacet*xWeight.x; - } - if(yWeight.y>0.){ - vec2 offset=vec2(0.,neighborSign.y); - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*yWeight.y;transform+=neighborTransform*yWeight.y;curvedSlope+=neighborCurved*yWeight.y;facetSlope+=neighborFacet*yWeight.y; - } - if(diagonalSplitWeight>0.){ - vec2 offset=neighborSign; - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*diagonalSplitWeight;transform+=neighborTransform*diagonalSplitWeight;curvedSlope+=neighborCurved*diagonalSplitWeight;facetSlope+=neighborFacet*diagonalSplitWeight; - } - } - } - vec3 nCurved=normalize(vec3(curvedSlope,1.)),nFacet=normalize(vec3(facetSlope,1.)); - vec3 straightHit=gh+i*((uSourceZ-gh.z)/safeZ(i.z)); - vec3 curvedRay=bend(i,nCurved),curvedHit=gh+curvedRay*((uSourceZ-gh.z)/safeZ(curvedRay.z)); - // Keep the artistic Mosaic optical path independent of physical glass-to-photo contact distance. - vec2 rawDelta=(curvedRay.xy/safeZ(curvedRay.z)-i.xy/safeZ(i.z))*opticalTravel; - vec2 worldDelta=vec2(softLimit(rawDelta.x,cellWorld*.55),softLimit(rawDelta.y,cellWorld*.55)); - if(style>.5){ - vec3 facetRay=bend(i,nFacet);vec3 facetHit=gh+facetRay*((uSourceZ-gh.z)/safeZ(facetRay.z)); - vec2 base=facetHit.xy-straightHit.xy,curve=curvedHit.xy-facetHit.xy; - worldDelta=vec2(softLimit(base.x,cellWorld*.08),softLimit(base.y,cellWorld*.08)); - vec2 d=curve/cellWorld; - worldDelta+=vec2(.3*d.x/(.3+abs(d.x)),.3*d.y/(.3+abs(d.y)))*cellWorld; - }else{ - vec3 referenceI=normalize(gh-vec3(0.,0.,uContentCameraPosition.z)),referenceRay=bend(referenceI,nCurved); - vec2 incidenceDelta=curvedRay.xy/max(-curvedRay.z,.0001)-referenceRay.xy/max(-referenceRay.z,.0001); - vec2 boundedIncidence=incidenceDelta/sqrt(incidenceDelta*incidenceDelta+vec2(.025*.025)); - vec2 cellEnvelope=.5+.5*cos(6.2831853*local); - worldDelta+=boundedIncidence*cellEnvelope*cellDimensions*signedCurvatureScale()*.18; - } - vec2 sampleUv=affineUv+transform*(worldDelta/uPaneSize); - float edgeDistance=min(min(paneUv.x,paneUv.y),min(1.-paneUv.x,1.-paneUv.y));float edgeTaper=style<=.5?1.25:.75;float edgeWeight=smoothstep(0.,max(cellSize.x,cellSize.y)*edgeTaper,edgeDistance);float strength=clamp(uStrength,0.,1.)*edgeWeight; - vec4 color;vec3 sceneHit=straightHit+vec3(worldDelta*strength,0.);vec2 finalSceneUv=projectUv(sceneHit); -#ifdef REGION_ATLAS - vec3 atlasCenterColor=sampleScene(finalSceneUv).rgb; - float atlasEvidence=regionProtectionWeight(finalSceneUv)*(1.-smoothstep(.10,.20,regionLuminance(atlasCenterColor))); -#endif -#ifdef REGION_ATLAS - if(style<=.5){ - float representativeEvidence=atlasEvidence; - color=vec4(regionAtlasRepresentative(atlasCenterColor,atlasEvidence,sceneHit,gh,representativeEvidence),representativeEvidence); - atlasEvidence=representativeEvidence; - }else{ - color=sampleCell(paneUv,sampleUv,strength,cell,cellSize,style); - } -#else - if(style<=.5){ - color=sampleScene(finalSceneUv); - }else{ - color=sampleCell(paneUv,sampleUv,strength,cell,cellSize,style); - } -#endif -#ifndef REGION_ATLAS - if(uRegionAvailable>.5&&uRegionStrength>.001&&uMosaicStyle<.5){ - vec3 p0=regionColor(cell,0.),p1=regionColor(cell,1.),p2=regionColor(cell,2.),p3=regionColor(cell,3.); - float ownLabel=nearestRegion(color.rgb,p0,p1,p2,p3);vec4 votes=vec4(0.);float totalWeight=0.,ownWeight=0.; - vec2 texelCoord=fract(gridUv)*8.-.5,anchor=floor(texelCoord+.5); - for(int y=-1;y<=1;y++)for(int x=-1;x<=1;x++){ - vec2 offset=vec2(float(x),float(y)),delta=anchor+offset-texelCoord; - float weight=pow(max(0.,1.-length(delta)/1.5),2.); - if(weight>0.){ - vec3 atlasColor=regionAtlasColor(cell,anchor+offset);float label=nearestRegion(atlasColor,p0,p1,p2,p3); - votes+=vec4(step(abs(label-vec4(0.,1.,2.,3.)),vec4(.1)))*weight;totalWeight+=weight; - ownWeight+=step(abs(label-ownLabel),.1)*weight; - } - } - float winningLabel=ownLabel,winningWeight=ownWeight; - if(votes.x>winningWeight){winningLabel=0.;winningWeight=votes.x;}if(votes.y>winningWeight){winningLabel=1.;winningWeight=votes.y;}if(votes.z>winningWeight){winningLabel=2.;winningWeight=votes.z;}if(votes.w>winningWeight){winningLabel=3.;winningWeight=votes.w;} - bool simplify=totalWeight>0.&&winningWeight/totalWeight>.55&&ownWeight/totalWeight<.40; - float radialLabel=simplify?winningLabel:ownLabel;vec3 radialColor=selectRegion(p0,p1,p2,p3,radialLabel); - vec2 historyTexel=clamp(floor(fract(gridUv)*8.),vec2(0.),vec2(7.)); - vec2 historyUv=(cell*8.+historyTexel+.5)/uRegionAtlasSize; - vec4 splitHistory=texture2D(uRegionHistory,historyUv); - vec3 splitColor=splitHistory.a>.00001?splitHistory.rgb/splitHistory.a:radialColor; - vec3 candidateColor=mix(radialColor,splitColor,splitHistory.a); - color.rgb=mix(color.rgb,candidateColor,clamp(uRegionStrength*clamp(uStrength,0.,1.)*regionSurfaceValid(finalSceneUv,gh),0.,1.)); - } -#endif -#ifndef REGION_ATLAS - color.a=1.; - vec3 v=normalize(uContentCameraPosition-gh),reflected=reflect(-v,nCurved); float lightT=(uLightPosition.z-gh.z)/safeZ(reflected.z); vec2 lightHit=gh.xy+reflected.xy*lightT; vec2 halfSize=vec2(.32,.42)*min(uPaneSize.x,uPaneSize.y); vec2 windowCoord=abs(lightHit-uLightPosition.xy)/halfSize; vec2 windowMask=1.-smoothstep(vec2(.45),vec2(1.15),windowCoord); float spec=windowMask.x*windowMask.y*step(.0001,reflected.z)*step(0.,lightT); float gloss=spec*clamp(uGlossStrength,0.,1.)*.12*edgeWeight*clamp(uStrength,0.,1.); color.rgb=mix(color.rgb,vec3(1.),gloss); gl_FragColor=color; - #include -#else - color.a=atlasEvidence; - gl_FragColor=color; -#endif -} diff --git a/docs/qa-surface-reflection/before-default.png b/docs/qa-surface-reflection/before-default.png deleted file mode 100644 index 839ee6b..0000000 Binary files a/docs/qa-surface-reflection/before-default.png and /dev/null differ diff --git a/docs/qa-surface-reflection/before-gloss0.png b/docs/qa-surface-reflection/before-gloss0.png deleted file mode 100644 index 64e39cc..0000000 Binary files a/docs/qa-surface-reflection/before-gloss0.png and /dev/null differ diff --git a/docs/qa-surface-reflection/before-right.png b/docs/qa-surface-reflection/before-right.png deleted file mode 100644 index c08f595..0000000 Binary files a/docs/qa-surface-reflection/before-right.png and /dev/null differ diff --git a/docs/qa-surface-reflection/implementation-report.md b/docs/qa-surface-reflection/implementation-report.md deleted file mode 100644 index 9481d61..0000000 --- a/docs/qa-surface-reflection/implementation-report.md +++ /dev/null @@ -1,206 +0,0 @@ -# Surface reflection implementation report - -## Status and scope - -Implemented Task 1 from `.superpowers/sdd/surface-reflection/task-1-brief.md`. -The change is limited to the final non-`REGION_ATLAS` reflection composition in -`src/shaders/mosaic.frag` plus one source/math regression script. Existing -uniforms were sufficient, so `src/main.ts` was not changed. - -The exact pre-edit shader is preserved at -`docs/qa-surface-reflection/baseline-mosaic.frag`. - -Baseline SHA-256: - -```text -CEE5F75C7A62A9146CBE451C661C2E0066EE57EB8963A7B0F56C281873F37E35 -``` - -## Implementation - -Changed files: - -- `src/shaders/mosaic.frag` -- `scripts/test-surface-reflection.mjs` -- `docs/qa-surface-reflection/baseline-mosaic.frag` (pre-edit snapshot) -- `docs/qa-surface-reflection/implementation-report.md` - -The existing rectangular reflection remains intact and is now named -`specGloss`. A separate broad reflection is added after color-plane -simplification and before `#include `. - -Final coefficients and rationale: - -- Surface reflection edge weight: `mix(0.35, 1.0, edgeWeight)`. This keeps the - existing refraction `edgeWeight` and `strength` path unchanged while reducing - reflection at pane edges without removing it entirely. -- Existing rectangular reflection strength: `.12`, unchanged. -- Broad reflection strength: `.035`, intentionally low relative to the - rectangular lobe. -- Broad spatial footprint: `smoothstep(vec2(.15), vec2(1.75), windowCoord)`, - wider and softer than the existing `.45` to `1.15` rectangular mask. -- View/surface response: `pow(max(dot(nCurved, v), 0.), 2.)`, using the same - signed curved normal that drives refraction and the existing reflection. -- Both reflection amplitudes use the same `clamp(uGlossStrength, 0., 1.)` - gate, so gloss `0` makes both contributions exactly zero. - -No environment texture, render pass, render target, dependency, palette input, -history input, UI, camera, placement, framing, or other glass-mode change was -added. - -## TDD evidence - -Focused regression: `scripts/test-surface-reflection.mjs`. -The assertions are source/math-only and do not claim to execute GLSL or prove -browser visuals. - -### RED - -Command: - -```text -node scripts/test-surface-reflection.mjs -``` - -Exact result against the pre-edit shader: - -```text -exit_code=1 -node:internal/modules/run_main:107 - triggerUncaughtException( - ^ - -AssertionError [ERR_ASSERTION]: both surface reflection terms must share a clamped gloss gate - at file:///D:/project/behind_glass/scripts/test-surface-reflection.mjs:11:8 { - generatedMessage: false, - actual: '#ifndef REGION_ATLAS\n' + - ' color.a=1.;\n' + - ' vec3 v=normalize(uContentCameraPosition-gh),reflected=reflect(-v,nCurved); float lightT=(uLightPosition.z-gh.z)/safeZ(reflected.z); vec2 lightHit=gh.xy+reflected.xy*lightT; vec2 halfSize=vec2(.32,.42)*min(uPaneSize.x,uPaneSize.y); vec2 windowCoord=abs(lightHit-uLightPosition.xy)/halfSize; vec2 windowMask=1.-smoothstep(vec2(.45),vec2(1.15),windowCoord); float spec=windowMask.x*windowMask.y*step(.0001,reflected.z)*step(0.,lightT); float gloss=spec*clamp(uGlossStrength,0.,1.)*.12*edgeWeight*clamp(uStrength,0.,1.); color.rgb=mix(color.rgb,vec3(1.),gloss); gl_FragColor=color;\n' + - ' #include \n', - expected: /float glossStrength=clamp\(uGlossStrength,0\.,1\.\);/, - operator: 'match' -} -``` - -This failed for the intended reason: the pre-edit shader had one reflection -term, no shared gloss gate, no broad reflection, and no separate surface edge -weight. - -### GREEN - -Command: - -```text -node scripts/test-surface-reflection.mjs -``` - -Exact result after the minimal shader edit: - -```text -exit_code=0 -surface reflection source/math regression passed -``` - -The final regression checks zero-gloss gating, `.35` to `1.0` surface-weight -bounds, preservation of the refraction edge weight, normal/view and light-hit -spatial dependence, non-atlas placement, and ordering before color-space -conversion. - -## Automated verification - -All six existing scripts from `docs/qa-window-immersion/verification.md` were -run with `node --experimental-strip-types` after implementation. - -```text -=== node --experimental-strip-types scripts/test-camera-history.mjs === -Camera/history checks passed: default/max clamp, model reset keys, ping-pong and disposal, premultiplied color, cadence 0.999955/0.999955/0.999955, 70ms settling. -=== node --experimental-strip-types scripts/test-region-axis-split.mjs === -Region axis-split checks passed: SSE axis/cut/pair scoring, vertical/horizontal cuts 2/6, observed side-label pairs, checkerboard model, single-label fallback, metadata round-trip, confidence blending, dark eye/nose protection, and edge-independent color strength. -=== node --experimental-strip-types scripts/test-mosaic-depth-distance.mjs === -Mosaic depth-region projection checks passed: 21 perspective reconstructions, 12 original-depth UV mappings across camera/zoom-pan/depthScale, near-depth gate, distance-independent color application, and invalid-surface guards. -=== node --experimental-strip-types scripts/test-mosaic-continuity.mjs === -Mosaic projected-UV continuity passed: 493760 Jacobians, 87200 seam convergence checks, center/edge anchors, and view-dependent within-cell displacement. -=== node --experimental-strip-types scripts/test-region-atlas-dark-sampling.mjs === -Region atlas dark sampling source/math-only regression passed: phase-offset narrow feature, far/invalid/uniform invariants, and four-probe bounded scoring contract. -=== node --experimental-strip-types scripts/test-window-reveal-coverage.mjs === -Window reveal coverage passed: 146 previous-frame misses sealed across 2 aspects, 3 depth scales, 17 view offsets (including neutral) and 49 aperture samples; geometry reuse/disposal verified. -``` - -Build command: - -```text -npm.cmd run build -``` - -Result: exit code `0`; TypeScript and Vite production build succeeded. Vite -reported the existing large-chunk advisory for the main and AI-depth assets. - -## Visual comparison and limitations - -No browser or GPU visual capture was performed in this implementation task. -The preserved shader baseline is available at -`docs/qa-surface-reflection/baseline-mosaic.frag`; use it for the -same-viewport dog1 comparison with the brief's fixed values, including gloss -0, 0.30, and 0.40, curvature -1/0/+1, camera 0.90, portrait, and indoor -checks. - -The automated regression does not prove grass highlight appearance, adjacent -cell coherence, edge leakage, eye/nose readability, mobile behavior, or GPU -shader compilation. Those remain visual/browser verification items. No claim -of GPU, mobile, or visual success is made here. - -## Round 1/5 regression hardening - -Addressed both Astra findings without changing production scope. The focused -script now extracts individual GLSL statements instead of using unrestricted -cross-statement matching, compares `edgeWeight`, `strength`, and `sceneHit` -against the preserved pre-edit shader, inspects the effective atlas branch, -and verifies simplification before final composition and composition before -color-space conversion. It evaluates the extracted `specGloss`, -`broadReflection`, and final mix expressions for gloss-zero output plus -representative spatial/view variation. It also applies an in-memory constant -50% final-mix mutation and requires the covering assertions to reject it. - -Exact covering command: - -```text -node scripts/test-surface-reflection.mjs -``` - -Exact output: - -```text -exit_code=0 -surface reflection source/math regression passed; constant-output mutation rejected -``` - -Only the focused regression was rerun because this round changed no -production file; the six existing checks and build remain covered by the prior -verification record above. - -## Round 2/5 atlas exclusion hardening - -Addressed the remaining atlas-exclusion finding without changing production -code. `scripts/test-surface-reflection.mjs` now walks all `REGION_ATLAS` -preprocessor branches, retains the complete effective source for the macro -defined, and compares that source with the preserved baseline. It also inserts -an in-memory gloss-dependent white reflection immediately after the earlier -atlas `atlasCenterColor` sample and requires the covering assertions to reject -that mutation. This remains a source/math regression and is not GPU visual -verification. - -Exact covering command: - -```text -node scripts/test-surface-reflection.mjs -``` - -Exact output: - -```text -exit_code=0 -surface reflection source/math regression passed; constant-output and atlas-reflection mutations rejected -``` - -No full suite or build was rerun because the production shader remained -unchanged. diff --git a/docs/qa-surface-reflection/visual-verification.md b/docs/qa-surface-reflection/visual-verification.md deleted file mode 100644 index 8a51527..0000000 --- a/docs/qa-surface-reflection/visual-verification.md +++ /dev/null @@ -1,36 +0,0 @@ -# Surface reflection browser verification - -2026-09-23, local Vite preview at 1280×720 unless noted. The primary comparison used dog1 after the same cached AI relative-depth generation completed: Final / Mosaic / 조각 유리, Grid 13, curvature +1, gloss 0.30, light 0.60/0.80, depth scale 0.25, camera offset 0.50, zoom/pan 1/0/0. - -## Same-condition comparison - -- `before-default.png`: pre-edit shader, centered view. -- `after-default.png`: final shader, centered view. -- `before-right.png`, `after-right.png`: equivalent pointer-drag probe; these are qualitative because camera smoothing does not guarantee identical final coordinates. -- The centered glass-pane crop changed by a mean absolute `0.3106/255` per RGB channel, maximum `14`, over `13.85%` of channels. The top-right quadrant contained nearly all of the visible change (`1.2244/255` mean absolute difference); the other three quadrants were below `0.013/255`. -- Compared with gloss 0, the pre-edit default gloss affected `12.80%` of crop channels with `0.6569/255` mean absolute difference; the final default gloss affected `15.81%` with `0.9015/255`. This is a broader but deliberately subtle highlight, not uniform pane brightening. - -The dog’s two dark eye planes and nose plane remained visible. Grass and face were not visibly washed out. The centered difference is too subtle to prove visual improvement by metric alone; `after-glass-only.png` confirms that the widened reflection remains localized around the common top-right light rather than becoming a constant white overlay. - -## Preservation checks - -- `before-gloss0.png` and `after-gloss0.png` are pixel-identical in the pane crop: mean absolute difference `0`, maximum `0`, changed channels `0`. -- `after-gloss040.png`: no obvious face/grass washout at gloss 0.40. -- `after-curvature0.png`, `after-curvature-minus1.png`: flat and concave cases rendered without reflection spill; the dark facial features remained identifiable. Curvature +1 was the default comparison. -- `after-camera090-right.png`: camera range 0.90 plus horizontal drag showed no reflection outside the pane, bright rim, or exposed background gap. -- `after-portrait.png`: 390×844 viewport retained the frame/pane fit and dark eye/nose planes. The temporary viewport override was reset. -- `after-indoor.png`: dog2 with completed AI depth rendered without reflection washout or pane-edge leakage. -- Reeded and Frosted were selected and rendered, then Mosaic was restored. No runtime errors appeared. - -The console contained only the already documented Three.js shader warning `X3595` about gradient instructions in a varying loop. No new error was observed. - -## Final fresh verification - -After both regression-review fix rounds, the controller reran the current workspace state. `scripts/test-surface-reflection.mjs` and the six existing regression scripts all exited successfully. `npm.cmd run build` completed TypeScript and Vite production output successfully; the existing main-chunk size advisory remained. - -## Limits - -- The requested intermediate “broad reflection only, before edge-weight separation” GPU screenshot was not captured; the exact pre-edit and final states are preserved instead. -- The pointer-drag screenshots do not record an exact camera coordinate and therefore are qualitative. -- Continuous-video flicker, physical mobile GPU performance, and real-device touch/gyro were not measured. -- The browser comparison establishes no obvious regression and a small widened reflection footprint. Whether the subtle default-strength change is aesthetically strong enough remains a product judgment, not an automated pass condition. diff --git a/docs/qa-varied-dogs-2026-09-23/dog1-grid13.png b/docs/qa-varied-dogs-2026-09-23/dog1-grid13.png deleted file mode 100644 index eb44c76..0000000 Binary files a/docs/qa-varied-dogs-2026-09-23/dog1-grid13.png and /dev/null differ diff --git a/docs/qa-varied-dogs-2026-09-23/dog1-mobile-grid13.png b/docs/qa-varied-dogs-2026-09-23/dog1-mobile-grid13.png deleted file mode 100644 index 8703906..0000000 Binary files a/docs/qa-varied-dogs-2026-09-23/dog1-mobile-grid13.png and /dev/null differ diff --git a/docs/qa-varied-dogs-2026-09-23/dog1-mobile-retest-viewport.png b/docs/qa-varied-dogs-2026-09-23/dog1-mobile-retest-viewport.png deleted file mode 100644 index 2bdaef6..0000000 Binary files a/docs/qa-varied-dogs-2026-09-23/dog1-mobile-retest-viewport.png and /dev/null differ diff --git a/docs/qa-varied-dogs-2026-09-23/dog1-noglass.png b/docs/qa-varied-dogs-2026-09-23/dog1-noglass.png deleted file mode 100644 index 10036cc..0000000 Binary files a/docs/qa-varied-dogs-2026-09-23/dog1-noglass.png and /dev/null differ diff --git a/docs/qa-varied-dogs-2026-09-23/dog2-grid13.png b/docs/qa-varied-dogs-2026-09-23/dog2-grid13.png deleted file mode 100644 index 2659e13..0000000 Binary files a/docs/qa-varied-dogs-2026-09-23/dog2-grid13.png and /dev/null differ diff --git a/docs/qa-varied-dogs-2026-09-23/dog2-noglass-drag.png b/docs/qa-varied-dogs-2026-09-23/dog2-noglass-drag.png deleted file mode 100644 index 1e02f0d..0000000 Binary files a/docs/qa-varied-dogs-2026-09-23/dog2-noglass-drag.png and /dev/null differ diff --git a/docs/qa-varied-dogs-2026-09-23/dog2-noglass.png b/docs/qa-varied-dogs-2026-09-23/dog2-noglass.png deleted file mode 100644 index 391b1af..0000000 Binary files a/docs/qa-varied-dogs-2026-09-23/dog2-noglass.png and /dev/null differ diff --git a/docs/qa-varied-dogs-2026-09-23/dog3-grid13.png b/docs/qa-varied-dogs-2026-09-23/dog3-grid13.png deleted file mode 100644 index 2b02061..0000000 Binary files a/docs/qa-varied-dogs-2026-09-23/dog3-grid13.png and /dev/null differ diff --git a/docs/qa-varied-dogs-2026-09-23/dog3-grid24-drag.png b/docs/qa-varied-dogs-2026-09-23/dog3-grid24-drag.png deleted file mode 100644 index c8305d3..0000000 Binary files a/docs/qa-varied-dogs-2026-09-23/dog3-grid24-drag.png and /dev/null differ diff --git a/docs/qa-varied-dogs-2026-09-23/dog3-grid24.png b/docs/qa-varied-dogs-2026-09-23/dog3-grid24.png deleted file mode 100644 index 32bf442..0000000 Binary files a/docs/qa-varied-dogs-2026-09-23/dog3-grid24.png and /dev/null differ diff --git a/docs/qa-varied-dogs-2026-09-23/dog3-noglass.png b/docs/qa-varied-dogs-2026-09-23/dog3-noglass.png deleted file mode 100644 index 49b36bd..0000000 Binary files a/docs/qa-varied-dogs-2026-09-23/dog3-noglass.png and /dev/null differ diff --git a/docs/qa-varied-dogs-2026-09-23/dog4-grid13.png b/docs/qa-varied-dogs-2026-09-23/dog4-grid13.png deleted file mode 100644 index 72d9dfd..0000000 Binary files a/docs/qa-varied-dogs-2026-09-23/dog4-grid13.png and /dev/null differ diff --git a/docs/qa-varied-dogs-2026-09-23/dog4-grid24.png b/docs/qa-varied-dogs-2026-09-23/dog4-grid24.png deleted file mode 100644 index 9641113..0000000 Binary files a/docs/qa-varied-dogs-2026-09-23/dog4-grid24.png and /dev/null differ diff --git a/docs/qa-varied-dogs-2026-09-23/dog4-mobile-fullpage.png b/docs/qa-varied-dogs-2026-09-23/dog4-mobile-fullpage.png deleted file mode 100644 index f553cee..0000000 Binary files a/docs/qa-varied-dogs-2026-09-23/dog4-mobile-fullpage.png and /dev/null differ diff --git a/docs/qa-varied-dogs-2026-09-23/dog4-mobile-viewport.png b/docs/qa-varied-dogs-2026-09-23/dog4-mobile-viewport.png deleted file mode 100644 index 3bc4cc3..0000000 Binary files a/docs/qa-varied-dogs-2026-09-23/dog4-mobile-viewport.png and /dev/null differ diff --git a/docs/qa-varied-dogs-2026-09-23/dog4-noglass.png b/docs/qa-varied-dogs-2026-09-23/dog4-noglass.png deleted file mode 100644 index 7c4c9ae..0000000 Binary files a/docs/qa-varied-dogs-2026-09-23/dog4-noglass.png and /dev/null differ diff --git a/docs/qa-varied-dogs-2026-09-23/final-diagnostics.json b/docs/qa-varied-dogs-2026-09-23/final-diagnostics.json deleted file mode 100644 index c8a6f12..0000000 --- a/docs/qa-varied-dogs-2026-09-23/final-diagnostics.json +++ /dev/null @@ -1,117 +0,0 @@ -{ - "recordedAt": "2026-09-22T22:38:36.729Z", - "finalBrowser": { - "controls": [ - { - "id": "image", - "value": "" - }, - { - "id": "test-photo", - "value": "dog1" - }, - { - "id": "grid-size", - "value": "13" - }, - { - "id": "curvature", - "value": "1" - }, - { - "id": "gloss-strength", - "value": "0.3" - }, - { - "id": "camera-offset", - "value": "0.5" - }, - { - "id": "photo-zoom", - "value": "1" - }, - { - "id": "photo-pan-x", - "value": "0" - }, - { - "id": "photo-pan-y", - "value": "0" - }, - { - "id": "video", - "value": "" - }, - { - "id": "depth-image", - "value": "" - }, - { - "id": "view-mode", - "value": "final" - }, - { - "id": "effect", - "value": "mosaic" - }, - { - "id": "mosaic-style", - "value": "0" - }, - { - "id": "depth-scale", - "value": "0.25" - }, - { - "id": "light-x", - "value": "0.6" - }, - { - "id": "light-y", - "value": "0.8" - }, - { - "id": "sensitivity", - "value": "1" - } - ], - "height": 720, - "width": 1280 - }, - "aiStatus": "자동 AI 추정 depth를 적용했습니다.", - "depthProvenance": "AI 추정 · Depth Anything V2 Small (상대 깊이, 0=뒤 · 1=앞)", - "viewportOverrideReset": true, - "consoleAudit": { - "levels": [ - "error", - "warn" - ], - "limit": 100, - "entries": [] - }, - "mobileRetest": { - "photo": "dog1", - "viewportWidth": 390, - "viewportHeight": 844, - "devicePixelRatio": 1, - "visualViewportScale": 1, - "scrollX": 0, - "scrollY": 0, - "documentScrollWidth": 375, - "canvas": { - "x": 0, - "y": 200, - "width": 375, - "height": 506.390625, - "bottom": 706.390625 - }, - "aside": { - "x": 0, - "y": 706.390625, - "width": 375, - "height": 966, - "bottom": 1672.390625 - }, - "screenshot": "dog1-mobile-retest-viewport.png" - } -} \ No newline at end of file diff --git a/docs/qa-varied-dogs-2026-09-23/framing-after-reload.png b/docs/qa-varied-dogs-2026-09-23/framing-after-reload.png deleted file mode 100644 index f275883..0000000 Binary files a/docs/qa-varied-dogs-2026-09-23/framing-after-reload.png and /dev/null differ diff --git a/docs/qa-varied-dogs-2026-09-23/framing-ai-regenerate-completed.txt b/docs/qa-varied-dogs-2026-09-23/framing-ai-regenerate-completed.txt deleted file mode 100644 index 128db68..0000000 --- a/docs/qa-varied-dogs-2026-09-23/framing-ai-regenerate-completed.txt +++ /dev/null @@ -1,114 +0,0 @@ -Browser tab: 1, Title: "Pet Behind Glass", URL: "http://127.0.0.1:5174/". -1 AXWebArea Pet Behind Glass, URL: 127.0.0.1:5174/ - 2 container - 3 container Description: 레퍼런스 비교 이미지, ID: reference-strip - 4 container Ref1 · 주 기준 - 5 text Ref1 · 주 기준 - 6 container Ref2 · 보조 - 7 text Ref2 · 보조 - 9 text 화면을 드래그해서 시점을 움직여보세요 - 10 heading Pet Behind Glass, Value: 1 - 11 text Pet Behind Glass - 12 container - 13 text 사진 선택 - 14 button 사진 선택, ID: image - 15 button AI 깊이 생성, ID: ai-depth - 130 text AI 추정 · Depth Anything V2 Small (상대 깊이, 0=뒤 · 1=앞) - 16 container - 17 text 테스트 사진 - 18 pop up button (collapsed, settable) 테스트 사진, Value: 멍멍이 4 · 벤치 위 갈색 닥스훈트, ID: test-photo, Secondary Actions: Expand - 19 menu - 20 기존 샘플 · 흰 강아지 얼굴 - 21 멍멍이 1 · 잔디 위 흰 포메라니안 - 22 멍멍이 2 · 실내에 엎드린 검정·갈색 강아지 - 23 멍멍이 3 · 후드 옷을 입은 강아지 두 마리 - 24 (selected) 멍멍이 4 · 벤치 위 갈색 닥스훈트 - 25 button 선택한 테스트 사진 불러오기, ID: sample - 26 text Ref1 기준 · 색면 단순화 1 · 굴절 1 (고정) - 27 container - 28 text Grid Size - 29 container Grid Size 13, ID: gridOut - 105 text 13 - 31 slider (settable, integer) Value: 13, ID: grid-size - 32 text 큰 얼굴 12–16 · 작은 얼굴/여러 마리 20–24 - 33 container gloss-controls - 34 container - 35 text 셀 굴곡 (−1 오목 · +1 볼록) - 36 container 셀 굴곡 (−1 오목 · +1 볼록) 1, ID: curvatureOut - 37 text 1.00 - 38 slider (settable, integer) Value: 1, ID: curvature - 39 text |굴곡| 0.65–1 권장 - 40 container - 41 text 광택 강도 - 42 container 광택 강도 0.3, ID: glossOut - 43 text 0.30 - 44 slider (settable, float) Value: 0.30000001192092896, Details: 0.3, ID: gloss-strength - 45 container - 46 text Camera Offset - 47 container Camera Offset 0.5, ID: cameraOut - 48 text 0.50 - 49 slider (settable, float) Value: 0.5, ID: camera-offset - 50 text 권장 0.35–0.65 · 시점 이동 범위 - 51 button 시점 초기화, ID: reset - 52 button Gyroscope: OFF, ID: gyro - 106 container - 107 button (expanded) 사진 구도, Secondary Actions: Collapse - 108 text 사진 구도 - 109 text 사진 확대 - 110 container 사진 확대 1.5, ID: photoZoomOut - 127 text 1.50 - 112 slider (settable, float) Value: 1.5, ID: photo-zoom - 113 text 사진 가로 위치 - 114 container 사진 가로 위치 0.1, ID: photoPanXOut - 128 text 0.10 - 116 slider (settable, float) Value: 0.10000000149011612, Details: 0.1, ID: photo-pan-x - 117 text 사진 세로 위치 - 118 container 사진 세로 위치 -0.1, ID: photoPanYOut - 129 text -0.10 - 120 slider (settable, float) Value: -0.10000000149011612, Details: -0.1, ID: photo-pan-y - 121 button 사진 구도 초기화, ID: photo-reset - 59 container - 60 button (expanded) 개발 비교, Secondary Actions: Collapse - 61 text 개발 비교 - 62 text 동영상 선택 - 63 button 동영상 선택, ID: video - 64 text Depth 이미지 선택 - 65 button Depth 이미지 선택, ID: depth-image - 66 text View Mode - 67 pop up button (collapsed, settable) View Mode, Value: Final, ID: view-mode, Secondary Actions: Expand - 68 menu - 69 (selected) Final - 70 No Glass - 71 RGB - 72 Depth - 73 Glass Only - 74 text Glass - 75 pop up button (collapsed, settable) Glass, Value: Mosaic, ID: effect, Secondary Actions: Expand - 76 menu - 77 (selected) Mosaic - 78 Reeded - 79 Frosted - 80 text Mosaic 스타일 - 81 pop up button (collapsed, settable) Mosaic 스타일, Value: 조각 유리, ID: mosaic-style, Secondary Actions: Expand - 82 menu - 83 (selected) 조각 유리 - 84 촘촘 유리 - 85 text Depth Scale - 86 container Depth Scale 0.25, ID: depthOut - 87 text 0.25 - 88 slider (settable, float) Value: 0.25, ID: depth-scale - 89 text 조명 가로 - 90 container 조명 가로 0.6, ID: lightXOut - 91 text 0.60 - 92 slider (settable, float) Value: 0.6000000238418579, Details: 0.6, ID: light-x - 93 text 조명 세로 - 94 container 조명 세로 0.8, ID: lightYOut - 95 text 0.80 - 96 slider (settable, float) Value: 0.800000011920929, Details: 0.8, ID: light-y - 97 text View sensitivity - 98 container View sensitivity 1, ID: sensitivityOut - 99 text 1.00 - 100 slider (settable, integer) Value: 1, ID: sensitivity - 131 text AI 추정 depth를 적용하고 Final 뷰로 돌아왔습니다. - -The focused UI element is 1 AXWebArea Pet Behind Glass, URL: 127.0.0.1:5174/ \ No newline at end of file diff --git a/docs/qa-varied-dogs-2026-09-23/framing-ai-regenerate-start.txt b/docs/qa-varied-dogs-2026-09-23/framing-ai-regenerate-start.txt deleted file mode 100644 index 20a5055..0000000 --- a/docs/qa-varied-dogs-2026-09-23/framing-ai-regenerate-start.txt +++ /dev/null @@ -1,15 +0,0 @@ -Browser tab: 1, Title: "Pet Behind Glass", URL: "http://127.0.0.1:5174/". -The following is a diff from the previous accessibility tree with ~ and + representing changed and added elements, respectively. Removed elements are summarized by ID range. -Removed element IDs: 123-125, 127 -~ 15 button (disabled) AI 깊이 생성 중…, ID: ai-depth -~ 110 container 사진 확대 1.5, ID: photoZoomOut -+ 127 text 1.50 -~ 112 slider (settable, float) Value: 1.5, ID: photo-zoom -~ 114 container 사진 가로 위치 0.1, ID: photoPanXOut -+ 128 text 0.10 -~ 116 slider (settable, float) Value: 0.10000000149011612, Details: 0.1, ID: photo-pan-x -~ 118 container 사진 세로 위치 -0.1, ID: photoPanYOut -+ 129 text -0.10 -~ 120 slider (settable, float) Value: -0.10000000149011612, Details: -0.1, ID: photo-pan-y -+ 130 text AI 깊이를 계산하는 중입니다… -The focused UI element is 1 AXWebArea Pet Behind Glass, URL: 127.0.0.1:5174/ \ No newline at end of file diff --git a/docs/qa-varied-dogs-2026-09-23/framing-before-reload.png b/docs/qa-varied-dogs-2026-09-23/framing-before-reload.png deleted file mode 100644 index c8912a8..0000000 Binary files a/docs/qa-varied-dogs-2026-09-23/framing-before-reload.png and /dev/null differ diff --git a/docs/qa-varied-dogs-2026-09-23/framing-before-reload.txt b/docs/qa-varied-dogs-2026-09-23/framing-before-reload.txt deleted file mode 100644 index eab0795..0000000 --- a/docs/qa-varied-dogs-2026-09-23/framing-before-reload.txt +++ /dev/null @@ -1,114 +0,0 @@ -Browser tab: 1, Title: "Pet Behind Glass", URL: "http://127.0.0.1:5174/". -1 AXWebArea Pet Behind Glass, URL: 127.0.0.1:5174/ - 2 container - 3 container Description: 레퍼런스 비교 이미지, ID: reference-strip - 4 container Ref1 · 주 기준 - 5 text Ref1 · 주 기준 - 6 container Ref2 · 보조 - 7 text Ref2 · 보조 - 9 text 화면을 드래그해서 시점을 움직여보세요 - 10 heading Pet Behind Glass, Value: 1 - 11 text Pet Behind Glass - 12 container - 13 text 사진 선택 - 14 button 사진 선택, ID: image - 15 button AI 깊이 생성, ID: ai-depth - 103 text AI 추정 · Depth Anything V2 Small (상대 깊이, 0=뒤 · 1=앞) - 16 container - 17 text 테스트 사진 - 18 pop up button (collapsed, settable) 테스트 사진, Value: 멍멍이 4 · 벤치 위 갈색 닥스훈트, ID: test-photo, Secondary Actions: Expand - 19 menu - 20 기존 샘플 · 흰 강아지 얼굴 - 21 멍멍이 1 · 잔디 위 흰 포메라니안 - 22 멍멍이 2 · 실내에 엎드린 검정·갈색 강아지 - 23 멍멍이 3 · 후드 옷을 입은 강아지 두 마리 - 24 (selected) 멍멍이 4 · 벤치 위 갈색 닥스훈트 - 25 button 선택한 테스트 사진 불러오기, ID: sample - 26 text Ref1 기준 · 색면 단순화 1 · 굴절 1 (고정) - 27 container - 28 text Grid Size - 29 container Grid Size 13, ID: gridOut - 105 text 13 - 31 slider (settable, integer) Value: 13, ID: grid-size - 32 text 큰 얼굴 12–16 · 작은 얼굴/여러 마리 20–24 - 33 container gloss-controls - 34 container - 35 text 셀 굴곡 (−1 오목 · +1 볼록) - 36 container 셀 굴곡 (−1 오목 · +1 볼록) 1, ID: curvatureOut - 37 text 1.00 - 38 slider (settable, integer) Value: 1, ID: curvature - 39 text |굴곡| 0.65–1 권장 - 40 container - 41 text 광택 강도 - 42 container 광택 강도 0.3, ID: glossOut - 43 text 0.30 - 44 slider (settable, float) Value: 0.30000001192092896, Details: 0.3, ID: gloss-strength - 45 container - 46 text Camera Offset - 47 container Camera Offset 0.5, ID: cameraOut - 48 text 0.50 - 49 slider (settable, float) Value: 0.5, ID: camera-offset - 50 text 권장 0.35–0.65 · 시점 이동 범위 - 51 button 시점 초기화, ID: reset - 52 button Gyroscope: OFF, ID: gyro - 106 container - 107 button (expanded) 사진 구도, Secondary Actions: Collapse - 108 text 사진 구도 - 109 text 사진 확대 - 110 container 사진 확대 1.5, ID: photoZoomOut - 111 text 1.50 - 112 slider (settable, float) Value: 1.5, ID: photo-zoom - 113 text 사진 가로 위치 - 114 container 사진 가로 위치 0.1, ID: photoPanXOut - 115 text 0.10 - 116 slider (settable, float) Value: 0.10000000149011612, Details: 0.1, ID: photo-pan-x - 117 text 사진 세로 위치 - 118 container 사진 세로 위치 -0.1, ID: photoPanYOut - 119 text -0.10 - 120 slider (settable, float) Value: -0.10000000149011612, Details: -0.1, ID: photo-pan-y - 121 button 사진 구도 초기화, ID: photo-reset - 59 container - 60 button (expanded) 개발 비교, Secondary Actions: Collapse - 61 text 개발 비교 - 62 text 동영상 선택 - 63 button 동영상 선택, ID: video - 64 text Depth 이미지 선택 - 65 button Depth 이미지 선택, ID: depth-image - 66 text View Mode - 67 pop up button (collapsed, settable) View Mode, Value: Final, ID: view-mode, Secondary Actions: Expand - 68 menu - 69 (selected) Final - 70 No Glass - 71 RGB - 72 Depth - 73 Glass Only - 74 text Glass - 75 pop up button (collapsed, settable) Glass, Value: Mosaic, ID: effect, Secondary Actions: Expand - 76 menu - 77 (selected) Mosaic - 78 Reeded - 79 Frosted - 80 text Mosaic 스타일 - 81 pop up button (collapsed, settable) Mosaic 스타일, Value: 조각 유리, ID: mosaic-style, Secondary Actions: Expand - 82 menu - 83 (selected) 조각 유리 - 84 촘촘 유리 - 85 text Depth Scale - 86 container Depth Scale 0.25, ID: depthOut - 87 text 0.25 - 88 slider (settable, float) Value: 0.25, ID: depth-scale - 89 text 조명 가로 - 90 container 조명 가로 0.6, ID: lightXOut - 91 text 0.60 - 92 slider (settable, float) Value: 0.6000000238418579, Details: 0.6, ID: light-x - 93 text 조명 세로 - 94 container 조명 세로 0.8, ID: lightYOut - 95 text 0.80 - 96 slider (settable, float) Value: 0.800000011920929, Details: 0.8, ID: light-y - 97 text View sensitivity - 98 container View sensitivity 1, ID: sensitivityOut - 99 text 1.00 - 100 slider (settable, integer) Value: 1, ID: sensitivity - 104 text 자동 AI 추정 depth를 적용했습니다. - -The focused UI element is 120 slider (settable, float) Value: -0.10000000149011612, Details: -0.1, ID: photo-pan-y \ No newline at end of file diff --git a/docs/qa-varied-dogs-2026-09-23/framing-reload-completed.txt b/docs/qa-varied-dogs-2026-09-23/framing-reload-completed.txt deleted file mode 100644 index 8faf964..0000000 --- a/docs/qa-varied-dogs-2026-09-23/framing-reload-completed.txt +++ /dev/null @@ -1,7 +0,0 @@ -Browser tab: 1, Title: "Pet Behind Glass", URL: "http://127.0.0.1:5174/". -The following is a diff from the previous accessibility tree with ~ and + representing changed and added elements, respectively. Removed elements are summarized by ID range. -Removed element IDs: 122 -~ 15 button AI 깊이 생성, ID: ai-depth -+ 126 text AI 추정 · Depth Anything V2 Small (상대 깊이, 0=뒤 · 1=앞) -+ 127 text 자동 AI 추정 depth를 적용했습니다. -The focused UI element is 25 button 선택한 테스트 사진 불러오기, ID: sample \ No newline at end of file diff --git a/docs/qa-varied-dogs-2026-09-23/framing-reload-immediate.txt b/docs/qa-varied-dogs-2026-09-23/framing-reload-immediate.txt deleted file mode 100644 index 85d7215..0000000 --- a/docs/qa-varied-dogs-2026-09-23/framing-reload-immediate.txt +++ /dev/null @@ -1,16 +0,0 @@ -Browser tab: 1, Title: "Pet Behind Glass", URL: "http://127.0.0.1:5174/". -The following is a diff from the previous accessibility tree with ~ and + representing changed and added elements, respectively. Removed elements are summarized by ID range. -Removed element IDs: 103-104, 111, 115, 119 -~ 15 button (disabled) AI 깊이 생성 중…, ID: ai-depth -+ 122 text Depth 없음 · 평면 사진 테스트 -~ 110 container 사진 확대 1, ID: photoZoomOut -+ 123 text 1.00 -~ 112 slider (settable, integer) Value: 1, ID: photo-zoom -~ 114 container 사진 가로 위치 0, ID: photoPanXOut -+ 124 text 0.00 -~ 116 slider (settable, integer) Value: 0, ID: photo-pan-x -~ 118 container 사진 세로 위치 0, ID: photoPanYOut -+ 125 text 0.00 -~ 120 slider (settable, integer) Value: 0, ID: photo-pan-y -+ 126 text AI 모델 다운로드 중 · 100% -The focused UI element is 25 button 선택한 테스트 사진 불러오기, ID: sample \ No newline at end of file diff --git a/docs/qa-varied-dogs-2026-09-23/report.md b/docs/qa-varied-dogs-2026-09-23/report.md deleted file mode 100644 index 460e866..0000000 --- a/docs/qa-varied-dogs-2026-09-23/report.md +++ /dev/null @@ -1,123 +0,0 @@ -# 다양한 강아지 사진 QA 결과 — 2026-09-23 - -기존 샘플 1장과 강아지 사진 4장으로 로컬 브라우저 QA를 진행했다. 강아지 사진 4장의 자동 AI 깊이 생성과 화면 출력을 확인했으며, **같은 사진을 다시 불러오면 수동 구도가 초기화되는 결함**을 재현했다. 어두운 얼굴과 작은 얼굴은 기본 Grid13에서 눈·코 식별성이 크게 낮아졌다. 두 마리 사진과 닥스훈트 사진은 Grid24에서 세부 구조가 더 남았지만, Ref1의 유리 표현을 충족했다고 판정하지는 않았다. - -이번 작업의 산출물은 QA 기록·스크린샷·진단 JSON이다. 소스 코드, 셰이더, 스타일, 빌드 설정과 테스트 코드는 수정하지 않았다. - -## 1. 검증 조건과 범위 - -| 항목 | 조건 | -| --- | --- | -| 실행 주소 | `http://127.0.0.1:5174/` | -| 주 시각 기준 | Ref1. Ref2는 보조 비교 자료 | -| 기본 효과 | Final / Mosaic / 조각 유리 | -| 기본값 | Grid13, 굴곡 +1, 광택 0.30, Camera Offset 0.50, Depth Scale 0.25 | -| 사진 구도 | 확대 1.00, 가로 0.00, 세로 0.00. 구도 재현 실험에서만 수동 변경 | -| 고정값 | 색면 단순화 1, 굴절 1 | -| 깊이 출처 | 기존 샘플: 수작업·절차적 근사. dog1–4: Depth Anything V2 Small AI 추정 | -| 모바일 확인 | 브라우저 뷰포트 390×844, DPR 1. 실제 휴대폰 검증은 아님 | - -AI 성공 문구와 깊이 출처 표시를 함께 확인했다. AI 완료 시 Final로 전환되므로 No Glass 비교는 추론 완료 후 선택했다. 사진 전환은 카메라를 초기화하지 않으므로 중앙 비교에는 시점 초기화를 사용했다. No Glass도 깊이로 변형된 사진 표면이며, 변형 없는 원본 RGB와 동일하다고 해석하지 않는다. - -## 2. 사진별 결과 - -| 사진 | 기능 검증 | 시각 관찰 및 증거 | -| --- | --- | --- | -| 기존 샘플 | 수작업 깊이 출처, No Glass 중앙/드래그, Final Grid13 | [Grid13](D:/project/behind_glass/docs/qa-varied-dogs-2026-09-23/sample-grid13.png). 초기 No Glass 캡처의 크롭은 아래 증거 제한 참고 | -| dog1 · 잔디 위 흰 포메라니안 | 자동 AI 성공, No Glass, Final Grid13, 모바일 재검증 성공 | 흰 몸과 어두운 눈·코가 비교적 구분된다. [No Glass](D:/project/behind_glass/docs/qa-varied-dogs-2026-09-23/dog1-noglass.png) · [Grid13](D:/project/behind_glass/docs/qa-varied-dogs-2026-09-23/dog1-grid13.png) | -| dog2 · 실내의 검정·갈색 강아지 | 자동 AI 성공, No Glass 중앙/드래그, Final Grid13 | 실루엣은 남지만 어두운 얼굴의 눈·코가 큰 색면에 섞인다. [No Glass](D:/project/behind_glass/docs/qa-varied-dogs-2026-09-23/dog2-noglass.png) · [Grid13](D:/project/behind_glass/docs/qa-varied-dogs-2026-09-23/dog2-grid13.png) | -| dog3 · 후드 옷을 입은 두 마리 | 서버 복구 후 자동 AI 성공, No Glass, Grid13/24, Grid24 드래그 | Grid13에서 작은 얼굴 정보가 대부분 사라진다. Grid24는 얼굴·옷·배경 구조를 더 남기지만 블록화 인상이 강하다. [No Glass](D:/project/behind_glass/docs/qa-varied-dogs-2026-09-23/dog3-noglass.png) · [드래그](D:/project/behind_glass/docs/qa-varied-dogs-2026-09-23/dog3-grid24-drag.png) | -| dog4 · 벤치 위 갈색 닥스훈트 | 자동 AI와 수동 AI 재생성 성공, No Glass, Grid13/24, 모바일 확인, 구도 대조 실험 | Grid13에서 갈색·어두운 얼굴 정보가 합쳐진다. Grid24는 구조를 더 남기며, 머리·오른쪽의 창문 모양 반사가 두드러진다. [No Glass](D:/project/behind_glass/docs/qa-varied-dogs-2026-09-23/dog4-noglass.png) · [Grid13](D:/project/behind_glass/docs/qa-varied-dogs-2026-09-23/dog4-grid13.png) · [Grid24](D:/project/behind_glass/docs/qa-varied-dogs-2026-09-23/dog4-grid24.png) | - -두 마리 사진의 같은 구도 비교: - -| Grid13 | Grid24 | -| --- | --- | -| ![두 마리 강아지 Grid13](D:/project/behind_glass/docs/qa-varied-dogs-2026-09-23/dog3-grid13.png) | ![두 마리 강아지 Grid24](D:/project/behind_glass/docs/qa-varied-dogs-2026-09-23/dog3-grid24.png) | - -이 평가는 저장된 출력의 시각 관찰이다. 출력이 블록처럼 보인다는 사실만으로 셰이더가 단순 저해상도 확대를 사용한다고 결론 내리지는 않는다. Grid24의 개선도 Ref1 재현 완료나 눈·코 식별성의 일반적인 보장을 뜻하지 않는다. - -## 3. 재현된 결함: 같은 사진 재불러오기 시 구도 초기화 - -**우선 수정 대상.** 자동 구도 변경 금지 요구사항과 충돌하며, 사용자가 맞춘 확대·팬을 잃는다. - -1. dog4를 불러오고 AI 생성 완료를 확인한다. -2. 사진 구도를 확대 **1.50**, 가로 **+0.10**, 세로 **−0.10**으로 설정한다. -3. 선택 사진을 바꾸지 않고 **선택한 테스트 사진 불러오기**를 누른다. -4. AI 생성이 진행 중인 시점에 이미 **1.00 / 0.00 / 0.00**으로 초기화된다. AI 완료 후에도 초기값이 유지된다. - -대조 실험에서는 같은 수동 구도에서 사진을 다시 불러오지 않고 **AI 깊이 생성**만 실행했다. 이때는 생성 중과 성공 후 모두 **1.50 / +0.10 / −0.10**이 유지됐다. 따라서 재현된 원인은 사진 로드 경로의 구도 초기화이며, AI 완료 단계가 구도 값을 초기화하는 것으로 보고하지 않는다. - -| 조건 | 실행 전 | 실행 중 | 완료 후 | -| --- | --- | --- | --- | -| 같은 사진 재불러오기 | 1.50 / +0.10 / −0.10 | 1.00 / 0.00 / 0.00 | 1.00 / 0.00 / 0.00 | -| 사진 재불러오기 없이 AI 재생성 | 1.50 / +0.10 / −0.10 | 1.50 / +0.10 / −0.10 | 1.50 / +0.10 / −0.10 | - -실제 코드의 [src/main.ts:210](D:/project/behind_glass/src/main.ts:210)에서 `applyMedia()`가 `photoZoom = 1; photoPanX = 0; photoPanY = 0;`을 수행한다. 이 공통 경로는 다른 미디어 로드에도 적용될 가능성을 보여주지만, 브라우저에서 직접 재현한 범위는 **같은 테스트 사진 재불러오기**다. - -증거: [변경 전](D:/project/behind_glass/docs/qa-varied-dogs-2026-09-23/framing-before-reload.txt), [재불러오기 직후](D:/project/behind_glass/docs/qa-varied-dogs-2026-09-23/framing-reload-immediate.txt), [재불러오기 완료](D:/project/behind_glass/docs/qa-varied-dogs-2026-09-23/framing-reload-completed.txt), [AI만 재생성 중](D:/project/behind_glass/docs/qa-varied-dogs-2026-09-23/framing-ai-regenerate-start.txt), [AI만 재생성 완료](D:/project/behind_glass/docs/qa-varied-dogs-2026-09-23/framing-ai-regenerate-completed.txt). - -| 사진 재불러오기 전 | 사진 재불러오기 후 | -| --- | --- | -| ![수동 구도 설정](D:/project/behind_glass/docs/qa-varied-dogs-2026-09-23/framing-before-reload.png) | ![재불러오기 후 구도 초기화](D:/project/behind_glass/docs/qa-varied-dogs-2026-09-23/framing-after-reload.png) | - -수정 후에는 같은 사진 재불러오기, 다른 사진 입력, AI만 재생성, 명시적인 사진 구도 초기화 버튼을 구분해 검증해야 한다. 이번 QA에서는 수정하지 않았다. - -## 4. 모바일 재검증과 최종 콘솔 - -초기 `dog1-mobile-grid13.png`에는 앱이 왼쪽에 작게 나타나는 이상 캡처가 있었다. 이후 dog4와 dog1을 390×844에서 다시 확인했을 때는 정상 크기의 세로 배치가 나타났으며, **이전 축소 현상은 재현되지 않았다**. 초기 캡처의 원인을 확정하거나 모바일 전체가 정상이라고 판정하지 않는다. - -dog1을 새로 불러와 자동 AI 성공을 확인한 뒤 측정한 값: - -| 측정값 | 결과 | -| --- | --- | -| `innerWidth × innerHeight` | 390 × 844 | -| DPR / `visualViewport.scale` | 1 / 1 | -| `scrollX / scrollY` | 0 / 0 | -| 문서 `scrollWidth` | 375 — 측정 시 가로 넘침 없음 | -| Canvas | x=0, y=200, 폭 375, 높이 506.390625 | -| 조절 패널 `aside` | x=0, y=706.390625, 폭 375, 높이 966 | - -![포메라니안 모바일 재검증](D:/project/behind_glass/docs/qa-varied-dogs-2026-09-23/dog1-mobile-retest-viewport.png) - -추가 증거: [닥스훈트 모바일 화면](D:/project/behind_glass/docs/qa-varied-dogs-2026-09-23/dog4-mobile-viewport.png) · [닥스훈트 전체 페이지](D:/project/behind_glass/docs/qa-varied-dogs-2026-09-23/dog4-mobile-fullpage.png). - -최종 콘솔 조회는 `error`·`warn` 수준, 최대 100건 범위에서 **빈 배열 `[]`**이었다. 이는 해당 탭에서 도구에 수집된 로그의 조회 결과이며, 모든 과거 세션이나 실제 휴대폰의 오류가 없음을 증명하지 않는다. - -임시 뷰포트 오버라이드를 `reset()`으로 해제했고, 이후 크기는 **1280×720**이었다. 최종 사진은 dog1이며, Final / Mosaic / 조각 유리, Grid13, 굴곡 +1, 광택 0.30, Camera Offset 0.50, Depth Scale 0.25, 확대·팬 1/0/0을 DOM 값으로 확인했다. 상태는 `자동 AI 추정 depth를 적용했습니다.`였다. 측정값·최종 설정·콘솔 결과는 [final-diagnostics.json](D:/project/behind_glass/docs/qa-varied-dogs-2026-09-23/final-diagnostics.json)에 저장했다. - -## 5. 기존 검사 결과와 테스트 유지보수 사항 - -다음은 **앞선 QA 단계에서 기록한 종료 코드 0 결과**다. 이번 마무리 단계에서는 소스 변경이 없어 재실행하지 않았다. - -```text -npm.cmd run build -node scripts/test-camera-history.mjs -node scripts/test-mosaic-continuity.mjs -node scripts/test-mosaic-depth-distance.mjs -node scripts/test-region-atlas-dark-sampling.mjs -node scripts/test-region-axis-split.mjs -node scripts/test-surface-reflection.mjs -node scripts/test-window-reveal-coverage.mjs -``` - -빌드 기록에는 500kB 초과 청크 경고가 있었다. 메인 JavaScript는 524.84kB, AI worker는 878.03kB였다. 이 수치만으로 로딩 시간이나 추론 성능을 판정하지 않는다. - -**테스트 코드에서 확인한 유지보수 사항:** - -- [test-region-axis-split.mjs:115](D:/project/behind_glass/scripts/test-region-axis-split.mjs:115)의 별도 JavaScript 모델은 안전한 어두운 palette 선택을 구현하며, [151행](D:/project/behind_glass/scripts/test-region-axis-split.mjs:151)은 안전한 색이 없으면 원본 RGB를 유지하는 동작을 검사한다. 최신 요구사항은 최종 픽셀의 원본 RGB 복원 분기를 제거하는 것이므로, 이 테스트 통과를 현행 셰이더의 눈·코 보호나 시각 품질 검증으로 사용할 수 없다. -- **실행하지 않은** [ai-depth-smoke.mjs:69](D:/project/behind_glass/scripts/ai-depth-smoke.mjs:69)는 AI 완료 후 캡처를 `no-glass.png`로 저장한다. 관찰된 앱은 AI 완료 시 Final로 돌아가므로 파일명이 실제 모드를 보장하지 않는다. [105행](D:/project/behind_glass/scripts/ai-depth-smoke.mjs:105)은 사진 전환 후 AI 버튼 활성화·깊이 출처 숨김을 기대하는데, 현재 사진 입력은 자동 AI를 시작하고 성공 시 출처를 표시한다. 이 기대값도 현재 흐름에 맞춘 검토가 필요하다. - -이 검사는 GPU 출력, 실제 AI 추론 성공, Ref1과의 시각적 유사성을 대신하지 않는다. `test-window-reveal-coverage`는 실제 클래스를 CPU raycasting으로 검사하지만 화면 렌더링 검사는 아니다. - -## 6. 증거의 한계와 남은 검증 - -기존 수작업 샘플의 드래그 실험 기록에서는 카메라 X가 0.065일 때 코의 투영 X가 520.448→516.144, 왼쪽 눈은 493.625→490.020, 몸은 453.585→450.871로 이동했다. 이는 **수작업 샘플의 깊이별 투영 차이**를 지지한다. dog2의 No Glass 드래그와 dog3의 Final 드래그도 시각적 변화를 보였지만, AI가 추정한 코·눈 깊이의 정확도는 정량 측정하지 않았다. - -초기 `sample-noglass-center.png`와 `sample-noglass-drag.png`는 stage 크롭을 사용했으나 출력에 레퍼런스 영역이 포함된 정황이 있어, 이 두 이미지의 크롭을 정밀 비교 근거로 사용하지 않는다. 이후 사진들은 일반 뷰포트 캡처를 사용했다. - -dog3의 첫 로드 실패 시점에는 5174 포트의 개발 서버가 내려가 있었다. 서버를 다시 실행한 뒤 같은 사진의 로드와 AI 추론이 성공했다. **WebP 디코딩 결함으로 분류할 근거는 없다.** - -실제 휴대폰 터치·자이로, 모바일 GPU와 FPS, 영상 플리커, 장시간 메모리·자원 해제, AI 중단/연속 입력의 모든 경합 상황, AI 깊이 정확도, 다른 유리 모드 전체 회귀는 이번 확인 범위에 포함되지 않는다. 샘플 사진과 QA 산출물을 외부에 게시하지 않았다. - -현재 우선순위는 **사진 로드 시 수동 구도 보존 결함 수정**, 다음으로 **어두운 얼굴·작은 얼굴의 식별성과 Ref1 표현 재평가**, 그리고 **현행 동작과 어긋난 테스트 기대값 정리**다. diff --git a/docs/qa-varied-dogs-2026-09-23/sample-grid13.png b/docs/qa-varied-dogs-2026-09-23/sample-grid13.png deleted file mode 100644 index b306b11..0000000 Binary files a/docs/qa-varied-dogs-2026-09-23/sample-grid13.png and /dev/null differ diff --git a/docs/qa-varied-dogs-2026-09-23/sample-noglass-center.png b/docs/qa-varied-dogs-2026-09-23/sample-noglass-center.png deleted file mode 100644 index de9acca..0000000 Binary files a/docs/qa-varied-dogs-2026-09-23/sample-noglass-center.png and /dev/null differ diff --git a/docs/qa-varied-dogs-2026-09-23/sample-noglass-drag.png b/docs/qa-varied-dogs-2026-09-23/sample-noglass-drag.png deleted file mode 100644 index 2e4797b..0000000 Binary files a/docs/qa-varied-dogs-2026-09-23/sample-noglass-drag.png and /dev/null differ diff --git a/docs/qa-window-immersion/atlas-dark-sampling.md b/docs/qa-window-immersion/atlas-dark-sampling.md deleted file mode 100644 index a673757..0000000 --- a/docs/qa-window-immersion/atlas-dark-sampling.md +++ /dev/null @@ -1,7 +0,0 @@ -# Atlas dark-feature sampling baseline - -This folder preserves the pre-change src/shaders/mosaic.frag as baseline-mosaic.frag so the Option2 atlas behavior remains reproducible. - -The focused change probes four fixed cardinal offsets inside one 8x8 atlas texel footprint during REGION_ATLAS construction. Each probe uses the existing projected scene UV for both source RGB and front-depth evidence. A probe is accepted only when its .80-.95 front-depth and .10-.20 luminance evidence are stronger than the center sample; the representative blend is capped at .4. Center, far, invalid, and uniform cells retain the old result. - -The added regression is a source/math-only check in scripts/test-region-atlas-dark-sampling.mjs; it does not claim browser visual success. The extra cost is four RGB probes per atlas texel, plus the existing validity/evidence lookups for those probe UVs. The final display pass, palette fitting, optical path, history, and camera gain are unchanged. diff --git a/docs/qa-window-immersion/baseline-mosaic.frag b/docs/qa-window-immersion/baseline-mosaic.frag deleted file mode 100644 index 01c6e3a..0000000 --- a/docs/qa-window-immersion/baseline-mosaic.frag +++ /dev/null @@ -1,234 +0,0 @@ -uniform sampler2D uSceneTexture,uSceneDepth; -uniform sampler2D uProtectionDepthMap; -uniform mat4 uContentViewProjection,uContentInverseViewProjection; -uniform mat4 uPetWorldToLocal; -uniform vec3 uContentCameraPosition,uLightPosition,uBackgroundColor; -uniform float uGlassZ,uSourceZ,uGridSize,uStrength,uMosaicStyle,uCurvature,uGlossStrength; -uniform vec2 uViewOffset,uPetSize,uPaneSize; -uniform vec4 uPaneRect; -uniform sampler2D uRegionPalette; -uniform sampler2D uRegionAtlas,uRegionHistory; -uniform vec2 uRegionAtlasSize,uRegionGridSize,uRegionPaletteSize; -uniform float uRegionStrength,uRegionAvailable; -varying vec2 vUv; -vec2 projectUv(vec3 p){vec4 c=uContentViewProjection*vec4(p,1.);float w=abs(c.w)<.0001?(c.w<0.?-.0001:.0001):c.w;return c.xy/w*.5+.5;} -vec4 sampleScene(vec2 uv){return texture2D(uSceneTexture,clamp(uv,0.,1.));} -vec4 samplePane(vec2 pane){return sampleScene(projectUv(vec3((pane-.5)*uPaneSize,uGlassZ)));} -float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);} -vec2 hash2(vec2 p){return vec2(hash(p),hash(p+vec2(19.19,73.73)));} -vec2 cellBlurStep(vec2 cell,vec2 cellSize,float style){ - if(style<=.5)return cellSize*mix(.006,.018,hash(cell+vec2(5.))); - return cellSize*mix(.006,.012,hash(cell+vec2(5.))); -} -vec4 sampleCell(vec2 pane,vec2 sourceUv,float strength,vec2 cell,vec2 cellSize,float style){ - vec2 center=mix(pane,sourceUv,strength); - vec2 blurOffset=strength*cellBlurStep(cell,cellSize,style); - vec4 color; - if(style<=.5){ - color=samplePane(center)*.6; - color+=samplePane(center+vec2(blurOffset.x,0.))*.1; - color+=samplePane(center-vec2(blurOffset.x,0.))*.1; - color+=samplePane(center+vec2(0.,blurOffset.y))*.1; - color+=samplePane(center-vec2(0.,blurOffset.y))*.1; - }else{ - color=samplePane(center)*.4; - color+=samplePane(center+vec2(blurOffset.x,0.))*.15; - color+=samplePane(center-vec2(blurOffset.x,0.))*.15; - color+=samplePane(center+vec2(0.,blurOffset.y))*.15; - color+=samplePane(center-vec2(0.,blurOffset.y))*.15; - } - return color; -} -float safeZ(float z){return abs(z)<.0001?(z<0.?-.0001:.0001):z;} -vec3 bend(vec3 i,vec3 n){vec3 r=refract(i,n,.75);return length(r)<.0001?i:r;} -float softLimit(float value,float limit){return value*limit/(limit+abs(value));} -float surfaceCurvature(){float curvature=clamp(uCurvature,-1.,1.),excess=max(curvature-.65,0.);return curvature-(.25/.35)*excess*excess;} -float signedCurvatureScale(){return clamp(surfaceCurvature()/.65,-1.25,1.25);} -float regionDistance(vec3 a,vec3 b){vec3 d=a-b;float y=dot(d,vec3(.299,.587,.114));return dot(d,d)+.35*y*y;} -float regionLuminance(vec3 c){return dot(c,vec3(.299,.587,.114));} -vec3 regionColor(vec2 cell,float index){vec2 uv=(vec2(cell.x*5.+index,cell.y)+.5)/uRegionPaletteSize;return texture2D(uRegionPalette,uv).rgb;} -float nearestRegion(vec3 color,vec2 cell){float best=0.,distance=regionDistance(color,regionColor(cell,0.));for(int i=1;i<4;i++){float candidate=regionDistance(color,regionColor(cell,float(i)));if(candidate1.||sceneUv.y<0.||sceneUv.y>1.)return false; - float depth=texture2D(uSceneDepth,sceneUv).x; - if(depth>=.999999)return false; - vec4 clip=vec4(sceneUv*2.-1.,depth*2.-1.,1.); - vec4 world=uContentInverseViewProjection*clip; - if(abs(world.w)<.0001)return false; - worldPoint=world.xyz/world.w; - return true; -} -float regionSurfaceValid(vec2 sceneUv,vec3 glassHit){ - vec3 worldPoint; - if(!reconstructScenePoint(sceneUv,worldPoint))return 0.; - float axialGap=glassHit.z-worldPoint.z; - if(axialGap<=.0001)return 0.; - return 1.; -} -float regionProtectionWeight(vec2 sceneUv){ - vec3 worldPoint; - if(!reconstructScenePoint(sceneUv,worldPoint))return 0.; - vec3 localPoint=(uPetWorldToLocal*vec4(worldPoint,1.)).xyz; - if(localPoint.x<-.5||localPoint.x>.5||localPoint.y<-.5||localPoint.y>.5)return 0.; - vec2 sourceUv=localPoint.xy+.5; - float sourceDepth=texture2D(uProtectionDepthMap,sourceUv).r; - return smoothstep(.8,.95,sourceDepth); -} -void evaluateCell(vec2 cell,vec2 local,vec2 grid,vec2 cellSize,vec2 cellDimensions,float cellWorld,float opticalTravel,float style,out vec2 affineUv,out mat2 transform,out vec2 curvedSlope,out vec2 facetSlope){ - vec2 random=hash2(cell),widths; - if(style>.5){ - widths=mix(vec2(.82),vec2(1.12),hash2(cell+vec2(11.4,9.8))); - float angle=(random.x-.5)*.08,c=cos(angle),s=sin(angle); - transform=mat2(widths.x*c,-widths.y*s,widths.x*s,widths.y*c); - float centerJitter=.16; - vec2 sourceCenter=(cell+.5)/grid+(random-.5)*centerJitter*cellSize; - affineUv=sourceCenter+transform*(local*cellSize); - }else{ - // Default style keeps a single continuous image footprint across cells. - transform=mat2(1.); - affineUv=(cell+.5)/grid+local*cellSize; - } - - // Positive height bulges toward the observer (+Z); negative height is concave. - float curvature=clamp(uCurvature,-1.,1.),surfaceCurvatureValue=surfaceCurvature(); - vec2 q=clamp(2.*local,-1.,1.),q2=q*q,q3=q2*q,b=1.-q2*q2; - if(style>.5){ - float amplitude=mix(.92,1.08,hash(cell+vec2(41.7,17.3))),height=.009*cellWorld*surfaceCurvatureValue*amplitude; - vec2 skew=(hash2(cell+vec2(23.8,61.2))-.5)*.28;float asym=1.+dot(skew,q); - vec2 dhdq=height*vec2(-4.*q3.x*b.y*asym+b.x*b.y*skew.x,-4.*q3.y*b.x*asym+b.x*b.y*skew.y); - vec2 grad=-2.*dhdq/cellDimensions; - curvedSlope=grad+(random-.5)*.012;facetSlope=(random-.5)*.012; - }else{ - curvedSlope=.30*cellDimensions/max(abs(opticalTravel),.6)*signedCurvatureScale()*sin(6.2831853*local); - facetSlope=vec2(0.); - } -} -void main(){ - vec2 screenUv=vUv; -#ifdef REGION_ATLAS - vec2 atlasPixel=floor(vUv*uRegionAtlasSize),atlasCell=floor(atlasPixel/8.),atlasLocal=(mod(atlasPixel,8.)+.5)/8.; - vec2 atlasPaneUv=(atlasCell+atlasLocal)/uRegionGridSize; - screenUv=projectUv(vec3((atlasPaneUv-.5)*uPaneSize,uGlassZ)); -#endif - if(uStrength<=.001){ -#ifdef REGION_ATLAS - gl_FragColor=vec4(sampleScene(screenUv).rgb,0.); -#else - gl_FragColor=sampleScene(screenUv); - #include -#endif - return;} - vec4 f=uContentInverseViewProjection*vec4(screenUv*2.-1.,1.,1.);float fw=abs(f.w)<.0001?(f.w<0.?-.0001:.0001):f.w;vec3 farWorld=f.xyz/fw;vec3 i=normalize(farWorld-uContentCameraPosition);float gt=(uGlassZ-uContentCameraPosition.z)/safeZ(i.z);vec3 gh=uContentCameraPosition+i*gt; - vec2 paneUv=gh.xy/uPaneSize+.5;vec2 grid=vec2(uGridSize,max(1.,uGridSize*uPaneSize.y/uPaneSize.x));vec2 gridUv=paneUv*grid,cell=floor(gridUv),local=fract(gridUv)-.5,cellSize=1./grid;float style=clamp(uMosaicStyle,0.,1.),cellWorld=min(uPaneSize.x/grid.x,uPaneSize.y/grid.y); -#ifdef REGION_ATLAS - paneUv=atlasPaneUv;grid= uRegionGridSize;gridUv=paneUv*grid;cell=floor(gridUv);local=fract(gridUv)-.5;cellSize=1./grid;cellWorld=min(uPaneSize.x/grid.x,uPaneSize.y/grid.y); -#endif - if(paneUv.x<0.||paneUv.x>1.||paneUv.y<0.||paneUv.y>1.){ -#ifdef REGION_ATLAS - gl_FragColor=vec4(uBackgroundColor,0.); -#else - gl_FragColor=vec4(uBackgroundColor,1.); - #include -#endif - return;} - vec2 cellDimensions=uPaneSize/grid; - float opticalTravel=-max(abs(uSourceZ-gh.z),.6); - vec2 affineUv,curvedSlope,facetSlope;mat2 transform; - evaluateCell(cell,local,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,affineUv,transform,curvedSlope,facetSlope); - if(style<=.5){ - vec2 smoothFacet=.003*vec2(sin(6.2831853*paneUv.x),sin(6.2831853*paneUv.y)); - curvedSlope+=smoothFacet;facetSlope=smoothFacet; - }else{ - vec2 edge=.5-abs(local),neighborSign=mix(vec2(-1.),vec2(1.),step(vec2(0.),local)); - float normalBlend=.16; - vec2 weights=1.-smoothstep(vec2(-normalBlend),vec2(normalBlend),edge); - float xSplitWeight=weights.x*(1.-weights.y),ySplitWeight=(1.-weights.x)*weights.y; - float diagonalSplitWeight=weights.x*weights.y,centerSplitWeight=(1.-weights.x)*(1.-weights.y); - if(weights.x>0.||weights.y>0.){ - vec2 neighborAffine,neighborCurved,neighborFacet;mat2 neighborTransform; - vec2 xWeight=vec2(xSplitWeight,0.); - vec2 yWeight=vec2(0.,ySplitWeight); - affineUv*=centerSplitWeight;transform*=centerSplitWeight;curvedSlope*=centerSplitWeight;facetSlope*=centerSplitWeight; - if(xWeight.x>0.){ - vec2 offset=vec2(neighborSign.x,0.); - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*xWeight.x;transform+=neighborTransform*xWeight.x;curvedSlope+=neighborCurved*xWeight.x;facetSlope+=neighborFacet*xWeight.x; - } - if(yWeight.y>0.){ - vec2 offset=vec2(0.,neighborSign.y); - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*yWeight.y;transform+=neighborTransform*yWeight.y;curvedSlope+=neighborCurved*yWeight.y;facetSlope+=neighborFacet*yWeight.y; - } - if(diagonalSplitWeight>0.){ - vec2 offset=neighborSign; - evaluateCell(cell+offset,local-offset,grid,cellSize,cellDimensions,cellWorld,opticalTravel,style,neighborAffine,neighborTransform,neighborCurved,neighborFacet); - affineUv+=neighborAffine*diagonalSplitWeight;transform+=neighborTransform*diagonalSplitWeight;curvedSlope+=neighborCurved*diagonalSplitWeight;facetSlope+=neighborFacet*diagonalSplitWeight; - } - } - } - vec3 nCurved=normalize(vec3(curvedSlope,1.)),nFacet=normalize(vec3(facetSlope,1.)); - vec3 straightHit=gh+i*((uSourceZ-gh.z)/safeZ(i.z)); - vec3 curvedRay=bend(i,nCurved),curvedHit=gh+curvedRay*((uSourceZ-gh.z)/safeZ(curvedRay.z)); - // Keep the artistic Mosaic optical path independent of physical glass-to-photo contact distance. - vec2 rawDelta=(curvedRay.xy/safeZ(curvedRay.z)-i.xy/safeZ(i.z))*opticalTravel; - vec2 worldDelta=vec2(softLimit(rawDelta.x,cellWorld*.55),softLimit(rawDelta.y,cellWorld*.55)); - if(style>.5){ - vec3 facetRay=bend(i,nFacet);vec3 facetHit=gh+facetRay*((uSourceZ-gh.z)/safeZ(facetRay.z)); - vec2 base=facetHit.xy-straightHit.xy,curve=curvedHit.xy-facetHit.xy; - worldDelta=vec2(softLimit(base.x,cellWorld*.08),softLimit(base.y,cellWorld*.08)); - vec2 d=curve/cellWorld; - worldDelta+=vec2(.3*d.x/(.3+abs(d.x)),.3*d.y/(.3+abs(d.y)))*cellWorld; - }else{ - vec3 referenceI=normalize(gh-vec3(0.,0.,uContentCameraPosition.z)),referenceRay=bend(referenceI,nCurved); - vec2 incidenceDelta=curvedRay.xy/max(-curvedRay.z,.0001)-referenceRay.xy/max(-referenceRay.z,.0001); - vec2 boundedIncidence=incidenceDelta/sqrt(incidenceDelta*incidenceDelta+vec2(.025*.025)); - vec2 cellEnvelope=.5+.5*cos(6.2831853*local); - worldDelta+=boundedIncidence*cellEnvelope*cellDimensions*signedCurvatureScale()*.18; - } - vec2 sampleUv=affineUv+transform*(worldDelta/uPaneSize); - float edgeDistance=min(min(paneUv.x,paneUv.y),min(1.-paneUv.x,1.-paneUv.y));float edgeTaper=style<=.5?1.25:.75;float edgeWeight=smoothstep(0.,max(cellSize.x,cellSize.y)*edgeTaper,edgeDistance);float strength=clamp(uStrength,0.,1.)*edgeWeight; - vec4 color;vec3 sceneHit=straightHit+vec3(worldDelta*strength,0.);vec2 finalSceneUv=projectUv(sceneHit); - if(style<=.5){ - color=sampleScene(finalSceneUv); - }else{ - color=sampleCell(paneUv,sampleUv,strength,cell,cellSize,style); - } -#ifndef REGION_ATLAS - if(uRegionAvailable>.5&&uRegionStrength>.001&&uMosaicStyle<.5){ - vec3 p0=regionColor(cell,0.),p1=regionColor(cell,1.),p2=regionColor(cell,2.),p3=regionColor(cell,3.); - float ownLabel=nearestRegion(color.rgb,p0,p1,p2,p3);vec4 votes=vec4(0.);float totalWeight=0.,ownWeight=0.; - vec2 texelCoord=fract(gridUv)*8.-.5,anchor=floor(texelCoord+.5); - for(int y=-1;y<=1;y++)for(int x=-1;x<=1;x++){ - vec2 offset=vec2(float(x),float(y)),delta=anchor+offset-texelCoord; - float weight=pow(max(0.,1.-length(delta)/1.5),2.); - if(weight>0.){ - vec3 atlasColor=regionAtlasColor(cell,anchor+offset);float label=nearestRegion(atlasColor,p0,p1,p2,p3); - votes+=vec4(step(abs(label-vec4(0.,1.,2.,3.)),vec4(.1)))*weight;totalWeight+=weight; - ownWeight+=step(abs(label-ownLabel),.1)*weight; - } - } - float winningLabel=ownLabel,winningWeight=ownWeight; - if(votes.x>winningWeight){winningLabel=0.;winningWeight=votes.x;}if(votes.y>winningWeight){winningLabel=1.;winningWeight=votes.y;}if(votes.z>winningWeight){winningLabel=2.;winningWeight=votes.z;}if(votes.w>winningWeight){winningLabel=3.;winningWeight=votes.w;} - bool simplify=totalWeight>0.&&winningWeight/totalWeight>.55&&ownWeight/totalWeight<.40; - float radialLabel=simplify?winningLabel:ownLabel;vec3 radialColor=selectRegion(p0,p1,p2,p3,radialLabel); - vec2 historyTexel=clamp(floor(fract(gridUv)*8.),vec2(0.),vec2(7.)); - vec2 historyUv=(cell*8.+historyTexel+.5)/uRegionAtlasSize; - vec4 splitHistory=texture2D(uRegionHistory,historyUv); - vec3 splitColor=splitHistory.a>.00001?splitHistory.rgb/splitHistory.a:radialColor; - vec3 candidateColor=mix(radialColor,splitColor,splitHistory.a); - color.rgb=mix(color.rgb,candidateColor,clamp(uRegionStrength*clamp(uStrength,0.,1.)*regionSurfaceValid(finalSceneUv,gh),0.,1.)); - } -#endif -#ifndef REGION_ATLAS - color.a=1.; - vec3 v=normalize(uContentCameraPosition-gh),reflected=reflect(-v,nCurved); float lightT=(uLightPosition.z-gh.z)/safeZ(reflected.z); vec2 lightHit=gh.xy+reflected.xy*lightT; vec2 halfSize=vec2(.32,.42)*min(uPaneSize.x,uPaneSize.y); vec2 windowCoord=abs(lightHit-uLightPosition.xy)/halfSize; vec2 windowMask=1.-smoothstep(vec2(.45),vec2(1.15),windowCoord); float spec=windowMask.x*windowMask.y*step(.0001,reflected.z)*step(0.,lightT); float gloss=spec*clamp(uGlossStrength,0.,1.)*.12*edgeWeight*clamp(uStrength,0.,1.); color.rgb=mix(color.rgb,vec3(1.),gloss); gl_FragColor=color; - #include -#else - color.a=regionProtectionWeight(finalSceneUv)*(1.-smoothstep(.10,.20,regionLuminance(color.rgb))); - gl_FragColor=color; -#endif -} - diff --git a/docs/qa-window-immersion/verification.md b/docs/qa-window-immersion/verification.md deleted file mode 100644 index 1e38053..0000000 --- a/docs/qa-window-immersion/verification.md +++ /dev/null @@ -1,44 +0,0 @@ -# 창문 뒤 반려동물 경험 개선 검증 - -2026-09-22. 비교 기준은 `docs/ref1-option-2.md`의 Ref1 옵션 2다. - -## 적용 내용 - -- `src/objects/WindowReveal.ts`, `src/main.ts`: 앞쪽 창문 개구부와 사진의 기준 평면 사이를 연결하는 네 면의 안쪽 창틀을 추가했다. 뒤쪽 사각형은 수동 확대·팬과 독립적이며, 사진 구도나 카메라 이동 한계를 보정 수단으로 바꾸지 않는다. 형상은 구도·깊이·리사이즈 변경 시 갱신하며 기존 버퍼를 재사용한다. -- `src/shaders/mosaic.frag`: 기본 Mosaic의 REGION_ATLAS에서 표본당 고정된 주변 네 지점을 추가로 조사한다. 같은 장면 UV에서 RGB와 앞쪽 깊이 증거를 읽으며, 더 강한 가까운 어두운 특징이 있을 때 대표색 혼합을 최대 0.4로 제한한다. 최종 화면의 원본 눈·코 픽셀 복원은 추가하지 않았다. -- `index.html`, `src/main.ts`, `src/input/PointerController.ts`, `src/style.css`: 안내를 “화면을 드래그해서 시점을 움직여보세요”로 명시했다. 안내는 첫 유효 드래그까지 유지하고 새 미디어에서 다시 표시한다. 같은 미디어에서 이미 드래그했다면 AI 깊이 완료가 안내를 다시 띄우지 않는다. 드래그 중 커서도 구분한다. - -기존 Grid 13, 굴곡 +1, 광택 0.30, 색면·굴절 강도 1, Camera Offset 기본 0.50/최대 0.90, 70ms history 및 DPR 상한 1.5를 유지한다. 사진은 기존의 단일 깊이 변위 표면이다. - -## 실행 검증 - -`npm.cmd run build` 통과. TypeScript와 Vite 빌드가 완료됐으며 메인 청크 524.46 kB에 대한 기존 500 kB 초과 경고는 남아 있다. - -다음 여섯 검사 각각 통과: - -```text -node --experimental-strip-types scripts/test-camera-history.mjs -node --experimental-strip-types scripts/test-region-axis-split.mjs -node --experimental-strip-types scripts/test-mosaic-depth-distance.mjs -node --experimental-strip-types scripts/test-mosaic-continuity.mjs -node --experimental-strip-types scripts/test-region-atlas-dark-sampling.mjs -node --experimental-strip-types scripts/test-window-reveal-coverage.mjs -``` - -창틀 검사는 실제 Three.js 메시와 Raycaster를 사용한다. 종횡비 0.7/1.6, 깊이 강도 0/0.25/0.4, 정면 및 ±0.5/±0.9의 가로·세로·대각선 조합 17개에서 개구부 광선 49개씩, 총 4,998개를 확인했다. 기존 네 개의 얕은 창틀 박스와 사진만으로는 146개가 빗나갔고 새 안쪽 면과 사진으로는 모두 교차했다. 형상·위치 버퍼 재사용과 형상별 한 번의 dispose 이벤트도 확인했다. 이는 정해진 형상 표본의 검사이며 모든 실제 사진·렌더링 결과를 보장하지 않는다. - -어두운 특징 검사는 production GLSL의 연결·표본 수·문턱값을 확인하고, 복제한 JavaScript 계산으로 합성 좁은 어두운 특징과 먼 표면·무효 표면·균일 색의 결과를 검사한다. 합성 검사는 GLSL을 실행하는 GPU 검사가 아니며 사진별 시각 품질 개선의 증명으로 해석하지 않는다. - -## 브라우저에서 확인한 범위 - -- dog1의 자동 AI 상대 깊이 생성 완료, 정면 Final에서 큰 사각 색면과 두 눈·코 표현을 확인했다. -- AI 작업 완료 후에도 안내가 유지됐고, 실제 드래그 후 안내 opacity가 0으로 바뀌었다. -- No Glass의 정면과 우측 이동 화면, 같은 이동 상태의 Final을 확인했다. Camera Offset 0.50 및 0.90 설정에서 안쪽 창틀 면과 사진이 접하는 결과를 확인했다. 이번 성공한 드래그의 정규화 이동은 약 +0.8이므로 ±1 끝점 전체의 브라우저 검증으로 기록하지 않는다. -- 다른 기존 샘플로 변경한 뒤 안내가 다시 표시되고 “수작업 테스트 Depth · AI 추정 아님”이 유지됨을 확인했다. -- 조회한 콘솔 로그에 실행 오류는 없었다. 기존 셰이더 X3595 경고(가변 반복문 안 gradient 연산)는 남아 있다. - -일부 추가 브라우저 드래그는 자동 승인 검토에서 보안 상태를 결정하지 못해 차단됐다. 전체 좌우·상하·대각선 끝점은 위 형상 검사에서 검증했으며 전체 실화면 검증은 완료하지 못했다. 모바일 FPS, 연속 영상의 깜빡임 계측, 실제 변위 정점의 유리 간격 측정도 이번 검증에 포함하지 않는다. - -## 비교 자료와 한계 - -수정 전 Mosaic 셰이더는 `baseline-mosaic.frag`에 보존되어 있다. UI·창틀의 수정 전 스냅샷은 없으며, 이번 검증에서 수정 전후의 동일 프레임 GPU 비교는 실행하지 않았다. 작은 눈·코가 모든 사진과 시점에서 보존된다고 보장하지 않는다. 숨겨진 옆면이나 배경을 복원하는 기능은 추가하지 않았다. diff --git a/docs/ref1-current-baseline.md b/docs/ref1-current-baseline.md deleted file mode 100644 index 65eb45f..0000000 --- a/docs/ref1-current-baseline.md +++ /dev/null @@ -1,52 +0,0 @@ -# Ref1 목표에 가장 근접한 현재 기준안 - -이 문서의 당시 기준안을 **옵션 1**로 보존한다. 2026-09-14 사용자가 현재 구현·설정을 **목표에 가장 근접한 두 번째 옵션**으로 추가 지정했다. 옵션 2의 정확한 설정과 구현 구분은 `docs/ref1-option-2.md`를 따른다. - -2026-09-14 사용자 지정: 지금까지 적용한 구현과 아래 비교 옵션을 **Ref1 목표에 가장 근접한 현재 기준안**으로 명시하고, 이후 작업은 이 기준안과 비교한다. 이는 지금까지의 프로젝트 내 선택이며 모든 사진의 최적 설정이나 Ref1 완성 판정을 뜻하지 않는다. - -## 기준 옵션 - -2026-09-14 현재 브라우저에서 확인한 비교 설정이다. 앱 초기 기본값과 혼동하지 않는다. - -| 항목 | 현재 기준 비교값 | 앱 기본값/범위 | -|---|---|---| -| View Mode / Glass / 스타일 | Final / Mosaic / 조각 유리 | 동일 | -| 색면 단순화 | 1.00 | 기본 0.65 | -| Grid Size | 10 | 기본 10 | -| Distortion | 1.00 | 기본 0.90 | -| 셀 굴곡 | +1.00 | 기본 +0.65, 범위 -1~+1 | -| 광택 / 조명 XY | 0.30 / 0.60, 0.80 | 동일 | -| Depth Scale | 0.25 | 기본 0.25 | -| Camera Offset | 0.50 | 기본 0.50, 최대 0.90 | -| 사진 확대 / 팬 XY | 1.00 / 0, 0 | 자동 변경 금지 | -| View sensitivity / Gyroscope | 1.00 / OFF | 동일 | - -비교 사진은 멍멍이 1(잔디 위 흰 포메라니안), 브라우저의 AI 추정 상대 depth다. 별도 회귀 확인에는 `public/assets/sample-pet.png`와 수작업 테스트 depth를 사용한다. 수작업 depth를 AI 추정이나 실제 측정으로 표현하지 않는다. 입력 사진의 촬영 구도와 질감이 다르므로 설정 숫자만으로 결과의 일치를 보장하지 않는다. - -## 기준 구현 - -- 공통 장면과 카메라 광선, 부호 있는 곡면 법선을 사용하는 시점 의존 굴절. 독립적인 셀별 무작위 크롭을 사용하지 않는다. -- RGB/Depth 공통 배치와 유리 근접 간격을 유지하고 확대·팬·크롭을 자동 변경하지 않는다. -- 가까운 얼굴의 색면을 줄이던 거리 감쇠는 제거했다. 사진 속 배경도 피사체와 동일한 유효 장면 표면이다. 유효하지 않은 깊이/화면 밖 영역 제외와 사진 배경의 단순화 제외는 다른 개념이다. -- 셀별 8×8 표본과 4색 팔레트, 설명률에 따른 수평·수직 2영역 분할, 복잡한 영역의 radial fallback. -- 셀 내부 시점 반응 계수 0.18. 기본 Mosaic 가장자리 taper 1.25셀, 촘촘 유리는 기존 0.75셀. -- 이산 분할 번호 대신 평가된 색면과 confidence만 70ms history로 보간한다. 원본 굴절은 현재 프레임을 사용한다. -- Ref1 주 기준 / Ref2 보조 비교 배치를 유지한다. - -## 이 기준에서 이어갈 작업 - -현재 기준안에도 잔디 등 배경의 작은 무늬가 많이 남는다. 사용자는 **눈·코의 보호 예외를 제거하고 얼굴과 배경에 같은 색면 규칙을 적용**하도록 정정했다. 눈·코는 결과에서 표정이 읽히는지 평가하는 대상이며, 어두운 픽셀이나 원본 RGB를 별도 보호하는 구현 조건이 아니다. 기존 보호 로직은 이 기준을 기록한 시점의 구현 이력이며 이후 작업에서 제거한다. - -배경까지 큰 면으로 정리하되 전체 사진 블러, 원본 저해상도 확대, 모든 셀의 일괄 단색화로 대체하지 않는다. 시점 반응과 전환 보간을 함께 유지한다. 기준안보다 개선됐는지는 같은 사진·같은 설정의 정면 및 이동 화면으로 확인한다. - -기존 검증 기록: `docs/ref1-shape-review.md`. 최대 대각 시점의 사진 바깥 여백, 실기기 FPS와 연속 영상 flicker 미측정은 기존 한계로 유지한다. - -## 후속 적용 결과 - -최신 방식은 `docs/ref1-dark-color-planes.md`를 따른다. 눈·코 원본 픽셀을 복원하는 대신 깊이·어두움 증거로 사각 색면의 선택을 보정한다. - -추가 정정: 보호 범위를 원본 depth의 앞쪽과 어두운 RGB의 교집합으로 제한한다. 기준 및 결과는 `docs/ref1-depth-protection.md`를 따른다. - -최신 사용자 정정: 아래 보호 제거 실험을 확인한 뒤 눈·코 보호 예외를 다시 유지하기로 했다. 기존 보호를 복원하고 배경 강화 및 SSE 분할은 유지한다. 아래 제거 내용은 실험 이력이며 현재 유지 조건이 아니다. - -위 기준안을 보존한 뒤 눈·코 보호 예외 제거, 사진 배경과 가장자리의 색면 강화, 공통 색 차이 오차를 최소화하는 분할 선택을 적용했다. 적용 내용과 같은 조건의 비교 결과는 `docs/ref1-scene-simplification.md`에 기록한다. 이 문서의 기준 옵션은 비교용 기록이며 앱 기본값을 자동 변경한 것이 아니다. diff --git a/docs/ref1-dark-color-planes.md b/docs/ref1-dark-color-planes.md deleted file mode 100644 index e973483..0000000 --- a/docs/ref1-dark-color-planes.md +++ /dev/null @@ -1,23 +0,0 @@ -# Ref1 어두운 색면 보존 - -사용자 지정: 이 구현과 현재 비교 설정은 **현재 프로젝트에서 Ref1 목표에 가장 근접한 두 번째 옵션**이다. 설정값은 `docs/ref1-option-2.md`에 보존한다. - -2026-09-14 사용자는 깊이 기반 보호 결과가 눈·코만 따로 붙인 듯 보인다고 지적했다. 눈·코도 주변과 같은 사각 면으로 단순화하되, 밝은 얼굴색에 완전히 묻히지 않도록 어두운 색면의 존재를 남기는 방향을 승인했다. - -## 구현 기준 - -- 최종 픽셀의 어두움 보호와 원본 RGB fallback을 제거한다. 색면 강도 슬라이더의 원본/효과 혼합은 유지한다. -- 기존 셀별 8×8 표본의 RGB를 유지하고 alpha에 앞쪽 depth × 어두운 색의 증거를 저장한다. 앞쪽 depth는 기존 0.80~0.95 smoothstep, 어두움은 `1-smoothstep(0.10,0.20,휘도)`이다. 유효하지 않은 표면의 증거는 0이다. -- SSE 후보 선택에서 각 표본의 가중치를 `1+3*증거`로 둔다. 최대 4배이며, 기존 팔레트·사각 분할 후보 안에서 선택한다. 별도로 눈·코를 그리지 않는다. -- 가까운 어두운 증거가 충분한 셀은 사각 분할 confidence를 1로 접근시켜 미세 윤곽 fallback을 줄인다. 셀 평균 증거 0.02~0.06 구간에서 부드럽게 증가한다. -- 70ms 색면 전환 보간, 시점 반응, 배경 색면 및 자동 구도 변경 금지는 유지한다. - -## 한계 - -사각 분할이 작은 눈보다 크면 어두운 면이 확대될 수 있다. 표본에 포착되지 않은 특징을 보존한다고 보장하지 않는다. 얼굴 인식 마스크는 아니므로 가까운 다른 어두운 물체도 가중된다. 이는 이전 픽셀 윤곽 보호를 대체하는 방식이다. - -## 검증 - -dog1 / AI 상대 depth / 색면 1 / Grid 13 / 굴곡 1 / Distortion 1 / 확대 1 / 팬 0에서 정면과 +120px 이동을 확인했다. 눈의 작은 반짝임과 코의 세부 윤곽이 사라지고 두 눈·코가 어두운 사각 면으로 표현됐다. 잔디의 큰 색면을 유지했고, 이동에 따라 얼굴과 색면이 변화했다. 색면 0에서 기존 사진 굴절 출력으로 복원됨을 확인했다. 같은 사진의 수동 비교이며 모든 사진의 식별이나 자연스러움을 보장하지 않는다. - -수정 파일은 `src/shaders/mosaic.frag`, `src/shaders/region-palette.frag` 및 관련 두 검사 스크립트다. axis-split, depth-distance(21 역투영/12 원본 UV 매핑), camera-history, continuity(493,760 Jacobian/87,200 seam) 검사와 `npm run build` 통과. 기존 큰 번들 경고는 유지된다. 별도 모바일 FPS/연속 영상 flicker 계측은 하지 않았다. diff --git a/docs/ref1-depth-protection.md b/docs/ref1-depth-protection.md deleted file mode 100644 index 78fe3e6..0000000 --- a/docs/ref1-depth-protection.md +++ /dev/null @@ -1,25 +0,0 @@ -# Ref1 깊이와 어두운 색을 함께 사용하는 보호 - -후속 변경: 아래 픽셀별 보호는 눈·코를 따로 붙인 듯 보인다는 사용자 평가로 대체됐다. 깊이·어두움은 유지하되 사각 색면의 대표색 선택에 사용한다. 최신 기준은 `docs/ref1-dark-color-planes.md`이다. - -2026-09-14 사용자는 원본 depth의 가장 흰 영역과 RGB의 검정 영역이 겹칠 때 보호하도록 제안했다. 목적은 눈·코 보호를 유지하면서 먼 잔디의 작은 어두운 무늬가 보호되는 현상을 줄이는 것이다. 이는 앞선 사진 전체의 어두운 특징 보호보다 우선한다. - -## 적용 기준 - -- 기존 RGB 보호 조건: 원본 밝기 < 0.20, 단순화 후보가 원본보다 0.16 초과 밝아지는 경우. -- 원본 상대 depth(0=뒤, 1=앞)의 `smoothstep(0.80, 0.95, depth)`를 보호 결과에만 적용한다. 0.80 이하는 보호하지 않고 0.95 이상은 기존 보호를 전부 적용한다. -- 안전 own palette → 허용 가능한 최암색 → 해당 원본 픽셀의 기존 보호 순서를 유지한다. -- 굴절 RGB의 finalSceneUv에서 장면 깊이를 역투영하고, 사진 메시의 역행렬로 원본 UV를 구해 원본 depth를 읽는다. 카메라의 비선형 depth-buffer 값을 흰색 정도로 사용하지 않는다. -- 색면 전체 강도는 거리와 독립이다. SSE 분할, 배경 색면 강화, 시점 반응과 70ms 보간을 유지한다. - -## 범위와 한계 - -눈·코 인식 마스크는 아니다. 가까운 잔디나 다른 검정 물체도 보호될 수 있고, AI depth가 눈을 뒤로 추정하면 보호가 줄 수 있다. 깊이 없는 0값 평면 texture에는 선택적 보호가 적용되지 않는다. 원본 depth가 있으면 Depth Scale 0에서도 보호 범위를 판정할 수 있다. 임계값은 현재 dog1 비교를 위한 초기값이며 모든 사진의 최적값을 의미하지 않는다. - -## 구현 및 검증 완료 - -수정: `src/main.ts`에 현재 원본 depth uniform 공유와 매 프레임 사진 메시 역행렬 갱신, `src/shaders/mosaic.frag`에 원본 UV 복원 및 보호 가중치 적용. `scripts/test-region-axis-split.mjs`, `scripts/test-mosaic-depth-distance.mjs`에서 보호 분기와 원본 UV 변환 검증을 갱신했다. - -dog1 / AI 상대 depth / 색면 1 / Grid 13 / 굴곡 1 / Distortion 1 / Camera Offset 0.5에서 정면과 +120px 이동을 확인했다. 이전 전체 어두운 특징 보호 때 잔디에 남던 작은 검은 무늬가 감소하고 눈·코 형태와 큰 배경 색면이 유지됐다. 눈 대비는 기존 전체 보호보다 약한 부분이 있다. Depth Scale 0에서도 눈·코와 잔디의 선택이 유지됐고, Depth Scale 0.25 / 수동 확대 1.3 / 가로 팬 0.3에서도 보호 위치가 얼굴을 따라가는 것을 확인했다. 검사 후 확대 1 / 팬 0 / 정면으로 복원했다. - -axis-split, depth-distance(21 역투영 및 카메라·확대/팬·Depth Scale 조합 12개), camera-history 테스트와 `npm run build` 통과. 기존 번들 크기 경고는 남는다. 한 사진의 수동 시각 검증이며 연속 프레임 깜빡임과 모바일 FPS는 계측하지 않았다. diff --git a/docs/ref1-design-review.md b/docs/ref1-design-review.md deleted file mode 100644 index 620b78d..0000000 --- a/docs/ref1-design-review.md +++ /dev/null @@ -1,38 +0,0 @@ -# Ref1 구현 방향 검토 — 2026-09-14 - -상태: 거리 감쇠 제거 구현 완료. 자동 검증 통과. 현재 dog1 브라우저에서 가까운 영역에도 색면 효과가 적용되는 것을 확인했으며, Ref1의 큰 사각 색면 달성 여부는 별도 시각 조정 과제로 남아 있다. - -## 현재 관찰 - -현재 브라우저: 멍멍이 1(잔디 위 흰 포메라니안), AI 추정 상대 depth, 조각 유리, Grid 10, 색면 1, Distortion 0.9, 굴곡 0.65, 광택 0.3, Depth Scale 0.25, 확대 1, 팬 0. - -얼굴의 털·눈 반사점·둥근 코·혀가 사진처럼 남고, 몸 외곽과 잔디는 작은 불규칙 색 영역으로 정리된다. Ref1의 큰 사각 얼굴 면과 차이가 있다. 다른 사진/구도이므로 절대 색감과 얼굴 크기의 일치는 평가하지 않는다. 이번에는 정지 화면을 관찰했고 새 동작 검증이나 빌드는 실행하지 않았다. - -## 판단 - -- 가까운 부분의 색면 처리를 약화하던 거리 가중치는 사용자 지시로 제거했다. 큰 면을 충분히 만들지 못하는 색상 라벨 처리 방식은 별도 문제다. -- Ref1 정지 이미지로 실제 거리나 광학 구조를 확정할 수 없다. 거리 모델의 물리적 옳고 그름보다 목표 모습에 적합한지 평가한다. -- 자동 구도 변경, 독립 무작위 크롭, 전체 블러, 셀 전체 단색화로 해결하지 않는다. - -## 거리 감쇠 제거 - -거리 가중치를 제거해 유효한 표면에 설정된 색면 강도를 그대로 적용한다. 배경 깊이·범위 밖 UV·역투영 실패·유리 앞/접촉 표면 등의 유효성 검사는 유지한다. RGB/Depth 배치와 굴절 좌표, 팔레트, 어두운 픽셀 보호는 변경하지 않는다. 구현과 자동 검증은 완료했다. - -같은 사진·구도·시점·Grid·굴곡·광택에서 색면 0.65와 1을 비교한다. 지정 sample-pet.png(수작업 테스트 depth, AI 아님)와 현재 dog1(AI 상대 depth)을 사용하고 각 A/B에서 같은 depth를 유지한다. - -평가 기준: - -1. 얼굴에서 잔털·작은 명암 조각이 줄고 넓은 밝은 면이 늘어나는가. -2. 두 눈과 코의 위치 및 표정이 읽히는가. 반사점·코 내부 디테일은 필수 조건이 아니다. -3. 셀 전체 단색화 없이 얼굴과 배경 경계가 유지되는가. -4. 이미 거리 가중치가 1인 먼 영역은 A/B가 같은가. -5. 작은 좌우 드래그에서 윤곽 연결과 색 변화가 안정적인가. -6. 색면 0과 Distortion 0에서 기존 출력이 유지되는가. - -## 결과에 따른 후속 검토 - -B에도 작은 불규칙 면이 남으면 기존 8×8 atlas의 색상 라벨을 선택적으로 병합하는 별도 실험을 한다. 인접 2×2에서 우세한 같은 라벨이 충분한 경우만 묶는 방식을 최소 후보로 삼는다. 모든 2×2를 강제로 한 색으로 만들지 않는다. 이 후보가 Ref1의 큰 면을 만들지는 시각 검증이 필요하다. - -어두운 원본 디테일이 계속 남으면 preserveDark의 원본 RGB 우회를 어두운 대표색 라벨 보호로 바꾸는 별도 실험을 검토한다. 눈·코가 밝은 면에 흡수되는 것을 막되 어두운 영역 안의 세부는 정리하는 방향이다. 어두운 털과 눈이 합쳐질 위험을 확인한다. - -거리 제한 해제만으로 먼 배경의 포스터화는 해결되지 않는다. 가까운 얼굴에 팔레트가 더 적용되어 시점 이동 시 색 전환이 눈에 띌 수도 있다. 여러 보정을 동시에 적용하지 않고 각 결과로 다음 변경을 결정한다. diff --git a/docs/ref1-direction.md b/docs/ref1-direction.md deleted file mode 100644 index a601c99..0000000 --- a/docs/ref1-direction.md +++ /dev/null @@ -1,26 +0,0 @@ -# Ref1 중심으로 시각 기준 전환 - -2026-09-14 사용자 요청: Ref2 구현을 주 목표로 삼는 방향을 중단하고 Ref1을 기준으로 작업한다. - -## 우선할 모습 - -최신 표현 정정: 눈·코 원본 윤곽이 따로 붙어 보이지 않도록 픽셀 복원을 없애고, 깊이·어두움 정보를 사각 색면의 선택에만 사용한다. `docs/ref1-dark-color-planes.md`가 아래 픽셀별 보호 방식보다 우선한다. - -가장 최근 보호 범위: 원본 depth의 앞쪽 흰 부분과 어두운 RGB가 겹치는 곳에만 기존 보호를 적용한다. 먼 배경의 어두운 무늬 보호를 줄인다. `docs/ref1-depth-protection.md`가 아래의 전체 어두운 특징 보호 설명보다 우선한다. - -현재까지의 구현과 비교 옵션은 사용자 지정에 따라 **Ref1 목표에 가장 근접한 현재 기준안**으로 기록한다. 정확한 비교값과 앱 기본값의 구분은 `docs/ref1-current-baseline.md`를 따른다. 이후 수정은 이 기준과 비교한다. - -최신 정정: 보호 제거 결과를 확인한 사용자가 눈·코 보호 예외를 유지하도록 다시 지시했다. 어두운 형태가 밝은 색면에 흡수될 때 안전 palette를 우선하고 필요한 픽셀에만 원본색 fallback을 적용하는 기존 보호를 복원한다. 배경까지 색면을 단순화하는 기본 규칙과 SSE 분할 선택은 유지한다. 앞선 보호 제거 지시보다 이 정정이 우선한다. - -Ref1에서 강아지 얼굴은 밝은 사각 색면으로 크게 정리되고, 눈·코는 적은 수의 어두운 면만으로 식별된다. 배경은 같은 격자 안에서도 일부 무늬와 명암이 남아 있다. 이를 모든 셀을 단색으로 채우는 필터로 단정하지 않는다. - -다음 효과 조정에서는 작은 불규칙 색 조각을 줄이고 유리 격자에 맞는 큰 면을 우선한다. 전체 표정과 인접 셀의 공간적 관계는 유지한다. Ref2의 큰 눈 내부 디테일과 가까움/멀어짐에 따른 급격한 선명도 변화는 주 통과 조건에서 제외한다. - -## 유지 사항과 현재 상태 - -- 자동 확대·팬·크롭 금지, 원본 사진 보존. -- 인접 셀이 서로 다른 사진 조각을 가져오는 듯한 무작위 크롭 금지. -- Ref1 | Ref2 비교 배치 유지; 주/보조 우선순위만 변경. -- 가까운 유효 표면의 색면 처리를 약화하던 거리 감쇠는 사용자 지시에 따라 제거한다. 범위 밖 UV·배경·역투영 실패·유리 앞/접촉 표면의 유효성 검사는 유지한다. - -이번 전환은 레퍼런스 우선순위와 평가 기준 변경이며 Ref1용 셰이더 재구현을 완료했다는 의미는 아니다. diff --git a/docs/ref1-option-2.md b/docs/ref1-option-2.md deleted file mode 100644 index abf4331..0000000 --- a/docs/ref1-option-2.md +++ /dev/null @@ -1,32 +0,0 @@ -# Ref1 목표에 가장 근접한 두 번째 옵션 - -2026-09-14 사용자 지정: **현재 구현과 아래 설정을 현재 프로젝트에서 Ref1 목표에 가장 근접한 두 번째 옵션(옵션 2)**으로 명시한다. 기존 `ref1-current-baseline.md`의 기준안은 옵션 1로 보존한다. 번호는 두 비교안을 구분하며, Ref2를 목표로 삼거나 성능 순위를 뜻하지 않는다. - -## 현재 설정 - -사용자 지정 시점의 브라우저에서 직접 확인한 값이다. - -| 항목 | 옵션 2 | -|---|---| -| View Mode / Glass / Mosaic 스타일 | Final / Mosaic / 조각 유리 | -| 색면 단순화 | 1.00 | -| Grid Size | 13 | -| Distortion | 1.00 | -| 셀 굴곡 | +1.00 | -| 광택 | 0.30 | -| 조명 가로 / 세로 | 0.60 / 0.80 | -| Depth Scale | 0.25 | -| Camera Offset | 0.50 | -| 사진 확대 | 1.00 | -| 사진 가로 / 세로 위치 | 0 / 0 | -| View sensitivity / Gyroscope | 1.00 / OFF | -| 비교 사진 | 멍멍이 1 · 잔디 위 흰 포메라니안 | -| Depth | Depth Anything V2 Small의 AI 추정 상대 깊이, 0=뒤·1=앞 | - -## 구현을 포함한 옵션 정의 - -이 옵션은 설정 숫자뿐 아니라 `ref1-dark-color-planes.md`의 구현을 포함한다. 눈·코 원본 픽셀을 복원하지 않고, 앞쪽 depth와 어두운 RGB 증거로 셀의 사각 색면 대표색 선택을 보정한다. 표본의 SSE 가중치는 최대 4배이며, 충분한 증거가 있는 셀은 사각 모델의 적용 비중을 높인다. 사진 배경도 큰 색면으로 단순화하고 시점 반응과 70ms 전환 보간을 유지한다. - -옵션 1은 Grid 10과 당시의 픽셀 윤곽 보호를 포함한 이전 기준안이다. 옵션 2는 Grid 13과 어두운 사각 색면 보존 방식이다. 현재 코드에서 Grid만 10으로 바꾸는 것으로 옵션 1의 구현까지 복원되지는 않는다. 이번 기록은 문서상의 비교안 지정이며 앱에 전환 프리셋을 추가하거나 기본값을 변경한 것이 아니다. - -후속 수정은 이 옵션을 비교 기준 중 하나로 사용한다. 기존 검증과 한계는 `ref1-dark-color-planes.md`를 따른다. 모든 사진의 최적값 또는 Ref1 완성 판정으로 해석하지 않는다. diff --git a/docs/ref1-option-ranges.md b/docs/ref1-option-ranges.md deleted file mode 100644 index e3c9f17..0000000 --- a/docs/ref1-option-ranges.md +++ /dev/null @@ -1,38 +0,0 @@ -# Ref1용 조절 범위와 UI 정리 - -2026-09-14 사용자 요청: 옵션 2의 색면 방식과 색면 단순화 1을 기준으로 Ref1에 가까운 Grid 및 유효 조절 범위를 선정하고 불필요한 조절을 정리한다. 옵션 1·2의 기록은 그대로 보존한다. - -## 권장 범위 - -| 항목 | 권장값/범위 | 처리 | -|---|---|---| -| 색면 단순화 | 1 고정 | 슬라이더·출력·이벤트 제거, 고정값 안내 | -| Distortion | 1 고정 | 조절 제거. 낮추면 원래 RGB 질감도 다시 섞임 | -| Grid — 얼굴이 큰 한 마리 | 12~16, 시작 13 | 주 조절 | -| Grid — 작은 얼굴/여러 마리 | 20~24, 시작 20 | 같은 주 조절. 전체 UI 범위 10~24 | -| 셀 굴곡 | 절댓값 0.65~1, 시작 +1 | 부호는 공간 변화를 바꾸므로 −1~+1 유지 | -| 광택 | 0~0.3, 시작 0.3 | UI 0~0.4. 무광부터 약한 반사까지 | -| Camera Offset | 0.35~0.65, 시작 0.5 | 기존 0~0.9 보존. 시점 이동 범위 조절 | -| 사진 확대·팬 | 사진에 따라 수동 | ‘사진 구도’로 접어 유지, 자동 변경 금지 | - -Grid는 화면 크기보다 사진에서 얼굴이 차지하는 비율에 따라 고른다. 숫자를 낮추면 큰 면이 되지만 눈·얼굴이 합쳐질 수 있다. 위 범위는 두 사진의 수동 비교와 현재 셰이더 구조를 바탕으로 한 작업 범위이며 전수 탐색의 최적값이 아니다. 곡률의 양·음 부호는 같은 모양을 보장하지 않는다. - -## 비교 근거 - -- 초기 UI의 테스트 사진 선택은 dog3, Grid 24 / 굴곡 −1 / 조명 X 2였다. 선택값과 이미 불러온 사진이 다를 수 있으므로 최종 검증에서는 dog3를 명시적으로 다시 불러왔다. 같은 굴곡 −1 / 조명 X 2에서 Grid 16·20·24를 비교했다. 16에서는 작은 얼굴 정보가 크게 합쳐졌고 20~24가 더 많은 얼굴 구분을 남겼다. -- dog1에서 Grid 10은 한쪽 눈이 밝은 면에 흡수됐고, 기존 옵션 2의 13은 두 눈을 사각 면으로 남겼다. 16은 더 작은 면으로 얼굴을 표현했다. 따라서 이 사진에서는 12~16을 우선 조절 범위로 잡는다. -- dog1 / Grid 16에서 Distortion 0.8과 1을 비교했다. 0.8은 잔디 질감과 눈·코의 세부 윤곽이 다시 드러나므로 Ref1 색면 작업에서는 1로 고정한다. -- dog1 / Grid 13 / 굴곡 +0.65 / 광택 0에서도 사각 색면은 유지됐다. 굴곡 +1과 얼굴의 면 선택은 달랐으며 반사는 핵심 색면 생성 요소가 아니다. -- Camera Offset 권장 범위는 기존 0.5 시점 검증과 0.9에서 사진 밖 여백이 보일 수 있다는 기록에 기반한 보수적 조절 범위다. 모든 중간값의 영상 검증을 수행한 것은 아니다. - -## 주 화면에서 제외할 항목 - -색면·Distortion은 고정하고 조절을 제거한다. 조명 XY(기본 0.6/0.8), Depth Scale(0.25), sensitivity(1)는 진단·비교 용도가 있어 접힌 ‘개발 비교’에 둔다. 다른 유리 효과/스타일, RGB·Depth·No Glass 등 보기 모드, 수동 depth 업로드와 영상 입력도 같은 곳으로 이동한다. 이들은 현재 Ref1의 주 조절에서 제외하며 렌더러 기능 자체를 삭제하지 않는다. - -사진/AI depth 생성·테스트 사진, 격자·굴곡·광택·시점 범위, 시점 초기화와 Gyroscope는 접근 가능하게 유지한다. 수동 AI depth 생성 후에는 Final로 돌아와 접힌 보기 모드 때문에 No Glass에 머무르지 않게 한다. - -## 적용 및 검증 - -`index.html`, `src/main.ts`, `src/style.css`와 관련 검사 스크립트를 수정했다. 색면/Distortion의 UI·출력·이벤트·해제 참조를 제거하고 셰이더 uniform은 1을 유지한다. 주 화면의 Grid 기본13/굴곡+1/광택.3/Camera.5와 실제 uniform을 맞췄다. 촘촘 유리 비교의 격자 초기값도 UI 상한24와 일치시켰다. - -axis-split, camera-history, depth-distance, DOM ID 참조 검사 및 build 통과. 기존 번들 크기 경고는 남는다. 실제 브라우저에서 네 가지 주 조절, 두 접기 영역, 깊이 상태 노출을 확인했고 No Glass에서 수동 AI 생성을 실행한 뒤 Final 복귀를 확인했다. 사진 확대1/팬0을 유지했다. 모바일 실기기 검증은 수행하지 않았다. diff --git a/docs/ref1-scene-simplification.md b/docs/ref1-scene-simplification.md deleted file mode 100644 index 0522c13..0000000 --- a/docs/ref1-scene-simplification.md +++ /dev/null @@ -1,39 +0,0 @@ -# Ref1 scene simplification: palette SSE experiment - -## 최신 정정 — 눈·코 보호 유지 - -2026-09-14 사용자는 이 실험의 실제 출력을 확인한 뒤 눈·코 보호 예외를 제거하지 않도록 정정했다. 기존의 안전 palette 우선 보호와 필요한 픽셀의 원본색 fallback을 복원한다. 아래의 보호 제거 설명은 실험 당시 이력이다. SSE 선택, 배경의 큰 색면, 가장자리 색면 강도, 거리 감쇠 제거와 시점/70ms 보간은 유지한다. - -복원 완료: `mosaic.frag`에서 원본 밝기 < 0.20이고 후보가 원본보다 0.16 초과 밝을 때 own palette → 허용 가능한 최암색 → 원본 RGB 순으로 보호한다. 눈·코를 인식하는 마스크가 아니라 어두운 특징에 공통 적용되므로 잔디의 작은 어두운 무늬도 일부 다시 남는다. dog1 / AI 상대 depth / 색면 1 / Grid 13 / 굴곡 1 / Distortion 1에서 정면과 +120px 이동의 두 눈·코 식별 및 큰 배경 색면 유지를 확인했다. axis-split, depth-distance, camera-history 테스트와 build 통과(기존 번들 크기 경고). 연속 영상 flicker나 실기기 FPS 검증은 아니다. - -2026-09-14 update to the adopted comparison baseline in `docs/ref1-current-baseline.md`. The baseline itself remains unchanged; this records the follow-up experiment and its observed result. - -## Change - -이번 후속 작업은 눈·코의 어두운 색/원본 RGB 보호 분기를 제거하고 얼굴·사진 배경에 동일한 규칙을 적용한다. 복잡한 잔디에도 유효한 두 색 분할의 적용 신뢰도를 최소 0.85로 두며, 색면 강도에서 사진 가장자리의 광학 taper 감쇠를 분리했다. 굴절 자체의 가장자리 taper, 시점 반응 계수 0.18과 70ms 색면 보간은 유지한다. 단일 색밖에 관측되지 않는 셀에는 임의의 두 번째 색을 만들지 않는다. - -The 8×8 cell samples are still assigned to the existing four-color palette. For each candidate axis and cut, the selector now tests distinct labels that were actually observed on their respective sides and minimizes the sum of squared palette-color error: - -```text -costA(a) = Σ_l votesA[l] * distanceColor(p_l, p_a) -costB(b) = Σ_l votesB[l] * distanceColor(p_l, p_b) -score(a,b) = costA(a) + costB(b) -``` - -The existing `distanceColor` metric is used for every pixel, including dark pixels; there is no eye/nose exception. Candidate traversal and strict comparisons preserve deterministic tie order (X before Y; cuts 4, 3, 5, 2, 6; then ascending labels). The selected pair's sample accuracy and gain still determine the existing confidence curve, with the valid two-color model confidence floor of 0.85. A cell without an observed, distinct label on both sides keeps the radial fallback. - -The previous count selector chose the observed label pair with the largest `votesA[a] + votesB[b]`, then chose the candidate with the highest pair accuracy. To restore that scoring rule, replace the `candidateCost`/`pairCost` comparisons in `src/shaders/region-palette.frag` with that pair-vote maximum and restore the cross-candidate `bestAccuracy` comparison. Palette fitting, metadata format, history smoothing, depth validity, distance-independent color application, edge-independent color strength, and view-dependent refraction were not changed in this experiment. - -## Verification - -Automated checks passed: - -- `node scripts/test-region-axis-split.mjs` checks the SSE scoring formula, a fixture where SSE selects a different representative than count majority, observed-side constraints, exact horizontal/vertical cuts, checkerboard and single-label behavior, confidence, and metadata encoding. -- `node scripts/test-mosaic-depth-distance.mjs` passed 21 perspective reconstructions and the invalid-surface guards. -- `npm run build` passed. Vite reported the existing large-chunk warning. - -Visual QA used dog1 with AI-estimated depth and the same front-view comparison settings (region strength 1, grid 10, curvature 1, distortion 1). The SSE version retained the large face and grass color planes. Where the count version had mostly absorbed the right eye into beige, SSE showed a weak brown shape, improving the overall expression in this sample. At +120 px camera movement, the large planes and face/background regions changed while remaining visible. - -This does not guarantee eye or nose recognition: the left eye and nose contrast also became weaker. The comparison is a manual visual check on one photo, not a broad image evaluation or a measured frame-by-frame flicker/performance test. The selected SSE rule is adopted for this baseline follow-up, without claiming Ref1 is complete. - -추가 브라우저 확인: dog1에서 색면 단순화 0은 큰 색면을 해제하고 원래 잔디 질감과 얼굴을 복원했다. 색면 1 / Distortion 0에서도 색면과 굴절이 해제된 출력을 확인했다. QA 종료 후 브라우저에서 관측했던 사용자 조절값인 색면 0.57 / Grid 13으로 복원했다. 이 값은 위 기준 비교값 1 / 10과 구분한다. diff --git a/docs/ref1-shape-review.md b/docs/ref1-shape-review.md deleted file mode 100644 index c691063..0000000 --- a/docs/ref1-shape-review.md +++ /dev/null @@ -1,28 +0,0 @@ -# Ref1 큰 색면 보정 검토 — 2026-09-14 - -## 구현 - -기본 Mosaic의 기존 8×8 atlas와 셀별 4색 palette를 유지하면서, 각 셀에 가장 잘 맞는 수직/수평 2영역 분할 하나를 찾는다. 축별 경계 후보는 2·3·4·5·6/8이며, 영역별 palette label 설명률이 가장 높은 분할을 고른다. 전체 한 label보다 개선되는 정도와 설명률로 confidence를 정하고 radial 3×3 grouping 결과와 섞어 복잡한 셀은 기존 fallback으로 남긴다. 모델 metadata는 palette target의 다섯 번째 texel에 저장한다. 이후 view 변화에 따른 경계 전환은 선택된 이산 metadata 자체가 아니라 셀별 8×8 split color/confidence field를 premultiplied alpha로 ping-pong history에 저장하고 70ms 지수 수렴시킨다. 현재 프레임의 사진 굴절과 .18 셀 내부 시점 변위는 즉시 계산한다. - -어두운 원본 형태가 밝은 label로 바뀌려 할 때 own palette를 우선 사용한다. own palette가 충분히 어두운 형태를 유지하지 못하면 palette에서 허용 가능한 가장 어두운 색을 고르고, 어떤 palette 색도 한계 안에 없을 때에만 해당 픽셀의 원본색을 남긴다. 이 절차는 시각 검사에서 확인한 눈 디테일 보호를 위한 예외이며, 전체적인 원본 RGB 우회는 사용하지 않는다. - -초기 4×4 다수결 실험은 이마·몸 외곽에 반셀 경계를 만들고 얼굴 내부 포스터화는 줄이지 못해 채택하지 않았다. 현재 축 분할 모델은 그 실험을 대체한다. - -## 시각 확인 - -- dog1, AI 상대 depth, Grid 10, 색면 1, 굴곡 1, Distortion 1, 광택 0.3, 확대 1, 팬 0에서 이마·볼·몸에 큰 직사각 색면이 늘고 두 눈·코·혀의 식별이 유지됐다. -- 좌우 약 120px 시점 이동에서 눈·코와 큰 색면 경계가 바뀌는 것을 확인했다. 정량적인 연속 영상 flicker 검사는 아니다. -- 추가 dog1 테스트에서 Grid 96과 약 120px 이동 중 정상 렌더링을 확인했다. FPS 계측과 실제 모바일 기기 성능은 확인하지 않았다. -- 지정 샘플 사진과 수작업 depth에서 Grid 10 / 색면 1 / 굴곡 1 / Distortion 1 / 광택 0.3으로 눈·코와 큰 면을 확인했다. AI 추정 또는 실제 측정 depth가 아니다. -- 색면 0은 기존 굴절 출력을 복원했고 Distortion 0도 무효과 화면으로 돌아갔다. -- Camera Offset 기본 .50에서 dog1/AI depth/색면 1/굴곡 1/Distortion 1/Grid 10/광택 .3/확대 1/팬 0을 좌우 약 120px 이동해 눈·코와 큰 면 변화를 확인했다. 정지 시 눈·코와 색면이 정상적으로 보였다. 영상 flicker를 정량 측정하지 않았다. -- 지정 샘플과 수작업 depth에서 Camera Offset .90 대각 최대 이동을 확인했다. debug camera X가 .900에 도달했고 좌표가 뒤집히는 현상은 보이지 않았다. 가장자리에서 사진 바깥 여백이 대각선 상단 일부에 노출됐다. 자동 구도 조정은 하지 않았다. -- 같은 수작업 샘플에서 No Glass 드래그 후 Final로 돌아와 정상 표시를 확인했다. Grid 96/굴곡 -1/Depth Scale 0/Camera Offset .90에서도 렌더링을 확인했다. FPS 계측과 실제 모바일 GPU 검증은 아니다. -- 사진을 수작업 depth 샘플에서 dog1 AI depth로 교체한 뒤, 이전 샘플 색면 잔류 없이 dog1의 정면 큰 면이 유지되는 것을 확인했다. -- history 수렴은 `1-exp(-dt/.07)`이며 CPU 검사는 30/60/120Hz의 700ms 결과 일치와 70ms 시정수, 첫 프레임/초기화, ping-pong 분리, camera 제외 reset key를 확인했다. 이는 수학적 cadence 확인이며 브라우저 영상의 깜빡임 부재 증명은 아니다. - -현재 결과는 Ref1의 큰 면 목표와 시점 반응에 대한 시각 개선이다. 모든 사진과 구도에서 같은 결과를 보장하거나 최종 Ref1 일치를 입증한 것은 아니다. split 경계는 temporal history로 완화했지만 정량 영상 flicker 평가는 아직 없다. - -## 자동 확인 - -`node scripts/test-region-axis-split.mjs`는 수직·수평 경계의 2/6 후보, 복잡/단색 셀 fallback, metadata byte encode/decode, confidence blending, dark eye/nose 보호 경로를 검사한다. `node scripts/test-camera-history.mjs`는 Camera Offset .5/.9 범위, reset key, ping-pong/dispose, premultiplied field와 30/60/120Hz cadence를 검사한다. `npm run build`, `node scripts/test-mosaic-depth-distance.mjs`, `node scripts/test-mosaic-continuity.mjs`도 통과했다. 최종 continuity suite는 camera offset ±.9를 포함해 493,760 Jacobian과 87,200 seam 수렴 검사를 통과했다. Build는 기존 500KB 초과 bundle warning을 출력한다. diff --git a/docs/reference-match-review.md b/docs/reference-match-review.md deleted file mode 100644 index 6525456..0000000 --- a/docs/reference-match-review.md +++ /dev/null @@ -1,29 +0,0 @@ -# Ref1·Ref2 대비 현재 결과 QA - -2026-09-14. 판정: 시각 목표 미달. 소스 수정 없이 현재 브라우저와 레퍼런스를 비교했다. - -## 비교 조건 - -- 5173, 멍멍이 3(후드 쓴 두 강아지), 자동 AI depth, Final/Mosaic 조각 유리. -- Grid 6, 색면 1, Distortion 0.9, 굴곡 0.65, 광택 0.3, depth 0.25, zoom 1, pan 0. -- 같은 사진과 시점에서 색면만 1 → 0 → 1로 비교하고 원래 값을 복원했다. 이번에는 드래그 검사를 반복하지 않았다. -- Ref2를 주 기준으로, Ref1을 보조 기준으로 직접 확인했다. Astra 독립 검토도 수행했다. - -## 관찰과 원인 - -1. 색면을 끄면 눈·코와 배경이 대부분 원래 사진의 형태로 읽힌다. 켜면 같은 형상이 평평한 색 조각으로 바뀐다. 현재 인상의 대부분은 렌즈에 의한 형태 재구성보다 색상 분류에서 나온다. -2. Ref2에서는 넓은 밝은 얼굴 면과 눈·코 내부 명암이 함께 남는다. 현재 오른쪽 강아지의 눈·코는 작은 회색 영역으로 약해지고, 바닥과 배경에는 여전히 작은 불규칙 영역이 많다. 중요 특징 보존과 작은 무늬 제거가 원하는 방향으로 분리되지 않았다. -3. 현재 사각 경계는 셀별 팔레트가 끊기는 경계로 두드러진다. 이것만으로 유리의 곡면에 의해 윤곽이 늘어나거나 압축되는 인상을 대신할 수 없다. - -코드상 기본 Mosaic의 형태 변화는 공통 광선과 곡면 법선으로 계산한 기준 평면 교점 차이에서 나온다. 근접 배치가 이 이동 거리를 줄인 문제는 contact-regression-review.md에 기록했다. 이후 색면 단계는 셀별 네 대표 색으로 분류할 뿐 눈·코의 공간적 크기나 위치를 바꾸지 않는다. 약해진 굴절을 색면 강도로 보완하려 한 방향이 잘못됐다. - -정지 레퍼런스만으로 실제 확대 배율, 유리 두께, 움직임을 확정할 수 없다. 현재 두 마리 사진과 Ref2의 큰 단일 얼굴은 입력 구도도 다르므로 절대 눈 크기만으로 굴절량을 판단하지 않는다. 자동 확대·팬·크롭은 해결책에서 제외한다. - -## 다음 구현의 검증 기준 - -1. 같은 사진·수동 구도를 유지하고 No Glass에서 깊이 상대 시차를 먼저 확인한다. -2. 색면과 광택을 0으로 놓아도 Mosaic의 곡면 때문에 눈·코 윤곽의 비율과 형태 변화가 분명해야 한다. 정면·좌·우·복귀를 비교한다. 공통 장면과 광선의 일관성을 유지한다. -3. 근접 배치와 굴절의 유효 광학 거리를 분리하는 근사부터 검토한다. 실제 간격을 다시 벌리거나 셀별 임의 크롭을 도입하지 않는다. -4. 그 후 색면을 보조 효과로 적용한다. 털과 바닥의 작은 무늬를 큰 영역으로 정리하면서 눈·코의 어두운 윤곽과 밝은 반사, 혀의 형태를 보존해야 한다. 현재 어두운 색 일부 보호만으로 충분하지 않다. - -이번 작업은 QA이며 구현과 빌드는 수행하지 않았다. 기능 작동 여부와 Ref 시각 일치 여부를 별개로 판정한다. diff --git a/docs/reference2-plan.md b/docs/reference2-plan.md deleted file mode 100644 index bcfa281..0000000 --- a/docs/reference2-plan.md +++ /dev/null @@ -1,11 +0,0 @@ -# 레퍼런스2 구도·굴절 보정 - -2026-09-11. 사용자 확정: 두 번째 사진을 주 시각 목표로 사용한다. - -- 사진 확대/가로/세로 위치와 구도 초기화 제공. RGB와 Depth에 같은 XY 변환, Z는 기존 유지. 원본 파일 불변. -- 유리판 크기/격자는 확대 전 contain 크기에 고정. 샘플 얼굴 구도2.4/-0.10/-0.35, 일반 미디어1/0/0. 위치는 baseSize*(zoom-1)/2*pan. -- 주 Mosaic: 약60% 일반 배율,30% 확대,10% 압축. 모든 셀을 단색화하지 않고 눈/코와 넓은 색면 공존을 목표로 한다. -- 활성 Mosaic의 유리판 바깥은 배경색으로 표시해 사진의 울퉁불퉁한 외곽이 노출되지 않도록 한다. Distortion0과 No Glass는 기존 진단용 원본 장면 우회를 유지하므로 확대된 사진 전체가 보인다. -- 기존 곡면/창 반사/Depth RT/다른 유리 셰이더 유지. 정확한 광선추적/리라이팅/AI 구도추정 추가 없음. - -시각 검증: 샘플 확대 No Glass에서 깊이 시차 → 같은 구도의 Mosaic에서 눈·코 배율 차이 → 유리 외곽/모바일/구도초기화/일반 업로드 초기화 확인. 명암·조명 차이가 있는 별도 사진이므로 참고와 픽셀 단위 일치를 주장하지 않는다. diff --git a/docs/reference2-validation.md b/docs/reference2-validation.md deleted file mode 100644 index d5b0c81..0000000 --- a/docs/reference2-validation.md +++ /dev/null @@ -1,14 +0,0 @@ -# 레퍼런스2 구현 검증 - -2026-09-11. Astra 설계/검토, Luna 소스 구현, 조정 에이전트 브라우저 QA. - -변경: main.ts/index.html 사진 확대1~3, 가로/세로 위치-1~1, 별도 사진 구도 초기화. pet/petDepth 동일 XY 변환, Z1. 확대 전 contain 기준 유리판 크기. 샘플2.4/-0.10/-0.35, 일반 업로드1/0/0. Mosaic는 배율 변화 작음60%,확대30%,압축10% 분포와 독립 hash. 유리판 밖 배경색 clipping. 실제 A/B 후 primary Grid10/Distortion.90 확정, compact28/.85 유지. - -실제 검증: -- 확대된 No Glass 드래그에서 코/눈/몸 시차 진단 유지. Final 전환 후 유리 외곽이 사진 외곽의 울퉁불퉁함을 노출하지 않음. -- Grid18과10 비교:10에서 레퍼런스2에 가까운 큰 눈/코 조각이 보이면서 표정 식별 가능. 완전한 레퍼런스 재현이나 물리 정확도를 주장하지 않음. -- 사진 구도 초기화 후1/0/0 확인. 확대2 상태에서 일반 파일 업로드 후1/0/0 확인. 샘플 재로드 시2.4/-0.10/-0.35 복원. -- 390x844 모바일에서 얼굴 구도와 사각 외곽 확인. viewport 복원. 최종 browser error 로그 []. -- Luna npm.cmd run build 성공, Astra 최종 정적 검토 차단문제 없음. - -한계: Distortion0/No Glass는 기존 진단용 전체 장면 표시라 확대 사진이 판 바깥까지 보인다. 샘플 구도는 수동 프리셋이며 얼굴 자동 검출 아님. 일반 업로드는 수동 확대/위치 조절 필요. 실제 영상/gyro/성능 측정 재실행하지 않음. 전체 셀을 단색화하지 않았으며 기존 Depth/RT/반사 구조 유지. diff --git a/docs/signed-curvature-validation.md b/docs/signed-curvature-validation.md deleted file mode 100644 index 9f160ae..0000000 --- a/docs/signed-curvature-validation.md +++ /dev/null @@ -1,16 +0,0 @@ -# 오목·볼록 셀 굴곡 - -2026-09-11. Astra 부호/공유 법선 검토, GPT-5.6 Luna 구현. - -- index.html: 셀 굴곡 -1..1, step 0.01, 기본값 +0.65. 관찰자 기준 방향 설명 추가. -- src/shaders/mosaic.frag: 높이의 signed clamp(-1,1). 양수는 +Z 관찰자 쪽 볼록, 음수는 사진 쪽 오목. 같은 법선을 굴절과 반사에서 사용한다. -- 0에서는 높이 미분이 0이므로 curved normal과 facet normal이 같아진다. 기존 셀 기울기·조각 샘플링은 유지한다. 실제 메시 변위 대신 표면 법선 근사이다. - -검증: -- Luna npm.cmd run build 통과. -- 지정 샘플/고정 시점/광택 0에서 -1, 0, +1 화면 비교: 눈·얼굴 및 배경 경계의 휘어짐 차이 확인. -- 0에서 키보드 왼쪽 화살표로 -0.01 입력 및 표시 확인. -- 광택 1, 조명 XY=0에서 -1/+1 반사 분포 변화 확인. -- Distortion 0에서 기존 원본 장면 우회 출력 확인. 창틀은 유지되며 원본 사진이 창틀 밖까지 보이는 기존 동작도 유지. -- 브라우저 error 로그 없음. 기본 +0.65/광택 .3/조명 .6,.8/강도 .9로 복원. -- 카메라, 창틀, Reeded/Frosted 코드는 변경하지 않았다. 이번 검증에서 영상/자이로 및 다른 효과의 시각 회귀는 별도 실행하지 않았다. diff --git a/docs/superpowers/plans/2026-09-30-depth-coupling.md b/docs/superpowers/plans/2026-09-30-depth-coupling.md deleted file mode 100644 index 1ba97d4..0000000 --- a/docs/superpowers/plans/2026-09-30-depth-coupling.md +++ /dev/null @@ -1,17 +0,0 @@ -# Depth-aware glass improvement - -Goal: retain Ref1 rectangular color planes while making transmission follow the existing displaced photo and preserving manual framing. - -Architecture: keep the current mesh, render targets, atlas and history. Add bounded screen-depth correction to Mosaic only, adaptive depth evidence from a histogram, and a subtle view-dependent environment reflection. No semantic dog segmentation or hidden-surface reconstruction is claimed. Preserve current maximum-depth placement for penetration safety; do not move the face forward by guessing its identity. - -Approved scope: user's “작업해봐” follows the in-chat review and proposed order. Work directly in this non-Git workspace; original main/shader saved in docs/qa-depth-coupling. No new agent-assignment instructions. - -- [x] Preserve manual zoom/pan on media input; explicit reset still resets. -- [x] Test then add depth histogram evidence thresholds (flat input disabled, sparse near outlier robust), constants under src/constants. -- [x] Add three bounded surface-depth iterations shared by atlas/final. Reject missing, front-of-glass or nonconvergent samples; retain existing artistic path as fallback. Do not attenuate color simplification with distance. -- [x] Add restrained common environment reflection after color simplification, with gloss/strength gates; preserve other modes. -- [x] Run focused regression scripts/build and browser AI, No Glass, Final, framing reload checks. Record limits and comparison evidence. - -Review correction: a collapsed P50–P85 interval did not always mean flat depth. Added failing bimodal-distribution cases and P5–P95 fallback; all tests then passed. Quantile trimming can still ignore foreground occupying under 5% of the image. This is a bounded heuristic, not segmentation. - -Acceptance: no automatic framing change; actual depth influences the sample correction, invalid samples fall back, no raw eye/nose restoration, gloss zero has no reflection, build and relevant checks pass. Visual comparison is qualitative, not proof of mobile performance or physical accuracy. diff --git a/docs/task-brief.txt b/docs/task-brief.txt deleted file mode 100644 index c652219..0000000 --- a/docs/task-brief.txt +++ /dev/null @@ -1,625 +0,0 @@ -프로젝트명 -Pet Glass / Pet Behind Glass - -목표 -사용자가 반려동물 사진 또는 동영상을 업로드하면, -Three.js 기반으로 "유리문 뒤에 반려동물이 있는 것처럼 보이는 시점 변화형 왜곡 효과"를 제공하는 웹 MVP를 구현한다. - -중요 -단순 이미지 필터가 아니라, -카메라/시점 이동에 따라 유리 굴절 결과가 동적으로 바뀌어야 한다. - -기술 스택 -- Vite -- TypeScript -- Three.js -- GLSL Shader -- Vanilla TS 기반 -- React 사용하지 않음 -- 별도 백엔드 없음 -- 모든 처리는 브라우저 로컬에서 수행 - -핵심 컨셉 - -구조: - -PerspectiveCamera - ↓ -Glass Plane - ↓ -Pet Plane - -Pet Plane에는 사용자가 업로드한 이미지 또는 동영상을 Texture로 적용한다. - -Glass Plane에는 ShaderMaterial을 적용하여 -유리 종류에 따른 굴절/왜곡을 표현한다. - -카메라 또는 view offset이 움직이면 -굴절되는 이미지 위치도 같이 변화해야 한다. - - -======================== -1. 프로젝트 초기 구성 -======================== - -Vite + vanilla-ts 기반으로 프로젝트 생성. - -필수 패키지: -- three - -예상 구조: - -src/ -├─ main.ts -├─ style.css -├─ scene/ -│ ├─ SceneManager.ts -│ ├─ CameraController.ts -│ └─ RendererManager.ts -├─ objects/ -│ ├─ PetPlane.ts -│ └─ GlassPlane.ts -├─ shaders/ -│ ├─ common.vert -│ ├─ mosaic.frag -│ ├─ reeded.frag -│ └─ frosted.frag -├─ input/ -│ ├─ MediaLoader.ts -│ ├─ PointerController.ts -│ └─ GyroController.ts -├─ types/ -│ └─ glass.ts -└─ ui/ - └─ controls.ts - - -======================== -2. 화면 구성 -======================== - -단일 페이지로 구현. - -화면은 크게 두 영역: - -1. 상단/사이드 컨트롤 영역 -2. Three.js Canvas 영역 - -초기 UI: - -- 사진 업로드 버튼 -- 동영상 업로드 버튼 -- 유리 효과 선택 - - Mosaic - - Reeded - - Frosted -- Distortion Strength 슬라이더 -- View Sensitivity 슬라이더 -- Reset View 버튼 -- Gyroscope 사용 버튼 -- 현재 효과명 표시 - -모바일 우선 반응형으로 구현. - - -======================== -3. 미디어 업로드 -======================== - -이미지: -- jpg -- jpeg -- png -- webp - -동영상: -- mp4 -- webm -- 브라우저에서 재생 가능한 파일 - -이미지 업로드 시: -THREE.Texture 생성 - -동영상 업로드 시: -HTMLVideoElement 생성 후 -THREE.VideoTexture 사용 - -새 파일을 업로드하면 -기존 Texture 및 Object URL을 적절히 dispose/revoke 처리할 것. - -업로드한 미디어의 aspect ratio를 유지해야 한다. - -예: -세로 사진이면 세로 비율 유지 -가로 사진이면 가로 비율 유지 - -Canvas 안에서 최대한 크게 보이되 잘리지 않도록 contain 방식으로 배치. - - -======================== -4. Three.js Scene 구성 -======================== - -PerspectiveCamera 사용. - -기본 구성: - -Scene -- Camera -- PetPlane -- GlassPlane - -PetPlane: -- PlaneGeometry -- 업로드된 Texture 적용 -- 기본 위치 z = 0 - -GlassPlane: -- PlaneGeometry -- PetPlane보다 카메라 방향으로 조금 앞 -- 예: z = 0.15 ~ 0.3 -- ShaderMaterial 사용 - -Camera: -- 기본 정면 위치 -- lookAt(0, 0, 0) - -예: -camera.position.set(0, 0, 3) - - -======================== -5. 시점 이동 -======================== - -마우스 또는 터치 drag로 시점을 이동할 수 있어야 한다. - -중요: -단순히 Canvas를 좌우 이동하는 것이 아니라 -실제 카메라 또는 shader의 view offset이 변해야 한다. - -PointerController 구현. - -입력값을 정규화: - -x: -1 ~ 1 -y: -1 ~ 1 - -카메라 이동 예: - -camera.position.x = normalizedX * maxOffsetX -camera.position.y = normalizedY * maxOffsetY - -항상: -camera.lookAt(0, 0, 0) - -단, -카메라 이동만으로 효과가 약한 경우 -shader uniform으로도 view offset을 넘길 것. - -예: - -uViewOffset: vec2 - -normalized pointer 값을 -ShaderMaterial uniform으로 전달. - - -======================== -6. Mosaic Glass 구현 -======================== - -가장 먼저 완성할 핵심 효과. - -사각형 모자이크 유리 구현. - -요구사항: - -- 전체 UV를 NxN grid로 나눈다. -- 각 셀은 작은 볼록/오목 렌즈처럼 동작한다. -- 셀 내부 위치에 따라 source texture의 UV가 변형된다. -- 카메라/view offset에 따라 sampling 위치가 바뀐다. -- 셀마다 약간씩 다른 distortion을 넣을 수 있다. -- 셀 경계가 살짝 보이면 좋다. - -필수 uniform: - -uTexture -uGridSize -uStrength -uViewOffset -uResolution -uTime - -개념: - -vec2 scaled = vUv * uGridSize; -vec2 cell = floor(scaled); -vec2 local = fract(scaled); - -local 좌표를 중심 기준: - -vec2 centered = local - 0.5; - -이를 이용해 렌즈 형태 distortion 적용. - -그 후 -uViewOffset에 따라 UV sampling 위치를 추가로 이동. - -중요: -시점을 좌우로 움직였을 때 -강아지의 눈/코/얼굴 부분이 셀 사이에서 서로 다른 위치로 이동해 -실제 모자이크 유리를 옆에서 보는 느낌이 나야 한다. - -단순 pixelation처럼 보이면 안 된다. - - -======================== -7. Reeded Glass 구현 -======================== - -세로 골유리 효과. - -유리를 세로 방향으로 반복되는 원통형 렌즈 배열처럼 표현. - -특징: - -- Y 방향 변화 거의 없음 -- X 방향 distortion 중심 -- 일정 간격의 vertical ridge -- 카메라가 좌우 이동하면 ridge마다 보이는 이미지 위치가 달라짐 - -sin 또는 반복 함수 사용 가능. - -예시 개념: - -float ridge = sin(vUv.x * frequency); - -uv.x += ridge * strength; - -여기에 -uViewOffset.x를 반영하여 -시점 변화가 눈에 띄게 구현. - - -======================== -8. Frosted Glass 구현 -======================== - -반투명 서리유리 느낌. - -요구사항: - -- 기본 blur -- UV noise distortion -- 이미지 형태는 대략 보이지만 디테일은 흐려짐 -- 시점 이동 시 noise sampling 또는 refraction 방향이 조금 변함 - -성능을 위해 -무거운 multi-pass blur는 MVP에서는 피할 수 있음. - -간단한 multi-sample 방식 사용 가능. - -예: -주변 4~9개 texture sample을 평균. - - -======================== -9. 효과 타입 관리 -======================== - -TypeScript 타입 정의: - -type GlassType = - | 'mosaic' - | 'reeded' - | 'frosted'; - -interface GlassSettings { - type: GlassType; - strength: number; - gridSize: number; - sensitivity: number; -} - -GlassPlane에서 현재 효과를 변경 가능하도록 구현. - -방법은 자유: -- material 교체 -또는 -- ShaderMaterial fragment shader 교체 - -가능하면 구조적으로 분리. - - -======================== -10. Gyroscope -======================== - -모바일 환경에서 DeviceOrientation 사용. - -사용자가 "Gyroscope 사용" 버튼을 누른 뒤 -권한 요청. - -iOS 등 권한 요청이 필요한 환경 고려. - -기기의 좌우/상하 tilt 값을 - --1 ~ 1 - -범위로 normalization하고 -PointerController와 동일한 view offset 시스템에 연결. - -즉: - -손가락 드래그 -또는 -휴대폰 기울이기 - -둘 다 같은 ViewController 상태를 변경하도록 만들 것. - -기본값은 gyro OFF. - - -======================== -11. 애니메이션 루프 -======================== - -requestAnimationFrame 사용. - -매 프레임: - -- input state 갱신 -- camera interpolation -- shader uniform 갱신 -- video texture update -- renderer.render() - -카메라 움직임은 바로 jump시키지 말고 -lerp를 적용해서 부드럽게 움직일 것. - -예: - -currentX += (targetX - currentX) * 0.08 - - -======================== -12. 모바일 UX -======================== - -모바일에서 가장 중요. - -Canvas: -- 터치 드래그 가능 -- 페이지 스크롤과 충돌하지 않도록 처리 - -화면 중앙에 처음 약 2초간 안내: - -"화면을 좌우로 움직여보세요" - -또는 - -"휴대폰을 기울여보세요" - -미디어 업로드 전에는 -placeholder 화면 표시: - -"반려동물 사진 또는 영상을 선택하세요" - - -======================== -13. 기본 샘플 -======================== - -사용자가 아무 파일도 업로드하지 않아도 테스트 가능하도록 -assets/sample-pet.* 형태의 샘플 이미지를 둘 수 있는 구조를 만들어둘 것. - -실제 파일이 없다면 -fallback placeholder로 구현해도 됨. - -샘플을 코드에 강하게 의존시키지는 말 것. - - -======================== -14. 성능 요구 -======================== - -모바일 웹 기준. - -목표: -60fps에 최대한 근접. - -주의: - -- 셀마다 실제 Mesh 생성 금지 -- Mosaic는 반드시 shader 기반 -- 수백 개 Plane 생성 금지 -- texture 재생성 최소화 -- resize 시 renderer.setSize 처리 -- devicePixelRatio 제한 - -예: - -renderer.setPixelRatio( - Math.min(window.devicePixelRatio, 2) -); - - -======================== -15. 리소스 정리 -======================== - -다음 경우 dispose 처리: - -- 새 이미지 업로드 -- 새 동영상 업로드 -- material 교체 -- geometry 교체 -- component/scene 제거 - -Three.js: -texture.dispose() -material.dispose() -geometry.dispose() - -Object URL: -URL.revokeObjectURL() - - -======================== -16. UI 스타일 -======================== - -디자인은 MVP 수준으로 간단하게. - -스타일 방향: -- Dark UI -- Canvas가 가장 큰 비중 -- 컨트롤은 반투명 panel -- 모바일에서는 하단 control sheet처럼 배치 가능 - -과한 디자인 작업 하지 말 것. - -기능 검증이 우선. - - -======================== -17. 중요 구현 원칙 -======================== - -이 프로젝트의 핵심은 아래이다. - -X: -사진에 단순 pixelation 필터 적용 - -O: -유리 plane과 반려동물 plane 사이에 공간이 있고, -사용자의 시점 변화에 따라 -유리를 통해 보이는 반려동물의 위치와 형태가 달라지는 것. - -따라서 Mosaic 효과 구현 시 -정면에서 좌우로 드래그했을 때 -결과 이미지가 확실히 변화해야 한다. - -단순하게 전체 이미지를 translate하는 방식도 안 된다. - -각 유리 cell/ridge마다 -서로 다른 refraction 느낌이 보여야 한다. - - -======================== -18. 1차 완료 기준 -======================== - -아래 조건 만족 시 MVP 1차 완료. - -1. -npm install -npm run dev -로 실행 가능 - -2. -사진 업로드 가능 - -3. -동영상 업로드 가능 - -4. -업로드한 미디어가 PetPlane에 표시됨 - -5. -Mosaic Glass 적용 가능 - -6. -마우스/터치 좌우 drag 시 -모자이크 굴절 결과가 동적으로 변화함 - -7. -Reeded Glass 적용 가능 - -8. -Frosted Glass 적용 가능 - -9. -Strength 조절 가능 - -10. -모바일 viewport 정상 대응 - -11. -TypeScript 오류 없음 - -12. -콘솔에 지속적인 에러 없음 - - -======================== -19. 구현 우선순위 -======================== - -아래 순서를 반드시 우선할 것. - -1. -Three.js Scene - -2. -이미지 Texture - -3. -PetPlane - -4. -GlassPlane - -5. -Pointer drag - -6. -Mosaic Shader - -7. -시점에 따른 refraction - -8. -VideoTexture - -9. -Reeded Shader - -10. -Frosted Shader - -11. -Gyroscope - -12. -UI polish - - -======================== -20. 작업 방식 -======================== - -먼저 현재 프로젝트 파일 구조를 확인한다. - -이미 코드가 있다면 -기존 구조를 최대한 유지하면서 구현한다. - -필요 이상으로 추상화하지 않는다. - -처음부터 완벽한 아키텍처를 만들기보다 -실제로 동작하는 shader prototype을 우선한다. - -특히 Mosaic Shader를 가장 먼저 눈으로 확인 가능한 수준까지 구현할 것. - -각 주요 단계 완료 후 -어떤 파일을 생성/수정했는지 간단히 정리한다. - -작업 완료 후 아래도 보고한다. - -- 생성/수정 파일 목록 -- 구현된 기능 -- 아직 구현하지 않은 기능 -- 실행 방법 -- 주요 shader 동작 원리 -- 다음 개선 포인트 \ No newline at end of file diff --git a/docs/visual-qa.md b/docs/visual-qa.md deleted file mode 100644 index 541530a..0000000 --- a/docs/visual-qa.md +++ /dev/null @@ -1,47 +0,0 @@ -# 시각 QA — 2026-09-11 - -사용자 요청: 결과가 마음에 들지 않는 원인 QA. 소스 수정 없이 실제 브라우저 비교와 Astra 정적 분석 수행. - -## 결과: 시각 목표 미달 - -1. P1 얼굴 정보 손실: mosaic.frag footprint .35~.50, compact .03~.10. 강도 1에서는 각각 2~2.9배, 10~33배 국소 확대. compact blur .07cell로 거의 단색처럼 보이기 쉬움. 브라우저에서 광택0/굴절.5로 낮추면 눈·코 정보가 더 남는 것을 확인. 단순 광택 추가로 해결되지 않음. -2. P1 일관성: grid는 사진이 아닌 화면 vUv 기준. 데스크톱 stage1000x720과 모바일 stage375x506에서 동일 Grid28의 사진 가로 셀 수가 약9와16으로 달라짐. 사진 contain과 stage 크기를 이용한 코드 계산 및 시각 비교. 셀은 정사각형이나 사진에 대한 밀도는 달라짐. -3. P2 광택: 흰색 mix 기반 broad highlight가 어두운 차 실내에서 회색 밝은 막처럼 보임. 미세 법선 차이만으로는 면별 유리 반사 인상이 부족. 공통 조명 방향은 반영되지만 사진 정보 손실을 가리기만 하는 경우 있음. -4. P2 경계/좌표: glass cell은 screen UV 고정, 조명 gh는 world 좌표. 중립 photo rect에 마스크/clamp하지만 depth silhouette은 실제 카메라에 따라 이동. 카메라 offset .6에서 좌측 드래그 후 사진 외곽 기울기와 고정 격자 경계 불일치 확인. 완전한 3D 유리판이 아닌 postprocess 절충. -5. 구도 차이: 참고 이미지의 얼굴은 화면/유리판을 크게 차지함. 샘플은 차 배경과 전신을 포함하므로 기본 설정에서 얼굴을 구성하는 셀 수가 작음. 비교 시 동일한 얼굴 점유율을 맞추는 확대·크롭 옵션이 도움될 수 있음. 원본 변경은 불필요. - -## 수정 우선순위 제안 - -유리 영역 기준으로 grid 밀도 고정 → 얼굴 세부를 남기는 셀별 샘플 폭/이동/축별 배율 조정 → 유리 패널/사진 경계 정책 일치 → 광택 형태와 강도 재조정. Depth/RenderTarget 유지. 리라이팅 불필요. - -검증 완료는 두 viewport 동일 얼굴 셀 밀도, 정지 화면 눈/코 식별, 광택ON에서 회색 막 억제, 큰 drag 경계 일관성으로 판단. 이번 브라우저 error 로그는 비어 있었으나 실행 오류 없음과 시각 목표 달성은 별개다. 기존 QA는 기능 통과에 치우쳤음. - -## 추가 QA: 셀 내부 굴곡 - -현재 법선에는 셀 전체 기울기 (random-.5)*.10과 셀 내부 변화 local*.025가 모두 있다. 굴곡이 아예 없는 것은 아니지만 중심→가장자리의 축별 법선 변화는 약0.72도로 약하고, 셀 전체 기울기 최대 약2.86도와 강한 샘플 확대에 가려진다. projected refraction의 ±.4cell clamp가 포화된 축에서는 국소 굴곡 변화가 잘릴 수도 있다(코드상 조건, 포화 빈도 계측은 미수행). - -Astra 제안: 사각 셀 중앙이 얕게 부풀고 가장자리로 내려오는 pillow형 높이 h=A(1-qx²)(1-qy²), q=2local의 기울기에서 법선을 유도. 셀별 높이/축 비율은 작은 고정 편차만 둔다. 같은 법선을 굴절과 광택에 사용. 원형 ring 왜곡/검은 테두리는 복원하지 않는다. 사진/유리 기준 셀 좌표와 샘플 폭 문제를 함께 정리해야 한다. - -수정 시 완료 기준: 광택0에서도 셀 내부 사진 윤곽의 완만한 휘어짐이 보이고, 광택ON에서는 같은 곡면을 따라 반사가 움직인다. 셀 중심·변·모서리의 반응 차이가 있으면서 눈/코 정보가 유지된다. Distortion0 원본 복원. 실제 메시 두께/실루엣까지 필요한 경우는 별도 범위이며 MVP에서는 셰이더 곡면 근사 가능. 이번 추가 QA는 코드 검토만 수행했고 소스 수정은 하지 않음. - -## 2차 곡면 QA - -2026-09-11. 사용자 요청에 따라 소스 수정 없이 재검토. - -- 실제 Glass Only, 조명 X/Y=0에서 같은 사각 쿠션 패턴의 반복이 뚜렷함. 기본 최종 화면에서도 어두운 차량 영역이 퀼팅처럼 보임. 모든 셀 동일한 대칭 높이함수+높이 ±12%만 바꾸는 구조가 주요 원인. -- 실제 Final 곡률 .65→.30 비교에서 얼굴 윤곽은 자연스러워지지만 표면 패턴의 반복 자체는 남음. 단순 강도 조절만으로는 해결되지 않음. -- 광택은 단일 smooth spec lobe와 흰색 혼합. 창/긴 광원의 반사 형태가 없어 유리 표면이라는 단서가 약함. 광택 증폭보다 약한 비대칭 곡면+분명한 넓은 광원 형태의 반사 근사가 후보. 실제 환경맵이나 리라이팅 서버 도입은 필요 없음. -- 후속 최소 방향: 셀 중앙을 비교적 평탄하게 하고 곡률 중심/가로세로 곡률을 고정된 작은 편차로 변경. 변형한 높이함수의 법선을 굴절/광택에 공유. 무작위 UV 노이즈를 따로 덧씌우지 않음. 같은 구도 A/B로 반복감과 눈/코 식별을 함께 판단. -- 조건부 정적 우려: contain으로 world pane 크기가 바뀌는 이미지/viewport 조합에서는 고정 유리-배경 거리와 cellWorld 정규화 때문에 셀 단위 굴절 강도가 달라질 수 있음. 현재 portrait 샘플과 일반 desktop/mobile 조합은 world scale=1.7로 같으므로 이 문제를 재현했다고 주장하지 않음. 가로 사진/매우 좁은 stage의 추가 회귀 항목. - -이 단계에서는 코드나 사용자 미리보기 설정을 수정하지 않음. 임시 QA 탭만 사용. - -## 최신 첨부 레퍼런스 비교 판단 - -사용자 최신 이미지1(목재 프레임/작은 색면),2(큰 얼굴/확대된 눈코 조각),3(현재 차량 사진)를 직접 비교. 이미지3의 실제 슬라이더 값은 확인하지 않았으므로 현재 기본값과 같다고 가정하지 않음. - -우선 차이는 광택보다 셀 안의 이미지 구성. 현재는 원사진의 선이 이어지다가 셀 경계에서 꺾여 잘라 붙인 듯 보임. 참고는 넓게 늘어난 색면과 눈코의 또렷한 확대 조각이 공존. 모든 원본 디테일을 보존하려던 이전 QA 기준을 수정: 반려동물 식별 특징을 유지하면서 셀별 정보량 차이를 허용해야 함. 과거 전체셀 극단 축소(.03~.10)로 복귀하지 않음. - -우선순위: (1) 확대/위치조절로 얼굴 대 셀 크기를 맞춘 비교 구도 제공, 원본 자산은 보존. (2) 이미지2를 첫 시각 목표로 삼아 일부 셀에서 축별 확대/압축 편차를 늘림. 이미지1은 색면 중심의 별도 프리셋 목표. (3) 화면3의 톱니형 외곽을 유리판 경계와 분리하여 안정적인 pane 경계 확보; 원본 overscan/클리핑 검토, 장식 프레임만으로 원인을 숨기지 않음. (4) 곡면과 반사는 보조 요소로 유지, 추가 광택 강화/리라이팅 도입 보류. - -완료 기준: 동일 얼굴 점유율에서 눈/코가 다른 배율의 조각으로 보임; 얼굴을 알아볼 수 있음; 단색 pixelation도 단순 이미지 타일 절단도 아님; 유리 외곽 안정. 이번에는 소스 변경 없음. diff --git a/index.html b/index.html index 0e2a2aa..430e545 100644 --- a/index.html +++ b/index.html @@ -1,14 +1,240 @@ - + - Pet Behind Glass + + + Behind Glass · 할머니집 창가 +
-
-
+ +
+
+
+ + + + + + + +
+ +
+ behind glass + + +
+ +
+
+ +

behind glass

+

할머니 집에
멍멍이가 왔어요

+ +
+
+ + + 비워두어도 괜찮아요 · 이 브라우저에만 저장돼요 + +
+ + +
+ + + +
+ +
+ +

정말 첫 화면으로 갈까요?

+

돌아오려면 사진을 다시 골라야 해요.

+
+
+ +

메뉴

+
+ + + + + + +
+
+ +

어떤 멍멍이를 만나볼까요?

+

사진을 고른 뒤 아래 버튼을 눌러주세요

+
+ + + + + +
+ +
+ +

화면을 잠시 그리지 못했어요

+

그래픽 연결이 끊겼어요. 브라우저가 복구하면 같은 사진으로 돌아가요.
계속 이 화면이면 새로고침해 주세요.

+ +

새로고침하면 사진을 다시 선택해야 해요

+
+ +

B 유리를 그리지 못했어요

+

사진과 설정은 그대로예요. B를 다시 시도하거나 A 진단 모드를 직접 선택할 수 있어요.

+ + +
+ + +

현재 구도 저장

+
+

마음에 드는 현재 구도를 저장해 보세요

+ +
+
+ +

만든 사람

+
제작
horoli
버그 제보
sunha321@gmail.com
+ 리소스·라이선스 안내 +
+ + + + +
+ +
+

사진을 선택하면 AI가 입체감을 준비해요

+ diff --git a/package-lock.json b/package-lock.json index dbc8082..89e5bff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,16 @@ { - "name": "behind_glass", + "name": "behind-glass-v30", "lockfileVersion": 3, "requires": true, "packages": { "": { "dependencies": { + "@fastify/rate-limit": "10.3.0", + "@fastify/static": "10.1.5", "@huggingface/transformers": "^4.3.0", + "better-sqlite3": "13.0.3", + "driver.js": "1.9.0", + "fastify": "5.12.5", "three": "^0.169.0" }, "devDependencies": { @@ -13,6 +18,9 @@ "playwright-core": "1.56.1", "typescript": "^5.6.3", "vite": "^8.3.2" + }, + "engines": { + "node": "24.x" } }, "node_modules/@emnapi/runtime": { @@ -25,6 +33,218 @@ "tslib": "^2.4.0" } }, + "node_modules/@fastify/accept-negotiator": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@fastify/accept-negotiator/-/accept-negotiator-2.1.0.tgz", + "integrity": "sha512-F3EVbzWt+xcnVaOHmWyIlpuFtbxOln7HDZQsh09MtMmMm/CipMayNt8hnIL8VQi54u2ZociDbf+iluGYkf7B1A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/@fastify/ajv-compiler": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-4.0.6.tgz", + "integrity": "sha512-NtuzM0SfaMJbGlnjr9LWQUN5LzgSrbB8tf/wRZNas+4E1O/Nmzl53e7ruT61HDZyRCJGC6FxIogmNZO1c5ETBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "ajv": "^8.12.0", + "ajv-formats": "^3.0.1", + "fast-uri": "^4.0.0" + } + }, + "node_modules/@fastify/error": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@fastify/error/-/error-4.2.0.tgz", + "integrity": "sha512-RSo3sVDXfHskiBZKBPRgnQTtIqpi/7zhJOEmAxCiBcM7d0uwdGdxLlsCaLzGs8v8NnxIRlfG0N51p5yFaOentQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/@fastify/fast-json-stringify-compiler": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@fastify/fast-json-stringify-compiler/-/fast-json-stringify-compiler-5.1.0.tgz", + "integrity": "sha512-PxcYtKLbQ8Z+yApiqjK8FwxIwvEj38k2OiLc17u8dkJSlmfi2wHHPaSnaoqBPQqtvF8YVsDgDpP2snDCfFrpfw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "fast-json-stringify": "^7.0.0" + } + }, + "node_modules/@fastify/forwarded": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@fastify/forwarded/-/forwarded-3.0.2.tgz", + "integrity": "sha512-NE8HgKLgYejV9lDpqkEFaDKMLYelJBVfHekhB0UKvX0ghagXRJqg68feg8er1NPXxG4N9i6vPxzt8E+3wHfcmA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/@fastify/merge-json-schemas": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@fastify/merge-json-schemas/-/merge-json-schemas-0.2.1.tgz", + "integrity": "sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/@fastify/proxy-addr": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@fastify/proxy-addr/-/proxy-addr-5.1.1.tgz", + "integrity": "sha512-zv07Y9GEuDsJPegZoDFd4SDWaZOW8N2pa0GSrYmKpId/tjt1Hgo3BjZBVjdVpfVrHaA+Qv5jawtS2O50J5xM9g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "@fastify/forwarded": "^3.0.0", + "ipaddr.js": "^2.1.0" + } + }, + "node_modules/@fastify/rate-limit": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@fastify/rate-limit/-/rate-limit-10.3.0.tgz", + "integrity": "sha512-eIGkG9XKQs0nyynatApA3EVrojHOuq4l6fhB4eeCk4PIOeadvOJz9/4w3vGI44Go17uaXOWEcPkaD8kuKm7g6Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "@lukeed/ms": "^2.0.2", + "fastify-plugin": "^5.0.0", + "toad-cache": "^3.7.0" + } + }, + "node_modules/@fastify/send": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@fastify/send/-/send-4.1.1.tgz", + "integrity": "sha512-BYo+EiaKwlxH+WetGk6hAs1d39iP0y1gqB8lGF/qwkJ9ZZ/cBY1vx5NvExb9Sc3yRMFjD5X4Eyh4e4+TzRkzdw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "@lukeed/ms": "^2.0.2", + "escape-html": "~1.0.3", + "fast-decode-uri-component": "^1.0.1", + "http-errors": "^2.0.0", + "mime": "^3" + } + }, + "node_modules/@fastify/static": { + "version": "10.1.5", + "resolved": "https://registry.npmjs.org/@fastify/static/-/static-10.1.5.tgz", + "integrity": "sha512-3r0ZFXo82nKlPzySOUYhwWVfPZStfiwjmyevkX7cJWL2yXmEzl0Rpxv+L6L1R4OxqvlDGqf3g8OdBzILKgqe6w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "@fastify/accept-negotiator": "^2.0.0", + "@fastify/error": "^4.0.0", + "@fastify/send": "^4.0.0", + "content-disposition": "^3.0.0", + "fastify-plugin": "^6.0.0", + "fastq": "^1.17.1", + "glob": "^13.0.0" + } + }, + "node_modules/@fastify/static/node_modules/fastify-plugin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-6.0.0.tgz", + "integrity": "sha512-fZOty7z3O7vOliF6d8bHE3wiEh1KcNnKEQensSgTk9C1DvN6nRLS++XVd86v33Hw/8u9Un8A1zDrQ8ujcQDHEg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, "node_modules/@huggingface/jinja": { "version": "0.5.10", "resolved": "https://registry.npmjs.org/@huggingface/jinja/-/jinja-0.5.10.tgz", @@ -164,9 +384,6 @@ "cpu": [ "arm" ], - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -183,9 +400,6 @@ "cpu": [ "arm64" ], - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -202,9 +416,6 @@ "cpu": [ "ppc64" ], - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -221,9 +432,6 @@ "cpu": [ "riscv64" ], - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -240,9 +448,6 @@ "cpu": [ "s390x" ], - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -259,9 +464,6 @@ "cpu": [ "x64" ], - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -278,9 +480,6 @@ "cpu": [ "arm64" ], - "libc": [ - "musl" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -297,9 +496,6 @@ "cpu": [ "x64" ], - "libc": [ - "musl" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -316,9 +512,6 @@ "cpu": [ "arm" ], - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -341,9 +534,6 @@ "cpu": [ "arm64" ], - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -366,9 +556,6 @@ "cpu": [ "ppc64" ], - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -391,9 +578,6 @@ "cpu": [ "riscv64" ], - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -416,9 +600,6 @@ "cpu": [ "s390x" ], - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -441,9 +622,6 @@ "cpu": [ "x64" ], - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -466,9 +644,6 @@ "cpu": [ "arm64" ], - "libc": [ - "musl" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -491,9 +666,6 @@ "cpu": [ "x64" ], - "libc": [ - "musl" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -601,6 +773,15 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@lukeed/ms": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@lukeed/ms/-/ms-2.0.2.tgz", + "integrity": "sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/@oxc-project/types": { "version": "0.152.0", "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.152.0.tgz", @@ -611,6 +792,12 @@ "url": "https://github.com/sponsors/oxc-project" } }, + "node_modules/@pinojs/redact": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz", + "integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==", + "license": "MIT" + }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -778,9 +965,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -798,9 +982,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -818,9 +999,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -838,9 +1016,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -858,9 +1033,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -878,9 +1050,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -1000,6 +1169,12 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/abstract-logging": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz", + "integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==", + "license": "MIT" + }, "node_modules/adm-zip": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.6.1.tgz", @@ -1009,6 +1184,144 @@ "node": ">=14.0" } }, + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv/node_modules/fast-uri": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.8.tgz", + "integrity": "sha512-GZMtZUTNRpOVIECoXwLNZS5xUGE+mVNbTB8h/7Rwh2TFWcBQiPzTgyZi05BF9UMZKkLJv8XBRJTlU7zg8+ZfMg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/avvio": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/avvio/-/avvio-9.3.0.tgz", + "integrity": "sha512-g2tQ7LE7oOSqDfwEm3M+ZCMTJc7KiZCdJ4UwyZJb5ckTKyYu50OYmvv0mCFXPuYXoM4zkSt8zM9XQ9KCvxA74A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "@fastify/error": "^4.0.0", + "fastq": "^1.17.1" + } + }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/better-sqlite3": { + "version": "13.0.3", + "gypfile": false, + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-13.0.3.tgz", + "integrity": "sha512-RbOBxmLBG8uvFUc15X9+9SFemKcQ0WBuISBVkpuiaUB2qblC8UWlHEjdWVoZ8AdhSwmoEgsiXKfopX0CQxaACQ==", + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.0.0" + }, + "engines": { + "node": ">=22" + } + }, + "node_modules/brace-expansion": { + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz", + "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==", + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/content-disposition": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-3.0.0.tgz", + "integrity": "sha512-ZH/0Xs9rMIFWCOmGdmS9eHBTF62qqQYNz4nVjQhkdIO/a0fCP4UIM3mRz/wiqL0L14YgAz/1xio4OaSY4+ON/A==", + "license": "MIT", + "engines": { + "node": ">=22" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -1043,6 +1356,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", @@ -1052,6 +1383,12 @@ "node": ">=8" } }, + "node_modules/driver.js": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/driver.js/-/driver.js-1.9.0.tgz", + "integrity": "sha512-+YWVdNVUrY1/2spszQshohWYY4soIjNBnMFS6lfmousT8igos2lmswhlqyuuNMhr+qbV0EjJ+L6i2FECPr6Ygg==", + "license": "MIT" + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -1070,6 +1407,12 @@ "node": ">= 0.4" } }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -1082,6 +1425,125 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/fast-decode-uri-component": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", + "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-json-stringify": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-7.0.1.tgz", + "integrity": "sha512-eRSayARSbbwlBjpP4vnTTIRD5QPcIrmihPxDeN1DtKnHPg66UuJLx+8hlK1kaFdjvzyQ/dzALoi4vwAQ+T+iZA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "@fastify/merge-json-schemas": "^0.2.0", + "ajv": "^8.12.0", + "ajv-formats": "^3.0.1", + "fast-uri": "^4.0.0", + "json-schema-ref-resolver": "^3.0.0", + "rfdc": "^1.2.0" + } + }, + "node_modules/fast-querystring": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fast-querystring/-/fast-querystring-1.1.2.tgz", + "integrity": "sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==", + "license": "MIT", + "dependencies": { + "fast-decode-uri-component": "^1.0.1" + } + }, + "node_modules/fast-uri": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-4.2.1.tgz", + "integrity": "sha512-TmHQgewjHtMq1E5QKA0tOE0yeYGQs25KZC/ziJpubRtWI15W92e6vPFydWOeZBVROSHBYw/QhD9d5OefdD6LDg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastify": { + "version": "5.12.5", + "resolved": "https://registry.npmjs.org/fastify/-/fastify-5.12.5.tgz", + "integrity": "sha512-OB2k1dlxs5/NAABqeKV2FUHkSD2BbENsCak8yULVcymn3fHIPDVa9TI3SDnJSWYSllZmSYuZXy2gTnsT+Sut1A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "@fastify/ajv-compiler": "^4.0.5", + "@fastify/error": "^4.0.0", + "@fastify/fast-json-stringify-compiler": "^5.0.0", + "@fastify/proxy-addr": "^5.0.0", + "abstract-logging": "^2.0.1", + "avvio": "^9.0.0", + "fast-json-stringify": "^7.0.0", + "find-my-way": "^9.6.0", + "light-my-request": "^6.0.0", + "pino": "^9.14.0 || ^10.1.0", + "process-warning": "^5.1.0", + "rfdc": "^1.3.1", + "secure-json-parse": "^4.0.0", + "semver": "^7.6.0", + "toad-cache": "^3.7.0" + } + }, + "node_modules/fastify-plugin": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-5.1.0.tgz", + "integrity": "sha512-FAIDA8eovSt5qcDgcBvDuX/v0Cjz0ohGhENZ/wpc3y+oZCY2afZ9Baqql3g/lC+OHRnciQol4ww7tuthOb9idw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.3.tgz", + "integrity": "sha512-XKv5nnLs6nLF71NgiKJLIZFLkPyIEuOselLG7ujZnGrRfQK8HpvY+WqKhAJUAdLomwVHErVS4LfxFlPq0/FTAw==", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", @@ -1107,6 +1569,20 @@ "dev": true, "license": "MIT" }, + "node_modules/find-my-way": { + "version": "9.9.0", + "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-9.9.0.tgz", + "integrity": "sha512-sJsgZ1sQH2UDuowPuMKg8az7Qc8F0jnj+SKkFWU/+T0xcFlgV5skgXOGUqmQzOdmW6ALA7AhJINWx3qFBkbLHA==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-querystring": "^1.0.0", + "safe-regex2": "^5.0.0" + }, + "engines": { + "node": ">=20" + } + }, "node_modules/flatbuffers": { "version": "25.9.23", "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-25.9.23.tgz", @@ -1128,6 +1604,23 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/global-agent": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-4.1.3.tgz", @@ -1189,6 +1682,103 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.5.0.tgz", + "integrity": "sha512-aq+t5NAc+cS6rZQQVWC2x98CPqGtKKTMDd4Gaodv0wShnItdKg/51djkGJ1hqH+Oy0ivDftCbSLCQob8zso01w==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/json-schema-ref-resolver": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-schema-ref-resolver/-/json-schema-ref-resolver-3.0.0.tgz", + "integrity": "sha512-hOrZIVL5jyYFjzk7+y7n5JDzGlU8rfWDuYyHwGa2WA8/pcmMHezp2xsVwxrebD/Q9t8Nc5DboieySDpCp4WG4A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/light-my-request": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-6.6.0.tgz", + "integrity": "sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause", + "dependencies": { + "cookie": "^1.0.1", + "process-warning": "^4.0.0", + "set-cookie-parser": "^2.6.0" + } + }, + "node_modules/light-my-request/node_modules/process-warning": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.1.tgz", + "integrity": "sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, "node_modules/lightningcss": { "version": "1.33.0", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", @@ -1332,9 +1922,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -1356,9 +1943,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -1380,9 +1964,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -1404,9 +1985,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -1468,6 +2046,15 @@ "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", "license": "Apache-2.0" }, + "node_modules/lru-cache": { + "version": "11.5.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.3.tgz", + "integrity": "sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, "node_modules/matcher": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/matcher/-/matcher-4.0.0.tgz", @@ -1490,6 +2077,42 @@ "dev": true, "license": "MIT" }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/nanoid": { "version": "3.3.19", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.19.tgz", @@ -1509,6 +2132,15 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/node-addon-api": { + "version": "8.9.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.9.2.tgz", + "integrity": "sha512-VijLXbi3UACN69I0JVXJsX4tjACjNoQDgv2gTF6sx2wWEi8tkSg2eX8p5gSIFi8z2+DL3oHmY6OyKce38SDolg==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -1518,6 +2150,15 @@ "node": ">= 0.4" } }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/onnxruntime-common": { "version": "1.30.0", "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.30.0.tgz", @@ -1561,6 +2202,22 @@ "integrity": "sha512-gBuF6U32YErKIAt+yD7DeGBpjRxhJ1uJwako6ygjokSZULDU6Pd+KWComX8Tumk1hYVHRxjPj7mdMnD0ryAPOw==", "license": "MIT" }, + "node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -1581,6 +2238,43 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pino": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-10.4.0.tgz", + "integrity": "sha512-bk1ZMTwG/Vymx+zPoa28MhNzucFvXJWp3csrSuxuHPSMeUettaCoQ5Jvg07mtC4JGNpcfTwz41oVCnNgBK9+vA==", + "license": "MIT", + "dependencies": { + "@pinojs/redact": "^0.4.0", + "atomic-sleep": "^1.0.0", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^3.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^5.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^1.0.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^4.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz", + "integrity": "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==", + "license": "MIT", + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.1.0.tgz", + "integrity": "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==", + "license": "MIT" + }, "node_modules/platform": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", @@ -1629,6 +2323,22 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/process-warning": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.1.0.tgz", + "integrity": "sha512-jQSaVHsPgtyw60e1rQ/A+/ArPEj/S8pS/vFnyGa/gYFXrKk/6RuDkoqVDQ5NI5MmS01698ltlAk0NoDBNLujRw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, "node_modules/protobufjs": { "version": "7.6.6", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.6.tgz", @@ -1652,6 +2362,52 @@ "node": ">=12.0.0" } }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", + "license": "MIT" + }, + "node_modules/real-require": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-1.0.0.tgz", + "integrity": "sha512-P4nbQYQfePJxRSmY+v/KINxVucm4NF3p3s7pJveMTtom52FR4YGltUQLB8idDXwDDWW+eYrWDFbuzUnjoWHF7g==", + "license": "MIT" + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ret": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.5.0.tgz", + "integrity": "sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "license": "MIT" + }, "node_modules/rolldown": { "version": "1.2.12", "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.12.tgz", @@ -1686,6 +2442,53 @@ "@rolldown/binding-win32-x64-msvc": "1.2.12" } }, + "node_modules/safe-regex2": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-5.1.1.tgz", + "integrity": "sha512-mOSBvHGDZMuIEZMdOz/aCEYDCv0E7nfcNsIhUF+/P+xC7Hyf3FkvymqgPbg9D1EdSGu+uKbJgy09K/RKKc7kJA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "ret": "~0.5.0" + }, + "bin": { + "safe-regex2": "bin/safe-regex2.js" + } + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/secure-json-parse": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-4.1.0.tgz", + "integrity": "sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/semver": { "version": "7.8.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", @@ -1713,6 +2516,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "license": "MIT" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, "node_modules/sharp": { "version": "0.35.5", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.5.tgz", @@ -1762,6 +2577,15 @@ } } }, + "node_modules/sonic-boom": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.1.tgz", + "integrity": "sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, "node_modules/source-map-js": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz", @@ -1772,6 +2596,36 @@ "node": ">=0.10.0" } }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/thread-stream": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-4.2.0.tgz", + "integrity": "sha512-e2zZ96wSChazBsbENf/Pcm/4swHt2cEKQ92rhUjkL9GCKiTDJIaTBenjE/m9DXi0QBmTMDkFDdOomUy20A1tDQ==", + "license": "MIT", + "dependencies": { + "real-require": "^1.0.0" + }, + "engines": { + "node": ">=20" + } + }, "node_modules/three": { "version": "0.169.0", "resolved": "https://registry.npmjs.org/three/-/three-0.169.0.tgz", @@ -1795,6 +2649,24 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, + "node_modules/toad-cache": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/toad-cache/-/toad-cache-3.7.4.tgz", + "integrity": "sha512-m1TdR/rvT7kgGJZhspNtXdsdYk0fddFpJJFlG5s+UkPFo6lkLoZ3YLOaovPYjq1R75NP5JfeTlSHaOsE09peCg==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", diff --git a/package.json b/package.json index dc0041b..61cf6a8 100644 --- a/package.json +++ b/package.json @@ -1 +1,40 @@ -{"scripts":{"dev":"vite","build":"tsc -b && vite build","preview":"vite preview","ai-depth-smoke":"node scripts/ai-depth-smoke.mjs","test:mosaic-depth-distance":"node scripts/test-mosaic-depth-distance.mjs"},"dependencies":{"@huggingface/transformers":"^4.3.0","three":"^0.169.0"},"devDependencies":{"@types/three":"^0.169.0","playwright-core":"1.56.1","typescript":"^5.6.3","vite":"^8.3.2"},"type":"module"} \ No newline at end of file +{ + "scripts": { + "dev": "vite", + "build": "tsc -b && node scripts/build.mjs VITE_ARRIVAL_ANALYTICS=false", + "preview": "vite preview", + "ai-depth-smoke": "node scripts/ai-depth-smoke.mjs", + "test:mosaic-depth-distance": "node scripts/test-mosaic-depth-distance.mjs", + "build:server": "tsc -b && node scripts/build.mjs VITE_ARRIVAL_ANALYTICS=true", + "test:arrival:server": "node --test scripts/test-arrival-db.mjs scripts/test-arrival-api.mjs scripts/test-arrival-operations.mjs", + "test:arrival:client": "node --test scripts/test-analytics-identity.mjs scripts/test-analytics-transport.mjs scripts/test-analytics-tracker.mjs scripts/test-arrival-count.mjs scripts/test-arrival-integration.mjs", + "test:arrival": "npm run test:arrival:server && npm run test:arrival:client", + "start": "node server/index.mjs", + "start:local": "node --env-file=deploy/arrival.local.env server/index.mjs", + "metrics": "node server/metrics.mjs", + "backup": "node server/backup.mjs" + }, + "dependencies": { + "@fastify/rate-limit": "10.3.0", + "@fastify/static": "10.1.5", + "@huggingface/transformers": "^4.3.0", + "better-sqlite3": "13.0.3", + "driver.js": "1.9.0", + "fastify": "5.12.5", + "three": "^0.169.0" + }, + "devDependencies": { + "@types/three": "^0.169.0", + "playwright-core": "1.56.1", + "typescript": "^5.6.3", + "vite": "^8.3.2" + }, + "type": "module", + "engines": { + "node": "24.x" + }, + "allowScripts": { + "onnxruntime-node@1.30.0": true, + "protobufjs@7.6.6": true + } +} diff --git a/public/THIRD-PARTY-NOTICES.txt b/public/THIRD-PARTY-NOTICES.txt index 4083286..4734160 100644 --- a/public/THIRD-PARTY-NOTICES.txt +++ b/public/THIRD-PARTY-NOTICES.txt @@ -1,4 +1,4 @@ -Pet Behind Glass · AI depth third-party notices +Pet Behind Glass · third-party notices Depth Anything V2 Small Model: onnx-community/depth-anything-v2-small-ONNX @@ -6,14 +6,6 @@ Model card: https://huggingface.co/onnx-community/depth-anything-v2-small-ONNX Upstream project: https://github.com/DepthAnything/Depth-Anything-V2 License: Apache License 2.0 -Depth Anything V2 Base (optional, noncommercial testing) -Model: onnx-community/depth-anything-v2-base-ONNX -Model card: https://huggingface.co/onnx-community/depth-anything-v2-base-ONNX -Upstream project: https://github.com/DepthAnything/Depth-Anything-V2 -License: Creative Commons Attribution-NonCommercial 4.0 International -License text: https://creativecommons.org/licenses/by-nc/4.0/legalcode.en -The Base ONNX weights are an ONNX conversion of the upstream Base model. - The ONNX model weights are downloaded from Hugging Face by the browser when the AI depth feature is first used. They are not included in this application bundle. @@ -23,3 +15,50 @@ Project: https://github.com/huggingface/transformers.js License: Apache License 2.0 The full Apache License 2.0 text is provided in licenses/Apache-2.0.txt. + +배민 꾸불림체 / BM Kkubulim +Copyright: Woowa Brothers Corporation +Official font page: https://www.woowahan.com/fonts +Original font: https://woowahan-cdn.woowahan.com/static/fonts/BMKkubulim.otf?d35cc1bf +Official licensing notice: https://www.woowahan.com/fonts/license +License: SIL Open Font License 1.1 + +The complete font is self-hosted in fonts/BMKkubulim.woff. This is lossless WOFF +packaging of the official OTF, with all original font tables byte-preserved, +no subsetting, and no added WOFF metadata. The font is not sold separately. +The full copyright, reserved font names, intellectual-property notice and OFL +text are provided in licenses/BMKkubulim-OFL.txt. + +Three.js 0.169.0 +Project: https://github.com/mrdoob/three.js +License: MIT +Full copyright and license: licenses/Threejs-MIT.txt + +ONNX Runtime Web / Common +Project: https://github.com/microsoft/onnxruntime +Source revision recorded by the installed web runtime: 8d85527a0 +License: MIT, Copyright (c) Microsoft Corporation +Full license: licenses/ONNX-Runtime-MIT.txt +Upstream third-party notices: licenses/ONNX-Runtime-ThirdPartyNotices.txt +The upstream notice collection covers multiple build targets; inclusion here does +not mean every listed component is shipped in this browser build. + +Hugging Face Jinja 0.5.10 +Bundled by Transformers.js. License: MIT +Full copyright and license: licenses/HuggingFace-Jinja-MIT.txt + +Hugging Face Tokenizers 0.2.0 +Bundled by Transformers.js. License: Apache License 2.0 +Full license: licenses/Apache-2.0.txt + +Retained experimental U2Netp model / cutout resources +Model and source details, Apache-2.0 and rembg code MIT text: +models/u2netp/LICENSES.txt +The experiment is not exposed in the consumer settings. These notices are +retained because the resources remain in the application distribution. + +Driver.js 1.9.0 +Project: https://driverjs.com/ +Copyright (c) Kamran Ahmed +License: MIT +Full copyright and permission text: licenses/Driverjs-MIT.txt diff --git a/public/assets/qa/dog1.jpeg b/public/assets/qa/dog1.jpeg deleted file mode 100644 index d0dc8ae..0000000 Binary files a/public/assets/qa/dog1.jpeg and /dev/null differ diff --git a/public/assets/qa/dog2.jpeg b/public/assets/qa/dog2.jpeg deleted file mode 100644 index af31ee7..0000000 Binary files a/public/assets/qa/dog2.jpeg and /dev/null differ diff --git a/public/assets/qa/dog3.webp b/public/assets/qa/dog3.webp deleted file mode 100644 index 639a94c..0000000 Binary files a/public/assets/qa/dog3.webp and /dev/null differ diff --git a/public/assets/qa/dog4.jpeg b/public/assets/qa/dog4.jpeg deleted file mode 100644 index 6fee9db..0000000 Binary files a/public/assets/qa/dog4.jpeg and /dev/null differ diff --git a/public/assets/sample-pet-depth.json b/public/assets/sample-pet-depth.json deleted file mode 100644 index 763bd63..0000000 --- a/public/assets/sample-pet-depth.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "width": 415, - "height": 739, - "convention": "0 = far/background, 1 = near/foreground", - "source": "Hand-authored procedural Gaussian ellipses for local testing; not AI-estimated or physically measured.", - "landmarks": [ - { - "name": "nose", - "x": 235, - "y": 310, - "depth": 0.98 - }, - { - "name": "left-eye", - "x": 198, - "y": 278, - "depth": 0.68 - }, - { - "name": "right-eye", - "x": 249, - "y": 273, - "depth": 0.68 - }, - { - "name": "face", - "x": 221, - "y": 267, - "depth": 0.6 - }, - { - "name": "left-ear", - "x": 158, - "y": 213, - "depth": 0.43 - }, - { - "name": "right-ear", - "x": 262, - "y": 206, - "depth": 0.43 - }, - { - "name": "body", - "x": 139, - "y": 419, - "depth": 0.3 - }, - { - "name": "muzzle", - "x": 224, - "y": 305, - "depth": 0.82 - } - ] -} diff --git a/public/assets/sample-pet-depth.png b/public/assets/sample-pet-depth.png deleted file mode 100644 index c764035..0000000 Binary files a/public/assets/sample-pet-depth.png and /dev/null differ diff --git a/public/assets/sample-pet.png b/public/assets/sample-pet.png deleted file mode 100644 index 320c9fa..0000000 Binary files a/public/assets/sample-pet.png and /dev/null differ diff --git a/public/assets/samples/dog1.jpg b/public/assets/samples/dog1.jpg new file mode 100644 index 0000000..ac5ec47 Binary files /dev/null and b/public/assets/samples/dog1.jpg differ diff --git a/public/assets/samples/dog2.jpg b/public/assets/samples/dog2.jpg new file mode 100644 index 0000000..905b076 Binary files /dev/null and b/public/assets/samples/dog2.jpg differ diff --git a/public/assets/samples/dog3.jpg b/public/assets/samples/dog3.jpg new file mode 100644 index 0000000..513b01a Binary files /dev/null and b/public/assets/samples/dog3.jpg differ diff --git a/public/assets/samples/dog4.jpg b/public/assets/samples/dog4.jpg new file mode 100644 index 0000000..80d5f8d Binary files /dev/null and b/public/assets/samples/dog4.jpg differ diff --git a/public/assets/samples/dog5.jpg b/public/assets/samples/dog5.jpg new file mode 100644 index 0000000..18f9201 Binary files /dev/null and b/public/assets/samples/dog5.jpg differ diff --git a/public/assets/window/grandma-house-surround.glb b/public/assets/window/grandma-house-surround.glb new file mode 100644 index 0000000..1061398 Binary files /dev/null and b/public/assets/window/grandma-house-surround.glb differ diff --git a/public/assets/window/grandma-wood-sash.glb b/public/assets/window/grandma-wood-sash.glb new file mode 100644 index 0000000..6b4cf54 Binary files /dev/null and b/public/assets/window/grandma-wood-sash.glb differ diff --git a/public/fonts/BMKkubulim.woff b/public/fonts/BMKkubulim.woff new file mode 100644 index 0000000..4a1a660 Binary files /dev/null and b/public/fonts/BMKkubulim.woff differ diff --git a/public/licenses/BMKkubulim-OFL.txt b/public/licenses/BMKkubulim-OFL.txt new file mode 100644 index 0000000..490ae30 --- /dev/null +++ b/public/licenses/BMKkubulim-OFL.txt @@ -0,0 +1,105 @@ +Baemin Kkubulim font licensing + +Official font source: https://www.woowahan.com/fonts +Official copyright and license page: https://www.woowahan.com/fonts/license +OFL text source: https://openfontlicense.org/documents/OFL.txt +Retrieved 2026-10-06. Font-specific introductory notice and copyright/RFN statement below are copied from Woowa Brothers. Full OFL body is copied from SIL's official text. + +The intellectual property rights of Hanna, Hanna Air, Hanna Pro, Jua, Dohyeon, Yeonsung, KirangHaerang, Euljiro, and Euljiro 10 Years Later, Baemin Geullim, Baemin Euljiro OraeOrae, BM Kkubulim fonts are held by Woowa Brothers. + Fonts distributed free of charge by Baedal Minjok (Hanna, Jua, Dohyeon, Yeonsung, KirangHaerang, Hanna Air, Hanna Pro, Euljiro, Euljiro 10 Years Later, Baemin Geullim, Baemin Euljiro OraeOrae, BM kkubulim) can be modified and hanged freely and used by both individual and corporate users for commercial or non-profit purposes. + However, please note that sales of the font file (OTF/TTF) is prohibited. + Images of prints, advertisements (including online advertisements), and other products using free fonts distributed by Baemin (Hanna, Jua, Dohyeon, Yeonsung, KirangHaerang, Hanna Air, Hanna Pro, Euljiro, Euljiro 10 Years Later, Baemin Geullim, Baemin Euljiro OraeOrae, BM Kkubulim) may be used for the company’s data collection and research purposes. If you wish to opt out of such use, please feel free to contact our Customer Service Center (+82-1600-0987 / CS@woowahan.com). + Provided that the full text of the "Intellectual Property Guide and License" below is shown, the fonts may be bundled, redistributed, or sold with other software. + Copyright © 2013, Woowa Brothers Corporation (https://www.woowahan.com), with Reserved Font Name BM HANNA 11yrs old, BM HANNA 11yrs old OTF, BMHANNAAir_otf, BMHANNAAir_ttf, BMHANNAPro_otf, BMHANNAPro_ttf, BM JUA_TTF, BM JUA_OTF, BM DoHyeon, BM DoHyeon OTF, BM YEONSUNG, BM YEONSUNG OTF, BM KIRANGHAERANG, BM KIRANGHAERANG OTF, BMEULJIRO, BMEULJIROTTF, BM EULJITO 10 YEARS LATER, BM EULJITO 10 YEARS LATER TTF, BMEuljirooraeoraeOTF, BMkkubulimTTF, BMkkubulim. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + diff --git a/public/licenses/Driverjs-MIT.txt b/public/licenses/Driverjs-MIT.txt new file mode 100644 index 0000000..7ceaeef --- /dev/null +++ b/public/licenses/Driverjs-MIT.txt @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) Kamran Ahmed + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/public/licenses/HuggingFace-Jinja-MIT.txt b/public/licenses/HuggingFace-Jinja-MIT.txt new file mode 100644 index 0000000..a3ce68e --- /dev/null +++ b/public/licenses/HuggingFace-Jinja-MIT.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Hugging Face + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/public/licenses/ONNX-Runtime-MIT.txt b/public/licenses/ONNX-Runtime-MIT.txt new file mode 100644 index 0000000..48bc6bb --- /dev/null +++ b/public/licenses/ONNX-Runtime-MIT.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Microsoft Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/public/licenses/ONNX-Runtime-ThirdPartyNotices.txt b/public/licenses/ONNX-Runtime-ThirdPartyNotices.txt new file mode 100644 index 0000000..75af6ad --- /dev/null +++ b/public/licenses/ONNX-Runtime-ThirdPartyNotices.txt @@ -0,0 +1,6369 @@ +THIRD PARTY SOFTWARE NOTICES AND INFORMATION + +Do Not Translate or Localize + +This software incorporates material from third parties. Microsoft makes certain +open source code available at http://3rdpartysource.microsoft.com, or you may +send a check or money order for US $5.00, including the product name, the open +source component name, and version number, to: + +Source Code Compliance Team +Microsoft Corporation +One Microsoft Way +Redmond, WA 98052 +USA + +Notwithstanding any other terms, you may reverse engineer this software to the +extent required to debug changes to any libraries licensed under the GNU Lesser +General Public License. + +_____ + +Intel Math Kernel Library (Intel MKL) + +Intel Simplified Software License (Version April 2018) + +Copyright (c) 2018 Intel Corporation. + +Use and Redistribution. You may use and redistribute the software (the “Software”), without modification, +provided the following conditions are met: + +* Redistributions must reproduce the above copyright notice and the following terms of use in the Software +and in the documentation and/or other materials provided with the distribution. + +* Neither the name of Intel nor the names of its suppliers may be used to endorse or promote products +derived from this Software without specific prior written permission. + +* No reverse engineering, decompilation, or disassembly of this Software is permitted. + +Limited patent license. Intel grants you a world-wide, royalty-free, non-exclusive license under patents it now +or hereafter owns or controls to make, have made, use, import, offer to sell and sell (“Utilize”) this Software, +but solely to the extent that any such patent is necessary to Utilize the Software alone. The patent license +shall not apply to any combinations which include this software. No hardware per se is licensed hereunder. + +Third party and other Intel programs. “Third Party Programs” are the files listed in the “third-party-programs.txt” +text file that is included with the Software and may include Intel programs under separate license terms. +Third Party Programs, even if included with the distribution of the Materials, are governed by +separate license terms and those license terms solely govern your use of those programs. + +DISCLAIMER. THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED. THIS SOFTWARE IS +NOT INTENDED FOR USE IN SYSTEMS OR APPLICATIONS WHERE FAILURE OF THE SOFTWARE +MAY CAUSE PERSONAL INJURY OR DEATH AND YOU AGREE THAT YOU ARE FULLY RESPONSIBLE FOR ANY +CLAIMS, COSTS, DAMAGES, EXPENSES, AND ATTORNEYS’ FEES ARISING OUT OF ANY SUCH USE, +EVEN IF ANY CLAIM ALLEGES THAT INTEL WAS NEGLIGENT REGARDING THE DESIGN OR MANUFACTURE OF +THE MATERIALS. + +LIMITATION OF LIABILITY. IN NO EVENT WILL INTEL BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. YOU AGREE TO INDEMNIFY AND HOLD INTEL HARMLESS AGAINST ANY CLAIMS +AND EXPENSES RESULTING FROM YOUR USE OR UNAUTHORIZED USE OF THE SOFTWARE. + +No support. Intel may make changes to the Software, at any time without notice, and is not obligated to +support, update or provide training for the Software. + +Termination. Intel may terminate your right to use the Software in the event of your breach of this Agreement +and you fail to cure the breach within a reasonable period of time. + +Feedback. Should you provide Intel with comments, modifications, corrections, enhancements or other input +(“Feedback”) related to the Software Intel will be free to use, disclose, reproduce, license or otherwise +distribute or exploit the Feedback in its sole discretion without any obligations or restrictions of any kind, +including without limitation, intellectual property rights or licensing obligations. + +Compliance with laws. You agree to comply with all relevant laws and regulations governing your use, +transfer, import or export (or prohibition thereof) of the Software. + +Governing law. All disputes will be governed by the laws of the United States of America and the State of +Delaware without reference to conflict of law principles and subject to the exclusive jurisdiction of the state or +federal courts sitting in the State of Delaware, and each party agrees that it submits to the personal +jurisdiction and venue of those courts and waives any objections. The United Nations Convention on +Contracts for the International Sale of Goods (1980) is specifically excluded and will not apply to the +Software. + +*Other names and brands may be claimed as the property of others. + +_____ + +protocolbuffers/protobuf + +Copyright 2008 Google Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Code generated by the Protocol Buffer compiler is owned by the owner +of the input file used when generating it. This code is not +standalone and requires a support library to be linked with it. This +support library is itself covered by the above license. + +_____ + +madler/zlib + +The deflate format used by zlib was defined by Phil Katz. The deflate and +zlib specifications were written by L. Peter Deutsch. Thanks to all the +people who reported problems and suggested various improvements in zlib; they +are too numerous to cite here. + +Copyright notice: + + (C) 1995-2017 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* receiving +lengthy legal documents to sign. The sources are provided for free but without +warranty of any kind. The library has been entirely written by Jean-loup +Gailly and Mark Adler; it does not include third-party code. + +If you redistribute modified sources, we would appreciate that you include in +the file ChangeLog history information documenting your changes. Please read +the FAQ for more information on the distribution of modified source versions. + +_____ + +pybind/pybind11 + +Copyright (c) 2016 Wenzel Jakob , All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Please also refer to the file CONTRIBUTING.md, which clarifies licensing of +external contributions to this project including patches, pull requests, etc. + +_____ + +onnx +Open Neural Network Exchange + +Copyright (c) Facebook, Inc. and Microsoft Corporation. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +_____ + +Eigen + +MPL v2.0 +Mozilla Public License Version 2.0 + + +================================== + +1. Definitions + +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions + +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities + +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination + +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. + +_____ + +intel/dnnl + +Copyright 2016-2018 Intel Corporation + +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +sub-components: + +xbyak + +Copyright (c) 2007 MITSUNARI Shigeo. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +Neither the name of the copyright owner nor the names of its contributors may +be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +_____ + +Microsoft GSL + +Copyright (c) 2015 Microsoft Corporation. All rights reserved. + +This code is licensed under the MIT License (MIT). + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +_____ + +Tensorflow + +Copyright 2018 The TensorFlow Authors. All rights reserved. + +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, +and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by +the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all +other entities that control, are controlled by, or are under common +control with that entity. For the purposes of this definition, +"control" means (i) the power, direct or indirect, to cause the +direction or management of such entity, whether by contract or +otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity +exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, +including but not limited to software source code, documentation +source, and configuration files. + +"Object" form shall mean any form resulting from mechanical +transformation or translation of a Source form, including but +not limited to compiled object code, generated documentation, +and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or +Object form, made available under the License, as indicated by a +copyright notice that is included in or attached to the work +(an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object +form, that is based on (or derived from) the Work and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. For the purposes +of this License, Derivative Works shall not include works that remain +separable from, or merely link (or bind by name) to the interfaces of, +the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including +the original version of the Work and any modifications or additions +to that Work or Derivative Works thereof, that is intentionally +submitted to Licensor for inclusion in the Work by the copyright owner +or by an individual or Legal Entity authorized to submit on behalf of +the copyright owner. For the purposes of this definition, "submitted" +means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, +and issue tracking systems that are managed by, or on behalf of, the +Licensor for the purpose of discussing and improving the Work, but +excluding communication that is conspicuously marked or otherwise +designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity +on behalf of whom a Contribution has been received by Licensor and +subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable +copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the +Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable +(except as stated in this section) patent license to make, have made, +use, offer to sell, sell, import, and otherwise transfer the Work, +where such license applies only to those patent claims licensable +by such Contributor that are necessarily infringed by their +Contribution(s) alone or by combination of their Contribution(s) +with the Work to which such Contribution(s) was submitted. If You +institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work +or a Contribution incorporated within the Work constitutes direct +or contributory patent infringement, then any patent licenses +granted to You under this License for that Work shall terminate +as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the +Work or Derivative Works thereof in any medium, with or without +modifications, and in Source or Object form, provided that You +meet the following conditions: + +(a) You must give any other recipients of the Work or +Derivative Works a copy of this License; and + +(b) You must cause any modified files to carry prominent notices +stating that You changed the files; and + +(c) You must retain, in the Source form of any Derivative Works +that You distribute, all copyright, patent, trademark, and +attribution notices from the Source form of the Work, +excluding those notices that do not pertain to any part of +the Derivative Works; and + +(d) If the Work includes a "NOTICE" text file as part of its +distribution, then any Derivative Works that You distribute must +include a readable copy of the attribution notices contained +within such NOTICE file, excluding those notices that do not +pertain to any part of the Derivative Works, in at least one +of the following places: within a NOTICE text file distributed +as part of the Derivative Works; within the Source form or +documentation, if provided along with the Derivative Works; or, +within a display generated by the Derivative Works, if and +wherever such third-party notices normally appear. The contents +of the NOTICE file are for informational purposes only and +do not modify the License. You may add Your own attribution +notices within Derivative Works that You distribute, alongside +or as an addendum to the NOTICE text from the Work, provided +that such additional attribution notices cannot be construed +as modifying the License. + +You may add Your own copyright statement to Your modifications and +may provide additional or different license terms and conditions +for use, reproduction, or distribution of Your modifications, or +for any such Derivative Works as a whole, provided Your use, +reproduction, and distribution of the Work otherwise complies with +the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, +any Contribution intentionally submitted for inclusion in the Work +by You to the Licensor shall be under the terms and conditions of +this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify +the terms of any separate license agreement you may have executed +with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade +names, trademarks, service marks, or product names of the Licensor, +except as required for reasonable and customary use in describing the +origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or +agreed to in writing, Licensor provides the Work (and each +Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied, including, without limitation, any warranties or conditions +of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +PARTICULAR PURPOSE. You are solely responsible for determining the +appropriateness of using or redistributing the Work and assume any +risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, +whether in tort (including negligence), contract, or otherwise, +unless required by applicable law (such as deliberate and grossly +negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, +incidental, or consequential damages of any character arising as a +result of this License or out of the use or inability to use the +Work (including but not limited to damages for loss of goodwill, +work stoppage, computer failure or malfunction, or any and all +other commercial damages or losses), even if such Contributor +has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing +the Work or Derivative Works thereof, You may choose to offer, +and charge a fee for, acceptance of support, warranty, indemnity, +or other liability obligations and/or rights consistent with this +License. However, in accepting such obligations, You may act only +on Your own behalf and on Your sole responsibility, not on behalf +of any other Contributor, and only if You agree to indemnify, +defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason +of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2017, The TensorFlow Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +_____ + +Microsoft Cognitive Toolkit (CNTK) + +Copyright (c) Microsoft Corporation. All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +_____ + +NumPy License + +Copyright (c) 2005, NumPy Developers + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + Neither the name of the NumPy Developers nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +_____ + +Pytorch / Caffe2 + +From PyTorch: + +Copyright (c) 2016- Facebook, Inc (Adam Paszke) +Copyright (c) 2014- Facebook, Inc (Soumith Chintala) +Copyright (c) 2011-2014 Idiap Research Institute (Ronan Collobert) +Copyright (c) 2012-2014 Deepmind Technologies (Koray Kavukcuoglu) +Copyright (c) 2011-2012 NEC Laboratories America (Koray Kavukcuoglu) +Copyright (c) 2011-2013 NYU (Clement Farabet) +Copyright (c) 2006-2010 NEC Laboratories America (Ronan Collobert, Leon Bottou, Iain Melvin, Jason Weston) +Copyright (c) 2006 Idiap Research Institute (Samy Bengio) +Copyright (c) 2001-2004 Idiap Research Institute (Ronan Collobert, Samy Bengio, Johnny Mariethoz) + +From Caffe2: + +Copyright (c) 2016-present, Facebook Inc. All rights reserved. + +All contributions by Facebook: +Copyright (c) 2016 Facebook Inc. + +All contributions by Google: +Copyright (c) 2015 Google Inc. +All rights reserved. + +All contributions by Yangqing Jia: +Copyright (c) 2015 Yangqing Jia +All rights reserved. + +All contributions from Caffe: +Copyright(c) 2013, 2014, 2015, the respective contributors +All rights reserved. + +All other contributions: +Copyright(c) 2015, 2016 the respective contributors +All rights reserved. + +Caffe2 uses a copyright model similar to Caffe: each contributor holds +copyright over their contributions to Caffe2. The project versioning records +all such contribution and copyright details. If a contributor wants to further +mark their specific copyright on a particular contribution, they should +indicate their copyright solely in the commit message of the change when it is +committed. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the names of Facebook, Deepmind Technologies, NYU, NEC Laboratories America + and IDIAP Research Institute nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +_____ + +Caffe + +COPYRIGHT + +All contributions by the University of California: +Copyright (c) 2014-2017 The Regents of the University of California (Regents) +All rights reserved. + +All other contributions: +Copyright (c) 2014-2017, the respective contributors +All rights reserved. + +Caffe uses a shared copyright model: each contributor holds copyright over +their contributions to Caffe. The project versioning records all such +contribution and copyright details. If a contributor wants to further mark +their specific copyright on a particular contribution, they should indicate +their copyright solely in the commit message of the change when it is +committed. + +LICENSE + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +CONTRIBUTION AGREEMENT + +By contributing to the BVLC/caffe repository through pull-request, comment, +or otherwise, the contributor releases their content to the +license and copyright terms herein. + +_____ + +The LLVM Compiler Infrastructure + +============================================================================== +LLVM Release License +============================================================================== +University of Illinois/NCSA +Open Source License + +Copyright (c) 2003-2017 University of Illinois at Urbana-Champaign. +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. + +============================================================================== +Copyrights and Licenses for Third Party Software Distributed with LLVM: +============================================================================== +The LLVM software contains code written by third parties. Such software will +have its own individual LICENSE.TXT file in the directory in which it appears. +This file will describe the copyrights, license, and restrictions which apply +to that code. + +The disclaimer of warranty in the University of Illinois Open Source License +applies to all code in the LLVM Distribution, and nothing in any of the +other licenses gives permission to use the names of the LLVM Team or the +University of Illinois to endorse or promote products derived from this +Software. + +The following pieces of software have additional or alternate copyrights, +licenses, and/or restrictions: + +Program Directory +------- --------- +Google Test llvm/utils/unittest/googletest +OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex} +pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT} +ARM contributions llvm/lib/Target/ARM/LICENSE.TXT +md5 contributions llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h + +_____ + +google/benchmark + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +CONTRIBUTORS + +# People who have agreed to one of the CLAs and can contribute patches. +# The AUTHORS file lists the copyright holders; this file +# lists people. For example, Google employees are listed here +# but not in AUTHORS, because Google holds the copyright. +# +# Names should be added to this file only after verifying that +# the individual or the individual's organization has agreed to +# the appropriate Contributor License Agreement, found here: +# +# https://developers.google.com/open-source/cla/individual +# https://developers.google.com/open-source/cla/corporate +# +# The agreement for individuals can be filled out on the web. +# +# When adding J Random Contributor's name to this file, +# either J's name or J's organization's name should be +# added to the AUTHORS file, depending on whether the +# individual or corporate CLA was used. +# +# Names should be added to this file as: +# Name +# +# Please keep the list sorted. + +Albert Pretorius +Arne Beer +Billy Robert O'Neal III +Chris Kennelly +Christopher Seymour +David Coeurjolly +Deniz Evrenci +Dominic Hamon +Dominik Czarnota +Eric Fiselier +Eugene Zhuk +Evgeny Safronov +Federico Ficarelli +Felix Homann +Ismael Jimenez Martinez +Jern-Kuan Leong +JianXiong Zhou +Joao Paulo Magalhaes +John Millikin +Jussi Knuuttila +Kai Wolf +Kishan Kumar +Kaito Udagawa +Lei Xu +Matt Clarkson +Maxim Vafin +Nick Hutchinson +Oleksandr Sochka +Pascal Leroy +Paul Redmond +Pierre Phaneuf +Radoslav Yovchev +Raul Marin +Ray Glover +Robert Guo +Roman Lebedev +Shuo Chen +Tobias Ulvgård +Tom Madams +Yixuan Qiu +Yusuke Suzuki +Zbigniew Skowron + +AUTHORS + +# This is the official list of benchmark authors for copyright purposes. +# This file is distinct from the CONTRIBUTORS files. +# See the latter for an explanation. +# +# Names should be added to this file as: +# Name or Organization +# The email address is not required for organizations. +# +# Please keep the list sorted. + +Albert Pretorius +Arne Beer +Carto +Christopher Seymour +David Coeurjolly +Deniz Evrenci +Dirac Research +Dominik Czarnota +Eric Fiselier +Eugene Zhuk +Evgeny Safronov +Federico Ficarelli +Felix Homann +Google Inc. +International Business Machines Corporation +Ismael Jimenez Martinez +Jern-Kuan Leong +JianXiong Zhou +Joao Paulo Magalhaes +Jussi Knuuttila +Kaito Udagawa +Kishan Kumar +Lei Xu +Matt Clarkson +Maxim Vafin +MongoDB Inc. +Nick Hutchinson +Oleksandr Sochka +Paul Redmond +Radoslav Yovchev +Roman Lebedev +Shuo Chen +Steinar H. Gunderson +Stripe, Inc. +Yixuan Qiu +Yusuke Suzuki +Zbigniew Skowron + +_____ + +HalideIR + +Copyright (c) 2016 HalideIR contributors +Copyright (c) 2012-2014 MIT CSAIL, Google Inc., and other contributors +HalideIR is derived from the Halide project. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +_____ + +Distributed Machine Learning Common Codebase + +Copyright (c) 2015 by Contributors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +_____ + +DLPack: Open In Memory Tensor Structure + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2017 by Contributors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +_____ + +HowardHinnant/date + +The source code in this project is released using the MIT License. There is no +global license for the project because each file is licensed individually with +different author names and/or dates. + +If you contribute to this project, please add your name to the license of each +file you modify. If you have already contributed to this project and forgot to +add your name to the license, please feel free to submit a new P/R to add your +name to the license in each file you modified. + +For convenience, here is a copy of the MIT license found in each file except +without author names or dates: + +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +_____ + +FreeBSD: getopt.c file + +Copyright (c) 1987, 1993, 1994 +The Regents of the University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +3. Neither the name of the University nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. +_____ + + +google/googletest + +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +_____ + +G3log : Asynchronous logger with Dynamic Sinks + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +_____ + +Scikit-learn + +Copyright (c) 2007–2018 The scikit-learn developers. +All rights reserved. + + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + a. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + b. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + c. Neither the name of the Scikit-learn Developers nor the names of + its contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. + + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + +_____ + +google/re2 + +Copyright (c) 2009 The RE2 Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +_____ +onnx/onnx-tensorrt + +MIT License + +Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. +Copyright (c) 2018 Open Neural Network Exchange + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +_____ +nvidia/cutlass + +Copyright (c) 2017 - 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +SPDX-License-Identifier: BSD-3-Clause + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +_____ +Boost + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + + +_____ + +JDAI-CV/DNNLibrary + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [2019] [JD.com Inc. JD AI] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +_____ + +google/flatbuffers + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2014 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +_____ + +google/glog + +Copyright (c) 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +A function gettimeofday in utilities.cc is based on + +http://www.google.com/codesearch/p?hl=en#dR3YEbitojA/COPYING&q=GetSystemTimeAsFileTime%20license:bsd + +The license of this code is: + +Copyright (c) 2003-2008, Jouni Malinen and contributors +All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name(s) of the above-listed copyright holder(s) nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +_____ + +abseil-cpp +https://github.com/abseil/abseil-cpp + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +_____ + +microsoft/wil + +MIT License + +Copyright (c) Microsoft Corporation. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE + +_____ + +nlohmann/json + +MIT License + +Copyright (c) 2013-2019 Niels Lohmann + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +_____ + +dcleblanc/SafeInt + +MIT License + +Copyright (c) 2018 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +_____ +Open MPI + +3-Clause BSD License + +Most files in this release are marked with the copyrights of the +organizations who have edited them. The copyrights below are in no +particular order and generally reflect members of the Open MPI core +team who have contributed code to this release. The copyrights for +code used under license from other parties are included in the +corresponding files. + +Copyright (c) 2004-2010 The Trustees of Indiana University and Indiana + University Research and Technology + Corporation. All rights reserved. +Copyright (c) 2004-2017 The University of Tennessee and The University + of Tennessee Research Foundation. All rights + reserved. +Copyright (c) 2004-2010 High Performance Computing Center Stuttgart, + University of Stuttgart. All rights reserved. +Copyright (c) 2004-2008 The Regents of the University of California. + All rights reserved. +Copyright (c) 2006-2017 Los Alamos National Security, LLC. All rights + reserved. +Copyright (c) 2006-2017 Cisco Systems, Inc. All rights reserved. +Copyright (c) 2006-2010 Voltaire, Inc. All rights reserved. +Copyright (c) 2006-2017 Sandia National Laboratories. All rights reserved. +Copyright (c) 2006-2010 Sun Microsystems, Inc. All rights reserved. + Use is subject to license terms. +Copyright (c) 2006-2017 The University of Houston. All rights reserved. +Copyright (c) 2006-2009 Myricom, Inc. All rights reserved. +Copyright (c) 2007-2017 UT-Battelle, LLC. All rights reserved. +Copyright (c) 2007-2017 IBM Corporation. All rights reserved. +Copyright (c) 1998-2005 Forschungszentrum Juelich, Juelich Supercomputing + Centre, Federal Republic of Germany +Copyright (c) 2005-2008 ZIH, TU Dresden, Federal Republic of Germany +Copyright (c) 2007 Evergrid, Inc. All rights reserved. +Copyright (c) 2008 Chelsio, Inc. All rights reserved. +Copyright (c) 2008-2009 Institut National de Recherche en + Informatique. All rights reserved. +Copyright (c) 2007 Lawrence Livermore National Security, LLC. + All rights reserved. +Copyright (c) 2007-2017 Mellanox Technologies. All rights reserved. +Copyright (c) 2006-2010 QLogic Corporation. All rights reserved. +Copyright (c) 2008-2017 Oak Ridge National Labs. All rights reserved. +Copyright (c) 2006-2012 Oracle and/or its affiliates. All rights reserved. +Copyright (c) 2009-2015 Bull SAS. All rights reserved. +Copyright (c) 2010 ARM ltd. All rights reserved. +Copyright (c) 2016 ARM, Inc. All rights reserved. +Copyright (c) 2010-2011 Alex Brick . All rights reserved. +Copyright (c) 2012 The University of Wisconsin-La Crosse. All rights + reserved. +Copyright (c) 2013-2016 Intel, Inc. All rights reserved. +Copyright (c) 2011-2017 NVIDIA Corporation. All rights reserved. +Copyright (c) 2016 Broadcom Limited. All rights reserved. +Copyright (c) 2011-2017 Fujitsu Limited. All rights reserved. +Copyright (c) 2014-2015 Hewlett-Packard Development Company, LP. All + rights reserved. +Copyright (c) 2013-2017 Research Organization for Information Science (RIST). + All rights reserved. +Copyright (c) 2017-2018 Amazon.com, Inc. or its affiliates. All Rights + reserved. +Copyright (c) 2018 DataDirect Networks. All rights reserved. +Copyright (c) 2018-2019 Triad National Security, LLC. All rights reserved. + +$COPYRIGHT$ + +Additional copyrights may follow + +$HEADER$ + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +- Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer listed + in this license in the documentation and/or other materials + provided with the distribution. + +- Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +The copyright holders provide no reassurances that the source code +provided does not infringe any patent, copyright, or any other +intellectual property rights of third parties. The copyright holders +disclaim any liability to any recipient for claims brought against +recipient by any third party for infringement of that parties +intellectual property rights. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +_____ + +The Android Open Source Project + +Copyright (C) 2017 The Android Open Source Project +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +------ + +libprotobuf-mutator + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + ----- + + openucx/ucx + https://github.com/openucx/ucx + + Copyright (c) 2014-2015 UT-Battelle, LLC. All rights reserved. + Copyright (C) 2014-2020 Mellanox Technologies Ltd. All rights reserved. + Copyright (C) 2014-2015 The University of Houston System. All rights reserved. + Copyright (C) 2015 The University of Tennessee and The University + of Tennessee Research Foundation. All rights reserved. + Copyright (C) 2016-2020 ARM Ltd. All rights reserved. + Copyright (c) 2016 Los Alamos National Security, LLC. All rights reserved. + Copyright (C) 2016-2020 Advanced Micro Devices, Inc. All rights reserved. + Copyright (C) 2019 UChicago Argonne, LLC. All rights reserved. + Copyright (c) 2018-2020 NVIDIA CORPORATION. All rights reserved. + Copyright (C) 2020 Huawei Technologies Co., Ltd. All rights reserved. + Copyright (C) 2016-2020 Stony Brook University. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + ----- + + From PyTorch: + + Copyright (c) 2016- Facebook, Inc (Adam Paszke) + Copyright (c) 2014- Facebook, Inc (Soumith Chintala) + Copyright (c) 2011-2014 Idiap Research Institute (Ronan Collobert) + Copyright (c) 2012-2014 Deepmind Technologies (Koray Kavukcuoglu) + Copyright (c) 2011-2012 NEC Laboratories America (Koray Kavukcuoglu) + Copyright (c) 2011-2013 NYU (Clement Farabet) + Copyright (c) 2006-2010 NEC Laboratories America (Ronan Collobert, Leon Bottou, Iain Melvin, Jason Weston) + Copyright (c) 2006 Idiap Research Institute (Samy Bengio) + Copyright (c) 2001-2004 Idiap Research Institute (Ronan Collobert, Samy Bengio, Johnny Mariethoz) + + From Caffe2: + + Copyright (c) 2016-present, Facebook Inc. All rights reserved. + + All contributions by Facebook: + Copyright (c) 2016 Facebook Inc. + + All contributions by Google: + Copyright (c) 2015 Google Inc. + All rights reserved. + + All contributions by Yangqing Jia: + Copyright (c) 2015 Yangqing Jia + All rights reserved. + + All contributions from Caffe: + Copyright(c) 2013, 2014, 2015, the respective contributors + All rights reserved. + + All other contributions: + Copyright(c) 2015, 2016 the respective contributors + All rights reserved. + + Caffe2 uses a copyright model similar to Caffe: each contributor holds + copyright over their contributions to Caffe2. The project versioning records + all such contribution and copyright details. If a contributor wants to further + mark their specific copyright on a particular contribution, they should + indicate their copyright solely in the commit message of the change when it is + committed. + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the names of Facebook, Deepmind Technologies, NYU, NEC Laboratories America + and IDIAP Research Institute nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +_____ + + mpi4py + https://github.com/mpi4py/mpi4py/ + + ======================= + LICENSE: MPI for Python + ======================= + + :Author: Lisandro Dalcin + :Contact: dalcinl@gmail.com + + + Copyright (c) 2019, Lisandro Dalcin. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +_____ +huggingface/transformers + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +_____ +msgpack/msgpack-python + +Copyright (C) 2008-2011 INADA Naoki + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +_____ +lanpa/tensorboardX + +MIT License + +Copyright (c) 2017 Tzu-Wei Huang + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +_____ +tensorflow/tensorboard + +Copyright 2017 The TensorFlow Authors. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2017, The TensorFlow Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +_____ + +cerberus + +Cerberus is a lightweight and extensible data validation library for Python. + +ISC License + +Copyright (c) 2012-2016 Nicola Iarocci. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + +_____ + +MurmurHash3 + +MIT license + +https://github.com/aappleby/smhasher + +SMHasher is a test suite designed to test the distribution, collision, and +performance properties of non-cryptographic hash functions. +This is the home for the MurmurHash family of hash functions along with the +SMHasher test suite used to verify them. +SMHasher is released under the MIT license. +All MurmurHash versions are public domain software, and the author disclaims all copyright to their code. + +_____ + +gtest-ios-framework + +https://github.com/mestevens/gtest-ios-framework + +Copyright (c) 2013 Matthew Stevens + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +_____ + +DLPack + +https://github.com/dmlc/dlpack + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2017 by Contributors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +_____ + +emsdk + +MIT/Expat license + +https://github.com/emscripten-core/emsdk + +Copyright (c) 2018 Emscripten authors (see AUTHORS in Emscripten) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +---------------------------------------------------------------------------- + +This is the MIT/Expat License. For more information see: + +1. http://www.opensource.org/licenses/mit-license.php + +2. http://en.wikipedia.org/wiki/MIT_License + +_____ + +coremltools + +BSD-3-Clause License + +https://github.com/apple/coremltools + +Copyright (c) 2020, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +© 2021 GitHub, Inc. + +_____ + +react-native + +MIT License + +https://github.com/facebook/react-native + +Copyright (c) Facebook, Inc. and its affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +_____ + +pytorch/cpuinfo + +BSD 2-Clause "Simplified" License + +https://github.com/pytorch/cpuinfo + +Copyright (c) 2019 Google LLC +Copyright (c) 2017-2018 Facebook Inc. +Copyright (C) 2012-2017 Georgia Institute of Technology +Copyright (C) 2010-2012 Marat Dukhan + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +_____ + +SQLite Is Public Domain + +All of the code and documentation in SQLite has been dedicated to the public +domain by the authors. All code authors, and representatives of the companies +they work for, have signed affidavits dedicating their contributions to the +public domain and originals of those signed affidavits are stored in a firesafe +at the main offices of Hwaci. Anyone is free to copy, modify, publish, use, +compile, sell, or distribute the original SQLite code, either in source code +form or as a compiled binary, for any purpose, commercial or non-commercial, +and by any means. + +The previous paragraph applies to the deliverable code and documentation in +SQLite - those parts of the SQLite library that you actually bundle and ship +with a larger application. Some scripts used as part of the build process (for +example the "configure" scripts generated by autoconf) might fall under other +open-source licenses. Nothing from these build scripts ever reaches the final +deliverable SQLite library, however, and so the licenses associated with those +scripts should not be a factor in assessing your rights to copy and use the +SQLite library. + +All of the deliverable code in SQLite has been written from scratch. No code +has been taken from other projects or from the open internet. Every line of +code can be traced back to its original author, and all of those authors have +public domain dedications on file. So the SQLite code base is clean and is +uncontaminated with licensed code from other projects. + +_____ + +google/XNNPACK + +BSD License + +For XNNPACK software + +Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. +Copyright 2019 Google LLC + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name Facebook nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +_____ + +google/sentencepiece, https://github.com/google/sentencepiece +(included when statically linked with onnxruntime-extensions) + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +_____ + +dlfcn-win32/dlfcn-win32 is licensed under the MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +_____ + +The Python Imaging Library (PIL) is + + Copyright © 1997-2011 by Secret Labs AB + Copyright © 1995-2011 by Fredrik Lundh + +Pillow is the friendly PIL fork. It is + + Copyright © 2010-2023 by Alex Clark and contributors + +Like PIL, Pillow is licensed under the open source HPND License: + +By obtaining, using, and/or copying this software and/or its associated +documentation, you agree that you have read, understood, and will comply +with the following terms and conditions: + +Permission to use, copy, modify, and distribute this software and its +associated documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies, and that +both that copyright notice and this permission notice appear in supporting +documentation, and that the name of Secret Labs AB or the author not be +used in advertising or publicity pertaining to distribution of the software +without specific, written prior permission. + +SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + +_____ + +openssl/openssl, https://github.com/openssl/openssl + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + +_____ + +Tencent/rapidjson, https://github.com/Tencent/rapidjson + +Tencent is pleased to support the open source community by making RapidJSON available. + +Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. + +If you have downloaded a copy of the RapidJSON binary from Tencent, please note that the RapidJSON binary is licensed under the MIT License. +If you have downloaded a copy of the RapidJSON source code from Tencent, please note that RapidJSON source code is licensed under the MIT License, except for the third-party components listed below which are subject to different license terms. Your integration of RapidJSON into your own projects may require compliance with the MIT License, as well as the other licenses applicable to the third-party components included within RapidJSON. To avoid the problematic JSON license in your own projects, it's sufficient to exclude the bin/jsonchecker/ directory, as it's the only code under the JSON license. +A copy of the MIT License is included in this file. + +Other dependencies and licenses: + +Open Source Software Licensed Under the BSD License: +-------------------------------------------------------------------- + +The msinttypes r29 +Copyright (c) 2006-2013 Alexander Chemeris +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Open Source Software Licensed Under the JSON License: +-------------------------------------------------------------------- + +json.org +Copyright (c) 2002 JSON.org +All Rights Reserved. + +JSON_checker +Copyright (c) 2002 JSON.org +All Rights Reserved. + + +Terms of the JSON License: +--------------------------------------------------- + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +Terms of the MIT License: +-------------------------------------------------------------------- + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +_____ + +boostorg/boost, https://github.com/boostorg/boost + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +_____ + +libb64/libb64, https://github.com/libb64/libb64 + +Copyright-Only Dedication (based on United States law) or Public Domain Certification + +The person or persons who have associated work with this document (the "Dedicator" or "Certifier") hereby either (a) certifies that, to the best of his knowledge, the work of authorship identified is in the public domain of the country from which the work is published, or (b) hereby dedicates whatever copyright the dedicators holds in the work of authorship identified below (the "Work") to the public domain. A certifier, moreover, dedicates any copyright interest he may have in the associated work, and for these purposes, is described as a "dedicator" below. + +A certifier has taken reasonable steps to verify the copyright status of this work. Certifier recognizes that his good faith efforts may not shield him from liability if in fact the work certified is not in the public domain. + +Dedicator makes this dedication for the benefit of the public at large and to the detriment of the Dedicator's heirs and successors. Dedicator intends this dedication to be an overt act of relinquishment in perpetuity of all present and future rights under copyright law, whether vested or contingent, in the Work. Dedicator understands that such relinquishment of all rights includes the relinquishment of all rights to enforce (by lawsuit or otherwise) those copyrights in the Work. + +Dedicator recognizes that, once placed in the public domain, the Work may be freely reproduced, distributed, transmitted, used, modified, built upon, or otherwise exploited by anyone for any purpose, commercial or non-commercial, and in any way, including by methods that have not yet been invented or conceived. + +_____ + +posix pthread library, https://sourceforge.net/projects/pthreads4w + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +_____ + +Triton Inference Server & Client, https://github.com/triton-inference-server + +Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of NVIDIA CORPORATION nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +_____ + +microsoft/mimalloc, https://github.com/microsoft/mimalloc + +MIT License + +Copyright (c) 2018-2021 Microsoft Corporation, Daan Leijen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +_____ + +TensorFlow.js + +https://github.com/tensorflow/tfjs + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +—— + +curl/curl + +https://github.com/curl + +COPYRIGHT AND PERMISSION NOTICE + +Copyright (C) Daniel Stenberg, , and many +contributors, see the THANKS file. + +All rights reserved. + +Permission to use, copy, modify, and distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright +notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall not +be used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization of the copyright holder. + +_____ + +Mbed TLS + +https://github.com/Mbed-TLS/mbedtls + +Copyright The Mbed TLS Contributors + +Mbed TLS is available under the Apache License 2.0 OR the GNU General Public +License, version 2 or later. This distribution uses Mbed TLS under the Apache +License 2.0. The full Apache License 2.0 terms are reproduced above in this +file. + +_____ + +Intel neural-compressor + +https://github.com/intel/neural-compressor + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + ============================================================================ + + Copyright 2016-2019 Intel Corporation + Copyright 2018 YANDEX LLC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + This distribution includes third party software ("third party programs"). + This third party software, even if included with the distribution of + the Intel software, may be governed by separate license terms, including + without limitation, third party license terms, other Intel software license + terms, and open source software license terms. These separate license terms + govern your use of the third party programs as set forth in the + "THIRD-PARTY-PROGRAMS" file. + +_____ + +FlashAttention, https://github.com/Dao-AILab/flash-attention + +BSD 3-Clause License + +Copyright (c) 2022, the respective contributors, as shown by the AUTHORS file. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +_____ + +neural-speed + +https://github.com/intel/neural-speed + + Apache License + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + ============================================================================ + + Copyright 2016-2019 Intel Corporation + Copyright 2018 YANDEX LLC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + This distribution includes third party software ("third party programs"). + This third party software, even if included with the distribution of + the Intel software, may be governed by separate license terms, including + without limitation, third party license terms, other Intel software license + terms, and open source software license terms. These separate license terms + govern your use of the third party programs as set forth in the + "THIRD-PARTY-PROGRAMS" file. + +_____ + +dawn + +https://dawn.googlesource.com/dawn + + BSD 3-Clause License + + Copyright 2017-2023 The Dawn & Tint Authors + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +_____ + +KleidiAI + +https://gitlab.arm.com/kleidi/kleidiai + +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +Copyright 2024-2025 Arm Limited and/or its affiliates + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +_____ + +microsoft/cpp_client_telemetry, https://github.com/microsoft/cpp_client_telemetry/ + +Apache License + +Copyright (c) Microsoft Corporation. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +_____ +DeepSeek DeepGEMM (https://github.com/deepseek-ai/DeepGEMM) +Commit: 559d79fb6994a58b8a15b4b93bf13ccc16edf247 + +MIT License + +Copyright (c) 2025 DeepSeek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/public/licenses/Threejs-MIT.txt b/public/licenses/Threejs-MIT.txt new file mode 100644 index 0000000..d33709f --- /dev/null +++ b/public/licenses/Threejs-MIT.txt @@ -0,0 +1,21 @@ +The MIT License + +Copyright © 2010-2024 three.js authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/public/models/u2netp/LICENSES.txt b/public/models/u2netp/LICENSES.txt new file mode 100644 index 0000000..278b5a4 --- /dev/null +++ b/public/models/u2netp/LICENSES.txt @@ -0,0 +1,222 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +MIT License + +Copyright (c) 2020 Daniel Gatis + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/public/models/u2netp/manifest.json b/public/models/u2netp/manifest.json new file mode 100644 index 0000000..6a4cea6 --- /dev/null +++ b/public/models/u2netp/manifest.json @@ -0,0 +1,182 @@ +{ + "name": "u2netp", + "revision": "sha256:309c8469258dda742793dce0ebea8e6dd393174f89934733ecc8b14c76f4ddd8", + "bytes": 4574861, + "sha256": "309c8469258dda742793dce0ebea8e6dd393174f89934733ecc8b14c76f4ddd8", + "md5": "8e83ca70e441ab06c318d82300c84806", + "source": { + "url": "https://github.com/danielgatis/rembg/releases/download/v0.0.0/u2netp.onnx", + "release": "v0.0.0", + "releaseAssetId": 85857953, + "assetUpdatedAt": "2022-11-24T19:22:32Z", + "publisher": "danielgatis", + "rembgRevision": "202e42649a8492a7c49f808de36608a7d1cbbfe3", + "upstreamU2NetRevision": "ac7e1c817ecab7c7dff5ce6b1abba61cd213ff29" + }, + "tensorContract": { + "input": [ + { + "name": "input.1", + "isTensor": true, + "type": "float32", + "shape": [ + 1, + 3, + 320, + 320 + ] + } + ], + "outputs": [ + { + "name": "1959", + "isTensor": true, + "type": "float32", + "shape": [ + 1, + 1, + 320, + 320 + ] + }, + { + "name": "1960", + "isTensor": true, + "type": "float32", + "shape": [ + 1, + 1, + 320, + 320 + ] + }, + { + "name": "1961", + "isTensor": true, + "type": "float32", + "shape": [ + 1, + 1, + 320, + 320 + ] + }, + { + "name": "1962", + "isTensor": true, + "type": "float32", + "shape": [ + 1, + 1, + 320, + 320 + ] + }, + { + "name": "1963", + "isTensor": true, + "type": "float32", + "shape": [ + 1, + 1, + 320, + 320 + ] + }, + { + "name": "1964", + "isTensor": true, + "type": "float32", + "shape": [ + 1, + 1, + 320, + 320 + ] + }, + { + "name": "1965", + "isTensor": true, + "type": "float32", + "shape": [ + 1, + 1, + 320, + 320 + ] + } + ], + "selectedOutput": "1959", + "resize": [ + 320, + 320 + ], + "layout": "NCHW", + "rgbScaling": "divide by max(maxRGB,1e-6)", + "mean": [ + 0.485, + 0.456, + 0.406 + ], + "std": [ + 0.229, + 0.224, + 0.225 + ], + "alphaPostprocess": "finite min/max normalize first output; uint8; restore canonical size" + }, + "conversionHistory": { + "status": "NOT FULLY VERIFIED", + "known": { + "1": [ + 6 + ], + "2": [ + "pytorch" + ], + "3": [ + "1.9" + ], + "8": [ + [ + [ + 2, + 0, + 11 + ] + ] + ] + }, + "missing": [ + "exact original checkpoint hash", + "export script/revision used for this release artifact", + "fully reproducible conversion chain" + ] + }, + "license": { + "upstreamU2Net": "Apache-2.0", + "rembgCode": "MIT", + "redistributionStatus": "NOT CLEARED FOR INTEGRATION: upstream license and publisher source verified, exact conversion chain remains unverified", + "licenseFiles": [ + "u2net-LICENSE", + "rembg-LICENSE.txt" + ] + }, + "qualityGate": "FAIL", + "browserRuntimeGate": "NOT RUN", + "localCpuEvidence": "u2netp-runtime-results.json", + "report": "model-gate.md", + "deploymentScope": { + "mode": "owner-private experiment", + "requiresExplicitMaskReviewForEveryPhoto": true, + "strictQualityGate": "failed", + "browserMobileGate": "not run", + "userApprovalDate": "2026-10-07", + "limitations": [ + "general foreground model, not dog-only semantic segmentation", + "body regions may disappear and background may remain", + "not a person-photo blocking mechanism" + ], + "downloadBytesMeaning": "Uncompressed model payload bytes, not measured network transfer bytes" + } +} diff --git a/public/models/u2netp/model.onnx b/public/models/u2netp/model.onnx new file mode 100644 index 0000000..4f21f9a Binary files /dev/null and b/public/models/u2netp/model.onnx differ diff --git a/scripts/ai-depth-smoke.mjs b/scripts/ai-depth-smoke.mjs index 5327ea4..f1f5dd2 100644 --- a/scripts/ai-depth-smoke.mjs +++ b/scripts/ai-depth-smoke.mjs @@ -98,7 +98,7 @@ try { await page.locator('#view-mode').selectOption('noglass'); await page.locator('#ai-depth').click(); await page.waitForFunction(() => document.querySelector('#ai-depth')?.textContent?.includes('생성 중'), null, { timeout: 5000 }); - await page.locator('#image').setInputFiles('public/assets/qa/dog1.jpeg'); + await page.locator('#image').setInputFiles('public/assets/samples/dog1.jpg'); await page.waitForFunction(() => { const button = document.querySelector('#ai-depth'); const provenance = document.querySelector('#depth-provenance'); diff --git a/scripts/build.mjs b/scripts/build.mjs new file mode 100644 index 0000000..cc1d4de --- /dev/null +++ b/scripts/build.mjs @@ -0,0 +1,14 @@ +import { spawnSync } from 'node:child_process'; +import { fileURLToPath } from 'node:url'; + +const flag = process.argv[2]; +if (!['VITE_ARRIVAL_ANALYTICS=false', 'VITE_ARRIVAL_ANALYTICS=true'].includes(flag)) { + throw new Error('Choose VITE_ARRIVAL_ANALYTICS=false or VITE_ARRIVAL_ANALYTICS=true'); +} +const viteCli = fileURLToPath(new URL('../node_modules/vite/bin/vite.js', import.meta.url)); +const result = spawnSync(process.execPath, [viteCli, 'build', ...process.argv.slice(3)], { + stdio: 'inherit', + env: { ...process.env, VITE_ARRIVAL_ANALYTICS: flag.split('=')[1] }, +}); +if (result.error) throw result.error; +process.exitCode = result.status ?? 1; diff --git a/scripts/check-sites-build.mjs b/scripts/check-sites-build.mjs new file mode 100644 index 0000000..82596e0 --- /dev/null +++ b/scripts/check-sites-build.mjs @@ -0,0 +1,45 @@ +import assert from 'node:assert/strict'; +import { readFileSync, readdirSync, statSync } from 'node:fs'; +import { join } from 'node:path'; + +const maxAssetBytes = 25 * 1024 * 1024; +function files(root, relative = '') { + return readdirSync(join(root, relative), { withFileTypes: true }).flatMap(entry => { + const path = join(relative, entry.name); + return entry.isDirectory() ? files(root, path) : [path]; + }); +} + +const built = files('dist'); +for (const file of built) { + const bytes = statSync(join('dist', file)).size; + assert(bytes <= maxAssetBytes, `${file}: ${bytes} bytes exceeds Sites' ${maxAssetBytes}-byte asset limit`); +} +for (const file of files('public')) { + assert(readFileSync(join('public', file)).equals(readFileSync(join('dist', file))), `${file}: public asset changed or missing in build`); +} +const html = readFileSync('dist/index.html', 'utf8'); +assert(html.includes('id="sample"'), 'Sample button is missing'); +assert(html.includes('value="dog1"'), 'Recommended sample option is missing'); +for (const match of html.matchAll(/(?:src|href)="(\/assets\/[^"?#]+)"/g)) { + assert(built.includes(match[1].slice(1)), `Missing HTML asset ${match[1]}`); +} +const js = built.filter(file => file.endsWith('.js')).map(file => readFileSync(join('dist', file), 'utf8')).join('\n'); +for (const id of ['dog1', 'dog2', 'dog3', 'dog4']) { + const path = `assets/samples/${id}.jpg`; + assert(built.includes(path), `Missing sample ${path}`); + assert(statSync(join('dist', path)).size < 1_000_000, `${path} must be under 1 MB`); + assert(html.includes('/' + path), `Missing sample thumbnail ${path}`); +} +assert(js.includes('/assets/samples/'), 'Sample loader path missing'); +assert(!/(?:sample-pet|assets\/qa\/dog)/.test(html + js), 'Retired sample reference in shipped bundle'); +assert(!built.some(file => /(?:sample-pet|assets\/qa\/dog)/.test(file)), 'Retired sample asset shipped'); +assert(js.includes('https://cdn.jsdelivr.net/npm/onnxruntime-web@'), 'Transformers runtime CDN configuration is missing'); +assert(!built.some(file => /(?:assets\/countryside\/|CountrysideExperience)/i.test(file)), 'Retired photo-composite scene must not ship'); +assert(built.includes('models/u2netp/model.onnx'),'Explicit opt-in small model is missing'); +assert(built.filter(file=>file.endsWith('.onnx')).length===1,'Unexpected additional model'); +assert(!/(?:cutout-review|countryside-start|scene-mode)/.test(html), 'Retired scene entry is still present'); +assert(!/(?:CountrysideExperience|\/assets\/countryside\/)/.test(js), 'Retired scene runtime can still be requested'); +assert(js.includes('이 누끼로 배치'),'Experiment must retain explicit review acceptance'); + +console.log(`Sites build checks passed: ${built.length} assets within 25 MiB, public assets byte-matched, sample UI/paths and runtime CDN configuration preserved, opt-in small cutout model present, retired photo-composite scene absent. Browser rendering and AI inference are separate checks.`); diff --git a/scripts/diagnose-stock-transmission.mjs b/scripts/diagnose-stock-transmission.mjs new file mode 100644 index 0000000..6edc09b --- /dev/null +++ b/scripts/diagnose-stock-transmission.mjs @@ -0,0 +1,46 @@ +// Numerical v13 stock-transmission formula applied to the unchanged real B geometry/thickness. +// CPU-only diagnostic: this does not execute the corrected shader or measure GPU pixels. +import {readFile} from 'node:fs/promises'; +import {pathToFileURL,fileURLToPath} from 'node:url'; +import ts from 'typescript'; +import * as THREE from 'three'; +const root=fileURLToPath(new URL('../',import.meta.url)); +async function compile(file){ + let s=await readFile(file,'utf8'); + s=s.replace(/from ['"]three['"]/g,`from '${pathToFileURL(root+'node_modules/three/build/three.module.js')}'`); + s=s.replace(/from ['"]three\/addons\/([^'"]+)['"]/g,(_,p)=>`from '${pathToFileURL(root+'node_modules/three/examples/jsm/'+p)}'`); + for(const m of [...s.matchAll(/from ['"](\.[^'"]+)['"]/g)]) s=s.replace(m[0],`from '${await compile(new URL(m[1]+'.ts',file))}'`); + return 'data:text/javascript;base64,'+Buffer.from(ts.transpileModule(s,{compilerOptions:{module:ts.ModuleKind.ES2020,target:ts.ScriptTarget.ES2020}}).outputText).toString('base64'); +} +const {PhysicalGlassComparison}=await import(await compile(pathToFileURL(root+'src/rendering/PhysicalGlassComparison.ts'))); +const {sampleGobangSurface}=await import(await compile(pathToFileURL(root+'src/rendering/PatternedGlassGeometry.ts'))); +const {comparisonLayout}=await import(await compile(pathToFileURL(root+'src/rendering/ComparisonLayout.ts'))); +const photo=new THREE.Mesh(new THREE.PlaneGeometry(1,1,128,128),new THREE.ShaderMaterial({uniforms:{uTexture:{value:new THREE.Texture()},uDepthMap:{value:new THREE.Texture()},uDepthScale:{value:.25},uDepthBias:{value:0}}})); +const adapter=new PhysicalGlassComparison({extensions:{has:()=>false}},photo); +const w=Number(process.argv[2]||390),h=Number(process.argv[3]||844), aspect=w/h, photoAspect=.8; +const baseH=Math.min(1.78*aspect/photoAspect,1.45),shape={width:baseH*photoAspect*.8,height:baseH*.8,grid:20,curvature:1}; +const panes=comparisonLayout(w,h,aspect).panes, pane=panes[0]; +const camera=new THREE.PerspectiveCamera(40,aspect,.1,100);camera.position.z=3;camera.updateMatrixWorld(); +adapter.sync(shape,.6,new THREE.Vector3(.6,.8,2.6),new THREE.Color()); +const geometry=adapter.glass.geometry,p=geometry.attributes.position,n=geometry.attributes.normal,uv=geometry.attributes.uv; +const tex=adapter.material.thicknessMap,texW=tex.image.width,texH=tex.image.height,texData=tex.image.data; +const thicknessFactor=adapter.material.thickness; +const xValues=[];for(let i=0;;i++){if(i>0&&uv.getY(i)!==0)break;xValues.push(uv.getX(i));} +const nx=xValues.length;const yValues=[];for(let i=0;itexData[(clamp(y,0,texH-1)*texW+clamp(x,0,texW-1))*4+1]/255;return thicknessFactor*((1-fy)*((1-fx)*at(x0,y0)+fx*at(x0+1,y0))+fy*((1-fx)*at(x0,y0+1)+fx*at(x0+1,y0+1)));} +function idx(a,v){let lo=0,hi=a.length-1;while(hi-lo>1){const m=(lo+hi)>>1;if(a[m]<=v)lo=m;else hi=m;}return lo;} +function interpAt(u,v){const ix=idx(xValues,u),iy=idx(yValues,v),fx=(u-xValues[ix])/(xValues[ix+1]-xValues[ix]),fy=(v-yValues[iy])/(yValues[iy+1]-yValues[iy]),a=iy*nx+ix,b=a+1,c=a+nx,d=c+1;const ids=fx>=fy?[a,b,d]:[a,d,c],ws=fx>=fy?[1-fx,fx-fy,fy]:[1-fy,fx,fy-fx];const pos=new THREE.Vector3(),norm=new THREE.Vector3();ids.forEach((id,i)=>{pos.addScaledVector(new THREE.Vector3().fromBufferAttribute(p,id),ws[i]);norm.addScaledVector(new THREE.Vector3().fromBufferAttribute(n,id),ws[i]);});pos.z+=.6;return{pos,norm:norm.normalize()};} +function refract(i,n,eta){const d=n.dot(i),k=1-eta*eta*(1-d*d);return k<0?new THREE.Vector3():i.clone().multiplyScalar(eta).addScaledVector(n,-(eta*d+Math.sqrt(k)));} +function screen(pt){const s=pt.clone().project(camera);return new THREE.Vector2(s.x*pane.width*.5,s.y*pane.height*.5);} +function resultAt(u,v){const {pos,norm}=interpAt(u,v),i=pos.clone().sub(camera.position).normalize(),r=refract(i,norm,1/1.5),t=tAt(u,v),e=pos.clone().addScaledVector(r,t),b=screen(e).distanceTo(screen(pos)),s=sampleGobangSurface(u,v,shape),normal=new THREE.Vector3(-s.dx,-s.dy,1).normalize(),front=new THREE.Vector3((u-.5)*shape.width,(v-.5)*shape.height,.6+s.height),inc=front.clone().sub(camera.position).normalize(),inside=refract(inc,normal,1/1.5),backZ=.6-.008-.085*shape.width/20,back=front.clone().addScaledVector(inside,(backZ-front.z)/inside.z),out=refract(inside,new THREE.Vector3(0,0,1),1.5);const aAt=z=>screen(back.clone().addScaledVector(out,(z-backZ)/out.z)).distanceTo(screen(front)); +const aBasePoint=back.clone().addScaledVector(out,(.6-.1296-.25-backZ)/out.z),aNearPoint=back.clone().addScaledVector(out,(.6-.1296-backZ)/out.z); +const nearReprojected=camera.position.clone().addScaledVector(aNearPoint.clone().sub(camera.position),(.6-.1296-.25-camera.position.z)/(aNearPoint.z-camera.position.z)); +const delta=nearReprojected.sub(aBasePoint);delta.z=0;delta.multiplyScalar(Math.min(1,(shape.width/20)*.35/Math.max(delta.length(),.00001))*.65); +const aNearRefined=screen(aBasePoint.clone().add(delta)).distanceTo(screen(front)); +return{u,v,normal:norm.toArray(),thickness:t,axial:pos.z-backZ,mapError:t-(pos.z-backZ),normalBakeCorrection:1/norm.z,pathCorrection:1/-r.z,b,aNear:aAt(.6-.1296),aBase:aAt(.6-.1296-.25),aNearRefined};} +let results=[];for(let y=0;y<250;y++)for(let x=0;x<200;x++)results.push(resultAt((x+.5)/200,(y+.5)/250)); +function stats(key){const vals=results.map(x=>x[key]).sort((a,b)=>a-b);return{min:vals[0],median:vals[(vals.length*.5)|0],p95:vals[(vals.length*.95)|0],max:vals.at(-1),mean:vals.reduce((a,b)=>a+b,0)/vals.length};} +const samples=[[.511,.509],[.5125,.5125],[.525,.525],[.505,.505],[.499,.5]].map(([u,v])=>resultAt(u,v)); +const pixelProjectionWidth=screen(new THREE.Vector3(shape.width/2,0,.6)).x*2; +console.log(JSON.stringify({shape,pane,glassDisplayedCssWidth:pixelProjectionWidth,material:{thickness:thicknessFactor,thicknessMap:{width:texW,height:texH,flipY:tex.flipY,colorSpace:tex.colorSpace,wrapS:tex.wrapS,wrapT:tex.wrapT,greenMin:Math.min(...texData.filter((v,i)=>i%4===1)),greenMax:Math.max(...texData.filter((v,i)=>i%4===1))}},frontSegments:[nx-1,yValues.length-1],thickness:stats('thickness'),mapError:stats('mapError'),normalBakeCorrection:stats('normalBakeCorrection'),actualNearAInteriorCss:stats('aNearRefined'),pathCorrection:stats('pathCorrection'),stockOffsetCss:stats('b'),twoSurfaceNearCss:stats('aNear'),twoSurfaceBaseCss:stats('aBase'),samples},null,2)); diff --git a/scripts/profile-photo-working-image.mjs b/scripts/profile-photo-working-image.mjs new file mode 100644 index 0000000..f088422 --- /dev/null +++ b/scripts/profile-photo-working-image.mjs @@ -0,0 +1,32 @@ +/** Node + Pillow CPU fixture check. Does not launch or emulate browser/GPU QA. */ +import assert from 'node:assert/strict'; +import {readFile,readdir,mkdtemp} from 'node:fs/promises'; +import {tmpdir} from 'node:os'; +import {join} from 'node:path'; +import {spawnSync} from 'node:child_process'; +import {createHash} from 'node:crypto'; +import {loadTypescript} from './support/load-typescript.mjs'; +const root=await mkdtemp(join(tmpdir(),'behind-glass-photo-fixtures-')); +const python=(...args)=>{const r=spawnSync('python',['scripts/support/photo-fixtures.py',...args],{encoding:'utf8'});if(r.status)throw new Error(r.stderr);return JSON.parse(r.stdout);}; +python('generate',root); +const {createPhotoSnapshot}=await loadTypescript(new URL('../src/input/PhotoSnapshot.ts',import.meta.url)); +const {readPhotoMetadata}=await loadTypescript(new URL('../src/input/PhotoMetadata.ts',import.meta.url)); +const rows=[];let closes=0; +globalThis.createImageBitmap=async(file,options)=>{assert.ok(options.resizeWidth<=1024&&options.resizeHeight<=1024,'all real fixture headers must enable first-decode bounds');const result=python('inspect',file.fixturePath,String(options.resizeWidth),String(options.resizeHeight));return{...result,close(){closes++;}};}; +for(const name of await readdir(root)){ + const path=join(root,name),bytes=await readFile(path),hash=createHash('sha256').update(bytes).digest('hex'); + const blob=new Blob([bytes]);blob.fixturePath=path; + const metadata=await readPhotoMetadata(blob),snapshot=await createPhotoSnapshot(blob,rows.length,new AbortController().signal),decoded=snapshot.bitmap; + assert.equal(snapshot.width,metadata.width<=metadata.height?Math.round(1024*metadata.width/metadata.height):1024); + assert.equal(snapshot.height,metadata.height<=metadata.width?Math.round(1024*metadata.height/metadata.width):1024); + assert.equal(decoded.sha256,hash,'original bytes untouched'); + assert.equal(createHash('sha256').update(await readFile(path)).digest('hex'),hash); + if(name.includes('alpha-rotated'))assert.deepEqual(decoded.corners.map(x=>x[3]),[64,255,0,192]); + if(name.includes('alpha-mirrored'))assert.deepEqual(decoded.corners.map(x=>x[3]),[64,0,255,192]); + if(name.includes('48mp'))assert.deepEqual(decoded.alphaExtrema,[128,128]); + snapshot.bitmap.close(); + const {close,...values}=decoded; + rows.push({file:name,...values,pixelReductionPercent:100*(1-values.workingRGBABytes/values.sourceRGBABytes)}); +} +assert.equal(closes,rows.length); +console.log(JSON.stringify({verification:'CPU Pillow decoder behind a test double for createImageBitmap; actual TypeScript header/resize pipeline and real JPEG/PNG/WebP fixture bytes. Not browser-native decode, WebGL upload, device memory or FPS.',fixtureDirectory:root,rows},null,2)); diff --git a/scripts/restore-source-assets.mjs b/scripts/restore-source-assets.mjs new file mode 100644 index 0000000..e9c818f --- /dev/null +++ b/scripts/restore-source-assets.mjs @@ -0,0 +1,30 @@ +// Restore byte-identical editable source assets from the included server build. +import {copyFileSync,mkdirSync} from 'node:fs'; +import {dirname,resolve} from 'node:path'; +import {fileURLToPath} from 'node:url'; +const root=fileURLToPath(new URL('..',import.meta.url)); +const files={ + "public/THIRD-PARTY-NOTICES.txt": "dist/THIRD-PARTY-NOTICES.txt", + "public/fonts/BMKkubulim.woff": "dist/fonts/BMKkubulim.woff", + "public/licenses/Threejs-MIT.txt": "dist/licenses/Threejs-MIT.txt", + "public/licenses/HuggingFace-Jinja-MIT.txt": "dist/licenses/HuggingFace-Jinja-MIT.txt", + "public/licenses/Driverjs-MIT.txt": "dist/licenses/Driverjs-MIT.txt", + "public/licenses/ONNX-Runtime-ThirdPartyNotices.txt": "dist/licenses/ONNX-Runtime-ThirdPartyNotices.txt", + "public/licenses/Apache-2.0.txt": "dist/licenses/Apache-2.0.txt", + "public/licenses/ONNX-Runtime-MIT.txt": "dist/licenses/ONNX-Runtime-MIT.txt", + "public/licenses/BMKkubulim-OFL.txt": "dist/licenses/BMKkubulim-OFL.txt", + "public/assets/samples/dog3.jpg": "dist/assets/samples/dog3.jpg", + "public/assets/samples/dog5.jpg": "dist/assets/samples/dog5.jpg", + "public/assets/samples/dog2.jpg": "dist/assets/samples/dog2.jpg", + "public/assets/samples/dog4.jpg": "dist/assets/samples/dog4.jpg", + "public/assets/samples/dog1.jpg": "dist/assets/samples/dog1.jpg", + "public/assets/window/grandma-house-surround.glb": "dist/assets/window/grandma-house-surround.glb", + "public/assets/window/grandma-wood-sash.glb": "dist/assets/window/grandma-wood-sash.glb", + "public/models/u2netp/LICENSES.txt": "dist/models/u2netp/LICENSES.txt", + "public/models/u2netp/manifest.json": "dist/models/u2netp/manifest.json", + "public/models/u2netp/model.onnx": "dist/models/u2netp/model.onnx", + "docs/qa-five-photos/reference2.png": "dist/assets/reference2-6y7JVIce.png", + "docs/qa-five-photos/reference1.png": "dist/assets/reference1-D4rK2azX.png" +}; +for(const [target,source] of Object.entries(files)){const to=resolve(root,target);mkdirSync(dirname(to),{recursive:true});copyFileSync(resolve(root,source),to);} +console.log('Source assets restored:',Object.keys(files).length); diff --git a/scripts/support/capture-courtyard-shaders.mjs b/scripts/support/capture-courtyard-shaders.mjs new file mode 100644 index 0000000..4781030 --- /dev/null +++ b/scripts/support/capture-courtyard-shaders.mjs @@ -0,0 +1,18 @@ +/** Capture Three-expanded courtyard/photo sources for optional offline compilers. + * This script creates no WebGL context and does not claim browser or GPU QA. */ +import fs from 'node:fs'; +import * as THREE from 'three'; +import {WebGLProgram} from 'three/src/renderers/webgl/WebGLProgram.js'; +import {loadTypescript} from './load-typescript.mjs'; +const {ExperimentalCourtyard}=await loadTypescript(new URL('../../src/objects/ExperimentalCourtyard.ts',import.meta.url)); +const {PetDepthMesh}=await loadTypescript(new URL('../../src/objects/PetDepthMesh.ts',import.meta.url)); +const {createHousePhotoOccluder}=await loadTypescript(new URL('../../src/objects/BlenderHouseSurround.ts',import.meta.url)); +const courtyard=new ExperimentalCourtyard(),photo=new PetDepthMesh(new THREE.Texture(),new THREE.Texture()),occluder=createHousePhotoOccluder(photo); +for(const [name,material] of [['courtyard',courtyard.group.children[0].material],['peeking-photo',photo.material],['peeking-occluder',occluder.mesh.material]]){ + const params={vertexShader:material.vertexShader,fragmentShader:material.fragmentShader,uniforms:material.uniforms,defines:material.defines,precision:'highp',shaderType:'ShaderMaterial',shaderName:name,isRawShaderMaterial:false,toneMapping:THREE.NoToneMapping,outputColorSpace:THREE.LinearSRGBColorSpace,numDirLights:0,numPointLights:0,numSpotLights:0,numSpotLightMaps:0,numRectAreaLights:0,numHemiLights:0,numDirLightShadows:0,numSpotLightShadows:0,numSpotLightShadowsWithMaps:0,numPointLightShadows:0,numClippingPlanes:0,numClipIntersection:0}; + const sentinel=new Error('offline-source-capture-complete'); + const gl={VERTEX_SHADER:0,FRAGMENT_SHADER:1,createProgram:()=>({}),createShader:type=>({type}),shaderSource:(shader,source)=>fs.writeFileSync(`/tmp/b-review-${name}.${shader.type===0?'vert':'frag'}`,source),compileShader:shader=>{if(shader.type===1)throw sentinel;}}; + try{new WebGLProgram({getContext:()=>gl},name,params,{});throw new Error(`Missing capture for ${name}`);}catch(error){if(error!==sentinel)throw error;console.log(`Captured r169 ${name} shader sources (no GL execution)`);} +} +occluder.dispose();courtyard.dispose();photo.geometry.dispose();photo.material.dispose(); +photo.material.uniforms.uTexture.value.dispose();photo.material.uniforms.uDepthMap.value.dispose(); diff --git a/scripts/support/capture-refraction-shaders.mjs b/scripts/support/capture-refraction-shaders.mjs new file mode 100644 index 0000000..d23a319 --- /dev/null +++ b/scripts/support/capture-refraction-shaders.mjs @@ -0,0 +1,12 @@ +/** Captures Three-expanded sources only. No WebGL context, browser, or GPU execution. */ +import fs from 'node:fs'; +import * as THREE from 'three'; +import {WebGLProgram} from 'three/src/renderers/webgl/WebGLProgram.js'; +import {loadTypescript} from './load-typescript.mjs'; +const {attachMeshRefraction}=await loadTypescript(new URL('../../src/rendering/MeshRefraction.ts',import.meta.url)); +const material=new THREE.MeshPhysicalMaterial({transmission:1});attachMeshRefraction(material,new THREE.Mesh());const shader={vertexShader:THREE.ShaderLib.physical.vertexShader,fragmentShader:THREE.ShaderLib.physical.fragmentShader,uniforms:{}};material.onBeforeCompile(shader,{}); +for(const area of [0,1]){ + const params={...shader,defines:material.defines,precision:'highp',shaderType:'MeshPhysicalMaterial',shaderName:'OfflineReview',transmission:true,thicknessMap:true,thicknessMapUv:'uv',envMap:true,envMapMode:THREE.CubeUVReflectionMapping,combine:THREE.MultiplyOperation,envMapCubeUVHeight:128,toneMapping:THREE.NoToneMapping,outputColorSpace:THREE.LinearSRGBColorSpace,numDirLights:0,numPointLights:0,numSpotLights:0,numSpotLightMaps:0,numRectAreaLights:area,numHemiLights:0,numDirLightShadows:0,numSpotLightShadows:0,numSpotLightShadowsWithMaps:0,numPointLightShadows:0,numClippingPlanes:1,numClipIntersection:0}; + const gl={VERTEX_SHADER:0,FRAGMENT_SHADER:1,createProgram:()=>({}),createShader:type=>({type}),shaderSource:(shader,source)=>fs.writeFileSync(`/tmp/b-review-${area}.${shader.type===0?'vert':'frag'}`,source),compileShader:shader=>{if(shader.type===1)throw new Error('Captured both sources; deliberately no GL compiler or driver used');}}; + try{new WebGLProgram({getContext:()=>gl},'offline-review',params,{});}catch(e){if(!e.message.startsWith('Captured'))throw e;console.log('Captured r169 shader sources for '+area+' area lights')} +} diff --git a/scripts/support/check-refraction-float32.mjs b/scripts/support/check-refraction-float32.mjs new file mode 100644 index 0000000..ca5729d --- /dev/null +++ b/scripts/support/check-refraction-float32.mjs @@ -0,0 +1,20 @@ +import assert from 'node:assert/strict'; +import * as R from './mesh-refraction-reference.mjs'; +const {v3,makeDepthTexture,depthAt,photoSurface,triangleOracle,tracePhotoDDA}=R; +const F=Math.fround,A=(a,b)=>F(a+b),S=(a,b)=>F(a-b),M=(a,b)=>F(a*b),D=(a,b)=>F(a/b),V=a=>a.map(F),add=(a,b)=>a.map((x,i)=>A(x,b[i])),sub=(a,b)=>a.map((x,i)=>S(x,b[i])),mul=(a,b)=>a.map(x=>M(x,b)),dot=(a,b)=>A(A(M(a[0],b[0]),M(a[1],b[1])),M(a[2],b[2])),cross=(a,b)=>[S(M(a[1],b[2]),M(a[2],b[1])),S(M(a[2],b[0]),M(a[0],b[2])),S(M(a[0],b[1]),M(a[1],b[0]))],INF=F(1e20); +function triangle(o,r,a,b,c){let e1=sub(b,a),e2=sub(c,a),p=cross(r,e2),det=dot(e1,p);if(det<=F(1e-9))return INF;let s=sub(o,a),u=D(dot(s,p),det);if(uF(1.00001))return INF;let q=cross(s,e1),v=D(dot(r,q),det);if(vF(1.00001))return INF;let t=D(dot(e2,q),det);return t>=0?t:INF;} +function shaderDDA(surface,origin,ray){const o=V(origin.toArray()),r=V(ray.toArray());let near=0,far=INF;const bounds=[[-.5,.5],[-.5,.5],[0,.25]];for(let i=0;i<3;i++){let [lo,hi]=bounds[i];if(Math.abs(r[i])=lo&&o[i]<=hi))return null;}else{let a=D(S(lo,o[i]),r[i]),b=D(S(hi,o[i]),r[i]);near=Math.max(near,Math.min(a,b));far=Math.min(far,Math.max(a,b));if(farMath.min(127,Math.max(0,Math.floor(A(M(A(v,.5),128),M(direction[i],.00001)))))),next=[INF,INF],delta=[INF,INF];for(let i=0;i<2;i++)if(Math.abs(r[i])>=F(1e-9)){next[i]=D(S(S(D(A(cell[i],r[i]>=0?1:0),128),.5),o[i]),r[i]);delta[i]=D(1,M(128,Math.abs(r[i])));} +const vert=(x,y)=>[S(D(x,128),.5),S(D(y,128),.5),M(F(depthAt(surface.texture,D(x,128),D(y,128))),.25)]; +for(let i=0;i<257;i++){let ll=vert(cell[0],cell[1]),lr=vert(A(cell[0],1),cell[1]),ul=vert(cell[0],A(cell[1],1)),ur=vert(A(cell[0],1),A(cell[1],1));let t=Math.min(triangle(o,r,ul,ll,ur),triangle(o,r,ll,lr,ur)),end=Math.min(far,...next);if(t>=S(near,.00001)&&t<=A(end,.00001)&&t=S(far,.000001))return null;let cx=next[0]<=next[1],cy=next[1]<=next[0];near=end;if(cx){cell[0]=A(cell[0],direction[0]);next[0]=A(next[0],delta[0]);}if(cy){cell[1]=A(cell[1],direction[1]);next[1]=A(next[1],delta[1]);}if(cell.some(v=>v<0||v>=128))return null;}throw Error('257 cells exhausted');} +const surface=photoSurface(makeDepthTexture(67,53,(x,y)=>.5+.21*Math.sin(x*1.2)+.25*Math.cos(y*.9+x*.4))); +let seed=0x5eed,random=()=>{seed=(Math.imul(seed,1664525)+1013904223)>>>0;return seed/2**32;},cases=[]; +for(let i=0;i<1500;i++){const o=v3((random()-.5)*1.8,(random()-.5)*1.8,.4+random()),target=v3((random()-.5)*1.2,(random()-.5)*1.2,random()*.2);cases.push([o,target.sub(o).normalize()]);} +for(const x of [-.5,-.25,0,.25,.5])for(const y of [-.5,-.25,0,.25,.5])for(const dx of [-.3,0,.3])for(const dy of [-.3,0,.3])cases.push([v3(x,y,1),v3(dx,dy,-1).normalize()]); +for(let i=0;i<20;i++)cases.push([v3(-.6,-.45+i*.02,.249),v3(1,.85,-.0001).normalize()]); +let misses=0,worst=0,maxcells=0; +for(let i=0;ix*y));let longWorst=0,longMax=0,longCases=0; +for(let i=0;i<80;i++){const o=v3(-.6,-.45+i*.005,.249),r=v3(1,.85,-.0001).normalize(),a=shaderDDA(longSurface,o,r),e=tracePhotoDDA(longSurface,o,r).hit;assert.equal(Boolean(a),Boolean(e),`long ray ${i}`);if(a){longMax=Math.max(longMax,a.cells);longWorst=Math.max(longWorst,v3(...a.point).distanceTo(e.point));assert.ok(v3(...a.point).distanceTo(e.point)<.0001);}longCases++;} +console.log(JSON.stringify({kind:'CPU Float32 long XY traversal',rays:longCases,worstHitPointError:longWorst,maxcells:longMax})); diff --git a/scripts/support/compile-refraction-shaders.py b/scripts/support/compile-refraction-shaders.py new file mode 100644 index 0000000..721ef5b --- /dev/null +++ b/scripts/support/compile-refraction-shaders.py @@ -0,0 +1,18 @@ +import ctypes as C,re,sys +from pathlib import Path +s=C.CDLL('/usr/lib/x86_64-linux-gnu/libshaderc.so.1') +def fn(name,restype,args): + f=getattr(s,name);f.restype=restype;f.argtypes=args;return f +init=fn('shaderc_compiler_initialize',C.c_void_p,[]); optinit=fn('shaderc_compile_options_initialize',C.c_void_p,[]) +setenv=fn('shaderc_compile_options_set_target_env',None,[C.c_void_p,C.c_int,C.c_uint]); auto=fn('shaderc_compile_options_set_auto_bind_uniforms',None,[C.c_void_p,C.c_bool]); loc=fn('shaderc_compile_options_set_auto_map_locations',None,[C.c_void_p,C.c_bool]); compile=fn('shaderc_compile_into_spv',C.c_void_p,[C.c_void_p,C.c_char_p,C.c_size_t,C.c_int,C.c_char_p,C.c_char_p,C.c_void_p]);status=fn('shaderc_result_get_compilation_status',C.c_int,[C.c_void_p]); msg=fn('shaderc_result_get_error_message',C.c_char_p,[C.c_void_p]);release=fn('shaderc_result_release',None,[C.c_void_p]) +c=init(); o=optinit();setenv(o,1,450);auto(o,True);loc(o,True) +failed=0 +for p in sorted(p for p in Path('/tmp').glob('b-review-*.*') if p.suffix in ('.vert','.frag')): + src=p.read_text().replace('#version 300 es','#version 310 es',1) + src=re.sub(r'\baverage\b','threeAverage',src) # 'average' becomes reserved after production GLSL ES 300 + src=src.encode();r=compile(c,src,len(src),0 if p.suffix=='.vert' else 1,str(p).encode(),b'main',o) + code=status(r);failed+=code!=0 + print(p.name,'status:',code,msg(r).decode());release(r) +print('CPU/offline shaderc only; version raised 300 es -> 310 es solely for SPIR-V compiler acceptance and stock average() renamed to avoid later-version reserved keyword; auto bindings/locations. No changes to B code. No WebGL or GPU execution.') + +sys.exit(1 if failed else 0) diff --git a/scripts/support/export-corner-preview.mjs b/scripts/support/export-corner-preview.mjs new file mode 100644 index 0000000..83db5a4 --- /dev/null +++ b/scripts/support/export-corner-preview.mjs @@ -0,0 +1,17 @@ +// Offline composition proof only: no browser, WebGL optics, or user photos. +import {writeFileSync} from 'node:fs';import * as T from 'three'; +import {loadTypescript} from './load-typescript.mjs';import {loadFrameGeometry} from './load-frame-geometry.mjs'; +const {prepareHouseAsset}=await loadTypescript(new URL('../../src/objects/BlenderHouseSurround.ts',import.meta.url)); +const {prepareFrameAsset,fitWindowScale}=await loadTypescript(new URL('../../src/objects/BlenderWindowFrame.ts',import.meta.url)); +const {CameraController}=await loadTypescript(new URL('../../src/input/CameraController.ts',import.meta.url)); +const views=[];for(const [label,aspect]of[['portrait',375/812],['landscape',844/390]]){ + const f=fitWindowScale(aspect,.8)*.82,w=f*.8*.8,h=f*.8,s=Math.min(w,h),room=loadFrameGeometry(new URL('../../public/assets/window/grandma-house-surround.glb',import.meta.url)),frame=loadFrameGeometry(); + prepareHouseAsset(room).resize(w,h,.6);prepareFrameAsset(frame).resize(w,h,.6);const root=new T.Group();root.add(room,frame);root.updateMatrixWorld(true); + const meshes=[];root.traverse(m=>{if(!m.isMesh)return;const g=m.geometry.clone().applyMatrix4(m.matrixWorld);meshes.push({name:m.name,positions:[...g.attributes.position.array],indices:g.index?[...g.index.array]:Array.from({length:g.attributes.position.count},(_,i)=>i),colors:g.attributes.color?[...g.attributes.color.array]:null});}); + for(const variant of['left','right','neutral']){ + const c=new T.PerspectiveCamera(40,aspect,.1,100),control=new CameraController(c);control.setRoomBounds(w,h,.6);control.setView(variant==='left'?-1:variant==='right'?1:0,0);control.update(10,1); + c.updateMatrixWorld(true); + views.push({name:label+'-'+variant,aspect,fov:c.fov,matrix:c.matrixWorld.toArray(),meshes}); + } +} +writeFileSync('/tmp/corner-qa/scenes.json',JSON.stringify(views)); diff --git a/scripts/support/export-wall-peek-preview.mjs b/scripts/support/export-wall-peek-preview.mjs new file mode 100644 index 0000000..4ff65ee --- /dev/null +++ b/scripts/support/export-wall-peek-preview.mjs @@ -0,0 +1,17 @@ +// Offline wall-hug geometry evidence only; no WebGL/photo rendering. +import {writeFileSync} from 'node:fs';import * as T from 'three'; +import {loadTypescript} from './load-typescript.mjs';import {loadFrameGeometry} from './load-frame-geometry.mjs'; +const {prepareHouseAsset}=await loadTypescript(new URL('../../src/objects/BlenderHouseSurround.ts',import.meta.url)); +const {prepareFrameAsset,fitWindowScale}=await loadTypescript(new URL('../../src/objects/BlenderWindowFrame.ts',import.meta.url)); +const {CameraController}=await loadTypescript(new URL('../../src/input/CameraController.ts',import.meta.url)); +const views=[];for(const [label,aspect]of[['portrait',375/812],['landscape',844/390]]){ + const f=fitWindowScale(aspect,.8)*.82,w=f*.8*.8,h=f*.8,s=Math.min(w,h),room=loadFrameGeometry(new URL('../../public/assets/window/grandma-house-surround.glb',import.meta.url)),frame=loadFrameGeometry(); + prepareHouseAsset(room).resize(w,h,.6,undefined,true);prepareFrameAsset(frame).resize(w,h,.6);const root=new T.Group();root.add(room,frame);root.updateMatrixWorld(true); + const meshes=[];root.traverse(m=>{if(!m.isMesh)return;const g=m.geometry.clone().applyMatrix4(m.matrixWorld);meshes.push({name:m.name,positions:[...g.attributes.position.array],indices:g.index?[...g.index.array]:Array.from({length:g.attributes.position.count},(_,i)=>i),colors:g.attributes.color?[...g.attributes.color.array]:null});}); + for(const variant of['left','right','middle','neutral']){ + const c=new T.PerspectiveCamera(40,aspect,.1,100),control=new CameraController(c);control.setRoomBounds(w,h,.6);control.setCompositionMode('wall');control.setView(variant==='left'?-1:variant==='right'?1:variant==='middle'?.65:0,0);control.update(10,1); + c.updateMatrixWorld(true); + views.push({name:label+'-'+variant,aspect,fov:c.fov,matrix:c.matrixWorld.toArray(),meshes}); + } +} +writeFileSync('/tmp/wall-final-qa/scenes.json',JSON.stringify(views)); diff --git a/scripts/support/load-frame-geometry.mjs b/scripts/support/load-frame-geometry.mjs new file mode 100644 index 0000000..dca9a9e --- /dev/null +++ b/scripts/support/load-frame-geometry.mjs @@ -0,0 +1,13 @@ +import * as THREE from 'three'; +import {readFileSync} from 'node:fs'; +/** Geometry-only GLB reader for deterministic Node tests; browser uses GLTFLoader. */ +export function loadFrameGeometry(file=new URL('../../public/assets/window/grandma-wood-sash.glb',import.meta.url)){ + const bytes=readFileSync(file); + const length=bytes.readUInt32LE(12),gltf=JSON.parse(bytes.subarray(20,20+length).toString()),bin=bytes.subarray(28+length); + const types={5121:Uint8Array,5126:Float32Array,5123:Uint16Array,5125:Uint32Array},counts={SCALAR:1,VEC2:2,VEC3:3,VEC4:4}; + const accessor=i=>{const a=gltf.accessors[i],v=gltf.bufferViews[a.bufferView],T=types[a.componentType],n=counts[a.type],array=new T(a.count*n);for(let row=0;rownew THREE.MeshStandardMaterial({name:m.name,side:m.doubleSided?THREE.DoubleSide:THREE.FrontSide})); + const nodes=gltf.nodes.map(n=>{let obj=new THREE.Group();if(n.mesh!==undefined){const primitive=gltf.meshes[n.mesh].primitives[0],geometry=new THREE.BufferGeometry();for(const [key,value] of Object.entries(primitive.attributes))geometry.setAttribute({POSITION:'position',NORMAL:'normal',TEXCOORD_0:'uv',TANGENT:'tangent',COLOR_0:'color'}[key],accessor(value));geometry.setIndex(accessor(primitive.indices));obj=new THREE.Mesh(geometry,materials[primitive.material]);}obj.name=n.name;if(n.translation)obj.position.fromArray(n.translation);return obj;}); + gltf.nodes.forEach((node,i)=>(node.children??[]).forEach(c=>nodes[i].add(nodes[c]))); + const scene=new THREE.Group();gltf.scenes[gltf.scene??0].nodes.forEach(i=>scene.add(nodes[i]));return scene; +} diff --git a/scripts/support/load-typescript.mjs b/scripts/support/load-typescript.mjs new file mode 100644 index 0000000..16c068f --- /dev/null +++ b/scripts/support/load-typescript.mjs @@ -0,0 +1,10 @@ +import { readFile } from 'node:fs/promises'; +import ts from 'typescript'; +const cache=new Map(); +export async function loadTypescript(file){const url=file instanceof URL?file:new URL(file,import.meta.url);return import(await moduleURL(url));} +async function moduleURL(url){ + if(cache.has(url.href))return cache.get(url.href); + let code=ts.transpileModule(await readFile(url,'utf8'),{compilerOptions:{target:ts.ScriptTarget.ES2020,module:ts.ModuleKind.ESNext}}).outputText; + for(const match of [...code.matchAll(/(?:from\s*|import\s*)['"]([^'"]+)['"]/g)]){const name=match[1];let ref;if(name.endsWith('?raw'))ref='data:text/javascript;base64,'+Buffer.from('export default '+JSON.stringify(await readFile(new URL(name.slice(0,-4),url),'utf8'))).toString('base64');else if(name.startsWith('.'))ref=await moduleURL(new URL(name.endsWith('.ts')?name:name+'.ts',url));else if(!name.startsWith('data:')&&!name.startsWith('file:'))ref=import.meta.resolve(name);if(ref)code=code.replaceAll("'"+name+"'",JSON.stringify(ref)).replaceAll(JSON.stringify(name),JSON.stringify(ref));} + code=code.replaceAll('import.meta.url',JSON.stringify(url.href));const result='data:text/javascript;base64,'+Buffer.from(code).toString('base64');cache.set(url.href,result);return result; +} diff --git a/scripts/support/mesh-refraction-reference.mjs b/scripts/support/mesh-refraction-reference.mjs new file mode 100644 index 0000000..7b5645c --- /dev/null +++ b/scripts/support/mesh-refraction-reference.mjs @@ -0,0 +1,149 @@ +/** Test-only, CPU numerical reference. Never imported by the renderer. + * Photo intersections use analytic per-triangle height planes and a bounded XY DDA; + * the independent oracle uses Three's indexed PlaneGeometry and Ray.intersectTriangle. + */ +import * as THREE from 'three'; +const EPS = 1e-10; +export const PHOTO_SEGMENTS = 128; +export const MAX_DDA_CELLS = 257; +export const v3 = (x=0,y=0,z=0) => new THREE.Vector3(x,y,z); + +export function makeDepthTexture(width, height, sample) { + const data = new Uint8Array(width*height*4); + for(let y=0;y [0,1]. */ +export function depthAt(texture,u,v) { + const {data,width,height}=texture.image; + if(texture.flipY)v=1-v; + const x=u*width-.5,y=v*height-.5,x0=Math.floor(x),y0=Math.floor(y),fx=x-x0,fy=y-y0; + const fetch=(i,j)=>data[4*(THREE.MathUtils.clamp(j,0,height-1)*width+THREE.MathUtils.clamp(i,0,width-1))]/255; + return THREE.MathUtils.lerp(THREE.MathUtils.lerp(fetch(x0,y0),fetch(x0+1,y0),fx),THREE.MathUtils.lerp(fetch(x0,y0+1),fetch(x0+1,y0+1),fx),fy); +} + +export function photoSurface(texture,{segments=128,depthScale=.25,depthBias=0,matrix=new THREE.Matrix4()}={}) { + if(!Number.isInteger(segments)||segments<1||segments>128) throw new Error('Photo grid must be 1..128'); + const heights=new Float64Array((segments+1)**2); + for(let y=0;y<=segments;y++) for(let x=0;x<=segments;x++) heights[y*(segments+1)+x]=(depthAt(texture,x/segments,y/segments)-depthBias)*depthScale; + const geometry=new THREE.PlaneGeometry(1,1,segments,segments),p=geometry.attributes.position,uv=geometry.attributes.uv; + for(let i=0;i=-EPS&&thi+EPS)return {hit:null,cells};continue;} + const a=(lo-o[axis])/d[axis],b=(hi-o[axis])/d[axis];enter=Math.max(enter,Math.min(a,b));leave=Math.min(leave,Math.max(a,b)); + } + if(leaveTHREE.MathUtils.clamp(Math.floor((x+.5)*n),0,n-1); + let ix=grid(at.x),iy=grid(at.y),t=enter; + const sx=Math.sign(d.x),sy=Math.sign(d.y); + const next=(axis,cell,step)=>step===0?Infinity:((cell+(step>0?1:0))/n-.5-o[axis])/d[axis]; + let tx=next('x',ix,sx),ty=next('y',iy,sy); + for(let step=0;step=-1e-14)continue; // FrontSide: approach the displaced photo front. + const candidate=(z00+ax*fx0+ay*fy0-o.z)/denom; + const fx=fx0+n*d.x*candidate,fy=fy0+n*d.y*candidate; + if(candidateend+EPS||candidate<0||fx<-EPS||fy<-EPS||fx>1+EPS||fy>1+EPS)continue; + if(lower?fy>fx+EPS:fx>fy+EPS)continue; + best=Math.min(best,candidate); + } + if(Number.isFinite(best)) {const local=o.clone().addScaledVector(d,best);return {hit:{t:best,local,point:local.clone().applyMatrix4(surface.matrix),uv:new THREE.Vector2(local.x+.5,local.y+.5)},cells};} + if(end>=leave-EPS)return {hit:null,cells}; + const crossX=tx<=ty+EPS,crossY=ty<=tx+EPS;t=end; + if(crossX) {ix+=sx;tx=next('x',ix,sx);}if(crossY) {iy+=sy;ty=next('y',iy,sy);} + if(ix<0||ix>=n||iy<0||iy>=n)return {hit:null,cells}; + } + throw new Error(`DDA exceeded ${MAX_DDA_CELLS} cells`); +} + +/** GLSL refract convention: normal opposes incident direction. */ +export function snell(incident,normal,eta) { + const i=incident.clone().normalize(),n=normal.clone().normalize(),dot=i.dot(n),k=1-eta*eta*(1-dot*dot); + if(k<0)return null; + return i.multiplyScalar(eta).addScaledVector(n,-eta*dot-Math.sqrt(k)).normalize(); +} + +/** Planar rear and finite side exits in local glass coordinates. */ +export function exitGlass(entry,inside,{width,height,backZ}) { + const candidates=[]; + for(const [axis,bounds] of [['x',[-width/2,width/2]],['y',[-height/2,height/2]],['z',[backZ]]]) { + if(Math.abs(inside[axis])<1e-14)continue; + for(const value of bounds) {const t=(value-entry[axis])/inside[axis];if(t>EPS)candidates.push({t,axis,value});} + } + candidates.sort((a,b)=>a.t-b.t); + for(const c of candidates) { + const point=entry.clone().addScaledVector(inside,c.t); + if(Math.abs(point.x)>width/2+EPS||Math.abs(point.y)>height/2+EPS||point.z0?'+':'-'}`}; + } + return null; +} + +export function traceGlass({entry,normal,incident,shape,ior=1.5,surface}) { + const inside=snell(incident,normal,1/ior);if(!inside)return {status:'entry-tir'}; + const exit=exitGlass(entry,inside,shape);if(!exit)return {status:'no-exit'}; + const outgoing=snell(inside,exit.normal.clone().negate(),ior);if(!outgoing)return {status:'tir',inside,exit}; + const result=tracePhotoDDA(surface,exit.point,outgoing); + return {status:result.hit?'hit':'miss',inside,exit,outgoing,...result}; +} + +/** Stock r169 only advances its refracted ray by material thickness, projects that + * endpoint, and looks up the already camera-rendered scene at that screen point. */ +export function stockR169PhotoHit({entry,normal,incident,camera,thickness,ior=1.5,surface}) { + const inside=snell(incident,normal,1/ior); + if(!inside)return null; + const endpoint=entry.clone().addScaledVector(inside,thickness); + return tracePhotoDDA(surface,camera,endpoint.sub(camera).normalize()).hit; +} + +/** Actual mesh intersection and perspective-correct interpolated vertex normal. */ +export function meshEntry(geometry,camera,target) { + const material=new THREE.MeshBasicMaterial({side:THREE.FrontSide}),mesh=new THREE.Mesh(geometry,material); + mesh.updateMatrixWorld(true); + const incident=target.clone().sub(camera).normalize(),hit=new THREE.Raycaster(camera,incident).intersectObject(mesh,false)[0]; + material.dispose(); + if(!hit)return null; + const p=geometry.attributes.position,n=geometry.attributes.normal,a=v3().fromBufferAttribute(p,hit.face.a),b=v3().fromBufferAttribute(p,hit.face.b),c=v3().fromBufferAttribute(p,hit.face.c); + const bary=THREE.Triangle.getBarycoord(hit.point,a,b,c,v3()); + const normal=v3().fromBufferAttribute(n,hit.face.a).multiplyScalar(bary.x).addScaledVector(v3().fromBufferAttribute(n,hit.face.b),bary.y).addScaledVector(v3().fromBufferAttribute(n,hit.face.c),bary.z).normalize(); + return {entry:hit.point,normal,incident,bary,face:hit.face}; +} diff --git a/scripts/support/photo-fixtures.py b/scripts/support/photo-fixtures.py new file mode 100644 index 0000000..582db52 --- /dev/null +++ b/scripts/support/photo-fixtures.py @@ -0,0 +1,42 @@ +"""Reproducible synthetic fixtures and CPU-only codec oracle, never browser QA.""" +import sys, json, hashlib +from pathlib import Path +from PIL import Image, ImageOps +import numpy as np + +if sys.argv[1] == 'generate': + root = Path(sys.argv[2]); root.mkdir(parents=True, exist_ok=True) + rng = np.random.default_rng(20261007) + width, height = 4032, 3024 + pixels = rng.integers(0, 256, (height, width, 3), dtype=np.uint8) + rgb = Image.fromarray(pixels) + alpha = Image.new('L', (width, height), 0) + alpha.paste(64, (width//2, 0, width, height//2)) + alpha.paste(192, (0, height//2, width//2, height)) + alpha.paste(255, (width//2, height//2, width, height)) + rgba = rgb.copy(); rgba.putalpha(alpha) + for name, image, orientation, options in [ + ('phone-12mp-rotated.jpg', rgb, 6, {'quality':95}), + ('phone-12mp-alpha-rotated.png', rgba, 8, {}), + ('phone-12mp-alpha-mirrored.webp', rgba, 2, {'lossless':True}), + ]: + exif = Image.Exif(); exif[274] = orientation + image.save(root / name, exif=exif, **options) + # Large pixel count with tiny encoded size exercises the pixel resource guard. + Image.new('RGBA', (8000,6000), (19,101,224,128)).save(root/'phone-48mp-alpha.png') + print(json.dumps({'directory':str(root),'files':[p.name for p in sorted(root.iterdir())]})) +else: + path = Path(sys.argv[2]) + with Image.open(path) as source: + source_width, source_height = source.size + orientation = source.getexif().get(274, 1) + oriented = ImageOps.exif_transpose(source).convert('RGBA') + if len(sys.argv) > 3: + oriented = oriented.resize((int(sys.argv[3]), int(sys.argv[4])), Image.Resampling.LANCZOS) + corners = [oriented.getpixel(point) for point in [(0,0),(oriented.width-1,0),(0,oriented.height-1),(oriented.width-1,oriented.height-1)]] + # Verify transparent/partial-alpha values survive a local lossless PNG adapter. + import io + encoded = io.BytesIO(); oriented.save(encoded, format='PNG') + decoded = Image.open(io.BytesIO(encoded.getvalue())).convert('RGBA') + assert decoded.tobytes() == oriented.tobytes() + print(json.dumps({'width':oriented.width,'height':oriented.height,'sourceWidth':source_width,'sourceHeight':source_height,'orientation':orientation,'corners':corners,'alphaExtrema':oriented.getchannel('A').getextrema(),'sourceBytes':path.stat().st_size,'workingPngBytes':len(encoded.getvalue()),'sourceRGBABytes':source_width*source_height*4,'workingRGBABytes':oriented.width*oriented.height*4,'sha256':hashlib.sha256(path.read_bytes()).hexdigest(),'pngRoundTripExact':True})) diff --git a/scripts/support/render-corner-preview.py b/scripts/support/render-corner-preview.py new file mode 100644 index 0000000..52adf45 --- /dev/null +++ b/scripts/support/render-corner-preview.py @@ -0,0 +1,23 @@ +import bpy,json,math +from mathutils import Matrix +views=json.load(open('/tmp/corner-qa/scenes.json')) +for v in views: + bpy.ops.object.select_all(action='SELECT');bpy.ops.object.delete(use_global=False) + for item in v['meshes']: + p=item['positions'];ind=item['indices'];mesh=bpy.data.meshes.new(item['name']);mesh.from_pydata(list(zip(p[::3],p[1::3],p[2::3])),[],list(zip(ind[::3],ind[1::3],ind[2::3])));mesh.update();ob=bpy.data.objects.new(item['name'],mesh);bpy.context.collection.objects.link(ob) + name=item['name'];color=(.67,.61,.49,1) if 'Plaster' in name or 'Shell' in name else (.3,.16,.08,1) if 'Wood' in name or 'Picture' in name else (.55,.51,.43,1) + if 'Curtain' in name:color=(.88,.85,.72,1) + mat=bpy.data.materials.new(name);mat.diffuse_color=color;ob.data.materials.append(mat) + if 'Picture' in name and item['colors']: + palette={};co=item['colors'] + for poly in mesh.polygons: + i=poly.vertices[0];rgb=tuple(round(x,5) for x in co[i*3:i*3+3]) + if rgb not in palette: + m=bpy.data.materials.new('Print');m.diffuse_color=(*rgb,1);ob.data.materials.append(m);palette[rgb]=len(ob.data.materials)-1 + poly.material_index=palette[rgb] + if item['colors']: + attr=mesh.color_attributes.new(name='Color',type='FLOAT_COLOR',domain='POINT');co=item['colors'] + for i,d in enumerate(attr.data):d.color=(*co[i*3:i*3+3],1) + camera=bpy.data.cameras.new('Camera');ob=bpy.data.objects.new('Camera',camera);bpy.context.collection.objects.link(ob);a=v['matrix'];ob.matrix_world=Matrix([[a[r+c*4] for c in range(4)]for r in range(4)]);camera.type='PERSP';camera.sensor_fit='VERTICAL';camera.sensor_height=24;camera.lens=24/(2*math.tan(math.radians(v['fov'])/2));bpy.context.scene.camera=ob + scene=bpy.context.scene;scene.render.engine='BLENDER_WORKBENCH';scene.display.shading.light='STUDIO';scene.display.shading.color_type='MATERIAL';scene.display.shading.show_shadows=True;scene.display.shading.show_cavity=True;scene.display.shading.cavity_type='BOTH';scene.display.shading.background_type='WORLD';scene.world.color=(.15,.15,.15) + scene.render.resolution_y=750;scene.render.resolution_x=int(750*v['aspect']);scene.render.resolution_percentage=100;scene.render.image_settings.file_format='PNG';scene.render.filepath='/tmp/corner-qa/'+v['name']+'.png';bpy.ops.render.render(write_still=True) diff --git a/scripts/support/render-wall-peek-preview.py b/scripts/support/render-wall-peek-preview.py new file mode 100644 index 0000000..562cdc9 --- /dev/null +++ b/scripts/support/render-wall-peek-preview.py @@ -0,0 +1,23 @@ +import bpy,json,math +from mathutils import Matrix +views=json.load(open('/tmp/wall-final-qa/scenes.json')) +for v in views: + bpy.ops.object.select_all(action='SELECT');bpy.ops.object.delete(use_global=False) + for item in v['meshes']: + p=item['positions'];ind=item['indices'];mesh=bpy.data.meshes.new(item['name']);mesh.from_pydata(list(zip(p[::3],p[1::3],p[2::3])),[],list(zip(ind[::3],ind[1::3],ind[2::3])));mesh.update();ob=bpy.data.objects.new(item['name'],mesh);bpy.context.collection.objects.link(ob) + name=item['name'];color=(.67,.61,.49,1) if 'Plaster' in name or 'Shell' in name else (.3,.16,.08,1) if 'Wood' in name or 'Picture' in name else (.55,.51,.43,1) + if 'Curtain' in name:color=(.88,.85,.72,1) + mat=bpy.data.materials.new(name);mat.diffuse_color=color;ob.data.materials.append(mat) + if 'Picture' in name and item['colors']: + palette={};co=item['colors'] + for poly in mesh.polygons: + i=poly.vertices[0];rgb=tuple(round(x,5) for x in co[i*3:i*3+3]) + if rgb not in palette: + m=bpy.data.materials.new('Print');m.diffuse_color=(*rgb,1);ob.data.materials.append(m);palette[rgb]=len(ob.data.materials)-1 + poly.material_index=palette[rgb] + if item['colors']: + attr=mesh.color_attributes.new(name='Color',type='FLOAT_COLOR',domain='POINT');co=item['colors'] + for i,d in enumerate(attr.data):d.color=(*co[i*3:i*3+3],1) + camera=bpy.data.cameras.new('Camera');ob=bpy.data.objects.new('Camera',camera);bpy.context.collection.objects.link(ob);a=v['matrix'];ob.matrix_world=Matrix([[a[r+c*4] for c in range(4)]for r in range(4)]);camera.type='PERSP';camera.sensor_fit='VERTICAL';camera.sensor_height=24;camera.lens=24/(2*math.tan(math.radians(v['fov'])/2));bpy.context.scene.camera=ob + scene=bpy.context.scene;scene.render.engine='BLENDER_WORKBENCH';scene.display.shading.light='STUDIO';scene.display.shading.color_type='MATERIAL';scene.display.shading.show_shadows=True;scene.display.shading.show_cavity=True;scene.display.shading.cavity_type='BOTH';scene.display.shading.background_type='WORLD';scene.world.color=(.15,.15,.15) + scene.render.resolution_y=750;scene.render.resolution_x=int(750*v['aspect']);scene.render.resolution_percentage=100;scene.render.image_settings.file_format='PNG';scene.render.filepath='/tmp/wall-final-qa/'+v['name']+'.png';bpy.ops.render.render(write_still=True) diff --git a/scripts/test-ai-depth-inference.mjs b/scripts/test-ai-depth-inference.mjs new file mode 100644 index 0000000..e4cdf9b --- /dev/null +++ b/scripts/test-ai-depth-inference.mjs @@ -0,0 +1,397 @@ +import assert from 'node:assert/strict'; +import { readFile, mkdtemp, writeFile, rm } from 'node:fs/promises'; +import { test } from 'node:test'; +import vm from 'node:vm'; +import { pathToFileURL } from 'node:url'; +import ts from 'typescript'; + +const gpu = { device: 'webgpu', dtype: 'fp32' }; +const wasm = { device: 'wasm', dtype: 'q8' }; + +async function providerHarness(capture) { + const sourceUrl = new URL('../src/depth/AiDepthProvider.ts', import.meta.url); + const directory = await mkdtemp(new URL('../.ai-depth-provider-test-', import.meta.url)); + const source = (await readFile(sourceUrl, 'utf8')).replace("'./DepthProcessor'", JSON.stringify(new URL('../src/depth/DepthProcessor.ts', import.meta.url).href)); + const { outputText } = ts.transpileModule(source, { compilerOptions: { target: ts.ScriptTarget.ES2020, module: ts.ModuleKind.ESNext } }); + await writeFile(`${directory}/provider.mjs`, outputText); + const originalWorker = globalThis.Worker; + const originalCapture = globalThis.createImageBitmap; + const workers = []; + const bitmaps = []; + globalThis.Worker = class { + constructor() { this.messages = []; this.terminated = false; workers.push(this); } + postMessage(message) { this.messages.push(message); } + terminate() { this.terminated = true; } + }; + globalThis.createImageBitmap = capture ?? (async () => { const bitmap = { width: 10, height: 10, closed: false, close() { this.closed = true; } }; bitmaps.push(bitmap); return bitmap; }); + const { AiDepthProvider } = await import(pathToFileURL(`${directory}/provider.mjs`).href); + const statuses = []; + const provider = new AiDepthProvider((status) => statuses.push(status)); + return { provider, workers, statuses, bitmaps, async cleanup() { provider.cancel(); globalThis.Worker = originalWorker; globalThis.createImageBitmap = originalCapture; await rm(directory, { recursive: true, force: true }); } }; +} +const photo = { naturalWidth: 100, naturalHeight: 50 }; +const tick = async () => { await Promise.resolve(); await Promise.resolve(); }; +function replyWithResult(worker, run) { + const id = worker.messages.at(-1).id; + worker.onmessage({ data: { type: 'result', id, width: 1, height: 1, values: Uint8Array.of(255).buffer, normalizedValues: Float32Array.of(1).buffer, run } }); +} + +test('provider sends a fixed-model request and preserves measured execution metadata', async () => { + const h = await providerHarness(); + try { + const pending = h.provider.getDepthMap(photo); + await tick(); + const worker = h.workers[0]; + const requestKeys = Object.keys(worker.messages[0]).sort(); + replyWithResult(worker, { model: 'small', ...gpu, preparationMs: 5, inferenceMs: 7, totalMs: 12 }); + const result = await pending; + assert.deepEqual(requestKeys, ['id', 'image', 'type']); + assert.equal(result.userData.aiDepthRun.model, 'small'); + assert.equal(result.userData.aiDepthRun.device, 'webgpu'); + assert.equal(result.userData.aiDepthRun.dtype, 'fp32'); + assert.equal(result.userData.aiDepthRun.preparationMs, 5); + assert.equal(result.userData.aiDepthRun.inferenceMs, 7); + assert.ok(result.userData.aiDepthRun.totalMs >= 0); + assert.equal(result.userData.normalizedDepth[0], 1); + assert.equal(worker.terminated, true, 'finished inference must release its runtime before scene rendering resumes'); + result.dispose(); + } finally { await h.cleanup(); } +}); + +test('provider cancellation is an AbortError and late captures are closed without spawning workers', async () => { + let resolveCapture; + const bitmap = { width: 10, height: 5, closed: false, close() { this.closed = true; } }; + const h = await providerHarness(() => new Promise((resolve) => { resolveCapture = resolve; })); + try { + const pending = h.provider.getDepthMap(photo); + const rejected = assert.rejects(pending, { name: 'AbortError' }); + h.provider.cancel(); + resolveCapture(bitmap); + await rejected; + await tick(); + assert.equal(bitmap.closed, true); + assert.equal(h.workers.length, 0); + } finally { await h.cleanup(); } +}); + +test('orphaned worker errors and messages cannot reject or settle a replacement request', async () => { + const h = await providerHarness(); + try { + const first = h.provider.getDepthMap(photo); + const firstRejected = assert.rejects(first); + await tick(); + const oldWorker = h.workers[0]; + h.provider.cancel(); await firstRejected; + const second = h.provider.getDepthMap(photo); + // Attach immediately so a failing implementation does not create an unhandled rejection. + const settled = second.then((value) => ({ value }), (error) => ({ error })); + await tick(); + const worker = h.workers[1]; + oldWorker.onerror({ message: 'late old worker failure' }); + oldWorker.onmessageerror({}); + oldWorker.onmessage({ data: { type: 'status', id: worker.messages[0].id, message: 'orphaned status' } }); + replyWithResult(worker, { model: 'small', ...wasm, preparationMs: 1, inferenceMs: 2, totalMs: 3 }); + const result = await settled; + assert.equal(result.error, undefined, 'orphaned callbacks must be ignored'); + assert.equal(h.statuses.includes('orphaned status'), false); + assert.equal(worker.terminated, true, 'the valid completed worker is released'); + result.value.dispose(); + } finally { await h.cleanup(); } +}); + +test('completed inference releases only its own worker and late replies cannot terminate a newer request', async () => { + const h = await providerHarness(); + try { + const first = h.provider.getDepthMap(photo); await tick(); + const old = h.workers[0]; + replyWithResult(old, { model: 'small', ...gpu, preparationMs: 1, inferenceMs: 2, totalMs: 3 }); + const firstTexture = await first; + assert.equal(old.terminated, true); + const next = h.provider.getDepthMap(photo); await tick(); + const current = h.workers[1]; + replyWithResult(old, { model: 'small', ...gpu, preparationMs: 1, inferenceMs: 2, totalMs: 3 }); + old.onerror({ message: 'late old failure' }); + assert.equal(current.terminated, false); + replyWithResult(current, { model: 'small', ...wasm, preparationMs: 1, inferenceMs: 2, totalMs: 3 }); + const texture = await next; + assert.equal(current.terminated, true); assert.equal(texture.userData.aiDepthRun.device, 'wasm'); + firstTexture.dispose(); texture.dispose(); + } finally { await h.cleanup(); } +}); + +async function workerHarness({ hasGpu = true, adapter = {}, adapterError = false, missingAdapterMethod = false, failLoad = () => false, failInference = () => false, beforeLoad = async () => {} } = {}) { + const source = await readFile(new URL('../src/depth/aiDepth.worker.ts', import.meta.url), 'utf8'); + const { outputText } = ts.transpileModule(source, { compilerOptions: { target: ts.ScriptTarget.ES2020, module: ts.ModuleKind.CommonJS } }); + const constants = await import(new URL('../src/constants/depth.ts', import.meta.url)); + let now = 0; + let listener; + let liveSessions = 0; + let adapterProbes = 0; + let maximumSessions = 0; + const loads = []; + const sessions = []; + const messages = []; + const terminals = new Map(); + const pipeline = async (_task, model, options) => { + loads.push({ model, device: options.device, dtype: options.dtype }); + now += 5; + options.progress_callback({ status: 'initiate' }); + options.progress_callback({ status: 'progress', progress: 50 }); + await beforeLoad(options); + if (failLoad(model, options)) throw new Error('load failure'); + liveSessions++; + maximumSessions = Math.max(maximumSessions, liveSessions); + const session = async () => { + now += 7; + if (failInference(model, options)) throw new Error('inference failure'); + const output = { dims: [1, 1, 2], data: Float32Array.of(1, 3), dispose() { session.tensorDisposals++; } }; + return { predicted_depth: output }; + }; + session.processor = { image_processor: { size: { width: 518, height: 518 } } }; + session.disposals = 0; + session.tensorDisposals = 0; + session.dispose = async () => { now += 2; session.disposals++; liveSessions--; }; + sessions.push(session); + return session; + }; + vm.runInNewContext(outputText, { + exports: {}, Error, + require(name) { + if (name === '@huggingface/transformers') return { pipeline }; + if (name === '../constants/depth') return constants; + throw new Error(`unexpected worker dependency ${name}`); + }, + performance: { now: () => now }, + navigator: hasGpu ? { gpu: missingAdapterMethod ? {} : { async requestAdapter() { adapterProbes++; if (adapterError) throw new Error('adapter unavailable'); return adapter; } } } : {}, + OffscreenCanvas: class { getContext() { return { drawImage() {} }; } }, + self: { + addEventListener(_type, callback) { listener = callback; }, + postMessage(message) { messages.push(message); if (message.type !== 'status') terminals.get(message.id)?.(message); }, + }, + }); + let requestId = 0; + return { + loads, sessions, messages, + get maximumSessions() { return maximumSessions; }, + get adapterProbes() { return adapterProbes; }, + request(legacyFields = {}) { + const id = ++requestId; + const bitmap = { width: 10, height: 5, closed: 0, close() { this.closed++; } }; + return new Promise((resolve) => { + terminals.set(id, (message) => { terminals.delete(id); resolve({ message, bitmap }); }); + listener({ data: { type: 'infer', id, image: bitmap, ...legacyFields } }); + }); + }, + }; +} + +test('worker uses Small 770 with WASM/q8 when WebGPU is absent', async () => { + const h = await workerHarness({ hasGpu: false }); + const { message, bitmap } = await h.request(); + assert.equal(message.type, 'result'); + assert.deepEqual(h.loads, [{ model: 'onnx-community/depth-anything-v2-small-ONNX', ...wasm }]); + assert.deepEqual({ ...message.run }, { model: 'small', ...wasm, preparationMs: 5, inferenceMs: 7, totalMs: 12 }); + assert.deepEqual({ ...h.sessions[0].processor.image_processor.size }, { width: 770, height: 770 }); + assert.deepEqual([...new Uint8Array(message.values)], [0, 255]); + assert.deepEqual([...new Float32Array(message.normalizedValues)], [0, 1]); + assert.equal(h.sessions[0].tensorDisposals, 1); + assert.equal(bitmap.closed, 1); +}); + +test('a stale model-selection field cannot load another model or override execution', async () => { + const h = await workerHarness(); + const { message } = await h.request({ model: 'base', preset: wasm }); + assert.equal(message.type, 'result'); + assert.deepEqual(h.loads, [{ model: 'onnx-community/depth-anything-v2-small-ONNX', ...gpu }]); + assert.equal(message.run.model, 'small'); +}); + +test('worker reuses the fixed Small session on repeated requests', async () => { + const h = await workerHarness(); + await h.request(); + const reused = await h.request(); + assert.equal(h.loads.length, 1); + assert.equal(h.adapterProbes, 1, 'cached session does not repeatedly probe GPU'); + assert.equal(h.maximumSessions, 1); + assert.equal(h.sessions[0].disposals, 0); + assert.equal(reused.message.run.preparationMs, 0); + assert.equal(reused.message.run.inferenceMs, 7); +}); + +test('GPU inference failure disposes and requests an isolated WASM retry', async () => { + const h = await workerHarness({ failInference: (_model, preset) => preset.device === 'webgpu' }); + const { message, bitmap } = await h.request(); + assert.equal(message.type, 'fallback'); + assert.deepEqual(h.loads, [{ model: 'onnx-community/depth-anything-v2-small-ONNX', ...gpu }]); + assert.equal(h.sessions[0].disposals, 1); + assert.equal(message.preparationMs, 7); assert.equal(message.inferenceMs, 7); + assert.equal(bitmap.closed, 1); +}); + +test('GPU loading failure requests fresh worker and retains failed preparation time', async () => { + const h = await workerHarness({ failLoad: (_model, preset) => preset.device === 'webgpu' }); + const { message } = await h.request(); + assert.equal(message.type, 'fallback'); + assert.equal(message.preparationMs, 5); assert.equal(message.inferenceMs, 0); + assert.equal(h.loads.length, 1, 'must not retry inside a poisoned worker'); +}); + +test('a present GPU API with null or rejected adapter selects WASM directly', async () => { + for (const options of [{ adapter: null }, { adapterError: true }, { missingAdapterMethod: true }]) { + const h = await workerHarness(options); const { message } = await h.request(); + assert.equal(message.type, 'result'); assert.equal(message.run.device, 'wasm'); + assert.deepEqual(h.loads, [{ model: 'onnx-community/depth-anything-v2-small-ONNX', ...wasm }]); + } +}); + +test('forced fallback worker bypasses GPU and retains Small 770', async () => { + const h = await workerHarness(); const { message } = await h.request({ forceWasm: true }); + assert.equal(message.type, 'result'); assert.equal(message.run.device, 'wasm'); + assert.deepEqual(h.loads, [{ model: 'onnx-community/depth-anything-v2-small-ONNX', ...wasm }]); + assert.equal(h.sessions[0].processor.image_processor.size.width, 770); + assert.equal(h.adapterProbes, 0, 'forced CPU retry cannot touch GPU again'); +}); + +test('terminal WASM failure closes the input and returns an error without more retries', async () => { + const h = await workerHarness({ hasGpu: false, failInference: () => true }); + const { message, bitmap } = await h.request(); + assert.equal(message.type, 'error'); + assert.equal(message.message, 'inference failure'); + assert.equal(h.loads.length, 1); + assert.equal(bitmap.closed, 1); +}); + +test('worker labels file progress without implying a cold download', async () => { + const h = await workerHarness(); + await h.request(); + const statuses = h.messages.filter(({ type }) => type === 'status').map(({ message }) => message); + assert.ok(statuses.includes('출발 준비 중 · 50%')); + assert.ok(statuses.includes('내비게이션으로 길을 찾는 중…')); + assert.ok(statuses.every((message) => !/AI|깊이|모델|WebGPU|CPU|계산/i.test(message))); + assert.ok(statuses.every((message) => !/다운로드|download/i.test(message))); +}); + + +test('provider retries once in a fresh worker and ignores orphan messages', async () => { + const h = await providerHarness(); + try { + const pending = h.provider.getDepthMap(photo); const settled = pending.then(value => ({ value }), error => ({ error })); + await tick(); const old = h.workers[0], id = old.messages[0].id; + old.onmessage({ data: { type: 'fallback', id, preparationMs: 5, inferenceMs: 7 } }); + await tick(); + assert.equal(h.statuses.at(-1), '다른 길을 찾고 있어요. 조금만 더 기다려 주세요…'); + assert.equal(h.workers.length, 2, 'fallback requires a new JS realm'); + const fallback = h.workers[1]; assert.equal(old.terminated, true); assert.equal(fallback.messages[0].forceWasm, true); + old.onmessage({ data: { type: 'error', id, message: 'late GPU failure' } }); + old.onerror({ message: 'late crash' }); + replyWithResult(fallback, { model: 'small', ...wasm, preparationMs: 10, inferenceMs: 20, totalMs: 30 }); + const result = await settled; assert.equal(result.error, undefined); + assert.equal(result.value.userData.aiDepthRun.preparationMs, 15); assert.equal(result.value.userData.aiDepthRun.inferenceMs, 27); + assert.equal(h.workers.length, 2); result.value.dispose(); + } finally { await h.cleanup(); } +}); + +test('fallback cannot loop and terminal failures discard the poisoned runtime', async () => { + const h = await providerHarness(); + try { + const pending = h.provider.getDepthMap(photo); const settled = pending.then(value => ({ value }), error => ({ error })); + await tick(); const old = h.workers[0], id = old.messages[0].id; + old.onmessage({ data: { type: 'fallback', id, preparationMs: 5, inferenceMs: 0 } }); await tick(); + assert.equal(h.workers.length, 2); + const fallback = h.workers[1]; fallback.onmessage({ data: { type: 'fallback', id, preparationMs: 5, inferenceMs: 0 } }); + const result = await settled; assert.ok(result.error); assert.equal(h.workers.length, 2); assert.equal(fallback.terminated, true); + } finally { await h.cleanup(); } +}); + +test('photo replacement during fallback capture closes stale bitmap without replacing new worker', async () => { + let captures = 0, release; + const h = await providerHarness(async () => { + captures++; + if (captures === 2) return new Promise(resolve => { release = resolve; }); + return { width: 10, height: 5, close() {} }; + }); + try { + const pending = h.provider.getDepthMap(photo); const rejected = assert.rejects(pending, { name: 'AbortError' }); + await tick(); const old = h.workers[0], id = old.messages[0].id; + old.onmessage({ data: { type: 'fallback', id, preparationMs: 5, inferenceMs: 0 } }); await tick(); + assert.equal(typeof release, 'function', 'fallback recaptures the requested photo'); + h.provider.cancel(); await rejected; + const replacement = h.provider.getDepthMap({ naturalWidth: 50, naturalHeight: 100 }); await tick(); + assert.equal(h.workers.length, 2); const current = h.workers[1]; + const stale = { width: 10, height: 5, closed: 0, close() { this.closed++; } }; release(stale); await tick(); + assert.equal(stale.closed, 1); assert.equal(h.workers.length, 2); assert.equal(old.terminated, true); + replyWithResult(current, { model: 'small', ...wasm, preparationMs: 1, inferenceMs: 2, totalMs: 3 }); (await replacement).dispose(); + } finally { await h.cleanup(); } +}); + +test('serialized terminal error also discards runtime so manual retry starts fresh', async () => { + const h = await providerHarness(); + try { + const pending = h.provider.getDepthMap(photo); const rejected = assert.rejects(pending, /WASM failed/); + await tick(); const old = h.workers[0], id = old.messages[0].id; + old.onmessage({ data: { type: 'error', id, message: 'WASM failed' } }); await rejected; + assert.equal(old.terminated, true); + const retry = h.provider.getDepthMap(photo); await tick(); assert.equal(h.workers.length, 2); + replyWithResult(h.workers[1], { model: 'small', ...wasm, preparationMs: 1, inferenceMs: 2, totalMs: 3 }); + (await retry).dispose(); + } finally { await h.cleanup(); } +}); + + +// Execute the installed dependency's actual initialization chain, replacing only ORT's +// slow hardware boundary. A rejected GPU load prevents same-realm WASM from running. +async function dependencyRuntime() { + const source = await readFile(new URL('../node_modules/@huggingface/transformers/src/backends/onnx.js', import.meta.url), 'utf8'); + const start = source.indexOf('export async function createInferenceSession('); + assert.ok(start >= 0); + const body = source.slice(start, source.indexOf('\n/**', start)).replace('export ', ''); + const calls = []; + const context = { + ensureWasmLoaded: async () => {}, getOnnxLogSeverityLevel: () => 2, env: {}, LogLevel: { WARNING: 2 }, apis: { IS_WEB_ENV: true }, + InferenceSession: { async create(_buffer, options) { + const device = options.executionProviders[0]; calls.push(device); + if (device === 'webgpu') throw new Error('Failed to get GPU adapter'); + return {}; + } }, + }; + vm.createContext(context); + vm.runInContext('let webInitChain = Promise.resolve();' + body + ';this.create = createInferenceSession;', context); + return { calls, create: preset => context.create(new Uint8Array(), { executionProviders: [preset.device] }, {}) }; +} + +test('real dependency rejected chain is isolated before WASM fallback', async () => { + const poisoned = await dependencyRuntime(); + const gpuWorker = await workerHarness({ beforeLoad: poisoned.create }); + const failed = await gpuWorker.request(); assert.equal(failed.message.type, 'fallback'); + assert.deepEqual(poisoned.calls, ['webgpu']); + await assert.rejects(poisoned.create(wasm), /Failed to get GPU adapter/); + assert.deepEqual(poisoned.calls, ['webgpu'], 'same-realm fallback is skipped by the dependency, matching the reported mechanism'); + const clean = await dependencyRuntime(); + const cpuWorker = await workerHarness({ beforeLoad: clean.create }); + const recovered = await cpuWorker.request({ forceWasm: true }); + assert.equal(recovered.message.type, 'result'); assert.equal(recovered.message.run.device, 'wasm'); + assert.deepEqual(clean.calls, ['wasm']); + await cpuWorker.request(); assert.deepEqual(clean.calls, ['wasm'], 'successful WASM session is reused'); +}); + +test('duplicate and stale fallback replies cannot replace the active CPU worker', async () => { + const h = await providerHarness(); + try { + const pending = h.provider.getDepthMap(photo); await tick(); const old = h.workers[0], id = old.messages[0].id; + const fallbackReply = { data: { type: 'fallback', id, preparationMs: 5, inferenceMs: 0 } }; + old.onmessage(fallbackReply); old.onmessage(fallbackReply); await tick(); + assert.equal(h.workers.length, 2); const current = h.workers[1]; + current.onmessage({ data: { type: 'fallback', id: id - 1, preparationMs: 0, inferenceMs: 0 } }); + assert.equal(current.terminated, false); assert.equal(h.workers.length, 2); + replyWithResult(current, { model: 'small', ...wasm, preparationMs: 1, inferenceMs: 2, totalMs: 3 }); (await pending).dispose(); + } finally { await h.cleanup(); } +}); + +test('Worker constructor failure closes the captured bitmap', async () => { + const h = await providerHarness(); + try { + globalThis.Worker = class { constructor() { throw new Error('worker unavailable'); } }; + await assert.rejects(h.provider.getDepthMap(photo), /worker unavailable/); + assert.equal(h.bitmaps[0].closed, true); + } finally { await h.cleanup(); } +}); diff --git a/scripts/test-analytics-identity.mjs b/scripts/test-analytics-identity.mjs new file mode 100644 index 0000000..74e0ff1 --- /dev/null +++ b/scripts/test-analytics-identity.mjs @@ -0,0 +1,87 @@ +import assert from 'node:assert/strict'; +import { access } from 'node:fs/promises'; +import { createHash, webcrypto } from 'node:crypto'; +import { test } from 'node:test'; +import { loadTypescript } from './support/load-typescript.mjs'; + +const moduleURL = new URL('../src/analytics/Identity.ts', import.meta.url); +assert.equal(await access(moduleURL).then(() => true, () => false), true, 'private browser identity module must exist'); +const { getVisitorId, makeDogId, VISITOR_ID_STORAGE_KEY } = await loadTypescript(moduleURL); +const first = '01234567-89ab-4cde-8f01-23456789abcd'; +const second = '12345678-9abc-4def-9012-3456789abcde'; +const digest = webcrypto.subtle.digest.bind(webcrypto.subtle); +const hash = (visitor, name) => makeDogId(visitor, name, digest); + +test('visitor UUID persists across collector reloads without creating another identifier', () => { + const values = new Map(); + const storage = { getItem: key => values.get(key) ?? null, setItem: (key, value) => values.set(key, value) }; + assert.equal(getVisitorId({ getStorage: () => storage, randomUUID: () => first }), first); + assert.equal(values.get(VISITOR_ID_STORAGE_KEY), first); + assert.equal(VISITOR_ID_STORAGE_KEY, 'behind-glass.visitor-id.v1'); + assert.equal(getVisitorId({ getStorage: () => storage, randomUUID: () => { throw Error('must reuse stored ID'); } }), first); +}); + +test('malformed stored UUID is replaced by a fresh valid random UUID', () => { + for (const bad of ['', 'not-a-uuid', first + 'x', '00000000-0000-0000-0000-000000000000', first.replace('-4cde-', '-1cde-'), first.replace('-4cde-', '-7cde-')]) { + let value = bad; + assert.equal(getVisitorId({ getStorage: () => ({ getItem: () => value, setItem: (_key, next) => { value = next; } }), randomUUID: () => first }), first); + assert.equal(value, first); + } +}); + +test('blocked storage getter, read, write, and absent storage use one UUID per collector', () => { + for (const getStorage of [ + () => undefined, + () => { throw Error('blocked getter'); }, + () => ({ getItem() { throw Error('blocked read'); }, setItem() { throw Error('blocked write'); } }), + () => ({ getItem: () => null, setItem() { throw Error('full'); } }), + ]) { + let created = 0; + const options = { getStorage, randomUUID: () => (++created === 1 ? first : second) }; + assert.equal(getVisitorId(options), first); + assert.equal(getVisitorId(options), first); + assert.equal(created, 1); + assert.equal(getVisitorId({ getStorage, randomUUID: () => second }), second); + } +}); + +test('unavailable, throwing, or invalid random UUID creation leaves telemetry inert', () => { + for (const randomUUID of [undefined, () => { throw Error('unavailable'); }, () => 'invented-fingerprint', () => first.replace('-4cde-', '-1cde-'), () => first.replace('-4cde-', '-7cde-')]) { + const options = { getStorage: () => undefined, randomUUID }; + assert.equal(getVisitorId(options), undefined); + assert.equal(getVisitorId(options), undefined); + } +}); + +test('stored uppercase UUID is replaced and noncanonical generated UUID stays inert', () => { + let stored = first.toUpperCase(); + const storage = { getItem: () => stored, setItem: (_key, value) => { stored = value; } }; + assert.equal(getVisitorId({ getStorage: () => storage, randomUUID: () => second }), second); + assert.equal(stored, second); + assert.equal(getVisitorId({ getStorage: () => undefined, randomUUID: () => first.toUpperCase() }), undefined); +}); + +test('empty and whitespace names use the explicit default name hash', async () => { + assert.equal(await hash(first, ''), await hash(first, '멍멍이')); + assert.equal(await hash(first, ' \n\t '), await hash(first, '멍멍이')); +}); + +test('hash uses NFC, trim and 20 code points without friendly display suffixes', async () => { + assert.equal(await hash(first, ' 호롱 '), await hash(first, '호롱')); + assert.equal(await hash(first, '🐕'.repeat(21)), await hash(first, '🐕'.repeat(20))); + assert.notEqual(await hash(first, '호롱'), await hash(first, '호롱이')); +}); + +test('WebCrypto hashes the exact versioned UTF-8 JSON tuple to lowercase SHA-256', async () => { + const expected = createHash('sha256').update(JSON.stringify([1, first, '호롱']), 'utf8').digest('hex'); + assert.equal(await hash(first, '호롱'), expected); + assert.match(expected, /^[0-9a-f]{64}$/); + assert.notEqual(await hash('a|b', 'c'), await hash('a', 'b|c'), 'tuple framing cannot collide through a delimiter'); +}); + +test('missing, throwing, rejected or malformed digest disables only the affected hash', async () => { + for (const unavailable of [undefined, () => { throw Error('unavailable'); }, async () => { throw Error('failed'); }, async () => new ArrayBuffer(0)]) { + assert.equal(await makeDogId(first, '호롱', unavailable), ''); + } + assert.match(await hash(first, '호롱'), /^[0-9a-f]{64}$/); +}); diff --git a/scripts/test-analytics-tracker.mjs b/scripts/test-analytics-tracker.mjs new file mode 100644 index 0000000..ece2dcb --- /dev/null +++ b/scripts/test-analytics-tracker.mjs @@ -0,0 +1,203 @@ +import assert from 'node:assert/strict'; +import { access } from 'node:fs/promises'; +import { test } from 'node:test'; +import { loadTypescript } from './support/load-typescript.mjs'; + +const moduleURL = new URL('../src/analytics/ArrivalTracker.ts', import.meta.url); +assert.equal(await access(moduleURL).then(() => true, () => false), true, 'journey collector must exist'); +const { createArrivalTracker } = await loadTypescript(moduleURL); +const { createTransport } = await loadTypescript(new URL('../src/analytics/Transport.ts', import.meta.url)); +const visitorId = '01234567-89ab-4cde-8f01-23456789abcd'; +const dogId = 'a'.repeat(64), otherDogId = 'b'.repeat(64); +const flush = () => new Promise(resolve => setImmediate(resolve)); +const deferred = () => { let resolve, reject; const promise = new Promise((yes, no) => { resolve = yes; reject = no; }); return { promise, resolve, reject }; }; + +function collector(overrides = {}) { + const calls = [], counts = [], hashes = []; + const tracker = createArrivalTracker({ + visitorId, + makeDogId: async (visitor, name) => { hashes.push({ visitor, name }); return dogId; }, + transport: { request: async (path, body, signal) => { calls.push({ path, body, signal }); return body === undefined ? { ok: true, count: 7 } : { ok: true }; } }, + onCount: count => counts.push(count), + ...overrides, + }); + return { tracker, calls, counts, hashes }; +} + +test('start is nonblocking and sends exactly one visit and initial count', async () => { + const { tracker, calls, counts } = collector(); + assert.equal(tracker.start(), undefined); tracker.start(); + await flush(); + assert.deepEqual(calls.map(({ path, body }) => ({ path, body })), [ + { path: '/api/visits', body: { visitor_id: visitorId } }, + { path: '/api/arrivals/count', body: undefined }, + ]); + assert.deepEqual(counts, [7]); + tracker.dispose(); +}); + +test('sample arrivals are excluded without suppressing their visit', async () => { + const { tracker, calls, hashes } = collector(); + tracker.start(); tracker.arrived(tracker.begin('sample', '호롱')); + await flush(); + assert.equal(calls.filter(call => call.path === '/api/visits').length, 1); + assert.equal(calls.some(call => call.path === '/api/arrivals'), false); + assert.deepEqual(hashes, []); + tracker.dispose(); +}); + +test('begin alone never registers an arrival and duplicate arrived calls send once', async () => { + const { tracker, calls } = collector(); + const token = tracker.begin('personal', '호롱'); + await flush(); assert.deepEqual(calls, []); + assert.equal(tracker.arrived(token), undefined); tracker.arrived(token); + await flush(); tracker.arrived(token); await flush(); + assert.deepEqual(calls.map(call => call.path), ['/api/arrivals', '/api/arrivals/count']); + assert.deepEqual(calls[0].body, { dog_id: dogId }); + tracker.dispose(); +}); + +test('hash completion after photo replacement cannot register the old journey', async () => { + const old = deferred(), next = deferred(); + let hashCalls = 0; + const { tracker, calls } = collector({ makeDogId: () => ++hashCalls === 1 ? old.promise : next.promise }); + const stale = tracker.begin('personal', '호롱'); tracker.arrived(stale); + const current = tracker.begin('personal', '보리'); + assert.ok(current > stale); tracker.arrived(stale); tracker.arrived(current); + old.resolve(dogId); await flush(); assert.deepEqual(calls, []); + next.resolve(otherDogId); await flush(); + assert.deepEqual(calls.filter(call => call.path === '/api/arrivals').map(call => call.body), [{ dog_id: otherDogId }]); + tracker.dispose(); +}); + +test('explicit invalidation makes delayed hashes and old tokens inert', async () => { + const pending = deferred(); + const { tracker, calls } = collector({ makeDogId: () => pending.promise }); + const token = tracker.begin('personal', '호롱'); tracker.arrived(token); tracker.invalidate(); + pending.resolve(dogId); tracker.arrived(token); await flush(); + assert.deepEqual(calls, []); + tracker.dispose(); +}); + +test('dispose cancels visits, count reads and delayed hash continuations permanently', async () => { + const pending = deferred(), calls = []; + const { tracker, counts } = collector({ + makeDogId: () => pending.promise, + transport: { request: (path, body, signal) => { calls.push({ path, signal }); return pending.promise.then(() => body === undefined ? { ok: true, count: 99 } : { ok: true }); } }, + }); + tracker.start(); const token = tracker.begin('personal', '호롱'); tracker.arrived(token); + tracker.dispose(); tracker.dispose(); tracker.start(); tracker.arrived(tracker.begin('personal', '보리')); + assert.ok(calls.every(call => call.signal.aborted)); + pending.resolve(dogId); await flush(); + assert.deepEqual(counts, []); + assert.deepEqual(calls.map(call => call.path), ['/api/visits', '/api/arrivals/count']); +}); + +test('begin synchronously captures the original visitor and raw name', async () => { + const pending = deferred(), captured = []; + const options = { visitorId, makeDogId: (visitor, name) => { captured.push({ visitor, name }); return pending.promise; } }; + const { tracker, calls } = collector(options); + let rawName = ' 호롱 '; + const token = tracker.begin('personal', rawName); + rawName = '보리'; options.visitorId = 'replacement'; + assert.deepEqual(captured, [{ visitor: visitorId, name: ' 호롱 ' }]); + tracker.arrived(token); pending.resolve(dogId); await flush(); + assert.deepEqual(calls[0].body, { dog_id: dogId }); + tracker.dispose(); +}); + +test('transport retries retain the journey ID after a name edit', async () => { + const sent = [], delays = []; + let name = '호롱'; + const transport = createTransport({ + fetch: async (path, init) => { + if (path.endsWith('/count')) return { status: 200, json: async () => ({ count: 8 }) }; + sent.push(init.body); name = '보리'; return { status: sent.length === 1 ? 503 : 204 }; + }, + sleep: async ms => { delays.push(ms); }, + }); + const { tracker, counts } = collector({ transport, makeDogId: async (_visitor, captured) => captured === '호롱' ? dogId : otherDogId }); + tracker.arrived(tracker.begin('personal', name)); await flush(); + assert.equal(name, '보리'); + assert.deepEqual(sent, [JSON.stringify({ dog_id: dogId }), JSON.stringify({ dog_id: dogId })]); + assert.deepEqual(delays, [500]); assert.deepEqual(counts, [8]); + tracker.dispose(); +}); + +test('invalidation during delayed retry cancels the next attempt', async t => { + t.mock.timers.enable({ apis: ['setTimeout'] }); + let calls = 0; + const transport = createTransport({ fetch: async () => { calls++; return { status: 503 }; } }); + const { tracker } = collector({ transport }); + tracker.arrived(tracker.begin('personal', '호롱')); await flush(); + assert.equal(calls, 1); tracker.invalidate(); + t.mock.timers.tick(10000); await flush(); assert.equal(calls, 1); + tracker.dispose(); +}); + +test('successful arrival refreshes the count while failed registration does not', async () => { + for (const ok of [true, false]) { + const calls = []; + const { tracker, counts } = collector({ transport: { request: async path => { calls.push(path); return path.endsWith('/count') ? { ok: true, count: 12 } : { ok }; } } }); + tracker.arrived(tracker.begin('personal', '호롱')); await flush(); + assert.deepEqual(calls, ok ? ['/api/arrivals', '/api/arrivals/count'] : ['/api/arrivals']); + assert.deepEqual(counts, ok ? [12] : []); tracker.dispose(); + } +}); + +test('late initial count cannot overwrite a newer successful arrival refresh', async () => { + const initial = deferred(), fresh = deferred(); + let reads = 0; + const { tracker, counts } = collector({ transport: { request: async path => path.endsWith('/count') ? (++reads === 1 ? initial.promise : fresh.promise) : { ok: true } } }); + tracker.start(); tracker.arrived(tracker.begin('personal', '호롱')); await flush(); + fresh.resolve({ ok: true, count: 11 }); await flush(); + initial.resolve({ ok: true, count: 10 }); await flush(); + assert.deepEqual(counts, [11]); tracker.dispose(); +}); + +test('a failed newer count read preserves the last good count and permits an earlier valid read', async () => { + const initial = deferred(), fresh = deferred(); + let reads = 0; + const { tracker, counts } = collector({ transport: { request: async path => path.endsWith('/count') ? (++reads === 1 ? initial.promise : fresh.promise) : { ok: true } } }); + tracker.start(); tracker.arrived(tracker.begin('personal', '호롱')); await flush(); + fresh.resolve({ ok: false }); await flush(); initial.resolve({ ok: true, count: 5 }); await flush(); + assert.deepEqual(counts, [5]); tracker.dispose(); +}); + +test('missing visitor disables identification events while aggregate reads remain available', async () => { + const { tracker, calls, hashes, counts } = collector({ visitorId: undefined }); + tracker.start(); tracker.arrived(tracker.begin('personal', '호롱')); await flush(); + assert.deepEqual(calls.map(call => call.path), ['/api/arrivals/count']); + assert.deepEqual(hashes, []); assert.deepEqual(counts, [7]); tracker.dispose(); +}); + +test('throwing and rejected hash or transport failures never escape fire-and-forget methods', async () => { + for (const makeDogId of [() => { throw Error('crypto'); }, async () => { throw Error('crypto'); }, async () => '', async () => 'invalid']) { + const { tracker, calls } = collector({ makeDogId }); + assert.doesNotThrow(() => tracker.arrived(tracker.begin('personal', '호롱'))); + await flush(); assert.deepEqual(calls, []); tracker.dispose(); + } + for (const request of [() => { throw Error('network'); }, async () => { throw Error('network'); }]) { + const { tracker, counts } = collector({ transport: { request } }); + assert.doesNotThrow(() => { tracker.start(); tracker.arrived(tracker.begin('personal', '호롱')); }); + await flush(); assert.deepEqual(counts, []); tracker.dispose(); + } + const { tracker } = collector({ onCount: () => { throw Error('removed DOM'); } }); + tracker.start(); await flush(); tracker.dispose(); +}); + +test('invalid count responses cannot reach presentation even through an injected transport', async () => { + for (const count of [-1, 0.5, '3', Number.MAX_SAFE_INTEGER + 1, undefined]) { + const { tracker, counts } = collector({ transport: { request: async () => ({ ok: true, count }) } }); + tracker.start(); await flush(); assert.deepEqual(counts, []); tracker.dispose(); + } +}); + +test('invalidation cancels pending work but cannot undo an already accepted server write', async () => { + const accepted = [], pending = deferred(); + const { tracker, counts } = collector({ transport: { request: async (path, body) => { accepted.push({ path, body }); return pending.promise; } } }); + tracker.arrived(tracker.begin('personal', '호롱')); await flush(); + tracker.invalidate(); pending.resolve({ ok: true }); await flush(); + assert.deepEqual(accepted, [{ path: '/api/arrivals', body: { dog_id: dogId } }]); + assert.deepEqual(counts, []); tracker.dispose(); +}); diff --git a/scripts/test-analytics-transport.mjs b/scripts/test-analytics-transport.mjs new file mode 100644 index 0000000..3dd07b7 --- /dev/null +++ b/scripts/test-analytics-transport.mjs @@ -0,0 +1,210 @@ +import assert from 'node:assert/strict'; +import { access } from 'node:fs/promises'; +import { test } from 'node:test'; +import { loadTypescript } from './support/load-typescript.mjs'; + +const moduleURL = new URL('../src/analytics/Transport.ts', import.meta.url); +assert.equal(await access(moduleURL).then(() => true, () => false), true, 'bounded telemetry transport module must exist'); +const { createTransport } = await loadTypescript(moduleURL); +const flush = () => new Promise(resolve => setImmediate(resolve)); +const response = (status, value) => ({ status, json: async () => value }); + +test('POST sends only serialized JSON and GET returns a valid count', async () => { + const sent = []; + const transport = createTransport({ fetch: async (path, init) => { sent.push({ path, ...init }); return response(init.method === 'POST' ? 204 : 200, { count: 1234 }); } }); + assert.deepEqual(await transport.request('/api/visits', { visitor_id: 'visitor' }), { ok: true }); + assert.equal(sent[0].body, '{"visitor_id":"visitor"}'); + assert.equal(sent[0].headers['Content-Type'], 'application/json'); + assert.equal(sent[0].method, 'POST'); + assert.equal(sent[0].credentials, 'same-origin'); + assert.deepEqual(await transport.request('/api/arrivals/count'), { ok: true, count: 1234 }); + assert.equal(sent[1].method, 'GET'); + assert.equal(sent[1].body, undefined); + assert.equal(sent[1].cache, 'no-store'); +}); + +for (const failure of ['network', 429, 500, 503]) { + test(`${failure} retries after 500 and 1500 ms with an identical payload, never a fourth attempt`, async () => { + const sent = [], delays = []; + const body = { dog_id: 'original' }; + const transport = createTransport({ + fetch: async (_path, init) => { sent.push(init.body); body.dog_id = 'edited'; if (failure === 'network') throw Error('offline'); return response(failure); }, + sleep: async ms => { delays.push(ms); }, + }); + assert.deepEqual(await transport.request('/api/arrivals', body), { ok: false }); + assert.deepEqual(delays, [500, 1500]); + assert.deepEqual(sent, ['{"dog_id":"original"}', '{"dog_id":"original"}', '{"dog_id":"original"}']); + }); +} + +test('a later successful retry finishes without further attempts', async () => { + let calls = 0; + const delays = []; + const transport = createTransport({ fetch: async () => response(++calls === 1 ? 503 : 204), sleep: async ms => { delays.push(ms); } }); + assert.deepEqual(await transport.request('/api/arrivals', { dog_id: 'id' }), { ok: true }); + assert.equal(calls, 2); + assert.deepEqual(delays, [500]); +}); + +for (const status of [400, 403, 404, 415]) { + test(`${status} is not retried`, async () => { + let calls = 0; + const transport = createTransport({ fetch: async () => { calls++; return response(status); }, sleep: async () => assert.fail('must not retry') }); + assert.deepEqual(await transport.request('/api/visits', { visitor_id: 'id' }), { ok: false }); + assert.equal(calls, 1); + }); +} + +test('the 3000 ms deadline aborts the actual fetch and is cleared after completion', async t => { + t.mock.timers.enable({ apis: ['setTimeout'] }); + let signal; + const transport = createTransport({ fetch: (_path, init) => { signal = init.signal; return new Promise(() => {}); }, retryDelays: [] }); + const pending = transport.request('/api/arrivals/count'); + await flush(); + t.mock.timers.tick(2999); + assert.equal(signal.aborted, false); + t.mock.timers.tick(1); + await flush(); + assert.equal(signal.aborted, true); + assert.deepEqual(await pending, { ok: false }); + let completedSignal; + const successful = createTransport({ fetch: async (_path, init) => { completedSignal = init.signal; return response(204); } }); + await successful.request('/api/visits', { visitor_id: 'id' }); + t.mock.timers.tick(10000); + assert.equal(completedSignal.aborted, false, 'completed attempt timeout was removed'); +}); + +test('deadline also covers a stalled JSON body read', async t => { + t.mock.timers.enable({ apis: ['setTimeout'] }); + let signal; + const transport = createTransport({ fetch: async (_path, init) => { signal = init.signal; return { status: 200, json: () => new Promise(() => {}) }; }, retryDelays: [] }); + const pending = transport.request('/api/arrivals/count'); + await flush(); + t.mock.timers.tick(3000); + await flush(); + assert.deepEqual(await pending, { ok: false }); + assert.equal(signal.aborted, true); +}); + +test('caller abort cancels an in-flight request, timeout and further retries', async t => { + t.mock.timers.enable({ apis: ['setTimeout'] }); + const caller = new AbortController(); + let calls = 0, signal; + const transport = createTransport({ fetch: (_path, init) => { calls++; signal = init.signal; return new Promise(() => {}); } }); + const pending = transport.request('/api/visits', { visitor_id: 'id' }, caller.signal); + await flush(); caller.abort(); await flush(); + assert.deepEqual(await pending, { ok: false }); + assert.equal(signal.aborted, true); + t.mock.timers.tick(100000); await flush(); + assert.equal(calls, 1); +}); + +test('caller abort cancels default delayed retry and never makes another request', async t => { + t.mock.timers.enable({ apis: ['setTimeout'] }); + const caller = new AbortController(); + let calls = 0; + const transport = createTransport({ fetch: async () => { calls++; throw Error('offline'); } }); + const pending = transport.request('/api/arrivals', { dog_id: 'id' }, caller.signal); + await flush(); t.mock.timers.tick(499); await flush(); + assert.equal(calls, 1); + caller.abort(); await flush(); + assert.deepEqual(await pending, { ok: false }); + t.mock.timers.tick(100000); await flush(); + assert.equal(calls, 1); +}); + +test('caller abort settles even an injected sleep that ignores cancellation', async () => { + const caller = new AbortController(); + let calls = 0, sleepSignal; + const transport = createTransport({ fetch: async () => { calls++; throw Error('offline'); }, sleep: (_ms, signal) => { sleepSignal = signal; return new Promise(() => {}); } }); + const pending = transport.request('/api/arrivals', { dog_id: 'id' }, caller.signal); + await flush(); caller.abort(); await flush(); + assert.deepEqual(await pending, { ok: false }); + assert.equal(sleepSignal.aborted, true); + assert.equal(calls, 1); +}); + +test('already-aborted requests are inert', async () => { + const caller = new AbortController(); caller.abort(); + const transport = createTransport({ fetch: () => assert.fail('must not fetch') }); + assert.deepEqual(await transport.request('/api/arrivals/count', undefined, caller.signal), { ok: false }); +}); + +test('malformed count values and malformed JSON never become displayed zero', async () => { + for (const value of [null, {}, [], { count: -1 }, { count: 0.5 }, { count: '2' }, { count: Number.MAX_SAFE_INTEGER + 1 }, { count: NaN }, { count: Infinity }]) { + const transport = createTransport({ fetch: async () => response(200, value) }); + assert.deepEqual(await transport.request('/api/arrivals/count'), { ok: false }); + } + for (const count of [0, 1, Number.MAX_SAFE_INTEGER]) { + assert.deepEqual(await createTransport({ fetch: async () => response(200, { count }) }).request('/api/arrivals/count'), { ok: true, count }); + } + assert.deepEqual(await createTransport({ fetch: async () => ({ status: 200, json: async () => { throw Error('bad JSON'); } }), retryDelays: [] }).request('/api/arrivals/count'), { ok: false }); +}); + +test('serialization and injected dependency failures are contained without rejection', async () => { + const circular = {}; circular.self = circular; + const transport = createTransport({ fetch: () => { throw Error('missing'); }, sleep: () => { throw Error('clock unavailable'); } }); + assert.deepEqual(await transport.request('/api/visits', circular), { ok: false }); + assert.deepEqual(await transport.request('/api/visits', { visitor_id: 'id' }), { ok: false }); +}); + +test('non-contract success statuses cannot register an arrival or invent a count', async () => { + assert.deepEqual(await createTransport({ fetch: async () => response(200, {}) }).request('/api/arrivals', { dog_id: 'id' }), { ok: false }); + assert.deepEqual(await createTransport({ fetch: async () => response(204) }).request('/api/arrivals/count'), { ok: false }); +}); + +test('network failure reading a count response body retries and can recover', async () => { + const delays = []; + let calls = 0; + const transport = createTransport({ + fetch: async () => ++calls === 1 + ? new Response(new ReadableStream({ start(controller) { controller.error(new TypeError('network reset')); } }), { status: 200 }) + : Response.json({ count: 14 }), + sleep: async ms => { delays.push(ms); }, + }); + assert.deepEqual(await transport.request('/api/arrivals/count'), { ok: true, count: 14 }); + assert.equal(calls, 2); assert.deepEqual(delays, [500]); +}); + +test('permanent network failure reading count bodies has exactly two delayed retries', async () => { + const delays = []; + let calls = 0; + const transport = createTransport({ + fetch: async () => { calls++; return new Response(new ReadableStream({ start(controller) { controller.error(new TypeError('network reset')); } }), { status: 200 }); }, + sleep: async ms => { delays.push(ms); }, + }); + assert.deepEqual(await transport.request('/api/arrivals/count'), { ok: false }); + assert.equal(calls, 3); assert.deepEqual(delays, [500, 1500]); +}); + +test('syntax-invalid JSON is not a retryable network failure', async () => { + let calls = 0; + const transport = createTransport({ fetch: async () => { calls++; return new Response('{invalid', { status: 200 }); }, sleep: async () => assert.fail('invalid JSON must not retry') }); + assert.deepEqual(await transport.request('/api/arrivals/count'), { ok: false }); + assert.equal(calls, 1); +}); + +test('retryable and terminal unread response bodies are cancelled before the attempt completes', async () => { + for (const [status, body, expectedAttempts] of [[429, { dog_id: 'id' }, 3], [503, { dog_id: 'id' }, 3], [200, { dog_id: 'id' }, 1], [403, undefined, 1]]) { + let calls = 0, cancelled = 0; + const cancelledBeforeRetry = []; + const caller = new AbortController(); + const transport = createTransport({ + fetch: async () => { calls++; return new Response(new ReadableStream({ cancel() { cancelled++; } }), { status }); }, + sleep: async () => { cancelledBeforeRetry.push(cancelled); }, + }); + assert.deepEqual(await transport.request('/api/arrivals', body, caller.signal), { ok: false }); + assert.equal(calls, expectedAttempts); assert.equal(cancelled, calls); + assert.deepEqual(cancelledBeforeRetry, expectedAttempts === 3 ? [1, 2] : []); + caller.abort(); await flush(); assert.equal(cancelled, calls, 'later caller abort leaves no open body behind'); + } +}); + +test('response-body cleanup failures cannot reject or stall the bounded request', async () => { + for (const cancel of [() => { throw Error('cancel failed'); }, () => Promise.reject(Error('cancel failed')), () => new Promise(() => {})]) { + let cancelled = 0, signal; + const transport = createTransport({ fetch: async (_path, init) => { signal = init.signal; return { status: 403, body: { cancel: () => { cancelled++; return cancel(); } } }; } }); + assert.deepEqual(await transport.request('/api/arrivals/count'), { ok: false }); + assert.equal(cancelled, 1); assert.equal(signal.aborted, true); + } +}); diff --git a/scripts/test-arrival-api.mjs b/scripts/test-arrival-api.mjs new file mode 100644 index 0000000..abf73ca --- /dev/null +++ b/scripts/test-arrival-api.mjs @@ -0,0 +1,208 @@ +import test from 'node:test'; +import assert from 'node:assert/strict'; +import { mkdtempSync, mkdirSync, writeFileSync, rmSync, symlinkSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; +import { buildApp } from '../server/app.mjs'; +import { openStore } from '../server/db.mjs'; + +const VISITOR = '12345678-1234-4123-8123-123456789abc'; +const DOG = 'a'.repeat(64); +const ORIGIN = 'https://arrival.example'; +async function fixture(t, options = {}) { + const root = mkdtempSync(join(tmpdir(), 'arrival-api-')); + const distRoot = join(root, 'dist'); + mkdirSync(join(distRoot, 'assets'), { recursive: true }); + mkdirSync(join(distRoot, 'fonts')); + mkdirSync(join(distRoot, 'models')); + writeFileSync(join(distRoot, 'index.html'), 'arrival fixture'); + writeFileSync(join(distRoot, 'assets', 'index-AbCd1234.js'), 'export const loaded = true'); + writeFileSync(join(distRoot, 'assets', 'worker-ZyXw9876.js'), 'self.onmessage = () => {}'); + writeFileSync(join(distRoot, 'assets', 'ort-wasm.wasm'), Buffer.from([0, 97, 115, 109])); + writeFileSync(join(distRoot, 'fonts', 'font.woff'), 'font'); + writeFileSync(join(distRoot, 'models', 'model.onnx'), 'model'); + writeFileSync(join(distRoot, 'config.json'), 'private-fixture-secret'); + writeFileSync(join(distRoot, 'counts.sqlite'), 'private-fixture-secret'); + writeFileSync(join(distRoot, 'counts.sqlite-wal'), 'private-fixture-secret'); + writeFileSync(join(distRoot, 'counts.sqlite-shm'), 'private-fixture-secret'); + writeFileSync(join(root, 'outside.txt'), 'private-fixture-secret'); + symlinkSync(join(root, 'outside.txt'), join(distRoot, 'assets', 'escaped.txt')); + const store = options.store ?? openStore({ dbPath: join(root, 'private', 'counts.sqlite') }); + const app = await buildApp({ store, distRoot, publicOrigin: ORIGIN, rateLimit: { max: 10000, timeWindow: 60000 }, ...options }); + t.after(async () => { await app.close(); rmSync(root, { recursive: true, force: true }); }); + return { app, store, root }; +} +function post(app, url, payload, headers = {}) { return app.inject({ method: 'POST', url, payload, headers }); } +function assertError(response, status) { + assert.equal(response.statusCode, status, response.body); + assert.match(response.headers['content-type'], /application\/json/); + assert.equal(response.headers['cache-control'], 'no-store'); + assert.doesNotMatch(response.body, /12345678|aaaaaaaaaa|sqlite|private-fixture-secret|visitor_id|dog_id|body\//i); +} + +test('visit and arrival contracts use real SQLite and concurrent duplicates stay at one', async t => { + const { app, store } = await fixture(t); + assert.deepEqual((await app.inject('/api/arrivals/count')).json(), { count: 0 }); + assert.equal((await post(app, '/api/visits', { visitor_id: VISITOR })).statusCode, 204); + const replies = await Promise.all(Array.from({ length: 20 }, () => post(app, '/api/arrivals', { dog_id: DOG }))); + for (const reply of replies) { assert.equal(reply.statusCode, 204); assert.equal(reply.body, ''); } + assert.equal(store.arrivalCount(), 1); + const count = await app.inject('/api/arrivals/count'); + assert.deepEqual(count.json(), { count: 1 }); + assert.equal(count.headers['cache-control'], 'no-store'); +}); + +test('exact schemas reject extra keys, coercion, invalid IDs, array/null and malformed JSON', async t => { + const { app } = await fixture(t); + for (const payload of [{}, { visitor_id: 1 }, { visitor_id: null }, { visitor_id: [VISITOR] }, { visitor_id: VISITOR, photo: 'private-fixture-secret' }, { visitor_id: VISITOR, name: 'private-fixture-secret' }, { visitor_id: VISITOR, visit_date: '2026-10-08' }, [], null]) { + assertError(await post(app, '/api/visits', JSON.stringify(payload), { 'content-type': 'application/json' }), 400); + } + for (const id of ['x', VISITOR.replace('-4', '-1'), VISITOR.replace('-8123', '-7123'), `${VISITOR}\n`, VISITOR.toUpperCase()]) assertError(await post(app, '/api/visits', { visitor_id: id }), 400); + for (const payload of [{}, { dog_id: 1 }, { dog_id: DOG.toUpperCase() }, { dog_id: DOG.slice(1) }, { dog_id: `${DOG}\n` }, { dog_id: DOG, photo: 'private-fixture-secret' }, { dog_id: DOG, name: 'private-fixture-secret' }, { dog_id: DOG, visitor_id: VISITOR }]) assertError(await post(app, '/api/arrivals', payload), 400); + assertError(await post(app, '/api/arrivals', '{"dog_id":', { 'content-type': 'application/json' }), 400); + assertError(await post(app, '/api/arrivals', JSON.stringify({ dog_id: DOG }), { 'content-type': 'text/plain' }), 415); + assertError(await post(app, '/api/arrivals', JSON.stringify({ dog_id: DOG }), { 'content-type': 'application/x-www-form-urlencoded' }), 415); + assertError(await post(app, '/api/arrivals', JSON.stringify({ dog_id: DOG, extra: 'x'.repeat(1024) }), { 'content-type': 'application/json' }), 413); +}); + +test('Origin validation uses configured public origin and allows absent Origin', async t => { + const { app } = await fixture(t); + for (const origin of [undefined, ORIGIN]) { + const headers = origin ? { origin } : {}; + assert.equal((await post(app, '/api/visits', { visitor_id: VISITOR }, headers)).statusCode, 204); + } + for (const origin of ['https://foreign.example', 'null', 'not-an-origin', `${ORIGIN}/path`, `${ORIGIN}, https://foreign.example`]) { + assertError(await post(app, '/api/visits', { visitor_id: VISITOR }, { origin, host: 'foreign.example', 'x-forwarded-host': 'foreign.example' }), 403); + } + assert.equal((await post(app, '/api/visits', { visitor_id: VISITOR }, { origin: ORIGIN, host: 'forged.example' })).statusCode, 204); +}); + +test('API rate limit is 60 per connection IP; forged forwarded headers do not evade it', async t => { + const { app } = await fixture(t, { rateLimit: { max: 60, timeWindow: 60000 } }); + for (let i = 0; i < 60; i++) assert.equal((await app.inject({ url: '/api/arrivals/count', headers: { 'x-forwarded-for': `203.0.113.${i}` } })).statusCode, 200); + assertError(await app.inject({ url: '/api/arrivals/count', headers: { 'x-forwarded-for': '198.51.100.99' } }), 429); + assert.equal((await app.inject({ url: '/api/arrivals/count', remoteAddress: '192.0.2.12' })).statusCode, 200); + assert.equal((await app.inject('/')).statusCode, 200); +}); + +test('closed/unavailable store returns generic 503 without identifiers or paths', async t => { + const { app, store } = await fixture(t); + store.close(); + assertError(await app.inject('/api/arrivals/count'), 503); + assertError(await post(app, '/api/visits', { visitor_id: VISITOR }), 503); + assertError(await post(app, '/api/arrivals', { dog_id: DOG }), 503); +}); + +test('app close owns its store exactly once and import never listens', async t => { + let closed = 0; + const { app } = await fixture(t, { store: { close() { closed++; }, arrivalCount() { return 0; } } }); + assert.equal(app.server.listening, false); + await app.close(); + await app.close(); + assert.equal(closed, 1); +}); + +test('unknown API and POST routes return JSON 404, never SPA HTML', async t => { + const { app } = await fixture(t); + for (const method of ['GET', 'POST']) for (const url of ['/api', '/api/', '/api/nope', '/api/monthly-visitors', '/api/visits/nope']) assertError(await app.inject({ method, url, headers: { accept: 'text/html' } }), 404); + assertError(await app.inject({ method: 'POST', url: '/somewhere', headers: { accept: 'text/html' } }), 404); +}); + +test('static MIME/cache and SPA navigation preserve worker/WASM/font/model asset routes', async t => { + const { app } = await fixture(t); + for (const url of ['/', '/index.html', '/journey/window']) { + const response = await app.inject({ url, headers: { accept: 'text/html' } }); + assert.equal(response.statusCode, 200); + assert.match(response.body, /arrival fixture/); + assert.equal(response.headers['cache-control'], 'no-store'); + } + assert.equal((await app.inject({ method: 'HEAD', url: '/journey/window', headers: { accept: 'text/html' } })).statusCode, 200); + for (const url of ['/assets/index-AbCd1234.js', '/assets/worker-ZyXw9876.js']) { + const response = await app.inject(url); + assert.equal(response.statusCode, 200); + assert.match(response.headers['content-type'], /javascript/); + assert.equal(response.headers['cache-control'], 'public,max-age=31536000,immutable'); + } + const wasm = await app.inject('/assets/ort-wasm.wasm'); + assert.equal(wasm.statusCode, 200); + assert.equal(wasm.headers['content-type'], 'application/wasm'); + assert.equal(wasm.headers['cache-control'], 'no-cache'); + for (const url of ['/fonts/font.woff', '/models/model.onnx']) assert.equal((await app.inject(url)).statusCode, 200); + for (const url of ['/assets/nope.js', '/models/missing.onnx', '/route.json', '/missing']) assertError(await app.inject({ url, headers: { accept: url === '/missing' ? '*/*' : 'text/html' } }), 404); +}); + +test('traversal, symlink escapes and guessed data/config files are never static responses', async t => { + const { app } = await fixture(t); + for (const url of ['/../outside.txt', '/%2e%2e/outside.txt', '/%2e%2e%2foutside.txt', '/assets/%2e%2e/%2e%2e/outside.txt', '/assets/escaped.txt', '/counts.sqlite', '/counts.sqlite-wal', '/counts.sqlite-shm', '/config.json', '/.env', '/.git/config', '/server/config.mjs', '/api/%2e%2e%2findex.html']) { + const response = await app.inject({ url, headers: { accept: 'text/html' } }); + assert.ok([400, 404].includes(response.statusCode), `${url}: ${response.statusCode}`); + assert.doesNotMatch(response.body, /private-fixture-secret|arrival fixture/); + } +}); + +test('unhashed existing GLB assets never receive an immutable build cache policy', async t => { + const { app, root } = await fixture(t); + const directory = join(root, 'dist', 'assets', 'window'); + mkdirSync(directory); + writeFileSync(join(directory, 'grandma-house-surround.glb'), 'geometry fixture'); + const response = await app.inject('/assets/window/grandma-house-surround.glb?v=2'); + assert.equal(response.statusCode, 200); + assert.equal(response.headers['cache-control'], 'no-cache'); +}); + +test('percent-encoded API route aliases share the same IP limit, including writes', async t => { + const { app, store } = await fixture(t, { rateLimit: { max: 1, timeWindow: 60000 } }); + assert.equal((await post(app, '/api/arrivals', { dog_id: DOG })).statusCode, 204); + for (const url of ['/%61pi/arrivals', '/a%70i/arrivals', '/ap%69/arrivals']) assertError(await post(app, url, { dog_id: 'f'.repeat(64) }), 429); + assert.equal(store.arrivalCount(), 1); + assertError(await app.inject('/%61pi/arrivals/count'), 429); +}); + +test('framework malformed-URL errors never echo request identifiers and are no-store', async t => { + const { app } = await fixture(t); + const response = await app.inject('/api/%ZZ/private-fixture-secret'); + assertError(response, 400); + assert.doesNotMatch(response.body, /%ZZ|private-fixture-secret|FST_ERR_BAD_URL/); +}); + +test('same-root symlink aliases cannot expose blocked database or configuration files', async t => { + const { app, root } = await fixture(t); + for (const [name, target] of [['alias.txt', 'counts.sqlite'], ['config-alias.txt', 'config.json'], ['wal-alias.txt', 'counts.sqlite-wal']]) { + symlinkSync(join(root, 'dist', target), join(root, 'dist', name)); + const response = await app.inject(`/${name}`); + assertError(response, 404); + } +}); + +test('unknown API paths return JSON 404 before unsupported or malformed body parsing', async t => { + const { app } = await fixture(t); + for (const url of ['/api', '/api/nope', '/api/visits/nope']) { + assertError(await post(app, url, 'private-fixture-secret', { 'content-type': 'text/plain' }), 404); + assertError(await post(app, url, '{"private-fixture-secret":', { 'content-type': 'application/json' }), 404); + } +}); + +test('absolute-form HTTP targets cannot bypass same-origin or API rate guards', async t => { + const { app, store } = await fixture(t, { rateLimit: { max: 1, timeWindow: 60000 } }); + const { default: inject } = await import('light-my-request'); + for (const origin of ['https://foreign.example', ORIGIN]) { + const response = await inject((request, reply) => { + request.url = 'http://arrival.example/api/arrivals'; + app.routing(request, reply); + }, { url: '/api/arrivals', method: 'POST', payload: { dog_id: DOG }, headers: { origin } }); + assertError(response, 400); + } + assert.equal(store.arrivalCount(), 0); +}); + +test('raw unnormalized traversal is rejected before the routing/static boundary', async t => { + const { app } = await fixture(t); + const { default: inject } = await import('light-my-request'); + for (const target of ['/api/%2e%2e/index.html', '/../index.html', '/assets/../index.html']) { + const response = await inject((request, reply) => { + request.url = target; + app.routing(request, reply); + }, { url: '/', headers: { accept: 'text/html' } }); + assertError(response, 404); + } +}); diff --git a/scripts/test-arrival-count.mjs b/scripts/test-arrival-count.mjs new file mode 100644 index 0000000..990c8f0 --- /dev/null +++ b/scripts/test-arrival-count.mjs @@ -0,0 +1,48 @@ +import assert from 'node:assert/strict'; +import { access, readFile } from 'node:fs/promises'; +import { test } from 'node:test'; +import { loadTypescript } from './support/load-typescript.mjs'; + +const moduleURL = new URL('../src/ui/ArrivalCount.ts', import.meta.url); +assert.equal(await access(moduleURL).then(() => true, () => false), true, 'arrival count presentation module must exist'); +const { renderArrivalCount } = await loadTypescript(moduleURL); +const element = () => ({ hidden: false, textContent: '', set innerHTML(_value) { assert.fail('numeric copy must use textContent'); } }); + +test('unknown initial count hides all count nodes without inventing zero', () => { + const elements = [element(), element()]; + renderArrivalCount(elements, undefined); + assert.ok(elements.every(node => node.hidden)); + assert.ok(elements.every(node => node.textContent === '')); +}); + +test('server zero is a real visible zero with the exact Korean copy', () => { + const elements = [element(), element()]; + renderArrivalCount(elements, 0); + for (const node of elements) { assert.equal(node.hidden, false); assert.equal(node.textContent, '지금까지 0번 도착했어요'); } +}); + +test('arrival count groups using Korean locale and updates both placements', () => { + const elements = [element(), element()]; + renderArrivalCount(elements, 1234); + for (const node of elements) { assert.equal(node.hidden, false); assert.equal(node.textContent, '지금까지 1,234번 도착했어요'); } +}); + +test('failed or invalid reads preserve the last valid count text and visibility', () => { + const elements = [element(), element()]; + renderArrivalCount(elements, 1234); + for (const count of [undefined, -1, 0.5, '0', Number.MAX_SAFE_INTEGER + 1, NaN]) { + renderArrivalCount(elements, count); + for (const node of elements) { assert.equal(node.hidden, false); assert.equal(node.textContent, '지금까지 1,234번 도착했어요'); } + } +}); + +test('malformed initial count is hidden rather than displayed', () => { + for (const count of [-1, 0.5, '0', Number.MAX_SAFE_INTEGER + 1, NaN]) { + const node = element(); renderArrivalCount([node], count); assert.equal(node.hidden, true); assert.equal(node.textContent, ''); + } +}); + +test('count presentation has no animation, polling or render-demand dependency', async () => { + const source = await readFile(moduleURL, 'utf8'); + assert.doesNotMatch(source, /innerHTML|requestAnimationFrame|setInterval|setTimeout|RenderDemand|invalidate/); +}); diff --git a/scripts/test-arrival-db.mjs b/scripts/test-arrival-db.mjs new file mode 100644 index 0000000..d3fd983 --- /dev/null +++ b/scripts/test-arrival-db.mjs @@ -0,0 +1,144 @@ +import test from 'node:test'; +import assert from 'node:assert/strict'; +import { mkdtempSync, rmSync, mkdirSync, statSync, symlinkSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join, resolve } from 'node:path'; +import { openStore } from '../server/db.mjs'; +import { readConfig } from '../server/config.mjs'; +import Database from 'better-sqlite3'; + +const VISITOR_A = '12345678-1234-4123-8123-123456789abc'; +const VISITOR_B = '87654321-4321-4321-a321-cba987654321'; +const DOG = 'a'.repeat(64); +function fixture(t, close = () => {}) { + const root = mkdtempSync(join(tmpdir(), 'arrival-db-')); + t.after(() => { close(); rmSync(root, { recursive: true, force: true }); }); + return { root, dbPath: join(root, 'private', 'counts.sqlite') }; +} +function inspect(path, fn) { + const db = new Database(path, { readonly: true, fileMustExist: true }); + try { return fn(db); } finally { db.close(); } +} + +test('real native SQLite uses exact schema, WAL, bounded busy timeout and private files', t => { + let store; + const { dbPath } = fixture(t, () => store?.close()); + store = openStore({ dbPath }); + assert.equal(store.arrivalCount(), 0); + inspect(dbPath, db => { + assert.match(db.prepare('SELECT sqlite_version() AS version').get().version, /^\d+\.\d+\.\d+$/); + assert.equal(db.pragma('journal_mode', { simple: true }), 'wal'); + assert.equal(db.pragma('user_version', { simple: true }), 1); + assert.deepEqual(db.pragma('table_info(visitors_daily)').map(c => c.name), ['visitor_id', 'visit_date', 'first_seen_at', 'last_seen_at']); + assert.deepEqual(db.pragma('table_info(arrivals)').map(c => c.name), ['dog_id', 'first_arrived_at']); + assert.ok(db.pragma('index_list(visitors_daily)').some(i => db.pragma(`index_info(${i.name})`).map(c => c.name).join() === 'visit_date')); + }); + if (process.platform !== 'win32') { + assert.equal(statSync(join(dbPath, '..')).mode & 0o777, 0o700); + for (const path of [dbPath, `${dbPath}-wal`, `${dbPath}-shm`]) assert.equal(statSync(path).mode & 0o077, 0); + } + assert.throws(() => openStore({ dbPath, busyTimeoutMs: -1 })); + assert.throws(() => openStore({ dbPath, busyTimeoutMs: 10001 })); +}); + +test('daily upserts preserve first time, update last time and MAU is DISTINCT across days', t => { + let store; + const { dbPath } = fixture(t, () => store?.close()); + let at = '2026-10-01T00:00:00.000Z'; + store = openStore({ dbPath, now: () => new Date(at) }); + store.recordVisit(VISITOR_A); + at = '2026-10-01T01:00:00.000Z'; + store.recordVisit(VISITOR_A); + let rows = inspect(dbPath, db => db.prepare('SELECT * FROM visitors_daily').all()); + assert.deepEqual(rows, [{ visitor_id: VISITOR_A, visit_date: '2026-10-01', first_seen_at: '2026-10-01T00:00:00.000Z', last_seen_at: at }]); + at = '2026-10-02T00:00:00.000Z'; + store.recordVisit(VISITOR_A); + store.recordVisit(VISITOR_B); + assert.equal(store.monthlyVisitors('2026-10'), 2); + assert.equal(inspect(dbPath, db => db.prepare('SELECT COUNT(*) AS n FROM visitors_daily').get().n), 3); + assert.equal(store.monthlyVisitors('2026-09'), 0); +}); + +for (const [before, after, previousMonth, nextMonth] of [ + ['2026-10-31T14:59:59.000Z', '2026-10-31T15:00:00.000Z', '2026-10', '2026-11'], + ['2026-12-31T14:59:59.000Z', '2026-12-31T15:00:00.000Z', '2026-12', '2027-01'], +]) test(`Seoul month boundary ${previousMonth} is independent of process timezone`, t => { + let store; + const { dbPath } = fixture(t, () => store?.close()); + let at = before; + store = openStore({ dbPath, now: () => new Date(at) }); + store.recordVisit(VISITOR_A); + at = after; + store.recordVisit(VISITOR_B); + assert.equal(store.monthlyVisitors(previousMonth), 1); + assert.equal(store.monthlyVisitors(nextMonth), 1); + const dates = inspect(dbPath, db => db.prepare('SELECT visit_date FROM visitors_daily ORDER BY visit_date').all()); + assert.equal(dates[1].visit_date, `${nextMonth}-01`); +}); + +test('arrivals are idempotent, first timestamp persists and migrations reopen without data loss', t => { + let store; + const { dbPath } = fixture(t, () => store?.close()); + let at = '2026-10-08T00:00:00.000Z'; + store = openStore({ dbPath, now: () => new Date(at) }); + store.recordArrival(DOG); + at = '2026-10-09T00:00:00.000Z'; + store.recordArrival(DOG); + assert.equal(store.arrivalCount(), 1); + store.close(); + store.close(); + store = openStore({ dbPath }); + assert.equal(store.arrivalCount(), 1); + assert.deepEqual(inspect(dbPath, db => db.prepare('SELECT * FROM arrivals').all()), [{ dog_id: DOG, first_arrived_at: '2026-10-08T00:00:00.000Z' }]); +}); + +test('strict month validation handles year bounds and December rollover', t => { + let store; + const { dbPath } = fixture(t, () => store?.close()); + store = openStore({ dbPath }); + for (const month of [undefined, null, 202610, '', '2026-1', '2026-00', '2026-13', '0000-01', '10000-01', '2026-10-01', ' 2026-10', '2026-10\n']) assert.throws(() => store.monthlyVisitors(month)); + for (const month of ['0001-01', '0099-12', '2026-12', '9999-12']) assert.equal(store.monthlyVisitors(month), 0); +}); + +test('configuration requires explicit absolute private DB path and strict origin/port', t => { + const { dbPath } = fixture(t); + const config = readConfig({ DB_PATH: dbPath }); + assert.deepEqual(config, { dbPath, distRoot: resolve('dist'), host: '127.0.0.1', port: 3000, publicOrigin: 'http://127.0.0.1:3000' }); + assert.equal(readConfig({ DB_PATH: dbPath, HOST: '0.0.0.0', PORT: '4010' }).host, '0.0.0.0'); + assert.throws(() => readConfig({})); + assert.throws(() => readConfig({ DB_PATH: 'relative.sqlite' })); + assert.throws(() => readConfig({ DB_PATH: ':memory:' })); + for (const path of ['local.sqlite', 'src/db.sqlite', 'public/db.sqlite', 'dist/db.sqlite']) assert.throws(() => readConfig({ DB_PATH: resolve(path) })); + for (const value of ['0', '-1', '65536', '3e3', '3000x', '1.2', '']) assert.throws(() => readConfig({ DB_PATH: dbPath, PORT: value })); + assert.throws(() => readConfig({ DB_PATH: dbPath, NODE_ENV: 'production' })); + for (const origin of ['null', 'ftp://example.com', 'https://user:pass@example.com', 'https://example.com/path', 'https://example.com?x', 'https://example.com#x']) assert.throws(() => readConfig({ DB_PATH: dbPath, NODE_ENV: 'production', PUBLIC_ORIGIN: origin })); + assert.equal(readConfig({ DB_PATH: dbPath, NODE_ENV: 'production', PUBLIC_ORIGIN: 'https://example.com' }).publicOrigin, 'https://example.com'); +}); + +test('canonical DB path validation catches existing and future paths through symlinks', t => { + const { root } = fixture(t); + symlinkSync(resolve('.'), join(root, 'source-link'), 'dir'); + for (const path of [join(root, 'source-link', 'db.sqlite'), join(root, 'source-link', 'new', 'db.sqlite')]) { + assert.throws(() => readConfig({ DB_PATH: path })); + assert.throws(() => openStore({ dbPath: path })); + } + mkdirSync(join(root, 'private'), { mode: 0o700 }); + symlinkSync(join(root, 'private'), join(root, 'safe-link'), 'dir'); + const config = readConfig({ DB_PATH: join(root, 'safe-link', 'db.sqlite') }); + assert.equal(config.dbPath, join(root, 'private', 'db.sqlite')); +}); + +test('DB paths reject raw and symlink-resolved whitespace before native filename trimming', async t => { + const { root, dbPath } = fixture(t); + const { writeFileSync } = await import('node:fs'); + const { openReadOnlyStore } = await import('../server/db.mjs'); + assert.throws(() => readConfig({ DB_PATH: `${dbPath} ` })); + assert.throws(() => openStore({ dbPath: `${dbPath}\t` })); + assert.throws(() => openReadOnlyStore(`${dbPath}\n`)); + const spacedTarget = join(root, 'target.sqlite '); + writeFileSync(spacedTarget, '', { mode: 0o600 }); + const alias = join(root, 'alias.sqlite'); + symlinkSync(spacedTarget, alias); + assert.throws(() => readConfig({ DB_PATH: alias })); + assert.throws(() => openStore({ dbPath: alias })); +}); diff --git a/scripts/test-arrival-integration.mjs b/scripts/test-arrival-integration.mjs new file mode 100644 index 0000000..8216316 --- /dev/null +++ b/scripts/test-arrival-integration.mjs @@ -0,0 +1,307 @@ +import assert from 'node:assert/strict'; +import { createHash } from 'node:crypto'; +import { readFile } from 'node:fs/promises'; +import { test } from 'node:test'; +import vm from 'node:vm'; +import ts from 'typescript'; +import { loadTypescript } from './support/load-typescript.mjs'; + +const main = await readFile(new URL('../src/main.ts', import.meta.url), 'utf8'); +const html = await readFile(new URL('../index.html', import.meta.url), 'utf8'); +const css = await readFile(new URL('../src/style.css', import.meta.url), 'utf8'); +const ast = ts.createSourceFile('main.ts', main, ts.ScriptTarget.Latest, true); +const statement = predicate => { + const found = ast.statements.find(node => predicate(node, node.getText(ast))); + assert.ok(found, 'required arrival lifecycle wiring is present'); + return found.getText(ast); +}; +const fn = name => statement(node => ts.isFunctionDeclaration(node) && node.name?.text === name); +const variable = name => statement(node => ts.isVariableStatement(node) && node.declarationList.declarations.some(declaration => declaration.name.getText(ast) === name)); +const expression = prefix => statement((node, text) => ts.isExpressionStatement(node) && text.startsWith(prefix)); +const deferred = () => { let resolve, reject; const promise = new Promise((a, b) => { resolve = a; reject = b; }); return { promise, resolve, reject }; }; +const tick = async () => { for (let index = 0; index < 25; index++) await Promise.resolve(); }; + +// These source contracts supplement executed production handlers below. Removing +// the gate, moving arrival to generic ready, or awaiting telemetry breaks them. +test('collector construction is explicitly opt-in and is started once outside rendering', () => { + assert.match(variable('arrivalTracker'), /import\.meta\.env\.VITE_ARRIVAL_ANALYTICS === 'true'/); + assert.equal((main.match(/arrivalTracker\?\.start\(\)/g) ?? []).length, 1); + assert.doesNotMatch(fn('frame'), /arrivalTracker|\/api\/|makeDogId/); + assert.doesNotMatch(main, /await\s+arrivalTracker/); +}); +test('AI success owns the only arrival call and captures a request-local token', () => { + const ai = fn('generateAIDepth'); + assert.equal((main.match(/arrivalTracker\?\.arrived\(/g) ?? []).length, 1); + assert.match(ai, /const arrivalToken = arrivalJourneyFor\(sourceTexture\)/); + assert.match(ai, /!renderLost && !meshFailure && arrivalToken !== null && arrivalToken === photoArrivalToken/); + assert.ok(ai.indexOf('setDepth(texture)') < ai.indexOf('arrivalTracker?.arrived(arrivalToken)')); + assert.ok(ai.indexOf('arrivalTracker?.arrived(arrivalToken)') < ai.indexOf("experience.setState('ready')")); + assert.match(fn('teardown'), /arrivalTracker\?\.dispose\(\)/); +}); +test('photo snapshot comes from the name store and survives retry without rereading the name', () => { + assert.match(fn('beginMediaLoad'), /petName\.name/); + assert.doesNotMatch(fn('arrivalJourneyFor'), /petName\.|querySelector|\.value/); + assert.match(fn('invalidateDepthRequests'), /cancelArrivalJourney\(\)/); + assert.match(fn('showMeshFailure'), /cancelArrivalJourney\(\)/); + assert.doesNotMatch(fn('generateAIDepth'), /beginMediaLoad|petNameForms/); +}); +test('two initially hidden counts sit below entry controls and the settings heading', () => { + const nodes = [...html.matchAll(/]*data-arrival-count[^>]*>/g)]; + assert.equal(nodes.length, 2); + for (const [node] of nodes) { assert.match(node, /\bhidden\b/); assert.doesNotMatch(node, /aria-live|role=/); } + assert.match(html, /id="notice-status"[^>]*><\/span>\s*<\/div>\s*]*data-arrival-count/); + assert.match(html, /id="settings-title"[\s\S]*?<\/div>\s*]*data-arrival-count/); + assert.match(css, /\.arrival-count\s*\{[^}]*(?:font-size|line-height)/); +}); + +class Element { + dataset = {}; attributes = {}; listeners = new Map(); hidden = false; open = false; inert = false; value = ''; isConnected = true; style = {}; + addEventListener(type, callback, { signal } = {}) { const set = this.listeners.get(type) ?? new Set(); set.add(callback); this.listeners.set(type, set); signal?.addEventListener('abort', () => set.delete(callback)); } + async dispatch(type, extra = {}) { for (const callback of [...(this.listeners.get(type) ?? [])]) await callback({ target: this, ...extra }); } + setAttribute(key, value) { this.attributes[key] = value; } + removeAttribute(key) { delete this.attributes[key]; } + focus() { if (!this.inert) this.root.activeElement = this; } + showModal() { this.open = true; } + close() { this.open = false; void this.dispatch('close'); } + getBoundingClientRect() { return { left: 0, top: 0, right: 400, bottom: 800 }; } + remove() {} +} + +async function harness({ enabled = true, reduced = false, pendingHash = false, retryArrival = false, cryptoFailure = '', invalidInitialId = false, blockedStorage = false } = {}) { + // Assert the actual feature before importing its separate production modules. + const initialization = ['arrivalTracker', 'photoArrivalSnapshot', 'photoArrivalTexture', 'photoArrivalToken'].map(variable).join('\n'); + const identity = await loadTypescript(new URL('../src/analytics/Identity.ts', import.meta.url)); + const { createArrivalTracker } = await loadTypescript(new URL('../src/analytics/ArrivalTracker.ts', import.meta.url)); + const { createTransport } = await loadTypescript(new URL('../src/analytics/Transport.ts', import.meta.url)); + const { renderArrivalCount } = await loadTypescript(new URL('../src/ui/ArrivalCount.ts', import.meta.url)); + const { createPetNameStore } = await loadTypescript(new URL('../src/state/PetName.ts', import.meta.url)); + const { initExperienceUI } = await loadTypescript(new URL('../src/ui/ExperienceUI.ts', import.meta.url)); + const root = new Element(), motion = new Element(), timers = new Map(); let timerId = 0; + motion.matches = reduced; + const elements = Object.fromEntries([...html.matchAll(/\bid="([^"]+)"/g)].map(([, id]) => [id, new Element()])); + const countNodes = [new Element(), new Element()]; countNodes.forEach(node => { node.hidden = true; }); + for (const node of Object.values(elements)) node.root = root; + root.querySelector = selector => elements[selector.slice(1)] ?? null; + root.querySelectorAll = selector => selector === '[data-arrival-count]' ? countNodes : []; + root.documentElement = new Element(); + root.defaultView = { localStorage: { getItem() { return null; }, setItem() {} }, matchMedia: () => motion, + setTimeout(callback, ms) { timers.set(++timerId, { callback, ms }); return timerId; }, clearTimeout(id) { timers.delete(id); } }; + const listenerAbort = new AbortController(); + const petName = createPetNameStore(() => root.defaultView.localStorage); petName.setName('호롱'); + const experience = initExperienceUI(root, listenerAbort.signal, () => {}, () => {}, () => {}, petName); + const requests = [], hashes = [], sleeps = [], inferences = [], sampleFetches = [], mediaLoads = []; + let identityReads = 0, transportCreations = 0, collectorCreations = 0, uuidCalls = 0, storageReads = 0, storageWrites = 0, digestCalls = 0; + const noop = () => {}; + const disposable = () => ({ dispose: noop }); + class Photo { width = 400; height = 500; src = 'blob:photo'; async decode() {} } + const texture = () => ({ ...disposable(), image: new Photo() }); + const emptyTex = texture(); + const context = { + document: root, listenerAbort, petName, experience, HTMLImageElement: Photo, Image: Photo, + AbortController, Object, Array, Error, Promise, Number, Boolean, Math, performance, + THREE: { SRGBColorSpace: 'srgb', Texture: class { constructor(image) { this.image = image; } } }, + AI_DEPTH: { modelName: 'Small', inputSize: 770 }, + active: emptyTex, emptyTex, activeIsVideo: false, aspect: 0, mediaRequest: 0, depthRequest: 0, + mediaBusy: false, manualDepthBusy: false, aiDepthBusy: false, renderLost: false, disposed: false, meshFailure: false, + pendingCutout: null, cutout: null, cutoutTexture: null, cutoutEnabled: false, + pendingSampleFraming: false, pendingPairDepth: null, pendingSampleDebugImage: null, pendingTestPhotoHasNoDepth: false, activeTestPhotoHasNoDepth: false, + aiDepthButton: elements['ai-depth'], imageInput: elements.image, videoInput: elements.video, + depthFileInput: elements['depth-image'], depthProvenance: elements['depth-provenance'], sampleButton: elements.sample, + testPhotoInput: { value: '' }, retry: new Element(), debugOutput: new Element(), hintElement: { dataset: {} }, + depthUniforms: { uTexture: {}, uDepthMap: { value: disposable() } }, depthMap: disposable(), + petMat: disposable(), petDepth: { geometry: disposable(), setVideo: noop }, empty: { style: {} }, + depthDebug: { clear: noop, setSample: noop }, DepthProcessor: { flatTexture: texture, toTexture: texture }, + setDepth(value) { context.appliedDepth = value; }, setMode: noop, setStatus: noop, showHint: noop, + resetViewCalls:0,resetNewPhotoView(){context.resetViewCalls++;},syncPhotoControls: noop, resize: noop, clearCutout: noop, renderPhotoTexture: () => context.active, + cancelDoorInteraction: noop, resetHintForMedia: noop, hideHintAfterDrag: noop, clearPendingTestState: noop, clearPendingPair: noop, + peekingUI: { cancel: noop, setState: noop, dispose: noop }, gyro: { setPaused: noop, dispose: noop }, + aiDepthProvider: { cancel: noop, getDepthMap(image) { const pending = deferred(); inferences.push({ ...pending, image }); return pending.promise; } }, + MediaLoader: class { constructor(ready, status) { this.ready = ready; this.status = status; context.loaderInstance = this; } load(file) { mediaLoads.push(file); } cancelPending() {} retry() {} dispose() {} }, + RenderRecovery: class { constructor(_canvas, _dialog, _button, lost, restored) { context.loseGraphics = lost; context.restoreGraphics = restored; } dispose() {} }, + fetch(path) { const pending = deferred(); sampleFetches.push({ ...pending, path }); return pending.promise; }, + File: class { constructor(_, name, options) { this.name = name; this.type = options.type; } }, + URL: { createObjectURL: () => 'blob:depth', revokeObjectURL: noop }, sampleDepthProvider: { getDepthMap: async () => texture() }, + rendererSelectionGeneration: 0, comparisonGeneration: 0, requestedRenderer: 'b', selectedRenderer: 'b', comparisonRequested: false, comparison: null, + meshErrorDialog: elements['mesh-render-error'], endComparison: noop, originalRenderer: null, + meshRenderer: { restore: noop, dispose: noop }, renderer: { domElement: new Element(), dispose: noop }, + rendererSelect: {}, rendererNotice: {}, courtyard: disposable(), peekingGrid: disposable(), doorMotion: { cancel: noop }, + raf: 0, cancelAnimationFrame: noop, observer: { disconnect: noop }, effectInput: {}, sensitivityInput: {}, resetButton: {}, gyroButton: {}, pointer: disposable(), + blenderFrame: disposable(), houseSurround: disposable(), housePhotoDepth: disposable(), windowFinish: disposable(), windowReveal: disposable(), windowRevealMaterial: disposable(), + frameMaterials: [], petDepthMaterial: disposable(), geometry: disposable(), frameGeometry: disposable(), + getVisitorId(options) { + identityReads++; + return identity.getVisitorId({ ...options, getStorage() { + storageReads++; + if (blockedStorage) throw new Error('storage unavailable'); + const storage = options.getStorage(); + return { getItem(key) { return invalidInitialId ? 'invalid stored id' : storage?.getItem(key); }, setItem(key, value) { storageWrites++; storage?.setItem(key, value); } }; + } }); + }, + makeDogId(visitor, name, digest) { const id = createHash('sha256').update(JSON.stringify([1, visitor, name.normalize('NFC').trim() || '멍멍이'])).digest('hex'); const pending = deferred(); hashes.push({ visitor, name, id, ...pending }); return pendingHash ? pending.promise : identity.makeDogId(visitor, name, digest); }, + createTransport() { transportCreations++; return createTransport({ + fetch: async (path, init = {}) => { requests.push({ path, body: init.body && JSON.parse(init.body), signal: init.signal }); return { ok: !(retryArrival && path === '/api/arrivals'), status: retryArrival && path === '/api/arrivals' ? 503 : init.body ? 204 : 200, json: async () => ({ count: 7 }) }; }, + sleep: (ms, signal) => { const pending = deferred(); sleeps.push({ ...pending, ms, signal }); return pending.promise; }, retryDelays: [1, 2] + }); }, + createArrivalTracker(options) { collectorCreations++; return createArrivalTracker(options); }, renderArrivalCount, + }; + // Test doubles are limited to external media/GPU/browser facilities. Lifecycle + // logic, retry transport, token cancellation, count renderer and UI are real. + const crypto = { + get randomUUID() { if (cryptoFailure === 'randomUUID') throw new Error('crypto UUID unavailable'); return () => { uuidCalls++; return '86f755c0-921b-4d34-a09c-5fcc8e4a21c6'; }; }, + get subtle() { + if (cryptoFailure === 'subtle') throw new Error('subtle unavailable'); + return { get digest() { if (cryptoFailure === 'digest') throw new Error('digest unavailable'); return (algorithm, data) => { digestCalls++; assert.equal(algorithm, 'SHA-256'); return Promise.resolve(Uint8Array.from(createHash('sha256').update(Buffer.from(data)).digest()).buffer); }; } }; + }, + }; + Object.defineProperty(context, 'crypto', { get() { if (cryptoFailure === 'crypto') throw new Error('crypto unavailable'); return crypto; } }); + context.meshErrorDialog ??= new Element(); + vm.createContext(context); + const functions = ['loadPersonalImage', 'cancelArrivalJourney', 'arrivalJourneyFor', 'beginMediaLoad', 'applyMedia', 'invalidateDepthRequests', 'syncAIDepthButton', 'generateAIDepth', 'loadSample', 'showMeshFailure', 'teardown'].map(fn); + const handlers = [expression('imageInput.onchange'), expression('videoInput.onchange'), expression("depthFileInput?.addEventListener('change'"), expression("document.querySelector('#flow-flat')"), expression("document.querySelector('#flow-retry')")]; + const code = [initialization, ...functions, variable('loader'), variable('renderRecovery'), ...handlers, expression('arrivalTracker?.start')].join('\n').replaceAll('import.meta.env.VITE_ARRIVAL_ANALYTICS', JSON.stringify(enabled ? 'true' : 'false')); + vm.runInContext(ts.transpileModule(code, { compilerOptions: { target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.ESNext } }).outputText, context); + await tick(); + const accept = (kind = 'personal') => { + const input = kind === 'video' ? context.videoInput : context.imageInput; + input.onchange({ target: { files: [{ type: kind === 'video' ? 'video/mp4' : 'image/png' }], value: 'selected' } }); + const photo = texture(); context.loaderInstance.ready(photo, 0.8, kind === 'video' ? {} : null); return photo; + }; + const finishAI = async (index = inferences.length - 1) => { inferences[index].resolve(texture()); await tick(); }; + const respondSample = async () => { sampleFetches.at(-1).resolve({ ok: true, blob: async () => ({}), headers: { get: () => 'image/jpeg' } }); await tick(); }; + return { context, elements, countNodes, timers, requests, hashes, sleeps, inferences, sampleFetches, mediaLoads, accept, finishAI, respondSample, + arrivals: () => requests.filter(request => request.path === '/api/arrivals'), counters: () => ({ identityReads, transportCreations, collectorCreations, uuidCalls, storageReads, storageWrites, digestCalls }) }; +} + +test('disabled static build creates no collector, identity, hash, storage or API work', async () => { + const h = await harness({ enabled: false }); h.accept(); await h.finishAI(); + assert.deepEqual(h.counters(), { identityReads: 0, transportCreations: 0, collectorCreations: 0, uuidCalls: 0, storageReads: 0, storageWrites: 0, digestCalls: 0 }); + assert.equal(h.requests.length, 0); assert.equal(h.hashes.length, 0); assert.ok(h.countNodes.every(node => node.hidden)); + assert.equal(h.elements.experience.dataset.flow, 'ready'); h.context.teardown(); +}); +test('valid AI success counts immediately for normal and reduced motion, without waiting for presentation', async () => { + for (const reduced of [false, true]) { + const h = await harness({ reduced }); h.accept(); await h.finishAI(); + assert.equal(h.arrivals().length, 1); assert.deepEqual(Object.keys(h.arrivals()[0].body), ['dog_id']); + assert.equal(h.elements.experience.dataset.flow, 'ready'); assert.equal(h.timers.size, reduced ? 0 : 1); + assert.equal(h.countNodes[0].textContent, h.countNodes[1].textContent); assert.ok(h.countNodes.every(node => !node.hidden)); + assert.equal(h.requests.filter(request => request.path === '/api/visits').length, 1); h.context.teardown(); + } +}); +test('picker cancellation creates no journey, while retry retains the accepted photo name', async () => { + const h = await harness(); h.context.imageInput.onchange({ target: { files: [], value: '' } }); + assert.equal(h.inferences.length, 0); h.accept(); h.context.petName.setName('초코'); + h.inferences[0].reject(new Error('AI unavailable')); await tick(); assert.equal(h.arrivals().length, 0); + const retry = h.context.generateAIDepth(); await h.finishAI(); await retry; + assert.equal(h.hashes.at(-1).name, '호롱'); assert.equal(h.arrivals().length, 1); + h.accept(); await h.finishAI(); assert.equal(h.hashes.at(-1).name, '초코'); assert.equal(h.arrivals().length, 2); h.context.teardown(); +}); +test('all replacement samples stay excluded after successful AI', async () => { + for (const selected of ['dog1', 'dog2', 'dog3', 'dog4', 'dog5']) { + const h = await harness(), loading = h.context.loadSample(selected); await h.respondSample(); + await loading; h.context.loaderInstance.ready({ image: new h.context.HTMLImageElement(), dispose() {} }, 0.8, null); + await h.finishAI(); + assert.equal(h.elements.experience.dataset.flow, 'ready'); assert.equal(h.arrivals().length, 0); assert.equal(h.hashes.length, 0); + assert.equal(h.requests.filter(request => request.path === '/api/visits').length, 1); h.context.teardown(); + } +}); +test('video, manual-depth, flat-view and errors do not create arrivals', async () => { + const video = await harness(); video.accept('video'); assert.equal(video.inferences.length, 0); assert.equal(video.arrivals().length, 0); video.context.teardown(); + for (const action of ['manual', 'flat', 'media-error', 'AI-error']) { + const h = await harness(); h.accept(); + if (action === 'manual') { h.context.depthFileInput.files = [{}]; await h.context.depthFileInput.dispatch('change'); } + if (action === 'flat') await h.elements['flow-flat'].dispatch('click'); + if (action === 'media-error') h.context.loaderInstance.status('cannot load'); + if (action === 'AI-error') { h.inferences[0].reject(new Error('failed')); await tick(); } + else await h.finishAI(); + assert.equal(h.arrivals().length, 0, action); h.context.teardown(); + } +}); +test('photo replacement and stale AI replies cannot switch to a newer identity', async () => { + const h = await harness(); h.accept(); h.context.petName.setName('초코'); h.accept(); + await h.finishAI(0); assert.equal(h.arrivals().length, 0); await h.finishAI(1); + assert.equal(h.arrivals().length, 1); assert.equal(h.hashes.at(-1).name, '초코'); h.context.teardown(); +}); +test('failed replacement cannot rearm a new name for the old active texture', async () => { + const h = await harness(); h.accept(); h.inferences[0].reject(new Error('failed')); await tick(); + h.context.petName.setName('초코'); h.context.imageInput.onchange({ target: { files: [{ type: 'image/png' }], value: 'new' } }); + h.context.loaderInstance.status('new photo failed'); const retry = h.context.generateAIDepth(); await h.finishAI(); await retry; + assert.equal(h.arrivals().length, 0); h.context.teardown(); +}); +test('graphics loss, render failure and teardown invalidate in-flight AI eligibility', async () => { + for (const action of ['context-loss', 'mesh-failure', 'dispose']) { + const h = await harness(); h.accept(); + if (action === 'context-loss') h.context.loseGraphics(); + if (action === 'mesh-failure') h.context.showMeshFailure(); + if (action === 'dispose') h.context.teardown(); + await h.finishAI(); assert.equal(h.arrivals().length, 0, action); + if (action !== 'dispose') h.context.teardown(); + } +}); +test('photo replacement, flat view, manual depth, errors and losses cancel a pending hash', async () => { + for (const action of ['replacement', 'flat', 'manual', 'media-error', 'context-loss', 'mesh-failure', 'dispose']) { + const h = await harness({ pendingHash: true }); h.accept(); await h.finishAI(); assert.equal(h.hashes.length, 1); + if (action === 'replacement') h.accept(); + if (action === 'flat') await h.elements['flow-flat'].dispatch('click'); + if (action === 'manual') { h.context.depthFileInput.files = [{}]; await h.context.depthFileInput.dispatch('change'); } + if (action === 'media-error') h.context.loaderInstance.status('cannot load'); + if (action === 'context-loss') h.context.loseGraphics(); + if (action === 'mesh-failure') h.context.showMeshFailure(); + if (action === 'dispose') h.context.teardown(); + h.hashes[0].resolve(h.hashes[0].id); await tick(); assert.equal(h.arrivals().length, 0, action); + if (action !== 'dispose') h.context.teardown(); + } +}); +test('invalidation aborts a delayed network retry without delaying the ready UI', async () => { + for (const action of ['replacement', 'flat', 'manual', 'media-error', 'context-loss', 'mesh-failure', 'dispose']) { + const h = await harness({ retryArrival: true }); h.accept(); await h.finishAI(); + assert.equal(h.elements.experience.dataset.flow, 'ready'); assert.equal(h.arrivals().length, 1); assert.equal(h.sleeps.length, 1); + if (action === 'replacement') h.accept(); + if (action === 'flat') await h.elements['flow-flat'].dispatch('click'); + if (action === 'manual') { h.context.depthFileInput.files = [{}]; await h.context.depthFileInput.dispatch('change'); } + if (action === 'media-error') h.context.loaderInstance.status('cannot load'); + if (action === 'mesh-failure') h.context.showMeshFailure(); + if (action === 'context-loss') h.context.loseGraphics(); + if (action === 'dispose') h.context.teardown(); + assert.equal(h.sleeps[0].signal.aborted, true, action); h.sleeps[0].resolve(); await tick(); assert.equal(h.arrivals().length, 1, action); + if (action !== 'dispose') h.context.teardown(); + } +}); + +test('invalid stored identity and unavailable storage recover without affecting AI startup', async () => { + for (const options of [{ invalidInitialId: true }, { blockedStorage: true }]) { + const h = await harness(options); h.accept(); await h.finishAI(); + assert.equal(h.elements.experience.dataset.flow, 'ready'); assert.equal(h.arrivals().length, 1); + assert.equal(h.counters().uuidCalls, 1); h.context.teardown(); + } +}); +test('throwing crypto, randomUUID, subtle and digest getters leave the experience usable', async () => { + for (const cryptoFailure of ['crypto', 'randomUUID', 'subtle', 'digest']) { + const h = await harness({ cryptoFailure }); h.accept(); await h.finishAI(); + assert.equal(h.elements.experience.dataset.flow, 'ready', cryptoFailure); assert.equal(h.arrivals().length, 0, cryptoFailure); + h.context.teardown(); + } +}); + +test('explicit AI retry after flat, manual depth or graphics recovery re-arms the original photo snapshot', async () => { + for (const reason of ['flat', 'manual', 'context-loss']) { + const h = await harness(); h.accept(); + h.inferences[0].reject(new Error('initial inference failed')); await tick(); + if (reason === 'flat') await h.elements['flow-flat'].dispatch('click'); + if (reason === 'manual') { h.context.depthFileInput.files = [{}]; await h.context.depthFileInput.dispatch('change'); } + if (reason === 'context-loss') { h.context.loseGraphics(); h.context.restoreGraphics(); } + h.context.petName.setName('보리'); + const retry = h.context.generateAIDepth(); await h.finishAI(); await retry; + assert.equal(h.arrivals().length, 1, reason); assert.equal(h.hashes.at(-1).name, '호롱', reason); + h.context.teardown(); + } +}); + + test('new-photo reset is called once on acceptance, never by picker cancellation, failure or AI retry',async()=>{ + const h=await harness({reduced:true});h.accept();await h.finishAI();assert.equal(h.context.resetViewCalls,1); + h.context.imageInput.onchange({target:{files:[],value:''}});assert.equal(h.context.resetViewCalls,1); + const retry=h.context.generateAIDepth();await h.finishAI();await retry;assert.equal(h.context.resetViewCalls,1); + h.context.imageInput.onchange({target:{files:[{type:'image/png'}],value:'new'}});h.context.loaderInstance.status('failed decode');assert.equal(h.context.resetViewCalls,1); + const sample=h.context.loadSample('dog5');await h.respondSample();await sample;assert.equal(h.context.resetViewCalls,1); + h.context.loaderInstance.ready({...h.context.active,image:new h.context.HTMLImageElement()},.8,null);await h.finishAI();assert.equal(h.context.resetViewCalls,2); + h.context.teardown(); + }); diff --git a/scripts/test-arrival-operations.mjs b/scripts/test-arrival-operations.mjs new file mode 100644 index 0000000..5e47ff5 --- /dev/null +++ b/scripts/test-arrival-operations.mjs @@ -0,0 +1,146 @@ +import test from 'node:test'; +import assert from 'node:assert/strict'; +import { mkdtempSync, mkdirSync, existsSync, copyFileSync, rmSync, statSync, writeFileSync, readFileSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join, resolve } from 'node:path'; +import { spawnSync } from 'node:child_process'; + +const VISITOR = '12345678-1234-4123-8123-123456789abc'; +const DOG = 'b'.repeat(64); +function fixture() { + const root = mkdtempSync(join(tmpdir(), 'arrival-ops-')); + return { root, dbPath: join(root, 'private', 'counts.sqlite') }; +} +function cli(script, args, dbPath, env = {}) { + return spawnSync(process.execPath, [resolve(`server/${script}.mjs`), ...args], { env: { ...process.env, DB_PATH: dbPath, ...env }, encoding: 'utf8' }); +} +async function setup(t) { + const { openStore, migrateDatabase } = await import('../server/db.mjs'); + const { default: Database } = await import('better-sqlite3'); + const fixtureData = fixture(); + let at = '2026-10-08T00:00:00.000Z'; + const store = openStore({ dbPath: fixtureData.dbPath, now: () => new Date(at) }); + t.after(() => { store.close(); rmSync(fixtureData.root, { recursive: true, force: true }); }); + store.recordVisit(VISITOR); store.recordArrival(DOG); + at = '2026-10-09T00:00:00.000Z'; + store.recordVisit(VISITOR); store.recordArrival(DOG); + return { ...fixtureData, store, openStore, migrateDatabase, Database }; +} +function snapshot(Database, path) { + const db = new Database(path, { readonly: true, fileMustExist: true }); + try { + assert.equal(db.pragma('integrity_check', { simple: true }), 'ok'); + return { visits: db.prepare('SELECT * FROM visitors_daily ORDER BY visitor_id,visit_date').all(), arrivals: db.prepare('SELECT * FROM arrivals ORDER BY dog_id').all(), version: db.pragma('user_version', { simple: true }) }; + } finally { db.close(); } +} + +test('operational CLI entrypoints exist without starting an HTTP listener', () => { + for (const script of ['metrics', 'backup']) assert.ok(existsSync(resolve(`server/${script}.mjs`)), `missing ${script} CLI`); +}); + +test('metrics prints aggregate-only JSON from an existing read-only database', async t => { + const { store, dbPath } = await setup(t); + const output = cli('metrics', ['--month', '2026-10'], dbPath); + assert.equal(output.status, 0, output.stderr); + assert.deepEqual(JSON.parse(output.stdout), { month: '2026-10', monthlyVisitors: 1, arrivals: 1 }); + assert.equal(output.stderr, ''); + assert.doesNotMatch(output.stdout, /12345678|bbbbbbbbbb|visitor_id|dog_id/); + assert.equal(store.arrivalCount(), 1); +}); + +test('metrics invalid arguments, missing path and bad schema fail without creating/migrating a DB', async t => { + const { dbPath, root, Database } = await setup(t); + for (const args of [[], ['--month', '2026-13'], ['--month', '0000-01'], ['--month', '2026-1'], ['--month', '2026-10', '--extra'], ['--month', '2026-10', '--month', '2026-11']]) { + const output = cli('metrics', args, dbPath); + assert.notEqual(output.status, 0); + assert.equal(output.stdout, ''); + assert.doesNotMatch(output.stderr, /12345678|bbbbbbbbbb|arrival-ops-|SELECT|SQLITE/); + } + const missing = join(root, 'typo', 'missing.sqlite'); + assert.notEqual(cli('metrics', ['--month', '2026-10'], missing).status, 0); + assert.equal(existsSync(missing), false); + assert.equal(existsSync(join(root, 'typo')), false); + const malformed = join(root, 'bad.sqlite'); + const db = new Database(malformed); db.exec('CREATE TABLE wrong(value TEXT)'); db.close(); + assert.notEqual(cli('metrics', ['--month', '2026-10'], malformed).status, 0); + const verify = new Database(malformed); + assert.equal(verify.pragma('user_version', { simple: true }), 0); verify.close(); +}); + +test('live SQLite backup restores both tables, first timestamps and metrics; restored writes work', async t => { + const { dbPath, root, store, openStore, Database } = await setup(t); + const backupPath = join(root, 'backups', 'snapshot.sqlite'); + const before = snapshot(Database, dbPath); + assert.ok(existsSync(`${dbPath}-wal`)); + const output = cli('backup', ['--output', backupPath], dbPath); + assert.equal(output.status, 0, output.stderr); + assert.doesNotMatch(output.stdout + output.stderr, /12345678|bbbbbbbbbb|visitor_id|dog_id/); + assert.deepEqual(snapshot(Database, backupPath), before); + if (process.platform !== 'win32') assert.equal(statSync(backupPath).mode & 0o077, 0); + store.recordArrival('c'.repeat(64)); + assert.equal(store.arrivalCount(), 2); + assert.equal(snapshot(Database, backupPath).arrivals.length, 1); + store.close(); + const restorePath = join(root, 'restore', 'counts.sqlite'); + mkdirSync(join(root, 'restore'), { mode: 0o700 }); + copyFileSync(backupPath, restorePath); + assert.deepEqual(snapshot(Database, restorePath), before); + assert.deepEqual(JSON.parse(cli('metrics', ['--month', '2026-10'], restorePath).stdout), { month: '2026-10', monthlyVisitors: 1, arrivals: 1 }); + const restored = openStore({ dbPath: restorePath }); + restored.recordArrival('d'.repeat(64)); + assert.equal(restored.arrivalCount(), 2); + restored.close(); + assert.equal(snapshot(Database, restorePath).arrivals.length, 2); +}); + +test('backup rejects overwrite, same source, invalid args, missing DB and destination failure', async t => { + const { dbPath, root, store } = await setup(t); + const existing = join(root, 'already.sqlite'); + writeFileSync(existing, 'do not overwrite'); + for (const args of [[], ['--output', dbPath], ['--output', existing], ['--output', 'relative.sqlite'], ['--output', join(root, 'new.sqlite'), '--extra']]) assert.notEqual(cli('backup', args, dbPath).status, 0); + assert.equal(readFileSync(existing, 'utf8'), 'do not overwrite'); + const missing = join(root, 'missing.sqlite'); + assert.notEqual(cli('backup', ['--output', join(root, 'out.sqlite')], missing).status, 0); + assert.equal(existsSync(missing), false); + await assert.rejects(store.backup(dbPath)); + await assert.rejects(store.backup(existing)); + const blockingFile = join(root, 'file'); writeFileSync(blockingFile, 'x'); + await assert.rejects(store.backup(join(blockingFile, 'out.sqlite'))); +}); + +test('failed versioned migration rolls back DDL and user_version without losing prior data', async t => { + const { root, migrateDatabase, Database } = await setup(t); + const path = join(root, 'rollback.sqlite'); + const db = new Database(path); + db.exec('CREATE TABLE retained (value TEXT); INSERT INTO retained VALUES (\'kept\'); PRAGMA user_version = 1'); + assert.throws(() => migrateDatabase(db, [{ version: 1, sql: '' }, { version: 2, sql: 'CREATE TABLE temporary_change(x TEXT); INVALID SQL STATEMENT;' }])); + assert.equal(db.pragma('user_version', { simple: true }), 1); + assert.equal(db.prepare('SELECT value FROM retained').get().value, 'kept'); + assert.equal(db.prepare("SELECT COUNT(*) AS n FROM sqlite_master WHERE name = 'temporary_change'").get().n, 0); + db.close(); +}); + +test('default and backend builds explicitly select analytics disabled/enabled', () => { + const pkg = JSON.parse(readFileSync(resolve('package.json'), 'utf8')); + assert.match(pkg.scripts.build, /VITE_ARRIVAL_ANALYTICS=false/); + assert.match(pkg.scripts['build:server'], /VITE_ARRIVAL_ANALYTICS=true/); +}); + +test('backup never overwrites through raw or symlink-resolved whitespace filenames', async t => { + const { dbPath, root, store, Database } = await setup(t); + const { symlinkSync } = await import('node:fs'); + const target = join(root, 'existing.sqlite'); + await store.backup(target); + store.recordArrival('e'.repeat(64)); + const before = snapshot(Database, target); + await assert.rejects(store.backup(`${target} `)); + assert.deepEqual(snapshot(Database, target), before); + assert.equal(existsSync(`${target} `), false); + const alias = join(root, 'aliased.sqlite'); + const spaced = join(root, 'canonical.sqlite '); + writeFileSync(spaced, 'untouched'); + symlinkSync(spaced, alias); + await assert.rejects(store.backup(alias)); + assert.equal(readFileSync(spaced, 'utf8'), 'untouched'); + assert.notEqual(cli('backup', ['--output', `${target}\t`], dbPath).status, 0); +}); diff --git a/scripts/test-blender-window-frame.mjs b/scripts/test-blender-window-frame.mjs new file mode 100644 index 0000000..cec9e94 --- /dev/null +++ b/scripts/test-blender-window-frame.mjs @@ -0,0 +1,61 @@ +import assert from 'node:assert/strict'; +import {test} from 'node:test'; +import {existsSync,readFileSync} from 'node:fs'; +import vm from 'node:vm';import ts from 'typescript';import * as THREE from 'three'; +import {loadFrameGeometry} from './support/load-frame-geometry.mjs'; +function module(){const path=new URL('../src/objects/BlenderWindowFrame.ts',import.meta.url);assert.ok(existsSync(path),'original Blender frame adapter must exist');const exports={};vm.runInNewContext(ts.transpileModule(readFileSync(path,'utf8'),{compilerOptions:{module:ts.ModuleKind.CommonJS,target:ts.ScriptTarget.ES2022}}).outputText,{exports,require:name=>name==='three'?THREE:{GLTFLoader:class{}},AbortController,fetch:()=>{throw Error('tests must inject loader')}});return exports;} +function trianglesOutside(root,w,h){let count=0;root.traverse(o=>{if(!o.isMesh)return;const p=o.geometry.attributes.position,i=o.geometry.index;for(let k=0;kp.getX(j)),ys=ids.map(j=>p.getY(j)),eps=1e-6*Math.min(w,h);assert.ok(Math.max(...xs)<=-w/2+eps||Math.min(...xs)>=w/2-eps||Math.max(...ys)<=-h/2+eps||Math.min(...ys)>=h/2-eps,'triangle must not cover clear opening');count++;}});assert.equal(count,6988);} +test('actual Blender triangles resize without covering the aperture or distorting latch',()=>{ + const {prepareFrameAsset}=module(),root=loadFrameGeometry(); + const sourceLatch=root.getObjectByName('MovableSash_Brass');sourceLatch.geometry.computeBoundingBox();const originalLatchSize=sourceLatch.geometry.boundingBox.getSize(new THREE.Vector3()).toArray(); + const asset=prepareFrameAsset(root); + for(const [w,h] of [[1,1.32],[1,1],[3,1],[1,3],[.2,4],[4,.2]]){ + asset.resize(w,h,.6);trianglesOutside(root,w,h);assert.equal(root.position.z,.6); + const latch=root.getObjectByName('MovableSash_Brass'),size=new THREE.Vector3();latch.geometry.computeBoundingBox();latch.geometry.boundingBox.getSize(size);const s=Math.min(w,h); + originalLatchSize.forEach((v,i)=>assert.ok(Math.abs(size.getComponent(i)-v*s)<1e-6)); + const bounds=new THREE.Box3().setFromObject(root);assert.ok(Math.abs(bounds.min.x-(-w/2-.122*s))<1e-6);assert.ok(Math.abs(bounds.min.y-(-h/2-.1815*s))<1e-6); + } + const capture=()=>{const values=[];root.traverse(o=>{if(o.isMesh)values.push([...o.geometry.attributes.position.array],[...o.geometry.attributes.uv.array]);});return values;}; + asset.resize(1,1.32,.6);const before=capture();asset.resize(3,1,.6);asset.resize(1,1.32,.6);assert.deepEqual(capture(),before,'resizing never accumulates deformation'); + asset.dispose(); +}); +test('asset uses length-compensated grain UVs and mirror-corrected normal map',()=>{ + const {prepareFrameAsset,configureWoodMaterial}=module(),root=loadFrameGeometry(),asset=prepareFrameAsset(root); + const wood=root.getObjectByName('FixedSurround_Wood'),uv=wood.geometry.attributes.uv; + asset.resize(1,1.32,0);const canonical=[...uv.array];asset.resize(3,1,0);let changed=0; + for(let i=0;i1e-5)changed++;}assert.ok(changed>0); + const material=new THREE.MeshStandardMaterial({map:new THREE.Texture(),normalMap:new THREE.Texture(),roughnessMap:new THREE.Texture()});configureWoodMaterial(material); + for(const texture of [material.map,material.normalMap,material.roughnessMap]){assert.equal(texture.wrapS,THREE.ClampToEdgeWrapping);assert.equal(texture.wrapT,THREE.MirroredRepeatWrapping);} + const shader={fragmentShader:'#include '};material.onBeforeCompile(shader,{});assert.match(shader.fragmentShader,/mapN\.y.*floor\(\s*vNormalMapUv\.y/);asset.dispose(); +}); +test('frame loading failure retains fallback, retry uses latest aspect/theme, and teardown rejects stale loads',async()=>{ + const {BlenderWindowFrame}=module(),scene=new THREE.Scene(),changes=[],pending=[]; + const frame=new BlenderWindowFrame(scene,(active,state)=>changes.push({active,state}),()=>new Promise((resolve,reject)=>pending.push({resolve,reject}))); + frame.resize(2,1,.6);frame.apply('wood');const first=frame.load();pending.shift().reject(Error('offline'));await first;assert.equal(changes.at(-1).active,false);assert.equal(changes.at(-1).state,'error'); + const retry=frame.load();frame.resize(1,3,.6);frame.apply('booth');pending.shift().resolve(loadFrameGeometry());await retry;assert.equal(changes.at(-1).active,false);frame.apply('wood');assert.equal(changes.at(-1).active,true);const asset=scene.children.find(x=>x.name==='blender-window-frame');assert.ok(asset.visible);trianglesOutside(asset,1,3);frame.dispose();assert.equal(scene.children.length,0); + const next=new BlenderWindowFrame(scene,()=>{},()=>new Promise(resolve=>pending.push({resolve})));const load=next.load();next.dispose();const stale=loadFrameGeometry();let disposed=0;stale.traverse(o=>{if(o.isMesh)o.geometry.addEventListener('dispose',()=>disposed++);});pending.shift().resolve(stale);await load;assert.equal(disposed,4);assert.equal(scene.children.length,0); +}); +test('neutral camera contains the actual imported surround on phone, tablet and desktop',()=>{ + const {prepareFrameAsset,fitWindowScale}=module(),root=loadFrameGeometry(),asset=prepareFrameAsset(root); + for(const [w,h] of [[375,812],[768,1024],[1440,900]])for(const aspect of [.25,1,4]){ + const camera=new THREE.PerspectiveCamera(40,w/h,.1,100);camera.position.z=3;camera.updateMatrixWorld(); + const scale=fitWindowScale(w/h,aspect);asset.resize(scale*aspect*.8,scale*.8,.6); + root.traverse(object=>{if(!object.isMesh)return;const p=object.geometry.attributes.position;for(let i=0;i{ + const {prepareFrameAsset,BlenderWindowFrame}=module(),root=loadFrameGeometry(),asset=prepareFrameAsset(root); + asset.resize(2,1,.6);asset.setOpen(.5);root.updateMatrixWorld(true); + assert.equal(root.getObjectByName('MovableSash').position.x,-1); + assert.equal(root.getObjectByName('FixedSurround').position.x,0); + const fixed=root.getObjectByName('FixedSurround_Wood'),sash=root.getObjectByName('MovableSash_Wood'); + assert.equal(fixed.material.clippingPlanes,null);assert.equal(sash.material.clippingPlanes[0].constant,1.05); + const handle=asset.handlePosition(new THREE.Vector3());assert.ok(Math.abs(handle.x-.026)<1e-8); + asset.resize(1,2,.6);assert.equal(root.getObjectByName('MovableSash').position.x,-.5); + asset.setOpen(4);assert.equal(root.getObjectByName('MovableSash').position.x,-1);asset.setOpen(-1);assert.equal(root.getObjectByName('MovableSash').position.x,0);asset.dispose(); + const scene=new THREE.Scene();let resolve;const frame=new BlenderWindowFrame(scene,()=>{},()=>new Promise(r=>resolve=r)); + frame.resize(2,1,.6);frame.setOpen(.4);const loaded=frame.load();resolve(loadFrameGeometry());await loaded; + assert.equal(scene.children[0].getObjectByName('MovableSash').position.x,-.8);frame.dispose(); +}); diff --git a/scripts/test-camera-composition.mjs b/scripts/test-camera-composition.mjs new file mode 100644 index 0000000..1d780d2 --- /dev/null +++ b/scripts/test-camera-composition.mjs @@ -0,0 +1,47 @@ +import assert from 'node:assert/strict'; +import {test} from 'node:test'; +import * as THREE from 'three'; +import {loadTypescript} from './support/load-typescript.mjs'; +const {CameraController}=await loadTypescript(new URL('../src/input/CameraController.ts',import.meta.url)); +const {readCameraComposition,saveCameraComposition}=await loadTypescript(new URL('../src/input/CameraComposition.ts',import.meta.url)); +test('wall experiment defaults locally, persists rollback and tolerates unavailable storage',()=>{ + const items=new Map(),storage={getItem:k=>items.get(k),setItem:(k,v)=>items.set(k,v)}; + assert.equal(readCameraComposition(storage),'wall');saveCameraComposition(storage,'legacy');assert.equal(readCameraComposition(storage),'legacy');saveCameraComposition(storage,'wall');assert.equal(readCameraComposition(storage),'wall'); + assert.equal(readCameraComposition({getItem(){throw Error('blocked');}}),'wall');assert.equal(saveCameraComposition({setItem(){throw Error('blocked');}},'legacy'),false); +}); +test('composition switch preserves input and projection state, exact rollback and neutral',()=>{ + const camera=new THREE.PerspectiveCamera(40,.46,.1,100),control=new CameraController(camera); + control.setRoomBounds(.76,.95,.6);control.setView(1,.25);control.update(10,1);camera.updateMatrixWorld(true);const legacy={position:camera.position.toArray(),quaternion:camera.quaternion.toArray(),fov:camera.fov}; + control.setCompositionMode('wall');control.update(10,1);assert.ok(camera.fov>40&&camera.fov<=65);assert.deepEqual(control.target.toArray(),[1,.25]);assert.deepEqual(control.current.toArray(),[1,.25]);assert.ok(camera.position.z{ + const poses=[]; + for(const aspect of [1,1.5,2.164])for(const side of [-1,1]){ + const c=new THREE.PerspectiveCamera(40,aspect,.1,100),ctrl=new CameraController(c);ctrl.setRoomBounds(.76096,.9512,.6);ctrl.setCompositionMode('wall');ctrl.setView(side,0);ctrl.update(10,1); + const half=.76096/2+.95*.76096,unit=half/1.45; + assert.ok(Math.abs(c.position.x-side*.65*half)<1e-10);assert.ok(Math.abs(c.position.z-(.6+.6*unit))<1e-10);assert.equal(c.fov,40); + const dir=c.getWorldDirection(new THREE.Vector3());assert.ok(Math.abs(Math.atan2(-dir.z,Math.abs(dir.x))*180/Math.PI-25)<1e-9);poses.push({side,p:c.position.toArray(),q:c.quaternion.toArray()}); + } + for(let i=2;i{ + const {loadFrameGeometry}=await import('./support/load-frame-geometry.mjs'); + const {prepareHouseAsset}=await loadTypescript(new URL('../src/objects/BlenderHouseSurround.ts',import.meta.url)); + const root=loadFrameGeometry(new URL('../public/assets/window/grandma-house-surround.glb',import.meta.url)),house=prepareHouseAsset(root); + const snapshot=()=>{const rows=[];root.traverse(o=>{if(o.isMesh)rows.push([o.name,...o.geometry.attributes.position.array]);});return rows;}; + house.resize(.76,.95,.6);const before=snapshot();house.resize(.76,.95,.6,.76,true);assert.notDeepEqual(snapshot(),before);house.resize(.76,.95,.6,.76,false);assert.deepEqual(snapshot(),before);house.dispose(); +}); +test('real startup wiring restores saved legacy mode and switches both camera and physical room',async()=>{ + const {readFile}=await import('node:fs/promises'),{default:ts}=await import('typescript'),{runInNewContext}=await import('node:vm'); + const main=await readFile(new URL('../src/main.ts',import.meta.url),'utf8'); + const code=main.slice(main.indexOf('let cameraCompositionStorage'),main.indexOf('const sceneZoom =')); + const elements=new Map(),callbacks=new Map();for(const id of ['#camera-composition','#camera-composition-note'])elements.set(id,{value:'',textContent:'',addEventListener:(_type,fn)=>callbacks.set(id,fn)}); + const items=new Map([['behind-glass-camera-composition-v32','legacy']]),camera=new THREE.PerspectiveCamera(40,.46,.1,100),cameraController=new CameraController(camera);cameraController.setRoomBounds(.76,.95,.6);cameraController.setView(1,0);cameraController.update(10,1);const legacy=camera.position.toArray(); + let roomMode,invalidations=0; + runInNewContext(ts.transpileModule(code,{compilerOptions:{target:ts.ScriptTarget.ES2022}}).outputText,{window:{localStorage:{getItem:key=>items.get(key),setItem:(key,value)=>items.set(key,value)}},readCameraComposition,saveCameraComposition,camera,cameraController,houseSurround:{setCompositionMode:mode=>roomMode=mode},document:{querySelector:id=>elements.get(id)},listenerAbort:new AbortController(),sensitivity:1,renderDemand:{invalidate(){invalidations++;}}}); + assert.equal(elements.get('#camera-composition').value,'legacy');assert.equal(roomMode,'legacy');cameraController.update(10,1);assert.deepEqual(camera.position.toArray(),legacy); + elements.get('#camera-composition').value='wall';callbacks.get('#camera-composition')();assert.equal(roomMode,'wall');assert.equal(items.get('behind-glass-camera-composition-v32'),'wall');assert.ok(camera.fov>40&&camera.fov<=65); + elements.get('#camera-composition').value='legacy';callbacks.get('#camera-composition')();assert.equal(roomMode,'legacy');assert.deepEqual(camera.position.toArray(),legacy);assert.equal(invalidations,2); +}); diff --git a/scripts/test-camera-envelope.mjs b/scripts/test-camera-envelope.mjs new file mode 100644 index 0000000..9da4c29 --- /dev/null +++ b/scripts/test-camera-envelope.mjs @@ -0,0 +1,62 @@ +import assert from 'node:assert/strict'; +import { test } from 'node:test'; +import * as THREE from 'three'; +import { loadTypescript } from './support/load-typescript.mjs'; +import { loadFrameGeometry } from './support/load-frame-geometry.mjs'; + +const { CameraController } = await loadTypescript(new URL('../src/input/CameraController.ts', import.meta.url)); +const { SceneZoomController } = await loadTypescript(new URL('../src/input/SceneZoomController.ts', import.meta.url)); +const { prepareHouseAsset, houseViewScale } = await loadTypescript(new URL('../src/objects/BlenderHouseSurround.ts', import.meta.url)); +const { prepareFrameAsset, fitWindowScale } = await loadTypescript(new URL('../src/objects/BlenderWindowFrame.ts', import.meta.url)); + +test('gentler .75 default and selectable .90 maximum widen both axes without changing forward distance', () => { + const camera = new THREE.PerspectiveCamera(40, 1, .1, 100), controller = new CameraController(camera); + for (const x of [-1, 0, 1]) for (const y of [-1, 0, 1]) { + controller.setView(x, y); controller.update(10, 1); + assert.deepEqual(camera.position.toArray(), [x * .75, y * .75, 3]); + const direction = camera.getWorldDirection(new THREE.Vector3()); + assert.ok(direction.distanceTo(camera.position.clone().negate().normalize()) < 1e-12); + } + controller.setMaxOffset(5); controller.setView(-9, 9); controller.update(10, 2); + assert.deepEqual(camera.position.toArray(), [-.9, .9, 3], 'sensitivity and excess range cannot exceed the measured envelope'); +}); + +test('old range choices, recenter, pinch hold and anchored projection zoom remain independent', () => { + const camera = new THREE.PerspectiveCamera(40, 1, .1, 100), controller = new CameraController(camera), zoom = new SceneZoomController(camera); + zoom.setZoom(2.1, { x: .25, y: -.4 }); + const projection = camera.projectionMatrix.toArray(), offset = zoom.offset.toArray(); + for (const value of [.35, .5, .65, .8, .9]) { + controller.setMaxOffset(value); controller.setView(1, -1); controller.update(10, 2); + assert.deepEqual(camera.position.toArray(), [value, -value, 3]); + controller.reset(); controller.update(.016, 1); assert.deepEqual(camera.position.toArray(), [0, 0, 3]); + controller.setView(1, -1); controller.update(10, 2); + assert.equal(camera.position.x, value, 'recenter retains the chosen movement range'); + } + controller.setView(-1, 1); controller.update(1 / 60, 1); + controller.hold(); const held = camera.position.toArray(); controller.update(.1, 1); + assert.deepEqual(camera.position.toArray(), held); + assert.deepEqual(camera.projectionMatrix.toArray(), projection); assert.deepEqual(zoom.offset.toArray(), offset); + assert.equal(zoom.value, 2.1); assert.equal(camera.near, .1); assert.equal(camera.fov, 40); +}); + +test('room-relative default and maximum camera paths keep the eye and visible near rays outside the real geometry', () => { + const house=loadFrameGeometry(new URL('../public/assets/window/grandma-house-surround.glb',import.meta.url)),frame=loadFrameGeometry(); + const roomAsset=prepareHouseAsset(house),frameAsset=prepareFrameAsset(frame),group=new THREE.Group();group.add(house,frame); + let rays=0; + for(const[vw,vh]of[[375,812],[844,390],[1440,900]])for(const aspect of[.05,.2,.56,.8,1,1.77,5,20]){ + const fit=fitWindowScale(vw/vh,aspect)*houseViewScale('wood'),w=fit*aspect*.8,h=fit*.8,s=Math.min(w,h),floor=-h/2-.24*s; + roomAsset.resize(w,h,.6);frameAsset.resize(w,h,.6); + const camera=new THREE.PerspectiveCamera(40,vw/vh,.1,100),control=new CameraController(camera);control.setRoomBounds(w,h,.6); + for(const cap of[.75,.9])for(const open of[0,.5,1]){control.setMaxOffset(cap);frameAsset.setOpen(open);group.updateMatrixWorld(true); + for(const x of[-1,-.5,0,.5,1])for(const y of[-1,-.5,0,.5,1]){ + control.setView(x,y);control.update(10,1);camera.updateMatrixWorld(true);assert.ok(camera.position.y>floor); + for(const px of[-1,0,1])for(const py of[-1,0,1]){ + const corner=new THREE.Vector3(px,py,-1).unproject(camera);assert.ok(corner.y>floor-1e-8,'near corners stay above the floor'); + const ray=new THREE.Raycaster();ray.setFromCamera(new THREE.Vector2(px,py),camera);const hit=ray.intersectObject(group,true).find(h=>!(h.object.material.clippingPlanes??[]).some(p=>p.distanceToPoint(h.point)<0)); + if(hit){const depth=-hit.point.clone().applyMatrix4(camera.matrixWorldInverse).z;assert.ok(depth>=camera.near-1e-7,JSON.stringify({vw,vh,aspect,cap,open,x,y,px,py,depth,near:camera.near,position:camera.position.toArray(),hit:hit.object.name}));}rays++; + } + } + } + } + console.log('Room envelope visible-ray and floor checks:',rays);roomAsset.dispose();frameAsset.dispose(); +}); diff --git a/scripts/test-camera-history.mjs b/scripts/test-camera-history.mjs index 3a39bf5..772f77b 100644 --- a/scripts/test-camera-history.mjs +++ b/scripts/test-camera-history.mjs @@ -3,16 +3,16 @@ import { readFile } from 'node:fs/promises'; const controller = await readFile(new URL('../src/input/CameraController.ts', import.meta.url), 'utf8'); const html = await readFile(new URL('../index.html', import.meta.url), 'utf8'); -const main = await readFile(new URL('../src/main.ts', import.meta.url), 'utf8'); +const main = await readFile(new URL('../src/rendering/OriginalGlassRenderer.ts', import.meta.url), 'utf8'); const historyShader = await readFile(new URL('../src/shaders/region-history.frag', import.meta.url), 'utf8'); const mosaicShader = await readFile(new URL('../src/shaders/mosaic.frag', import.meta.url), 'utf8'); -assert.match(controller, /maxOffset = 0\.5/); -assert.match(controller, /clamp\(value, 0, 0\.9\)/); +assert.match(controller, /maxOffset = 0\.75/); +assert.match(controller, /clamp\(value, 0\.35, 0\.90\)/); assert.match(controller, /multiplyScalar\(sensitivity\)/); -assert.match(html, /id="camera-offset" type="range" min="0" max="0\.9" step="0\.01" value="0\.5"/); +assert.match(html, /id="camera-offset" type="range" min="0\.35" max="0\.90" step="0\.01" value="0\.75"/); assert.match(html, /id="sensitivity" type="range" min="0\.2" max="2"/); -assert.match(html, /Camera Offset 0\.50/); -assert.match(html, /권장 0\.35–0\.65 · 시점 이동 범위/); +assert.match(html, /움직임 범위 0\.75/); +assert.match(html, /움직임 범위[\s\S]*살짝[\s\S]*넓게/); assert.match(mosaicShader, /edgeTaper=style<=\.5\?1\.25:\.75/); assert.match(mosaicShader, /historyTexel=clamp\(floor\(fract\(gridUv\)\*8\.\),vec2\(0\.\),vec2\(7\.\)\)/); assert.equal(Math.floor(0.45 * 8), 3, 'split sample just left of the half-cell boundary stays in texel 3'); @@ -20,24 +20,26 @@ assert.equal(Math.floor(0.50 * 8), 4, 'split sample at the half-cell boundary en const clamp = (value, min, max) => Math.max(min, Math.min(max, value)); const cameraPosition = (target, sensitivity, maxOffset) => clamp(target * sensitivity, -1, 1) * maxOffset; -assert.equal(cameraPosition(1, 1, 0.5), 0.5, 'default offset reaches the configured midpoint'); -assert.equal(cameraPosition(1, 1, 0.9), 0.9, 'maximum offset reaches 0.9'); -assert.equal(cameraPosition(1, 2, 0.9), 0.9, 'sensitivity does not exceed the view clamp'); -assert.equal(clamp(1, 0, 0.9), 0.9, 'UI maximum matches controller clamp'); +assert.equal(cameraPosition(1, 1, 0.75), 0.75, 'default offset reaches the gentler 0.75'); +assert.equal(cameraPosition(1, 1, 0.90), 0.90, 'maximum offset reaches 0.90'); +assert.equal(cameraPosition(1, 2, 0.90), 0.90, 'sensitivity does not exceed the view clamp'); +assert.equal(clamp(1, 0.35, 0.90), 0.90, 'UI maximum matches controller clamp'); +assert.equal(clamp(0, 0.35, 0.90), 0.35, 'UI minimum matches controller clamp'); const signatureStart = main.indexOf('function currentSplitHistorySignature()'); const signatureEnd = main.indexOf('\nfunction clearSplitHistory()', signatureStart); assert.ok(signatureStart >= 0 && signatureEnd > signatureStart, 'history reset signature exists'); const signature = main.slice(signatureStart, signatureEnd); -for (const key of ['mode', 'effectInput.value', 'mosaicStyleInput.value', 'active.uuid', 'depth.uuid', 'uRegionAvailable', 'uGridSize', 'uStrength', 'uRegionStrength', 'uCurvature', 'uPaneSize', 'matrixWorld', 'uDepthScale', 'uDepthBias', 'renderTarget.width', 'regionAtlasTarget.width', 'regionPaletteTarget.width']) { +for (const key of ['mode', 'effect', 'style', 'active.uuid', 'depth.uuid', 'uRegionAvailable', 'uGridSize', 'uStrength', 'uRegionStrength', 'uCurvature', 'uPaneSize', 'matrixWorld', 'uDepthScale', 'uDepthBias', 'renderTarget.width', 'regionAtlasTarget.width', 'regionPaletteTarget.width']) { assert.ok(signature.includes(key), `model-reset signature includes ${key}`); } assert.doesNotMatch(signature, /uContentViewProjection|cameraController|uContentCameraPosition/, 'camera movement must not reset split history'); +assert.match(main, /function render\(dt: number, output: THREE\.WebGLRenderTarget \| null = null\)/, 'explicit A single view still defaults to the screen'); assert.match(main, /const writeIndex = 1 - splitHistoryRead/); assert.match(main, /uPreviousHistory\.value = splitHistoryTargets\[splitHistoryRead\]\.texture/); assert.match(main, /uHistoryBlend\.value = splitHistoryInitialized \? 1 - Math\.exp\(-dt \/ 0\.07\) : 1/); -assert.match(main, /updateSplitHistory\(dt\); renderer\.setRenderTarget\(null\); renderer\.render\(scene, camera\)/, 'inactive view updates the signature and clears stale history'); -assert.match(main, /splitHistoryTargets\.forEach\(\(target\) => target\.dispose\(\)\)/); +assert.match(main, /updateSplitHistory\(dt\); renderer\.setRenderTarget\(output\); renderer\.render\(scene, camera\)/, 'inactive view updates the signature and clears stale history'); +assert.match(main, /splitHistoryTargets\.forEach\(target=>target\.dispose\(\)\)/); assert.match(main, /target\.setSize\(atlasWidth, atlasHeight\)/); assert.match(historyShader, /if\(uHistoryBlend>=\.9999\)\{gl_FragColor=current;return;\}/, 'first frame avoids sampling uninitialized history'); assert.match(historyShader, /gl_FragColor=mix\(previous,current,clamp\(uHistoryBlend,0\.,1\.\)\)/); diff --git a/scripts/test-car-journey.mjs b/scripts/test-car-journey.mjs new file mode 100644 index 0000000..6d04495 --- /dev/null +++ b/scripts/test-car-journey.mjs @@ -0,0 +1,298 @@ +import assert from 'node:assert/strict'; +import { readFile } from 'node:fs/promises'; +import { test } from 'node:test'; +import { loadTypescript } from './support/load-typescript.mjs'; + +const html = await readFile(new URL('../index.html', import.meta.url), 'utf8'); +const source = await readFile(new URL('../src/ui/ExperienceUI.ts', import.meta.url), 'utf8'); +const exports = await loadTypescript(new URL('../src/ui/ExperienceUI.ts', import.meta.url)); +class Element { + dataset = {}; attributes = {}; listeners = new Map(); hidden = false; open = false; inert = false; value = ''; isConnected = true; + addEventListener(type, fn, { signal } = {}) { const list = this.listeners.get(type) ?? new Set(); list.add(fn); this.listeners.set(type, list); signal?.addEventListener('abort', () => list.delete(fn)); } + dispatch(type, extra = {}) { for (const fn of [...(this.listeners.get(type) ?? [])]) fn({ target: this, ...extra }); } + setAttribute(key, value) { this.attributes[key] = value; } + focus() { if (!this.inert) this.root.activeElement = this; } + showModal() { this.open = true; } + close() { this.open = false; this.dispatch('close'); } + getBoundingClientRect() { return { left: 0, top: 0, right: 400, bottom: 800 }; } +} +function harness(reduced = false) { + const root = new Element(), media = new Element(), timers = new Map(); let timerId = 0; + media.matches = reduced; + const els = Object.fromEntries([...html.matchAll(/\bid="([^"]+)"/g)].map(([, id]) => [id, new Element()])); + for (const element of Object.values(els)) element.root = root; + root.querySelectorAll = () => []; root.documentElement = new Element(); root.querySelector = selector => els[selector.slice(1)] ?? null; + root.defaultView = { localStorage: { getItem() { return null; }, setItem() {} }, matchMedia: () => media, + setTimeout(fn, ms) { timers.set(++timerId, { fn, ms }); return timerId; }, clearTimeout(id) { timers.delete(id); } }; + let reveals = 0; + const abort = new AbortController(), ui = exports.initExperienceUI(root, abort.signal, () => {}, () => { reveals += 1; }); + const tick = () => { const [id, timer] = timers.entries().next().value; timers.delete(id); timer.fn(); return timer.ms; }; + return { root, els, ui, media, timers, abort, tick, get reveals() { return reveals; } }; +} + +test('only an explicit real AI start drives the selected photo, without a completion timer', () => { + const h = harness(); + assert.equal(typeof h.ui.startJourney, 'function', 'AI work needs its own truthful journey start'); + h.ui.setPhoto('blob:user-photo'); h.ui.setState('loading'); + assert.notEqual(h.els['flow-overlay'].dataset.journey, 'driving', 'plain file loading is not AI travel'); + h.ui.startJourney(); h.ui.setDetail('CPU/WASM에서 입체감을 계산하고 있어요'); + assert.equal(h.els['flow-photo'].src, 'blob:user-photo'); + assert.equal(h.els['flow-overlay'].dataset.journey, 'driving'); + assert.equal(h.els['flow-overlay'].attributes['aria-busy'], 'true'); + assert.equal(h.ui.isBlocked(), true); assert.equal(h.timers.size, 0, 'slow inference must not arrive on a timer'); + assert.match(h.els['flow-detail'].textContent, /CPU\/WASM/); +}); +test('real success holds arrival for 1350ms, unpacks for 1500ms, then reveals the scene', () => { + const h = harness(); h.ui.setPhoto('blob:photo'); h.ui.startJourney(); h.ui.setState('ready'); + assert.equal(h.els.experience.dataset.flow, 'ready', 'inference has truthfully completed'); + assert.equal(h.ui.isBlocked(), true, 'scene input waits for the short presentation'); + assert.equal(h.els['canvas-wrap'].inert, true); + assert.equal(h.els['flow-overlay'].hidden, false); + assert.equal(h.els['flow-overlay'].dataset.journey, 'arrived'); + assert.equal(h.els['flow-overlay'].attributes['aria-busy'], 'false'); + assert.match(h.els['flow-title'].textContent, /할머니 집에 도착/); + assert.equal(h.els['flow-detail'].hidden, true, 'technical success text stays out of the arrival moment'); + assert.equal(h.els['flow-actions'].hidden, true); + h.els['flow-overlay'].dispatch('animationend', { animationName: 'journey-arrival-fade' }); + assert.equal(h.els['flow-overlay'].hidden, false, 'old animation events cannot skip the holds'); + assert.equal(h.tick(), 1350); + assert.equal(h.els['flow-overlay'].dataset.journey, 'unpacking'); + assert.equal(h.els['flow-title'].textContent, '짐을 푸는 중…'); + assert.equal(h.ui.isBlocked(), true); assert.equal(h.reveals, 0); + assert.equal(h.tick(), 1500); + assert.equal(h.els['flow-overlay'].hidden, true); assert.equal(h.timers.size, 0); + assert.equal(h.ui.isBlocked(), false); assert.equal(h.els['canvas-wrap'].inert, false); + assert.equal(h.root.activeElement, h.els['canvas-wrap']); assert.equal(h.reveals, 1); +}); +test('failure stops the trip and flat fallback cannot masquerade as arrival', () => { + const h = harness(); h.ui.setPhoto('blob:photo'); h.ui.startJourney(); h.ui.setState('error', true); + assert.equal(h.els['flow-overlay'].dataset.journey, 'idle'); assert.equal(h.els['flow-retry'].hidden, false); + assert.equal(h.els['flow-flat'].hidden, false); assert.doesNotMatch(h.els['flow-title'].textContent, /도착/); + assert.equal(h.timers.size, 0); h.ui.setState('ready'); assert.equal(h.els['flow-overlay'].hidden, true); +}); +test('motion pause and reduced motion never pause AI or fabricate progress', () => { + const h = harness(); h.ui.setPhoto('blob:photo'); h.ui.startJourney(); + assert.equal(h.els['flow-overlay'].dataset.motion, 'running'); + assert.equal(h.els.experience.dataset.flow, 'loading'); assert.equal(h.els['flow-overlay'].attributes['aria-busy'], 'true'); + + h.media.matches = true; h.media.dispatch('change'); assert.equal(h.els['flow-overlay'].dataset.motion, 'paused'); + h.ui.setState('ready'); assert.equal(h.els['flow-overlay'].hidden, true); + assert.equal(h.timers.size, 0); assert.equal(h.ui.isBlocked(), false); + assert.equal(h.root.activeElement, h.els['canvas-wrap'], 'reduced-motion reveal focuses the now-interactive scene'); + const reduced = harness(true); reduced.ui.setPhoto('blob:photo'); reduced.ui.startJourney(); + assert.equal(reduced.els['flow-overlay'].dataset.motion, 'paused'); +}); +test('replacement and retry cancel old arrival cleanup without hiding the newer operation', () => { + const h = harness(); h.ui.setPhoto('blob:first'); h.ui.startJourney(); h.ui.setState('ready'); + const oldCleanup = [...h.timers.values()][0].fn; + h.ui.setPhoto(''); h.ui.setState('loading'); h.ui.setPhoto('blob:second'); h.ui.startJourney(); oldCleanup(); + assert.equal(h.els['flow-photo'].src, 'blob:second'); assert.equal(h.els['flow-overlay'].hidden, false); + assert.equal(h.els['flow-overlay'].dataset.journey, 'driving'); assert.equal(h.els.experience.dataset.flow, 'loading'); + h.ui.setState('error', true); h.ui.startJourney(); assert.equal(h.els['flow-overlay'].dataset.journey, 'driving'); +}); +test('render loss blocks input and stops travel/arrival; teardown removes all pending animation work', () => { + const h = harness(); h.ui.setPhoto('blob:photo'); h.ui.startJourney(); h.ui.setRenderLost(true); + assert.equal(h.ui.isBlocked(), true); assert.notEqual(h.els['flow-overlay'].dataset.journey, 'driving'); + h.ui.setState('ready'); assert.equal(h.els['flow-overlay'].hidden, true); assert.equal(h.ui.isBlocked(), true); + h.ui.setRenderLost(false); assert.equal(h.ui.isBlocked(), false); + h.ui.startJourney(); h.ui.setState('ready'); assert.equal(h.timers.size, 1); h.abort.abort(); + assert.equal(h.timers.size, 0); h.media.matches=true;h.media.dispatch('change'); + assert.notEqual(h.els['flow-overlay'].dataset.journey, 'driving'); +}); +test('both arrival stages cancel safely on replacement, recovery, reduced motion and disposal', () => { + for (const stage of ['arrived', 'unpacking']) { + for (const reason of ['photo', 'loading', 'error', 'render-loss', 'reduced-motion', 'dispose']) { + const h = harness(); h.ui.setPhoto('blob:photo'); h.ui.startJourney(); h.ui.setState('ready'); + if (stage === 'unpacking') h.tick(); + const stale = [...h.timers.values()][0].fn; + if (reason === 'photo') h.ui.setPhoto('blob:replacement'); + if (reason === 'loading') h.ui.startJourney(); + if (reason === 'error') h.ui.setState('error', true); + if (reason === 'render-loss') h.ui.setRenderLost(true); + if (reason === 'reduced-motion') { h.media.matches = true; h.media.dispatch('change'); } + if (reason === 'dispose') h.abort.abort(); + const title = h.els['flow-title'].textContent, hidden = h.els['flow-overlay'].hidden; + stale(); + assert.equal(h.timers.size, 0, `${stage}/${reason} leaves no pending timer`); + assert.equal(h.els['flow-title'].textContent, title, `${stage}/${reason} ignores stale callback`); + assert.equal(h.els['flow-overlay'].hidden, hidden); + if (reason === 'photo' || reason === 'reduced-motion') { + assert.equal(hidden, true); assert.equal(h.ui.isBlocked(), false); + } + } + } +}); +test('opening settings dismisses the arrival without stealing dialog focus later', () => { + const h = harness(); h.ui.setPhoto('blob:photo'); h.ui.startJourney(); h.ui.setState('ready'); h.tick(); + const stale = [...h.timers.values()][0].fn; + h.els['settings-open'].dispatch('click'); + assert.equal(h.els['flow-overlay'].hidden, true); assert.equal(h.timers.size, 0); + assert.equal(h.root.activeElement, h.els['settings-close']); stale(); + assert.equal(h.root.activeElement, h.els['settings-close']); assert.equal(h.ui.isBlocked(), true); +}); +test('the illustration is original inline SVG with contained photo and no scrolling or progress meter', async () => { + const css = await readFile(new URL('../src/style.css', import.meta.url), 'utf8'); + assert.match(html, /id="journey"/); assert.match(html, /class="journey-car"/); assert.match(html, /class="journey-house"/); + assert.doesNotMatch(html, /id="journey-motion"/); + assert.doesNotMatch(html, /arrival-scroll|scroll-story| { + const css = await readFile(new URL('../src/style.css', import.meta.url), 'utf8'); + assert.match(css, /width:min\(var\(--journey-car-width\),\s*calc\(\(var\(--journey-height\)\s*-\s*38px\)\s*\*\s*5\s*\/\s*3\)\)/, + 'car width must also be bounded by available illustration height, not only viewport width'); + for (const [viewportWidth, viewportHeight] of [[1280,450],[500,400],[1024,600],[900,431],[375,667],[320,568],[1440,900]]) { + const compact = viewportHeight <= 650; + const illustrationHeight = compact ? Math.max(100, Math.min(.27 * viewportHeight, 160)) : Math.max(144, Math.min(.3 * viewportHeight, 236)); + const illustrationWidth = Math.min(compact ? 380 : 460, viewportWidth * (compact ? .8 : .88)); + const carWidth = Math.min(illustrationWidth * (compact ? .54 : .58), (illustrationHeight - 38) * 5 / 3, 267); + // Same box geometry as CSS; reserve 8px for the photo rotation and gentle bob. + assert.ok(illustrationHeight - 24 - carWidth * 3 / 5 - 8 >= 0, `${viewportWidth}×${viewportHeight} leaves the photo unclipped`); + } +}); + + +test('unpacking hops the contained original photo before walking and fades only in the final 200ms', async () => { + const css = await readFile(new URL('../src/style.css', import.meta.url), 'utf8'); + assert.match(html, /class="journey-traveler"/); + assert.match(css, /data-journey=unpacking\] \.journey-traveler[^}]*animation:journey-walk 1\.3s/); + assert.match(css, /data-journey=unpacking\] \.journey-passenger[^}]*animation:journey-waddle 1\.3s/); + assert.match(css, /data-journey=unpacking\] \{ animation:journey-arrival-fade \.2s ease-in 1\.3s both/); + assert.match(css, /@keyframes journey-walk\s*\{\s*0%,28%\s*\{ left:16%; transform:translateX\(-10%\); \}/); + assert.match(css, /@keyframes journey-waddle[^@]*28%\s*\{ top:35%;/); + assert.match(css, /@keyframes journey-waddle[^@]*100%\s*\{ top:35%;/); + assert.match(css, /@keyframes journey-waddle[^@]*rotate\(5deg\)/); + assert.ok(css.indexOf('#flow-overlay[data-motion=paused] .journey *') > css.indexOf('animation:journey-waddle'), 'manual pause wins over animation shorthand reset'); + const h = harness(); h.ui.setPhoto('blob:original-photo'); h.ui.startJourney(); + h.ui.setState('ready'); h.tick(); + assert.equal(h.els['flow-photo'].src, 'blob:original-photo'); + assert.equal(h.els['flow-overlay'].dataset.motion, 'running'); + assert.equal(h.tick(), 1500, 'walking completes on the existing reveal timer'); + assert.equal(h.ui.isBlocked(), false); +}); + + +test('walking photo stays inside responsive journey bounds through its full route', () => { + for (const [w, h] of [[460,236],[380,160],[256,153.36],[300,100],[170,170],[180,100]]) { + const c=Math.min(w*(h<=160?.54:.58),(h-38)*5/3,267); + for(let i=0;i<=100;i++) { + const t=i/100; const walk=Math.max(0,(t-.28)/.72); const drop=Math.min(t/.24,1); + const left=(.16+.715*walk)*w+(-.1-.29*walk)*c+.22*c; + // Conservative rotated card envelope, including the 3px upward footstep. + const rotationAllowance=Math.sin(5*Math.PI/180)*.65*.6*c; + assert.ok(left-rotationAllowance>=0); + assert.ok(left+.34*c+rotationAllowance<=w); + const top=h-24-.6*c+.35*.6*c*drop; + assert.ok(top-3-rotationAllowance>=0); + assert.ok(top+.65*.6*c+rotationAllowance<=h); + } + } +}); + +// Parse production keyframes so changing the CSS trajectory breaks these checks. +async function hopFrames() { + const css = await readFile(new URL('../src/style.css', import.meta.url), 'utf8'); + const block = css.match(/@keyframes journey-waddle \{([\s\S]*?)\n\}/)[1]; + return [...block.matchAll(/(\d+)%\s*\{([^}]+)\}/g)].map(([, percent, body]) => ({ + time: +percent, top: +body.match(/top:([\d.]+)/)[1], + y: +body.match(/translateY\((-?[\d.]+)(?:px)?\)/)[1], body, + })); +} +test('photo rises before descending, softens its landing, and settles before X travel', async () => { + const frames = await hopFrames(); + const lift = frames.find(f => f.y < 0 && f.top === 0); + assert.ok(lift, 'photo needs an upward takeoff before the descent'); + const landing = frames.find(f => f.top === 35); + const settled = frames.find(f => f.time > landing.time && f.y === 0 && /scaleY\(1\)/.test(f.body)); + assert.ok(lift.time < landing.time && landing.time < settled.time); + assert.match(landing.body, /scaleY\(\.97\)/, 'small foot-pivot landing compression'); + assert.match(lift.body, /animation-timing-function:cubic-bezier\(\.4,0,\.65,1\)/, 'descent eases to a soft zero-speed landing'); + assert.equal(settled.time, 28, 'X hold ends only after the landing settles'); + assert.ok(frames.filter(f => f.time >= settled.time).every(f => f.top === 35), 'walking stays at ground baseline'); +}); +test('production hop keyframes fit short and narrow illustrations including takeoff headroom', async () => { + const frames = await hopFrames(); + for (const [w,h,ratio] of [[460,236,.58],[380,160,.54],[256,153.36,.54],[300,100,.54],[170,170,.54],[180,100,.54]]) { + const c = Math.min(w*ratio,(h-38)*5/3,267); + for (const f of frames) { + const walk = Math.max(0,(f.time-28)/72); + const x = (.16+.715*walk)*w+(-.1-.29*walk)*c+.22*c; + const rotation = Math.sin(5*Math.PI/180)*.65*.6*c; + const top = h-24-.6*c+f.top/100*.6*c+f.y; + assert.ok(top-rotation>=0, `${w}x${h} at ${f.time}% retains takeoff headroom`); + assert.ok(top+.65*.6*c+rotation<=h); + assert.ok(x-rotation>=0 && x+.34*c+rotation<=w); + } + } +}); + +test('editing the global name changes copy without restarting loading, arrival or unpacking timers', () => { + const h = harness(); + const edit = name => { h.els['entry-pet-name'].value = name; h.els['entry-pet-name'].dispatch('input'); }; + edit('호롱'); h.ui.setPhoto('blob:photo'); h.ui.startJourney(); + assert.equal(h.els['flow-title'].textContent, '호롱이를 할머니 집으로 데려가는 중…'); + assert.equal(h.timers.size, 0); + h.ui.setState('ready'); const arrivalTimer = [...h.timers.entries()][0]; + edit('초코'); assert.equal(h.els['flow-title'].textContent, '초코가 할머니 집에 도착했어요'); + assert.deepEqual([...h.timers.entries()][0], arrivalTimer, 'name edits preserve the exact arrival timer'); + assert.equal(h.tick(), 1350); const unpackTimer = [...h.timers.entries()][0]; + edit('보리'); assert.equal(h.els['flow-title'].textContent, '짐을 푸는 중…'); + assert.deepEqual([...h.timers.entries()][0], unpackTimer, 'name edits preserve the exact unpacking timer'); + assert.equal(h.tick(), 1500); assert.equal(h.reveals, 1); assert.equal(h.ui.isBlocked(), false); +}); +test('sample copy uses its nickname across both themes and never changes the stored name', () => { + for (const theme of ['wood', 'booth']) { + const h = harness(); h.els['entry-pet-name'].value = '호롱'; h.els['entry-pet-name'].dispatch('input'); + h.els['theme-select'].value = theme; h.els['theme-select'].dispatch('change'); + h.ui.setMediaOrigin('sample'); h.ui.setPhoto('blob:sample'); h.ui.startJourney(); + assert.match(h.els['flow-title'].textContent, /누렁이/); assert.doesNotMatch(h.els['flow-title'].textContent, /호롱/); + h.ui.setState('ready'); assert.match(h.els['flow-title'].textContent, /누렁이/); + assert.equal(h.els['settings-pet-name'].value, '호롱'); + h.ui.setMediaOrigin('personal'); h.ui.setPhoto('blob:own'); h.ui.startJourney(); + assert.match(h.els['flow-title'].textContent, /호롱이/); + } +}); + +test('sample return cancels arrival timers and keeps landing focus even after stale callbacks', () => { + const h = harness(); h.ui.setMediaOrigin('sample'); h.ui.setPhoto('blob:sample'); + h.ui.startJourney(); h.ui.setState('ready'); + const stale = [...h.timers.values()][0].fn; + h.els['sample-home'].dispatch('click');h.els['home-confirm'].dispatch('click'); + assert.equal(h.timers.size, 0); + stale(); + assert.equal(h.timers.size, 0); + assert.equal(h.els.experience.dataset.flow, 'entry'); + assert.equal(h.els['flow-overlay'].hidden, true); + assert.equal(h.els['canvas-wrap'].inert, true); + assert.equal(h.root.activeElement, h.els['entry-photo-button']); + assert.equal(h.reveals, 0); +}); + +test('sample return during unpacking cancels reveal and preserves the selected name', () => { + const h = harness(); h.els['entry-pet-name'].value='장준'; h.els['entry-pet-name'].dispatch('input'); + h.ui.setMediaOrigin('sample'); h.ui.setPhoto('blob:sample'); h.ui.startJourney(); h.ui.setState('ready'); h.tick(); + const stale = [...h.timers.values()][0].fn; + h.els['sample-home'].dispatch('click');h.els['home-confirm'].dispatch('click'); stale(); + assert.equal(h.els.experience.dataset.flow, 'entry'); + assert.equal(h.els['flow-overlay'].hidden, true); + assert.equal(h.els['entry-pet-name'].value, '장준'); + assert.equal(h.els['entry-photo-button'].textContent, '장준이 사진 고르기'); + assert.equal(h.timers.size, 0); assert.equal(h.reveals, 0); +}); + +test('personal and sample journeys share identical loading and arrival templates', () => { + for (const theme of ['wood','booth']) { + const h=harness();h.els['entry-pet-name'].value='누렁이';h.els['entry-pet-name'].dispatch('input');h.els['theme-select'].value=theme;h.els['theme-select'].dispatch('change'); + h.ui.setMediaOrigin('personal');h.ui.setPhoto('blob:own');h.ui.startJourney();const loading=h.els['flow-title'].textContent;h.ui.setState('ready');const arrived=h.els['flow-title'].textContent; + h.ui.setMediaOrigin('sample');h.ui.setSampleName('누렁이');h.ui.setPhoto('blob:sample');h.ui.startJourney();assert.equal(h.els['flow-title'].textContent,loading);h.ui.setState('ready');assert.equal(h.els['flow-title'].textContent,arrived); + } +}); + +test('menu interrupts arrival without consuming first tutorial or leaving timers alive',()=>{ + const h=harness();h.ui.setPhoto('blob:dog');h.ui.startJourney();h.ui.setState('ready'); + assert.ok(h.timers.size>0);h.els['scene-menu-open'].dispatch('click'); + assert.equal(h.els['scene-menu'].open,true);assert.equal(h.timers.size,0);assert.equal(h.reveals,0); + h.els['scene-menu-close'].dispatch('click');assert.equal(h.ui.isBlocked(),false); +}); diff --git a/scripts/test-cutout-mask.mjs b/scripts/test-cutout-mask.mjs new file mode 100644 index 0000000..172bd45 --- /dev/null +++ b/scripts/test-cutout-mask.mjs @@ -0,0 +1,8 @@ +import assert from 'node:assert/strict'; +import {test} from 'node:test'; +import {loadTypescript} from './support/load-typescript.mjs'; +const load=()=>loadTypescript(new URL('../src/cutout/CutoutMask.ts',import.meta.url)); +test('cutout bounds retain all components, padded edges, and unchanged soft alpha',async()=>{const {analyzeCutout}=await load();const mask=new Uint8Array(100*80);mask[0]=255;mask[7999]=255;mask[1]=12;const original=mask.slice();const result=analyzeCutout(mask,100,80);assert.deepEqual(result.bounds,{x0:0,y0:0,x1:100,y1:80});assert.deepEqual(mask,original);assert.equal(result.largeComponentCount,2);assert.ok(result.warnings.includes('multiple-foreground'));}); +test('invalid masks fail, binary silhouettes pass, tiny silhouettes require review',async()=>{const {analyzeCutout}=await load();for(const a of [new Uint8Array(4),new Uint8Array(4).fill(255),new Uint8Array(3)])assert.throws(()=>analyzeCutout(a,2,2));const a=new Uint8Array(100);a[55]=255;const r=analyzeCutout(a,10,10);assert.ok(r.warnings.includes('tiny-foreground'));assert.ok(r.bounds.x1>r.bounds.x0);}); +test('model alpha rejects NaN/constant and returns canonical soft values without thresholding',async()=>{const {normalizeMask}=await load();assert.throws(()=>normalizeMask(Float32Array.of(1,NaN,2,3),2,2,2,2));assert.throws(()=>normalizeMask(new Float32Array(4).fill(.4),2,2,2,2));const result=normalizeMask(Float32Array.of(0,.25,.5,1),2,2,2,2);assert.deepEqual([...result],[0,64,128,255]);}); +test('U2Net preprocessing uses one RGB maximum, channel mean/std and CHW',async()=>{const {preprocessU2Net}=await loadTypescript(new URL('../src/cutout/U2NetPreprocess.ts',import.meta.url));const x=preprocessU2Net(Uint8ClampedArray.of(255,128,0,255),1,1);assert.equal(x.length,3);assert.ok(Math.abs(x[0]-(1-.485)/.229)<1e-5);assert.ok(Math.abs(x[1]-(128/255-.456)/.224)<1e-5);assert.ok(Math.abs(x[2]+.406/.225)<1e-5);}); diff --git a/scripts/test-cutout-model.mjs b/scripts/test-cutout-model.mjs new file mode 100644 index 0000000..a26e980 --- /dev/null +++ b/scripts/test-cutout-model.mjs @@ -0,0 +1,27 @@ +import assert from 'node:assert/strict'; +import { readFile } from 'node:fs/promises'; +import { createHash } from 'node:crypto'; +import { test } from 'node:test'; + +const read = path => readFile(new URL('../' + path, import.meta.url)); +test('opt-in model is the unchanged licensed 4.57 MB foreground model', async () => { + const bytes = await read('public/models/u2netp/model.onnx'); + const manifest = JSON.parse(await read('public/models/u2netp/manifest.json')); + assert.equal(bytes.length, 4574861); + assert.equal(bytes.length, manifest.bytes); + assert.equal(createHash('sha256').update(bytes).digest('hex'), manifest.sha256); + assert.equal(manifest.sha256, '309c8469258dda742793dce0ebea8e6dd393174f89934733ecc8b14c76f4ddd8'); + assert.match((await read('public/models/u2netp/LICENSES.txt')).toString(), /Apache|MIT/); +}); +test('worker uses local pixels, same-origin model and installed external WASM runtime', async () => { + const source = (await read('src/cutout/cutout.worker.ts')).toString(); + const runtime = JSON.parse(await read('node_modules/onnxruntime-web/package.json')); + assert.match(source, /new OffscreenCanvas\(320,320\)/); + assert.match(source, /context.drawImage\(image/); + assert.match(source, /const MODEL='\/models\/u2netp\/model.onnx'/); + assert.ok(source.includes(`const RUNTIME='${runtime.version}'`)); + assert.match(source, /crypto.subtle.digest\('SHA-256',bytes\)/); + assert.match(source, /ort.env.wasm.numThreads=1/); + assert.equal([...source.matchAll(/\bfetch\(/g)].length, 1); + assert.doesNotMatch(source, /FormData|XMLHttpRequest|sendBeacon|method:\s*['"]POST/); +}); diff --git a/scripts/test-cutout-preparation.mjs b/scripts/test-cutout-preparation.mjs new file mode 100644 index 0000000..2a40b00 --- /dev/null +++ b/scripts/test-cutout-preparation.mjs @@ -0,0 +1,149 @@ +import assert from 'node:assert/strict'; +import { test } from 'node:test'; +import { readFile } from 'node:fs/promises'; +import vm from 'node:vm'; +import ts from 'typescript'; +import { loadTypescript } from './support/load-typescript.mjs'; +const maskModule = await loadTypescript(new URL('../src/cutout/CutoutMask.ts', import.meta.url)); + +const tick = async () => { for (let i = 0; i < 20; i++) await Promise.resolve(); }; +async function harness({ delayedSnapshot = false, delayedPreview = false, previewError = false, encodeError = false } = {}) { + const source = await readFile(new URL('../src/cutout/CutoutPreparation.ts', import.meta.url), 'utf8'); + const exports = {}, captures = [], workers = [], images = [], blobs = [], revoked = [], canvases = []; + const pixels = Uint8ClampedArray.of(200, 120, 20, 255, 10, 30, 90, 128, 44, 55, 66, 255, 11, 22, 33, 255); + class Provider { + constructor(onStatus) { this.onStatus = onStatus; this.cancelled = 0; workers.push(this); } + run(snapshot, signal) { this.snapshot = snapshot; this.signal = signal; return new Promise((resolve, reject) => { this.resolve = resolve; this.reject = reject; signal.addEventListener('abort', () => reject(new DOMException('cancel', 'AbortError')), { once: true }); }); } + cancel() { this.cancelled++; } + dispose() { this.disposed = true; } + } + function capture(_file, id, signal) { + const snapshot = { requestId: id, width: 2, height: 2, bitmap: { width: 2, height: 2, closes: 0, close() { this.closes++; } } }; + const request = { snapshot, signal }; + captures.push(request); + return delayedSnapshot ? new Promise(resolve => { request.resolve = () => resolve(snapshot); }) : Promise.resolve(snapshot); + } + const document = { createElement(tag) { + assert.equal(tag, 'canvas'); + const canvas = { width: 0, height: 0, pixels: pixels.slice(), draws: [], getContext() { return { + drawImage: image => canvas.draws.push(image), + getImageData: () => ({ data: canvas.pixels.slice() }), + putImageData: data => { canvas.pixels = data.data.slice(); }, + }; }, toBlob(callback, type) { + assert.equal(type, 'image/png', 'every adapter must be PNG, never SVG'); + const blob = new Blob([canvas.pixels], { type }); + blob.rgba = canvas.pixels.slice(); + blobs.push(blob); + callback(encodeError ? null : blob); + } }; + canvases.push(canvas); + return canvas; + } }; + class Image { + constructor() { images.push(this); } + set src(value) { this._src = value; if (!delayedPreview) queueMicrotask(() => previewError ? this.onerror?.() : this.onload?.()); } + get src() { return this._src; } + removeAttribute(name) { assert.equal(name, 'src'); this._src = ''; } + } + const urls = []; + vm.runInNewContext(ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022 } }).outputText, { + exports, AbortController, Blob, DOMException, Error, Image, Set, Uint8Array, Uint8ClampedArray, document, + URL: { createObjectURL(blob) { urls.push(blob); return `blob:png-${urls.length}`; }, revokeObjectURL(url) { revoked.push(url); } }, + require(name) { if (name.includes('PhotoSnapshot')) return { createPhotoSnapshot: capture }; if (name.includes('CutoutMask')) return maskModule; if (name.includes('CutoutProvider')) return { CutoutProvider: Provider }; throw new Error(name); }, + }); + const preparation = new exports.CutoutPreparation(); + function succeed(alpha = Uint8Array.of(0, 128, 255, 255)) { + const p = workers[0]; + p.resolve({ requestId: p.snapshot.requestId, width: 2, height: 2, alpha, bounds: { x0: 0, y0: 0, x1: 2, y1: 2 }, warnings: [], largeComponentCount: 1, run: { model: 'test' } }); + } + return { preparation, captures, workers, images, blobs, urls, revoked, canvases, pixels, succeed }; +} + +test('preparation is lazy and produces review-only PNGs with full original RGB preserved', async () => { + const h = await harness(); + assert.equal(h.captures.length, 0); + const progress = [], task = h.preparation.prepare(new Blob(['photo']), message => progress.push(message)); + await tick(); + assert.equal(h.workers[0].snapshot, h.captures[0].snapshot); + h.workers[0].onStatus(h.captures[0].snapshot.requestId, 'mask ready'); + h.succeed(); + const result = await task; + assert.equal(result.originalBlob.type, 'image/png'); + assert.equal(result.cutoutBlob.type, 'image/png'); + assert.deepEqual([...result.originalBlob.rgba], [...h.pixels]); + assert.deepEqual([...result.cutoutBlob.rgba], [200,120,20,0,10,30,90,64,44,55,66,255,11,22,33,255]); + assert.deepEqual([...result.alpha], [0,64,255,255], 'result alpha is the actual combined alpha'); + assert.equal(result.originalImage.src, result.originalUrl); + assert.equal(result.cutoutImage.src, result.cutoutUrl); + assert.equal(result.width, 2); + assert.equal(result.height, 2); + assert.equal(result.requiresReview, true); + assert.ok(progress.includes('mask ready')); + assert.equal(h.captures[0].snapshot.bitmap.closes, 1); + assert.ok(h.canvases.every(canvas => canvas.width === 1 && canvas.height === 1)); + result.dispose(); result.dispose(); + assert.equal(h.revoked.length, 2); + assert.ok(h.images.every(image => image.src === '')); + h.preparation.dispose(); + assert.equal(h.revoked.length, 2); +}); + +test('external cancellation terminates inference and cannot publish preview URLs', async () => { + const h = await harness(), abort = new AbortController(); + const task = h.preparation.prepare(new Blob(), undefined, abort.signal), rejected = assert.rejects(task, { name: 'AbortError' }); + await tick(); abort.abort(); await rejected; + assert.equal(h.workers[0].signal.aborted, true); + assert.equal(h.captures[0].snapshot.bitmap.closes, 1); + assert.equal(h.urls.length, 0); +}); + +test('cancel while decoding closes a late snapshot and never starts segmentation', async () => { + const h = await harness({ delayedSnapshot: true }); + const task = h.preparation.prepare(new Blob()), rejected = assert.rejects(task, { name: 'AbortError' }); + h.preparation.cancel(); h.captures[0].resolve(); await rejected; + assert.equal(h.captures[0].snapshot.bitmap.closes, 1); + assert.equal(h.workers[0].snapshot, undefined); + assert.equal(h.urls.length, 0); +}); + +test('replacement invalidates old work while a delivered result survives until disposal', async () => { + const h = await harness(); + const first = h.preparation.prepare(new Blob()), rejected = assert.rejects(first, { name: 'AbortError' }); + await tick(); + const second = h.preparation.prepare(new Blob()); + await rejected; await tick(); h.succeed(); const result = await second; + const third = h.preparation.prepare(new Blob()), thirdRejected = assert.rejects(third, { name: 'AbortError' }); + assert.equal(h.revoked.length, 0, 'accepted old consumer owns its URLs through a replacement'); + await tick(); h.preparation.dispose(); await thirdRejected; + assert.equal(h.revoked.length, 2); + assert.equal(result.originalImage.src, ''); + assert.equal(h.workers[0].disposed, true); + await assert.rejects(h.preparation.prepare(new Blob()), /종료|disposed/); +}); + +test('preview PNG decoding failure revokes both URLs and releases the bitmap', async () => { + const h = await harness({ previewError: true }); + const task = h.preparation.prepare(new Blob()), rejected = assert.rejects(task, /미리보기|사진|PNG/); + await tick(); h.succeed(); await rejected; + assert.equal(h.captures[0].snapshot.bitmap.closes, 1); + assert.equal(h.revoked.length, h.urls.length); + assert.ok(h.images.every(image => image.src === '')); +}); + +test('cancellation during pending PNG preview decode clears handlers and URLs', async () => { + const h = await harness({ delayedPreview: true }), abort = new AbortController(); + const task = h.preparation.prepare(new Blob(), undefined, abort.signal), rejected = assert.rejects(task, { name: 'AbortError' }); + await tick(); h.succeed(); await tick(); + assert.ok(h.urls.length > 0); + abort.abort(); await rejected; + assert.equal(h.revoked.length, h.urls.length); + assert.ok(h.images.every(image => image.src === '' && image.onload === null && image.onerror === null)); +}); + +test('PNG encoding failure does not return incomplete preview or leak snapshot', async () => { + const h = await harness({ encodeError: true }); + const task = h.preparation.prepare(new Blob()), rejected = assert.rejects(task, /PNG|미리보기|사진/); + await tick(); h.succeed(); await rejected; + assert.equal(h.captures[0].snapshot.bitmap.closes, 1); + assert.equal(h.urls.length, 0); +}); diff --git a/scripts/test-cutout-provider.mjs b/scripts/test-cutout-provider.mjs new file mode 100644 index 0000000..84ecb1f --- /dev/null +++ b/scripts/test-cutout-provider.mjs @@ -0,0 +1,15 @@ +import assert from 'node:assert/strict';import {test} from 'node:test';import {loadTypescript} from './support/load-typescript.mjs'; +const tick=async()=>{for(let i=0;i<8;i++)await Promise.resolve();}; +async function harness(){const workers=[],bitmaps=[];const oldW=globalThis.Worker,oldB=globalThis.createImageBitmap;globalThis.Worker=class{constructor(){this.messages=[];this.terminated=false;workers.push(this);}postMessage(m){this.messages.push(m);}terminate(){this.terminated=true;}};globalThis.createImageBitmap=async()=>{const b={width:10,height:10,closed:false,close(){this.closed=true;}};bitmaps.push(b);return b;};const {CutoutProvider}=await loadTypescript(new URL('../src/cutout/CutoutProvider.ts',import.meta.url));const statuses=[];const p=new CutoutProvider((id,m)=>statuses.push([id,m]));return{p,workers,bitmaps,statuses,cleanup(){p.cancel();globalThis.Worker=oldW;globalThis.createImageBitmap=oldB;}};} +const snapshot={requestId:12,width:10,height:10,bitmap:{}}; +function success(w){const alpha=new Uint8Array(100);alpha.fill(255,30,60);w.onmessage({data:{type:'result',id:12,width:10,height:10,alpha:alpha.buffer,run:{model:'u2netp',revision:'test',backend:'wasm',downloadBytes:0,preparationMs:1,inferenceMs:1,totalMs:2}}});} +test('provider validates result and terminates inference worker before resolving',async()=>{const h=await harness();try{const task=h.p.run(snapshot,new AbortController().signal);await tick();success(h.workers[0]);const result=await task;assert.equal(result.requestId,12);assert.equal(h.workers[0].terminated,true);assert.ok(result.bounds.x1>result.bounds.x0);}finally{h.cleanup();}}); +test('GPU failure retries at most once in a fresh WASM worker; stale messages ignored',async()=>{const h=await harness();try{const task=h.p.run(snapshot,new AbortController().signal);await tick();const old=h.workers[0];old.onmessage({data:{type:'fallback',id:12}});await tick();assert.equal(old.terminated,true);assert.equal(h.workers[1].messages[0].forceWasm,true);old.onmessage({data:{type:'error',id:12,message:'late'}});success(h.workers[1]);await task;assert.equal(h.workers.length,2);}finally{h.cleanup();}}); +test('abort terminates and rejects, never accepting a late result or status',async()=>{const h=await harness();try{const abort=new AbortController();const task=h.p.run(snapshot,abort.signal);const rejected=assert.rejects(task,{name:'AbortError'});await tick();const w=h.workers[0];abort.abort();await rejected;success(w);w.onmessage({data:{type:'status',id:12,message:'late'}});assert.equal(w.terminated,true);assert.equal(h.statuses.length,0);}finally{h.cleanup();}}); +test('photo snapshot applies EXIF once then constrains canonical longest edge',async()=>{const original=globalThis.createImageBitmap;const calls=[];let closed=0;globalThis.createImageBitmap=async(source,options)=>{calls.push(options);return calls.length===1?{width:1600,height:800,close(){closed++;}}:{width:1024,height:512,close(){closed++;}};};try{const {createPhotoSnapshot}=await loadTypescript(new URL('../src/input/PhotoSnapshot.ts',import.meta.url));const result=await createPhotoSnapshot({},2,new AbortController().signal);assert.equal(result.width,1024);assert.equal(result.height,512);assert.equal(calls[0].imageOrientation,'from-image');assert.equal(calls[1].resizeWidth,1024);assert.equal(closed,1);}finally{globalThis.createImageBitmap=original;}}); +test('late rejected capture never rejects a newer request',async()=>{const h=await harness();try{let rejectCapture;globalThis.createImageBitmap=()=>new Promise((_,reject)=>{rejectCapture=reject;});const first=h.p.run(snapshot,new AbortController().signal);const firstRejected=assert.rejects(first,{name:'AbortError'});h.p.cancel();await firstRejected;globalThis.createImageBitmap=async()=>({width:10,height:10,close(){}});const next=h.p.run(snapshot,new AbortController().signal);const settled=next.then(value=>({value}),error=>({error}));await tick();rejectCapture(new Error('old decode failure'));await tick();success(h.workers[0]);assert.equal((await settled).error,undefined);}finally{h.cleanup();}}); +test('worker construction failure closes the untransferred clone',async()=>{const h=await harness();try{globalThis.Worker=class{constructor(){throw new Error('worker unavailable');}};await assert.rejects(h.p.run(snapshot,new AbortController().signal),/worker unavailable/);assert.equal(h.bitmaps[0].closed,true);}finally{h.cleanup();}}); +test('abort while clone is pending closes only clone and never creates a worker',async()=>{const h=await harness();try{let resolveCapture;let canonicalClosed=0,cloneClosed=0;const snap={...snapshot,bitmap:{close(){canonicalClosed++;}}};globalThis.createImageBitmap=()=>new Promise(resolve=>{resolveCapture=resolve;});const abort=new AbortController(),task=h.p.run(snap,abort.signal);const rejected=assert.rejects(task,{name:'AbortError'});abort.abort();await rejected;resolveCapture({width:10,height:10,close(){cloneClosed++;}});await tick();assert.equal(cloneClosed,1);assert.equal(canonicalClosed,0);assert.equal(h.workers.length,0);}finally{h.cleanup();}}); +test('second fallback fails with no third worker',async()=>{const h=await harness();try{const task=h.p.run(snapshot,new AbortController().signal);const rejected=assert.rejects(task,/계산하지 못/);await tick();h.workers[0].onmessage({data:{type:'fallback',id:12}});await tick();h.workers[1].onmessage({data:{type:'fallback',id:12}});await rejected;assert.equal(h.workers.length,2);assert.ok(h.workers.every(w=>w.terminated));}finally{h.cleanup();}}); +test('snapshot abort during resize closes decoded and resized bitmaps exactly once',async()=>{const old=globalThis.createImageBitmap;let resolveResize,decodedClosed=0,resizedClosed=0;let count=0;globalThis.createImageBitmap=async()=>{if(++count===1)return{width:1600,height:800,close(){decodedClosed++;}};return new Promise(resolve=>{resolveResize=resolve;});};try{const {createPhotoSnapshot}=await loadTypescript(new URL('../src/input/PhotoSnapshot.ts',import.meta.url));const abort=new AbortController(),task=createPhotoSnapshot({},2,abort.signal),rejected=assert.rejects(task,{name:'AbortError'});await tick();abort.abort();resolveResize({width:1024,height:512,close(){resizedClosed++;}});await rejected;assert.equal(decodedClosed,1);assert.equal(resizedClosed,1);}finally{globalThis.createImageBitmap=old;}}); +test('disposing a provider cancels active work and permanently prevents a new worker',async()=>{const h=await harness();try{const task=h.p.run(snapshot,new AbortController().signal),rejected=assert.rejects(task,{name:'AbortError'});await tick();h.p.dispose();h.p.dispose();await rejected;assert.equal(h.workers[0].terminated,true);await assert.rejects(h.p.run(snapshot,new AbortController().signal),/종료/);assert.equal(h.workers.length,1);}finally{h.cleanup();}}); diff --git a/scripts/test-cutout-worker.mjs b/scripts/test-cutout-worker.mjs new file mode 100644 index 0000000..bc222b1 --- /dev/null +++ b/scripts/test-cutout-worker.mjs @@ -0,0 +1,53 @@ +/** Production worker + real ORT-Web WASM under Node. Canvas supplies retained + * local RGB fixture pixels; this is not browser, GPU, CDN or mobile validation. */ +import assert from 'node:assert/strict'; +import { test } from 'node:test'; +import { readFile } from 'node:fs/promises'; +import vm from 'node:vm'; +import ts from 'typescript'; +import * as ort from 'onnxruntime-web/webgpu'; +import { webcrypto } from 'node:crypto'; +import { loadTypescript } from './support/load-typescript.mjs'; + +test('production worker executes the retained local model and releases its input', { timeout: 30000 }, async () => { + const mask = await loadTypescript(new URL('../src/cutout/CutoutMask.ts', import.meta.url)); + const preprocess = await loadTypescript(new URL('../src/cutout/U2NetPreprocess.ts', import.meta.url)); + const model = await readFile(new URL('../public/models/u2netp/model.onnx', import.meta.url)); + const rgba = await readFile(new URL('../docs/qa-countryside-cutout-2026-10-07/runtime/sample-320.rgba', import.meta.url)); + // Only the host boundary is changed. The model and all preprocess, inference, + // normalization and worker cleanup logic are the actual production code. + ort.env.wasm.wasmPaths = new URL('../node_modules/onnxruntime-web/dist/', import.meta.url).href; + ort.env.wasm.numThreads = 1; + const wasm = new Proxy(ort.env.wasm, { set(target, key, value) { if (key !== 'wasmPaths') target[key] = value; return true; } }); + const runtime = { ...ort, env: { ...ort.env, wasm } }; + let listener, complete; + const terminal = new Promise(resolve => { complete = resolve; }); + const messages = [], requested = []; + const image = { width: 415, height: 739, closes: 0, close() { this.closes++; } }; + const source = await readFile(new URL('../src/cutout/cutout.worker.ts', import.meta.url), 'utf8'); + vm.runInNewContext(ts.transpileModule(source, { compilerOptions: { target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.CommonJS } }).outputText, { + exports: {}, require: name => name === 'onnxruntime-web/webgpu' ? runtime : name === './U2NetPreprocess' ? preprocess : mask, + performance, crypto: webcrypto, navigator: {}, + fetch: async (url, options) => { requested.push({ url, options }); return { ok: true, arrayBuffer: async () => model.buffer.slice(model.byteOffset, model.byteOffset + model.byteLength) }; }, + OffscreenCanvas: class { constructor(width, height) { assert.equal(width, 320); assert.equal(height, 320); } getContext() { return { drawImage(input) { assert.equal(input, image); }, getImageData() { return { data: new Uint8ClampedArray(rgba) }; } }; } }, + self: { addEventListener(_type, fn) { listener = fn; }, postMessage(message) { messages.push(message); if (['result', 'error', 'fallback'].includes(message.type)) complete(message); } }, + }); + listener({ data: { type: 'infer', id: 17, image, forceWasm: true } }); + const result = await terminal; + await new Promise(resolve => setImmediate(resolve)); + assert.equal(result.type, 'result', result.message); + assert.equal(result.id, 17); + assert.equal(result.width, 415); + assert.equal(result.height, 739); + assert.equal(result.run.backend, 'wasm'); + assert.equal(result.run.downloadBytes, 4574861); + const alpha = new Uint8Array(result.alpha), analysis = mask.analyzeCutout(alpha, result.width, result.height); + assert.equal(alpha.length, 415 * 739); + assert.ok(alpha.some(value => value > 0 && value < 255), 'soft fringe is retained'); + assert.ok(analysis.bounds.y0 > 0 && analysis.bounds.y1 < result.height); + assert.equal(image.closes, 1); + assert.equal(requested.length, 1); + assert.equal(requested[0].url, '/models/u2netp/model.onnx'); + assert.equal(requested[0].options.body, undefined); + assert.equal(messages.filter(message => message.type === 'status').length, 2); +}); diff --git a/scripts/test-default-renderer.mjs b/scripts/test-default-renderer.mjs new file mode 100644 index 0000000..ec59618 --- /dev/null +++ b/scripts/test-default-renderer.mjs @@ -0,0 +1,139 @@ +import assert from 'node:assert/strict'; +import { existsSync, readFileSync } from 'node:fs'; +import { test } from 'node:test'; +import vm from 'node:vm'; +import ts from 'typescript'; +import * as THREE from 'three'; +import { RectAreaLightUniformsLib } from 'three/addons/lights/RectAreaLightUniformsLib.js'; +function load(relative) { + const path=new URL(relative,import.meta.url); const exports={}; + const source=readFileSync(path,'utf8'); + vm.runInNewContext(ts.transpileModule(source,{compilerOptions:{module:ts.ModuleKind.CommonJS,target:ts.ScriptTarget.ES2022}}).outputText,{exports,require(spec){if(spec==='three')return THREE;if(spec.includes('RectArea'))return {RectAreaLightUniformsLib};return load(new URL(spec+'.ts',path).href);}}); + return exports; +} +function fixture(){ + const {MeshGlassRenderer}=load('../src/rendering/MeshGlassRenderer.ts'); + const calls=[];let target=null; const renderer={autoClear:true,extensions:{has:()=>false},debug:{},getContext:()=>({isContextLost:()=>false}),getRenderTarget:()=>target,setRenderTarget(t){target=t;calls.push(['target',t]);},setScissorTest(){},clearDepth(){},render(scene,camera){camera.updateMatrixWorld();scene.updateMatrixWorld();calls.push(['render',scene,target]);scene.traverse(o=>{if(o.isMesh)o.onBeforeRender(renderer,scene,camera,o.geometry,o.material,null);});}}; + const source=new THREE.Mesh(new THREE.PlaneGeometry(1,1,128,128),new THREE.ShaderMaterial({uniforms:{uTexture:{value:new THREE.Texture()},uDepthMap:{value:new THREE.Texture()},uDepthScale:{value:.25},uDepthBias:{value:0},uIsVideo:{value:false}}})); + const b=new MeshGlassRenderer(renderer,source);return {b,renderer,calls,source}; +} +test('B is a standalone default renderer without A output targets or shaders',()=>{ + assert.ok(existsSync(new URL('../src/rendering/MeshGlassRenderer.ts',import.meta.url)),'standalone B module must exist'); + const {b,calls}=fixture(); b.sync({width:1,height:1.32,grid:20,curvature:1},.6,new THREE.Vector3(.6,.8,2.6),new THREE.Color()); + const camera=new THREE.PerspectiveCamera(),frame=new THREE.Scene();b.render(camera,frame,true); + assert.equal('targetA' in b,false);assert.equal('targetB' in b,false); + assert.equal(calls.filter(c=>c[0]==='render').length,2);assert.equal(calls.filter(c=>c[0]==='render')[0][2],null); + b.dispose(); +}); +test('B shares replacements and photo transforms without first rendering A',()=>{ + const {b,source}=fixture(),shape={width:1,height:1.32,grid:20,curvature:1}; + b.sync(shape,.6,new THREE.Vector3(),new THREE.Color());const geometry=b.glass.geometry; + source.position.set(.1,-.2,.22);source.scale.set(.8,1.1,1);const texture=new THREE.Texture();source.material.uniforms.uTexture.value=texture; + b.sync(shape,.6,new THREE.Vector3(),new THREE.Color());assert.equal(b.glass.geometry,geometry); + const shader={uniforms:{},vertexShader:THREE.ShaderLib.physical.vertexShader,fragmentShader:THREE.ShaderLib.physical.fragmentShader};b.material.onBeforeCompile(shader,{}); + assert.equal(shader.uniforms.uBPhoto.value,texture);assert.deepEqual(b.scene.children.find(x=>x.geometry===source.geometry).position.toArray(),source.position.toArray()); + b.dispose(); +}); +test('B excludes caller output from owned transmission targets and disposes once',()=>{ + const {b,renderer,source}=fixture();b.sync({width:1,height:1,grid:20,curvature:1},.6,new THREE.Vector3(),new THREE.Color()); + const output=new THREE.WebGLRenderTarget(20,20);let outputDisposed=0,sourceDisposed=0,glassDisposed=0; + output.addEventListener('dispose',()=>outputDisposed++);source.geometry.addEventListener('dispose',()=>sourceDisposed++);b.glass.geometry.addEventListener('dispose',()=>glassDisposed++); + b.render(new THREE.PerspectiveCamera(),new THREE.Scene(),true,output);b.dispose();b.dispose(); + assert.equal(outputDisposed,0);assert.equal(sourceDisposed,0);assert.equal(glassDisposed,1);output.dispose(); +}); +test('normal flow selects B, A is an explicit lazy option, and failure never silently selects A',()=>{ + const main=readFileSync(new URL('../src/main.ts',import.meta.url),'utf8'),html=readFileSync(new URL('../index.html',import.meta.url),'utf8'); + assert.match(html,/value="b" selected/);assert.match(main,/import\('\.\/rendering\/OriginalGlassRenderer'\)/); + assert.match(main,/meshRenderer\.render/);assert.match(main,/showMeshFailure/); + assert.match(main,/meshRenderer\.restore/);assert.match(main,/originalRenderer\?\.invalidate/); +}); +test('a compiled B failure stays explicit until retry or context restoration',()=>{ + const {b,renderer}=fixture();let first=true;const render=renderer.render.bind(renderer); + renderer.render=(...args)=>{if(first){first=false;renderer.debug.onShaderError?.({},null,null,null);}render(...args);}; + const camera=new THREE.PerspectiveCamera(),frame=new THREE.Scene(); + assert.throws(()=>b.render(camera,frame,true),/shader|failed/i); + assert.throws(()=>b.render(camera,frame,true),/shader|failed/i,'Three caches failed programs; absence of a second callback is not success'); + b.restore();assert.doesNotThrow(()=>b.render(camera,frame,true));b.dispose(); +}); +test('fresh Glass Only still releases the hidden transmission target without drawing the photo',()=>{ + const {b,renderer,source}=fixture(),internal=new THREE.WebGLRenderTarget(1,1);let frees=0; + internal.addEventListener('dispose',()=>frees++); + const original=renderer.render.bind(renderer),setTarget=renderer.setRenderTarget.bind(renderer); + renderer.render=(scene,camera)=>{ + if(scene===b.scene){const output=renderer.getRenderTarget();setTarget(internal);for(const object of scene.children)if(object.visible&&object.geometry&&object!==b.glass){assert.equal(object.material.colorWrite,false);assert.equal(object.material.depthWrite,false);object.onBeforeRender(renderer,scene,camera,object.geometry,object.material,null);}setTarget(output);} + original(scene,camera); + }; + b.render(new THREE.PerspectiveCamera(),new THREE.Scene(),true,null,false);b.dispose(); + assert.equal(frees,1);assert.equal(source.material.colorWrite,true);assert.equal(source.material.depthWrite,true,'shared photo material state restores'); +}); + +test('sliding B moves only the actual pane and keeps world-space exits tied to the translated geometry',()=>{ + const {b,source}=fixture(),shape={width:1,height:1.32,grid:20,curvature:1}; + b.setSlide(-.5);b.sync(shape,.6,new THREE.Vector3(),new THREE.Color()); + assert.equal(b.glass.position.x,-.5);assert.equal(source.position.x,0); + const geometry=b.glass.geometry; + const shader={uniforms:{},fragmentShader:THREE.ShaderLib.physical.fragmentShader};b.material.onBeforeCompile(shader,{}); + assert.equal(shader.uniforms.uBPaneCenterX.value,-.5); + assert.match(shader.fragmentShader,/side\*uBPaneHalfSize\.x\+uBPaneCenterX-entry\.x/); + assert.ok(b.material.clippingPlanes.length===1);assert.equal(b.material.clippingPlanes[0].constant,.55); + b.setSlide(-1);b.sync(shape,.6,new THREE.Vector3(),new THREE.Color()); + assert.equal(b.glass.geometry,geometry,'opening does not rebuild patterned glass'); + assert.equal(shader.uniforms.uBPaneCenterX.value,-1); + assert.equal(b.scene.children.find(x=>x.geometry===source.geometry).position.x,0); + b.restore();assert.equal(b.glass.position.x,-1);b.dispose(); +}); + +// A CPU depth-buffer oracle around the real production render calls. Geometry +// intersections are real Three triangles; this does not execute WebGL shaders. +test('B preserves pane depth into the frame pass while foreground and open-door reveal still draw',()=>{ + const {b,renderer,source}=fixture(); + const {WindowReveal}=load('../src/objects/WindowReveal.ts'); + source.position.z=.2;source.scale.set(1.2,1.584,1); + const frame=new THREE.Scene(),wood=new THREE.MeshBasicMaterial({side:THREE.DoubleSide}); + const reveal=new WindowReveal(wood);reveal.update(1,1.32,1.2,1.584,.6,.2); + frame.add(...reveal.meshes);reveal.meshes.forEach(mesh=>mesh.name='reveal'); + const front=new THREE.Mesh(new THREE.BoxGeometry(.12,1.6,.16),wood);front.position.set(-.55,0,.66);front.name='foreground';frame.add(front); + const originalRender=renderer.render.bind(renderer);let samples=[],depth=[],winner=[]; + renderer.clearDepth=()=>{depth.fill(Infinity);}; + renderer.render=(scene,camera)=>{ + originalRender(scene,camera); + if(renderer.autoClear){depth=samples.map(()=>Infinity);winner=samples.map(()=>null);} + for(let i=0;ihit.object.visible&&hit.object.material.depthTest!==false); + for(const hit of hits){if(hit.object===b.glass&&hit.point.x < -b.material.clippingPlanes[0].constant)continue; + if(hit.distance<=depth[i]){if(hit.object.material.colorWrite)winner[i]=hit.object;if(hit.object.material.depthWrite)depth[i]=hit.distance;} + } + } + }; + let protectedRear=0,visibleFront=0,visibleOpenReveal=0; + for(const opening of [0,.5,1])for(const eye of [[0,0,3],[.6,-.2,1.1],[-.6,-.2,1.1],[0,.5,1.05]]){ + b.setSlide(-opening);b.sync({width:1,height:1.32,grid:20,curvature:1},.6,new THREE.Vector3(),new THREE.Color()); + const camera=new THREE.PerspectiveCamera();camera.position.set(...eye);camera.lookAt(0,0,.6);camera.updateMatrixWorld(); + samples=[];for(const y of [-.6,-.3,0,.3,.6])for(const x of [-.56,-.49,-.4,-.2,0,.2,.4,.49])samples.push(new THREE.Vector3(x,y,.6)); + b.render(camera,frame,true); + for(let i=0;ihit.object.visible&&!(hit.object===b.glass&&hit.point.x < -b.material.clippingPlanes[0].constant)); + const nearest=all[0]?.object??null; + assert.equal(winner[i]?.uuid,nearest?.uuid,`opening ${opening}, eye ${eye}, target ${samples[i].toArray()}: rear frame must not overwrite a nearer pane`); + if(nearest===b.glass&&all.some(hit=>reveal.meshes.includes(hit.object)))protectedRear++; + if(nearest===front)visibleFront++; + if(opening>0&&reveal.meshes.includes(nearest))visibleOpenReveal++; + } + } + assert.ok(protectedRear>0,'regression rays actually see rear reveal behind glass'); + assert.ok(visibleFront>0,'near-side wood still occludes the pane'); + assert.ok(visibleOpenReveal>0,'slid-open areas retain direct reveal coverage'); + console.log('B/frame depth oracle:',JSON.stringify({protectedRear,visibleFront,visibleOpenReveal})); + b.dispose();reveal.dispose();front.geometry.dispose();wood.dispose();source.geometry.dispose();source.material.dispose(); +}); + +test('B keeps caller render state after a failing frame pass without clearing the pane depth',()=>{ + const {b,renderer}=fixture(),frame=new THREE.Scene();let clears=0; + renderer.clearDepth=()=>{clears++;};const render=renderer.render.bind(renderer); + renderer.render=(scene,camera)=>{if(scene===frame)throw new Error('frame failure');render(scene,camera);}; + assert.throws(()=>b.render(new THREE.PerspectiveCamera(),frame,true),/frame failure/); + assert.equal(renderer.autoClear,true);assert.equal(clears,0,'frame failure must not discard the current pane depth'); + b.dispose(); +}); diff --git a/scripts/test-depth-refraction.mjs b/scripts/test-depth-refraction.mjs index c08ade6..d801739 100644 --- a/scripts/test-depth-refraction.mjs +++ b/scripts/test-depth-refraction.mjs @@ -6,7 +6,9 @@ import { DEPTH_REFRACTION } from '../src/constants/depth.ts'; const shader = await readFile(new URL('../src/shaders/mosaic.frag', import.meta.url), 'utf8'); const main = await readFile(new URL('../src/main.ts', import.meta.url), 'utf8'); const media = main.slice(main.indexOf('function applyMedia('), main.indexOf('function setDepth(')); -assert.doesNotMatch(media, /photo(?:Zoom|PanX|PanY)\s*=/, 'media replacement preserves manual framing'); +const ordinaryMedia=media.replace(/if\(incoming&&!video\)\{[^}]*\}else incoming\?\.dispose\(\);/,''); +assert.doesNotMatch(ordinaryMedia, /photo(?:Zoom|PanX|PanY)\s*=/, 'ordinary media replacement preserves manual framing'); +assert.match(media,/if\(incoming&&!video\)\{[^}]*photoZoom=1;photoPanX=photoPanY=0/,'only explicit experiment acceptance starts its peeking placement'); assert.match(shader, /sceneHit=refineSceneHit\(gh,normalize\(mix\(i,curvedRay,strength\)\),sceneHit,cellWorld\)/); assert.match(shader, /if\(!reconstructScenePoint\(projectUv\(hit\),surface\)\)return artisticHit/); assert.match(shader, /confidence=1\.-smoothstep/); diff --git a/scripts/test-entry-notices.mjs b/scripts/test-entry-notices.mjs new file mode 100644 index 0000000..56d9b6b --- /dev/null +++ b/scripts/test-entry-notices.mjs @@ -0,0 +1,57 @@ +import assert from 'node:assert/strict'; +import {test} from 'node:test'; +import {readFile} from 'node:fs/promises'; +import {loadTypescript} from './support/load-typescript.mjs'; +// Removing the carousel markup must fail before implementing it. +test('entry replaces three permanent explanations with one manually controlled notice region',async()=>{ + const html=await readFile(new URL('../index.html',import.meta.url),'utf8'); + assert.match(html,/id="entry-notices"/); + assert.match(html,/id="notice-prev"[^>]*aria-label="이전 안내"/); + assert.match(html,/id="notice-next"[^>]*aria-label="다음 안내"/); + assert.doesNotMatch(html,/

/); +}); +class El extends EventTarget { + constructor(id){super();this.id=id;this.hidden=false;this.dataset={};this.attrs={};} + setAttribute(k,v){this.attrs[k]=v;} + fire(type,props={}){const e=new Event(type,{cancelable:true});Object.assign(e,props);this.dispatchEvent(e);return e;} + closest(){return null;} +} +async function harness(desktop=false){ + const {initEntryNotices}=await loadTypescript(new URL('../src/ui/EntryNotices.ts',import.meta.url)); + const ids=['entry-notices','notice-prev','notice-next','notice-position','notice-status','photo-tip','privacy-tip','paste-tip']; + const els=Object.fromEntries(ids.map(id=>[id,new El(id)])); + els['photo-tip'].textContent='정면 사진이면 더 귀여워요';els['privacy-tip'].textContent='사진은 이 브라우저 안에서만 처리해요';els['paste-tip'].textContent='복사한 사진도 붙여넣을 수 있어요 Ctrl+V · ⌘V'; + const media=new El('media');media.matches=desktop; + const root={querySelector:s=>els[s.slice(1)],defaultView:{matchMedia:()=>media}}; + const controller=new AbortController();initEntryNotices(root,controller.signal); + return {els,media,controller,active:()=>ids.filter(id=>els[id].dataset.active==='true')}; +} +test('mobile has two notices, arrows loop, and initial render is silent',async()=>{ + const h=await harness();assert.deepEqual(h.active(),['photo-tip']);assert.equal(h.els['paste-tip'].hidden,true);assert.equal(h.els['notice-position'].textContent,'1 / 2');assert.equal(h.els['notice-status'].textContent,undefined); + h.els['notice-next'].fire('click');assert.deepEqual(h.active(),['privacy-tip']);assert.match(h.els['notice-status'].textContent,/2 \/ 2/); + h.els['notice-next'].fire('click');assert.deepEqual(h.active(),['photo-tip']); + h.els['notice-prev'].fire('click');assert.deepEqual(h.active(),['privacy-tip']); +}); +test('desktop adds paste notice and changing to touch-only removes it immediately',async()=>{ + const h=await harness(true);h.els['notice-prev'].fire('click');assert.deepEqual(h.active(),['paste-tip']); + h.media.matches=false;h.media.fire('change');assert.deepEqual(h.active(),['photo-tip']);assert.equal(h.els['paste-tip'].hidden,true);assert.equal(h.els['notice-status'].textContent,''); +}); +test('horizontal single-touch swipe advances; vertical, cancelled and multiple pointers do not',async()=>{ + const h=await harness();const el=h.els['entry-notices']; + const down=(id=1)=>el.fire('pointerdown',{pointerId:id,pointerType:'touch',isPrimary:true,clientX:160,clientY:20,targetElement:null}); + const up=(x,y=20,id=1)=>el.fire('pointerup',{pointerId:id,clientX:x,clientY:y}); + down();up(70);assert.deepEqual(h.active(),['privacy-tip']); + down();up(150,100);assert.deepEqual(h.active(),['privacy-tip']); + down();el.fire('pointercancel',{pointerId:1});up(70);assert.deepEqual(h.active(),['privacy-tip']); + down();el.fire('pointerdown',{pointerId:2,pointerType:'touch',isPrimary:false,clientX:120,clientY:20});up(70);assert.deepEqual(h.active(),['privacy-tip']); +}); +test('abort removes interaction and media listeners',async()=>{ + const h=await harness(true);h.controller.abort();h.els['notice-next'].fire('click');h.media.matches=false;h.media.fire('change');assert.deepEqual(h.active(),['photo-tip']);assert.equal(h.els['paste-tip'].hidden,false); +}); +test('notices follow the sample action and use app-font counters with a bottom mobile layout',async()=>{ + const html=await readFile(new URL('../index.html',import.meta.url),'utf8'); + const css=await readFile(new URL('../src/style.css',import.meta.url),'utf8'); + assert.ok(html.indexOf('id="entry-samples"') < html.indexOf('id="entry-notices"')); + assert.match(css,/#notice-position\s*\{[^}]*font-family:inherit/); + assert.match(css,/@media\s*\(max-width:640px\)[\s\S]*#entry-notices\s*\{[^}]*margin-top:auto/); +}); diff --git a/scripts/test-experience-ui.mjs b/scripts/test-experience-ui.mjs new file mode 100644 index 0000000..729604b --- /dev/null +++ b/scripts/test-experience-ui.mjs @@ -0,0 +1,277 @@ +import assert from 'node:assert/strict'; +import { readFile } from 'node:fs/promises'; +import { loadTypescript } from './support/load-typescript.mjs'; +const html = await readFile(new URL('../index.html', import.meta.url),'utf8'); +assert.match(html, /id="settings-dialog"/, 'all options must be in a dismissible dialog, never a persistent sidebar'); +const themes=await loadTypescript(new URL('../src/ui/themes.ts',import.meta.url)); +const {initExperienceUI}=await loadTypescript(new URL('../src/ui/ExperienceUI.ts',import.meta.url)); +class Element { + dataset={};attributes={};listeners={};value='';hidden=false;open=false;inert=false;isConnected=true; + addEventListener(type,fn,{signal}={}){(this.listeners[type]??=[]).push(fn);signal?.addEventListener('abort',()=>this.listeners[type]=this.listeners[type].filter(f=>f!==fn));} + dispatch(type,extra={}){for(const fn of this.listeners[type]??[])fn({target:this,...extra});} + setAttribute(key,value){this.attributes[key]=value;} + focus(){this.owner.activeElement=this;} + showModal(){this.open=true;} + close(){this.open=false;this.dispatch('close');} + getBoundingClientRect(){return {left:20,right:300,top:20,bottom:500};} +} +function harness(value=null,{readError=false,writeError=false}={}){ + const values=new Map(value===null?[]:[[themes.THEME_STORAGE_KEY,value]]);let writes=0; + const root=new Element();root.documentElement=new Element();root.activeElement=null; + const ids=['home-dialog','home-confirm','home-cancel','photo-adjust-open','photo-adjust-panel','photo-adjust-done','scene-menu','scene-menu-open','scene-menu-close','scene-guide-replay','scene-zoom-reset','comparison-exit','first-guide','export-open','export-dialog','credits-open','credits-close','credits-dialog','entry-notices','entry-pet-name','settings-pet-name','entry-name-notice','settings-name-notice','welcome-name','entry-photo-button','image','pet-stage','experience','welcome','flow-overlay','flow-title','flow-detail','flow-photo','journey','journey-motion','flow-actions','flow-retry','flow-flat','settings-dialog','settings-open','settings-close','entry-samples','sample-browser','sample-dialog','sample-close','sample-confirm','flow-samples','theme-select','canvas-wrap','scene-toolbar','scene-photo-change','sample-home','entry-name-step','entry-photo-step','entry-name-next','entry-name-skip','entry-name-edit']; + const els=Object.fromEntries(ids.map(id=>[id,new Element()]));Object.values(els).forEach(e=>e.owner=root);root.querySelector=s=>els[s.slice(1)]??null; + const choices=['dog5','dog1','dog2','dog3','dog4'].map(id=>{const e=new Element();e.owner=root;e.dataset.sampleChoice=id;return e;});root.querySelectorAll=()=>choices; + root.defaultView={get localStorage(){if(readError)throw new Error('blocked');return{getItem:key=>values.get(key)??null,setItem(key,value){if(writeError)throw new Error('full');values.set(key,value);writes++;}};}}; + let homeCalls=0,arrivalEnds=0;const samples=[];const themesSeen=[];const abort=new AbortController();const ui=initExperienceUI(root,abort.signal,theme=>themesSeen.push(theme),()=>{arrivalEnds++;},sample=>samples.push(sample), undefined, ()=>homeCalls++); + return {root,els,choices,samples,ui,themesSeen,values,abort,get writes(){return writes;},get homeCalls(){return homeCalls;},get arrivalEnds(){return arrivalEnds;}}; +} +for(const [value,expected] of [[null,'wood'],['wood','wood'],['booth','booth'],['invalid','wood'],['','wood']]){const h=harness(value);assert.equal(h.root.documentElement.dataset.theme,expected);assert.equal(h.els['theme-select'].value,expected);assert.equal(h.themesSeen.at(-1),expected);assert.equal(h.els['settings-dialog'].open,false);assert.equal(h.els.experience.dataset.flow,'entry');assert.equal(h.ui.isBlocked(),true);} +for(const errors of [{readError:true},{writeError:true},{}]){const h=harness(null,errors);h.els['theme-select'].value='booth';h.els['theme-select'].dispatch('change');assert.equal(h.root.documentElement.dataset.theme,'booth');assert.equal(h.themesSeen.at(-1),'booth');h.els['theme-select'].dispatch('change');assert.equal(h.themesSeen.length,2,'reselect causes no additional appearance work');} +const h=harness();h.els['theme-select'].value='booth';h.els['theme-select'].dispatch('change');assert.equal(h.values.get(themes.THEME_STORAGE_KEY),'booth');assert.equal(harness(h.values.get(themes.THEME_STORAGE_KEY)).els['theme-select'].value,'booth'); +h.ui.setPhoto('blob:photo');h.ui.setState('loading');assert.equal(h.els['flow-photo'].src,'blob:photo');assert.equal(h.els.experience.dataset.flow,'loading');assert.equal(h.els['flow-retry'].hidden,true);assert.equal(h.ui.isBlocked(),true); +h.ui.setDetail('model download');assert.equal(h.els['flow-detail'].textContent,'model download'); +h.ui.setState('error',true);assert.equal(h.els.experience.dataset.flow,'error');assert.equal(h.els['flow-retry'].hidden,false);assert.equal(h.els['flow-flat'].hidden,false); +h.ui.setState('ready');assert.equal(h.els['flow-overlay'].hidden,true);assert.equal(h.els.welcome.hidden,true);assert.equal(h.ui.isBlocked(),false); +h.ui.setRenderLost(true);assert.equal(h.ui.isBlocked(),true);assert.equal(h.els['canvas-wrap'].inert,true); +h.ui.setState('ready');assert.equal(h.ui.isBlocked(),true,'a late ready state cannot bypass render recovery'); +h.ui.setRenderLost(false);assert.equal(h.ui.isBlocked(),false);assert.equal(h.els['canvas-wrap'].inert,false); +h.els['settings-open'].focus();h.els['settings-open'].dispatch('click');assert.equal(h.els['settings-dialog'].open,true);assert.equal(h.ui.isBlocked(),true);assert.equal(h.els['canvas-wrap'].inert,true); +h.els['settings-dialog'].dispatch('cancel',{preventDefault(){}});assert.equal(h.els['settings-dialog'].open,false);assert.equal(h.root.activeElement,h.els['scene-menu-open']);assert.equal(h.els['canvas-wrap'].inert,false); +h.root.activeElement=null;h.els['settings-open'].dispatch('click');h.els['settings-dialog'].dispatch('click',{clientX:10,clientY:10});assert.equal(h.els['settings-dialog'].open,false);assert.equal(h.root.activeElement,h.els['scene-menu-open'],'pointer browsers that do not focus buttons still restore to the opener'); +h.els['entry-samples'].focus();h.els['entry-samples'].dispatch('click');assert.equal(h.els['sample-dialog'].open,true);assert.equal(h.els['settings-dialog'].open,false);h.els['sample-close'].dispatch('click');assert.equal(h.root.activeElement,h.els['entry-samples']); +h.els['settings-open'].dispatch('click');h.ui.setState('loading');assert.equal(h.els['settings-dialog'].open,false,'new media closes the options');assert.equal(h.ui.isBlocked(),true); +h.els['entry-samples'].dispatch('click'); +assert.equal(h.choices[0].attributes['aria-pressed'],'true'); +h.choices[2].dispatch('click');assert.equal(h.choices[2].attributes['aria-pressed'],'true');assert.equal(h.choices[0].attributes['aria-pressed'],'false');assert.equal(h.samples.length,0,'selection must never start the experience'); +h.els['sample-confirm'].dispatch('click');assert.deepEqual(h.samples,['dog2']);assert.equal(h.els['sample-dialog'].open,false); +h.els['entry-samples'].dispatch('click');h.els['sample-confirm'].dispatch('click');assert.deepEqual(h.samples,['dog2','dog2'],'same photo can be reselected'); +h.ui.setState('error');assert.equal(h.els['flow-samples'].hidden,false);h.els['flow-samples'].dispatch('click');assert.equal(h.els['sample-dialog'].open,true);h.els['sample-dialog'].dispatch('cancel',{preventDefault(){}});assert.equal(h.root.activeElement,h.els['flow-samples']); +h.els['flow-samples'].dispatch('click');h.ui.setRenderLost(true);assert.equal(h.els['sample-dialog'].open,false);h.els['flow-samples'].dispatch('click');assert.equal(h.els['sample-dialog'].open,false);h.ui.setRenderLost(false); +h.els['flow-samples'].dispatch('click');h.abort.abort();assert.equal(h.els['sample-dialog'].open,false);const count=h.themesSeen.length;h.els['theme-select'].value='wood';h.els['theme-select'].dispatch('change');assert.equal(h.themesSeen.length,count,'teardown removes theme handlers'); +console.log('Experience UI: default/persisted/invalid/unavailable storage, no-op reselect, real-state flow, source preview, error recovery, modal dismiss/focus/inert, teardown passed (DOM boundary double, no visual QA)'); + +const named=harness(); +const entryName=named.els['entry-pet-name'], settingsName=named.els['settings-pet-name']; +entryName.value='호롱';entryName.dispatch('input'); +assert.equal(named.els['entry-photo-button'].textContent,'호롱이 사진 고르기','typing a name updates landing copy'); +assert.equal(settingsName.value,'호롱','settings reflects the same app state'); +assert.equal(named.els['welcome-name'].textContent,'호롱이가 왔어요'); +named.ui.startJourney();assert.equal(named.els['flow-title'].textContent,'호롱이를 할머니 집으로 데려가는 중…'); +settingsName.value='초코';settingsName.dispatch('input'); +assert.equal(named.els['flow-title'].textContent,'초코를 할머니 집으로 데려가는 중…'); +assert.equal(entryName.value,'초코'); +settingsName.dispatch('compositionstart');settingsName.value='보';settingsName.dispatch('input',{isComposing:true}); +assert.equal(named.els['entry-photo-button'].textContent,'초코 사진 고르기','IME intermediate input does not update state'); +settingsName.value='보리';settingsName.dispatch('compositionend'); +assert.equal(named.els['entry-photo-button'].textContent,'보리 사진 고르기'); +settingsName.value=' ';settingsName.dispatch('change'); +assert.equal(settingsName.value,'');assert.equal(named.els['entry-photo-button'].textContent,' 사진 고르기'); +named.ui.setMediaOrigin('sample');named.ui.startJourney(); +assert.equal(named.els['flow-title'].textContent,'누렁이를 할머니 집으로 데려가는 중…'); +assert.equal(settingsName.value,'','sample never overwrites the saved name'); +named.ui.setMediaOrigin('personal');named.ui.startJourney(); +assert.equal(named.els['flow-title'].textContent,'를 할머니 집으로 데려가는 중…'); +settingsName.value=' ';settingsName.dispatch('change');assert.equal(named.els['entry-photo-button'].textContent,'멍멍이 사진 고르기'); +const blockedName=harness(null,{writeError:true});blockedName.els['entry-pet-name'].value='호롱';blockedName.els['entry-pet-name'].dispatch('input'); +assert.equal(blockedName.els['entry-name-notice'].hidden,false);assert.equal(blockedName.els['settings-name-notice'].hidden,false); +assert.equal(blockedName.els['entry-photo-button'].textContent,'호롱이 사진 고르기'); +console.log('Pet name UI: live shared copy, Korean IME, literal HTML-like names, sample origin, clearing, storage warning passed.'); +const longName = harness(); longName.root.activeElement = longName.els['entry-pet-name']; +longName.els['entry-pet-name'].value = '가'.repeat(30); longName.els['entry-pet-name'].dispatch('input'); +assert.equal(longName.els['entry-pet-name'].value, '가'.repeat(20), 'focused field enforces the advertised name length after completed input'); +for (const [root, unavailable] of [[named, false], [blockedName, true]]) { + for (const prefix of ['entry', 'settings']) { + const description = root.els[`${prefix}-pet-name`].attributes['aria-describedby']; + assert.equal(description, `${prefix}-name-help${unavailable ? ` ${prefix}-name-notice` : ''}`, 'screen-reader descriptions include storage failure only when true'); + } +} + +const sampleHome = harness(); +sampleHome.ui.setMediaOrigin('sample'); sampleHome.ui.setPhoto('blob:sample'); sampleHome.ui.setState('ready'); +assert.equal(sampleHome.els['sample-home'].hidden, false); +assert.equal(sampleHome.els['scene-photo-change'].hidden, true); +assert.equal(sampleHome.els['settings-open'].hidden, true); +sampleHome.els['settings-open'].dispatch('click'); +assert.equal(sampleHome.els['settings-dialog'].open, false, 'sample settings cannot be opened by stale clicks'); +sampleHome.els['sample-home'].dispatch('click');sampleHome.els['home-confirm'].dispatch('click'); +assert.equal(sampleHome.homeCalls, 1, 'home invokes media cancellation callback once'); +assert.equal(sampleHome.els.experience.dataset.flow, 'entry'); +assert.equal(sampleHome.els.welcome.hidden, false); +assert.equal(sampleHome.els['sample-home'].hidden, true); +assert.equal(sampleHome.els['settings-open'].hidden, true);assert.equal(sampleHome.els['credits-open'].hidden,false); +assert.equal(sampleHome.els['flow-photo'].src, ''); +assert.equal(sampleHome.root.activeElement, sampleHome.els['entry-photo-button']); +sampleHome.ui.setMediaOrigin('personal'); sampleHome.ui.setState('ready'); +assert.equal(sampleHome.els['scene-photo-change'].hidden, false); +assert.equal(sampleHome.els['sample-home'].hidden, false); +assert.match(html, /placeholder="예시 : 장준"/); +assert.doesNotMatch(html, /placeholder="예: 호롱"|창문 열기/); +console.log('Sample return: own-photo controls restored, sample settings gated, landing focus and placeholder verified.'); + +for (const state of ['loading', 'error']) { + const h = harness(); h.ui.setMediaOrigin('sample'); h.ui.setState(state); + assert.equal(h.els['sample-home'].hidden, false); + assert.equal(h.els['settings-open'].hidden, true); + assert.equal(h.els['scene-photo-change'].hidden, true); + h.els['sample-home'].dispatch('click');h.els['home-confirm'].dispatch('click'); + assert.equal(h.homeCalls, 1); + assert.equal(h.els.experience.dataset.flow, 'entry'); +} +const pasteGate=harness(); +assert.equal(pasteGate.ui.canAcceptPhotoPaste(),false,'name step keeps focus on naming');pasteGate.els['entry-name-skip'].dispatch('click');assert.equal(pasteGate.ui.canAcceptPhotoPaste(),true,'photo step accepts paste'); +pasteGate.ui.setMediaOrigin('sample');pasteGate.ui.setState('ready'); +assert.equal(pasteGate.ui.canAcceptPhotoPaste(),false,'sample presentation cannot bypass hidden replace action'); +pasteGate.els['sample-home'].dispatch('click');pasteGate.els['home-confirm'].dispatch('click');assert.equal(pasteGate.ui.canAcceptPhotoPaste(),true); +pasteGate.els['credits-open'].dispatch('click');assert.equal(pasteGate.ui.canAcceptPhotoPaste(),false); +pasteGate.els['credits-close'].dispatch('click');assert.equal(pasteGate.ui.canAcceptPhotoPaste(),true); +pasteGate.ui.setRenderLost(true);assert.equal(pasteGate.ui.canAcceptPhotoPaste(),false); +pasteGate.ui.setRenderLost(false);pasteGate.abort.abort();assert.equal(pasteGate.ui.canAcceptPhotoPaste(),false); + +const step=harness(); +assert.equal(step.els['entry-name-step'].hidden,false); +assert.equal(step.els['entry-photo-step'].hidden,true);assert.equal(step.els['entry-notices'].hidden,true); +step.els['entry-name-skip'].dispatch('click'); +assert.equal(step.els['entry-name-step'].hidden,true); +assert.equal(step.els['entry-photo-step'].hidden,false);assert.equal(step.els['entry-notices'].hidden,false); +step.ui.setMediaOrigin('sample');step.ui.setState('ready');step.els['sample-home'].dispatch('click');step.els['home-confirm'].dispatch('click'); +assert.equal(step.els['entry-photo-step'].hidden,false,'sample return skips already-completed name step'); +step.els['entry-name-edit'].dispatch('click');assert.equal(step.els['entry-name-step'].hidden,false); +step.els['entry-pet-name'].value='장준';step.els['entry-pet-name'].dispatch('input');step.els['entry-name-next'].dispatch('click'); +assert.equal(step.els['entry-photo-button'].textContent,'장준이 사진 고르기'); +assert.equal(step.els['entry-photo-step'].hidden,false);assert.equal(step.els['entry-notices'].hidden,false); + +const imeStep=harness();imeStep.els['entry-pet-name'].dispatch('compositionstart');imeStep.els['entry-pet-name'].value='누'; +imeStep.els['entry-pet-name'].dispatch('keydown',{key:'Enter',isComposing:false,keyCode:229,preventDefault(){}}); +assert.equal(imeStep.els['entry-name-step'].hidden,false,'IME commit Enter never advances or steals focus'); +imeStep.els['entry-pet-name'].value='누렁';imeStep.els['entry-pet-name'].dispatch('compositionend'); +imeStep.els['entry-pet-name'].dispatch('keydown',{key:'Enter',isComposing:false,keyCode:13,preventDefault(){}}); +assert.equal(imeStep.els['entry-photo-step'].hidden,false); + +const personalHome=harness();personalHome.els['entry-name-skip'].dispatch('click');personalHome.ui.setMediaOrigin('personal');personalHome.ui.setPhoto('blob:own');personalHome.ui.setState('ready'); +assert.equal(personalHome.els['sample-home'].hidden,false,'personal scene also offers home'); +personalHome.els['sample-home'].dispatch('click');personalHome.els['home-confirm'].dispatch('click');assert.equal(personalHome.homeCalls,1);assert.equal(personalHome.els.experience.dataset.flow,'entry');assert.equal(personalHome.els['entry-photo-step'].hidden,false); +const skipVisibility=harness();const nameField=skipVisibility.els['entry-pet-name']; +assert.equal(skipVisibility.els['entry-name-skip'].hidden,false); +nameField.value='장준';nameField.dispatch('input');assert.equal(skipVisibility.els['entry-name-skip'].hidden,true); +nameField.value=' ';nameField.dispatch('input');assert.equal(skipVisibility.els['entry-name-skip'].hidden,false); +nameField.dispatch('compositionstart');nameField.value='장';nameField.dispatch('input',{isComposing:true});assert.equal(skipVisibility.els['entry-name-skip'].hidden,true,'visible composing text hides skip without mutating stored name'); +nameField.value='';nameField.dispatch('compositionend');assert.equal(skipVisibility.els['entry-name-skip'].hidden,false); + +// Main entry has maker details instead of settings, without starting a photo flow. +const credits=harness(); +assert.equal(credits.els['credits-open'].hidden,false); +assert.equal(credits.els['settings-open'].hidden,true);assert.equal(credits.els['scene-photo-change'].hidden,true); +credits.els['entry-name-skip'].dispatch('click'); +credits.els['credits-open'].dispatch('click'); +assert.equal(credits.els['credits-dialog'].open,true); +assert.equal(credits.ui.canAcceptPhotoPaste(),false); +credits.els['credits-dialog'].dispatch('cancel',{preventDefault(){}}); +assert.equal(credits.els['credits-dialog'].open,false); +assert.equal(credits.root.activeElement,credits.els['credits-open']); +credits.els['credits-open'].dispatch('click');credits.ui.setState('loading'); +assert.equal(credits.els['credits-dialog'].open,false); +assert.equal(credits.els['credits-open'].hidden,true); +credits.ui.setState('ready');assert.equal(credits.els['settings-open'].hidden,false); +credits.els['credits-open'].dispatch('click');assert.equal(credits.els['credits-dialog'].open,false); +credits.els['sample-home'].dispatch('click');credits.els['home-confirm'].dispatch('click');assert.equal(credits.els['credits-open'].hidden,false); +credits.els['credits-open'].dispatch('click');credits.abort.abort();assert.equal(credits.els['credits-dialog'].open,false); +assert.match(html, /id="scene-photo-change"[^>]*\bhidden\b/, 'entry markup must not reserve an invisible photo action before JS starts'); +const creditsDismiss=harness(); +creditsDismiss.els['credits-open'].dispatch('click');assert.equal(creditsDismiss.els['credits-dialog'].open,true,'maker works from name entry'); +creditsDismiss.els['credits-open'].dispatch('click');assert.equal(creditsDismiss.els['credits-dialog'].open,true,'repeated click is safe'); +creditsDismiss.els['credits-dialog'].dispatch('click',{clientX:100,clientY:100});assert.equal(creditsDismiss.els['credits-dialog'].open,true,'inside click remains open'); +creditsDismiss.els['credits-dialog'].dispatch('click',{clientX:0,clientY:0});assert.equal(creditsDismiss.els['credits-dialog'].open,false,'backdrop closes'); +creditsDismiss.els['credits-open'].dispatch('click');creditsDismiss.ui.setRenderLost(true);assert.equal(creditsDismiss.els['credits-dialog'].open,false); +creditsDismiss.els['credits-open'].dispatch('click');assert.equal(creditsDismiss.els['credits-dialog'].open,false,'render-loss guards reopen'); +assert.match(html,/href="mailto:sunha321@gmail.com"/);assert.match(html,/

horoli<\/dd>/); + +const firstArrival=harness();firstArrival.ui.setPhoto('blob:dog');firstArrival.ui.startJourney();firstArrival.ui.setState('ready'); +assert.equal(firstArrival.arrivalEnds,1,'immediate/reduced arrival notifies onboarding once');assert.equal(firstArrival.ui.canShowFirstGuide(),true); +firstArrival.els['first-guide'].showModal();firstArrival.ui.refreshBlocking();assert.equal(firstArrival.ui.isBlocked(),true);assert.equal(firstArrival.ui.canAcceptPhotoPaste(),false);assert.equal(firstArrival.ui.canExportPhoto(),false); +firstArrival.ui.setState('loading');assert.equal(firstArrival.els['first-guide'].open,false); +firstArrival.ui.setMediaOrigin('sample');firstArrival.ui.setState('ready');assert.equal(firstArrival.ui.canShowFirstGuide(),false); +firstArrival.ui.setMediaOrigin('personal');firstArrival.els['theme-select'].value='booth';firstArrival.els['theme-select'].dispatch('change');assert.equal(firstArrival.ui.canShowFirstGuide(),false); +const timedGuide=harness();const guideTimers=new Map();let guideTimerId=0; +timedGuide.root.defaultView.setTimeout=(fn,ms)=>{guideTimers.set(++guideTimerId,{fn,ms});return guideTimerId;};timedGuide.root.defaultView.clearTimeout=id=>guideTimers.delete(id); +timedGuide.ui.setPhoto('blob:dog');timedGuide.ui.startJourney();timedGuide.ui.setState('ready'); +assert.equal(timedGuide.arrivalEnds,0);assert.equal(timedGuide.ui.canShowFirstGuide(),false); +let guideTimer=[...guideTimers.entries()][0];assert.equal(guideTimer[1].ms,1350);guideTimers.delete(guideTimer[0]);guideTimer[1].fn();assert.equal(timedGuide.arrivalEnds,0); +guideTimer=[...guideTimers.entries()][0];assert.equal(guideTimer[1].ms,1500);guideTimers.delete(guideTimer[0]);guideTimer[1].fn();assert.equal(timedGuide.arrivalEnds,1);assert.equal(timedGuide.ui.canShowFirstGuide(),true); +timedGuide.ui.setPhoto('blob:next');timedGuide.ui.startJourney();timedGuide.ui.setState('ready');timedGuide.els['settings-open'].dispatch('click'); +assert.equal(timedGuide.arrivalEnds,1,'interrupting arrival never opens a guide beneath another modal');assert.equal(guideTimers.size,0); + +const menu = harness(); +assert.equal(menu.els['scene-menu-open'].hidden,true,'entry uses credits, not scene menu'); +menu.ui.setState('ready');menu.els['scene-menu-open'].dispatch('click'); +assert.equal(menu.els['scene-menu'].open,true,'scene menu opens'); +assert.equal(menu.ui.isBlocked(),true,'scene input is blocked behind menu'); +assert.equal(menu.ui.canAcceptPhotoPaste(),false,'menu blocks paste'); +assert.equal(menu.ui.canExportPhoto(),true,'menu must not disable export eligibility'); +menu.els['scene-menu'].dispatch('cancel',{preventDefault(){}}); +assert.equal(menu.els['scene-menu'].open,false);assert.equal(menu.root.activeElement,menu.els['scene-menu-open']); +menu.els['scene-menu-open'].dispatch('click');menu.els['settings-open'].dispatch('click'); +assert.equal(menu.els['scene-menu'].open,false);assert.equal(menu.els['settings-dialog'].open,true); +menu.els['settings-close'].dispatch('click');assert.equal(menu.root.activeElement,menu.els['scene-menu-open']); +for (const state of ['loading','error']) { + menu.ui.setState(state);menu.els['scene-menu-open'].dispatch('click');assert.equal(menu.els['scene-menu'].open,true); + menu.ui.setState('ready');assert.equal(menu.els['scene-menu'].open,false); +} +menu.els['scene-menu-open'].dispatch('click');menu.ui.setRenderLost(true);assert.equal(menu.els['scene-menu'].open,false); +menu.els['scene-menu-open'].dispatch('click');assert.equal(menu.els['scene-menu'].open,false); +menu.ui.setRenderLost(false);menu.els['scene-menu-open'].dispatch('click');menu.abort.abort();assert.equal(menu.els['scene-menu'].open,false); +const toolbar=html.match(/
/)[0]; +for(const id of ['scene-photo-change','export-open','settings-open','scene-zoom-reset'])assert.ok(!toolbar.includes('id="'+id+'"'),'secondary action removed from header: '+id); +assert.ok(toolbar.includes('id="scene-menu-open"')); +console.log('Scene menu: lifecycle, blocking, action handoff, focus and reduced header passed.'); +const repeatMenu=harness();repeatMenu.ui.setState('ready'); +repeatMenu.els['scene-menu-open'].dispatch('click');repeatMenu.els['scene-menu-open'].dispatch('click'); +repeatMenu.els['scene-menu-close'].dispatch('click');repeatMenu.els['scene-menu-open'].dispatch('click'); +repeatMenu.els['scene-menu'].dispatch('close');assert.equal(repeatMenu.els['scene-menu'].open,true);assert.equal(repeatMenu.els['scene-menu-open'].attributes['aria-expanded'],'true'); +repeatMenu.els['scene-menu'].dispatch('click',{clientX:0,clientY:0});assert.equal(repeatMenu.els['scene-menu'].open,false); +for(const action of ['scene-photo-change','export-open','scene-zoom-reset','scene-guide-replay']){ + repeatMenu.els['scene-menu-open'].dispatch('click');repeatMenu.els[action].dispatch('click');assert.equal(repeatMenu.els['scene-menu'].open,false,action+' closes the sheet synchronously'); +} +repeatMenu.ui.setMediaOrigin('sample');repeatMenu.els['scene-menu-open'].dispatch('click'); +for(const action of ['scene-photo-change','export-open','settings-open','scene-guide-replay'])assert.equal(repeatMenu.els[action].hidden,true); +repeatMenu.els['sample-home'].dispatch('click');repeatMenu.els['home-confirm'].dispatch('click');assert.equal(repeatMenu.els['scene-menu'].open,false);assert.equal(repeatMenu.els['scene-menu-open'].hidden,true);assert.equal(repeatMenu.root.activeElement,repeatMenu.els['entry-photo-button']); +const loadingActions=harness(); +for(const origin of ['personal','sample']){ + loadingActions.ui.setMediaOrigin(origin); + for(const state of ['entry','loading','ready']){ + loadingActions.ui.setState(state);assert.equal(loadingActions.els['flow-actions'].hidden,true,'no replacement action in '+state); + } + loadingActions.ui.setState('error',true);assert.equal(loadingActions.els['flow-actions'].hidden,false,'error keeps recovery actions'); + assert.equal(loadingActions.els['flow-retry'].hidden,false); +} +const publicSettings=html.match(//)[0]; +assert.ok(!publicSettings.includes('id="camera-composition"'),'window composition is not a consumer setting'); +assert.ok(html.indexOf('id="camera-composition"')>html.indexOf('id="internal-controls"'),'retain hidden rollback adapter without changing saved camera'); +assert.ok(!html.includes('익숙한 유리문 너머에서 만나보세요'),'redundant landing introduction removed'); +assert.ok(!html.includes('id="welcome-pet-copy"'),'removed introduction has no live name binding'); + +const edit=harness();edit.ui.setState('ready'); +assert.equal(typeof edit.ui.startPhotoAdjust,'function');edit.ui.startPhotoAdjust(); +assert.equal(edit.ui.isPhotoAdjusting(),true);assert.equal(edit.ui.isBlocked(),false);assert.equal(edit.els['canvas-wrap'].inert,false); +assert.equal(edit.ui.canShowFirstGuide(),false);assert.equal(edit.ui.canAcceptPhotoPaste(),false);assert.equal(edit.ui.canExportPhoto(),false); +edit.els['photo-adjust-done'].dispatch('click');assert.equal(edit.ui.isPhotoAdjusting(),false); +edit.ui.setMediaOrigin('sample');edit.ui.startPhotoAdjust();assert.equal(edit.ui.isPhotoAdjusting(),true,'sample edit supported'); +edit.root.dispatch('keydown',{key:'Escape',preventDefault(){}});assert.equal(edit.ui.isPhotoAdjusting(),false); +edit.ui.startPhotoAdjust();edit.els['scene-menu-open'].dispatch('click');assert.equal(edit.ui.isPhotoAdjusting(),false);edit.els['scene-menu-close'].dispatch('click'); +edit.ui.startPhotoAdjust();edit.els['sample-home'].dispatch('click');assert.equal(edit.ui.isPhotoAdjusting(),false);assert.equal(edit.homeCalls,0);assert.equal(edit.els['home-dialog'].open,true); +edit.els['home-cancel'].dispatch('click');assert.equal(edit.els['home-dialog'].open,false);assert.equal(edit.root.activeElement,edit.els['sample-home']);assert.equal(edit.els.experience.dataset.flow,'ready'); +edit.els['sample-home'].dispatch('click');edit.els['home-confirm'].dispatch('click');assert.equal(edit.homeCalls,1);assert.equal(edit.els.experience.dataset.flow,'entry'); +for(const transition of ['state','photo','origin','loss','abort']){ + const e=harness();e.ui.setState('ready');e.ui.startPhotoAdjust(); + if(transition==='state')e.ui.setState('loading');if(transition==='photo')e.ui.setPhoto('blob:new');if(transition==='origin')e.ui.setMediaOrigin('sample');if(transition==='loss')e.ui.setRenderLost(true);if(transition==='abort')e.abort.abort(); + assert.equal(e.ui.isPhotoAdjusting(),false,transition+' exits photo edit'); +} +const askHome=harness();askHome.ui.setMediaOrigin('sample');askHome.ui.setPhoto('blob:unchanged');askHome.ui.setState('loading'); +askHome.els['sample-home'].dispatch('click');askHome.els['sample-home'].dispatch('click');assert.equal(askHome.homeCalls,0); +askHome.els['home-dialog'].dispatch('cancel',{preventDefault(){}});assert.equal(askHome.els['flow-photo'].src,'blob:unchanged');assert.equal(askHome.els.experience.dataset.flow,'loading');assert.equal(askHome.homeCalls,0); +askHome.els['sample-home'].dispatch('click');askHome.els['home-dialog'].dispatch('click',{clientX:0,clientY:0});assert.equal(askHome.els['home-dialog'].open,false); +askHome.els['sample-home'].dispatch('click');askHome.ui.setState('ready');askHome.els['home-confirm'].dispatch('click');assert.equal(askHome.homeCalls,0,'stale confirmation after new state cannot navigate'); +askHome.els['sample-home'].dispatch('click');askHome.els['home-dialog'].dispatch('close');assert.equal(askHome.els['home-dialog'].open,true,'old close event cannot close a new confirmation'); +askHome.ui.setRenderLost(true);assert.equal(askHome.els['home-dialog'].open,false); +assert.match(toolbar,/id="sample-home"[^>]*aria-label="첫 화면으로 가기"/); +assert.ok(!html.match(//)[0].includes('id="sample-home"')); +assert.ok(!html.match(//)[0].includes('id="photo-adjust-open"')); diff --git a/scripts/test-experimental-courtyard.mjs b/scripts/test-experimental-courtyard.mjs new file mode 100644 index 0000000..b652b37 --- /dev/null +++ b/scripts/test-experimental-courtyard.mjs @@ -0,0 +1,144 @@ +import {test} from 'node:test'; +/** CPU geometry/ray contract checks; these do not execute GLSL or verify WebGL pixels. */ +import assert from 'node:assert/strict'; +import { existsSync } from 'node:fs'; +import * as THREE from 'three'; + +const source = new URL('../src/objects/ExperimentalCourtyard.ts', import.meta.url); +assert.ok(existsSync(source), 'the opt-in courtyard module must exist'); +const { ExperimentalCourtyard, createCourtyardUniforms, createCourtyardLayout, courtyardShader, courtyardSurfaceShader } = await import(source); +assert.equal(typeof createCourtyardUniforms, 'function', 'B needs independent default-disabled uniforms before a courtyard exists'); +const defaults = createCourtyardUniforms(); +assert.equal(defaults.uYardEnabled.value, 0); +assert.notEqual(defaults.uYardBoxMin.value, createCourtyardUniforms().uYardBoxMin.value); + +// Independent slab traversal matching the shader, compared with actual raster triangles. +function intersectBoxes(layout, origin, ray) { + let closest = null; + for (const box of layout) { + let near = -1e20, far = 1e20, nearAxis = -1, farAxis = -1; + let missed = false; + for (let axis = 0; axis < 3; axis++) { + const p = origin.getComponent(axis), d = ray.getComponent(axis); + if (Math.abs(d) < 1e-8) { + if (p < box.min[axis] || p > box.max[axis]) missed = true; + continue; + } + const a = (box.min[axis] - p) / d, b = (box.max[axis] - p) / d; + if (Math.min(a, b) > near) { near = Math.min(a, b); nearAxis = axis; } + if (Math.max(a, b) < far) { far = Math.max(a, b); farAxis = axis; } + } + if (missed || near > far || far < 1e-5) continue; + const outside = near >= 1e-5, distance = outside ? near : far; + const axis = outside ? nearAxis : farAxis; + const normal = new THREE.Vector3().setComponent(axis, Math.sign(ray.getComponent(axis)) * (outside ? -1 : 1)); + if (!closest || distance < closest.distance) closest = { distance, normal, box }; + } + return closest; +} + +const yard = new ExperimentalCourtyard(); +assert.equal(yard.group.visible, false, 'ordinary photo mode must not show the courtyard'); +assert.equal(yard.uniforms.uYardEnabled.value, 0); +assert.equal(yard.group.children.length, 1, 'all courtyard surfaces must share one draw'); +const mesh = yard.group.children[0]; +assert.ok(mesh.isMesh); +assert.equal(mesh.material.uniforms, yard.uniforms, 'raster and B must share live uniform objects'); +assert.equal(mesh.material.side, THREE.DoubleSide, 'inside-box hits must match the double-sided raster geometry'); +assert.equal(mesh.material.lights, false); +assert.ok(mesh.material.fragmentShader.includes(courtyardSurfaceShader)); +assert.ok(courtyardShader.includes(courtyardSurfaceShader), 'direct and refracted colors need identical source'); +assert.match(courtyardShader, /bool bCourtyardHit\(vec3 origin,\s*vec3 ray,\s*out float distance,\s*out vec3 color\)/); +assert.ok(!yard.group.children.some(object => object.isLight)); + +const uniformIdentities = Object.fromEntries(Object.entries(yard.uniforms).map(([key, uniform]) => [key, uniform])); +let seed = 291; +const random = () => ((seed = Math.imul(seed, 1664525) + 1013904223 | 0) >>> 0) / 4294967296; +let rays = 0, hits = 0, maxError = 0; +for (const [width, height] of [[.9, 1.4], [1.8, 1.1], [2.8, .35], [.3, 2.2]]) { + const glassZ = .6; + yard.resize(width, height, glassZ); + yard.setEnabled(true); + yard.group.updateMatrixWorld(true); + const layout = createCourtyardLayout(width, height, glassZ); + assert.ok(layout.length <= 16); + assert.equal(mesh.geometry.getAttribute('position').count, layout.length * 36); + assert.equal(mesh.geometry.groups.length, 0, 'merged geometry must not preserve per-box draw groups'); + const floor = layout.find(box => box.name === 'ground'); + assert.ok(Math.abs(floor.max[1] - (-height / 2 - .1 * Math.min(width, height))) < 1e-10); + assert.ok(Math.abs(layout.find(box => box.name === 'boundary-wall').max[2] - (glassZ - 3 * height)) < 1e-10); + assert.ok(layout.find(box => box.name === 'wood-platform').max[0] < 0, 'the dog foreground on the right stays clear'); + for (let boxIndex = 0; boxIndex < layout.length; boxIndex++) { + const box = layout[boxIndex]; + assert.deepEqual(yard.uniforms.uYardBoxMin.value[boxIndex].toArray(), box.min); + assert.deepEqual(yard.uniforms.uYardBoxMax.value[boxIndex].toArray(), box.max); + assert.equal(yard.uniforms.uYardBoxKind.value[boxIndex], box.kind); + assert.ok(box.max[2] < glassZ, `${box.name} must be outside the glass`); + assert.ok(box.min.every((min, axis) => min < box.max[axis])); + } + const cases = []; + // Exit rays from glass, side/under views, both signs and exactly parallel slabs. + for (let i = 0; i < 1600; i++) { + cases.push([ + new THREE.Vector3((random() - .5) * width * 4, (random() - .5) * height * 3, glassZ + (random() - .7) * height * 5), + new THREE.Vector3(random() - .5, random() - .5, random() - .5).normalize() + ]); + } + for (const box of layout) { + const center = new THREE.Vector3().fromArray(box.min).add(new THREE.Vector3().fromArray(box.max)).multiplyScalar(.5); + for (let axis = 0; axis < 3; axis++) for (const sign of [-1, 1]) { + cases.push([center, new THREE.Vector3().setComponent(axis, sign)]); + const surface = center.clone().setComponent(axis, sign < 0 ? box.min[axis] : box.max[axis]); + cases.push([surface.clone().addScaledVector(new THREE.Vector3().setComponent(axis, sign), height), new THREE.Vector3().setComponent(axis, -sign)]); + } + } + for (const [origin, direction] of cases) { + const intersections = new THREE.Raycaster(origin, direction, 1e-5).intersectObject(mesh, false); + const expected = intersections[0]; + const actual = intersectBoxes(layout, origin, direction); + assert.equal(Boolean(actual), Boolean(expected), `hit mismatch at ray ${rays}`); + if (expected) { + const error = Math.abs(expected.distance - actual.distance); + maxError = Math.max(error, maxError); + assert.ok(error < 5e-5, `nearest distance mismatch ${error} at ray ${rays}`); + // Box junctions have coincident inward/outward faces. Float32 mesh bounds can reverse their tie order. + assert.ok(intersections.some(hit => Math.abs(hit.distance - actual.distance) < 5e-5 && actual.normal.dot(hit.face.normal) > .999), `outward normal mismatch at ray ${rays}`); + hits++; + } + rays++; + } + for (const [key, uniform] of Object.entries(uniformIdentities)) assert.equal(yard.uniforms[key], uniform, `${key} identity must survive resize`); +} + +const previousGeometry = mesh.geometry; +let replacedDisposed = 0; +previousGeometry.addEventListener('dispose', () => replacedDisposed++); +yard.resize(1, 1, .6); +assert.equal(replacedDisposed, 1, 'resize must release replaced geometry'); +yard.setEnabled(false); +assert.equal(yard.group.visible, false); +assert.equal(yard.uniforms.uYardEnabled.value, 0); +yard.setEnabled(true); +assert.equal(yard.group.visible, true); +assert.equal(yard.uniforms.uYardEnabled.value, 1); +assert.throws(() => yard.resize(0, 1, .6), /positive/); +assert.throws(() => yard.resize(1, NaN, .6), /finite/); +assert.throws(() => yard.resize(1, 1, Infinity), /finite/); +const scene = new THREE.Scene(); +scene.add(yard.group); +let geometryDisposed = 0, materialDisposed = 0; +mesh.geometry.addEventListener('dispose', () => geometryDisposed++); +mesh.material.addEventListener('dispose', () => materialDisposed++); +yard.dispose(); +yard.dispose(); +assert.equal(geometryDisposed, 1); +assert.equal(materialDisposed, 1); +assert.equal(yard.group.parent, null); +assert.equal(yard.uniforms.uYardEnabled.value, 0); +console.log(JSON.stringify({ test: 'ExperimentalCourtyard CPU geometry/analytic ray contract', rays, hits, maxError, boxes: yard.uniforms.uYardBoxMin.value.length, draws: 1, webglPixels: 'not tested' })); + +test('optional dog contact shadow uses the shared yard shader without another mesh or pass',()=>{ + const yard=new ExperimentalCourtyard();yard.setDogContact(.2,.35,.12,.6); + assert.deepEqual(yard.uniforms.uYardDogContact.value.toArray(),[.2,.35,.12,.6]); + assert.equal(yard.group.children.length,1);assert.match(yard.group.children[0].material.fragmentShader,/uYardDogContact/);assert.match(courtyardShader,/uYardDogContact/);yard.dispose(); +}); diff --git a/scripts/test-export-ui.mjs b/scripts/test-export-ui.mjs new file mode 100644 index 0000000..cc76f09 --- /dev/null +++ b/scripts/test-export-ui.mjs @@ -0,0 +1,47 @@ +import {test} from 'node:test'; +import assert from 'node:assert/strict'; +import {loadTypescript} from './support/load-typescript.mjs'; +class El extends EventTarget { + hidden=false;disabled=false;open=false;attrs={};textContent='';isConnected=true;dataset={}; + setAttribute(k,v){this.attrs[k]=v;}removeAttribute(k){delete this.attrs[k];} + focus(){this.focused=true;}showModal(){this.open=true;}close(){this.open=false;this.dispatchEvent(new Event('close'));} + fire(type,values={}){const e=new Event(type,{cancelable:true});Object.assign(e,values);this.dispatchEvent(e);} + getBoundingClientRect(){return {left:10,right:100,top:10,bottom:100};} +} +async function harness(){ + const {initExportUI}=await loadTypescript(new URL('../src/ui/ExportUI.ts',import.meta.url)); + const ids=['scene-menu-open','export-open','export-dialog','export-close','export-photo','export-scene','export-preview','export-status','export-download','export-share']; + const els=Object.fromEntries(ids.map(id=>[id,new El()]));const revoked=[],pending=[];let allowed=true; + const root={querySelector:s=>els[s.slice(1)],defaultView:{URL:{createObjectURL:()=>`blob:${pending.length}`,revokeObjectURL:url=>revoked.push(url)},navigator:{}}}; + const abort=new AbortController();const ui=initExportUI(root,abort.signal,()=>allowed,(kind,signal)=>new Promise((resolve,reject)=>pending.push({kind,signal,resolve,reject})),()=>{}); + return {els,pending,revoked,abort,ui,nav:root.defaultView.navigator,setAllowed:v=>allowed=v}; +} +const tick=()=>new Promise(r=>setTimeout(r,0)); +test('export is opt-in, repeated capture is ignored, preview is ready before saving',async()=>{ + const h=await harness();assert.equal(h.pending.length,0);h.els['export-open'].fire('click');assert.equal(h.els['export-dialog'].open,true); + h.els['export-photo'].fire('click');h.els['export-photo'].fire('click');assert.equal(h.pending.length,1);assert.equal(h.pending[0].kind,'photo'); + h.pending[0].resolve(new Blob(['png'],{type:'image/png'}));await tick();assert.equal(h.els['export-download'].hidden,false);assert.equal(h.els['export-preview'].src,'blob:1'); + h.els['export-close'].fire('click');assert.deepEqual(h.revoked,['blob:1']);assert.equal(h.els['export-dialog'].open,false); +}); +test('cancel and abort suppress stale PNG and revoke results',async()=>{ + const h=await harness();h.els['export-open'].fire('click');h.els['export-scene'].fire('click');h.els['export-dialog'].fire('cancel'); + assert.equal(h.pending[0].signal.aborted,true);h.pending[0].resolve(new Blob(['png']));await tick();assert.equal(h.els['export-download'].hidden,true); + h.els['export-open'].fire('click');h.els['export-photo'].fire('click');h.abort.abort();assert.equal(h.pending[1].signal.aborted,true);assert.equal(h.els['export-dialog'].open,false); +}); +test('unavailable scene cannot open or start export; recoverable errors remain retryable',async()=>{ + const h=await harness();h.setAllowed(false);h.els['export-open'].fire('click');assert.equal(h.els['export-dialog'].open,false); + h.setAllowed(true);h.els['export-open'].fire('click');h.els['export-photo'].fire('click');h.pending[0].reject(new Error('try again'));await tick();assert.equal(h.els['export-photo'].disabled,false);assert.match(h.els['export-status'].textContent,/try again/); +}); + +test('interrupting a native share does not disable sharing the next preview',async()=>{ + const h=await harness();let finish;h.nav.canShare=()=>true;h.nav.share=()=>new Promise(resolve=>finish=resolve); + h.els['export-open'].fire('click');h.els['export-photo'].fire('click');h.pending[0].resolve(new Blob(['png']));await tick(); + h.els['export-share'].fire('click');assert.equal(h.els['export-share'].disabled,true); + h.els['export-close'].fire('click');h.els['export-open'].fire('click');h.els['export-photo'].fire('click');h.pending[1].resolve(new Blob(['png']));await tick(); + finish();await tick();assert.equal(h.els['export-share'].disabled,false);assert.equal(h.els['export-share'].hidden,false); +}); + + test('export dismissal restores focus to visible scene menu, not the hidden sheet action',async()=>{ + const h=await harness();h.els['export-open'].fire('click');h.els['export-close'].fire('click'); + assert.equal(h.els['scene-menu-open'].focused,true);assert.notEqual(h.els['export-open'].focused,true); + }); diff --git a/scripts/test-first-guide.mjs b/scripts/test-first-guide.mjs new file mode 100644 index 0000000..1ab25f5 --- /dev/null +++ b/scripts/test-first-guide.mjs @@ -0,0 +1,47 @@ +import assert from 'node:assert/strict'; +import {test} from 'node:test'; +import {loadTypescript} from './support/load-typescript.mjs'; +class El extends EventTarget {open=false;inert=false;hidden=false;textContent='';focus(){}show(){this.open=true;}close(){this.open=false;this.dispatchEvent(new Event('close'));}setAttribute(){}removeAttribute(){}getBoundingClientRect(){return {width:100,height:44};}closest(){return this.hidden?this:null;}fire(t){this.dispatchEvent(new Event(t,{cancelable:true}));}} +async function harness(mobile=false,saved={},throws=false){ + const {initFirstGuide}=await loadTypescript(new URL('../src/ui/FirstGuide.ts',import.meta.url)); + const ids=['first-guide','experience','guide-scene-target','door-toggle','gyro','gyro-recenter'];const els=Object.fromEntries(ids.map(id=>[id,new El()]));let eligible=true;const values=new Map(Object.entries(saved)),writes=[],tours=[]; + const view=new El();Object.defineProperty(view,'localStorage',{get(){if(throws)throw Error('blocked');return {getItem:k=>values.get(k)??null,setItem:(k,v)=>{writes.push(k);values.set(k,v);}};}});view.matchMedia=()=>({matches:true});view.visualViewport=new El(); + const root={querySelector:s=>els[s.slice(1)],defaultView:view}; + const factory=config=>{let index=0,active=false;const tour={config,drive(){active=true;},isActive:()=>active,isLastStep:()=>index===config.steps.length-1,moveNext(){index++;},getActiveIndex:()=>index,refresh(){tour.refreshed=true;},destroy(){if(!active)return;active=false;config.onDestroyed?.();}};tours.push(tour);return tour;}; + const abort=new AbortController();const guide=initFirstGuide(root,abort.signal,mobile,()=>eligible,()=>{},factory); + return {els,guide,abort,writes,tours,view,values,setEligible:v=>eligible=v}; +} +test('mobile driver tour highlights actual controls, blocks actions, and finishes once',async()=>{ + const h=await harness(true);h.guide.start();const t=h.tours[0];assert.equal(h.els['first-guide'].open,true);assert.equal(h.els.experience.inert,true); + assert.deepEqual(t.config.steps.map(s=>s.element()),[h.els['guide-scene-target'],h.els['door-toggle'],h.els.gyro]); + assert.equal(t.config.disableActiveInteraction,true);assert.equal(t.config.overlayClickBehavior,'none');assert.equal(t.config.animate,false); + t.config.onNextClick();t.config.onNextClick();assert.equal(h.writes.length,0);t.config.onNextClick();assert.equal(h.writes.length,1);assert.equal(h.els.experience.inert,false);h.guide.start();assert.equal(h.tours.length,1); +}); +test('desktop has two steps; previous completion suppresses auto tour but replay works',async()=>{ + const h=await harness(false,{'behind-glass.first-guide.v1':'1'});h.guide.start();assert.equal(h.tours.length,0);h.guide.start(true);assert.equal(h.tours[0].config.steps.length,2);h.tours[0].config.onCloseClick();assert.equal(h.els['first-guide'].open,false); +}); +test('external close and abort do not save completion; explicit Escape does',async()=>{ + const h=await harness();h.setEligible(false);h.guide.start();assert.equal(h.tours.length,0);h.setEligible(true);h.guide.start();h.els['first-guide'].close();assert.equal(h.writes.length,0);assert.equal(h.els.experience.inert,false); + h.guide.start();h.tours[1].config.onDestroyStarted();assert.equal(h.writes.length,1); + const a=await harness();a.guide.start();a.abort.abort();assert.equal(a.els['first-guide'].open,false);assert.equal(a.writes.length,0);a.guide.start();assert.equal(a.tours.length,1); +}); +test('recenter hint is contextual, mobile-only and independently once-per-browser',async()=>{ + const h=await harness(true,{'behind-glass.first-guide.v1':'1'});h.els['gyro-recenter'].hidden=true;h.guide.recenter();assert.equal(h.tours.length,0);h.els['gyro-recenter'].hidden=false;h.guide.recenter();assert.equal(h.tours[0].config.steps.length,1);h.tours[0].config.onNextClick();assert.ok(h.values.has('behind-glass.recenter-guide.v1'));h.guide.recenter();assert.equal(h.tours.length,1); + const pc=await harness(false,{'behind-glass.first-guide.v1':'1'});pc.guide.recenter();assert.equal(pc.tours.length,0); +}); +test('storage denial is session-only, missing targets resolve undefined, viewport changes refresh active tour',async()=>{ + const h=await harness(true,{},true);h.guide.start();h.els['door-toggle'].hidden=true;assert.equal(h.tours[0].config.steps[1].element(),undefined);h.view.visualViewport.fire('resize');assert.equal(h.tours[0].refreshed,true);h.tours[0].config.onCloseClick();h.guide.start();assert.equal(h.tours.length,1); +}); + +test('cleanup still runs when Driver destroys before its first RAF without onDestroyed',async()=>{ + const h=await harness();h.guide.start();h.tours[0].destroy=()=>{};h.abort.abort();assert.equal(h.els.experience.inert,false);assert.equal(h.els['first-guide'].open,false);assert.equal(h.writes.length,0); +}); +test('queued close from prior run cannot cancel a newer replay',async()=>{ + const h=await harness();h.guide.start();h.els['first-guide'].close();h.guide.start(true);h.els['first-guide'].fire('close');assert.equal(h.els['first-guide'].open,true);assert.equal(h.els.experience.inert,true); +}); +test('spotlight popover keeps arrows outside scroll clipping and colors the correct edge',async()=>{ + const {readFile}=await import('node:fs/promises');const css=await readFile(new URL('../src/style.css',import.meta.url),'utf8'); + assert.match(css,/\.behind-glass-tour\s*\{[^}]*overflow:visible/); + assert.match(css,/arrow-side-top\s*\{\s*border-top-color:var\(--cream\)/); + assert.match(css,/arrow-side-bottom\s*\{\s*border-bottom-color:var\(--cream\)/); +}); diff --git a/scripts/test-glass-controls.mjs b/scripts/test-glass-controls.mjs new file mode 100644 index 0000000..6378437 --- /dev/null +++ b/scripts/test-glass-controls.mjs @@ -0,0 +1,37 @@ +import assert from 'node:assert/strict'; +import { readFile } from 'node:fs/promises'; +import { test } from 'node:test'; + +const html = await readFile(new URL('../index.html', import.meta.url), 'utf8'); +const range = id => { + const input = html.match(new RegExp(`]*\\bid="${id}"[^>]*>`))?.[0]; + assert.ok(input, `${id} is a real HTML input`); + return Object.fromEntries([...input.matchAll(/([\w-]+)="([^"]*)"/g)].map(([, key, value]) => [key, value])); +}; + +test('photo distance defaults to 16 within the original 0–21 percent range', () => { + const input = range('photo-glass-distance'); + assert.deepEqual([input.type, input.min, input.max, input.step, input.value], ['range', '0', '21', '1', '16']); + assert.match(html, /16%<\/output>/); + assert.doesNotMatch(html, /100% 멀어짐/); +}); + +test('camera offset exposes 0.35–0.90 with the gentler 0.75 default', () => { + const input = range('camera-offset'); + assert.deepEqual([input.type, input.min, input.max, input.step, input.value], ['range', '0.35', '0.90', '0.01', '0.75']); +}); + +test('curvature offers exactly convex and concave with convex selected', () => { + const select = html.match(/]*\bid="curvature"[^>]*>([\s\S]*?)<\/select>/)?.[1]; + assert.ok(select, 'curvature is a select rather than a continuous slider'); + const options = [...select.matchAll(/]*)>([^<]*)<\/option>/g)]; + assert.equal(options.length, 2); + assert.deepEqual(options.map(([, attrs, label]) => [attrs.match(/value="([^"]+)"/)?.[1], label]), [['1', '볼록'], ['-1', '오목']]); + assert.match(options[0][1], /\bselected\b/); + assert.doesNotMatch(options[1][1], /\bselected\b/); + assert.doesNotMatch(html, /id="curvatureOut"/); +}); + +test('the gloss slider and its output are removed from the DOM', () => { + assert.doesNotMatch(html, /id="gloss-strength"|id="glossOut"/); +}); diff --git a/scripts/test-gyro-controller.mjs b/scripts/test-gyro-controller.mjs new file mode 100644 index 0000000..9941b44 --- /dev/null +++ b/scripts/test-gyro-controller.mjs @@ -0,0 +1,173 @@ +import assert from 'node:assert/strict'; +import { readFile } from 'node:fs/promises'; +import { test } from 'node:test'; +import ts from 'typescript'; +const source = await readFile(new URL('../src/input/GyroController.ts', import.meta.url), 'utf8'); +const compiled = ts.transpileModule(source, { compilerOptions: { target: ts.ScriptTarget.ES2020, module: ts.ModuleKind.ES2020 } }).outputText; +const { GyroController } = await import(`data:text/javascript;base64,${Buffer.from(compiled).toString('base64')}`); +class Events { + listeners = new Map(); + addEventListener(type, fn) { if (!this.listeners.has(type)) this.listeners.set(type, new Set()); this.listeners.get(type).add(fn); } + removeEventListener(type, fn) { this.listeners.get(type)?.delete(fn); } + emit(type, data = {}) { for (const fn of [...(this.listeners.get(type) ?? [])]) fn(data); } + count(type) { return this.listeners.get(type)?.size ?? 0; } +} +function setup({ secure = true, permission, supported = true, angle = 0 } = {}) { + const win = new Events(), doc = new Events(), orientation = new Events(); + const timers = new Map(); let next = 0; + Object.assign(win, { isSecureContext: secure, screen: { orientation }, setTimeout: fn => { timers.set(++next, fn); return next; }, clearTimeout: id => timers.delete(id) }); + orientation.angle = angle; doc.hidden = false; + if (supported) win.DeviceOrientationEvent = permission ? { requestPermission: permission } : {}; + globalThis.window = win; globalThis.document = doc; + const view = { x: .2, y: -.1 }, values = [], states = []; + const gyro = new GyroController((x, y) => { Object.assign(view, { x, y }); values.push([x, y]); }, (state, message) => states.push({ state, message }), () => ({ ...view })); + return { gyro, win, doc, orientation, view, values, states, timers, + reading: (beta = 0, gamma = 0, alpha = 0) => win.emit('deviceorientation', { beta, gamma, alpha }), + expire: () => { const callbacks = [...timers.values()]; timers.clear(); callbacks.forEach(fn => fn()); } }; +} +const near = (actual, expected, tolerance = 1e-10) => assert.ok(Math.abs(actual - expected) < tolerance, `${actual} != ${expected}`); +test('no automatic permission request; toggle calls permission synchronously in gesture', async () => { + let calls = 0; const s = setup({ permission: () => { calls++; return Promise.resolve('granted'); } }); + assert.equal(calls, 0); assert.equal(s.win.count('deviceorientation'), 0); + const starting = s.gyro.toggle(); assert.equal(calls, 1); await starting; + assert.equal(s.gyro.state, 'waiting'); s.reading(45, 8, 180); + assert.equal(s.gyro.state, 'active'); assert.deepEqual(s.values.at(-1), [0, 0]); + s.gyro.dispose(); assert.equal(s.timers.size, 0); +}); +test('insecure and unsupported contexts, denial, and permission errors leave drag fallback', async () => { + for (const options of [{ secure: false }, { supported: false }, { permission: async () => 'denied' }, { permission: () => { throw Error('Blocked'); } }]) { + const s = setup(options); await s.gyro.toggle(); assert.equal(s.gyro.state, 'unavailable'); + assert.match(s.states.at(-1).message, /드래그/); assert.equal(s.win.count('deviceorientation'), 0); assert.deepEqual(s.values, []); + s.gyro.dispose(); + } +}); +test('only finite full orientation samples activate; no-data timeout cleans listeners', async () => { + const s = setup(); await s.gyro.toggle(); + for (const [beta, gamma, alpha] of [[null, 0, 0], [0, NaN, 0], [0, 0, Infinity], [0, 0, null], [Infinity, 0, 0]]) s.reading(beta, gamma, alpha); + assert.equal(s.gyro.state, 'waiting'); assert.deepEqual(s.values, []); s.expire(); + assert.equal(s.gyro.state, 'unavailable'); assert.match(s.states.at(-1).message, /드래그/); assert.equal(s.win.count('deviceorientation'), 0); +}); +test('relative tilt is limited, orientation compensated, and starts at neutral', async () => { + for (const angle of [0, 90, 180, 270, -90]) { + const s = setup({ angle }); await s.gyro.toggle(); s.reading(); s.reading(0, 17.5); + near(s.view.x, .5 * Math.cos(angle * Math.PI / 180)); near(s.view.y, -.5 * Math.sin(angle * Math.PI / 180)); + s.reading(0, 85); assert.ok(Math.abs(s.view.x) <= 1 && Math.abs(s.view.y) <= 1); s.gyro.dispose(); + } +}); +test('upright equivalent Euler representations do not cause a jump', async () => { + const s = setup(); await s.gyro.toggle(); s.reading(89, 10, 20); + s.reading(91, -170, 200); // same rotation expressed across the Euler representation boundary + assert.ok(Math.abs(s.view.x) < .1 && Math.abs(s.view.y) < .1); + s.gyro.dispose(); +}); +test('pause ignores motion and resumes relative to current manual view with no jump', async () => { + const s = setup(); await s.gyro.toggle(); s.reading(); s.reading(0, 10); s.gyro.setPaused(true); + const frozen = { ...s.view }; s.reading(30, 25); assert.deepEqual(s.view, frozen); + Object.assign(s.view, { x: .4, y: -.3 }); s.gyro.setPaused(false); s.reading(35, 30); + near(s.view.x, .4); near(s.view.y, -.3); s.reading(35, 32); assert.ok(s.view.x > .4); s.gyro.dispose(); +}); +test('screen rotation rebases while preserving current view, including legacy angle', async () => { + const s = setup(); await s.gyro.toggle(); s.reading(); s.reading(0, 10); const frozen = { ...s.view }; + s.orientation.angle = 90; s.orientation.emit('change'); s.reading(30, 20); assert.deepEqual(s.view, frozen); + delete s.win.screen.orientation; s.win.orientation = -90; s.win.emit('orientationchange'); s.reading(20, 15); assert.deepEqual(s.view, frozen); + s.gyro.dispose(); assert.equal(s.orientation.count('change'), 0); +}); +test('recenter resets neutral and disable preserves manual fallback', async () => { + const s = setup(); await s.gyro.toggle(); s.reading(); s.reading(0, 10); s.gyro.reset(); s.reading(20, 20); + assert.deepEqual(s.values.at(-1), [0, 0]); await s.gyro.toggle(); assert.equal(s.gyro.state, 'off'); + const count = s.values.length; s.reading(); assert.equal(s.values.length, count); +}); +test('background removes sensor listener, resumes without jump, pagehide stops', async () => { + const s = setup(); await s.gyro.toggle(); s.reading(); s.reading(0, 10); const frozen = { ...s.view }; + s.doc.hidden = true; s.doc.emit('visibilitychange'); assert.equal(s.win.count('deviceorientation'), 0); assert.equal(s.timers.size, 0); + s.doc.hidden = false; s.doc.emit('visibilitychange'); assert.equal(s.win.count('deviceorientation'), 1); s.reading(35, 20); assert.deepEqual(s.view, frozen); + s.win.emit('pagehide'); assert.equal(s.gyro.state, 'off'); assert.equal(s.win.count('deviceorientation'), 0); s.gyro.dispose(); +}); +test('cancelled permission resolutions cannot activate or overwrite a newer start', async () => { + let resolve; const s = setup({ permission: () => new Promise(r => { resolve = r; }) }); + const first = s.gyro.toggle(); await s.gyro.toggle(); resolve('granted'); await first; + assert.equal(s.gyro.state, 'off'); assert.equal(s.win.count('deviceorientation'), 0); + const second = s.gyro.toggle(); const oldResolve = resolve; s.gyro.dispose(); oldResolve('granted'); await second; + assert.equal(s.win.count('deviceorientation'), 0); assert.equal(s.doc.count('visibilitychange'), 0); +}); +test('repeat start/stop does not accumulate listeners or timers; stationary active has no watchdog', async () => { + const s = setup(); for (let i = 0; i < 5; i++) { + await s.gyro.toggle(); assert.equal(s.win.count('deviceorientation'), 1); s.reading(); assert.equal(s.timers.size, 0); + await s.gyro.toggle(); assert.equal(s.win.count('deviceorientation'), 0); assert.equal(s.timers.size, 0); + } + s.gyro.dispose(); assert.equal(s.doc.count('visibilitychange'), 0); assert.equal(s.win.count('orientationchange'), 0); assert.equal(s.win.count('pagehide'), 0); +}); +test('enabling inside settings validates data but waits to center until the scene resumes', async () => { + const s = setup(); s.gyro.setPaused(true); await s.gyro.toggle(); s.reading(50, 15); + assert.equal(s.gyro.state, 'paused'); assert.deepEqual(s.values, []); assert.equal(s.timers.size, 0); + s.gyro.setPaused(false); s.reading(55, 18); assert.deepEqual(s.values.at(-1), [0, 0]); s.gyro.dispose(); +}); +test('invalid readings after activation cannot poison the last finite camera target', async () => { + const s = setup(); await s.gyro.toggle(); s.reading(); s.reading(0, 10); const before = { ...s.view }; + s.reading(NaN, 10); s.reading(30, Infinity); assert.deepEqual(s.view, before); s.gyro.dispose(); +}); +test('late rejected old permission cannot cancel a newer sensor session', async () => { + let reject; let calls = 0; + const s = setup({ permission: () => ++calls === 1 ? new Promise((_, r) => { reject = r; }) : Promise.resolve('granted') }); + const old = s.gyro.toggle(); await s.gyro.toggle(); await s.gyro.toggle(); s.reading(); + reject(Error('late')); await old; assert.equal(s.gyro.state, 'active'); assert.equal(s.win.count('deviceorientation'), 1); s.gyro.dispose(); +}); +test('background during permission cancels activation; proven stationary sensor stays active on resume', async () => { + let resolve; const pending = setup({ permission: () => new Promise(r => { resolve = r; }) }); + const first = pending.gyro.toggle(); pending.doc.hidden = true; pending.doc.emit('visibilitychange'); resolve('granted'); await first; + assert.equal(pending.gyro.state, 'off'); assert.equal(pending.win.count('deviceorientation'), 0); pending.gyro.dispose(); + const s = setup(); await s.gyro.toggle(); s.reading(); s.doc.hidden = true; s.doc.emit('visibilitychange'); s.doc.hidden = false; s.doc.emit('visibilitychange'); s.expire(); + assert.equal(s.gyro.state, 'active'); assert.equal(s.win.count('deviceorientation'), 1); s.gyro.dispose(); +}); +test('sensor controller neither transmits nor stores readings', () => { + assert.doesNotMatch(source, /fetch\s*\(|XMLHttpRequest|WebSocket|sendBeacon|localStorage|sessionStorage|indexedDB|console\./); +}); + +test('proven stationary sensors do not fail after a tap, settings, recenter or rotation', async () => { + const s = setup(); await s.gyro.toggle(); s.reading(); + s.gyro.setPaused(true); s.gyro.setPaused(false); s.expire(); assert.equal(s.gyro.state, 'active'); + s.gyro.reset(); s.expire(); assert.equal(s.gyro.state, 'active'); + s.orientation.angle = 90; s.orientation.emit('change'); s.expire(); assert.equal(s.win.count('deviceorientation'), 1); + s.gyro.dispose(); +}); +test('hint intent ignores sensor jitter and rebases after pause; only deliberate relative tilt counts', async()=>{ + const s=setup();let gestures=0; + s.gyro.dispose(); + const gyro=new GyroController(()=>{},()=>{},()=>({x:0,y:0}),()=>gestures++); + await gyro.toggle();s.reading(); + for(let i=0;i<80;i++)s.reading(.08*Math.sin(i),.12*Math.cos(i)); + assert.equal(gestures,0); + s.reading(0,6);assert.equal(gestures,1); + for(let i=0;i<80;i++)s.reading(0,6+.12*Math.cos(i)); + assert.equal(gestures,1,'holding a tilted pose is idle, not repeated action'); + gyro.setPaused(true);s.reading(40,30);gyro.setPaused(false);s.reading(40,30); + assert.equal(gestures,1);s.reading(40,42);assert.equal(gestures,2);gyro.dispose(); +}); +test('recenter makes the current held phone pose the new zero without re-requesting permission',async()=>{ + let permissionCalls=0;const s=setup({permission:async()=>{permissionCalls++;return 'granted';}}); + await s.gyro.toggle();s.reading(20,10,15);s.reading(20,25,15);assert.notEqual(s.view.x,0); + s.gyro.reset();s.reading(20,25,15);near(s.view.x,0);near(s.view.y,0); + s.reading(20,30,15);assert.notEqual(s.view.x,0);assert.equal(permissionCalls,1);s.gyro.dispose(); +}); + +test('explicit disconnect is idempotent and invalidates a pending permission result',async()=>{ + let resolve,calls=0;const s=setup({permission:()=>{calls++;return new Promise(r=>resolve=r);}}); + assert.equal(typeof s.gyro.disconnect,'function');s.gyro.disconnect();assert.equal(calls,0);assert.equal(s.gyro.state,'off'); + const pending=s.gyro.toggle();assert.equal(calls,1);s.gyro.disconnect();resolve('granted');assert.equal(await pending,false); + assert.equal(s.gyro.state,'off');assert.equal(s.win.count('deviceorientation'),0);assert.equal(s.timers.size,0); + s.gyro.disconnect();assert.equal(calls,1);s.gyro.dispose(); +}); +test('disconnect removes active listeners and does not reenable on visibility changes',async()=>{ + const s=setup();await s.gyro.toggle();s.reading();s.reading(0,12);const old=s.values.length; + s.gyro.disconnect();s.reading(0,30);s.doc.hidden=true;s.doc.emit('visibilitychange');s.doc.hidden=false;s.doc.emit('visibilitychange'); + assert.equal(s.values.length,old);assert.equal(s.gyro.state,'off');assert.equal(s.win.count('deviceorientation'),0);assert.equal(s.timers.size,0); + await s.gyro.toggle();s.reading(0,30);assert.deepEqual(s.values.at(-1),[0,0]);s.gyro.dispose(); +}); +test('old permission completion cannot overwrite a newer explicitly reconnected session',async()=>{ + for(const rejected of [false,true]){ + const requests=[];const s=setup({permission:()=>new Promise((resolve,reject)=>requests.push({resolve,reject}))}); + const old=s.gyro.toggle();s.gyro.disconnect();const fresh=s.gyro.toggle();requests[1].resolve('granted');await fresh;s.reading(0,8);assert.equal(s.gyro.state,'active'); + if(rejected)requests[0].reject(new Error('old permission failed'));else requests[0].resolve('granted');await old; + assert.equal(s.gyro.state,'active');assert.equal(s.win.count('deviceorientation'),1);s.gyro.dispose(); + } +}); diff --git a/scripts/test-house-lighting.mjs b/scripts/test-house-lighting.mjs new file mode 100644 index 0000000..99c9b73 --- /dev/null +++ b/scripts/test-house-lighting.mjs @@ -0,0 +1,33 @@ +import assert from 'node:assert/strict'; +import {test} from 'node:test'; +import * as THREE from 'three'; +import {loadTypescript} from './support/load-typescript.mjs'; +const {WindowFinish}=await loadTypescript(new URL('../src/objects/WindowFinish.ts',import.meta.url)); +const {WindowReveal}=await loadTypescript(new URL('../src/objects/WindowReveal.ts',import.meta.url)); +const {attachMeshRefraction}=await loadTypescript(new URL('../src/rendering/MeshRefraction.ts',import.meta.url)); +function fixture(){ + const geometry=new THREE.BoxGeometry(),materials=[new THREE.MeshBasicMaterial()],frames=Array.from({length:4},()=>new THREE.Mesh(geometry,materials)),scene=new THREE.Scene(),reveal=new WindowReveal(materials[0]); + const finish=new WindowFinish(scene,frames,reveal,materials,materials[0]);finish.apply('wood'); + return {scene,finish,reveal,dispose(){finish.dispose();reveal.dispose();geometry.dispose();materials.forEach(m=>m.dispose());}}; +} +test('room finish has neutral fill and upper-right daylight without new render passes',()=>{ + const f=fixture(),lights=f.scene.children.filter(o=>o.isLight),ambient=lights.find(o=>o.isAmbientLight),key=lights.find(o=>o.isDirectionalLight); + assert.equal(lights.length,2,'one ambient and one key keep existing B reveal and mobile light budget'); + assert.ok(ambient.color.b/ambient.color.r>.95,'room fill must not turn ivory/plaster olive'); + assert.ok(key.position.x>0&&key.position.y>0&&key.position.z>0,'daylight comes from upper right in the shipped frame scene'); + assert.ok(ambient.intensity>=1.35&&ambient.intensity<=1.7); + assert.ok(key.intensity>=2&&key.intensity<=2.5); + assert.equal(key.castShadow,false,'portable authored contact shading avoids new shadow-map passes'); + f.finish.apply('booth');assert.ok(lights.every(l=>!l.visible));f.finish.apply('wood');assert.ok(lights.every(l=>l.visible)); + f.dispose();assert.ok(lights.every(l=>l.parent===null)); +}); +test('custom B reveal reads the same refined room lights, not stale preview lighting',()=>{ + const f=fixture(),source=new THREE.Mesh(new THREE.PlaneGeometry(1,1),new THREE.ShaderMaterial({uniforms:{uDepthMap:{value:new THREE.Texture()},uDepthScale:{value:.25},uDepthBias:{value:0}}})); + const glass=new THREE.MeshPhysicalMaterial(),optics=attachMeshRefraction(glass,source); + optics.syncReveal(f.reveal.meshes,f.scene); + const ambient=f.scene.children.find(o=>o.isAmbientLight),key=f.scene.children.find(o=>o.isDirectionalLight); + assert.deepEqual(optics.uniforms.uBRevealAmbient.value.toArray(),ambient.color.clone().multiplyScalar(ambient.intensity).toArray()); + assert.deepEqual(optics.uniforms.uBRevealLightColor.value.toArray(),key.color.clone().multiplyScalar(key.intensity).toArray()); + assert.ok(optics.uniforms.uBRevealLightDirection.value.distanceTo(key.position.clone().normalize())<1e-12); + f.dispose();source.geometry.dispose();source.material.uniforms.uDepthMap.value.dispose();source.material.dispose();glass.dispose(); +}); diff --git a/scripts/test-house-surround.mjs b/scripts/test-house-surround.mjs new file mode 100644 index 0000000..390d285 --- /dev/null +++ b/scripts/test-house-surround.mjs @@ -0,0 +1,125 @@ +import assert from 'node:assert/strict'; +import { existsSync, readFileSync } from 'node:fs'; +import { test } from 'node:test'; +import * as THREE from 'three'; +import { loadTypescript } from './support/load-typescript.mjs'; +import { loadFrameGeometry } from './support/load-frame-geometry.mjs'; +const modulePath = new URL('../src/objects/BlenderHouseSurround.ts', import.meta.url); +const assetPath = new URL('../public/assets/window/grandma-house-surround.glb', import.meta.url); +const load = async () => { assert.ok(existsSync(modulePath), 'A bounded adapter must attach the authored room around the intact photo'); return loadTypescript(modulePath); }; +const geometry = () => loadFrameGeometry(assetPath); +function vertices(root) { const result=[]; root.traverse(o=>{if(o.isMesh)result.push([...o.geometry.attributes.position.array]);}); return result; } + +test('house surround attaches to the existing frame scene and has a bounded room fit', async () => { + const { houseViewScale } = await load(); + assert.equal(houseViewScale('wood'), .82); + assert.equal(houseViewScale('booth'), 1); +}); + +test('authored house geometry preserves an open photo aperture, stable resize and slipper proportions', async () => { + const { prepareHouseAsset } = await load(), root=geometry(), slippers=root.getObjectByName('HouseSlippers'); + slippers.geometry.computeBoundingBox(); const original=slippers.geometry.boundingBox.getSize(new THREE.Vector3()); + const asset=prepareHouseAsset(root); + for(const [w,h] of [[1,1.32],[1,1],[3,1],[1,3],[.2,4],[4,.2]]) { + asset.resize(w,h,.6); root.updateMatrixWorld(true); + root.traverse(o=>{if(!o.isMesh)return;const p=o.geometry.attributes.position,n=o.geometry.attributes.normal; + for(let i=0;i