19 March, 2025

Projection of space onto a plane

V minulej časti bol popísaný postup ako vykresliť dvojrozmerné objekty na obrazovku počítača (na tzv. plátno). Takýto postup je priamočiary, to znamená, akýmkoľvek spôsobom zadáme súradnice objektu, na plátno vykresľujeme v tých istých súradniciach, prípadne obohatené o transformačné vzťahy, najčastejšie posunu objektu, otočenie alebo zmenu mierky objektu. camSituácia sa zmení pridaním ďalšieho rozmeru obrazu - rozmeru håbky. V tomto okamihu už dochádza k simulácii ľudského videnia, avšak stále len k simulácii, napodobovaniu, pretože zostrojiť úplne dokonalý obraz ľudského videnia reálneho sveta nie je doposiaľ možné. Z fyzikálneho hľadiska si môžme predstaviť okolitý svet ako spojitý, analógový a svet elektroniky ako nespojitý, digitálny. Najlepšie to reprezentuje videokamera alebo fotoaparát, ktorým snímame jednotlivé obrázky. Procesom snímania okolitého sveta prostredníctvom objektívu je vždy nejaký prevod obrazu z tohto objektívu (analógový signál) na obrazový formát (digitálny signál). Tento prevod je daný nejakou transformáciou. Doposiaľ žiadny objektív nedokáže zachytiť obraz bezchybne, takže okrem samotnej transformácie obrazu dochádza aj k transformačným, korekčným chybám objektívov. Tieto korekcie, transformácie sú vo všeobecnosti vzťahy, ktoré vyjadrujú spojitosť, väzbu, medzi jednotlivými prvkami. Premietanie v našom prípade je transformácia, ktorá charakterizuje prevod trojrozmerných súradníc objektu do dvojrozmerných súradníc, pričom v takejto reprezentácii, ako už bolo spomínané, dochádza vždy k strate priestorovej informácie. Deskriptívna geometria je jedna z matematických disciplín, ktorá sa zaoberá rôznymi prepismi geometrických scén. eyeProces ľudského videnia je založený v konečnom dôsledku na vyhodnotení signálov v mozgu. Preto, čím vernejšie vykreslíme 3D scénu na monitore počítača, tým prirodzenejšie bude schopný mozog spracovať jednotlivé signály. Pri spracovaní videnia v určitej fáze prebieha v mozgu k tzv. stranovému kríženiu obrazu (okrem toho aj k zmenšeniu a dvojitému stranovému otočeniu obrazu) z ľavého a pravého oka. Týmto procesom vnímame okolitý svet priestorovo, vzniká dojem håbky. Takýto priestor nie je možné vytvoriť v mozgu z roviny akéhoko¾vek monitora, takže aj keï prakticky neustále dochádza k stranovému kríženiu obrazu, výsledný obraz bude priestorový len do kvality poskytnutej 3D transformácie. Poznámka: V súvislosti s procesom videnia mozgom, pozná neurológia určitý stav, kedy vidíme obraz, nejaké predmety, ale nedokážeme ich identifikovať. Teda, na sietnici oka sa premieta obraz z okolitého prostredia, ale napriek tomu náš mozog nedokáže jednotlivé signály spracovať a v dôsledku toho, vlastne nevidíme nič, sme slepí. Takýto stav sprevádzajú pomerne ťažké neurologické ochorenia, ale aj keï nie presne v tomto význame ich občas môže zažiť aj zdravý človek, napr. nieko¾ko sekúnd po prebudení zo spánku, alebo tesne pri zaspávaní a v neposlednom rade aj pri požití omamných a psychotropných látok.

Premietanie

Premietanie je transformácia, ktorá charakterizuje prevod trojrozmerných súradníc objektu do dvojrozmerných súradníc. Obraz, ktorý vznikne premietaním sa nazýva priemet. Takyto priemet sa premieta na priemetni, co je možné si predstaviť ako monitor počítača, na ktorom vidíme už výsledný obraz scény. Tento obraz na priemetni vznikne premietajúcimi lúčmi, ktoré dopadnú na túto priemetòu. Premietací lúč si je možné predstaviť matematicky ako polpriamku, ktorá vychádza v určitom konkrétnom bode a ktorej smer určuje konkrétna premietacia metóda. Smer premietacich lucov moze byt vo vseobecnosti v zasade len bud rovnobezny, tzv. rovnobezne premietanie (paralelne), kde jednotlive polpriamky su navzajom rovnobezne, alebo roznobezny, tzv. stredove premietanie (perspektivne), kde vychadzaju z jedneho bodu. Cieľom je nájdenie transformačných matíc, ktoré definujú transformáciu súradníc premietaných bodov. V nasledujúcich častiach budú popísané najpoužívanejšie typy premietania, rovnobežné premietanie, ktorej zástupcom je axonometrické premietanie a stredové premietanie, alebo tiež perspektívne. Ostatné typy sú podobné týmto typom a líšia sa len zmenou niektorých parametrov.

