# Gösterim Kalitesi (Tessellation) — Tanı + Tasarım

> SALT TANI + PLAN. Kod yazılmadı. Tessellation **yalnız gösterimdir**; B-rep
> topolojisi/hesap (hacim, alan, seçim ordinali, CAM, analiz) DEĞİŞMEZ — sadece
> görsel üçgen/çizgi yoğunluğu ayarlanır.

---

## 1. Kök Neden (kanıt: dosya:satır)

### 1.1 Yüzey tessellation — `BrepGovde::ucgenle`

`motor/geometri/src/brep.cpp:239-249`

```cpp
MeshVeri BrepGovde::ucgenle(Vec3f renk, f64 kaliteOrani = 0.004) const {   // hpp:54
  ...
  const f64 kosegen = ... sqrt(kutucuk.SquareExtent());   // bbox köşegeni
  const f64 sapma   = std::max(kosegen * kaliteOrani, 1e-4);  // LINEAR deflection
  BRepMesh_IncrementalMesh(icerik_->sekil, sapma, false, 0.35, true);
}
```

OCCT imzası:
`BRepMesh_IncrementalMesh(shape, theLinDeflection, isRelative, theAngDeflection, isInParallel)`

Yani verilen parametreler:

| Parametre | Değer | Yorum |
|-----------|-------|-------|
| `theLinDeflection` | `kosegen * 0.004` | doğrusal sapma — **düzlemsel** hatayı sınırlar |
| `isRelative` | `false` | ama linear zaten elle köşegene oranlanmış → pratikte size-relative ✓ |
| `theAngDeflection` | **`0.35` rad ≈ 20° — SABİT** | **eğrisellik kontrolü — asıl suçlu** |
| `isInParallel` | `true` | çok-çekirdek meshleme ✓ |

**ASIL KÖK NEDEN — açısal sapma sabit ve kaba (0.35 rad ≈ 20°):**

Bir silindir/fillet/eğri yüzeyde bir yay üzerindeki facet sayısını **açısal
sapma** belirler (linear değil). 20°'de:
- 90°'lik bir fillet yayı ≈ **90/20 ≈ 5 facet** → gözle görülür köşeli/poligonal.
- Küçük radiuslarda linear sapma zaten çok küçük kalır (yay kısa), sınırlayıcı
  faktör tamamen açısal olur → radius'lar köşeli görünür.

**Kritik:** `theAngDeflection` **`kaliteOrani`'na bağlı DEĞİL** — sabit `0.35`.
Yani kaliteyi artırsan bile (linear sapmayı küçültsen bile) **eğriler aynı kaba
kalır**. Kullanıcının "radius'larda ve formlu/eğrisel yüzeylerde köşeli" şikayeti
tam olarak bu: linear knob eğriselliği kontrol etmiyor, angular knob ise sabit +
kaba.

> Referans: OCCT varsayılan açısal sapma 0.5 rad; burada 0.35 verilmiş — yine de
> pürüzsüz eğri için 0.08–0.2 rad aralığı gerekir.

### 1.2 Kenar tessellation — `BrepGovde::kenarMesh`

`motor/geometri/src/brep.cpp:307-336` (özellikle satır **326**)

```cpp
KenarVeri BrepGovde::kenarMesh(f64 kaliteOrani = 0.004) const {   // hpp:62
  const f64 sapma = std::max(kosegen * kaliteOrani, 1e-4);
  ...
  BRepAdaptor_Curve uyarli(kenar);
  GCPnts_TangentialDeflection ornekleyici(uyarli, sapma, 0.2, 2);  // ← BURASI
}
```

Kenarlar yüz mesh'inden (BRepMesh) **BAĞIMSIZ** kendi örnekleyicisiyle çıkar.
`GCPnts_TangentialDeflection` imzası:
`(adaptor, theCurvatureDeflection, theAngularDeflection, theMinimumOfPoints)`

| Parametre | Değer | Yorum |
|-----------|-------|-------|
| `theCurvatureDeflection` | `kosegen * 0.004` (linear) | teğetsel/eğrilik sapması |
| `theAngularDeflection` | **`0.2` rad ≈ 11.5° — SABİT** | eğri kenar segment açısı |
| `theMinimumOfPoints` | `2` | küçük tam çember → az nokta riski |

