Hlavní navigace

Myslíme v jazyku POV-Ray

11. 11. 2008
Doba čtení: 14 minut

Sdílet

Název dnešní části seriálu o raytraceru POV-Ray, který paroduje tituly knížek „Myslíme v jazyku XXX“, naznačuje, jakou vlastností POV-Raye se budeme zabývat. Ukážeme si, jakým způsobem lze konstruovat programové smyčky, podmínky i objekty a jak nám tyto techniky mohou ulehčit tvorbu trojrozměrných scén.

Obsah

1. Myslíme v jazyku POV-Ray
2. Vkládání externích souborů
3. Deklarace nových identifikátorů
4. Rušení identifikátorů
5. Podmíněný příkaz
6. Programové smyčky
7. První demonstrační příklad – animované těleso vytvořené programovou smyčkou
8. Druhý demonstrační příklad – spirála s pěti rameny vytvořená dvojicí smyček
9. Obsah další části seriálu

1. Myslíme v jazyku POV-Ray

Při tvorbě zdrojových textů trojrozměrných scén pro POV-Ray se nemusíme omezovat pouze na deklarativní zápis jednotlivých objektů, ale je možné použít i některé konstrukce známé z běžných programovacích jazyků. I to je jeden z důvodů, proč existuje tak málo aplikací, které dokáží spolehlivě načíst POV-Rayovské scény – aby byl import scén bezproblémový, musí se implementovat poměrně velká část funkcionality tohoto vyspělého raytraceru (pokud bych se měl držet terminologie z teorie překladačů, jedná se o front end). Před popisem jednotlivých jazykových konstrukcí, které je možné v POV-Rayi použít, si musíme vysvětlit, jakým způsobem vlastně POV-Ray před renderingem i v jeho průběhu pracuje. Jeho základní funkce je poměrně jednoduchá: při spuštění tohoto raytraceru je nutné zadat jméno (popř. i cestu) k textovému souboru, který obsahuje popis scény, jež se má vykreslit. Tento soubor je postupně načítán a zpracováván takzvaným preprocesorem, který plní podobnou funkci jako preprocesor programovacího jazyka C či C++.

povray3501

Obrázek 1: Těleso vytvořené poměrně jednoduchým skriptem – dvojicí vnořených programových smyček. Celý objekt je vytvořen z koulí, které se raytracingem vykreslují velmi rychle.

V průběhu preprocesingu se mohou do scény vkládat další soubory, používat (rozvinout) dříve vytvořená makra, vyhodnocovat podmíněné výrazy a dokonce i podmíněné smyčky. Výsledkem práce preprocesoru je po částech generovaný zdrojový text scény (umístěný v operační paměti, nikoli v souboru), který je dále analyzován a zpracováván, tj. parsován, přičemž je průběžně vytvářena stromová struktura jednotlivých objektů, které se ve scéně vyskytují, doplněná o další automaticky vytvořená data, například informace o obalových tělesech. Tato datová struktura je již použita při vlastním raytracingu. Důležité je, že načítání souboru se zdrojovým kódem, preprocesing i parsing, se provádí souběžně, tj. výstup z jednoho bloku je přesměrován na vstup bloku následujícího. Tím dochází k menší spotřebě operační paměti, do níž je umístěna až výsledná stromová (binární) struktura představující vykreslovanou scénu. Tato struktura má obecně menší velikost, než zdrojové kódy představované textovými soubory (výjimkou mohou být složité scény využívající právě makra a smyčky).

povray3502

Obrázek 2: Tento objekt, který vytvořil v roce 1992 Truman Brown, je taktéž složen pouze z koulí, jejichž velikost a umístění bylo vypočteno programovým skriptem.

Z výše uvedených informací vyplývá, že prakticky všechny dále popsané konstrukce jsou prováděny preprocesorem při načítání a základním zpracovávání zdrojových kódů – tyto konstrukce budeme nazývat direktivy, protože řídí činnost preprocesoru. Samotný preprocesor je poměrně vyspělý, jelikož dokáže zpracovávat základní aritmetické a logické výrazy, při deklaracích identifikátorů rozeznávat datové typy apod. Vzhledem k tomu, že je preprocesing zdrojového kódu oddělen od parsingu a tvorby interní stromové struktury, mohou se všechny dále popsané konstrukce vyskytovat ve zdrojovém textu prakticky kdekoli – například direktiva #if představující podmínku může být zapsána uvnitř nějakého objektu a končit až za deklarací tohoto objektu atd. Na tomto místě je vhodné říci, že předchozí verze POV-Raye se v tomto ohledu chovaly odlišně. Z tohoto důvodu mohou nastat problémy při zpracování starších zdrojových kódů – tyto problémy lze vyřešit korektním nastavením verze pomocí direktivy #version).

