Myslíme v jazyku POV-Ray 2

Pavel Tišnovský 18. 11. 2008

Ve třicáté šesté části seriálu o raytraceru POV-Ray si vysvětlíme způsob tvorby „rekurzivních“ objektů a použití vestavěných funkcí při konstrukci složitějších těles. Ukážeme si také tři demonstrační příklady, ve kterých budou popisované programové konstrukce jazyka POV-Ray použity.

Obsah

1. Myslíme v jazyku POV-Ray 2
2. Základní direktivy preprocesoru
3. První demonstrační příklad – rekurzivní objekt vytvořený pomocí direktivy #include
4. Druhý demonstrační příklad – animovaná fraktální pyramida složená z metaballs
5. Zabudované konstanty
6. Zabudované proměnné
7. Matematické funkce
8. Třetí demonstrační příklad – animovaná plocha s „hřebíky“
9. Obsah další části seriálu

1. Myslíme v jazyku POV-Ray 2

V předchozí části tohoto seriálu byl ve stručnosti popsán způsob, jakým POV-Ray načítá a posléze i vykresluje trojrozměrné scény. Před vlastním vykreslením scény (renderingem) je nutné provést dvě operace – načtení scény uložené v externím textovém souboru (včetně postupného zpracování načítaných dat preprocesorem, který plní podobnou funkci jako preprocesor programovacího jazyka C a C++) a následné vytvoření interní reprezentace scény. Scéna je v operační paměti představována poměrně složitě členěnou stromovou datovou strukturou, v níž se nachází všechny uživatelem definované objekty doplněné například o automaticky vypočtená obalová tělesa a další pomocná data (statistické informace o použitých objektech POV-Ray vypisuje při ukončení své činnosti).

povray3601

Obrázek 1: Kvádry tvořící těleso tunelu jsou vytvořeny programem zpracovávaným přímo POV-Rayem, nemusela se tedy použít žádná externí modelovací aplikace.

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é (nepočítané) programové 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), jenž 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 již výše zmíněné informace o obalových tělesech. Práci preprocesoru je možné ovlivnit pomocí direktiv – v tomto ohledu se POV-Ray chová podobně jako preprocesory známé z některých běžných programovacích jazyků nebo programové utility typu awk.

povray3602

Obrázek 2: Výsledná scéna, ve které jsou použity kvádry zobrazené na prvním obrázku, na něž byl aplikován bump-mapping a nanesena procedurální textura.

2. Základní direktivy preprocesoru

Mezi základní direktivy, které rozpoznává preprocesor POV-Raye, patří především direktiva #include sloužící pro vložení obsahu textového souboru na místo, v němž se tato direktiva nachází (direktiva je ve zdrojovém textu nahrazena obsahem souboru). Dále se jedná o direktivu #declare, pomocí níž je možné vytvářet další identifikátory představující pojmenované objekty. Podobnou úlohu má i direktiva #local, ovšem s tím rozdílem, že objekty vytvořené touto direktivou mají pouze lokální platnost. Objekty definované buď s využitím direktivy #declare nebo i #local je možné zneplatnit (a popřípadě i zcela odstranit z operační paměti) pomocí direktivy #undef.

povray3603

Obrázek 3: Tato „fraktální“ pyramida byla vytvořena rekurzivním vkládáním obsahu textového souboru do sebe sama. Zde je nastavena úroveň rekurze na hodnotu 1. Viz první demonstrační příklad popsaný v navazující kapitole.

Při tvorbě složitějších objektů (v následujících kapitolách budou některé takové objekty ukázány) je možné použít i podmíněné příkazy, které lze konstruovat pomocí direktiv #if, #else, #end, #switch, #case a #break. Preprocesor dokonce umožňuje i tvorbu programových smyček, s nimiž je možné některou část kódu opakovat vícekrát na základě libovolné podmínky zapsané výrazem. Prakticky všechny běžně používané smyčky lze vytvořit z univerzální programové smyčky typu while, v POV-Rayi představovanou direktivami #while a #end. Většina direktiv zmíněných v tomto odstavci bude použita v následujících třech demonstračních příkladech.

