Contributors

VRMLworks

comp.lang.vrml FAQ Answers
5. Techniques

  1. How do I embed a VRML world in a frame or a web page?

    There are two ways to have both 2D text and graphics and a 3D VRML world on the same web page: putting the world in a frame and embedding it in a webpage.

    In the first case, you use the <FRAME> tag inside the <FRAMESET> container tag. You can find documentation at the HTML Compendium (among other places) for the grammar and options of the <FRAME> tag and the <FRAMESET> tag.

    Example: <FRAME SRC="my.wrl" NAME="vrmlframe">

    In the second case you use the <EMBED> tag.

    Example: <EMBED SRC="my.wrl" WIDTH="500" HEIGHT="280">

    The <OBJECT> tag is preferred in HTML 4.0. Here's an example from Braden McDaniel which works in MSIE 4.0 but not Netscape Navigator or Communicator:

    <OBJECT DATA="foo.wrl" TYPE="model/vrml" WIDTH="320"
       HEIGHT="240" STYLE="width: 100%; height: 100%">
    <PARAM NAME="SRC" VALUE="foo.wrl">
    Alternate content goes here.
    </OBJECT>

    Braden reports that you can use percent values for width and height, which is not valid HTML, but which both Netscape Communicator and Microsoft Internet Explorer 4.0 will accept.

  2. How do I spawn off a new little window for my VRML world?

    A JavaScript script will do this:

    <SCRIPT LANGUAGE="JavaScript">
    <!-- You know why
    function newWindow(width, height, world) {
      window.open(world,'vrmlWindow','width='+width+',height='+height);
    }
    // -->
    </SCRIPT>

    And later on in the page:

    Click <A TARGET="_self" HREF="javascript:newWindow(300,200,'foo.wrl')">here</A>

    Note that the "TARGET=" field isn't necessary unless you've got another TARGET in your HEAD container.

    David Frerichs of Cosmo Software says that you should always control the size of the display window, either this way or by embedding it in a frame with a fixed height and width, so that you have better control over the speed and detail of your world. I've followed his advice in this FAQ.

  3. How can I let the user click on something and fire up a web page or another VRML world in a different window or frame so she doesn't have to keep reloading the VRML world?

    In the specification for the VRML 2.0 Anchor node, there's a "parameter" field. You use it like this:

      Anchor {
        url "http://vrmlworks.crispen.org/faq/"
        description "Click here for the VRML FAQ"
        parameter "target=newpage"
        children [
          Wally
          The_Beaver
        ]
      }
    

    If you have a frame named "newpage", then the Anchor's reference (in the example, this FAQ) will come up in that frame. If you don't, then Netscape and Internet Explorer will launch a new browser window and name it "newpage". That means that if you have several Anchors all pointing to "newpage", you'll only bring up one extra window on the visitor's screen instead of littering her screen with extra windows.

    There is nothing special about the name "newpage". It's not a reserved target name in HTML. It was chosen because it's not likely to be the name of a frame. If you use the name of an existing frame on your page, VRML browsers that support this feature will cause the text to load in the frame you name. This is very useful for web pages that consist of both text and VRML and allows you to change the text by clicking on an object in the VRML world.

    Note that VRML browsers aren't required by the spec to support "target=" in the parameter field, but since it's listed as an example in the spec, and since it's so useful, all VRML browsers I know of do support it.

  4. Can I get rid of the VRML browser's control panel?

    There is one way that's absolutely independent of the VRML browser that visits your world:

    NavigationInfo {
      type [ "NONE" ]
      ...
    }

    In this case you will need to provide some VRML objects (see the answer to another question) that your visitor can use to navigate through the world.

    Cosmo Software and Intervista support the following extra parameters in the EMBED tag:

    WorldView:

        <EMBED SRC="my.wrl" WIDTH="500" HEIGHT="280" VRML_DASHBOARD="FALSE">

    Cosmo Player:

        <EMBED SRC="my.wrl" WIDTH="500" HEIGHT="280" VRML-DASHBOARD="FALSE">

    Murat Aktihanoglu reports that if you use the <OBJECT> tag, as in the answer to a previous FAQ, adding

    <PARAM NAME="VRML-DASHBOARD" VALUE="FALSE">

    will work. Note that using any browser-specific parameter is generally a bad idea unless you can guararantee that only the users of a particular browser will ever visit your VRML world. You gain the ability to let the visitor navigate without seeing the dashboard, and without your doing the work of providing alternate navigation controls, but you lose universality and can alienate the visitors to your world who have the "wrong" browser.

  5. How do I make a substitute for the VRML control panel that will always stay in front of the visitor?

    This is sometimes called a heads-up display or HUD and can contain controls, displays or both.

    Here are two examples you can download: a simple HUD by Chris Fouts [download] and a slightly more elaborate HUD by Flounder [download]. Chris's is elaborately commented and I've modified Flounder's example, which originally displayed the numbers rounded off, because different VRML browsers generate string values in JavaScript differently, making the results of rounding difficult to guarantee across platforms. The answer to another FAQ shows some controls in a HUD.

  6. I can't get [createVrmlFromURL/createVrmlFromString] to work.

    If you're using Java, the best tutorial is Justin Couch's tutorial here at the VRMLworks. If you're using ECMAScript, look at this example [download] which uses createVrmlFromString() -- click on the cube to add the children or this example [download], which uses createVrmlFromURL() -- approach the yellow cube and it turns into a red sphere.

  7. How do you bind Viewpoints?

    Although it's possible to ROUTE a sensor's isActive eventOut to a Viewpoint's set_bind as we do in this example [download VRML and texture] (approach the disc and be taken on a tour around the sacred head of "Bob"), pull back away from the disc as it's moving to see why this is a bad idea. The jump from the disk (if the browser lets you do it) is disorienting. In other applications, if the visitor wanders too far away from the sensor that's causing the viewpoint to be bound, he could jump back to the original viewpoint. It's far better to ROUTE the sensor's isActive eventOut through a diode Script. There's an example of a diode Script in the answer to another FAQ.

    It's called a diode because it only passes TRUE values. By putting the diode between the sensor and the viewpoint, you keep the viewpoint bound even when the visitor moves out of the sensor's range, and the user doesn't pop to a different place in the scene unexpectedly.

  8. How can I take my visitor for a ride in a [car/balloon/spaceship/elevator]?

    The answer to the previous FAQ has an example of taking the visitor for a ride. The duck [download (tar.gz)] at the VRML 98 website has an even more elaborate ride (wait till everything loads, then click on the duck to take the ride). Basically, you bind the viewpoint to a viewpoint that's the child of an object that you animate. Notice that after the duck gets to the castle, a ProximitySensor by the castle binds the viewpoint (through a diode) so that the duck can fly away and leave the visitor behind without snapping the visitor back to the mountain top.

  9. How can I make my VRML world faster?

    There's a page at the VRMLworks that discusses this question in detail and points to some excellent tutorials and articles. How fast is fast enough? Here's what Rikk Carey said on www-vrml not long ago:

    Frames per second Effect

    20-60

    Perfect illusion, fully 3D experience, dream-like clarity

    12-20

    Reasonable illusion of 3D, good enough

    8-12

    Operable 3D interface, subconscious frustration, boat-like navigation, ok for design/expert tool

    1-8

    Unusable 3D interface, poor navigation, conscious frustration, in need of different UI techniques (e.g. Myst)

  10. I want the visitors to my site to see a VRML banner ad if they have a VRML browser, but if they don't, I want to show them an animated GIF. How do I do that?

    Ligos has a free VRML Detector that will detect VRML browsers in Netscape Navigator/Communicator and Microsoft Internet Explorer and will show them the appropriate content. John Fairley of Platinum Technology has written another VRML Detector with the help of some members of www-vrml.

  11. How do I make a viewpoint track an object as it moves around my world?

    Tom Kaye of SGI's Huntsville office has developed a camera tracking PROTO.

  12. How can I make VRML worlds communicate through sockets?

    David McLure has written an article on this that includes some sample implementations. The DIS-Java-VRML Working Group has developed some applications in Java that communicate via sockets and solve some of the Java security problems.

  13. Is it possible to morph shapes in VRML?

    Yes, through a CoordinateInterpolator. Here's an example of a dolphin [download] in which each of the points morphs. I turned the famous dolphins [download] from the Avalon Repository into one morphing dolphin.

  14. How do I figure out the magic numbers to plug into the orientation field of a Viewpoint node to make the camera point to where I want it?

    Here are two answers. The first is for people who want to understand the "magic numbers". The first three numbers in the orientation field are a vector that describes which way up is. But wait a minute; three numbers describe a point; how can they describe a vector? Easy. The other point in the vector is the origin (0,0,0). The vector is nominally a unit vector, but I don't know of any VRML browser that complains if the length of the vector isn't 1. The fourth number is the rotation about that vector, using the right-hand rule (point your right thumb along the line from the origin to the point you described with the first three numbers, and the direction your fingers curl is a positive angle).

    The second answer is for people who don't remember their high school math. Instead of figuring out what the numbers mean, use Stephen Chenney's orient (C source code and Win95 executable).

    Some object modelers and scene modelers will let you fly your camera to a point in the scene, orient your view, and then set that as a Viewpoint node.

  15. How do you make addChildren and removeChildren work?

    Here are two examples: one that uses addChildren [download] and one that uses removeChildren [download]. In both examples, click on the yellow cube.

  16. How do you put a texture on one side of a box?

    This is easier to demonstrate than to explain. Here's an example [download].

  17. How do you make things disappear when you (e.g.) click on them?

    The quickest and probably the best way is to use a Switch node and a Script. In this example [download], click on the yellow cube and it disappears. You can also:

    but all those methods put an unnecessary load on the browser, since the browser will still have to do the computations to render the object (or at least determine if it's visible). You can also use removeChildren, but that would be overkill, especially if you ever want to make the object reappear. Finally, an LOD is also a kind of sensor, and you could make the object disappear when you approach it by having an empty Group node in the range field.

    Slightly different code in the script in our example could make an object appear or make one object disappear and another appear.

  18. Is there any way to get the user's position in real time?

    The second example in a previous answer shows the user's position. Note that the user's orientation is also available from the ProximitySensor and can be displayed the same way.

  19. When I set solid to TRUE, I only see one side of an object. It isn't solid at all!

    Yup. That one confused me too at first. The solid field tells the browser that your object is solid and that it only needs to render one face. That's the default. Unless you have objects without thickness and need to show both sides, leave it alone.

  20. Can you use VRML worlds in a C++ or Java application?

    Open Worlds has a C++ toolkit that allows you to develop a stand-alone application that can view and manipulate VRML worlds. [I'd be glad to note the names of other companies who are working on similar toolkits.] A number of VRML browsers, among them Cosmo Player 2.1, WorldView 2.1, and Blaxxun CCPro 3.x, can use Microsoft's COM to interface between the VRML browsers and applications.

    Justin Couch has a set of classes called JVerge that replicate the VRML 97 nodes as individual Java classes.

    Intervista has a package WorldView for Developers that lets you develop applications in C++, Visual Basic, Java, and Macromedia Director Xtras and use WorldView as an embedded VRML application.

    Open Inventor from Silicon Graphics can use their own nodes, VRML 1 nodes, and (this is relatively new) VRML 97 nodes.

  21. How do you write Script nodes in [Visual Basic/Ada/COBOL]?

    First of all, think about security. You're asking the visitors to your world to run an application on their machines when they don't know you from Adam. You need to give the visitor some assurance that your Script won't format their disks or swipe their collection of dirty pictures. The surest way to do that in Netscape Navigator is to use Java, which runs in Netscape's security "sandbox". But you needn't code in Java. There's a list at developer.com of [x]-to-Java cross compilers and, yes, Ada, Visual Basic and even COBOL are on that list.

  22. How do you let the visitor move objects around in the world?

    By attaching sensors to objects. There are four kinds of sensors you can use for manipulating objects: TouchSensor, PlaneSensor, CylinderSensor, and SphereSensor. We've used a TouchSensor in the example for an answer to a previous question. This example [download VRML and texture] uses a PlaneSensor to control speed forwards and backwards, a CylinderSensor for a steering wheel, and a SphereSensor to manipulate one of the objects. It's based on Chris Fouts's HUD from the answer to a previous question. Vladimir Bulatov supplied the solution to a serious problem in the original version and suggested a way to make it look more object oriented.

    Note that this example also shows a way to integrate variables over time. In this case, we integrate the velocity to produce a position.

  23. How can you get LODs to prefetch in the background?

    The best way is to use createVrmlFromURL in a Script and trigger the Script when you want the object to load. This also works to prevent downloads of invisible levels of detail, since nothing in the spec requires the browser to load an invisible LOD or avoid loading an invisible LOD. This example shows a LOD that doesn't load until the user gets close enough. [download].

  24. How do you turn off collision for the avatar?

    Use the Collision node, put it around everything you don't want your avatar to collide with, and set the collide field FALSE. There are some objects in your scene that it's impossible for the avatar to collide with, like ornaments on the tops of buildings, and it might be worthwhile experimenting in a few browsers to see if wrapping those objects in a Collision node would speed up your frame rate.

  25. How do you detect when other objects in the scene (not the avatar) collide with one another?

    Short answer: you can't. Longer answer: you need to write either a Script or an EAI applet that computes collisions for the objects you want to have collide with one another. You can often work around this limitation of VRML by pre-programming the movement of objects or by filtering object movements through a Script that applies limits to simulate collisions. A paper at the 1997 VRML Symposium: "V-COLLIDE: Accelerated Collision Detection for VRML" by Thomas C. Hudson et al (pdf) talked about a program for detecting collisions between objects.

  26. How do you print a VRML world?

    No VRML browser I know of will let you print the screen from your web browser's Print button. But there's a workaround. Many platforms give you the capability of doing a screen capture (on PCs Alt-Print Screen will capture the current window). You can then open up a 2D bitmap graphics program such as Photoshop (Mac and PC), Paint Shop Pro (PC), or xv (Unix) and either paste the image onto another blank image or paste it as a new image. Unix systems may automatically save the screen capture in a file. The better 2D bitmap graphics programs will then let you edit and print the image or convert it to a format like EPS which can be printed.

  27. How do you make a motion trail that follows the path of an object?

    Tom Kaye of SGI's Huntsville office has developed a PROTO for generating motion trails [download].

  28. Can you view an object in wireframe as well as solid?

    Some browsers offer this as a viewing option, but you can do it in any browser. DEF your Coordinate node from your IndexedFaceSet and then USE it in an IndexedLineSet node. You will need to generate the coordIndex field for the IndexedLineSet, but this can be easily done by copying the field from the IndexedFaceSet and trimming out duplicate lines. Put the two nodes in branches of a Switch node and toggle the switch from a script.

  29. How big a VRML world is too big?

    Dennis McKenzie said not long ago that he tries to keep his VRML files down to 2K polygons or less. David Frerichs uses a stricter heuristic that needs to be more widely known:

    Download Speed Type Maximum Size

    28.8Kb/Sec

    NanoVRML

    12KB

    56Kb/Sec, ISDN

    Vignette

    200KB

    CD-ROM, T1

    Immersive

    1MB+

    The critical parameter is how fast the average visitor's modem is. Right now that average is around 28.8K.

  30. How many digits of precision do you need in your IndexedFaceSet numbers?

    First, let's do some figuring. If the average visitor to your world has an 800 x 600 screen, then the difference between a point with coordinates 1000 0 0 and 1001 0 0 is a little less than one pixel. That would seem to mean that 3 digits of precision is enough for any virtual world, but that doesn't take the user's viewpoint into account.

    Suppose you have a slide on a virtual microscope. A difference between 4.0000001 and 4 might be enormous. On the other hand, if you have a temple roof with a carving that will never get larger than 2 degrees in the visitor's field of view, you can probably cut both precision and polygons without harm.

    The true answer is to figure out for each object, and perhaps even each part of each object (say, an automatic teller machine on a long wall that the visitor might approach and use), how big that object will ever be in the visitor's field of view, and then figure out how many polygons and how much precision you need.

    One more point: in the real world we're used to objects revealing themselves in more and more detail as we approach them. That's an important part of how we perceive distance. By using LODs selectively, we can mimic that experience in our virtual worlds and make them more realistic.

  31. How do you do a guided tour?

    Many people have noticed that the example of a guided tour in Hartman & Wernecke's book doesn't work the way it should. Jed has a thoroughly commented replacement for the example in the book.

  32. How do you animate a texture without using a MovieTexture?

    This example [download] shows a stick of dynamite with a sizzling fuse using PixelTextures and a Script. There's a utility at the VRMLworks that can turn an ordinary GIF or JPEG image into a PixelTexture.

  33. PROTOs can have exposedFields, but Script nodes can't. How can you map a PROTO to a Script?

    This is a known deficiency in the spec. The following example from Greg Seidman shows a way to get around that limitation:

    PROTO Foo [ exposedField SFBool enabled TRUE ] {
      DEF CONTROL Script {
        field SFNode enabled ENABLED PointLight { on IS enabled }
        eventIn SFBool set_enabled
        url [ "vrmlscript:
          function set_enabled(val, time) {
           //do something based on the new value
          }
        "]
      }
      ROUTE ENABLED.on_changed TO CONTROL.set_enabled
    }

    Greg notes that it's sometimes necessary to set directOutput TRUE. In my own work, I've often discovered that an eventIn or an eventOut is all that's necessary, and have avoided exposedFields in PROTOs.

  34. How do you make an ElevationGrid?

    You could sit down with your text editor and type in points, but that's absurd. Most VRML modelers have a tool that does that. But if you don't have a VRML modeler or if you find that modeler's ElevationGrid tool hard to use, there are other ways to make an ElevationGrid.

    One way is to use a regular 2D bitmap graphics program like Photoshop or Paint Shop Pro and create a greyscale terrain map. The lighter the color, the higher the elevation. Then save it as a PGM or greyscale PNM file. Most 2D bitmap graphics programs will let you save in one of those formats, and if yours doesn't, you can almost certainly save as a greyscale (256-grey values) GIF file and use "giftopnm", included in the free pnmtopix utility from the VRMLworks, to turn it into a greyscale PNM. Then take your PGM or PNM file and use a free utility from the VRMLworks called pbm2wrl to convert it to an ElevationGrid.

    Another way to make an ElevationGrid is by taking real elevation data from the U.S. Geological Survey or other sources and using a free utility from the VRMLworks called dem2wrl to convert it to an ElevationGrid. DEMs can be huge, so unless the level of detail in the DEM is vital to your application, make sure you cull that data; 10-to-1 reduction is average for what I've done.

    Still another way is to take advantage of the work people in the raytracing community have done on terrain generation tools. Jörn Seger has created a list of raytracing utilities, many of them free. I've used both Silver Software's Terrain Forge and Tapio Vocadlo's Leveler. In both cases you export a 2D greyscale map (in Terrain Forge, a Windows bitmap and in Leveler a targa file -- though Tapio and I are working on a plugin so that Leveler will directly export VRML ElevationGrids). Then you use pbm2wrl to convert it to an ElevationGrid.


[line]

Did I leave something out on one of these questions that you need to know? Let me know.

-- Bob Crispen
-- Thursday, June 11, 1998