Hlavní navigace

Zobrazení objemových dat v POV-Rayi 2

21. 10. 2008
Doba čtení: 15 minut

Sdílet

V dnešní části seriálu o raytraceru POV-Ray si na praktických příkladech ukážeme, jakým způsobem lze zpracovat objemová data a zařadit je do vykreslované scény. Také si popíšeme formát souboru používaný pro uchování objemových dat i to, jak lze tyto soubory jednoduše programově vytvářet.

Obsah

1. Zobrazení objemových dat v POV-Rayi
2. Datový formát DF3 určený pro uložení objemových dat
3. První demonstrační příklad – vytvoření souboru typu DF3 pomocí céčkové utility
4. Použití objemových dat uložených v souborech typu DF3
5. Druhý demonstrační příklad – kvádr vyplněný voxely
6. Třetí demonstrační příklad – zvýraznění vybraných hodnot v prostorových datech
7. Odkazy na Internetu
8. Obsah další části seriálu

1. Zobrazení objemových dat v POV-Rayi

V předchozí části tohoto seriálu jsme si uvedli základní informace o problematice reprezentace a vykreslení objemových dat uložených ve formě pravidelné prostorové mřížky, která dělí prostor na objemové elementy – voxely. Objemová data je možné vykreslovat mnoha různými způsoby, přičemž nejzákladnější dělení je na algoritmy zobrazující povrchy a přímé objemové algoritmy. V POV-Rayi je podporováno přímé vykreslení objemových dat (Direct volume rendering algorithms) bez nutnosti vytváření pomocných povrchů. Jak si však ukážeme v další části seriálu, je možné – i když v omezené míře a většinou s velkými vizuálními chybami – přímo v POV-Rayi v objemových datech nalézt povrch a ten následně zobrazit jako izoplochu. Nejedná se sice o typickou oblast použití (podle mě je výhodnější použít předzpracování například algoritmem Marching Cubes či Marching Tetrahedra s vyhlazením výsledné trojúhelníkové sítě), ale jedná se o zajímavou a přitom poměrně neznámou vlastnost POV-Raye, takže by bylo škoda ji zde nezveřejnit.

povray3301

Obrázek 1: Mraky v této scéně byly vykresleny na základě objemových dat, nejedná se tedy o 2D textury.

2. Datový formát DF3 určený pro uložení objemových dat

Objemová data reprezentovaná pravidelnou prostorovou mřížkou voxelů, je možné uchovávat a přenášet v souborech různých formátů. V praxi se poměrně často používají formáty určené především pro medicínské aplikace, ve kterých je mj. podporována komprimace prostorové mřížky, uložení voxelů v různých bitových hloubkách (často 12 bitů na voxel) a přidání metadat (například údajích o pacientech, nastavení CT či MR zařízení atd.). Autoři raytraceru POV-Ray namísto adaptace některého z těchto formátů (což by s sebou mohlo nést například pro volně šířený program neakceptovatelné licenční podmínky atd.) navrhli formát vlastní, který se vyznačuje především značnou jednoduchostí. Tento formát, jenž je nazýván podle koncovky souborů DF3, je podporován i několika dalšími utilitami a konverzními programy. Jak si ukážeme v další kapitole, je práce s tímto formátem přímočará a soubory typu DF3 je možné generovat pomocí prakticky jakéhokoli programovacího jazyka, který dokáže korektně pracovat s binárními soubory.

povray3302

Obrázek 2: Další scéna obsahující skutečné „objemové“ mraky.