povray3503

Obrázek 3: Objekt vytvořený pomocí druhého demonstračního příkladu po mírné modifikaci jeho zdrojových kódů.

2. Vkládání externích souborů

První direktivou, se kterou jsme se již mohli setkat prakticky ve všech demonstračních příkladech, je direktiva #include určená pro vložení obsahu nějakého (většinou odlišného) textového souboru. Jakmile preprocesor tuto direktivu při zpracovávání zdrojového textu nalezne, přečte si jméno souboru uvedeného za touto direktivou a vloží obsah souboru na místo, kde se direktiva v textu nachází. Poté pokračuje dále v preprocesingu. V praxi to znamená, že pokud se ve vkládaném textu opět vyskytuje direktiva #include, je taktéž preprocesorem zpracována, dokonce je možné provést rekurzivní vložení – zde je ovšem počet rekurzivně vkládaných souborů omezen na deset. Jméno vkládaného souboru může obsahovat i absolutní či relativní cestu. Kromě toho jsou vkládané soubory hledány i v adresáři specifikovaném při spuštění POV-Raye parametrem +L. Běžně je prohledáván standardní adresář obsahující soubory s užitečnými deklaracemi a makry. Například se může jednat o adresář /usr/share/povray/include, konkrétní umístění se však může v závislosti na způsobu instalace lišit. Vkládané soubory mívají podle konvencí příponu .inc.

povray3504

Obrázek 4: Tato „fraktální“ pyramida byla vytvořena rekurzivním vkládáním obsahu textového souboru do sebe sama. Použitý zdrojový kód si ukážeme v následující části tohoto seriálu.

3. Deklarace nových identifikátorů

Pomocí direktivy #declare a #local je možné vytvářet další identifikátory, které představují pojmenované objekty. Slovem „objekt“ je v tomto případě myšlen objekt jazyka POV-Raye, nikoli nutně geometrický objekt (těleso). Mezi použitelné typy objektů patří číslo (podporována jsou reálná čísla, přesněji řečeno jejich aproximace datovým typem double), řetězec, barva, vektor (typicky obsahující několik reálných čísel), textura, barvová mapa a v neposlední řadě i skutečný geometrický objekt, který by měl být raytracerem vykreslen. Deklarace nového identifikátoru pomocí direktivy #declare vytvoří globální objekt, který není automaticky rušen – jeho zrušení je nutné provést dále popsanou direktivou #undef. Naproti tomu je při použití direktivy #local vytvořen objekt lokální. Lokalita je omezena buď na rozsah makra, ve kterém je identifikátor vytvořen (makra budou vysvětlena příště), nebo jednoho souboru – to má význam především při vkládání souborů pomocí výše popsané direktivy #include. Příklad deklarace několika nových identifikátorů představovaných objekty různého typu:

#declare A=0.1;                          // objekt typu reálné číslo (zde musí být použit středník na konci deklarace)

#declare Y=r1*sin(A*Count)*sin(B*Count)*cos(A*B*Count) // na pravé straně přiřazení se může vyskytovat složitější výraz

#declare New_Sky = sky_sphere            // deklarace objektu typu sky_sphere představujícího oblohu
{
    S_Cloud2
}

#declare bigring =                       // složitější objekt vytvořený pomocí CSG
difference
{
    difference
    {
        cylinder
        {
            <0, 0, tickness/2>, <0, 0, -tickness/2>, bigradius
        }
        cylinder
        {
            <0, 0, tickness/2 + epsilon>, <0, 0, -(tickness/2 + epsilon)>, bigradiusint
        }
        cone
        {
            <0, 0, -(bigradius + 1 - bevel)>, 0, <0, 0, 1 + bevel>, bigradius + 2 inverse
        }
        cone
        {
            <0, 0, bigradius + 1 - bevel>, 0, <0, 0, -(1 + bevel)>, bigradius + 2 inverse
        }
        merge
        {
            cone
            {
                <0, 0, -((bigradiusint - 1) + bevel)>, 0, <0, 0, -((bigradiusint - 1) + bevel) + bigradius>, bigradius
            }
            cone
            {
                <0, 0, (bigradiusint - 1) + bevel>, 0, <0, 0, (bigradiusint - 1) + bevel - bigradius>, bigradius
            }
        }
    }
    torus
    {
        (bigradiusint + smallradius) / 2,
        sphereradius
        rotate x * 90
    }
    box
    {
        <0, 0, -1000>, <1000, 1000, 1000>
    }
}