**Kenar kök nedeni:** açısal sapma **`0.2` rad ≈ 11.5°, sabit**. 90° yay ≈ 8
segment → eğrisel kenarlar (fillet sınır çizgileri, spline, çember) köşeli
görünür. Yüzlerden biraz daha ince (11.5° < 20°) ama yine kaba ve **kaliteye
bağlı değil**. Kenar örneklemesi ayrı olduğu için kalite ayarının **hem yüz hem
kenar** açısal sapmasını birlikte düzeltmesi gerekir.

### 1.3 Runtime kalite kontrolü — **YOK**

Tüm çağrılar **varsayılan 0.004** ile çağrılıyor; hiçbir yerde runtime kalite
argümanı geçilmiyor:

- `motor/sahne/src/sahne.cpp:187` → `d.brep->ucgenle(d.renk)`
- `motor/sahne/src/sahne.cpp:189-190` → `kenarMesh()`, `noktaMesh()`
- `motor/sahne/src/sahne.cpp:564` → `brep->ucgenle(d->renk)`
- `uygulama/fikocad/dosya_islemleri.cpp:288-290` → import (paralel) `ucgenle/kenarMesh/noktaMesh`

**Sonuç:** Referans (web) toolbar'daki "3D KALİTE slider (0.004) + Orta dropdown"
native'de **karşılığı yok**. Kaliteyi değiştirmek bugün **imkânsız**; üstelik
varsayılan 0.004'te bile (§1.1/§1.2) eğriler açısal sapma yüzünden kaba. Yani iki
ayrı sorun: (a) ayarlanamıyor, (b) varsayılan bile pürüzsüz değil.

### 1.4 STEP import kalitesi vs runtime kalitesi

Şu an ikisi de aynı sabit 0.004 + sabit açısal. Import `dosya_islemleri.cpp:259`
gövde-başına PARALEL mesh'liyor (deep-copy ile shared-geom race guard'ı var).
Runtime'da ayrı bir yeniden-mesh yolu var (§3) ama tetikleyicisi yok.

---

## 2. Kalite-Ayar Tasarımı

### 2.1 Merkezi `KaliteAyar` (deflection kaynağı)

Hardcode'lu `0.35` (yüz açısal) ve `0.2` (kenar açısal) + `0.004` (linear oran)
tek merkeze taşınır. `motor/geometri` içinde küçük bir struct + global erişimci:

```
// motor/geometri/include/fiko/geometri/kalite.hpp  (öneri)
struct KaliteAyar {
  f64 linOran      = 0.004;  // linear = bbox_kosegen * linOran
  f64 yuzAngRad    = 0.30;   // BRepMesh açısal (eğrisel yüzey pürüzsüzlüğü)
  f64 kenarAngRad  = 0.25;   // GCPnts açısal (eğrisel kenar pürüzsüzlüğü)
  bool relative    = false;  // BRepMesh isRelative (opsiyonel gelişmiş)
};
geometri::KaliteAyar& kalite();  // global tekil (tek doğruluk kaynağı)
```

`ucgenle`/`kenarMesh` artık sabit yerine `kalite()`'den okur (imza aynı kalır ya
da `kaliteOrani` argümanı `KaliteAyar` ile genişletilir). **Tek değişiklik nokta**
= mesh yoğunluğu; B-rep dokunulmaz.

### 2.2 Seviye → (linear + açısal) map

RTX 4090 → Yüksek/Ultra ucuz; varsayılan **Yüksek** önerilir.

| Seviye | linOran (×köşegen) | yuzAngRad (≈°) | kenarAngRad (≈°) | Not |
|--------|--------------------|----------------|------------------|-----|
| **Düşük**  | 0.010  | 0.50 (~28.6°) | 0.50 (~28.6°) | hızlı önizleme / dev makine |
| **Orta**   | 0.004  | 0.30 (~17°)   | 0.25 (~14°)   | ≈ bugünkü linear, angular iyileşir |
| **Yüksek** | 0.0015 | 0.15 (~8.6°)  | 0.12 (~7°)    | **varsayılan** — pürüzsüz |
| **Ultra**  | 0.0006 | 0.08 (~4.6°)  | 0.06 (~3.4°)  | render/ekran görüntüsü kalite |

