Hlavní navigace

Použití konstruktivní geometrie těles v praxi

18. 3. 2008
Doba čtení: 19 minut

Sdílet

Ve čtvrté části seriálu o raytraceru POV-Ray si ukážeme, jakým způsobem je možné použít konstruktivní geometrii těles (CSG) v praxi, tj. k modelování vlastních 3D scén. Kromě několika výukových příkladů budou uvedeny i dva příklady složitější: vykreslení modelu ventilu a modelu kuličkového ložiska.

Obsah

1. Použití konstruktivní geometrie těles v praxi
2. Popis operací sjednocení, sloučení, průniku a rozdílu
3. Základní demonstrační scéna
4. Demonstrační příklad sjednocení (union) dvou těles
5. Demonstrační příklad sloučení (merge) dvou těles
6. Demonstrační příklad průniku (intersection) dvou těles
7. Demonstrační příklad rozdílu (difference) dvou těles
8. Kombinace sjednocení a rozdílu při tvorbě složitého tělesa pomocí CSG
9. Obsah následující části seriálu

1. Čtyři základní operace CSG

V předchozí části tohoto seriálu jsme si popsali základy takzvané konstruktivní geometrie těles (CSG – Constructive Solid Geometry. Pomocí této poměrně vyspělé a přitom snadno použitelné modelovací techniky je možné vytvářet různé typy modelů, především umělé (technické) objekty a artefakty. Dnes si na několika demonstračních příkladech ukážeme, jakým způsobem je možné konstruktivní geometrii těles použít v praxi, a to i bez pomoci modelovacího programu s grafickým uživatelským rozhraním. První demonstrační příklady budou poměrně jednoduché – bude se vždy jednat o dvě základní geometrická tělesa zkombinovaná pomocí množinových operací – ale ukážeme si také dva příklad složitější, ve kterém bude ukázán způsob vytvoření přesného modelu ventilu pomocí zdrojového kódu, jehož velikost nepřesáhne 3 kB. Druhý složitější příklad posloužil k vytvoření rozříznutého modelu kuličkového ložiska.

povray0401

Z teorie množin známe několik množinových operací, mezi něž patří především sjednocení, průnik, rozdíl a doplněk množiny. Konstruktivní geometrie těles je sice založena na teorii množin, ovšem sada dostupných operací je poněkud odlišná. V dalším textu se zaměříme především na program POV-Ray a jeho specifika. V něm jsou implementovány čtyři CSG operace. Tyto operace je možné provádět pouze nad tělesy, u nichž je jasně definován jejich vnitřek a vnějšek. To je případ uzavřených těles (ty jsme si popsali minule – jedná se o kvádr, kouli, válec, kužel a toroid), implicitních ploch, superelipsoidů (budou popsány v dalším pokračování tohoto seriálu) a překvapivě také nekonečného tělesa „poloprostor“, což není nic jiného než rovina s normálovým vektorem, který určuje, která část prostoru patří dovnitř a která vně. Oněmi čtyřmi základními operacemi použitelnými v POV-Rayi jsou:

  1. sjednocení (union) dvou či více těles
  2. sloučení (merge) dvou či více těles
  3. průnik (intersection) dvou či více těles
  4. rozdíl (difference) dvou či více těles

2. Popis operací sjednocení, sloučení, průniku a rozdílu

Sjednocení (union)

CSG operace sjednocení (union) je poměrně jednoduchá. Dvě nebo více těles se pomocí této operace skutečně sjednotí, tj. lze s nimi pracovat jako s novým tělesem. Podobnou operaci nabízí ve 2D provedení prakticky všechny vektorové editory (InkScape, CorelDraw!, OpenOffice.org Draw atd.). Způsobů využití této operace je skutečně mnoho, typické je však použití takto sjednoceného tělesa v dalších CSG operacích popsaných dále. Od dále popsané operace sloučení (merge) se union odlišuje především v tom, že jsou zachovány všechny hranice těles. To mj. znamená, že při sjednocení dvou koulí (zobrazených na následujícím obrázku v řezu jako kružnice) jsou ve výsledném tělese přítomny i ty části stěn koulí, které se nachází uvnitř. V případě neprůhledných objektů nám to samozřejmě nevadí, ovšem pokud by se sjednocovaly objekty průhledné, byly by „vnitřní“ stěny viditelné, což většinou není žádoucí. Na druhou stranu je operace union velmi rychlá, proto je doporučeno ji pro neprůhledné objekty upřednostnit.

povray0402

Příklad aplikace operace union v 2D

Sloučení (merge)

CSG operace sloučení (merge) je velmi podobná operaci sjednocení. Už v předchozím odstavci jsem se zmínil o tom, že při sjednocování těles dochází k zachování vnitřních stěn těchto těles, což může způsobit vytváření nechtěných vizuálních artefaktů při volbě průhledného materiálu. Naproti tomu při aplikaci operace merge dojde k odstranění vnitřních stěn, takže výsledné těleso je opravu jednolité. Mohlo by se tedy zdát, že je vždy výhodnější použít operaci merge a ne union. Ovšem merge je výpočetně náročnější, protože se při raytracingu musí neustále zjišťovat, které stěny se mají ignorovat a které nikoli, proto se pro neprůhledné objekty doporučuje upřednostnit union.

povray0403

Příklad aplikace operace merge v 2D

Průnik (intersection)

Zatímco předchozí dvě CSG operace byly z hlediska vytváření nových tvarů poměrně „nezáživné“ (s podobným výsledkem se totiž tělesa dají pouze překrýt), je CSG operace průniku (intersection) již mnohem zajímavější, protože její vhodnou aplikací mohou vznikat i docela složité tvary. Ze dvou nebo více těles, které jsou podrobeny této operaci, zbude pouze ta část, která leží uvnitř všech těchto těles, tj. je společná pro všechna tělesa. Průnikem krychle a koule může vzniknout při vhodném poměru velikostí hrací kostka do hry „Člověče nezlob se“ atd. Velmi zajímavé je použití průniku více poloprostorů (v podstatě rovin), protože se dají vytvářet nejenom řezy různými tělesy, ale jednoduše modelovat i takové objekty, jakými jsou dokonalá tělesa atd. Jednotlivé poloprostory totiž z celkového objemu „ukusují“ další části, až zbude pouze ta část, která je všem poloprostorům společná, což je technika, kterou si ukážeme příště.

povray0404

Příklad aplikace operace intersection v 2D

Rozdíl (difference)

Poslední CSG operací, která je v POV-Rayi podporovaná, je rozdíl (difference). V případě aplikace této transformace je jedno těleso „vykousnuto“ druhým tělesem. Průběh operace vlastně odpovídá obrábění – první těleso představuje zpracovávaný materiál, druhé těleso pak nástroj (například frézovací hlavu), která materiál obrábí. Způsobů použití této operace je velmi mnoho, typická je tvorba otvorů do již vymodelovaných částí. Všimněte si, že v případě hraniční reprezentace těles (trojúhelníkové sítě či NURBS) se jedná o potenciálně velmi složitou operaci, při níž je zapotřebí kompletně přepočítat plášť tělesa, zatímco v CSG jde o operaci velmi jednoduchou. To je ostatně jeden z důvodů, proč se CSG zavádělo například do programů typu CAD, zejména ve strojírenství: operace difference odpovídá obrábění a operace union a merge pak lepení či svařování.

povray0405

Příklad aplikace operace difference v 2D

3. Základní demonstrační scéna

V dalších kapitolách si budeme mj. ukazovat vliv jednotlivých CSG operací na dvě tělesa – kouli a krychli – která jsou vytvořena z materiálu podobného zelenému sklu. Základní scéna bez uvedení CSG operace a krychle má následující tvar:

// ------------------------------------------------------------
// Jednoduchá scéna s jedním uzavřeným objektem, jedním nekonečným
// objektem, trojicí světel a jednou kamerou (pozorovatelem)
//
// Založeno na souboru původně vytvořeném Danem Farmerem (leden 2002)
//
// rendering lze spustit příkazem:
//     povray +W800 +H600 +B100 +FN +D +Iscena2.pov +Oscena2.png
// (pro náhled postačí zadat povray scena2.pov)
// ------------------------------------------------------------

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

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

// nastavení kamery (pozorovatele)
camera {
    location  <1.65, 5.5, -5.0>          // pozice kamery
    up        <0.0,  1.0,  0.0>          // vektor směřující vzhůru
    right     <4/3,  0.0,  0.0>          // vektor směřující doprava
    look_at   <0,    0.5, -1.0>          // bod, na který kamera směřuje
}

// tři světelné zdroje
light_source {
    <-30, 11,  20>                       // pozice světelného zdroje
    color White                          // barva světla
}

light_source {
    < 31, 12, -20>                       // pozice světelného zdroje
    color White                          // barva světla
}

light_source {
    < 32, 11, -20>                       // pozice světelného zdroje
    color LightGray                      // barva světla
}

// jediný uzavřený objekt ve scéně - zelená skleněná koule
sphere {
    <0, 0, 0>,                           // souřadnice středu koule
    1.75                                 // poloměr koule
    interior {                           // vlastnosti "vnitřku" koule
        caustics 1.0                     // světelná "prasátka"
        ior 1.5                          // index lomu
    }
    texture {                            // textura - povrch koule
        T_Glass1                         // definováno v externím souboru
        pigment {
            color green 0.90 filter 0.85 // barva povrchu
        }
        finish {                         // optické vlastnosti materiálu
            phong 1                      // velikost a síla odlesků
            phong_size 300
            reflection 0.15              // odrazivost
        }
    }
}

// druhý objekt - nekonečná rovina
plane {
    y,                                   // orientace roviny
    -1.5                                 // vzdálenost od počátku
    texture {                            // textura - vlastnosti povrchu
        T_Stone1                         // definováno v externím souboru
        pigment {                        // vlastní vzorek textury
            octaves 3                    // modifikace procedurálního vzorku
            rotate 90*z
        }
        finish {                         // optické vlastnosti materiálu
            reflection 0.10
        }
    }
}



// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 
povray0406

Obrázek vzniklý vykreslením základní demonstrační scény

4. Demonstrační příklad sjednocení (union) dvou těles

Jak jsme si již řekli v první kapitole, jsou při operaci sjednocení zachovány všechny stěny sjednocovaných těles, tj. i stěny vnitřní. To je jasně patrné v následující scéně, ve které je sjednocena krychle a koule, protože dvojité vnitřní stěny zcela změní charakter výsledného průhledného objektu. Všimněte si způsobu zápisu sjednocení, který je obdobný pro všechny CSG operace: tělesa, které se operaci podrobí, jsou umístěna do bloku, který nese název dané operace. V tomto případě se jedná o blok union. Vzhledem k tomu, že jsou tělesa umístěna v jednom bloku, lze je například současně otáčet:

// ------------------------------------------------------------
// Aplikace CSG operace sjednocení koule a krychle
//
// Založeno na souboru původně vytvořeném Danem Farmerem (leden 2002)
//
// rendering lze spustit příkazem:
//     povray +W800 +H600 +B100 +FN +D +Iscena2.pov +Oscena2.png
// (pro náhled postačí zadat povray scena2.pov)
// ------------------------------------------------------------

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

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

// nastavení kamery (pozorovatele)
camera {
    location  <1.65, 5.5, -5.0>          // pozice kamery
    up        <0.0,  1.0,  0.0>          // vektor směřující vzhůru
    right     <4/3,  0.0,  0.0>          // vektor směřující doprava
    look_at   <0,    0.5, -1.0>          // bod, na který kamera směřuje
}

// tři světelné zdroje
light_source {
    <-30, 11,  20>                       // pozice světelného zdroje
    color White                          // barva světla
}

light_source {
    < 31, 12, -20>                       // pozice světelného zdroje
    color White                          // barva světla
}

light_source {
    < 32, 11, -20>                       // pozice světelného zdroje
    color LightGray                      // barva světla
}

#declare VEL=1.4;                        // velikost krychle

union {
    box {
        <-VEL, -VEL, -VEL>               // jeden z vrcholů krychle na tělesové úhlopříčce
        < VEL,  VEL,  VEL>               // druhý z vrcholů krychle na tělesové úhlopříčce
        interior {                       // vlastnosti "vnitřku" koule
            caustics 1.0
            ior 1.5
        }
        texture {                        // textura - povrch krychle
            T_Glass1                     // definováno v externím souboru
            pigment {
                color green 0.90 filter 0.85 // barva povrchu
            }
            finish {                     // optické vlastnosti materiálu
                phong 1                  // velikost a síla odlesků
                phong_size 300
                reflection 0.15          // odrazivost
            }
        }
    }
    sphere {
        <0, 0, 0>,                       // souřadnice středu koule
        1.8                              // poloměr koule
        interior {                       // vlastnosti "vnitřku" koule
            caustics 1.0
            ior 1.5
        }
        texture {                        // textura - povrch koule
            T_Glass1                     // definováno v externím souboru
            pigment {
                color green 0.90 filter 0.85 // barva povrchu
            }
            finish {                     // optické vlastnosti materiálu
                phong 1                  // velikost a síla odlesků
                phong_size 300
                reflection 0.15          // odrazivost
            }
        }
    }
    rotate <0,45,0>                      // rotace výsledného "dvojtělesa"
}

// druhý objekt - nekonečná rovina
plane {
    y,                                   // orientace roviny
    -1.5                                 // vzdálenost od počátku
    texture {                            // textura - vlastnosti povrchu
        T_Stone1                         // definováno v externím souboru
        pigment {                        // vlastní vzorek textury
            octaves 3                    // modifikace procedurálního vzorku
            rotate 90*z
        }
        finish {                         // optické vlastnosti materiálu
            reflection 0.10
        }
    }
}



// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 
povray0407

Výsledek sjednocení průhledné krychle a koule

5. Demonstrační příklad sloučení (merge) dvou těles

Zatímco při sjednocení průhledných objektů docházelo ke vzniku nežádoucích optických poruch, operace sloučení již proběhne zcela v pořádku, ovšem za cenu prodloužení času renderingu, tj. výpočtu celé scény. Slučovaná tělesa jsou umístěna v bloku nazvaném merge:

// ------------------------------------------------------------
// Aplikace CSG operace sloučení koule a krychle
//
// Založeno na souboru původně vytvořeném Danem Farmerem (leden 2002)
//
// rendering lze spustit příkazem:
//     povray +W800 +H600 +B100 +FN +D +Iscena2.pov +Oscena2.png
// (pro náhled postačí zadat povray scena2.pov)
// ------------------------------------------------------------

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

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

// nastavení kamery (pozorovatele)
camera {
    location  <1.65, 5.5, -5.0>          // pozice kamery
    up        <0.0,  1.0,  0.0>          // vektor směřující vzhůru
    right     <4/3,  0.0,  0.0>          // vektor směřující doprava
    look_at   <0,    0.5, -1.0>          // bod, na který kamera směřuje
}

// tři světelné zdroje
light_source {
    <-30, 11,  20>                       // pozice světelného zdroje
    color White                          // barva světla
}

light_source {
    < 31, 12, -20>                       // pozice světelného zdroje
    color White                          // barva světla
}

light_source {
    < 32, 11, -20>                       // pozice světelného zdroje
    color LightGray                      // barva světla
}

#declare VEL=1.4;                        // velikost krychle

merge {
    box {
        <-VEL, -VEL, -VEL>               // jeden z vrcholů krychle na tělesové úhlopříčce
        < VEL,  VEL,  VEL>               // druhý z vrcholů krychle na tělesové úhlopříčce
        interior {                       // vlastnosti "vnitřku" koule
            caustics 1.0
            ior 1.5
        }
        texture {                        // textura - povrch krychle
            T_Glass1                     // definováno v externím souboru
            pigment {
                color green 0.90 filter 0.85 // barva povrchu
            }
            finish {                     // optické vlastnosti materiálu
                phong 1                  // velikost a síla odlesků
                phong_size 300
                reflection 0.15          // odrazivost
            }
        }
    }
    sphere {
        <0, 0, 0>,                       // souřadnice středu koule
        1.8                              // poloměr koule
        interior {                       // vlastnosti "vnitřku" koule
            caustics 1.0
            ior 1.5
        }
        texture {                        // textura - povrch koule
            T_Glass1                     // definováno v externím souboru
            pigment {
                color green 0.90 filter 0.85 // barva povrchu
            }
            finish {                     // optické vlastnosti materiálu
                phong 1                  // velikost a síla odlesků
                phong_size 300
                reflection 0.15          // odrazivost
            }
        }
    }
    rotate <0,45,0>                      // rotace výsledného "dvojtělesa"
}

// druhý objekt - nekonečná rovina
plane {
    y,                                   // orientace roviny
    -1.5                                 // vzdálenost od počátku
    texture {                            // textura - vlastnosti povrchu
        T_Stone1                         // definováno v externím souboru
        pigment {                        // vlastní vzorek textury
            octaves 3                    // modifikace procedurálního vzorku
            rotate 90*z
        }
        finish {                         // optické vlastnosti materiálu
            reflection 0.10
        }
    }
}



// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 
povray0408

Výsledek sloučení průhledné krychle a koule

6. Demonstrační příklad průniku (intersection) dvou těles

Pomocí průniku koule a krychle lze mj. vymodelovat i jednoduchý model kostky pro hru „Člověče nezlob se“, jak je ukázáno na dalším příkladu. Vzhledem k tomu, že u průhledných těles nevynikne výsledný tvar, byly v této scéně použity odlišené textury a zvolen neprůhledný materiál. Tělesa podrobené operaci průniku jsou umístěna do uzlu nazvaného intersection:

// ------------------------------------------------------------
// Aplikace CSG operace průniku koule a krychle
//
// Založeno na souboru původně vytvořeném Danem Farmerem (leden 2002)
//
// rendering lze spustit příkazem:
//     povray +W800 +H600 +B100 +FN +D +Iscena2.pov +Oscena2.png
// (pro náhled postačí zadat povray scena2.pov)
// ------------------------------------------------------------

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

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

// nastavení kamery (pozorovatele)
camera {
    location  <1.65, 5.5, -5.0>          // pozice kamery
    up        <0.0,  1.0,  0.0>          // vektor směřující vzhůru
    right     <4/3,  0.0,  0.0>          // vektor směřující doprava
    look_at   <0,    0.5, -1.0>          // bod, na který kamera směřuje
}

// tři světelné zdroje
light_source {
    <-30, 11,  20>                       // pozice světelného zdroje
    color White                          // barva světla
}

light_source {
    < 31, 12, -20>                       // pozice světelného zdroje
    color White                          // barva světla
}

light_source {
    < 32, 11, -20>                       // pozice světelného zdroje
    color LightGray                      // barva světla
}

#declare VEL=1.4;                        // velikost krychle

intersection {
    box {
        <-VEL, -VEL, -VEL>               // jeden z vrcholů krychle na tělesové úhlopříčce
        < VEL,  VEL,  VEL>               // druhý z vrcholů krychle na tělesové úhlopříčce
        interior {                       // vlastnosti "vnitřku" koule
            caustics 1.0
            ior 1.5
        }
        texture {                        // textura - povrch krychle
            T_Stone1
            finish {                     // optické vlastnosti materiálu
                phong 1                  // velikost a síla odlesků
                phong_size 300
                reflection 0.15          // odrazivost
            }
        }
    }
    sphere {
        <0, 0, 0>,                       // souřadnice středu koule
        1.8                              // poloměr koule
        texture {                        // textura - povrch koule
            T_Stone1
            finish {                     // optické vlastnosti materiálu
                phong 1                  // velikost a síla odlesků
                phong_size 300
                reflection 0.15          // odrazivost
            }
        }
    }
    rotate <0,45,0>                      // rotace výsledného "dvojtělesa"
}

// druhý objekt - nekonečná rovina
plane {
    y,                                   // orientace roviny
    -1.5                                 // vzdálenost od počátku
    texture {                            // textura - vlastnosti povrchu
        pigment {
            crackle
        }
        finish {                         // optické vlastnosti materiálu
            reflection 0.10
        }
    }
}



// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 
povray0409

Výsledek průniku krychle a koule

povray0410

Výsledek průniku toroidu a koule

7. Demonstrační příklad rozdílu (difference) dvou těles

Výsledek CSG operace rozdílu dvou těles je vcelku předvídatelný, ovšem je zapotřebí dát pozor na to, které těleso je „odečítáno“, tj. na pořadí těles v bloku nazvaném difference:

// ------------------------------------------------------------
// Aplikace CSG operace rozdílu koule a krychle
//
// Založeno na souboru původně vytvořeném Danem Farmerem (leden 2002)
//
// rendering lze spustit příkazem:
//     povray +W800 +H600 +B100 +FN +D +Iscena2.pov +Oscena2.png
// (pro náhled postačí zadat povray scena2.pov)
// ------------------------------------------------------------

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

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

// nastavení kamery (pozorovatele)
camera {
    location  <1.65, 5.5, -5.0>          // pozice kamery
    up        <0.0,  1.0,  0.0>          // vektor směřující vzhůru
    right     <4/3,  0.0,  0.0>          // vektor směřující doprava
    look_at   <0,    0.5, -1.0>          // bod, na který kamera směřuje
}

// tři světelné zdroje
light_source {
    <-30, 11,  20>                       // pozice světelného zdroje
    color White                          // barva světla
}

light_source {
    < 31, 12, -20>                       // pozice světelného zdroje
    color White                          // barva světla
}

light_source {
    < 32, 11, -20>                       // pozice světelného zdroje
    color LightGray                      // barva světla
}

#declare VEL=1.45;                       // velikost krychle

difference {
    box {
        <-VEL, -VEL, -VEL>               // jeden z vrcholů krychle na tělesové úhlopříčce
        < VEL,  VEL,  VEL>               // druhý z vrcholů krychle na tělesové úhlopříčce
        texture {                        // textura - povrch krychle
            T_Glass1                     // definováno v externím souboru
            pigment {
                color green 0.90 filter 0.85 // barva povrchu
            }
            finish {                     // optické vlastnosti materiálu
                phong 1                  // velikost a síla odlesků
                phong_size 300
                reflection 0.15          // odrazivost
            }
        }
    }
    sphere {
        <0, 0, 0>,                       // souřadnice středu koule
        1.8                              // poloměr koule
        interior {                       // vlastnosti "vnitřku" koule
            caustics 1.0
            ior 1.5
        }
        texture {                        // textura - povrch koule
            T_Glass1                     // definováno v externím souboru
            pigment {
                color green 0.90 filter 0.85 // barva povrchu
            }
            finish {                     // optické vlastnosti materiálu
                phong 1                  // velikost a síla odlesků
                phong_size 300
                reflection 0.15          // odrazivost
            }
        }
    }
    rotate <0,45,0>                      // rotace výsledného "dvojtělesa"
}

// druhý objekt - nekonečná rovina
plane {
    y,                                   // orientace roviny
    -1.5                                 // vzdálenost od počátku
    texture {                            // textura - vlastnosti povrchu
        T_Stone1                         // definováno v externím souboru
        pigment {                        // vlastní vzorek textury
            octaves 3                    // modifikace procedurálního vzorku
            rotate 90*z
        }
        finish {                         // optické vlastnosti materiálu
            reflection 0.10
        }
    }
}



// ------------------------------------------------------------
// finito
// ------------------------------------------------------------ 
povray0411

Výsledek rozdílu krychle a koule

povray0412

Nyní je od koule „odečítána“ krychle

povray0413

Výsledek rozdílu koule a toroidu

8. Kombinace sjednocení a rozdílu při tvorbě složitého tělesa pomocí CSG

Následuje poměrně složitý příklad, ve kterém jsou použity CSG operace sjednocení a rozdílu pro tvorbu skupiny těles představující ventil. Zdrojový soubor je uspořádaný tak, aby bylo možné provést animaci otevírání a zavírání ventilu, tvorbu animací si však ukážeme až někdy příště. Díky použití CSG vznikl přesný model (žádné plošky) a přitom je velikost souboru pouhé 3 kB (po odstranění přebytečného formátování i o něco méně):

// Persistence of Vision Ray Tracer Scene Description File
// File: Butterfly_Valve.pov
// Vers: 3.1
// Desc: Basic Scene Example
// Date: 29/04/01
// Auth: siegfriedfeterowsky@web.de

// Good for animation. Let clock run from 0 to 1.
#declare winkel = clock*360*3;
#declare rotall = clock*360;
#declare winkel = 45;

global_settings { assumed_gamma 1.0 number_of_waves 1 }

#include "colors.inc"
#include "shapes.inc"
#include "textures.inc"
#include "metals.inc"

camera {
    location <-20.0, 30.0,-75>
    direction z * 3
    up y
    right x*4/3
    look_at < -1, 0, 0>
}

plane {
    y, -5
    pigment {
        Navy * .1
    }
}

light_source {
    <10.0, 50.0, 35.0>
    color White
}

light_source {
    <-35.0, 30.0, -150.0>
    color White
}

#declare loch =difference {
    cylinder {
        <0,-4,0>, <0,-5,0>, 1
        texture {
            T_Chrome_5D
        }
    }
    cylinder {
        <0,-3.9,0>, <0,-5.1,0>,.5
        texture {
            T_Chrome_1A
        }
    }
}