#declare Ball_Bearing =                  // objekt představující ložisko
union
{
    object
    {
        bigring texture
        {
            Chrome_Metal color Red
        }
    }
    object
    {
        smallring texture
        {
            Chrome_Metal color Blue
        }
    }
    object
    {
        spheres texture
        {
            Polished_Chrome color Yellow
        }
    }
    object
    {
        cage texture
        {
            Polished_Chrome color Green
        }
    }
} 
povray3505

Obrázek 5: Ložisko představované objektem pojmenovaným Ball_Bearing (viz části kódu vypsané výše)

4. Rušení identifikátorů

V předchozí kapitole jsme si řekli, že pomocí direktivy #declare se vytváří identifikátor s globální platností. Ve většině případů není zapotřebí takový identifikátor rušit (jeho platnost trvá až do ukončení parsingu celé scény), ovšem někdy se – především při skládání scény z několika navzájem vkládaných souborů – můžeme dostat do situace, ve které se rozsahy platnosti některých identifikátorů překrývají a může docházet k nežádoucím jevům (u lokálních identifikátorů tato situace nenastává, protože POV-Ray pro každé makro i vkládaný soubor vytváří vlastní tabulku symbolů a prohledávání je prováděno od „nejbližší“ tabulky směrem k tabulce globální). V případě, že je zapotřebí globální identifikátor zrušit, je možné použít direktivy nazvané #undef, za kterou se napíše jméno rušeného identifikátoru.

povray3506

Obrázek 6: Tato na první pohled složitě a pracně vymodelovaná scéna je ve skutečnosti naprogramována doslova na několika řádcích POV-Rayovského kódu. Jedná se o scénu, která se zúčastnila soutěže o co nejkratší a přitom nejzajímavější kód.

5. Podmíněný příkaz

Preprocesor POV-Raye umožňuje i tvorbu podmíněných příkazů typu if-then-else, popřípadě switch-case. Podobně jako v mnoha dalších programovacích jazycích, které nerozeznávají datový typ boolean, je rozhodnutí, zda je podmínka splněna či nesplněna, provedeno na základě vyhodnocení aritmetického výrazu (i numerická konstanta je považována za výraz). Pokud je výsledek výrazu roven nule (nebo se nule velmi přiblíží, což znamená, že je menší než cca 1e-10), je výraz považován za nepravdivý, v opačném případě za pravdivý. Zkrácená verze podmíněného příkazu má tvar:

#if (výraz)  // výraz musí být zapsán v závorkách
...
...
#end 

Samozřejmě je možné přidat i větev else:

#if (výraz)  // výraz musí být zapsán v závorkách
...
...
#else
...
...
#end 

Podmíněné příkazy je možné zanořovat, současný maximální počet zanořených výrazů je roven 200, což je více než dostačující hodnota. V praxi si většinou vystačíme s maximálně třemi úrovněmi zanoření.

POV-Ray podporuje i podmíněný příkaz typu switch-case, který má tvar:

#switch (výraz)                          // výraz musí být zapsán v závorkách
  #case (výraz_1)                        // tato větev je použita pokud výraz=výraz_1
  ...
  ...
  #break                                 // ukončení první větve
  #case (výraz_2)                        // tato větev je použita pokud výraz=výraz_2
  ...
  ...
  #break                                 // ukončení druhé větve
  #range (dolní_hodnota, horní hodnota)  // tato větev je použita,
  ...                                    // pokud výraz>=dolní_hodnota
  ...                                    // a současně výraz<horní_hodnota
  ...
  #break                                 // ukončení třetí větve
  #else                                  // odpovídá "default" v Céčku
  ...
  ...
  #break                                 // ukončení větve "default"
 #end                                    // konec podmíněného příkazu 

Povšimněte si způsobu zápisu třetí větve tohoto podmíněného příkazu. Místo direktivy #case je použita direktiva #range, pomocí níž se testuje, zda hodnota výrazu leží v uvedeném (uzavřeném) intervalu. Díky této direktivě je možné některé programové konstrukce napsat velmi snadno. Také si všimněte, že větev „default“ známá například z Céčka či Javy je zde uvozena direktivou #else, což se spíše podobá syntaxi Pythonu. Tento podmíněný příkaz bude použit ve druhém demonstračním příkladu.

