#include "fiko/render/golge_kamera.hpp" #include #include // Vulkan YOK — saf matematik TU'su (fiko_render_test buna baglanir). namespace fiko { namespace { // AABB'nin 8 köşesini verilen eksene projekte et → [min, max]. void eksenAralik(const Aabbf& s, Vec3f merkez, Vec3f eksen, f32& mn, f32& mx) { mn = 1e30f; mx = -1e30f; for (int i = 0; i < 8; ++i) { const Vec3f k8{(i & 1) ? s.azami.x : s.asgari.x, (i & 2) ? s.azami.y : s.asgari.y, (i & 4) ? s.azami.z : s.asgari.z}; const f32 p = (k8 - merkez).nokta(eksen); mn = std::min(mn, p); mx = std::max(mx, p); } } } // namespace GolgeKamera golgeKameraKur(const Aabbf& sinir, Vec3f yon, f32 marjOran) { return golgeKameraKur(sinir, sinir, yon, marjOran); } GolgeKamera golgeKameraKur(const Aabbf& hedefSinir, const Aabbf& engelSinir, Vec3f yon, f32 marjOran) { GolgeKamera k; if (!hedefSinir.gecerliMi()) return k; // Engel sınırı geçersizse hedefe düş (tek gövdeli sahne). const Aabbf& engel = engelSinir.gecerliMi() ? engelSinir : hedefSinir; const f32 yl = std::sqrt(yon.uzunlukKare()); if (yl < 1e-12f) return k; const Vec3f d{yon.x / yl, yon.y / yl, yon.z / yl}; // Yöne EN DİK global eksen → sağlam "yukarı" (yön global bir eksene paralelse // capraz sıfır olurdu; en-dik seçimi bunu önler). Web upVector seçimiyle aynı. const Vec3f eksenler[3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; int en = 0; f32 enKucuk = 2.0f; for (int i = 0; i < 3; ++i) { const f32 a = std::abs(d.nokta(eksenler[i])); if (a < enKucuk) { enKucuk = a; en = i; } } const Vec3f sag = d.capraz(eksenler[en]).birim(); const Vec3f yukari = sag.capraz(d).birim(); // yeniden dikleştir // XY (yanal): YALNIZ hedef gövde → texel yoğunluğu maksimum. // Z (derinlik): TÜM engeller → örten gövdeler haritaya girer. const Vec3f merkez = hedefSinir.merkez(); f32 minX, maksX, minY, maksY, minZ, maksZ; eksenAralik(hedefSinir, merkez, sag, minX, maksX); eksenAralik(hedefSinir, merkez, yukari, minY, maksY); eksenAralik(engel, merkez, d, minZ, maksZ); // Marj: kenardaki yüzeyler frustum dışında kalıp yanlışlıkla "açık" görünmesin. const f32 mxy = std::max(maksX - minX, maksY - minY) * marjOran + 1e-3f; minX -= mxy; maksX += mxy; minY -= mxy; maksY += mxy; const f32 zAralik = std::max(maksZ - minZ, 1e-4f); const f32 mz = zAralik * marjOran + 1e-3f; // Kamera AABB'nin YÖN tarafına çekilir, merkeze bakar → ileri = -d. Böylece // yön boyunca YUKARIDAKİ nokta kameraya daha YAKIN → reverse-Z'de daha BÜYÜK z. const f32 mesafe = (maksZ + mz) + zAralik; // yakın düzlem tüm gövdenin dışında const Vec3f goz = merkez + d * mesafe; const Mat4f gorunum = Mat4f::bak(goz, merkez, yukari); const f32 yakin = std::max(mesafe - (maksZ + mz), 1e-3f); const f32 uzak = mesafe - (minZ - mz); k.vp = Mat4f::dikey(minX, maksX, minY, maksY, yakin, uzak) * gorunum; k.zAralik = uzak - yakin; k.gecerli = true; return k; } } // namespace fiko