Formát DF3 se skládá ze dvou částí – hlavičky a vlastních objemových dat. Hlavička má vždy délku 6 byte a je v ní uloženo rozlišení prostorové mřížky. Jedná se o trojici šestnáctibitových hodnot, první hodnota udává rozlišení v x-ové ose, druhá hodnota rozlišení v ose y-ové a třetí hodnota v ose z-ové. Při práci se soubory typu DF3 na počítačích s architekturou x86 je nutné dát pozor na to, že dvojice bytů představujících šestnáctibitovou hodnotu je uložena v pořadí vyšší byte–nižší byte (rozdíl little endian vs big endian). Ihned za touto jednoduchou hlavičkou následují objemová data, která se skládají z jednotlivých voxelů. Počet bitů na jeden voxel může být 8 (256 různých hodnot), 16 (65536 hodnot) či 32 (4294967296 h­odnot). Vzhledem k tomu, že počet bitů na voxel není uložen v hlavičce, musí POV-Ray správnou hodnotu zjistit sám. Udělá to velmi jednoduše – od celkové velikosti souboru odečte šest bytů hlavičky a takto zjištěnou hodnotu podělí celkovým počtem voxelů (ten získá vynásobením rozlišení mřížky). Výsledkem je hodnota 1, 2 nebo 4 odpovídající počtu bytů na jeden voxel. V případě, že má soubor odlišnou délku, tj. vydělením vznikne jiná hodnota než celé číslo 1, 2 či 4, je při zpracování scény nahlášena chyba.

povray3303

Obrázek 3: Prostorová data představující výsledek počítačové simulace kosmologických je­vů.

Pro představu s jakou mírou roste velikost souborů typu DF3, spolu s rostoucím rozlišením mřížky a počtem bytů, kterými je vyjádřena hustota voxelů, jsem vypracoval tabulku zobrazenou pod tímto odstavcem. Rozlišení prostorové mřížky, ve které jsou voxely uloženy, roste mezi jednotlivými řádky tabulky s mocninou dvou, pro jeden voxel může být (alespoň v současné verzi POV-Raye) alokován jeden byte, dva byty či čtyři byty a délka hlavičky je, jak jsme se již dozvěděli, vždy rovna šesti bytům. Při pohledu na tabulku je patrné, že celková velikost souboru je i pro relativně malé rozlišení mřížky (2563 voxelů) poměrně velká – v současnosti se například pomocí CT vytváří mřížky o rozlišení až 512×512×200 voxelů s bitovou hloubkou typicky 12 bitů (1,5 bytu) na voxel. V POV-Rayi je v mnoha případech (pokud se tedy nezobrazují data získaná z CT či MR) vhodnější pracovat spíše s menšími mřížkami; například pro vytváření modelů mraků či ohně většinou postačuje rozlišení 1283 voxelů s bitovou hloubkou jeden byte na voxel.

Rozlišení mřížky Počet bytů na jeden voxel Počet bytů v hlavičce Celková velikost souboru
32× 32× 32 1 6 32774
32× 32× 32 2 6 65542
32× 32× 32 4 6 131078
64× 64× 64 1 6 262150
64× 64× 64 2 6 524294
64× 64× 64 4 6 1048582
128×128×128 1 6 2097158
128×128×128 2 6 4194310
128×128×128 4 6 8388614
256×256×256 1 6 16777222
256×256×256 2 6 33554438
256×256×256 4 6 67108870
povray3304

Obrázek 4: Druhý demonstrační příklad, ve kterém je použita prostorová mřížka o velmi malém rozlišení 32×32×32 voxelů. Při vykreslování objemových dat nebyla použita interpolace (po zvětšení jsou jednotlivé voxely jasně viditelné).

3. První demonstrační příklad – vytvoření souboru typu DF3 pomocí céčkové utility

