Vivid raytracer
Egyebek
Fotózás

Műveletek testekkel

Az előzőekben végigvettük az alaptesteket (primitívek), de joggal adódik a kérdés, hogy hogyan lehet gömbökből, hengerekből vagy sokszögekből összetett testeket építeni? Alapvetően két útja van ennek:

Vágási műveletek

Az alakítás egyik lehetősége a vágás. Gyakorlatilag szinte bármely alaptestet elvághatjuk (kifúrhatjuk, metszhetjük stb.) egy másikkal, így végtelen számú variációs lehetőség adódik. A vágási utasítást kétféle módon is megadhatjuk, az egyik módszer, hogy az elvágandó test utasításába építjük bele. Ilyenkor a vágási művelet csak arra az egy testre vonatkozik, amelybe beleépítettük a vágást. Természetesen akár több (végtelen) vágási utasítást is kiadhatunk egy testre. A másik lehetőség, hogy ha sok testet akarunk ugyanúgy megvágni, akkor külön vágási blokkot írunk, és ezen belül helyezzük el a testeket, a vágás pedig minden testre vonatkozni fog ami ezen a blokkon belül van. Na de menjünk is sorba az egyes variációkon…


Vágás síkkal

A legegyszerűbb vágási művelet, mikor egy alaptestet elvágunk egy síkkal. Ehhez csak arra van szükség, hogy az elvágandó testbe építsünk egy clip nevű utasítást, amiben meghatározzuk azt a síkot, amivel kettévágjuk a testet. A példában egy gömböt fogok kettévágni egy síkkal. Azt, hogy a gömbnek melyik fele marad meg, és melyik lesz levágva, a sík normálvektora határozza meg. Mindjárt közérthetőbb lesz:

sphere {
      center -2 0 1.2
      radius 1.2
      clip {
        center 1 0 2
        normal 0 0 1 } }

Mint látható, a gömb utasításába belekerült a clip, mely újabb kapcsos zárójelet nyit, megadja saját utasításait, és zárja a kapcsos zárójelet. A clip-en belüli center parancs, annak a síknak a középpontját jelenti, amellyel kettészeljük a gömböt. A normal pedig a sík normálvektorát jelenti. Mint látható ez „felfelé” mutat. Felvetődik a kérdés, hogy mutathatna „lefelé” is, mert a sík attól még ugyanaz maradna? A válasz igen, lefelé is mutathatna, de mégis van jelentősége, mert ez határozza meg, hogy a gömb mely része marad meg vágás után. A lenti képen a bal oldali gömbböt „lefelé” mutató síkkal vágtam el, a jobb oldalit „felfelé” mutatóval.

Clip with plane

Hogy a dolog teljesen közérthető legyen, készítettem egy szemléltető ábrát is:

Vágás síkkal


Vágás gömbbel

Szintén nem túl bonyolult feladat, gömbbel is végezhetünk vágást. A lenti példában egy hengert fogok elvágni egy gömbbel. Először is nézzük magát az utasítást:

cone {
      apex 1 0 3
      base 1 0 0
      radius 1.2
      clip {
        center 2.2 0 1.2
        radius .7
        inside } }

Felbukkant egy új játékos, az inside. Ennek párja az outside. Ezek döntik el, hogy a vágás után melyik része maradjon meg az elvágott testnek. A lenti képen balra egy outside, jobbra egy inside látható.

Vágás gömbbel


Vágás hengerrel

Hengerrel is tudunk vágni, ugyanúgy használható itt is az outside és az inside, sőt akárcsak a henger testnél itt is használhatjuk az apex_radius valamint base_radius jelöléseket, ami lehetővé teszi, hogy kúp alakzattal vágjunk.

cone {
      apex 1 0 3
      base 1 0 0
      radius 1.2
      clip {
        apex 2 0 1
        base 1 1 3
        radius .7
        inside } }

A példában, egy hengert vágtam egy másik hengerrel. A lenti képen látszik, hogy ez hogyan néz ki. Balról jobbra: Henger vágva hengerrel (outside), henger vágva hengerrel (inside), gömb vágva hengerrel (outside).

Vágás hengerrel


Tömeges vágás (global clip)

Elérkeztünk a csoportos vágáshoz, amikor definiálunk egy vágási műveletet, és ezt testek csoportjára alkalmazzuk. Nézzük is meg, hogy hogyan néz ez ki:

global_clip {
      clip { ... }
      clip { ... }
      clip { ... } }


Ide jönnek a testek sorban...
Ide jönnek a testek sorban...
Ide jönnek a testek sorban...
Ide jönnek a testek sorban...

clip_pop

A tömeges vágást a global_clip paranccsal nyitjuk, majd sorban megadjuk egyenként a vágásokat (lehet vegyesen síkkal, gömbbel, hengerrel vágni). Ha megadtunk minden vágást amit el akarunk végezni az ez után következő testeken, akkor kapcsos zárójellel zárjuk a global_clip utasítást, és egyszerűen megadjuk a vágandó testeket. Ha ez is kész, akkor a clip_pop paranccsal tudjuk lezárni a vágást. A tömeges vágásnál akár több szinten is ágyazhatunk be újabb tömeges vagy egyedi vágásokat tetszőleges számban. Ilyenkor figyeljünk rá, hogy ha két global_clip-et nyitunk meg, akkor utána kétszer is kell lezárni a clip_pop utasítással! A lenti képen egy tömeges vágás látható, ahol egy hengerrel vágtam el két gömböt és egy kúpot.

