Skriptovanie v Pythone#

Režim skriptovania v jazyku Python ponúka plne programovateľné štýly čiar. V tomto režime ovládania sa všetky operácie štylizácie zapisujú ako skripty jazyka Python, ktoré sa v terminológii Voľného štýlu označujú ako moduly štýlov. Vstupom modulu štýlu je mapa zobrazenia (t. j. súbor zistených hrán prvkov) a výstupom je súbor štylizovaných ťahov.

Modul štýlu sa skladá z postupných volaní piatich základných operátorov: výber, reťazenie, rozdelenie, triedenie a vytváranie ťahov. Operátor výberu identifikuje podsústavu hrán vstupných prvkov na základe jednej alebo viacerých užívateľom definovaných podmienok výberu (tvrdení). Vybrané hrany sa spracúvajú operátormi reťazenia, rozdelenia a triedenia na vytvorenie reťazcov hrany prvkov. Tieto operátory sú tiež riadené tvrdeniami a funkciami zadanými užívateľom s cieľom určiť, ako transformovať hrany prvkov do reťazcov. Nakoniec sa reťazce transformujú na štylizované ťahy operátorom na vytváranie ťahov, ktorý prijíma zoznam užívateľom definovaných tieňov ťahov.

Moduly štýlu Python sú uložené v blend súboroch ako textové bloky údajov. Externé súbory štýlových modulov je potrebné najprv načítať v textovom editore. Potom ponuka výberu v rámci položky zásobníka modulov štýlov umožňuje vybrať modul zo zoznamu načítaných modulov štýlov.

../../_images/render_freestyle_python_scripting-mode.png

Snímka obrazovky modulu štýlu cartoon.py načítaného v textovom editore (vľavo), ako aj možností Voľného štýlu v režime Skriptovanie jazyka Python na tlačidlách Vrstva zobrazenia (vpravo).#

Voľný štýl pre Blender sa dodáva s množstvom modulov štýlov Python, ktoré môžu slúžiť ako východiskový bod pre písanie vlastných modulov štýlov. Pozrite si tiež časť Voľný štýl Python API v referenčnej príručke Blender Python API, kde nájdete všetky podrobnosti o konštrukciách modulov štýlov.

../../_images/render_freestyle_python_scripting-mode-example-1.jpg

By T.K. using the Python Scripting mode (blend-file, CC0).#

../../_images/render_freestyle_python_scripting-mode-example-2.png

By T.K. using the Python Scripting mode (blend-file, CC0).#

Písanie Modulov štýlu#

Modul štýlu je časť kódu zodpovedná za štylizáciu kreslenia čiar vo Voľnom štýle. Vstupom modulu štýlu je sústava hrán prvkov nazývaná Mapa zobrazenia (ViewMap). Výstupom je súbor štylizovaných čiar označovaných aj ako ťahy. Modul štýlu je štruktúrovaný ako postupnosť operácií, ktoré umožňujú vytvárať ťahy zo vstupných hrán v rámci mapy zobrazenia.

