Hlavní navigace

Tvorba 2D a 3D modelů pomocí Lparseru

5. 12. 2006
Doba čtení: 11 minut

Sdílet

V dnešní části seriálu pojednávajícího o fraktálech používaných nejenom v počítačové grafice se budeme zabývat použitím programu Lparser při tvorbě modelů zadaných pomocí přepisovacích gramatik. Ukážeme si způsob vykreslování takzvaných "větví" a "listů", použití rekurze, zásobníku a dalších prostředků, které Lparser nabízí.

Obsah

1. Zápis přepisovacích gramatik v souborech .ls
2. Příkazy želví grafiky implementované v Lparseru1
   2.1 Příkazy ovlivňující orientaci želvy
   2.2 Speciální příkazy ovlivňující orientaci želvy
   2.3 Příkazy pro posun želvy s případným kreslením
   2.4 Práce se zásobníkem a „listy“
   2.5 Ovlivnění stavových proměnných želvy
   2.6 Další příkazy
3. Nastavení axiomu pro jednodušší tvorbu 2D modelů
4. Vytvoření gramatik jednoduchých 2D modelů
5. Tvorba „větví“
6. Tvorba „listů“
7. Fraktální struktury vytvořené v ploše
8. Obsah dalšího pokračování tohoto seriálu

1. Zápis přepisovacích gramatik v souborech .ls

V předchozí části tohoto seriálu jsme si zevrubně popsali program L-System Parser/Mutator (zkráceně pojmenovaný pouze jako Lparser), včetně zdůraznění největších rozdílů mezi jeho první a druhou verzí. V dnešní části si na praktických příkladech přepisovacích gramatik ukážeme použití Lparseru verze 1 při tvorbě plošných (2D) modelů. Volba první verze není v žádném případě náhodná – pro tuto verzi totiž existuje zdrojový kód, takže je možné Lparser přeložit a spustit na prakticky jakékoli 32 či 64bitové platformě vybavené překladačem programovacího jazyka ANSI C. Pro připomenutí dodám, že zdrojový kód Lparseru1, příklady gramatik z původní DOSovské verze a další materiál je možné získat na adrese http://home.wa­nadoo.nl/lauren­s.lapre/lparser­.html.

Lparser verze 1 předpokládá, že přepisovací gramatiky modelů jsou uloženy v textových souborech s koncovkou „.ls“. V těchto souborech se kromě vlastních přepisovacích pravidel nachází také zápis axiomu (řetězce, který se v jednotlivých iteracích přepisuje), specifikace maximálního počtu iterací, implicitní úhel, o který se otáčí želva při provádění některých příkazů a počáteční tloušťka „větví“, které želva při svém pohybu kreslí. V souborech „.ls“ se mohou nacházet i poznámky, které začínají znakem „#“ a končí znakem či dvojicí znaků značících konec řádku (z tohoto důvodu by neměl být problém s přenosem „.ls“ souborů mezi Microsoftími operačními systémy a jejich unixovými protějšky). Poznámky se mohou vyskytovat kdekoli, tj. i za číselnými údaji popsanými v dalším odstavci.

Na prvních třech významných řádcích (tj. řádcích, které neobsahují pouze bílé znaky a/nebo poznámku) se nachází tři důležité číselné údaje. Prvním údajem je maximální počet prováděných iterací (hloubka rekurze), druhým údajem implicitní úhel otáčení želvy a konečně údajem třetím počáteční tloušťka větví. Větve odpovídají úsečkám, které jsme kreslili v případě plošných modelů. Na čtvrtém významovém řádku je zapsán axiom (přepisovaný řetězec) a na řádcích ležících za ním již jednotlivá přepisovací pravidla, která mají tvar symbol=řetězec. Celý soubor by měl být ukončen řádkem, který obsahuje jediný znak „@“. Tento znak zápis celého objektu ukončuje. Výše uvedené informace se vztahují k první verzi Lparseru, verze druhá přidává do souboru klíčová slova (axiom, rule, thickness) a z tohoto důvodu nepoužívá ukončující znak.