povray3604

Obrázek 4: „Fraktální“ pyramida vytvořená taktéž s využitím prvního demonstračního příkladu při úrovni rekurze nastavené na hodnotu 2.

3. První demonstrační příklad – rekurzivní objekt vytvořený pomocí direktivy #include

V dnešním prvním demonstračním příkladu si ukážeme tvorbu fraktální pyramidy zkonstruované s využitím rekurzivního vkládání souborů do scény zpracovávané preprocesorem POV-Raye. Celý demonstrační příklad je představován dvojicí zdrojových souborů nazvaných scene1.pov a pyramid1.inc doplněných o standardní soubory colors.inc a textures.inc, které jsou dodávány spolu s POV-Rayem. První soubor scene1.pov obsahuje definice základních prvků scény, především kamery, světelného zdroje a kvádru, do nějž je pyramida umístěna. Druhý soubor pyramid1.inc, jenž je do prvního souboru vkládaný (z tohoto důvodu má příponu .inc), obsahuje pouze jedno těleso – kouli – tvořící stavební prvek pyramidy.

povray3605

Obrázek 5: Již při úrovni rekurze 3 je patrná základní konstrukce pyramidy.

Kromě tohoto tělesa je ve vkládaném souboru umístěna podmínka zapsaná pomocí direktivy #if, při jejímž splnění se změní hodnoty několika proměnných a s těmito novými parametry je soubor několikrát vložen sám do sebe direktivou #include. Každé vložení souboru znamená konstrukci další koule, tentokrát s polovičním poloměrem i odlišnými souřadnicemi jejího středu, a navíc i potenciální možnost dalšího rekurzivního vložení souboru. Čím větší je počáteční hodnota počitadla rekurze představovaného proměnnou level, tím více koulí je vytvořeno. Například při maximální úrovni rekurze 5 musí POV-Ray zpracovat celkem 9332 objektů a při úrovni o jedničku vyšší je to dokonce 55988 objektů!

povray3606

Obrázek 6: První demonstrační příklad, úroveň rekurze je nastavena na hodnotu 4.

Následuje výpis zdrojového kódu prvního demonstračního příkladu. Přesněji řečeno se jedná o soubor scene1.pov, zdrojový kód vkládaného souboru je vypsán až sedmým dalším obrázkem:

// ------------------------------------------------------------
// První demonstrační příklad
//
// Fraktální pyramida vytvořená pomocí rekurzivního vkládání
// souboru do parsované scény. Změnou hodnoty proměnné "level"
// se mění úroveň rekurze a tím i míra "fraktálnosti" pyramidy.
//
// Založeno na zdrojovém souboru, jehož autorem je:
//      Sven Hilscher * 3D-Max usergroup germany
//      email: sven@rufus.central.de
//
// rendering lze spustit příkazem:
//     povray +W800 +H600 +B100 +FN +D +Iscena1.pov +Oscena1.png
//
// (pro náhled postačí zadat povray scena1.pov)
// ------------------------------------------------------------

#version 3.0

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

// načtení všech potřebných externích souborů
#include "colors.inc"
#include "textures.inc"

// nastavení kamery (pozorovatele)
camera
{
    location <5, 17, 19>                 // pozice kamery v prostoru
    look_at  <0, 0, 0>                   // bod, na který se kamera dívá
}

// nastavení světelného zdroje
light_source
{
    <2, 20, 10>                          // pozice světelného zdroje v prostoru
    color rgb <1, 1, 1>                  // barva světla - bílá
}

// barva pozadí scény (využito, pokud je kvádr odstraněn)
background
{
    color rgb <0.4, 0.3, 0.2>
}