Existuje päť druhov operácií (uvedené s príslušnými funkciami operátora):

  • Výber Operators.select()

  • Reťazenie Operators.chain(), Operators.bidirectional_chain()

  • Rozdelenie Operators.sequential_split(), Operators.recursive_split()

  • Triedenie Operators.sort()`

  • Vytvorenie ťahu Operators.create()

Mapa vstupného zobrazenia je naplnená súborom objektov Zobrazených hrán (ViewEdge). Operácia výberu sa používa na výber objektov Zobrazených hrán, ktoré umelcov zaujímajú, na základe užívateľom definovaných podmienok výberu (tvrdení). Operácie reťazenia vyberú podsústavu Zobrazených hrán a vytvoria reťazce spojením Zobrazených hrán podľa užívateľom definovaných tvrdení a funkcií. Reťazce možno ďalej spresniť ich rozdelením na menšie časti (napr. v miestach, kde hrany robia ostrú zákrutu) a výberom ich časti (napr. ponechať len tie, ktoré sú dlhšie ako prahová dĺžka). Operácia triedenia sa používa na usporiadanie poradia ukladania reťazcov, aby sa nakreslila jedna čiara na druhú. Reťazce sa nakoniec transformujú na štylizované ťahy operáciou vytvárania ťahov, ktorá na jednotlivé reťazce aplikuje sériu ťahových tieňov.

Zobrazené hrany, Reťaze a Ťahy sa všeobecne označujú ako jednorozmerné (1D) prvky. 1D prvok je polygónová čiara, ktorá je sériou spojených priamok. Vrcholy 1D prvkov sa vo všeobecnosti nazývajú 0D prvky.

Všetky operátory pôsobia na sústavu aktívnych 1D prvkov. Počiatočná aktívna sústava je sústava Zobrazených hrán na vstupnej mape zobrazenia. Aktívna sústava sa aktualizuje operátormi.

Výber#

Operátor výberu prechádza cez všetky prvky aktívnej sústavy a ponecháva iba tie, ktoré vyhovujú určitému tvrdeniu. Metóda Operators.select () berie ako argument jednočlenné tvrdenie, ktoré funguje na akomkoľvek Interface1D, ktorý predstavuje 1D prvok. Napríklad:

Operators.select(QuantitativeInvisibilityUP1D(0))

Táto výberová operácia používa tvrdenie QuantitativeInvisibilityUP1D na výber iba viditeľných ViewEdge (presnejšie tých, ktorých kvantitatívna neviditeľnosť sa rovná 0). Operátor výberu je určený na selektívne použitie štýlu na zlomok aktívnych 1D prvkov.

Je potrebné poznamenať, že QuantitativeInvisibilityUP1D je trieda implementujúca tvrdenie, ktoré testuje viditeľnosť čiar a metóda Operators.select() prijíma ako argument inštanciu triedy tvrdení. Testovanie tvrdenia pre daný prvok 1D sa vlastne vykonáva volaním inštancie tvrdenia, teda volaním metódy __call__ triedy tvrdenia. Inými slovami, metóda Operators.select() prijíma ako argument funktora (funkčné slovo), ktorý zase prijíma ako argument objekt Interface0D. Rozhranie API Freestyle Python využíva funktory vo veľkej miere na implementáciu tvrdení, ako aj funkcií.

Reťazenie#

Operátory reťazenia pôsobia na sústavu aktívnych objektov ViewEdge a určujú topológiu budúcich ťahov. Myšlienkou je implementovať opakovač na prechádzanie grafu Mapy zobrazenia pochodovaním pozdĺž Zobrazených hrán. Opakovač definuje pravidlo reťazenia, ktoré určuje ďalšiu ViewEdge, ktorá sa má sledovať v danom vrchole (pozri ViewEdgeIterator). Niekoľko takýchto opakovačov je k dispozícii ako súčasť Voľného štýlu API Python (pozri ChainPredicateIterator a ChainSilhouetteIterator). Vlastné opakovače možno definovať zdedením triedy ViewEdgeIterator. Operátor reťazenia tiež prijíma ako argument UnaryPredicate (jednočlenné tvrdenie) pracujúci na Interface1D ako zastavovacie kritérium. Reťazenie sa zastaví, keď opakovač počas pochodu pozdĺž grafu dosiahne ViewEdge vyhovujúci tomuto tvrdeniu.

Reťazenie môže byť jednosmerné Operators.chain() alebo obojsmerné Operators.bidirectional_chain(). V druhom prípade sa reťazenie šíri v oboch smeroch od počiatočnej hrany.

Nasleduje príklad kódu obojsmerného reťazenia:

Operators.bidirectional_chain(
        ChainSilhouetteIterator(),
        NotUP1D(QuantitativeInvisibilityUP1D(0)),
        )

Operátor reťazenia používa ChainSilhouetteIterator ako pravidlo reťazenia a zastaví reťazenie, len čo opakovač príde k neviditeľnému ViewEdge.

Operátory reťazenia spracúvajú sústavu aktívnych objektov ViewEdge v poradí. Aktívne objekty ViewEdge (Zobrazená hrana) možno predtým zoradiť pomocou metódy Operators.sort() (pozri nižšie). Reťazenie sa začína prvým objektom ViewEdge z aktívnej množiny. Všetky ViewEdge, ktoré už boli zapojené do procesu reťazenia, sú označené (v prípade vyššie uvedeného príkladu je časová značka každého ViewEdge štandardne zmenená), aby sa ten istý ViewEdge nespracoval dvakrát. Keď reťazenie dosiahne ViewEdge, ktorý spĺňa predikát zastavenia, reťazenie sa ukončí. Potom sa spustí nový reťazec od prvého neoznačeného ViewEdge v aktívnej sústave. Táto operácia sa opakuje, kým sa nespracuje posledný neoznačený ViewEdge z aktívnej sústavy. Na konci operácie reťazenia sa aktívna sústava nastaví na reťazce, ktoré boli práve vytvorené.

Rozdelenie#

Operácia rozdelenia sa používa na spresnenie topológie každého reťazca. Rozdelenie sa vykonáva buď postupne, alebo rekurzívne. Sekvenčné rozdelenie Operators.sequentialSplit() vo svojej základnej forme analyzuje Reťazec v danom ľubovoľnom rozlíšení a vyhodnocuje jednočlenné tvrdenie (pracuje s prvkami 0D) v každom bode pozdĺž Reťazca. Vždy, keď je predikát splnený, reťazec sa rozdelí na dva reťazce. Na konci operácie postupného rozdelenia sa aktívna sústava reťazcov nastaví na nové reťazce

Operators.sequentialSplit(TrueUP0D(), 2)

V tomto príklade je reťaz rozdelená každé 2 jednotky. Rozvinutejšia verzia používa dva tvrdenia namiesto jedného: Jeden na určenie počiatočného bodu nového reťazca a druhý na určenie jeho koncového bodu. Táto druhá verzia môže viesť k sústave reťazcov, ktoré sú nespojité alebo ktoré sa prekrývajú, ak sú tieto dva tvrdenia rôzne (viac informácií nájdete v časti Operators.sequentialSplit()).

Rekurzívne rozdelenie Operators.recursiveSplit()` vyhodnotí funkciu na prvkoch 0D pozdĺž reťazca s daným rozlíšením a nájde bod, ktorý dáva maximálnu hodnotu funkcie. Reťazec sa potom v tomto bode rozdelí na dve časti. Tento proces sa rekurzívne opakuje na každom z dvoch nových reťazcov, kým vstupný reťazec nespĺňa užívateľom zadanú podmienku zastavenia