Následuje příklad zápisu 3D modelu pomocí přepisovacích gramatik. V původní DOSové verzi je L-systém tohoto 3D modelu uložen v souboru bop01.ls

# --- L-System Parser/Mutator --- Lj Lapre ----------------------------------
5       # recursion depth
18      # angle
50      # thickness as % of length
p
p=i++[p+o]--->>[--l]i[++l]--[po]+++po
i=Fs[>>&&l][>>^^l]Fs
s=sFs
l=[c{++f--ff--f++|++f--ff--f}]
o=[&!ce>w>>>>w>>>>w>>>>w>>>>w]
e=FF
w=[c^!F][cc&&&&{---f+++f|---f+++f}]
@ 

Pomocí výše uvedeného souboru je možné vygenerovat zajímavě vypadající trojrozměrný model:

fractals58_1

Obrázek 1: Trojrozměrný model specifikovaný v souboru „bop01.ls“ vytvořený pomocí blobů (metaballs)

fractals58_2

Obrázek 2: Trojrozměrný model specifikovaný v souboru „bop01.ls“ vytvořený pomocí trojúhelníků

2. Příkazy želví grafiky implementované v Lparseru1

Lparser používá v přepisovacích gramatikách pouze jednopísmenné příkazy ovládající želvu či měnící její stav (tloušťku kreslené stopy, barvu stopy aj.). Omezení na pouze jedno písmeno má svůj praktický význam, neboť se tím celé zpracování urychlí, což je patrné zejména u modelů používajících složitá přepisovací pravidla. V tabulkách uvedených v následujících podkapitolách jsou vypsány všechny symboly, které Lparser rozpoznává, ostatní zde neuvedené symboly je možné použít pro pojmenování pravidel. Přesný význam jednotlivých symbolů bude popsán v dalších kapitolách a některé z nich až v navazující části tohoto seriálu.

2.1 Příkazy ovlivňující orientaci želvy

Želva se může v prostoru otáčet okolo trojice vektorů, které tvoří její souřadný systém. Tyto vektory jsou zobrazené na třetím obrázku. Pomocí dále uvedených příkazů je možné otáčení želvy okolo zadané osy spustit. Úhel α, který je v tabulce zmíněn, je zadán přímo v souboru „.ls“ jako jeden z globálních parametrů.

fractals58_3

Obrázek 3: Trojice vektorů tvořících souřadný systém želvy
Symbol Příkaz Úhel
+ turn left RU(α)
+(x) turn left RU(x)
- turn right RU(-α)
-(x) turn right RU(-x)
& pitch down RL(α)
&(x) pitch down RL(x)
^ pitch up RL(-α)
^(x) pitch up RL(-x)
< roll left RH(α)
<(x) roll left RH(x)
> roll right RH(-α)
>(x) roll right RH(-x)

2.2 Speciální příkazy ovlivňující orientaci želvy

Následující příkazy také ovlivňují orientaci želvy. Některé slouží k jejímu otočení o 180° (π), pokaždé však okolo jiného vektoru. Další příkazy slouží k narovnání želvy do vodorovné polohy, otočení o náhodný úhel nebo pro takzvanou korekci gravitace, tj. změnu otočení želvy směrem dolů nezávisle na tom, kde se želva nachází a jakou má orientaci.

Symbol Příkaz
| turn around (o π = 180°)
% roll around (o π = 180°)
$ roll until horizontal
~ turn/pitch/roll in a random direction
~(x) turn/pitch/roll in a random direction (max. x)
t correction for gravity with 0.2
t(x) correction for gravity with x

2.3 Příkazy pro posun želvy s případným kreslením

