Hlavní navigace

L-systémy v 3D: Lparser, POV-Ray a Blender

28. 11. 2006
Doba čtení: 13 minut

Sdílet

Celá dnešní část seriálu o fraktálech je věnována popisu aplikace Lparser. Tento program slouží k tvorbě trojrozměrných modelů přírodních objektů i umělých artefaktů vytvářených pomocí L-systémů. Kromě běžných přepisovacích gramatik je možné použít i pokročilejší techniky, například takzvanou mutaci a simulaci gravitace.

Obsah

1. Úvodní informace o programu Lparser
2. Lparser1 verze 3.0 a 5.0 (instalace v Linuxu)
3. Rendering vytvořených modelů v programu POV-Ray
4. Použití implicitních ploch (metaballs, blobs)
5. Více objektů složených z implicitních ploch
6. Lparser2 verze 1.0
7. Zobrazení vytvořených modelů v Blenderu
8. Odkazy na další informační zdroje
9. Obsah dalšího pokračování tohoto seriálu

1. Úvodní informace o programu Lparser

V předchozích částech tohoto seriálu jsme si uvedli poměrně velké množství demonstračních příkladů vykreslujících plošné modely tvořené pomocí L-systémů. Ve všech případech se jednalo o velmi jednoduché aplikace, výsledkem jejichž činnosti byl dvourozměrný (plošný) model vykreslený pomocí úseček do okna spravovaného grafickou knihovnou OpenGL. L-systémy však mají své použití především v trojrozměrné grafice. Z tohoto důvodu se od dnešní části začneme zabývat zajímavou a přitom poměrně neznámou aplikací – generátorem trojrozměrných modelů L-systémů.

Jedná se o program nazvaný Lparser (celým názvem L-System Parser/Mutator), který vytvořil Laurens J. Lapre. Tuto aplikaci je možné získat na adresách uvedených v osmé kapitole. K dispozici je původní DOSovská (první) verze; dále verze číslo 2, která vytváří pouze soubory typu VRML a konečně zdrojový soubor napsaný v programovacím jazyku C, který je možné použít pro přenos první verze na různé platformy, samozřejmě včetně Linuxu.

Program Lparser je programem spustitelným z příkazového řádku, neobsahuje tedy žádné grafické uživatelské rozhraní. V nejjednodušším případě se do příkazového řádku zadá jako argument jméno souboru obsahujícího přepisovací gramatiku L-systému (tyto soubory mají koncovku .ls, v tomto případě se jedná o zvláštní programovací jazyk) a Lparser následně provede načtení gramatiky, přepis řetězců podle pravidel v gramatice, aplikaci mutace a dalších doplňkových procedur a následně pomocí trojrozměrné želví grafiky vytvoří výstupní soubor, který obsahuje informace o vygenerovaném trojrozměrném modelu.

V dalších kapitolách si řekneme, jaké výstupní formáty jsou podporovány (volba formátu se provede parametrem zadávaným z příkazového řádku). Všimněte si, že Lparser žádným způsobem neřeší samotné vykreslení (rendering) model – to je ponecháno na specializovaných aplikacích. Jedná se o typické využití známého principu „rozděl a panuj“, který uživatelé Linuxu či jiných unixových systémů jistě znají.

Program Lparser v současnosti existuje ve více verzích. Vzhledem k určitému zmatku v číslování verzí bude další popis rozdělen na dvě části: popis Lparseru1 (verze 3.0 a 5.0), který vychází z původní DOSovské vývojové větve a Lparseru2, jež je orientován na uživatele vlastnící nějaký prohlížeč souborů uložených ve formátu VRML. Rozdělení popisu na dvě části není samoúčelné, protože v některých případech je použití Lparseru1 vhodnější, zejména ve spojení s nástroji typu CAD (AutoCAD) či renderovacím programem POV-Ray – to si ostatně ukážeme v následujících kapitolách.

fractals57_1

Obrázek 1: Trojrozměrný model vytvořený pomocí programu Lparser

