Home Map Index Search News Archives Links About LF
[Top Bar]
[Bottom Bar]
[Photo of the Author]
Antonio Castro
L'Autore: L'informatica è il mio lavoro e occupa gran parte del mio tempo libero. Come a tutti, suppongo, mi piace condividere le mie passioni. Lo riconosco, sono uno di quegli strani tipi a cui non piace Winsozz (si chiama così, credo) :- ) Per lo meno l'MSDOS, che viene ritenuto un giocattolo, è meno pretenzioso, e non ti riempie il computer di file di tutti i tipi che non sai cosa ci stanno a fare nè se per caso ne manca qualcuno.

Contenuto:
Sezione 1
Sezione 2
Sezione 3

Disegno di strutture iterative

[Ilustration]

Abstract: In questo articolo vedremo come usare Povray per il disegno di strutture iterative e come si può lavorare con queste belle immagini.




L'arte e la tecnica nell'infografia.

In questi articoli su Povray si parla sia degli aspetti tecnici sia di quegli aspetti che tecnici non sono. Abbiamo già detto che la tecnica e importante, bisogna però saper anche trarre il massimo profitto da essa.
L'infografia è tanto distinta dalle altre discipline che non è detto che qualcuno non possa scoprire le proprie capacità artistiche.
Non abbandoneremo la tecnica perchè è necessaria, però la tecnica è solo uno strumento per dominare le forme d'espressione. Per questo continueremo mescolando la fredda esposizione degli aspetti tecnici con aspetti più creativi.
Si tratta di comunicare idee. A partire dalle quali si possono esplorare molti cammini. Capita che mi metta a disegnare degli esempi e mi diverta talmente tanto che l'argomento che dovrei spiegare passa in secondo piano. Un'esposizione freddamente sistematica risulterebbe noiosa e perciò poco didattica. Il manuale di Povray sì che è scritto seguendo uno svolgimento sistematico degli argomenti. Come strumento di consultazione è ottimo. Io lo uso molto. A differenza del sistema metodico e sequenziale impiegato nel manuale io uso un metodo che potremmo definire a spirale, che torna spesso sulgi argomenti trattati per approfondirli.
Gli esempi che utilizzerò per illustrare alcuni aspetti tecnici non saranno meri esercizi perchè ricercherò un buon risultato estetico e un quadro completo del lavoro anche se questo introdurrà elementi non spiegati nell'esempio.
Poco a poco si andrà riconoscendo tutti gli aspetti, poichè quello che non potrà essere compreso in una sola lettura potrà essere trattato negli articoli successivi.
D'altra parte molti concetti sono talmente visivi da necessitare appena di una spiegazione, perchè il solo vederli in un esempio risulta suffieciente a poterli applicare alla perfezione. Forse meglio che se li leggessimo sul manuale senza una buona immagine come esempio.
Tuttavia non posso dimenticare che per quanti desiderino procedere con maggior speditezza è sempre possibile ricorrere al manuale di Povray.

Oggetti geometrici semplici