Před vysvětlením použití prostorových dat ve scénách vykreslovaných POV-Rayem si ukážeme, jakým způsobem je možné taková data vytvořit. Demonstrační program, jehož okomentovaný výpis můžete vidět níže, je naprogramován v céčku a slouží pro vytvoření prostorové mřížky o rozlišení 32×32×32 voxelů až 256×256×256 voxelů s následným uložením této mřížky do externího souboru. V programu se pracuje se strukturou t_voxels, která reprezentuje prostorovou mřížku, tj. její rozlišení i hodnoty jednotlivých voxelů, které jsou uloženy v trojrozměrném dynamickém poli. Paměť se pro mřížku alokuje pomocí funkce voxels_alloca­te(), maže (nuluje) funkcí voxels_erase() a ukládá do externího souboru ve funkci voxels_save(). Vzhledem k tomu, že hodnoty voxelů jsou uloženy ve formátu pohyblivé řádové čárky, je před uložením zapotřebí všechny voxely znormalizovat tak, aby jejich hodnoty ležely v rozsahu 0,0 až 1,0, což zajišťuje funkce voxels_normali­ze(). Poslední funkcí, která s prostorovou mřížkou pracuje, je funkce voxels_fill(), ve které se hodnoty voxelů naplňují na základě jednoduché prostorové funkce, kterou lze snadno změnit a dosáhnout tak zcela jiného obrázku po vykreslení voxelů POV-Rayem.

povray3305

Obrázek 5: Druhý demonstrační příklad, ve kterém je použita prostorová mřížka o velmi malém rozlišení 32×32×32 voxelů. Při vykreslování objemových dat však byla použita trilineární interpolace, která i při takto malém rozlišení mřížky efektivně jednotlivé voxely „rozmaže“.

Následuje výpis zdrojového kódu výše popsané utility:

//-----------------------------------------------------------------------------
// Ukázkový příklad napsaný v céčku, který slouží pro vytvoření souboru ve
// formátu DF3. Překlad lze provést například takto:
// gcc -O3 -Wall make_df3.c
//-----------------------------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define MAX(x, y) ((x)>(y) ? (x) : (y))
#define MIN(x, y) ((x)<(y) ? (x) : (y))

#define HIBYTE(val) ((val) >> 8)
#define LOBYTE(val) ((val) & 0xff)



//-----------------------------------------------------------------------------
// Struktura nesoucí základní informace o prostorové mřížce a ukazatel na tuto
// strukturu (ten je použitý pro zjednodušení volání funkcí)
//-----------------------------------------------------------------------------
typedef struct
{
    float *** volume;                    // prostorová mřížka - pole voxelů
    int x_res;                           // rozlišení prostorové mřížky
    int y_res;
    int z_res;
} t_voxels, *p_voxels;



//-----------------------------------------------------------------------------
// Alokace paměti pro prostorovou mřížku
//-----------------------------------------------------------------------------
p_voxels voxels_allocate(const int x_res, const int y_res, const int z_res)
{
    int i, j;

    p_voxels voxels = malloc(sizeof(t_voxels));

    // nastavení rozlišení prostorové mřížky
    voxels->x_res = x_res;
    voxels->y_res = y_res;
    voxels->z_res = z_res;

    // alokace paměti pro nejvyšší dimenzi
    voxels->volume = malloc(x_res*sizeof(float **));

    // alokace paměti pro druhou dimenzi
    for (i=0; i<x_res; i++)
    {
        voxels->volume[i] = malloc(y_res*sizeof(float *));
    }

    // alokace paměti pro třetí dimenzi
    for (i=0; i<x_res; i++)
    {
        for (j=0; j<y_res; j++)
        {
            voxels->volume[i][j] = malloc(z_res*sizeof(float));
        }
    }

    return voxels;
}



//-----------------------------------------------------------------------------
// Vymazání prostorové mřížky - všechny voxely se nastaví na nulovou hodnotu
//-----------------------------------------------------------------------------
void voxels_erase(p_voxels voxels)
{
    int i, j, k;
    for (i=0; i<voxels->x_res; i++)
    {
        for (j=0; j<voxels->y_res; j++)
        {
            for (k=0; k<voxels->z_res; k++)  // v případě IEEE formatu float
            {                                // lze nahradit voláním memset()
                voxels->volume[i][j][k] = 0;
            }
        }
    }
}