Příkazy z této kategorie slouží k přesunu želvy ve směru její orientace, přesněji řečeno ve směru vektoru Forward (F). Želva přitom může během posunu vykreslovat dva typy entit: „větve“ a/nebo „listy“ (buď současně nebo každý zvlášť). Některé příkazy želvu přesunou bez nakreslení větve, jiné naopak vykreslení provádí. Poněkud speciální je v této skupině příkaz „.“, při jehož interpretaci se želva neposune, pouze se zapíše její pozice do seznamu vrcholů (vertexů). Detaily vykreslování „větví“ a „listů“ budou vysvětleny v následujících kapitolách.

Symbol Příkaz
F move forward and draw full length
F(x) move x forward and draw
Z move forward and draw half length
Z(x) move x forward and draw
f move forward with full length, record vertex
f(x) move x forward, record vertex
z move forward with half length, record vertex
z(x) move x forward, record vertex
g move forward with full length
g(x) move x forward
. don't move, record vertex

2.4 Práce se zásobníkem a „listy“

V tabulce uvedené v této podkapitole jsou vypsány dvě skupiny příkazů. První skupina příkazů slouží pro ukládání stavu želvy na zásobník (stack) a následné zpětné načítání stavu želvy ze zásobníku. Tyto příkazy mají obdobný význam jako v případě dříve popisovaných 2D L-systémů, ovšem s tím rozdílem, že stavový vektor želvy je v případě 3D L-systémů delší, tj. obsahuje větší počet stavových proměnných. Druhá skupina příkazů slouží k zahájení a ukončení záznamu vrcholů (vertexů), ze kterých se posléze vytváří „listy“, tj. plošné entity.

Symbol Příkaz
[ push current state
] pop current state
{ start polygon shape
} end polygon shape

2.5 Ovlivnění stavových proměnných želvy

Příkazy uvedené v této podkapitole slouží k ovlivnění obsahu interních proměnných, které společně tvoří stavový vektor želvy. Ten je, jak jsme si již řekli v předchozích částech tohoto seriálu, tvořen skupinou proměnných plně popisujících želvu nacházející se v prostoru. Mezi stavové proměnné patří například proměnná popisující tloušťku „větví“ vytvářených při pohybu želvy, úhel, o který se želva natáčí okolo svého souřadného systému tvořeného vektory Forward (F), Up (U) a Left (L) a také o délku kroku želvy, která přímo ovlivňuje délku vytvářených větví (viz příkazy z předchozích podkapitol).

Symbol Příkaz
" increment length with 1.1
' decrement length with 0.9
"(x) multiply length with x
'(x) multiply length with x
; increment angle with 1.1
: decrement angle with 0.9
:(x) multiply angle with x
;(x) multiply angle with x
? increment thickness with 1.4
! decrement thickness with 0.7
?(x) multiply thickness with x
!(x) multiply thickness with x

2.6 Další příkazy

Do poslední skupiny příkazů jsou zařazeny příkazy používané pro změnu barvy vykreslovaných větví a listů – tyto barvy jsou použity například při vykreslování modelů pomocí programu POV-Ray nebo při exportu vytvořeného modelu do souborů typu VRML. Dále je v této skupině uveden příkaz, který znovunastaví stavové proměnné želvy na hodnoty specifikované ve vstupním souboru „.ls“ (reset). Poslední příkaz z této skupiny již známe: jedná se o zavináč (@), který ukončuje definici celého objektu. Po výskytu tohoto znaku se generování objektu pomocí želví grafiky zastaví.

Symbol Příkaz
c increment color index
c(x) set color index to x
* reset color, thickness, length and angle
@ end of object

3. Nastavení axiomu pro jednodušší tvorbu 2D modelů

