// K2/K3 regresyon: gecersiz/bos geometri yollari yerelSinir'i asla gecersiz // birakmamali (ters varsayilan Aabb → NaN kamera fit → viewport kaybolur). // Sahne'nin ilgili dallari Vulkan gerektirdiginden burada fix'in dayandigi // sentinel-bbox sozlesmesi (gecerlilik + minik-pay) dogrulanir. #include "fiko/core/mat/aabb.hpp" #include "fiko_test.hpp" using namespace fiko; // yenidenInsa/gsdDugumGuncelle icindeki sentinel ile birebir ayni uretim. static Aabbf sentinelBbox() { const Vec3f m{0, 0, 0}; return {{m.x - 0.01f, m.y - 0.01f, m.z - 0.01f}, {m.x + 0.01f, m.y + 0.01f, m.z + 0.01f}}; } FIKO_TEST(gecersiz_mesh_varsayilan_aabb_gecersiz) { // Varsayilan Aabb terstir: gecersizMi olmali (bu tam olarak nuksun kaynagi). Aabbf varsayilan; FIKO_KONTROL(!varsayilan.gecerliMi()); } FIKO_TEST(gecersiz_mesh_sentinel_gecerli_ve_paysiz_degil) { const Aabbf s = sentinelBbox(); // Fix sonrasi yerelSinir gecerli olmali (NaN fit engellenir). FIKO_KONTROL(s.gecerliMi()); // Sifir-hacim degil: fit icin gercek pay olsun (kosegen > 0). FIKO_KONTROL(s.kosegen() > 1e-4f); // Merkez orijinde, kosegen sonlu. FIKO_YAKIN(s.merkez().x, 0.0f, 1e-6f); const f32 k = s.kosegen(); FIKO_KONTROL(k == k); // NaN degil } // ---- Işın-BVH (isinVur hız yapısı) yapısal doğruluk ------------------------ #include #include #include "fiko/sahne/isin_bvh.hpp" // Izgara üçgen bulutu kur → BVH: her üçgen TAM BİR yaprakta, yaprak kutusu kapsar. FIKO_TEST(isin_bvh_yapraklar_tum_ucgenleri_kapsar) { std::vector konum; std::vector indeks; for (int g = 0; g < 100; ++g) { // 100 üçgen (10x10 ızgara hücresi) const f32 x = (f32)(g % 10), y = (f32)(g / 10); const u32 t = (u32)konum.size(); konum.push_back({x, y, 0}); konum.push_back({x + 1, y, 0}); konum.push_back({x, y + 1, (f32)g * 0.1f}); indeks.push_back(t); indeks.push_back(t + 1); indeks.push_back(t + 2); } auto bvh = isinBvhKur(konum, indeks); FIKO_KONTROL(bvh != nullptr); FIKO_KONTROL(bvh->ucgen.size() == 100); std::vector gorulme(100, 0); for (const auto& dal : bvh->dallar) { FIKO_KONTROL(dal.kutu.gecerliMi()); if (!dal.yaprak) continue; for (u32 i = 0; i < dal.b; ++i) { const u32 t = bvh->ucgen[dal.a + i]; ++gorulme[t]; // Yaprak kutusu üçgenin 3 köşesini kapsamalı. for (int v = 0; v < 3; ++v) { const Vec3f& p = konum[indeks[t * 3 + v]]; FIKO_KONTROL(p.x >= dal.kutu.asgari.x - 1e-5f && p.x <= dal.kutu.azami.x + 1e-5f); FIKO_KONTROL(p.y >= dal.kutu.asgari.y - 1e-5f && p.y <= dal.kutu.azami.y + 1e-5f); FIKO_KONTROL(p.z >= dal.kutu.asgari.z - 1e-5f && p.z <= dal.kutu.azami.z + 1e-5f); } } } // Her üçgen tam bir kez (kayıp/çift yok → isinVur brute-force ile birebir sonuç). FIKO_KONTROL(std::all_of(gorulme.begin(), gorulme.end(), [](int n) { return n == 1; })); } FIKO_TEST(isin_bvh_bos_giris_null) { std::vector konum; std::vector indeks; FIKO_KONTROL(isinBvhKur(konum, indeks) == nullptr); } // ---- Kesit (clip) düzlemi pick kırpması ------------------------------------ // Kesit yalnız render'da discard olduğu sürece KIRPILAN yüzey tıklanabiliyordu // (ölçüm görünmeyen yüzeye tutunuyordu). Kural analiz.frag/secim.frag ile ikiz: // dot(p,n)+d < -tol → kırpıldı. Sahne örneği Vulkan ister → saf kural test edilir. #include "fiko/sahne/sahne.hpp" FIKO_TEST(kesit_pick_kirpma_kurali) { using KD = Sahne::KirpDuzlem; // +X yarısını tutan düzlem (x < 0 kırpılır). const KD d[1] = {{{1, 0, 0}, 0.0f}}; FIKO_KONTROL(!Sahne::kirpDuzlemDisinda(d, 1, {5, 0, 0})); // tutulan taraf FIKO_KONTROL(Sahne::kirpDuzlemDisinda(d, 1, {-5, 0, 0})); // kırpılan (görünmez) taraf // Kesit kapağı/eğrisi TAM düzlem üzerinde (mesafe 0) → elenmemeli, yoksa kesit // yüzeyinden ölçü alınamaz. FIKO_KONTROL(!Sahne::kirpDuzlemDisinda(d, 1, {0, 0, 0})); FIKO_KONTROL(!Sahne::kirpDuzlemDisinda(d, 1, {-1e-4f, 0, 0})); // tolerans içi // Düzlem yok → hiçbir şey kırpılmaz (eski davranış birebir). FIKO_KONTROL(!Sahne::kirpDuzlemDisinda(nullptr, 0, {-5, 0, 0})); // Ters çevrilmiş düzlem (-X yarısını tutar) → simetrik. const KD t[1] = {{{-1, 0, 0}, 0.0f}}; FIKO_KONTROL(Sahne::kirpDuzlemDisinda(t, 1, {5, 0, 0})); FIKO_KONTROL(!Sahne::kirpDuzlemDisinda(t, 1, {-5, 0, 0})); // Ofsetli düzlem: x >= 10 tutulur (d = -10). const KD o[1] = {{{1, 0, 0}, -10.0f}}; FIKO_KONTROL(Sahne::kirpDuzlemDisinda(o, 1, {5, 0, 0})); FIKO_KONTROL(!Sahne::kirpDuzlemDisinda(o, 1, {12, 0, 0})); // Çoklu düzlem: HERHANGİ biri kırparsa nokta görünmez (shader döngüsüyle aynı). const KD c[2] = {{{1, 0, 0}, 0.0f}, {{0, 1, 0}, 0.0f}}; FIKO_KONTROL(!Sahne::kirpDuzlemDisinda(c, 2, {5, 5, 0})); FIKO_KONTROL(Sahne::kirpDuzlemDisinda(c, 2, {5, -5, 0})); FIKO_KONTROL(Sahne::kirpDuzlemDisinda(c, 2, {-5, 5, 0})); }