//-----------------------------------------------------------------------------
// Normalizace dat tak, aby padly do rozsahu 0-1
//-----------------------------------------------------------------------------
void voxels_normalize(p_voxels voxels)
{
    float min=1e20, max=-1e20;
    float delta;
    int i, j, k;

    // najdeme minimální a maximální hodnotu
    for (i=0; i<voxels->x_res; i++)
    {
        for (j=0; j<voxels->y_res; j++)
        {
            for (k=0; k<voxels->z_res; k++)
            {
                min = MIN(min, voxels->volume[i][j][k]);
                max = MAX(max, voxels->volume[i][j][k]);
            }
        }
    }
    // pokud jsou všechny hodnoty shodné, úprava minim a maxim
    if (min >= max)
    {
        max=min+1;
        min-=1;
    }
    printf("min=%6.3f  max=%6.3f\n", min, max);

    // druhy průchod mřížkou = vlastní normalizace
    delta=max-min;
    for (i=0; i<voxels->x_res; i++)
    {
        for (j=0; j<voxels->y_res; j++)
        {
            for (k=0; k<voxels->z_res; k++)
            {
                voxels->volume[i][j][k] = (voxels->volume[i][j][k]-min)/delta;
            }
        }
    }
}



//-----------------------------------------------------------------------------
// Uložení mřížky do externího souboru
//-----------------------------------------------------------------------------
void voxels_save(p_voxels voxels, const char *filename)
{
    int i, j, k;
    FILE *fout=fopen(filename, "wb");

    if (fout!=NULL)
    {
        // zápis hlavičky - nezapomenout na pořadí vyšší byte - nižší byte
        fputc(HIBYTE(voxels->x_res), fout);
        fputc(LOBYTE(voxels->x_res), fout);
        fputc(HIBYTE(voxels->y_res), fout);
        fputc(LOBYTE(voxels->y_res), fout);
        fputc(HIBYTE(voxels->z_res), fout);
        fputc(LOBYTE(voxels->z_res), fout);

        // zápis vlastních dat uložených v prostorové mřížce
        for (i=0; i<voxels->x_res; i++)
        {
            for (j=0; j<voxels->y_res; j++)
            {
                for (k=0; k<voxels->z_res; k++)
                {
                    fputc(255.0*voxels->volume[i][j][k], fout);
                }
            }
        }
        printf("do souboru %s bylo zapsano %ld bytu\n", filename, ftell(fout));
        fclose(fout);
    }
}



//-----------------------------------------------------------------------------
// Vyplnění mřížky jednoduchým obrazcem
//-----------------------------------------------------------------------------
void voxels_fill(p_voxels voxels)
{
    int i, j, k;
    for (i=0; i<voxels->x_res; i++)
    {
        for (j=0; j<voxels->y_res; j++)
        {
            for (k=0; k<voxels->z_res; k++)
            {
                // normalizované souřadnice v prostorové mřížce
                float x = (float)i/voxels->x_res;
                float y = (float)j/voxels->y_res;
                float z = (float)k/voxels->z_res;
                // zde je možné si libovolně vyhrát
                voxels->volume[i][j][k] = sin(x*2.0*M_PI)+sin(y*2.0*M_PI)+sin(z*2.0*M_PI);
            }
        }
    }
}



//-----------------------------------------------------------------------------
// Hlavni funkce konzolové aplikace
//-----------------------------------------------------------------------------
int main(void)
{
    int resolution;
    // vytvoříme volumetrická data o různém rozlišení
    for (resolution = 32; resolution<=256; resolution*=2)
    {
        char filename[20];
        p_voxels voxels = voxels_allocate(resolution, resolution, resolution);

        voxels_erase(voxels); // není v tomto případě zapotřebí
        voxels_fill(voxels);  // vlastní naplnění voxelů vypočtenými daty

        voxels_normalize(voxels); // normalizace je nutná, předchozí funkce ji nemusela provést
        sprintf(filename, "pokus%03d.df3", resolution);
        voxels_save(voxels, filename);
    }

   return 0;
}