// kvádr, do kterého je celá scéna uzavřena
box
{
    <-20,-10,-20>,                       // kamera i světelný zdroj
    <20, 25, 25>                         // se nachází uvnitř kvádru
    texture
    {
        pigment
        {                                // šachovnicová textura
            checker
            color <0.1, 0.3, 0.4>,
            color <0.2, 0.5, 0.7>
        }
        finish
        {                                // odlesky a odrazy na povrchu
            diffuse 0.7                  // kvádru
            reflection 0.2
        }
        scale 3                          // změna měřítka textury
    }
}

// objekt představující fraktální pyramidu
union
{
    #declare radius_max = 4              // poloměr koulí na nejvyšší úrovni
    #declare level = 6//5                // zde je možné měnit členitost pyramidy

    #declare x_pos = 0                   // proměnné použité při výpočtu
    #declare y_pos = 0                   // středů koulí v pyramidě
    #declare z_pos = 0

    #include "pyramid1.inc"              // zde se zahajuje rekurze

    texture
    {
        pigment                          // pyramida má žlutý povrch
        {
            color rgb <1,1,0>
        }
        finish                           // odlesky
        {
            phong 1.0
        }
    }
}



// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 
povray3607

Obrázek 7: První demonstrační příklad, úroveň rekurze je nastavena na hodnotu 5.

Zdrojový kód vkládaného souboru, který se musí jmenovat pyramid1.inc, má následující obsah:

// ------------------------------------------------------------
// Soubor, který je rekurzivně vkládán sám do sebe, čímž se
// vytvoří fraktální objekt.
//
// Založeno na zdrojovém souboru, jehož autorem je:
//      Sven Hilscher * 3D-Max usergroup germany
//      email: sven@rufus.central.de
// ------------------------------------------------------------

// přidání koule do vytvářené pyramidy
sphere
{
    <x_pos, y_pos, z_pos>, radius_max
}

// další kód se bude zpracovávat, jen pokud nebylo dosaženo konce
// rekurzivního sestupu
#if (level > 0)
    // na nižší úrovni mají koule poloviční poloměr
    #declare level      = level - 1
    #declare radius_max = radius_max / 2

    // z+
    #declare z_pos = z_pos + radius_max * 3
    #include "pyramid1.inc"
    #declare z_pos = z_pos - radius_max * 3

    // z-
    #declare z_pos = z_pos - radius_max * 3
    #include "pyramid1.inc"
    #declare z_pos = z_pos + radius_max * 3

    // x+
    #declare x_pos = x_pos + radius_max * 3
    #include "pyramid1.inc"
    #declare x_pos = x_pos - radius_max * 3

    // x-
    #declare x_pos = x_pos - radius_max * 3
    #include "pyramid1.inc"
    #declare x_pos = x_pos + radius_max * 3

    // y+
    #declare y_pos = y_pos + radius_max * 3
    #include "pyramid1.inc"
    #declare y_pos = y_pos - radius_max * 3

    // y-
    #declare y_pos = y_pos - radius_max * 3
    #include "pyramid1.inc"
    #declare y_pos = y_pos + radius_max * 3

    // důležité - jedná se o globální proměnné, tak je nutné obnovit jejich obsah
    #declare level = level + 1
    #declare radius_max = radius_max * 2
#end



// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 
povray3608

Obrázek 8: První demonstrační příklad, úroveň rekurze je nastavena na hodnotu 6.

4. Druhý demonstrační příklad – animovaná fraktální pyramida složená z metaballs