func = Curvature2DAngleF0D()
Operators.recursive_split(func, NotUP1D(HigherLengthUP1D(5)), 5)

V uvedenom príklade kódu sa reťazce rekurzívne rozdelia v bodoch s najväčším 2D zakrivením. Zakrivenie sa vyhodnocuje v bodoch pozdĺž reťazca s rozlíšením 5 jednotiek. Reťazce kratšie ako 5 jednotiek sa už nerozdelia.

Zoradenie#

Operátor triedenia Operators.sort() usporiada poradie aktívnych 1D prvkov. Ako argument prijíma binárne tvrdenie, ktoré sa používa ako operátor „menšie ako“ na zoradenie dvoch 1D prvkov.

Operators.sort(Length2DBP1D())

V tomto príklade kódu triedenie používa binárny predikát Length2DBP1D na zoradenie objektov Interface1D vzostupne podľa dĺžky 2D.

Triedenie je obzvlášť užitočné v kombinácii s hustotou príčin. Hustota príčin totiž vyhodnocuje hustotu výsledného obrazu pri jeho úprave. Ak chceme takýto nástroj použiť na rozhodovanie o odstránení ťahov vždy, keď je lokálna hustota príliš vysoká, je dôležité kontrolovať poradie, v akom sa ťahy kreslia. V tomto prípade by sme použili operátor triedenia, aby sme zabezpečili, že sa najprv nakreslia „najdôležitejšie“ čiary.

Vytvorenie ťahu#

Nakoniec operátor vytvárania ťahu Operators.create()` berie ako vstup aktívnu sústavu reťazcov a vytvára ťahy. Operátor prijíma dva argumenty. Prvým je jednočlenné tvrdenie, ktoré pracuje na Interface1D, ktorý je určený na vykonanie posledného výberu na sústave reťazcov. Reťazec, ktorý nespĺňa podmienku, nepovedie k vytvoreniu ťahu. Druhým vstupom je zoznam tieňovačov, ktoré budú zodpovedné za tieňovanie každého vytvoreného ťahu

shaders_list = [
    SamplingShader(5.0),
    ConstantThicknessShader(2),
    ConstantColorShader(0.2,0.2,0.2,1),
    ]
Operators.create(DensityUP1D(8,0.1, IntegrationType.MEAN), shaders_list)

V tomto príklade sa tvrdenie DensityUP1D použije na odstránenie všetkých reťazcov, ktorých priemerná hustota je vyššia ako 0,1. Každý reťazec sa transformuje na ťah tak, že sa opätovne zosníma tak, aby mal bod každých 5 jednotiek, a priradí sa mu konštantná hrúbka 2 jednotky a tmavosivá konštantná farba.

Kontrola užívateľa nad definíciou potrubia#

Písanie modulov štýlov ponúka rôzne typy ovládania užívateľom, aj keď jednotlivé moduly štýlov majú pevnú štruktúru potrubia. Jedným z nich je postupnosť rôznych riadiacich štruktúr potrubia a ďalším je definovanie objektov funktorov, ktoré sa odovzdávajú ako argument v celého potrubia.

Rôzne štruktúry riadenia potrubia možno definovať postupnosťou operácií výberu, reťazenia, rozdelenia a triedenia. Vytvorenie ťahu je vždy poslednou operáciou, ktorá uzatvára modul štýlu.

Tvrdenia, funkcie, reťazové opakovače a tieňovače ťahov možno definovať dedením základných tried a prepisovaním príslušných metód. Ďalšie informácie o užívateľsky skriptovateľných konštrukciách nájdete v referenčných manuáloch týchto základných tried.

Viď aj

Tvrdenia, funkcie, reťazové opakovače a tieňovače ťahov možno definovať dedením základných tried a prepisovaním príslušných metód. Pre viac informácií o užívateľsky skriptovateľných konštrukciách si pozrite časť Modul Python Voľného štýlu.