Per a situar, orientar i escalar els objectes al nostre gust dins l'entorn que estem construïnt, cal poder aplicar transformacions. Les transformacions bàsiques són: translació, rotació i escalat. També existeixen variants d'aquestes però que no veurem.
Per a fer transformacions en VRML, cal utilitzar el
node Transform. Aquest node
pot realitzar qualsevol de les tres operacions o les tres. Per a veure com funciona anirem fent exemples:
Translacions
|
Exemple1: Definirem una esfera vermella a l'origen de coordenades i una esfera
verda traslladada 10 unitats en l'eix de les X.
Shape { # Esfera vermella que ens senyala l'origen de coordenades
geometry Sphere { radius 2 }
appearance Appearance { material Material { diffuseColor 1 0 0 } }
}
Transform {
translation 10 0 0
children [
Shape { # Esfera verda traslladada 10 unitats en l'eix X
geometry Sphere { radius 2 }
appearance Appearance { material Material { diffuseColor 0 1 0 } }
}
]
}
|
Analitzem el que fa aquest fragment de codi. La primera part, defineix l'esfera vermella que ens servirà de referència per a veure clarament que l'esfera verda ha estat traslladada. Com es pot observar, l'esfera vermella no pateix cap transformació.
La segona part és la que realment ens interessa. Aquí es defineix un node Transform. Aquest té un field translation on es defineix el desplaçament que patirà l'objecte que volem traslladar. Així doncs, es defineix un desplaçament de 10 unitats en l'eix X, 0 unitats en l'eix Y i 0 unitats en l'eix Z.
Després del field translation podem veure el field children. Aquest field, permet donar una llista d'objectes que seran afectats per la trasnformació que estem fent. En aquest cas, la llista d'objectes es limita a un de sol. És l'esfera verda que volem situar a 10 unitats de l'origen en l'eix X. (De fet, aquest node és un dels nodes agrupadors que esmentabem al mòdul Nodes, Camps i Esdeveniments I).
(NOTA: Com a referència pel que fa els tipus dels fields, el field children és de tipus MFNode, és a dir, de tipus node multivaluat pel fet que pot contenir una llista de valors).
Compliquem una mica més l'entorn:
|
Exemple2: Ara volem afegir un con blau sobre la nostre esfera verda. Per a fer
això, hem de traslladar el con 10 unitats en l'eix de les X igual que l'esfera, però a més,
l'hem de traslladar 3 unitats en l'eix de les Y (segons les mesures de l'esfera i el con).
Shape { # Esfera vermella que ens senyala l'origen de coordenades
geometry Sphere { radius 2 }
appearance Appearance { material Material { diffuseColor 1 0 0 } }
}
Transform {
translation 10 0 0
children [
Shape { # Esfera verda traslladada 10 unitats en l'eix X
geometry Sphere { radius 2 }
appearance Appearance { material Material { diffuseColor 0 1 0 } }
}
]
}
Transform {
translation 10 3 0
children [
Shape { # Con blau traslladat 10 unitats en l'eix X i 3 en l'eix Y
geometry Cone { bottomRadius 2 height 2 }
appearance Appearance { material Material { diffuseColor 0 0 1 } }
}
]
}
|
Ara hem definit un altre node Transform per a la translació del con blau. També podiem
haver aprofitat pel con el desplaçament de 10 unitats en l'eix X que ja tenim fet en l'esfera verda. Llavors
ja només hauriem d'afegir una transformació de 3 unitats en l'eix Y de la següent manera:
Shape { # Esfera vermella que ens senyala l'origen de coordenades
geometry Sphere { radius 2 }
appearance Appearance { material Material { diffuseColor 1 0 0 } }
}
Transform {
translation 10 0 0
children [
Shape { # Esfera verda traslladada 10 unitats en l'eix X
geometry Sphere { radius 2 }
appearance Appearance { material Material { diffuseColor 0 1 0 } }
}
Transform { # Germà de l'esfera verda
translation 0 3 0
children [
Shape { # Con blau traslladat 10 unitats en l'eix X i 3 en l'eix Y
geometry Cone { bottomRadius 2 height 2 }
appearance Appearance { material Material { diffuseColor 0 0 1 } }
}
]
}
]
}
Resultat
|
Com es pot observar, hem ficat la transformació de translació de 3 unitats en l'eix Y com a fill
de la translació de 10 unitats en l'eix X. És a dir, com a germà de l'esfera verda. D'aquesta
manera, el con pateix primer un desplaçament de 3 unitats en l'eix Y, i tot seguit s'agrupa amb l'esfera
verda. Un cop agrupats, tots dos pateixen el desplaçament de 10 unitats en l'eix X.
Rotacions
|
Exemple3: Definirem una caixa groga a l'origen de coordenades amb les cares
paral.leles als plans coordenats, i una altra caixa blava(més estreta i més alta) rotada 45 graus respecte l'eix
Y.
Shape { # Caixa groga que ens senyala la rotació zero
geometry Box { size 4 2 4 }
appearance Appearance { material Material { diffuseColor 1 1 0 } }
}
Transform {
rotation 0 1 0 0.7854 # 45 graus en radians
children [
Shape { # Caixa blava que es rotada 45 graus respecte l'eix Y
geometry Box { size 2 4 2 }
appearance Appearance { material Material { diffuseColor 0 0 1 } }
}
]
}
|
Analitzem el que fa aquest fragment de codi. La primera part, defineix la caixa groga que ens servirà de referència per a veure clarament que la caixa blava ha estat rotada. Com es pot observar, la caixa groga no pateix cap transformació i per tant té les seves cares paral.leles al plans coordenats.
La segona part és la que realment ens interessa. Aquí es defineix un node Transform. Aquest té un field rotation on es defineix la rotació que patirà l'objecte que volem modificar. Així doncs, es defineix una rotació de 45 graus (0.7854 radians) respecte l'eix Y. Això es defineix d'una forma molt curiosa en VRML.
El field rotation té en realitat dues parts. Els tres primers valors defineixen un vector en l'espai 3D, és a dir, l'orientació de l'eix de rotació. L'eix de rotació coïncideix amb els eixos coordenats quan:
Aquest sistema de definir l'eix de rotació de la transformació és molt flexible i general, però resulta complicada quan l'eix té una orientació diferent a la dels eixos coordenats.
La segona part és l'angle de rotació que volem aplicar (expressat en radians) al voltant de l'eix que hem definit amb els tres primers valors.
Després del field translation podem veure el field children que, com abans, engloba la llista d'objectes que seran afectats per la rotació. En aquest cas, la llista d'objectes torna a ser un de sol, la caixa blava que volem rotar 45 graus respecte l'eix Y.
Compliquem una mica més l'entorn:
|
Exemple4: Ara volem que la caixa blava també roti 45 graus respecte
l'eix X.
Shape { # Caixa groga que ens senyala la rotació zero
geometry Box { size 4 2 4 }
appearance Appearance { material Material { diffuseColor 1 1 0 } }
}
Transform {
rotation 1 0 0 0.7854 # Rotació eix X
children [
Transform {
rotation 0 1 0 0.7854 # Rotació eix Y
children [
Shape { # Caixa blava
geometry Box { size 2 4 2 }
appearance Appearance { material Material { diffuseColor 0 0 1 } }
}
]
}
]
}
|
Pel que fa els escalats cal pensar que es poden diferenciar dos tipus d'escalats: els uniformes i els no uniformes (tot i que
els uniformes són un cas particular dels no uniformes). Els uniformes, engrandeixen o redueixen un objecte en totes
direccions per igual, mentre que els no uniformes ho fan en tan sols alguna direcció o direccions. Per tant, en els escalats
uniformes, els objectes mantenen les seves proporcions, mentre que en els no uniformes, els objectes queden deformats.
|
Exemple5: Definirem un escalat no uniforme sobre un cub. En concret, escalarem
el cub al doble de la seva mida en la direcció de l'eix de les X.
Transform {
scale 2 1 1 # Creix al doble en la direcció X i queda igual en les direccions Y i Z
children [
Shape { # Cub taronja
geometry Box { size 1 1 1 }
appearance Appearance { material Material { diffuseColor 1 0.5 0 } }
}
]
}
|
Analitzem el que fa aquest fragment de codi. Aquí es defineix un node Transform que té un field scale on es defineix l'escalat no uniforme que patirà l'objecte que volem modificar. Per a definir l'escalat li diem el tant per u que volem engrandir/reduïr l'objecte en cada una de les direccions que defineixen els eixos.
Com que l'escalat no uniforme que definim en l'exemple es de [2 1 1], és per això que el cub de 1 unitat ja no apareix com a tal, si no com a una caixa allargada horitzontalment que fa exactament 2 unitats d'ample, 1 unitat d'alçada i 1 unitat de fons.
Si volem aplicar un escalat uniforme, tan sols cal posar la mateixa xifra d'escalat en totes tres direccions.
Encadenament de Transformacions
Quan es vol fer més d'una transformació, no cal definir necessàriament un node Transform
per a cada una, si no que podem posar-les totes sota un mateix node.
|
Exemple6: Definirem un cub de 1 unitat i li aplicarem una translació
de [5 4 0], una rotació de 30 graus respecte l'eix X i un escalat de [0.5 0.5 2].
Transform {
translation 5 4 0
rotation 1 0 0 0.5236 # 30 graus
scale 0.5 0.5 1
children [
Shape { # Cub verd fosc
geometry Box { size 1 1 1 }
appearance Appearance { material Material { diffuseColor 0 0.5 0.2 } }
}
]
}
|
Analitzem el que fa aquest fragment de codi. El que hem definit aquí no és tan senzill com sembla ja que no obtenim el mateix resultat si apliquem les tres operacions en un ordre que si les apliquem en un altre.
Per definició, VRML defineix un ordre de preferència d'operacions de transformació que és el següent:
Per tant el codi d'adalt seria equivalent al següent si fessim les transformacions per separat:
Transform {
translation 5 4 0
children [
Transform {
rotation 1 0 0 0.5236 # 30 graus
children [
Transform {
scale 0.5 0.5 1
children [
Shape { # Cub verd fosc
geometry Box { size 1 1 1 }
appearance Appearance { material Material { diffuseColor 0 0.5 0.2 } }
}
]
}
]
}
]
}
Resultat.
|
Com podem comprobar el resultat és el mateix que abans.
Cal no caure en l'error de pensar que això es llegeix de dalt a baix. Aquest codi cal llegir-lo de dins cap a fora i per tant l'ordre en que s'apliquen les operacions és començant per l'objecte i anar sortint en fora: Cub escalat rotat i traslladat.
Per aplicar les transformacions en l'ordre que hem dit inicialment caldria invertir-ho de la següent manera:
Transform {
scale 0.5 0.5 1
children [
Transform {
rotation 1 0 0 0.5236 # 30 graus
children [
Transform {
translation 5 4 0
children [
Shape { # Cub verd fosc
geometry Box { size 1 1 1 }
appearance Appearance { material Material { diffuseColor 0 0.5 0.2 } }
}
]
}
]
}
]
}
Resultat.
|
Com podem comprobar el resultat és totalment diferent dels dos d'abans. De fet la nostre caixa ha que era
un paral.lelepíped d'angles rectes ara ha quedat deformada.
Exercicis proposats:
|