Scénu zkonstruovanou pomocí prvního demonstračního příkladu je možné jednoduše „rozpohybovat“, a to dokonce několika různými způsoby. Vzhledem k tomu, že úroveň rekurze je představována celým číslem, při jehož zvýšení či snížení dochází ke skokové změně celé scény, nejedná se o vhodný parametr, který by bylo vhodné v animaci měnit. Zaměříme se tedy na jiný parametr, kterým jsou souřadnice jednotlivých koulí. Ty je již možné měnit plynule, například tak, že jednotlivé koule budou rotovány okolo středu souřadného systému. Aby byla celá animace zajímavější, je místo obyčejných koulí použita implicitní plocha (metaballs, blobs) s bodovými prvky kostry, přičemž barvy prvků kostry jsou odvozeny od jejich původních souřadnic vypočtených před jejich rotací.

povray3609

Obrázek 9: Druhý demonstrační příklad – začátek celé animace.

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. Všimněte si, že v průběhu animace se na okrajích fraktálního objektu v některých místech objevují a po chvíli zase mizí jednotlivé prvky kostry. Je to způsobeno tím, že hranice (threshold) nutná pro zobrazení bodu ležícího na implicitní ploše, je poměrně vysoká (0,8), takže samotný prvek kostry, jehož „síla“ je nastavena pouze na hodnotu 0,7, není vykreslen. Až při dostatečném přiblížení dvou či více prvků kostry dojde k jejich zviditelnění.

povray3610

Obrázek 10: Druhý demonstrační příklad – konec celé animace.

Následuje výpis zdrojového kódu druhého demonstračního příkladu:

// ------------------------------------------------------------
// Druhý demonstrační příklad
//
// Fraktální pyramida složená z metaballs (implicitní plochy),
// která je zkonstruovaná pomocí rekurzivního vkládání souboru
// do parsované scény. Změnou hodnoty proměnné "level" se mění
// úroveň rekurze a tím i míra "fraktálnosti" pyramidy. Celou
// scénu je možné animovat, v průběhu animace se mění polohy
// jednotlivých prvků kostry implicitní plochy.
//
// Založeno na zdrojovém souboru, jehož autorem je:
//      Sven Hilscher * 3D-Max usergroup germany
//      email: sven@rufus.central.de
//
// rendering lze spustit příkazem:
//     povray +W800 +H600 +B100 +FN +D +Iscena2.pov +Oscena2.png
//
// (pro náhled postačí zadat povray scena2.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
// ------------------------------------------------------------

#version 3.0

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

// načtení všech potřebných externích souborů
#include "colors.inc"
#include "textures.inc"

// nastavení kamery (pozorovatele)
camera
{
    location <5, 17, 19>                 // pozice kamery v prostoru
    look_at  <0, 0, 0>                   // bod, na který se kamera dívá
}

// nastavení světelného zdroje
light_source
{
    <2, 20, 10>                          // pozice světelného zdroje v prostoru
    color rgb <1, 1, 1>                  // barva světla - bílá
}

// barva pozadí scény (využito, pokud je kvádr odstraněn)
background
{
    color rgb <0.4, 0.3, 0.2>
}

// kvádr, do kterého je celá scéna uzavřena
box
{
    <-20,-10,-20>,                       // kamera i světelný zdroj
    <20, 25, 25>                         // se nachází uvnitř kvádru
    texture
    {
        pigment
        {                                // šachovnicová textura
            checker
            color <0.4, 0.3, 0.1>,
            color <0.7, 0.5, 0.2>
        }
        finish
        {                                // odlesky a odrazy na povrchu
            diffuse 0.7                  // kvádru
            reflection 0.2
        }
        scale 3                          // změna měřítka textury
    }
}

// objekt představující fraktální pyramidu
blob
{
    threshold 0.8                        // globální nastavení prahové hodnoty
    #declare radius_max = 4              // poloměr prvků kostry na nejvyšší úrovni
    #declare level = 4                   // zde je možné měnit členitost pyramidy

    #declare x_pos = 0                   // proměnné použité při výpočtu
    #declare y_pos = 0                   // středů koulí v pyramidě
    #declare z_pos = 0

    #include "pyramid2.inc"              // zde se zahajuje rekurzivní konstrukce pyramidy
}



// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 
povray3611