2. Lparser1 verze 3.0 a 5.0 (instalace v Linuxu)

Program Lparser1 byl původně vyvíjen pro operační systémy DOS, konkrétně se jedná o LParser1 verze 3.0. Kromě samotného Lparseru jsou na této platformě k dispozici i další pomocné programy, zejména prohlížeč vytvořených trojrozměrných modelů, který se jmenuje Lviewer, a převaděč vytvořených modelů do formátů zpracovatelných raytracery POV-Ray a Vivid. Tento převaděč se jmenuje lv2povid. Raytracer POV-Ray je známější, ale Vivid měl oproti němu jednu úžasnou vlastnost: pracoval i na procesorech 286 a renderovací časy také podle toho vypadaly (na druhou stranu byly zase v dobách procesorů 286 vyráběny už z principu tišší počítače, takže renderování mohlo probíhat přes noc).

fractals57_2

Obrázek 2: Prohlížeč Lviewer spuštěný v DOSBoxu

Prohlížeč trojrozměrných modelů Lviewer nabízí kromě základního náhledu na vytvořený model i další funkce, zejména možnost otáčení modelem, současný pohled na model z více stran (čtyři podokna) a mimo jiné také skrytí neviditelných hran pomocí malířova algoritmu (Painter's al­gorithm). V současnosti, kdy má prakticky každý majitel PC k dispozici výkonný grafický akcelerátor zobrazující vystínované a otexturované polygony, se tento program nutně jeví jako archaický, stále je však použitelný. Na operačních systémech Microsoft Windows je ho možné spustit přímo (testováno na Windows 98 a Windows XP), v Linuxu se bez problémů spouští například v DOSBoxu – viz screenshoty umístěné na druhém a třetím obrázku.

fractals57_3

Obrázek 3: Skrytí neviditelných hran pomocí malířova algoritmu

Nyní si řekneme, jakým způsobem je možné Lparser nainstalovat na operační systém Linux. Na stránkách programu (viz osmá kapitola) je možné nalézt i zdrojový kód Lparseru1 verze 5.0. Jedná se o jediný soubor se jménem lparser.c, který je možné přeložit jak pod Microsoft Windows (testováno s Borland C++ Compilerem 5.5 a GCC 3.2), tak i v Linuxu (testováno s GCC 3.3.5) a s velkou pravděpodobností i na ostatních unixových systémech. Při linkování je nutné připojit knihovnu s matematickými funkcemi, tj. zadat příkaz:

gcc -o lparser lparser.c -lm 

Kromě zdrojového kódu aplikace je vhodné stáhnout i původní LParser1; v archivu s tímto programem se totiž nachází i soubory *.ls, které obsahují definice přepisovacích gramatik zajímavých trojrozměrných L-systémů, ze kterých budeme v dalším textu vycházet. Mezi Lparserem1 a Lparserem2 se způsob zápisu gramatik (a tím i obsah souborů *.ls) změnil, námi přeložený Lparser1 tedy nebude s novými soubory funkční! V dalších třech kapitolách si řekneme, jakým způsobem můžeme námi přeložený Lparser použít pro tvorbu modelů, a jak je možné tyto modely vykreslit (vyrendrovat).

3. Rendering vytvořených modelů v programu POV-Ray

Téměř ideálním doplňkem programu Lparser je raytracer POV-Ray. Jeho instalaci si popisovat nebudeme, protože je (na rozdíl od Lparseru) popsána přímo na stránkách http://www.po­vray.org. Při zpracovávání přepisovacích gramatik Lparserem je možné specifikovat, jakým způsobem bude provádět výstup výsledného trojrozměrného modelu. K dispozici je několik výstupních formátů, nás však nyní budou zajímat především formáty, kterým „rozumí“ POV-Ray. Soubory s popisem 3D scény v POV-Rayi jsou zapsány pomocí syntaxe, která se blíží syntaxi programovacího jazyka C. Zdaleka se nejedná o první raytracer, který tuto syntaxi používá.

Lparser1 je v oblasti exportu 3D modelů vybaven takřka dokonale, protože generuje přímo zdrojové soubory pro POV-Ray. K dispozici jsou dva typy objektů, ze kterých se trojrozměrné modely mohou skládat. Prvním typem jsou obligátní plošné polygony (trojúhelníky i víceúhelníky), druhým typem implicitní plochy, známé pod názvy metaballs či blobs. V tabulce níže jsou vypsány volby Lparseru1, které ovlivňují výstup do programu POV-Ray:

Volba Význam volby
-v výstup ve formě plošných polygonů v syntaxi POV-Raye
-b výstup ve formě jednoho objektu složeného z blobů
-B výstup ve formě více objektů složených z blobů
-c místo samostatných souborů s koncovkou .pov se generují include soubory .inc

Nyní si ukážeme, jakým způsobem je možné vytvořit a následně pomocí POV-Raye vykreslit nějaký 3D model. Budeme potřebovat lparser1 přeložený způsobem popsaným v předchozí kapitole, původní lparser1 (datové soubory s gramatikou) a korektně nainstalovaný POV-Ray. Pokud je již lparser přeložen, použijeme datový soubor s gramatikou nazvaný fern.ls, který má následující obsah:

# --- L-System Parser/Mutator --- Lj Lapre ----------------------------------
#
20                  # recursion
20                  # angle
15                  # thickness
#
#---------------------------------------- axioms
#
#&(60)C                 # use this as axiom to test a leave
#b                  # use this as axiom to test a branch
b>(60)b>60)b>60)b>60)b>60)b      # the whole thing
#
# ---------------------------------------- rules
#
b=[&(30)A]
#
A=~(7)$t(.1)F[+(40)C][-(40)C]!(.95)~(7)t(.1)FA
#
C=~(10)$tF[+(60)L][-(60)L]C
#
L=[~(15)cc{-f+f+f-|-f+f}]
#
F='(1.3)F'(.77)
f='(1.3)f'(.77)
#
#~=_                    # uncomment to remove random efx
@ 