//-----------------------------------------------------------------------------
// finito
//----------------------------------------------------------------------------- 
povray3306

Obrázek 6: Vhodnou volbou funkce voxels_fill lze vytvořit i jednoduchý model kouře; zde je zobrazen v nepravých barvách.

4. Použití objemových dat uložených v souborech typu DF3

V případě, že již máme vytvořeny validní soubory typu DF3, které obsahují vypočtená či jiným způsobem zjištěná objemová data, lze přistoupit k jejich vykreslení pomocí POV-Raye. K tomuto účelu se nejčastěji používá nám již známý uzel media, kterým je možné specifikovat vlastnosti částic, jimiž je vyplněn vnitřek libovolného uzavřeného tělesa. V tomto uzlu se kromě několika důležitých parametrů určených pro algoritmus vykreslování specifikuje také funkce použitá pro výpočet hustoty částic v daném místě prostoru. Ovšem – a to je v našem případě důležité – místo nějaké matematické funkce či procedury (typu agate či bozo) lze specifikovat i externí soubor typu DF3, ve kterém jsou hustoty uloženy.

V tomto případě se předpokládá, že jsou v externím souboru uloženy informace o hustotách částic, které se nachází v prostoru omezeném jednotkovou krychlí, jejíž tělesová úhlopříčka končí v bodech [0,0,0] a [1,1,1] – to mj. znamená, že pokud se má objemovými daty vyplnit větší těleso či těleso, které se nachází na jiném místě prostoru, je nutné použít některou z lineárních transformací typu translate, rotate či scale. Pokud má objemová mřížka uložená v externím souboru malé rozlišení, je zapotřebí také nastavit správnou metodu interpolace objemových dat při jejich vykreslování. Pomocí atributu interpolate lze interpolaci buď zakázat (hodnota 0, nejrychlejší metoda), zvolit trilineární interpolaci (hodnota 1, většinou dává vyhovující výsledky) či interpolaci trikubickou (hodnota 2, v každém směru se hodnoty prokládají kubickou křivkou).

5. Druhý demonstrační příklad – kvádr vyplněný voxely

V dnešním druhém demonstračním příkladu je ukázán způsob vykreslení objemových dat pomocí uzlu media. Ve scéně se nachází jediné těleso – krychle s neviditelnými stěnami – která je vyplněna částicemi emitujícími a rozptylujícími světlo. Hustota částic a současně i barva emitovaného světla je odvozena z obsahu souboru typu DF3, který byl vytvořen pomocí prvního demonstračního příkladu (je možné použít kterýkoli vygenerovaný soubor, vizuální kvalita však bude závislá na rozlišení objemové mřížky, tj. celkovém počtu voxelů, kterými paprsek prochází). Při vykreslování objemové mřížky jsou hodnoty hustoty interpolovány pomocí lineární interpolace. Zvýšením hodnoty atributu intervals je možné docílit přesnějšího výpočtu, ovšem na úkor rychlosti vykreslování. Zdrojový kód druhého demonstračního příkladu má tvar:

// ------------------------------------------------------------
// Druhý demonstrační příklad na použití objemových dat
// v prostorových scénách vykreslovaných POV-Rayem.
//
// V této scéně je použitý jeden bodový zdroj světla, vnitřek
// kvádru je vyplněn částicemi emitujícími a rozptylujícími
// světlo, jejichž hustota (a přeneseně i barva) je načtena
// z externího souboru.
//
// rendering lze spustit příkazem:
//     povray +W800 +H600 +B100 +FN +D +Iscena1.pov +Oscena1.png
// (pro náhled postačí zadat povray scena1.pov)
// ------------------------------------------------------------

#include "colors.inc"

// nastavení kamery
camera
{
    location  <0, 0, -10>                // pozice kamery
    look_at   <0, 0, 0>                  // bod, na který se kamera dívá
    angle 48                             // zorný úhel
}