povray3507

Obrázek 7: I tato scéna je vytvořená programově, nikoli v modelovacím programu.

6. Programové smyčky

POV-Rayi lze pomocí direktiv #while a #end vytvořit programovou smyčku typu while. Jedná se univerzální typ smyčky, s jejíž pomocí lze realizovat i další typy smyček – repeat-until či počítanou smyčku for. Tato smyčka bude použita v obou demonstračních příkladech, zde si pouze řekneme, že výraz uvedený za direktivou #while je testován na nulovou hodnotu. Pokud je výraz skutečně nulový, není tělo smyčky preprocesorem a parserem zpracováno; v případě, že je naopak nenulový, je tělo smyčky zpracováno a preprocesor se ihned poté vrátí na začátek smyčky, aby mohl výraz vyhodnotit znovu. Smyčky je samozřejmě možné vnořovat, maximální počet zanoření je opět roven hodnotě 200.

povray3508

Obrázek 8: Další scéna „naprogramovaná“ v POV-Rayi

7. První demonstrační příklad – animované těleso vytvořené programovou smyčkou

Po teoretickém vysvětlení základů programování v POV-Rayi si konečně můžeme ukázat demonstrační příklady, na nichž si předvedeme některé užitečné vlastnosti jazyka tohoto raytraceru. Dnešní první demonstrační příklad, ve kterém je mj. použito připojení obsahu externího souboru, deklarace proměnných, aritmetické výrazy s goniometrickými funkcemi i konstrukce programové smyčky, je určený pro rendering animace tělesa složeného z jediné implicitní plochy (nazývané také metaball či postaru blob), u níž se postupně (v jednotlivých snímcích animace) mění souřadnice středů prvků kostry.

povray3509

Obrázek 9: Jeden z prvních snímků získaných z animované sekvence vytvořené pomocí prvního demonstračního příkladu

Pod implicitní plochou je umístěna rovina, která je pomocí bump-mappingu zdánlivě zvlněna, přičemž i samotné vlny se v jednotlivých snímcích animace mění – pro tento účel je využíván jeden modifikátor procedurálních textur, do nějž je dosazována hodnota interní proměnné clock. Zcela stejným způsobem, tj. postupnou modifikací některého parametru procedurální textury, by bylo možné animovat i mraky na obloze.

povray3510

Obrázek 10: Animace vytvořená pomocí prvního demonstračního příkladu ve své první třetině

Všechny výše zmíněné vlastnosti POV-Raye jsme si již v tomto seriálu popsali: problematika implicitních ploch byla vysvětlena v části šesté a sedmé, bump-mapping, neboli modulace normálových vektorů, v částech 22 a 23 a konečně tvorba animací v částech 27 a 28. Ve zdrojovém kódu prvního demonstračního příkladu si povšimněte zejména způsobu využití interní proměnné clock hned v několika aritmetických výrazech a také toho, jakým způsobem lze zkonstruovat počítanou programovou smyčku typu for, kterou POV-Ray přímo nepodporuje.

povray3511

Obrázek 11: Animace vytvořená pomocí prvního demonstračního příkladu dosáhla své druhé třetiny

Výslednou animaci uloženou ve formátu MPEG-1 s rozlišením 320×240 pixelů je možné získat po kliku na tento odkaz. Celá animace obsahuje 500 snímků, doba jejího trvání je tedy cca 20 sekund (druhá polovina animace je zajímavější :-). Následuje výpis zdrojového kódu prvního demonstračního příkladu:

// ------------------------------------------------------------
// První demonstrační příklad
//
// Těleso vytvořené pomocí deklarace proměnných a použití
// programové smyčky typu "while", která simuluje smyčku
// typu "for" (ta přímo v POV-Rayi neexistuje).
//
// Tvar tělesa se v animaci mění díky použití interní proměnné
// "clock". Samotné animované těleso se skládá z jedné implicitní
// plochy, jejímž základem jsou bodové a úsečkové prvky kostry.
//
// Vodní plocha pod tělesem má animované vlny.
//
// Založeno na souboru dodávaném současně s POV-Ray 3.x (značné úpravy)
//
// rendering lze spustit příkazem:
//     povray +W800 +H600 +B100 +FN +D +Iwhile1.pov +Owhile1.png
//     (pro náhled postačí zadat povray while1.pov)
//
// animaci lze vytvořit přidáním parametru:
//     +KFFpočet_snímků
//
// popř. je možné zvolit konkrétní hodnotu proměnné clock:
//     +Kn.n
// -----------------------------------------------------------