Rovnobežné premietanie

Do rovnobežného premietania patrí axonometria a jej špeciálne prípady ako dimetria, trimetria, izometria. Špeciálny prípad rovnobežného premietania je kolmé premietanie a jej charakteristickým prípadom je Mongeové premietanie, kedy premietacie lúče sú kolmé na priemetòu, čím vytvárajú priemet objektu v troch smeroch, spredu (nárys - Front), zboku (bokorys - Side), zhora (pôdorys - Top). axnImgV súradnicovej sústave P, x_1, x_2 je axonometria reprezentovaná súradnicovou sústavou O_a, E_{a}^{x}, E_{a}^{y}, E_{a}^{z}, uhlami \xi, \eta a tzv. axonometrickým trojuholníkom, ktorý tvoria jednotkové vektory e^x, e^y, e^z. Nech bod A \in E^3 má súradnice A(x^A, y^A, z^A) a jeho pôdorys A_1(x^A, y^A, 0). V axonometrii \phi: E^3 \rightarrow \varepsilon \times \varepsilon[/latex] je obrazom bodov A, A_1 usporiadaná dvojica bodov (A_a, A_{1a}) pre ktorú platí [latex]A_a A_{1a} \parallel z_a. Vzh¾adom na axonometrickú súradnicovú sústavu O_a, E_{a}^{x}, E_{a}^{y}, E_{a}^{z} majú body A_a A_{1a} súradnice A_a(x^A e^x, y^A e^y, z^A e^z), A_{1a}(x^A e^x, y^A e^y, 0). Výpočet konkrétneho bodu A_a(x_1^A, x_2^A) vzhľadom na súradnicovú sústavu Px_1x_2 bude záležitosťou použitia goniometrických funkcií. Teda, podľa daného obrázku platí:
 


Jednotlivé uhly vyjadrujú určité typy axonometrie, napr. dimetria, izometria, vojenská axonometria a podobne. Tento zápis je možné napísať aj pomocou maticového zápisu vo forme transformačného vzťahu v homogénnych súradniciach: 





 Samotný programový kód v podstate na každý bod obrazu aplikuje uvedené transformačné vzťahy pre určitý typ axonometrie.
namespace _3D_Renderer
{
    class Projection
    {
        int[,] transformation = new int[8, 2];
        

        public void Axonometric(int x, int y, int z, int n)
        {
            transformation[n, 0] = (int)(-x * Math.Cos(-0.7) + y * Math.Cos(0.8) + 800 / 2);
            transformation[n, 1] = (int)(-x * Math.Sin(-0.3) - y * Math.Sin(-0.2) + z + 600 / 2);
        }
        

        public int[,] Transformation
        {
            get
            {
                return transformation;
            }
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            int width = 800;
            int height = 600;

            Canvas canvas = new Canvas(width, height);
            Projection projection = new Projection();

            Color background = new Color(0, 0, 0);
            Color white = new Color(255, 255, 255);

            canvas.clearColor(background);

            int[,] mVertices = { { 0, 0, 0 }, { 100, 0, 0 }, { 100, 0, 100 }, { 0, 0, 100 }, { 0, 100, 0 }, { 100, 100, 0 }, { 100, 100, 100 }, { 0, 100, 100 } };


            int[,] mIndices = { 
                                          { 0, 1, 0, 1, 1, 0, 0, 0 },
                                          { 1, 0, 1, 0, 0, 1, 0, 0 },
                                          { 0, 1, 0, 1, 0, 0, 1, 0 },
                                          { 1, 0, 1, 0, 0, 0, 0, 1 },
                                          { 1, 0, 0, 0, 0, 1, 0, 1 },
                                          { 0, 1, 0, 0, 1, 0, 1, 0 },
                                          { 0, 0, 1, 0, 0, 1, 0, 1 },
                                          { 0, 0, 0, 1, 1, 0, 0, 0 },
                                      };


            for (int n = 0; n < 8; n++)
            {
                projection.Axonometric(mVertices[n, 0], mVertices[n, 1], mVertices[n, 2], n);
            }


            for (int i = 0; i < 8; i++)
            {
                for (int j = i; j < 8; j++)
                {
                    if (mIndices[i, j] == 1)
                    {
                        canvas.drawLine(white, projection.Transformation[i, 0], projection.Transformation[i, 1], projection.Transformation[j, 0], projection.Transformation[j, 1]);
                    }
                }
            }

            canvas.render();
            System.Diagnostics.Process.Start("Frame.exe", "frame.ppm");
        }
    }
}
V našom prípade zobrazíme všeobecný typ axonometrie, kedy sú všetky tri uhly navzájom rôzne (trimeria).

 


