Fins ara tan sols hem vist les primitives com objectes 3D per a modelar el nostre entorn. Això és evidentment molt restrictiu quan a formes i per tant VRML defineix unes estructures per a poder definir geometries arbitràries.
Les estructures es basen en una variant del que en gràfics 3D es coneix com a model de fronteres i que permet definir la geometria d'un objecte 3D a partir dels seus vértexs i cares.
Per exemple, un cub unitari (amb tots els costats de 1 unitat) es pot definir a partir de 8 vértexs i 6 cares.
Això es podria fer de la següent manera:
|
| |||||||||||||||||||||||||||||||||
La llista de cares del cub mostra, per a cada cara, els vértexs que formen la cara segons els indexos de la llista de vértexs. L'ordre en que es donen els vértexs és molt important, ja que si no es respecten unes certes normes els poligons no es dibuixaran correctament. Les normes per a donar els vértexs són:
En VRML aquesta estructura es pot definir mitjançant el
node IndexedFaceSet amb l'ajut
del node Coordinate. Així doncs,
el cub unitari el podriem definir com es mostra a continuació:
|
Exemple1: Definició per cares i vértexs d'un cub unitari.
Shape {
appearance Appearance { material Material { diffuseColor 1 0 0 } }
geometry
IndexedFaceSet {
coord Coordinate {
point [
0.5 0.5 0.5,
0.5 0.5 -0.5,
-0.5 0.5 -0.5,
-0.5 0.5 0.5,
0.5 -0.5 0.5,
0.5 -0.5 -0.5,
-0.5 -0.5 -0.5,
-0.5 -0.5 0.5
]
}
coordIndex [
0, 1, 2, 3, -1,
0, 4, 5, 1, -1,
1, 5, 6, 2, -1,
2, 6, 7, 3, -1,
3, 7, 4, 0, -1,
4, 7, 6, 5, -1
]
}
}
|
Analitzem aquest fragment de codi. En primer lloc trobem que per a veure un objecte definit amb node IndexedFaceSet cal posar-lo dins d'un node Shape. Per tant li assignem una aparença i en el field geometry hi posem el node IndexedFaceSet.
Ara si, mirem com funciona el node IndexedFaceSet. en primer lloc es defineix la llista de vértexs de forma similar a la taula d'abans. Per a definir aquesta llista es fa servir el node Coordinate que té el field point on s'hi llisten els punts que formen els vértexs de l'objecte.
Un cop definits els vértexs, ja només queda definir els polígons que formen les cares. Això es fa amb el field coordIndex, on s'hi llisten les cares posant la successió d'indexos de vértexs per a cada una. Cal notar que les cares poden tenir tants vértexs com es vulgui i per tant, per a definir que ja s'ha acabat una cara cal posar un -1.
(Nota: El nombre mínim de vértexs per cara és tres).
Evidentment, fer un cub que ja existeix com a primitiva no té massa sentit, però amb aquest sistema podem modelar qualsevol objecte facetat, és a dir fet de cares planes.
El color també es pot donar a l'objecte polígon a polígon mitjançant el field color i
el field colorPerVertex. A continuació es mostra un exemple:
|
Exemple2: Definició per cares i vértexs d'un cub unitari amb
cada cara d'un color diferent (vermell, verd, blau, magenta, groc i cian).
Shape {
geometry
IndexedFaceSet {
coord Coordinate {
point [
0.5 0.5 0.5,
0.5 0.5 -0.5,
-0.5 0.5 -0.5,
-0.5 0.5 0.5,
0.5 -0.5 0.5,
0.5 -0.5 -0.5,
-0.5 -0.5 -0.5,
-0.5 -0.5 0.5
]
}
coordIndex [
0, 1, 2, 3, -1,
0, 4, 5, 1, -1,
1, 5, 6, 2, -1,
2, 6, 7, 3, -1,
3, 7, 4, 0, -1,
4, 7, 6, 5, -1
]
colorPerVertex FALSE
color Color {
color [
1 0 0,
0 1 0,
0 0 1,
1 0 1,
1 1 0,
0 1 1
]
}
}
}
|
Vejam com funciona això. El field colorPerVertex diu si els colors s'assignaran als vértexs o a les cares de l'objecte. El posem a FALSE per tal que l'assiganció de colors sigui per cara.
A continuació el field color conté la llista de colors (RGB) que s'assignaran a les cares a través del node Color. Cal llistar els colors en l'ordre corresponent a l'ordre en que estan llistades les cares a coordIndex, ja que el VRML va aparellant cara amb color de forma consecutiva.
Pero si volem que la meitat de les cares siguin d'un color i la meitat d'un altre, no cal repetir el color per a cada cara. Es
pot utilitzar el field colorIndex de la següent manera:
|
Exemple3: Definició per cares i vértexs d'un cub unitari amb
3 cares blaves i 3 grogues.
Shape {
geometry
IndexedFaceSet {
coord Coordinate {
point [
0.5 0.5 0.5,
0.5 0.5 -0.5,
-0.5 0.5 -0.5,
-0.5 0.5 0.5,
0.5 -0.5 0.5,
0.5 -0.5 -0.5,
-0.5 -0.5 -0.5,
-0.5 -0.5 0.5
]
}
coordIndex [
0, 1, 2, 3, -1,
0, 4, 5, 1, -1,
1, 5, 6, 2, -1,
2, 6, 7, 3, -1,
3, 7, 4, 0, -1,
4, 7, 6, 5, -1
]
colorPerVertex FALSE
color Color {
color [
0 0 1,
1 1 0
]
}
colorIndex [
0, 0, 0, 1, 1, 1
]
}
}
|
Això el que fa es dir quin color li correspon a cada cara, a partir del número d'index que tenen els colors. Per tant, el VRML recorre cara per cara i va mirant a la llista d'indexos de colors del field colorIndex quin color li pertany a la cara.
Finalment veurem com assignar colors als vértexs de les cares. Això pot ser interessant per a crear degradats
de colors, o ombrejats. Vejam un exemple:
|
Exemple4: Definició per cares i vértexs d'un cub unitari amb
colors assignats als vértexs.
Shape {
geometry
IndexedFaceSet {
coord Coordinate {
point [
0.5 0.5 0.5,
0.5 0.5 -0.5,
-0.5 0.5 -0.5,
-0.5 0.5 0.5,
0.5 -0.5 0.5,
0.5 -0.5 -0.5,
-0.5 -0.5 -0.5,
-0.5 -0.5 0.5
]
}
coordIndex [
0, 1, 2, 3, -1,
0, 4, 5, 1, -1,
1, 5, 6, 2, -1,
2, 6, 7, 3, -1,
3, 7, 4, 0, -1,
4, 7, 6, 5, -1
]
colorPerVertex TRUE # No caldria posar-ho per que es el valor per defecte.
color Color {
color [
1 0 0,
0 1 0,
0 0 1,
1 0 1,
1 1 0,
0 1 1,
1 0.5 0,
0 1 0.5
]
}
colorIndex [
0, 1, 2, 3, -1,
0, 4, 5, 1, -1,
1, 5, 6, 2, -1,
2, 6, 7, 3, -1,
3, 7, 4, 0, -1,
4, 7, 6, 5, -1
]
}
}
|
Vejam el que hem definit. En primer lloc hem posat el field colorPerVertex a TRUE (cert) per que l'assignació de colors sigui per vértex i no per cara. Això no caldria fer-ho per que és la situació per defecte, però ho posem per claredat.
En segon lloc, ara el field colorIndex funciona de forma diferent. La llista que conté, és la llista
d'indexos de colors per a cada vértex de cada cara. És a dir, cada grup d'indexos acabat amb un -1
forma el conjunt de colors que se li assignen als vértexs de cada cara.
De forma similar a com hem definit objectes sòlids, també podem definir objectes enomenats de "filferro", és
a dir, objectes formats simplement per arestes (sense cares planes). Això es pot obtenir amb el
node IndexedLineSet.Vejam com
es definiria el nostre cub unitari amb aquest sistema:
|
| |||||||||||||||||||||||||||||||||
Cal tenir en compte que ara treballem amb arestes (lines) i que poden ser múltiples (polylines). Tal i com es veu en les taules, la llista d'arestes té dues polylines i quatre lines. Les dues primeres porduirien la part superior i inferior del cub respectivament. Com que ara ja no parlem de cares, cal especificar que la primera polyline cal que sigui tancada (cosa que no és obligatori en general) i per això cal especificar el segment 3 0 (i 5 8 en la segona).
Vejam com es faria en VRML:
|
Exemple5: Definició d'un cub unitari de filferro.
Shape {
appearance Appearance { material Material { emissiveColor 0 0.8 1 } }
geometry
IndexedLineSet {
coord Coordinate {
point [
0.5 0.5 0.5,
0.5 0.5 -0.5,
-0.5 0.5 -0.5,
-0.5 0.5 0.5,
0.5 -0.5 0.5,
0.5 -0.5 -0.5,
-0.5 -0.5 -0.5,
-0.5 -0.5 0.5
]
}
coordIndex [
0, 1, 2, 3, 0, -1,
4, 5, 6, 7, 4, -1,
0, 4, -1,
1, 5, -1,
2, 6, -1,
3, 7, -1
]
}
}
|
També es poden assignar colors diferents als diferents trams de polyline mitjançant el field color , field colorIndex i field colorPerVertex de manera anàloga a com s'ha fet abans. Es deixa al lector que faci proves amb aquests fields com exercici.
NOTA: En dibuixar objectes en filferro, cal utilitzar el field emissiveColor en lloc del diffuseColor en l'aparença.
A continuació donem un altre exemple on utilitzem les polylines per escriure "VRML".
|
Exemple6: Escriure "VRML" mitjançant polylines.
Shape {
geometry
IndexedLineSet {
coord Coordinate {
point [
-22 4 0,
-18 -6 0,
-14 4 0,
-10 -6 0,
-10 4 0,
-4 4 0,
-2 2 0,
-2 0 0,
-4 -2 0,
-10 -2 0,
-2 -6 0,
2 -6 0,
2 4 0,
6 0 0,
10 4 0,
10 -6 0,
14 4 0,
14 -6 0,
22 -6 0
]
}
coordIndex [
0, 1, 2, -1, # V
3, 4, 5, 6, 7, 8, 9, -1, 8, 10, -1, # R
11, 12, 13, 14, 15, -1, # M
16, 17, 18, -1 # L
]
colorPerVertex FALSE
color Color {
color [
1 0 0, 0 1 0, 0 0 1, 1 1 0
]
}
colorIndex [
0, 1, 1, 2, 3
]
}
}
|
De forma similar a com hem definit objectes sòlids i objectes de "filferro", també es poden obtenir punts
aïllats en l'espai, però que formen un sol objecte, amb el
node PointSet.Vejam com es definirien
els punts que formen els vértexs del nostre cub unitari amb aquest sistema:
|
Exemple7: Definició de punts a l'espai corresponents als vértexs
d'un cub unitari.
Shape {
appearance Appearance { material Material { emissiveColor 1 1 0 } }
geometry
PointSet {
coord Coordinate {
point [
0.5, 0.5, 0.5,
0.5, 0.5, -0.5,
-0.5, 0.5, -0.5,
-0.5, 0.5, 0.5,
0.5, -0.5, 0.5,
0.5, -0.5, -0.5,
-0.5, -0.5, -0.5,
-0.5, -0.5, 0.5
]
}
}
}
|
NOTA: Aquí també cal definir un material amb el field emissiveColor en lloc de
field diffuseColor.
Exercicis proposats:
|