union {
cone {
    <-7,0,0>, 2.6, <-6.2,0,0>, 3.2
    texture {
        T_Chrome_5D
    }
}

cylinder {
    <-6.2,0,0>, <-4.4,0,0>, 3.2
    texture {
        T_Chrome_5D
    }
}

difference {
    union {
        object {
            loch
            translate <-5,9,-3.2>
        }
        object {
            loch
            translate <4.5,9,-2.4>
        }
        object {
            loch
            translate <-0.7,9,5.3>
        }
        cylinder {
            <-.4,-4,0>, <-.4,5,0>, 5
            texture {
                T_Chrome_5D
            }
        }
    }
    cylinder {
        <-.4,-4.1,0>, <-.4,5.1,0>, 4
        texture {
            T_Chrome_5D
        }
    }
    plane {
        <0,0,1>,-3.2
        texture {
            T_Chrome_5D
        }
    }
}

difference {
    cylinder {
        <-.4,-4,0>, <-.4,-5,0>, 5
        texture {
            T_Chrome_5D
        }
    }
    cylinder {
        <-.4,-3.9,0>, <-.4,-5.1,0>, 4
        texture {
            T_Chrome_5D
        }
    }
}

cylinder {
    <3.6 0,0>, <5.6,0,0> ,1.8
    texture {
        T_Chrome_5D
    }
}

// Mountings

object {
    loch
    translate <-5,0,-3.2>
}
object {
    loch
    translate <4.5,0,-2.4>
}
object {
    loch
    translate <-0.7,0,5.3>
}

#declare welle = union {
    cylinder {
        <-9.2,0,0> , <5.8,0,0>, .6
        texture {
            T_Copper_5A
        }
        finish {
            metallic
        }
    }
    cylinder {
        <-.4,0,-.2>, <-.4,0,.2>, 4
        texture {
            T_Copper_5A
        }
        finish {
            metallic
        }
    }
    cylinder {
        <-9.,0,0>, <-7.,0,0>, 1.8
        texture {
            T_Copper_5E
        }
    }
    cylinder {
        <-9.1,-1,0>, <-9.1,1,0>, .1
        texture {
            T_Copper_5E
        }
    }
    box {
        <-8.5, -1.8, 0>
        <-7.5,  1.8,  -10>
        texture {
            T_Copper_5E
        }
    }
    difference {
        cylinder {
            <-9.,0,-10>, <-7,0,-10>, 1.8
            texture {
                T_Copper_5E
            }
        }
        cylinder {
            <-9.1,0,-10>, <-6.9,0,-10>, .9
            texture {
                T_Copper_5E
            }
        }
    }
}