// zdroj světla
light_source
{
    <500, 500, -500>                     // pozice zdroje světla
    color White                          // barva světla
}

box                                      // objemová data jsou představována kvádrem
{
    <0,0,0>, <1,1,1>
    texture
    {
        pigment
        {
            rgbt 1                       // zcela průhledné stěny kvádru - zajímá nás pouze jeho vnitřek
        }
    }
    interior
    {
        media
        {
            emission 0.5                 // částice emitující světlo
            scattering {1, 0.1}          // částice rozptylující světlo
            intervals 1                  // vyšší hodnota - větší přesnost výpočtu, ovšem také delší čas
            samples 5
            method 3
            density                      // definice hustoty částic na základě souboru s volumetrickými daty
            {
                density_file df3 "pokus032.df3" interpolate 1
                color_map                // mapování hustoty na barvu
                {
                    [0    rgb 0]
                    [0.4  Blue]
                    [0.7  Yellow]
                    [1    Red]
                }
            }
        }
    }
    hollow                               // aby výpočet rozptylu probíhal korektně, je důležité
                                         // používat prázdná uzavřená tělesa
    translate -0.5
    scale 4
    rotate <60,30,0>
}



// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 
povray3307

Obrázek 7: Druhý demonstrační příklad, ve kterém je použita prostorová mřížka o rozlišení 256×256×256 voxelů. Je použita alternativní barvová mapa.

6. Třetí demonstrační příklad – zvýraznění vybraných hodnot v prostorových da­tech

Jednoduchou úpravou barvové mapy, pomocí níž se jednotlivým voxelům přiřazuje na základě jejich hustoty barva, lze docílit toho, že se v prostorových datech zvýrazní vybrané hodnoty, které většinou tvoří izoplochy, tj. souvislou plochu voxelů se stejnou či velmi podobnou hustotou. Vše probíhá následujícím způsobem: každému voxelu je při výpočtu barvy každého paprsku procházejícího scénou přiřazena hustota ležící v intervalu 0,0 až 1,0 na základě hodnoty přečtené z externího souboru typu DF3. Přitom nezáleží na tom, kolik bytů bylo pro jeden voxel alokováno. Jinými slovy je v případě uložení 1 byte na voxel hustota vypočtena vzorcem přečtený_byte/(28), v případě 2 bytů na voxel je použit vzorec přečtený_byte/(216) atd. Výsledkem je vždy hodnota ležící v již zmíněném intervalu 0,0 až 1,0, která je použita při čtení hodnoty barvy z barvové mapy. Důležité je, že tento výpočet je prováděn až v průběhu vykreslování, nikoli v přípravné fázi – to znamená, že se i prostorové mřížky s velkým rozlišením alokuje v operační paměti pouze tolik prostoru, jaká je velikost souboru typu DF3 na disku, i když samotné výpočty probíhají s hodnotami typu double (8 bytů).

povray3308

Obrázek 8: Izoplocha spojující voxely s hustotou 0,50.

V případě, že je barvová mapa upravena tím způsobem, že obsahuje pouze několik „pruhů“ barev oddělených od sebe větším intervalem černé barvy, jsou po vykreslení objemových dat viditelné plochy právě v těch místech, které odpovídají barevnému pruhu. Při tomto způsobu vizualizace je většinou nutné zvolit vyšší hodnotu atributu intervals a samples, aby se zamezilo vzniku nežádoucích vizuálních artefaktů, které jsou způsobeny „kostkovitostí“ rastrové mřížky. Upravený zdrojový kód, ve kterém je pro objemová data vytvořena barvová mapa se třemi různými pruhy, má následující tvar:

// ------------------------------------------------------------
// Třetí demonstrační příklad na použití objemových dat
// v prostorových scénách vykreslovaných POV-Rayem.
//
// V této scéně je použitý jeden bodový zdroj světla, vnitřek
// kvádru je vyplněn částicemi emitujícími a rozptylujícími
// světlo, jejichž hustota (a přeneseně i barva) je načtena
// z externího souboru.
//
// rendering lze spustit příkazem:
//     povray +W800 +H600 +B100 +FN +D +Iscena1.pov +Oscena1.png
// (pro náhled postačí zadat povray scena1.pov)
// ------------------------------------------------------------