Pro vytvoření 3D modelu tohoto L-systému použijeme volby -v a -c. První volba způsobí výstup ve formě plošných polygonů, druhá volba tvorbu vkládaného souboru .inc místo souboru .pov (vkládané soubory se do značné míry podobají C-čkovým hlavičkovým souborům). Vytvoření modelu je velmi jednoduché:

./lparser -v -c fern 

Měl by se vytvořit poměrně velký soubor output.inc s mnoha 3D objekty. Tento soubor bude vkládán do zdrojového souboru fern.pov, který vytvoříme malou úpravou ukázkového souboru setup1.pov. Úprava spočívá v nastavení souřadnic kamery (pozorovatele) a světel:

// --- L-System Parser/Mutator --- Lj Lapre ---
// use with output.inc generated by lparser -vc
// and change direction/zoom scale to get correct view

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

// Choose 16 colors

#declare col_0  = colour red 0.8 green 0.498039 blue 0.196078
#declare col_1  = colour red 0.5 green 0.5 blue 0.5
#declare col_2  = colour red 1.0
#declare col_3  = colour red 1.0 green 1.0
#declare col_4  = colour red 0.2 green 0.7 blue 0.1
#declare col_5  = colour blue 1.0 green 1.0
#declare col_6  = colour blue 1.0
#declare col_7  = colour red 1.0 blue 1.0
#declare col_8  = colour red 0.439216 green 0.858824 blue 0.576471
#declare col_9  = colour red 1.0 green 0.498039 blue 0.0
#declare col_10 = colour red 0.258824 green 0.258824 blue 0.435294
#declare col_11 = colour red 0.6 green 0.196078 blue 0.8
#declare col_12 = colour red 0.439216 green 0.576471 blue 0.858824
#declare col_13 = colour red 0.556863 green 0.137255 blue 0.137255
#declare col_14 = colour red 0.858824 green 0.858824 blue 0.439216
#declare col_15 = colour red 0.623529 green 0.623529 blue 0.372549