Vzhledem k tomu, že se v dnešní části seriálu zabýváme pouze tvorbou 2D, tj. plošných modelů, ukážeme si, jakým způsobem se nastaví axiom (přepisovací řetězec) tak, aby se želva pohybovala v ploše x-y. Lparser při inicializaci nastaví želvu do takové pozice, aby byla umístěna v počátku [0, 0, 0], vektor Forward směřoval ve směru růstu osy z a vektor Left ve směru osy y (vektor Up není problém dopočítat pomocí vektorového součinu s využitím zbývajících dvou vektorů). Pomocí příkazů &(90) a +(90) můžeme želvu natočit do roviny x-y tak, jak jsme zvyklí z 2D L-systémů. Proto také každý axiom, který si dnes ukážeme, bude začínat následujícím řetězcem:

&(90)+(90) 

4. Vytvoření gramatik jednoduchých 2D modelů

S pomocí želví grafiky je možné v Lparseru vytvářet dva typy objektů. Podle tvaru a funkce budeme v dalším textu tyto objekty nazývat „větve“ a „listy“. Mezi větvemi a listy existuje jeden podstatný rozdíl: větve jsou tvořeny relativně úzkými a dlouhými objekty (podle způsobu konstrukce modelu například válcem či čtveřicí úzkých obdélníků) a želva tyto objekty generuje při svém pohybu v prostoru. Počáteční bod větve leží v místě počátku pohybu želvy, koncový bod pak v místě, kde želva svůj pohyb ukončí.

Listy jsou naproti tomu tvořeny plošnými polygony, jejichž vrcholy určuje želva pokládáním „značek“ při svém pohybu. Položení značky je nutné specifikovat pomocí speciálního příkazu, který buď kombinuje tvorbu značky s pohybem želvy, nebo značku nastaví na aktuální poloze želvy. Počet vrcholů polygonů není omezen, většinou se však při exportu modelu polygon rozpadá na trojúhelníky, u nichž je ve všech případech zaručeno, že tvoří rovinný útvar. V páté kapitole si na jednoduchých L-systémech ukážeme tvorbu modelů sestavených z větví, v kapitole šesté do vytvářených modelů přidáme i listy.

5. Tvorba „větví“

V předchozí kapitole jsme si řekli, že struktury typu „větve“ jsou generovány přímo při pohybu želvy. Podobně jako u 2D L-systémů, i zde je možné použít příkaz F, který želvu instruuje k posunu ve směru jejího vektoru Forward spolu s vytvořením větve vedoucí od počátečního do koncového bodu cesty želvy. Vše si ukážeme na jednoduchém demonstračním příkladu, který vykreslí čtverec pomocí čtyř příkazů F (posun dopředu) a třech příkazů + (otočení želvy okolo vektoru Up). Úhel otočení je nastavený na 90°, počet iterací na 1. V tomto případě však počet iterací nehraje vůbec žádnou roli, protože se v přepisovacích pravidlech nevyskytuje rekurze:

# demonstracni L-system cislo 1
# Vykresleni ctverce pouze pomoci vetvi
1                # hloubka rekurze
90               # implicitni uhel natoceni zelvy
10               # tloustka vetvi
&(90)+(90)X      # axiom (natoceni zelvy a leva strana pravidla)
X=F+F+F+F        # jedine prepisovaci pravidlo
@                # konec specifikace objektu 

fractals58_4

Obrázek 4: Čtverec vytvořený prvním demonstračním L-systémem

6. Tvorba „listů“

Na rozdíl od „větví“ nejsou „listy“ vytvářeny přímo při pohybu želvy, tj. nekopírují dráhu jejího pohybu, ale jejich tvorba nastává až v následujícím kroku zpracování 2D či 3D modelu. Želva při svém pohybu může do prostoru pomocí několika příkazů klást značky, které určují polohy jednotlivých vrcholů (vertexů) tvořících krajní body polygonů, ze kterých se listy skládají. Lparser automaticky z těchto značek požadované plošky vytvoří a popř. i provede rozpad plošek do jednotlivých trojúhelníků (takzvaná teselace). Začátek a konec plošky je v přepisovacích pravidlech reprezentován příkazy „{“ a „}“, místo příkazů „F“ jsou použity příkazy „f“, které želvu posunují bez kreslení větví, ovšem se zaznamenáním vrcholu listu. Vše si opět můžeme ukázat na příkladu, který vykreslí čtverec, tentokrát však složený ze čtvercového listu