#include "colors.inc"

// nastavení kamery
camera
{
    location  <0, 0, -10>                // pozice kamery
    look_at   <0, 0, 0>                  // bod, na který se kamera dívá
    angle 48                             // zorný úhel
}

// zdroj světla
light_source
{
    <500, 500, -500>                     // pozice zdroje světla
    color White                          // barva světla
}

box                                      // objemová data jsou představována kvádrem
{
    <0,0,0>, <1,1,1>
    texture
    {
        pigment
        {
            rgbt 1                       // zcela průhledné stěny kvádru - zajímá nás pouze jeho vnitřek
        }
    }
    interior
    {
        media
        {
            emission 0.5                 // částice emitující světlo
            scattering {1, 0.1}          // částice rozptylující světlo
            intervals 8                  // vyšší hodnota - větší přesnost výpočtu, ovšem také delší čas
            samples 10
            method 3
            density                      // definice hustoty částic na základě souboru s volumetrickými daty
            {
                density_file df3 "pokus256.df3" interpolate 1
                color_map                // mapování hustoty na barvu
                {
                    [0.0  rgb 0]

                    [0.23 rgb 0]         // první barevný pruh
                    [0.23 Blue]
                    [0.29 Blue]
                    [0.29 rgb 0]

                    [0.47 rgb 0]         // druhý barevný pruh
                    [0.47 Yellow]
                    [0.53 Yellow]
                    [0.53 rgb 0]

                    [0.73 rgb 0]         // třetí barevný pruh
                    [0.73 Red]
                    [0.79 Red]
                    [0.79 rgb 0]

                    [1    rgb 0]
                }
            }
        }
    }
    hollow                               // aby výpočet rozptylu probíhal korektně, je důležité
                                         // používat prázdná uzavřená tělesa
    translate -0.5
    scale 4
    rotate <60,30,0>
}



// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 
povray3309

Obrázek 9: Třetí demonstrační příklad, ve kterém je použita prostorová mřížka o rozlišení 256×256×256 voxelů.

7. Odkazy na Internetu

  1. Cloud generator (POV-Ray),
    http://www.oy­onale.com/mode­les.php?lang=en&pa­ge=36
  2. ImageJ Plugins DF3,
    http://fly.mpi-cbg.de/~saalfel­d/df3.html
  3. POVRay density (DF3) files or Using POVRay as a volume renderer,
    http://local.was­p.uwa.edu.au/~pbou­rke/miscellane­ous/df3/
  4. Scientific Visualizations with POV-Ray,
    http://www.li­nuxjournal.com/ar­ticle/7486
  5. df3 Python Class,
    http://povray­.tashcorp.net/tu­torials/scrip­t_df3/
povray3310

Obrázek 10: Odlišná barvová mapa vede ke zvýraznění jiných izoploch, konkrétně izoploch spojujících voxely s hustotou 0,62, 0,82 a 0,92.

root_podpora

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

V následující části seriálu o raytraceru POV-Ray dokončíme část věnovanou vizualizaci objemových dat. Současně začneme s popisem alternativního způsobu výpočtu ambientní složky světla pomocí takzvané radiozitní (vyzařovací) metody. Jedná se o metodu, která byla do POV-Raye přidána ve verzi 3.1, my si však popíšeme novější variantu algoritmu výpočtu globálního osvětlení platnou pro verzi 3.5 a samozřejmě i pro verze vyšší.

povray3311

Obrázek 11: Třetí demonstrační příklad vykreslený s využitím alternativní barvové mapy zvýrazňující hustoty 0,12, 0,22 a 0,32.

Byl pro vás článek přínosný?

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.