La maggior parte di questi oggetti non è stata utilizzata in alcun disegno. Li tratteremo quindi qui a mò di ripasso.
Il numero di oggetti che si possono .disegnare utilizzando queste forme è enorme, e in più si deve tener conto che l'uso di frome semplice è un gran risparmio di tempo nella costruzione della scena.
  • sfera

  • sphere { < x, y, z>, radio ..... } /
    x, y, z sono le coordinate del centro della sfera.
    Al pos to dei punti di sospensione si possono aggiungere valori per
    la scala, la r,otazione, la traslazione, il colore, la tessitura etc...
  • cono

  • In realtà la sintassi permette di definire un tronco di cono.
    cone { <x1, y1, z1>, rad1 <x2, y2, z2>, rad2 [open] ..... }
    x1, y1, z1 sono le coordinate del centro a un estremo del
    cono, e rad1 il raggio a questo estremo.
    x2, y2, z2 sono le coordinate del centro all'altro estremo del tronco di cono, y rad2 il raggio a questo estremo. Perchè il tronco di cono si trasformi in cono è suffieciente che uno dei raggi sia 0. Se vogliamo che sia un cono vuoto useremo la parola 'open' in caso contrario la omettiamo ed otteniamo un cono pieno.
  • cilindro

  • cylinder { <x1, y1, z1>, <x2, y2, z2>, rad [open] ...... }
    x1, y1, z1 sono le coordinate del centro ad un estremo del cilindro, x2, y2, z2 sono le coordinate del centro all'altro estremo, e rad è il raggio del cilindro. Perchè sia un cilindro vuoto useremo la parola 'open', in caso contrario la ometteremo ed otterremo un cilindro pieno.
    Ricordiamoci che nel caso di sfere, coni e cilindri, possiamo deformare gli oggetti usando un adeguato fattore di scala. E' possibile farlo anche con altre forme, ma in questo caso è particolarmente interessante perchè apparentemente otteniamo degli oggetti distinti.
  • piano

  • plane { <x, y, z>, dist ..... }
    In questo caso x, y, z non rappresentano una posizione ma un vettore la cui direzione è perpendicolare alla superficie del piano. Il valore dist sarà la distanza dal centro delle coordinate. Ricordiamo che in Povray si può abbreviare l'espressione di un vettore. x = <0, 1 , 0> -z = <0, 0, -1>
    Al posto di un piano si può usare una sfera di grandi dimensioni. Ciò non causa nessuno problema. Noi lo abbiamo fatto molte volte.
  • quadrilateri

  • box { <x1, y1, z1>, <x2, y2, z2>...... }
    x1, y1, z1 sono le coordinate di una delle facce della figura x2, y2, z2 sono le coordinate della faccia opposta.

Oggetti geometrici trigonometrici composti. (CSG)

Le primitive CSG consentono di combinare più forme in un'unica più complessa. Fatto questo ci ritroviamo con un oggetto che può essere manipolato tranquillam ente sulla scala, traslazione, tessitura etc... senza bisogno di intervenire sulle caratteristiche dei singoli componenti.
I modi in cui si possono combinare elementi semplici sono quattro, e ne esiste una quinta che si può applicare ad un singolo elemento.
  • Unione

  • 'union { object {A} object{B} }'
    Tutti i punti all'interno di A o B
  • Intersezione

  • 'intersection { object {A} object {B} }'
    Tutti i punti all'interno di A e B
  • Complemento

  • object {A inverse}
  • Sottrazione

  • 'difference { object {A} object {B} }'
    Tutti i punti di A non inclusi in B
    Equivale a 'union { object {A} object {B inverse }'
  • Mescolanza

  • 'merge { object {A} object {B} }'
    Come l'unione, però spariscono le superficii interne
    dei componenti A e B. Se gli ogetti sono tutti opachi
    quato dettaglio non è di interesse alcuno.
Nei seguenti esempi si utilizzano alcune di queste funzioni.
Come metodo per disegnare senza confondersi si può utilizzare il seguente. Unite tutte le primitive che acquistano un volume in un unico oggetto. Proseguite con le intersezioni di questo oggetto con le primitive che sottraggono volume.

 
#define ManzanaMordida = intersection { 
      object { ManzanaEntera } 
      object { Mordisco1 inverse } 
      object { Mordisco2 inverse } 
} 
 

Fate sì che non vi siano superfici in comune tra le figure composte, perchè ciò può produrre un'incertezza sull'oggetto a cui appartiene la superficie comune. Per risolvere questo problema basta assegnare una dimensione inferiore ad uno degli oggetti.

L'utilizzo di commenti e condizioni in Povray.