// Setup camera

camera {
    location  <4000, 4000, 3000>
    direction <0, 0, 2.0>
    look_at   <0, 1000, 0>
}

// Setup light sources

object { light_source { <5000, 8000, 5000> color White } }

// Select lbase object

#declare l_base = object { sphere { <0, 0.75, 0> 0.75 } }

// Textures for l_base object and leafs

#declare t_base = finish { ambient 0.3 diffuse 0.7 phong 1 }
#declare t_leaf = finish { ambient 0.3 diffuse 0.7 }

#include "output.inc" 

Rendering pomocí POV-Raye provede příkaz:

povray +w800 +h600 +b100 +a0.05 +ifern.pov +ofern.tga 

Výsledkem by měl být následující obrázek:

fractals57_4

Obrázek 4: Vykreslený model L-systému Fern složený z trojúhelníků

4. Použití implicitních ploch (metaballs, blobs)

Ukážeme si ještě, jakým způsobem je možné pomocí Lparseru a POV-Raye vytvořit objekt složený z blobů (metaballs). Použijeme stejnou přepisovací gramatiku, jako v předchozím příkladu (fern.ls), ovšem při vytváření výsledného modelu budou použity jiné přepínače, konkrétně:

./lparser -b -c fern 

Tyto příkazy zajistí vytvoření souboru output.inc, který obsahuje jeden samostatný objekt složený z blobů (přesněji řečeno z prvků kostry, které tvoří základ pro vykreslení blobů). Popis scény vychází z demonstračního souboru setup2.pov, ve kterém je opět upravena pozice kamery a světel:

// --- L-System Parser/Mutator --- Lj Lapre ---
// use with output.inc generated by lparser -vc
// and change direction/zoom scale to get correct view

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

// Choose 16 colors

#declare col_0  = colour red 0.8 green 0.498039 blue 0.196078
#declare col_1  = colour red 0.5 green 0.5 blue 0.5
#declare col_2  = colour red 1.0
#declare col_3  = colour red 1.0 green 1.0
#declare col_4  = colour red 0.2 green 0.7 blue 0.1
#declare col_5  = colour blue 1.0 green 1.0
#declare col_6  = colour blue 1.0
#declare col_7  = colour red 1.0 blue 1.0
#declare col_8  = colour red 0.439216 green 0.858824 blue 0.576471
#declare col_9  = colour red 1.0 green 0.498039 blue 0.0
#declare col_10 = colour red 0.258824 green 0.258824 blue 0.435294
#declare col_11 = colour red 0.6 green 0.196078 blue 0.8
#declare col_12 = colour red 0.439216 green 0.576471 blue 0.858824
#declare col_13 = colour red 0.556863 green 0.137255 blue 0.137255
#declare col_14 = colour red 0.858824 green 0.858824 blue 0.439216
#declare col_15 = colour red 0.623529 green 0.623529 blue 0.372549

// Setup camera

camera {
    location  <4000, 4000, 3000>
    direction <0, 0, 2.0>
    look_at   <0, 1000, 0>
}

// Setup light sources

object { light_source { <5000, 8000, 5000> color White } }

// Select lbase object

#declare l_base = object { sphere { <0, 0.75, 0> 0.75 } }

// Textures for l_base object and leafs

#declare t_base = finish { ambient 0.3 diffuse 0.7 phong 1 }
#declare t_leaf = finish { ambient 0.3 diffuse 0.7 }

object {
        blob {
        threshold 0.5
#include "output.inc"
        sturm
        }
        finish { ambient 0.3 diffuse 0.7 phong 1 }
    pigment { color red 1 }
} 

Výsledkem renderování této scény je následující obrázek:

fractals57_5

Obrázek 5: Vykreslený model L-systému Fern složený z blobů

5. Více objektů složených z implicitních ploch