#include "colors.inc"
#include "metals.inc"
#include "skies.inc"

#version 3.0

// globální nastavení parametrů scény
global_settings
{
    assumed_gamma 2.2
}

// nastavení kamery (pozorovatele)
camera
{
    location  <0, 0,-30>                 // pozice kamery ve scéně
    direction <0, 0,  1>                 // směr pohledu kamery
    up        <0, 1, 0>                  // orientace souřadného systému kamery
    right     <4/3, 0, 0>
    look_at   <0, 0, 0>
}

background
{
    color rgb <0.5, 0.5, 0.5>            // barva pozadí celé scény
}


light_source
{
    <20, 30, -100>                       // pozice světelného zdroje
    color <1.0, 1.0, 1.0>                // barva světelného zdroje
}

#declare r1=12;                          // "poloměr" tělesa
#declare A=0.1;                          // první parametr
#declare B=0.15*clock;                   // druhý parametr je ovlivněný proměnnou "clock"

#declare Count=400;                      // počitadlo smyčky
#declare RadiusVal   = 1.2;              // parametry prvků kostry implicitní plochy
#declare StrengthVal = 1.2;

blob                                     // implicitní plocha
{
    threshold 0.6
    #while (Count>=0)                    // programová smyčka typu "while"
                                         // výpočet souřadnic středů bodových prvků kostry tvořících těleso
        #declare X=r1*sin(A*Count)*cos(B*Count)
        #declare Y=r1*sin(A*Count)*sin(B*Count)*cos(A*B*Count)
        #declare Z=r1*cos(A*Count)
        sphere
        {
            <X,Y,Z>, RadiusVal, StrengthVal // souřadnice středu bodového prvku kostry a jeho poloměr
            texture
            {
                pigment                  // barva jednotlivých "koulí" je závislá na jejich poloze
                {
                    color rgb <abs(X/r1), abs(Y/r1), abs(Z/r1)>
                }
                finish                   // změna optických vlastností materiálu
                {
                    ambient 0.2          // ambientní složka
                    diffuse 0.6          // difúzní složka
                    phong 0.3            // míra odlesků
                    phong_size 100       // relativní velikost odlesků
                }
            }
        }
        #declare Count=Count-1           // snížení počitadla
                                         // (simulace počítané smyčky typu "for", která v POV-Rayi neexistuje)
    #end                                 // konec těla programové smyčky #while
    rotate <-20,45,clock*360>            // výsledné natočení tělesa ve scéně
}

#declare New_Sky = sky_sphere            // deklarace objektu představujícího oblohu
{
    S_Cloud2
}

sky_sphere                               // použití výše nadeklarované oblohy
{
    New_Sky
}

// vodní plocha
plane
{
    y, -12.0                             // vzdálenost od počátku
    texture
    {
        T_Chrome_2D
        normal
        {                                // bump mapa pro hladinu
            waves 0.05
            frequency 5000.0
            scale 3000.0
            sine_wave
            phase 10*clock               // i hladina je animovaná
        }
    }
}

// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 
povray3512

Obrázek 12: Animace vytvořená pomocí prvního demonstračního příkladu dosáhla svého konce

8. Druhý demonstrační příklad – spirála s pěti rameny vytvořená dvojicí smyček

Ve druhém demonstračním příkladu je ukázáno použití dvou do sebe vnořených programových smyček zapsaných direktivami #while a #end. Pomocí těchto smyček je vytvořena spirála se šesti rameny, přičemž sudá ramena mají barvu odlišnou od ramen lichých. Výběr barvy je proveden pomocí podmíněného příkazu zapsaného direktivami #switch, #case, #else, #break a #end. I toto těleso je možné animovat. Zdrojový kód tohoto příkladu má tvar:

// ------------------------------------------------------------
// Druhý demonstrační příklad
//
// Tvar tělesa se v animaci mění díky použití interní proměnné
// "clock". Samotné animované těleso se skládá z jedné implicitní
// plochy, jejímž základem jsou bodové prvky kostry.
//
// rendering lze spustit příkazem:
//     povray +W800 +H600 +B100 +FN +D +Iwhile2.pov +Owhile2.png
//     (pro náhled postačí zadat povray while2.pov)
//
// animaci lze vytvořit přidáním parametru:
//     +KFFpočet_snímků
//
// popř. je možné zvolit konkrétní hodnotu proměnné clock:
//     +Kn.n
// -----------------------------------------------------------

