feat(labs): opticsbench round 2 — wave optics + interference + visual depth

Новый режим «Волны» (DiffractionSim, ~400 строк):
- Опыт Юнга: I = I₀·cos²(πd·sinθ/λ), полосы Δy = λL/d, концентрические волновые фронты
- Однощелевая дифракция: (sin α/α)², центральный максимум 2λ/a, минимумы
- Дифракционная решётка: (sin Nψ/N sin ψ)², главные порядки 0,±1,±2,±3, white-light спектр

Новый режим «Интерференция» (InterferenceSim):
- Кольца Ньютона: top-down + cross-section, r_n = √(nλR) тёмные / √((n+½)λR) светлые
- Тонкоплёночная интерференция: integrate I=cos²(π·OPD/λ) по спектру → цвет плёнки
  пресеты: мыльная плёнка / масло на воде / антибликовое покрытие
- Поляризация: P1+P2, закон Малюса I=I₀·cos²θ, анимированные E-векторы, гашение при 90°
  + связь с Брюстером из refraction mode

Визуальные эффекты (5 toggle'ов в <details>):
- «Волновые фронты»: перпендикулярные tick-marks вдоль лучей, λ_screen∝1/n в среде
- «Туман»: LabFX smoke partikles по всему canvas — лучи видны через дым
- «Lens flare»: 6-spike starburst + ghost-reflections + chromatic ring (additive composite)
- «Конструкция Гюйгенса»: расходящиеся wavelets на границе для refraction/reflection
- «Каустики»: 20-ray trace через линзу с aberration-shifted f_eff → настоящая caustic curve
- localStorage persist + zero cost when off

THEORY entry расширен 3 секциями (Юнг + однощель + решётка).

Каталог теперь: 7 вкладок в оптической скамье (lens / mirror / refraction / freebuild / prism / waves / interf).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-05-26 12:33:10 +03:00
parent 2a8011d68e
commit add17b1bb4
4 changed files with 1602 additions and 11 deletions
+44
View File
@@ -1512,3 +1512,47 @@ canvas[data-draggable]:active { cursor: grabbing; }
border-radius: 4px;
background: #0a0a18;
}
/* ═══ OB_FX Effects panel ═══ */
.ob-fx-panel {
flex-shrink: 0;
background: #0d0d1e;
border-bottom: 1px solid #1e1e32;
}
.ob-fx-summary {
display: flex;
align-items: center;
gap: 6px;
padding: 5px 10px;
font-size: .72rem;
font-weight: 700;
color: #888;
cursor: pointer;
list-style: none;
user-select: none;
}
.ob-fx-summary::-webkit-details-marker { display: none; }
.ob-fx-summary:hover { color: var(--cyan); }
.ob-fx-summary .ic { fill: currentColor; opacity: 0.7; flex-shrink: 0; }
.ob-fx-row {
display: flex;
flex-wrap: wrap;
gap: 6px 14px;
padding: 6px 12px 8px;
}
.ob-fx-label {
display: flex;
align-items: center;
gap: 5px;
font-size: .72rem;
color: #bbb;
cursor: pointer;
white-space: nowrap;
}
.ob-fx-label:hover { color: #fff; }
.ob-fx-label input[type=checkbox] {
accent-color: var(--cyan);
width: 13px;
height: 13px;
cursor: pointer;
}