Obrázek 11: Druhý demonstrační příklad v první třetině animace.

Zdrojový kód souboru rekurzivně vkládaného do druhého demonstračního příkladu je v mnoha ohledech stejný, jako vkládaný soubor v demonstračním příkladu prvním. Liší se však jeho úvodní část, ve které jsou vypočteny parametry animace, tj. natočení jednotlivých prvků kostry okolo počátku i barva prvků kostry implicitní plochy, jež je určena na základě jejich původní polohy před natočením. Tento soubor musí nést název pyramid2.inc, protože právě pod tímto názvem se na něj ve zdrojovém kódu (vypsaném výše) odkazujeme:

// ------------------------------------------------------------
// Soubor, který je rekurzivně vkládán sám do sebe, čímž se
// vytvoří fraktální objekt.
//
// Založeno na zdrojovém souboru, jehož autorem je:
//      Sven Hilscher * 3D-Max usergroup germany
//      email: sven@rufus.central.de
// ------------------------------------------------------------

// přidání koule do vytvářené pyramidy
sphere
{
    <x_pos, y_pos, z_pos>, 2.2*radius_max, 0.7
    // výpočet koeficientů rotace
    #declare rotate_coefficient = 20.0*(1.0-clock)
    // vlastní rotace každého prvku kostry
    rotate <x_pos*rotate_coefficient, y_pos*rotate_coefficient, z_pos*rotate_coefficient>
    texture
    {
        pigment                          // každá součást metaballs má jinou barvu
        {
            color rgb <x_pos,y_pos,z_pos>// v závislosti na její poloze v prostoru
        }
        finish                           // odlesky
        {
            phong 1.0
        }
    }
}

// další kód se bude zpracovávat, jen pokud nebylo dosaženo konce
// rekurzivního sestupu
#if (level > 0)
    // na nižší úrovni mají koule poloviční poloměr
    #declare level      = level - 1
    #declare radius_max = radius_max / 2

    // z+
    #declare z_pos = z_pos + radius_max * 3
    #include "pyramid2.inc"
    #declare z_pos = z_pos - radius_max * 3

    // z-
    #declare z_pos = z_pos - radius_max * 3
    #include "pyramid2.inc"
    #declare z_pos = z_pos + radius_max * 3

    // x+
    #declare x_pos = x_pos + radius_max * 3
    #include "pyramid2.inc"
    #declare x_pos = x_pos - radius_max * 3

    // x-
    #declare x_pos = x_pos - radius_max * 3
    #include "pyramid2.inc"
    #declare x_pos = x_pos + radius_max * 3

    // y+
    #declare y_pos = y_pos + radius_max * 3
    #include "pyramid2.inc"
    #declare y_pos = y_pos - radius_max * 3

    // y-
    #declare y_pos = y_pos - radius_max * 3
    #include "pyramid2.inc"
    #declare y_pos = y_pos + radius_max * 3

    // důležité - jedná se o globální proměnné, je nutné obnovit jejich obsah
    #declare level = level + 1
    #declare radius_max = radius_max * 2
#end



// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 
povray3612

Obrázek 12: Druhý demonstrační příklad přesně v polovině animace.

5. Zabudované konstanty

Při ručním vytváření trojrozměrných scén, tj. zdrojových souborů připravovaných bez asistence externího modelovacího programu, si můžeme práci ulehčit použitím konstant a proměnných, které jsou zabudované přímo do jazyka POV-Raye. Zabudované konstanty není možné změnit, což je důležité, protože máme jistotu, že i při vkládání souborů vytvořených jinými autory je možné se vždy spolehnout na to, že zabudované konstanty zůstanou nemodifikovány. Mezi zabudované konstanty patří především vektory, které se velmi často používají při deklaraci lineárních transformací, souřadnicích v textuře, někdy i specifikaci barev apod. Například místo zápisu translate <5,0,0> lze použít zápis translate 5*x, který je kratší a současně i čitelnější. Mezi konstantní vektory (použitelné ve všech zdrojových kódech) patří:

#declare x = <1, 0, 0>;
#declare y = <0, 1, 0>;
#declare z = <0, 0, 1>;
#declare t = <0, 0, 0, 1>;
#declare u = <1, 0>;
#declare v = <0, 1>; 
povray3613

Obrázek 13: Druhý demonstrační příklad ve druhé třetině animace.

6. Zabudované proměnné

Zabudované proměnné jsou vytvořeny a inicializovány samotným POV-Rayem ještě před začátkem preprocesingu zdrojového kódu s uloženou scénou. To mj. znamená, že tyto proměnné je možné použít při konstrukci větvení (viz podmíněné příkazy i doposud nepopsaný podmíněný výraz), tvorbě maker, uživatelských proměnných i programových smyček. Ve vytvářených scénách je možné využít především tyto zabudované proměnné:

Jméno proměnné Význam
clock aktuální hodnota řídicí animaci, která běžně nabývá hodnot v rozsahu 0..1
clock_delta rozdíl hodnoty proměnné clock mezi dvěma po sobě jdoucími snímky
clock_on pravdivostní hodnota (0 nebo 1) nastavená podle toho, zda je povolena animace
initial_clock počáteční hodnota proměnné clock, tato proměnná je většinou nastavena na 0,0
final_clock koncová hodnota proměnné clock, tato proměnná je většinou nastavena na 1,0
frame_number číslo právě vykreslovaného snímku
initial_frame číslo prvního snímku v animaci
final_frame číslo posledního snímku v animaci
image_width šířka obrázku v pixelech, většinou použito při nastavení kamery
image_height výška obrázku v pixelech
version verze raytraceru, například 3.1 (jedná se tedy o reálné číslo)
povray3614

Obrázek 14: Třetí demonstrační příklad – „hřebíky“ na vlnící se ploše.

7. Matematické funkce

V některých scénách, například ve všech dnešních demonstračních příkladech, je nutné zapsat složitější matematické výrazy, pomocí nichž se vypočtou rozměry a pozice objektů ve scéně, jejich barva, parametry textury atd. Jazyk POV-Raye nám nabízí poměrně velké množství matematických funkcí, které je možné při výpočtech využít. Jedná se především o funkce s reálnou nezávislou proměnnou – sin, cos, atan, sqrt či log, ale i funkce složitější, například sum. Zvláštní kapitolou jsou funkce vektorové, jejichž parametrem je vektor, nebo které vektor naopak vrací jako svůj výsledek. Tyto funkce jsou v některých případech velmi jednoduché (skalární a vektorový součin – vdot a vcross, normalizace vektoru – vnormalize, výpočet délky vektoru – vlength), v případech dalších jsou naopak poměrně složité a do značné míry využívají analytické i numerické postupy používané samotným POV-Rayem. Jedna ze složitějších funkcí je použita ve třetím demonstračním příkladu.

povray3615

Obrázek 15: Snímek z animace vlnící se plochy vytvořené pomocí třetího demonstračního příkladu

8. Třetí demonstrační příklad – animovaná plocha s „hřebíky“

V dnešním třetím a současně i posledním demonstračním příkladu je ukázáno, jakým způsobem je možné využít některé funkce, které má POV-Ray ve svém repertoáru. Nejprve je vytvořena izoplocha, která se „vlní“ v závislosti na aktuální hodnotě interní proměnné clock. Na této ploše se nachází pravidelně rozmístěné „hřebíky“ představované pro jednoduchost úzkými zelenými válci. Tyto hřebíky mají jednu zajímavou vlastnost – jsou vždy kolmé na plochu. Jak je však možné zajistit, aby byl každý hřebík/válec vždy kolmý na izoplochu, která má v každém snímku animace odlišný tvar? Teoreticky je nutné vypočítat tečné vektory v místě dotyku válce a izoplochy a z těchto tečných vektorů pomocí vektorového součinu získat normálu k povrchu.