#include "colors.inc"
#include "metals.inc"
#include "skies.inc"

#version 3.0

// globální nastavení parametrů scény
global_settings
{
    assumed_gamma 2.2
}

// nastavení kamery (pozorovatele)
camera
{
    location  <0, 25,-30>                // pozice kamery ve scéně
    direction <0, 0,  1>                 // směr pohledu kamery
    up        <0, 1, 0>                  // orientace souřadného systému kamery
    right     <4/3, 0, 0>
    look_at   <0, 0, 0>
}

background
{
    color rgb <0.5, 0.5, 0.5>            // barva pozadí celé scény
}


light_source
{
    <20, 30, -100>                       // pozice světelného zdroje
    color <1.0, 1.0, 1.0>                // barva světelného zdroje
}

#declare r1=12;                          // "poloměr" tělesa
#declare A=0.1;                          // první parametr
#declare B=0.15*clock;                   // druhý parametr je ovlivněný proměnnou "clock"

#declare RadiusVal=0.9;                  // parametry
#declare Count=720;                      // počitadlo smyčky
#declare Coils=6;                        //

#while (Count>=0)                        // programová smyčka typu "while"
    #declare Spiral=0;
    #while (Spiral<Coils)                // vložená programová smyčka
        sphere
        {
            <0,0,0>, RadiusVal           // souřadnice středu bodového prvku kostry a jeho poloměr
            texture
            {
                pigment                  // barva jednotlivých "koulí" je závislá na jejich poloze
                {                        // v ramenu spirály
                    #switch (Spiral)
                    #case (0)
                    #case (2)
                    #case (4)
                        color rgb <1.0, 0.0, 1.0 - Count/720>
                    #break
                    #else
                        color rgb <1.0, 1.0, 1.0 - Count/720>
                    #break
                    #end
                }
                finish                   // změna optických vlastností materiálu
                {
                    ambient 0.2          // ambientní složka
                    diffuse 0.6          // difúzní složka
                    phong 0.9            // míra odlesků
                    phong_size 100       // relativní velikost odlesků
                }
            }
            translate <12-Count/30*(clock)/*10*/, -18+Count/23, 0>
            rotate <0, Count, 0>
            rotate <0, Spiral*360/Coils, 0>
        }
        #declare Spiral=Spiral+1
    #end
    #declare Count=Count-1               // snížení počitadla
                                         // (simulace počítané smyčky typu "for", která v POV-Rayi neexistuje)
#end                                     // konec těla programové smyčky #while

#declare New_Sky = sky_sphere            // deklarace objektu představujícího oblohu
{
    S_Cloud2
}

sky_sphere                               // použití výše nadeklarované oblohy
{
    New_Sky
}

// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 
povray3513

Obrázek 13: Screenshot druhého demonstračního příkladu po vykreslení v POV-Rayi

9. Obsah další části seriálu

V navazující části tohoto seriálu se budeme taktéž zabývat problematikou „programování“ POV-Raye. Řekneme si, jakým způsobem lze pracovat s externími soubory, ve kterých mohou být uložena například zdrojová data vypočtená pomocí nějaké simulace či klíčové atributy použité při tvorbě animace. Textové soubory může dokonce vytvářet samotný POV-Ray, do těchto souborů lze zapsat libovolnou posloupnost řetězců, číselnou hodnotu nebo vektor (prozatím však není podporována „serializace“ složitějších objektů). Taktéž si ukážeme způsob definice maker, rekurzivního volání maker a také postup při tisku krátkých zpráv, které lze generovat v průběhu zpracování vstupních souborů s popisem vykreslované scény. Při zápisu zdrojového kódu s trojrozměrnou scénou lze využívat i některé konstanty a proměnné, které jsou interně vytvořeny samotným POV-Rayem. I popisem těchto užitečných objektů se budeme příště zabývat, jejich znalost může v mnoha případech vést ke zjednodušení a zpřehlednění zápisu scén.

povray3514

Obrázek 14: Programově vytvořené výškové pole s naznačenými normálovými vektory

Autor článku

Pavel Tišnovský vystudoval VUT FIT a v současné době pracuje ve společnosti Red Hat, kde vyvíjí nástroje pro OpenShift.io.