#VRML V2.0 utf8
#pointset.wrl
#Demonstrates use of a simple pointset
Shape {
appearance Appearance {
material Material {
# note emissive color makes these dots easier to see
emissiveColor 1 1 1
} # end material
} # end appearance
geometry PointSet {
coord Coordinate {
point [
#base of pyramid
-2 0 2,
-2 0 -2,
2 0 -2,
2 0 2,
#point
0 2 0,
] # end point
} # end coord
} # end geometry
} # end shape
# force browser into 'examine mode'
NavigationInfo{
type "EXAMINE"
}
Notice that there is a new node in the geometry node. It is a PointSet.
The pointset consists of a coordinate node. The next few geometries
we look at will use this node. In this simple form, it holds an array
of points. The points are coordinates in 3D space. Note that I used
comments to describe where the points were. This becomes increasingly
important as we do more with these pointsets.
The pointset itself is of limited use. We might use it to simulate constellations in an observatory (oooh, we could animate their motion realistically!!) or perhaps we could use them to simulate electrons in an atom. Both these applications would be stronger with animation, so let's hold off on that for a while longer.
On a practical note, you may have noticed that rather than using diffuseColor as I usually do, I went with emissiveColor in this model. That was done because diffuseColor describes how light reflects off of a surface. While that can be very effective with 3d objects, it causes some problems when I'm working with points, which are hard to see even if they are not shaded. EmissiveColor essentially turns 'off' the shading, as if this object was eminating the color from within. We will talk more about lighting and shading in another lesson. The concept here is this: If the shading effects are making it hard for you to see what's going on in a model, try switching to emissiveColor.
#VRML V2.0 utf8
#lineset.wrl
#Demonstrates use of a simple indexed lineset
Shape {
geometry IndexedLineSet {
coord Coordinate {
point [
#base of pyramid
-2 0 2, # point 0, left and close
-2 0 -2, # point 1, left and back
2 0 -2, # point 2, right and back
2 0 2, # point 3, right and close
#top of pyramid
0 2 0, #point 4, top of pyramid
] # end point
} # end coord
coordIndex [
#base
0, 1, 2, 3, 0, -1,
#vertical edges
0, 4, -1,
1, 4, -1,
2, 4, -1,
3, 4, -1,
] # end coordIndex
} # end geometry
} # end shape
As you can see, this model was built on the last one. The geometry
node containes an IndexedLineSet node, which holds a coord node and a
coordIndex node. The coord node is just like that in the pointset.
It holds an array of points in 3-space. The coordIndex node is like a
'connect the dots' game. The base is drawn by connecting the four
points at the bottom of the pyramid. Essentially, we have said "draw
from point 0 to 1, then 1 to 2, to 3, back to 0."
The -1 tells the browser we are done drawing this set of lines.
The remaining code fragments draw edges from each of the bottom
vertices to the point of the pyramid.
Indexed line sets are terrific for making wireframe models. Because all the computer has to draw is lines, and the lines are not shaded, such models are typically very quickly drawn. Unfortunately, wireframe drawings are difficult to understand once they get complex.
#VRML V2.0 utf8
#faceeset.wrl
#extends previous examples to make a faceSet
Shape {
appearance Appearance {
material Material {
diffuseColor 1 1 1
} # end material
} # end appearance
geometry IndexedFaceSet {
solid TRUE
coord Coordinate {
point [
# the pointset hasn't changed
#base of pyramid
-2 0 2, # point 0, left and close
-2 0 -2, # point 1, left and back
2 0 -2, # point 2, right and back
2 0 2, # point 3, right and close
#top of pyramid
0 2 0, #point 4, top of pyramid
] # end point
} # end coord
coordIndex [
#base
#note that now it is CRUCIAL that I go counter-clockwise
#from the OUTSIDE.
0, 1, 2, 3, 0, -1,
#vertical faces
#now rather than defining the edges, I am describing the faces
0, 4, 1, -1, # left side
1, 4, 2, -1, # back side
2, 4, 3, -1, # right side
3, 4, 0, -1, # front side
] # end coordIndex
} # end geometry
} # end shape
NavigationInfo{
type "EXAMINE"
} # end NavigationInfo
You can see what is happening here. This is quite similar to an
indexed line set, except that the coordIndex now represents FACES or
polygons, rather than lines. This distinction is really important.
You had a lot more options in a line set. You could, for example,
define each line of the base independantly. When you are defining a
faceset, all the vertices that describe a polygon must be defined. In
addition, you must be careful about the order in which the lines are
described. The VRML browser tries to save time by drawing only one
side of each face if the entity you are describing is solid (which is
the default.) In this case, the pyramid will be closed. There should
be no reason for the browser to draw and shade the INSIDE of the
pyramid, just the outside. By using this feature, we are cutting our
processing requirements in half. This can make a HUGE difference when
we work with large or complex facesets.
We tell the browser which side of the face to draw by following a special convention: When describing the face, list the vertices in counter-clockwise order around the polygon. The counter-clockwise face is the one that will be drawn. The face you would see if you describe the points in a clockwise rotation will not be drawn.
Wow.
This seems scary, and it can be a pain to work around, but it is worth
the effort.
If you are doing a very simple model, and you don't mind the extra processor time, you can set the SOLID node of the IndexedFaceSet to FALSE. This will draw BOTH sides of every polygon, costing more processor time, but not requiring you to be so careful about counter-clockwise description of your faces.
Sometimes you might describe an open shape that will require both sides of every polygon to be drawn. In that case, you will need to specify the solid node as FALSE. That is really why you are allowed to make the solid node false.
You guessed it. Take a look at the code below:
colorFaces.wrl
#VRML V2.0 utf8
#colorFaces.wrl
#extends previous examples to illustrate color indices
# make N and S faces Red, E and W blue, and bottom green.
Shape {
geometry IndexedFaceSet {
solid TRUE
coord Coordinate {
point [
# the pointset hasn't changed
#base of pyramid
-2 0 2,
-2 0 -2,
2 0 -2,
2 0 2,
#point
0 2 0,
] # end point
} # end coord
coordIndex [
#base
#note that now it is CRUCIAL that I go counter-clockwise
0, 1, 2, 3, 0, -1,
#vertical faces
#now rather than defining the edges, I am describing the faces
0, 4, 1, -1,
1, 4, 2, -1,
2, 4, 3, -1,
3, 4, 0, -1,
] # end coordIndex
colorPerVertex FALSE
color Color {
color [
#defining a palette of colors to use in the colorIndex
1 0 0 # color #0 is red
0 1 0 # color #1 is green
0 0 1 # color #2 is blue
] # end inner color group
} # end color node
colorIndex [
# make the 0th face green (color 1)
# make the 1st and 3rd faces red (color 0)
# make the 2nd and 4th face blue (color 2)
1 0 2 0 2
] # end colorIndex
} # end geometry
} # end shape
Upon examining the code, you no doubt noticed that this starts out
just like a normal IndexedFaceSet. Things get a little strange in the
color node. So far, this is the most obtuse syntax I have found in
VRML. It's hard to get used to it, but all you really have to do is
copy the structure and change it to fit your needs.
Anyway, here's how it works: The IndexedFaceSet contains a color field, which is usually filled by a Color (note the capitalization) node. This is not too unusual; remember material Material and appearance Appearance?
The Color node contains a field ALSO called color, but this thing holds an ARRAY of colors. (I would have called it colorList or colors, but nobody asked my opinion). This is just a place to store a palette of colors to use later. Note that I kept track of the index of each color in a comment. They are always numbered from 0 to n-1 (when there are n colors being described). You will see why keeping track of the numbers matters in just a moment.
The next field is the colorIndex. It expects an array of integers,
with the same number of values as there are faces in the shape. It
looks at the first value, and assigns the corresponding color to the
first side. The next color is assigned to the next side, and so on.
Yeah, I know, it's a little strange. Try playing around with the
values below:
#VRML V2.0 utf8
#colorVertex.wrl
#extends previous examples to illustrate color indices
# This time we will illustrate color by VERTEX
Shape {
geometry IndexedFaceSet {
solid FALSE
coord Coordinate {
point [
# the pointset hasn't changed
#base of pyramid
-2 0 2, # vertex 0
-2 0 -2, # v 1
2 0 -2, # v 2
2 0 2, # v 3
#point
0 2 0, #v 4
] # end point
} # end coord
coordIndex [
#base
0, 1, 2, 3, 0, -1, # line 0
#vertical faces
0, 1, 4, -1, # l1
1, 2, 4, -1, # l2
2, 3, 4, -1, # l3
3, 0, 4, -1, # l4
] # end coordIndex
colorPerVertex TRUE
color Color {
color [
#defining a pallette of colors to use in the colorIndex
1 0 0 # color #0 is red
0 1 0 # color #1 is green
0 0 1 # color #2 is blue
] # end inner color group
} # end color node
colorIndex [
# now the colorIndex values are applied to VERTICES, not faces.
1 0 2 0 1 -1
1 0 2 -1
0 1 2 -1
1 0 2 -1
0 1 2 -1
] # end colorIndex
} # end geometry
} # end shape
Here's the strategy for devising a faceset from a floorplan.