**Kilit fix (seviyeden bağımsız):** yüz açısal `0.35 → seviye-güdümlü`, kenar
açısal `0.2 → seviye-güdümlü`. Sadece bu tek değişiklik bile varsayılan görünümü
belirgin düzeltir; slider üstüne gelir.

**Adaptiflik bedava:** BRepMesh + GCPnts açısal sapmayı asıl knob yapınca
eğrisellik başına adaptasyon otomatik olur — düz yüzler az üçgen, eğri
yüzler/fillet çok üçgen alır (linear knob'un veremediği şey). İsteğe bağlı
`isRelative=true` ile küçük fillet'ler oransal olarak daha ince mesh'lenir
(gelişmiş kullanıcıya bırakılır; küçük feature'ları aşırı-tessellate edebilir).

### 2.3 AyarSistemi entegrasyonu (makro + plugin + olay bedava)

Mevcut merkezi ayar altyapısı kullanılır:
`motor/ayar/include/fiko/ayar/ayar_sistemi.hpp` + kayıt örneği
`uygulama/fikocad/ayar_kayitlari.cpp:102` (ortam_siddet slider kalıbı).

Yeni kayıt (kategori "Görünüm"), `ayar_kayitlari.cpp`'ye eklenir:

1. **`gorunum.kalite`** — `AyarTip::Secenek`, seçenekler
   `{"Düşük","Orta","Yüksek","Ultra"}`, `al`=mevcut seviye, `ata`= seviyeyi
   `KaliteAyar`'a map'le (§2.2) + **tüm gövdeleri yeniden tessellate** (§3).
2. (Gelişmiş, opsiyonel) `gorunum.kalite_linear` (F32) + `gorunum.kalite_aci`
   (F32, rad) — güç kullanıcı için doğrudan slider; "Özel" seviye olarak.

`AyarSistemi.degisti` köprüsü (bağlanışı `main.cpp:1798` `ayarlarKaydet`) zaten:
- **kalıcılık** (ayar_kalici → sonraki açılışta yüklenir)
- **`AyarDegisti` olayı** yayınlar

Böylece §mimari-ilke gereği makro (`fiko.ayar.*`) + plugin + olay **doğuştan**
gelir; ayrı sistem yazılmaz. Referans toolbar'daki "3D KALİTE + dropdown" bu
`gorunum.kalite` ayarına bağlanır (toolbar butonu → `degerAta`).

---

## 3. Yeniden-Tessellate Akışı

### 3.1 Mevcut altyapı (hazır)

- `Sahne::yenidenInsa(Dugum&)` — `motor/sahne/src/sahne.cpp:159` →
  `ucgenle`/`kenarMesh`/`noktaMesh` → `tamponlariYukle`.
- `Sahne::tamponlariYukle` — `sahne.cpp:197` → **yüz + kenar + nokta** GPU
  tamponlarını **birlikte** günceller (satır 208-219); eski tamponlar uçuşta ise
  `GpuTampon` move-assign ile EMEKLİ listesine ertelenir (device-idle beklemez).
- `Sahne::bekleyenleriYenidenInsa()` — `sahne.cpp:136` → `yenidenInsaGerek`
  işaretli düğümleri gezerek yeniden inşa eder.
- `Sahne::dugumler()` — `sahne.hpp:279` → tüm düğümlere erişim.

### 3.2 Kalite değişiminde "tümünü yeniden mesh'le"

`gorunum.kalite` `ata` (veya `AyarDegisti` dinleyicisi):

1. `KaliteAyar`'ı güncelle (§2.1).
2. `for (auto& d : sahne.dugumler()) d.yenidenInsaGerek = true;`
3. Sonraki kare başında `bekleyenleriYenidenInsa()` (main-thread, Vulkan + olay —
   `tamponlariYukle` yalnız main-thread'de güvenli).

Böylece **yüz + kenar** tamponları tek geçişte birlikte yenilenir (kenar da yeni
`kenarAngRad`'la örneklendiği için eğrisel kenarlar da düzelir). Seçim ordinali
(`yuzOrdinal` TopExp sırasından) yeniden-mesh'te korunur → seçim/CAM referansları
bozulmaz.

> **Not — mimari uyum:** `yenidenInsa` primitiflerde brep'i parametreden yeniden
> kurar (`sahne.cpp:160-169`); import gövdelerinde mevcut brep'i yeniden mesh'ler.
> İkisi de aynı `ucgenle` deflection'ından beslendiği için tek `KaliteAyar` her
> ikisini de kapsar.

---

## 4. Performans

Yeniden-mesh maliyeti = **CPU OCCT meshleme** (GPU değil). Büyük montajda saniyeler
sürebilir; RTX 4090 yoğun mesh'i çizmekte rahat, darboğaz OCCT.

**Öneriler (import'un async/progress kalıbıyla tutarlı):**

1. **Paralel + progress:** Import'taki güvenli kalıbı tekrar kullan
   (`dosya_islemleri.cpp:259-300`): önce paylaşımlı geometriyi kopar (seri deep-copy,
   `govdeDerinKopya`), sonra gövde-başına PARALEL mesh (`std::thread` kuyruk).
   `Bekci.ilerlet(...)` ile progress. **Kalite değişiminde bunu yeniden kullan** —
   ayrı yol yazma.
2. **Debounce:** Slider sürüklenirken her kare re-mesh **etme**; yalnız
   `AyarDegisti` (bırakınca / dropdown seçilince) tetikle. `AyarSistemi.bildir`
   canlı sürüklemeyi, `degerAta` kesin değişimi ayırır — re-mesh yalnız kesin
   değişimde.
3. **Kademeli (opsiyonel):** Önce **görünür/seçili** gövdeleri yeniden mesh'le,
   gerisini arka planda; büyük montajda anlık geri bildirim.
4. **Sınır:** çok küçük açısal sapma (Ultra) + çok linear = üçgen patlaması →
   bellek/VRAM. `1e-4` linear alt-sınırı zaten var; açısal için de makul alt-sınır
   (≥0.04 rad) + üçgen sayısı uyarısı düşünülebilir.

---

## 5. UI — "3D KALİTE" kontrolü nasıl bağlanır

- **Kaynak tek:** `gorunum.kalite` (AyarSistemi Secenek). Ayarlar penceresi bunu
  otomatik listeler (kategori "Görünüm").
- **Toolbar butonu/dropdown:** referans toolbar'daki "3D KALİTE" → `Düşük/Orta/
  Yüksek/Ultra` dropdown → `sistem().degerAta("gorunum.kalite", dMetin(seciliAd))`.
  Slider isteniyorsa gelişmiş `gorunum.kalite_linear`/`_aci`'ya bağlanır.
- **Anlık değilse progress:** re-mesh süresi eşiği aşarsa (§4) `Bekci` progress
  çubuğu; küçük modelde anında.
- **Kalıcılık:** seçilen kalite `ayar_kalici` ile saklanır → sonraki açılışta aynı
  kalite (§2.3).

---

## Özet — yapılacaklar (kod dalgası için)

1. `brep.cpp:249` (yüz) `0.35` ve `brep.cpp:326` (kenar) `0.2` sabitlerini
   `geometri::kalite()` (yeni `KaliteAyar`) alanlarıyla değiştir — **tek fix ile
   varsayılan görünüm düzelir**.
2. `motor/geometri` `kalite.hpp` — merkezi `KaliteAyar` + seviye→deflection map (§2.2).
3. `ayar_kayitlari.cpp` — `gorunum.kalite` Secenek kaydı; `ata`→map+re-mesh (§2.3/§3.2).
4. Re-mesh: `dugumler()` işaretle + `bekleyenleriYenidenInsa()`; büyük model için
   import'un paralel+progress kalıbı + debounce (§4).
5. Toolbar "3D KALİTE" → `gorunum.kalite`'ye bağla (§5).

Hepsi gösterim; B-rep topolojisi/hesap/seçim ordinali korunur.
