All Categories :
VRML
Chapter 17
The VRML Art Gallery: A VRML World by Hand
-by Justin Couch
CONTENTS
You now have enough information to start creating your first large
VRML 2.0 world. In Chapter 2, "Up
and Running: First VRML Creation," you created everything
using readily available tools, which limited you to generating
1.0 worlds. Now that you've gotten this far, it's time to dust
off your favorite text editor because this VRML world is going
to be done all by hand.
One of the best things about virtual reality is that you don't
need to conform to traditional earthbound construction-you can
do whatever you want. I'm the sort of person who likes to experiment
with things, so this creation is going to be a virtual art gallery.
What am I going to put in this gallery? Well, my co-author has
been good enough to create the content for me:
- First, you need to plan what the gallery will look like, then
construct the basic outlines.
- After the gallery is constructed, add the content. You'll
collect the pictures, organize them, and offer a virtual tour.
- The basic gallery is still a little boring, so you can spice
it up with some extra links and scenery.
If you've been reading the preceding few chapters, many of the
pieces will look familiar to you. Once you've created a few worlds,
you will find that you've built up a library of parts you use
over and over. Now you'll see the reason for doing what seemed
like trivial examples in previous chapters; when you combine them,
you get quite a stunning scene.
So far in your collection of parts, you have a marble column,
a tree, an arrow floating in space, and a few lights and cameras.
Not much, but it's really all you need. It's amazing what you
can do with just a few basic parts. I also have eight images from
my co-author in my collection of pictures that I want to display.
A series of islands sounds like fun to me. Of course, since this
is virtual reality, they will have to float in space, too. The
islands will be connected by a series of wooden bridges, and the
marble columns can be used to act as a gateway.
Each island will be made from an IndexedFaceSet. You could have
used the ElevationGrid to create the islands, but to get a real
3D look, I didn't want all the islands to be the same height.
Using IndexedFaceSets allows you to create a floating island that
can be viewed from all angles.
The first island is easy. It's almost a cone, but if you use a
face set, you can control some of the properties.
- Declare the list of vertices that you want to make the island
from. The island will have an octagonal base and a single-point
vertex at the top in the center.
- Next, join the vertices so you get a triangular face that
has the base as one side of the octagon and the top as the single
center point. There should be eight of these.
- Create the base by making a single large face that has the
edges of the octagon as the face's edges.
- Put this all into a Shape node and make the material color
green-the islands must be grass-covered, after all.
- Load the single island and move around it, checking that each
face is visible. If not, then reverse the order of the vertices
declared in the coordIndex field. Don't forget to check the base
as well.
The island declaration is given in Listing 17.1.
Tip |
Make note of the order that the vertices are declared in the coordIndex field. If they were declared in the opposite order (for example, 8, 0, 1, 0), the island would become invisible when you moved over the top of it. Normals aren't specified for the face, so the renderer works it out. If you have problems with the face not appearing when you expect it to, then try reversing the order.
|
Listing 17.1. The basic island.
#VRML V2.0 utf8
#
# A simple island constructed from an IndexedFaceSet
Shape {
appearance Appearance {
material Material {
diffuseColor 0.1 0.5 0.2
emissiveColor 0.05 0.1 0.05
}
}
geometry IndexedFaceSet {
coord Coordinate {
point [
20 0 0, 15 0 15, 0 0 20, -15 0 15, -20 0 0, -15 0 -15, 0 0 -20,
Â15 0 -15,
0 10 0
]
}
coordIndex [
8, 1, 0, 8, -1,
8, 2, 1, 8, -1,
8, 3, 2, 8, -1,
8, 4, 3, 8, -1,
8, 5, 4, 8, -1,
8, 6, 5, 8, -1,
8, 7, 6, 8, -1,
8, 0, 7, 8, -1,
0, 1, 2, 3, 4, 5, 6, 7, 0, -1,
]
}
}
Creating More Islands by Reusing Objects
If you wrote out all the code for the object every single time
you used the file, it would soon get out of hand. With VRML, you
can reuse an object in the file by naming it, then using that
name when you need the object again. This method applies to any
node in the scene, which could be anything from a material to
a script.
To name a node, place the keyword DEF
and the name in front of the node you want to reuse. To use it
somewhere else, insert the keyword USE
and that same name. Yes, you've seen these keywords before. In
Chapter 15, "Sprucing Up Models with
Textures and Materials," when you texture-mapped the cylinders
to make the marble column, you reused a single cylinder and scaled
it to fit with the other cylinders.
Now create four more islands to go into the scene. The first island
was based around the origin, so move it by placing a Transform
node around it. You'll do the same thing when you clone the island,
so that means you need to use the DEF
keyword on the Shape node, then insert the USE
keyword in the children of the other Transform nodes. Listing
17.2 shows how to do this:
Listing 17.2. Reusing parts of the scene graph with the DEF
and USE keywords.
Transfrom {
translation 0 -20 0
children [
DEF island Shape { # rest of shape definition
}
]
}
transform {
translation 50 0 0
children [ USE island ]
}
When you use the keyword USE
on an object, you're creating a reference to the original, not
a copy of it. This can be both bad and good. By creating a reference,
if any properties of the original change, every other version
with the USE keyword will
change as well. If you've declared many instances of the one object
and you want them all to change color together, then this is an
effective technique. Change one, and you change the rest. Of course,
creating a reference has its bad points, too, because this method
might cause unwanted side effects. Basically, keep use of the
USE keyword to the minimum
you need to get the effect you want. In the previous example,
you used the DEF keyword
on just the Shape node, rather than the whole Transform node,
because that was all that was necessary.
If you've seen the basic layout of the world already, you'll notice
that I have placed four islands at one level and a fifth one at
a different level. How should they be connected? I think a set
of stairs would work nicely between them. Sticking to the theme,
these stairs should just be floating in space. Make the stairs
from boxes, and use the texture Bubsy used on the background of
his pages to give them that surreal industrial look.
To construct the stairs, follow these steps:
- Create a very thin single box.
- Add the texture of the safety metal to the box, using the
ImageTexture node in the appearance field.
- Create a series of boxes with each one offset from the next
one below it to produce a single staircase.
- Take copies of the completed staircase and place them on each
of the four sides that lead from the central island to the elevated
ones.
Each one must be offset from the previous one, which you can declare
in two different ways. The first method is to create several individual
Transform nodes, putting the stairs at a fixed offset in relation
to the origin or some other point in space. The second method
is to position the first stair, then offset each subsequent one
in relation to the one below it (assuming you build the staircase
from the bottom up). I prefer the second method, because if you
move the second stair, for example, then the rest automatically
move to stay in the same relative position.
Once you've created the first staircase, then you want to copy
it for the other staircases between the islands. Here's what I
did:
Transform {
translation 21 -20 0
children [
DEF stair_group Group {
children [
DEF a_stair Shape {
appearance Appearance {
texture ImageTexture { url "safety_metal.jpg" }
}
geometry Box { size 2 0.1 6 }
}
Transform {
translation 2 2 0
children [
USE a_stair
Transform {
# etc etc for the stairs
}
]
}
}
]
}
Transform {
translation 0 -20 -21
rotation 0 1 0 1.57
children [ USE stair_group ]
}
The tricky part to copying this staircase is that you need to
use both the first untransformed step (as the base point) and
the rest of the staircase. To do this, you must put a wrapper
around both of them. Use the Group node as this wrapper; it has
no function other than to collect a group of nodes together so
you can use the DEF keyword
on them. See how much cleaner the code has become when you get
ready to add the stairs to the other islands?
Now connect the top islands with some wooden planks. By now you
should know what to do-first, declare a single box with a wood
texture, use the DEF keyword,
then translate it into position.
Now that you have a basic world up and running, you need to put
some pictures in it. I've chosen eight pictures from the first
part of the book that I want to put in the upper levels of the
islands. For now, I'm going to leave the bottom level empty.
Putting in the Pictures
Each of the pictures is a different size, so this time you can't
use the DEF and USE
keywords to save file space. Each image requires a box of its
own. I used boxes rather than face sets to get the image on both
sides without any effort. Later, you'll use this effect when doing
guided tours.
To create an individual picture, you need to do the following:
- Create a thin vertical box.
- Apply the appropriate image as a texture, using ImageTexture.
- Adjust the size of the box to maintain the correct aspect
ratio of the image.
- Place it on an island by using a Transform node. At the same
time, you want to add a rotation so that the viewer needs a separate
viewing position for each image in the world.
Creating separate boxes for each picture makes it even more "fun"
when you're writing files by hand. It's a continual process of
adjusting and reloading the files so that everything looks right.
One of the many tasks involved was readjusting the boxes so that
the corners weren't sticking into the island's hills. You'll discover
similar problems when creating your own worlds.
Adding the Basic Guided Tour
If you don't specify a default viewpoint, then the browser puts
you quite a distance away. To avoid this, add a viewpoint to the
file. The first one declared is the default entry; in this case,
it starts you off in the middle of the center island.
This is an art gallery, so everyone wants to view the pictures.
In a real-life tour of an art gallery, people stop to look at
the pictures, so you should, too, in your virtual gallery. For
each picture, I created a viewpoint about 4 meters away looking
straight at it. It's worth the planning effort to make sure you're
facing in the correct direction. The amount of time you spend
adjusting everything to get that right look can be huge, so a
little planning never hurts.
Once you have these viewpoints, put them in a logical order so
that the tour makes sense. You don't want visitors to your gallery
jumping randomly around the scene. In Chapter 23,
"Real-Life Examples: A 3D Gallery: An Advanced VRML World,"
when you continue developing this scene, you'll offer an automated
guided tour. Having the viewpoints logically defined already will
make automating the tour easier.
Although developing this world has been fun, remember that you
need to make it a worthwhile place to visit, too. Since I've used
my co-author's pictures in the gallery, it makes sense to link
the pictures back to some description. In this case, I've set
the links up to point to the corresponding file on the CD-ROM
where that image was created.
- Create the basic image and box in the scene, as you normally
would.
- Decide which page you're going to be linking it to.
- Build the Web pages.
- Place an Anchor node around the geometry you built in Step
1.
I found one of the images on the POVRay site, so I've supplied
a link back to its home page so you can see where it came from.
In Chapter 13, "Exploring VRML Browsers
and Development Tools," you learned about the Anchor node;
now you get to use it properly for the first time. Surround each
of the pictures' Transform nodes with an Anchor-that's all you
need to do to provide links. For example, the Anchor declaration
for the picture linking back to the POVRay site looks like the
following:
Anchor {
url "http://www.povray.org/"
children [
# place the code to produce the picture here
]
}
For this chapter, all the links are to other HTML files. You could
make the links point to another VRML file, as demonstrated in
a previous chapter. There's no need to use the parameters field,
either, because this is just a pure VRML document. It is possible
to create worlds that use HTML frames. The next workshop, in Chapter 23,
explores the use of multi-framed documents combining VRML and
HTML.
A few things are still missing in your VRML world. Every world
you've created so far has had a black background. For some people,
this is fine, but basic black can get a bit boring. Try spicing
up the background a bit with the Background node.
The Background node is very handy; by using it, you can specify
pictures or a color gradient for sky colors. You can even use
a combination of colors and pictures. I like the idea of those
islands up in space, so I found a star picture I'm going to use
as the background. To do this, put the URL of the image file in
the Background node, as shown here:
Background {
eventIn SFBool set_bind
exposedField MFFloat groundAngle []
exposedfield MFColor groundColor []
exposedField MFString backUrl []
exposedField MFString bottomUrl []
exposedField MFString frontUrl []
exposedField MFString leftUrl []
exposedField MFString rightUrl []
exposedField MFString topUrl []
exposedField MFFloat skyAngle []
exposedField MFColor skyColor [ 0 0 0 ]
eventOut SFBool isBound
}
Which one of the six fields for holding image file URLs do you
pick? Usually, you choose the ones defining the sides. The background
pictures are mapped onto a box surrounding the world, with each
URL referring to one side of the box. If you want, you can specify
a different image for each side. In this world, I wanted the whole
lot to appear in a star field, so I put the same image file URL
in all the url fields.
The other method of putting in a background is specifying a collection
of colors and angles. You need to supply one more color than the
number of angles because the colors go between a pair of angles,
giving a ring effect. There are two fields: one for the ground
and the other for the sky. You can combine the images and colors
together. If you don't specify an image, then the color is used.
Therefore, a common tactic is specifying the images around the
sides but letting the sky/ground color show through on the other
two-the top and bottom for the box that defines the background.
You want the star background to totally envelop the world, so
the same declaration goes in each of the URL fields and nothing
goes in the color field.
Sometimes you want to create your model in a scale that's different
from what's normal. For example, a chemical model would be no
good drawn at real scale. However, you need to consider the problem
of fitting the user to the scene. The NavigationInfo node is used
to give the browser some basic information about the properties
of the user in the scene:
NavigationInfo {
eventIn SFBool set_bind
exposedField MFFloat avatarSize 1.0
exposedField SFBool headlight TRUE
exposedField SFFloat speed 1.0
exposedField MFString type "WALK"
exposedField SFFloat visibilityLimit 0.0
eventOut SFBool isBound
}
The user can set the size, as well as other basic properties.
By now, you've probably discovered the options available by clicking
the right mouse button. Several of these options can be predefined
when the scene is loaded by specifying the values in the NavigationInfo
node. A detailed description of all the options is given in Chapter 13.
When you start talking about virtual reality, you'll see the word
avatar pop up quite frequently; it refers to the user's
representation in the virtual world. The avatar is what other
people in the world see and also how the world reacts to your
presence as you navigate through it.
The avatarSize field is particularly important in most VRML files.
It contains several values that specify how the avatar will behave.
The first value is your collision radius-how close you can get
to objects. The second value defines how high your "eyes"
sit above the terrain. VRML 2.0 allows you to define a terrain
by using the ElevationGrid node. As you wander over one of these
nodes, the browser maintains the specified distance above the
ground.
If you have collision detection running, then the third value
defines what the maximum step height is that the user can negotiate.
Anything higher than this value and you will have to make the
avatar negotiate (fly?) the obstacle. In the world you designed,
the steps are 2 meters apart, so the step height needs to be more
than 2 meters so you can "walk" up the stairs without
any extra effort. However, in this scene I didn't add collision
nodes to the stairs. Feel free to do this and experiment with
the results.
Visibility limit, specified in the visibilityLimit field,
defines how far you can see. If you have a very large world, then
the value supplied in this field is important. If it's too small,
then the visibility limit would cut out a lot of the scene that
might need to be rendered. The headlight field sets the default
state for its use, and the type field specifies what sort of navigation
you want to do. The types of navigation available were defined
in Chapter 13 and include the types Walk,
Examine, and Fly.
The island in the middle is still a little blank, so to spice
it up a bit I'm going to drag out the tree and marble columns
from previous chapters and place them on the island. The columns
will form archways leading to the stairs, and I'll add a block
across the top of the columns to complete the arch. For consistency,
the blocks use the same marble texture.
Now I get to have a bit of fun. For each staircase, I'm going
to put a message up as well. VRML does have a 3D text function,
but getting the text to line up can be tricky. The most reliable
method is to create the individual signs as transparent GIF images,
using all the 3D effects you've learned from my co-author, and
then place them on a plane that sits very close to the top block.
One of the benefits of taking this approach is that you can create
shadowed highlights you wouldn't normally get from creating the
scene in VRML 3D text.
Adding Information to the Scene with WorldInfo
The final node covered in this chapter is WorldInfo. This one
doesn't display anything on the screen; it just contains a series
of text strings. The title field is the world title that normally
appears in the browser's title bar. It has the same effect as
the <TITLE> HTML tag.
If you want to store other information, like copyright notices,
in the scene, then you put this in the info field. The browser
might take this information and display it in a separate dialog
box, like the infamous About box. A proposal has been put forward
to place meta information in the info field, as well. The proposal
uses essentially the same fields and names as the <META>
tag. At this stage, it's not a recommended use of the info field,
but it is valid nonetheless.
There you have it-your first fairly large VRML world. The sample
file was created all by hand; not a single modeling tool was used.
Most of the file is consumed by the definition of each object
type. Once you have the definition, then it's repeatedly cloned
with the USE command. Imagine
how much bigger the file would be if you had to declare each object
explicitly.
With a bit of effort and time, you can create very cool worlds
like the one presented in this chapter. Apart from the face sets
for the islands, the rest of the scene was constructed using just
the basic primitives with some color and textures thrown in. Careful
design in the first place means you can spend more time playing
around with things later. Also notice how I've used the viewpoints
to act as a guided tour in a logical sequence around the art gallery,
rather than use random ordering. Details like this are what make
the difference between an average world and a good one.
Next Steps
Now that you've mastered the basics of VRML, it's time to move
on to the more advanced topics covered in Part V, "Advanced
VRML Techniques":
- The next chapter takes a look at optimizing your worlds for
use on the Internet.
- Then the fun and games begin. Chapter 19,
"Using Built-in Animation Techniques," starts the ball
rolling, literally. You learn how to create basic animations in
a scene by using the built-in VRML animation techniques.
- When the built-in techniques aren't enough, then you need
to create your own. Chapter 20, "Interfacing
VRML Worlds with Scripts," introduces the concept of the
Script node and also looks at one language to write be-haviors
in.
- If you're really keen to see what can be done, then head straight
to Chapter 23, "Real-Life Examples:
A 3D Gallery: An Advanced VRML World," where I continue to
develop this scene to include behaviors and other interesting
features.
Q&A
Q: | Did you really write that whole scene by hand?
|
A: | Yes. All I used was Notepad with Netscape 2.02 with CosmoPlayer beta 1a. There were some serious memory leaks that resulted in having to shut down Netscape and restart it; however, they were the only two tools used. A lot of the pieces I just pinched from other files-like the columns and trees-so this makes the development time much shorter. Once you're happy with the basic design, then it's just a matter of using a Transform node to move copies around the scene graph.
|
Q: | Where did you get the textures from?
|
A: | Apart from the sign textures-which were created in Paint Shop Pro-everything can be done just by using standard textures and pictures straight from the Internet. As you can see, all the big pictures came straight from my co-author without any modifications. These days most of the modeling tools come with a collection of textures and images that can be used to create your worlds with. Also check out places like Netscape's background texture page or one of the Internet search engines for other places.
|
Q: | What other sorts of things can I do with VRML? This 2.0 stuff looks just like the 1.0 worlds. Why do I need to upgrade?
|
A: | VRML 1.0 is designed only for static scenes. So far, what you've covered is the equivalent functioning of 1.0, but with the 2.0 syntax. In the next part of the book, you get into what this latest version is all about: creating moving worlds.
|