|
||||||
ROBOTICA
video
immagini
papers
progettati
costruiti
toolbox
vrml
simulatori
Approfondimenti sulle Textures |
Anticipo la parte di approfondimenti
sulle textures... (a gran richiesta di una persona ;) ).
Avevamo visto nella prima
parte come mappare textures sulle superfici degli oggetti. In particolare
si era analizzato il caso di mapping sulle semplici primitive geometriche
rese disponibili da Vrml (Cone,Sphere,Cylinder,Box). Ricapitoliamo velocemente
quanto visto con un banale esempio:
Nel campo texture del
nodo Appearance introduco un nodo ImageTexture il cui campo url contiene una
reference alla immagine da mappare. Fin qui e' tutto noto.
Vediamo ora di approfondire
le nostre conoscenze su come gestire le textures. Si noti bene che nella maggior
parte dei casi si utilizzeranno le modalita' di default; quando pero' si vogliono
ottenere certi effetti e maggiore controllo sul mapping ci si deve preoccupare
di aspetti piu' 'complicati'.
Iniziamo con l'analizzare
un campo del nodo Appearance che ancora ci manca: textureTransform. Questo
campo serve per modificare le modalita' secondo cui mappare le textures sulle
superfici. Il campo textureTransform contiene al suo interno un nodo TextureTransform
(attenzione alle lettere maiuscole). La specifica del nodo TextureTransform
e' la seguente:
I campi sono molto semplici.
Il campo rotation offre la possibilita' di ruotare la texture da mappare.
La rotazione viene ovviamente effettuata attorno all'asse perpendicolare al
piano della texture. Il centro attorno a cui effettuare la rotazione viene
specificato nel campo center. Questo deve essere espresso in coordinate s,t
della texture.
Molto brevemente, le
coordinate s,t indicano le variabili utilizzate per la scansione dell'immagine
da mappare. s in pratica indica l'ascissa di un punto dell'immagine, mentre
t ne rappresenta l'ordinata. La coppia 0 0 indica l'angolo in basso a sinistra;
1 0 l'angolo in basso a destra, 0 1 l'angolo in alto a sinistra; 1 1 l'angolo
in alto a destra. Per cui .5 .5 indica il centro dell'immagine.
Il campo translation
serve per traslare la texture. Anche qui utilizziamo le coordinate s,t. Fornendo
la coppia .5 0 si trasla la texture verso destra di una quantita' di pixels
pari a meta' dell'immagine. La parte a sinistra che rimane scoperta viene
mappata con la parte destra dell'immagine stessa (si ha un rientro).
Il campo scale serve
per scalare l'immagine da mappare. Sotto certe condizioni questo consente
di mappare sulla superficie piu' copie della stessa texture. Vedremo poi come
ottenere questo effetto.
Non preoccupatevi se
ora vi sembra tutto abbastanza confuso. Con gli esempi successivi vedremo
di chiarirci le idee.
Tutte queste operazioni
hanno senso nel caso di un IndexedFaceSet; per le primitive il modo di mapping
e' quello standard.
Vediamo allora come mappare
una texture su un semplice oggetto creato con IndexedFaceSet. Il piu' semplice
oggetto di questo tipo e' una singola faccia. Definiamo dunque un quadrilatero
e vediamo gli effetti che otteniamo.
L'effetto che otteniamo
non e' affatto buono... tant'e' che non riusciamo neppure ad intravedere l'immagine
che forma la texture. Quando si ha un IndexedFaceSet il browser (Cosmo Player
beta 3 e' quello di riferimento in questo caso) mappa la texture sulla bounding
box che avvolge l'oggetto. Per cui in questo caso si vede solo una piccola
parte della texture.
Cio' che serve e' un
qualcosa che ci consenta di dimensionare la texture in modo opportuno. In
particolare dobbiamo indicare che nell'angolo in basso a sinistra della faccia
vogliamo che si vada a mappare l'angolo in basso a sinistra dell'immagine;
e lo stesso per tutti gli altri 3 angoli.
Il nodo IndexedFaceSet
offre appunto questa possibilita'. In particolare si utilizzano i campi texCoord
e texCoordIndex il cui funzionamento e' identico a quello dei campi usati
per definire la faccia.
Vediamo l'esempio e poi
spieghiamo in dettaglio questi nuovi campi. (nell'esempio riporto solo il
nodo Shape).
In questo caso otteniamo
il risultato che ci attendavamo.
Il campo texCoord contiene
il nodo TextureCoordinate. In pratica questo nodo contiene le stesse informazioni
contenute nel nodo Coordinate, con la sola differenza che qui ci si riferisce
alle coordinate della texture. Quindi si specifica una coppia di valori; in
particolare associamo al primo punto del quadrilatero la coppia 0 0 che indica
appunto l'angolo in basso della texture. E cosi' via per quanto riguarda gli
altri angoli. Il campo texCoordIndex contiene gli indici dei punti contenuti
nel campo point del nodo TextureCoordinate; in questo caso definiamo dunque
una texture quadrata che va a mapparsi sul quadrilatero generato.
Finche' ci si limita
a mappare textures su forme geometriche piuttosto semplici, si puo' fare questo
lavoro a mano; ma se avessimo geometrie molto piu' complicate allora la cosa
diventa ingestibile e l'ausilio di un tool di sviluppo risulta necessario.
Prima di passare ad analizzare
come impiegare le potenzialita' del nodo TextureTransform, mi interessa evidenziare
l'esistenza di altri due campi non ancora analizzati e che fanno parte del
nodo ImageTexture. Infatti, oltre al campo url, vi sono i campi repeatS e
repeatT. Questi due prendono un valore booleano e sono settati a TRUE di default.
In pratica abilitano la ripetizione delle textures in fase di mapping. Vediamo
subito un esempio.
Nell'esempio precedente
abbiamo mappato la Gioconda sopra un quadrilatero, senza preoccuparci molto
delle dimensioni della texture e del quadrilatero stesso. Imponendo che agli
angoli del quadrilatero le coordinate s,t devono assumere certi valori, si
impone al browser di interpolare nelle posizioni intermedie e in pratica di
riempire l'intero quadrilatero.
Supponiamo ora di volere
mappare piu' esemplari della Gioconda sul piano. In tal caso un modo possibile
e' quello di riscalare la texture tramite il nodo TextureTransform. Se i campi
repeatS e repeatT sono settati a TRUE il browser effettuera' il tiling della
texture.
Vediamo il risultato
con il seguente esempio:
Come si puo' vedere abbiamo
ora quattro copie della Gioconda mappate sul piano. Una tale operazione puo'
essere molto utile quando dobbiamo mappare una texture che rappresenta un
certo materiale sopra una superficie molto grossa. Applicando la texture singola
a tutto l'oggetto si ha una dilatazione eccessiva che porta a dettagli molto
grossolani.
Fornendo valori maggiori
di 1 al campo scale si ottiene il rimpicciolimento della texture. Valori minori
di 1 (ma comunque maggiori di 0) realizzano invece un ingrandimento.
Vediamo ora brevemente
il funzionamento degli altri campi.
Qui di seguito riporto
due esempi; il primo riguarda una traslazione della texture, mentre l'altro
una rotazione effettuata attorno al centro.
Primo esempio:
Secondo esempio:
Direi che possiamo fermarci
a questo livello con le textures. Penso che abbiamo analizato grossomodo tutti
gli aspetti piu' importanti. Solo un ultimo appunto: non si possono avere
oggetti con diverse textures, a meno che l'oggetto stesso non sia definito
da piu' nodi Shape.
Rimando inoltre al tutorial
sull'uso di Vrml che trovate al sito:
http://www.ywd.com/cindy/texture.html
Questo e' molto piu'
completo del presente documento e presenta inoltre diversi esempi, nonche'
una introduzione per comprendere come effettivamente lavorano le textures
(che qui non riporto per motivi di spazio).
#VRML V2.0 utf8
#esempio di mapping su primitiva
Shape {
appearance Appearance {
material Material { diffuseColor 1 1 1 }
texture ImageTexture { url "immagine.jpg" }
}
geometry Sphere { }
}
Il mapping sulle primitive viene eseguito secondo certe modalita' di default.
In particolare, per la sfera l'immagine viene avvolta sull'intera superficie;
per il cilindro si avvolge l'immagine sulla superficie laterale e due copie
delle immagini sono mappate sulle due basi; per il cono si effettua un avvolgimento
sulla superficie laterale e si pone una copia sulla base; per la box si riporta
una copia dell'immagine per ogni faccia.
TextureTransform {
exposedField SFVec2f center 0 0
exposedField SFFloat rotation 0
exposedField SFVec2f scale 1 1
exposedField SFVec2f translation 0 0
}
#VRML V2.0 utf8
# esempio texture 1
DirectionalLight {
direction 0 -1 -1
}
NavigationInfo {
headlight FALSE
}
Viewpoint {
position 0 10 50
}
Shape {
appearance Appearance {
material Material { diffuseColor 1 1 1 }
texture ImageTexture { url "../textures/generali/gioconda.jpg" }
}
geometry IndexedFaceSet {
coord Coordinate {
point [ -10 0 0, 10 0 0, 10 20 0, -10 20 0 ]
}
coordIndex [0,1,2,3,-1]
}
}
Shape {
appearance Appearance {
material Material { diffuseColor 1 1 1 }
texture ImageTexture { url "../textures/generali/gioconda.jpg" }
}
geometry IndexedFaceSet {
coord Coordinate {
point [ -10 0 0, 10 0 0, 10 25 0, -10 25 0 ]
}
coordIndex [0,1,2,3,-1]
texCoord TextureCoordinate {
point [0 0, 1 0, 1 1, 1 0]
}
texCoordIndex [0,1,2,3,-1]
}
}
Shape {
appearance Appearance {
material Material { diffuseColor 1 1 1 }
textureTransform TextureTransform {
scale 2 2
}
texture ImageTexture { url "../textures/generali/gioconda.jpg" }
}
geometry IndexedFaceSet {
coord Coordinate {
point [ -10 0 0, 10 0 0, 10 25 0, -10 25 0 ]
}
coordIndex [0,1,2,3,-1]
texCoord TextureCoordinate {
point [0 0, 1 0, 1 1, 1 0]
}
texCoordIndex [0,1,2,3,-1]
}
}
TextureTransform {
translation .5 0
}
TextureTransform {
center .5 .5
rotation 1.57
}