Ukážeme si ještě, jak vypadá 3D model složený z více implicitních ploch (blobů). Vytvoření několika bloků zajišťuje parametr -B. Pro otestování takto vytvořeného 3D modelu jsem místo gramatiky fern.ls použil gramatiku airhorse.ls (z toho důvodu, že v gramatice fern.ls nejsou použity příkazy pro tvorbu více objektů). Vytvoření zdrojových souborů pro POV-Ray zajistí příkaz:

./lparser -B -c airhorse 

Výsledkem práce Lparseru je sedm souborů nazvaných output0.incoutput7.inc, z nichž každý obsahuje jeden objekt složený z blobů (tj. celkem existuje osm koster implicitních ploch). Scéna určená pro rendering má tvar:

// --- L-System Parser/Mutator --- Lj Lapre ---
// use with output.inc generated by lparser -vc
// and change direction/zoom scale to get correct view

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

// Choose 16 colors

#declare col_0  = colour red 0.8 green 0.498039 blue 0.196078
#declare col_1  = colour red 0.5 green 0.5 blue 0.5
#declare col_2  = colour red 1.0
#declare col_3  = colour red 1.0 green 1.0
#declare col_4  = colour red 0.2 green 0.7 blue 0.1
#declare col_5  = colour blue 1.0 green 1.0
#declare col_6  = colour blue 1.0
#declare col_7  = colour red 1.0 blue 1.0
#declare col_8  = colour red 0.439216 green 0.858824 blue 0.576471
#declare col_9  = colour red 1.0 green 0.498039 blue 0.0
#declare col_10 = colour red 0.258824 green 0.258824 blue 0.435294
#declare col_11 = colour red 0.6 green 0.196078 blue 0.8
#declare col_12 = colour red 0.439216 green 0.576471 blue 0.858824
#declare col_13 = colour red 0.556863 green 0.137255 blue 0.137255
#declare col_14 = colour red 0.858824 green 0.858824 blue 0.439216
#declare col_15 = colour red 0.623529 green 0.623529 blue 0.372549

// Setup camera

camera {
    location  <80, 80, 50>
    direction <0, 0, 2.0>
    look_at   <0, 10, 0>
}

// Setup light sources

object { light_source { <5000, 8000, 5000> color White } }

// Select lbase object

#declare l_base = object { sphere { <0, 0.75, 0> 0.75 } }

// Textures for l_base object and leafs

#declare t_base = finish { ambient 0.3 diffuse 0.7 phong 1 }
#declare t_leaf = finish { ambient 0.3 diffuse 0.7 }

object {
        blob {
        threshold 0.5
#include "output0.inc"
        sturm
        }
        finish { ambient 0.3 diffuse 0.7 phong 1 }
    pigment { color col_0 }
}

object {
        blob {
        threshold 0.5
#include "output1.inc"
        sturm
        }
        finish { ambient 0.3 diffuse 0.7 phong 1 }
    pigment { color col_1 }
}

object {
        blob {
        threshold 0.5
#include "output2.inc"
        sturm
        }
        finish { ambient 0.3 diffuse 0.7 phong 1 }
    pigment { color col_2 }
}

object {
        blob {
        threshold 0.5
#include "output3.inc"
        sturm
        }
        finish { ambient 0.3 diffuse 0.7 phong 1 }
    pigment { color col_3 }
}

object {
        blob {
        threshold 0.5
#include "output4.inc"
        sturm
        }
        finish { ambient 0.3 diffuse 0.7 phong 1 }
    pigment { color col_4 }
}

object {
        blob {
        threshold 0.5
#include "output5.inc"
        sturm
        }
        finish { ambient 0.3 diffuse 0.7 phong 1 }
    pigment { color col_5 }
}

object {
        blob {
        threshold 0.5
#include "output6.inc"
        sturm
        }
        finish { ambient 0.3 diffuse 0.7 phong 1 }
    pigment { color col_6 }
}