Stredové premietanie

Stredové premietanie je charakteristické premietajúcimi lúčmi vychádzajúcich z jedného bodu. Týmto spôsobom tento model premietania odpovedá najviac ľudskému videniu, pretože zobrazuje objekty tak, že sa nám na ploche javia s určitou håbkou, perspektívou, a aj z toho dôvodu sa označuje ako perspektívne premietanie. prsImgPri hľadaní perspektívneho zobrazenia sú určujúce jednotlivé priesečníky priemetne \varepsilon so stenou \nu = xz prakticky vytvárajúci pravouhlý trojhran, a tiež voľba stredu lineárnej perspektívy S(s, -d, v). Podľa obrázku (niektoré nasledujúce symboly nie sú na obrázku označené) reprezentuje v, výšku začiatočného bodu S, úsečky SR (teda táto výška rovnobežná s osou z=x_2) a z hľadiska manipulácie perspektívneho obrazu bude možné týmto parametrom meniť výšku celkového pohľadu výsledného obrazu, teda uhol otočenia okolo osy x. Jedná sa o vzdialenosť od tzv. základnej roviny. V prípade v=0 sa budeme nachádzať priamo v horizonte, na obrázku s označením h. Vzdialenosť s je daná začiatočným bodom S, úsečky SR a osy y, resp. pomyselnej roviny yz a bodu S. Týmto parametrom bude možné meniť šírku celkového pohľadu, teda uhol natočenia okolo osy z. A napokon parameter d je tzv. dištancia a je to veľkosť úsečky SH, teda vzdialenosť bodu S od bodu horizontu H. Týmto parametrom bude možné nastaviť celkovú håbku perspektívy. Z uvedeného popisu perspektívnej scény potrebujeme vyjadriť parametrické rovnice priamky SR. Tie vyjadríme pre každú zložku nasledujúcim spôsobom:
 



Parameter d (dištancia) je v tomto prípade záporný, pretože os y nadobúda vo vyznačenom smere kladné hodnoty, a zároveň preto, že na stanovenie priesečníka R_s by mal začiatočný bod S ležať za priemetňou \varepsilon. Bod R_s je priesečník úsečky SR a priemetne \varepsilon, ktorá má rovnicu y=0. Hodnotu parametra t vypočítame nasledovne:


odtiaľ


Po dosadení a úprave získame súradnice bodu, priesečníka R_s v sústave E^3:
 



V súradnicovej sústave E^2 platia vzťahy pre x_1 a x_2. Tieto vzťahy budú obsahom nasledovného kódu, ktorý jednotlivé body obrazu z priestoru konvertuje uvedenými transformačnými vzťahmi do roviny.
namespace _3D_Renderer
{
    class Projection
    {
        int[,] transformation = new int[8, 2];


        public void Perspective(int x, int y, int z, int n)
        {
            int d = 150;
            int s = 200;
            int v = -75;

            transformation[n, 0] = (int)((d * x + s * y) / (d + y) + 800 / 2);
            transformation[n, 1] = (int)((v * y + d * z) / (d + y) + 600 / 2);
        }
        