object {
    welle
    rotate <winkel,0,0>
}
    rotate rotall*y
} 
povray0414

Ventil vytvořený s pomocí výše uvedeného popisu scény

Dnešní poslední příklad je ještě rozsáhlejší než příklad předchozí. Je na něm ukázána tvorba kuličkového ložiska i se všemi jeho součástmi, včetně věnečku, který slouží k pravidelnému rozmístění kuliček po obvodu. Jak vlastní model, tak i jeho rozříznutí je vytvořeno za pomoci CSG. Za zmínku také stojí analytický popis modelu pomocí číselných výrazů – v příkladu se nevyskytují „magické hodnoty“, ale pouze číselné výrazy využívající několik předem nadefinovaných hodnot, takže tvar ložiska je možné měnit pomocí příkazů #declare umístěných na začátku souboru.

// This is a Ball Bearing on a checker floor.
// To render the whole object search for "remove this!"
// in the file "BallBearing.INC" and comment out the two lines.
// Diego Krota, 1998.
// dkrota@geocities.com
// http://www.geocities.com/SiliconValley/Way/2419

#version 2.5


#include "colors.inc"
#include "textures.inc"

#declare bigradius = 6
#declare bigradiusint = 5
#declare smallradius = 4
#declare smallradiusint = 3
#declare tickness = 2
#declare sphereradius = .8
#declare bigsphereradius = sphereradius + sphereradius/4
#declare smallsphereradius = sphereradius + sphereradius/10
#declare bevel = .2
#declare epsilon = .01

