14 August, 2025

Vertex snapping

Relatívne častou operáciou v počítačovej grafike je prichytávanie kurzoru myši k vertexu v 3D scéne. Niektoré grafické engine poskytujú metódy na realizáciu tohto problému vo forme vstavaných funkcionalít. Napr. grafický engine Unity používa svoje prvky na realizáciu snappingu, teda prichytávania objektov vo všeobecnosti. Osobne som vedel o tom, že Unity niečo také poskytuje, pretože som najprv hľadal množstvo materiálov na túto tému. Avšak, potreboval som naprogramovať snapping bez obslúžnych funkcionalít grafických engine. Prečo ? Pretože použitie funkcionalít z rôznych enginov je vzťahované na daný engine, nie je to univerzálne riešenie. Po vzore programovania terénu ma napadlo použiť systém priesečníka bodu na realizáciu prichytávania bodov. Povedal som si, že akonáhle mám bod prieniku na Face, plôške, tak tento bod je možné prepočítať na okolité body vertexov, pretože musí platiť, že daný bod sa nachádza presne na rovine zarovno s okolitými vertexmi, čo je zrejmé. Ak to takto je, tak stačí abstrahovať bod prieniku a porovnať tento bod z okolitými bodmi, vertexmi. Zámerne píšem slovo abstrahovať a nie zaokrúhľovať. Uvediem môj programový kód: (GIT: https://github.com/indicatrix-git/tycoon-terrain-enhanced/blob/main/SnapVertex.cs)
public Vector3 SnapVertex(Vector3 hitPoint)
    {
        float snapX = 0, snapY = 0, snapZ = 0;

        int xx = (int)hitPoint.x; float x = hitPoint.x - xx;
        int zz = (int)hitPoint.z; float z = hitPoint.z - zz;

        if (x >= 0.0f && x <= 0.5f) { snapX = xx; }
        else snapX = xx + 1;

        if (z >= 0.0f && z <= 0.5f) { snapZ = zz; }
        else snapZ = zz + 1;

        snapY = FunctionalValueY(snapX, snapZ);
        snapSphere.transform.position = new Vector3(snapX, snapY, snapZ);

        return new Vector3(snapX, snapY, snapZ);
    }
Ako je možné vidieť, nefiguruje tam zaokrúhľovanie bodu. Pôvodne som to takto mal, ale zistil som, že aplikácia funguje dosť pomaly. Operácia bola časovo náročná. Napadlo ma abtrahovať bod prieniku a riešiť kvázi dichotomický problém, teda to, že dané číslo je väčšie alebo menšie ako separované číslo. Takže máte vedený bod prieniku, napr. 2.1447859 a toto číslo abstrahujeme, teda odstrihneme celú časť čísla tak, aby nám ostalo číslo 0.14478569. A toto číslo bude môcť nadobúdať rozsah od 0 až 1. Teda jednotlivá plôška, Face, rozdelí túto plôšku na štyri časti, kvázi kvadranty. A potom už len kontrolujeme, či sa dané číslo nachádza v danom rozsahu. Ak áno, tak sa priradí celá časť čísla do snapping premennej, ak nie, tak tam bude číslo o +1 väčšie, pretože to bude číslo druhej súradnice po rovnakej línii. Otázka je, že ak som riešil toto pre súradnice x a z, tak situácia bola schodná, ale akonáhle som tento princíp chcel uplatniť pre y súradnicu, tak nastal problém. Jednak v tom, že y súradnica sa navyšuje, čo by ešte bolo možné vyriešiť, ale problém bol v tom, že kurzor nezachytával exaktne vždy daný bod, preskakoval na iný vertex. Napadlo ma použiť funkčnú hodnotu Y pre coords, teda zoznam súradníc celého terénu. Zadáme hodnoty X a Z a jednoduchá funkcia nám vráti hodnotu Y. Teda, vždy bude isté, že ak zadáme dve funkčné hodnoty, tak tretia funkčná hodnota musí byť presná v každom prípade, pretože je to originálna hodnota pre coords. V nasledujúcom videu to popisujem podrobnejšie:
Share:

0 comments:

Post a Comment