Tömeges vágás (global clip)


Transzformációk

A testeket nem csak vagdosni tudjuk, hanem forgatni, átméretezni és odébbtenni is, ezeket a műveleteket nevezzük transzformációknak. A transzformációk nem csak a testre vonatkozhatnak, hanem a testek felületére is (például tektúra, mintázat stb.) attól függően, hogy belevesszük e ezeket is a műveletbe. Nézzük is sorban...


Elmozgatás

Az elmozgatás arra jó, hogy egy testet (vagy testek csoportját) odébbtegyük a tér bármelyik irányában. Az utasítás kicsit hasonló a tömeges vágáshoz:

transform {
     translate 4 5 1 }


Ide jönnek a testek és/vagy felületek sorban...

transform_pop


Átméretezés

Testet vagy testek csoportját tudod vele átméretezni. Olyankor hasznos, ha például összetett testet kell beillesztened a képde, de a méretarány nem stimmel. Így kell leírni:

transform {
     scale 4 }


Ide jönnek a testek és/vagy felületek sorban...

transform_pop

A scale számértéke adja a szorzót, amivel növelve lesz a test. Ha egynél kissebb a szám, akkor csökkentésről beszélünk, ha nagyobb akkor növelés. A dolog teljesen lineáris, ha a scale értéke 2 akkor kétszeresére nő minden mérete a testnek. A lenti képen egyszerre alkalmaztam az eltolást és az átméretezést ugyanazon a testen, amit 4-szer linkeltem be az #include paranccsal.

Transzformáció eltolás és átméretezés


Forgatás

Harmadik játékosunk a forgatás. Ezzel a paranccsal a három koordináta mentén tetszőlegesen elforgathatunk testet, vagy felszínt. A forgatás mértékét fokokkal adjuk meg, tehát a 360° egy teljes körbefordulást jelent. Az utasítás így néz ki:

transform {
     rotate 15 291 107 }


Ide jönnek a testek és/vagy felületek sorban...

transform_pop

A lenti képen ugyanazt a testet többször belinkeltem, eltoltam, majd elforgattam mindet 30° -al az előzőtől.

Transzformáció forgatás


Többféle transzformáció egyszerre

Természetesen lehetőség van rá, hogy egy transzformáción belül többféle átalakítást is végezzünk. Ezt minden további nélkül megtehetjük, csak transform utasításban fel kell sorolni egymás után az elvégzendő műveleteket. Amit viszont fontos szem előtt tartani, hogy a műveletek sorrendje nem mindegy! A vivid olyan sorrendben fogja végrehajtani az átalakításokat, amilyenben mi megadtuk. Tehát ha eltolok valamit, majd utána elforgatom az nem egyenlő azzal mintha először elforgatnám és utána tolnám el, ugyanis az első esetben az eltolás is elforgatásra kerül! A fenti képen jól látható ez, körben állnak a kupidó szobrok. Ezt úgy értem el, hogy a középpontból eltoltam a szobrot, majd utána forgattam. Ha először forgattam volna el, és csak aztán jön az eltolás, akkor minden szobor ugyanoda került volna, csak különböző szögben elfordulva. Valahogy így:

Transzformáció forgatás

Persze előfordulhat, hogy pont ez a cél, mindenesetre a sorrend lényeges, tehát átgondolva adjuk meg az átalakításokat. Maga az utasítás egyébként így néz ki:

transform {
     scale 5
     rotate 15 291 107
     translate 0 2 1 }


Ide jönnek a testek és/vagy felületek sorban...

transform_pop


Transzformációk egymásba ágyazva

Van még további lehetőség is a variálásra. Ez az, amikor egymásba ágyazunk több transzformációt is. Például szeretnénk sok belinkelt testet fele méretre csökkenteni, és ezen belül néhány testet el is akarunk forgatni. Ilyenkor nyitunk egy transform utasítást, amiben megadjuk az átméretezést, majd jöhetnek azok a testek amiket csak átméretezni akarunk. Amikor azok a testek következnek, amiket az átméretezés mellett forgatni is szeretnénk, akkor nyitunk egy újabb transform -ot, amiben megadjuk a forgatást, majd jöhetnek a maradék testek. Ha minden megvan, akkor kétszer zárjuk a transform_pop utasítással, egyszer a méretezéskor megnyitott transform-t, egyszer pedig a forgatás miatt nyitottat. Így néz ki az utasítás:

transform {
     scale .5 }


Ide jönnek a testek és/vagy felületek amiket csak átméretezni akarunk...

transform {
     rotate 0 0 35 }


Ide jönnek a testek és/vagy felületek amiket forgatni is akarunk...

transform_pop
transform_pop


Tovább a felületek definiálásához...»
foot