Gli elementi di uno scenario si descrivono generalmente in ordine arbitrario. Perciò vi sono circostanze in cui può essere necessario implementare commenti descrittivi, ad esmpio per la creazione di strutture iterative. In Povray vi sono molti modi per farlo. Uno mediante le strutture di controllo di flusso che implementa il linguaagio proprio di Povray. Qui menzioniamo le direttive di linguaggio #declare e #include e ne qualifichiamo molte altre come di minor im portanza. Quando le useremo vedremo però che sono quasi imprescindibili. Nell'esempio seguente usiamo un programma scritto direttamente in linguaggio Povray. Ci tengo a dire che personalmente è la prima volta che lo uso. Il motivo è che non lo considero necessario. Si possono ottenere gli stessi risultati con programmi esterni che producano il sorgente necessario, e vedremo più avanti un esempio di questa seconda possibilità, che io uso in genere. Si possono anche fare cose miste. Vedremo che lo stile di programmazione con Povray non richiede l'eleganza di un linguaggio più generico. Il motivo è che Povray fu concepito come linguaggio per la desrizione di scene, e queste cose sono risultati recenti. Vedremo che con Povray si possono programmoare ogni sorta di commenti ed espressioni matematiche complesse. A mio giudizio è bene che incorpori queste caratteristiche, esse non sono però imprescindibili. Tutto ciò si può ottenere con programmazione esterna, per la produzione di un sorgente più o meno iterativo. Credo che farlo in un modo o nell'altro non abbia nulla a che fare con la componente artistica, che è l'importante, per cui non c'è merito particolare nell'usare l'uno o l'altro metodo. L'importante è l'immagine finale. Tuttavia può essere importante la quantità di calcolo e di lavoro del porcessore impiegata. Se si conosce un linguaggio generico con il quale ci si sente più comodi si usi Povray come passo finale. Se si ha bisogno di implementare qualcosa semplicemente si usi direttamente Povray. Vedremo come fare entrambe le cose, ma prima aggiungeremo qualche altro commento.

Prova e errore, di fronte al calcolo.

Si tenga presente che molte scene si possono disegnare partendo da un'idea. Prima si inizia con valori stimati per approssimazione, poi si va correggendo con prove ed errori fino ad ottenere il risultato desiderato. Per questo abbiamo già un interfaccia che ci consente di usare il Povray comodamente (POV). Ma se si crede di poter fare tutto in questo modo si è in errore. A volte non c'è latro modo che prendere carta, penna e calcolatrice. Ora i problemi da risolvere sono problemi geometrici in 3D. E' necessaria un po' di conoscenza di geometria spaziale e di trigonometria se si vogliono ottenere certi effetti. Rivediamo qualche cosa.

sin(a) = A / C = (Cateto opposto / Ipotenusa)
cos(a) = B / C = (Cateto adiacente / Ipotenusa)
tan(a) = A / B = (Cateto opposto / Cateto adiacente)

Per tanto:

A = sin(a)/C
B = cos(a)/C
C = sqrt(A^2 + B^2)
Come 2* Pi radianti = 360º

1 Radiante = 180 / Pi = 57,29577951308232
1º = Pi / 180 = 0,174532925199432957

Andiamo ora a rivedere i range delle principali funzioni trigonometriche in funzione del quadrante :


Quadrante Seno Coseno Tangente
0 .. 90 0 .. +1 +1 .. 0 0 .. +Infinito
90 .. 180 +1 .. 0 0 .. -1 -Infinito .. 0
180 .. 270 0 .. -1 -1 .. 0 0 .. +Infinito
270 .. 360 -1 .. 0 0 .. +1 -Infinito .. 0


a = atan(A/B)

Quest'ultima funzione è un po' ambigua. In realtà non possiamo conoscere il valore di alpha se non conosciamo il quadrante, perciò è meglio usare:

a = atan2(A,B)

La distanza tra P1(x1,y1,z1) y P2(x2,y2,z2) è

D = sqrt( (x2-x1)^2 + (y2-y1)^2 + (z2-z1)^2 )