# demonstracni L-system cislo 2
# Vykresleni ctverce pouze pomoci listu
1                # hloubka rekurze
90               # implicitni uhel natoceni zelvy
10               # tloustka vetvi (nema vyznam)
&(90)+(90)X      # axiom (natoceni zelvy a leva strana pravidla)
X={f+f+f+f}      # jedine prepisovaci pravidlo
@                # konec specifikace objektu 

fractals58_5

Obrázek 5: Čtverec vytvořený druhým demonstračním L-systémem

Kombinace větví a listů je ukázána na třetím demonstračním příkladu. Všimněte si použití složených závorek (tvorba listů) a příkazů „F“ (kreslení větví) spolu s příkazem „.“ (záznam vertexu).

# demonstracni L-system cislo 3
# Vykresleni ctverce pouze pomoci vetvi i listu
1                # hloubka rekurze
90               # implicitni uhel natoceni zelvy
10               # tloustka vetvi
&(90)+(90)X      # axiom
X={F.+F.+F.+F.}  # jedine prepisovaci pravidlo
@                # konec specifikace objektu 

fractals58_6

Obrázek 6: Čtverec vytvořený třetím demonstračním L-systémem

7. Fraktální struktury vytvořené v ploše

Na tvorbě fraktálních struktur Lparserem není nic záhadného. Podobně jako u klasických 2D L-systémů, i zde se využije rekurze v přepisovacích gramatikách, kdy se na pravé straně nějakého přepisovacího pravidla objeví levá strana jiného či stejného pravidla. Ukážeme si použití rekurze na klasickém příkladu: křivce Helge von Kocha.

# demonstracni L-system cislo 4
# Vykresleni krivky Helge von Kocha
4                # hloubka rekurze
60               # implicitni uhel natoceni zelvy
20               # tloustka vetvi
&(90)+(90)F--F--F# axiom
F=F+F--F+F       # jedine prepisovaci pravidlo
@                # konec specifikace objektu 

fractals58_7

Obrázek 7: Křivka Helge von Kocha

Další příklad slouží k vykreslení Sierpinského křivky:

# demonstracni L-system cislo 5
# Vykresleni Sierpinskeho krivky
5                # hloubka rekurze
60               # implicitni uhel natoceni zelvy
30               # tloustka vetvi
&(90)+(90)YF     # axiom
X=YF+XF+Y
Y=XF-YF-X
@                # konec specifikace objektu 

fractals58_8

Obrázek 8: Sierpinského křivka

S využitím zásobníku je možné vytvářet mnohem složitější objekty, například následující kruhovou mozaiku:

# demonstracni L-system cislo 6
# Vykresleni kruhove mozaiky
3                # hloubka rekurze
15               # uhel natoceni zelvy
20               # tloustka vetvi
&(90)+(90)X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X
X=[F+F+F+F[---X-Y]+++++F++++++++F-F-F-F]
Y=[F+F+F+F[---Y]+++++F++++++++F-F-F-F]
@                # konec specifikace objektu 

fractals58_9

Obrázek 9: Obrázek kruhové mozaiky

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

V následujícím pokračování seriálu o fraktálech se již budeme věnovat té nejdůležitější funkcionalitě Lparseru. Ukážeme si tvorbu trojrozměrných modelů, od těch nejjednodušších (obdoba binárního stromu) až po velmi složité modely obsahující stovky tisíc polygonů. Také si řekneme, jakým způsobem je možné vytvářené modely při jejich generování nechat „zmutovat“.

ikonka

Zajímá vás toto téma? Chcete se o něm dozvědět víc?

Objednejte si upozornění na nově vydané články do vašeho mailu. Žádný článek vám tak neuteče.

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.