#pragma once // CATIA/FreeCAD tarzı ViewCube — sağ üstte (compass'ın altında) kamera yönelimini // gösteren PAHLI küp: 6 yüz + 12 kenar + 8 köşe facet'i, hepsi tıklanabilir. // Yüz → ortografik görünüş; kenar → kenar-bakışı; köşe → çapraz/izometrik bakış // (alt-çapraz, sağ-alt-çapraz…). Kamera döndükçe küp döner. Salt yönelim gizmosu. // Ayarlar: aç/kapat · pahlı köşe/kenar · yukarı ekseni (Z/Y). #include #include #include #include "fiko/render/orbit_kamera.hpp" #include "imgui.h" namespace fiko { struct VizyonKupuAyar { bool aktif = true; // ViewCube görünür mü bool pahli = true; // köşe+kenar pahları (kapalı → düz 6-yüz küp) int yukariEksen = 0; // 0 = Z yukarı, 1 = Y yukarı (snap up vektörü) }; inline VizyonKupuAyar& vizyonKupuAyar() { static VizyonKupuAyar a; return a; } inline bool& vizyonKupuAktif() { return vizyonKupuAyar().aktif; } // geriye-uyum namespace vkupu_ic { inline void setC(Vec3f& v, int i, f32 val) { (i == 0 ? v.x : i == 1 ? v.y : v.z) = val; } inline bool poligonIcinde(ImVec2 p, const ImVec2* v, int n) { bool neg = false, poz = false; for (int i = 0; i < n; ++i) { const ImVec2 a = v[i], b = v[(i + 1) % n]; const f32 d = (b.x - a.x) * (p.y - a.y) - (b.y - a.y) * (p.x - a.x); if (d < 0) neg = true; else if (d > 0) poz = true; if (neg && poz) return false; } return true; } struct Facet { Vec3f v[4]; int n = 0; Vec3f dir{}; int tip = 0; const char* et = nullptr; // tip:0 yüz,1 kenar,2 köşe }; } // namespace vkupu_ic // ustunde: küp üstünde etkileşim (main pusulaUstunde'ye OR'lar → kamera/seçim bastır). inline void vizyonKupuCizVeIsle(OrbitKamera& kamera, ImDrawList* dl, ImGuiIO& io, bool vpHover, f32 mx, f32 my, f32 vw, f32 vh, bool& ustunde) { using namespace vkupu_ic; ustunde = false; const VizyonKupuAyar& ayar = vizyonKupuAyar(); const f32 R = 40.0f; const ImVec2 mrk(mx + vw - R - 30.0f, my + R + 170.0f); // compass'ın altı const Mat4f gv = kamera.gorunum(); const ImVec2 fp = io.MousePos; const f32 g = ayar.pahli ? 0.66f : 1.0f; // yüz yarı-boyutu; pah kalınlığı = 1-g // ---- Facet listesi ---- std::vector fs; fs.reserve(26); const char* faceEt[3][2] = {{"SAĞ", "SOL"}, {"ARKA", "ÖN"}, {"ÜST", "ALT"}}; for (int ax = 0; ax < 3; ++ax) for (int si = 0; si < 2; ++si) { const f32 s = si ? -1.0f : 1.0f; const int a1 = (ax + 1) % 3, a2 = (ax + 2) % 3; Facet f; f.n = 4; f.tip = 0; f.et = faceEt[ax][si]; setC(f.dir, ax, s); const f32 sg[4][2] = {{g, g}, {g, -g}, {-g, -g}, {-g, g}}; for (int k = 0; k < 4; ++k) { Vec3f p{}; setC(p, ax, s); setC(p, a1, sg[k][0]); setC(p, a2, sg[k][1]); f.v[k] = p; } fs.push_back(f); } if (ayar.pahli) { for (int ax1 = 0; ax1 < 3; ++ax1) for (int ax2 = ax1 + 1; ax2 < 3; ++ax2) { const int ax3 = 3 - ax1 - ax2; for (int a = 0; a < 2; ++a) for (int b = 0; b < 2; ++b) { const f32 s1 = a ? -1.0f : 1.0f, s2 = b ? -1.0f : 1.0f; Facet f; f.n = 4; f.tip = 1; Vec3f dir{}; setC(dir, ax1, s1); setC(dir, ax2, s2); f.dir = dir.birim(); Vec3f p0{}, p1{}, p2{}, p3{}; setC(p0, ax1, s1); setC(p0, ax2, s2 * g); setC(p0, ax3, g); setC(p1, ax1, s1); setC(p1, ax2, s2 * g); setC(p1, ax3, -g); setC(p2, ax1, s1 * g); setC(p2, ax2, s2); setC(p2, ax3, -g); setC(p3, ax1, s1 * g); setC(p3, ax2, s2); setC(p3, ax3, g); f.v[0] = p0; f.v[1] = p1; f.v[2] = p2; f.v[3] = p3; fs.push_back(f); } } for (int sx = 0; sx < 2; ++sx) for (int sy = 0; sy < 2; ++sy) for (int sz = 0; sz < 2; ++sz) { const f32 X = sx ? -1.0f : 1.0f, Y = sy ? -1.0f : 1.0f, Z = sz ? -1.0f : 1.0f; Facet f; f.n = 3; f.tip = 2; f.dir = Vec3f{X, Y, Z}.birim(); f.v[0] = {X, Y * g, Z * g}; f.v[1] = {X * g, Y, Z * g}; f.v[2] = {X * g, Y * g, Z}; fs.push_back(f); } } // ---- Projeksiyon + derinlik ---- const int N = (int)fs.size(); std::vector derinlik(N); std::vector sira(N); for (int i = 0; i < N; ++i) { derinlik[i] = gv.yonDonustur(fs[i].dir).z; // >0 → kameraya bakan (ön) facet sira[i] = i; } std::sort(sira.begin(), sira.end(), [&](int a, int b) { return derinlik[a] < derinlik[b]; }); auto ekr = [&](Vec3f p) { const Vec3f v = gv.yonDonustur(p); return ImVec2(mrk.x + v.x * R, mrk.y - v.y * R); }; // ---- Hover: en öndeki ön facet ---- int hover = -1; if (vpHover) { for (int s = N - 1; s >= 0; --s) { const int fi = sira[s]; if (derinlik[fi] <= 0.03f) continue; ImVec2 pr[4]; for (int k = 0; k < fs[fi].n; ++k) pr[k] = ekr(fs[fi].v[k]); if (poligonIcinde(fp, pr, fs[fi].n)) { hover = fi; break; } } } if (hover >= 0) ustunde = true; // ---- Çiz (uzak→yakın) ---- for (int s = 0; s < N; ++s) { const int fi = sira[s]; const Facet& f = fs[fi]; const bool on = derinlik[fi] > 0.03f; const bool hv = (fi == hover); ImVec2 pr[4]; for (int k = 0; k < f.n; ++k) pr[k] = ekr(f.v[k]); ImU32 dolgu; if (!on) dolgu = IM_COL32(38, 46, 60, 150); else if (hv) dolgu = IM_COL32(90, 175, 255, 240); else if (f.tip == 0) dolgu = IM_COL32(72, 86, 110, 225); // yüz else dolgu = IM_COL32(52, 62, 82, 220); // kenar/köşe (pah) daha koyu const ImU32 kenar = on ? IM_COL32(150, 180, 220, 230) : IM_COL32(64, 76, 98, 110); if (f.n == 3) dl->AddTriangleFilled(pr[0], pr[1], pr[2], dolgu); else dl->AddQuadFilled(pr[0], pr[1], pr[2], pr[3], dolgu); for (int k = 0; k < f.n; ++k) dl->AddLine(pr[k], pr[(k + 1) % f.n], kenar, 1.2f); if (on && f.tip == 0 && f.et) { ImVec2 c{0, 0}; for (int k = 0; k < f.n; ++k) { c.x += pr[k].x; c.y += pr[k].y; } c.x /= f.n; c.y /= f.n; const ImVec2 ts = ImGui::CalcTextSize(f.et); dl->AddText(ImVec2(c.x - ts.x * 0.5f, c.y - ts.y * 0.5f), hv ? IM_COL32(255, 255, 255, 255) : IM_COL32(220, 230, 240, 235), f.et); } } // ---- Tık → snap (yukarı ekseni ayarına göre) ---- if (hover >= 0 && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) { const Vec3f dir = fs[hover].dir; Vec3f up = ayar.yukariEksen == 1 ? Vec3f{0, 1, 0} : Vec3f{0, 0, 1}; if (std::abs(dir.birim().nokta(up)) > 0.985f) // dik bakış → up dejenere, diğer eksene geç up = ayar.yukariEksen == 1 ? Vec3f{0, 0, 1} : Vec3f{0, 1, 0}; kamera.bakisGit(dir, up); ustunde = true; } } } // namespace fiko