#declare bigring =
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>} // remove this! (To render the whole Ball Bearing)
}

#declare smallring =
difference{
    difference{
        cylinder{<0, 0, tickness/2>, <0, 0, -tickness/2>, smallradius}
        cylinder{<0, 0, tickness/2 + epsilon>, <0, 0, -(tickness/2 + epsilon)>, smallradiusint}
        cone{<0, 0, -(smallradius + 1 - bevel)>, 0, <0, 0, 1 + bevel>, smallradius + 2 inverse}
        cone{<0, 0, smallradius + 1 - bevel>, 0, <0, 0, -(1 + bevel)>, smallradius + 2 inverse}
        merge{
            cone{<0, 0, -((smallradiusint - 1) + bevel)>, 0, <0, 0, -((smallradiusint - 1) + bevel) + smallradius>, smallradius}
            cone{<0, 0, (smallradiusint - 1) + bevel>, 0, <0, 0, (smallradiusint - 1) + bevel - smallradius>, smallradius}
        }
    }
    torus{
        (bigradiusint + smallradius) / 2,
        sphereradius
        rotate x * 90
    }
    box{<0, 0, -1000>, <1000, 1000, 1000>} // remove this! (To render the whole Ball Bearing)
}

#declare spheres =
union{
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        sphereradius
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        sphereradius
        rotate z * 1 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        sphereradius
        rotate z * 2 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        sphereradius
        rotate z * 3 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        sphereradius
        rotate z * 4 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        sphereradius
        rotate z * 5 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        sphereradius
        rotate z * 6 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        sphereradius
        rotate z * 7 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        sphereradius
        rotate z * 8 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        sphereradius
        rotate z * 9 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        sphereradius
        rotate z * 10 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        sphereradius
        rotate z * 11 * 30
    }
}