Snadnější je však v tomto případě použití funkce trace, která pro zadaný bod a směrový vektor zjistí, zda takto definovaný paprsek protíná zvolený objekt. V případě nalezení průsečíku paprsku s objektem se vrátí souřadnice průsečíku (ta nás nezajímá) a také normálový vektor, který již můžeme využít (evidentně se jedná o funkci, kterou využívá samotný raytracer při zjišťování průsečíků primárních i sekundárních paprsků s tělesy). V demonstračním příkladu se nad izoplochou vytvořila mřížka, ze které se vrhají paprsky ve směru osy y v místě průsečíku paprsků s izoplochou funkce trace vrátí normálový vektor, který se jen „prodlouží“ na požadovanou délku hřebíku. Animaci vytvořenou pomocí třetího demonstračního příkladu můžete získat zde.

povray3616

Obrázek 16: Další snímek z animace vlnící se plochy vytvořené pomocí třetího demonstračního příkladu

Zdrojový kód třetího demonstračního příkladu má tvar:

widgety

// ------------------------------------------------------------
// Třetí demonstrační příklad: animovaná vlnící se plocha, na
// jejímž povrchu jsou hřebíky (každý hřebík je k ploše vždy
// kolmý).
//
// Založeno na zdrojovém souboru, jehož autorem je:
//     Chris Huff
//
// rendering lze spustit příkazem:
//     povray +W800 +H600 +B100 +FN +D +Iscena3.pov +Oscena3.png
//
// (pro náhled postačí zadat povray scena3.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
// ------------------------------------------------------------

#declare GridXRes = 16;                  // rozlišení mřížky
#declare GridZRes = 16;
#declare PinHeight = 0.25;               // výška hřebíků

#version 3.5;

#include "functions.inc"
#include "math.inc"
#include "consts.inc"
#include "colors.inc"

global_settings
{
    assumed_gamma 1
}

#default                                 // implicitní hodnoty, které
{                                        // se použijí pro ty objekty,
    finish                               // u nichž není žádná jiná
    {                                    // specifikace optických
        ambient 0                        // vlastností materiálu
        diffuse 1
    }
}

#declare CamLoc = < 3, 4,-5>;            // pozice kamery v prostoru

// kamera
camera
{
    location CamLoc                      // umístění kamery v prostoru
    look_at < 0, 0, 0>                   // bod, na který se kamera dívá
    angle 24                             // zorný úhel
}

// první světelný zdroj
light_source
{
    CamLoc                               // pozice světelného zdroje
    color White*0.35                     // barva světelného zdroje
}

// druhý světelný zdroj
light_source
{
    <-50, 150,-75>                       // pozice světelného zdroje
    color White                          // barva světelného zdroje
}

// vlnící se izoplocha
#declare Land =
isosurface
{
    function                             // funkce použitá při výpočtu
    {                                    // "výšek"
        y + f_noise3d(x, y+clock*2, z)   // animace: mění se hodnota clock
    }
    threshold 0
    max_gradient 1.75
    contained_by                         // ořezové těleso, ve kterém
    {                                    // se izoplocha nachází
        box
        {
            <-1.1,-1,-1.1>, < 1.1, 1, 1.1>
        }
    }
    translate y*0.75
}