Vi sono molte formule utili in trigonometria, ma credo che queste siano sufficienti alla maggior parte dei casi. In Povray si assume che per le funzione trigonometriche lavorimao con i radianti, perciò si assume radiante()= radiante(Alfa). Al contrario per gli angoli si assume che lavoriamo in gradi. :-(

Riccio di mare

l'esempio seguente è un buon esercizio per ripassare le basi della trigonometria. Si può notare come gli aculeii nel riccio hanno una collocazione abbastanza buona. Questo non si può improvvisare, bisogna analizzarlo, ricavare un algoritmo ed implementarlo avendo bene in mente ciò che si vuole ottenere. Il sorgente è ampiamente commentato per risultare il più chiaro possibile. E' un chiaro caso in cui si utilizza una struttura iterativa.In questo caso scegliamo Povray come linguaggio per implementarla, ma non c'è alcuna ragione per non farlo nell'altro modo che vedremo più avanti con un programma esterno.

erizo

Iniziamo mostrando il sorgente degli aculeii. Si tratta di una figura composta in cui utilizziamo le primitive CGS di cui già abbiamo parlato.

balistap.inc

Poi il sorgente principale dove definiamo il resto della scena. La più parte notevole sono indubbiamente i ricci, gli autentici protagonisti:

erizo.pov

Ci sono elemtni in questa scena che non abbiamo commentato, e sono gli effetti di superficie (la sabbia ondulata). Nè abbiamo trattato gli effetti atmosferici (in questo caso ci riferiamo ad una nebbia verde mare molto fitta e perciò molto umida.) :-), così come abbiamo usato le figure composte senza averlo spiegato. Si tratta di ciò che si può definire come una figura come unione, intersezione, differenza o complesso di altre. Insomma si tratta di un modo di combinare elementi semplici per ottenerne altri di complessi. Quest'ultima cosa la vedermo più avanti in questo stesso articolo. L'illuminazione di questa scena si ottiene utilizzando molti punti luce per simulare la luce subacquea caratterizata dal disordine introdotto dalle ond in superficie. Un solo punto luce non sarebbe soddisfacente perchè l'ombra del riccio risulterebbe troppo nitida.

La generazione mediante programmi esterni.

Un tracciatore di raggi è solo lo strumento per generare un'intera scena che è stata descritta con l'aiuto di un linguaggio formale che è il tracciatore di linee. Questo può capire le specifiche di forme colorate, luci, etc.. però molto spesso esiste un lavoro precedente per ottenere quel che desideriamo. Scanner tridimensionale, programmi di modellazione, traduttori di formato, programmazione, etc.. In questo processo un tracciatore di raggi può essere utilizzato solo come un anello in più nella catena di strumenti che ci permettono di ottenere il risultato finale. In altre parole non è necessario scrivere direttamente il sorgente per il tracciatore di raggi per realizzare la nostra idea. Possiamo servirci di strumenti e anche della programmazione per generare ogni genere di figure complete altamente ripetitive o ricorsive. Facciamo un esempio di quel che stiamo dicendo. Questo programma è scritto in C e fa la cosa seguente. Definisce uno spazio con le proporzioni della risoluzione impiegata (1000*750). Una volta definita quest'area il programma si occupa di situarvi delle sfere. Dovrà controllare che la posizione generata non tenga conto di altro che delle sfere già generate per evitare che si compenetrino. Per far ciò controliamo la posizione di ciascuna sfera e il suo volume. Se la posizione cade sopra un'altra sfera proviamo in un'altra posizione. Altrimenti verifichiamo la distanza minima dal bordo della sfera più vicina. Se necessario riduciamo il volume della sfera perchè ci stia. Dopo un elevato numero di iterazione avremo una superficie piena di sfere di diverso volume con un minimo spazio libero tra esse. Stiamo usando molta forza ruta di calcolo, perchè ad ogni ciclo il programma ha bisogno di più tentativi per collocare una nuova sfera.

burbujas.c