#declare bigspheres =
union{
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        bigsphereradius
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        bigsphereradius
        rotate z * 1 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        bigsphereradius
        rotate z * 2 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        bigsphereradius
        rotate z * 3 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        bigsphereradius
        rotate z * 4 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        bigsphereradius
        rotate z * 5 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        bigsphereradius
        rotate z * 6 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        bigsphereradius
        rotate z * 7 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        bigsphereradius
        rotate z * 8 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        bigsphereradius
        rotate z * 9 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        bigsphereradius
        rotate z * 10 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        bigsphereradius
        rotate z * 11 * 30
    }
}

#declare smallspheres =
union{
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        smallsphereradius
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        smallsphereradius
        rotate z * 1 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        smallsphereradius
        rotate z * 2 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        smallsphereradius
        rotate z * 3 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        smallsphereradius
        rotate z * 4 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        smallsphereradius
        rotate z * 5 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        smallsphereradius
        rotate z * 6 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        smallsphereradius
        rotate z * 7 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        smallsphereradius
        rotate z * 8 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        smallsphereradius
        rotate z * 9 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        smallsphereradius
        rotate z * 10 * 30
    }
    sphere{
        <0, (bigradiusint + smallradius) / 2, 0>,
        smallsphereradius
        rotate z * 11 * 30
    }
}