// objekt složený z většího množství "hřebíků"
union
{
    #declare J = 0;                      // počitadlo vnější smyčky
    #while (J < GridXRes)
        #declare K = 0;                  // počitadlo vnitřní smyčky
        #while (K < GridZRes)
            // výpočet souřadnice jednoho konce hřebíku
            #declare stPt = <2*J/(GridXRes-1) - 1, 10, 2*K/(GridZRes-1) - 1>;
            #declare iNorm = y;
            // nalezení průsečíku s izoplochou
            #declare iPt = trace(Land, stPt, -y, iNorm);
            // pokud není normálový vektor nulový, vykreslí se hřebík
            #if (!VZero(iNorm))
                cylinder
                {
                    iPt, iPt + iNorm*PinHeight, 0.01
                }
            #end
            #declare K = K + 1;          // příprava na další krok
        #end                             // vnitřní smyčky
        #declare J = J + 1;              // příprava na další krok
    #end                                 // vnější smyčky
    texture
    {
        pigment
        {
            color Green                  // barva "hřebíků"
        }
        finish
        {
            specular 1                   // odlesky na povrchu
        }
    }
}

// vložení izoplochy do vykreslované scény
object
{
    Land
    texture
    {
        pigment
        {                                // šachovnicová textura
            checker
            color <0.4, 0.3, 0.1>,
            color <0.7, 0.5, 0.2>
        }
        finish
        {
            specular 1                   // odlesky na povrchu
        }
        scale 0.1
    }
}



// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 

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

V následující části seriálu o raytraceru POV-Ray bude popsán způsob deklarace uživatelských funkcí, vytváření nových maker, práce s vektory a poli i další možnosti programovacího jazyka, který je možné v tomto raytraceru použít.

povray3617
Našli jste v článku chybu?
Lupa.cz: Jak se prodává firma za miliardu?

Jak se prodává firma za miliardu?

Podnikatel.cz: Poslanci chtějí sebrat majetek Bakalovi

Poslanci chtějí sebrat majetek Bakalovi

DigiZone.cz: Sony MP-CL1A: miniaturní projektor

Sony MP-CL1A: miniaturní projektor

Lupa.cz: Patička e-mailu závazná jako vlastnoruční podpis?

Patička e-mailu závazná jako vlastnoruční podpis?

Podnikatel.cz: Udělali jsme velkou chybu, napsal Čupr

Udělali jsme velkou chybu, napsal Čupr

Lupa.cz: Jak levné procesory změnily svět?

Jak levné procesory změnily svět?

Lupa.cz: Aukro.cz mění majitele. Vrací se do českých rukou

Aukro.cz mění majitele. Vrací se do českých rukou

DigiZone.cz: DVB-T2 ověřeno: seznam TV zveřejněn

DVB-T2 ověřeno: seznam TV zveřejněn

Lupa.cz: Blíží se konec Wi-Fi sítí bez hesla?

Blíží se konec Wi-Fi sítí bez hesla?

Vitalia.cz: Jak Ondra o astma přišel

Jak Ondra o astma přišel

Podnikatel.cz: Takhle se prodávají mražené potraviny

Takhle se prodávají mražené potraviny

DigiZone.cz: Rapl: seriál, který vás smíří s ČT

Rapl: seriál, který vás smíří s ČT

Lupa.cz: Hackeři mají data z půlmiliardy účtů Yahoo

Hackeři mají data z půlmiliardy účtů Yahoo

Vitalia.cz: 5 chyb, které děláme při skladování potravin

5 chyb, které děláme při skladování potravin

Vitalia.cz: Muž, který miluje příliš. Ženám neimponuje

Muž, který miluje příliš. Ženám neimponuje

Vitalia.cz: Voda z Vltavy před a po úpravě na pitnou

Voda z Vltavy před a po úpravě na pitnou

Měšec.cz: TEST: Vyzkoušeli jsme pražské taxikáře

TEST: Vyzkoušeli jsme pražské taxikáře

Lupa.cz: Další Češi si nechali vložit do těla čip

Další Češi si nechali vložit do těla čip

Vitalia.cz: Fyzioterapeutka: Chůze naboso? Rozhodně ano!

Fyzioterapeutka: Chůze naboso? Rozhodně ano!

DigiZone.cz: Ginx TV: pořad o počítačových hráčích

Ginx TV: pořad o počítačových hráčích