Una volta compilato lo eseguiremo indirizzando il risultato al file 'burbujas.inc' dove si troveranno i dati. burbujas > burbujas.inc Il listato ottenuto sarà di questo tipo:

 
sphere{<-375, 0,   33> 55.0000000 texture{Gold_Metal}} //(0/1) 
sphere{< -86, 0,   62> 55.0000000 texture{Gold_Metal}} //(1/2) 
sphere{<-326, 0,  346> 55.0000000 texture{Gold_Metal}} //(2/3) 
sphere{< 190, 0, -156> 55.0000000 texture{Gold_Metal}} //(3/4) 
sphere{<  62, 0, -293> 55.0000000 texture{Gold_Metal}} //(4/5) 
sphere{< 323, 0,  161> 55.0000000 texture{Gold_Metal}} //(5/6) 
sphere{< 341, 0,  -15> 55.0000000 texture{Gold_Metal}} //(6/7) 
................... 

Dobbiamo aver pazienza, però se vediamo che il tempo passa senza progressi possiamo interrompere il processo. Basta editare il file e verificare che l'ultima linea sia completa, altrimenti tagliarla. Il sorgente pov sarà il seguente:

burbujas.pov

Andiamo ad utilizzare il valore clock però in questo caso con uno scopo molto diverso. In questo caso non produrremo una sequenza di immagini corrispondnte ad un'animazione, ma quattro immagini molto diverse come conseguenza del variare dell'apertura e della posizione dell'obbiettivo della camera. Abbiamo già detto nell'articolo precedente che avremmo visto degli esem pi per sperimentare le possibilità della camera. Possiamo ben fare riferimento a questo esempio. Possiamo vedere i diversi effetti di prospettiva ottenuti a seconda dell'uso di un angolo aperto o chiuso, grande o piccolo. il più grande angolo possibile per l'aèertura dell'obbiettivo è di 180 gradi. E' un caso estremo in cui le forme non si distinguono. Come si può vedere un semplice gioc con la camera produce effetti interessanti. Le immagini sono state realizzate con un Pentium 200 MMX 48 MB Ram (398 bogomips) Le otteniamo come suggerito usando lo strumento 'pov' con il comando seguente:


pov burbujas 6 9 1 5 1 5
Tempo totale =

I parametri e i loro significati sono:

  • Useremo il sorgente $HOME/dat/pov/LF2-Burb1/LF2-Burb1.pov
  • volume 6 = (400x300)
  • qualità 9
  • fotogramma iniziale = 1
  • fotogramma finale = 5
  • clock iniziale = 1
  • clock finale = 5

La differenza di tempo tra i singoli fotogrammi è notevole. Tracciando con maggior qualità si ottengono i tempi seguenti

pov burbujas 9 9 1 5 1 5

Tempo totale = 4 ore e mezza.
Primo fotogramma 2 minuti
Secondo fotogramma 5 minuti.
Terzo fotogramma 10 minuti
Quarto fotogramma 13 minuti
Quinto fotogramma 4 ore !!

Vediamo poi i risultati. In primo luogo nei primi quattro fotogrammi varia solo la posizione della camera. (posición, angulo, dirrección, etc)

Manca un fotogramma che mostreremo in seguito dopo aver trattato alcuni argomenti in relazione con quest'ultimo.

Ottimizzazione dell'uso della CPU

Come possiamo vedere l'ultimo fotogramma è il più definito e completo, e Povray non ha saputo ottimizzarlo. Quando abbiamo una figura composta il tracciatore cerca di determinare una figura più semplice che la contenga. Questo nelle precedenti versioni di Povray andava fatto sempre manualmente. Si specificava con la primitiva 'bounded_by' una forma che conteneva uno o più oggetti e da questa forma il tracciatore assumeva che i raggi che non ncidevano su questa non incideva nemmeno sugli oggetti interni limitandosi a questa verifica. Attualmente sono pochi i casi i cui resta utile una ottimizzazione manuale, però ci troviamo di fronte ad uno di essi. L'ultimo foogramma corrisponde ad una figura composta eccessivamente complessa. Per questo sarebbe stato meglio raggruppare preventivamente i bargugli per zone ben delimitate e combinarli preventivamente in varie figure composte per guidare così l'ottimizzatore o megilio combinarle tutte assieme come si fa nell'esempio però usando un gruppo di sfere che stanno in una zone bben delimitata con il comando 'bounded_by'. La sintassi sarà:

 
    union { 
    sphere { <x1, y1, z1>, r1 }  
    sphere { <x2, y2, z2>, r1 } 
    sphere { <x3, y3, z3>, r1 } 
    .......................... 
    bounded_by { sphere { <xb, yb, zb>, rb } } 
  } 