#declare cage =
union{
    difference{
        object{bigspheres}
        object{smallspheres}
        cylinder{<0, 0, tickness/2>, <0, 0, -tickness/2>, 4.1}
        cylinder{<0, 0, tickness/2>, <0, 0, -tickness/2>, 4.9 inverse}
    }
    difference{
        cylinder{<0, 0, tickness/10>, <0, 0, -tickness/10>, 4.9}
        cylinder{<0, 0, tickness/2>, <0, 0, -tickness/2>, 4.1}
        object{smallspheres}
    }
}

#declare Ball_Bearing =
union{
    object{bigring texture{Chrome_Metal}}
    object{smallring texture{Chrome_Metal}}
    object{spheres texture{Polished_Chrome}}
    object{cage texture{Polished_Chrome}}
}

camera{
    location  <0, 8, -12>
    look_at   <0, 0, 0>
}

light_source{ <6, 6, -20> color White * 2}

object{
    Ball_Bearing
    bounded_by {
        difference{
            cylinder{<0, 0, -tickness/2 - epsilon>, <0, 0, +tickness/2 + epsilon>, bigradius + epsilon}
            cylinder{<0, 0, -tickness/2 - epsilon>, <0, 0, +tickness/2 + epsilon>, smallradiusint - epsilon}
        }
    }
    rotate y * 40

}

plane{ // The checker floor
    y, -bigradius
    texture{
        pigment{
        checker
            color White
            color Black
            scale 10
            rotate y * 40
        }
    }
} 
povray0415

Model kuličkového ložiska

cyber23

9. Obsah následující části seriálu

V další části seriálu o raytraceru POV-Ray si popíšeme (už minule slibované) velmi užitečné těleso nazvané superellipsoid, které lze použít v mnoha případech, například modelování krychle se zaoblenými hranami, jehlanu se zaoblenými hranami, střechy východního stylu atd., ve kterých by se jinak muselo použít CSG či modelování pomocí parametrických ploch. Přednost superelipsoidů spočívá jak v jednoduchosti jejich popisu (jedná se o pouhé dvě reálné hodnoty definující tvar tělesa), tak i v možnostech kombinace s dalšími tělesy pomocí CSG. Na závěr si ukážeme použití CSG spolu s poloprostorem.

povray0416

Vybrané tvary superelipsoidů ve scéně popsané v příští části seriálu

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.