From BlenderWiki

Jump to: navigation, search
Blender3D FreeTip.gif
IMPORTANT! Do not update this page!
We have moved the Blender User Manual to a new location. Please do not update this page, as it will be locked soon.

Modalità Python Scripting

La modalità Python Scripting offre piena programmabilità per la styling della linea. In questa modalità di controllo,tutte le operazioni di styling sono scritte come scripts di Python riportati come moduli di stile nella terminologia di Freestyle. L'input di un modulo di stile è una viewmap (esempio,un set di modalità bordi ), e l'output è un set di tratti stylizzati.

Un modulo di stile è composto chiamate in sequenza di 5 operatori di base : selection(selezione), chaining(concatenamento), splitting(Scissione), sorting(Ordinamento) e stroke creation(Creazione tratto).Gli operatori di selezione identificano un subset di modalità di input bordi basato su uno o piu condizione di selezione definita dall'utente(predicati).I bordi selezionati vengono processati con gli operatori chaining(concatenamento), splitting(Scissione), sorting(Ordinamento) per costruire catene o modalità dei bordi. Questi operatori possono anche essere controllati dai predicati e le funzioni fornite dall'utente in ordine per determinare come le modalità di trasformazione delle modalità dei bordi nel concatenamento.In fine, la catena viene trasformata nel tratto stylizzato dal operatore di creazione del tratto,il quale prende una lista di shaders di tratti definbiti dall'utente.

I moduli di Python style sono immagazzinati all' interno dei files .blend come un text datablocks.Moduli esterni di stilehanno in primo luogo bisogno di essere caricate nella finestra del Text Editor .Quindi il menu a discesa all'interno Then the pull-down menu within un'ingresso di moduli a stack di stile che vi permetterà di selezionare un modulo dalla lista di stile caricati.

A Lo screen capture di un modulo di stile (cartoon.py)caricato nella finestra Text Editor (Sinistra), così come le opzioni Freestyle in modalità Python Scripting nel pannello Render Layers buttons (Destra)

Freestyle per Blender è dotato di una serie di moduli Python per lo style che possono servire come punto di partenza della propria scrittura dei moduli di style. Vedi anche la sezione delle Freestyle Python API nel manuale di Blender Python API di riferimento per informazioni dettagliate e complete di costrutti dei moduli per lo style.

By T.K. Usando la modalità di Python Scripting (File:Turning Pages.zip, CC0)
By T.K. usando la modalità Python Scripting (File:Lily Broken Topology.zip, CC0)

Scrivere moduli di Stile

Un modulo stile è un pezzo di codice responsabile per la stilizzazione della Freestyle linea di disegno. L'ingresso di un modulo stile è un set di funzionalità dei bordi chiamata view map (ViewMap). L'uscita è un insieme di linee stilizzate detto anche tratto. Un modulo stile è strutturato come una catena di operazioni che consentono di costruire tratti dai bordi in ingresso all'interno della view map. Ci sono cinque tipi di operazioni (corrispondenti operatori di funzioni tra parentesi):

  • Selection (Operators.select())
  • Chaining (Operators.chain(), Operators.bidirectional_chain())
  • Splitting (Operators.sequential_split(), Operators.recursive_split())
  • Sorting (Operators.sort())
  • Stroke creation (Operators.create())

La visualizzazione della mappa di input è popolata con un set di oggetti ViewEdge. L'operazione di selezione è utilizzato per raccogliere i ViewEdges di interesse per gli artisti in base alle condizioni di selezione definiti dall'utente (predicati). Operazioni di concatenamento prendono il sottoinsieme di i ViewEdges e costruiscono catene concatenando i ViewEdges secondo ai predicati e alle  funzioni definite dall'utente. Le catene possono essere ulteriormente raffinate attraverso lo splitting in pezzi più piccoli (ad esempio, nei punti in cui i bordi formano una piega acuta) e selezionando una frazione di essi (ad esempio, per mantenere solo quelli più lunghi di una soglia di lunghezza) splitting. L'operazione di ordinamento viene utilizzata per disporre l'ordine di sovrapposizione delle catene per disegnare una linea sopra un'altra. Le catene sono finalmente trasformate in tratti stilizzati dall'operazione di creazione a un singolo tratto applicando una serie di shader a un singolo tratto . ViewEdges, Chains and Strokes fanno in genere riferimento a una dimensione sola (1D) degli elementi. A 1D element is a polyline that is a series of connected straight lines. Vertices of 1D elements are called 0D elements in general.

All the operators act on a set of active 1D elements. The initial active set is the set of ViewEdges in the input view map. The active set is updated by the operators.

Selection

The selection operator goes through every element of the active set and keeps only the ones satisfying a certain predicate. The Operators.select() method takes as the argument a unary predicate that works on any Interface1D that represents a 1D element. For example:

Operators.select(QuantitativeInvisibilityUP1D(0))

This selection operation uses the QuantitativeInvisibilityUP1D predicate to select only the visible ViewEdge (more precisely, those whose quantitative invisibility is equal to 0). The selection operator is intended to selectively apply the style to a fraction of the active 1D elements.

It is noted that QuantitativeInvisibilityUP1D is a class implementing the predicate that tests line visibility, and the Operators.select() method takes an instance of the predicate class as argument. The testing of the predicate for a given 1D element is actually done by calling the predicate instance, that is, by invoking the __call__ method of the predicate class. In other words, the Operators.select() method takes as argument a functor which in turn takes an Interface0D object as argument. The Freestyle Python API employs functors extensively to implement predicates, as well as functions.

Chaining (Concatenamento)