Si può applicare non solo ad unioni od intersezioni ma a qualsiasi oggetto, e si può usare in 'bounded_by' una forma distinta per sviluppare i migliori risultati tra le sfere e i poligoni. Se la forma scelta era già parte dell'oggetto il risultato può essere difettoso. Reputo che la necessità di fare ciò sia molto rara. Quest'ultimo esempio aveva molte cattive idee e l'ottimizzatore di Povray non poteva fare di più. Si tratta di un oggetto composto con 2154 sfere. Potete contarle nell'immagine se non mi credete. :-) L'ultima immagine è ilrisultato dell'aver continuato a giocare con le possibilità del tracciatore. Molte volte ad una stessa idea corrispondono svariate possibilità ed è qui che entrano in gioco la nostra immaginazione e la nostra creatività. Ciò a dire che molte volte no sia ha che da partire con una buona idea e continuare a provare e ad immaginare fino a realizzare qualcosa di nostro gusto.

Si possono immaginare moltissimi scenari in cui la programmazione serva da appoggio alla generazione di immagini sintetiche, estetiche o in movimento.

Quello che si nota meno.

Povray proporziona molte funzioni matematiche più o meno interessanti, però ce n'è una interessantissima che manca. Si tratta della funzione spline. Non c'è niente di più comodo che tracciare una serie di punti con carta e penna e poi applicare una funzione che tracci una curva passante per quei punti. La primitiva spline di Povray non si può utilizzare come funzione perchè genera una linea come base per costruire delle forme, però sarebbe molto meglio applicare questa funzione alle variabili che noi forniamo. Da questa forma potremmo muovere oggetti come la camera per ottenere una ripresa lungo un percorso qualsiasi. Tuttavia sarebbe bene poter implementare tale funzione esternamente. Bene, in qualche maniera questo si può compensare usando inclusi e programmazione esterna. In Linux abbiamo un utility chiamata 'spline'. Si utilizza come comando e genera il dislivello corrispondente alla curva desiderata, a partire da un valore che può essere una coppia di punti. Può essere molto utile combinare questo comando con la programmazione esterna. Per esmpio per ottenere delle animazioni, o dei movimenti di camera.

Esercizi

  • Se qualcuno lo desidera può provare come esercizio ad ottimizzare quest'ultimo fotogramma seguendo le raccomandazioni date.
  • Trasferire il programma burbujas.c in linguaggio Povray.
  • Trasferire il programma erizos.c in un linguaggio generico.

Contributi dei lettori.

Se qualche lettore implementa qualche altro algoritmo per la costruzione di forme ricorsive o iterative mi può inviare i suoi esperimenti, sotto forma di sorgenti compressi in gzip. Se vi sarà materiale suffieciente potrà essere incluso in qualche articolo dedicato a Povray con una selezione delle immagini più curiose, accompagnate dai sorgenti. Astenersi dal mandare materiale che implichi licenza d'uso comemrciale di qualsiasi tipo. Interessano soprattutto i sorgenti.

pov3.tar.gz Sorgenti dei programmi di quest'articolo (43 K bytes)


Traduzione in italiano a cura di Seipse

Questo sito è gestito da Miguel Angel Sepulveda
© Antonio Castro 1998
LinuxFocus 1998