        public int[,] Transformation
        {
            get
            {
                return transformation;
            }
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            int width = 800;
            int height = 600;

            Canvas canvas = new Canvas(width, height);
            Projection projection = new Projection();

            Color background = new Color(0, 0, 0);
            Color white = new Color(255, 255, 255);

            canvas.clearColor(background);

            int[,] mVertices = { { 0, 0, 0 }, { 100, 0, 0 }, { 100, 0, 100 }, { 0, 0, 100 }, { 0, 100, 0 }, { 100, 100, 0 }, { 100, 100, 100 }, { 0, 100, 100 } };


            int[,] mIndices = { 
                                          { 0, 1, 0, 1, 1, 0, 0, 0 },
                                          { 1, 0, 1, 0, 0, 1, 0, 0 },
                                          { 0, 1, 0, 1, 0, 0, 1, 0 },
                                          { 1, 0, 1, 0, 0, 0, 0, 1 },
                                          { 1, 0, 0, 0, 0, 1, 0, 1 },
                                          { 0, 1, 0, 0, 1, 0, 1, 0 },
                                          { 0, 0, 1, 0, 0, 1, 0, 1 },
                                          { 0, 0, 0, 1, 1, 0, 0, 0 },
                                      };


            for (int n = 0; n < 8; n++)
            {
                projection.Perspective(mVertices[n, 0], mVertices[n, 1], mVertices[n, 2], n);
            }


            for (int i = 0; i < 8; i++)
            {
                for (int j = i; j < 8; j++)
                {
                    if (mIndices[i, j] == 1)
                    {
                        canvas.drawLine(white, projection.Transformation[i, 0], projection.Transformation[i, 1], projection.Transformation[j, 0], projection.Transformation[j, 1]);
                    }
                }
            }

            canvas.render();
            System.Diagnostics.Process.Start("Frame.exe", "frame.ppm");
        }
    }
}
Teda, z hľadiska kódu sa jedná o analogický postup ako pri axonometrii. Jednotlivé vstupné parametre metódy Perspective(), predstavujú už spomínané perspektívne parametre, pričom tieto parametre sa uplatòujú po korekcii šírky a výšky obrazu, takže z toho dôvodu sa obraz nachádza v štvrtom kvadrante celkového obrazu. Ak chceme zobraziť pohľad smerujúci zhora na daný objekt, tak parameter v by mal mať zápornú hodnotu, pretože začiatok súradnicovej sústavy (0,0) je v ľavom hornom rohu obrazu a keï chceme posunúť bod S smerom kolmo nahor, tak potrebujeme odpočítať určitú hodnotu od obrazovej osy y. Výsledný obrázok perspektívneho zobrazenia kocky pomocou jedného úbežníka je na nasledujúcom obrázku:

 


Renderovanie

glassesUvedené spôsoby poukázali na niektoré najčastejšie typy premietaní. Vykresľovanie doposiaľ prebiehalo spôsobom známym z OpenGL/DirectX, kedy len pomocou bodu a úsečky vykresľujeme komplexné objekty. Grafické priemyselné štandardy pracujú v režime vykresľovania scény v reálnom čase, to znamená, že akékoľvek grafické objekty sú na priemetni prekresľované v pravidelných časových intervaloch a navyše takýto spôsob vykresľovania úzko súvisí s hardwarovými vymoženosťami grafickej karty. V celom seriály ako aj u uvedenom prípade bol použitý spôsob vykresľovania objektov z grafických priemyselných štandardov, avšak vykresľovanie scény bolo realizované jednorazovym prepisom prostredníctvom zaznamenanych bodov z platna do obrazového suboru typu PPM. Prakticky to znamenalo to, že sme pouzili vektorovy sposob zapisu objektov, a tento zapis sme priamo aplikovali na priemetnu v povodnom stave, ktory sme uz len jednoducho ulozili do uz spominaneho obrazového suboru. Každe vykreslovanie grafických objektov urcitym systemom sa nazyva renderovanie, avšak v povodnom vyzname tohto oznacenia sa jedna o proces, ktory vedie k fotorealistickému zobrazovaniu geometrických objektov. V nasledujucich castiach serialu pojde o tzv. renderovanie v klasickom vyzname, to znamena, proces tvorby obrazu z 2D/3D modelov pouzitim textur, osvetlovacich modelov a algoritmami tienovania. Jedna sa o systém znamy z integrovanych renderovacich nastrojov od spolocnosti Autodesk, ktora vydava svoje jednotlive produkty ako napr. 3D Studio MAX, Maya, alebo niektore verzie AutoCADu.
Share:

0 comments:

Post a Comment