L'operatore di chaining ha effetto nel set degli oggetti ViewEdge e determina la topologia del tratto futuro.L'idea è di implementare un'iteratore per attraversare il grafico ViewMap lungo ViewEdges. L'iteratore definisce una regola di concatenamento che determina il successivo ViewEdge di seguire in un dato vertice (vedi degli iteratori ViewEdge). Parecchi di questi iteratori sono forniti come parte delle Python API di Freestyle (vedi Concatenamento degli iteratori dei predicati e ChainSilhouetteIterator). Iteratori personalizzate possono essere definiti ereditando la classe degli iteratori ViewEdge. L'operatore di concatenamento prende anche come argomento un Predicato unario per lavorare su un' Interfaccis 1D come criterio di arresto. Il concatenamento si ferma quando l'iteratore ha raggiunto un ViewEdge soddisfacendo questo predicato durante la marcia lungo il grafico. Chaining can be either unidirectional (Operators::chain()) or bidirectional (Operators::bidirectional_chain()). In the latter case, the chaining will propagate in the two directions from the starting edge.


The following is a code example of bidirectional chaining:

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

The chaining operator uses the ChainSilhouetteIterator as the chaining rule and stops chaining as soon as the iterator has come to an invisible ViewEdge.

The chaining operators process the set of active ViewEdge objects in order. The active ViewEdges can be previously sorted using the Operators::sort() method (see below). It starts a chain with the first ViewEdge of the active set. All ViewEdges that have already been involved in the chaining process are marked (in the case of the example above, the time stamp of each ViewEdge is modified by default), in order not to process the same ViewEdge twice. Once the chaining reaches a ViewEdge that satisfies the stopping predicate, the chain is terminated. Then a new chain is started from the first unmarked ViewEdge in the active set. This operation is repeated until the last unmarked ViewEdge of the active set was processed. At the end of the chaining operation, the active set is set to the Chains that have just been constructed.

Splitting

The splitting operation is used to refine the topology of each Chain. Splitting is performed either sequentially or recursively. Sequential splitting (Operators::sequentialSplit()) in its basic form, parses the Chain at a given arbitrary resolution and evaluates a unary predicate (working on 0D elements) at each point along the Chain. Every time the predicate is satisfied, the chain is split into two chains. At the end of the sequential split operation, the active set of chains is set to the new chains.

Operators.sequentialSplit(TrueUP0D(), 2)

In this example, the chain is split every 2 units. A more elaborated version uses two predicates instead of one: One to determine the starting point of the new chain and the other to determine its ending point. This second version can lead to a set of Chains that are disjoint or that overlap if the two predicates are different. (see Operators::sequentialSplit() for more details).

Recursive splitting (Operators::recursiveSplit()) evaluates a function on the 0D elements along the Chain at a given resolution and find the point that gives the maximum value for the function. The Chain is then split into two at that point. This process is recursively repeated on each of the two new Chains, until the input Chain satisfies a user-specified stopping condition.

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

In the code example above, the Chains are recursively split at points of the highest 2D curvature. The curvature is evaluated at points along the Chain at a resolution of 5 units. Chains shorter than 5 units won't be split anymore.

Sorting

The sorting operator (Operators::sort()) arranges the stacking order of active 1D elements. It takes as argument a binary predicate used as a “smaller than” operator to order two 1D elements.

Operators.sort(Length2DBP1D())

In this code example, the sorting uses the Length2DBP1D binary predicate to sort the Interface1D objects in the ascending order in terms of 2D length.

The sorting is particularly useful when combined with causal density. Indeed, the causal density evaluates the density of the resulting image as it is modified. If we wish to use such a tool to decide to remove strokes whenever the local density is too high, it is important to control the order in which the strokes are drawn. In this case, we would use the sorting operator to insure that the most "important" lines are drawn first.

Stroke creation

Finally, the stroke creation operator (Operators::create()) takes the active set of Chains as input and build Strokes. The operator takes two arguments. The first is a unary predicate that works on Interface1D that is designed to make a last selection on the set of chains. A Chain that doesn't satisfy the condition won't lead to a Stroke. The second input is a list of Shaders that will be responsible for the shading of each built stroke.

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)

In this example, the DensityUP1D predicate is used to remove all Chains whose mean density is higher than 0.1. Each chain is transformed into a stroke by resampling it so as to have a point every 5 units and assigning to it a constant thickness of 2 units and a dark gray constant color.

User control on the pipeline definition

Style module writing offers different types of user control, even though individual style modules have a fixed pipeline structure. One is the sequencing of different pipeline control structures, and another is through the definition of functor objects that are passed as argument all along the pipeline.

Different pipeline control structures can be defined by sequencing the selection, chaining, splitting, and sorting operations. The stroke creation is always the last operation that concludes a style module.

Predicates, functions, chaining iterators, and stroke shaders can be defined by inheriting base classes and overriding appropriate methods. See the reference manual entries of the following base classes for more information on the user-scriptable constructs.

  • UnaryPredicate0D
  • UnaryPredicate1D
  • BinaryPredicate0D
  • BinaryPredicate1D
  • UnaryFunction0DDouble
  • UnaryFunction0DEdgeNature
  • UnaryFunction0DFloat
  • UnaryFunction0DId
  • UnaryFunction0DMaterial
  • UnaryFunction0DUnsigned
  • UnaryFunction0DVec2f
  • UnaryFunction0DVec3f
  • UnaryFunction0DVectorViewShape
  • UnaryFunction0DViewShape
  • UnaryFunction1DDouble
  • UnaryFunction1DEdgeNature
  • UnaryFunction1DFloat
  • UnaryFunction1DUnsigned
  • UnaryFunction1DVec2f
  • UnaryFunction1DVec3f
  • UnaryFunction1DVectorViewShape
  • UnaryFunction1DVoid
  • ViewEdgeIterator
  • StrokeShader