object {
        blob {
        threshold 0.5
#include "output7.inc"
        sturm
        }
        finish { ambient 0.3 diffuse 0.7 phong 1 }
    pigment { color col_7 }
} 

Všimněte si použití osmi příkazů #include. Po renderingu v POV-Rayi by se měl vytvořit následující obrázek:

fractals57_6

Obrázek 6: Vykreslený model L-systému Airhorse složený z více objektů s bloby

6. Lparser2 verze 1.0

V předchozích kapitolách jsme si popisovali použití Lparseru1. Existuje ještě novější verze se jménem Lparser2, která se liší ve dvou oblastech: používá odlišný formát souborů s gramatikami a jediným výstupním formátem je VRML – Virtual Reality Modelling Language (ten budu popisovat v paralelně běžícím seriálu). Z tohoto důvodu je zobrazení výsledného modelu poněkud problematičtější, protože VRML se zdaleka neprosadil tak, jak mu bylo prorokováno a stále je tak trochu akademickým formátem. Jedno možné řešení však existuje – použití Blenderu. To si ukážeme v následující kapitole.

7. Zobrazení vytvořených modelů v Blenderu

Nejprve v Lparseru2 vytvoříme model uložený do VRML. To je velmi jednoduché, protože není zapotřebí používat žádné přepínače:

./lparser2 airhorse 

Pro vygenerování 3D modelu ve formátu VRML je možné použít i Lparser1, zde je však nutné specifikovat typ výstupního formátu pomocí volby -V:

./lparser -V airhorse 

Výsledkem je v každém případě soubor output.wrl, který je možné dále zpracovat (minimálně zobrazit) v Blenderu následujícím způsobem:

  1. Spuštění Blenderu s prázdným projektem
  2. Import souboru output.wrl do Blenderu pomocí voleb: File->Import->VRML 1.0 (viz obrázek číslo 7)
  3. Nastavení kamery/pozorovatele (viz obrázek číslo 8). Možné jsou i další úpravy modelu, například nanesení textur či přidání dalších světel, podlahy apod.
  4. Nastavení rendereru a provedení vykreslení (viz obrázek číslo 9)

fractals57_7

Obrázek 7: Import modelu do aplikace Blender

fractals57_8

Obrázek 8: Nastavení kamery (pozorovatele) v Blenderu

fractals57_9

Obrázek 9: Finální rendering pomocí vestavěného rendereru

root_podpora

8. Odkazy na další informační zdroje

  1. Publikace Biological Modeling and Visualization research group (University of Calgary):
    http://algorit­hmicbotany.or­g/papers/
  2. Stránka programu Lparser:
    http://home.wa­nadoo.nl/lauren­s.lapre/lparser­.html
  3. Galerie modelů vytvořených v Lparseru:
    http://home.wa­nadoo.nl/lauren­s.lapre/lparser2­.html
  4. Charlie Chernohorsky :-) L-systémy ve FractIntu:
    http://fractin­t.oblivion.cz/
  5. Hill, F. S. jr.: „Computer Graphics using OpenGL“,
    Prentice Hall, 2001
  6. Prusinkiewicz Przemyslaw and Hanan James: „Lindenmayer Systems, Fractals, and Plants“,
    Springer-Verlag, New York, 1989.
  7. Prusinkiewicz Przemyslaw and Lindenmayer Aristid: „The Algorithmic Beauty of Plants“,
    Springer-Verlag, NY, 1990. ISBN 0–387–97297–8
    http://algorit­hmicbotany.or­g/papers/abop/a­bop.lowquality­.pdf
  8. Weber J., Penn J.: „Creation and Rendering of Realistic Trees“,
    Proceedings of SIGGRAPH '95, volume 22(4), ACM SIGGRAPH, New York, 1995

9. Obsah dalšího pokračování tohoto seriálu

V následujícím pokračování tohoto seriálu si podrobněji popíšeme gramatiky použité v programu Lparser. Také si ukážeme demonstrační aplikaci pro zobrazení výsledných 3D modelů a jednoduchou tvorbu animací.

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.